Skip to content

Commit c973ed8

Browse files
Merge pull request #1329 from palaviv/scope-linked-list
Use LinkedList in scope locals
2 parents 0ad1144 + 29d9105 commit c973ed8

File tree

1 file changed

+10
-58
lines changed

1 file changed

+10
-58
lines changed

vm/src/scope.rs

Lines changed: 10 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::fmt;
2-
use std::rc::Rc;
32

43
use crate::obj::objdict::PyDictRef;
54
use crate::pyobject::{ItemProtocol, PyContext, PyObjectRef, PyResult};
@@ -9,58 +8,9 @@ use crate::vm::VirtualMachine;
98
* So a scope is a linked list of scopes.
109
* When a name is looked up, it is check in its scope.
1110
*/
12-
#[derive(Debug)]
13-
struct RcListNode<T> {
14-
elem: T,
15-
next: Option<Rc<RcListNode<T>>>,
16-
}
17-
18-
#[derive(Debug, Clone)]
19-
struct RcList<T> {
20-
head: Option<Rc<RcListNode<T>>>,
21-
}
22-
23-
struct Iter<'a, T: 'a> {
24-
next: Option<&'a RcListNode<T>>,
25-
}
26-
27-
impl<T> RcList<T> {
28-
pub fn new() -> Self {
29-
RcList { head: None }
30-
}
31-
32-
pub fn insert(self, elem: T) -> Self {
33-
RcList {
34-
head: Some(Rc::new(RcListNode {
35-
elem,
36-
next: self.head,
37-
})),
38-
}
39-
}
40-
41-
#[cfg_attr(feature = "flame-it", flame("RcList"))]
42-
pub fn iter(&self) -> Iter<T> {
43-
Iter {
44-
next: self.head.as_ref().map(|node| &**node),
45-
}
46-
}
47-
}
48-
49-
impl<'a, T> Iterator for Iter<'a, T> {
50-
type Item = &'a T;
51-
52-
#[cfg_attr(feature = "flame-it", flame("Iter"))]
53-
fn next(&mut self) -> Option<Self::Item> {
54-
self.next.map(|node| {
55-
self.next = node.next.as_ref().map(|node| &**node);
56-
&node.elem
57-
})
58-
}
59-
}
60-
6111
#[derive(Clone)]
6212
pub struct Scope {
63-
locals: RcList<PyDictRef>,
13+
locals: Vec<PyDictRef>,
6414
pub globals: PyDictRef,
6515
}
6616

@@ -74,8 +24,8 @@ impl fmt::Debug for Scope {
7424
impl Scope {
7525
pub fn new(locals: Option<PyDictRef>, globals: PyDictRef, vm: &VirtualMachine) -> Scope {
7626
let locals = match locals {
77-
Some(dict) => RcList::new().insert(dict),
78-
None => RcList::new(),
27+
Some(dict) => vec![dict],
28+
None => vec![],
7929
};
8030
let scope = Scope { locals, globals };
8131
scope.store_name(vm, "__annotations__", vm.ctx.new_dict().into_object());
@@ -97,19 +47,22 @@ impl Scope {
9747
}
9848

9949
pub fn get_locals(&self) -> PyDictRef {
100-
match self.locals.iter().next() {
50+
match self.locals.first() {
10151
Some(dict) => dict.clone(),
10252
None => self.globals.clone(),
10353
}
10454
}
10555

10656
pub fn get_only_locals(&self) -> Option<PyDictRef> {
107-
self.locals.iter().next().cloned()
57+
self.locals.first().cloned()
10858
}
10959

11060
pub fn new_child_scope_with_locals(&self, locals: PyDictRef) -> Scope {
61+
let mut new_locals = Vec::with_capacity(self.locals.len() + 1);
62+
new_locals.push(locals);
63+
new_locals.extend_from_slice(&self.locals);
11164
Scope {
112-
locals: self.locals.clone().insert(locals),
65+
locals: new_locals,
11366
globals: self.globals.clone(),
11467
}
11568
}
@@ -161,8 +114,7 @@ impl NameProtocol for Scope {
161114

162115
fn store_cell(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef) {
163116
self.locals
164-
.iter()
165-
.nth(1)
117+
.get(1)
166118
.expect("no outer scope for non-local")
167119
.set_item(name, value, vm)
168120
.unwrap();

0 commit comments

Comments
 (0)