From 44ed0bbc0e13d1afe877eed24083d7f30bff15d0 Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Wed, 8 Jul 2020 15:22:19 +0800 Subject: [PATCH 1/8] list and set ops --- mypyc/codegen/notes.md | 29 +++++++++++++ mypyc/irbuild/expression.py | 10 ++--- mypyc/irbuild/for_helpers.py | 2 +- mypyc/irbuild/ll_builder.py | 2 +- mypyc/primitives/list_ops.py | 25 +++++------ mypyc/primitives/set_ops.py | 44 +++++++++---------- mypyc/test-data/exceptions.test | 6 +-- mypyc/test-data/irbuild-basic.test | 12 +++--- mypyc/test-data/irbuild-lists.test | 12 +++--- mypyc/test-data/irbuild-set.test | 68 +++++++++++++++--------------- mypyc/test-data/irbuild-tuple.test | 8 ++-- mypyc/test-data/refcount.test | 4 +- mypyc/test/test_emitfunc.py | 4 +- runtests.py | 4 +- 14 files changed, 130 insertions(+), 100 deletions(-) create mode 100644 mypyc/codegen/notes.md diff --git a/mypyc/codegen/notes.md b/mypyc/codegen/notes.md new file mode 100644 index 000000000000..d442f0ada86b --- /dev/null +++ b/mypyc/codegen/notes.md @@ -0,0 +1,29 @@ +lib_prefix: get_module_group_prefix -> context.group_map -> modify context.group_deps when necessary + +private_name: NameGenerator translations/module_map + +this also helps to solve native_function_name(which depends on NameGenerator) + +cast type generation + +remaining `LoadStatic`: + +load_globals_dict + return self.add(LoadStatic(dict_rprimitive, 'globals', self.module_name)) + +gen_arg_defaults + return builder.add(LoadStatic(target.type, name, builder.module_name)) + +allocate_class: + +template = builder.add(LoadStatic(object_rprimitive, cdef.name + "_template", builder.module_name, NAMESPACE_TYPE)) + +load_static_checked: +value = self.add(LoadStatic(typ, identifier, module_name, namespace, line=line)) + +def load_module(self, name: str) -> Value: + return self.add(LoadStatic(object_rprimitive, name, namespace=NAMESPACE_MODULE)) + +def load_native_type_object(self, fullname: str) -> Value: + module, name = fullname.rsplit('.', 1) + return self.add(LoadStatic(object_rprimitive, name, module, NAMESPACE_TYPE)) \ No newline at end of file diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 9daf2b302875..0cb09d393334 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -20,7 +20,7 @@ ) from mypyc.ir.rtypes import RTuple, object_rprimitive, is_none_rprimitive from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD -from mypyc.primitives.registry import name_ref_ops +from mypyc.primitives.registry import name_ref_ops, CFunctionDescription from mypyc.primitives.generic_ops import iter_op from mypyc.primitives.misc_ops import new_slice_op, ellipsis_op, type_op from mypyc.primitives.list_ops import new_list_op, list_append_op, list_extend_op @@ -491,8 +491,8 @@ def transform_set_expr(builder: IRBuilder, expr: SetExpr) -> Value: def _visit_display(builder: IRBuilder, items: List[Expression], constructor_op: OpDescription, - append_op: OpDescription, - extend_op: OpDescription, + append_op: CFunctionDescription, + extend_op: CFunctionDescription, line: int ) -> Value: accepted_items = [] @@ -512,7 +512,7 @@ def _visit_display(builder: IRBuilder, if result is None: result = builder.primitive_op(constructor_op, initial_items, line) - builder.primitive_op(extend_op if starred else append_op, [result, value], line) + builder.call_c(extend_op if starred else append_op, [result, value], line) if result is None: result = builder.primitive_op(constructor_op, initial_items, line) @@ -534,7 +534,7 @@ def transform_set_comprehension(builder: IRBuilder, o: SetComprehension) -> Valu def gen_inner_stmts() -> None: e = builder.accept(gen.left_expr) - builder.primitive_op(set_add_op, [set_ops, e], o.line) + builder.call_c(set_add_op, [set_ops, e], o.line) comprehension_helper(builder, loop_params, gen_inner_stmts, o.line) return set_ops diff --git a/mypyc/irbuild/for_helpers.py b/mypyc/irbuild/for_helpers.py index 1c65fec05eb3..d2aca4149457 100644 --- a/mypyc/irbuild/for_helpers.py +++ b/mypyc/irbuild/for_helpers.py @@ -92,7 +92,7 @@ def translate_list_comprehension(builder: IRBuilder, gen: GeneratorExpr) -> Valu def gen_inner_stmts() -> None: e = builder.accept(gen.left_expr) - builder.primitive_op(list_append_op, [list_ops, e], gen.line) + builder.call_c(list_append_op, [list_ops, e], gen.line) comprehension_helper(builder, loop_params, gen_inner_stmts, gen.line) return list_ops diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index ecc7bfccbbb5..ec9f0ede2102 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -269,7 +269,7 @@ def py_call(self, # don't have an extend method. pos_args_list = self.primitive_op(new_list_op, pos_arg_values, line) for star_arg_value in star_arg_values: - self.primitive_op(list_extend_op, [pos_args_list, star_arg_value], line) + self.call_c(list_extend_op, [pos_args_list, star_arg_value], line) pos_args_tuple = self.call_c(list_tuple_op, [pos_args_list], line) kw_args_dict = self.make_dict(kw_arg_key_value_pairs, line) diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index ddacc7c9b0a5..24546e9f1914 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -2,13 +2,14 @@ from typing import List -from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER, ERR_FALSE, EmitterInterface +from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER, ERR_FALSE, ERR_NEG_INT, EmitterInterface from mypyc.ir.rtypes import ( - int_rprimitive, short_int_rprimitive, list_rprimitive, object_rprimitive, bool_rprimitive + int_rprimitive, short_int_rprimitive, list_rprimitive, object_rprimitive, bool_rprimitive, + c_int_rprimitive ) from mypyc.primitives.registry import ( - name_ref_op, func_op, method_op, custom_op, name_emit, - call_emit, call_negative_bool_emit, c_function_op, c_binary_op, c_method_op + name_ref_op, func_op, custom_op, name_emit, + call_emit, c_function_op, c_binary_op, c_method_op ) @@ -85,20 +86,20 @@ def emit_new(emitter: EmitterInterface, args: List[str], dest: str) -> None: steals=[False, False, True]) # list.append(obj) -list_append_op = method_op( +list_append_op = c_method_op( name='append', arg_types=[list_rprimitive, object_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('PyList_Append')) + return_type=c_int_rprimitive, + c_function_name='PyList_Append', + error_kind=ERR_NEG_INT) # list.extend(obj) -list_extend_op = method_op( +list_extend_op = c_method_op( name='extend', arg_types=[list_rprimitive, object_rprimitive], - result_type=object_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyList_Extend')) + return_type=object_rprimitive, + c_function_name='CPyList_Extend', + error_kind=ERR_MAGIC) # list.pop() list_pop_last = c_method_op( diff --git a/mypyc/primitives/set_ops.py b/mypyc/primitives/set_ops.py index a81b309b944b..fd929829b2ed 100644 --- a/mypyc/primitives/set_ops.py +++ b/mypyc/primitives/set_ops.py @@ -1,8 +1,7 @@ """Primitive set (and frozenset) ops.""" from mypyc.primitives.registry import ( - func_op, method_op, binary_op, simple_emit, negative_int_emit, - call_negative_bool_emit, c_function_op, c_method_op + func_op, simple_emit, c_function_op, c_method_op, c_binary_op ) from mypyc.ir.ops import ERR_MAGIC, ERR_FALSE, ERR_NEVER, ERR_NEG_INT, EmitterInterface from mypyc.ir.rtypes import ( @@ -54,14 +53,14 @@ def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: ) # item in set -binary_op( - op='in', +c_binary_op( + name='in', arg_types=[object_rprimitive, set_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_MAGIC, - format_str='{dest} = {args[0]} in {args[1]} :: set', - emit=negative_int_emit('{dest} = PySet_Contains({args[1]}, {args[0]});') -) + return_type=c_int_rprimitive, + c_function_name='PySet_Contains', + error_kind=ERR_NEG_INT, + truncated_type=bool_rprimitive, + ordering=[1, 0]) # set.remove(obj) c_method_op( @@ -80,33 +79,30 @@ def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: error_kind=ERR_NEG_INT) # set.add(obj) -set_add_op = method_op( +set_add_op = c_method_op( name='add', arg_types=[set_rprimitive, object_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('PySet_Add') -) + return_type=c_int_rprimitive, + c_function_name='PySet_Add', + error_kind=ERR_NEG_INT) # set.update(obj) # # This is not a public API but looks like it should be fine. -set_update_op = method_op( +set_update_op = c_method_op( name='update', arg_types=[set_rprimitive, object_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('_PySet_Update') -) + return_type=c_int_rprimitive, + c_function_name='_PySet_Update', + error_kind=ERR_NEG_INT) # set.clear() -method_op( +c_method_op( name='clear', arg_types=[set_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('PySet_Clear') -) + return_type=c_int_rprimitive, + c_function_name='PySet_Clear', + error_kind=ERR_NEG_INT) # set.pop() c_method_op( diff --git a/mypyc/test-data/exceptions.test b/mypyc/test-data/exceptions.test index edac4269afc8..0848943f8d4d 100644 --- a/mypyc/test-data/exceptions.test +++ b/mypyc/test-data/exceptions.test @@ -36,7 +36,7 @@ def f(x, y, z): x :: list y, z :: int r0 :: object - r1 :: bool + r1 :: int32 r2 :: None r3 :: object r4 :: bool @@ -44,9 +44,9 @@ def f(x, y, z): L0: inc_ref y :: int r0 = box(int, y) - r1 = x.append(r0) :: list + r1 = PyList_Append(x, r0) dec_ref r0 - if not r1 goto L3 (error at f:3) else goto L1 :: bool + if r1 < 0 goto L3 (error at f:3) else goto L1 L1: r2 = None inc_ref z :: int diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 85c203dbe548..71a54a3a51ab 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -1632,7 +1632,7 @@ L0: r6 = r4[r5] :: dict r7 = [] r8 = box(tuple[int, int, int], r3) - r9 = r7.extend(r8) :: list + r9 = CPyList_Extend(r7, r8) r10 = PyList_AsTuple(r7) r11 = PyDict_New() r12 = py_call_with_kwargs(r6, r10, r11) @@ -1661,7 +1661,7 @@ L0: r7 = box(short_int, r0) r8 = [r7] r9 = box(tuple[int, int], r3) - r10 = r8.extend(r9) :: list + r10 = CPyList_Extend(r8, r9) r11 = PyList_AsTuple(r8) r12 = PyDict_New() r13 = py_call_with_kwargs(r6, r11, r12) @@ -1879,7 +1879,7 @@ def f(): r17 :: bool r18 :: int r19 :: object - r20 :: bool + r20 :: int32 r21, r22 :: short_int L0: r0 = [] @@ -1914,7 +1914,7 @@ L5: L6: r18 = CPyTagged_Multiply(x, x) r19 = box(int, r18) - r20 = r0.append(r19) :: list + r20 = PyList_Append(r0, r19) L7: r21 = 1 r22 = r9 + r21 @@ -2012,7 +2012,7 @@ def f(l): r17 :: tuple[int, int, int] r18, r19, r20, r21, r22 :: int r23 :: object - r24 :: bool + r24 :: int32 r25, r26 :: short_int L0: r0 = 0 @@ -2055,7 +2055,7 @@ L6: r21 = CPyTagged_Add(x0, y0) r22 = CPyTagged_Add(r21, z0) r23 = box(int, r22) - r24 = r11.append(r23) :: list + r24 = PyList_Append(r11, r23) L7: r25 = 1 r26 = r13 + r25 diff --git a/mypyc/test-data/irbuild-lists.test b/mypyc/test-data/irbuild-lists.test index dcf11aeae641..2db12c6a4975 100644 --- a/mypyc/test-data/irbuild-lists.test +++ b/mypyc/test-data/irbuild-lists.test @@ -153,11 +153,11 @@ def f(a, x): a :: list x :: int r0 :: object - r1 :: bool + r1 :: int32 r2, r3 :: None L0: r0 = box(int, x) - r1 = a.append(r0) :: list + r1 = PyList_Append(a, r0) r2 = None r3 = None return r3 @@ -213,7 +213,7 @@ def f(x, y): r3, r4 :: object r5 :: list r6, r7, r8 :: object - r9 :: bool + r9 :: int32 L0: r0 = 1 r1 = 2 @@ -221,9 +221,9 @@ L0: r3 = box(short_int, r0) r4 = box(short_int, r1) r5 = [r3, r4] - r6 = r5.extend(x) :: list - r7 = r5.extend(y) :: list + r6 = CPyList_Extend(r5, x) + r7 = CPyList_Extend(r5, y) r8 = box(short_int, r2) - r9 = r5.append(r8) :: list + r9 = PyList_Append(r5, r8) return r5 diff --git a/mypyc/test-data/irbuild-set.test b/mypyc/test-data/irbuild-set.test index 5a3babb2967f..9ffee68de5b2 100644 --- a/mypyc/test-data/irbuild-set.test +++ b/mypyc/test-data/irbuild-set.test @@ -7,22 +7,22 @@ def f(): r0, r1, r2 :: short_int r3 :: set r4 :: object - r5 :: bool + r5 :: int32 r6 :: object - r7 :: bool + r7 :: int32 r8 :: object - r9 :: bool + r9 :: int32 L0: r0 = 1 r1 = 2 r2 = 3 r3 = set r4 = box(short_int, r0) - r5 = r3.add(r4) :: set + r5 = PySet_Add(r3, r4) r6 = box(short_int, r1) - r7 = r3.add(r6) :: set + r7 = PySet_Add(r3, r6) r8 = box(short_int, r2) - r9 = r3.add(r8) :: set + r9 = PySet_Add(r3, r8) return r3 [case testNewEmptySet] @@ -57,11 +57,11 @@ def f(): r0, r1, r2 :: short_int r3 :: set r4 :: object - r5 :: bool + r5 :: int32 r6 :: object - r7 :: bool + r7 :: int32 r8 :: object - r9 :: bool + r9 :: int32 r10 :: int L0: r0 = 1 @@ -69,11 +69,11 @@ L0: r2 = 3 r3 = set r4 = box(short_int, r0) - r5 = r3.add(r4) :: set + r5 = PySet_Add(r3, r4) r6 = box(short_int, r1) - r7 = r3.add(r6) :: set + r7 = PySet_Add(r3, r6) r8 = box(short_int, r2) - r9 = r3.add(r8) :: set + r9 = PySet_Add(r3, r8) r10 = len r3 :: set return r10 @@ -87,26 +87,28 @@ def f(): r0, r1 :: short_int r2 :: set r3 :: object - r4 :: bool + r4 :: int32 r5 :: object - r6 :: bool + r6 :: int32 x :: set r7 :: short_int r8 :: object - r9 :: bool + r9 :: int32 + r10 :: bool L0: r0 = 3 r1 = 4 r2 = set r3 = box(short_int, r0) - r4 = r2.add(r3) :: set + r4 = PySet_Add(r2, r3) r5 = box(short_int, r1) - r6 = r2.add(r5) :: set + r6 = PySet_Add(r2, r5) x = r2 r7 = 5 r8 = box(short_int, r7) - r9 = r8 in x :: set - return r9 + r9 = PySet_Contains(x, r8) + r10 = truncate r9: int32 to builtins.bool + return r10 [case testSetRemove] from typing import Set @@ -163,14 +165,14 @@ def f(): r0, x :: set r1 :: short_int r2 :: object - r3 :: bool + r3 :: int32 r4 :: None L0: r0 = set x = r0 r1 = 1 r2 = box(short_int, r1) - r3 = x.add(r2) :: set + r3 = PySet_Add(x, r2) r4 = None return x @@ -183,12 +185,12 @@ def f() -> Set[int]: [out] def f(): r0, x :: set - r1 :: bool + r1 :: int32 r2 :: None L0: r0 = set x = r0 - r1 = x.clear() :: set + r1 = PySet_Clear(x) r2 = None return x @@ -214,10 +216,10 @@ def update(s: Set[int], x: List[int]) -> None: def update(s, x): s :: set x :: list - r0 :: bool + r0 :: int32 r1, r2 :: None L0: - r0 = s.update(x) :: set + r0 = _PySet_Update(s, x) r1 = None r2 = None return r2 @@ -232,23 +234,23 @@ def f(x, y): r0, r1, r2 :: short_int r3 :: set r4 :: object - r5 :: bool + r5 :: int32 r6 :: object - r7, r8, r9 :: bool + r7, r8, r9 :: int32 r10 :: object - r11 :: bool + r11 :: int32 L0: r0 = 1 r1 = 2 r2 = 3 r3 = set r4 = box(short_int, r0) - r5 = r3.add(r4) :: set + r5 = PySet_Add(r3, r4) r6 = box(short_int, r1) - r7 = r3.add(r6) :: set - r8 = r3.update(x) :: set - r9 = r3.update(y) :: set + r7 = PySet_Add(r3, r6) + r8 = _PySet_Update(r3, x) + r9 = _PySet_Update(r3, y) r10 = box(short_int, r2) - r11 = r3.add(r10) :: set + r11 = PySet_Add(r3, r10) return r3 diff --git a/mypyc/test-data/irbuild-tuple.test b/mypyc/test-data/irbuild-tuple.test index 0d9f255dc606..477d387a369b 100644 --- a/mypyc/test-data/irbuild-tuple.test +++ b/mypyc/test-data/irbuild-tuple.test @@ -111,7 +111,7 @@ def f(x, y): r3, r4 :: object r5 :: list r6, r7, r8 :: object - r9 :: bool + r9 :: int32 r10 :: tuple L0: r0 = 1 @@ -120,10 +120,10 @@ L0: r3 = box(short_int, r0) r4 = box(short_int, r1) r5 = [r3, r4] - r6 = r5.extend(x) :: list - r7 = r5.extend(y) :: list + r6 = CPyList_Extend(r5, x) + r7 = CPyList_Extend(r5, y) r8 = box(short_int, r2) - r9 = r5.append(r8) :: list + r9 = PyList_Append(r5, r8) r10 = PyList_AsTuple(r5) return r10 diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index c356d8fa23a5..4f25ca96ce7b 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -770,12 +770,12 @@ def f(a, x): a :: list x :: int r0 :: object - r1 :: bool + r1 :: int32 r2, r3 :: None L0: inc_ref x :: int r0 = box(int, x) - r1 = a.append(r0) :: list + r1 = PyList_Append(a, r0) dec_ref r0 r2 = None r3 = None diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 5277427a95b2..580cd0e0a580 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -191,7 +191,9 @@ def test_new_list(self) -> None: """) def test_list_append(self) -> None: - self.assert_emit(PrimitiveOp([self.l, self.o], list_append_op, 1), + self.assert_emit(CallC(list_append_op.c_function_name, [self.l, self.o], + list_append_op.return_type, list_append_op.steals, + list_append_op.error_kind, 1), """cpy_r_r0 = PyList_Append(cpy_r_l, cpy_r_o) >= 0;""") def test_get_attr(self) -> None: diff --git a/runtests.py b/runtests.py index dec2c1b97cf5..3e13bacfabad 100755 --- a/runtests.py +++ b/runtests.py @@ -65,11 +65,11 @@ # time to run. cmds = { # Self type check - 'self': python_name + ' -m mypy --config-file mypy_self_check.ini -p mypy', + 'self': python_name + ' -m mypy --config-file mypy_self_check.ini -p mypyc', # Lint 'lint': 'flake8 -j0', # Fast test cases only (this is the bulk of the test suite) - 'pytest-fast': 'pytest -k "not (%s)"' % ' or '.join(ALL_NON_FAST), + 'pytest-fast': 'pytest --update-data -k "not (%s)"' % ' or '.join(ALL_NON_FAST), # Test cases that invoke mypy (with small inputs) 'pytest-cmdline': 'pytest -k "%s"' % ' or '.join([CMDLINE, EVALUATION, From 9b3a0e0e956f5a20c33000d390e4d10c7150b53f Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Wed, 8 Jul 2020 15:48:41 +0800 Subject: [PATCH 2/8] remove --- mypyc/codegen/notes.md | 29 ----------------------------- runtests.py | 4 ++-- 2 files changed, 2 insertions(+), 31 deletions(-) delete mode 100644 mypyc/codegen/notes.md diff --git a/mypyc/codegen/notes.md b/mypyc/codegen/notes.md deleted file mode 100644 index d442f0ada86b..000000000000 --- a/mypyc/codegen/notes.md +++ /dev/null @@ -1,29 +0,0 @@ -lib_prefix: get_module_group_prefix -> context.group_map -> modify context.group_deps when necessary - -private_name: NameGenerator translations/module_map - -this also helps to solve native_function_name(which depends on NameGenerator) - -cast type generation - -remaining `LoadStatic`: - -load_globals_dict - return self.add(LoadStatic(dict_rprimitive, 'globals', self.module_name)) - -gen_arg_defaults - return builder.add(LoadStatic(target.type, name, builder.module_name)) - -allocate_class: - -template = builder.add(LoadStatic(object_rprimitive, cdef.name + "_template", builder.module_name, NAMESPACE_TYPE)) - -load_static_checked: -value = self.add(LoadStatic(typ, identifier, module_name, namespace, line=line)) - -def load_module(self, name: str) -> Value: - return self.add(LoadStatic(object_rprimitive, name, namespace=NAMESPACE_MODULE)) - -def load_native_type_object(self, fullname: str) -> Value: - module, name = fullname.rsplit('.', 1) - return self.add(LoadStatic(object_rprimitive, name, module, NAMESPACE_TYPE)) \ No newline at end of file diff --git a/runtests.py b/runtests.py index 3e13bacfabad..dec2c1b97cf5 100755 --- a/runtests.py +++ b/runtests.py @@ -65,11 +65,11 @@ # time to run. cmds = { # Self type check - 'self': python_name + ' -m mypy --config-file mypy_self_check.ini -p mypyc', + 'self': python_name + ' -m mypy --config-file mypy_self_check.ini -p mypy', # Lint 'lint': 'flake8 -j0', # Fast test cases only (this is the bulk of the test suite) - 'pytest-fast': 'pytest --update-data -k "not (%s)"' % ' or '.join(ALL_NON_FAST), + 'pytest-fast': 'pytest -k "not (%s)"' % ' or '.join(ALL_NON_FAST), # Test cases that invoke mypy (with small inputs) 'pytest-cmdline': 'pytest -k "%s"' % ' or '.join([CMDLINE, EVALUATION, From 5e69ee2998a8491c6632c29426fbc86ebaea08f6 Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Wed, 8 Jul 2020 22:39:16 +0800 Subject: [PATCH 3/8] fix emit test --- mypyc/test/test_emitfunc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 580cd0e0a580..afeaa78977f9 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -194,7 +194,7 @@ def test_list_append(self) -> None: self.assert_emit(CallC(list_append_op.c_function_name, [self.l, self.o], list_append_op.return_type, list_append_op.steals, list_append_op.error_kind, 1), - """cpy_r_r0 = PyList_Append(cpy_r_l, cpy_r_o) >= 0;""") + """cpy_r_r0 = PyList_Append(cpy_r_l, cpy_r_o);""") def test_get_attr(self) -> None: self.assert_emit( From 5ec43e4c77577d00fb821dcf0a30e4cac9c1d31d Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Thu, 9 Jul 2020 09:32:12 +0800 Subject: [PATCH 4/8] fix box int32/int64 --- mypyc/codegen/emit.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mypyc/codegen/emit.py b/mypyc/codegen/emit.py index 037182674a11..7b26c3003c52 100644 --- a/mypyc/codegen/emit.py +++ b/mypyc/codegen/emit.py @@ -13,7 +13,7 @@ is_float_rprimitive, is_bool_rprimitive, is_int_rprimitive, is_short_int_rprimitive, is_list_rprimitive, is_dict_rprimitive, is_set_rprimitive, is_tuple_rprimitive, is_none_rprimitive, is_object_rprimitive, object_rprimitive, is_str_rprimitive, - int_rprimitive, is_optional_type, optional_value_type + int_rprimitive, is_optional_type, optional_value_type, is_int32_rprimitive, is_int64_rprimitive ) from mypyc.ir.func_ir import FuncDecl from mypyc.ir.class_ir import ClassIR, all_concrete_classes @@ -695,6 +695,11 @@ def emit_box(self, src: str, dest: str, typ: RType, declare_dest: bool = False, self.emit_lines('{}{} = Py_None;'.format(declaration, dest)) if not can_borrow: self.emit_inc_ref(dest, object_rprimitive) + # TODO: This is a hack to handle mypy's false negative on unreachable code. + # All ops returning int32/int64 should not be coerced into object. + # Since their result will not be used elsewhere, it's safe to use NULL here + elif is_int32_rprimitive(typ) or is_int64_rprimitive(typ): + self.emit_lines('{}{} = NULL;'.format(declaration, dest)) elif isinstance(typ, RTuple): self.declare_tuple_struct(typ) self.emit_line('{}{} = PyTuple_New({});'.format(declaration, dest, len(typ.types))) From aebf92b6555e9b87b51b1205802fb7c39f340870 Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Thu, 9 Jul 2020 10:16:07 +0800 Subject: [PATCH 5/8] some dict ops --- mypyc/irbuild/builder.py | 4 +- mypyc/irbuild/classdef.py | 32 ++++----- mypyc/irbuild/expression.py | 2 +- mypyc/irbuild/for_helpers.py | 6 +- mypyc/irbuild/function.py | 8 +-- mypyc/irbuild/statement.py | 4 +- mypyc/primitives/dict_ops.py | 26 ++++--- mypyc/test-data/irbuild-basic.test | 94 ++++++++++++------------- mypyc/test-data/irbuild-classes.test | 36 +++++----- mypyc/test-data/irbuild-dict.test | 32 +++++---- mypyc/test-data/irbuild-statements.test | 10 +-- mypyc/test-data/refcount.test | 4 +- mypyc/test/test_emitfunc.py | 10 ++- 13 files changed, 136 insertions(+), 132 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 30699b5a7ac2..e1d50df98bde 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -245,7 +245,7 @@ def add_to_non_ext_dict(self, non_ext: NonExtClassInfo, key: str, val: Value, line: int) -> None: # Add an attribute entry into the class dict of a non-extension class. key_unicode = self.load_static_unicode(key) - self.primitive_op(dict_set_item_op, [non_ext.dict, key_unicode, val], line) + self.call_c(dict_set_item_op, [non_ext.dict, key_unicode, val], line) def gen_import(self, id: str, line: int) -> None: self.imports[id] = None @@ -884,7 +884,7 @@ def load_global(self, expr: NameExpr) -> Value: def load_global_str(self, name: str, line: int) -> Value: _globals = self.load_globals_dict() reg = self.load_static_unicode(name) - return self.primitive_op(dict_get_item_op, [_globals, reg], line) + return self.call_c(dict_get_item_op, [_globals, reg], line) def load_globals_dict(self) -> Value: return self.add(LoadStatic(dict_rprimitive, 'globals', self.module_name)) diff --git a/mypyc/irbuild/classdef.py b/mypyc/irbuild/classdef.py index 7d9244b23f83..8b5f1da98d26 100644 --- a/mypyc/irbuild/classdef.py +++ b/mypyc/irbuild/classdef.py @@ -149,12 +149,12 @@ def transform_class_def(builder: IRBuilder, cdef: ClassDef) -> None: builder.add(InitStatic(non_ext_class, cdef.name, builder.module_name, NAMESPACE_TYPE)) # Add the non-extension class to the dict - builder.primitive_op(dict_set_item_op, - [ - builder.load_globals_dict(), - builder.load_static_unicode(cdef.name), - non_ext_class - ], cdef.line) + builder.call_c(dict_set_item_op, + [ + builder.load_globals_dict(), + builder.load_static_unicode(cdef.name), + non_ext_class + ], cdef.line) # Cache any cachable class attributes cache_class_attrs(builder, attrs_to_cache, cdef) @@ -191,12 +191,12 @@ def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value: builder.add(InitStatic(tp, cdef.name, builder.module_name, NAMESPACE_TYPE)) # Add it to the dict - builder.primitive_op(dict_set_item_op, - [ - builder.load_globals_dict(), - builder.load_static_unicode(cdef.name), - tp, - ], cdef.line) + builder.call_c(dict_set_item_op, + [ + builder.load_globals_dict(), + builder.load_static_unicode(cdef.name), + tp, + ], cdef.line) return tp @@ -280,7 +280,7 @@ def add_non_ext_class_attr(builder: IRBuilder, # TODO: Maybe generate more precise types for annotations key = builder.load_static_unicode(lvalue.name) typ = builder.primitive_op(type_object_op, [], stmt.line) - builder.primitive_op(dict_set_item_op, [non_ext.anns, key, typ], stmt.line) + builder.call_c(dict_set_item_op, [non_ext.anns, key, typ], stmt.line) # Only add the attribute to the __dict__ if the assignment is of the form: # x: type = value (don't add attributes of the form 'x: type' to the __dict__). @@ -470,9 +470,9 @@ def create_mypyc_attrs_tuple(builder: IRBuilder, ir: ClassIR, line: int) -> Valu def finish_non_ext_dict(builder: IRBuilder, non_ext: NonExtClassInfo, line: int) -> None: # Add __annotations__ to the class dict. - builder.primitive_op(dict_set_item_op, - [non_ext.dict, builder.load_static_unicode('__annotations__'), - non_ext.anns], -1) + builder.call_c(dict_set_item_op, + [non_ext.dict, builder.load_static_unicode('__annotations__'), + non_ext.anns], -1) # We add a __doc__ attribute so if the non-extension class is decorated with the # dataclass decorator, dataclass will not try to look for __text_signature__. diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 0cb09d393334..a52a7ee83479 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -547,7 +547,7 @@ def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehe def gen_inner_stmts() -> None: k = builder.accept(o.key) v = builder.accept(o.value) - builder.primitive_op(dict_set_item_op, [d, k, v], o.line) + builder.call_c(dict_set_item_op, [d, k, v], o.line) comprehension_helper(builder, loop_params, gen_inner_stmts, o.line) return d diff --git a/mypyc/irbuild/for_helpers.py b/mypyc/irbuild/for_helpers.py index d2aca4149457..6cc19f0e17bc 100644 --- a/mypyc/irbuild/for_helpers.py +++ b/mypyc/irbuild/for_helpers.py @@ -532,9 +532,9 @@ def gen_step(self) -> None: builder = self.builder line = self.line # Technically, we don't need a new primitive for this, but it is simpler. - builder.primitive_op(dict_check_size_op, - [builder.read(self.expr_target, line), - builder.read(self.size, line)], line) + builder.call_c(dict_check_size_op, + [builder.read(self.expr_target, line), + builder.read(self.size, line)], line) def gen_cleanup(self) -> None: # Same as for generic ForIterable. diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index 8687df6b6487..ad42a12584ee 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -93,10 +93,10 @@ def transform_decorator(builder: IRBuilder, dec: Decorator) -> None: decorated_func = load_decorated_func(builder, dec.func, orig_func) # Set the callable object representing the decorated function as a global. - builder.primitive_op(dict_set_item_op, - [builder.load_globals_dict(), - builder.load_static_unicode(dec.func.name), decorated_func], - decorated_func.line) + builder.call_c(dict_set_item_op, + [builder.load_globals_dict(), + builder.load_static_unicode(dec.func.name), decorated_func], + decorated_func.line) builder.functions.append(func_ir) diff --git a/mypyc/irbuild/statement.py b/mypyc/irbuild/statement.py index 1f669930c634..ac88ecb04858 100644 --- a/mypyc/irbuild/statement.py +++ b/mypyc/irbuild/statement.py @@ -126,8 +126,8 @@ def transform_import(builder: IRBuilder, node: Import) -> None: # Python 3.7 has a nice 'PyImport_GetModule' function that we can't use :( mod_dict = builder.primitive_op(get_module_dict_op, [], node.line) - obj = builder.primitive_op(dict_get_item_op, - [mod_dict, builder.load_static_unicode(base)], node.line) + obj = builder.call_c(dict_get_item_op, + [mod_dict, builder.load_static_unicode(base)], node.line) builder.gen_method_call( globals, '__setitem__', [builder.load_static_unicode(name), obj], result_type=None, line=node.line) diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 1ee2e40920b7..7076d8f00242 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -24,20 +24,20 @@ is_borrowed=True) # dict[key] -dict_get_item_op = method_op( +dict_get_item_op = c_method_op( name='__getitem__', arg_types=[dict_rprimitive, object_rprimitive], - result_type=object_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyDict_GetItem')) + return_type=object_rprimitive, + c_function_name='CPyDict_GetItem', + error_kind=ERR_MAGIC) # dict[key] = value -dict_set_item_op = method_op( +dict_set_item_op = c_method_op( name='__setitem__', arg_types=[dict_rprimitive, object_rprimitive, object_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('CPyDict_SetItem')) + return_type=c_int_rprimitive, + c_function_name='CPyDict_SetItem', + error_kind=ERR_NEG_INT) # key in dict c_binary_op( @@ -241,10 +241,8 @@ def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: ) # check that len(dict) == const during iteration -dict_check_size_op = custom_op( +dict_check_size_op = c_custom_op( arg_types=[dict_rprimitive, int_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_emit('CPyDict_CheckSize'), - format_str='{dest} = assert size({args[0]}) == {args[1]}', -) + return_type=bool_rprimitive, + c_function_name='CPyDict_CheckSize', + error_kind=ERR_FALSE) diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 71a54a3a51ab..46438491a596 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -594,7 +594,7 @@ def f(x): L0: r0 = __main__.globals :: static r1 = unicode_2 :: static ('g') - r2 = r0[r1] :: dict + r2 = CPyDict_GetItem(r0, r1) r3 = box(int, x) r4 = py_call(r2, r3) r5 = unbox(int, r4) @@ -1058,7 +1058,7 @@ def return_callable_type(): L0: r0 = __main__.globals :: static r1 = unicode_4 :: static ('return_float') - r2 = r0[r1] :: dict + r2 = CPyDict_GetItem(r0, r1) return r2 def call_callable_type(): r0, f, r1 :: object @@ -1359,7 +1359,7 @@ def f(): L0: r0 = __main__.globals :: static r1 = unicode_1 :: static ('x') - r2 = r0[r1] :: dict + r2 = CPyDict_GetItem(r0, r1) r3 = unbox(int, r2) r4 = builtins :: module r5 = unicode_2 :: static ('print') @@ -1377,7 +1377,7 @@ def __top_level__(): r6 :: dict r7 :: str r8 :: object - r9 :: bool + r9 :: int32 r10 :: dict r11 :: str r12 :: object @@ -1400,10 +1400,10 @@ L2: r6 = __main__.globals :: static r7 = unicode_1 :: static ('x') r8 = box(short_int, r5) - r9 = r6.__setitem__(r7, r8) :: dict + r9 = CPyDict_SetItem(r6, r7, r8) r10 = __main__.globals :: static r11 = unicode_1 :: static ('x') - r12 = r10[r11] :: dict + r12 = CPyDict_GetItem(r10, r11) r13 = unbox(int, r12) r14 = builtins :: module r15 = unicode_2 :: static ('print') @@ -1629,7 +1629,7 @@ L0: r3 = (r0, r1, r2) r4 = __main__.globals :: static r5 = unicode_3 :: static ('f') - r6 = r4[r5] :: dict + r6 = CPyDict_GetItem(r4, r5) r7 = [] r8 = box(tuple[int, int, int], r3) r9 = CPyList_Extend(r7, r8) @@ -1657,7 +1657,7 @@ L0: r3 = (r1, r2) r4 = __main__.globals :: static r5 = unicode_3 :: static ('f') - r6 = r4[r5] :: dict + r6 = CPyDict_GetItem(r4, r5) r7 = box(short_int, r0) r8 = [r7] r9 = box(tuple[int, int], r3) @@ -1690,7 +1690,7 @@ def g(): r3 :: short_int r4 :: str r5 :: short_int - r6 :: native_int + r6 :: int64 r7, r8, r9 :: object r10, r11 :: dict r12 :: str @@ -1714,7 +1714,7 @@ L0: r10 = CPyDict_Build(r6, r0, r7, r2, r8, r4, r9) r11 = __main__.globals :: static r12 = unicode_6 :: static ('f') - r13 = r11[r12] :: dict + r13 = CPyDict_GetItem(r11, r12) r14 = () :: tuple r15 = PyDict_New() r16 = r15.update(r10) (display) :: dict @@ -1727,7 +1727,7 @@ def h(): r2 :: short_int r3 :: str r4 :: short_int - r5 :: native_int + r5 :: int64 r6, r7 :: object r8, r9 :: dict r10 :: str @@ -1749,7 +1749,7 @@ L0: r8 = CPyDict_Build(r5, r1, r6, r3, r7) r9 = __main__.globals :: static r10 = unicode_6 :: static ('f') - r11 = r9[r10] :: dict + r11 = CPyDict_GetItem(r9, r10) r12 = box(short_int, r0) r13 = (r12) :: tuple r14 = PyDict_New() @@ -1943,7 +1943,7 @@ def f(): r17 :: bool r18 :: int r19, r20 :: object - r21 :: bool + r21 :: int32 r22, r23 :: short_int L0: r0 = PyDict_New() @@ -1979,7 +1979,7 @@ L6: r18 = CPyTagged_Multiply(x, x) r19 = box(int, x) r20 = box(int, r18) - r21 = r0.__setitem__(r19, r20) :: dict + r21 = CPyDict_SetItem(r0, r19, r20) L7: r22 = 1 r23 = r9 + r22 @@ -2412,15 +2412,15 @@ def __top_level__(): r12 :: str r13 :: object r14 :: str - r15 :: bool + r15 :: int32 r16 :: str r17 :: object r18 :: str - r19 :: bool + r19 :: int32 r20 :: str r21 :: object r22 :: str - r23 :: bool + r23 :: int32 r24, r25 :: str r26 :: object r27 :: tuple[str, object] @@ -2436,7 +2436,7 @@ def __top_level__(): r37, r38 :: object r39 :: dict r40 :: str - r41 :: bool + r41 :: int32 r42 :: short_int r43 :: str r44 :: dict @@ -2445,13 +2445,13 @@ def __top_level__(): r49 :: tuple r50 :: dict r51 :: str - r52 :: bool + r52 :: int32 r53 :: dict r54 :: str r55, r56, r57 :: object r58 :: dict r59 :: str - r60 :: bool + r60 :: int32 r61 :: str r62 :: dict r63 :: str @@ -2461,7 +2461,7 @@ def __top_level__(): r67, r68 :: object r69 :: dict r70 :: str - r71 :: bool + r71 :: int32 r72, r73, r74 :: short_int r75, r76, r77 :: object r78 :: list @@ -2470,7 +2470,7 @@ def __top_level__(): r81, r82 :: object r83 :: dict r84 :: str - r85 :: bool + r85 :: int32 r86 :: None L0: r0 = builtins :: module @@ -2496,15 +2496,15 @@ L4: r12 = unicode_2 :: static ('List') r13 = getattr r10, r12 r14 = unicode_2 :: static ('List') - r15 = r11.__setitem__(r14, r13) :: dict + r15 = CPyDict_SetItem(r11, r14, r13) r16 = unicode_3 :: static ('NewType') r17 = getattr r10, r16 r18 = unicode_3 :: static ('NewType') - r19 = r11.__setitem__(r18, r17) :: dict + r19 = CPyDict_SetItem(r11, r18, r17) r20 = unicode_4 :: static ('NamedTuple') r21 = getattr r10, r20 r22 = unicode_4 :: static ('NamedTuple') - r23 = r11.__setitem__(r22, r21) :: dict + r23 = CPyDict_SetItem(r11, r22, r21) r24 = unicode_5 :: static ('Lol') r25 = unicode_6 :: static ('a') r26 = int @@ -2518,41 +2518,41 @@ L4: r34 = box(tuple[object, object], r33) r35 = __main__.globals :: static r36 = unicode_4 :: static ('NamedTuple') - r37 = r35[r36] :: dict + r37 = CPyDict_GetItem(r35, r36) r38 = py_call(r37, r24, r34) r39 = __main__.globals :: static r40 = unicode_5 :: static ('Lol') - r41 = r39.__setitem__(r40, r38) :: dict + r41 = CPyDict_SetItem(r39, r40, r38) r42 = 1 r43 = unicode_8 :: static r44 = __main__.globals :: static r45 = unicode_5 :: static ('Lol') - r46 = r44[r45] :: dict + r46 = CPyDict_GetItem(r44, r45) r47 = box(short_int, r42) r48 = py_call(r46, r47, r43) r49 = cast(tuple, r48) r50 = __main__.globals :: static r51 = unicode_9 :: static ('x') - r52 = r50.__setitem__(r51, r49) :: dict + r52 = CPyDict_SetItem(r50, r51, r49) r53 = __main__.globals :: static r54 = unicode_2 :: static ('List') - r55 = r53[r54] :: dict + r55 = CPyDict_GetItem(r53, r54) r56 = int r57 = r55[r56] :: object r58 = __main__.globals :: static r59 = unicode_10 :: static ('Foo') - r60 = r58.__setitem__(r59, r57) :: dict + r60 = CPyDict_SetItem(r58, r59, r57) r61 = unicode_11 :: static ('Bar') r62 = __main__.globals :: static r63 = unicode_10 :: static ('Foo') - r64 = r62[r63] :: dict + r64 = CPyDict_GetItem(r62, r63) r65 = __main__.globals :: static r66 = unicode_3 :: static ('NewType') - r67 = r65[r66] :: dict + r67 = CPyDict_GetItem(r65, r66) r68 = py_call(r67, r61, r64) r69 = __main__.globals :: static r70 = unicode_11 :: static ('Bar') - r71 = r69.__setitem__(r70, r68) :: dict + r71 = CPyDict_SetItem(r69, r70, r68) r72 = 1 r73 = 2 r74 = 3 @@ -2562,11 +2562,11 @@ L4: r78 = [r75, r76, r77] r79 = __main__.globals :: static r80 = unicode_11 :: static ('Bar') - r81 = r79[r80] :: dict + r81 = CPyDict_GetItem(r79, r80) r82 = py_call(r81, r78) r83 = __main__.globals :: static r84 = unicode_12 :: static ('y') - r85 = r83.__setitem__(r84, r82) :: dict + r85 = CPyDict_SetItem(r83, r84, r82) r86 = None return r86 @@ -2829,11 +2829,11 @@ L0: r1.__mypyc_env__ = r0; r2 = is_error r3 = __main__.globals :: static r4 = unicode_8 :: static ('b') - r5 = r3[r4] :: dict + r5 = CPyDict_GetItem(r3, r4) r6 = py_call(r5, r1) r7 = __main__.globals :: static r8 = unicode_9 :: static ('a') - r9 = r7[r8] :: dict + r9 = CPyDict_GetItem(r7, r8) r10 = py_call(r9, r6) r0.d = r10; r11 = is_error r12 = unicode_10 :: static ('c') @@ -2857,7 +2857,7 @@ def __top_level__(): r12 :: str r13 :: object r14 :: str - r15 :: bool + r15 :: int32 r16 :: dict r17 :: str r18 :: object @@ -2869,7 +2869,7 @@ def __top_level__(): r25, r26 :: object r27 :: dict r28 :: str - r29 :: bool + r29 :: int32 r30 :: None L0: r0 = builtins :: module @@ -2895,21 +2895,21 @@ L4: r12 = unicode_2 :: static ('Callable') r13 = getattr r10, r12 r14 = unicode_2 :: static ('Callable') - r15 = r11.__setitem__(r14, r13) :: dict + r15 = CPyDict_SetItem(r11, r14, r13) r16 = __main__.globals :: static r17 = unicode_11 :: static ('__mypyc_c_decorator_helper__') - r18 = r16[r17] :: dict + r18 = CPyDict_GetItem(r16, r17) r19 = __main__.globals :: static r20 = unicode_8 :: static ('b') - r21 = r19[r20] :: dict + r21 = CPyDict_GetItem(r19, r20) r22 = py_call(r21, r18) r23 = __main__.globals :: static r24 = unicode_9 :: static ('a') - r25 = r23[r24] :: dict + r25 = CPyDict_GetItem(r23, r24) r26 = py_call(r25, r22) r27 = __main__.globals :: static r28 = unicode_10 :: static ('c') - r29 = r27.__setitem__(r28, r26) :: dict + r29 = CPyDict_SetItem(r27, r28, r26) r30 = None return r30 @@ -2995,7 +2995,7 @@ def __top_level__(): r12 :: str r13 :: object r14 :: str - r15 :: bool + r15 :: int32 r16 :: None L0: r0 = builtins :: module @@ -3021,7 +3021,7 @@ L4: r12 = unicode_2 :: static ('Callable') r13 = getattr r10, r12 r14 = unicode_2 :: static ('Callable') - r15 = r11.__setitem__(r14, r13) :: dict + r15 = CPyDict_SetItem(r11, r14, r13) r16 = None return r16 diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index 99880d75de17..0c26a76500b7 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -333,11 +333,11 @@ def __top_level__(): r12 :: str r13 :: object r14 :: str - r15 :: bool + r15 :: int32 r16 :: str r17 :: object r18 :: str - r19 :: bool + r19 :: int32 r20, r21 :: object r22 :: bool r23 :: str @@ -346,14 +346,14 @@ def __top_level__(): r27 :: str r28 :: object r29 :: str - r30 :: bool + r30 :: int32 r31 :: str r32 :: dict r33 :: str r34, r35 :: object r36 :: dict r37 :: str - r38 :: bool + r38 :: int32 r39 :: object r40 :: str r41, r42 :: object @@ -363,7 +363,7 @@ def __top_level__(): r46 :: bool r47 :: dict r48 :: str - r49 :: bool + r49 :: int32 r50 :: object r51 :: str r52, r53 :: object @@ -372,7 +372,7 @@ def __top_level__(): r56 :: bool r57 :: dict r58 :: str - r59 :: bool + r59 :: int32 r60, r61 :: object r62 :: dict r63 :: str @@ -389,7 +389,7 @@ def __top_level__(): r77 :: bool r78 :: dict r79 :: str - r80 :: bool + r80 :: int32 r81 :: None L0: r0 = builtins :: module @@ -415,11 +415,11 @@ L4: r12 = unicode_2 :: static ('TypeVar') r13 = getattr r10, r12 r14 = unicode_2 :: static ('TypeVar') - r15 = r11.__setitem__(r14, r13) :: dict + r15 = CPyDict_SetItem(r11, r14, r13) r16 = unicode_3 :: static ('Generic') r17 = getattr r10, r16 r18 = unicode_3 :: static ('Generic') - r19 = r11.__setitem__(r18, r17) :: dict + r19 = CPyDict_SetItem(r11, r18, r17) r20 = mypy_extensions :: module r21 = builtins.None :: object r22 = r20 is not r21 @@ -434,15 +434,15 @@ L6: r27 = unicode_5 :: static ('trait') r28 = getattr r25, r27 r29 = unicode_5 :: static ('trait') - r30 = r26.__setitem__(r29, r28) :: dict + r30 = CPyDict_SetItem(r26, r29, r28) r31 = unicode_6 :: static ('T') r32 = __main__.globals :: static r33 = unicode_2 :: static ('TypeVar') - r34 = r32[r33] :: dict + r34 = CPyDict_GetItem(r32, r33) r35 = py_call(r34, r31) r36 = __main__.globals :: static r37 = unicode_6 :: static ('T') - r38 = r36.__setitem__(r37, r35) :: dict + r38 = CPyDict_SetItem(r36, r37, r35) r39 = :: object r40 = unicode_7 :: static ('__main__') r41 = __main__.C_template :: type @@ -454,7 +454,7 @@ L6: __main__.C = r42 :: type r47 = __main__.globals :: static r48 = unicode_9 :: static ('C') - r49 = r47.__setitem__(r48, r42) :: dict + r49 = CPyDict_SetItem(r47, r48, r42) r50 = :: object r51 = unicode_7 :: static ('__main__') r52 = __main__.S_template :: type @@ -465,15 +465,15 @@ L6: __main__.S = r53 :: type r57 = __main__.globals :: static r58 = unicode_10 :: static ('S') - r59 = r57.__setitem__(r58, r53) :: dict + r59 = CPyDict_SetItem(r57, r58, r53) r60 = __main__.C :: type r61 = __main__.S :: type r62 = __main__.globals :: static r63 = unicode_3 :: static ('Generic') - r64 = r62[r63] :: dict + r64 = CPyDict_GetItem(r62, r63) r65 = __main__.globals :: static r66 = unicode_6 :: static ('T') - r67 = r65[r66] :: dict + r67 = CPyDict_GetItem(r65, r66) r68 = r64[r67] :: object r69 = (r60, r61, r68) :: tuple r70 = unicode_7 :: static ('__main__') @@ -487,7 +487,7 @@ L6: __main__.D = r72 :: type r78 = __main__.globals :: static r79 = unicode_12 :: static ('D') - r80 = r78.__setitem__(r79, r72) :: dict + r80 = CPyDict_SetItem(r78, r79, r72) r81 = None return r81 @@ -1047,7 +1047,7 @@ L0: __mypyc_self__.x = r0; r1 = is_error r2 = __main__.globals :: static r3 = unicode_9 :: static ('LOL') - r4 = r2[r3] :: dict + r4 = CPyDict_GetItem(r2, r3) r5 = cast(str, r4) __mypyc_self__.y = r5; r6 = is_error r7 = None diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 5844d12ed095..a9c70e4d4d69 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -11,7 +11,7 @@ def f(d): L0: r0 = 0 r1 = box(short_int, r0) - r2 = d[r1] :: dict + r2 = CPyDict_GetItem(d, r1) r3 = unbox(bool, r2) return r3 @@ -25,14 +25,14 @@ def f(d): r0 :: bool r1 :: short_int r2, r3 :: object - r4 :: bool + r4 :: int32 r5 :: None L0: r0 = False r1 = 0 r2 = box(short_int, r1) r3 = box(bool, r0) - r4 = d.__setitem__(r2, r3) :: dict + r4 = CPyDict_SetItem(d, r2, r3) r5 = None return r5 @@ -168,7 +168,8 @@ def increment(d): r9 :: object r10 :: short_int r11, r12 :: object - r13, r14, r15 :: bool + r13 :: int32 + r14, r15 :: bool L0: r0 = 0 r1 = r0 @@ -184,13 +185,13 @@ L2: r7 = r4[2] r8 = cast(str, r7) k = r8 - r9 = d[k] :: dict + r9 = CPyDict_GetItem(d, k) r10 = 1 r11 = box(short_int, r10) r12 = r9 += r11 - r13 = d.__setitem__(k, r12) :: dict + r13 = CPyDict_SetItem(d, k, r12) L3: - r14 = assert size(d) == r2 + r14 = CPyDict_CheckSize(d, r2) goto L1 L4: r15 = no_err_occurred @@ -208,12 +209,12 @@ def f(x, y): r0 :: short_int r1 :: str r2 :: short_int - r3 :: native_int + r3 :: int64 r4 :: object r5 :: dict r6 :: bool r7 :: object - r8 :: bool + r8 :: int32 L0: r0 = 2 r1 = unicode_3 :: static ('z') @@ -223,7 +224,7 @@ L0: r5 = CPyDict_Build(r3, x, r4) r6 = r5.update(y) (display) :: dict r7 = box(short_int, r2) - r8 = r5.__setitem__(r1, r7) :: dict + r8 = CPyDict_SetItem(r5, r1, r7) return r5 [case testDictIterationMethods] @@ -259,7 +260,8 @@ def print_dict_methods(d1, d2): r22, r23 :: object r24, r25, k :: int r26, r27, r28, r29, r30 :: object - r31, r32, r33 :: bool + r31 :: int32 + r32, r33 :: bool r34 :: None L0: r0 = 0 @@ -285,7 +287,7 @@ L3: return r12 L4: L5: - r13 = assert size(d1) == r2 + r13 = CPyDict_CheckSize(d1, r2) goto L1 L6: r14 = no_err_occurred @@ -308,13 +310,13 @@ L9: k = r24 v = r25 r26 = box(int, k) - r27 = d2[r26] :: dict + r27 = CPyDict_GetItem(d2, r26) r28 = box(int, v) r29 = r27 += r28 r30 = box(int, k) - r31 = d2.__setitem__(r30, r29) :: dict + r31 = CPyDict_SetItem(d2, r30, r29) L10: - r32 = assert size(d2) == r17 + r32 = CPyDict_CheckSize(d2, r17) goto L8 L11: r33 = no_err_occurred diff --git a/mypyc/test-data/irbuild-statements.test b/mypyc/test-data/irbuild-statements.test index b385edfc4f17..5786f75ac3ab 100644 --- a/mypyc/test-data/irbuild-statements.test +++ b/mypyc/test-data/irbuild-statements.test @@ -324,10 +324,10 @@ L2: r8 = unbox(int, r7) key = r8 r9 = box(int, key) - r10 = d[r9] :: dict + r10 = CPyDict_GetItem(d, r9) r11 = unbox(int, r10) L3: - r12 = assert size(d) == r2 + r12 = CPyDict_CheckSize(d, r2) goto L1 L4: r13 = no_err_occurred @@ -385,7 +385,7 @@ L2: r9 = unbox(int, r8) key = r9 r10 = box(int, key) - r11 = d[r10] :: dict + r11 = CPyDict_GetItem(d, r10) r12 = unbox(int, r11) r13 = 2 r14 = CPyTagged_Remainder(r12, r13) @@ -396,12 +396,12 @@ L3: goto L5 L4: r17 = box(int, key) - r18 = d[r17] :: dict + r18 = CPyDict_GetItem(d, r17) r19 = unbox(int, r18) r20 = CPyTagged_Add(s, r19) s = r20 L5: - r21 = assert size(d) == r3 + r21 = CPyDict_CheckSize(d, r3) goto L1 L6: r22 = no_err_occurred diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index 4f25ca96ce7b..274d248e5acb 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -820,13 +820,13 @@ L2: dec_ref r7 key = r8 r9 = box(int, key) - r10 = d[r9] :: dict + r10 = CPyDict_GetItem(d, r9) dec_ref r9 r11 = unbox(int, r10) dec_ref r10 dec_ref r11 :: int L3: - r12 = assert size(d) == r2 + r12 = CPyDict_CheckSize(d, r2) goto L1 L4: r13 = no_err_occurred diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index afeaa78977f9..881015e103ad 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -218,12 +218,16 @@ def test_set_attr(self) -> None: """) def test_dict_get_item(self) -> None: - self.assert_emit(PrimitiveOp([self.d, self.o2], dict_get_item_op, 1), + self.assert_emit(CallC(dict_get_item_op.c_function_name, [self.d, self.o2], + dict_get_item_op.return_type, dict_get_item_op.steals, + dict_get_item_op.error_kind, 1), """cpy_r_r0 = CPyDict_GetItem(cpy_r_d, cpy_r_o2);""") def test_dict_set_item(self) -> None: - self.assert_emit(PrimitiveOp([self.d, self.o, self.o2], dict_set_item_op, 1), - """cpy_r_r0 = CPyDict_SetItem(cpy_r_d, cpy_r_o, cpy_r_o2) >= 0;""") + self.assert_emit(CallC(dict_set_item_op.c_function_name, [self.d, self.o, self.o2], + dict_set_item_op.return_type, dict_set_item_op.steals, + dict_set_item_op.error_kind, 1), + """cpy_r_r0 = CPyDict_SetItem(cpy_r_d, cpy_r_o, cpy_r_o2);""") def test_dict_update(self) -> None: self.assert_emit(PrimitiveOp([self.d, self.o], dict_update_op, 1), From 261b96dcfaf95a962e2f46aadec129e86edee97c Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Thu, 9 Jul 2020 10:41:01 +0800 Subject: [PATCH 6/8] more dict ops --- mypyc/irbuild/ll_builder.py | 2 +- mypyc/primitives/dict_ops.py | 27 +++++++++++++-------------- mypyc/test-data/irbuild-basic.test | 8 ++++---- mypyc/test-data/irbuild-classes.test | 4 ++-- mypyc/test-data/irbuild-dict.test | 8 ++++---- mypyc/test/test_emitfunc.py | 6 ++++-- 6 files changed, 28 insertions(+), 27 deletions(-) diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index ec9f0ede2102..359dea60d068 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -591,7 +591,7 @@ def make_dict(self, key_value_pairs: Sequence[DictEntry], line: int) -> Value: if result is None: result = self._create_dict(keys, values, line) - self.primitive_op( + self.call_c( dict_update_in_display_op, [result, value], line=line diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 7076d8f00242..f871f33d07af 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -11,7 +11,7 @@ from mypyc.primitives.registry import ( name_ref_op, method_op, func_op, custom_op, - simple_emit, call_emit, call_negative_bool_emit, + simple_emit, call_emit, name_emit, c_custom_op, c_method_op, c_function_op, c_binary_op ) @@ -50,30 +50,29 @@ ordering=[1, 0]) # dict1.update(dict2) -dict_update_op = method_op( +dict_update_op = c_method_op( name='update', arg_types=[dict_rprimitive, dict_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('CPyDict_Update'), + return_type=c_int_rprimitive, + c_function_name='CPyDict_Update', + error_kind=ERR_NEG_INT, priority=2) # Operation used for **value in dict displays. # This is mostly like dict.update(obj), but has customized error handling. -dict_update_in_display_op = custom_op( +dict_update_in_display_op = c_custom_op( arg_types=[dict_rprimitive, dict_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('CPyDict_UpdateInDisplay'), - format_str='{dest} = {args[0]}.update({args[1]}) (display) :: dict',) + return_type=c_int_rprimitive, + c_function_name='CPyDict_UpdateInDisplay', + error_kind=ERR_NEG_INT) # dict.update(obj) -method_op( +c_method_op( name='update', arg_types=[dict_rprimitive, object_rprimitive], - result_type=bool_rprimitive, - error_kind=ERR_FALSE, - emit=call_negative_bool_emit('CPyDict_UpdateFromAny')) + return_type=c_int_rprimitive, + c_function_name='CPyDict_UpdateFromAny', + error_kind=ERR_NEG_INT) # dict.get(key, default) c_method_op( diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 46438491a596..7585f42e2154 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -1697,7 +1697,7 @@ def g(): r13 :: object r14 :: tuple r15 :: dict - r16 :: bool + r16 :: int32 r17 :: object r18 :: tuple[int, int, int] L0: @@ -1717,7 +1717,7 @@ L0: r13 = CPyDict_GetItem(r11, r12) r14 = () :: tuple r15 = PyDict_New() - r16 = r15.update(r10) (display) :: dict + r16 = CPyDict_UpdateInDisplay(r15, r10) r17 = py_call_with_kwargs(r13, r14, r15) r18 = unbox(tuple[int, int, int], r17) return r18 @@ -1734,7 +1734,7 @@ def h(): r11, r12 :: object r13 :: tuple r14 :: dict - r15 :: bool + r15 :: int32 r16 :: object r17 :: tuple[int, int, int] L0: @@ -1753,7 +1753,7 @@ L0: r12 = box(short_int, r0) r13 = (r12) :: tuple r14 = PyDict_New() - r15 = r14.update(r8) (display) :: dict + r15 = CPyDict_UpdateInDisplay(r14, r8) r16 = py_call_with_kwargs(r11, r13, r14) r17 = unbox(tuple[int, int, int], r16) return r17 diff --git a/mypyc/test-data/irbuild-classes.test b/mypyc/test-data/irbuild-classes.test index 0c26a76500b7..eabe0c3f45ea 100644 --- a/mypyc/test-data/irbuild-classes.test +++ b/mypyc/test-data/irbuild-classes.test @@ -1068,10 +1068,10 @@ def foo(x: WelpDict) -> None: [out] def foo(x): x :: dict - r0 :: bool + r0 :: int32 r1, r2 :: None L0: - r0 = x.update(x) :: dict + r0 = CPyDict_Update(x, x) r1 = None r2 = None return r2 diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index a9c70e4d4d69..2547cb8068f3 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -140,10 +140,10 @@ def f(a: Dict[int, int], b: Dict[int, int]) -> None: [out] def f(a, b): a, b :: dict - r0 :: bool + r0 :: int32 r1, r2 :: None L0: - r0 = a.update(b) :: dict + r0 = CPyDict_Update(a, b) r1 = None r2 = None return r2 @@ -212,7 +212,7 @@ def f(x, y): r3 :: int64 r4 :: object r5 :: dict - r6 :: bool + r6 :: int32 r7 :: object r8 :: int32 L0: @@ -222,7 +222,7 @@ L0: r3 = 1 r4 = box(short_int, r0) r5 = CPyDict_Build(r3, x, r4) - r6 = r5.update(y) (display) :: dict + r6 = CPyDict_UpdateInDisplay(r5, y) r7 = box(short_int, r2) r8 = CPyDict_SetItem(r5, r1, r7) return r5 diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 881015e103ad..e182275ae070 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -230,8 +230,10 @@ def test_dict_set_item(self) -> None: """cpy_r_r0 = CPyDict_SetItem(cpy_r_d, cpy_r_o, cpy_r_o2);""") def test_dict_update(self) -> None: - self.assert_emit(PrimitiveOp([self.d, self.o], dict_update_op, 1), - """cpy_r_r0 = CPyDict_Update(cpy_r_d, cpy_r_o) >= 0;""") + self.assert_emit(CallC(dict_update_op.c_function_name, [self.d, self.o], + dict_update_op.return_type, dict_update_op.steals, + dict_update_op.error_kind, 1), + """cpy_r_r0 = CPyDict_Update(cpy_r_d, cpy_r_o);""") def test_new_dict(self) -> None: self.assert_emit(CallC(dict_new_op.c_function_name, [], dict_new_op.return_type, From f30303f6dd6de899c99fdfd34dbb490fc52db65f Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Thu, 9 Jul 2020 10:54:40 +0800 Subject: [PATCH 7/8] more dict ops --- mypyc/irbuild/specialize.py | 6 +++--- mypyc/primitives/dict_ops.py | 30 ++++++++++++------------------ mypyc/test-data/irbuild-basic.test | 4 ++-- mypyc/test-data/irbuild-dict.test | 2 +- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/mypyc/irbuild/specialize.py b/mypyc/irbuild/specialize.py index 137e6abf30e1..d10387c26f6b 100644 --- a/mypyc/irbuild/specialize.py +++ b/mypyc/irbuild/specialize.py @@ -99,11 +99,11 @@ def dict_methods_fast_path( # Note that it is not safe to use fast methods on dict subclasses, so # the corresponding helpers in CPy.h fallback to (inlined) generic logic. if attr == 'keys': - return builder.primitive_op(dict_keys_op, [obj], expr.line) + return builder.call_c(dict_keys_op, [obj], expr.line) elif attr == 'values': - return builder.primitive_op(dict_values_op, [obj], expr.line) + return builder.call_c(dict_values_op, [obj], expr.line) else: - return builder.primitive_op(dict_items_op, [obj], expr.line) + return builder.call_c(dict_items_op, [obj], expr.line) @specialize_function('builtins.tuple') diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index f871f33d07af..80db24e2fedc 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -149,31 +149,25 @@ error_kind=ERR_MAGIC) # list(dict.keys()) -dict_keys_op = custom_op( - name='keys', +dict_keys_op = c_custom_op( arg_types=[dict_rprimitive], - result_type=list_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyDict_Keys') -) + return_type=list_rprimitive, + c_function_name='CPyDict_Keys', + error_kind=ERR_MAGIC) # list(dict.values()) -dict_values_op = custom_op( - name='values', +dict_values_op = c_custom_op( arg_types=[dict_rprimitive], - result_type=list_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyDict_Values') -) + return_type=list_rprimitive, + c_function_name='CPyDict_Values', + error_kind=ERR_MAGIC) # list(dict.items()) -dict_items_op = custom_op( - name='items', +dict_items_op = c_custom_op( arg_types=[dict_rprimitive], - result_type=list_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyDict_Items') -) + return_type=list_rprimitive, + c_function_name='CPyDict_Items', + error_kind=ERR_MAGIC) def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 7585f42e2154..eac963c9adcc 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -1690,7 +1690,7 @@ def g(): r3 :: short_int r4 :: str r5 :: short_int - r6 :: int64 + r6 :: native_int r7, r8, r9 :: object r10, r11 :: dict r12 :: str @@ -1727,7 +1727,7 @@ def h(): r2 :: short_int r3 :: str r4 :: short_int - r5 :: int64 + r5 :: native_int r6, r7 :: object r8, r9 :: dict r10 :: str diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 2547cb8068f3..6db3231355c1 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -209,7 +209,7 @@ def f(x, y): r0 :: short_int r1 :: str r2 :: short_int - r3 :: int64 + r3 :: native_int r4 :: object r5 :: dict r6 :: int32 From 10ee64a542785bde62f348da9320604ea3bd9ea0 Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Thu, 9 Jul 2020 11:05:22 +0800 Subject: [PATCH 8/8] final ones --- mypyc/irbuild/for_helpers.py | 11 +++-- mypyc/primitives/dict_ops.py | 65 ++++++++++--------------- mypyc/test-data/irbuild-dict.test | 12 ++--- mypyc/test-data/irbuild-statements.test | 8 +-- mypyc/test-data/refcount.test | 4 +- 5 files changed, 44 insertions(+), 56 deletions(-) diff --git a/mypyc/irbuild/for_helpers.py b/mypyc/irbuild/for_helpers.py index 6cc19f0e17bc..38e75016b26e 100644 --- a/mypyc/irbuild/for_helpers.py +++ b/mypyc/irbuild/for_helpers.py @@ -13,12 +13,13 @@ ) from mypyc.ir.ops import ( Value, BasicBlock, LoadInt, Branch, Register, AssignmentTarget, TupleGet, - AssignmentTargetTuple, TupleSet, OpDescription, BinaryIntOp + AssignmentTargetTuple, TupleSet, BinaryIntOp ) from mypyc.ir.rtypes import ( RType, is_short_int_rprimitive, is_list_rprimitive, is_sequence_rprimitive, RTuple, is_dict_rprimitive, short_int_rprimitive ) +from mypyc.primitives.registry import CFunctionDescription from mypyc.primitives.dict_ops import ( dict_next_key_op, dict_next_value_op, dict_next_item_op, dict_check_size_op, dict_key_iter_op, dict_value_iter_op, dict_item_iter_op @@ -485,8 +486,8 @@ class ForDictionaryCommon(ForGenerator): since they may override some iteration methods in subtly incompatible manner. The fallback logic is implemented in CPy.h via dynamic type check. """ - dict_next_op = None # type: ClassVar[OpDescription] - dict_iter_op = None # type: ClassVar[OpDescription] + dict_next_op = None # type: ClassVar[CFunctionDescription] + dict_iter_op = None # type: ClassVar[CFunctionDescription] def need_cleanup(self) -> bool: # Technically, a dict subclass can raise an unrelated exception @@ -504,14 +505,14 @@ def init(self, expr_reg: Value, target_type: RType) -> None: self.size = builder.maybe_spill(self.load_len(self.expr_target)) # For dict class (not a subclass) this is the dictionary itself. - iter_reg = builder.primitive_op(self.dict_iter_op, [expr_reg], self.line) + iter_reg = builder.call_c(self.dict_iter_op, [expr_reg], self.line) self.iter_target = builder.maybe_spill(iter_reg) def gen_condition(self) -> None: """Get next key/value pair, set new offset, and check if we should continue.""" builder = self.builder line = self.line - self.next_tuple = self.builder.primitive_op( + self.next_tuple = self.builder.call_c( self.dict_next_op, [builder.read(self.iter_target, line), builder.read(self.offset_target, line)], line) diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index 80db24e2fedc..47a2712709c1 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -10,9 +10,8 @@ ) from mypyc.primitives.registry import ( - name_ref_op, method_op, func_op, custom_op, - simple_emit, call_emit, - name_emit, c_custom_op, c_method_op, c_function_op, c_binary_op + name_ref_op, method_op, func_op, + simple_emit, name_emit, c_custom_op, c_method_op, c_function_op, c_binary_op ) @@ -185,53 +184,41 @@ def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: emit=emit_len) # PyDict_Next() fast iteration -dict_key_iter_op = custom_op( - name='key_iter', +dict_key_iter_op = c_custom_op( arg_types=[dict_rprimitive], - result_type=object_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyDict_GetKeysIter'), -) + return_type=object_rprimitive, + c_function_name='CPyDict_GetKeysIter', + error_kind=ERR_MAGIC) -dict_value_iter_op = custom_op( - name='value_iter', +dict_value_iter_op = c_custom_op( arg_types=[dict_rprimitive], - result_type=object_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyDict_GetValuesIter'), -) + return_type=object_rprimitive, + c_function_name='CPyDict_GetValuesIter', + error_kind=ERR_MAGIC) -dict_item_iter_op = custom_op( - name='item_iter', +dict_item_iter_op = c_custom_op( arg_types=[dict_rprimitive], - result_type=object_rprimitive, - error_kind=ERR_MAGIC, - emit=call_emit('CPyDict_GetItemsIter'), -) + return_type=object_rprimitive, + c_function_name='CPyDict_GetItemsIter', + error_kind=ERR_MAGIC) -dict_next_key_op = custom_op( +dict_next_key_op = c_custom_op( arg_types=[object_rprimitive, int_rprimitive], - result_type=dict_next_rtuple_single, - error_kind=ERR_NEVER, - emit=call_emit('CPyDict_NextKey'), - format_str='{dest} = next_key {args[0]}, offset={args[1]}', -) + return_type=dict_next_rtuple_single, + c_function_name='CPyDict_NextKey', + error_kind=ERR_NEVER) -dict_next_value_op = custom_op( +dict_next_value_op = c_custom_op( arg_types=[object_rprimitive, int_rprimitive], - result_type=dict_next_rtuple_single, - error_kind=ERR_NEVER, - emit=call_emit('CPyDict_NextValue'), - format_str='{dest} = next_value {args[0]}, offset={args[1]}', -) + return_type=dict_next_rtuple_single, + c_function_name='CPyDict_NextValue', + error_kind=ERR_NEVER) -dict_next_item_op = custom_op( +dict_next_item_op = c_custom_op( arg_types=[object_rprimitive, int_rprimitive], - result_type=dict_next_rtuple_pair, - error_kind=ERR_NEVER, - emit=call_emit('CPyDict_NextItem'), - format_str='{dest} = next_item {args[0]}, offset={args[1]}', -) + return_type=dict_next_rtuple_pair, + c_function_name='CPyDict_NextItem', + error_kind=ERR_NEVER) # check that len(dict) == const during iteration dict_check_size_op = c_custom_op( diff --git a/mypyc/test-data/irbuild-dict.test b/mypyc/test-data/irbuild-dict.test index 6db3231355c1..a5a47e0fd3bb 100644 --- a/mypyc/test-data/irbuild-dict.test +++ b/mypyc/test-data/irbuild-dict.test @@ -174,9 +174,9 @@ L0: r0 = 0 r1 = r0 r2 = len d :: dict - r3 = key_iter d :: dict + r3 = CPyDict_GetKeysIter(d) L1: - r4 = next_key r3, offset=r1 + r4 = CPyDict_NextKey(r3, r1) r5 = r4[1] r1 = r5 r6 = r4[0] @@ -267,9 +267,9 @@ L0: r0 = 0 r1 = r0 r2 = len d1 :: dict - r3 = value_iter d1 :: dict + r3 = CPyDict_GetValuesIter(d1) L1: - r4 = next_value r3, offset=r1 + r4 = CPyDict_NextValue(r3, r1) r5 = r4[1] r1 = r5 r6 = r4[0] @@ -295,9 +295,9 @@ L7: r15 = 0 r16 = r15 r17 = len d2 :: dict - r18 = item_iter d2 :: dict + r18 = CPyDict_GetItemsIter(d2) L8: - r19 = next_item r18, offset=r16 + r19 = CPyDict_NextItem(r18, r16) r20 = r19[1] r16 = r20 r21 = r19[0] diff --git a/mypyc/test-data/irbuild-statements.test b/mypyc/test-data/irbuild-statements.test index 5786f75ac3ab..596e6671da5e 100644 --- a/mypyc/test-data/irbuild-statements.test +++ b/mypyc/test-data/irbuild-statements.test @@ -312,9 +312,9 @@ L0: r0 = 0 r1 = r0 r2 = len d :: dict - r3 = key_iter d :: dict + r3 = CPyDict_GetKeysIter(d) L1: - r4 = next_key r3, offset=r1 + r4 = CPyDict_NextKey(r3, r1) r5 = r4[1] r1 = r5 r6 = r4[0] @@ -373,9 +373,9 @@ L0: r1 = 0 r2 = r1 r3 = len d :: dict - r4 = key_iter d :: dict + r4 = CPyDict_GetKeysIter(d) L1: - r5 = next_key r4, offset=r2 + r5 = CPyDict_NextKey(r4, r2) r6 = r5[1] r2 = r6 r7 = r5[0] diff --git a/mypyc/test-data/refcount.test b/mypyc/test-data/refcount.test index 274d248e5acb..3729a6fe207b 100644 --- a/mypyc/test-data/refcount.test +++ b/mypyc/test-data/refcount.test @@ -806,9 +806,9 @@ L0: r0 = 0 r1 = r0 r2 = len d :: dict - r3 = key_iter d :: dict + r3 = CPyDict_GetKeysIter(d) L1: - r4 = next_key r3, offset=r1 + r4 = CPyDict_NextKey(r3, r1) r5 = r4[1] r1 = r5 r6 = r4[0]