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

View File

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

View File

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

View File

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

View File

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

View File

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