This commit is contained in:
blueloveTH 2023-04-17 19:25:55 +08:00
parent ca78599049
commit ff98646064
4 changed files with 34 additions and 17 deletions

View File

@ -37,7 +37,7 @@
#define DEBUG_DIS_EXEC 0 #define DEBUG_DIS_EXEC 0
#define DEBUG_CEVAL_STEP 0 #define DEBUG_CEVAL_STEP 0
#define DEBUG_CEVAL_STEP_MIN 0 #define DEBUG_CEVAL_STEP_MIN 0
#define DEBUG_FULL_EXCEPTION 1 #define DEBUG_FULL_EXCEPTION 0
#define DEBUG_MEMORY_POOL 0 #define DEBUG_MEMORY_POOL 0
#define DEBUG_NO_MEMORY_POOL 0 #define DEBUG_NO_MEMORY_POOL 0
#define DEBUG_NO_AUTO_GC 0 #define DEBUG_NO_AUTO_GC 0

View File

@ -63,6 +63,8 @@ public:
inline PyObject* Generator::next(){ inline PyObject* Generator::next(){
if(state == 2) return nullptr; if(state == 2) return nullptr;
// reset frame._sp_base
frame._sp_base = frame._s->_sp;
// restore the context // restore the context
for(PyObject* obj: s_data) frame._s->push(obj); for(PyObject* obj: s_data) frame._s->push(obj);
s_data.clear(); s_data.clear();
@ -71,10 +73,11 @@ inline PyObject* Generator::next(){
if(ret == vm->_py_op_yield){ if(ret == vm->_py_op_yield){
// backup the context // backup the context
frame = std::move(vm->callstack.top()); frame = std::move(vm->callstack.top());
PyObject* ret = frame._s->popx();
for(PyObject* obj: frame.stack_view()) s_data.push_back(obj); for(PyObject* obj: frame.stack_view()) s_data.push_back(obj);
vm->_pop_frame(); vm->_pop_frame();
state = 1; state = 1;
return frame._s->popx(); return ret;
}else{ }else{
state = 2; state = 2;
return nullptr; return nullptr;

View File

@ -100,7 +100,7 @@ public:
// for quick access // for quick access
Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str; Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str;
Type tp_list, tp_tuple; Type tp_list, tp_tuple;
Type tp_function, tp_native_function, tp_iterator, tp_bound_method; Type tp_function, tp_native_func, tp_iterator, tp_bound_method;
Type tp_slice, tp_range, tp_module; Type tp_slice, tp_range, tp_module;
Type tp_super, tp_exception; Type tp_super, tp_exception;
@ -237,7 +237,7 @@ public:
PyObject* property(NativeFuncRaw fget){ PyObject* property(NativeFuncRaw fget){
PyObject* p = builtins->attr("property"); PyObject* p = builtins->attr("property");
PyObject* method = heap.gcnew(tp_native_function, NativeFunc(fget, 1, false)); PyObject* method = heap.gcnew(tp_native_func, NativeFunc(fget, 1, false));
return call_(p, method); return call_(p, method);
} }
@ -404,7 +404,7 @@ DEF_NATIVE_2(Str, tp_str)
DEF_NATIVE_2(List, tp_list) DEF_NATIVE_2(List, tp_list)
DEF_NATIVE_2(Tuple, tp_tuple) DEF_NATIVE_2(Tuple, tp_tuple)
DEF_NATIVE_2(Function, tp_function) DEF_NATIVE_2(Function, tp_function)
DEF_NATIVE_2(NativeFunc, tp_native_function) DEF_NATIVE_2(NativeFunc, tp_native_func)
DEF_NATIVE_2(BoundMethod, tp_bound_method) DEF_NATIVE_2(BoundMethod, tp_bound_method)
DEF_NATIVE_2(Range, tp_range) DEF_NATIVE_2(Range, tp_range)
DEF_NATIVE_2(Slice, tp_slice) DEF_NATIVE_2(Slice, tp_slice)
@ -658,13 +658,20 @@ inline void VM::_log_s_data(const char* title) {
std::stringstream ss; std::stringstream ss;
if(title) ss << title << " | "; if(title) ss << title << " | ";
FrameId frame = top_frame(); FrameId frame = top_frame();
ss << frame->co->name << ": ["; int line = frame->co->lines[frame->_ip];
ss << frame->co->name << ":" << line << " [";
for(PyObject* obj: s_data){ for(PyObject* obj: s_data){
if(obj == _py_begin_call) ss << "BEGIN_CALL"; if(obj == nullptr) ss << "(nil)";
else if(obj == _py_begin_call) ss << "BEGIN_CALL";
else if(obj == _py_null) ss << "NULL"; else if(obj == _py_null) ss << "NULL";
else if(is_int(obj)) ss << CAST(i64, obj); else if(is_int(obj)) ss << CAST(i64, obj);
else if(is_float(obj)) ss << CAST(f64, obj); else if(is_float(obj)) ss << CAST(f64, obj);
else ss << obj << "(" << obj_type_name(this, obj->type) << ")"; else if(is_type(obj, tp_str)) ss << CAST(Str, obj).escape();
else if(obj == None) ss << "None";
else if(obj == True) ss << "True";
else if(obj == False) ss << "False";
// else ss << obj << "(" << obj_type_name(this, obj->type) << ")";
else ss << "(" << obj_type_name(this, obj->type) << ")";
ss << ", "; ss << ", ";
} }
std::string output = ss.str(); std::string output = ss.str();
@ -693,7 +700,7 @@ inline void VM::init_builtin_types(){
tp_range = _new_type_object("range"); tp_range = _new_type_object("range");
tp_module = _new_type_object("module"); tp_module = _new_type_object("module");
tp_function = _new_type_object("function"); tp_function = _new_type_object("function");
tp_native_function = _new_type_object("native_function"); tp_native_func = _new_type_object("native_func");
tp_iterator = _new_type_object("iterator"); tp_iterator = _new_type_object("iterator");
tp_bound_method = _new_type_object("bound_method"); tp_bound_method = _new_type_object("bound_method");
tp_super = _new_type_object("super"); tp_super = _new_type_object("super");
@ -761,9 +768,9 @@ inline PyObject* VM::_vectorcall(int ARGC, int KWARGC, bool op_call){
// [unbound, self, args..., kwargs...] // [unbound, self, args..., kwargs...]
} }
if(is_non_tagged_type(callable, tp_native_function)){ if(is_non_tagged_type(callable, tp_native_func)){
const auto& f = OBJ_GET(NativeFunc, callable); const auto& f = OBJ_GET(NativeFunc, callable);
if(KWARGC != 0) TypeError("native_function does not accept keyword arguments"); if(KWARGC != 0) TypeError("native_func does not accept keyword arguments");
PyObject* ret = f(this, args); PyObject* ret = f(this, args);
s_data.reset(p0); s_data.reset(p0);
return ret; return ret;
@ -792,7 +799,6 @@ inline PyObject* VM::_vectorcall(int ARGC, int KWARGC, bool op_call){
PUSH(_py_null); PUSH(_py_null);
for(PyObject* obj: args) PUSH(obj); for(PyObject* obj: args) PUSH(obj);
for(PyObject* obj: kwargs) PUSH(obj); for(PyObject* obj: kwargs) PUSH(obj);
// _log_s_data("L790");
obj = _vectorcall(ARGC, KWARGC); obj = _vectorcall(ARGC, KWARGC);
if(!isinstance(obj, OBJ_GET(Type, callable))) return obj; if(!isinstance(obj, OBJ_GET(Type, callable))) return obj;
}else{ }else{
@ -873,9 +879,11 @@ inline PyObject* VM::_py_call(PyObject** sp_base, PyObject* callable, ArgsView a
if(!ok) TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()")); if(!ok) TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()"));
} }
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module; PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
if(co->is_generator) return PyIter(Generator(this, Frame( if(co->is_generator){
&s_data, sp_base, co, _module, std::move(locals), fn._closure PyObject* ret = PyIter(Generator(this, Frame(&s_data, sp_base, co, _module, std::move(locals), fn._closure)));
))); s_data.reset(sp_base);
return ret;
}
callstack.emplace(&s_data, sp_base, co, _module, std::move(locals), fn._closure); callstack.emplace(&s_data, sp_base, co, _module, std::move(locals), fn._closure);
return nullptr; return nullptr;
} }
@ -902,7 +910,7 @@ inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
} }
if(cls_var != nullptr){ if(cls_var != nullptr){
// bound method is non-data descriptor // bound method is non-data descriptor
if(is_type(cls_var, tp_function) || is_type(cls_var, tp_native_function)){ if(is_type(cls_var, tp_function) || is_type(cls_var, tp_native_func)){
return VAR(BoundMethod(obj, cls_var)); return VAR(BoundMethod(obj, cls_var));
} }
return cls_var; return cls_var;
@ -938,7 +946,7 @@ inline PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject**
} }
if(cls_var != nullptr){ if(cls_var != nullptr){
if(is_type(cls_var, tp_function) || is_type(cls_var, tp_native_function)){ if(is_type(cls_var, tp_function) || is_type(cls_var, tp_native_func)){
*self = obj; *self = obj;
} }
return cls_var; return cls_var;

View File

@ -2,6 +2,12 @@ def f(n):
for i in range(n): for i in range(n):
yield i yield i
x = 0
for j in f(5):
x += j
assert x == 10
a = [i for i in f(6)] a = [i for i in f(6)]
assert a == [0,1,2,3,4,5] assert a == [0,1,2,3,4,5]