Skip to content

Commit 6f61e58

Browse files
Merge pull request RustPython#603 from RustPython/joey/set-dict-payload
Convert set and dict to Any payload
2 parents c5fca1b + 894fa59 commit 6f61e58

File tree

5 files changed

+127
-126
lines changed

5 files changed

+127
-126
lines changed

vm/src/frame.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::import::{import, import_module};
1111
use crate::obj::objbool;
1212
use crate::obj::objcode;
1313
use crate::obj::objdict;
14+
use crate::obj::objdict::PyDict;
1415
use crate::obj::objiter;
1516
use crate::obj::objlist;
1617
use crate::obj::objstr;
@@ -1125,18 +1126,13 @@ impl fmt::Debug for Frame {
11251126
.map(|elem| format!("\n > {:?}", elem))
11261127
.collect::<Vec<_>>()
11271128
.join("");
1128-
let local_str = match self.scope.locals.payload {
1129-
PyObjectPayload::Dict { ref elements } => {
1130-
objdict::get_key_value_pairs_from_content(&elements.borrow())
1131-
.iter()
1132-
.map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1))
1133-
.collect::<Vec<_>>()
1134-
.join("")
1135-
}
1136-
ref unexpected => panic!(
1137-
"locals unexpectedly not wrapping a dict! instead: {:?}",
1138-
unexpected
1139-
),
1129+
let local_str = match self.scope.locals.payload::<PyDict>() {
1130+
Some(dict) => objdict::get_key_value_pairs_from_content(&dict.entries.borrow())
1131+
.iter()
1132+
.map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1))
1133+
.collect::<Vec<_>>()
1134+
.join(""),
1135+
None => panic!("locals unexpectedly not wrapping a dict!",),
11401136
};
11411137
write!(
11421138
f,

vm/src/obj/objbool.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::objdict::PyDict;
12
use super::objfloat::PyFloat;
23
use super::objstr::PyString;
34
use super::objtype;
@@ -20,10 +21,12 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
2021
if let Some(value) = obj.payload::<PyFloat>() {
2122
return Ok(*value != PyFloat::from(0.0));
2223
}
24+
if let Some(dict) = obj.payload::<PyDict>() {
25+
return Ok(!dict.entries.borrow().is_empty());
26+
}
2327
let result = match obj.payload {
2428
PyObjectPayload::Integer { ref value } => !value.is_zero(),
2529
PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(),
26-
PyObjectPayload::Dict { ref elements } => !elements.borrow().is_empty(),
2730
PyObjectPayload::None { .. } => false,
2831
_ => {
2932
if let Ok(f) = vm.get_method(obj.clone(), "__bool__") {

vm/src/obj/objdict.rs

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,31 @@ use super::objiter;
66
use super::objstr;
77
use super::objtype;
88
use crate::pyobject::{
9-
PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
10-
TypeProtocol,
9+
PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef,
10+
PyResult, TypeProtocol,
1111
};
1212
use crate::vm::{ReprGuard, VirtualMachine};
1313

14-
// This typedef abstracts the actual dict type used.
15-
// pub type DictContentType = HashMap<usize, Vec<(PyObjectRef, PyObjectRef)>>;
16-
// pub type DictContentType = HashMap<String, PyObjectRef>;
1714
pub type DictContentType = HashMap<String, (PyObjectRef, PyObjectRef)>;
18-
// pub type DictContentType = HashMap<String, Vec<(PyObjectRef, PyObjectRef)>>;
1915

20-
pub fn new(dict_type: PyObjectRef) -> PyObjectRef {
21-
PyObject::new(
22-
PyObjectPayload::Dict {
23-
elements: RefCell::new(HashMap::new()),
24-
},
25-
dict_type.clone(),
26-
)
16+
#[derive(Default, Debug)]
17+
pub struct PyDict {
18+
// TODO: should be private
19+
pub entries: RefCell<DictContentType>,
2720
}
2821

29-
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = DictContentType> + 'a {
30-
if let PyObjectPayload::Dict { ref elements } = obj.payload {
31-
elements.borrow()
32-
} else {
33-
panic!("Cannot extract dict elements");
22+
impl PyObjectPayload2 for PyDict {
23+
fn required_type(ctx: &PyContext) -> PyObjectRef {
24+
ctx.dict_type()
3425
}
3526
}
3627

28+
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = DictContentType> + 'a {
29+
obj.payload::<PyDict>().unwrap().entries.borrow()
30+
}
31+
3732
fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = DictContentType> + 'a {
38-
if let PyObjectPayload::Dict { ref elements } = obj.payload {
39-
elements.borrow_mut()
40-
} else {
41-
panic!("Cannot extract dict elements");
42-
}
33+
obj.payload::<PyDict>().unwrap().entries.borrow_mut()
4334
}
4435

4536
pub fn set_item(

vm/src/obj/objset.rs

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,26 @@ use super::objiter;
1313
use super::objstr;
1414
use super::objtype;
1515
use crate::pyobject::{
16-
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
16+
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
17+
TypeProtocol,
1718
};
1819
use crate::vm::{ReprGuard, VirtualMachine};
1920

20-
pub fn get_elements(obj: &PyObjectRef) -> HashMap<u64, PyObjectRef> {
21-
if let PyObjectPayload::Set { elements } = &obj.payload {
22-
elements.borrow().clone()
23-
} else {
24-
panic!("Cannot extract set elements from non-set");
21+
#[derive(Debug, Default)]
22+
pub struct PySet {
23+
elements: RefCell<HashMap<u64, PyObjectRef>>,
24+
}
25+
26+
impl PyObjectPayload2 for PySet {
27+
fn required_type(ctx: &PyContext) -> PyObjectRef {
28+
ctx.set_type()
2529
}
2630
}
2731

32+
pub fn get_elements(obj: &PyObjectRef) -> HashMap<u64, PyObjectRef> {
33+
obj.payload::<PySet>().unwrap().elements.borrow().clone()
34+
}
35+
2836
fn perform_action_with_hash(
2937
vm: &mut VirtualMachine,
3038
elements: &mut HashMap<u64, PyObjectRef>,
@@ -62,12 +70,10 @@ fn set_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
6270
arg_check!(
6371
vm,
6472
args,
65-
required = [(s, Some(vm.ctx.set_type())), (item, None)]
73+
required = [(zelf, Some(vm.ctx.set_type())), (item, None)]
6674
);
67-
match s.payload {
68-
PyObjectPayload::Set { ref elements } => {
69-
insert_into_set(vm, &mut elements.borrow_mut(), item)
70-
}
75+
match zelf.payload::<PySet>() {
76+
Some(set) => insert_into_set(vm, &mut set.elements.borrow_mut(), item),
7177
_ => Err(vm.new_type_error("set.add is called with no item".to_string())),
7278
}
7379
}
@@ -79,8 +85,8 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7985
args,
8086
required = [(s, Some(vm.ctx.set_type())), (item, None)]
8187
);
82-
match s.payload {
83-
PyObjectPayload::Set { ref elements } => {
88+
match s.payload::<PySet>() {
89+
Some(set) => {
8490
fn remove(
8591
vm: &mut VirtualMachine,
8692
elements: &mut HashMap<u64, PyObjectRef>,
@@ -95,7 +101,7 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
95101
Some(_) => Ok(vm.get_none()),
96102
}
97103
}
98-
perform_action_with_hash(vm, &mut elements.borrow_mut(), item, &remove)
104+
perform_action_with_hash(vm, &mut set.elements.borrow_mut(), item, &remove)
99105
}
100106
_ => Err(vm.new_type_error("set.remove is called with no item".to_string())),
101107
}
@@ -108,8 +114,8 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
108114
args,
109115
required = [(s, Some(vm.ctx.set_type())), (item, None)]
110116
);
111-
match s.payload {
112-
PyObjectPayload::Set { ref elements } => {
117+
match s.payload::<PySet>() {
118+
Some(set) => {
113119
fn discard(
114120
vm: &mut VirtualMachine,
115121
elements: &mut HashMap<u64, PyObjectRef>,
@@ -119,21 +125,21 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
119125
elements.remove(&key);
120126
Ok(vm.get_none())
121127
}
122-
perform_action_with_hash(vm, &mut elements.borrow_mut(), item, &discard)
128+
perform_action_with_hash(vm, &mut set.elements.borrow_mut(), item, &discard)
123129
}
124-
_ => Err(vm.new_type_error("set.discard is called with no item".to_string())),
130+
None => Err(vm.new_type_error("set.discard is called with no item".to_string())),
125131
}
126132
}
127133

128134
fn set_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
129135
trace!("set.clear called");
130136
arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]);
131-
match s.payload {
132-
PyObjectPayload::Set { ref elements } => {
133-
elements.borrow_mut().clear();
137+
match s.payload::<PySet>() {
138+
Some(set) => {
139+
set.elements.borrow_mut().clear();
134140
Ok(vm.get_none())
135141
}
136-
_ => Err(vm.new_type_error("".to_string())),
142+
None => Err(vm.new_type_error("".to_string())),
137143
}
138144
}
139145

@@ -163,8 +169,10 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
163169
};
164170

165171
Ok(PyObject::new(
166-
PyObjectPayload::Set {
167-
elements: RefCell::new(elements),
172+
PyObjectPayload::AnyRustValue {
173+
value: Box::new(PySet {
174+
elements: RefCell::new(elements),
175+
}),
168176
},
169177
cls.clone(),
170178
))
@@ -182,8 +190,10 @@ fn set_copy(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
182190
arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]);
183191
let elements = get_elements(s);
184192
Ok(PyObject::new(
185-
PyObjectPayload::Set {
186-
elements: RefCell::new(elements),
193+
PyObjectPayload::AnyRustValue {
194+
value: Box::new(PySet {
195+
elements: RefCell::new(elements),
196+
}),
187197
},
188198
vm.ctx.set_type(),
189199
))
@@ -336,8 +346,10 @@ fn set_union(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
336346
elements.extend(get_elements(other).clone());
337347

338348
Ok(PyObject::new(
339-
PyObjectPayload::Set {
340-
elements: RefCell::new(elements),
349+
PyObjectPayload::AnyRustValue {
350+
value: Box::new(PySet {
351+
elements: RefCell::new(elements),
352+
}),
341353
},
342354
vm.ctx.set_type(),
343355
))
@@ -378,8 +390,10 @@ fn set_symmetric_difference(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResu
378390
}
379391

380392
Ok(PyObject::new(
381-
PyObjectPayload::Set {
382-
elements: RefCell::new(elements),
393+
PyObjectPayload::AnyRustValue {
394+
value: Box::new(PySet {
395+
elements: RefCell::new(elements),
396+
}),
383397
},
384398
vm.ctx.set_type(),
385399
))
@@ -418,8 +432,10 @@ fn set_combine_inner(
418432
}
419433

420434
Ok(PyObject::new(
421-
PyObjectPayload::Set {
422-
elements: RefCell::new(elements),
435+
PyObjectPayload::AnyRustValue {
436+
value: Box::new(PySet {
437+
elements: RefCell::new(elements),
438+
}),
423439
},
424440
vm.ctx.set_type(),
425441
))
@@ -428,9 +444,9 @@ fn set_combine_inner(
428444
fn set_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
429445
arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]);
430446

431-
match s.payload {
432-
PyObjectPayload::Set { ref elements } => {
433-
let mut elements = elements.borrow_mut();
447+
match s.payload::<PySet>() {
448+
Some(set) => {
449+
let mut elements = set.elements.borrow_mut();
434450
match elements.clone().keys().next() {
435451
Some(key) => Ok(elements.remove(key).unwrap()),
436452
None => Err(vm.new_key_error("pop from an empty set".to_string())),
@@ -452,11 +468,11 @@ fn set_ior(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
452468
required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)]
453469
);
454470

455-
match zelf.payload {
456-
PyObjectPayload::Set { ref elements } => {
471+
match zelf.payload::<PySet>() {
472+
Some(set) => {
457473
let iterator = objiter::get_iter(vm, iterable)?;
458474
while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) {
459-
insert_into_set(vm, &mut elements.borrow_mut(), &v)?;
475+
insert_into_set(vm, &mut set.elements.borrow_mut(), &v)?;
460476
}
461477
}
462478
_ => return Err(vm.new_type_error("set.update is called with no other".to_string())),
@@ -493,9 +509,9 @@ fn set_combine_update_inner(
493509
required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)]
494510
);
495511

496-
match zelf.payload {
497-
PyObjectPayload::Set { ref elements } => {
498-
let mut elements = elements.borrow_mut();
512+
match zelf.payload::<PySet>() {
513+
Some(set) => {
514+
let mut elements = set.elements.borrow_mut();
499515
for element in elements.clone().iter() {
500516
let value = vm.call_method(iterable, "__contains__", vec![element.1.clone()])?;
501517
let should_remove = match op {
@@ -524,17 +540,17 @@ fn set_ixor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
524540
required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)]
525541
);
526542

527-
match zelf.payload {
528-
PyObjectPayload::Set { ref elements } => {
529-
let elements_original = elements.borrow().clone();
543+
match zelf.payload::<PySet>() {
544+
Some(set) => {
545+
let elements_original = set.elements.borrow().clone();
530546
let iterator = objiter::get_iter(vm, iterable)?;
531547
while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) {
532-
insert_into_set(vm, &mut elements.borrow_mut(), &v)?;
548+
insert_into_set(vm, &mut set.elements.borrow_mut(), &v)?;
533549
}
534550
for element in elements_original.iter() {
535551
let value = vm.call_method(iterable, "__contains__", vec![element.1.clone()])?;
536552
if objbool::get_value(&value) {
537-
elements.borrow_mut().remove(&element.0.clone());
553+
set.elements.borrow_mut().remove(&element.0.clone());
538554
}
539555
}
540556
}

0 commit comments

Comments
 (0)