This commit is contained in:
blueloveTH 2023-07-16 23:18:31 +08:00
parent 9d633c6eb3
commit d5711da2ad
4 changed files with 95 additions and 15 deletions

View File

@ -66,6 +66,32 @@ int test_multiple_return(pkpy_vm* vm) {
return 2; return 2;
} }
int test_minus(pkpy_vm* vm) {
int a, b;
pkpy_to_int(vm, 0, &a);
pkpy_to_int(vm, 1, &b);
pkpy_push_int(vm, a - b);
return 1;
}
int test_fib(pkpy_vm* vm) {
int n;
pkpy_to_int(vm, 0, &n);
if (n == 1) {
pkpy_push_int(vm, n);
} else {
pkpy_getglobal(vm, pkpy_name("test_fib"));
pkpy_push_null(vm);
pkpy_push_int(vm, n-1);
pkpy_vectorcall(vm, 1);
int r_int;
pkpy_to_int(vm, -1, &r_int);
pkpy_pop_top(vm);
pkpy_push_int(vm, r_int + n);
}
return 1;
}
int test_default_argument(pkpy_vm* vm){ int test_default_argument(pkpy_vm* vm){
int x; int x;
pkpy_to_int(vm, -1, &x); pkpy_to_int(vm, -1, &x);
@ -311,6 +337,19 @@ int main(int argc, char** argv) {
check(pkpy_pop_top(vm)); check(pkpy_pop_top(vm));
check(pkpy_stack_size(vm) == 0); check(pkpy_stack_size(vm) == 0);
PRINT_TITLE("test bindings 2");
check(pkpy_push_function(vm, "test_minus(a, b)", test_minus));
check(pkpy_setglobal(vm, pkpy_name("test_minus")));
check(pkpy_exec(vm, "print(test_minus(5, 3))"));
check(pkpy_exec(vm, "for i in range(5): print(test_minus(5, i))"));
check(pkpy_stack_size(vm) == 0);
PRINT_TITLE("test bindings fib");
check(pkpy_push_function(vm, "test_fib(n: int) -> int", test_fib));
check(pkpy_setglobal(vm, pkpy_name("test_fib")));
check(pkpy_exec(vm, "print(test_fib(10))"));
check(pkpy_stack_size(vm) == 0);
PRINT_TITLE("test error propagate"); PRINT_TITLE("test error propagate");
check(pkpy_push_function(vm, "test_error_propagate()", test_error_propagate)); check(pkpy_push_function(vm, "test_error_propagate()", test_error_propagate));
check(pkpy_setglobal(vm, pkpy_name("test_error_propagate"))); check(pkpy_setglobal(vm, pkpy_name("test_error_propagate")));

View File

@ -59,6 +59,17 @@ TypeError: expected 2 positional arguments, got 0 (x)
====== test bindings ====== ====== test bindings ======
12 12
====== test bindings 2 ======
2
5
4
3
2
1
====== test bindings fib ======
55
====== test error propagate ====== ====== test error propagate ======
successfully errored with this message: successfully errored with this message:
Traceback (most recent call last): Traceback (most recent call last):
@ -81,6 +92,10 @@ successfully errored with this message:
TypeError: expected 'int', got 'float' TypeError: expected 'int', got 'float'
====== test complicated errors ====== ====== test complicated errors ======
Traceback (most recent call last):
File "main.py", line 1
test_error_propagate()
NameError: catch me
successfully errored with this message: successfully errored with this message:
Traceback (most recent call last): Traceback (most recent call last):
_: test direct error mechanism _: test direct error mechanism

View File

@ -119,6 +119,7 @@ public:
struct{ struct{
PyObject* error; PyObject* error;
stack<ArgsView> s_view;
} _c; } _c;
PyObject* None; PyObject* None;

View File

@ -21,23 +21,24 @@ static int count_extra_elements(VM* vm, int n){
if(vm->callstack.empty()){ if(vm->callstack.empty()){
return vm->s_data.size(); return vm->s_data.size();
} }
PyObject** base = vm->top_frame()->_locals.end(); PK_ASSERT(!vm->_c.s_view.empty());
return vm->s_data._sp - base; return vm->s_data._sp - vm->_c.s_view.top().end();
} }
static PyObject* stack_item(VM* vm, int index){ static PyObject* stack_item(VM* vm, int index){
PyObject** begin; PyObject** begin;
PyObject** end; PyObject** end = vm->s_data.end();
if(vm->callstack.empty()){ if(vm->callstack.empty()){
begin = vm->s_data.begin(); begin = vm->s_data.begin();
end = vm->s_data.end();
}else{ }else{
Frame* frame = vm->top_frame().get(); PK_ASSERT(!vm->_c.s_view.empty());
begin = frame->_locals.begin(); begin = vm->_c.s_view.top().begin();
end = frame->_locals.end(); }
int size = end - begin;
if(index < 0) index += size;
if(index < 0 || index >= size){
throw std::runtime_error("stack_item() => index out of range");
} }
// may raise
index = vm->normalized_index(index, end-begin);
return begin[index]; return begin[index];
} }
@ -126,7 +127,8 @@ int pkpy_stack_size(pkpy_vm* vm_handle){
if(vm->callstack.empty()){ if(vm->callstack.empty()){
return vm->s_data.size(); return vm->s_data.size();
} }
return vm->top_frame()->stack_size(); PK_ASSERT(!vm->_c.s_view.empty());
return vm->s_data._sp - vm->_c.s_view.top().begin();
} }
// int // int
@ -299,11 +301,31 @@ bool pkpy_push_null(pkpy_vm* vm_handle) {
return true; return true;
} }
struct TempViewPopper{
VM* vm;
bool used;
TempViewPopper(VM* vm): vm(vm), used(false) {}
void restore() noexcept{
if(used) return;
vm->_c.s_view.pop();
used = true;
}
~TempViewPopper(){ restore(); }
};
// function // function
static PyObject* c_function_wrapper(VM* vm, ArgsView args) { static PyObject* c_function_wrapper(VM* vm, ArgsView args) {
LuaStyleFuncC f = lambda_get_userdata<LuaStyleFuncC>(args.begin()); LuaStyleFuncC f = lambda_get_userdata<LuaStyleFuncC>(args.begin());
PyObject** curr_sp = vm->s_data._sp; PyObject** curr_sp = vm->s_data._sp;
int retc = f(vm);
vm->_c.s_view.push(args);
TempViewPopper _tvp(vm);
int retc = f(vm); // may raise, _tvp will handle this via RAII
_tvp.restore();
// propagate_if_errored // propagate_if_errored
if (vm->_c.error != nullptr){ if (vm->_c.error != nullptr){
Exception e = _py_cast<Exception&>(vm, vm->_c.error); Exception e = _py_cast<Exception&>(vm, vm->_c.error);
@ -472,11 +494,14 @@ bool pkpy_clear_error(pkpy_vm* vm_handle, char** message) {
if (message != nullptr) if (message != nullptr)
*message = e.summary().c_str_dup(); *message = e.summary().c_str_dup();
else else
std::cerr << e.summary() << std::endl; std::cout << e.summary() << std::endl;
vm->_c.error = nullptr; vm->_c.error = nullptr;
// clear the whole stack?? if(vm->callstack.empty()){
vm->callstack.clear(); vm->s_data.clear();
vm->s_data.clear(); }else{
PK_ASSERT(!vm->_c.s_view.empty());
vm->s_data.reset(vm->_c.s_view.top().end());
}
return true; return true;
} }