use pattern_wishcast::pattern_wishcast;
pattern_wishcast! {
enum StrictValue = Literal | { Lambda { param: String, body: Box<Term> } };
enum StuckValue = Variable | { Apply { func: Box<StuckValue>, arg: Box<FlexValue> } };
enum FlexValue = StrictValue | StuckValue;
enum Term = FlexValue;
}
#[derive(Debug, Clone)]
pub struct Literal {
pub value: i32,
}
#[derive(Debug, Clone)]
pub struct Variable {
pub name: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_composition() {
let lit = Literal { value: 42 };
let strict: StrictValue = lit.into();
let flex: FlexValue = strict.into();
let term: Term = flex.into();
let var = Variable { name: "x".to_string() };
let stuck: StuckValue = var.into();
let _flex2: FlexValue = stuck.into();
match term {
Term::FlexValue(FlexValue::StrictValue(StrictValue::Literal(lit))) => {
assert_eq!(lit.value, 42);
}
_ => panic!("Expected literal"),
}
}
#[test]
fn test_inline_variants() {
let lambda = StrictValue::Lambda {
param: "x".to_string(),
body: Box::new(Term::FlexValue(FlexValue::StuckValue(StuckValue::Variable(Variable {
name: "x".to_string(),
})))),
};
match lambda {
StrictValue::Lambda { param, body: _ } => {
assert_eq!(param, "x");
}
_ => panic!("Expected lambda"),
}
}
}