Skip to content

Commit 1bcbb28

Browse files
Convert list and tuple to Any payload
1 parent 3495b04 commit 1bcbb28

File tree

7 files changed

+137
-77
lines changed

7 files changed

+137
-77
lines changed

vm/src/obj/objbool.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use num_traits::Zero;
22

3-
use crate::pyobject::{
4-
IntoPyObject, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
5-
};
3+
use crate::pyobject::{IntoPyObject, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
64
use crate::vm::VirtualMachine;
75

86
use super::objdict::PyDict;
97
use super::objfloat::PyFloat;
108
use super::objint::PyInt;
9+
use super::objlist::PyList;
1110
use super::objstr::PyString;
11+
use super::objtuple::PyTuple;
1212
use super::objtype;
1313

1414
impl IntoPyObject for bool {
@@ -30,21 +30,22 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
3030
if let Some(i) = obj.payload::<PyInt>() {
3131
return Ok(!i.value.is_zero());
3232
}
33-
let result = match obj.payload {
34-
PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(),
35-
_ => {
36-
if let Ok(f) = vm.get_method(obj.clone(), "__bool__") {
37-
let bool_res = vm.invoke(f, PyFuncArgs::default())?;
38-
match bool_res.payload::<PyInt>() {
39-
Some(i) => !i.value.is_zero(),
40-
None => return Err(vm.new_type_error(String::from("TypeError"))),
41-
}
42-
} else {
43-
true
44-
}
33+
if let Some(list) = obj.payload::<PyList>() {
34+
return Ok(!list.elements.borrow().is_empty());
35+
}
36+
if let Some(tuple) = obj.payload::<PyTuple>() {
37+
return Ok(!tuple.elements.borrow().is_empty());
38+
}
39+
40+
Ok(if let Ok(f) = vm.get_method(obj.clone(), "__bool__") {
41+
let bool_res = vm.invoke(f, PyFuncArgs::default())?;
42+
match bool_res.payload::<PyInt>() {
43+
Some(i) => !i.value.is_zero(),
44+
None => return Err(vm.new_type_error(String::from("TypeError"))),
4545
}
46-
};
47-
Ok(result)
46+
} else {
47+
true
48+
})
4849
}
4950

5051
pub fn init(context: &PyContext) {

vm/src/obj/objiter.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use super::objbool;
1111
use super::objbytearray::PyByteArray;
1212
use super::objbytes::PyBytes;
1313
use super::objrange::PyRange;
14+
use super::objsequence;
1415
use super::objtype;
1516

1617
/*
@@ -156,19 +157,13 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
156157
Err(new_stop_iteration(vm))
157158
}
158159
} else {
159-
match iterated_obj_ref.payload {
160-
PyObjectPayload::Sequence { ref elements } => {
161-
if position.get() < elements.borrow().len() {
162-
let obj_ref = elements.borrow()[position.get()].clone();
163-
position.set(position.get() + 1);
164-
Ok(obj_ref)
165-
} else {
166-
Err(new_stop_iteration(vm))
167-
}
168-
}
169-
_ => {
170-
panic!("NOT IMPL");
171-
}
160+
let elements = objsequence::get_elements(iterated_obj_ref);
161+
if position.get() < elements.len() {
162+
let obj_ref = elements[position.get()].clone();
163+
position.set(position.get() + 1);
164+
Ok(obj_ref)
165+
} else {
166+
Err(new_stop_iteration(vm))
172167
}
173168
}
174169
} else {

vm/src/obj/objlist.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,32 @@ use super::objsequence::{
99
use super::objstr;
1010
use super::objtype;
1111
use crate::pyobject::{
12-
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
13-
TypeProtocol,
12+
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef,
13+
PyResult, TypeProtocol,
1414
};
1515
use crate::vm::{ReprGuard, VirtualMachine};
1616
use num_traits::ToPrimitive;
1717

18+
#[derive(Debug, Default)]
19+
pub struct PyList {
20+
// TODO: shouldn't be public
21+
pub elements: RefCell<Vec<PyObjectRef>>,
22+
}
23+
24+
impl From<Vec<PyObjectRef>> for PyList {
25+
fn from(elements: Vec<PyObjectRef>) -> Self {
26+
PyList {
27+
elements: RefCell::new(elements),
28+
}
29+
}
30+
}
31+
32+
impl PyObjectPayload2 for PyList {
33+
fn required_type(ctx: &PyContext) -> PyObjectRef {
34+
ctx.list_type()
35+
}
36+
}
37+
1838
// set_item:
1939
fn set_item(
2040
vm: &mut VirtualMachine,
@@ -57,8 +77,8 @@ fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
5777
};
5878

5979
Ok(PyObject::new(
60-
PyObjectPayload::Sequence {
61-
elements: RefCell::new(elements),
80+
PyObjectPayload::AnyRustValue {
81+
value: Box::new(PyList::from(elements)),
6282
},
6383
cls.clone(),
6484
))

vm/src/obj/objsequence.rs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ use std::cell::RefCell;
22
use std::marker::Sized;
33
use std::ops::{Deref, DerefMut, Range};
44

5-
use super::objbool;
6-
use super::objint::{self, PyInt};
7-
use crate::pyobject::{IdProtocol, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol};
8-
use crate::vm::VirtualMachine;
95
use num_bigint::BigInt;
106
use num_traits::{One, Signed, ToPrimitive, Zero};
117

8+
use crate::pyobject::{IdProtocol, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol};
9+
use crate::vm::VirtualMachine;
10+
11+
use super::objbool;
12+
use super::objint::{self, PyInt};
13+
use super::objlist::PyList;
14+
use super::objtuple::PyTuple;
15+
1216
pub trait PySliceableSequence {
1317
fn do_slice(&self, range: Range<usize>) -> Self;
1418
fn do_slice_reverse(&self, range: Range<usize>) -> Self;
@@ -156,16 +160,27 @@ pub fn get_item(
156160
}
157161
};
158162
}
163+
159164
match &subscript.payload {
160-
PyObjectPayload::Slice { .. } => Ok(PyObject::new(
161-
match &sequence.payload {
162-
PyObjectPayload::Sequence { .. } => PyObjectPayload::Sequence {
163-
elements: RefCell::new(elements.to_vec().get_slice_items(vm, &subscript)?),
164-
},
165-
ref payload => panic!("sequence get_item called for non-sequence: {:?}", payload),
166-
},
167-
sequence.typ(),
168-
)),
165+
PyObjectPayload::Slice { .. } => {
166+
let payload = if sequence.payload::<PyList>().is_some() {
167+
PyObjectPayload::AnyRustValue {
168+
value: Box::new(PyList::from(
169+
elements.to_vec().get_slice_items(vm, &subscript)?,
170+
)),
171+
}
172+
} else if sequence.payload::<PyTuple>().is_some() {
173+
PyObjectPayload::AnyRustValue {
174+
value: Box::new(PyTuple::from(
175+
elements.to_vec().get_slice_items(vm, &subscript)?,
176+
)),
177+
}
178+
} else {
179+
panic!("sequence get_item called for non-sequence")
180+
};
181+
182+
Ok(PyObject::new(payload, sequence.typ()))
183+
}
169184
_ => Err(vm.new_type_error(format!(
170185
"TypeError: indexing type {:?} with index {:?} is not supported (yet?)",
171186
sequence, subscript
@@ -304,27 +319,31 @@ pub fn seq_mul(elements: &[PyObjectRef], product: &PyObjectRef) -> Vec<PyObjectR
304319
}
305320

306321
pub fn get_elements_cell<'a>(obj: &'a PyObjectRef) -> &'a RefCell<Vec<PyObjectRef>> {
307-
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
308-
elements
309-
} else {
310-
panic!("Cannot extract elements from non-sequence");
322+
if let Some(list) = obj.payload::<PyList>() {
323+
return &list.elements;
311324
}
325+
if let Some(tuple) = obj.payload::<PyTuple>() {
326+
return &tuple.elements;
327+
}
328+
panic!("Cannot extract elements from non-sequence");
312329
}
313330

314331
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
315-
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
316-
elements.borrow()
317-
} else {
318-
panic!("Cannot extract elements from non-sequence");
332+
if let Some(list) = obj.payload::<PyList>() {
333+
return list.elements.borrow();
334+
}
335+
if let Some(tuple) = obj.payload::<PyTuple>() {
336+
return tuple.elements.borrow();
319337
}
338+
panic!("Cannot extract elements from non-sequence");
320339
}
321340

322341
pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<PyObjectRef>> + 'a {
323-
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
324-
elements.borrow_mut()
325-
} else {
326-
panic!("Cannot extract list elements from non-sequence");
327-
// TODO: raise proper error?
328-
// Err(vm.new_type_error("list.append is called with no list".to_string()))
342+
if let Some(list) = obj.payload::<PyList>() {
343+
return list.elements.borrow_mut();
344+
}
345+
if let Some(tuple) = obj.payload::<PyTuple>() {
346+
return tuple.elements.borrow_mut();
329347
}
348+
panic!("Cannot extract elements from non-sequence");
330349
}

vm/src/obj/objtuple.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,40 @@
11
use std::cell::{Cell, RefCell};
22
use std::hash::{Hash, Hasher};
33

4+
use crate::pyobject::{
5+
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
6+
TypeProtocol,
7+
};
8+
use crate::vm::{ReprGuard, VirtualMachine};
9+
410
use super::objbool;
511
use super::objint;
612
use super::objsequence::{
713
get_elements, get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul,
814
};
915
use super::objstr;
1016
use super::objtype;
11-
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
12-
use crate::vm::{ReprGuard, VirtualMachine};
17+
18+
#[derive(Debug, Default)]
19+
pub struct PyTuple {
20+
// TODO: shouldn't be public
21+
// TODO: tuples are immutable, remove this RefCell
22+
pub elements: RefCell<Vec<PyObjectRef>>,
23+
}
24+
25+
impl From<Vec<PyObjectRef>> for PyTuple {
26+
fn from(elements: Vec<PyObjectRef>) -> Self {
27+
PyTuple {
28+
elements: RefCell::new(elements),
29+
}
30+
}
31+
}
32+
33+
impl PyObjectPayload2 for PyTuple {
34+
fn required_type(ctx: &PyContext) -> PyObjectRef {
35+
ctx.tuple_type()
36+
}
37+
}
1338

1439
fn tuple_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
1540
arg_check!(
@@ -185,8 +210,8 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
185210
};
186211

187212
Ok(PyObject::new(
188-
PyObjectPayload::Sequence {
189-
elements: RefCell::new(elements),
213+
PyObjectPayload::AnyRustValue {
214+
value: Box::new(PyTuple::from(elements)),
190215
},
191216
cls.clone(),
192217
))

vm/src/pyobject.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::obj::objfunction;
2828
use crate::obj::objgenerator;
2929
use crate::obj::objint::{self, PyInt};
3030
use crate::obj::objiter;
31-
use crate::obj::objlist;
31+
use crate::obj::objlist::{self, PyList};
3232
use crate::obj::objmap;
3333
use crate::obj::objmemory;
3434
use crate::obj::objmodule;
@@ -40,7 +40,7 @@ use crate::obj::objset::{self, PySet};
4040
use crate::obj::objslice;
4141
use crate::obj::objstr;
4242
use crate::obj::objsuper;
43-
use crate::obj::objtuple;
43+
use crate::obj::objtuple::{self, PyTuple};
4444
use crate::obj::objtype;
4545
use crate::obj::objzip;
4646
use crate::vm::VirtualMachine;
@@ -549,17 +549,17 @@ impl PyContext {
549549

550550
pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
551551
PyObject::new(
552-
PyObjectPayload::Sequence {
553-
elements: RefCell::new(elements),
552+
PyObjectPayload::AnyRustValue {
553+
value: Box::new(PyTuple::from(elements)),
554554
},
555555
self.tuple_type(),
556556
)
557557
}
558558

559559
pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
560560
PyObject::new(
561-
PyObjectPayload::Sequence {
562-
elements: RefCell::new(elements),
561+
PyObjectPayload::AnyRustValue {
562+
value: Box::new(PyList::from(elements)),
563563
},
564564
self.list_type(),
565565
)
@@ -1467,9 +1467,6 @@ into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E));
14671467
/// of rust data for a particular python object. Determine the python type
14681468
/// by using for example the `.typ()` method on a python object.
14691469
pub enum PyObjectPayload {
1470-
Sequence {
1471-
elements: RefCell<Vec<PyObjectRef>>,
1472-
},
14731470
Iterator {
14741471
position: Cell<usize>,
14751472
iterated_obj: PyObjectRef,
@@ -1542,7 +1539,6 @@ impl fmt::Debug for PyObjectPayload {
15421539
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15431540
match self {
15441541
PyObjectPayload::MemoryView { ref obj } => write!(f, "bytes/bytearray {:?}", obj),
1545-
PyObjectPayload::Sequence { .. } => write!(f, "list or tuple"),
15461542
PyObjectPayload::WeakRef { .. } => write!(f, "weakref"),
15471543
PyObjectPayload::Iterator { .. } => write!(f, "iterator"),
15481544
PyObjectPayload::EnumerateIterator { .. } => write!(f, "enumerate"),

vm/src/vm.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ use crate::obj::objcode;
2020
use crate::obj::objframe;
2121
use crate::obj::objgenerator;
2222
use crate::obj::objiter;
23+
use crate::obj::objlist::PyList;
2324
use crate::obj::objsequence;
2425
use crate::obj::objstr;
26+
use crate::obj::objtuple::PyTuple;
2527
use crate::obj::objtype;
2628
use crate::pyobject::{
2729
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload,
@@ -446,8 +448,10 @@ impl VirtualMachine {
446448
if nargs < nexpected_args {
447449
let available_defaults = if defaults.is(&self.get_none()) {
448450
vec![]
449-
} else if let PyObjectPayload::Sequence { ref elements } = defaults.payload {
450-
elements.borrow().clone()
451+
} else if let Some(list) = defaults.payload::<PyList>() {
452+
list.elements.borrow().clone()
453+
} else if let Some(tuple) = defaults.payload::<PyTuple>() {
454+
tuple.elements.borrow().clone()
451455
} else {
452456
panic!("function defaults not tuple or None");
453457
};

0 commit comments

Comments
 (0)