mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
support function
This commit is contained in:
parent
803e7f1791
commit
5c959e7274
@ -47,7 +47,7 @@ typedef struct Frame {
|
|||||||
} Frame;
|
} Frame;
|
||||||
|
|
||||||
Frame* Frame__new(const CodeObject* co,
|
Frame* Frame__new(const CodeObject* co,
|
||||||
const py_TValue* module,
|
PyObject* module,
|
||||||
const py_TValue* function,
|
const py_TValue* function,
|
||||||
py_TValue* p0,
|
py_TValue* p0,
|
||||||
py_TValue* locals,
|
py_TValue* locals,
|
||||||
|
@ -95,6 +95,7 @@ void pk_number__register();
|
|||||||
py_Type pk_str__register();
|
py_Type pk_str__register();
|
||||||
py_Type pk_bytes__register();
|
py_Type pk_bytes__register();
|
||||||
py_Type pk_list__register();
|
py_Type pk_list__register();
|
||||||
|
py_Type pk_function__register();
|
||||||
|
|
||||||
py_TValue pk_builtins__register();
|
py_TValue pk_builtins__register();
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ typedef enum FuncType {
|
|||||||
FuncType_UNSET,
|
FuncType_UNSET,
|
||||||
FuncType_NORMAL,
|
FuncType_NORMAL,
|
||||||
FuncType_SIMPLE,
|
FuncType_SIMPLE,
|
||||||
FuncType_EMPTY,
|
|
||||||
FuncType_GENERATOR,
|
FuncType_GENERATOR,
|
||||||
} FuncType;
|
} FuncType;
|
||||||
|
|
||||||
|
@ -1638,15 +1638,9 @@ static Error* pop_context(Compiler* self) {
|
|||||||
|
|
||||||
if(is_simple) {
|
if(is_simple) {
|
||||||
func->type = FuncType_SIMPLE;
|
func->type = FuncType_SIMPLE;
|
||||||
|
} else {
|
||||||
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
|
|
||||||
func->type = FuncType_NORMAL;
|
func->type = FuncType_NORMAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(func->type != FuncType_UNSET);
|
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;
|
*out_index = top_ctx->co->func_decls.count - 1;
|
||||||
// push new context
|
// push new context
|
||||||
top_ctx = c11_vector__emplace(&self->contexts);
|
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);
|
Ctx__ctor(top_ctx, &decl->code, decl, self->contexts.count);
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
@ -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); \
|
pk_FrameResult res = pk_VM__vectorcall(self, (argc), (kwargc), true); \
|
||||||
switch(res) { \
|
switch(res) { \
|
||||||
case RES_RETURN: PUSH(&self->last_retval); break; \
|
case RES_RETURN: PUSH(&self->last_retval); break; \
|
||||||
case RES_CALL: \
|
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
|
||||||
frame = self->top_frame; \
|
|
||||||
PUSH(&self->last_retval); \
|
|
||||||
goto __NEXT_FRAME; \
|
|
||||||
case RES_ERROR: goto __ERROR; \
|
case RES_ERROR: goto __ERROR; \
|
||||||
default: c11__unreachedable(); \
|
default: c11__unreachedable(); \
|
||||||
} \
|
} \
|
||||||
|
@ -34,7 +34,7 @@ UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset) {
|
|||||||
void UnwindTarget__delete(UnwindTarget* self) { free(self); }
|
void UnwindTarget__delete(UnwindTarget* self) { free(self); }
|
||||||
|
|
||||||
Frame* Frame__new(const CodeObject* co,
|
Frame* Frame__new(const CodeObject* co,
|
||||||
const py_TValue* module,
|
PyObject* module,
|
||||||
const py_TValue* function,
|
const py_TValue* function,
|
||||||
py_TValue* p0,
|
py_TValue* p0,
|
||||||
py_TValue* locals,
|
py_TValue* locals,
|
||||||
@ -44,7 +44,7 @@ Frame* Frame__new(const CodeObject* co,
|
|||||||
self->f_back = NULL;
|
self->f_back = NULL;
|
||||||
self->ip = (Bytecode*)co->codes.data - 1;
|
self->ip = (Bytecode*)co->codes.data - 1;
|
||||||
self->co = co;
|
self->co = co;
|
||||||
self->module = module->_obj;
|
self->module = module;
|
||||||
self->function = function ? function->_obj : NULL;
|
self->function = function ? function->_obj : NULL;
|
||||||
self->p0 = p0;
|
self->p0 = p0;
|
||||||
self->locals = locals;
|
self->locals = locals;
|
||||||
|
@ -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_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void pk_VM__ctor(pk_VM* self) {
|
void pk_VM__ctor(pk_VM* self) {
|
||||||
self->top_frame = NULL;
|
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_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_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_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));
|
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...]
|
// [unbound, self, args..., kwargs...]
|
||||||
}
|
}
|
||||||
|
|
||||||
// PyVar* _base = args.begin();
|
|
||||||
py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1;
|
py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1;
|
||||||
|
int argc2 = argv - p0;
|
||||||
|
|
||||||
#if 0
|
if(p0->type == tp_function) {
|
||||||
if(callable_t == tp_function) {
|
|
||||||
/*****************_py_call*****************/
|
/*****************_py_call*****************/
|
||||||
// check stack overflow
|
// check stack overflow
|
||||||
if(self->stack.sp > self->stack.end){
|
if(self->stack.sp > self->stack.end) {
|
||||||
StackOverflowError();
|
py_exception("StackOverflowError", "");
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Function& fn = PK_OBJ_GET(Function, callable);
|
Function* fn = py_touserdata(p0);
|
||||||
const CodeObject* co = fn.decl->code;
|
const CodeObject* co = &fn->decl->code;
|
||||||
|
|
||||||
switch(fn.decl->type) {
|
switch(fn->decl->type) {
|
||||||
case FuncType_NORMAL:
|
case FuncType_NORMAL:
|
||||||
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
assert(false);
|
||||||
// copy buffer back to stack
|
// __prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
s_data.reset(_base + co->nlocals);
|
// // copy buffer back to stack
|
||||||
for(int j = 0; j < co->nlocals; j++)
|
// self->stack.sp = argv + co->nlocals;
|
||||||
_base[j] = __vectorcall_buffer[j];
|
// for(int j = 0; j < co->nlocals; j++)
|
||||||
|
// argv[j] = self->__vectorcall_buffer[j];
|
||||||
break;
|
break;
|
||||||
case FuncType_SIMPLE:
|
case FuncType_SIMPLE:
|
||||||
if(args.size() != fn.decl->args.count) {
|
if(argc2 != fn->decl->args.count) {
|
||||||
TypeError(pk_format("{} takes {} positional arguments but {} were given",
|
const char* fmt = "%s() takes %d positional arguments but %d were given";
|
||||||
&co->name,
|
TypeError(fmt, co->name, fn->decl->args.count, argc2);
|
||||||
fn.decl->args.count,
|
return RES_ERROR;
|
||||||
args.size()));
|
|
||||||
}
|
}
|
||||||
if(!kwargs.empty()) {
|
if(kwargc) {
|
||||||
TypeError(pk_format("{} takes no keyword arguments", &co->name));
|
TypeError("%s() takes no keyword arguments", co->name->data);
|
||||||
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
// [callable, <self>, args..., local_vars...]
|
// [callable, <self>, args..., local_vars...]
|
||||||
// ^p0 ^p1 ^_sp
|
// ^p0 ^p1 ^_sp
|
||||||
s_data.reset(_base + co->nlocals);
|
self->stack.sp = argv + co->nlocals;
|
||||||
// initialize local variables to PY_NIL
|
// 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;
|
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:
|
case FuncType_GENERATOR:
|
||||||
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
assert(false);
|
||||||
s_data.reset(p0);
|
break;
|
||||||
callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
|
// __prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
return __py_generator(
|
// s_data.reset(p0);
|
||||||
callstack.popx(),
|
// callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
|
||||||
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals));
|
// return __py_generator(
|
||||||
default: c11__unreachedable()
|
// callstack.popx(),
|
||||||
|
// ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals));
|
||||||
|
default: c11__unreachedable();
|
||||||
};
|
};
|
||||||
|
|
||||||
// simple or normal
|
// simple or normal
|
||||||
callstack.emplace(p0, co, fn._module, callable.get(), args.begin());
|
Frame* frame = Frame__new(co, fn->module, p0, p0, argv, co);
|
||||||
if(op_call) return pkpy_OP_CALL;
|
pk_VM__push_frame(self, frame);
|
||||||
return __run_top_frame();
|
if(opcall) return RES_CALL;
|
||||||
|
return pk_VM__run_top_frame(self);
|
||||||
/*****************_py_call*****************/
|
/*****************_py_call*****************/
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if(p0->type == tp_nativefunc) {
|
if(p0->type == tp_nativefunc) {
|
||||||
// const auto& f = PK_OBJ_GET(NativeFunc, callable);
|
// const auto& f = PK_OBJ_GET(NativeFunc, callable);
|
||||||
|
@ -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);
|
PY_CHECK_ARGC(1);
|
||||||
return py_repr(argv);
|
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;
|
int code = 0;
|
||||||
if(argc > 1) return TypeError("exit() takes at most 1 argument");
|
if(argc > 1) return TypeError("exit() takes at most 1 argument");
|
||||||
if(argc == 1){
|
if(argc == 1) {
|
||||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||||
code = py_toint(argv);
|
code = py_toint(argv);
|
||||||
}
|
}
|
||||||
@ -70,9 +70,17 @@ static bool _py_builtins__exit(int argc, py_Ref argv){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
py_TValue pk_builtins__register(){
|
py_TValue pk_builtins__register() {
|
||||||
py_Ref builtins = py_newmodule("builtins", NULL);
|
py_Ref builtins = py_newmodule("builtins", NULL);
|
||||||
py_bindnativefunc(builtins, "repr", _py_builtins__repr);
|
py_bindnativefunc(builtins, "repr", _py_builtins__repr);
|
||||||
py_bindnativefunc(builtins, "exit", _py_builtins__exit);
|
py_bindnativefunc(builtins, "exit", _py_builtins__exit);
|
||||||
return *builtins;
|
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;
|
||||||
}
|
}
|
@ -170,7 +170,7 @@ static bool
|
|||||||
|
|
||||||
// disassemble(&co);
|
// 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_VM__push_frame(vm, frame);
|
||||||
pk_FrameResult res = pk_VM__run_top_frame(vm);
|
pk_FrameResult res = pk_VM__run_top_frame(vm);
|
||||||
CodeObject__dtor(&co);
|
CodeObject__dtor(&co);
|
||||||
|
105
tests/00_tmp.py
105
tests/00_tmp.py
@ -1,103 +1,4 @@
|
|||||||
# test int literals
|
def f(a, b):
|
||||||
assert 0xffff == 65535
|
return a+b
|
||||||
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
|
|
||||||
|
|
||||||
# test oct literals
|
assert f(1, 2) == 3
|
||||||
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
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user