arg methods are now inherent to CallArgs, rather than parser

This commit is contained in:
Connor Skees 2020-07-10 21:42:10 -04:00
parent 3c756f661d
commit 5902ebd642
14 changed files with 245 additions and 314 deletions

View File

@ -5,7 +5,6 @@ use codemap::{Span, Spanned};
use crate::{
common::Identifier,
error::SassResult,
parse::Parser,
value::Value,
{Cow, Token},
};
@ -65,7 +64,7 @@ impl CallArgs {
CallArgs(HashMap::new(), span)
}
pub fn to_css_string(self, parser: &mut Parser<'_>) -> SassResult<Spanned<String>> {
pub fn to_css_string(self) -> SassResult<Spanned<String>> {
let mut string = String::with_capacity(2 + self.len() * 10);
string.push('(');
let mut span = self.1;
@ -77,7 +76,7 @@ impl CallArgs {
});
}
let args = match parser.variadic_args(self) {
let args = match self.get_variadic() {
Ok(v) => v,
Err(..) => {
return Err(("Plain CSS functions don't support keyword arguments.", span).into())
@ -123,11 +122,11 @@ impl CallArgs {
}
}
pub fn get_err(&mut self, position: usize, name: &'static str) -> SassResult<Spanned<Value>> {
pub fn get_err(&mut self, position: usize, name: &'static str) -> SassResult<Value> {
match self.get_named(name) {
Some(v) => v,
Some(v) => Ok(v?.node),
None => match self.get_positional(position) {
Some(v) => v,
Some(v) => Ok(v?.node),
None => Err((format!("Missing argument ${}.", name), self.span()).into()),
},
}
@ -190,4 +189,50 @@ impl CallArgs {
}
Ok(())
}
pub fn default_arg(
&mut self,
position: usize,
name: &'static str,
default: Value,
) -> SassResult<Value> {
Ok(match self.get(position, name) {
Some(val) => val?.node,
None => default,
})
}
pub fn positional_arg(&mut self, position: usize) -> Option<SassResult<Spanned<Value>>> {
self.get_positional(position)
}
#[allow(dead_code, clippy::unused_self)]
fn named_arg(&mut self, name: &'static str) -> Option<SassResult<Spanned<Value>>> {
self.get_named(name)
}
pub fn default_named_arg(&mut self, name: &'static str, default: Value) -> SassResult<Value> {
Ok(match self.get_named(name) {
Some(val) => val?.node,
None => default,
})
}
pub fn get_variadic(self) -> SassResult<Vec<Spanned<Value>>> {
let mut vals = Vec::new();
let mut args = match self
.0
.into_iter()
.map(|(a, v)| Ok((a.position()?, v)))
.collect::<Result<Vec<(usize, SassResult<Spanned<Value>>)>, String>>()
{
Ok(v) => v,
Err(e) => return Err((format!("No argument named ${}.", e), self.1).into()),
};
args.sort_by(|(a1, _), (a2, _)| a1.cmp(a2));
for arg in args {
vals.push(arg.1?);
}
Ok(vals)
}
}

View File

@ -18,7 +18,7 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
}
if args.len() == 1 {
let mut channels = match parser.arg(&mut args, 0, "channels")? {
let mut channels = match args.get_err(0, "channels")? {
Value::List(v, ..) => v,
_ => return Err(("Missing argument $channels.", args.span()).into()),
};
@ -77,11 +77,11 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
Number::one(),
))))
} else {
let hue = match parser.arg(&mut args, 0, "hue")? {
let hue = match args.get_err(0, "hue")? {
Value::Dimension(n, ..) => n,
v if v.is_special_function() => {
let saturation = parser.arg(&mut args, 1, "saturation")?;
let lightness = parser.arg(&mut args, 2, "lightness")?;
let saturation = args.get_err(1, "saturation")?;
let lightness = args.get_err(2, "lightness")?;
let mut string = format!(
"{}({}, {}, {}",
name,
@ -91,11 +91,7 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&parser
.arg(&mut args, 3, "alpha")?
.to_css_string(args.span())?,
);
string.push_str(&args.get_err(3, "alpha")?.to_css_string(args.span())?);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
@ -108,10 +104,10 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
};
let saturation = match parser.arg(&mut args, 1, "saturation")? {
let saturation = match args.get_err(1, "saturation")? {
Value::Dimension(n, ..) => n / Number::from(100),
v if v.is_special_function() => {
let lightness = parser.arg(&mut args, 2, "lightness")?;
let lightness = args.get_err(2, "lightness")?;
let mut string = format!(
"{}({}, {}, {}",
name,
@ -121,11 +117,7 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&parser
.arg(&mut args, 3, "alpha")?
.to_css_string(args.span())?,
);
string.push_str(&args.get_err(3, "alpha")?.to_css_string(args.span())?);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
@ -141,7 +133,7 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
};
let lightness = match parser.arg(&mut args, 2, "lightness")? {
let lightness = match args.get_err(2, "lightness")? {
Value::Dimension(n, ..) => n / Number::from(100),
v if v.is_special_function() => {
let mut string = format!(
@ -153,11 +145,7 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&parser
.arg(&mut args, 3, "alpha")?
.to_css_string(args.span())?,
);
string.push_str(&args.get_err(3, "alpha")?.to_css_string(args.span())?);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
@ -173,8 +161,7 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
};
let alpha = match parser.default_arg(
&mut args,
let alpha = match args.default_arg(
3,
"alpha",
Value::Dimension(Number::one(), Unit::None, true),
@ -228,7 +215,7 @@ fn hsla(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn hue(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.hue(), Unit::Deg, true)),
v => Err((
format!("$color: {} is not a color.", v.inspect(args.span())?),
@ -240,7 +227,7 @@ fn hue(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn saturation(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.saturation(), Unit::Percent, true)),
v => Err((
format!("$color: {} is not a color.", v.inspect(args.span())?),
@ -252,7 +239,7 @@ fn saturation(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn lightness(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.lightness(), Unit::Percent, true)),
v => Err((
format!("$color: {} is not a color.", v.inspect(args.span())?),
@ -264,7 +251,7 @@ fn lightness(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn adjust_hue(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -274,7 +261,7 @@ fn adjust_hue(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
.into())
}
};
let degrees = match parser.arg(&mut args, 1, "degrees")? {
let degrees = match args.get_err(1, "degrees")? {
Value::Dimension(n, ..) => n,
v => {
return Err((
@ -292,7 +279,7 @@ fn adjust_hue(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn lighten(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -302,7 +289,7 @@ fn lighten(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 100) / Number::from(100),
v => {
return Err((
@ -320,7 +307,7 @@ fn lighten(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn darken(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -330,7 +317,7 @@ fn darken(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 100) / Number::from(100),
v => {
return Err((
@ -352,15 +339,13 @@ fn saturate(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
return Ok(Value::String(
format!(
"saturate({})",
parser
.arg(&mut args, 0, "amount")?
.to_css_string(args.span())?
args.get_err(0, "amount")?.to_css_string(args.span())?
),
QuoteKind::None,
));
}
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 100) / Number::from(100),
v => {
return Err((
@ -373,7 +358,7 @@ fn saturate(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
Value::Dimension(n, u, _) => {
return Ok(Value::String(
@ -394,7 +379,7 @@ fn saturate(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn desaturate(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -404,7 +389,7 @@ fn desaturate(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
.into())
}
};
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 100) / Number::from(100),
v => {
return Err((
@ -422,7 +407,7 @@ fn desaturate(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn grayscale(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
Value::Dimension(n, u, _) => {
return Ok(Value::String(
@ -443,7 +428,7 @@ fn grayscale(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn complement(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -458,8 +443,7 @@ fn complement(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn invert(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let weight = match parser.default_arg(
&mut args,
let weight = match args.default_arg(
1,
"weight",
Value::Dimension(Number::from(100), Unit::Percent, true),
@ -476,7 +460,7 @@ fn invert(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Color(Box::new(c.invert(weight)))),
Value::Dimension(n, Unit::Percent, _) => {
Ok(Value::String(format!("invert({}%)", n), QuoteKind::None))

View File

@ -7,7 +7,7 @@ use crate::{
fn alpha(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.alpha(), Unit::None, true)),
v => Err((
format!("$color: {} is not a color.", v.inspect(args.span())?),
@ -19,7 +19,7 @@ fn alpha(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn opacity(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.alpha(), Unit::None, true)),
Value::Dimension(num, unit, _) => Ok(Value::String(
format!("opacity({}{})", num, unit),
@ -35,7 +35,7 @@ fn opacity(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn opacify(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -45,7 +45,7 @@ fn opacify(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 1),
v => {
return Err((
@ -60,7 +60,7 @@ fn opacify(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn fade_in(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -70,7 +70,7 @@ fn fade_in(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 1),
v => {
return Err((
@ -85,7 +85,7 @@ fn fade_in(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn transparentize(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -95,7 +95,7 @@ fn transparentize(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Val
.into())
}
};
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 1),
v => {
return Err((
@ -110,7 +110,7 @@ fn transparentize(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Val
fn fade_out(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -120,7 +120,7 @@ fn fade_out(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let amount = match parser.arg(&mut args, 1, "amount")? {
let amount = match args.get_err(1, "amount")? {
Value::Dimension(n, u, _) => bound!(args, "amount", n, u, 0, 1),
v => {
return Err((

View File

@ -13,8 +13,8 @@ use crate::{
};
macro_rules! opt_rgba {
($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal, $parser:ident) => {
let $name = match $parser.default_named_arg(&mut $args, $arg, Value::Null)? {
($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal) => {
let $name = match $args.default_named_arg($arg, Value::Null)? {
Value::Dimension(n, u, _) => Some(bound!($args, $arg, n, u, $low, $high)),
Value::Null => None,
v => {
@ -29,8 +29,8 @@ macro_rules! opt_rgba {
}
macro_rules! opt_hsl {
($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal, $parser:ident) => {
let $name = match $parser.default_named_arg(&mut $args, $arg, Value::Null)? {
($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal) => {
let $name = match $args.default_named_arg($arg, Value::Null)? {
Value::Dimension(n, u, _) => {
Some(bound!($args, $arg, n, u, $low, $high) / Number::from(100))
}
@ -47,7 +47,7 @@ macro_rules! opt_hsl {
}
fn change_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
if parser.positional_arg(&mut args, 1).is_some() {
if args.positional_arg(1).is_some() {
return Err((
"Only one positional argument is allowed. All other arguments must be passed by name.",
args.span(),
@ -55,7 +55,7 @@ fn change_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
.into());
}
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -66,10 +66,10 @@ fn change_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
}
};
opt_rgba!(args, alpha, "alpha", 0, 1, parser);
opt_rgba!(args, red, "red", 0, 255, parser);
opt_rgba!(args, green, "green", 0, 255, parser);
opt_rgba!(args, blue, "blue", 0, 255, parser);
opt_rgba!(args, alpha, "alpha", 0, 1);
opt_rgba!(args, red, "red", 0, 255);
opt_rgba!(args, green, "green", 0, 255);
opt_rgba!(args, blue, "blue", 0, 255);
if red.is_some() || green.is_some() || blue.is_some() {
return Ok(Value::Color(Box::new(Color::from_rgba(
@ -80,7 +80,7 @@ fn change_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
))));
}
let hue = match parser.default_named_arg(&mut args, "hue", Value::Null)? {
let hue = match args.default_named_arg("hue", Value::Null)? {
Value::Dimension(n, ..) => Some(n),
Value::Null => None,
v => {
@ -92,8 +92,8 @@ fn change_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
}
};
opt_hsl!(args, saturation, "saturation", 0, 100, parser);
opt_hsl!(args, luminance, "lightness", 0, 100, parser);
opt_hsl!(args, saturation, "saturation", 0, 100);
opt_hsl!(args, luminance, "lightness", 0, 100);
if hue.is_some() || saturation.is_some() || luminance.is_some() {
// Color::as_hsla() returns more exact values than Color::hue(), etc.
@ -114,7 +114,7 @@ fn change_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
}
fn adjust_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -125,10 +125,10 @@ fn adjust_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
}
};
opt_rgba!(args, alpha, "alpha", -1, 1, parser);
opt_rgba!(args, red, "red", -255, 255, parser);
opt_rgba!(args, green, "green", -255, 255, parser);
opt_rgba!(args, blue, "blue", -255, 255, parser);
opt_rgba!(args, alpha, "alpha", -1, 1);
opt_rgba!(args, red, "red", -255, 255);
opt_rgba!(args, green, "green", -255, 255);
opt_rgba!(args, blue, "blue", -255, 255);
if red.is_some() || green.is_some() || blue.is_some() {
return Ok(Value::Color(Box::new(Color::from_rgba(
@ -139,7 +139,7 @@ fn adjust_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
))));
}
let hue = match parser.default_named_arg(&mut args, "hue", Value::Null)? {
let hue = match args.default_named_arg("hue", Value::Null)? {
Value::Dimension(n, ..) => Some(n),
Value::Null => None,
v => {
@ -151,8 +151,8 @@ fn adjust_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
}
};
opt_hsl!(args, saturation, "saturation", -100, 100, parser);
opt_hsl!(args, luminance, "lightness", -100, 100, parser);
opt_hsl!(args, saturation, "saturation", -100, 100);
opt_hsl!(args, luminance, "lightness", -100, 100);
if hue.is_some() || saturation.is_some() || luminance.is_some() {
// Color::as_hsla() returns more exact values than Color::hue(), etc.
@ -184,7 +184,7 @@ fn scale_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
}
let span = args.span();
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((
@ -196,8 +196,8 @@ fn scale_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
};
macro_rules! opt_scale_arg {
($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal, $parser:ident) => {
let $name = match $parser.default_named_arg(&mut $args, $arg, Value::Null)? {
($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal) => {
let $name = match $args.default_named_arg($arg, Value::Null)? {
Value::Dimension(n, Unit::Percent, _) => {
Some(bound!($args, $arg, n, Unit::Percent, $low, $high) / Number::from(100))
}
@ -224,10 +224,10 @@ fn scale_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
};
}
opt_scale_arg!(args, alpha, "alpha", -100, 100, parser);
opt_scale_arg!(args, red, "red", -100, 100, parser);
opt_scale_arg!(args, green, "green", -100, 100, parser);
opt_scale_arg!(args, blue, "blue", -100, 100, parser);
opt_scale_arg!(args, alpha, "alpha", -100, 100);
opt_scale_arg!(args, red, "red", -100, 100);
opt_scale_arg!(args, green, "green", -100, 100);
opt_scale_arg!(args, blue, "blue", -100, 100);
if red.is_some() || green.is_some() || blue.is_some() {
return Ok(Value::Color(Box::new(Color::from_rgba(
@ -254,8 +254,8 @@ fn scale_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
))));
}
opt_scale_arg!(args, saturation, "saturation", -100, 100, parser);
opt_scale_arg!(args, luminance, "lightness", -100, 100, parser);
opt_scale_arg!(args, saturation, "saturation", -100, 100);
opt_scale_arg!(args, luminance, "lightness", -100, 100);
if saturation.is_some() || luminance.is_some() {
// Color::as_hsla() returns more exact values than Color::hue(), etc.
@ -290,7 +290,7 @@ fn scale_color(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn ie_hex_str(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v => {
return Err((

View File

@ -21,7 +21,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
}
if args.len() == 1 {
let mut channels = match parser.arg(&mut args, 0, "channels")? {
let mut channels = match args.get_err(0, "channels")? {
Value::List(v, ..) => v,
_ => return Err(("Missing argument $channels.", args.span()).into()),
};
@ -125,10 +125,10 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
Ok(Value::Color(Box::new(color)))
} else if args.len() == 2 {
let color = match parser.arg(&mut args, 0, "color")? {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v if v.is_special_function() => {
let alpha = parser.arg(&mut args, 1, "alpha")?;
let alpha = args.get_err(1, "alpha")?;
return Ok(Value::String(
format!(
"{}({}, {})",
@ -147,7 +147,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
};
let alpha = match parser.arg(&mut args, 1, "alpha")? {
let alpha = match args.get_err(1, "alpha")? {
Value::Dimension(n, Unit::None, _) => n,
Value::Dimension(n, Unit::Percent, _) => n / Number::from(100),
v @ Value::Dimension(..) => {
@ -183,7 +183,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
};
Ok(Value::Color(Box::new(color.with_alpha(alpha))))
} else {
let red = match parser.arg(&mut args, 0, "red")? {
let red = match args.get_err(0, "red")? {
Value::Dimension(n, Unit::None, _) => n,
Value::Dimension(n, Unit::Percent, _) => (n / Number::from(100)) * Number::from(255),
v @ Value::Dimension(..) => {
@ -197,8 +197,8 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
v if v.is_special_function() => {
let green = parser.arg(&mut args, 1, "green")?;
let blue = parser.arg(&mut args, 2, "blue")?;
let green = args.get_err(1, "green")?;
let blue = args.get_err(2, "blue")?;
let mut string = format!(
"{}({}, {}, {}",
name,
@ -208,11 +208,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&parser
.arg(&mut args, 3, "alpha")?
.to_css_string(args.span())?,
);
string.push_str(&args.get_err(3, "alpha")?.to_css_string(args.span())?);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
@ -225,7 +221,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
};
let green = match parser.arg(&mut args, 1, "green")? {
let green = match args.get_err(1, "green")? {
Value::Dimension(n, Unit::None, _) => n,
Value::Dimension(n, Unit::Percent, _) => (n / Number::from(100)) * Number::from(255),
v @ Value::Dimension(..) => {
@ -239,7 +235,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
v if v.is_special_function() => {
let blue = parser.arg(&mut args, 2, "blue")?;
let blue = args.get_err(2, "blue")?;
let mut string = format!(
"{}({}, {}, {}",
name,
@ -249,11 +245,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&parser
.arg(&mut args, 3, "alpha")?
.to_css_string(args.span())?,
);
string.push_str(&args.get_err(3, "alpha")?.to_css_string(args.span())?);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
@ -266,7 +258,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
};
let blue = match parser.arg(&mut args, 2, "blue")? {
let blue = match args.get_err(2, "blue")? {
Value::Dimension(n, Unit::None, _) => n,
Value::Dimension(n, Unit::Percent, _) => (n / Number::from(100)) * Number::from(255),
v @ Value::Dimension(..) => {
@ -289,11 +281,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&parser
.arg(&mut args, 3, "alpha")?
.to_css_string(args.span())?,
);
string.push_str(&args.get_err(3, "alpha")?.to_css_string(args.span())?);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
@ -306,8 +294,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser<'_>) ->
.into())
}
};
let alpha = match parser.default_arg(
&mut args,
let alpha = match args.default_arg(
3,
"alpha",
Value::Dimension(Number::one(), Unit::None, true),
@ -359,7 +346,7 @@ fn rgba(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn red(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.red(), Unit::None, true)),
v => Err((
format!("$color: {} is not a color.", v.inspect(args.span())?),
@ -371,7 +358,7 @@ fn red(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn green(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.green(), Unit::None, true)),
v => Err((
format!("$color: {} is not a color.", v.inspect(args.span())?),
@ -383,7 +370,7 @@ fn green(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn blue(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "color")? {
match args.get_err(0, "color")? {
Value::Color(c) => Ok(Value::Dimension(c.blue(), Unit::None, true)),
v => Err((
format!("$color: {} is not a color.", v.inspect(args.span())?),
@ -395,7 +382,7 @@ fn blue(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn mix(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let color1 = match parser.arg(&mut args, 0, "color1")? {
let color1 = match args.get_err(0, "color1")? {
Value::Color(c) => c,
v => {
return Err((
@ -406,7 +393,7 @@ fn mix(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
}
};
let color2 = match parser.arg(&mut args, 1, "color2")? {
let color2 = match args.get_err(1, "color2")? {
Value::Color(c) => c,
v => {
return Err((
@ -417,8 +404,7 @@ fn mix(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
}
};
let weight = match parser.default_arg(
&mut args,
let weight = match args.default_arg(
2,
"weight",
Value::Dimension(Number::from(50), Unit::None, true),

View File

@ -14,7 +14,7 @@ use crate::{
fn length(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
Ok(Value::Dimension(
Number::from(parser.arg(&mut args, 0, "list")?.as_list().len()),
Number::from(args.get_err(0, "list")?.as_list().len()),
Unit::None,
true,
))
@ -22,8 +22,8 @@ fn length(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn nth(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let mut list = parser.arg(&mut args, 0, "list")?.as_list();
let n = match parser.arg(&mut args, 1, "n")? {
let mut list = args.get_err(0, "list")?.as_list();
let n = match args.get_err(1, "n")? {
Value::Dimension(num, ..) => num,
v => {
return Err((
@ -64,7 +64,7 @@ fn nth(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn list_separator(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
Ok(Value::String(
match parser.arg(&mut args, 0, "list")? {
match args.get_err(0, "list")? {
Value::List(_, sep, ..) => sep.name(),
_ => ListSeparator::Space.name(),
}
@ -75,12 +75,12 @@ fn list_separator(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Val
fn set_nth(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let (mut list, sep, brackets) = match parser.arg(&mut args, 0, "list")? {
let (mut list, sep, brackets) = match args.get_err(0, "list")? {
Value::List(v, sep, b) => (v, sep, b),
Value::Map(m) => (m.as_list(), ListSeparator::Comma, Brackets::None),
v => (vec![v], ListSeparator::Space, Brackets::None),
};
let n = match parser.arg(&mut args, 1, "n")? {
let n = match args.get_err(1, "n")? {
Value::Dimension(num, ..) => num,
v => {
return Err((
@ -109,7 +109,7 @@ fn set_nth(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
return Err((format!("$n: {} is not an int.", n), args.span()).into());
}
let val = parser.arg(&mut args, 2, "value")?;
let val = args.get_err(2, "value")?;
if n.is_positive() {
list[n.to_integer().to_usize().unwrap_or(std::usize::MAX) - 1] = val;
@ -122,13 +122,12 @@ fn set_nth(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn append(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let (mut list, sep, brackets) = match parser.arg(&mut args, 0, "list")? {
let (mut list, sep, brackets) = match args.get_err(0, "list")? {
Value::List(v, sep, b) => (v, sep, b),
v => (vec![v], ListSeparator::Space, Brackets::None),
};
let val = parser.arg(&mut args, 1, "val")?;
let sep = match parser.default_arg(
&mut args,
let val = args.get_err(1, "val")?;
let sep = match args.default_arg(
2,
"separator",
Value::String("auto".to_owned(), QuoteKind::None),
@ -161,18 +160,17 @@ fn append(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn join(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(4)?;
let (mut list1, sep1, brackets) = match parser.arg(&mut args, 0, "list1")? {
let (mut list1, sep1, brackets) = match args.get_err(0, "list1")? {
Value::List(v, sep, brackets) => (v, sep, brackets),
Value::Map(m) => (m.as_list(), ListSeparator::Comma, Brackets::None),
v => (vec![v], ListSeparator::Space, Brackets::None),
};
let (list2, sep2) = match parser.arg(&mut args, 1, "list2")? {
let (list2, sep2) = match args.get_err(1, "list2")? {
Value::List(v, sep, ..) => (v, sep),
Value::Map(m) => (m.as_list(), ListSeparator::Comma),
v => (vec![v], ListSeparator::Space),
};
let sep = match parser.default_arg(
&mut args,
let sep = match args.default_arg(
2,
"separator",
Value::String("auto".to_owned(), QuoteKind::None),
@ -204,8 +202,7 @@ fn join(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
}
};
let brackets = match parser.default_arg(
&mut args,
let brackets = match args.default_arg(
3,
"bracketed",
Value::String("auto".to_owned(), QuoteKind::None),
@ -230,7 +227,7 @@ fn join(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn is_bracketed(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
Ok(Value::bool(match parser.arg(&mut args, 0, "list")? {
Ok(Value::bool(match args.get_err(0, "list")? {
Value::List(.., brackets) => match brackets {
Brackets::Bracketed => true,
Brackets::None => false,
@ -241,8 +238,8 @@ fn is_bracketed(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
fn index(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let list = parser.arg(&mut args, 0, "list")?.as_list();
let value = parser.arg(&mut args, 1, "value")?;
let list = args.get_err(0, "list")?.as_list();
let value = args.get_err(1, "value")?;
// TODO: find a way to propagate any errors here
// Potential input to fuzz: index(1px 1in 1cm, 96px + 1rem)
let index = match list.into_iter().position(|v| v == value) {
@ -253,8 +250,8 @@ fn index(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
}
fn zip(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
let lists = parser
.variadic_args(args)?
let lists = args
.get_variadic()?
.into_iter()
.map(|x| x.node.as_list())
.collect::<Vec<Vec<Value>>>();

View File

@ -10,8 +10,8 @@ use crate::{
fn map_get(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let key = parser.arg(&mut args, 1, "key")?;
let map = match parser.arg(&mut args, 0, "map")? {
let key = args.get_err(1, "key")?;
let map = match args.get_err(0, "map")? {
Value::Map(m) => m,
Value::List(v, ..) if v.is_empty() => SassMap::new(),
Value::ArgList(v) if v.is_empty() => SassMap::new(),
@ -28,8 +28,8 @@ fn map_get(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn map_has_key(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let key = parser.arg(&mut args, 1, "key")?;
let map = match parser.arg(&mut args, 0, "map")? {
let key = args.get_err(1, "key")?;
let map = match args.get_err(0, "map")? {
Value::Map(m) => m,
Value::List(v, ..) if v.is_empty() => SassMap::new(),
Value::ArgList(v) if v.is_empty() => SassMap::new(),
@ -46,7 +46,7 @@ fn map_has_key(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn map_keys(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let map = match parser.arg(&mut args, 0, "map")? {
let map = match args.get_err(0, "map")? {
Value::Map(m) => m,
Value::List(v, ..) if v.is_empty() => SassMap::new(),
Value::ArgList(v) if v.is_empty() => SassMap::new(),
@ -67,7 +67,7 @@ fn map_keys(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn map_values(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let map = match parser.arg(&mut args, 0, "map")? {
let map = match args.get_err(0, "map")? {
Value::Map(m) => m,
Value::List(v, ..) if v.is_empty() => SassMap::new(),
Value::ArgList(v) if v.is_empty() => SassMap::new(),
@ -88,7 +88,7 @@ fn map_values(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn map_merge(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let mut map1 = match parser.arg(&mut args, 0, "map1")? {
let mut map1 = match args.get_err(0, "map1")? {
Value::Map(m) => m,
Value::List(v, ..) if v.is_empty() => SassMap::new(),
Value::ArgList(v) if v.is_empty() => SassMap::new(),
@ -100,7 +100,7 @@ fn map_merge(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let map2 = match parser.arg(&mut args, 1, "map2")? {
let map2 = match args.get_err(1, "map2")? {
Value::Map(m) => m,
Value::List(v, ..) if v.is_empty() => SassMap::new(),
Value::ArgList(v) if v.is_empty() => SassMap::new(),
@ -117,7 +117,7 @@ fn map_merge(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
}
fn map_remove(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
let mut map = match parser.arg(&mut args, 0, "map")? {
let mut map = match args.get_err(0, "map")? {
Value::Map(m) => m,
Value::List(v, ..) if v.is_empty() => SassMap::new(),
Value::ArgList(v) if v.is_empty() => SassMap::new(),
@ -129,7 +129,7 @@ fn map_remove(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
.into())
}
};
let keys = parser.variadic_args(args)?;
let keys = args.get_variadic()?;
for key in keys {
map.remove(&key);
}

View File

@ -15,7 +15,7 @@ use crate::{
fn percentage(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let num = match parser.arg(&mut args, 0, "number")? {
let num = match args.get_err(0, "number")? {
Value::Dimension(n, Unit::None, _) => n * Number::from(100),
v @ Value::Dimension(..) => {
return Err((
@ -40,7 +40,7 @@ fn percentage(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn round(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "number")? {
match args.get_err(0, "number")? {
Value::Dimension(n, u, _) => Ok(Value::Dimension(n.round(), u, true)),
v => Err((
format!("$number: {} is not a number.", v.inspect(args.span())?),
@ -52,7 +52,7 @@ fn round(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn ceil(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "number")? {
match args.get_err(0, "number")? {
Value::Dimension(n, u, _) => Ok(Value::Dimension(n.ceil(), u, true)),
v => Err((
format!("$number: {} is not a number.", v.inspect(args.span())?),
@ -64,7 +64,7 @@ fn ceil(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn floor(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "number")? {
match args.get_err(0, "number")? {
Value::Dimension(n, u, _) => Ok(Value::Dimension(n.floor(), u, true)),
v => Err((
format!("$number: {} is not a number.", v.inspect(args.span())?),
@ -76,7 +76,7 @@ fn floor(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn abs(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "number")? {
match args.get_err(0, "number")? {
Value::Dimension(n, u, _) => Ok(Value::Dimension(n.abs(), u, true)),
v => Err((
format!("$number: {} is not a number.", v.inspect(args.span())?),
@ -88,7 +88,7 @@ fn abs(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn comparable(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let unit1 = match parser.arg(&mut args, 0, "number1")? {
let unit1 = match args.get_err(0, "number1")? {
Value::Dimension(_, u, _) => u,
v => {
return Err((
@ -98,7 +98,7 @@ fn comparable(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
.into())
}
};
let unit2 = match parser.arg(&mut args, 1, "number2")? {
let unit2 = match args.get_err(1, "number2")? {
Value::Dimension(_, u, _) => u,
v => {
return Err((
@ -116,7 +116,7 @@ fn comparable(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
#[cfg(feature = "random")]
fn random(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let limit = match parser.default_arg(&mut args, 0, "limit", Value::Null)? {
let limit = match args.default_arg(0, "limit", Value::Null)? {
Value::Dimension(n, ..) => n,
Value::Null => {
let mut rng = rand::thread_rng();
@ -173,8 +173,8 @@ fn random(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn min(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.min_args(1)?;
let span = args.span();
let mut nums = parser
.variadic_args(args)?
let mut nums = args
.get_variadic()?
.into_iter()
.map(|val| match val.node {
Value::Dimension(number, unit, _) => Ok((number, unit)),
@ -211,8 +211,8 @@ fn min(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn max(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.min_args(1)?;
let span = args.span();
let mut nums = parser
.variadic_args(args)?
let mut nums = args
.get_variadic()?
.into_iter()
.map(|val| match val.node {
Value::Dimension(number, unit, _) => Ok((number, unit)),

View File

@ -13,16 +13,16 @@ use crate::{
fn if_(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
if parser.arg(&mut args, 0, "condition")?.is_true() {
Ok(parser.arg(&mut args, 1, "if-true")?)
if args.get_err(0, "condition")?.is_true() {
Ok(args.get_err(1, "if-true")?)
} else {
Ok(parser.arg(&mut args, 2, "if-false")?)
Ok(args.get_err(2, "if-false")?)
}
}
fn feature_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "feature")? {
match args.get_err(0, "feature")? {
#[allow(clippy::match_same_arms)]
Value::String(s, _) => Ok(match s.as_str() {
// A local variable will shadow a global variable unless
@ -52,7 +52,7 @@ fn feature_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Val
fn unit(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let unit = match parser.arg(&mut args, 0, "number")? {
let unit = match args.get_err(0, "number")? {
Value::Dimension(_, u, _) => u.to_string(),
v => {
return Err((
@ -67,14 +67,14 @@ fn unit(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn type_of(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let value = parser.arg(&mut args, 0, "value")?;
let value = args.get_err(0, "value")?;
Ok(Value::String(value.kind().to_owned(), QuoteKind::None))
}
fn unitless(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
#[allow(clippy::match_same_arms)]
Ok(match parser.arg(&mut args, 0, "number")? {
Ok(match args.get_err(0, "number")? {
Value::Dimension(_, Unit::None, _) => Value::True,
Value::Dimension(..) => Value::False,
_ => Value::True,
@ -84,17 +84,14 @@ fn unitless(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn inspect(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
Ok(Value::String(
parser
.arg(&mut args, 0, "value")?
.inspect(args.span())?
.into_owned(),
args.get_err(0, "value")?.inspect(args.span())?.into_owned(),
QuoteKind::None,
))
}
fn variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "name")? {
match args.get_err(0, "name")? {
Value::String(s, _) => Ok(Value::bool(
parser.scopes.var_exists(s.into(), parser.global_scope),
)),
@ -108,7 +105,7 @@ fn variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Va
fn global_variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "name")? {
match args.get_err(0, "name")? {
Value::String(s, _) => Ok(Value::bool(parser.global_scope.var_exists(s.into()))),
v => Err((
format!("$name: {} is not a string.", v.inspect(args.span())?),
@ -120,7 +117,7 @@ fn global_variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassRe
fn mixin_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
match parser.arg(&mut args, 0, "name")? {
match args.get_err(0, "name")? {
Value::String(s, _) => Ok(Value::bool(
parser.scopes.mixin_exists(s.into(), parser.global_scope),
)),
@ -134,7 +131,7 @@ fn mixin_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
fn function_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
match parser.arg(&mut args, 0, "name")? {
match args.get_err(0, "name")? {
Value::String(s, _) => Ok(Value::bool(
parser.scopes.fn_exists(s.into(), parser.global_scope),
)),
@ -148,7 +145,7 @@ fn function_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Va
fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let name: Identifier = match parser.arg(&mut args, 0, "name")? {
let name: Identifier = match args.get_err(0, "name")? {
Value::String(s, _) => s.into(),
v => {
return Err((
@ -158,10 +155,8 @@ fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
.into())
}
};
let css = parser
.default_arg(&mut args, 1, "css", Value::False)?
.is_true();
let module = match parser.default_arg(&mut args, 2, "module", Value::Null)? {
let css = args.default_arg(1, "css", Value::False)?.is_true();
let module = match args.default_arg(2, "module", Value::Null)? {
Value::String(s, ..) => Some(s),
Value::Null => None,
v => {
@ -199,7 +194,7 @@ fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
}
fn call(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
let func = match parser.arg(&mut args, 0, "function")? {
let func = match args.get_err(0, "function")? {
Value::FunctionRef(f) => f,
v => {
return Err((

View File

@ -1,3 +1,6 @@
// A reference to the parser is only necessary for some functions
#![allow(unused_variables)]
use std::{
collections::HashMap,
sync::atomic::{AtomicUsize, Ordering},

View File

@ -11,12 +11,10 @@ use crate::{
fn is_superselector(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let parent_selector = parser
.arg(&mut args, 0, "super")?
let parent_selector = args
.get_err(0, "super")?
.to_selector(parser, "super", false)?;
let child_selector = parser
.arg(&mut args, 1, "sub")?
.to_selector(parser, "sub", false)?;
let child_selector = args.get_err(1, "sub")?.to_selector(parser, "sub", false)?;
Ok(Value::bool(
parent_selector.is_super_selector(&child_selector),
@ -26,8 +24,8 @@ fn is_superselector(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<V
fn simple_selectors(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
// todo: Value::to_compound_selector
let selector = parser
.arg(&mut args, 0, "selector")?
let selector = args
.get_err(0, "selector")?
.to_selector(parser, "selector", false)?;
if selector.0.components.len() != 1 {
@ -55,15 +53,15 @@ fn simple_selectors(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<V
fn selector_parse(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
Ok(parser
.arg(&mut args, 0, "selector")?
Ok(args
.get_err(0, "selector")?
.to_selector(parser, "selector", false)?
.into_value())
}
fn selector_nest(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
let span = args.span();
let selectors = parser.variadic_args(args)?;
let selectors = args.get_variadic()?;
if selectors.is_empty() {
return Err(("$selectors: At least one selector must be passed.", span).into());
}
@ -84,7 +82,7 @@ fn selector_nest(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn selector_append(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
let span = args.span();
let selectors = parser.variadic_args(args)?;
let selectors = args.get_variadic()?;
if selectors.is_empty() {
return Err(("$selectors: At least one selector must be passed.", span).into());
}
@ -142,14 +140,14 @@ fn selector_append(args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn selector_extend(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let selector = parser
.arg(&mut args, 0, "selector")?
let selector = args
.get_err(0, "selector")?
.to_selector(parser, "selector", false)?;
let target = parser
.arg(&mut args, 1, "extendee")?
let target = args
.get_err(1, "extendee")?
.to_selector(parser, "extendee", false)?;
let source = parser
.arg(&mut args, 2, "extender")?
let source = args
.get_err(2, "extender")?
.to_selector(parser, "extender", false)?;
Ok(Extender::extend(selector.0, source.0, target.0, args.span())?.to_sass_list())
@ -157,25 +155,23 @@ fn selector_extend(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Va
fn selector_replace(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let selector = parser
.arg(&mut args, 0, "selector")?
let selector = args
.get_err(0, "selector")?
.to_selector(parser, "selector", false)?;
let target = parser
.arg(&mut args, 1, "original")?
let target = args
.get_err(1, "original")?
.to_selector(parser, "original", false)?;
let source =
parser
.arg(&mut args, 2, "replacement")?
.to_selector(parser, "replacement", false)?;
let source = args
.get_err(2, "replacement")?
.to_selector(parser, "replacement", false)?;
Ok(Extender::replace(selector.0, source.0, target.0, args.span())?.to_sass_list())
}
fn selector_unify(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let selector1 =
parser
.arg(&mut args, 0, "selector1")?
.to_selector(parser, "selector1", false)?;
let selector1 = args
.get_err(0, "selector1")?
.to_selector(parser, "selector1", false)?;
if selector1.contains_parent_selector() {
return Err((
@ -185,10 +181,9 @@ fn selector_unify(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Val
.into());
}
let selector2 =
parser
.arg(&mut args, 1, "selector2")?
.to_selector(parser, "selector2", false)?;
let selector2 = args
.get_err(1, "selector2")?
.to_selector(parser, "selector2", false)?;
if selector2.contains_parent_selector() {
return Err((

View File

@ -17,7 +17,7 @@ use crate::{
fn to_upper_case(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "string")? {
match args.get_err(0, "string")? {
Value::String(mut i, q) => {
i.make_ascii_uppercase();
Ok(Value::String(i, q))
@ -32,7 +32,7 @@ fn to_upper_case(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Valu
fn to_lower_case(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "string")? {
match args.get_err(0, "string")? {
Value::String(mut i, q) => {
i.make_ascii_lowercase();
Ok(Value::String(i, q))
@ -47,7 +47,7 @@ fn to_lower_case(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Valu
fn str_length(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "string")? {
match args.get_err(0, "string")? {
Value::String(i, _) => Ok(Value::Dimension(
Number::from(i.chars().count()),
Unit::None,
@ -63,7 +63,7 @@ fn str_length(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
fn quote(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "string")? {
match args.get_err(0, "string")? {
Value::String(i, _) => Ok(Value::String(i, QuoteKind::Quoted)),
v => Err((
format!("$string: {} is not a string.", v.inspect(args.span())?),
@ -75,7 +75,7 @@ fn quote(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn unquote(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
match parser.arg(&mut args, 0, "string")? {
match args.get_err(0, "string")? {
i @ Value::String(..) => Ok(i.unquote()),
v => Err((
format!("$string: {} is not a string.", v.inspect(args.span())?),
@ -87,7 +87,7 @@ fn unquote(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn str_slice(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let (string, quotes) = match parser.arg(&mut args, 0, "string")? {
let (string, quotes) = match args.get_err(0, "string")? {
Value::String(s, q) => (s, q),
v => {
return Err((
@ -98,7 +98,7 @@ fn str_slice(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
}
};
let str_len = string.chars().count();
let start = match parser.arg(&mut args, 1, "start-at")? {
let start = match args.get_err(1, "start-at")? {
Value::Dimension(n, Unit::None, _) if n.is_decimal() => {
return Err((format!("{} is not an int.", n), args.span()).into())
}
@ -128,7 +128,7 @@ fn str_slice(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
.into())
}
};
let mut end = match parser.default_arg(&mut args, 2, "end-at", Value::Null)? {
let mut end = match args.default_arg(2, "end-at", Value::Null)? {
Value::Dimension(n, Unit::None, _) if n.is_decimal() => {
return Err((format!("{} is not an int.", n), args.span()).into())
}
@ -180,7 +180,7 @@ fn str_slice(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn str_index(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
let s1 = match parser.arg(&mut args, 0, "string")? {
let s1 = match args.get_err(0, "string")? {
Value::String(i, _) => i,
v => {
return Err((
@ -191,7 +191,7 @@ fn str_index(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
}
};
let substr = match parser.arg(&mut args, 1, "substring")? {
let substr = match args.get_err(1, "substring")? {
Value::String(i, _) => i,
v => {
return Err((
@ -210,7 +210,7 @@ fn str_index(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn str_insert(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(3)?;
let (s1, quotes) = match parser.arg(&mut args, 0, "string")? {
let (s1, quotes) = match args.get_err(0, "string")? {
Value::String(i, q) => (i, q),
v => {
return Err((
@ -221,7 +221,7 @@ fn str_insert(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
}
};
let substr = match parser.arg(&mut args, 1, "insert")? {
let substr = match args.get_err(1, "insert")? {
Value::String(i, _) => i,
v => {
return Err((
@ -232,7 +232,7 @@ fn str_insert(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value>
}
};
let index = match parser.arg(&mut args, 2, "index")? {
let index = match args.get_err(2, "index")? {
Value::Dimension(n, Unit::None, _) if n.is_decimal() => {
return Err((format!("$index: {} is not an int.", n), args.span()).into())
}

View File

@ -277,80 +277,6 @@ impl<'a> Parser<'a> {
}
impl<'a> Parser<'a> {
#[allow(clippy::unused_self)]
pub fn arg(
&self,
args: &mut CallArgs,
position: usize,
name: &'static str,
) -> SassResult<Value> {
Ok(args.get_err(position, name)?.node)
}
#[allow(clippy::unused_self)]
pub fn default_arg(
&self,
args: &mut CallArgs,
position: usize,
name: &'static str,
default: Value,
) -> SassResult<Value> {
Ok(match args.get(position, name) {
Some(val) => val?.node,
None => default,
})
}
#[allow(clippy::unused_self)]
pub fn positional_arg(
&self,
args: &mut CallArgs,
position: usize,
) -> Option<SassResult<Spanned<Value>>> {
args.get_positional(position)
}
#[allow(dead_code, clippy::unused_self)]
fn named_arg(
&self,
args: &mut CallArgs,
name: &'static str,
) -> Option<SassResult<Spanned<Value>>> {
args.get_named(name)
}
#[allow(clippy::unused_self)]
pub fn default_named_arg(
&self,
args: &mut CallArgs,
name: &'static str,
default: Value,
) -> SassResult<Value> {
Ok(match args.get_named(name) {
Some(val) => val?.node,
None => default,
})
}
#[allow(clippy::unused_self)]
pub fn variadic_args(&self, args: CallArgs) -> SassResult<Vec<Spanned<Value>>> {
let mut vals = Vec::new();
let mut args = match args
.0
.into_iter()
.map(|(a, v)| Ok((a.position()?, v)))
.collect::<Result<Vec<(usize, SassResult<Spanned<Value>>)>, String>>()
{
Ok(v) => v,
Err(e) => return Err((format!("No argument named ${}.", e), args.1).into()),
};
args.sort_by(|(a1, _), (a2, _)| a1.cmp(a2));
for arg in args {
vals.push(arg.1?);
}
Ok(vals)
}
pub(super) fn eval_args(&mut self, fn_args: FuncArgs, mut args: CallArgs) -> SassResult<Scope> {
let mut scope = Scope::new();
if fn_args.0.is_empty() {
@ -361,7 +287,7 @@ impl<'a> Parser<'a> {
for (idx, mut arg) in fn_args.0.into_iter().enumerate() {
if arg.is_variadic {
let span = args.span();
let arg_list = Value::ArgList(self.variadic_args(args)?);
let arg_list = Value::ArgList(args.get_variadic()?);
scope.insert_var(
arg.name,
Spanned {

View File

@ -284,9 +284,9 @@ impl<'a> Parser<'a> {
}
"url" => match self.try_parse_url()? {
Some(val) => s = val,
None => s.push_str(&self.parse_call_args()?.to_css_string(self)?),
None => s.push_str(&self.parse_call_args()?.to_css_string()?),
},
_ => s.push_str(&self.parse_call_args()?.to_css_string(self)?),
_ => s.push_str(&self.parse_call_args()?.to_css_string()?),
}
return Ok(IntermediateValue::Value(HigherIntermediateValue::Literal(