fix exception

This commit is contained in:
blueloveTH 2024-05-26 14:34:54 +08:00
parent 0d4bab9098
commit 360efc0805
7 changed files with 13 additions and 25 deletions

View File

@ -42,13 +42,12 @@ inline const int BC_KEEPLINE = -1;
struct CodeBlock { struct CodeBlock {
CodeBlockType type; CodeBlockType type;
int parent; // parent index in blocks int parent; // parent index in blocks
int base_stack_size; // this is used for exception handling
int start; // start index of this block in codes, inclusive int start; // start index of this block in codes, inclusive
int end; // end index of this block in codes, exclusive int end; // end index of this block in codes, exclusive
int end2; // ... int end2; // ...
CodeBlock(CodeBlockType type, int parent, int base_stack_size, int start): CodeBlock(CodeBlockType type, int parent, int start):
type(type), parent(parent), base_stack_size(base_stack_size), start(start), end(-1), end2(-1) {} type(type), parent(parent), start(start), end(-1), end2(-1) {}
int get_break_end() const{ int get_break_end() const{
if(end2 != -1) return end2; if(end2 != -1) return end2;

View File

@ -104,7 +104,6 @@ struct CodeEmitContext{
int curr_iblock = 0; int curr_iblock = 0;
bool is_compiling_class = false; bool is_compiling_class = false;
int base_stack_size = 0;
std::map<PyVar, int> _co_consts_nonstring_dedup_map; std::map<PyVar, int> _co_consts_nonstring_dedup_map;
std::map<std::string, int, std::less<>> _co_consts_string_dedup_map; std::map<std::string, int, std::less<>> _co_consts_string_dedup_map;

View File

@ -102,8 +102,6 @@ struct Frame {
: _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) {}
PyVar* actual_sp_base() const { return _locals.a; } PyVar* actual_sp_base() const { return _locals.a; }
int stack_size(ValueStack* _s) const { return _s->_sp - actual_sp_base(); }
ArgsView stack_view(ValueStack* _s) const { return ArgsView(actual_sp_base(), _s->_sp); } ArgsView stack_view(ValueStack* _s) const { return ArgsView(actual_sp_base(), _s->_sp); }
[[nodiscard]] int prepare_jump_exception_handler(ValueStack*); [[nodiscard]] int prepare_jump_exception_handler(ValueStack*);

View File

@ -4,7 +4,7 @@ namespace pkpy{
CodeObject::CodeObject(std::shared_ptr<SourceData> src, const Str& name): CodeObject::CodeObject(std::shared_ptr<SourceData> src, const Str& name):
src(src), name(name), nlocals(0), start_line(-1), end_line(-1) { src(src), name(name), nlocals(0), start_line(-1), end_line(-1) {
blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0)); blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0));
} }
PyVar const PY_OP_CALL(Type(), new PyObject(Type())); PyVar const PY_OP_CALL(Type(), new PyObject(Type()));

View File

@ -24,17 +24,13 @@ namespace pkpy{
} }
CodeBlock* CodeEmitContext::enter_block(CodeBlockType type){ CodeBlock* CodeEmitContext::enter_block(CodeBlockType type){
if(type==CodeBlockType::FOR_LOOP || type==CodeBlockType::CONTEXT_MANAGER) base_stack_size++; co->blocks.push_back(CodeBlock(type, curr_iblock, (int)co->codes.size()));
co->blocks.push_back(CodeBlock(
type, curr_iblock, base_stack_size, (int)co->codes.size()
));
curr_iblock = co->blocks.size()-1; curr_iblock = co->blocks.size()-1;
return &co->blocks[curr_iblock]; return &co->blocks[curr_iblock];
} }
void CodeEmitContext::exit_block(){ void CodeEmitContext::exit_block(){
auto curr_type = co->blocks[curr_iblock].type; auto curr_type = co->blocks[curr_iblock].type;
if(curr_type == CodeBlockType::FOR_LOOP || curr_type==CodeBlockType::CONTEXT_MANAGER) base_stack_size--;
co->blocks[curr_iblock].end = co->codes.size(); co->blocks[curr_iblock].end = co->codes.size();
curr_iblock = co->blocks[curr_iblock].parent; curr_iblock = co->blocks[curr_iblock].parent;
if(curr_iblock < 0) PK_FATAL_ERROR(); if(curr_iblock < 0) PK_FATAL_ERROR();

View File

@ -24,20 +24,16 @@ namespace pkpy{
} }
int Frame::prepare_jump_exception_handler(ValueStack* _s){ int Frame::prepare_jump_exception_handler(ValueStack* _s){
PyVar obj = _s->popx();
// try to find a parent try block // try to find a parent try block
int block = co->lines[ip()].iblock; int i = co->lines[ip()].iblock;
while(block >= 0){ while(i >= 0){
if(co->blocks[block].type == CodeBlockType::TRY_EXCEPT) break; if(co->blocks[i].type == CodeBlockType::TRY_EXCEPT) break;
block = co->blocks[block].parent; i = _exit_block(_s, i);
} }
if(block < 0) return -1; _s->push(obj);
PyVar obj = _s->popx(); // pop exception object if(i < 0) return -1;
// get the stack size of the try block return co->blocks[i].end;
int _stack_size = co->blocks[block].base_stack_size;
if(stack_size(_s) < _stack_size) throw std::runtime_error(_S("invalid state: ", stack_size(_s), '<', _stack_size).str());
_s->reset(actual_sp_base() + _locals.size() + _stack_size); // rollback the stack
_s->push(obj); // push exception object
return co->blocks[block].end;
} }
int Frame::_exit_block(ValueStack* _s, int i){ int Frame::_exit_block(ValueStack* _s, int i){

View File

@ -909,7 +909,7 @@ void VM::__init_builtin_types(){
validate(tp_none_type, new_type_object(nullptr, "NoneType", tp_object, false)); validate(tp_none_type, new_type_object(nullptr, "NoneType", tp_object, false));
validate(tp_not_implemented, new_type_object(nullptr, "NotImplementedType", tp_object, false)); validate(tp_not_implemented, new_type_object(nullptr, "NotImplementedType", tp_object, false));
validate(tp_ellipsis, new_type_object(nullptr, "ellipsis", tp_object, false)); validate(tp_ellipsis, new_type_object(nullptr, "ellipsis", tp_object, false));
validate(tp_stack_memory, new_type_object<StackMemory>(nullptr, "stack_memory", tp_object, false)); validate(tp_stack_memory, new_type_object<StackMemory>(nullptr, "_stack_memory", tp_object, false));
// SyntaxError and IndentationError must be created here // SyntaxError and IndentationError must be created here
PyVar SyntaxError = new_type_object(nullptr, "SyntaxError", tp_exception, true); PyVar SyntaxError = new_type_object(nullptr, "SyntaxError", tp_exception, true);