Skip to content

Commit 5ef8220

Browse files
Merge pull request RustPython#751 from RustPython/scope_holds_dictionaries
Change types inside Scope to PyDictRef.
2 parents e68eb9c + 4a5592d commit 5ef8220

File tree

6 files changed

+59
-71
lines changed

6 files changed

+59
-71
lines changed

vm/src/builtins.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use num_traits::{Signed, ToPrimitive};
1111
use crate::compile;
1212
use crate::import::import_module;
1313
use crate::obj::objbool;
14+
use crate::obj::objdict::PyDictRef;
1415
use crate::obj::objint;
1516
use crate::obj::objiter;
1617
use crate::obj::objstr::{self, PyStringRef};
@@ -27,14 +28,6 @@ use crate::obj::objcode::PyCodeRef;
2728
#[cfg(not(target_arch = "wasm32"))]
2829
use crate::stdlib::io::io_open;
2930

30-
fn get_locals(vm: &VirtualMachine) -> PyObjectRef {
31-
vm.get_locals()
32-
}
33-
34-
fn dir_locals(vm: &VirtualMachine) -> PyObjectRef {
35-
get_locals(vm)
36-
}
37-
3831
fn builtin_abs(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
3932
arg_check!(vm, args, required = [(x, None)]);
4033
match vm.get_method(x.clone(), "__abs__") {
@@ -146,7 +139,7 @@ fn builtin_delattr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
146139

147140
fn builtin_dir(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
148141
if args.args.is_empty() {
149-
Ok(dir_locals(vm))
142+
Ok(vm.get_locals().into_object())
150143
} else {
151144
let obj = args.args.into_iter().next().unwrap();
152145
let seq = vm.call_method(&obj, "__dir__", vec![])?;
@@ -254,11 +247,11 @@ fn make_scope(
254247

255248
let current_scope = vm.current_scope();
256249
let globals = match globals {
257-
Some(dict) => dict.clone(),
250+
Some(dict) => dict.clone().downcast().unwrap(),
258251
None => current_scope.globals.clone(),
259252
};
260253
let locals = match locals {
261-
Some(dict) => Some(dict.clone()),
254+
Some(dict) => dict.clone().downcast().ok(),
262255
None => current_scope.get_only_locals(),
263256
};
264257

@@ -300,7 +293,7 @@ fn builtin_getattr(
300293
}
301294
}
302295

303-
fn builtin_globals(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult {
296+
fn builtin_globals(vm: &VirtualMachine) -> PyResult<PyDictRef> {
304297
Ok(vm.current_scope().globals.clone())
305298
}
306299

@@ -374,9 +367,8 @@ fn builtin_len(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
374367
}
375368
}
376369

377-
fn builtin_locals(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
378-
arg_check!(vm, args);
379-
Ok(vm.get_locals())
370+
fn builtin_locals(vm: &VirtualMachine) -> PyDictRef {
371+
vm.get_locals()
380372
}
381373

382374
fn builtin_max(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -814,13 +806,15 @@ pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResu
814806
let prepare = vm.get_attribute(metaclass.clone().into_object(), "__prepare__")?;
815807
let namespace = vm.invoke(prepare, vec![name_arg.clone(), bases.clone()])?;
816808

809+
let namespace: PyDictRef = TryFromObject::try_from_object(vm, namespace)?;
810+
817811
let cells = vm.ctx.new_dict();
818812

819-
vm.invoke_with_locals(function, cells.clone().into_object(), namespace.clone())?;
813+
vm.invoke_with_locals(function, cells.clone(), namespace.clone())?;
820814
let class = vm.call_method(
821815
metaclass.as_object(),
822816
"__call__",
823-
vec![name_arg, bases, namespace],
817+
vec![name_arg, bases, namespace.into_object()],
824818
)?;
825819
cells.set_item(&vm.ctx, "__class__", class.clone());
826820
Ok(class)

vm/src/frame.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ use crate::function::PyFuncArgs;
1212
use crate::obj::objbool;
1313
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
1414
use crate::obj::objcode::PyCodeRef;
15-
use crate::obj::objdict;
16-
use crate::obj::objdict::PyDict;
15+
use crate::obj::objdict::{self, PyDictRef};
1716
use crate::obj::objint::PyInt;
1817
use crate::obj::objiter;
1918
use crate::obj::objlist;
@@ -80,8 +79,8 @@ impl<'a, T> Iterator for Iter<'a, T> {
8079

8180
#[derive(Clone)]
8281
pub struct Scope {
83-
locals: RcList<PyObjectRef>,
84-
pub globals: PyObjectRef,
82+
locals: RcList<PyDictRef>,
83+
pub globals: PyDictRef,
8584
}
8685

8786
impl fmt::Debug for Scope {
@@ -92,34 +91,34 @@ impl fmt::Debug for Scope {
9291
}
9392

9493
impl Scope {
95-
pub fn new(locals: Option<PyObjectRef>, globals: PyObjectRef) -> Scope {
94+
pub fn new(locals: Option<PyDictRef>, globals: PyDictRef) -> Scope {
9695
let locals = match locals {
9796
Some(dict) => RcList::new().insert(dict),
9897
None => RcList::new(),
9998
};
10099
Scope { locals, globals }
101100
}
102101

103-
pub fn get_locals(&self) -> PyObjectRef {
102+
pub fn get_locals(&self) -> PyDictRef {
104103
match self.locals.iter().next() {
105104
Some(dict) => dict.clone(),
106105
None => self.globals.clone(),
107106
}
108107
}
109108

110-
pub fn get_only_locals(&self) -> Option<PyObjectRef> {
109+
pub fn get_only_locals(&self) -> Option<PyDictRef> {
111110
self.locals.iter().next().cloned()
112111
}
113112

114-
pub fn child_scope_with_locals(&self, locals: PyObjectRef) -> Scope {
113+
pub fn child_scope_with_locals(&self, locals: PyDictRef) -> Scope {
115114
Scope {
116115
locals: self.locals.clone().insert(locals),
117116
globals: self.globals.clone(),
118117
}
119118
}
120119

121120
pub fn child_scope(&self, ctx: &PyContext) -> Scope {
122-
self.child_scope_with_locals(ctx.new_dict().into_object())
121+
self.child_scope_with_locals(ctx.new_dict())
123122
}
124123
}
125124

@@ -1232,13 +1231,11 @@ impl fmt::Debug for Frame {
12321231
.iter()
12331232
.map(|elem| format!("\n > {:?}", elem))
12341233
.collect::<String>();
1235-
let local_str = match self.scope.get_locals().payload::<PyDict>() {
1236-
Some(dict) => objdict::get_key_value_pairs_from_content(&dict.entries.borrow())
1237-
.iter()
1238-
.map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1))
1239-
.collect::<String>(),
1240-
None => panic!("locals unexpectedly not wrapping a dict!",),
1241-
};
1234+
let dict = self.scope.get_locals();
1235+
let local_str = objdict::get_key_value_pairs_from_content(&dict.entries.borrow())
1236+
.iter()
1237+
.map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1))
1238+
.collect::<String>();
12421239
write!(
12431240
f,
12441241
"Frame Object {{ \n Stack:{}\n Blocks:{}\n Locals:{}\n}}",

vm/src/import.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fn import_uncached_module(vm: &VirtualMachine, current_path: PathBuf, module: &s
4040

4141
let attrs = vm.ctx.new_dict();
4242
attrs.set_item(&vm.ctx, "__name__", vm.new_str(module.to_string()));
43-
vm.run_code_obj(code_obj, Scope::new(None, attrs.clone().into_object()))?;
43+
vm.run_code_obj(code_obj, Scope::new(None, attrs.clone()))?;
4444
Ok(vm.ctx.new_module(module, attrs))
4545
}
4646

vm/src/obj/objframe.rs

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,35 @@
22
33
*/
44

5-
use crate::frame::Frame;
6-
use crate::function::PyFuncArgs;
7-
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
5+
use super::objcode::PyCodeRef;
6+
use super::objdict::PyDictRef;
7+
use crate::frame::FrameRef;
8+
use crate::pyobject::{PyContext, PyResult};
89
use crate::vm::VirtualMachine;
910

1011
pub fn init(context: &PyContext) {
11-
let frame_type = &context.frame_type;
12-
extend_class!(context, frame_type, {
13-
"__new__" => context.new_rustfunc(frame_new),
14-
"__repr__" => context.new_rustfunc(frame_repr),
15-
"f_locals" => context.new_property(frame_flocals),
16-
"f_code" => context.new_property(frame_fcode)
12+
extend_class!(context, &context.frame_type, {
13+
"__new__" => context.new_rustfunc(FrameRef::new),
14+
"__repr__" => context.new_rustfunc(FrameRef::repr),
15+
"f_locals" => context.new_property(FrameRef::flocals),
16+
"f_code" => context.new_property(FrameRef::fcode),
1717
});
1818
}
1919

20-
fn frame_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
21-
arg_check!(vm, args, required = [(_cls, None)]);
22-
Err(vm.new_type_error("Cannot directly create frame object".to_string()))
23-
}
20+
impl FrameRef {
21+
fn new(_class: FrameRef, vm: &VirtualMachine) -> PyResult {
22+
Err(vm.new_type_error("Cannot directly create frame object".to_string()))
23+
}
2424

25-
fn frame_repr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
26-
arg_check!(vm, args, required = [(_frame, Some(vm.ctx.frame_type()))]);
27-
let repr = "<frame object at .. >".to_string();
28-
Ok(vm.new_str(repr))
29-
}
25+
fn repr(self, _vm: &VirtualMachine) -> String {
26+
"<frame object at .. >".to_string()
27+
}
3028

31-
fn frame_flocals(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
32-
arg_check!(vm, args, required = [(frame, Some(vm.ctx.frame_type()))]);
33-
let frame = get_value(frame);
34-
Ok(frame.scope.get_locals().clone())
35-
}
36-
37-
fn frame_fcode(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
38-
arg_check!(vm, args, required = [(frame, Some(vm.ctx.frame_type()))]);
39-
Ok(vm.ctx.new_code_object(get_value(frame).code.clone()))
40-
}
29+
fn flocals(self, _vm: &VirtualMachine) -> PyDictRef {
30+
self.scope.get_locals()
31+
}
4132

42-
pub fn get_value(obj: &PyObjectRef) -> &Frame {
43-
&obj.payload::<Frame>().unwrap()
33+
fn fcode(self, vm: &VirtualMachine) -> PyCodeRef {
34+
vm.ctx.new_code_object(self.code.clone())
35+
}
4436
}

vm/src/pyobject.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ impl PyContext {
582582
}
583583

584584
pub fn new_scope(&self) -> Scope {
585-
Scope::new(None, self.new_dict().into_object())
585+
Scope::new(None, self.new_dict())
586586
}
587587

588588
pub fn new_module(&self, name: &str, dict: PyDictRef) -> PyObjectRef {
@@ -613,8 +613,10 @@ impl PyContext {
613613
PropertyBuilder::new(self).add_getter(f).create()
614614
}
615615

616-
pub fn new_code_object(&self, code: bytecode::CodeObject) -> PyObjectRef {
616+
pub fn new_code_object(&self, code: bytecode::CodeObject) -> PyCodeRef {
617617
PyObject::new(objcode::PyCode::new(code), self.code_type(), None)
618+
.downcast()
619+
.unwrap()
618620
}
619621

620622
pub fn new_function(
@@ -683,7 +685,9 @@ impl PyContext {
683685
bytecode::Constant::String { ref value } => self.new_str(value.clone()),
684686
bytecode::Constant::Bytes { ref value } => self.new_bytes(value.clone()),
685687
bytecode::Constant::Boolean { ref value } => self.new_bool(value.clone()),
686-
bytecode::Constant::Code { ref code } => self.new_code_object(*code.clone()),
688+
bytecode::Constant::Code { ref code } => {
689+
self.new_code_object(*code.clone()).into_object()
690+
}
687691
bytecode::Constant::Tuple { ref elements } => {
688692
let elements = elements
689693
.iter()

vm/src/vm.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::function::PyFuncArgs;
1919
use crate::obj::objbool;
2020
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
2121
use crate::obj::objcode::PyCodeRef;
22+
use crate::obj::objdict::PyDictRef;
2223
use crate::obj::objfunction::{PyFunction, PyMethod};
2324
use crate::obj::objgenerator::PyGeneratorRef;
2425
use crate::obj::objiter;
@@ -231,7 +232,7 @@ impl VirtualMachine {
231232
self.ctx.object()
232233
}
233234

234-
pub fn get_locals(&self) -> PyObjectRef {
235+
pub fn get_locals(&self) -> PyDictRef {
235236
self.current_scope().get_locals().clone()
236237
}
237238

@@ -371,8 +372,8 @@ impl VirtualMachine {
371372
pub fn invoke_with_locals(
372373
&self,
373374
function: PyObjectRef,
374-
cells: PyObjectRef,
375-
locals: PyObjectRef,
375+
cells: PyDictRef,
376+
locals: PyDictRef,
376377
) -> PyResult {
377378
if let Some(PyFunction {
378379
code,
@@ -395,7 +396,7 @@ impl VirtualMachine {
395396
fn fill_locals_from_args(
396397
&self,
397398
code_object: &bytecode::CodeObject,
398-
locals: &PyObjectRef,
399+
locals: &PyDictRef,
399400
args: PyFuncArgs,
400401
defaults: &PyObjectRef,
401402
) -> PyResult<()> {

0 commit comments

Comments
 (0)