Implement mul and div for Value and builtin function percentage()

This commit is contained in:
ConnorSkees 2020-02-09 16:05:07 -05:00
parent c7f1941823
commit 405a1c2d42
5 changed files with 153 additions and 9 deletions

View File

@ -1 +1,16 @@
use std::collections::BTreeMap;
use super::Builtin;
use crate::units::Unit;
use crate::value::{Number, Value};
pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
decl!(f "percentage", |args, _| {
let arg = dbg!(arg!(args, 0, "number").eval());
let num = match arg {
Value::Dimension(n, Unit::None) => n * Number::from(100),
_ => todo!("expected unitless number in builtin function `percentage()`")
};
Some(Value::Dimension(num, Unit::Percent))
});
}

View File

@ -22,6 +22,7 @@ lazy_static! {
pub(crate) static ref GLOBAL_FUNCTIONS: BTreeMap<String, Builtin> = {
let mut m = BTreeMap::new();
color::register(&mut m);
math::register(&mut m);
meta::register(&mut m);
string::register(&mut m);
m

View File

@ -98,6 +98,8 @@ impl Value {
Op::Minus => *lhs.clone() - *rhs.clone(),
Op::Equal => Self::bool(*lhs == *rhs),
Op::NotEqual => Self::bool(*lhs != *rhs),
Op::Mul => *lhs.clone() * *rhs.clone(),
Op::Div => *lhs.clone() / *rhs.clone(),
_ => Self::BinaryOp(lhs.clone(), *op, rhs.clone()),
},
_ => self.clone(),

View File

@ -1,6 +1,7 @@
use std::ops::{Add, Sub};
use std::ops::{Add, Sub, Mul, Div};
use crate::common::QuoteKind;
use crate::units::Unit;
use crate::value::Value;
impl Add for Value {
@ -78,12 +79,9 @@ impl Sub for Value {
fn sub(self, other: Self) -> Self {
match self {
// Self::Important => todo!(),
// Self::True => todo!(),
// Self::False => todo!(),
// Self::Null => todo!(),
Self::Null => todo!(),
Self::Dimension(num, unit) => match other {
// Self::Dimension(num2, unit2) => Value::Dimension(num - num2, unit),
Self::Dimension(num2, unit2) => Value::Dimension(num - num2, unit),
_ => todo!(),
},
// Self::List(..) => todo!(),
@ -99,8 +97,8 @@ impl Sub for Value {
Self::Dimension(..) => todo!("investigate adding numbers and colors"),
_ => Value::Ident(format!("{}-{}", c, other), QuoteKind::None),
},
// Self::BinaryOp(..) => todo!(),
// Self::Paren(..) => todo!(),
Self::BinaryOp(..)
| Self::Paren(..) => self.eval(),
Self::Ident(s1, quotes1) => match other {
Self::Ident(s2, quotes2) => {
let quotes1 = match quotes1 {
@ -139,7 +137,115 @@ impl Sub for Value {
}
_ => todo!(),
},
_ => todo!(),
_ => match other {
Self::Ident(s, quotes) => {
let quotes = match quotes {
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
QuoteKind::None => QuoteKind::None,
};
Value::Ident(format!("{}-{}{}{}", self, quotes, s, quotes), QuoteKind::None)
}
Self::Null => Value::Ident(format!("{}-", self), QuoteKind::None),
_ => Value::Ident(format!("{}-{}", self, other), QuoteKind::None),
},
}
}
}
impl Mul for Value {
type Output = Self;
fn mul(self, other: Self) -> Self {
match self {
Self::Null => todo!(),
Self::Dimension(num, unit) => match other {
Self::Dimension(num2, unit2) => Value::Dimension(num - num2, unit),
_ => todo!(),
},
Self::BinaryOp(..)
| Self::Paren(..) => self.eval(),
_ => todo!("incompatible mul types")
}
}
}
impl Div for Value {
type Output = Self;
fn div(self, other: Self) -> Self {
match self {
Self::Null => todo!(),
Self::Dimension(num, unit) => match other {
Self::Dimension(num2, unit2) => if unit == unit2 {
Value::Dimension(num / num2, Unit::None)
} else {
todo!("unit conversions")
},
_ => todo!(),
},
// Self::List(..) => todo!(),
Self::Color(c) => match other {
Self::Ident(s, quotes) => {
let quotes = match quotes {
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
QuoteKind::None => QuoteKind::None,
};
Value::Ident(format!("{}/{}{}{}", c, quotes, s, quotes), QuoteKind::None)
}
Self::Null => Value::Ident(format!("{}/", c), QuoteKind::None),
Self::Dimension(..) => todo!("investigate adding numbers and colors"),
_ => Value::Ident(format!("{}/{}", c, other), QuoteKind::None),
},
Self::BinaryOp(..)
| Self::Paren(..) => self.eval(),
Self::Ident(s1, quotes1) => match other {
Self::Ident(s2, quotes2) => {
let quotes1 = match quotes1 {
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
QuoteKind::None => QuoteKind::None,
};
let quotes2 = match quotes2 {
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
QuoteKind::None => QuoteKind::None,
};
Value::Ident(
format!("{}{}{}/{}{}{}", quotes1, s1, quotes1, quotes2, s2, quotes2),
QuoteKind::None,
)
}
Self::Important
| Self::True
| Self::False
| Self::Dimension(..)
| Self::Color(..) => {
let quotes = match quotes1 {
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
QuoteKind::None => QuoteKind::None,
};
Value::Ident(
format!("{}{}{}/{}", quotes, s1, quotes, other),
QuoteKind::None,
)
}
Self::Null => {
let quotes = match quotes1 {
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
QuoteKind::None => QuoteKind::None,
};
Value::Ident(format!("{}{}{}/", quotes, s1, quotes), QuoteKind::None)
}
_ => todo!(),
},
_ => match other {
Self::Ident(s, quotes) => {
let quotes = match quotes {
QuoteKind::Double | QuoteKind::Single => QuoteKind::Double,
QuoteKind::None => QuoteKind::None,
};
Value::Ident(format!("{}/{}{}{}", self, quotes, s, quotes), QuoteKind::None)
}
Self::Null => Value::Ident(format!("{}/", self), QuoteKind::None),
_ => Value::Ident(format!("{}/{}", self, other), QuoteKind::None),
},
}
}
}

20
tests/math.rs Normal file
View File

@ -0,0 +1,20 @@
#![cfg(test)]
#[macro_use]
mod macros;
test!(
percentage_decimal,
"a {\n color: percentage(0.2);\n}\n",
"a {\n color: 20%;\n}\n"
);
test!(
percentage_division,
"a {\n color: percentage(100px / 50px);\n}\n",
"a {\n color: 200%;\n}\n"
);
test!(
integer_division,
"a {\n color: percentage(2);\n}\n",
"a {\n color: 200%;\n}\n"
);