Skip to content

Commit 1033f20

Browse files
authored
Merge pull request RustPython#430 from RustPython/dict5
Change to more usage of VirtualMachine in anticipation of proper dicts
2 parents ca51f2d + b1e07f6 commit 1033f20

File tree

5 files changed

+125
-118
lines changed

5 files changed

+125
-118
lines changed

vm/src/builtins.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn get_locals(vm: &mut VirtualMachine) -> PyObjectRef {
2929
let locals = vm.get_locals();
3030
let key_value_pairs = objdict::get_key_value_pairs(&locals);
3131
for (key, value) in key_value_pairs {
32-
objdict::set_item(&d, &key, &value);
32+
objdict::set_item(&d, vm, &key, &value);
3333
}
3434
d
3535
}
@@ -656,7 +656,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
656656
//set __name__ fixes: https://github.com/RustPython/RustPython/issues/146
657657
ctx.set_attr(&py_mod, "__name__", ctx.new_str(String::from("__main__")));
658658

659-
ctx.set_item(&py_mod, "abs", ctx.new_rustfunc(builtin_abs));
659+
ctx.set_attr(&py_mod, "abs", ctx.new_rustfunc(builtin_abs));
660660
ctx.set_attr(&py_mod, "all", ctx.new_rustfunc(builtin_all));
661661
ctx.set_attr(&py_mod, "any", ctx.new_rustfunc(builtin_any));
662662
ctx.set_attr(&py_mod, "bin", ctx.new_rustfunc(builtin_bin));

vm/src/frame.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,11 @@ impl Frame {
247247
// Take all key-value pairs from the dict:
248248
let dict_elements = objdict::get_key_value_pairs(&obj);
249249
for (key, value) in dict_elements.iter() {
250-
objdict::set_item(&map_obj, key, value);
250+
objdict::set_item(&map_obj, vm, key, value);
251251
}
252252
} else {
253253
let key = self.pop_value();
254-
objdict::set_item(&map_obj, &key, &obj);
254+
objdict::set_item(&map_obj, vm, &key, &obj);
255255
}
256256
}
257257
self.push_value(map_obj);

vm/src/obj/objdict.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = DictCont
4444
})
4545
}
4646

47-
pub fn set_item(dict: &PyObjectRef, needle: &PyObjectRef, value: &PyObjectRef) {
47+
pub fn set_item(
48+
dict: &PyObjectRef,
49+
_vm: &mut VirtualMachine,
50+
needle: &PyObjectRef,
51+
value: &PyObjectRef,
52+
) {
53+
// TODO: use vm to call eventual __hash__ and __eq__methods.
4854
let mut elements = get_mut_elements(dict);
4955
set_item_in_content(&mut elements, needle, value);
5056
}
@@ -121,7 +127,7 @@ fn dict_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
121127
if let Some(dict_obj) = dict_obj {
122128
if objtype::isinstance(&dict_obj, &vm.ctx.dict_type()) {
123129
for (needle, value) in get_key_value_pairs(&dict_obj) {
124-
set_item(&dict, &needle, &value);
130+
set_item(&dict, vm, &needle, &value);
125131
}
126132
} else {
127133
let iter = objiter::get_iter(vm, dict_obj)?;
@@ -139,12 +145,13 @@ fn dict_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
139145
if objiter::get_next_object(vm, &elem_iter)?.is_some() {
140146
return Err(err(vm));
141147
}
142-
set_item(&dict, &needle, &value);
148+
set_item(&dict, vm, &needle, &value);
143149
}
144150
}
145151
}
146152
for (needle, value) in args.kwargs {
147-
set_item(&dict, &vm.new_str(needle), &value);
153+
let py_needle = vm.new_str(needle);
154+
set_item(&dict, vm, &py_needle, &value);
148155
}
149156
Ok(dict)
150157
}
@@ -249,7 +256,7 @@ fn dict_setitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
249256
]
250257
);
251258

252-
set_item(dict, needle, value);
259+
set_item(dict, vm, needle, value);
253260

254261
Ok(vm.get_none())
255262
}

vm/src/stdlib/json.rs

Lines changed: 99 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ use num_traits::cast::ToPrimitive;
1717
// PyObject serialisation via a proxy object which holds a reference to a VM
1818
struct PyObjectSerializer<'s> {
1919
pyobject: &'s PyObjectRef,
20-
ctx: &'s PyContext,
20+
vm: &'s VirtualMachine,
2121
}
2222

2323
impl<'s> PyObjectSerializer<'s> {
2424
fn clone_with_object(&self, pyobject: &'s PyObjectRef) -> PyObjectSerializer {
2525
PyObjectSerializer {
2626
pyobject,
27-
ctx: self.ctx,
27+
vm: self.vm,
2828
}
2929
}
3030
}
@@ -42,23 +42,23 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
4242
}
4343
seq.end()
4444
};
45-
if objtype::isinstance(self.pyobject, &self.ctx.str_type()) {
45+
if objtype::isinstance(self.pyobject, &self.vm.ctx.str_type()) {
4646
serializer.serialize_str(&objstr::get_value(&self.pyobject))
47-
} else if objtype::isinstance(self.pyobject, &self.ctx.float_type()) {
47+
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.float_type()) {
4848
serializer.serialize_f64(objfloat::get_value(self.pyobject))
49-
} else if objtype::isinstance(self.pyobject, &self.ctx.bool_type()) {
49+
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.bool_type()) {
5050
serializer.serialize_bool(objbool::get_value(self.pyobject))
51-
} else if objtype::isinstance(self.pyobject, &self.ctx.int_type()) {
51+
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.int_type()) {
5252
let v = objint::get_value(self.pyobject);
5353
serializer.serialize_i64(v.to_i64().unwrap())
5454
// Although this may seem nice, it does not give the right result:
5555
// v.serialize(serializer)
56-
} else if objtype::isinstance(self.pyobject, &self.ctx.list_type())
57-
|| objtype::isinstance(self.pyobject, &self.ctx.tuple_type())
56+
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.list_type())
57+
|| objtype::isinstance(self.pyobject, &self.vm.ctx.tuple_type())
5858
{
5959
let elements = objsequence::get_elements(self.pyobject);
6060
serialize_seq_elements(serializer, &elements)
61-
} else if objtype::isinstance(self.pyobject, &self.ctx.dict_type()) {
61+
} else if objtype::isinstance(self.pyobject, &self.vm.ctx.dict_type()) {
6262
let pairs = objdict::get_elements(self.pyobject);
6363
let mut map = serializer.serialize_map(Some(pairs.len()))?;
6464
for (key, e) in pairs.iter() {
@@ -80,7 +80,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
8080
// creation
8181
#[derive(Clone)]
8282
struct PyObjectDeserializer<'c> {
83-
ctx: &'c PyContext,
83+
vm: &'c VirtualMachine,
8484
}
8585

8686
impl<'de> serde::de::DeserializeSeed<'de> for PyObjectDeserializer<'de> {
@@ -90,121 +90,121 @@ impl<'de> serde::de::DeserializeSeed<'de> for PyObjectDeserializer<'de> {
9090
where
9191
D: serde::Deserializer<'de>,
9292
{
93-
impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
94-
type Value = PyObjectRef;
93+
deserializer.deserialize_any(self.clone())
94+
}
95+
}
9596

96-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
97-
formatter.write_str("a type that can deserialise in Python")
98-
}
97+
impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
98+
type Value = PyObjectRef;
9999

100-
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
101-
where
102-
E: serde::de::Error,
103-
{
104-
Ok(self.ctx.new_str(value.to_string()))
105-
}
100+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
101+
formatter.write_str("a type that can deserialise in Python")
102+
}
106103

107-
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
108-
where
109-
E: serde::de::Error,
110-
{
111-
Ok(self.ctx.new_str(value))
112-
}
104+
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
105+
where
106+
E: serde::de::Error,
107+
{
108+
Ok(self.vm.ctx.new_str(value.to_string()))
109+
}
113110

114-
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
115-
where
116-
E: serde::de::Error,
117-
{
118-
// The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
119-
// implement those for now
120-
Ok(self.ctx.new_int(value))
121-
}
111+
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
112+
where
113+
E: serde::de::Error,
114+
{
115+
Ok(self.vm.ctx.new_str(value))
116+
}
122117

123-
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
124-
where
125-
E: serde::de::Error,
126-
{
127-
// The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
128-
// implement those for now
129-
Ok(self.ctx.new_int(value))
130-
}
118+
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
119+
where
120+
E: serde::de::Error,
121+
{
122+
// The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
123+
// implement those for now
124+
Ok(self.vm.ctx.new_int(value))
125+
}
131126

132-
fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
133-
where
134-
E: serde::de::Error,
135-
{
136-
Ok(self.ctx.new_float(value))
137-
}
127+
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
128+
where
129+
E: serde::de::Error,
130+
{
131+
// The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
132+
// implement those for now
133+
Ok(self.vm.ctx.new_int(value))
134+
}
138135

139-
fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
140-
where
141-
E: serde::de::Error,
142-
{
143-
Ok(self.ctx.new_bool(value))
144-
}
136+
fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
137+
where
138+
E: serde::de::Error,
139+
{
140+
Ok(self.vm.ctx.new_float(value))
141+
}
145142

146-
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
147-
where
148-
A: serde::de::SeqAccess<'de>,
149-
{
150-
let mut seq = Vec::with_capacity(access.size_hint().unwrap_or(0));
151-
while let Some(value) = access.next_element_seed(self.clone())? {
152-
seq.push(value);
153-
}
154-
Ok(self.ctx.new_list(seq))
155-
}
143+
fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
144+
where
145+
E: serde::de::Error,
146+
{
147+
Ok(self.vm.ctx.new_bool(value))
148+
}
156149

157-
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
158-
where
159-
M: serde::de::MapAccess<'de>,
160-
{
161-
let dict = self.ctx.new_dict();
162-
// TODO: Given keys must be strings, we can probably do something more efficient
163-
// than wrapping the given object up and then unwrapping it to determine whether or
164-
// not it is a string
165-
while let Some((key_obj, value)) =
166-
access.next_entry_seed(self.clone(), self.clone())?
167-
{
168-
let key = match key_obj.borrow().payload {
169-
PyObjectPayload::String { ref value } => value.clone(),
170-
_ => unimplemented!("map keys must be strings"),
171-
};
172-
self.ctx.set_item(&dict, &key, value);
173-
}
174-
Ok(dict)
175-
}
150+
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
151+
where
152+
A: serde::de::SeqAccess<'de>,
153+
{
154+
let mut seq = Vec::with_capacity(access.size_hint().unwrap_or(0));
155+
while let Some(value) = access.next_element_seed(self.clone())? {
156+
seq.push(value);
157+
}
158+
Ok(self.vm.ctx.new_list(seq))
159+
}
176160

177-
fn visit_unit<E>(self) -> Result<Self::Value, E>
178-
where
179-
E: serde::de::Error,
180-
{
181-
Ok(self.ctx.none.clone())
182-
}
161+
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
162+
where
163+
M: serde::de::MapAccess<'de>,
164+
{
165+
let dict = self.vm.ctx.new_dict();
166+
// TODO: Given keys must be strings, we can probably do something more efficient
167+
// than wrapping the given object up and then unwrapping it to determine whether or
168+
// not it is a string
169+
while let Some((key_obj, value)) = access.next_entry_seed(self.clone(), self.clone())? {
170+
let key = match key_obj.borrow().payload {
171+
PyObjectPayload::String { ref value } => value.clone(),
172+
_ => unimplemented!("map keys must be strings"),
173+
};
174+
self.vm.ctx.set_item(&dict, &key, value);
183175
}
176+
Ok(dict)
177+
}
184178

185-
deserializer.deserialize_any(self.clone())
179+
fn visit_unit<E>(self) -> Result<Self::Value, E>
180+
where
181+
E: serde::de::Error,
182+
{
183+
Ok(self.vm.ctx.none.clone())
186184
}
187185
}
188186

189-
fn dumps(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
187+
/// Implement json.dumps
188+
fn json_dumps(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
190189
// TODO: Implement non-trivial serialisation case
191190
arg_check!(vm, args, required = [(obj, None)]);
192191
let res = {
193192
let serializer = PyObjectSerializer {
194193
pyobject: obj,
195-
ctx: &vm.ctx,
194+
vm: vm,
196195
};
197196
serde_json::to_string(&serializer)
198197
};
199198
let string = res.map_err(|err| vm.new_type_error(format!("{}", err)))?;
200199
Ok(vm.context().new_str(string))
201200
}
202201

203-
fn loads(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
202+
/// Implement json.loads
203+
fn json_loads(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
204204
// TODO: Implement non-trivial deserialisation case
205205
arg_check!(vm, args, required = [(string, Some(vm.ctx.str_type()))]);
206206
let res = {
207-
let de = PyObjectDeserializer { ctx: &vm.ctx };
207+
let de = PyObjectDeserializer { vm: vm };
208208
// TODO: Support deserializing string sub-classes
209209
de.deserialize(&mut serde_json::Deserializer::from_str(&objstr::get_value(
210210
&string,
@@ -221,17 +221,17 @@ fn loads(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
221221
.get_item("JSONDecodeError")
222222
.unwrap();
223223
let exc = vm.new_exception(json_decode_error, format!("{}", err));
224-
vm.ctx.set_item(&exc, "lineno", vm.ctx.new_int(err.line()));
225-
vm.ctx.set_item(&exc, "colno", vm.ctx.new_int(err.column()));
224+
vm.ctx.set_attr(&exc, "lineno", vm.ctx.new_int(err.line()));
225+
vm.ctx.set_attr(&exc, "colno", vm.ctx.new_int(err.column()));
226226
exc
227227
})
228228
}
229229

230230
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
231231
let json_mod = ctx.new_module("json", ctx.new_scope(None));
232232

233-
ctx.set_attr(&json_mod, "dumps", ctx.new_rustfunc(dumps));
234-
ctx.set_attr(&json_mod, "loads", ctx.new_rustfunc(loads));
233+
ctx.set_attr(&json_mod, "dumps", ctx.new_rustfunc(json_dumps));
234+
ctx.set_attr(&json_mod, "loads", ctx.new_rustfunc(json_loads));
235235

236236
// TODO: Make this a proper type with a constructor
237237
let json_decode_error = create_type(

vm/src/sysmodule.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,16 @@ settrace() -- set the global debug tracing function
126126

127127
ctx.set_item(&modules, sys_name, sys_mod.clone());
128128

129-
ctx.set_item(&sys_mod, "modules", modules);
130-
ctx.set_item(&sys_mod, "argv", argv(ctx));
131-
ctx.set_item(&sys_mod, "getrefcount", ctx.new_rustfunc(sys_getrefcount));
132-
ctx.set_item(&sys_mod, "getsizeof", ctx.new_rustfunc(sys_getsizeof));
133-
ctx.set_item(&sys_mod, "maxsize", ctx.new_int(std::usize::MAX));
134-
ctx.set_item(&sys_mod, "path", path);
135-
ctx.set_item(&sys_mod, "ps1", ctx.new_str(">>>>> ".to_string()));
136-
ctx.set_item(&sys_mod, "ps2", ctx.new_str("..... ".to_string()));
137-
ctx.set_item(&sys_mod, "__doc__", ctx.new_str(sys_doc.to_string()));
138-
ctx.set_item(&sys_mod, "_getframe", ctx.new_rustfunc(getframe));
129+
ctx.set_attr(&sys_mod, "modules", modules);
130+
ctx.set_attr(&sys_mod, "argv", argv(ctx));
131+
ctx.set_attr(&sys_mod, "getrefcount", ctx.new_rustfunc(sys_getrefcount));
132+
ctx.set_attr(&sys_mod, "getsizeof", ctx.new_rustfunc(sys_getsizeof));
133+
ctx.set_attr(&sys_mod, "maxsize", ctx.new_int(std::usize::MAX));
134+
ctx.set_attr(&sys_mod, "path", path);
135+
ctx.set_attr(&sys_mod, "ps1", ctx.new_str(">>>>> ".to_string()));
136+
ctx.set_attr(&sys_mod, "ps2", ctx.new_str("..... ".to_string()));
137+
ctx.set_attr(&sys_mod, "__doc__", ctx.new_str(sys_doc.to_string()));
138+
ctx.set_attr(&sys_mod, "_getframe", ctx.new_rustfunc(getframe));
139139

140140
sys_mod
141141
}

0 commit comments

Comments
 (0)