diff --git a/examples/builtins/eq.py b/examples/builtins/eq.py new file mode 100644 index 000000000..745b7a17e --- /dev/null +++ b/examples/builtins/eq.py @@ -0,0 +1,23 @@ +assert [1, 2, 3] == [1, 2, 3] +assert [1, 2, 3] != [1, 2, 4] + +assert (1, 2, 3) == (1, 2, 3) +assert (1, 2, 3) != (1, 2, 4) + +assert (1, 2, 3) != [1, 2, 3] +assert [1, 2, 3] != (1, 2, 3) +assert [1, 2, 3] != 1 + +assert 1 != (1, 2, 3) + +assert ('a', 'b', 'c') == ('a', 'b', 'c') +assert ('a', 'b', 'c') != ('a', 'b', 'd') + +dict1 = {'a': 1, 'b': 2, 'c': 3} +dict2 = {'a': 1, 'b': 2, 'c': 3} +dict3 = {'a': 1, 'b': 2, 'c': 4} + +assert dict1 == dict2 +assert dict1 != dict3 + +print("PASS") diff --git a/package/PikaStdLib/PikaStdData.pyi b/package/PikaStdLib/PikaStdData.pyi index 412f23e4a..15cb78735 100644 --- a/package/PikaStdLib/PikaStdData.pyi +++ b/package/PikaStdLib/PikaStdData.pyi @@ -27,6 +27,9 @@ class Tuple: def __contains__(self, val: any) -> int: """ support val in list """ + def __eq__(self, other: any) -> int: + """ support list == list """ + class List(Tuple): def __init__(self): ... @@ -90,6 +93,9 @@ class Dict: def update(self, other: Dict): """ update dict """ + + def __eq__(self, other: any) -> int: + """ support dict == dict """ class dict_keys: diff --git a/package/PikaStdLib/PikaStdData_Dict.c b/package/PikaStdLib/PikaStdData_Dict.c index aa9ddd3af..29f9d5736 100644 --- a/package/PikaStdLib/PikaStdData_Dict.c +++ b/package/PikaStdLib/PikaStdData_Dict.c @@ -293,3 +293,28 @@ void PikaStdData_Dict_update(PikaObj* self, PikaObj* other) { pikaVM_runByteCode(context, (uint8_t*)bytes); obj_deinit(context); } + +int PikaStdData_Dict___eq__(PikaObj* self, Arg* other) { + if (!arg_isObject(other)) { + return 0; + } + PikaObj* oOther = arg_getObj(other); + if (self->constructor != oOther->constructor) { + return 0; + } + if (obj_getSize(self) != obj_getSize(oOther)) { + return 0; + } + for (size_t i = 0; i < obj_getSize(self); i++) { + Arg* key = args_getArgByIndex(_OBJ2KEYS(self), i); + Arg* val = args_getArgByIndex(_OBJ2DICT(self), i); + Arg* oVal = pikaDict_get(oOther, arg_getStr(key)); + if (NULL == oVal) { + return 0; + } + if (!arg_isEqual(val, oVal)) { + return 0; + } + } + return 1; +} diff --git a/package/PikaStdLib/PikaStdData_Tuple.c b/package/PikaStdLib/PikaStdData_Tuple.c index f3c4d7152..a1b50d118 100644 --- a/package/PikaStdLib/PikaStdData_Tuple.c +++ b/package/PikaStdLib/PikaStdData_Tuple.c @@ -106,3 +106,24 @@ int PikaStdData_Tuple___contains__(PikaObj* self, Arg* val) { } return 0; } + +int PikaStdData_Tuple___eq__(PikaObj* self, Arg* other) { + if (!arg_isObject(other)) { + return 0; + } + PikaObj* oOther = arg_getObj(other); + if (self->constructor != oOther->constructor) { + return 0; + } + if (obj_getSize(self) != obj_getSize(oOther)) { + return 0; + } + for (size_t i = 0; i < pikaList_getSize(self); i++) { + Arg* arg = pikaList_get(self, i); + Arg* otherArg = pikaList_get(oOther, i); + if (!arg_isEqual(arg, otherArg)) { + return 0; + } + } + return 1; +} diff --git a/port/linux/.vscode/launch.json b/port/linux/.vscode/launch.json index e4d0acff6..62642f4ae 100644 --- a/port/linux/.vscode/launch.json +++ b/port/linux/.vscode/launch.json @@ -12,7 +12,7 @@ // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain", "args": [ // "--gtest_filter=vm.keyword_2" - "--gtest_filter=struct.unpack" + "--gtest_filter=builtin.eq" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/port/linux/package/pikascript/PikaStdData.pyi b/port/linux/package/pikascript/PikaStdData.pyi index 412f23e4a..15cb78735 100644 --- a/port/linux/package/pikascript/PikaStdData.pyi +++ b/port/linux/package/pikascript/PikaStdData.pyi @@ -27,6 +27,9 @@ class Tuple: def __contains__(self, val: any) -> int: """ support val in list """ + def __eq__(self, other: any) -> int: + """ support list == list """ + class List(Tuple): def __init__(self): ... @@ -90,6 +93,9 @@ class Dict: def update(self, other: Dict): """ update dict """ + + def __eq__(self, other: any) -> int: + """ support dict == dict """ class dict_keys: diff --git a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Dict.c b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Dict.c index aa9ddd3af..29f9d5736 100644 --- a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Dict.c +++ b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Dict.c @@ -293,3 +293,28 @@ void PikaStdData_Dict_update(PikaObj* self, PikaObj* other) { pikaVM_runByteCode(context, (uint8_t*)bytes); obj_deinit(context); } + +int PikaStdData_Dict___eq__(PikaObj* self, Arg* other) { + if (!arg_isObject(other)) { + return 0; + } + PikaObj* oOther = arg_getObj(other); + if (self->constructor != oOther->constructor) { + return 0; + } + if (obj_getSize(self) != obj_getSize(oOther)) { + return 0; + } + for (size_t i = 0; i < obj_getSize(self); i++) { + Arg* key = args_getArgByIndex(_OBJ2KEYS(self), i); + Arg* val = args_getArgByIndex(_OBJ2DICT(self), i); + Arg* oVal = pikaDict_get(oOther, arg_getStr(key)); + if (NULL == oVal) { + return 0; + } + if (!arg_isEqual(val, oVal)) { + return 0; + } + } + return 1; +} diff --git a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Tuple.c b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Tuple.c index f3c4d7152..a1b50d118 100644 --- a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Tuple.c +++ b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_Tuple.c @@ -106,3 +106,24 @@ int PikaStdData_Tuple___contains__(PikaObj* self, Arg* val) { } return 0; } + +int PikaStdData_Tuple___eq__(PikaObj* self, Arg* other) { + if (!arg_isObject(other)) { + return 0; + } + PikaObj* oOther = arg_getObj(other); + if (self->constructor != oOther->constructor) { + return 0; + } + if (obj_getSize(self) != obj_getSize(oOther)) { + return 0; + } + for (size_t i = 0; i < pikaList_getSize(self); i++) { + Arg* arg = pikaList_get(self, i); + Arg* otherArg = pikaList_get(oOther, i); + if (!arg_isEqual(arg, otherArg)) { + return 0; + } + } + return 1; +} diff --git a/port/linux/test/compile-test.cpp b/port/linux/test/compile-test.cpp index 97ae12f51..beed42cc2 100644 --- a/port/linux/test/compile-test.cpp +++ b/port/linux/test/compile-test.cpp @@ -594,6 +594,12 @@ TEST(compiler, __add__) { EXPECT_EQ(pikaMemNow(), 0); } +TEST(compiler, __eq__) { + char* lines = "@res_eq = __eq__(__others)"; + pika_lines2Array(lines); + EXPECT_EQ(pikaMemNow(), 0); +} + TEST(compiler, __iter__) { char* lines = "@res_iter = __iter__()"; pika_lines2Array(lines); diff --git a/port/linux/test/python/builtins/eq.py b/port/linux/test/python/builtins/eq.py new file mode 100644 index 000000000..745b7a17e --- /dev/null +++ b/port/linux/test/python/builtins/eq.py @@ -0,0 +1,23 @@ +assert [1, 2, 3] == [1, 2, 3] +assert [1, 2, 3] != [1, 2, 4] + +assert (1, 2, 3) == (1, 2, 3) +assert (1, 2, 3) != (1, 2, 4) + +assert (1, 2, 3) != [1, 2, 3] +assert [1, 2, 3] != (1, 2, 3) +assert [1, 2, 3] != 1 + +assert 1 != (1, 2, 3) + +assert ('a', 'b', 'c') == ('a', 'b', 'c') +assert ('a', 'b', 'c') != ('a', 'b', 'd') + +dict1 = {'a': 1, 'b': 2, 'c': 3} +dict2 = {'a': 1, 'b': 2, 'c': 3} +dict3 = {'a': 1, 'b': 2, 'c': 4} + +assert dict1 == dict2 +assert dict1 != dict3 + +print("PASS") diff --git a/src/PikaVM.c b/src/PikaVM.c index 5bb65bc24..735f28e59 100644 --- a/src/PikaVM.c +++ b/src/PikaVM.c @@ -2697,6 +2697,34 @@ static void _OPT_EQU(OperatorInfo* op) { } if (argType_isObject(op->t1) && argType_isObject(op->t2)) { is_equ = (arg_getPtr(op->a1) == arg_getPtr(op->a2)); + if (is_equ) { + goto __exit; + } + Arg* __eq__ = + obj_getMethodArgWithFullPath(arg_getPtr(op->a1), "__eq__"); + if (NULL != __eq__) { + arg_deinit(__eq__); + PikaObj* oThis = arg_getObj(op->a1); + obj_setArg(oThis, "__others", op->a2); + /* clang-format off */ + PIKA_PYTHON( + @res_eq = __eq__(__others) + ) + /* clang-format on */ + const uint8_t bytes[] = { + 0x0c, 0x00, 0x00, 0x00, /* instruct array size */ + 0x10, 0x81, 0x01, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x04, + 0x11, 0x00, + /* instruct array */ + 0x19, 0x00, 0x00, 0x00, /* const pool size */ + 0x00, 0x5f, 0x5f, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x73, 0x00, + 0x5f, 0x5f, 0x65, 0x71, 0x5f, 0x5f, 0x00, 0x40, 0x72, 0x65, + 0x73, 0x5f, 0x65, 0x71, 0x00, + /* const pool */ + }; + pikaVM_runByteCode(oThis, (uint8_t*)bytes); + is_equ = obj_getInt(oThis, "@res_eq"); + } goto __exit; } /* default: int bool, and float */ diff --git a/src/PikaVersion.h b/src/PikaVersion.h index 0aba5dd75..7965b3f3e 100644 --- a/src/PikaVersion.h +++ b/src/PikaVersion.h @@ -2,4 +2,4 @@ #define PIKA_VERSION_MINOR 12 #define PIKA_VERSION_MICRO 5 -#define PIKA_EDIT_TIME "2023/08/17 22:02:10" +#define PIKA_EDIT_TIME "2023/08/17 23:33:21"