Generate a bounded-depth `KExpr ` with de Bruijn indices in `0..=max_var`. Leaf distribution is biased toward concrete data (Var/Sort/Const) to produce meaningful expressions.
(
env: &mut InternTable<Anon>,
rng: &mut Prng,
depth: u32,
max_var: u64,
)
| 1367 | } |
| 1368 | |
| 1369 | #[test] |
| 1370 | fn abstract_fvars_position_mapping() { |
| 1371 | let mut env = InternTable::<Anon>::new(); |
| 1372 | let fv0 = AE::fvar(FVarId(0), ()); |
| 1373 | let fv1 = AE::fvar(FVarId(1), ()); |
| 1374 | let app = AE::app(fv0, fv1); |
| 1375 | // [fv0, fv1]: fv0 outermost (Var(1)), fv1 innermost (Var(0)) |
| 1376 | let result = abstract_fvars(&mut env, &app, &[FVarId(0), FVarId(1)]); |
| 1377 | let expected = AE::app(AE::var(1, ()), AE::var(0, ())); |
| 1378 | assert_eq!(result, expected); |
| 1379 | } |
| 1380 | |
| 1381 | #[test] |
| 1382 | fn abstract_fvars_unrelated_pass_through() { |
| 1383 | let mut env = InternTable::<Anon>::new(); |
| 1384 | let fv0 = AE::fvar(FVarId(0), ()); |
| 1385 | let fv2 = AE::fvar(FVarId(2), ()); |
| 1386 | // fv2 is not in the abstraction list → unchanged |
| 1387 | let result = abstract_fvars(&mut env, &fv2, &[FVarId(0), FVarId(1)]); |
| 1388 | assert!(result.ptr_eq(&fv2)); |
| 1389 | let _ = fv0; // silence unused |
| 1390 | } |
| 1391 | |
| 1392 | #[test] |
| 1393 | fn abstract_fvars_lifts_loose_bvars() { |
| 1394 | let mut env = InternTable::<Anon>::new(); |
| 1395 | let fv0 = AE::fvar(FVarId(0), ()); |
| 1396 | let v0 = AE::var(0, ()); |
| 1397 | let app = AE::app(fv0, v0); |
| 1398 | // Wrap one new binder around `app`; fv0 → Var(0); existing Var(0) |
| 1399 | // (loose) shifts up to Var(1). |
| 1400 | let result = abstract_fvars(&mut env, &app, &[FVarId(0)]); |
| 1401 | let expected = AE::app(AE::var(0, ()), AE::var(1, ())); |
| 1402 | assert_eq!(result, expected); |
| 1403 | } |
| 1404 | |
| 1405 | #[test] |
| 1406 | fn instantiate_rev_then_abstract_roundtrip() { |
| 1407 | let mut env = InternTable::<Anon>::new(); |
| 1408 | // Body: λ. App(#0, #1) — under one extra binder; Var(0) is the inner |
| 1409 | // peeled binder, Var(1) is the outer one. |
| 1410 | let nat = AE::cnst(KId::new(mk_addr("Nat"), ()), Box::new([])); |