support function

This commit is contained in:
blueloveTH 2024-07-07 00:06:21 +08:00
parent 803e7f1791
commit 5c959e7274
10 changed files with 59 additions and 172 deletions

View File

@ -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,

View File

@ -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();

View File

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

View File

@ -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;
}

View File

@ -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(); \
} \

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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