blueloveTH 1 год назад
Родитель
Сommit
3da176fbfb

+ 1 - 1
include/pocketpy/objects/base.h

@@ -36,7 +36,7 @@ typedef struct py_TValue {
 static_assert(sizeof(py_CFunction) <= 8, "sizeof(py_CFunction) > 8");
 static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16");
 
-extern py_TValue PY_NULL;
+extern py_TValue PY_NIL;
 
 #ifdef __cplusplus
 }

+ 2 - 2
include/pocketpy/pocketpy.h

@@ -56,7 +56,7 @@ unsigned char* py_newbytes(py_Ref, int);
 void py_newnone(py_Ref);
 void py_newnotimplemented(py_Ref out);
 void py_newellipsis(py_Ref out);
-void py_newnull(py_Ref);
+void py_newnil(py_Ref);
 
 /// Create a tuple with n UNINITIALIZED elements.
 /// You should initialize all elements before using it.
@@ -281,7 +281,7 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv);
 /// The return value of the most recent call.
 py_GlobalRef py_retval();
 
-#define py_isnull(self) ((self)->type == 0)
+#define py_isnil(self) ((self)->type == 0)
 
 /* tuple */
 

+ 19 - 10
src/interpreter/ceval.c

@@ -83,8 +83,17 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
     __NEXT_STEP:
         byte = *frame->ip;
 
-        // log
-        printf("byte.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
+#if 1
+        c11_sbuf buf;
+        c11_sbuf__ctor(&buf);
+        for(py_Ref p = self->stack.begin; p != SP(); p++){
+            c11_sbuf__write_cstr(&buf, py_tpname(p->type));
+            if(p != TOP()) c11_sbuf__write_cstr(&buf, ", ");
+        }
+        c11_string* stack_str = c11_sbuf__submit(&buf);
+        printf("L%d: %s [%s]\n", Frame__lineno(frame), pk_opname(byte.op), stack_str->data);
+        c11_string__delete(stack_str);
+#endif
 
         switch((Opcode)byte.op) {
             case OP_NO_OP: DISPATCH();
@@ -124,7 +133,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             case OP_LOAD_TRUE: py_newbool(SP()++, true); DISPATCH();
             case OP_LOAD_FALSE: py_newbool(SP()++, false); DISPATCH();
             /*****************************************/
-            case OP_LOAD_SMALL_INT: py_newint(SP()++, (int64_t)(int16_t)byte.arg); DISPATCH();
+            case OP_LOAD_SMALL_INT: py_newint(SP()++, (int16_t)byte.arg); DISPATCH();
             /*****************************************/
             case OP_LOAD_ELLIPSIS: py_newellipsis(SP()++); DISPATCH();
             case OP_LOAD_FUNCTION: {
@@ -144,12 +153,12 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 // PUSH(obj);DISPATCH();
             }
             case OP_LOAD_NULL:
-                py_newnull(SP()++);
+                py_newnil(SP()++);
                 DISPATCH();
                 /*****************************************/
             case OP_LOAD_FAST: {
                 PUSH(&frame->locals[byte.arg]);
-                if(py_isnull(TOP())) {
+                if(py_isnil(TOP())) {
                     py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg);
                     UnboundLocalError(name);
                     goto __ERROR;
@@ -160,7 +169,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 py_Name name = byte.arg;
                 py_Ref tmp = Frame__f_locals_try_get(frame, name);
                 if(tmp != NULL) {
-                    if(py_isnull(tmp)) {
+                    if(py_isnil(tmp)) {
                         UnboundLocalError(name);
                         goto __ERROR;
                     }
@@ -341,12 +350,12 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             }
             case OP_DELETE_FAST: {
                 py_Ref tmp = &frame->locals[byte.arg];
-                if(py_isnull(tmp)) {
+                if(py_isnil(tmp)) {
                     py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
                     UnboundLocalError(name);
                     goto __ERROR;
                 }
-                py_newnull(tmp);
+                py_newnil(tmp);
                 DISPATCH();
             }
             case OP_DELETE_NAME: {
@@ -354,7 +363,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 if(frame->function) {
                     py_TValue* slot = Frame__f_locals_try_get(frame, name);
                     if(slot) {
-                        py_newnull(slot);
+                        py_newnil(slot);
                     } else {
                         // Function& func = frame->_callable->as<Function>();
                         // if(func.decl == __dynamic_func_decl) {
@@ -427,7 +436,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 assert(f != NULL);
                 py_TValue tmp = *TOP();
                 *TOP() = *f;              // [complex]
-                py_newnull(SP()++);       // [complex, NULL]
+                py_newnil(SP()++);       // [complex, NULL]
                 py_newint(SP()++, 0);     // [complex, NULL, 0]
                 *SP()++ = tmp;            // [complex, NULL, 0, x]
                 vectorcall_opcall(2, 0);  // [complex(x)]

+ 1 - 1
src/interpreter/frame.c

@@ -20,7 +20,7 @@ pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
     pk_NameDict* dict = pk_NameDict__new();
     c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
         py_TValue value = locals[entry->value];
-        if(!py_isnull(&value)){
+        if(!py_isnil(&value)){
             pk_NameDict__set(dict, entry->key, value);
         }
     }

+ 19 - 18
src/interpreter/vm.c

@@ -48,7 +48,7 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self,
         ._obj = typeobj,
     };
 
-    self->module = module ? *module : PY_NULL;
+    self->module = module ? *module : PY_NIL;
     self->subclass_enabled = subclass_enabled;
 
     c11_vector__ctor(&self->annotated_fields, sizeof(py_Name));
@@ -69,20 +69,20 @@ void pk_VM__ctor(pk_VM* self) {
     pk_NameDict__ctor(&self->modules);
     c11_vector__ctor(&self->types, sizeof(pk_TypeInfo));
 
-    self->StopIteration = PY_NULL;
-    self->builtins = PY_NULL;
-    self->main = PY_NULL;
+    self->StopIteration = PY_NIL;
+    self->builtins = PY_NIL;
+    self->main = PY_NIL;
 
     self->_ceval_on_step = NULL;
     self->_import_file = pk_default_import_file;
     self->_stdout = pk_default_stdout;
     self->_stderr = pk_default_stderr;
 
-    self->last_retval = PY_NULL;
+    self->last_retval = PY_NIL;
     self->has_error = false;
 
-    self->__curr_class = PY_NULL;
-    self->__cached_object_new = PY_NULL;
+    self->__curr_class = PY_NIL;
+    self->__cached_object_new = PY_NIL;
     self->__dynamic_func_decl = NULL;
 
     pk_ManagedHeap__ctor(&self->heap, self);
@@ -210,16 +210,16 @@ py_Type pk_VM__new_type(pk_VM* self,
     return index;
 }
 
-pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bool opcall) {
-    py_Ref p1 = self->stack.sp - KWARGC * 2;
-    py_Ref p0 = p1 - ARGC - 2;
+pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall) {
+    py_Ref p1 = self->stack.sp - kwargc * 2;
+    py_Ref p0 = p1 - argc - 2;
     // [callable, <self>, args..., kwargs...]
     //      ^p0                    ^p1      ^_sp
 
     // handle boundmethod, do a patch
     if(p0->type == tp_bound_method) {
         assert(false);
-        assert(py_isnull(p0 + 1));  // self must be NULL
+        assert(py_isnil(p0 + 1));  // self must be NULL
         // BoundMethod& bm = PK_OBJ_GET(BoundMethod, callable);
         // callable = bm.func;  // get unbound method
         // callable_t = _tp(callable);
@@ -229,7 +229,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
     }
 
     // PyVar* _base = args.begin();
-    py_Ref argv = py_isnull(p0 + 1) ? p0 + 2 : p0 + 1;
+    py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1;
 
 #if 0
     if(callable_t == tp_function) {
@@ -264,7 +264,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
                 // [callable, <self>, args..., local_vars...]
                 //      ^p0                    ^p1      ^_sp
                 s_data.reset(_base + co->nlocals);
-                // initialize local variables to PY_NULL
+                // initialize local variables to PY_NIL
                 std::memset(p1, 0, (char*)s_data._sp - (char*)p1);
                 break;
             case FuncType_EMPTY:
@@ -321,7 +321,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
         //     ret = f.call(this, args);
         // }
 
-        if(!p0->_cfunc(ARGC, argv)) return RES_ERROR;
+        // `argc` passed to _cfunc must include self if exists
+        if(!p0->_cfunc(p1 - argv, argv)) return RES_ERROR;
         self->stack.sp = p0;
         return RES_RETURN;
     }
@@ -329,7 +330,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
     if(p0->type == tp_type) {
         // [cls, NULL, args..., kwargs...]
         py_Ref new_f = py_tpfindmagic(py_totype(p0), __new__);
-        assert(new_f && py_isnull(p0 + 1));
+        assert(new_f && py_isnil(p0 + 1));
 
         // prepare a copy of args and kwargs
         int span = self->stack.sp - argv;
@@ -339,7 +340,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
         self->stack.sp += span;
 
         // [new_f, cls, args..., kwargs...]
-        pk_FrameResult res = pk_VM__vectorcall(self, ARGC, KWARGC, false);
+        pk_FrameResult res = pk_VM__vectorcall(self, argc, kwargc, false);
         if(res == RES_ERROR) return RES_ERROR;
         assert(res == RES_RETURN);
         // by recursively using vectorcall, args and kwargs are consumed
@@ -353,7 +354,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
             *p0 = *init_f;              // __init__
             p0[1] = self->last_retval;  // self
             // [__init__, self, args..., kwargs...]
-            pk_FrameResult res = pk_VM__vectorcall(self, ARGC, KWARGC, false);
+            pk_FrameResult res = pk_VM__vectorcall(self, argc, kwargc, false);
             if(res == RES_ERROR) return RES_ERROR;
             assert(res == RES_RETURN);
         } else {
@@ -366,7 +367,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
     // handle `__call__` overload
     if(py_getunboundmethod(p0, __call__, p0, p0 + 1)) {
         // [__call__, self, args..., kwargs...]
-        pk_FrameResult res = pk_VM__vectorcall(self, ARGC, KWARGC, false);
+        pk_FrameResult res = pk_VM__vectorcall(self, argc, kwargc, false);
         if(res == RES_ERROR) return RES_ERROR;
         assert(res == RES_RETURN);
     }

+ 1 - 1
src/objects/base.c

@@ -1,4 +1,4 @@
 #include "pocketpy/objects/base.h"
 
-py_TValue PY_NULL = {.type=0, .is_ptr=false, .extra=0, ._i64=0};
+py_TValue PY_NIL = {.type=0, .is_ptr=false, .extra=0, ._i64=0};
 

+ 2 - 2
src/public/stack_ops.c

@@ -13,7 +13,7 @@ py_Ref py_getdict(const py_Ref self, py_Name name){
     if(self->type == tp_type && py_ismagicname(name)){
         py_Type* ud = py_touserdata(self);
         py_Ref slot = py_tpmagic(*ud, name);
-        return py_isnull(slot) ? NULL : slot;
+        return py_isnil(slot) ? NULL : slot;
     }
     return pk_NameDict__try_get(PyObject__dict(self->_obj), name);
 }
@@ -66,6 +66,6 @@ void py_push(const py_Ref src){
 
 py_Ref py_pushtmp(){
     pk_VM* vm = pk_current_vm;
-    py_newnull(vm->stack.sp++);
+    py_newnil(vm->stack.sp++);
     return py_gettop();
 }

+ 1 - 1
src/public/values.c

@@ -39,7 +39,7 @@ void py_newellipsis(py_Ref out) {
     out->is_ptr = false;
 }
 
-void py_newnull(py_Ref out) { out->type = 0; }
+void py_newnil(py_Ref out) { out->type = 0; }
 
 
 void py_newfunction(py_Ref out, py_CFunction f, const char* sig) {

+ 13 - 5
src/public/vm.c

@@ -209,16 +209,23 @@ bool py_getunboundmethod(py_Ref self, py_Name name, py_Ref out, py_Ref out_self)
     py_Ref cls_var = py_tpfindname(type, name);
     if(cls_var != NULL) {
         switch(cls_var->type) {
-            case tp_function: *out_self = *self; break;
-            case tp_nativefunc: *out_self = *self; break;
+            case tp_function:
+            case tp_nativefunc: {
+                py_TValue self_bak = *self;
+                // `out` may overlap with `self`. If we assign `out`, `self` may be corrupted.
+                *out = *cls_var;
+                *out_self = self_bak;
+                break;
+            }
             case tp_staticmethod:
-                py_newnull(self);
                 *out = *py_getslot(cls_var, 0);
+                py_newnil(out_self);
                 break;
             case tp_classmethod:
-                *out_self = c11__getitem(pk_TypeInfo, &pk_current_vm->types, type).self;
                 *out = *py_getslot(cls_var, 0);
+                *out_self = c11__getitem(pk_TypeInfo, &pk_current_vm->types, type).self;
                 break;
+            default: PK_UNREACHABLE();
         }
         return true;
     }
@@ -236,7 +243,7 @@ py_Ref py_tpfindmagic(py_Type t, py_Name name) {
     pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
     do {
         py_Ref f = &types[t].magic[name];
-        if(!py_isnull(f)) return f;
+        if(!py_isnil(f)) return f;
         t = types[t].base;
     } while(t);
     return NULL;
@@ -264,6 +271,7 @@ py_Ref py_tpobject(py_Type type) {
 }
 
 const char* py_tpname(py_Type type) {
+    if(!type) return "nil";
     pk_VM* vm = pk_current_vm;
     py_Name name = c11__at(pk_TypeInfo, &vm->types, type)->name;
     return py_name2str(name);