allow NaN to take units and refactor math.acos

This commit is contained in:
Connor Skees 2020-07-26 23:45:00 -04:00
parent 78da4ad2fe
commit fbcee00bdd
3 changed files with 65 additions and 7 deletions

View File

@ -1,5 +1,7 @@
use std::cmp::Ordering;
use num_traits::{One, Zero};
use crate::{
args::CallArgs,
builtin::{
@ -180,10 +182,45 @@ macro_rules! trig_fn {
trig_fn!(cos, cos_deg);
trig_fn!(sin, sin_deg);
trig_fn!(tan, tan_deg);
trig_fn!(acos, acos_deg);
trig_fn!(asin, asin_deg);
trig_fn!(atan, atan_deg);
fn acos(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?;
let number = args.get_err(0, "number")?;
Ok(match number {
Value::Dimension(Some(n), Unit::None, ..) => {
if n > Number::from(1) || n < Number::from(-1) {
return Ok(Value::Dimension(None, Unit::Deg, true));
} else if n.is_one() {
return Ok(Value::Dimension(Some(Number::zero()), Unit::Deg, true));
}
Value::Dimension(n.acos(), Unit::Deg, true)
}
v @ Value::Dimension(Some(..), ..) => {
return Err((
format!(
"$number: Expected {} to be unitless.",
v.inspect(args.span())?
),
args.span(),
)
.into())
}
Value::Dimension(None, ..) => Value::Dimension(None, Unit::Deg, true),
v => {
return Err((
format!("$number: {} is not a number.", v.inspect(args.span())?),
args.span(),
)
.into())
}
})
}
fn atan2(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?;
todo!()

View File

@ -202,13 +202,24 @@ impl Value {
pub fn to_css_string(&self, span: Span) -> SassResult<Cow<'static, str>> {
Ok(match self {
Value::Important => Cow::const_str("!important"),
Value::Dimension(Some(num), unit, _) => match unit {
Value::Dimension(num, unit, _) => match unit {
Unit::Mul(..) | Unit::Div(..) => {
return Err((format!("{}{} isn't a valid CSS value.", num, unit), span).into());
if let Some(num) = num {
return Err(
(format!("{}{} isn't a valid CSS value.", num, unit), span).into()
);
} else {
return Err((format!("NaN{} isn't a valid CSS value.", unit), span).into());
}
}
_ => {
if let Some(num) = num {
Cow::owned(format!("{}{}", num, unit))
} else {
Cow::owned(format!("NaN{}", unit))
}
}
_ => Cow::owned(format!("{}{}", num, unit)),
},
Value::Dimension(None, ..) => Cow::const_str("NaN"),
Value::Map(..) | Value::FunctionRef(..) => {
return Err((
format!("{} isn't a valid CSS value.", self.inspect(span)?),
@ -470,7 +481,7 @@ impl Value {
.join(", ")
)),
Value::Dimension(Some(num), unit, _) => Cow::owned(format!("{}{}", num, unit)),
Value::Dimension(None, ..) => Cow::const_str("NaN"),
Value::Dimension(None, unit, ..) => Cow::owned(format!("NaN{}", unit)),
Value::ArgList(args) if args.is_empty() => Cow::const_str("()"),
Value::ArgList(args) if args.len() == 1 => Cow::owned(format!(
"({},)",

View File

@ -140,12 +140,22 @@ macro_rules! trig_fn(
}
);
macro_rules! inverse_trig_fn(
($name:ident) => {
pub fn $name(self) -> Option<Self> {
Some(Number::Big(Box::new(BigRational::from_float(
self.as_float()?.$name().to_degrees(),
)?)))
}
}
);
/// Trigonometry methods
impl Number {
trig_fn!(cos, cos_deg);
trig_fn!(sin, sin_deg);
trig_fn!(tan, tan_deg);
trig_fn!(acos, acos_deg);
inverse_trig_fn!(acos);
trig_fn!(asin, asin_deg);
trig_fn!(atan, atan_deg);
}