mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
fix bugs
This commit is contained in:
parent
360efc0805
commit
c680da3154
@ -150,4 +150,20 @@ PK_EXPORT bool pkpy_is_none(pkpy_vm*, int i);
|
||||
|
||||
```
|
||||
[value] -> [repr(value)]
|
||||
```
|
||||
```
|
||||
|
||||
+ `bool pkpy_py_str(pkpy_vm*)`
|
||||
|
||||
Get the str of the value at the top of the stack.
|
||||
|
||||
```
|
||||
[value] -> [str(value)]
|
||||
```
|
||||
|
||||
+ `bool pkpy_py_import(pkpy_vm*, const char* name)`
|
||||
|
||||
Import a module and push it onto the stack.
|
||||
|
||||
```
|
||||
[] -> [module]
|
||||
```
|
||||
|
@ -75,6 +75,14 @@ struct ValueStack {
|
||||
ValueStack& operator=(ValueStack&&) = delete;
|
||||
};
|
||||
|
||||
struct UnwindTarget{
|
||||
UnwindTarget* next;
|
||||
int iblock;
|
||||
int offset;
|
||||
|
||||
UnwindTarget(int iblock, int offset): next(nullptr), iblock(iblock), offset(offset) {}
|
||||
};
|
||||
|
||||
struct Frame {
|
||||
const Bytecode* _ip;
|
||||
// This is for unwinding only, use `actual_sp_base()` for value stack access
|
||||
@ -85,21 +93,24 @@ struct Frame {
|
||||
PyVar _callable; // a function object or nullptr (global scope)
|
||||
FastLocals _locals;
|
||||
|
||||
// This list will be freed in __pop_frame
|
||||
UnwindTarget* _uw_list;
|
||||
|
||||
NameDict& f_globals() { return _module->attr(); }
|
||||
PyVar f_closure_try_get(StrName name);
|
||||
int ip() const { return _ip - co->codes.data(); }
|
||||
|
||||
// function scope
|
||||
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, PyVar* _locals_base)
|
||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base) { }
|
||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base), _uw_list(nullptr) { }
|
||||
|
||||
// exec/eval
|
||||
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, FastLocals _locals)
|
||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals) { }
|
||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals), _uw_list(nullptr) { }
|
||||
|
||||
// global scope
|
||||
Frame(PyVar* p0, const CodeObject_& co, PyVar _module)
|
||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0) {}
|
||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0), _uw_list(nullptr) { }
|
||||
|
||||
PyVar* actual_sp_base() const { return _locals.a; }
|
||||
ArgsView stack_view(ValueStack* _s) const { return ArgsView(actual_sp_base(), _s->_sp); }
|
||||
@ -116,6 +127,10 @@ struct Frame {
|
||||
|
||||
int curr_lineno() const { return co->lines[ip()].lineno; }
|
||||
|
||||
void set_unwind_target(PyVar* _sp);
|
||||
UnwindTarget* find_unwind_target(int iblock);
|
||||
void free_unwind_target();
|
||||
|
||||
void _gc_mark(VM* vm) const;
|
||||
};
|
||||
|
||||
|
@ -140,6 +140,7 @@ OPCODE(ADD_CLASS_ANNOTATION)
|
||||
OPCODE(WITH_ENTER)
|
||||
OPCODE(WITH_EXIT)
|
||||
/**************************/
|
||||
OPCODE(TRY_ENTER)
|
||||
OPCODE(EXCEPTION_MATCH)
|
||||
OPCODE(RAISE)
|
||||
OPCODE(RAISE_ASSERT)
|
||||
|
@ -77,6 +77,7 @@ PK_EXPORT bool pkpy_unpack_sequence(pkpy_vm*, int size);
|
||||
PK_EXPORT bool pkpy_get_unbound_method(pkpy_vm*, pkpy_CName name);
|
||||
PK_EXPORT bool pkpy_py_repr(pkpy_vm*);
|
||||
PK_EXPORT bool pkpy_py_str(pkpy_vm*);
|
||||
PK_EXPORT bool pkpy_py_import(pkpy_vm*, pkpy_CString name);
|
||||
|
||||
/* Error Handling */
|
||||
PK_EXPORT bool pkpy_error(pkpy_vm*, const char* name, pkpy_CString msg);
|
||||
|
@ -986,6 +986,10 @@ __NEXT_STEP:
|
||||
POP();
|
||||
DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_TRY_ENTER: {
|
||||
frame->set_unwind_target(s_data._sp);
|
||||
DISPATCH()
|
||||
}
|
||||
case OP_EXCEPTION_MATCH: {
|
||||
PyVar assumed_type = POPX();
|
||||
check_type(assumed_type, tp_type);
|
||||
|
@ -703,6 +703,7 @@ __EAT_DOTS_END:
|
||||
|
||||
void Compiler::compile_try_except() {
|
||||
ctx()->enter_block(CodeBlockType::TRY_EXCEPT);
|
||||
ctx()->emit_(OP_TRY_ENTER, BC_NOARG, prev().line);
|
||||
compile_block_body();
|
||||
small_vector_2<int, 6> patches;
|
||||
patches.push_back(
|
||||
|
@ -24,15 +24,17 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
int Frame::prepare_jump_exception_handler(ValueStack* _s){
|
||||
PyVar obj = _s->popx();
|
||||
// try to find a parent try block
|
||||
int i = co->lines[ip()].iblock;
|
||||
while(i >= 0){
|
||||
if(co->blocks[i].type == CodeBlockType::TRY_EXCEPT) break;
|
||||
i = _exit_block(_s, i);
|
||||
i = co->blocks[i].parent;
|
||||
}
|
||||
_s->push(obj);
|
||||
if(i < 0) return -1;
|
||||
PyVar obj = _s->popx(); // pop exception object
|
||||
UnwindTarget* uw = find_unwind_target(i);
|
||||
_s->reset(actual_sp_base() + uw->offset); // unwind the stack
|
||||
_s->push(obj); // push it back
|
||||
return co->blocks[i].end;
|
||||
}
|
||||
|
||||
@ -69,4 +71,32 @@ namespace pkpy{
|
||||
}
|
||||
}
|
||||
|
||||
void Frame::set_unwind_target(PyVar* _sp){
|
||||
int iblock = co->lines[ip()].iblock;
|
||||
UnwindTarget* existing = find_unwind_target(iblock);
|
||||
if(existing){
|
||||
existing->offset = _sp - actual_sp_base();
|
||||
}else{
|
||||
UnwindTarget* prev = _uw_list;
|
||||
_uw_list = new UnwindTarget(iblock, _sp - actual_sp_base());
|
||||
_uw_list->next = prev;
|
||||
}
|
||||
}
|
||||
|
||||
UnwindTarget* Frame::find_unwind_target(int iblock){
|
||||
UnwindTarget* p;
|
||||
for(p=_uw_list; p!=nullptr; p=p->next){
|
||||
if(p->iblock == iblock) return p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Frame::free_unwind_target(){
|
||||
while(_uw_list != nullptr){
|
||||
UnwindTarget* p = _uw_list;
|
||||
_uw_list = p->next;
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
11
src/iter.cpp
11
src/iter.cpp
@ -55,6 +55,17 @@ namespace pkpy{
|
||||
frame._locals.a = vm->s_data._sp;
|
||||
// restore the context
|
||||
for(PyVar obj: s_backup) vm->s_data.push(obj);
|
||||
// relocate stack objects (their addresses become invalid)
|
||||
for(PyVar* p=frame.actual_sp_base(); p!=vm->s_data.end(); p++){
|
||||
if(p->type == VM::tp_stack_memory){
|
||||
// TODO: refactor this
|
||||
int count = p->as<StackMemory>().count;
|
||||
if(count < 0){
|
||||
void* new_p = p + count;
|
||||
p[1]._1 = reinterpret_cast<i64>(new_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
s_backup.clear();
|
||||
vm->callstack.emplace(std::move(frame));
|
||||
|
||||
|
@ -489,6 +489,16 @@ bool pkpy_py_str(pkpy_vm* vm_handle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pkpy_py_import(pkpy_vm* vm_handle, pkpy_CString name) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyVar module = vm->py_import(name);
|
||||
vm->s_data.push(module);
|
||||
)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Error Handling */
|
||||
bool pkpy_error(pkpy_vm* vm_handle, const char* name, pkpy_CString message) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
|
@ -1644,7 +1644,9 @@ void NextBreakpoint::_step(VM* vm){
|
||||
#endif
|
||||
|
||||
void VM::__pop_frame(){
|
||||
s_data.reset(callstack.top()._sp_base);
|
||||
Frame& frame = callstack.top();
|
||||
s_data.reset(frame._sp_base);
|
||||
frame.free_unwind_target();
|
||||
callstack.pop();
|
||||
|
||||
#if PK_ENABLE_PROFILER
|
||||
|
@ -65,7 +65,7 @@ int main(int argc, char** argv){
|
||||
pkpy_vm* vm = pkpy_new_vm(true);
|
||||
|
||||
pkpy_push_function(vm, "input(prompt=None) -> str", f_input);
|
||||
pkpy_eval(vm, "__import__('builtins')");
|
||||
pkpy_py_import(vm, "builtins");
|
||||
pkpy_setattr(vm, pkpy_name("input"));
|
||||
|
||||
if(argc == 1){
|
||||
|
@ -203,6 +203,11 @@ bool pkpy_py_str(pkpy_vm* vm) {
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
bool pkpy_py_import(pkpy_vm* vm, pkpy_CString name) {
|
||||
bool returnValue;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
bool pkpy_error(pkpy_vm* vm, const char* name, pkpy_CString msg) {
|
||||
bool returnValue;
|
||||
return returnValue;
|
||||
|
@ -210,9 +210,12 @@ for e in [d, deque('abc'), deque('ab'), deque(), list(d)]:
|
||||
assertEqual(d == e, type(d) == type(e) and list(d) == list(e))
|
||||
assertEqual(d != e, not (type(d) == type(e) and list(d) == list(e)))
|
||||
|
||||
args = map(deque, ('', 'a', 'b', 'ab', 'ba', 'abc', 'xba', 'xabc', 'cba'))
|
||||
for x in args:
|
||||
for y in args:
|
||||
def get_args():
|
||||
args = map(deque, ('', 'a', 'b', 'ab', 'ba', 'abc', 'xba', 'xabc', 'cba'))
|
||||
return args
|
||||
|
||||
for x in get_args():
|
||||
for y in get_args():
|
||||
assertEqual(x == y, list(x) == list(y))
|
||||
assertEqual(x != y, list(x) != list(y))
|
||||
# assertEqual(x < y, list(x) < list(y)) # not currently supported
|
||||
|
@ -1,3 +1,11 @@
|
||||
# multi-loop generator
|
||||
out = []
|
||||
args = map(lambda x: x+1, [1, 2, 3])
|
||||
for x in args:
|
||||
for y in args:
|
||||
out.append((x, y))
|
||||
assert out == [(2, 3), (2, 4)]
|
||||
|
||||
# multi loop bug
|
||||
out = []
|
||||
a = [1, 2]
|
||||
|
Loading…
x
Reference in New Issue
Block a user