diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4e610e34..857a48ed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,6 +12,7 @@ jobs: CL -std:c++17 -GR- -EHsc -O2 -Fe:pocketpy src/main.cpp python3 scripts/run_tests.py ./pocketpy tests/1.py + ./pocketpy tests/2.py build_linux: runs-on: ubuntu-latest steps: @@ -21,6 +22,7 @@ jobs: bash build_cpp.sh python3 scripts/run_tests.py ./pocketpy tests/1.py + ./pocketpy tests/2.py build_web: runs-on: ubuntu-latest steps: diff --git a/src/builtins.h b/src/builtins.h index 7ad4c555..59db54ad 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -155,6 +155,8 @@ def __iterable4__eq__(self, other): return True list.__eq__ = __iterable4__eq__ tuple.__eq__ = __iterable4__eq__ +list.__ne__ = lambda self, other: not self.__eq__(other) +tuple.__ne__ = lambda self, other: not self.__eq__(other) del __iterable4__eq__ def __iterable4count(self, x): @@ -396,6 +398,9 @@ class set: def __eq__(self, other): return self.__xor__(other).__len__() == 0 + + def __ne__(self, other): + return self.__xor__(other).__len__() != 0 def isdisjoint(self, other): return self.__and__(other).__len__() == 0 diff --git a/src/pocketpy.h b/src/pocketpy.h index 7c0bb819..88e73cb9 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -29,7 +29,7 @@ _Code VM::compile(_Str source, _Str filename, CompileMode mode) { bool _0 = args[0]->is_type(vm->_tp_int) || args[0]->is_type(vm->_tp_float); \ bool _1 = args[1]->is_type(vm->_tp_int) || args[1]->is_type(vm->_tp_float); \ if(!_0 || !_1){ \ - if constexpr(is_eq) return vm->PyBool(args[0] == args[1]); \ + if constexpr(is_eq) return vm->PyBool(args[0].get() op args[1].get()); \ vm->typeError("unsupported operand type(s) for " #op ); \ } \ return vm->PyBool(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \ @@ -46,6 +46,7 @@ void __initializeBuiltinFunctions(VM* _vm) { BIND_NUM_LOGICAL_OPT(__gt__, >, false) BIND_NUM_LOGICAL_OPT(__ge__, >=, false) BIND_NUM_LOGICAL_OPT(__eq__, ==, true) + BIND_NUM_LOGICAL_OPT(__ne__, !=, true) #undef BIND_NUM_ARITH_OPT #undef BIND_NUM_LOGICAL_OPT @@ -133,7 +134,7 @@ void __initializeBuiltinFunctions(VM* _vm) { }); _vm->bindMethod<1>("object", "__eq__", CPP_LAMBDA(vm->PyBool(args[0] == args[1]))); - + _vm->bindMethod<1>("object", "__ne__", CPP_LAMBDA(vm->PyBool(args[0] != args[1]))); _vm->bindStaticMethod<1>("type", "__new__", CPP_LAMBDA(args[0]->_type)); _vm->bindStaticMethod<-1>("range", "__new__", [](VM* vm, const pkpy::ArgList& args) { @@ -299,6 +300,12 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyBool(args[0] == args[1]); }); + _vm->bindMethod<1>("str", "__ne__", [](VM* vm, const pkpy::ArgList& args) { + if(args[0]->is_type(vm->_tp_str) && args[1]->is_type(vm->_tp_str)) + return vm->PyBool(vm->PyStr_AS_C(args[0]) != vm->PyStr_AS_C(args[1])); + return vm->PyBool(args[0] != args[1]); + }); + _vm->bindMethod<1>("str", "__getitem__", [](VM* vm, const pkpy::ArgList& args) { const _Str& _self (vm->PyStr_AS_C(args[0])); diff --git a/src/str.h b/src/str.h index 3c6c4294..40fec3a6 100644 --- a/src/str.h +++ b/src/str.h @@ -44,7 +44,7 @@ public: } } - size_t hash() const{ + inline size_t hash() const{ if(!hash_initialized){ _hash = std::hash()(*this); hash_initialized = true; @@ -141,7 +141,7 @@ public: namespace std { template<> struct hash<_Str> { - std::size_t operator()(const _Str& s) const { + inline std::size_t operator()(const _Str& s) const { return s.hash(); } }; @@ -171,7 +171,7 @@ const _Str& __exit__ = _Str("__exit__"); const _Str CMP_SPECIAL_METHODS[] = { "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__" -}; // __ne__ should not be used +}; const _Str BINARY_SPECIAL_METHODS[] = { "__add__", "__sub__", "__mul__", "__truediv__", "__floordiv__", "__mod__", "__pow__" diff --git a/src/vm.h b/src/vm.h index 2d39a4ee..2901cc8d 100644 --- a/src/vm.h +++ b/src/vm.h @@ -147,17 +147,17 @@ protected: } break; case OP_COMPARE_OP: { - // for __ne__ we use the negation of __eq__ - int op = byte.arg == 3 ? 2 : byte.arg; - PyVar res = fast_call(CMP_SPECIAL_METHODS[op], frame->pop_n_values_reversed(this, 2)); - if(op != byte.arg) res = PyBool(!PyBool_AS_C(res)); - frame->push(std::move(res)); + pkpy::ArgList args(2); + args[1] = frame->pop_value(this); + args[0] = frame->top_value(this); + frame->top() = fast_call(CMP_SPECIAL_METHODS[byte.arg], std::move(args)); } break; case OP_IS_OP: { - bool ret_c = frame->pop_value(this) == frame->pop_value(this); + PyVar rhs = frame->pop_value(this); + bool ret_c = rhs == frame->top_value(this); if(byte.arg == 1) ret_c = !ret_c; - frame->push(PyBool(ret_c)); + frame->top() = PyBool(ret_c); } break; case OP_CONTAINS_OP: { @@ -167,10 +167,8 @@ protected: frame->push(PyBool(ret_c)); } break; case OP_UNARY_NEGATIVE: - { - PyVar obj = frame->pop_value(this); - frame->push(num_negated(obj)); - } break; + frame->top() = num_negated(frame->top_value(this)); + break; case OP_UNARY_NOT: { PyVar obj = frame->pop_value(this); diff --git a/tests/2.py b/tests/2.py new file mode 100644 index 00000000..3c6098f4 --- /dev/null +++ b/tests/2.py @@ -0,0 +1,4 @@ +import random + +a = [random.randint(-100000, 100000) for i in range(1500)] +a = sorted(a) \ No newline at end of file