mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
...
This commit is contained in:
parent
3bac1d7388
commit
e5fb7a65ff
111
src/ceval.h
111
src/ceval.h
@ -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();
|
||||||
|
_ti = _inst_type_info(_0);
|
||||||
|
if(_ti->m__delitem__){
|
||||||
|
_ti->m__delitem__(this, _0, _1);
|
||||||
|
}else{
|
||||||
call_method(_0, __delitem__, _1);
|
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();
|
|
||||||
_0 = TOP();
|
|
||||||
if(is_float(_0)){
|
|
||||||
TOP() = VAR(_CAST(f64, _0) / num_to_float(_1));
|
|
||||||
}else{
|
|
||||||
TOP() = call_method(_0, __truediv__, _1);
|
|
||||||
}
|
|
||||||
DISPATCH();
|
|
||||||
TARGET(BINARY_POW)
|
|
||||||
_1 = POPX();
|
|
||||||
_0 = TOP();
|
|
||||||
TOP() = call_method(_0, __pow__, _1);
|
|
||||||
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(); \
|
_1 = POPX(); \
|
||||||
_0 = TOP(); \
|
_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); \
|
TOP() = call_method(_0, func, _1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET(BINARY_TRUEDIV)
|
||||||
|
BINARY_OP_SPECIAL(__truediv__);
|
||||||
|
DISPATCH();
|
||||||
|
TARGET(BINARY_POW)
|
||||||
|
BINARY_OP_SPECIAL(__pow__);
|
||||||
|
DISPATCH();
|
||||||
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
|
||||||
|
_ti = _inst_type_info(TOP());
|
||||||
|
if(_ti->m__contains__){
|
||||||
|
_0 = VAR(_ti->m__contains__(this, TOP(), SECOND()));
|
||||||
|
}else{
|
||||||
_0 = call_method(TOP(), __contains__, SECOND());
|
_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) {
|
||||||
|
18
src/linalg.h
18
src/linalg.h
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
51
src/vm.h
51
src/vm.h
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user