arglists are lists too

This commit is contained in:
ConnorSkees 2020-06-17 05:24:42 -04:00
parent 1f82d65eac
commit 82ffd0ddde
4 changed files with 40 additions and 23 deletions

View File

@ -1,6 +1,6 @@
use super::{Builtin, GlobalFunctionMap}; use super::{Builtin, GlobalFunctionMap};
use num_traits::{One, Signed, ToPrimitive, Zero}; use num_traits::{Signed, ToPrimitive, Zero};
use crate::{ use crate::{
args::CallArgs, args::CallArgs,
@ -13,12 +13,10 @@ use crate::{
fn length(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> { fn length(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?; args.max_args(1)?;
let len = match parser.arg(&mut args, 0, "list")? { Ok(Value::Dimension(
Value::List(v, ..) => Number::from(v.len()), Number::from(parser.arg(&mut args, 0, "list")?.as_list().len()),
Value::Map(m) => Number::from(m.len()), Unit::None,
_ => Number::one(), ))
};
Ok(Value::Dimension(len, Unit::None))
} }
fn nth(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> { fn nth(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {

View File

@ -856,14 +856,7 @@ impl<'a> Parser<'a> {
self.whitespace(); self.whitespace();
let iter_val_toks = read_until_open_curly_brace(self.toks)?; let iter_val_toks = read_until_open_curly_brace(self.toks)?;
let iter_val = self.parse_value_from_vec(iter_val_toks)?; let iter_val = self.parse_value_from_vec(iter_val_toks)?;
let iter = match iter_val.node.eval(iter_val.span)?.node { let iter = iter_val.node.eval(iter_val.span)?.node.as_list();
Value::List(v, ..) => v,
Value::Map(m) => m
.into_iter()
.map(|(k, v)| Value::List(vec![k, v], ListSeparator::Space, Brackets::None))
.collect(),
v => vec![v],
};
self.toks.next(); self.toks.next();
self.whitespace(); self.whitespace();
let mut body = read_until_closing_curly_brace(self.toks)?; let mut body = read_until_closing_curly_brace(self.toks)?;
@ -873,14 +866,7 @@ impl<'a> Parser<'a> {
let mut stmts = Vec::new(); let mut stmts = Vec::new();
for row in iter { for row in iter {
let this_iterator = match row { let this_iterator = row.as_list();
Value::List(v, ..) => v,
Value::Map(m) => m
.into_iter()
.map(|(k, v)| Value::List(vec![k, v], ListSeparator::Space, Brackets::None))
.collect(),
v => vec![v],
};
if vars.len() == 1 { if vars.len() == 1 {
if this_iterator.len() == 1 { if this_iterator.len() == 1 {

View File

@ -317,6 +317,7 @@ impl Value {
match self { match self {
Value::List(v, ..) => v, Value::List(v, ..) => v,
Value::Map(m) => m.entries(), Value::Map(m) => m.entries(),
Value::ArgList(v) => v.into_iter().map(|val| val.node).collect(),
v => vec![v], v => vec![v],
} }
} }

32
tests/arglist.rs Normal file
View File

@ -0,0 +1,32 @@
#![cfg(test)]
#[macro_use]
mod macros;
test!(
length_of_empty_arglist,
"@mixin foo($a...) {\n color: length($list: $a);\n}\na {\n @include foo;\n}\n",
"a {\n color: 0;\n}\n"
);
test!(
length_of_arglist_in_mixin,
"@mixin foo($a...) {\n color: length($list: $a);\n}\na {\n @include foo(a, 2, c);\n}\n",
"a {\n color: 3;\n}\n"
);
test!(
arglist_in_at_each,
"@function sum($numbers...) {
$sum: 0;
@each $number in $numbers {
$sum: $sum + $number;
}
@return $sum;
}
a {
width: sum(50px, 30px, 100px);
}",
"a {\n width: 180px;\n}\n"
);