blueloveTH 1 سال پیش
والد
کامیت
8f97e9419f
8فایلهای تغییر یافته به همراه45 افزوده شده و 48 حذف شده
  1. 2 0
      include/pocketpy/pocketpy.h
  2. 8 16
      src/interpreter/ceval.c
  3. 2 28
      src/interpreter/vm.c
  4. 22 0
      src/public/modules.c
  5. 0 1
      src/public/py_dict.c
  6. 1 0
      src/public/py_list.c
  7. 2 2
      src/public/values.c
  8. 8 1
      src/public/vm.c

+ 2 - 0
include/pocketpy/pocketpy.h

@@ -324,6 +324,8 @@ bool py_callmethod(py_Ref self, py_Name, int argc, py_Ref argv);
 /// The result will be set to `py_retval()`.
 /// The stack remains unchanged after the operation.
 bool py_callmagic(py_Name name, int argc, py_Ref argv);
+/// Call a `py_CFunction` in a safe way.
+bool py_callcfunc(py_StackRef p0, py_CFunction cfunc, int argc, py_Ref argv);
 
 bool py_str(py_Ref val);
 #define py_repr(val) py_callmagic(__repr__, 1, val)

+ 8 - 16
src/interpreter/ceval.c

@@ -267,10 +267,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
                 if(magic) {
                     if(magic->type == tp_nativefunc) {
-                        py_TValue* next_sp = TOP();
-                        bool ok = magic->_cfunc(2, SECOND());
-                        if(!ok) goto __ERROR;
-                        SP() = next_sp;
+                        py_TValue* p0 = TOP();
+                        if(!py_callcfunc(p0, magic->_cfunc, 2, SECOND())) goto __ERROR;
                         *TOP() = self->last_retval;
                     } else {
                         INSERT_THIRD();     // [?, a, b]
@@ -321,10 +319,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 if(magic) {
                     PUSH(THIRD());  // [val, a, b, val]
                     if(magic->type == tp_nativefunc) {
-                        py_TValue* next_sp = FOURTH();
-                        bool ok = magic->_cfunc(3, THIRD());
-                        if(!ok) goto __ERROR;
-                        SP() = next_sp;
+                        py_TValue* p0 = FOURTH();
+                        if(!py_callcfunc(p0, magic->_cfunc, 3, THIRD())) goto __ERROR;
                     } else {
                         *FOURTH() = *magic;  // [__selitem__, a, b, val]
                         if(!py_vectorcall(2, 0)) goto __ERROR;
@@ -391,10 +387,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
                 if(magic) {
                     if(magic->type == tp_nativefunc) {
-                        py_TValue* next_sp = SECOND();
-                        bool ok = magic->_cfunc(2, SECOND());
-                        if(!ok) goto __ERROR;
-                        SP() = next_sp;
+                        py_TValue* p0 = SECOND();
+                        if(!py_callcfunc(p0, magic->_cfunc, 2, SECOND())) goto __ERROR;
                     } else {
                         INSERT_THIRD();     // [?, a, b]
                         *THIRD() = *magic;  // [__delitem__, a, b]
@@ -533,10 +527,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
                 if(magic) {
                     if(magic->type == tp_nativefunc) {
-                        py_TValue* next_sp = TOP();
-                        bool ok = magic->_cfunc(2, SECOND());
-                        if(!ok) goto __ERROR;
-                        SP() = next_sp;
+                        py_TValue* p0 = TOP();
+                        if(!py_callcfunc(p0, magic->_cfunc, 2, SECOND())) goto __ERROR;
                         *TOP() = self->last_retval;
                     } else {
                         INSERT_THIRD();     // [?, b, a]

+ 2 - 28
src/interpreter/vm.c

@@ -391,8 +391,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
                     pk_VM__push_frame(self, Frame__new(co, fn->module, p0, p0, argv, co));
                     return opcall ? RES_CALL : pk_VM__run_top_frame(self);
                 } else {
-                    bool ok = fn->cfunc(co->nlocals, argv);
-                    self->stack.sp = p0;
+                    bool ok = py_callcfunc(p0, fn->cfunc, co->nlocals, argv);
                     return ok ? RES_RETURN : RES_ERROR;
                 }
             }
@@ -431,32 +430,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
     }
 
     if(p0->type == tp_nativefunc) {
-        // const auto& f = PK_OBJ_GET(NativeFunc, callable);
-        // PyVar ret;
-        // if(f.decl != nullptr) {
-        //     int co_nlocals = f.decl->code->nlocals;
-        //     prepare_py_call(__vectorcall_buffer, args, kwargs, f.decl);
-        //     // copy buffer back to stack
-        //     s_data.reset(_base + co_nlocals);
-        //     for(int j = 0; j < co_nlocals; j++)
-        //         _base[j] = __vectorcall_buffer[j];
-        //     ret = f.call(vm, ArgsView(s_data._sp - co_nlocals, s_data._sp));
-        // } else {
-        //     if(f.argc != -1) {
-        //         if(KWARGC != 0)
-        //             TypeError(
-        //                 "old-style native_func does not accept keyword arguments. If you want to
-        //                 skip this check, specify `argc` to -1");
-        //         if(args.size() != f.argc) {
-        //             vm->TypeError(_S("expected ", f.argc, " arguments, got ", args.size()));
-        //         }
-        //     }
-        //     ret = f.call(this, args);
-        // }
-
-        // `argc` passed to _cfunc must include self if exists
-        if(!p0->_cfunc(p1 - argv, argv)) return RES_ERROR;
-        self->stack.sp = p0;
+        if(!py_callcfunc(p0, p0->_cfunc, p1 - argv, argv)) return RES_ERROR;
         return RES_RETURN;
     }
 

+ 22 - 0
src/public/modules.c

@@ -178,6 +178,27 @@ static bool _py_builtins__sum(int argc, py_Ref argv) {
     return true;
 }
 
+static bool _py_builtins__print(int argc, py_Ref argv) {
+    int length;
+    py_TValue* args = pk_arrayview(argv, &length);
+    assert(args != NULL);
+    c11_sv sep = py_tosv(py_arg(1));
+    c11_sv end = py_tosv(py_arg(2));
+    c11_sbuf buf;
+    c11_sbuf__ctor(&buf);
+    for(int i = 0; i < length; i++) {
+        if(i > 0) c11_sbuf__write_sv(&buf, sep);
+        if(!py_str(&args[i])) return false;
+        c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
+    }
+    c11_sbuf__write_sv(&buf, end);
+    c11_string* res = c11_sbuf__submit(&buf);
+    pk_current_vm->_stdout("%s", res->data);
+    c11_string__delete(res);
+    py_newnone(py_retval());
+    return true;
+}
+
 py_TValue pk_builtins__register() {
     py_Ref builtins = py_newmodule("builtins", NULL);
     py_bindnativefunc(builtins, "repr", _py_builtins__repr);
@@ -191,6 +212,7 @@ py_TValue pk_builtins__register() {
     py_bindnativefunc(builtins, "abs", _py_builtins__abs);
     py_bindnativefunc(builtins, "sum", _py_builtins__sum);
 
+    py_bind(builtins, "print(*args, sep=' ', end='\\n')", _py_builtins__print);
     py_bind(builtins, "sorted(iterable, key=None, reverse=False)", _py_builtins__sorted);
     return *builtins;
 }

+ 0 - 1
src/public/py_dict.c

@@ -250,7 +250,6 @@ static bool _py_dict__delitem__(int argc, py_Ref argv) {
     PY_CHECK_ARGC(2);
     Dict* self = py_touserdata(argv);
     if(!Dict__pop(self, py_arg(1))) return false;
-    py_newnone(py_retval());
     return true;
 }
 

+ 1 - 0
src/public/py_list.c

@@ -174,6 +174,7 @@ static bool _py_list__delitem__(int argc, py_Ref argv) {
     int index = py_toint(py_arg(1));
     if(!pk__normalize_index(&index, self->count)) return false;
     c11_vector__erase(py_TValue, self, index);
+    py_newnone(py_retval());
     return true;
 }
 

+ 2 - 2
src/public/values.c

@@ -66,7 +66,7 @@ void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f) {
 
 void py_bind(py_Ref obj, const char* sig, py_CFunction f) {
     py_TValue tmp;
-    do{
+    do {
         char buffer[256];
         snprintf(buffer, sizeof(buffer), "def %s: pass", sig);
         // fn(a, b, *c, d=1) -> None
@@ -82,7 +82,7 @@ void py_bind(py_Ref obj, const char* sig, py_CFunction f) {
         ud->cfunc = f;
         CodeObject__dtor(&code);
         PK_DECREF(source);
-    }while(0);
+    } while(0);
     Function* ud = py_touserdata(&tmp);
     py_Name name = py_name(ud->decl->code.name->data);
     py_setdict(obj, name, &tmp);

+ 8 - 1
src/public/vm.c

@@ -203,7 +203,8 @@ bool py_exec2(const char* source, const char* filename, enum py_CompileMode mode
 
 bool py_call(py_Ref f, int argc, py_Ref argv) {
     if(f->type == tp_nativefunc) {
-        return f->_cfunc(argc, argv);
+        py_TValue* p0 = pk_current_vm->stack.sp;
+        return py_callcfunc(p0, f->_cfunc, argc, argv);
     } else {
         py_push(f);
         py_pushnil();
@@ -311,6 +312,12 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv) {
     return py_call(tmp, argc, argv);
 }
 
+bool py_callcfunc(py_StackRef p0, py_CFunction cfunc, int argc, py_Ref argv) {
+    bool ok = cfunc(argc, argv);
+    pk_current_vm->stack.sp = p0;
+    return ok;
+}
+
 bool StopIteration() {
     pk_VM* vm = pk_current_vm;
     assert(!vm->is_stopiteration);  // flag is already set