mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
refactor
This commit is contained in:
parent
5e0e2c9c51
commit
9a1a7f92b7
@ -11,9 +11,16 @@ struct NeedMoreLines {
|
|||||||
bool is_compiling_class;
|
bool is_compiling_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HandledException {};
|
enum class InternalExceptionType: int{
|
||||||
struct UnhandledException {};
|
Null, Handled, Unhandled, ToBeRaised
|
||||||
struct ToBeRaisedException {};
|
};
|
||||||
|
|
||||||
|
struct InternalException final{
|
||||||
|
InternalExceptionType type;
|
||||||
|
int arg;
|
||||||
|
InternalException(): type(InternalExceptionType::Null), arg(-1) {}
|
||||||
|
InternalException(InternalExceptionType type, int arg=-1): type(type), arg(arg) {}
|
||||||
|
};
|
||||||
|
|
||||||
enum CompileMode {
|
enum CompileMode {
|
||||||
EXEC_MODE,
|
EXEC_MODE,
|
||||||
|
@ -70,7 +70,6 @@ struct ValueStack {
|
|||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
int _ip;
|
int _ip;
|
||||||
int _next_ip;
|
|
||||||
// This is for unwinding only, use `actual_sp_base()` for value stack access
|
// This is for unwinding only, use `actual_sp_base()` for value stack access
|
||||||
PyVar* _sp_base;
|
PyVar* _sp_base;
|
||||||
|
|
||||||
@ -84,28 +83,29 @@ struct Frame {
|
|||||||
|
|
||||||
// function scope
|
// function scope
|
||||||
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, PyVar* _locals_base)
|
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, PyVar* _locals_base)
|
||||||
: _ip(-1), _next_ip(0), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base) { }
|
: _ip(-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base) { }
|
||||||
|
|
||||||
// exec/eval
|
// exec/eval
|
||||||
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, FastLocals _locals)
|
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, FastLocals _locals)
|
||||||
: _ip(-1), _next_ip(0), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals) { }
|
: _ip(-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals) { }
|
||||||
|
|
||||||
// global scope
|
// global scope
|
||||||
Frame(PyVar* p0, const CodeObject_& co, PyVar _module)
|
Frame(PyVar* p0, const CodeObject_& co, PyVar _module)
|
||||||
: _ip(-1), _next_ip(0), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0) {}
|
: _ip(-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(); }
|
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); }
|
||||||
|
|
||||||
void jump_abs(int i){ _next_ip = i; }
|
[[nodiscard]] int prepare_jump_exception_handler(ValueStack*);
|
||||||
bool jump_to_exception_handler(ValueStack*);
|
void prepare_jump_break(ValueStack*, int);
|
||||||
int _exit_block(ValueStack*, int);
|
int _exit_block(ValueStack*, int);
|
||||||
void jump_abs_break(ValueStack*, int);
|
|
||||||
|
|
||||||
void loop_break(ValueStack* s_data, const CodeObject*){
|
[[nodiscard]] int prepare_loop_break(ValueStack* s_data){
|
||||||
jump_abs_break(s_data, co->_get_block_codei(_ip).end);
|
int target = co->_get_block_codei(_ip).end;
|
||||||
|
prepare_jump_break(s_data, target);
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
int curr_lineno() const { return co->lines[_ip].lineno; }
|
int curr_lineno() const { return co->lines[_ip].lineno; }
|
||||||
|
@ -157,6 +157,7 @@ public:
|
|||||||
std::map<std::string_view, CodeObject_> __cached_codes;
|
std::map<std::string_view, CodeObject_> __cached_codes;
|
||||||
std::map<std::string_view, PyVar> __cached_op_funcs;
|
std::map<std::string_view, PyVar> __cached_op_funcs;
|
||||||
FuncDecl_ __dynamic_func_decl;
|
FuncDecl_ __dynamic_func_decl;
|
||||||
|
InternalException __internal_exception;
|
||||||
PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||||
|
|
||||||
#if PK_ENABLE_PROFILER
|
#if PK_ENABLE_PROFILER
|
||||||
|
200
src/ceval.cpp
200
src/ceval.cpp
@ -81,22 +81,6 @@ bool VM::py_ge(PyVar _0, PyVar _1){
|
|||||||
|
|
||||||
#undef BINARY_F_COMPARE
|
#undef BINARY_F_COMPARE
|
||||||
|
|
||||||
PyVar VM::__run_top_frame(){
|
|
||||||
Frame* frame = &callstack.top();
|
|
||||||
const Frame* base_frame = frame;
|
|
||||||
bool need_raise = false;
|
|
||||||
|
|
||||||
while(true){
|
|
||||||
try{
|
|
||||||
if(need_raise){ need_raise = false; __raise_exc(); }
|
|
||||||
/**********************************************************************/
|
|
||||||
/* NOTE:
|
|
||||||
* Be aware of accidental gc!
|
|
||||||
* DO NOT leave any strong reference of PyVar in the C stack
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
#if PK_ENABLE_PROFILER
|
#if PK_ENABLE_PROFILER
|
||||||
#define CEVAL_STEP_CALLBACK() \
|
#define CEVAL_STEP_CALLBACK() \
|
||||||
if(_ceval_on_step) _ceval_on_step(this, frame, byte); \
|
if(_ceval_on_step) _ceval_on_step(this, frame, byte); \
|
||||||
@ -109,17 +93,38 @@ PyVar VM::__run_top_frame(){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DISPATCH() goto __NEXT_STEP;
|
#define DISPATCH() { frame->_ip++; goto __NEXT_STEP; }
|
||||||
|
#define DISPATCH_JUMP(__target) { frame->_ip = __target; goto __NEXT_STEP; }
|
||||||
|
#define RETURN_OP_YIELD() { frame->_ip++; return PY_OP_YIELD; }
|
||||||
|
|
||||||
|
PyVar VM::__run_top_frame(){
|
||||||
|
Frame* frame = &callstack.top();
|
||||||
|
const Frame* base_frame = frame;
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
try{
|
||||||
|
/**********************************************************************/
|
||||||
|
{
|
||||||
__NEXT_FRAME:
|
__NEXT_FRAME:
|
||||||
const CodeObject* co = frame->co;
|
if(__internal_exception.type == InternalExceptionType::Null){
|
||||||
|
// None
|
||||||
|
frame->_ip++;
|
||||||
|
}else if(__internal_exception.type == InternalExceptionType::Handled){
|
||||||
|
// HandledException + continue
|
||||||
|
frame->_ip = __internal_exception.arg;
|
||||||
|
__internal_exception = {};
|
||||||
|
}else{
|
||||||
|
// UnhandledException + continue (need_raise = true)
|
||||||
|
// ToBeRaisedException + continue (need_raise = true)
|
||||||
|
__internal_exception = {};
|
||||||
|
__raise_exc(); // no return
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: when jit is enabled, co_codes may not be const
|
// TODO: when jit is enabled, co_codes may not be const
|
||||||
const Bytecode* co_codes = co->codes.data();
|
const Bytecode* co_codes = frame->co->codes.data();
|
||||||
Bytecode byte;
|
Bytecode byte;
|
||||||
|
|
||||||
__NEXT_STEP:
|
__NEXT_STEP:
|
||||||
frame->_ip = frame->_next_ip;
|
|
||||||
frame->_next_ip++;
|
|
||||||
byte = co_codes[frame->_ip];
|
byte = co_codes[frame->_ip];
|
||||||
CEVAL_STEP_CALLBACK()
|
CEVAL_STEP_CALLBACK()
|
||||||
|
|
||||||
@ -139,13 +144,13 @@ __NEXT_STEP:
|
|||||||
SECOND() = THIRD();
|
SECOND() = THIRD();
|
||||||
THIRD() = _0;
|
THIRD() = _0;
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_PRINT_EXPR:{
|
case OP_PRINT_EXPR:
|
||||||
if(TOP() != None) stdout_write(py_repr(TOP()) + "\n");
|
if(TOP() != None) stdout_write(py_repr(TOP()) + "\n");
|
||||||
POP();
|
POP();
|
||||||
} DISPATCH()
|
DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_CONST:
|
case OP_LOAD_CONST:
|
||||||
PUSH(co->consts[byte.arg]);
|
PUSH(frame->co->consts[byte.arg]);
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_LOAD_NONE: PUSH(None); DISPATCH()
|
case OP_LOAD_NONE: PUSH(None); DISPATCH()
|
||||||
case OP_LOAD_TRUE: PUSH(True); DISPATCH()
|
case OP_LOAD_TRUE: PUSH(True); DISPATCH()
|
||||||
@ -155,7 +160,7 @@ __NEXT_STEP:
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
|
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
|
||||||
case OP_LOAD_FUNCTION: {
|
case OP_LOAD_FUNCTION: {
|
||||||
const FuncDecl_& decl = co->func_decls[byte.arg];
|
const FuncDecl_& decl = frame->co->func_decls[byte.arg];
|
||||||
PyVar obj;
|
PyVar obj;
|
||||||
if(decl->nested){
|
if(decl->nested){
|
||||||
NameDict_ captured = frame->_locals.to_namedict();
|
NameDict_ captured = frame->_locals.to_namedict();
|
||||||
@ -170,7 +175,7 @@ __NEXT_STEP:
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_FAST: {
|
case OP_LOAD_FAST: {
|
||||||
PyVar _0 = frame->_locals[byte.arg];
|
PyVar _0 = frame->_locals[byte.arg];
|
||||||
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
if(_0 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_LOAD_NAME: {
|
case OP_LOAD_NAME: {
|
||||||
@ -239,7 +244,7 @@ __NEXT_STEP:
|
|||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_LOAD_SUBSCR_FAST:{
|
case OP_LOAD_SUBSCR_FAST:{
|
||||||
PyVar _1 = frame->_locals[byte.arg];
|
PyVar _1 = frame->_locals[byte.arg];
|
||||||
if(_1 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
if(_1 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
||||||
PyVar _0 = TOP(); // a
|
PyVar _0 = TOP(); // a
|
||||||
auto _ti = _tp_info(_0);
|
auto _ti = _tp_info(_0);
|
||||||
if(_ti->m__getitem__){
|
if(_ti->m__getitem__){
|
||||||
@ -303,7 +308,7 @@ __NEXT_STEP:
|
|||||||
}DISPATCH()
|
}DISPATCH()
|
||||||
case OP_STORE_SUBSCR_FAST:{
|
case OP_STORE_SUBSCR_FAST:{
|
||||||
PyVar _2 = frame->_locals[byte.arg]; // b
|
PyVar _2 = frame->_locals[byte.arg]; // b
|
||||||
if(_2 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
if(_2 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
||||||
PyVar _1 = POPX(); // a
|
PyVar _1 = POPX(); // a
|
||||||
PyVar _0 = POPX(); // val
|
PyVar _0 = POPX(); // val
|
||||||
auto _ti = _tp_info(_1);
|
auto _ti = _tp_info(_1);
|
||||||
@ -315,7 +320,7 @@ __NEXT_STEP:
|
|||||||
}DISPATCH()
|
}DISPATCH()
|
||||||
case OP_DELETE_FAST:{
|
case OP_DELETE_FAST:{
|
||||||
PyVar _0 = frame->_locals[byte.arg];
|
PyVar _0 = frame->_locals[byte.arg];
|
||||||
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
if(_0 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
||||||
frame->_locals[byte.arg] = PY_NULL;
|
frame->_locals[byte.arg] = PY_NULL;
|
||||||
}DISPATCH()
|
}DISPATCH()
|
||||||
case OP_DELETE_NAME:{
|
case OP_DELETE_NAME:{
|
||||||
@ -626,49 +631,45 @@ __NEXT_STEP:
|
|||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_JUMP_ABSOLUTE:
|
case OP_JUMP_ABSOLUTE:
|
||||||
frame->jump_abs(byte.arg);
|
DISPATCH_JUMP(byte.arg)
|
||||||
DISPATCH()
|
|
||||||
case OP_JUMP_ABSOLUTE_TOP:
|
case OP_JUMP_ABSOLUTE_TOP:
|
||||||
frame->jump_abs(_CAST(int, POPX()));
|
DISPATCH_JUMP(_CAST(int, POPX()))
|
||||||
|
case OP_POP_JUMP_IF_FALSE:
|
||||||
|
if(!py_bool(POPX())) DISPATCH_JUMP(byte.arg)
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_POP_JUMP_IF_FALSE:{
|
case OP_POP_JUMP_IF_TRUE:
|
||||||
if(!py_bool(TOP())) frame->jump_abs(byte.arg);
|
if(py_bool(POPX())) DISPATCH_JUMP(byte.arg)
|
||||||
POP();
|
DISPATCH()
|
||||||
} DISPATCH()
|
case OP_JUMP_IF_TRUE_OR_POP:
|
||||||
case OP_POP_JUMP_IF_TRUE:{
|
if(py_bool(POPX())) DISPATCH_JUMP(byte.arg)
|
||||||
if(py_bool(TOP())) frame->jump_abs(byte.arg);
|
DISPATCH()
|
||||||
POP();
|
case OP_JUMP_IF_FALSE_OR_POP:
|
||||||
} DISPATCH()
|
if(!py_bool(POPX())) DISPATCH_JUMP(byte.arg)
|
||||||
case OP_JUMP_IF_TRUE_OR_POP:{
|
DISPATCH()
|
||||||
if(py_bool(TOP())) frame->jump_abs(byte.arg);
|
case OP_SHORTCUT_IF_FALSE_OR_POP:
|
||||||
else POP();
|
|
||||||
} DISPATCH()
|
|
||||||
case OP_JUMP_IF_FALSE_OR_POP:{
|
|
||||||
if(!py_bool(TOP())) frame->jump_abs(byte.arg);
|
|
||||||
else POP();
|
|
||||||
} DISPATCH()
|
|
||||||
case OP_SHORTCUT_IF_FALSE_OR_POP:{
|
|
||||||
if(!py_bool(TOP())){ // [b, False]
|
if(!py_bool(TOP())){ // [b, False]
|
||||||
STACK_SHRINK(2); // []
|
STACK_SHRINK(2); // []
|
||||||
PUSH(vm->False); // [False]
|
PUSH(vm->False); // [False]
|
||||||
frame->jump_abs(byte.arg);
|
DISPATCH_JUMP(byte.arg)
|
||||||
} else POP(); // [b]
|
} else{
|
||||||
} DISPATCH()
|
POP(); // [b]
|
||||||
|
DISPATCH()
|
||||||
|
}
|
||||||
case OP_LOOP_CONTINUE:
|
case OP_LOOP_CONTINUE:
|
||||||
frame->jump_abs(byte.arg);
|
DISPATCH_JUMP(byte.arg)
|
||||||
DISPATCH()
|
|
||||||
case OP_LOOP_BREAK:
|
case OP_LOOP_BREAK:
|
||||||
frame->jump_abs_break(&s_data, byte.arg);
|
frame->prepare_jump_break(&s_data, byte.arg);
|
||||||
DISPATCH()
|
DISPATCH_JUMP(byte.arg)
|
||||||
case OP_GOTO: {
|
case OP_GOTO: {
|
||||||
StrName _name(byte.arg);
|
StrName _name(byte.arg);
|
||||||
int index = co->labels.try_get_likely_found(_name);
|
int target = frame->co->labels.try_get_likely_found(_name);
|
||||||
if(index < 0) RuntimeError(_S("label ", _name.escape(), " not found"));
|
if(target < 0) RuntimeError(_S("label ", _name.escape(), " not found"));
|
||||||
frame->jump_abs_break(&s_data, index);
|
frame->prepare_jump_break(&s_data, target);
|
||||||
} DISPATCH()
|
DISPATCH_JUMP(target)
|
||||||
|
}
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_FSTRING_EVAL:{
|
case OP_FSTRING_EVAL:{
|
||||||
PyVar _0 = co->consts[byte.arg];
|
PyVar _0 = frame->co->consts[byte.arg];
|
||||||
std::string_view string = CAST(Str&, _0).sv();
|
std::string_view string = CAST(Str&, _0).sv();
|
||||||
auto it = __cached_codes.find(string);
|
auto it = __cached_codes.find(string);
|
||||||
CodeObject_ code;
|
CodeObject_ code;
|
||||||
@ -743,8 +744,7 @@ __NEXT_STEP:
|
|||||||
goto __NEXT_FRAME;
|
goto __NEXT_FRAME;
|
||||||
}
|
}
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_YIELD_VALUE:
|
case OP_YIELD_VALUE: RETURN_OP_YIELD()
|
||||||
return PY_OP_YIELD;
|
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LIST_APPEND:{
|
case OP_LIST_APPEND:{
|
||||||
PyVar _0 = POPX();
|
PyVar _0 = POPX();
|
||||||
@ -785,34 +785,44 @@ __NEXT_STEP:
|
|||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_FOR_ITER:{
|
case OP_FOR_ITER:{
|
||||||
PyVar _0 = py_next(TOP());
|
PyVar _0 = py_next(TOP());
|
||||||
if(_0 == StopIteration) frame->loop_break(&s_data, co);
|
if(_0 == StopIteration){
|
||||||
else PUSH(_0);
|
int target = frame->prepare_loop_break(&s_data);
|
||||||
} DISPATCH()
|
DISPATCH_JUMP(target)
|
||||||
|
} else{
|
||||||
|
PUSH(_0);
|
||||||
|
DISPATCH()
|
||||||
|
}
|
||||||
|
}
|
||||||
case OP_FOR_ITER_STORE_FAST:{
|
case OP_FOR_ITER_STORE_FAST:{
|
||||||
PyVar _0 = py_next(TOP());
|
PyVar _0 = py_next(TOP());
|
||||||
if(_0 == StopIteration){
|
if(_0 == StopIteration){
|
||||||
frame->loop_break(&s_data, co);
|
int target = frame->prepare_loop_break(&s_data);
|
||||||
|
DISPATCH_JUMP(target)
|
||||||
}else{
|
}else{
|
||||||
frame->_locals[byte.arg] = _0;
|
frame->_locals[byte.arg] = _0;
|
||||||
|
DISPATCH()
|
||||||
}
|
}
|
||||||
} DISPATCH()
|
}
|
||||||
case OP_FOR_ITER_STORE_GLOBAL:{
|
case OP_FOR_ITER_STORE_GLOBAL:{
|
||||||
PyVar _0 = py_next(TOP());
|
PyVar _0 = py_next(TOP());
|
||||||
if(_0 == StopIteration){
|
if(_0 == StopIteration){
|
||||||
frame->loop_break(&s_data, co);
|
int target = frame->prepare_loop_break(&s_data);
|
||||||
|
DISPATCH_JUMP(target)
|
||||||
}else{
|
}else{
|
||||||
frame->f_globals().set(StrName(byte.arg), _0);
|
frame->f_globals().set(StrName(byte.arg), _0);
|
||||||
|
DISPATCH()
|
||||||
}
|
}
|
||||||
} DISPATCH()
|
}
|
||||||
case OP_FOR_ITER_YIELD_VALUE:{
|
case OP_FOR_ITER_YIELD_VALUE:{
|
||||||
PyVar _0 = py_next(TOP());
|
PyVar _0 = py_next(TOP());
|
||||||
if(_0 == StopIteration){
|
if(_0 == StopIteration){
|
||||||
frame->loop_break(&s_data, co);
|
int target = frame->prepare_loop_break(&s_data);
|
||||||
|
DISPATCH_JUMP(target)
|
||||||
}else{
|
}else{
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
return PY_OP_YIELD;
|
RETURN_OP_YIELD()
|
||||||
}
|
}
|
||||||
} DISPATCH()
|
}
|
||||||
case OP_FOR_ITER_UNPACK:{
|
case OP_FOR_ITER_UNPACK:{
|
||||||
PyVar _0 = TOP();
|
PyVar _0 = TOP();
|
||||||
const PyTypeInfo* _ti = _tp_info(_0);
|
const PyTypeInfo* _ti = _tp_info(_0);
|
||||||
@ -820,7 +830,8 @@ __NEXT_STEP:
|
|||||||
unsigned n = _ti->m__next__(this, _0);
|
unsigned n = _ti->m__next__(this, _0);
|
||||||
if(n == 0){
|
if(n == 0){
|
||||||
// StopIteration
|
// StopIteration
|
||||||
frame->loop_break(&s_data, co);
|
int target = frame->prepare_loop_break(&s_data);
|
||||||
|
DISPATCH_JUMP(target)
|
||||||
}else if(n == 1){
|
}else if(n == 1){
|
||||||
// UNPACK_SEQUENCE
|
// UNPACK_SEQUENCE
|
||||||
__op_unpack_sequence(byte.arg);
|
__op_unpack_sequence(byte.arg);
|
||||||
@ -837,13 +848,14 @@ __NEXT_STEP:
|
|||||||
// UNPACK_SEQUENCE
|
// UNPACK_SEQUENCE
|
||||||
__op_unpack_sequence(byte.arg);
|
__op_unpack_sequence(byte.arg);
|
||||||
}else{
|
}else{
|
||||||
frame->loop_break(&s_data, co);
|
int target = frame->prepare_loop_break(&s_data);
|
||||||
|
DISPATCH_JUMP(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_IMPORT_PATH:{
|
case OP_IMPORT_PATH:{
|
||||||
PyVar _0 = co->consts[byte.arg];
|
PyVar _0 = frame->co->consts[byte.arg];
|
||||||
PUSH(py_import(CAST(Str&, _0)));
|
PUSH(py_import(CAST(Str&, _0)));
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_POP_IMPORT_STAR: {
|
case OP_POP_IMPORT_STAR: {
|
||||||
@ -970,18 +982,18 @@ __NEXT_STEP:
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_FORMAT_STRING: {
|
case OP_FORMAT_STRING: {
|
||||||
PyVar _0 = POPX();
|
PyVar _0 = POPX();
|
||||||
const Str& spec = CAST(Str&, co->consts[byte.arg]);
|
const Str& spec = CAST(Str&, frame->co->consts[byte.arg]);
|
||||||
PUSH(__format_object(_0, spec));
|
PUSH(__format_object(_0, spec));
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_INC_FAST:{
|
case OP_INC_FAST:{
|
||||||
PyVar* p = &frame->_locals[byte.arg];
|
PyVar* p = &frame->_locals[byte.arg];
|
||||||
if(*p == PY_NULL) vm->NameError(co->varnames[byte.arg]);
|
if(*p == PY_NULL) vm->NameError(frame->co->varnames[byte.arg]);
|
||||||
*p = VAR(CAST(i64, *p) + 1);
|
*p = VAR(CAST(i64, *p) + 1);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_DEC_FAST:{
|
case OP_DEC_FAST:{
|
||||||
PyVar* p = &frame->_locals[byte.arg];
|
PyVar* p = &frame->_locals[byte.arg];
|
||||||
if(*p == PY_NULL) vm->NameError(co->varnames[byte.arg]);
|
if(*p == PY_NULL) vm->NameError(frame->co->varnames[byte.arg]);
|
||||||
*p = VAR(CAST(i64, *p) - 1);
|
*p = VAR(CAST(i64, *p) - 1);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_INC_GLOBAL:{
|
case OP_INC_GLOBAL:{
|
||||||
@ -1002,20 +1014,20 @@ __NEXT_STEP:
|
|||||||
}
|
}
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
PK_UNREACHABLE();
|
PK_UNREACHABLE();
|
||||||
}catch(HandledException){
|
}catch(InternalException internal){
|
||||||
continue;
|
this->__internal_exception = internal;
|
||||||
}catch(UnhandledException){
|
if(internal.type == InternalExceptionType::Unhandled){
|
||||||
PyVar e_obj = POPX();
|
PyVar e_obj = POPX();
|
||||||
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
||||||
bool is_base_frame_to_be_popped = frame == base_frame;
|
bool is_base_frame_to_be_popped = frame == base_frame;
|
||||||
__pop_frame();
|
__pop_frame();
|
||||||
if(callstack.empty()) throw _e; // propagate to the top level
|
if(callstack.empty()) throw _e; // propagate to the top level
|
||||||
frame = &callstack.top();
|
frame = &callstack.top();
|
||||||
PUSH(e_obj);
|
PUSH(e_obj);
|
||||||
if(is_base_frame_to_be_popped) throw ToBeRaisedException();
|
if(is_base_frame_to_be_popped){
|
||||||
need_raise = true;
|
throw InternalException(InternalExceptionType::ToBeRaised);
|
||||||
}catch(ToBeRaisedException){
|
}
|
||||||
need_raise = true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1030,6 +1042,8 @@ __NEXT_STEP:
|
|||||||
#undef STACK_VIEW
|
#undef STACK_VIEW
|
||||||
|
|
||||||
#undef DISPATCH
|
#undef DISPATCH
|
||||||
|
#undef DISPATCH_JUMP
|
||||||
|
#undef RETURN_OP_YIELD
|
||||||
#undef CEVAL_STEP_CALLBACK
|
#undef CEVAL_STEP_CALLBACK
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -23,22 +23,21 @@ namespace pkpy{
|
|||||||
return fn._closure->try_get(name);
|
return fn._closure->try_get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Frame::jump_to_exception_handler(ValueStack* _s){
|
int Frame::prepare_jump_exception_handler(ValueStack* _s){
|
||||||
// try to find a parent try block
|
// try to find a parent try block
|
||||||
int block = co->iblocks[_ip];
|
int block = co->iblocks[_ip];
|
||||||
while(block >= 0){
|
while(block >= 0){
|
||||||
if(co->blocks[block].type == CodeBlockType::TRY_EXCEPT) break;
|
if(co->blocks[block].type == CodeBlockType::TRY_EXCEPT) break;
|
||||||
block = co->blocks[block].parent;
|
block = co->blocks[block].parent;
|
||||||
}
|
}
|
||||||
if(block < 0) return false;
|
if(block < 0) return -1;
|
||||||
PyVar obj = _s->popx(); // pop exception object
|
PyVar obj = _s->popx(); // pop exception object
|
||||||
// get the stack size of the try block
|
// get the stack size of the try block
|
||||||
int _stack_size = co->blocks[block].base_stack_size;
|
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());
|
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->reset(actual_sp_base() + _locals.size() + _stack_size); // rollback the stack
|
||||||
_s->push(obj); // push exception object
|
_s->push(obj); // push exception object
|
||||||
_next_ip = co->blocks[block].end;
|
return co->blocks[block].end;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Frame::_exit_block(ValueStack* _s, int i){
|
int Frame::_exit_block(ValueStack* _s, int i){
|
||||||
@ -47,10 +46,9 @@ namespace pkpy{
|
|||||||
return co->blocks[i].parent;
|
return co->blocks[i].parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::jump_abs_break(ValueStack* _s, int target){
|
void Frame::prepare_jump_break(ValueStack* _s, int target){
|
||||||
int i = co->iblocks[_ip];
|
int i = co->iblocks[_ip];
|
||||||
_next_ip = target;
|
if(target >= co->codes.size()){
|
||||||
if(_next_ip >= co->codes.size()){
|
|
||||||
while(i>=0) i = _exit_block(_s, i);
|
while(i>=0) i = _exit_block(_s, i);
|
||||||
}else{
|
}else{
|
||||||
// BUG (solved)
|
// BUG (solved)
|
||||||
|
11
src/vm.cpp
11
src/vm.cpp
@ -425,7 +425,7 @@ bool VM::__py_bool_non_trivial(PyVar obj){
|
|||||||
PyVar len_f = get_unbound_method(obj, __len__, &self, false);
|
PyVar len_f = get_unbound_method(obj, __len__, &self, false);
|
||||||
if(self != PY_NULL){
|
if(self != PY_NULL){
|
||||||
PyVar ret = call_method(self, len_f);
|
PyVar ret = call_method(self, len_f);
|
||||||
return CAST(i64, ret) > 0;
|
return CAST(i64, ret) != 0;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1398,7 +1398,7 @@ void VM::__raise_exc(bool re_raise){
|
|||||||
e._ip_on_error = frame->_ip;
|
e._ip_on_error = frame->_ip;
|
||||||
e._code_on_error = (void*)frame->co;
|
e._code_on_error = (void*)frame->co;
|
||||||
}
|
}
|
||||||
bool ok = frame->jump_to_exception_handler(&s_data);
|
int next_ip = frame->prepare_jump_exception_handler(&s_data);
|
||||||
|
|
||||||
int actual_ip = frame->_ip;
|
int actual_ip = frame->_ip;
|
||||||
if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error;
|
if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error;
|
||||||
@ -1407,8 +1407,11 @@ void VM::__raise_exc(bool re_raise){
|
|||||||
if(frame->_callable == nullptr) current_f_name = ""; // not in a function
|
if(frame->_callable == nullptr) current_f_name = ""; // not in a function
|
||||||
e.st_push(frame->co->src, current_line, nullptr, current_f_name);
|
e.st_push(frame->co->src, current_line, nullptr, current_f_name);
|
||||||
|
|
||||||
if(ok) throw HandledException();
|
if(next_ip >= 0){
|
||||||
else throw UnhandledException();
|
throw InternalException(InternalExceptionType::Handled, next_ip);
|
||||||
|
}else{
|
||||||
|
throw InternalException(InternalExceptionType::Unhandled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManagedHeap::mark() {
|
void ManagedHeap::mark() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user