This commit is contained in:
blueloveTH 2024-05-05 10:51:06 +08:00
parent 10f886bb9b
commit 0f47105b27
6 changed files with 84 additions and 68 deletions

View File

@ -109,6 +109,8 @@ struct Type {
#define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) { return VAR(x); }) #define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) { return VAR(x); })
#define PK_ACTION(x) ([](VM* vm, ArgsView args) { x; return vm->None; }) #define PK_ACTION(x) ([](VM* vm, ArgsView args) { x; return vm->None; })
#define PK_REGION(name) 1
#ifdef POCKETPY_H #ifdef POCKETPY_H
#define PK_FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!"); #define PK_FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!");
#else #else

View File

@ -128,7 +128,7 @@ struct ImportContext{
class VM { class VM {
PK_ALWAYS_PASS_BY_POINTER(VM) PK_ALWAYS_PASS_BY_POINTER(VM)
VM* vm; // self reference for simplify code VM* vm; // self reference to simplify code
public: public:
ManagedHeap heap; ManagedHeap heap;
ValueStack s_data; ValueStack s_data;
@ -152,9 +152,9 @@ public:
// this is for repr() recursion detection (no need to mark) // this is for repr() recursion detection (no need to mark)
std::set<PyObject*> _repr_recursion_set; std::set<PyObject*> _repr_recursion_set;
ImportContext __import_context; // for import ImportContext __import_context;
PyObject* __last_exception; // last exception PyObject* __last_exception;
PyObject* __curr_class; // current class being defined PyObject* __curr_class;
PyObject* __cached_object_new; PyObject* __cached_object_new;
std::map<std::string_view, CodeObject_> __cached_codes; std::map<std::string_view, CodeObject_> __cached_codes;
@ -182,45 +182,50 @@ public:
const bool enable_os; const bool enable_os;
VM(bool enable_os=true); VM(bool enable_os=true);
/********** py_xxx **********/ #if PK_REGION("Python Equivalents")
PyObject* py_str(PyObject* obj); PyObject* py_str(PyObject* obj); // x -> str(x)
PyObject* py_repr(PyObject* obj); PyObject* py_repr(PyObject* obj); // x -> repr(x)
PyObject* py_json(PyObject* obj); PyObject* py_json(PyObject* obj); // x -> json.dumps(x)
PyObject* py_iter(PyObject* obj); PyObject* py_iter(PyObject* obj); // x -> iter(x)
PyObject* py_next(PyObject*); PyObject* py_next(PyObject*); // x -> next(x)
PyObject* _py_next(const PyTypeInfo*, PyObject*); PyObject* _py_next(const PyTypeInfo*, PyObject*); // x -> next(x) with type info cache
PyObject* py_import(Str path, bool throw_err=true); PyObject* py_import(Str path, bool throw_err=true); // x -> __import__(x)
PyObject* py_negate(PyObject* obj); PyObject* py_negate(PyObject* obj); // x -> -x
List py_list(PyObject*); List py_list(PyObject*); // x -> list(x)
bool py_callable(PyObject* obj); bool py_callable(PyObject* obj); // x -> callable(x)
bool py_bool(PyObject* obj); bool py_bool(PyObject* obj); // x -> bool(x)
i64 py_hash(PyObject* obj); i64 py_hash(PyObject* obj); // x -> hash(x)
bool py_eq(PyObject* lhs, PyObject* rhs); bool py_eq(PyObject* lhs, PyObject* rhs); // (lhs, rhs) -> lhs == rhs
// new in v1.2.9 bool py_lt(PyObject* lhs, PyObject* rhs); // (lhs, rhs) -> lhs < rhs
bool py_lt(PyObject* lhs, PyObject* rhs); bool py_le(PyObject* lhs, PyObject* rhs); // (lhs, rhs) -> lhs <= rhs
bool py_le(PyObject* lhs, PyObject* rhs); bool py_gt(PyObject* lhs, PyObject* rhs); // (lhs, rhs) -> lhs > rhs
bool py_gt(PyObject* lhs, PyObject* rhs); bool py_ge(PyObject* lhs, PyObject* rhs); // (lhs, rhs) -> lhs >= rhs
bool py_ge(PyObject* lhs, PyObject* rhs); bool py_ne(PyObject* lhs, PyObject* rhs) { // (lhs, rhs) -> lhs != rhs
bool py_ne(PyObject* lhs, PyObject* rhs) { return !py_eq(lhs, rhs); } return !py_eq(lhs, rhs);
}
#endif
/********** utils **********/ #if PK_REGION("Utility Methods")
PyObject* new_module(Str name, Str package=""); PyObject* new_module(Str name, Str package="");
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled=true);
ArgsView cast_array_view(PyObject* obj); ArgsView cast_array_view(PyObject* obj);
void set_main_argv(int argc, char** argv); void set_main_argv(int argc, char** argv);
i64 normalized_index(i64 index, int size); i64 normalized_index(i64 index, int size);
Str disassemble(CodeObject_ co); Str disassemble(CodeObject_ co);
void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step); void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step);
#endif
/********** name lookup **********/ #if PK_REGION("Name Lookup Methods")
PyObject* find_name_in_mro(Type cls, StrName name); PyObject* find_name_in_mro(Type cls, StrName name);
PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false);
PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true); PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true);
void delattr(PyObject* obj, StrName name); void delattr(PyObject* obj, StrName name);
PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false);
void setattr(PyObject* obj, StrName name, PyObject* value); void setattr(PyObject* obj, StrName name, PyObject* value);
#endif
/********** execution **********/ #if PK_REGION("Source Execution Methods")
CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false); CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
Str precompile(std::string_view source, const Str& filename, CompileMode mode); Str precompile(std::string_view source, const Str& filename, CompileMode mode);
PyObject* exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module=nullptr); PyObject* exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module=nullptr);
@ -232,8 +237,9 @@ public:
callstack.emplace(s_data._sp, std::forward<Args>(args)...); callstack.emplace(s_data._sp, std::forward<Args>(args)...);
return __run_top_frame(); return __run_top_frame();
} }
#endif
/********** invocation **********/ #if PK_REGION("Invocation Methods")
PyObject* vectorcall(int ARGC, int KWARGC=0, bool op_call=false); PyObject* vectorcall(int ARGC, int KWARGC=0, bool op_call=false);
template<typename... Args> template<typename... Args>
@ -255,12 +261,14 @@ public:
PyObject* callable = get_unbound_method(self, name, &self); PyObject* callable = get_unbound_method(self, name, &self);
return call_method(self, callable, args...); return call_method(self, callable, args...);
} }
#endif
/********** io **********/ #if PK_REGION("Logging Methods")
virtual void stdout_write(const Str& s){ _stdout(s.data, s.size); } virtual void stdout_write(const Str& s){ _stdout(s.data, s.size); }
virtual void stderr_write(const Str& s){ _stderr(s.data, s.size); } virtual void stderr_write(const Str& s){ _stderr(s.data, s.size); }
#endif
/********** bindings **********/ #if PK_REGION("Magic Bindings")
void bind__repr__(Type type, PyObject* (*f)(VM*, PyObject*)); void bind__repr__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__str__(Type type, PyObject* (*f)(VM*, PyObject*)); void bind__str__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*)); void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*));
@ -296,7 +304,9 @@ public:
void bind__getitem__(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*)); void bind__getitem__(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*));
void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*)); void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*));
void bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*)); void bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*));
// new style binding api #endif
#if PK_REGION("General Bindings")
PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT); PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT);
PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT){ PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT){
return bind_func(_t(type), name, argc, fn, userdata, bt); return bind_func(_t(type), name, argc, fn, userdata, bt);
@ -304,19 +314,21 @@ public:
PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr); PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
template<typename T, typename F, bool ReadOnly=false> template<typename T, typename F, bool ReadOnly=false>
PyObject* bind_field(PyObject*, const char*, F T::*); PyObject* bind_field(PyObject*, const char*, F T::*);
// without docstring
PyObject* bind(PyObject*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT);
template<typename Ret, typename... Params> template<typename Ret, typename... Params>
PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
template<typename Ret, typename T, typename... Params> template<typename Ret, typename T, typename... Params>
PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
// with docstring
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT);
template<typename Ret, typename... Params> template<typename Ret, typename... Params>
PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
template<typename Ret, typename T, typename... Params> template<typename Ret, typename T, typename... Params>
PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT); PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
/********** error **********/ #endif
#if PK_REGION("Error Reporting Methods")
void _error(PyObject*); void _error(PyObject*);
void StackOverflowError() { __builtin_error("StackOverflowError"); } void StackOverflowError() { __builtin_error("StackOverflowError"); }
void IOError(const Str& msg) { __builtin_error("IOError", msg); } void IOError(const Str& msg) { __builtin_error("IOError", msg); }
@ -337,10 +349,9 @@ public:
void BinaryOptError(const char* op, PyObject* _0, PyObject* _1); void BinaryOptError(const char* op, PyObject* _0, PyObject* _1);
void AttributeError(PyObject* obj, StrName name); void AttributeError(PyObject* obj, StrName name);
void AttributeError(const Str& msg){ __builtin_error("AttributeError", msg); } void AttributeError(const Str& msg){ __builtin_error("AttributeError", msg); }
#endif
/********** type **********/ #if PK_REGION("Type Checking Methods")
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled=true);
const PyTypeInfo* _inst_type_info(PyObject* obj);
bool isinstance(PyObject* obj, Type base); bool isinstance(PyObject* obj, Type base);
bool issubclass(Type cls, Type base); bool issubclass(Type cls, Type base);
void check_type(PyObject* obj, Type type){ if(!is_type(obj, type)) TypeError(type, _tp(obj)); } void check_type(PyObject* obj, Type type){ if(!is_type(obj, type)) TypeError(type, _tp(obj)); }
@ -348,8 +359,10 @@ public:
PyObject* _t(PyObject* obj){ return _all_types[_tp(obj)].obj; } PyObject* _t(PyObject* obj){ return _all_types[_tp(obj)].obj; }
PyObject* _t(Type t){ return _all_types[t.index].obj; } PyObject* _t(Type t){ return _all_types[t.index].obj; }
Type _tp(PyObject* obj){ return is_small_int(obj) ? tp_int : obj->type; } Type _tp(PyObject* obj){ return is_small_int(obj) ? tp_int : obj->type; }
const PyTypeInfo* _tp_info(PyObject* obj);
#endif
/********** user type **********/ #if PK_REGION("User Type Registration")
template<typename T> template<typename T>
Type _tp_user(){ return _find_type_in_cxx_typeid_map<T>(); } Type _tp_user(){ return _find_type_in_cxx_typeid_map<T>(); }
template<typename T> template<typename T>
@ -379,6 +392,7 @@ public:
} }
return it->second; return it->second;
} }
#endif
/********** private **********/ /********** private **********/
virtual ~VM(); virtual ~VM();

View File

@ -17,7 +17,7 @@ namespace pkpy{
#define BINARY_F_COMPARE(func, op, rfunc) \ #define BINARY_F_COMPARE(func, op, rfunc) \
PyObject* ret; \ PyObject* ret; \
const PyTypeInfo* _ti = _inst_type_info(_0); \ const PyTypeInfo* _ti = _tp_info(_0); \
if(_ti->m##func){ \ if(_ti->m##func){ \
ret = _ti->m##func(this, _0, _1); \ ret = _ti->m##func(this, _0, _1); \
}else{ \ }else{ \
@ -48,7 +48,7 @@ void VM::__op_unpack_sequence(uint16_t arg){
}else{ }else{
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
_0 = py_iter(_0); _0 = py_iter(_0);
const PyTypeInfo* ti = _inst_type_info(_0); const PyTypeInfo* ti = _tp_info(_0);
for(int i=0; i<arg; i++){ for(int i=0; i<arg; i++){
PyObject* _1 = _py_next(ti, _0); PyObject* _1 = _py_next(ti, _0);
if(_1 == StopIteration) ValueError("not enough values to unpack"); if(_1 == StopIteration) ValueError("not enough values to unpack");
@ -224,7 +224,7 @@ __NEXT_STEP:;
case OP_LOAD_SUBSCR:{ case OP_LOAD_SUBSCR:{
PyObject* _1 = POPX(); // b PyObject* _1 = POPX(); // b
PyObject* _0 = TOP(); // a PyObject* _0 = TOP(); // a
auto _ti = _inst_type_info(_0); auto _ti = _tp_info(_0);
if(_ti->m__getitem__){ if(_ti->m__getitem__){
TOP() = _ti->m__getitem__(this, _0, _1); TOP() = _ti->m__getitem__(this, _0, _1);
}else{ }else{
@ -235,7 +235,7 @@ __NEXT_STEP:;
PyObject* _1 = frame->_locals[byte.arg]; PyObject* _1 = frame->_locals[byte.arg];
if(_1 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_1 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
PyObject* _0 = TOP(); // a PyObject* _0 = TOP(); // a
auto _ti = _inst_type_info(_0); auto _ti = _tp_info(_0);
if(_ti->m__getitem__){ if(_ti->m__getitem__){
TOP() = _ti->m__getitem__(this, _0, _1); TOP() = _ti->m__getitem__(this, _0, _1);
}else{ }else{
@ -245,7 +245,7 @@ __NEXT_STEP:;
case OP_LOAD_SUBSCR_SMALL_INT:{ case OP_LOAD_SUBSCR_SMALL_INT:{
PyObject* _1 = (PyObject*)(uintptr_t)byte.arg; PyObject* _1 = (PyObject*)(uintptr_t)byte.arg;
PyObject* _0 = TOP(); // a PyObject* _0 = TOP(); // a
auto _ti = _inst_type_info(_0); auto _ti = _tp_info(_0);
if(_ti->m__getitem__){ if(_ti->m__getitem__){
TOP() = _ti->m__getitem__(this, _0, _1); TOP() = _ti->m__getitem__(this, _0, _1);
}else{ }else{
@ -279,7 +279,7 @@ __NEXT_STEP:;
PyObject* _2 = POPX(); // b PyObject* _2 = POPX(); // b
PyObject* _1 = POPX(); // a PyObject* _1 = POPX(); // a
PyObject* _0 = POPX(); // val PyObject* _0 = POPX(); // val
auto _ti = _inst_type_info(_1); auto _ti = _tp_info(_1);
if(_ti->m__setitem__){ if(_ti->m__setitem__){
_ti->m__setitem__(this, _1, _2, _0); _ti->m__setitem__(this, _1, _2, _0);
}else{ }else{
@ -291,7 +291,7 @@ __NEXT_STEP:;
if(_2 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]); if(_2 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
PyObject* _1 = POPX(); // a PyObject* _1 = POPX(); // a
PyObject* _0 = POPX(); // val PyObject* _0 = POPX(); // val
auto _ti = _inst_type_info(_1); auto _ti = _tp_info(_1);
if(_ti->m__setitem__){ if(_ti->m__setitem__){
_ti->m__setitem__(this, _1, _2, _0); _ti->m__setitem__(this, _1, _2, _0);
}else{ }else{
@ -324,7 +324,7 @@ __NEXT_STEP:;
case OP_DELETE_SUBSCR:{ case OP_DELETE_SUBSCR:{
PyObject* _1 = POPX(); PyObject* _1 = POPX();
PyObject* _0 = POPX(); PyObject* _0 = POPX();
auto _ti = _inst_type_info(_0); auto _ti = _tp_info(_0);
if(_ti->m__delitem__){ if(_ti->m__delitem__){
_ti->m__delitem__(this, _0, _1); _ti->m__delitem__(this, _0, _1);
}else{ }else{
@ -423,7 +423,7 @@ __NEXT_STEP:;
} DISPATCH() } DISPATCH()
/*****************************************/ /*****************************************/
#define BINARY_OP_SPECIAL(func) \ #define BINARY_OP_SPECIAL(func) \
_ti = _inst_type_info(_0); \ _ti = _tp_info(_0); \
if(_ti->m##func){ \ if(_ti->m##func){ \
TOP() = _ti->m##func(this, _0, _1); \ TOP() = _ti->m##func(this, _0, _1); \
}else{ \ }else{ \
@ -589,7 +589,7 @@ __NEXT_STEP:;
} DISPATCH() } DISPATCH()
case OP_CONTAINS_OP:{ case OP_CONTAINS_OP:{
// a in b -> b __contains__ a // a in b -> b __contains__ a
auto _ti = _inst_type_info(TOP()); auto _ti = _tp_info(TOP());
PyObject* _0; PyObject* _0;
if(_ti->m__contains__){ if(_ti->m__contains__){
_0 = _ti->m__contains__(this, TOP(), SECOND()); _0 = _ti->m__contains__(this, TOP(), SECOND());
@ -749,7 +749,7 @@ __NEXT_STEP:;
DISPATCH() DISPATCH()
case OP_UNARY_INVERT:{ case OP_UNARY_INVERT:{
PyObject* _0; PyObject* _0;
auto _ti = _inst_type_info(TOP()); auto _ti = _tp_info(TOP());
if(_ti->m__invert__) _0 = _ti->m__invert__(this, TOP()); if(_ti->m__invert__) _0 = _ti->m__invert__(this, TOP());
else _0 = call_method(TOP(), __invert__); else _0 = call_method(TOP(), __invert__);
TOP() = _0; TOP() = _0;
@ -790,7 +790,7 @@ __NEXT_STEP:;
} DISPATCH() } DISPATCH()
case OP_FOR_ITER_UNPACK:{ case OP_FOR_ITER_UNPACK:{
PyObject* _0 = TOP(); PyObject* _0 = TOP();
const PyTypeInfo* _ti = _inst_type_info(_0); const PyTypeInfo* _ti = _tp_info(_0);
if(_ti->m__next__){ if(_ti->m__next__){
unsigned n = _ti->m__next__(this, _0); unsigned n = _ti->m__next__(this, _0);
if(n == 0){ if(n == 0){
@ -850,7 +850,7 @@ __NEXT_STEP:;
case OP_UNPACK_EX: { case OP_UNPACK_EX: {
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
PyObject* _0 = py_iter(POPX()); PyObject* _0 = py_iter(POPX());
const PyTypeInfo* _ti = _inst_type_info(_0); const PyTypeInfo* _ti = _tp_info(_0);
PyObject* _1; PyObject* _1;
for(int i=0; i<byte.arg; i++){ for(int i=0; i<byte.arg; i++){
_1 = _py_next(_ti, _0); _1 = _py_next(_ti, _0);

View File

@ -104,7 +104,7 @@ void add_module_dataclasses(VM* vm){
}); });
vm->bind_func(mod, "asdict", 1, [](VM* vm, ArgsView args){ vm->bind_func(mod, "asdict", 1, [](VM* vm, ArgsView args){
const auto& fields = vm->_inst_type_info(args[0])->annotated_fields; const auto& fields = vm->_tp_info(args[0])->annotated_fields;
const NameDict& obj_d = args[0]->attr(); const NameDict& obj_d = args[0]->attr();
Dict d(vm); Dict d(vm);
for(StrName field: fields){ for(StrName field: fields){

View File

@ -249,7 +249,7 @@ void __init_builtins(VM* _vm) {
}); });
_vm->bind_func(_vm->builtins, "len", 1, [](VM* vm, ArgsView args){ _vm->bind_func(_vm->builtins, "len", 1, [](VM* vm, ArgsView args){
const PyTypeInfo* ti = vm->_inst_type_info(args[0]); const PyTypeInfo* ti = vm->_tp_info(args[0]);
if(ti->m__len__) return VAR(ti->m__len__(vm, args[0])); if(ti->m__len__) return VAR(ti->m__len__(vm, args[0]));
return vm->call_method(args[0], __len__); return vm->call_method(args[0], __len__);
}); });
@ -691,7 +691,7 @@ void __init_builtins(VM* _vm) {
const Str& self = _CAST(Str&, args[0]); const Str& self = _CAST(Str&, args[0]);
SStream ss; SStream ss;
PyObject* it = vm->py_iter(args[1]); // strong ref PyObject* it = vm->py_iter(args[1]); // strong ref
const PyTypeInfo* info = vm->_inst_type_info(args[1]); const PyTypeInfo* info = vm->_tp_info(args[1]);
PyObject* obj = vm->_py_next(info, it); PyObject* obj = vm->_py_next(info, it);
while(obj != vm->StopIteration){ while(obj != vm->StopIteration){
if(!ss.empty()) ss << self; if(!ss.empty()) ss << self;
@ -913,7 +913,7 @@ void __init_builtins(VM* _vm) {
auto _lock = vm->heap.gc_scope_lock(); auto _lock = vm->heap.gc_scope_lock();
List& self = _CAST(List&, args[0]); List& self = _CAST(List&, args[0]);
PyObject* it = vm->py_iter(args[1]); // strong ref PyObject* it = vm->py_iter(args[1]); // strong ref
const PyTypeInfo* info = vm->_inst_type_info(args[1]); const PyTypeInfo* info = vm->_tp_info(args[1]);
PyObject* obj = vm->_py_next(info, it); PyObject* obj = vm->_py_next(info, it);
while(obj != vm->StopIteration){ while(obj != vm->StopIteration){
self.push_back(obj); self.push_back(obj);

View File

@ -84,7 +84,7 @@ namespace pkpy{
} }
PyObject* VM::py_str(PyObject* obj){ PyObject* VM::py_str(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj); const PyTypeInfo* ti = _tp_info(obj);
if(ti->m__str__) return ti->m__str__(this, obj); if(ti->m__str__) return ti->m__str__(this, obj);
PyObject* self; PyObject* self;
PyObject* f = get_unbound_method(obj, __str__, &self, false); PyObject* f = get_unbound_method(obj, __str__, &self, false);
@ -93,7 +93,7 @@ namespace pkpy{
} }
PyObject* VM::py_repr(PyObject* obj){ PyObject* VM::py_repr(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj); const PyTypeInfo* ti = _tp_info(obj);
if(ti->m__repr__) return ti->m__repr__(this, obj); if(ti->m__repr__) return ti->m__repr__(this, obj);
return call_method(obj, __repr__); return call_method(obj, __repr__);
} }
@ -104,7 +104,7 @@ namespace pkpy{
} }
PyObject* VM::py_iter(PyObject* obj){ PyObject* VM::py_iter(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj); const PyTypeInfo* ti = _tp_info(obj);
if(ti->m__iter__) return ti->m__iter__(this, obj); if(ti->m__iter__) return ti->m__iter__(this, obj);
PyObject* self; PyObject* self;
PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false); PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
@ -212,14 +212,14 @@ namespace pkpy{
return obj; return obj;
} }
const PyTypeInfo* VM::_inst_type_info(PyObject* obj){ const PyTypeInfo* VM::_tp_info(PyObject* obj){
if(is_small_int(obj)) return &_all_types[tp_int]; if(is_small_int(obj)) return &_all_types[tp_int];
return &_all_types[obj->type]; return &_all_types[obj->type];
} }
bool VM::py_eq(PyObject* lhs, PyObject* rhs){ bool VM::py_eq(PyObject* lhs, PyObject* rhs){
if(lhs == rhs) return true; if(lhs == rhs) return true;
const PyTypeInfo* ti = _inst_type_info(lhs); const PyTypeInfo* ti = _tp_info(lhs);
PyObject* res; PyObject* res;
if(ti->m__eq__){ if(ti->m__eq__){
res = ti->m__eq__(this, lhs, rhs); res = ti->m__eq__(this, lhs, rhs);
@ -228,7 +228,7 @@ namespace pkpy{
res = call_method(lhs, __eq__, rhs); res = call_method(lhs, __eq__, rhs);
if(res != vm->NotImplemented) return res == vm->True; if(res != vm->NotImplemented) return res == vm->True;
ti = _inst_type_info(rhs); ti = _tp_info(rhs);
if(ti->m__eq__){ if(ti->m__eq__){
res = ti->m__eq__(this, rhs, lhs); res = ti->m__eq__(this, rhs, lhs);
if(res != vm->NotImplemented) return res == vm->True; if(res != vm->NotImplemented) return res == vm->True;
@ -255,7 +255,7 @@ namespace pkpy{
} }
PyObject* VM::py_next(PyObject* obj){ PyObject* VM::py_next(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj); const PyTypeInfo* ti = _tp_info(obj);
return _py_next(ti, obj); return _py_next(ti, obj);
} }
@ -394,7 +394,7 @@ namespace pkpy{
} }
PyObject* VM::py_negate(PyObject* obj){ PyObject* VM::py_negate(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj); const PyTypeInfo* ti = _tp_info(obj);
if(ti->m__neg__) return ti->m__neg__(this, obj); if(ti->m__neg__) return ti->m__neg__(this, obj);
return call_method(obj, __neg__); return call_method(obj, __neg__);
} }
@ -418,7 +418,7 @@ List VM::py_list(PyObject* it){
auto _lock = heap.gc_scope_lock(); auto _lock = heap.gc_scope_lock();
it = py_iter(it); it = py_iter(it);
List list; List list;
const PyTypeInfo* info = _inst_type_info(it); const PyTypeInfo* info = _tp_info(it);
PyObject* obj = _py_next(info, it); PyObject* obj = _py_next(info, it);
while(obj != StopIteration){ while(obj != StopIteration){
list.push_back(obj); list.push_back(obj);
@ -473,7 +473,7 @@ void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int&
i64 VM::py_hash(PyObject* obj){ i64 VM::py_hash(PyObject* obj){
// https://docs.python.org/3.10/reference/datamodel.html#object.__hash__ // https://docs.python.org/3.10/reference/datamodel.html#object.__hash__
const PyTypeInfo* ti = _inst_type_info(obj); const PyTypeInfo* ti = _tp_info(obj);
if(ti->m__hash__) return ti->m__hash__(this, obj); if(ti->m__hash__) return ti->m__hash__(this, obj);
PyObject* self; PyObject* self;
@ -814,7 +814,7 @@ void VM::__unpack_as_list(ArgsView args, List& list){
// maybe this check should be done in the compile time // maybe this check should be done in the compile time
if(w.level != 1) TypeError("expected level 1 star wrapper"); if(w.level != 1) TypeError("expected level 1 star wrapper");
PyObject* _0 = py_iter(w.obj); PyObject* _0 = py_iter(w.obj);
const PyTypeInfo* info = _inst_type_info(_0); const PyTypeInfo* info = _tp_info(_0);
PyObject* _1 = _py_next(info, _0); PyObject* _1 = _py_next(info, _0);
while(_1 != StopIteration){ while(_1 != StopIteration){
list.push_back(_1); list.push_back(_1);
@ -1048,7 +1048,7 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
} }
void VM::delattr(PyObject *_0, StrName _name){ void VM::delattr(PyObject *_0, StrName _name){
const PyTypeInfo* ti = _inst_type_info(_0); const PyTypeInfo* ti = _tp_info(_0);
if(ti->m__delattr__ && ti->m__delattr__(this, _0, _name)) return; if(ti->m__delattr__ && ti->m__delattr__(this, _0, _name)) return;
if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute"); if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute");
if(!_0->attr().del(_name)) AttributeError(_0, _name); if(!_0->attr().del(_name)) AttributeError(_0, _name);