This commit is contained in:
blueloveTH 2023-05-19 22:37:43 +08:00
parent 3bac1d7388
commit e5fb7a65ff
6 changed files with 128 additions and 114 deletions

View File

@ -68,7 +68,7 @@ __NEXT_STEP:;
TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
TARGET(PRINT_EXPR)
if(TOP() != None){
_stdout(this, CAST(Str&, asRepr(TOP())));
_stdout(this, CAST(Str&, py_repr(TOP())));
_stdout(this, "\n");
}
POP();
@ -220,7 +220,12 @@ __NEXT_STEP:;
TARGET(DELETE_SUBSCR)
_1 = POPX();
_0 = POPX();
call_method(_0, __delitem__, _1);
_ti = _inst_type_info(_0);
if(_ti->m__delitem__){
_ti->m__delitem__(this, _0, _1);
}else{
call_method(_0, __delitem__, _1);
}
DISPATCH();
/*****************************************/
TARGET(BUILD_LIST)
@ -229,16 +234,16 @@ __NEXT_STEP:;
PUSH(_0);
DISPATCH();
TARGET(BUILD_DICT)
const static StrName m_dict("dict");
DEF_SNAME(dict);
_0 = VAR(STACK_VIEW(byte.arg).to_tuple());
_0 = call(builtins->attr(m_dict), _0);
_0 = call(builtins->attr(dict), _0);
STACK_SHRINK(byte.arg);
PUSH(_0);
DISPATCH();
TARGET(BUILD_SET)
const static StrName m_set("set");
DEF_SNAME(set);
_0 = VAR(STACK_VIEW(byte.arg).to_tuple());
_0 = call(builtins->attr(m_set), _0);
_0 = call(builtins->attr(set), _0);
STACK_SHRINK(byte.arg);
PUSH(_0);
DISPATCH();
@ -256,58 +261,47 @@ __NEXT_STEP:;
TARGET(BUILD_STRING) {
std::stringstream ss;
ArgsView view = STACK_VIEW(byte.arg);
for(PyObject* obj : view) ss << CAST(Str&, asStr(obj));
for(PyObject* obj : view) ss << CAST(Str&, py_str(obj));
STACK_SHRINK(byte.arg);
PUSH(VAR(ss.str()));
} DISPATCH();
/*****************************************/
TARGET(BINARY_TRUEDIV)
_1 = POPX();
_0 = TOP();
if(is_float(_0)){
TOP() = VAR(_CAST(f64, _0) / num_to_float(_1));
}else{
TOP() = call_method(_0, __truediv__, _1);
#define BINARY_OP_SPECIAL(func) \
_1 = POPX(); \
_0 = TOP(); \
_ti = _inst_type_info(_0); \
if(_ti->m##func){ \
TOP() = VAR(_ti->m##func(this, _0, _1)); \
}else{ \
TOP() = call_method(_0, func, _1); \
}
TARGET(BINARY_TRUEDIV)
BINARY_OP_SPECIAL(__truediv__);
DISPATCH();
TARGET(BINARY_POW)
_1 = POPX();
_0 = TOP();
TOP() = call_method(_0, __pow__, _1);
BINARY_OP_SPECIAL(__pow__);
DISPATCH();
#define INT_BINARY_OP(op, func) \
if(is_both_int(TOP(), SECOND())){ \
i64 b = _CAST(i64, TOP()); \
i64 a = _CAST(i64, SECOND()); \
POP(); \
TOP() = VAR(a op b); \
}else{ \
_1 = POPX(); \
_0 = TOP(); \
TOP() = call_method(_0, func, _1); \
}
TARGET(BINARY_ADD)
INT_BINARY_OP(+, __add__)
BINARY_OP_SPECIAL(__add__);
DISPATCH()
TARGET(BINARY_SUB)
INT_BINARY_OP(-, __sub__)
BINARY_OP_SPECIAL(__sub__);
DISPATCH()
TARGET(BINARY_MUL)
INT_BINARY_OP(*, __mul__)
BINARY_OP_SPECIAL(__mul__);
DISPATCH()
TARGET(BINARY_FLOORDIV)
INT_BINARY_OP(/, __floordiv__)
BINARY_OP_SPECIAL(__floordiv__);
DISPATCH()
TARGET(BINARY_MOD)
INT_BINARY_OP(%, __mod__)
BINARY_OP_SPECIAL(__mod__);
DISPATCH()
TARGET(COMPARE_LT)
INT_BINARY_OP(<, __lt__)
BINARY_OP_SPECIAL(__lt__);
DISPATCH()
TARGET(COMPARE_LE)
INT_BINARY_OP(<=, __le__)
BINARY_OP_SPECIAL(__le__);
DISPATCH()
TARGET(COMPARE_EQ)
_1 = POPX();
@ -320,34 +314,32 @@ __NEXT_STEP:;
TOP() = VAR(py_not_equals(_0, _1));
DISPATCH()
TARGET(COMPARE_GT)
INT_BINARY_OP(>, __gt__)
BINARY_OP_SPECIAL(__gt__);
DISPATCH()
TARGET(COMPARE_GE)
INT_BINARY_OP(>=, __ge__)
BINARY_OP_SPECIAL(__ge__);
DISPATCH()
TARGET(BITWISE_LSHIFT)
INT_BINARY_OP(<<, __lshift__)
BINARY_OP_SPECIAL(__lshift__);
DISPATCH()
TARGET(BITWISE_RSHIFT)
INT_BINARY_OP(>>, __rshift__)
BINARY_OP_SPECIAL(__rshift__);
DISPATCH()
TARGET(BITWISE_AND)
INT_BINARY_OP(&, __and__)
BINARY_OP_SPECIAL(__and__);
DISPATCH()
TARGET(BITWISE_OR)
INT_BINARY_OP(|, __or__)
BINARY_OP_SPECIAL(__or__);
DISPATCH()
TARGET(BITWISE_XOR)
INT_BINARY_OP(^, __xor__)
BINARY_OP_SPECIAL(__xor__);
DISPATCH()
#undef INT_BINARY_OP
TARGET(BINARY_MATMUL)
_1 = POPX();
_0 = TOP();
TOP() = call_method(_0, __matmul__, _1);
BINARY_OP_SPECIAL(__matmul__);
DISPATCH();
#undef BINARY_OP_SPECIAL
TARGET(IS_OP)
_1 = POPX(); // rhs
_0 = TOP(); // lhs
@ -359,7 +351,12 @@ __NEXT_STEP:;
DISPATCH();
TARGET(CONTAINS_OP)
// a in b -> b __contains__ a
_0 = call_method(TOP(), __contains__, SECOND());
_ti = _inst_type_info(TOP());
if(_ti->m__contains__){
_0 = VAR(_ti->m__contains__(this, TOP(), SECOND()));
}else{
_0 = call_method(TOP(), __contains__, SECOND());
}
POP();
if(byte.arg == 1){
TOP() = VAR(!CAST(bool, _0));
@ -430,9 +427,9 @@ __NEXT_STEP:;
call_method(SECOND(), __setitem__, t[0], t[1]);
} DISPATCH();
TARGET(SET_ADD)
const static StrName m_add("add");
DEF_SNAME(add);
_0 = POPX();
call_method(SECOND(), m_add, _0);
call_method(SECOND(), add, _0);
DISPATCH();
/*****************************************/
TARGET(UNARY_NEGATIVE)
@ -443,7 +440,7 @@ __NEXT_STEP:;
DISPATCH();
/*****************************************/
TARGET(GET_ITER)
TOP() = asIter(TOP());
TOP() = py_iter(TOP());
DISPATCH();
TARGET(FOR_ITER)
_0 = PyIterNext(TOP());
@ -489,7 +486,7 @@ __NEXT_STEP:;
TARGET(UNPACK_SEQUENCE)
TARGET(UNPACK_EX) {
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
_0 = asIter(POPX());
_0 = py_iter(POPX());
for(int i=0; i<byte.arg; i++){
_1 = PyIterNext(_0);
if(_1 == StopIteration) ValueError("not enough values to unpack");
@ -510,7 +507,7 @@ __NEXT_STEP:;
} DISPATCH();
TARGET(UNPACK_UNLIMITED) {
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
_0 = asIter(POPX());
_0 = py_iter(POPX());
_1 = PyIterNext(_0);
while(_1 != StopIteration){
PUSH(_1);
@ -538,11 +535,11 @@ __NEXT_STEP:;
/*****************************************/
// TODO: using "goto" inside with block may cause __exit__ not called
TARGET(WITH_ENTER)
const static StrName __enter__("__enter__");
DEF_SNAME(__enter__);
call_method(POPX(), __enter__);
DISPATCH();
TARGET(WITH_EXIT)
const static StrName __exit__("__exit__");
DEF_SNAME(__exit__);
call_method(POPX(), __exit__);
DISPATCH();
/*****************************************/
@ -553,7 +550,7 @@ __NEXT_STEP:;
auto& t = CAST(Tuple&, _0);
if(t.size() != 2) ValueError("assert tuple must have 2 elements");
_0 = t[0];
msg = CAST(Str&, asStr(t[1]));
msg = CAST(Str&, py_str(t[1]));
}
bool ok = asBool(_0);
POP();
@ -566,13 +563,13 @@ __NEXT_STEP:;
} DISPATCH();
TARGET(RAISE) {
_0 = POPX();
Str msg = _0 == None ? "" : CAST(Str, asStr(_0));
Str msg = _0 == None ? "" : CAST(Str, py_str(_0));
_error(StrName(byte.arg), msg);
} DISPATCH();
TARGET(RE_RAISE) _raise(); DISPATCH();
/*****************************************/
TARGET(SETUP_DOCSTRING)
const static StrName __doc__("__doc__");
DEF_SNAME(__doc__);
TOP()->attr().set(__doc__, co_consts[byte.arg]);
DISPATCH();
TARGET(FORMAT_STRING) {

View File

@ -347,8 +347,8 @@ struct PyVec2: Vec2 {
return VAR(Vec2(x, y));
});
vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
PyVec2& self = _CAST(PyVec2&, args[0]);
vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyVec2& self = _CAST(PyVec2&, obj);
std::stringstream ss;
ss << "vec2(" << self.x << ", " << self.y << ")";
return VAR(ss.str());
@ -397,8 +397,8 @@ struct PyVec3: Vec3 {
return VAR(Vec3(x, y, z));
});
vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
PyVec3& self = _CAST(PyVec3&, args[0]);
vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyVec3& self = _CAST(PyVec3&, obj);
std::stringstream ss;
ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
return VAR(ss.str());
@ -471,8 +471,8 @@ struct PyMat3x3: Mat3x3{
#undef METHOD_PROXY_NONE
vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
PyMat3x3& self = _CAST(PyMat3x3&, obj);
std::stringstream ss;
ss << std::fixed << std::setprecision(4);
ss << "mat3x3([[" << self._11 << ", " << self._12 << ", " << self._13 << "],\n";
@ -486,9 +486,9 @@ struct PyMat3x3: Mat3x3{
return VAR_T(PyMat3x3, self);
});
vm->bind_method<1>(type, "__getitem__", [](VM* vm, ArgsView args){
PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
Tuple& t = CAST(Tuple&, args[1]);
vm->bind__getitem__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){
PyMat3x3& self = _CAST(PyMat3x3&, obj);
Tuple& t = CAST(Tuple&, index);
if(t.size() != 2){
vm->TypeError("Mat3x3.__getitem__ takes a tuple of 2 integers");
return vm->None;

View File

@ -187,7 +187,7 @@ Str obj_type_name(VM* vm, Type type);
#if DEBUG_NO_BUILTIN_MODULES
#define OBJ_NAME(obj) Str("<?>")
#else
const static StrName __name__("__name__");
DEF_SNAME(__name__);
#define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__))
#endif

View File

@ -58,8 +58,8 @@ inline void init_builtins(VM* _vm) {
return false; \
}); \
_vm->bind##name(_vm->tp_float, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
if(is_int(rhs)) return _CAST(f64, lhs) == _CAST(i64, rhs); \
if(is_float(rhs)) return _CAST(f64, lhs) == _CAST(f64, rhs); \
if(is_int(rhs)) return _CAST(f64, lhs) op _CAST(i64, rhs); \
if(is_float(rhs)) return _CAST(f64, lhs) op _CAST(f64, rhs); \
if constexpr(is_eq) return lhs op rhs; \
vm->TypeError("unsupported operand type(s) for " #op ); \
return false; \
@ -131,7 +131,7 @@ inline void init_builtins(VM* _vm) {
return vm->None;
});
_vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->asRepr(args[0])));
_vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->py_repr(args[0])));
_vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){
const PyTypeInfo* ti = vm->_inst_type_info(args[0]);
@ -140,7 +140,7 @@ inline void init_builtins(VM* _vm) {
});
_vm->bind_builtin_func<1>("hash", [](VM* vm, ArgsView args){
i64 value = vm->py_hash(args[0]);
i64 value = vm->hash(args[0]);
if(((value << 2) >> 2) != value) value >>= 2;
return VAR(value);
});
@ -178,7 +178,7 @@ inline void init_builtins(VM* _vm) {
});
_vm->bind_builtin_func<1>("iter", [](VM* vm, ArgsView args) {
return vm->asIter(args[0]);
return vm->py_iter(args[0]);
});
_vm->bind_builtin_func<1>("next", [](VM* vm, ArgsView args) {
@ -199,8 +199,9 @@ inline void init_builtins(VM* _vm) {
return VAR(std::move(ret));
});
_vm->bind__repr__(_vm->tp_object, [](VM* vm, PyObject* self) {
if(is_tagged(self)) self = nullptr;
_vm->bind__repr__(_vm->tp_object, [](VM* vm, PyObject* obj) {
PyObject* self = obj;
if(is_tagged(obj)) self = nullptr;
std::stringstream ss;
ss << "<" << OBJ_NAME(vm->_t(self)) << " object at " << std::hex << self << ">";
return VAR(ss.str());
@ -356,7 +357,7 @@ inline void init_builtins(VM* _vm) {
});
/************ PyString ************/
_vm->bind_constructor<2>("str", CPP_LAMBDA(vm->asStr(args[1])));
_vm->bind_constructor<2>("str", CPP_LAMBDA(vm->py_str(args[1])));
_vm->bind__hash__(_vm->tp_str, [](VM* vm, PyObject* obj) {
return (i64)_CAST(Str&, obj).hash();
@ -460,7 +461,7 @@ inline void init_builtins(VM* _vm) {
auto _lock = vm->heap.gc_scope_lock();
const Str& self = _CAST(Str&, args[0]);
FastStrStream ss;
PyObject* it = vm->asIter(args[1]); // strong ref
PyObject* it = vm->py_iter(args[1]); // strong ref
PyObject* obj = vm->PyIterNext(it);
while(obj != vm->StopIteration){
if(!ss.empty()) ss << self;
@ -494,7 +495,7 @@ inline void init_builtins(VM* _vm) {
_vm->bind_method<1>("list", "extend", [](VM* vm, ArgsView args) {
auto _lock = vm->heap.gc_scope_lock();
List& self = _CAST(List&, args[0]);
PyObject* it = vm->asIter(args[1]); // strong ref
PyObject* it = vm->py_iter(args[1]); // strong ref
PyObject* obj = vm->PyIterNext(it);
while(obj != vm->StopIteration){
self.push_back(obj);
@ -578,7 +579,7 @@ inline void init_builtins(VM* _vm) {
i64 x = 1000003;
const Tuple& items = CAST(Tuple&, obj);
for (int i=0; i<items.size(); i++) {
i64 y = vm->py_hash(items[i]);
i64 y = vm->hash(items[i]);
// recommended by Github Copilot
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
}
@ -617,7 +618,12 @@ inline void init_builtins(VM* _vm) {
_vm->bind__xor__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) {
return VAR(_CAST(bool, lhs) != CAST(bool, rhs));
});
_vm->bind__eq__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) {
return _CAST(bool, lhs) == CAST(bool, rhs);
});
_vm->bind__ne__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) {
return _CAST(bool, lhs) != CAST(bool, rhs);
});
_vm->bind__repr__(_vm->_type("ellipsis"), [](VM* vm, PyObject* self) {
return VAR("Ellipsis");
});
@ -697,9 +703,9 @@ inline void init_builtins(VM* _vm) {
const Slice& self = _CAST(Slice&, obj);
std::stringstream ss;
ss << "slice(";
ss << CAST(Str, vm->asRepr(self.start)) << ", ";
ss << CAST(Str, vm->asRepr(self.stop)) << ", ";
ss << CAST(Str, vm->asRepr(self.step)) << ")";
ss << CAST(Str, vm->py_repr(self.start)) << ", ";
ss << CAST(Str, vm->py_repr(self.stop)) << ", ";
ss << CAST(Str, vm->py_repr(self.step)) << ")";
return VAR(ss.str());
});
@ -748,7 +754,7 @@ inline void init_builtins(VM* _vm) {
for(auto& item : self.attr().items()){
if(!first) ss << ", ";
first = false;
ss << item.first.escape() << ": " << CAST(Str, vm->asRepr(item.second));
ss << item.first.escape() << ": " << CAST(Str, vm->py_repr(item.second));
}
ss << "})";
return VAR(ss.str());
@ -818,7 +824,11 @@ inline void add_module_json(VM* vm){
return vm->_exec(code, vm->top_frame()->_module);
});
vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->call_method(args[0], __json__)));
vm->bind_func<1>(mod, "dumps", [](VM* vm, ArgsView args) {
const PyTypeInfo* ti = vm->_inst_type_info(args[0]);
if(ti->m__json__) return ti->m__json__(vm, args[0]);
return vm->call_method(args[0], __json__);
});
}
@ -1129,7 +1139,7 @@ extern "C" {
pkpy::PyObject* val = vm->_main->attr().try_get(name);
if(val == nullptr) return nullptr;
try{
pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->asRepr(val));
pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->py_repr(val));
return repr.c_str_dup();
}catch(...){
return nullptr;
@ -1141,7 +1151,7 @@ extern "C" {
pkpy::PyObject* ret = vm->exec(source, "<eval>", pkpy::EVAL_MODE);
if(ret == nullptr) return nullptr;
try{
pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->asRepr(ret));
pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->py_repr(ret));
return repr.c_str_dup();
}catch(...){
return nullptr;

View File

@ -387,7 +387,6 @@ const StrName __next__ = StrName::get("__next__"); // unused
const StrName __json__ = StrName::get("__json__");
const StrName __neg__ = StrName::get("__neg__"); // unused
const StrName __bool__ = StrName::get("__bool__"); // unused
// logical operators
const StrName __eq__ = StrName::get("__eq__");
const StrName __ne__ = StrName::get("__ne__");
@ -396,7 +395,6 @@ const StrName __le__ = StrName::get("__le__");
const StrName __gt__ = StrName::get("__gt__");
const StrName __ge__ = StrName::get("__ge__");
const StrName __contains__ = StrName::get("__contains__");
// binary operators
const StrName __add__ = StrName::get("__add__");
const StrName __sub__ = StrName::get("__sub__");
@ -406,16 +404,16 @@ const StrName __floordiv__ = StrName::get("__floordiv__");
const StrName __mod__ = StrName::get("__mod__");
const StrName __pow__ = StrName::get("__pow__");
const StrName __matmul__ = StrName::get("__matmul__");
const StrName __lshift__ = StrName::get("__lshift__");
const StrName __rshift__ = StrName::get("__rshift__");
const StrName __and__ = StrName::get("__and__");
const StrName __or__ = StrName::get("__or__");
const StrName __xor__ = StrName::get("__xor__");
// indexer
const StrName __getitem__ = StrName::get("__getitem__");
const StrName __setitem__ = StrName::get("__setitem__");
const StrName __delitem__ = StrName::get("__delitem__");
#define DEF_SNAME(name) const static StrName name(#name)
} // namespace pkpy

View File

@ -166,15 +166,25 @@ public:
return FrameId(&callstack.data(), callstack.size()-1);
}
PyObject* asStr(PyObject* obj){
PyObject* py_str(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj);
if(ti->m__str__) return ti->m__str__(this, obj);
PyObject* self;
PyObject* f = get_unbound_method(obj, __str__, &self, false);
if(self != PY_NULL) return call_method(self, f);
return asRepr(obj);
return py_repr(obj);
}
PyObject* asIter(PyObject* obj){
PyObject* py_repr(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj);
if(ti->m__repr__) return ti->m__repr__(this, obj);
return call_method(obj, __repr__);
}
PyObject* py_iter(PyObject* obj){
if(is_type(obj, tp_iterator)) return obj;
const PyTypeInfo* ti = _inst_type_info(obj);
if(ti->m__iter__) return ti->m__iter__(this, obj);
PyObject* self;
PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
if(self != PY_NULL) return call_method(self, iter_f);
@ -300,11 +310,11 @@ public:
PyObject* _find_type_object(const Str& type){
PyObject* obj = builtins->attr().try_get(type);
check_non_tagged_type(obj, tp_type);
if(obj == nullptr){
for(auto& t: _all_types) if(t.name == type) return t.obj;
throw std::runtime_error(fmt("type not found: ", type));
}
check_non_tagged_type(obj, tp_type);
return obj;
}
@ -560,8 +570,7 @@ public:
PyObject* num_negated(PyObject* obj);
f64 num_to_float(PyObject* obj);
bool asBool(PyObject* obj);
i64 py_hash(PyObject* obj);
PyObject* asRepr(PyObject*);
i64 hash(PyObject* obj);
PyObject* asList(PyObject*);
PyObject* new_module(StrName name);
Str disassemble(CodeObject_ co);
@ -713,6 +722,10 @@ inline PyObject* py_var(VM* vm, NoReturn val){
return vm->None;
}
inline PyObject* py_var(VM* vm, PyObject* val){
return val;
}
inline PyObject* VM::num_negated(PyObject* obj){
if (is_int(obj)){
return VAR(-CAST(i64, obj));
@ -749,7 +762,7 @@ inline bool VM::asBool(PyObject* obj){
inline PyObject* VM::asList(PyObject* it){
auto _lock = heap.gc_scope_lock();
it = asIter(it);
it = py_iter(it);
List list;
PyObject* obj = PyIterNext(it);
while(obj != StopIteration){
@ -801,19 +814,15 @@ inline void VM::parse_int_slice(const Slice& s, int length, int& start, int& sto
}
}
inline i64 VM::py_hash(PyObject* obj){
inline i64 VM::hash(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(obj);
if(ti->m__hash__) return ti->m__hash__(this, obj);
PyObject* ret = call_method(obj, __hash__);
return CAST(i64, ret);
}
inline PyObject* VM::asRepr(PyObject* obj){
return call_method(obj, __repr__);
}
inline PyObject* VM::format(Str spec, PyObject* obj){
if(spec.empty()) return asStr(obj);
if(spec.empty()) return py_str(obj);
char type;
switch(spec.end()[-1]){
case 'f': case 'd': case 's':
@ -867,7 +876,7 @@ inline PyObject* VM::format(Str spec, PyObject* obj){
}else if(type == 's'){
ret = CAST(Str&, obj);
}else{
ret = CAST(Str&, asStr(obj));
ret = CAST(Str&, py_str(obj));
}
if(width > ret.length()){
int pad = width - ret.length();
@ -893,7 +902,7 @@ inline std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
switch(byte.op){
case OP_LOAD_CONST:
if(vm != nullptr){
argStr += fmt(" (", CAST(Str, vm->asRepr(co->consts[byte.arg])), ")");
argStr += fmt(" (", CAST(Str, vm->py_repr(co->consts[byte.arg])), ")");
}
break;
case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
@ -1117,7 +1126,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
if(method_call) FATAL_ERROR();
// [type, NULL, args..., kwargs...]
const static StrName __new__("__new__");
DEF_SNAME(__new__);
PyObject* new_f = find_name_in_mro(callable, __new__);
PyObject* obj;
if(new_f != nullptr){
@ -1136,7 +1145,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
// __init__
PyObject* self;
const static StrName __init__("__init__");
DEF_SNAME(__init__);
callable = get_unbound_method(obj, __init__, &self, false);
if (self != PY_NULL) {
// replace `NULL` with `self`
@ -1155,7 +1164,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
// handle `__call__` overload
PyObject* self;
const static StrName __call__("__call__");
DEF_SNAME(__call__);
PyObject* call_f = get_unbound_method(callable, __call__, &self, false);
if(self != PY_NULL){
p1[-(ARGC + 2)] = call_f;
@ -1245,8 +1254,8 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
return nullptr;
}
const static StrName __get__("__get__");
const static StrName __set__("__set__");
DEF_SNAME(__get__);
DEF_SNAME(__set__);
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
@ -1424,7 +1433,7 @@ inline void VM::bind__len__(Type type, i64 (*f)(VM* vm, PyObject*)){
inline void Dict::_probe(PyObject *key, bool &ok, int &i) const{
ok = false;
i = vm->py_hash(key) & _mask;
i = vm->hash(key) & _mask;
while(_items[i].first != nullptr) {
if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
i = (i + 1) & _mask;