diff options
Diffstat (limited to 'rust/src/lambda.rs')
| -rw-r--r-- | rust/src/lambda.rs | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/rust/src/lambda.rs b/rust/src/lambda.rs index ee5cb1f..3a8372b 100644 --- a/rust/src/lambda.rs +++ b/rust/src/lambda.rs @@ -117,6 +117,11 @@ pub fn generate_expr(size: u32, runner: &mut TestRunner) -> Value { 6 => simple_lambda().new_tree(runner).unwrap().current(), 7 => app_to_lambda().new_tree(runner).unwrap().current(), 8 => multi_app().new_tree(runner).unwrap().current(), + 9 => any::<u16>() + .prop_flat_map(gen_terms) + .new_tree(runner) + .unwrap() + .current(), _ => todo!(), } } @@ -157,6 +162,34 @@ fn app_to_lambda() -> impl Strategy<Value = Value> { (lam, arg).prop_map(|(l, a)| Value::App(Box::new(l), Box::new(a))) } +fn pairing(k: u16) -> (u16, u16) { + let a = ((((8 * (k as u32) + 1) as f32).sqrt() - 1.0) / 2.0).floor(); + let b = (a * (a + 1.0)) / 2.0; + let n = (k as f32) - b; + (n as u16, (a - n) as u16) +} + +fn gen_terms(u: u16) -> impl Strategy<Value = Value> { + if u % 2 != 0 { + let j = (u - 1) / 2; + if j % 2 == 0 { + let k = j / 2; + let (n, m) = pairing(k); + let r = (gen_terms(n), gen_terms(m)) + .prop_map(move |(l, r)| Value::App(Box::new(l), Box::new(r))); + r.boxed() + } else { + let k = (j - 1) / 2; + let (n, m) = pairing(k); + let r = gen_terms(m).prop_map(move |v| Value::Lam(format!("x_{}", n), Box::new(v))); + r.boxed() + } + } else { + let j = u / 2; + Just(Value::Sym(format!("x_{}", j))).boxed() + } +} + #[cfg(test)] mod lambda_test { use crate::parser::parse; |
