From d300cd046a62a341fc0f1c2eed5691c02cb95db9 Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Sun, 16 Feb 2020 10:14:17 -0500 Subject: [PATCH] Use SassError over Option inside builtins --- src/builtin/color/hsl.rs | 26 +++++++++++++------------- src/builtin/color/opacity.rs | 14 +++++++------- src/builtin/color/other.rs | 20 ++++++++++---------- src/builtin/color/rgb.rs | 20 ++++++++++---------- src/builtin/list.rs | 2 +- src/builtin/math.rs | 12 ++++++------ src/builtin/meta.rs | 34 +++++++++++++++++----------------- src/builtin/mod.rs | 3 ++- src/builtin/string.rs | 18 +++++++++--------- src/value/parse.rs | 2 +- 10 files changed, 76 insertions(+), 75 deletions(-) diff --git a/src/builtin/color/hsl.rs b/src/builtin/color/hsl.rs index d3ced94..d064aad 100644 --- a/src/builtin/color/hsl.rs +++ b/src/builtin/color/hsl.rs @@ -28,7 +28,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("non-number alpha given to builtin function `rgb()`") }; - Some(Value::Color(Color::from_hsla(hue, saturation, luminance, alpha))) + Ok(Value::Color(Color::from_hsla(hue, saturation, luminance, alpha))) }); decl!(f "hsla", |args, _| { let hue = match arg!(args, 0, "hue").eval() { @@ -52,23 +52,23 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for alpha"), }; - Some(Value::Color(Color::from_hsla(hue, saturation, luminance, alpha))) + Ok(Value::Color(Color::from_hsla(hue, saturation, luminance, alpha))) }); decl!(f "hue", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.hue(), Unit::Deg)), + Value::Color(c) => Ok(Value::Dimension(c.hue(), Unit::Deg)), _ => todo!("non-color given to builtin function `hue()`") } }); decl!(f "saturation", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.saturation(), Unit::Percent)), + Value::Color(c) => Ok(Value::Dimension(c.saturation(), Unit::Percent)), _ => todo!("non-color given to builtin function `saturation()`") } }); decl!(f "lightness", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.lightness(), Unit::Percent)), + Value::Color(c) => Ok(Value::Dimension(c.lightness(), Unit::Percent)), _ => todo!("non-color given to builtin function `lightness()`") } }); @@ -83,7 +83,7 @@ pub(crate) fn register(f: &mut BTreeMap) { | Value::Dimension(n, Unit::Deg) => n, _ => todo!("expected either unitless or % number for degrees"), }; - Some(Value::Color(color.adjust_hue(degrees))) + Ok(Value::Color(color.adjust_hue(degrees))) }); decl!(f "lighten", |args, _| { let color = match arg!(args, 0, "color").eval() { @@ -95,7 +95,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.lighten(amount))) + Ok(Value::Color(color.lighten(amount))) }); decl!(f "darken", |args, _| { let color = match arg!(args, 0, "color").eval() { @@ -107,7 +107,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.darken(amount))) + Ok(Value::Color(color.darken(amount))) }); decl!(f "saturate", |args, _| { let color = match arg!(args, 0, "color").eval() { @@ -119,7 +119,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.saturate(amount))) + Ok(Value::Color(color.saturate(amount))) }); decl!(f "desaturate", |args, _| { let color = match arg!(args, 0, "color").eval() { @@ -131,21 +131,21 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.desaturate(amount))) + Ok(Value::Color(color.desaturate(amount))) }); decl!(f "grayscale", |args, _| { let color = match arg!(args, 0, "color").eval() { Value::Color(c) => c, _ => todo!("non-color given to builtin function `grayscale()`") }; - Some(Value::Color(color.desaturate(Number::from(1)))) + Ok(Value::Color(color.desaturate(Number::from(1)))) }); decl!(f "complement", |args, _| { let color = match arg!(args, 0, "color").eval() { Value::Color(c) => c, _ => todo!("non-color given to builtin function `complement()`") }; - Some(Value::Color(color.complement())) + Ok(Value::Color(color.complement())) }); decl!(f "invert", |args, _| { let weight = match arg!(args, 1, "weight"=Value::Dimension(Number::from(100), Unit::Percent)) { @@ -154,7 +154,7 @@ pub(crate) fn register(f: &mut BTreeMap) { _ => todo!("non-number weight given to builtin function `invert()`") }; match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Color(c.invert(weight))), + Value::Color(c) => Ok(Value::Color(c.invert(weight))), _ => todo!("non-color given to builtin function `invert()`") } }); diff --git a/src/builtin/color/opacity.rs b/src/builtin/color/opacity.rs index 3755c40..bdb2095 100644 --- a/src/builtin/color/opacity.rs +++ b/src/builtin/color/opacity.rs @@ -8,14 +8,14 @@ use crate::value::{Number, Value}; pub(crate) fn register(f: &mut BTreeMap) { decl!(f "alpha", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.alpha(), Unit::None)), + Value::Color(c) => Ok(Value::Dimension(c.alpha(), Unit::None)), _ => todo!("non-color given to builtin function `alpha()`") } }); decl!(f "opacity", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.alpha(), Unit::None)), - Value::Dimension(num, unit) => Some(Value::Ident(format!("opacity({}{})", num , unit), QuoteKind::None)), + Value::Color(c) => Ok(Value::Dimension(c.alpha(), Unit::None)), + Value::Dimension(num, unit) => Ok(Value::Ident(format!("opacity({}{})", num , unit), QuoteKind::None)), _ => todo!("non-color given to builtin function `opacity()`") } }); @@ -29,7 +29,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.fade_in(amount))) + Ok(Value::Color(color.fade_in(amount))) }); decl!(f "fade-in", |args, _| { let color = match arg!(args, 0, "color").eval() { @@ -41,7 +41,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.fade_in(amount))) + Ok(Value::Color(color.fade_in(amount))) }); decl!(f "transparentize", |args, _| { let color = match arg!(args, 0, "color").eval() { @@ -53,7 +53,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.fade_out(amount))) + Ok(Value::Color(color.fade_out(amount))) }); decl!(f "fade-out", |args, _| { let color = match arg!(args, 0, "color").eval() { @@ -65,6 +65,6 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for amount"), }; - Some(Value::Color(color.fade_out(amount))) + Ok(Value::Color(color.fade_out(amount))) }); } diff --git a/src/builtin/color/other.rs b/src/builtin/color/other.rs index 197f6d6..417a991 100644 --- a/src/builtin/color/other.rs +++ b/src/builtin/color/other.rs @@ -39,7 +39,7 @@ pub(crate) fn register(f: &mut BTreeMap) { opt_arg!(args, blue, "blue"); if red.is_some() || green.is_some() || blue.is_some() { - return Some(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())))) + 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() { @@ -56,10 +56,10 @@ pub(crate) fn register(f: &mut BTreeMap) { if hue.is_some() || saturation.is_some() || luminance.is_some() { // Color::as_hsla() returns more exact values than Color::hue(), etc. let (this_hue, this_saturation, this_luminance, this_alpha) = color.as_hsla(); - return Some(Value::Color(Color::from_hsla(hue.unwrap_or(this_hue), saturation.unwrap_or(this_saturation), luminance.unwrap_or(this_luminance), alpha.unwrap_or(this_alpha)))) + return Ok(Value::Color(Color::from_hsla(hue.unwrap_or(this_hue), saturation.unwrap_or(this_saturation), luminance.unwrap_or(this_luminance), alpha.unwrap_or(this_alpha)))) } - Some(Value::Color(if let Some(a) = alpha { + Ok(Value::Color(if let Some(a) = alpha { color.with_alpha(a) } else { color @@ -78,7 +78,7 @@ pub(crate) fn register(f: &mut BTreeMap) { if red.is_some() || green.is_some() || blue.is_some() { return - Some(Value::Color( + Ok(Value::Color( Color::from_rgba( color.red() + red.unwrap_or(Number::from(0)), color.green() + green.unwrap_or(Number::from(0)), @@ -102,7 +102,7 @@ pub(crate) fn register(f: &mut BTreeMap) { if hue.is_some() || saturation.is_some() || luminance.is_some() { // Color::as_hsla() returns more exact values than Color::hue(), etc. let (this_hue, this_saturation, this_luminance, this_alpha) = color.as_hsla(); - return Some(Value::Color( + return Ok(Value::Color( Color::from_hsla( this_hue + hue.unwrap_or(Number::from(0)), this_saturation + saturation.unwrap_or(Number::from(0)), @@ -112,7 +112,7 @@ pub(crate) fn register(f: &mut BTreeMap) { )) } - Some(Value::Color(if let Some(a) = alpha { + Ok(Value::Color(if let Some(a) = alpha { let temp_alpha = color.alpha(); color.with_alpha(temp_alpha + a) } else { @@ -132,7 +132,7 @@ pub(crate) fn register(f: &mut BTreeMap) { if red.is_some() || green.is_some() || blue.is_some() { return - Some(Value::Color( + Ok(Value::Color( Color::from_rgba( scale(color.red(), red.unwrap_or(Number::from(0)), Number::from(255)), scale(color.green(), green.unwrap_or(Number::from(0)), Number::from(255)), @@ -156,7 +156,7 @@ pub(crate) fn register(f: &mut BTreeMap) { if hue.is_some() || saturation.is_some() || luminance.is_some() { // Color::as_hsla() returns more exact values than Color::hue(), etc. let (this_hue, this_saturation, this_luminance, this_alpha) = color.as_hsla(); - return Some(Value::Color( + return Ok(Value::Color( Color::from_hsla( scale(this_hue, hue.unwrap_or(Number::from(0)), Number::from(360)), scale(this_saturation, saturation.unwrap_or(Number::from(0)), Number::from(1)), @@ -166,7 +166,7 @@ pub(crate) fn register(f: &mut BTreeMap) { )) } - Some(Value::Color(if let Some(a) = alpha { + Ok(Value::Color(if let Some(a) = alpha { let temp_alpha = color.alpha(); color.with_alpha(scale(temp_alpha, a, Number::from(1))) } else { @@ -178,7 +178,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Color(c) => c.clone(), _ => todo!("non-color given to builtin function `ie-hex-str()`") }; - Some(Value::Ident(color.to_ie_hex_str(), QuoteKind::None)) + Ok(Value::Ident(color.to_ie_hex_str(), QuoteKind::None)) }); } diff --git a/src/builtin/color/rgb.rs b/src/builtin/color/rgb.rs index 0afc2f8..ca2ba3b 100644 --- a/src/builtin/color/rgb.rs +++ b/src/builtin/color/rgb.rs @@ -35,7 +35,7 @@ pub(crate) fn register(f: &mut BTreeMap) { let color = Color::from_rgba(red, green, blue, Number::from(1)); - Some(Value::Color(color)) + Ok(Value::Color(color)) } else if args.len() == 2 { let color = match arg!(args, 0, "color").eval() { @@ -47,7 +47,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for alpha"), }; - Some(Value::Color(color.with_alpha(alpha))) + Ok(Value::Color(color.with_alpha(alpha))) } else { let red = match arg!(args, 0, "red").eval() { Value::Dimension(n, Unit::None) => n, @@ -69,7 +69,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for alpha") }; - Some(Value::Color(Color::from_rgba(red, green, blue, alpha))) + Ok(Value::Color(Color::from_rgba(red, green, blue, alpha))) } }); decl!(f "rgba", |args, _| { @@ -101,7 +101,7 @@ pub(crate) fn register(f: &mut BTreeMap) { let color = Color::from_rgba(red, green, blue, Number::from(1)); - Some(Value::Color(color)) + Ok(Value::Color(color)) } else if args.len() == 2 { let color = match arg!(args, 0, "color").eval() { @@ -113,7 +113,7 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for alpha"), }; - Some(Value::Color(color.with_alpha(alpha))) + Ok(Value::Color(color.with_alpha(alpha))) } else { let red = match arg!(args, 0, "red").eval() { Value::Dimension(n, Unit::None) => n, @@ -135,24 +135,24 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for alpha") }; - Some(Value::Color(Color::from_rgba(red, green, blue, alpha))) + Ok(Value::Color(Color::from_rgba(red, green, blue, alpha))) } }); decl!(f "red", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.red(), Unit::None)), + Value::Color(c) => Ok(Value::Dimension(c.red(), Unit::None)), _ => todo!("non-color given to builtin function `red()`") } }); decl!(f "green", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.green(), Unit::None)), + Value::Color(c) => Ok(Value::Dimension(c.green(), Unit::None)), _ => todo!("non-color given to builtin function `green()`") } }); decl!(f "blue", |args, _| { match arg!(args, 0, "color") { - Value::Color(c) => Some(Value::Dimension(c.blue(), Unit::None)), + Value::Color(c) => Ok(Value::Dimension(c.blue(), Unit::None)), _ => todo!("non-color given to builtin function `blue()`") } }); @@ -172,6 +172,6 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::Percent) => n / Number::from(100), _ => todo!("expected either unitless or % number for $weight") }; - Some(Value::Color(color1.mix(color2, weight))) + Ok(Value::Color(color1.mix(color2, weight))) }); } diff --git a/src/builtin/list.rs b/src/builtin/list.rs index 58acc76..55ec320 100644 --- a/src/builtin/list.rs +++ b/src/builtin/list.rs @@ -10,6 +10,6 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::List(v, _) => Number::from(v.len()), _ => Number::from(1) }; - Some(Value::Dimension(len, Unit::None)) + Ok(Value::Dimension(len, Unit::None)) }); } diff --git a/src/builtin/math.rs b/src/builtin/math.rs index 4c4def4..a890bd7 100644 --- a/src/builtin/math.rs +++ b/src/builtin/math.rs @@ -10,29 +10,29 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(n, Unit::None) => n * Number::from(100), _ => todo!("expected unitless number in builtin function `percentage()`") }; - Some(Value::Dimension(num, Unit::Percent)) + Ok(Value::Dimension(num, Unit::Percent)) }); decl!(f "round", |args, _| { match arg!(args, 0, "number").eval() { - Value::Dimension(n, u) => Some(Value::Dimension(n.round(), u)), + Value::Dimension(n, u) => Ok(Value::Dimension(n.round(), u)), _ => todo!("expected number in builtin function `round()`") } }); decl!(f "ceil", |args, _| { match arg!(args, 0, "number").eval() { - Value::Dimension(n, u) => Some(Value::Dimension(n.ceil(), u)), + Value::Dimension(n, u) => Ok(Value::Dimension(n.ceil(), u)), _ => todo!("expected number in builtin function `ceil()`") } }); decl!(f "floor", |args, _| { match arg!(args, 0, "number").eval() { - Value::Dimension(n, u) => Some(Value::Dimension(n.floor(), u)), + Value::Dimension(n, u) => Ok(Value::Dimension(n.floor(), u)), _ => todo!("expected number in builtin function `floor()`") } }); decl!(f "abs", |args, _| { match arg!(args, 0, "number").eval() { - Value::Dimension(n, u) => Some(Value::Dimension(n.abs(), u)), + Value::Dimension(n, u) => Ok(Value::Dimension(n.abs(), u)), _ => todo!("expected number in builtin function `abs()`") } }); @@ -46,6 +46,6 @@ pub(crate) fn register(f: &mut BTreeMap) { _ => todo!("$number2: ____ is not a number.") }; - Some(Value::bool(unit1.comparable(&unit2))) + Ok(Value::bool(unit1.comparable(&unit2))) }); } diff --git a/src/builtin/meta.rs b/src/builtin/meta.rs index edc0e02..6ef1224 100644 --- a/src/builtin/meta.rs +++ b/src/builtin/meta.rs @@ -11,9 +11,9 @@ pub(crate) fn register(f: &mut BTreeMap) { let if_true = arg!(args, 1, "if-true").clone(); let if_false = arg!(args, 2, "if-false").clone(); if cond.is_true() { - Some(if_true) + Ok(if_true) } else { - Some(if_false) + Ok(if_false) } }); decl!(f "feature-exists", |args, _| { @@ -21,20 +21,20 @@ pub(crate) fn register(f: &mut BTreeMap) { match feature.clone().unquote().to_string().as_str() { // A local variable will shadow a global variable unless // `!global` is used. - "global-variable-shadowing" => Some(Value::False), + "global-variable-shadowing" => Ok(Value::False), // the @extend rule will affect selectors nested in pseudo-classes // like :not() - "extend-selector-pseudoclass" => Some(Value::False), + "extend-selector-pseudoclass" => Ok(Value::False), // Full support for unit arithmetic using units defined in the // [Values and Units Level 3][] spec. - "units-level-3" => Some(Value::False), + "units-level-3" => Ok(Value::False), // The Sass `@error` directive is supported. - "at-error" => Some(Value::True), + "at-error" => Ok(Value::True), // The "Custom Properties Level 1" spec is supported. This means // that custom properties are parsed statically, with only // interpolation treated as SassScript. - "custom-property" => Some(Value::False), - _ => Some(Value::False), + "custom-property" => Ok(Value::False), + _ => Ok(Value::False), } }); decl!(f "unit", |args, _| { @@ -43,36 +43,36 @@ pub(crate) fn register(f: &mut BTreeMap) { Value::Dimension(_, u) => u.to_string(), _ => String::new() }; - Some(Value::Ident(unit, QuoteKind::Double)) + Ok(Value::Ident(unit, QuoteKind::Double)) }); decl!(f "type-of", |args, _| { let value = arg!(args, 0, "value"); - Some(Value::Ident(value.kind().to_owned(), QuoteKind::None)) + Ok(Value::Ident(value.kind().to_owned(), QuoteKind::None)) }); decl!(f "unitless", |args, _| { let number = arg!(args, 0, "number"); match number { - Value::Dimension(_, Unit::None) => Some(Value::True), - Value::Dimension(_, _) => Some(Value::False), - _ => Some(Value::True) + Value::Dimension(_, Unit::None) => Ok(Value::True), + Value::Dimension(_, _) => Ok(Value::False), + _ => Ok(Value::True) } }); decl!(f "inspect", |args, _| { let value = arg!(args, 0, "value"); - Some(Value::Ident(value.to_string(), QuoteKind::None)) + Ok(Value::Ident(value.to_string(), QuoteKind::None)) }); decl!(f "variable-exists", |args, scope| { let value = arg!(args, 0, "name"); - Some(Value::bool(scope.var_exists(&value.to_string()))) + Ok(Value::bool(scope.var_exists(&value.to_string()))) }); decl!(f "mixin-exists", |args, scope| { let value = arg!(args, 0, "name"); - Some(Value::bool(scope.mixin_exists(&value.to_string()))) + Ok(Value::bool(scope.mixin_exists(&value.to_string()))) }); decl!(f "function-exists", |args, scope| { let value = arg!(args, 0, "name"); let s = value.eval().unquote().to_string(); - Some(Value::bool(scope.fn_exists(&s) || GLOBAL_FUNCTIONS.contains_key(&s))) + Ok(Value::bool(scope.fn_exists(&s) || GLOBAL_FUNCTIONS.contains_key(&s))) }); decl!(f "call", |_args, _scope| { todo!("builtin function `call()` is blocked on refactoring how call args are stored and parsed") diff --git a/src/builtin/mod.rs b/src/builtin/mod.rs index 3cb388f..454f344 100644 --- a/src/builtin/mod.rs +++ b/src/builtin/mod.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; use crate::args::CallArgs; use crate::common::Scope; +use crate::error::SassResult; use crate::value::Value; #[macro_use] @@ -16,7 +17,7 @@ mod meta; mod selector; mod string; -pub(crate) type Builtin = Box Option + 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 5b0bf16..49c5fd9 100644 --- a/src/builtin/string.rs +++ b/src/builtin/string.rs @@ -13,33 +13,33 @@ pub(crate) fn register(f: &mut BTreeMap) { decl!(f "to-upper-case", |args, _| { let s: &Value = arg!(args, 0, "string"); match s.eval() { - Value::Ident(i, q) => Some(Value::Ident(i.to_ascii_uppercase(), q)), + Value::Ident(i, q) => Ok(Value::Ident(i.to_ascii_uppercase(), q)), _ => todo!("") } }); decl!(f "to-lower-case", |args, _| { let s: &Value = arg!(args, 0, "string"); match s.eval() { - Value::Ident(i, q) => Some(Value::Ident(i.to_ascii_lowercase(), q)), + Value::Ident(i, q) => Ok(Value::Ident(i.to_ascii_lowercase(), q)), _ => todo!("") } }); decl!(f "str-length", |args, _| { let s: &Value = arg!(args, 0, "string"); match s.eval() { - Value::Ident(i, _) => Some(Value::Dimension(Number::from(i.len()), Unit::None)), + Value::Ident(i, _) => Ok(Value::Dimension(Number::from(i.len()), Unit::None)), _ => todo!("") } }); decl!(f "quote", |args, _| { let s = arg!(args, 0, "string").eval(); match s { - Value::Ident(i, _) => Some(Value::Ident(i, QuoteKind::Double)), + Value::Ident(i, _) => Ok(Value::Ident(i, QuoteKind::Double)), _ => todo!("") } }); decl!(f "unquote", |args, _| { - Some(arg!(args, 0, "string").eval().unquote()) + Ok(arg!(args, 0, "string").eval().unquote()) }); decl!(f "str-slice", |args, _| { let (string, quotes) = match arg!(args, 0, "string").eval() { @@ -71,14 +71,14 @@ pub(crate) fn register(f: &mut BTreeMap) { if start > end || start > str_len { match quotes { - QuoteKind::Double | QuoteKind::Single => Some(Value::Ident(String::new(), QuoteKind::Double)), - QuoteKind::None => Some(Value::Null), + QuoteKind::Double | QuoteKind::Single => Ok(Value::Ident(String::new(), QuoteKind::Double)), + QuoteKind::None => Ok(Value::Null), } } else { let s = string[start-1..end].to_string(); match quotes { - QuoteKind::Double | QuoteKind::Single => Some(Value::Ident(s, QuoteKind::Double)), - QuoteKind::None => Some(Value::Ident(s, QuoteKind::None)), + QuoteKind::Double | QuoteKind::Single => Ok(Value::Ident(s, QuoteKind::Double)), + QuoteKind::None => Ok(Value::Ident(s, QuoteKind::None)), } } }); diff --git a/src/value/parse.rs b/src/value/parse.rs index 1cd879b..0611f7b 100644 --- a/src/value/parse.rs +++ b/src/value/parse.rs @@ -222,7 +222,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(&eat_call_args(toks, scope), scope).ok(), None => { s.push('('); let mut unclosed_parens = 0;