diff --git a/src/builtin/meta.rs b/src/builtin/meta.rs index 1daf253..052ab5f 100644 --- a/src/builtin/meta.rs +++ b/src/builtin/meta.rs @@ -44,4 +44,8 @@ pub(crate) fn register(f: &mut BTreeMap) { }; Some(Value::Ident(unit, QuoteKind::Double)) }); + decl!(f "type-of", |args| { + let value = arg!(args, 0, "value"); + Some(Value::Ident(value.kind().to_owned(), QuoteKind::None)) + }); } \ No newline at end of file diff --git a/src/value.rs b/src/value.rs index 8763b65..6f90035 100644 --- a/src/value.rs +++ b/src/value.rs @@ -197,11 +197,7 @@ impl Display for Value { .join(sep.as_str()) ), Self::Color(c) => write!(f, "{}", c), - Self::BinaryOp(lhs, op, rhs) => match op { - Op::Plus => write!(f, "{}", *lhs.clone() + *rhs.clone()), - Op::Minus => write!(f, "{}", *lhs.clone() - *rhs.clone()), - _ => write!(f, "{}{}{}", lhs, op, rhs), - }, + Self::BinaryOp(..) => write!(f, "{}", self.eval()), Self::Paren(val) => write!(f, "{}", val), Self::Ident(val, kind) => write!(f, "{}{}{}", kind.as_str(), val, kind.as_str()), Self::True => write!(f, "true"), @@ -227,6 +223,32 @@ impl Value { } } + pub fn kind(&self) -> &'static str { + match self { + Value::Color(..) => "color", + Value::Ident(..) => "string", + Value::Dimension(..) => "number", + Value::List(..) => "list", + // Value::Function(..) => "function", + Value::True | Value::False => "bool", + Value::Null => "null", + Value::BinaryOp(..) => self.eval().kind(), + _ => "unknown", + + } + } + + pub fn eval(&self) -> Self { + match self { + Self::BinaryOp(lhs, op, rhs) => match op { + Op::Plus => *lhs.clone() + *rhs.clone(), + Op::Minus => *lhs.clone() - *rhs.clone(), + _ => Self::BinaryOp(lhs.clone(), op.clone(), rhs.clone()), + } + _ => self.clone(), + } + } + pub fn from_tokens>( toks: &mut Peekable, scope: &Scope, diff --git a/tests/meta.rs b/tests/meta.rs index 68cb07a..2031ca7 100644 --- a/tests/meta.rs +++ b/tests/meta.rs @@ -58,3 +58,68 @@ test!( "a {\n color: unit($number: 1px)\n}\n", "a {\n color: \"px\";\n}\n" ); +test!( + type_of_number, + "a {\n color: type-of(1)\n}\n", + "a {\n color: number;\n}\n" +); +test!( + type_of_number_unit, + "a {\n color: type-of(1px)\n}\n", + "a {\n color: number;\n}\n" +); +test!( + type_of_unquoted, + "a {\n color: type-of(foo)\n}\n", + "a {\n color: string;\n}\n" +); +test!( + type_of_sgl_unquoted, + "a {\n color: type-of('red')\n}\n", + "a {\n color: string;\n}\n" +); +test!( + type_of_dbl_unquoted, + "a {\n color: type-of(\"red\")\n}\n", + "a {\n color: string;\n}\n" +); +// test!( +// type_of_3_hex_color, +// "a {\n color: type-of(#fff)\n}\n", +// "a {\n color: color;\n}\n" +// ); +// test!( +// type_of_6_hex_color, +// "a {\n color: type-of(#ffffff)\n}\n", +// "a {\n color: color;\n}\n" +// ); +// test!( +// type_of_named_color, +// "a {\n color: type-of(red)\n}\n", +// "a {\n color: color;\n}\n" +// ); +// test!( +// type_of_spaced_list, +// "a {\n color: type-of(1 2 3)\n}\n", +// "a {\n color: list;\n}\n" +// ); +test!( + type_of_true, + "a {\n color: type-of(true)\n}\n", + "a {\n color: bool;\n}\n" +); +test!( + type_of_false, + "a {\n color: type-of(false)\n}\n", + "a {\n color: bool;\n}\n" +); +test!( + type_of_null, + "a {\n color: type-of(null)\n}\n", + "a {\n color: null;\n}\n" +); +test!( + type_of_ident_plus_ident, + "a {\n color: type-of(hi + bye)\n}\n", + "a {\n color: string;\n}\n" +);