From 72bb5c78eab51742d1cbd264c21934410a781b04 Mon Sep 17 00:00:00 2001 From: vsakkas Date: Sat, 14 Nov 2020 21:07:23 +0200 Subject: [PATCH 1/7] Implement dict clear primitive --- mypyc/primitives/dict_ops.py | 10 +++++++++- mypyc/test-data/irbuild-dict.test | 11 +++++++++++ mypyc/test-data/run-dicts.test | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 2838a7c06b17..409a6d8863bd 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -2,7 +2,7 @@ from mypyc.ir.ops import ERR_FALSE, ERR_MAGIC, ERR_NEVER from mypyc.ir.rtypes import ( - dict_rprimitive, object_rprimitive, bool_rprimitive, int_rprimitive, + dict_rprimitive, object_rprimitive, bool_rprimitive, int_rprimitive, void_rtype, list_rprimitive, dict_next_rtuple_single, dict_next_rtuple_pair, c_pyssize_t_rprimitive, c_int_rprimitive, bit_rprimitive ) @@ -142,6 +142,14 @@ c_function_name='CPyDict_ItemsView', error_kind=ERR_MAGIC) +# dict.clear() +c_method_op( + name='clear', + arg_types=[dict_rprimitive], + return_type=void_rtype, + c_function_name='PyDict_Clear', + error_kind=ERR_NEVER) + # list(dict.keys()) dict_keys_op = custom_op( arg_types=[dict_rprimitive], diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 37bbd09d1cef..5b2882ea3031 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -312,3 +312,14 @@ L0: r0 = load_address PyDict_Type x = r0 return 1 + +[case testDictClear] +from typing import Dict +def f(d: Dict[int, int]) -> None: + return d.clear() +[out] +def f(d): + d :: dict +L0: + PyDict_Clear(d) + return 1 diff --git a/mypyc/test-data/run-dicts.test b/mypyc/test-data/run-dicts.test index cac68b9af060..46e8edabc2bb 100644 --- a/mypyc/test-data/run-dicts.test +++ b/mypyc/test-data/run-dicts.test @@ -91,6 +91,10 @@ od.move_to_end(1) assert get_content(od) == ([3, 1], [4, 2], [(3, 4), (1, 2)]) assert get_content_set({1: 2}) == ({1}, {2}, {(1, 2)}) assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)}) + +d = {'a': 1, 'b': 2} +d.clear() +assert d == {} [typing fixtures/typing-full.pyi] [case testDictIterationMethodsRun] From c728478de0a904845bba0533c66cf7cbcf4dfeae Mon Sep 17 00:00:00 2001 From: vsakkas Date: Tue, 17 Nov 2020 23:44:15 +0200 Subject: [PATCH 2/7] Implement dict clear C helper function --- mypyc/lib-rt/CPy.h | 1 + mypyc/lib-rt/dict_ops.c | 8 ++++++++ mypyc/primitives/dict_ops.py | 4 ++-- mypyc/test-data/irbuild-dict.test | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index fa5e9ee499a8..e76e67645456 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -347,6 +347,7 @@ PyObject *CPyDict_ItemsView(PyObject *dict); PyObject *CPyDict_Keys(PyObject *dict); PyObject *CPyDict_Values(PyObject *dict); PyObject *CPyDict_Items(PyObject *dict); +void CPyDict_Clear(PyObject *dict); PyObject *CPyDict_GetKeysIter(PyObject *dict); PyObject *CPyDict_GetItemsIter(PyObject *dict); PyObject *CPyDict_GetValuesIter(PyObject *dict); diff --git a/mypyc/lib-rt/dict_ops.c b/mypyc/lib-rt/dict_ops.c index 52ccc2c94b77..b699d2d5f809 100644 --- a/mypyc/lib-rt/dict_ops.c +++ b/mypyc/lib-rt/dict_ops.c @@ -226,6 +226,14 @@ PyObject *CPyDict_Items(PyObject *dict) { return list; } +void CPyDict_Clear(PyObject *dict) { + if (PyDict_CheckExact(dict)) { + PyDict_Clear(dict); + } else { + PyObject_CallMethod(dict, "clear", NULL); + } +} + PyObject *CPyDict_GetKeysIter(PyObject *dict) { if (PyDict_CheckExact(dict)) { // Return dict itself to indicate we can use fast path instead. diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 409a6d8863bd..0b9fca6ea2c0 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -143,11 +143,11 @@ error_kind=ERR_MAGIC) # dict.clear() -c_method_op( +method_op( name='clear', arg_types=[dict_rprimitive], return_type=void_rtype, - c_function_name='PyDict_Clear', + c_function_name='CPyDict_Clear', error_kind=ERR_NEVER) # list(dict.keys()) diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 5b2882ea3031..5f7353b5c81d 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -321,5 +321,5 @@ def f(d: Dict[int, int]) -> None: def f(d): d :: dict L0: - PyDict_Clear(d) + CPyDict_Clear(d) return 1 From 72f73d56ebf81c9a7653ab183f38f0e366ff9290 Mon Sep 17 00:00:00 2001 From: vsakkas Date: Fri, 20 Nov 2020 22:28:13 +0200 Subject: [PATCH 3/7] Update dict clear tests --- mypyc/test-data/run-dicts.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mypyc/test-data/run-dicts.test b/mypyc/test-data/run-dicts.test index 46e8edabc2bb..66c8eb0e7cb3 100644 --- a/mypyc/test-data/run-dicts.test +++ b/mypyc/test-data/run-dicts.test @@ -95,6 +95,9 @@ assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)}) d = {'a': 1, 'b': 2} d.clear() assert d == {} +d = defaultdict(int) +d.clear() +assert d == {} [typing fixtures/typing-full.pyi] [case testDictIterationMethodsRun] From db962b8a0e1a8d7cdde0827cbc157c49ec9e86f9 Mon Sep 17 00:00:00 2001 From: vsakkas Date: Fri, 20 Nov 2020 22:28:36 +0200 Subject: [PATCH 4/7] Update dict clear error kind --- mypyc/primitives/dict_ops.py | 2 +- mypyc/test-data/run-dicts.test | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 0b9fca6ea2c0..e40eb644c1e3 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -148,7 +148,7 @@ arg_types=[dict_rprimitive], return_type=void_rtype, c_function_name='CPyDict_Clear', - error_kind=ERR_NEVER) + error_kind=ERR_MAGIC) # list(dict.keys()) dict_keys_op = custom_op( diff --git a/mypyc/test-data/run-dicts.test b/mypyc/test-data/run-dicts.test index 66c8eb0e7cb3..651f72db2957 100644 --- a/mypyc/test-data/run-dicts.test +++ b/mypyc/test-data/run-dicts.test @@ -92,6 +92,7 @@ assert get_content(od) == ([3, 1], [4, 2], [(3, 4), (1, 2)]) assert get_content_set({1: 2}) == ({1}, {2}, {(1, 2)}) assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)}) +from collections import defaultdict d = {'a': 1, 'b': 2} d.clear() assert d == {} From 195e4bb5dc2ef4c9676e9023d0c9299f8afcc248 Mon Sep 17 00:00:00 2001 From: vsakkas Date: Sun, 22 Nov 2020 15:34:37 +0200 Subject: [PATCH 5/7] Update dict clear return and error types --- mypyc/lib-rt/CPy.h | 2 +- mypyc/lib-rt/dict_ops.c | 8 ++++++-- mypyc/primitives/dict_ops.py | 6 +++--- mypyc/test-data/irbuild-dict.test | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index e76e67645456..012df8227fa9 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -347,7 +347,7 @@ PyObject *CPyDict_ItemsView(PyObject *dict); PyObject *CPyDict_Keys(PyObject *dict); PyObject *CPyDict_Values(PyObject *dict); PyObject *CPyDict_Items(PyObject *dict); -void CPyDict_Clear(PyObject *dict); +char CPyDict_Clear(PyObject *dict); PyObject *CPyDict_GetKeysIter(PyObject *dict); PyObject *CPyDict_GetItemsIter(PyObject *dict); PyObject *CPyDict_GetValuesIter(PyObject *dict); diff --git a/mypyc/lib-rt/dict_ops.c b/mypyc/lib-rt/dict_ops.c index b699d2d5f809..fca096468ddd 100644 --- a/mypyc/lib-rt/dict_ops.c +++ b/mypyc/lib-rt/dict_ops.c @@ -226,12 +226,16 @@ PyObject *CPyDict_Items(PyObject *dict) { return list; } -void CPyDict_Clear(PyObject *dict) { +char CPyDict_Clear(PyObject *dict) { if (PyDict_CheckExact(dict)) { PyDict_Clear(dict); } else { - PyObject_CallMethod(dict, "clear", NULL); + PyObject *res = PyObject_CallMethod(dict, "clear", NULL); + if (res == NULL) { + return 0; + } } + return 1; } PyObject *CPyDict_GetKeysIter(PyObject *dict) { diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index e40eb644c1e3..e0278182d5fe 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -2,7 +2,7 @@ from mypyc.ir.ops import ERR_FALSE, ERR_MAGIC, ERR_NEVER from mypyc.ir.rtypes import ( - dict_rprimitive, object_rprimitive, bool_rprimitive, int_rprimitive, void_rtype, + dict_rprimitive, object_rprimitive, bool_rprimitive, int_rprimitive, list_rprimitive, dict_next_rtuple_single, dict_next_rtuple_pair, c_pyssize_t_rprimitive, c_int_rprimitive, bit_rprimitive ) @@ -146,9 +146,9 @@ method_op( name='clear', arg_types=[dict_rprimitive], - return_type=void_rtype, + return_type=bit_rprimitive, c_function_name='CPyDict_Clear', - error_kind=ERR_MAGIC) + error_kind=ERR_FALSE) # list(dict.keys()) dict_keys_op = custom_op( diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 5f7353b5c81d..3ba24c448972 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -320,6 +320,7 @@ def f(d: Dict[int, int]) -> None: [out] def f(d): d :: dict + r0 :: bit L0: - CPyDict_Clear(d) + r0 = CPyDict_Clear(d) return 1 From e7db60ecab72c766ed23c41854689f4cf15dcb06 Mon Sep 17 00:00:00 2001 From: vsakkas Date: Sun, 22 Nov 2020 15:38:16 +0200 Subject: [PATCH 6/7] Update dict clear tests --- mypyc/test-data/run-dicts.test | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mypyc/test-data/run-dicts.test b/mypyc/test-data/run-dicts.test index 651f72db2957..06cf348aed64 100644 --- a/mypyc/test-data/run-dicts.test +++ b/mypyc/test-data/run-dicts.test @@ -96,9 +96,10 @@ from collections import defaultdict d = {'a': 1, 'b': 2} d.clear() assert d == {} -d = defaultdict(int) -d.clear() -assert d == {} +dd: Dict[str, int] = defaultdict(int) +dd['a'] = 1 +dd.clear() +assert dd == {} [typing fixtures/typing-full.pyi] [case testDictIterationMethodsRun] From 31e0d587c61f72b407959d9978dccd2940b06523 Mon Sep 17 00:00:00 2001 From: vsakkas Date: Sun, 29 Nov 2020 19:50:54 +0200 Subject: [PATCH 7/7] Update dict clear tests --- mypyc/test-data/run-dicts.test | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/mypyc/test-data/run-dicts.test b/mypyc/test-data/run-dicts.test index 06cf348aed64..1955d514d43a 100644 --- a/mypyc/test-data/run-dicts.test +++ b/mypyc/test-data/run-dicts.test @@ -92,14 +92,6 @@ assert get_content(od) == ([3, 1], [4, 2], [(3, 4), (1, 2)]) assert get_content_set({1: 2}) == ({1}, {2}, {(1, 2)}) assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)}) -from collections import defaultdict -d = {'a': 1, 'b': 2} -d.clear() -assert d == {} -dd: Dict[str, int] = defaultdict(int) -dd['a'] = 1 -dd.clear() -assert dd == {} [typing fixtures/typing-full.pyi] [case testDictIterationMethodsRun] @@ -201,3 +193,16 @@ else: 2 4 2 + +[case testDictMethods] +from collections import defaultdict +from typing import Dict + +def test_dict_clear() -> None: + d = {'a': 1, 'b': 2} + d.clear() + assert d == {} + dd: Dict[str, int] = defaultdict(int) + dd['a'] = 1 + dd.clear() + assert dd == {}