implement builtin function nth

This commit is contained in:
ConnorSkees 2020-03-20 12:09:08 -04:00
parent fb84361fae
commit dd1c1e5b06
3 changed files with 58 additions and 4 deletions

View File

@ -1,5 +1,7 @@
use std::collections::HashMap;
use num_traits::cast::ToPrimitive;
use super::Builtin;
use crate::unit::Unit;
use crate::value::{Number, Value};
@ -16,4 +18,41 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
Ok(Value::Dimension(len, Unit::None))
}),
);
f.insert(
"nth".to_owned(),
Box::new(|args, _| {
max_args!(args, 2);
let list = match arg!(args, 0, "list") {
Value::List(v, _) => v,
_ => return Err("Missing argument $list.".into()),
};
let n = match arg!(args, 1, "n") {
Value::Dimension(num, _) => num,
v => return Err(format!("$n: {} is not a number.", v).into()),
};
if n == Number::from(0) {
return Err("$n: List index may not be 0.".into());
}
if n.abs() > Number::from(list.len()) {
return Err(format!(
"$n: Invalid index {} for a list with {} elements.",
n,
list.len()
)
.into());
}
if n.is_decimal() {
return Err(format!("$n: {} is not an int.", n).into());
}
if n > Number::from(0) {
Ok(list[n.to_integer().to_usize().unwrap() - 1].clone())
} else {
Ok(list[list.len() - n.abs().to_integer().to_usize().unwrap()].clone())
}
}),
);
}

View File

@ -28,25 +28,25 @@ impl Number {
Number::new(BigRational::new(a.into(), b.into()))
}
pub fn round(self) -> Self {
pub fn round(&self) -> Self {
Number {
val: self.val.round(),
}
}
pub fn ceil(self) -> Self {
pub fn ceil(&self) -> Self {
Number {
val: self.val.ceil(),
}
}
pub fn floor(self) -> Self {
pub fn floor(&self) -> Self {
Number {
val: self.val.floor(),
}
}
pub fn abs(self) -> Self {
pub fn abs(&self) -> Self {
Number {
val: self.val.abs(),
}

View File

@ -18,3 +18,18 @@ test!(
"a {\n color: length((1, 2, 3, 4, 5));\n}\n",
"a {\n color: 5;\n}\n"
);
test!(
nth_space_separated,
"a {\n color: nth(a b c, 1);\n}\n",
"a {\n color: a;\n}\n"
);
test!(
nth_negative_index,
"a {\n color: nth(a b c, -2);\n}\n",
"a {\n color: b;\n}\n"
);
test!(
nth_comma_separated,
"a {\n color: nth((a, b, c), 3);\n}\n",
"a {\n color: c;\n}\n"
);