From 715c8670d11825cc33e02437283807b459f18a92 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Fri, 16 Jun 2023 21:35:28 +0800 Subject: [PATCH] ... --- python/_long.py | 4 +- src/ceval.h | 9 ++-- src/cffi.h | 37 ++++++++------- src/common.h | 2 +- src/pocketpy.h | 116 +++++++++++++++++++++++------------------------ src/vm.h | 90 ++++++++++++++++++------------------ tests/09_long.py | 6 ++- 7 files changed, 137 insertions(+), 127 deletions(-) diff --git a/python/_long.py b/python/_long.py index 908f96ee..fcb7df79 100644 --- a/python/_long.py +++ b/python/_long.py @@ -307,8 +307,8 @@ class long: def __cmp__(self, other): if type(other) is int: other = long(other) - else: - assert type(other) is long + elif type(other) is not long: + return NotImplemented if self.sign > other.sign: return 1 elif self.sign < other.sign: diff --git a/src/ceval.h b/src/ceval.h index 7067d632..f30c411f 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -337,6 +337,7 @@ __NEXT_STEP:; _2 = get_unbound_method(_1, func, &self, false); \ if(_2 != nullptr) TOP() = call_method(self, _2, _0); \ else BinaryOptError(op); \ + if(TOP() == NotImplemented) BinaryOptError(op); \ } TARGET(BINARY_TRUEDIV) @@ -373,11 +374,11 @@ __NEXT_STEP:; DISPATCH() TARGET(COMPARE_LT) BINARY_OP_SPECIAL(__lt__); - if(TOP() == NotImplemented) BinaryOptError("<"); + BINARY_OP_RSPECIAL("<", __gt__); DISPATCH() TARGET(COMPARE_LE) BINARY_OP_SPECIAL(__le__); - if(TOP() == NotImplemented) BinaryOptError("<="); + BINARY_OP_RSPECIAL("<=", __ge__); DISPATCH() TARGET(COMPARE_EQ) _1 = POPX(); @@ -391,11 +392,11 @@ __NEXT_STEP:; DISPATCH() TARGET(COMPARE_GT) BINARY_OP_SPECIAL(__gt__); - if(TOP() == NotImplemented) BinaryOptError(">"); + BINARY_OP_RSPECIAL(">", __lt__); DISPATCH() TARGET(COMPARE_GE) BINARY_OP_SPECIAL(__ge__); - if(TOP() == NotImplemented) BinaryOptError(">="); + BINARY_OP_RSPECIAL(">=", __le__); DISPATCH() TARGET(BITWISE_LSHIFT) PREDICT_INT_OP(<<); diff --git a/src/cffi.h b/src/cffi.h index 244e317c..bd942928 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -45,6 +45,11 @@ struct VoidP{ bool operator!=(const VoidP& other) const { return ptr != other.ptr || base_offset != other.base_offset; } + bool operator<(const VoidP& other) const { return ptr < other.ptr; } + bool operator<=(const VoidP& other) const { return ptr <= other.ptr; } + bool operator>(const VoidP& other) const { return ptr > other.ptr; } + bool operator>=(const VoidP& other) const { return ptr >= other.ptr; } + Str hex() const{ std::stringstream ss; @@ -76,23 +81,20 @@ struct VoidP{ return VAR(ss.str()); }); - vm->bind__eq__(OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ - if(!is_non_tagged_type(rhs, VoidP::_type(vm))) return false; - return _CAST(VoidP&, lhs) == _CAST(VoidP&, rhs); - }); - vm->bind__gt__(OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ - return _CAST(VoidP&, lhs).ptr > CAST(VoidP&, rhs).ptr; - }); - vm->bind__lt__(OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ - return _CAST(VoidP&, lhs).ptr < CAST(VoidP&, rhs).ptr; - }); - vm->bind__ge__(OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ - return _CAST(VoidP&, lhs).ptr >= CAST(VoidP&, rhs).ptr; - }); - vm->bind__le__(OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ - return _CAST(VoidP&, lhs).ptr <= CAST(VoidP&, rhs).ptr; +#define BIND_CMP(name, op) \ + vm->bind##name(OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ \ + if(!is_non_tagged_type(rhs, VoidP::_type(vm))) return vm->NotImplemented; \ + return VAR(_CAST(VoidP&, lhs) op _CAST(VoidP&, rhs)); \ }); + BIND_CMP(__eq__, ==) + BIND_CMP(__lt__, <) + BIND_CMP(__le__, <=) + BIND_CMP(__gt__, >) + BIND_CMP(__ge__, >=) + +#undef BIND_CMP + vm->bind__hash__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){ VoidP& self = _CAST(VoidP&, obj); return reinterpret_cast(self.ptr); @@ -243,9 +245,10 @@ struct C99Struct{ vm->bind__eq__(OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ C99Struct& self = _CAST(C99Struct&, lhs); - if(!is_non_tagged_type(rhs, C99Struct::_type(vm))) return false; + if(!is_non_tagged_type(rhs, C99Struct::_type(vm))) return vm->NotImplemented; C99Struct& other = _CAST(C99Struct&, rhs); - return self.size == other.size && memcmp(self.p, other.p, self.size) == 0; + bool ok = self.size == other.size && memcmp(self.p, other.p, self.size) == 0; + return VAR(ok); }); // patch VoidP diff --git a/src/common.h b/src/common.h index 96087fff..781c8938 100644 --- a/src/common.h +++ b/src/common.h @@ -20,7 +20,7 @@ #include #include -#define PK_VERSION "1.0.3" +#define PK_VERSION "1.0.4" #include "config.h" diff --git a/src/pocketpy.h b/src/pocketpy.h index 2fc59c04..82334bb8 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -52,28 +52,24 @@ inline void init_builtins(VM* _vm) { #undef BIND_NUM_ARITH_OPT -#define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \ +#define BIND_NUM_LOGICAL_OPT(name, op) \ _vm->bind##name(_vm->tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \ - if(is_int(rhs)) return _CAST(i64, lhs) op _CAST(i64, rhs); \ - if(is_float(rhs)) return _CAST(i64, lhs) op _CAST(f64, rhs); \ - if constexpr(is_eq) return lhs op rhs; \ - vm->TypeError("unsupported operand type(s) for " #op ); \ - return false; \ + if(is_int(rhs)) return VAR(_CAST(i64, lhs) op _CAST(i64, rhs)); \ + if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \ + return vm->NotImplemented; \ }); \ _vm->bind##name(_vm->tp_float, [](VM* vm, PyObject* lhs, PyObject* 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; \ + if(is_int(rhs)) return VAR(_CAST(f64, lhs) op _CAST(i64, rhs)); \ + if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \ + return vm->NotImplemented; \ }); - BIND_NUM_LOGICAL_OPT(__lt__, <, false) - BIND_NUM_LOGICAL_OPT(__le__, <=, false) - BIND_NUM_LOGICAL_OPT(__gt__, >, false) - BIND_NUM_LOGICAL_OPT(__ge__, >=, false) - BIND_NUM_LOGICAL_OPT(__eq__, ==, true) - + BIND_NUM_LOGICAL_OPT(__eq__, ==) + BIND_NUM_LOGICAL_OPT(__lt__, <) + BIND_NUM_LOGICAL_OPT(__le__, <=) + BIND_NUM_LOGICAL_OPT(__gt__, >) + BIND_NUM_LOGICAL_OPT(__ge__, >=) + #undef BIND_NUM_ARITH_OPT #undef BIND_NUM_LOGICAL_OPT @@ -263,7 +259,7 @@ inline void init_builtins(VM* _vm) { return VAR(ss.str()); }); - _vm->bind__eq__(_vm->tp_object, [](VM* vm, PyObject* lhs, PyObject* rhs) { return lhs == rhs; }); + _vm->bind__eq__(_vm->tp_object, [](VM* vm, PyObject* lhs, PyObject* rhs) { return VAR(lhs == rhs); }); _vm->bind__hash__(_vm->tp_object, [](VM* vm, PyObject* obj) { return BITS(obj); }); _vm->cached_object__new__ = _vm->bind_constructor<1>("object", [](VM* vm, ArgsView args) { @@ -449,8 +445,7 @@ inline void init_builtins(VM* _vm) { }); _vm->bind__contains__(_vm->tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { const Str& self = _CAST(Str&, lhs); - const Str& other = CAST(Str&, rhs); - return self.index(other) != -1; + return VAR(self.index(CAST(Str&, rhs)) != -1); }); _vm->bind__str__(_vm->tp_str, [](VM* vm, PyObject* obj) { return obj; }); _vm->bind__iter__(_vm->tp_str, [](VM* vm, PyObject* obj) { return VAR_T(StringIter, obj); }); @@ -462,23 +457,20 @@ inline void init_builtins(VM* _vm) { const Str& self = _CAST(Str&, obj); return VAR(self.escape(false)); }); - _vm->bind__eq__(_vm->tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { - if(!is_non_tagged_type(rhs, vm->tp_str)) return false; - return _CAST(Str&, lhs) == _CAST(Str&, rhs); - }); - _vm->bind__gt__(_vm->tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { - return _CAST(Str&, lhs) > CAST(Str&, rhs); - }); - _vm->bind__lt__(_vm->tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { - return _CAST(Str&, lhs) < CAST(Str&, rhs); - }); - _vm->bind__ge__(_vm->tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { - return _CAST(Str&, lhs) >= CAST(Str&, rhs); - }); - _vm->bind__le__(_vm->tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { - return _CAST(Str&, lhs) <= CAST(Str&, rhs); + +#define BIND_CMP_STR(name, op) \ + _vm->bind##name(_vm->tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { \ + if(!is_non_tagged_type(rhs, vm->tp_str)) return vm->NotImplemented; \ + return VAR(_CAST(Str&, lhs) op _CAST(Str&, rhs)); \ }); + BIND_CMP_STR(__eq__, ==) + BIND_CMP_STR(__lt__, <) + BIND_CMP_STR(__le__, <=) + BIND_CMP_STR(__gt__, >) + BIND_CMP_STR(__ge__, >=) +#undef BIND_CMP_STR + _vm->bind__getitem__(_vm->tp_str, [](VM* vm, PyObject* obj, PyObject* index) { const Str& self = _CAST(Str&, obj); if(is_non_tagged_type(index, vm->tp_slice)){ @@ -572,8 +564,8 @@ inline void init_builtins(VM* _vm) { _vm->bind__contains__(_vm->tp_list, [](VM* vm, PyObject* obj, PyObject* item) { List& self = _CAST(List&, obj); - for(PyObject* i: self) if(vm->py_equals(i, item)) return true; - return false; + for(PyObject* i: self) if(vm->py_equals(i, item)) return vm->True; + return vm->False; }); _vm->bind_method<1>("list", "count", [](VM* vm, ArgsView args) { @@ -585,12 +577,13 @@ inline void init_builtins(VM* _vm) { _vm->bind__eq__(_vm->tp_list, [](VM* vm, PyObject* lhs, PyObject* rhs) { List& a = _CAST(List&, lhs); + if(!is_non_tagged_type(rhs, vm->tp_list)) return vm->NotImplemented; List& b = _CAST(List&, rhs); - if(a.size() != b.size()) return false; + if(a.size() != b.size()) return vm->False; for(int i=0; ipy_equals(a[i], b[i])) return false; + if(!vm->py_equals(a[i], b[i])) return vm->False; } - return true; + return vm->True; }); _vm->bind_method<1>("list", "index", [](VM* vm, ArgsView args) { @@ -725,8 +718,8 @@ inline void init_builtins(VM* _vm) { _vm->bind__contains__(_vm->tp_tuple, [](VM* vm, PyObject* obj, PyObject* item) { Tuple& self = _CAST(Tuple&, obj); - for(PyObject* i: self) if(vm->py_equals(i, item)) return true; - return false; + for(PyObject* i: self) if(vm->py_equals(i, item)) return vm->True; + return vm->False; }); _vm->bind_method<1>("tuple", "count", [](VM* vm, ArgsView args) { @@ -738,12 +731,13 @@ inline void init_builtins(VM* _vm) { _vm->bind__eq__(_vm->tp_tuple, [](VM* vm, PyObject* lhs, PyObject* rhs) { const Tuple& self = _CAST(Tuple&, lhs); - const Tuple& other = CAST(Tuple&, rhs); - if(self.size() != other.size()) return false; + if(!is_non_tagged_type(rhs, vm->tp_tuple)) return vm->NotImplemented; + const Tuple& other = _CAST(Tuple&, rhs); + if(self.size() != other.size()) return vm->False; for(int i = 0; i < self.size(); i++) { - if(!vm->py_equals(self[i], other[i])) return false; + if(!vm->py_equals(self[i], other[i])) return vm->False; } - return true; + return vm->True; }); _vm->bind__hash__(_vm->tp_tuple, [](VM* vm, PyObject* obj) { @@ -790,10 +784,15 @@ inline void init_builtins(VM* _vm) { 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); + if(is_non_tagged_type(rhs, vm->tp_bool)) return VAR(lhs == rhs); + if(is_int(rhs)) return VAR(_CAST(bool, lhs) == (bool)CAST(i64, rhs)); + return vm->NotImplemented; }); _vm->bind__repr__(_vm->_type("ellipsis"), [](VM* vm, PyObject* self) { - return VAR("Ellipsis"); + return VAR("..."); + }); + _vm->bind__repr__(_vm->_type("NotImplementedType"), [](VM* vm, PyObject* self) { + return VAR("NotImplemented"); }); /************ bytes ************/ @@ -856,7 +855,8 @@ inline void init_builtins(VM* _vm) { }); _vm->bind__eq__(_vm->tp_bytes, [](VM* vm, PyObject* lhs, PyObject* rhs) { - return _CAST(Bytes&, lhs) == _CAST(Bytes&, rhs); + if(!is_non_tagged_type(rhs, vm->tp_bytes)) return vm->NotImplemented; + return VAR(_CAST(Bytes&, lhs) == _CAST(Bytes&, rhs)); }); /************ slice ************/ _vm->bind_constructor<4>("slice", [](VM* vm, ArgsView args) { @@ -926,7 +926,7 @@ inline void init_builtins(VM* _vm) { _vm->bind__contains__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj, PyObject* key) { MappingProxy& self = _CAST(MappingProxy&, obj); - return self.attr().contains(CAST(Str&, key)); + return VAR(self.attr().contains(CAST(Str&, key))); }); /************ dict ************/ @@ -986,7 +986,7 @@ inline void init_builtins(VM* _vm) { _vm->bind__contains__(_vm->tp_dict, [](VM* vm, PyObject* obj, PyObject* key) { Dict& self = _CAST(Dict&, obj); - return self.contains(key); + return VAR(self.contains(key)); }); _vm->bind_method<-1>("dict", "get", [](VM* vm, ArgsView args) { @@ -1080,15 +1080,15 @@ inline void init_builtins(VM* _vm) { _vm->bind__eq__(_vm->tp_dict, [](VM* vm, PyObject* a, PyObject* b) { Dict& self = _CAST(Dict&, a); - if(!is_non_tagged_type(b, vm->tp_dict)) return false; + if(!is_non_tagged_type(b, vm->tp_dict)) return vm->NotImplemented; Dict& other = _CAST(Dict&, b); - if(self.size() != other.size()) return false; + if(self.size() != other.size()) return vm->False; for(auto& item : self.items()){ PyObject* value = other.try_get(item.first); - if(value == nullptr) return false; - if(!vm->py_equals(item.second, value)) return false; + if(value == nullptr) return vm->False; + if(!vm->py_equals(item.second, value)) return vm->False; } - return true; + return vm->True; }); /************ property ************/ _vm->bind_constructor<-1>("property", [](VM* vm, ArgsView args) { @@ -1370,8 +1370,8 @@ inline void VM::post_init(){ })); bind__eq__(tp_bound_method, [](VM* vm, PyObject* lhs, PyObject* rhs){ - if(!is_non_tagged_type(rhs, vm->tp_bound_method)) return false; - return _CAST(BoundMethod&, lhs) == _CAST(BoundMethod&, rhs); + if(!is_non_tagged_type(rhs, vm->tp_bound_method)) return vm->NotImplemented; + return VAR(_CAST(BoundMethod&, lhs) == _CAST(BoundMethod&, rhs)); }); _t(tp_slice)->attr().set("start", property([](VM* vm, ArgsView args){ return CAST(Slice&, args[0]).start; diff --git a/src/vm.h b/src/vm.h index e9dbbb3e..3516455b 100644 --- a/src/vm.h +++ b/src/vm.h @@ -44,6 +44,8 @@ namespace pkpy{ inline PyObject* py_var(VM* vm, ctype&& value) { return vm->heap.gcnew(vm->ptype, std::move(value));} +typedef PyObject* (*BinaryFuncC)(VM*, PyObject*, PyObject*); + struct PyTypeInfo{ PyObject* obj; Type base; @@ -62,28 +64,28 @@ struct PyTypeInfo{ PyObject* (*m__neg__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__bool__)(VM* vm, PyObject*) = nullptr; - bool (*m__eq__)(VM* vm, PyObject*, PyObject*) = nullptr; - bool (*m__lt__)(VM* vm, PyObject*, PyObject*) = nullptr; - bool (*m__le__)(VM* vm, PyObject*, PyObject*) = nullptr; - bool (*m__gt__)(VM* vm, PyObject*, PyObject*) = nullptr; - bool (*m__ge__)(VM* vm, PyObject*, PyObject*) = nullptr; - bool (*m__contains__)(VM* vm, PyObject*, PyObject*) = nullptr; + BinaryFuncC m__eq__ = nullptr; + BinaryFuncC m__lt__ = nullptr; + BinaryFuncC m__le__ = nullptr; + BinaryFuncC m__gt__ = nullptr; + BinaryFuncC m__ge__ = nullptr; + BinaryFuncC m__contains__ = nullptr; // binary operators - PyObject* (*m__add__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__sub__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__mul__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__truediv__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__floordiv__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__mod__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__pow__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__matmul__)(VM* vm, PyObject*, PyObject*) = nullptr; + BinaryFuncC m__add__ = nullptr; + BinaryFuncC m__sub__ = nullptr; + BinaryFuncC m__mul__ = nullptr; + BinaryFuncC m__truediv__ = nullptr; + BinaryFuncC m__floordiv__ = nullptr; + BinaryFuncC m__mod__ = nullptr; + BinaryFuncC m__pow__ = nullptr; + BinaryFuncC m__matmul__ = nullptr; - PyObject* (*m__lshift__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__rshift__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__and__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__or__)(VM* vm, PyObject*, PyObject*) = nullptr; - PyObject* (*m__xor__)(VM* vm, PyObject*, PyObject*) = nullptr; + BinaryFuncC m__lshift__ = nullptr; + BinaryFuncC m__rshift__ = nullptr; + BinaryFuncC m__and__ = nullptr; + BinaryFuncC m__or__ = nullptr; + BinaryFuncC m__xor__ = nullptr; // indexer PyObject* (*m__getitem__)(VM* vm, PyObject*, PyObject*) = nullptr; @@ -358,37 +360,23 @@ public: #undef BIND_UNARY_SPECIAL -#define BIND_LOGICAL_SPECIAL(name) \ - void bind##name(Type type, bool (*f)(VM*, PyObject*, PyObject*)){ \ - PyObject* obj = _t(type); \ - _all_types[type].m##name = f; \ - PyObject* nf = bind_method<1>(obj, #name, [](VM* vm, ArgsView args){ \ - bool ok = lambda_get_userdata(args.begin())(vm, args[0], args[1]); \ - return ok ? vm->True : vm->False; \ - }); \ - OBJ_GET(NativeFunc, nf).set_userdata(f); \ - } - - BIND_LOGICAL_SPECIAL(__eq__) - BIND_LOGICAL_SPECIAL(__lt__) - BIND_LOGICAL_SPECIAL(__le__) - BIND_LOGICAL_SPECIAL(__gt__) - BIND_LOGICAL_SPECIAL(__ge__) - BIND_LOGICAL_SPECIAL(__contains__) - -#undef BIND_LOGICAL_SPECIAL - - #define BIND_BINARY_SPECIAL(name) \ - void bind##name(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*)){ \ + void bind##name(Type type, BinaryFuncC f){ \ PyObject* obj = _t(type); \ _all_types[type].m##name = f; \ PyObject* nf = bind_method<1>(obj, #name, [](VM* vm, ArgsView args){ \ - return lambda_get_userdata(args.begin())(vm, args[0], args[1]); \ + return lambda_get_userdata(args.begin())(vm, args[0], args[1]); \ }); \ OBJ_GET(NativeFunc, nf).set_userdata(f); \ } + BIND_BINARY_SPECIAL(__eq__) + BIND_BINARY_SPECIAL(__lt__) + BIND_BINARY_SPECIAL(__le__) + BIND_BINARY_SPECIAL(__gt__) + BIND_BINARY_SPECIAL(__ge__) + BIND_BINARY_SPECIAL(__contains__) + BIND_BINARY_SPECIAL(__add__) BIND_BINARY_SPECIAL(__sub__) BIND_BINARY_SPECIAL(__mul__) @@ -438,8 +426,22 @@ public: bool py_equals(PyObject* lhs, PyObject* rhs){ if(lhs == rhs) return true; const PyTypeInfo* ti = _inst_type_info(lhs); - if(ti->m__eq__) return ti->m__eq__(this, lhs, rhs); - return call_method(lhs, __eq__, rhs) == True; + PyObject* res; + if(ti->m__eq__){ + res = ti->m__eq__(this, lhs, rhs); + if(res != vm->NotImplemented) return res == vm->True; + } + res = call_method(lhs, __eq__, rhs); + if(res != vm->NotImplemented) return res == vm->True; + + ti = _inst_type_info(rhs); + if(ti->m__eq__){ + res = ti->m__eq__(this, rhs, lhs); + if(res != vm->NotImplemented) return res == vm->True; + } + res = call_method(rhs, __eq__, lhs); + if(res != vm->NotImplemented) return res == vm->True; + return false; } template diff --git a/tests/09_long.py b/tests/09_long.py index d7313c1e..412a2d38 100644 --- a/tests/09_long.py +++ b/tests/09_long.py @@ -1,4 +1,4 @@ -assert long(123) == long('123') == 123L == 123 +assert long(123) == long('123') == 123 == 123L a = long(2) assert a ** 0 == 1 @@ -32,3 +32,7 @@ while a != 0: s.append(r) assert s == [4, 6, 7, 2, 3] + +assert 1 < 2L < 3 < 6.6 +assert 1L < 2 < 9.6 >= 7 > 2L +assert 1L < 2 < 3 < 6.6 \ No newline at end of file