mirror of
https://github.com/pocketpy/pocketpy
synced 2025-12-07 18:50:19 +00:00
...
This commit is contained in:
parent
bccabaa872
commit
697c2b0922
326
src/ceval.h
326
src/ceval.h
@ -11,6 +11,10 @@ inline PyObject* VM::_run_top_frame(){
|
|||||||
const int base_id = frame.index;
|
const int base_id = frame.index;
|
||||||
bool need_raise = false;
|
bool need_raise = false;
|
||||||
|
|
||||||
|
// shared registers
|
||||||
|
PyObject *_0, *_1, *_2;
|
||||||
|
StrName _name;
|
||||||
|
|
||||||
while(true){
|
while(true){
|
||||||
#if DEBUG_EXTRA_CHECK
|
#if DEBUG_EXTRA_CHECK
|
||||||
if(frame.index < base_id) FATAL_ERROR();
|
if(frame.index < base_id) FATAL_ERROR();
|
||||||
@ -21,8 +25,6 @@ inline PyObject* VM::_run_top_frame(){
|
|||||||
/* NOTE:
|
/* NOTE:
|
||||||
* Be aware of accidental gc!
|
* Be aware of accidental gc!
|
||||||
* DO NOT leave any strong reference of PyObject* in the C stack
|
* DO NOT leave any strong reference of PyObject* in the C stack
|
||||||
* For example, POPX() returns a strong reference which may be dangerous
|
|
||||||
* `Args` containing strong references is safe if it is passed to `call` or `fast_call`
|
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
#define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
|
#define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
|
||||||
@ -63,11 +65,10 @@ __NEXT_STEP:;
|
|||||||
TARGET(POP_TOP) POP(); DISPATCH();
|
TARGET(POP_TOP) POP(); DISPATCH();
|
||||||
TARGET(DUP_TOP) PUSH(TOP()); DISPATCH();
|
TARGET(DUP_TOP) PUSH(TOP()); DISPATCH();
|
||||||
TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
|
TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
|
||||||
TARGET(PRINT_EXPR) {
|
TARGET(PRINT_EXPR)
|
||||||
PyObject* obj = TOP(); // use top() to avoid accidental gc
|
if(TOP() != None) *_stdout << CAST(Str&, asRepr(TOP())) << '\n';
|
||||||
if(obj != None) *_stdout << CAST(Str&, asRepr(obj)) << '\n';
|
|
||||||
POP();
|
POP();
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(LOAD_CONST)
|
TARGET(LOAD_CONST)
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
@ -93,134 +94,127 @@ __NEXT_STEP:;
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(LOAD_FAST) {
|
TARGET(LOAD_FAST) {
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
PyObject* val = frame->_locals[byte.arg];
|
_0 = frame->_locals[byte.arg];
|
||||||
if(val == nullptr) vm->NameError(co->varnames[byte.arg]);
|
if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]);
|
||||||
PUSH(val);
|
PUSH(_0);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(LOAD_NAME) {
|
TARGET(LOAD_NAME)
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
StrName name(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
PyObject* val;
|
_0 = frame->_locals.try_get(_name);
|
||||||
val = frame->_locals.try_get(name);
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
_0 = frame->_closure.try_get(_name);
|
||||||
val = frame->_closure.try_get(name);
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
_0 = frame->f_globals().try_get(_name);
|
||||||
val = frame->f_globals().try_get(name);
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
_0 = vm->builtins->attr().try_get(_name);
|
||||||
val = vm->builtins->attr().try_get(name);
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
vm->NameError(_name);
|
||||||
vm->NameError(name);
|
DISPATCH();
|
||||||
} DISPATCH();
|
|
||||||
TARGET(LOAD_NONLOCAL) {
|
TARGET(LOAD_NONLOCAL) {
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
StrName name(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
PyObject* val;
|
// _0 = frame->_locals.try_get(_name);
|
||||||
val = frame->_closure.try_get(name);
|
// if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
_0 = frame->_closure.try_get(_name);
|
||||||
val = frame->f_globals().try_get(name);
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
_0 = frame->f_globals().try_get(_name);
|
||||||
val = vm->builtins->attr().try_get(name);
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
_0 = vm->builtins->attr().try_get(_name);
|
||||||
vm->NameError(name);
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
|
vm->NameError(_name);
|
||||||
|
DISPATCH();
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(LOAD_GLOBAL) {
|
TARGET(LOAD_GLOBAL)
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
StrName name(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
PyObject* val = frame->f_globals().try_get(name);
|
_0 = frame->f_globals().try_get(_name);
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
val = vm->builtins->attr().try_get(name);
|
_0 = vm->builtins->attr().try_get(_name);
|
||||||
if(val != nullptr) { PUSH(val); DISPATCH(); }
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
vm->NameError(name);
|
vm->NameError(_name);
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(LOAD_ATTR) {
|
TARGET(LOAD_ATTR)
|
||||||
PyObject* a = TOP();
|
TOP() = getattr(TOP(), StrName(byte.arg));
|
||||||
StrName name(byte.arg);
|
DISPATCH();
|
||||||
TOP() = getattr(a, name);
|
TARGET(LOAD_METHOD)
|
||||||
} DISPATCH();
|
TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true);
|
||||||
TARGET(LOAD_METHOD) {
|
PUSH(_0);
|
||||||
PyObject* a = TOP();
|
DISPATCH();
|
||||||
StrName name(byte.arg);
|
TARGET(LOAD_SUBSCR)
|
||||||
PyObject* self;
|
_1 = POPX();
|
||||||
TOP() = get_unbound_method(a, name, &self, true, true);
|
_0 = TOP();
|
||||||
PUSH(self);
|
TOP() = call_method(_0, __getitem__, _1);
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(LOAD_SUBSCR) {
|
|
||||||
PyObject* b = POPX();
|
|
||||||
PyObject* a = TOP();
|
|
||||||
TOP() = call_method(a, __getitem__, b);
|
|
||||||
} DISPATCH();
|
|
||||||
TARGET(STORE_FAST)
|
TARGET(STORE_FAST)
|
||||||
frame->_locals[byte.arg] = POPX();
|
frame->_locals[byte.arg] = POPX();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(STORE_NAME) {
|
TARGET(STORE_NAME)
|
||||||
StrName name(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
PyObject* val = POPX();
|
_0 = POPX();
|
||||||
if(frame->_locals.is_valid()){
|
if(frame->_locals.is_valid()){
|
||||||
bool ok = frame->_locals.try_set(name, val);
|
bool ok = frame->_locals.try_set(_name, _0);
|
||||||
if(!ok) vm->NameError(name);
|
if(!ok) vm->NameError(_name);
|
||||||
}else{
|
}else{
|
||||||
frame->f_globals().set(name, val);
|
frame->f_globals().set(_name, _0);
|
||||||
}
|
}
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(STORE_GLOBAL) {
|
TARGET(STORE_GLOBAL)
|
||||||
StrName name(byte.arg);
|
frame->f_globals().set(StrName(byte.arg), POPX());
|
||||||
frame->f_globals().set(name, POPX());
|
DISPATCH();
|
||||||
} DISPATCH();
|
|
||||||
TARGET(STORE_ATTR) {
|
TARGET(STORE_ATTR) {
|
||||||
StrName name(byte.arg);
|
_0 = TOP(); // a
|
||||||
PyObject* a = TOP();
|
_1 = SECOND(); // val
|
||||||
PyObject* val = SECOND();
|
setattr(_0, StrName(byte.arg), _1);
|
||||||
setattr(a, name, val);
|
|
||||||
STACK_SHRINK(2);
|
STACK_SHRINK(2);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(STORE_SUBSCR) {
|
TARGET(STORE_SUBSCR)
|
||||||
// val a b
|
_2 = POPX(); // b
|
||||||
PyObject* b = POPX();
|
_1 = POPX(); // a
|
||||||
PyObject* a = POPX();
|
_0 = POPX(); // val
|
||||||
PyObject* val = POPX();
|
call_method(_1, __setitem__, _2, _0);
|
||||||
call_method(a, __setitem__, b, val);
|
DISPATCH();
|
||||||
} DISPATCH();
|
TARGET(DELETE_FAST)
|
||||||
TARGET(DELETE_FAST) {
|
_0 = frame->_locals[byte.arg];
|
||||||
PyObject* val = frame->_locals[byte.arg];
|
if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]);
|
||||||
if(val == nullptr) vm->NameError(co->varnames[byte.arg]);
|
|
||||||
frame->_locals[byte.arg] = nullptr;
|
frame->_locals[byte.arg] = nullptr;
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(DELETE_NAME) {
|
TARGET(DELETE_NAME)
|
||||||
StrName name(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
if(frame->_locals.is_valid()){
|
if(frame->_locals.is_valid()){
|
||||||
if(!frame->_locals.contains(name)) vm->NameError(name);
|
if(!frame->_locals.contains(_name)) vm->NameError(_name);
|
||||||
frame->_locals.erase(name);
|
frame->_locals.erase(_name);
|
||||||
}else{
|
}else{
|
||||||
if(!frame->f_globals().contains(name)) vm->NameError(name);
|
if(!frame->f_globals().contains(_name)) vm->NameError(_name);
|
||||||
frame->f_globals().erase(name);
|
frame->f_globals().erase(_name);
|
||||||
}
|
}
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(DELETE_GLOBAL) {
|
TARGET(DELETE_GLOBAL)
|
||||||
StrName name(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
if(frame->f_globals().contains(name)){
|
if(frame->f_globals().contains(_name)){
|
||||||
frame->f_globals().erase(name);
|
frame->f_globals().erase(_name);
|
||||||
}else{
|
}else{
|
||||||
NameError(name);
|
NameError(_name);
|
||||||
}
|
}
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(DELETE_ATTR) {
|
TARGET(DELETE_ATTR)
|
||||||
PyObject* a = POPX();
|
_0 = POPX();
|
||||||
StrName name(byte.arg);
|
_name = StrName(byte.arg);
|
||||||
if(!a->is_attr_valid()) TypeError("cannot delete attribute");
|
if(!_0->is_attr_valid()) TypeError("cannot delete attribute");
|
||||||
if(!a->attr().contains(name)) AttributeError(a, name);
|
if(!_0->attr().contains(_name)) AttributeError(_0, _name);
|
||||||
a->attr().erase(name);
|
_0->attr().erase(_name);
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(DELETE_SUBSCR) {
|
TARGET(DELETE_SUBSCR)
|
||||||
PyObject* b = POPX();
|
_1 = POPX();
|
||||||
PyObject* a = POPX();
|
_0 = POPX();
|
||||||
call_method(a, __delitem__, b);
|
call_method(_0, __delitem__, _1);
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(BUILD_LIST) {
|
TARGET(BUILD_LIST)
|
||||||
PyObject* obj = VAR(STACK_VIEW(byte.arg).to_list());
|
_0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||||
STACK_SHRINK(byte.arg);
|
STACK_SHRINK(byte.arg);
|
||||||
PUSH(obj);
|
PUSH(_0);
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(BUILD_DICT) {
|
TARGET(BUILD_DICT) {
|
||||||
PyObject* t = VAR(STACK_VIEW(byte.arg).to_tuple());
|
PyObject* t = VAR(STACK_VIEW(byte.arg).to_tuple());
|
||||||
PyObject* obj = call_(builtins->attr(m_dict), t);
|
PyObject* obj = call_(builtins->attr(m_dict), t);
|
||||||
@ -234,20 +228,20 @@ __NEXT_STEP:;
|
|||||||
PUSH(obj);
|
PUSH(obj);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(BUILD_SLICE) {
|
TARGET(BUILD_SLICE) {
|
||||||
PyObject* step = POPX();
|
_2 = POPX();
|
||||||
PyObject* stop = POPX();
|
_1 = POPX();
|
||||||
PyObject* start = POPX();
|
_0 = POPX();
|
||||||
Slice s;
|
Slice s;
|
||||||
if(start != None) s.start = CAST(int, start);
|
if(_0 != None) s.start = CAST(int, _0);
|
||||||
if(stop != None) s.stop = CAST(int, stop);
|
if(_1 != None) s.stop = CAST(int, _1);
|
||||||
if(step != None) s.step = CAST(int, step);
|
if(_2 != None) s.step = CAST(int, _2);
|
||||||
PUSH(VAR(s));
|
PUSH(VAR(s));
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(BUILD_TUPLE) {
|
TARGET(BUILD_TUPLE)
|
||||||
PyObject* obj = VAR(STACK_VIEW(byte.arg).to_tuple());
|
_0 = VAR(STACK_VIEW(byte.arg).to_tuple());
|
||||||
STACK_SHRINK(byte.arg);
|
STACK_SHRINK(byte.arg);
|
||||||
PUSH(obj);
|
PUSH(_0);
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
TARGET(BUILD_STRING) {
|
TARGET(BUILD_STRING) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
auto view = STACK_VIEW(byte.arg);
|
auto view = STACK_VIEW(byte.arg);
|
||||||
@ -256,11 +250,11 @@ __NEXT_STEP:;
|
|||||||
PUSH(VAR(ss.str()));
|
PUSH(VAR(ss.str()));
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(BINARY_OP) {
|
TARGET(BINARY_OP)
|
||||||
PyObject* b = POPX();
|
_1 = POPX(); // b
|
||||||
PyObject* a = TOP();
|
_0 = TOP(); // a
|
||||||
TOP() = call_method(a, BINARY_SPECIAL_METHODS[byte.arg], b);
|
TOP() = call_method(_0, BINARY_SPECIAL_METHODS[byte.arg], _1);
|
||||||
} DISPATCH();
|
DISPATCH();
|
||||||
|
|
||||||
#define INT_BINARY_OP(op, func) \
|
#define INT_BINARY_OP(op, func) \
|
||||||
if(is_both_int(TOP(), SECOND())){ \
|
if(is_both_int(TOP(), SECOND())){ \
|
||||||
@ -269,9 +263,9 @@ __NEXT_STEP:;
|
|||||||
POP(); \
|
POP(); \
|
||||||
TOP() = VAR(a op b); \
|
TOP() = VAR(a op b); \
|
||||||
}else{ \
|
}else{ \
|
||||||
PyObject* b = POPX(); \
|
_1 = POPX(); \
|
||||||
PyObject* a = TOP(); \
|
_0 = TOP(); \
|
||||||
TOP() = call_method(a, func, b); \
|
TOP() = call_method(_0, func, _1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BINARY_ADD)
|
TARGET(BINARY_ADD)
|
||||||
@ -323,22 +317,29 @@ __NEXT_STEP:;
|
|||||||
INT_BINARY_OP(^, __xor__)
|
INT_BINARY_OP(^, __xor__)
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
#undef INT_BINARY_OP
|
#undef INT_BINARY_OP
|
||||||
TARGET(IS_OP) {
|
|
||||||
PyObject* rhs = POPX();
|
TARGET(IS_OP)
|
||||||
PyObject* lhs = TOP();
|
_1 = POPX(); // rhs
|
||||||
bool ret_c = lhs == rhs;
|
_0 = TOP(); // lhs
|
||||||
if(byte.arg == 1) ret_c = !ret_c;
|
if(byte.arg == 1){
|
||||||
TOP() = VAR(ret_c);
|
TOP() = VAR(_0 != _1);
|
||||||
} DISPATCH();
|
}else{
|
||||||
TARGET(CONTAINS_OP) {
|
TOP() = VAR(_0 == _1);
|
||||||
|
}
|
||||||
|
DISPATCH();
|
||||||
|
TARGET(CONTAINS_OP)
|
||||||
// a in b -> b __contains__ a
|
// a in b -> b __contains__ a
|
||||||
PyObject* ret = call_method(TOP(), __contains__, SECOND());
|
_0 = call_method(TOP(), __contains__, SECOND());
|
||||||
bool ret_c = CAST(bool, ret);
|
if(byte.arg == 1){
|
||||||
if(byte.arg == 1) ret_c = !ret_c;
|
TOP() = VAR(!CAST(bool, _0));
|
||||||
TOP() = VAR(ret_c);
|
}else{
|
||||||
} DISPATCH();
|
TOP() = VAR(CAST(bool, _0));
|
||||||
|
}
|
||||||
|
DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(JUMP_ABSOLUTE) frame->jump_abs(byte.arg); DISPATCH();
|
TARGET(JUMP_ABSOLUTE)
|
||||||
|
frame->jump_abs(byte.arg);
|
||||||
|
DISPATCH();
|
||||||
TARGET(POP_JUMP_IF_FALSE)
|
TARGET(POP_JUMP_IF_FALSE)
|
||||||
if(!asBool(POPX())) frame->jump_abs(byte.arg);
|
if(!asBool(POPX())) frame->jump_abs(byte.arg);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -354,10 +355,11 @@ __NEXT_STEP:;
|
|||||||
int target = co_blocks[byte.block].start;
|
int target = co_blocks[byte.block].start;
|
||||||
frame->jump_abs(target);
|
frame->jump_abs(target);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(LOOP_BREAK) {
|
TARGET(LOOP_BREAK)
|
||||||
int target = co_blocks[byte.block].end;
|
frame->jump_abs_break(
|
||||||
frame->jump_abs_break(target);
|
co_blocks[byte.block].end
|
||||||
} DISPATCH();
|
);
|
||||||
|
DISPATCH();
|
||||||
TARGET(GOTO) {
|
TARGET(GOTO) {
|
||||||
StrName name(byte.arg);
|
StrName name(byte.arg);
|
||||||
int index = co->labels->try_get(name);
|
int index = co->labels->try_get(name);
|
||||||
@ -368,27 +370,27 @@ __NEXT_STEP:;
|
|||||||
TARGET(BEGIN_CALL)
|
TARGET(BEGIN_CALL)
|
||||||
PUSH(_py_begin_call);
|
PUSH(_py_begin_call);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(CALL) {
|
TARGET(CALL)
|
||||||
int ARGC = byte.arg & 0xFFFF;
|
_0 = _vectorcall(
|
||||||
int KWARGC = (byte.arg >> 16) & 0xFFFF;
|
byte.arg & 0xFFFF, // ARGC
|
||||||
PyObject* ret = _vectorcall(ARGC, KWARGC, true);
|
(byte.arg>>16) & 0xFFFF, // KWARGC
|
||||||
if(ret == _py_op_call) { DISPATCH_OP_CALL(); }
|
true
|
||||||
PUSH(ret);
|
);
|
||||||
|
if(_0 == _py_op_call) DISPATCH_OP_CALL();
|
||||||
|
PUSH(_0);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
TARGET(RETURN_VALUE)
|
||||||
TARGET(RETURN_VALUE) {
|
_0 = POPX();
|
||||||
PyObject* __ret = POPX();
|
|
||||||
// cleanup the stack on return
|
// cleanup the stack on return
|
||||||
callstack.pop();
|
callstack.pop();
|
||||||
s_data.reset(frame->_sp_base);
|
s_data.reset(frame->_sp_base);
|
||||||
if(frame.index == base_id){ // [ frameBase<- ]
|
if(frame.index == base_id){ // [ frameBase<- ]
|
||||||
return __ret;
|
return _0;
|
||||||
}else{
|
}else{
|
||||||
frame = top_frame();
|
frame = top_frame();
|
||||||
PUSH(__ret);
|
PUSH(_0);
|
||||||
goto __NEXT_FRAME;
|
goto __NEXT_FRAME;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
TARGET(YIELD_VALUE)
|
TARGET(YIELD_VALUE)
|
||||||
return _py_op_yield;
|
return _py_op_yield;
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
@ -423,9 +425,9 @@ __NEXT_STEP:;
|
|||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(FOR_ITER) {
|
TARGET(FOR_ITER) {
|
||||||
BaseIter* it = PyIter_AS_C(TOP());
|
BaseIter* it = PyIter_AS_C(TOP());
|
||||||
PyObject* obj = it->next();
|
_0 = it->next();
|
||||||
if(obj != nullptr){
|
if(_0 != nullptr){
|
||||||
PUSH(obj);
|
PUSH(_0);
|
||||||
}else{
|
}else{
|
||||||
int target = co_blocks[byte.block].end;
|
int target = co_blocks[byte.block].end;
|
||||||
frame->jump_abs_break(target);
|
frame->jump_abs_break(target);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user