Merge pull request #1329 from palaviv/scope-linked-list

Use LinkedList in scope locals
This commit is contained in:
Windel Bouwman
2019-09-04 21:31:53 +02:00
committed by GitHub

View File

@@ -1,5 +1,4 @@
use std::fmt;
use std::rc::Rc;
use crate::obj::objdict::PyDictRef;
use crate::pyobject::{ItemProtocol, PyContext, PyObjectRef, PyResult};
@@ -9,58 +8,9 @@ use crate::vm::VirtualMachine;
* So a scope is a linked list of scopes.
* When a name is looked up, it is check in its scope.
*/
#[derive(Debug)]
struct RcListNode<T> {
elem: T,
next: Option<Rc<RcListNode<T>>>,
}
#[derive(Debug, Clone)]
struct RcList<T> {
head: Option<Rc<RcListNode<T>>>,
}
struct Iter<'a, T: 'a> {
next: Option<&'a RcListNode<T>>,
}
impl<T> RcList<T> {
pub fn new() -> Self {
RcList { head: None }
}
pub fn insert(self, elem: T) -> Self {
RcList {
head: Some(Rc::new(RcListNode {
elem,
next: self.head,
})),
}
}
#[cfg_attr(feature = "flame-it", flame("RcList"))]
pub fn iter(&self) -> Iter<T> {
Iter {
next: self.head.as_ref().map(|node| &**node),
}
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
#[cfg_attr(feature = "flame-it", flame("Iter"))]
fn next(&mut self) -> Option<Self::Item> {
self.next.map(|node| {
self.next = node.next.as_ref().map(|node| &**node);
&node.elem
})
}
}
#[derive(Clone)]
pub struct Scope {
locals: RcList<PyDictRef>,
locals: Vec<PyDictRef>,
pub globals: PyDictRef,
}
@@ -74,8 +24,8 @@ impl fmt::Debug for Scope {
impl Scope {
pub fn new(locals: Option<PyDictRef>, globals: PyDictRef, vm: &VirtualMachine) -> Scope {
let locals = match locals {
Some(dict) => RcList::new().insert(dict),
None => RcList::new(),
Some(dict) => vec![dict],
None => vec![],
};
let scope = Scope { locals, globals };
scope.store_name(vm, "__annotations__", vm.ctx.new_dict().into_object());
@@ -97,19 +47,22 @@ impl Scope {
}
pub fn get_locals(&self) -> PyDictRef {
match self.locals.iter().next() {
match self.locals.first() {
Some(dict) => dict.clone(),
None => self.globals.clone(),
}
}
pub fn get_only_locals(&self) -> Option<PyDictRef> {
self.locals.iter().next().cloned()
self.locals.first().cloned()
}
pub fn new_child_scope_with_locals(&self, locals: PyDictRef) -> Scope {
let mut new_locals = Vec::with_capacity(self.locals.len() + 1);
new_locals.push(locals);
new_locals.extend_from_slice(&self.locals);
Scope {
locals: self.locals.clone().insert(locals),
locals: new_locals,
globals: self.globals.clone(),
}
}
@@ -161,8 +114,7 @@ impl NameProtocol for Scope {
fn store_cell(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef) {
self.locals
.iter()
.nth(1)
.get(1)
.expect("no outer scope for non-local")
.set_item(name, value, vm)
.unwrap();