Skip to content

Commit c2e2441

Browse files
committed
Remove Scope variant from PyObject.
1 parent 387c21f commit c2e2441

File tree

11 files changed

+123
-189
lines changed

11 files changed

+123
-189
lines changed

src/main.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustpython_vm::{
1515
import,
1616
obj::objstr,
1717
print_exception,
18-
pyobject::{AttributeProtocol, PyObjectRef, PyResult},
18+
pyobject::{AttributeProtocol, PyResult, ScopeRef},
1919
util, VirtualMachine,
2020
};
2121
use rustyline::{error::ReadlineError, Editor};
@@ -120,11 +120,7 @@ fn run_script(vm: &mut VirtualMachine, script_file: &str) -> PyResult {
120120
}
121121
}
122122

123-
fn shell_exec(
124-
vm: &mut VirtualMachine,
125-
source: &str,
126-
scope: PyObjectRef,
127-
) -> Result<(), CompileError> {
123+
fn shell_exec(vm: &mut VirtualMachine, source: &str, scope: ScopeRef) -> Result<(), CompileError> {
128124
match compile::compile(
129125
source,
130126
&compile::Mode::Single,

vm/src/builtins.rs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! Implements functions listed here: https://docs.python.org/3/library/builtins.html
44
55
// use std::ops::Deref;
6-
use std::cell::RefCell;
76
use std::char;
87
use std::io::{self, Write};
98

@@ -16,9 +15,10 @@ use crate::obj::objstr;
1615
use crate::obj::objtype;
1716

1817
use crate::pyobject::{
19-
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
20-
PyResult, Scope, TypeProtocol,
18+
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, Scope, ScopeRef,
19+
TypeProtocol,
2120
};
21+
use std::rc::Rc;
2222

2323
#[cfg(not(target_arch = "wasm32"))]
2424
use crate::stdlib::io::io_open;
@@ -258,7 +258,7 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
258258
vm.run_code_obj(code_obj, scope)
259259
}
260260

261-
fn make_scope(vm: &mut VirtualMachine, locals: Option<&PyObjectRef>) -> PyObjectRef {
261+
fn make_scope(vm: &mut VirtualMachine, locals: Option<&PyObjectRef>) -> ScopeRef {
262262
// handle optional global and locals
263263
let locals = if let Some(locals) = locals {
264264
locals.clone()
@@ -268,18 +268,10 @@ fn make_scope(vm: &mut VirtualMachine, locals: Option<&PyObjectRef>) -> PyObject
268268

269269
// TODO: handle optional globals
270270
// Construct new scope:
271-
let scope_inner = Scope {
271+
Rc::new(Scope {
272272
locals,
273273
parent: None,
274-
};
275-
276-
PyObject {
277-
payload: PyObjectPayload::Scope {
278-
scope: RefCell::new(scope_inner),
279-
},
280-
typ: None,
281-
}
282-
.into_ref()
274+
})
283275
}
284276

285277
fn builtin_format(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -842,13 +834,7 @@ pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> Py
842834
},
843835
)?;
844836

845-
vm.invoke(
846-
function,
847-
PyFuncArgs {
848-
args: vec![namespace.clone()],
849-
kwargs: vec![],
850-
},
851-
)?;
837+
vm.invoke_with_locals(function, namespace.clone())?;
852838

853839
vm.call_method(&metaclass, "__call__", vec![name_arg, bases, namespace])
854840
}

vm/src/bytecode.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ pub enum Instruction {
159159
},
160160
PrintExpr,
161161
LoadBuildClass,
162-
StoreLocals,
163162
UnpackSequence {
164163
size: usize,
165164
},
@@ -358,7 +357,6 @@ impl Instruction {
358357
MapAdd { i } => w!(MapAdd, i),
359358
PrintExpr => w!(PrintExpr),
360359
LoadBuildClass => w!(LoadBuildClass),
361-
StoreLocals => w!(StoreLocals),
362360
UnpackSequence { size } => w!(UnpackSequence, size),
363361
UnpackEx { before, after } => w!(UnpackEx, before, after),
364362
Unpack => w!(Unpack),

vm/src/compile.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -482,18 +482,14 @@ impl Compiler {
482482
self.emit(Instruction::LoadBuildClass);
483483
let line_number = self.get_source_line_number();
484484
self.code_object_stack.push(CodeObject::new(
485-
vec![String::from("__locals__")],
485+
vec![],
486486
None,
487487
vec![],
488488
None,
489489
self.source_path.clone().unwrap(),
490490
line_number,
491491
name.clone(),
492492
));
493-
self.emit(Instruction::LoadName {
494-
name: String::from("__locals__"),
495-
});
496-
self.emit(Instruction::StoreLocals);
497493
self.compile_statements(body)?;
498494
self.emit(Instruction::LoadConst {
499495
value: bytecode::Constant::None,

vm/src/eval.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,10 @@ extern crate rustpython_parser;
33
use std::error::Error;
44

55
use crate::compile;
6-
use crate::pyobject::{PyObjectRef, PyResult};
6+
use crate::pyobject::{PyResult, ScopeRef};
77
use crate::vm::VirtualMachine;
88

9-
pub fn eval(
10-
vm: &mut VirtualMachine,
11-
source: &str,
12-
scope: PyObjectRef,
13-
source_path: &str,
14-
) -> PyResult {
9+
pub fn eval(vm: &mut VirtualMachine, source: &str, scope: ScopeRef, source_path: &str) -> PyResult {
1510
match compile::compile(
1611
source,
1712
&compile::Mode::Eval,

vm/src/frame.rs

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use crate::obj::objlist;
1616
use crate::obj::objstr;
1717
use crate::obj::objtype;
1818
use crate::pyobject::{
19-
DictProtocol, IdProtocol, ParentProtocol, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
20-
PyResult, TypeProtocol,
19+
DictProtocol, IdProtocol, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
20+
ScopeRef, TypeProtocol,
2121
};
2222
use crate::vm::VirtualMachine;
2323
use num_bigint::BigInt;
@@ -50,7 +50,7 @@ pub struct Frame {
5050
// We need 1 stack per frame
5151
stack: RefCell<Vec<PyObjectRef>>, // The main data frame of the stack machine
5252
blocks: RefCell<Vec<Block>>, // Block frames, for controlling loops and exceptions
53-
pub locals: PyObjectRef, // Variables
53+
pub scope: ScopeRef, // Variables
5454
pub lasti: RefCell<usize>, // index of last instruction ran
5555
}
5656

@@ -64,7 +64,7 @@ pub enum ExecutionResult {
6464
pub type FrameResult = Result<Option<ExecutionResult>, PyObjectRef>;
6565

6666
impl Frame {
67-
pub fn new(code: PyObjectRef, globals: PyObjectRef) -> Frame {
67+
pub fn new(code: PyObjectRef, scope: ScopeRef) -> Frame {
6868
//populate the globals and locals
6969
//TODO: This is wrong, check https://github.com/nedbat/byterun/blob/31e6c4a8212c35b5157919abff43a7daa0f377c6/byterun/pyvm2.py#L95
7070
/*
@@ -73,7 +73,7 @@ impl Frame {
7373
None => HashMap::new(),
7474
};
7575
*/
76-
let locals = globals;
76+
// let locals = globals;
7777
// locals.extend(callargs);
7878

7979
Frame {
@@ -82,7 +82,7 @@ impl Frame {
8282
blocks: RefCell::new(vec![]),
8383
// save the callargs as locals
8484
// globals: locals.clone(),
85-
locals,
85+
scope,
8686
lasti: RefCell::new(0),
8787
}
8888
}
@@ -436,7 +436,7 @@ impl Frame {
436436
};
437437
// pop argc arguments
438438
// argument: name, args, globals
439-
let scope = self.locals.clone();
439+
let scope = self.scope.clone();
440440
let obj = vm.ctx.new_function(code_obj, scope, defaults);
441441
self.push_value(obj);
442442
Ok(None)
@@ -582,16 +582,6 @@ impl Frame {
582582
self.push_value(rustfunc);
583583
Ok(None)
584584
}
585-
bytecode::Instruction::StoreLocals => {
586-
let locals = self.pop_value();
587-
match self.locals.payload {
588-
PyObjectPayload::Scope { ref scope } => {
589-
(*scope.borrow_mut()).locals = locals;
590-
}
591-
_ => panic!("We really expect our scope to be a scope!"),
592-
}
593-
Ok(None)
594-
}
595585
bytecode::Instruction::UnpackSequence { size } => {
596586
let value = self.pop_value();
597587
let elements = vm.extract_elements(&value)?;
@@ -715,8 +705,10 @@ impl Frame {
715705
let obj = import_module(vm, current_path, module)?;
716706

717707
for (k, v) in obj.get_key_value_pairs().iter() {
718-
vm.ctx
719-
.set_attr(&self.locals, &objstr::get_value(k), v.clone());
708+
&self
709+
.scope
710+
.locals
711+
.set_item(&vm.ctx, &objstr::get_value(k), v.clone());
720712
}
721713
Ok(None)
722714
}
@@ -838,37 +830,35 @@ impl Frame {
838830

839831
fn store_name(&self, vm: &mut VirtualMachine, name: &str) -> FrameResult {
840832
let obj = self.pop_value();
841-
vm.ctx.set_attr(&self.locals, name, obj);
833+
self.scope.locals.set_item(&vm.ctx, name, obj);
842834
Ok(None)
843835
}
844836

845837
fn delete_name(&self, vm: &mut VirtualMachine, name: &str) -> FrameResult {
846-
let locals = match self.locals.payload {
847-
PyObjectPayload::Scope { ref scope } => scope.borrow().locals.clone(),
848-
_ => panic!("We really expect our scope to be a scope!"),
849-
};
850-
851-
// Assume here that locals is a dict
852838
let name = vm.ctx.new_str(name.to_string());
853-
vm.call_method(&locals, "__delitem__", vec![name])?;
839+
vm.call_method(&self.scope.locals, "__delitem__", vec![name])?;
854840
Ok(None)
855841
}
856842

857843
fn load_name(&self, vm: &mut VirtualMachine, name: &str) -> FrameResult {
858844
// Lookup name in scope and put it onto the stack!
859-
let mut scope = self.locals.clone();
845+
let mut scope = self.scope.clone();
860846
loop {
861-
if scope.contains_key(name) {
862-
let obj = scope.get_item(name).unwrap();
847+
if scope.locals.contains_key(name) {
848+
let obj = scope.locals.get_item(name).unwrap();
863849
self.push_value(obj);
864-
break Ok(None);
865-
} else if scope.has_parent() {
866-
scope = scope.get_parent();
867-
} else {
868-
let name_error_type = vm.ctx.exceptions.name_error.clone();
869-
let msg = format!("name '{}' is not defined", name);
870-
let name_error = vm.new_exception(name_error_type, msg);
871-
break Err(name_error);
850+
return Ok(None);
851+
}
852+
match &scope.parent {
853+
Some(parent_scope) => {
854+
scope = parent_scope.clone();
855+
}
856+
None => {
857+
let name_error_type = vm.ctx.exceptions.name_error.clone();
858+
let msg = format!("name '{}' is not defined", name);
859+
let name_error = vm.new_exception(name_error_type, msg);
860+
return Err(name_error);
861+
}
872862
}
873863
}
874864
}
@@ -1119,21 +1109,18 @@ impl fmt::Debug for Frame {
11191109
.map(|elem| format!("\n > {:?}", elem))
11201110
.collect::<Vec<_>>()
11211111
.join("");
1122-
let local_str = match self.locals.payload {
1123-
PyObjectPayload::Scope { ref scope } => match scope.borrow().locals.payload {
1124-
PyObjectPayload::Dict { ref elements } => {
1125-
objdict::get_key_value_pairs_from_content(&elements.borrow())
1126-
.iter()
1127-
.map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1))
1128-
.collect::<Vec<_>>()
1129-
.join("")
1130-
}
1131-
ref unexpected => panic!(
1132-
"locals unexpectedly not wrapping a dict! instead: {:?}",
1133-
unexpected
1134-
),
1135-
},
1136-
ref unexpected => panic!("locals unexpectedly not a scope! instead: {:?}", unexpected),
1112+
let local_str = match self.scope.locals.payload {
1113+
PyObjectPayload::Dict { ref elements } => {
1114+
objdict::get_key_value_pairs_from_content(&elements.borrow())
1115+
.iter()
1116+
.map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1))
1117+
.collect::<Vec<_>>()
1118+
.join("")
1119+
}
1120+
ref unexpected => panic!(
1121+
"locals unexpectedly not wrapping a dict! instead: {:?}",
1122+
unexpected
1123+
),
11371124
};
11381125
write!(
11391126
f,

vm/src/import.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ fn import_uncached_module(
4343

4444
let builtins = vm.get_builtin_scope();
4545
let scope = vm.ctx.new_scope(Some(builtins));
46-
vm.ctx
47-
.set_attr(&scope, "__name__", vm.new_str(module.to_string()));
46+
scope
47+
.locals
48+
.set_item(&vm.ctx, "__name__", vm.new_str(module.to_string()));
4849
vm.run_code_obj(code_obj, scope.clone())?;
4950
Ok(vm.ctx.new_module(module, scope))
5051
}

vm/src/obj/objframe.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,7 @@ fn frame_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3030
fn frame_flocals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3131
arg_check!(vm, args, required = [(frame, Some(vm.ctx.frame_type()))]);
3232
let frame = get_value(frame);
33-
let py_scope = frame.locals.clone();
34-
35-
if let PyObjectPayload::Scope { scope } = &py_scope.payload {
36-
Ok(scope.borrow().locals.clone())
37-
} else {
38-
panic!("The scope isn't a scope!");
39-
}
33+
Ok(frame.scope.locals.clone())
4034
}
4135

4236
fn frame_fcode(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

0 commit comments

Comments
 (0)