소스 검색

support function

blueloveTH 1 년 전
부모
커밋
5c959e7274

+ 1 - 1
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,

+ 1 - 0
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();
 

+ 0 - 1
include/pocketpy/objects/codeobject.h

@@ -21,7 +21,6 @@ typedef enum FuncType {
     FuncType_UNSET,
     FuncType_NORMAL,
     FuncType_SIMPLE,
-    FuncType_EMPTY,
     FuncType_GENERATOR,
 } FuncType;
 

+ 2 - 9
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;
 }

+ 1 - 4
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();                                                         \
         }                                                                                          \

+ 2 - 2
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;

+ 36 - 48
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, <self>, 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);

+ 12 - 4
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;
 }

+ 1 - 1
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);

+ 3 - 102
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
+assert f(1, 2) == 3