use std::{collections::HashMap, rc::Rc};
use pax_runtime_api::{
functions::Functions, CoercionRules, Color, ColorChannel, Numeric, PaxValue, Size,
};
use crate::{interpreter::compute_paxel, DependencyCollector};
use super::{parse_pax_expression, PaxExpression, PaxInfix, PaxOperator, PaxPrimary};
fn initialize_test_resolver() -> Rc<HashMap<String, PaxValue>> {
Functions::register_all_functions();
let mut idr = HashMap::new();
idr.insert("a".to_string(), PaxValue::Numeric(Numeric::I64(10)));
idr.insert("b".to_string(), PaxValue::Numeric(Numeric::I64(4)));
idr.insert(
"c".to_string(),
PaxValue::Vec(vec![
PaxValue::Numeric(Numeric::I64(1)),
PaxValue::Numeric(Numeric::I64(2)),
]),
);
idr.insert(
"d".to_string(),
PaxValue::Object(
vec![
("a".to_string(), PaxValue::Numeric(Numeric::I64(1))),
("b".to_string(), PaxValue::Numeric(Numeric::I64(2))),
]
.into_iter()
.collect(),
),
);
idr.insert(
"e".to_string(),
PaxValue::Object(
vec![
("a".to_string(), PaxValue::Numeric(Numeric::I64(1))),
("b".to_string(), PaxValue::Numeric(Numeric::I64(2))),
(
"c".to_string(),
PaxValue::Object(
vec![
("a".to_string(), PaxValue::Numeric(Numeric::I64(1))),
("b".to_string(), PaxValue::Numeric(Numeric::I64(2))),
]
.into_iter()
.collect(),
),
),
]
.into_iter()
.collect(),
),
);
Rc::new(idr)
}
#[test]
fn test_ast() {
let expr = "10 + 4";
let expected = PaxExpression::Infix(Box::new(PaxInfix {
operator: PaxOperator {
name: "+".to_string(),
},
lhs: Box::new(PaxExpression::Primary(Box::new(PaxPrimary::Literal(
PaxValue::Numeric(Numeric::I64(10)),
)))),
rhs: Box::new(PaxExpression::Primary(Box::new(PaxPrimary::Literal(
PaxValue::Numeric(Numeric::I64(4)),
)))),
}));
let v = parse_pax_expression(expr).unwrap();
assert_eq!(expected, v);
}
#[test]
fn test_addition() {
let idr = initialize_test_resolver();
let expr = "10 + 4";
let expected = PaxValue::Numeric(Numeric::I64(14));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_subtraction() {
let idr = initialize_test_resolver();
let expr = "10 - 4";
let expected = PaxValue::Numeric(Numeric::I64(6));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_multiplication() {
let idr = initialize_test_resolver();
let expr = "10 * 4";
let expected = PaxValue::Numeric(Numeric::I64(40));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_division() {
let idr = initialize_test_resolver();
let expr = "10.0 / 4";
let expected = PaxValue::Numeric(Numeric::F64(2.5));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_exponentiation() {
let idr = initialize_test_resolver();
let expr = "10 ^ 4";
let expected = PaxValue::Numeric(Numeric::F64(10000.0));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_modulus() {
let idr = initialize_test_resolver();
let expr = "10 %% 4";
let expected = PaxValue::Numeric(Numeric::I64(2));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_rel_eq() {
let idr = initialize_test_resolver();
let expr = "10 == 4";
let expected: PaxValue = PaxValue::Bool(false);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_rel_gt() {
let idr = initialize_test_resolver();
let expr = "10 > 4";
let expected = PaxValue::Bool(true);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_rel_gte() {
let idr = initialize_test_resolver();
let expr = "10 >= 4";
let expected = PaxValue::Bool(true);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_rel_lt() {
let idr = initialize_test_resolver();
let expr = "10 < 4";
let expected = PaxValue::Bool(false);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_rel_lte() {
let idr = initialize_test_resolver();
let expr = "10 <= 4";
let expected = PaxValue::Bool(false);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_rel_neq() {
let idr = initialize_test_resolver();
let expr = "10 != 4";
let expected = PaxValue::Bool(true);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_bool_and() {
let idr = initialize_test_resolver();
let expr = "true && false";
let expected = PaxValue::Bool(false);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_bool_or() {
let idr = initialize_test_resolver();
let expr = "true || false";
let expected = PaxValue::Bool(true);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_parentheses() {
let idr = initialize_test_resolver();
let expr = "(10 + 4) * 2";
let expected = PaxValue::Numeric(Numeric::I64(28));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_parentheses_units() {
let idr = initialize_test_resolver();
let expr = "(10 + 4)px";
let expected = PaxValue::Size(Size::Pixels(Numeric::I64(14)));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_adding_strings() {
let idr = initialize_test_resolver();
let expr = "\"hello\" + \" world\"";
let expected = PaxValue::String("hello world".to_string());
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_function_call() {
let idr = initialize_test_resolver();
let expr = "Math::min(3,5)";
let expected = PaxValue::Numeric(Numeric::I64(3));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_function_call_with_expression() {
let idr = initialize_test_resolver();
let expr = "Math::min(10,3 + 1)";
let expected = PaxValue::Numeric(Numeric::I64(4));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_function_call_with_expression_and_variable() {
let idr = initialize_test_resolver();
let expr = "Math::min(a,3 + 1)";
let expected = PaxValue::Numeric(Numeric::I64(4));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_expr_to_numeric() {
let idr = initialize_test_resolver();
let expr = "Math::min(a,Math::max(3,1))";
let expected = Numeric::from(3);
let result = Numeric::try_coerce(compute_paxel(expr, idr).unwrap()).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_object_expression() {
let idr = initialize_test_resolver();
let expr = "{a: 10+4, b: true || false }";
let expected = PaxValue::Object(
vec![
("a".to_string(), PaxValue::Numeric(Numeric::I64(14))),
("b".to_string(), PaxValue::Bool(true)),
]
.into_iter()
.collect(),
);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_nested_object_expression() {
let idr = initialize_test_resolver();
let expr = "{a: 10+4, b: {c: 10, d: 50-30} }";
let expected = PaxValue::Object(
vec![
("a".to_string(), PaxValue::Numeric(Numeric::I64(14))),
(
"b".to_string(),
PaxValue::Object(
vec![
("c".to_string(), PaxValue::Numeric(Numeric::I64(10))),
("d".to_string(), PaxValue::Numeric(Numeric::I64(20))),
]
.into_iter()
.collect(),
),
),
]
.into_iter()
.collect(),
);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_range_expression() {
let idr = initialize_test_resolver();
let expr = "a..b";
let expected = PaxValue::Range(
Box::new(PaxValue::Numeric(Numeric::I64(10))),
Box::new(PaxValue::Numeric(Numeric::I64(4))),
);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_tuple_expression() {
let idr = initialize_test_resolver();
let expr = "(a, b)";
let expected = PaxValue::Vec(vec![
PaxValue::Numeric(Numeric::I64(10)),
PaxValue::Numeric(Numeric::I64(4)),
]);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_list_expression() {
let idr = initialize_test_resolver();
let expr = "[a, b]";
let expected = PaxValue::Vec(vec![
PaxValue::Numeric(Numeric::I64(10)),
PaxValue::Numeric(Numeric::I64(4)),
]);
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_tuple_access() {
let idr = initialize_test_resolver();
let expr = "c.0";
let expected = PaxValue::Numeric(Numeric::I64(1));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_list_access() {
let idr = initialize_test_resolver();
let expr = "c[1]";
let expected = PaxValue::Numeric(Numeric::I64(2));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_color_expression() {
let idr = initialize_test_resolver();
let expr = "rgba(10, 20, 30,4)";
let result = compute_paxel(expr, idr).unwrap();
let expected = PaxValue::Color(Box::new(Color::rgba(
ColorChannel::Integer(10),
ColorChannel::Integer(20),
ColorChannel::Integer(30),
ColorChannel::Integer(4),
)));
assert_eq!(expected, result);
}
#[test]
fn test_struct_access() {
let idr = initialize_test_resolver();
let expr = "d.a";
let expected = PaxValue::Numeric(Numeric::I64(1));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_triple_nesting_struct_access() {
let idr = initialize_test_resolver();
let expr = "e.c.a";
let expected = PaxValue::Numeric(Numeric::I64(1));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_collect_dependencies() {
let expr = "a + b";
let expected = vec!["a".to_string(), "b".to_string()];
let result = PaxExpression::collect_dependencies(&parse_pax_expression(expr).unwrap());
assert_eq!(expected, result);
}
#[test]
fn test_negative_size() {
let idr = initialize_test_resolver();
let expr = "-10px";
let expected = PaxValue::Size(Size::Pixels(Numeric::I64(-10)));
let result = compute_paxel(expr, idr).unwrap();
assert_eq!(expected, result);
}
#[test]
fn test_display_expression() {
let expr = "10 + 4";
let expected = "10 + 4";
let result = format!("{}", parse_pax_expression(expr).unwrap());
assert_eq!(expected, result);
}
#[test]
fn test_display_complex_expression() {
let expr = "Math::min(a,Math::max(3,1))";
let expected = "Math::min(a, Math::max(3, 1))";
let result = format!("{}", parse_pax_expression(expr).unwrap());
assert_eq!(expected, result);
}
#[test]
fn test_display_object() {
let expr = "{a: 10+4, b: true || false }";
let expected = "{a: 10 + 4, b: true || false}";
let result = format!("{}", parse_pax_expression(expr).unwrap());
assert_eq!(expected, result);
}