From 0a44a852f916403f34c84c645fc2754c88f81632 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Wed, 28 Dec 2022 15:48:17 -0500 Subject: [PATCH] optimize repeated variable lookups --- src/evaluate/env.rs | 4 +++- src/evaluate/scope.rs | 34 +++++++++++++++++++++++++++++----- tests/media.rs | 3 +-- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/evaluate/env.rs b/src/evaluate/env.rs index ed4f044..87e08a4 100644 --- a/src/evaluate/env.rs +++ b/src/evaluate/env.rs @@ -120,7 +120,7 @@ impl Environment { } pub fn get_var( - &self, + &mut self, name: Spanned, namespace: Option>, ) -> SassResult { @@ -190,6 +190,8 @@ impl Environment { index = self.scopes.len() - 1; } + self.scopes.last_variable_index = Some((name.node, index)); + self.scopes.insert_var(index, name.node, value); Ok(()) diff --git a/src/evaluate/scope.rs b/src/evaluate/scope.rs index 578a469..579b1c3 100644 --- a/src/evaluate/scope.rs +++ b/src/evaluate/scope.rs @@ -21,6 +21,7 @@ pub(crate) struct Scopes { mixins: Arc>>>>>, functions: Arc>>>>>, len: Arc>, + pub last_variable_index: Option<(Identifier, usize)>, } impl Scopes { @@ -30,6 +31,7 @@ impl Scopes { mixins: Arc::new(RefCell::new(vec![Arc::new(RefCell::new(BTreeMap::new()))])), functions: Arc::new(RefCell::new(vec![Arc::new(RefCell::new(BTreeMap::new()))])), len: Arc::new(Cell::new(1)), + last_variable_index: None, } } @@ -46,6 +48,7 @@ impl Scopes { (*self.functions).borrow().iter().map(Arc::clone).collect(), )), len: Arc::new(Cell::new(self.len())), + last_variable_index: self.last_variable_index, } } @@ -62,10 +65,17 @@ impl Scopes { Arc::clone(&(*self.mixins).borrow()[0]) } - pub fn find_var(&self, name: Identifier) -> Option { + pub fn find_var(&mut self, name: Identifier) -> Option { debug_assert_eq!(self.len(), (*self.variables).borrow().len()); + + match self.last_variable_index { + Some((prev_name, idx)) if prev_name == name => return Some(idx), + _ => {} + }; + for (idx, scope) in (*self.variables).borrow().iter().enumerate().rev() { if (**scope).borrow().contains_key(&name) { + self.last_variable_index = Some((name, idx)); return Some(idx); } } @@ -99,6 +109,7 @@ impl Scopes { (*self.variables).borrow_mut().pop(); (*self.mixins).borrow_mut().pop(); (*self.functions).borrow_mut().pop(); + self.last_variable_index = None; } } @@ -116,16 +127,29 @@ impl Scopes { /// Used, for example, for variables from `@each` and `@for` pub fn insert_var_last(&mut self, name: Identifier, v: Value) -> Option { debug_assert_eq!(self.len(), (*self.variables).borrow().len()); - (*(*self.variables).borrow_mut()[self.len() - 1]) + let last_idx = self.len() - 1; + self.last_variable_index = Some((name, last_idx)); + (*(*self.variables).borrow_mut()[last_idx]) .borrow_mut() .insert(name, v) } - pub fn get_var(&self, name: Spanned) -> SassResult { + pub fn get_var(&mut self, name: Spanned) -> SassResult { debug_assert_eq!(self.len(), (*self.variables).borrow().len()); - for scope in (*self.variables).borrow().iter().rev() { + + match self.last_variable_index { + Some((prev_name, idx)) if prev_name == name.node => { + return Ok((*(*self.variables).borrow()[idx]).borrow()[&name.node].clone()); + } + _ => {} + }; + + for (idx, scope) in (*self.variables).borrow().iter().enumerate().rev() { match (**scope).borrow().get(&name.node) { - Some(var) => return Ok(var.clone()), + Some(var) => { + self.last_variable_index = Some((name.node, idx)); + return Ok(var.clone()); + } None => continue, } } diff --git a/tests/media.rs b/tests/media.rs index fdff61b..59edda0 100644 --- a/tests/media.rs +++ b/tests/media.rs @@ -572,6 +572,5 @@ error!( ); error!( empty_query_after_resolving_interpolation, - "@media #{null} {}", - "Error: expected no more input." + "@media #{null} {}", "Error: expected no more input." );