Skip to content

Commit c7ea011

Browse files
authored

File tree

11 files changed

+104
-1
lines changed

11 files changed

+104
-1
lines changed

mypyc/doc/list_operations.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Operators
3333
* ``lst[n]`` (get item by integer index)
3434
* ``lst[n:m]``, ``lst[n:]``, ``lst[:m]``, ``lst[:]`` (slicing)
3535
* ``lst1 + lst2``, ``lst += iter``
36-
* ``lst * n``, ``n * lst``
36+
* ``lst * n``, ``n * lst``, ``lst *= n``
3737
* ``obj in lst``
3838

3939
Statements

mypyc/doc/tuple_operations.rst

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Operators
2222
* ``tup[n]`` (integer index)
2323
* ``tup[n:m]``, ``tup[n:]``, ``tup[:m]`` (slicing)
2424
* ``tup1 + tup2``
25+
* ``tup * n``, ``n * tup``
2526

2627
Statements
2728
----------

mypyc/lib-rt/CPy.h

+1
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ int CPyList_Remove(PyObject *list, PyObject *obj);
664664
CPyTagged CPyList_Index(PyObject *list, PyObject *obj);
665665
PyObject *CPySequence_Multiply(PyObject *seq, CPyTagged t_size);
666666
PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq);
667+
PyObject *CPySequence_InPlaceMultiply(PyObject *seq, CPyTagged t_size);
667668
PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end);
668669
PyObject *CPyList_Copy(PyObject *list);
669670
int CPySequence_Check(PyObject *obj);

mypyc/lib-rt/list_ops.c

+8
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,14 @@ PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq) {
331331
return CPySequence_Multiply(seq, t_size);
332332
}
333333

334+
PyObject *CPySequence_InPlaceMultiply(PyObject *seq, CPyTagged t_size) {
335+
Py_ssize_t size = CPyTagged_AsSsize_t(t_size);
336+
if (size == -1 && PyErr_Occurred()) {
337+
return NULL;
338+
}
339+
return PySequence_InPlaceRepeat(seq, size);
340+
}
341+
334342
PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) {
335343
if (likely(PyList_CheckExact(obj)
336344
&& CPyTagged_CheckShort(start) && CPyTagged_CheckShort(end))) {

mypyc/primitives/list_ops.py

+9
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,15 @@
307307
error_kind=ERR_MAGIC,
308308
)
309309

310+
# list *= int
311+
binary_op(
312+
name="*=",
313+
arg_types=[list_rprimitive, int_rprimitive],
314+
return_type=list_rprimitive,
315+
c_function_name="CPySequence_InPlaceMultiply",
316+
error_kind=ERR_MAGIC,
317+
)
318+
310319
# list[begin:end]
311320
list_slice_op = custom_op(
312321
arg_types=[list_rprimitive, int_rprimitive, int_rprimitive],

mypyc/primitives/tuple_ops.py

+18
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,24 @@
8383
error_kind=ERR_MAGIC,
8484
)
8585

86+
# tuple * int
87+
binary_op(
88+
name="*",
89+
arg_types=[tuple_rprimitive, int_rprimitive],
90+
return_type=tuple_rprimitive,
91+
c_function_name="CPySequence_Multiply",
92+
error_kind=ERR_MAGIC,
93+
)
94+
95+
# int * tuple
96+
binary_op(
97+
name="*",
98+
arg_types=[int_rprimitive, tuple_rprimitive],
99+
return_type=tuple_rprimitive,
100+
c_function_name="CPySequence_RMultiply",
101+
error_kind=ERR_MAGIC,
102+
)
103+
86104
# tuple[begin:end]
87105
tuple_slice_op = custom_op(
88106
arg_types=[tuple_rprimitive, int_rprimitive, int_rprimitive],

mypyc/test-data/fixtures/ir.py

+3
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ def __contains__(self, item: object) -> int: ...
212212
def __add__(self, value: Tuple[T_co, ...], /) -> Tuple[T_co, ...]: ...
213213
@overload
214214
def __add__(self, value: Tuple[_T, ...], /) -> Tuple[T_co | _T, ...]: ...
215+
def __mul__(self, value: int, /) -> Tuple[T_co, ...]: ...
216+
def __rmul__(self, value: int, /) -> Tuple[T_co, ...]: ...
215217

216218
class function: pass
217219

@@ -225,6 +227,7 @@ def __setitem__(self, i: int, o: _T) -> None: pass
225227
def __delitem__(self, i: int) -> None: pass
226228
def __mul__(self, i: int) -> List[_T]: pass
227229
def __rmul__(self, i: int) -> List[_T]: pass
230+
def __imul__(self, i: int) -> List[_T]: ...
228231
def __iter__(self) -> Iterator[_T]: pass
229232
def __len__(self) -> int: pass
230233
def __contains__(self, item: object) -> int: ...

mypyc/test-data/irbuild-lists.test

+12
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@ L0:
194194
b = r4
195195
return 1
196196

197+
[case testListIMultiply]
198+
from typing import List
199+
def f(a: List[int]) -> None:
200+
a *= 2
201+
[out]
202+
def f(a):
203+
a, r0 :: list
204+
L0:
205+
r0 = CPySequence_InPlaceMultiply(a, 4)
206+
a = r0
207+
return 1
208+
197209
[case testListLen]
198210
from typing import List
199211
def f(a: List[int]) -> int:

mypyc/test-data/irbuild-tuple.test

+35
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,38 @@ L0:
418418
r3 = unbox(tuple[int, int, int, int], r2)
419419
c = r3
420420
return 1
421+
422+
[case testTupleMultiply]
423+
from typing import Tuple
424+
def f(a: Tuple[int]) -> None:
425+
b = a * 2
426+
c = 3 * (2,)
427+
def g(a: Tuple[int, ...]) -> None:
428+
b = a * 2
429+
[out]
430+
def f(a):
431+
a :: tuple[int]
432+
r0 :: object
433+
r1 :: tuple
434+
r2, b :: tuple[int, int]
435+
r3 :: tuple[int]
436+
r4 :: object
437+
r5 :: tuple
438+
r6, c :: tuple[int, int, int]
439+
L0:
440+
r0 = box(tuple[int], a)
441+
r1 = CPySequence_Multiply(r0, 4)
442+
r2 = unbox(tuple[int, int], r1)
443+
b = r2
444+
r3 = (4)
445+
r4 = box(tuple[int], r3)
446+
r5 = CPySequence_RMultiply(6, r4)
447+
r6 = unbox(tuple[int, int, int], r5)
448+
c = r6
449+
return 1
450+
def g(a):
451+
a, r0, b :: tuple
452+
L0:
453+
r0 = CPySequence_Multiply(a, 4)
454+
b = r0
455+
return 1

mypyc/test-data/run-lists.test

+7
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,13 @@ def test_add() -> None:
313313
assert in_place_add({3: "", 4: ""}) == res
314314
assert in_place_add(range(3, 5)) == res
315315

316+
def test_multiply() -> None:
317+
l1 = [1]
318+
assert l1 * 3 == [1, 1, 1]
319+
assert 3 * l1 == [1, 1, 1]
320+
l1 *= 3
321+
assert l1 == [1, 1, 1]
322+
316323
[case testOperatorInExpression]
317324

318325
def tuple_in_int0(i: int) -> bool:

mypyc/test-data/run-tuples.test

+9
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,12 @@ def test_add() -> None:
269269
assert (1, 2) + (3, 4) == res
270270
with assertRaises(TypeError, 'can only concatenate tuple (not "list") to tuple'):
271271
assert (1, 2) + cast(Any, [3, 4]) == res
272+
273+
def multiply(a: Tuple[Any, ...], b: int) -> Tuple[Any, ...]:
274+
return a * b
275+
276+
def test_multiply() -> None:
277+
res = (1, 1, 1)
278+
assert (1,) * 3 == res
279+
assert 3 * (1,) == res
280+
assert multiply((1,), 3) == res

0 commit comments

Comments
 (0)