Skip to content

Commit d9cd236

Browse files
author
Daniel Watkins
committed
Unify string and sequence slicing operations
1 parent 4227a7c commit d9cd236

2 files changed

Lines changed: 34 additions & 32 deletions

File tree

vm/src/objsequence.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,28 @@ pub fn get_pos(sequence_length: usize, p: i32) -> usize {
1313
}
1414
}
1515

16-
fn get_slice_items(l: &Vec<PyObjectRef>, slice: &PyObjectRef) -> Vec<PyObjectRef> {
16+
pub trait PySliceableSequence {
17+
fn do_slice(&self, start: usize, stop: usize) -> Self;
18+
fn do_stepped_slice(&self, start: usize, stop: usize, step: usize) -> Self;
19+
fn len(&self) -> usize;
20+
}
21+
22+
impl PySliceableSequence for Vec<PyObjectRef> {
23+
fn do_slice(&self, start: usize, stop: usize) -> Self {
24+
self[start..stop].to_vec()
25+
}
26+
fn do_stepped_slice(&self, start: usize, stop: usize, step: usize) -> Self {
27+
self[start..stop].iter().step_by(step).cloned().collect()
28+
}
29+
fn len(&self) -> usize {
30+
self.len()
31+
}
32+
}
33+
34+
pub fn get_slice_items<S>(l: &S, slice: &PyObjectRef) -> S
35+
where
36+
S: PySliceableSequence,
37+
{
1738
// TODO: we could potentially avoid this copy and use slice
1839
match &(slice.borrow()).kind {
1940
PyObjectKind::Slice { start, stop, step } => {
@@ -26,16 +47,12 @@ fn get_slice_items(l: &Vec<PyObjectRef>, slice: &PyObjectRef) -> Vec<PyObjectRef
2647
&None => l.len() as usize,
2748
};
2849
match step {
29-
&None | &Some(1) => l[start..stop].to_vec(),
50+
&None | &Some(1) => l.do_slice(start, stop),
3051
&Some(num) => {
3152
if num < 0 {
3253
unimplemented!("negative step indexing not yet supported")
3354
};
34-
l[start..stop]
35-
.iter()
36-
.step_by(num as usize)
37-
.cloned()
38-
.collect()
55+
l.do_stepped_slice(start, stop, num as usize)
3956
}
4057
}
4158
}

vm/src/objstr.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,15 @@ use super::objsequence;
22
use super::pyobject::{PyObjectKind, PyObjectRef, PyResult};
33
use super::vm::VirtualMachine;
44

5-
fn get_slice_items(value: &String, slice: &PyObjectRef) -> String {
6-
match &(slice.borrow()).kind {
7-
PyObjectKind::Slice { start, stop, step } => {
8-
let start2: usize = match start {
9-
// &Some(_) => panic!("Bad start index for string slicing {:?}", start),
10-
&Some(start) => objsequence::get_pos(value.len(), start),
11-
&None => 0,
12-
};
13-
let stop2: usize = match stop {
14-
&Some(stop) => objsequence::get_pos(value.len(), stop),
15-
// &Some(_) => panic!("Bad stop index for string slicing"),
16-
&None => value.len() as usize,
17-
};
18-
match step {
19-
&None | &Some(1) => value[start2..stop2].to_string(),
20-
&Some(num) => {
21-
if num < 0 {
22-
unimplemented!("negative step indexing not yet supported")
23-
};
24-
value[start2..stop2].chars().step_by(num as usize).collect()
25-
}
26-
}
27-
}
28-
kind => panic!("get_slice_items called with non-slice: {:?}", kind),
5+
impl objsequence::PySliceableSequence for String {
6+
fn do_slice(&self, start: usize, stop: usize) -> Self {
7+
self[start..stop].to_string()
8+
}
9+
fn do_stepped_slice(&self, start: usize, stop: usize, step: usize) -> Self {
10+
self[start..stop].chars().step_by(step).collect()
11+
}
12+
fn len(&self) -> usize {
13+
self.len()
2914
}
3015
}
3116

@@ -40,7 +25,7 @@ pub fn subscript(vm: &mut VirtualMachine, value: &String, b: PyObjectRef) -> PyR
4025
start: _,
4126
stop: _,
4227
step: _,
43-
} => Ok(vm.new_str(get_slice_items(value, &b))),
28+
} => Ok(vm.new_str(objsequence::get_slice_items(value, &b))),
4429
_ => panic!(
4530
"TypeError: indexing type {:?} with index {:?} is not supported (yet?)",
4631
value, b

0 commit comments

Comments
 (0)