optimize repeated variable lookups
This commit is contained in:
parent
bb937ae84f
commit
0a44a852f9
@ -120,7 +120,7 @@ impl Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_var(
|
pub fn get_var(
|
||||||
&self,
|
&mut self,
|
||||||
name: Spanned<Identifier>,
|
name: Spanned<Identifier>,
|
||||||
namespace: Option<Spanned<Identifier>>,
|
namespace: Option<Spanned<Identifier>>,
|
||||||
) -> SassResult<Value> {
|
) -> SassResult<Value> {
|
||||||
@ -190,6 +190,8 @@ impl Environment {
|
|||||||
index = self.scopes.len() - 1;
|
index = self.scopes.len() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.scopes.last_variable_index = Some((name.node, index));
|
||||||
|
|
||||||
self.scopes.insert_var(index, name.node, value);
|
self.scopes.insert_var(index, name.node, value);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -21,6 +21,7 @@ pub(crate) struct Scopes {
|
|||||||
mixins: Arc<RefCell<Vec<Arc<RefCell<BTreeMap<Identifier, Mixin>>>>>>,
|
mixins: Arc<RefCell<Vec<Arc<RefCell<BTreeMap<Identifier, Mixin>>>>>>,
|
||||||
functions: Arc<RefCell<Vec<Arc<RefCell<BTreeMap<Identifier, SassFunction>>>>>>,
|
functions: Arc<RefCell<Vec<Arc<RefCell<BTreeMap<Identifier, SassFunction>>>>>>,
|
||||||
len: Arc<Cell<usize>>,
|
len: Arc<Cell<usize>>,
|
||||||
|
pub last_variable_index: Option<(Identifier, usize)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scopes {
|
impl Scopes {
|
||||||
@ -30,6 +31,7 @@ impl Scopes {
|
|||||||
mixins: Arc::new(RefCell::new(vec![Arc::new(RefCell::new(BTreeMap::new()))])),
|
mixins: Arc::new(RefCell::new(vec![Arc::new(RefCell::new(BTreeMap::new()))])),
|
||||||
functions: 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)),
|
len: Arc::new(Cell::new(1)),
|
||||||
|
last_variable_index: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ impl Scopes {
|
|||||||
(*self.functions).borrow().iter().map(Arc::clone).collect(),
|
(*self.functions).borrow().iter().map(Arc::clone).collect(),
|
||||||
)),
|
)),
|
||||||
len: Arc::new(Cell::new(self.len())),
|
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])
|
Arc::clone(&(*self.mixins).borrow()[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_var(&self, name: Identifier) -> Option<usize> {
|
pub fn find_var(&mut self, name: Identifier) -> Option<usize> {
|
||||||
debug_assert_eq!(self.len(), (*self.variables).borrow().len());
|
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() {
|
for (idx, scope) in (*self.variables).borrow().iter().enumerate().rev() {
|
||||||
if (**scope).borrow().contains_key(&name) {
|
if (**scope).borrow().contains_key(&name) {
|
||||||
|
self.last_variable_index = Some((name, idx));
|
||||||
return Some(idx);
|
return Some(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,6 +109,7 @@ impl Scopes {
|
|||||||
(*self.variables).borrow_mut().pop();
|
(*self.variables).borrow_mut().pop();
|
||||||
(*self.mixins).borrow_mut().pop();
|
(*self.mixins).borrow_mut().pop();
|
||||||
(*self.functions).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`
|
/// Used, for example, for variables from `@each` and `@for`
|
||||||
pub fn insert_var_last(&mut self, name: Identifier, v: Value) -> Option<Value> {
|
pub fn insert_var_last(&mut self, name: Identifier, v: Value) -> Option<Value> {
|
||||||
debug_assert_eq!(self.len(), (*self.variables).borrow().len());
|
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()
|
.borrow_mut()
|
||||||
.insert(name, v)
|
.insert(name, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_var(&self, name: Spanned<Identifier>) -> SassResult<Value> {
|
pub fn get_var(&mut self, name: Spanned<Identifier>) -> SassResult<Value> {
|
||||||
debug_assert_eq!(self.len(), (*self.variables).borrow().len());
|
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) {
|
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,
|
None => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,6 +572,5 @@ error!(
|
|||||||
);
|
);
|
||||||
error!(
|
error!(
|
||||||
empty_query_after_resolving_interpolation,
|
empty_query_after_resolving_interpolation,
|
||||||
"@media #{null} {}",
|
"@media #{null} {}", "Error: expected no more input."
|
||||||
"Error: expected no more input."
|
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user