diff --git a/include/pocketpy/interpreter/frame.h b/include/pocketpy/interpreter/frame.h index a31321c7..169d81e3 100644 --- a/include/pocketpy/interpreter/frame.h +++ b/include/pocketpy/interpreter/frame.h @@ -47,7 +47,7 @@ typedef struct Frame { } Frame; Frame* Frame__new(const CodeObject* co, - const py_TValue* module, + PyObject* module, const py_TValue* function, py_TValue* p0, py_TValue* locals, diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 17091a97..01e7e96b 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -95,6 +95,7 @@ void pk_number__register(); py_Type pk_str__register(); py_Type pk_bytes__register(); py_Type pk_list__register(); +py_Type pk_function__register(); py_TValue pk_builtins__register(); diff --git a/include/pocketpy/objects/codeobject.h b/include/pocketpy/objects/codeobject.h index cf08dc57..a43db0c6 100644 --- a/include/pocketpy/objects/codeobject.h +++ b/include/pocketpy/objects/codeobject.h @@ -21,7 +21,6 @@ typedef enum FuncType { FuncType_UNSET, FuncType_NORMAL, FuncType_SIMPLE, - FuncType_EMPTY, FuncType_GENERATOR, } FuncType; diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 2738087c..e1832b1b 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1638,15 +1638,9 @@ static Error* pop_context(Compiler* self) { if(is_simple) { func->type = FuncType_SIMPLE; - - bool is_empty = false; - if(func->code.codes.count == 1) { - Bytecode bc = c11__getitem(Bytecode, &func->code.codes, 0); - if(bc.op == OP_RETURN_VALUE && bc.arg == 1) { is_empty = true; } - } - if(is_empty) func->type = FuncType_EMPTY; - } else + } else { func->type = FuncType_NORMAL; + } } assert(func->type != FuncType_UNSET); @@ -2197,7 +2191,6 @@ static FuncDecl_ push_f_context(Compiler* self, c11_sv name, int* out_index) { *out_index = top_ctx->co->func_decls.count - 1; // push new context top_ctx = c11_vector__emplace(&self->contexts); - // contexts.push_back(CodeEmitContext(vm, decl->code, contexts.size())); Ctx__ctor(top_ctx, &decl->code, decl, self->contexts.count); return decl; } diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 0f6641be..629ae8c8 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -51,10 +51,7 @@ static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop); pk_FrameResult res = pk_VM__vectorcall(self, (argc), (kwargc), true); \ switch(res) { \ case RES_RETURN: PUSH(&self->last_retval); break; \ - case RES_CALL: \ - frame = self->top_frame; \ - PUSH(&self->last_retval); \ - goto __NEXT_FRAME; \ + case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \ case RES_ERROR: goto __ERROR; \ default: c11__unreachedable(); \ } \ diff --git a/src/interpreter/frame.c b/src/interpreter/frame.c index 8b84e3f7..3d27d58c 100644 --- a/src/interpreter/frame.c +++ b/src/interpreter/frame.c @@ -34,7 +34,7 @@ UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset) { void UnwindTarget__delete(UnwindTarget* self) { free(self); } Frame* Frame__new(const CodeObject* co, - const py_TValue* module, + PyObject* module, const py_TValue* function, py_TValue* p0, py_TValue* locals, @@ -44,7 +44,7 @@ Frame* Frame__new(const CodeObject* co, self->f_back = NULL; self->ip = (Bytecode*)co->codes.data - 1; self->co = co; - self->module = module->_obj; + self->module = module; self->function = function ? function->_obj : NULL; self->p0 = p0; self->locals = locals; diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index dc077648..c2b031c9 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -56,8 +56,6 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self, void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); } - - void pk_VM__ctor(pk_VM* self) { self->top_frame = NULL; @@ -106,7 +104,7 @@ void pk_VM__ctor(pk_VM* self) { validate(tp_range, pk_VM__new_type(self, "range", tp_object, NULL, false)); validate(tp_module, pk_VM__new_type(self, "module", tp_object, NULL, false)); - validate(tp_function, pk_VM__new_type(self, "function", tp_object, NULL, false)); + validate(tp_function, pk_function__register()); validate(tp_nativefunc, pk_VM__new_type(self, "nativefunc", tp_object, NULL, false)); validate(tp_bound_method, pk_VM__new_type(self, "bound_method", tp_object, NULL, false)); @@ -220,74 +218,64 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo // [unbound, self, args..., kwargs...] } - // PyVar* _base = args.begin(); py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1; + int argc2 = argv - p0; -#if 0 - if(callable_t == tp_function) { + if(p0->type == tp_function) { /*****************_py_call*****************/ // check stack overflow - if(self->stack.sp > self->stack.end){ - StackOverflowError(); + if(self->stack.sp > self->stack.end) { + py_exception("StackOverflowError", ""); return RES_ERROR; } - const Function& fn = PK_OBJ_GET(Function, callable); - const CodeObject* co = fn.decl->code; + Function* fn = py_touserdata(p0); + const CodeObject* co = &fn->decl->code; - switch(fn.decl->type) { + switch(fn->decl->type) { case FuncType_NORMAL: - __prepare_py_call(__vectorcall_buffer, args, kwargs, fn.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]; + assert(false); + // __prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl); + // // copy buffer back to stack + // self->stack.sp = argv + co->nlocals; + // for(int j = 0; j < co->nlocals; j++) + // argv[j] = self->__vectorcall_buffer[j]; break; case FuncType_SIMPLE: - if(args.size() != fn.decl->args.count) { - TypeError(pk_format("{} takes {} positional arguments but {} were given", - &co->name, - fn.decl->args.count, - args.size())); + if(argc2 != fn->decl->args.count) { + const char* fmt = "%s() takes %d positional arguments but %d were given"; + TypeError(fmt, co->name, fn->decl->args.count, argc2); + return RES_ERROR; } - if(!kwargs.empty()) { - TypeError(pk_format("{} takes no keyword arguments", &co->name)); + if(kwargc) { + TypeError("%s() takes no keyword arguments", co->name->data); + return RES_ERROR; } // [callable, , args..., local_vars...] // ^p0 ^p1 ^_sp - s_data.reset(_base + co->nlocals); + self->stack.sp = argv + co->nlocals; // initialize local variables to PY_NIL - std::memset(p1, 0, (char*)s_data._sp - (char*)p1); + memset(p1, 0, (char*)self->stack.sp - (char*)p1); break; - case FuncType_EMPTY: - if(args.size() != fn.decl->args.count) { - TypeError(pk_format("{} takes {} positional arguments but {} were given", - &co->name, - fn.decl->args.count, - args.size())); - } - if(!kwargs.empty()) { - TypeError(pk_format("{} takes no keyword arguments", &co->name)); - } - s_data.reset(p0); - return None; case FuncType_GENERATOR: - __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( - callstack.popx(), - ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)); - default: c11__unreachedable() + assert(false); + break; + // __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( + // callstack.popx(), + // ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)); + default: c11__unreachedable(); }; // simple or normal - callstack.emplace(p0, co, fn._module, callable.get(), args.begin()); - if(op_call) return pkpy_OP_CALL; - return __run_top_frame(); + Frame* frame = Frame__new(co, fn->module, p0, p0, argv, co); + pk_VM__push_frame(self, frame); + if(opcall) return RES_CALL; + return pk_VM__run_top_frame(self); /*****************_py_call*****************/ } -#endif if(p0->type == tp_nativefunc) { // const auto& f = PK_OBJ_GET(NativeFunc, callable); diff --git a/src/public/modules.c b/src/public/modules.c index 9549170c..4d481119 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -53,15 +53,15 @@ py_Ref py_newmodule(const char* name, const char* package) { ////////////////////////// -static bool _py_builtins__repr(int argc, py_Ref argv){ +static bool _py_builtins__repr(int argc, py_Ref argv) { PY_CHECK_ARGC(1); return py_repr(argv); } -static bool _py_builtins__exit(int argc, py_Ref argv){ +static bool _py_builtins__exit(int argc, py_Ref argv) { int code = 0; if(argc > 1) return TypeError("exit() takes at most 1 argument"); - if(argc == 1){ + if(argc == 1) { PY_CHECK_ARG_TYPE(0, tp_int); code = py_toint(argv); } @@ -70,9 +70,17 @@ static bool _py_builtins__exit(int argc, py_Ref argv){ return false; } -py_TValue pk_builtins__register(){ +py_TValue pk_builtins__register() { py_Ref builtins = py_newmodule("builtins", NULL); py_bindnativefunc(builtins, "repr", _py_builtins__repr); py_bindnativefunc(builtins, "exit", _py_builtins__exit); return *builtins; +} + +py_Type pk_function__register() { + pk_VM* vm = pk_current_vm; + py_Type type = pk_VM__new_type(vm, "function", tp_object, NULL, false); + pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type); + ti->dtor = (void (*)(void*))Function__dtor; + return type; } \ No newline at end of file diff --git a/src/public/vm.c b/src/public/vm.c index 656ccabd..94673095 100644 --- a/src/public/vm.c +++ b/src/public/vm.c @@ -170,7 +170,7 @@ static bool // disassemble(&co); - Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co); + Frame* frame = Frame__new(&co, vm->main._obj, NULL, vm->stack.sp, vm->stack.sp, &co); pk_VM__push_frame(vm, frame); pk_FrameResult res = pk_VM__run_top_frame(vm); CodeObject__dtor(&co); diff --git a/tests/00_tmp.py b/tests/00_tmp.py index 95f60179..ca5cf9be 100644 --- a/tests/00_tmp.py +++ b/tests/00_tmp.py @@ -1,103 +1,4 @@ -# test int literals -assert 0xffff == 65535 -assert 0xAAFFFF == 11206655 -assert 0x7fffffff == 2147483647 -assert -0xffff == -65535 -assert -0xAAFFFF == -11206655 -assert -0x7fffffff == -2147483647 -# test 64-bit -assert 2**60-1 + 546 - 0xfffffffffffff == 1148417904979477026 +def f(a, b): + return a+b -# test oct literals -assert 0o1234 == 668 -assert 0o17777777777 == 2147483647 -assert -0o1234 == -668 -assert -0o17777777777 == -2147483647 - -# test binary literals -assert 0b10010 == 18 -assert -0b10010 == -18 -assert 0b11111111111111111111111111111111 == 4294967295 -assert -0b11111 == -31 - -# test == != >= <= < > -assert -1 == -1 -assert -1 != 1 -assert -1 >= -1 -assert -1 <= -1 -assert -1 < 1 -assert -1 > -2 - -# test + - * % ** // -assert -1 + 1 == 0 -assert -1 - 1 == -2 -assert 4 * -1 == -4 -assert 5 % 2 == 1 -assert 2 ** 3 == 8 -assert 4 // 2 == 2 -assert 5 // 2 == 2 - -# test += -= *= //= -x = 3 -x += 1 -assert x == 4 -x -= 1 -assert x == 3 -x *= 2 -assert x == 6 -x //= 2 -assert x == 3 - -# test bit_length -assert (1).bit_length() == 1 -assert (2).bit_length() == 2 -assert (3).bit_length() == 2 - -assert (-1).bit_length() == 1 -assert (-2).bit_length() == 2 -assert (-3).bit_length() == 2 - -assert (123123123123123).bit_length() == 47 -assert (-3123123123).bit_length() == 32 - -# test int() -assert int() == 0 -assert int(True) == 1 -assert int(False) == 0 - -assert int(1) == 1 -assert int(1.0) == 1 -assert int(1.1) == 1 -assert int(1.9) == 1 -assert int(-1.9) == -1 -assert int(1.5) == 1 -assert int(-1.5) == -1 -assert int("123") == 123 - -assert int("0x123", 16) == 291 -assert int("0o123", 8) == 83 -assert int("-0x123", 16) == -291 -assert int("-0o123", 8) == -83 -assert int("-123") == -123 -assert int("+123") == 123 - -# test >> << & | ^ -assert 12 >> 1 == 6 -assert 12 << 1 == 24 -assert 12 & 1 == 0 -assert 12 | 1 == 13 -assert 12 ^ 1 == 13 - -# test high precision int pow -assert 7**21 == 558545864083284007 -assert 2**60 == 1152921504606846976 -assert -2**60 == -1152921504606846976 -assert 4**13 == 67108864 -assert (-4)**13 == -67108864 - -assert ~3 == -4 -assert ~-3 == 2 -assert ~0 == -1 - -# tmp code -assert [1, 2].__len__() == 2 \ No newline at end of file +assert f(1, 2) == 3