reduce cloning in argument evaluation

This commit is contained in:
connorskees 2023-01-08 15:05:59 +00:00
parent bf0d912dc8
commit f321f36faf
3 changed files with 56 additions and 53 deletions

View File

@ -78,28 +78,27 @@ impl CssTree {
} }
fn add_child_to_parent(&self, child: CssStmt, parent_idx: CssTreeIdx) { fn add_child_to_parent(&self, child: CssStmt, parent_idx: CssTreeIdx) {
let mut parent = self.stmts[parent_idx.0].borrow_mut().take(); RefMut::map(self.stmts[parent_idx.0].borrow_mut(), |parent| {
match &mut parent { match parent {
Some(CssStmt::RuleSet { body, .. }) => body.push(child), Some(CssStmt::RuleSet { body, .. }) => body.push(child),
Some(CssStmt::Style(..) | CssStmt::Comment(..) | CssStmt::Import(..)) | None => { Some(CssStmt::Style(..) | CssStmt::Comment(..) | CssStmt::Import(..)) | None => {
unreachable!() unreachable!()
} }
Some(CssStmt::Media(media, ..)) => { Some(CssStmt::Media(media, ..)) => {
media.body.push(child); media.body.push(child);
} }
Some(CssStmt::UnknownAtRule(at_rule, ..)) => { Some(CssStmt::UnknownAtRule(at_rule, ..)) => {
at_rule.body.push(child); at_rule.body.push(child);
} }
Some(CssStmt::Supports(supports, ..)) => { Some(CssStmt::Supports(supports, ..)) => {
supports.body.push(child); supports.body.push(child);
} }
Some(CssStmt::KeyframesRuleSet(keyframes)) => { Some(CssStmt::KeyframesRuleSet(keyframes)) => {
keyframes.body.push(child); keyframes.body.push(child);
} }
} };
self.stmts[parent_idx.0] parent
.borrow_mut() });
.replace(parent.unwrap());
} }
pub fn add_child(&mut self, child: CssStmt, parent_idx: CssTreeIdx) -> CssTreeIdx { pub fn add_child(&mut self, child: CssStmt, parent_idx: CssTreeIdx) -> CssTreeIdx {

View File

@ -2125,26 +2125,25 @@ impl<'a> Visitor<'a> {
evaluated.span, evaluated.span,
)?; )?;
// todo: superfluous clone let declared_arguments = &func.arguments().args;
let declared_arguments = func.arguments().args.clone();
let min_len = evaluated.positional.len().min(declared_arguments.len()); let min_len = evaluated.positional.len().min(declared_arguments.len());
let positional_len = evaluated.positional.len();
#[allow(clippy::needless_range_loop)] #[allow(clippy::needless_range_loop)]
for i in 0..min_len { for i in (0..min_len).rev() {
// todo: superfluous clone
visitor.env.scopes_mut().insert_var_last( visitor.env.scopes_mut().insert_var_last(
declared_arguments[i].name, declared_arguments[i].name,
evaluated.positional[i].clone(), evaluated.positional.remove(i),
); );
} }
// todo: better name for var // todo: better name for var
let additional_declared_args = let additional_declared_args = if declared_arguments.len() > positional_len {
if declared_arguments.len() > evaluated.positional.len() { &declared_arguments[positional_len..declared_arguments.len()]
&declared_arguments[evaluated.positional.len()..declared_arguments.len()] } else {
} else { &[]
&[] };
};
for argument in additional_declared_args { for argument in additional_declared_args {
let name = argument.name; let name = argument.name;
@ -2161,17 +2160,19 @@ impl<'a> Visitor<'a> {
let were_keywords_accessed = Arc::new(Cell::new(false)); let were_keywords_accessed = Arc::new(Cell::new(false));
let argument_list = if let Some(rest_arg) = func.arguments().rest { let num_named_args = evaluated.named.len();
let rest = if evaluated.positional.len() > declared_arguments.len() {
&evaluated.positional[declared_arguments.len()..] let has_arg_list = if let Some(rest_arg) = func.arguments().rest {
let rest = if evaluated.positional.len() > 0 {
evaluated.positional
} else { } else {
&[] Vec::new()
}; };
let arg_list = Value::ArgList(ArgList::new( let arg_list = Value::ArgList(ArgList::new(
rest.to_vec(), rest,
// todo: superfluous clone
Arc::clone(&were_keywords_accessed), Arc::clone(&were_keywords_accessed),
// todo: superfluous clone
evaluated.named.clone(), evaluated.named.clone(),
if evaluated.separator == ListSeparator::Undecided { if evaluated.separator == ListSeparator::Undecided {
ListSeparator::Comma ListSeparator::Comma
@ -2180,20 +2181,16 @@ impl<'a> Visitor<'a> {
}, },
)); ));
visitor visitor.env.scopes_mut().insert_var_last(rest_arg, arg_list);
.env
.scopes_mut()
// todo: superfluous clone
.insert_var_last(rest_arg, arg_list.clone());
Some(arg_list) true
} else { } else {
None false
}; };
let val = run(func, visitor)?; let val = run(func, visitor)?;
if argument_list.is_none() || evaluated.named.is_empty() { if !has_arg_list || num_named_args == 0 {
return Ok(val); return Ok(val);
} }
@ -2201,7 +2198,7 @@ impl<'a> Visitor<'a> {
return Ok(val); return Ok(val);
} }
let argument_word = if evaluated.named.len() == 1 { let argument_word = if num_named_args == 1 {
"argument" "argument"
} else { } else {
"arguments" "arguments"

View File

@ -13,8 +13,8 @@ use crate::{
}, },
utils::hex_char_for, utils::hex_char_for,
value::{ value::{
fuzzy_equals, ArgList, CalculationArg, SassCalculation, SassFunction, SassMap, SassNumber, fuzzy_equals, ArgList, CalculationArg, CalculationName, SassCalculation, SassFunction,
Value, SassMap, SassNumber, Value,
}, },
Options, Options,
}; };
@ -299,10 +299,17 @@ impl<'a> Serializer<'a> {
self.write_optional_space(); self.write_optional_space();
} }
fn write_calculation_name(&mut self, name: CalculationName) {
match name {
CalculationName::Calc => self.buffer.extend_from_slice(b"calc"),
CalculationName::Min => self.buffer.extend_from_slice(b"min"),
CalculationName::Max => self.buffer.extend_from_slice(b"max"),
CalculationName::Clamp => self.buffer.extend_from_slice(b"clamp"),
}
}
fn visit_calculation(&mut self, calculation: &SassCalculation) -> SassResult<()> { fn visit_calculation(&mut self, calculation: &SassCalculation) -> SassResult<()> {
// todo: superfluous allocation self.write_calculation_name(calculation.name);
self.buffer
.extend_from_slice(calculation.name.to_string().as_bytes());
self.buffer.push(b'('); self.buffer.push(b'(');
if let Some((last, slice)) = calculation.args.split_last() { if let Some((last, slice)) = calculation.args.split_last() {