Merge pull request #637 from RustPython/scope_globals_locals · RustPython/RustPython@e8ec497 · GitHub
Skip to content

Commit e8ec497

Browse files
Merge pull request #637 from RustPython/scope_globals_locals
Scope globals locals
2 parents 1751333 + 3fbf627 commit e8ec497

14 files changed

Lines changed: 222 additions & 134 deletions

File tree

src/main.rs

Lines changed: 4 additions & 6 deletions

tests/snippets/test_exec.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,34 @@
1313

1414
exec("assert max(1, 5, square(5)) == 25", None)
1515

16-
#
17-
# These doesn't work yet:
18-
#
1916
# Local environment shouldn't replace global environment:
20-
#
21-
# exec("assert max(1, 5, square(5)) == 25", None, {})
22-
#
17+
exec("assert max(1, 5, square(5)) == 25", None, {})
18+
2319
# Closures aren't available if local scope is replaced:
24-
#
25-
# def g():
26-
# seven = "seven"
27-
# def f():
28-
# try:
29-
# exec("seven", None, {})
30-
# except NameError:
31-
# pass
32-
# else:
33-
# raise NameError("seven shouldn't be in scope")
34-
# f()
35-
# g()
20+
def g():
21+
seven = "seven"
22+
def f():
23+
try:
24+
exec("seven", None, {})
25+
except NameError:
26+
pass
27+
else:
28+
raise NameError("seven shouldn't be in scope")
29+
f()
30+
g()
3631

3732
try:
3833
exec("", 1)
3934
except TypeError:
4035
pass
4136
else:
4237
raise TypeError("exec should fail unless globals is a dict or None")
38+
39+
g = globals()
40+
g['x'] = 2
41+
exec('x += 2')
42+
assert x == 4
43+
assert g['x'] == x
44+
45+
exec("del x")
46+
assert 'x' not in g

vm/src/builtins.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::obj::objiter;
1414
use crate::obj::objstr;
1515
use crate::obj::objtype;
1616

17-
use crate::frame::{Scope, ScopeRef};
17+
use crate::frame::Scope;
1818
use crate::pyobject::{
1919
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
2020
};
@@ -245,7 +245,7 @@ fn make_scope(
245245
vm: &mut VirtualMachine,
246246
globals: Option<&PyObjectRef>,
247247
locals: Option<&PyObjectRef>,
248-
) -> PyResult<ScopeRef> {
248+
) -> PyResult<Scope> {
249249
let dict_type = vm.ctx.dict_type();
250250
let globals = match globals {
251251
Some(arg) => {
@@ -269,16 +269,16 @@ fn make_scope(
269269
};
270270

271271
let current_scope = vm.current_scope();
272-
let parent = match globals {
273-
Some(dict) => Some(Scope::new(dict.clone(), Some(vm.get_builtin_scope()))),
274-
None => current_scope.parent.clone(),
272+
let globals = match globals {
273+
Some(dict) => dict.clone(),
274+
None => current_scope.globals.clone(),
275275
};
276276
let locals = match locals {
277-
Some(dict) => dict.clone(),
278-
None => current_scope.locals.clone(),
277+
Some(dict) => Some(dict.clone()),
278+
None => current_scope.get_only_locals(),
279279
};
280280

281-
Ok(Scope::new(locals, parent))
281+
Ok(Scope::new(locals, globals))
282282
}
283283

284284
fn builtin_format(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -303,7 +303,9 @@ fn builtin_getattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
303303
vm.get_attribute(obj.clone(), attr.clone())
304304
}
305305

306-
// builtin_globals
306+
fn builtin_globals(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
307+
Ok(vm.current_scope().globals.clone())
308+
}
307309

308310
fn builtin_hasattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
309311
arg_check!(
@@ -743,6 +745,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
743745
"filter" => ctx.filter_type(),
744746
"format" => ctx.new_rustfunc(builtin_format),
745747
"getattr" => ctx.new_rustfunc(builtin_getattr),
748+
"globals" => ctx.new_rustfunc(builtin_globals),
746749
"hasattr" => ctx.new_rustfunc(builtin_hasattr),
747750
"hash" => ctx.new_rustfunc(builtin_hash),
748751
"hex" => ctx.new_rustfunc(builtin_hex),

vm/src/eval.rs

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

55
use crate::compile;
6-
use crate::frame::ScopeRef;
6+
use crate::frame::Scope;
77
use crate::pyobject::PyResult;
88
use crate::vm::VirtualMachine;
99

10-
pub fn eval(vm: &mut VirtualMachine, source: &str, scope: ScopeRef, source_path: &str) -> PyResult {
10+
pub fn eval(vm: &mut VirtualMachine, source: &str, scope: Scope, source_path: &str) -> PyResult {
1111
match compile::compile(
1212
source,
1313
&compile::Mode::Eval,
@@ -34,7 +34,7 @@ mod tests {
3434
fn test_print_42() {
3535
let source = String::from("print('Hello world')\n");
3636
let mut vm = VirtualMachine::new();
37-
let vars = vm.context().new_scope(None);
37+
let vars = vm.ctx.new_scope();
3838
let _result = eval(&mut vm, &source, vars, "<unittest>");
3939

4040
// TODO: check result?

vm/src/frame.rs

Lines changed: 125 additions & 32 deletions

0 commit comments

Comments
 (0)