Skip to content

Commit 38bf2dd

Browse files
Merge pull request RustPython#274 from skinny121/tuple_mul
Add tuple.__mul__
2 parents 37e9f98 + 8f9b733 commit 38bf2dd

File tree

5 files changed

+40
-11
lines changed

5 files changed

+40
-11
lines changed

tests/snippets/list.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
assert y == [2, 1, 2, 3, 1, 2, 3]
1111

1212
assert x * 0 == [], "list __mul__ by 0 failed"
13+
assert x * -1 == [], "list __mul__ by -1 failed"
1314
assert x * 2 == [1, 2, 3, 1, 2, 3], "list __mul__ by 2 failed"
1415

1516
assert ['a', 'b', 'c'].index('b') == 1

tests/snippets/tuple.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,8 @@
55

66
y = (1,)
77
assert y[0] == 1
8+
9+
assert x * 3 == (1, 2, 1, 2, 1, 2)
10+
# assert 3 * x == (1, 2, 1, 2, 1, 2)
11+
assert x * 0 == ()
12+
assert x * -1 == () # integers less than zero treated as 0

vm/src/obj/objlist.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::super::vm::VirtualMachine;
55
use super::objbool;
66
use super::objint;
77
use super::objsequence::{
8-
get_elements, get_item, get_mut_elements, seq_equal, PySliceableSequence,
8+
get_elements, get_item, get_mut_elements, seq_equal, seq_mul, PySliceableSequence,
99
};
1010
use super::objstr;
1111
use super::objtype;
@@ -259,15 +259,7 @@ fn list_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
259259
]
260260
);
261261

262-
let counter = objint::get_value(&product).to_usize().unwrap();
263-
264-
let elements = get_elements(list);
265-
let current_len = elements.len();
266-
let mut new_elements = Vec::with_capacity(counter * current_len);
267-
268-
for _ in 0..counter {
269-
new_elements.extend(elements.clone());
270-
}
262+
let new_elements = seq_mul(&get_elements(list), product);
271263

272264
Ok(vm.ctx.new_list(new_elements))
273265
}

vm/src/obj/objsequence.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::super::pyobject::{PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol};
22
use super::super::vm::VirtualMachine;
33
use super::objbool;
4+
use super::objint;
45
use num_traits::ToPrimitive;
56
use std::cell::{Ref, RefMut};
67
use std::marker::Sized;
@@ -120,6 +121,20 @@ pub fn seq_equal(
120121
}
121122
}
122123

124+
pub fn seq_mul(elements: &Vec<PyObjectRef>, product: &PyObjectRef) -> Vec<PyObjectRef> {
125+
let counter = objint::get_value(&product).to_isize().unwrap();
126+
127+
let current_len = elements.len();
128+
let new_len = counter.max(0) as usize * current_len;
129+
let mut new_elements = Vec::with_capacity(new_len);
130+
131+
for _ in 0..counter {
132+
new_elements.extend(elements.clone());
133+
}
134+
135+
new_elements
136+
}
137+
123138
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
124139
Ref::map(obj.borrow(), |x| {
125140
if let PyObjectPayload::Sequence { ref elements } = x.payload {

vm/src/obj/objtuple.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::super::pyobject::{
44
use super::super::vm::VirtualMachine;
55
use super::objbool;
66
use super::objint;
7-
use super::objsequence::{get_elements, get_item, seq_equal};
7+
use super::objsequence::{get_elements, get_item, seq_equal, seq_mul};
88
use super::objstr;
99
use super::objtype;
1010
use num_bigint::ToBigInt;
@@ -119,6 +119,21 @@ fn tuple_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
119119
Ok(vm.new_str(s))
120120
}
121121

122+
fn tuple_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
123+
arg_check!(
124+
vm,
125+
args,
126+
required = [
127+
(zelf, Some(vm.ctx.tuple_type())),
128+
(product, Some(vm.ctx.int_type()))
129+
]
130+
);
131+
132+
let new_elements = seq_mul(&get_elements(zelf), product);
133+
134+
Ok(vm.ctx.new_tuple(new_elements))
135+
}
136+
122137
fn tuple_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
123138
arg_check!(
124139
vm,
@@ -165,6 +180,7 @@ pub fn init(context: &PyContext) {
165180
context.set_attr(&tuple_type, "__iter__", context.new_rustfunc(tuple_iter));
166181
context.set_attr(&tuple_type, "__len__", context.new_rustfunc(tuple_len));
167182
context.set_attr(&tuple_type, "__new__", context.new_rustfunc(tuple_new));
183+
context.set_attr(&tuple_type, "__mul__", context.new_rustfunc(tuple_mul));
168184
context.set_attr(&tuple_type, "__repr__", context.new_rustfunc(tuple_repr));
169185
context.set_attr(&tuple_type, "count", context.new_rustfunc(tuple_count));
170186
}

0 commit comments

Comments
 (0)