support __eq__ for tuple & list & dict

This commit is contained in:
Lyon 2023-08-17 23:33:31 +08:00
parent edd320c9d3
commit f882ff153b
12 changed files with 186 additions and 2 deletions

23
examples/builtins/eq.py Normal file
View File

@ -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")

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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}",

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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")

View File

@ -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 */

View File

@ -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"