From c9df1046343c9fa602f1c99e9d0f2caa5c33c505 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Wed, 10 Jul 2024 13:41:28 +0800 Subject: [PATCH] ... --- include/pocketpy/pocketpy.h | 4 +-- src/interpreter/ceval.c | 69 +++++++++++++++++++++++++++++++++++-- src/interpreter/vm.c | 8 ++--- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 503bdab6..31fb5850 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -420,8 +420,8 @@ enum py_PredefinedTypes { tp_bytes, tp_mappingproxy, tp_dict, - tp_property, // 2 slots (getter + setter) - tp_star_wrapper, + tp_property, // 2 slots (getter + setter) + tp_star_wrapper, // 1 slot + int level tp_staticmethod, // 1 slot tp_classmethod, // 1 slot tp_NoneType, diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 6d239d25..021b5930 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -1,3 +1,4 @@ +#include "pocketpy/common/config.h" #include "pocketpy/interpreter/vm.h" #include "pocketpy/common/memorypool.h" #include "pocketpy/common/sstream.h" @@ -30,6 +31,7 @@ static bool stack_unpack_sequence(pk_VM* self, uint16_t arg); #define THIRD() (self->stack.sp - 3) #define FOURTH() (self->stack.sp - 4) #define STACK_SHRINK(n) (self->stack.sp -= n) +#define STACK_GROW(n) (self->stack.sp += n) #define PUSH(v) \ do { \ *self->stack.sp = *(v); \ @@ -625,7 +627,64 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { DISPATCH(); } case OP_CALL_VARGS: { - assert(false); + uint16_t argc = byte.arg & 0xFF; + uint16_t kwargc = byte.arg >> 8; + int size = 0; + py_TValue* buf = self->__vectorcall_buffer; + + // if(size == PK_MAX_CO_VARNAMES) { + // ValueError("**kwargs is too large to unpack"); + // goto __ERROR; + // } + + uint16_t new_argc = argc; + uint16_t new_kwargc = kwargc; + + // pop kwargc + for(int i = 0; i < kwargc; i++) { + // [k1, v1, k2, v2, ...] -> reversed + py_TValue value = POPX(); + py_TValue key = POPX(); + if(value.type == tp_star_wrapper) { + value = *py_getslot(&value, 0); + // unpack dict + if(value.type != tp_dict) { + TypeError("**kwargs should be a dict, got '%t'", value.type); + goto __ERROR; + } + new_kwargc += (0) - 1; + } else { + buf[size++] = value; + buf[size++] = key; + } + } + // pop argc + for(int i = 0; i < argc; i++) { + py_TValue value = POPX(); + if(value.type == tp_star_wrapper) { + value = *py_getslot(&value, 0); + int length; + py_TValue* p = pk_arrayview(&value, &length); + if(!p) { + TypeError("*args should be a list or tuple, got '%t'", value.type); + goto __ERROR; + } + for(int j = 0; j < length; j++) { + buf[size++] = p[j]; + } + new_argc += length - 1; + } else { + buf[size++] = value; + } + } + + // push everything back in reversed order + for(int i = size - 1; i >= 0; i--) { + PUSH(buf + i); + } + + vectorcall_opcall(new_argc, new_kwargc); + DISPATCH(); } case OP_RETURN_VALUE: { if(byte.arg == BC_NOARG) { @@ -671,7 +730,13 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { py_newbool(TOP(), !res); DISPATCH(); } - // case OP_UNARY_STAR: TOP() = VAR(StarWrapper(byte.arg, TOP())); DISPATCH(); + case OP_UNARY_STAR: { + py_TValue value = POPX(); + int* level = py_newobject(SP()++, tp_star_wrapper, 1, sizeof(int)); + *level = byte.arg; + py_setslot(TOP(), 0, &value); + DISPATCH(); + } case OP_UNARY_INVERT: { if(!py_callmagic(__invert__, 1, TOP())) goto __ERROR; *TOP() = self->last_retval; diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 29ca621c..b2febc94 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -276,7 +276,7 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo } static bool - __prepare_py_call(py_TValue* buffer, py_Ref argv, py_Ref p1, int kwargc, const FuncDecl* decl) { + prepare_py_call(py_TValue* buffer, py_Ref argv, py_Ref p1, int kwargc, const FuncDecl* decl) { const CodeObject* co = &decl->code; int decl_argc = decl->args.count; @@ -376,7 +376,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo switch(fn->decl->type) { case FuncType_NORMAL: { - bool ok = __prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl); + bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl); if(!ok) return RES_ERROR; // copy buffer back to stack self->stack.sp = argv + co->nlocals; @@ -412,7 +412,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo case FuncType_GENERATOR: assert(false); break; - // __prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl); + // prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl); // s_data.reset(p0); // callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr); // return __py_generator( @@ -430,7 +430,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo // PyVar ret; // if(f.decl != nullptr) { // int co_nlocals = f.decl->code->nlocals; - // __prepare_py_call(__vectorcall_buffer, args, kwargs, f.decl); + // 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++)