From 23b90aa97e16de54bb810c51122a38805606bd74 Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Sun, 16 Feb 2020 22:04:54 -0500 Subject: [PATCH] Use remove() rather than .get() to avoid a clone --- src/args.rs | 4 ++++ src/builtin/color/hsl.rs | 38 ++++++++++++++++++------------------ src/builtin/color/opacity.rs | 16 +++++++-------- src/builtin/color/other.rs | 22 ++++++++++++--------- src/builtin/color/rgb.rs | 32 +++++++++++++++--------------- src/builtin/list.rs | 2 +- src/builtin/macros.rs | 8 ++++---- src/builtin/math.rs | 14 ++++++------- src/builtin/meta.rs | 10 +++++----- src/builtin/mod.rs | 2 +- src/builtin/string.rs | 20 ++++++++----------- src/value/parse.rs | 2 +- 12 files changed, 87 insertions(+), 83 deletions(-) diff --git a/src/args.rs b/src/args.rs index 23692cb..d012185 100644 --- a/src/args.rs +++ b/src/args.rs @@ -37,6 +37,10 @@ impl CallArgs { pub fn len(&self) -> usize { self.0.len() } + + pub fn remove(&mut self, s: &str) -> Option { + self.0.remove(s) + } } pub(crate) fn eat_func_args>( diff --git a/src/builtin/color/hsl.rs b/src/builtin/color/hsl.rs index a0c2ee2..af35247 100644 --- a/src/builtin/color/hsl.rs +++ b/src/builtin/color/hsl.rs @@ -8,15 +8,15 @@ use crate::value::{Number, Value}; pub(crate) fn register(f: &mut BTreeMap) { decl!(f "hsl", |args, _| { - let hue = match arg!(args, 0, "hue").eval() { + let hue = match arg!(args, 0, "hue") { Value::Dimension(n, _) => n, v => return Err(format!("$hue: {} is not a number.", v).into()), }; - let saturation = match arg!(args, 1, "saturation").eval() { + let saturation = match arg!(args, 1, "saturation") { Value::Dimension(n, _) => n / Number::from(100), v => return Err(format!("$saturation: {} is not a number.", v).into()), }; - let luminance = match arg!(args, 2, "luminance").eval() { + let luminance = match arg!(args, 2, "luminance") { Value::Dimension(n, _) => n / Number::from(100), v => return Err(format!("$luminance: {} is not a number.", v).into()), }; @@ -29,19 +29,19 @@ pub(crate) fn register(f: &mut BTreeMap) { Ok(Value::Color(Color::from_hsla(hue, saturation, luminance, alpha))) }); decl!(f "hsla", |args, _| { - let hue = match arg!(args, 0, "hue").eval() { + let hue = match arg!(args, 0, "hue") { Value::Dimension(n, _) => n, v => return Err(format!("$hue: {} is not a number.", v).into()), }; - let saturation = match arg!(args, 1, "saturation").eval() { + let saturation = match arg!(args, 1, "saturation") { Value::Dimension(n, _) => n / Number::from(100), v => return Err(format!("$saturation: {} is not a number.", v).into()), }; - let luminance = match arg!(args, 2, "luminance").eval() { + let luminance = match arg!(args, 2, "luminance") { Value::Dimension(n, _) => n / Number::from(100), v => return Err(format!("$luminance: {} is not a number.", v).into()), }; - let alpha = match arg!(args, 3, "alpha").eval() { + let alpha = match arg!(args, 3, "alpha") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => n / Number::from(100), v @ Value::Dimension(..) => return Err(format!("$alpha: Expected {} to have no units or \"%\".", v).into()), @@ -72,11 +72,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "adjust-hue", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let degrees = match arg!(args, 1, "degrees").eval() { + let degrees = match arg!(args, 1, "degrees") { Value::Dimension(n, _) => n, v => return Err(format!("$degrees: {} is not a number.", v).into()), }; @@ -84,11 +84,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "lighten", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 100) / Number::from(100), v => return Err(format!("$amount: {} is not a number.", v).into()) }; @@ -96,11 +96,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "darken", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 100) / Number::from(100), v => return Err(format!("$amount: {} is not a number.", v).into()) }; @@ -108,11 +108,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "saturate", |args, _| { max_args!(args, 2); - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 100) / Number::from(100), v => return Err(format!("$amount: {} is not a number.", v).into()) }; - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, Value::Dimension(n, u) => return Ok(Value::Ident(format!("saturate({}{})", n, u), QuoteKind::None)), v => return Err(format!("$color: {} is not a color.", v).into()), @@ -121,11 +121,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "desaturate", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 100) / Number::from(100), v => return Err(format!("$amount: {} is not a number.", v).into()) }; @@ -133,7 +133,7 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "grayscale", |args, _| { max_args!(args, 1); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, Value::Dimension(n, u) => return Ok(Value::Ident(format!("grayscale({}{})", n, u), QuoteKind::None)), v => return Err(format!("$color: {} is not a color.", v).into()), @@ -142,7 +142,7 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "complement", |args, _| { max_args!(args, 1); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; diff --git a/src/builtin/color/opacity.rs b/src/builtin/color/opacity.rs index f469cd9..ffa3027 100644 --- a/src/builtin/color/opacity.rs +++ b/src/builtin/color/opacity.rs @@ -24,11 +24,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "opacify", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 1), v => return Err(format!("$amount: {} is not a number.", v).into()), }; @@ -36,11 +36,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "fade-in", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 1), v => return Err(format!("$amount: {} is not a number.", v).into()), }; @@ -48,11 +48,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "transparentize", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 1), v => return Err(format!("$amount: {} is not a number.", v).into()), }; @@ -60,11 +60,11 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "fade-out", |args, _| { max_args!(args, 2); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let amount = match arg!(args, 1, "amount").eval() { + let amount = match arg!(args, 1, "amount") { Value::Dimension(n, u) => bound!("amount", n, u, 0, 1), v => return Err(format!("$amount: {} is not a number.", v).into()), }; diff --git a/src/builtin/color/other.rs b/src/builtin/color/other.rs index 2440239..99a208f 100644 --- a/src/builtin/color/other.rs +++ b/src/builtin/color/other.rs @@ -8,7 +8,7 @@ use crate::value::{Number, Value}; macro_rules! opt_arg { ($args:ident, $name:ident, $arg:literal) => { - let $name = match arg!($args, -1, $arg = Value::Null).eval() { + let $name = match arg!($args, -1, $arg = Value::Null) { Value::Dimension(n, Unit::None) => Some(n), Value::Dimension(n, Unit::Percent) => Some(n / Number::from(100)), Value::Null => None, @@ -16,7 +16,7 @@ macro_rules! opt_arg { }; }; (hsl: $args:ident, $name:ident, $arg:literal) => { - let $name = match arg!($args, -1, $arg = Value::Null).eval() { + let $name = match arg!($args, -1, $arg = Value::Null) { Value::Dimension(n, Unit::None) | Value::Dimension(n, Unit::Percent) => { Some(n / Number::from(100)) } @@ -28,7 +28,11 @@ macro_rules! opt_arg { pub(crate) fn register(f: &mut BTreeMap) { decl!(f "change-color", |args, _| { - let color = match arg!(args, 0, "color").eval() { + if args.get("1").is_some() { + return Err("Only one positional argument is allowed. All other arguments must be passed by name.".into()); + } + + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; @@ -42,7 +46,7 @@ pub(crate) fn register(f: &mut BTreeMap) { return Ok(Value::Color(Color::from_rgba(red.unwrap_or(color.red()), green.unwrap_or(color.green()), blue.unwrap_or(color.blue()), alpha.unwrap_or(color.alpha())))) } - let hue = match arg!(args, -1, "hue"=Value::Null).eval() { + let hue = match arg!(args, -1, "hue"=Value::Null) { Value::Dimension(n, Unit::None) | Value::Dimension(n, Unit::Percent) | Value::Dimension(n, Unit::Deg) => Some(n), @@ -66,7 +70,7 @@ pub(crate) fn register(f: &mut BTreeMap) { })) }); decl!(f "adjust-color", |args, _| { - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; @@ -88,7 +92,7 @@ pub(crate) fn register(f: &mut BTreeMap) { )) } - let hue = match arg!(args, -1, "hue"=Value::Null).eval() { + let hue = match arg!(args, -1, "hue"=Value::Null) { Value::Dimension(n, Unit::None) | Value::Dimension(n, Unit::Percent) | Value::Dimension(n, Unit::Deg) => Some(n), @@ -120,7 +124,7 @@ pub(crate) fn register(f: &mut BTreeMap) { })) }); decl!(f "scale-color", |args, _| { - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; @@ -142,7 +146,7 @@ pub(crate) fn register(f: &mut BTreeMap) { )) } - let hue = match arg!(args, -1, "hue"=Value::Null).eval() { + let hue = match arg!(args, -1, "hue"=Value::Null) { Value::Dimension(n, Unit::None) | Value::Dimension(n, Unit::Percent) | Value::Dimension(n, Unit::Deg) => Some(n), @@ -175,7 +179,7 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "ie-hex-str", |args, _| { max_args!(args, 1); - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; diff --git a/src/builtin/color/rgb.rs b/src/builtin/color/rgb.rs index ebc7f37..df56967 100644 --- a/src/builtin/color/rgb.rs +++ b/src/builtin/color/rgb.rs @@ -8,7 +8,7 @@ use crate::value::{Number, Value}; pub(crate) fn register(f: &mut BTreeMap) { decl!(f "rgb", |args, _| { if args.len() == 1 { - let mut channels = match arg!(args, 0, "channels").eval() { + let mut channels = match arg!(args, 0, "channels") { Value::List(v, _) => v, _ => return Err("Missing element $green.".into()) }; @@ -41,11 +41,11 @@ pub(crate) fn register(f: &mut BTreeMap) { Ok(Value::Color(color)) } else if args.len() == 2 { - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let alpha = match arg!(args, 1, "alpha").eval() { + let alpha = match arg!(args, 1, "alpha") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => n / Number::from(100), v @ Value::Dimension(..) => return Err(format!("$alpha: Expected {} to have no units or \"%\".", v).into()), @@ -53,25 +53,25 @@ pub(crate) fn register(f: &mut BTreeMap) { }; Ok(Value::Color(color.with_alpha(alpha))) } else { - let red = match arg!(args, 0, "red").eval() { + let red = match arg!(args, 0, "red") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255), v @ Value::Dimension(..) => return Err(format!("$red: Expected {} to have no units or \"%\".", v).into()), v => return Err(format!("$red: {} is not a number.", v).into()), }; - let green = match arg!(args, 1, "green").eval() { + let green = match arg!(args, 1, "green") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255), v @ Value::Dimension(..) => return Err(format!("$green: Expected {} to have no units or \"%\".", v).into()), v => return Err(format!("$green: {} is not a number.", v).into()), }; - let blue = match arg!(args, 2, "blue").eval() { + let blue = match arg!(args, 2, "blue") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255), v @ Value::Dimension(..) => return Err(format!("$blue: Expected {} to have no units or \"%\".", v).into()), v => return Err(format!("$blue: {} is not a number.", v).into()), }; - let alpha = match arg!(args, 3, "alpha"=Value::Dimension(Number::from(1), Unit::None)).eval() { + let alpha = match arg!(args, 3, "alpha"=Value::Dimension(Number::from(1), Unit::None)) { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => n / Number::from(100), v @ Value::Dimension(..) => return Err(format!("$alpha: Expected {} to have no units or \"%\".", v).into()), @@ -82,7 +82,7 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "rgba", |args, _| { if args.len() == 1 { - let mut channels = match arg!(args, 0, "channels").eval() { + let mut channels = match arg!(args, 0, "channels") { Value::List(v, _) => v, _ => return Err("Missing element $green.".into()) }; @@ -115,11 +115,11 @@ pub(crate) fn register(f: &mut BTreeMap) { Ok(Value::Color(color)) } else if args.len() == 2 { - let color = match arg!(args, 0, "color").eval() { + let color = match arg!(args, 0, "color") { Value::Color(c) => c, v => return Err(format!("$color: {} is not a color.", v).into()), }; - let alpha = match arg!(args, 1, "alpha").eval() { + let alpha = match arg!(args, 1, "alpha") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => n / Number::from(100), v @ Value::Dimension(..) => return Err(format!("$alpha: Expected {} to have no units or \"%\".", v).into()), @@ -127,25 +127,25 @@ pub(crate) fn register(f: &mut BTreeMap) { }; Ok(Value::Color(color.with_alpha(alpha))) } else { - let red = match arg!(args, 0, "red").eval() { + let red = match arg!(args, 0, "red") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255), v @ Value::Dimension(..) => return Err(format!("$red: Expected {} to have no units or \"%\".", v).into()), v => return Err(format!("$red: {} is not a number.", v).into()), }; - let green = match arg!(args, 1, "green").eval() { + let green = match arg!(args, 1, "green") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255), v @ Value::Dimension(..) => return Err(format!("$green: Expected {} to have no units or \"%\".", v).into()), v => return Err(format!("$green: {} is not a number.", v).into()), }; - let blue = match arg!(args, 2, "blue").eval() { + let blue = match arg!(args, 2, "blue") { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255), v @ Value::Dimension(..) => return Err(format!("$blue: Expected {} to have no units or \"%\".", v).into()), v => return Err(format!("$blue: {} is not a number.", v).into()), }; - let alpha = match arg!(args, 3, "alpha"=Value::Dimension(Number::from(1), Unit::None)).eval() { + let alpha = match arg!(args, 3, "alpha"=Value::Dimension(Number::from(1), Unit::None)) { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => n / Number::from(100), v @ Value::Dimension(..) => return Err(format!("$alpha: Expected {} to have no units or \"%\".", v).into()), @@ -177,12 +177,12 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "mix", |args, _| { max_args!(args, 3); - let color1 = match arg!(args, 0, "color1").eval() { + let color1 = match arg!(args, 0, "color1") { Value::Color(c) => c, v => return Err(format!("$color1: {} is not a color.", v).into()), }; - let color2 = match arg!(args, 1, "color2").eval() { + let color2 = match arg!(args, 1, "color2") { Value::Color(c) => c, v => return Err(format!("$color2: {} is not a color.", v).into()), }; diff --git a/src/builtin/list.rs b/src/builtin/list.rs index 55ec320..96d5a95 100644 --- a/src/builtin/list.rs +++ b/src/builtin/list.rs @@ -6,7 +6,7 @@ use crate::value::{Number, Value}; pub(crate) fn register(f: &mut BTreeMap) { decl!(f "length", |args, _| { - let len = match arg!(args, 0, "list").eval() { + let len = match arg!(args, 0, "list") { Value::List(v, _) => Number::from(v.len()), _ => Number::from(1) }; diff --git a/src/builtin/macros.rs b/src/builtin/macros.rs index 67bc8d4..1a4d248 100644 --- a/src/builtin/macros.rs +++ b/src/builtin/macros.rs @@ -1,9 +1,9 @@ macro_rules! arg { ($args:ident, $idx:literal, $name:literal) => { - match $args.get(stringify!($idx)) { - Some(v) => v, - None => match $args.get($name) { - Some(v) => v, + match $args.remove(stringify!($idx)) { + Some(v) => v.eval(), + None => match $args.remove($name) { + Some(v) => v.eval(), None => return Err(concat!("Missing argument $", $name, ".").into()), }, }; diff --git a/src/builtin/math.rs b/src/builtin/math.rs index d61b73a..fc9d47b 100644 --- a/src/builtin/math.rs +++ b/src/builtin/math.rs @@ -7,7 +7,7 @@ use crate::value::{Number, Value}; pub(crate) fn register(f: &mut BTreeMap) { decl!(f "percentage", |args, _| { max_args!(args, 1); - let num = match arg!(args, 0, "number").eval() { + let num = match arg!(args, 0, "number") { Value::Dimension(n, Unit::None) => n * Number::from(100), v @ Value::Dimension(..) => return Err(format!("$number: Expected {} to have no units.", v).into()), v => return Err(format!("$number: {} is not a number.", v).into()), @@ -16,39 +16,39 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "round", |args, _| { max_args!(args, 1); - match arg!(args, 0, "number").eval() { + match arg!(args, 0, "number") { Value::Dimension(n, u) => Ok(Value::Dimension(n.round(), u)), v => return Err(format!("$number: {} is not a number.", v).into()), } }); decl!(f "ceil", |args, _| { max_args!(args, 1); - match arg!(args, 0, "number").eval() { + match arg!(args, 0, "number") { Value::Dimension(n, u) => Ok(Value::Dimension(n.ceil(), u)), v => return Err(format!("$number: {} is not a number.", v).into()), } }); decl!(f "floor", |args, _| { max_args!(args, 1); - match arg!(args, 0, "number").eval() { + match arg!(args, 0, "number") { Value::Dimension(n, u) => Ok(Value::Dimension(n.floor(), u)), v => return Err(format!("$number: {} is not a number.", v).into()), } }); decl!(f "abs", |args, _| { max_args!(args, 1); - match arg!(args, 0, "number").eval() { + match arg!(args, 0, "number") { Value::Dimension(n, u) => Ok(Value::Dimension(n.abs(), u)), v => return Err(format!("$number: {} is not a number.", v).into()), } }); decl!(f "comparable", |args, _| { max_args!(args, 2); - let unit1 = match arg!(args, 0, "number1").eval() { + let unit1 = match arg!(args, 0, "number1") { Value::Dimension(_, u) => u, v => return Err(format!("$number1: {} is not a number.", v).into()), }; - let unit2 = match arg!(args, 1, "number2").eval() { + let unit2 = match arg!(args, 1, "number2") { Value::Dimension(_, u) => u, v => return Err(format!("$number2: {} is not a number.", v).into()), }; diff --git a/src/builtin/meta.rs b/src/builtin/meta.rs index 9dd79c8..1e7a9b6 100644 --- a/src/builtin/meta.rs +++ b/src/builtin/meta.rs @@ -9,14 +9,14 @@ pub(crate) fn register(f: &mut BTreeMap) { decl!(f "if", |args, _| { max_args!(args, 3); if arg!(args, 0, "condition").is_true() { - Ok(arg!(args, 1, "if-true").eval()) + Ok(arg!(args, 1, "if-true")) } else { - Ok(arg!(args, 2, "if-false").eval()) + Ok(arg!(args, 2, "if-false")) } }); decl!(f "feature-exists", |args, _| { max_args!(args, 1); - match arg!(args, 0, "feature").eval().unquote().to_string().as_str() { + match arg!(args, 0, "feature").unquote().to_string().as_str() { // A local variable will shadow a global variable unless // `!global` is used. "global-variable-shadowing" => Ok(Value::False), @@ -45,7 +45,7 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "type-of", |args, _| { max_args!(args, 1); - let value = arg!(args, 0, "value").eval(); + let value = arg!(args, 0, "value"); Ok(Value::Ident(value.kind().to_owned(), QuoteKind::None)) }); decl!(f "unitless", |args, _| { @@ -74,7 +74,7 @@ pub(crate) fn register(f: &mut BTreeMap) { decl!(f "function-exists", |args, scope| { max_args!(args, 1); let value = arg!(args, 0, "name"); - let s = value.eval().unquote().to_string(); + let s = value.unquote().to_string(); Ok(Value::bool(scope.fn_exists(&s) || GLOBAL_FUNCTIONS.contains_key(&s))) }); decl!(f "call", |_args, _scope| { diff --git a/src/builtin/mod.rs b/src/builtin/mod.rs index 454f344..eced1c3 100644 --- a/src/builtin/mod.rs +++ b/src/builtin/mod.rs @@ -17,7 +17,7 @@ mod meta; mod selector; mod string; -pub(crate) type Builtin = Box SassResult + Send + Sync>; +pub(crate) type Builtin = Box SassResult + Send + Sync>; lazy_static! { pub(crate) static ref GLOBAL_FUNCTIONS: BTreeMap = { diff --git a/src/builtin/string.rs b/src/builtin/string.rs index fdf0eab..a782ae7 100644 --- a/src/builtin/string.rs +++ b/src/builtin/string.rs @@ -12,39 +12,35 @@ use crate::value::{Number, Value}; pub(crate) fn register(f: &mut BTreeMap) { decl!(f "to-upper-case", |args, _| { max_args!(args, 1); - let s: &Value = arg!(args, 0, "string"); - match s.eval() { + match arg!(args, 0, "string") { Value::Ident(i, q) => Ok(Value::Ident(i.to_ascii_uppercase(), q)), v => Err(format!("$string: {} is not a string.", v).into()), } }); decl!(f "to-lower-case", |args, _| { max_args!(args, 1); - let s: &Value = arg!(args, 0, "string"); - match s.eval() { + match arg!(args, 0, "string") { Value::Ident(i, q) => Ok(Value::Ident(i.to_ascii_lowercase(), q)), v => Err(format!("$string: {} is not a string.", v).into()), } }); decl!(f "str-length", |args, _| { max_args!(args, 1); - let s: &Value = arg!(args, 0, "string"); - match s.eval() { + match arg!(args, 0, "string") { Value::Ident(i, _) => Ok(Value::Dimension(Number::from(i.len()), Unit::None)), v => Err(format!("$string: {} is not a string.", v).into()), } }); decl!(f "quote", |args, _| { max_args!(args, 1); - let s = arg!(args, 0, "string").eval(); - match s { + match arg!(args, 0, "string") { Value::Ident(i, _) => Ok(Value::Ident(i, QuoteKind::Double)), v => Err(format!("$string: {} is not a string.", v).into()), } }); decl!(f "unquote", |args, _| { max_args!(args, 1); - match arg!(args, 0, "string").eval() { + match arg!(args, 0, "string") { Value::Ident(i, _) if i.is_empty() => Ok(Value::Null), i @ Value::Ident(..) => Ok(i.unquote()), v => Err(format!("$string: {} is not a string.", v).into()), @@ -52,12 +48,12 @@ pub(crate) fn register(f: &mut BTreeMap) { }); decl!(f "str-slice", |args, _| { max_args!(args, 3); - let (string, quotes) = match arg!(args, 0, "string").eval() { + let (string, quotes) = match arg!(args, 0, "string") { Value::Ident(s, q) => (s, q), v => return Err(format!("$string: {} is not a string.", v).into()), }; let str_len = string.len(); - let start = match arg!(args, 1, "start-at").eval() { + let start = match arg!(args, 1, "start-at") { Value::Dimension(n, Unit::None) if n.is_decimal() => return Err(format!("{} is not an int.", n).into()), Value::Dimension(n, Unit::None) if n.to_integer().is_positive() => n.to_integer().to_usize().unwrap(), Value::Dimension(n, Unit::None) if n == Number::from(0) => 1_usize, @@ -66,7 +62,7 @@ pub(crate) fn register(f: &mut BTreeMap) { v @ Value::Dimension(..) => return Err(format!("$start: Expected {} to have no units.", v).into()), v => return Err(format!("$start-at: {} is not a number.", v).into()), }; - let mut end = match arg!(args, 2, "end-at"=Value::Null).eval() { + let mut end = match arg!(args, 2, "end-at"=Value::Null) { Value::Dimension(n, Unit::None) if n.is_decimal() => return Err(format!("{} is not an int.", n).into()), Value::Dimension(n, Unit::None) if n.to_integer().is_positive() => n.to_integer().to_usize().unwrap(), Value::Dimension(n, Unit::None) if n == Number::from(0) => 0_usize, diff --git a/src/value/parse.rs b/src/value/parse.rs index 4f00eda..569bbac 100644 --- a/src/value/parse.rs +++ b/src/value/parse.rs @@ -223,7 +223,7 @@ impl Value { let func = match scope.get_fn(&s) { Ok(f) => f, Err(_) => match GLOBAL_FUNCTIONS.get(&s) { - Some(f) => return f(&eat_call_args(toks, scope)?, scope), + Some(f) => return f(&mut eat_call_args(toks, scope)?, scope), None => { s.push('('); let mut unclosed_parens = 0;