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 | let expected_closed = AE::app(AE::var(0, ()), AE::var(1, ())); |
| 1368 | assert_eq!(closed, expected_closed); |
| 1369 | } |
| 1370 | |
| 1371 | #[test] |
| 1372 | fn simul_subst_basic() { |
| 1373 | let mut env = InternTable::<Anon>::new(); |
| 1374 | let v0 = AE::var(0, ()); |
| 1375 | let v1 = AE::var(1, ()); |
| 1376 | let app = AE::app(v1, v0); // App(Var(1), Var(0)) |
| 1377 | |
| 1378 | let a = AE::nat(Nat::from(1u64), mk_addr("a")); |
| 1379 | let b = AE::nat(Nat::from(2u64), mk_addr("b")); |
| 1380 | |
| 1381 | // simul_subst([a, b], depth=0): |
| 1382 | // Var(0) → substs[0] = a |
| 1383 | // Var(1) → substs[1] = b |
| 1384 | let result = simul_subst(&mut env, &app, &[a.clone(), b.clone()], 0); |
| 1385 | let expected = AE::app(b, a); |
| 1386 | assert_eq!(result, expected); |
| 1387 | } |
| 1388 | |
| 1389 | #[test] |
| 1390 | fn simul_subst_shift() { |
| 1391 | let mut env = InternTable::<Anon>::new(); |
| 1392 | let v2 = AE::var(2, ()); |
| 1393 | |
| 1394 | let a = AE::nat(Nat::from(1u64), mk_addr("a")); |
| 1395 | let b = AE::nat(Nat::from(2u64), mk_addr("b")); |
| 1396 | |
| 1397 | // Var(2) >= depth+2 → shifted to Var(0) |
| 1398 | let result = simul_subst(&mut env, &v2, &[a, b], 0); |
| 1399 | assert_eq!(result, AE::var(0, ())); |
| 1400 | } |
| 1401 | |
| 1402 | #[test] |
| 1403 | fn intern_dedup() { |
| 1404 | let mut env = InternTable::<Anon>::new(); |
| 1405 | let _v0 = AE::var(0, ()); |
| 1406 | let v2 = AE::var(2, ()); |
| 1407 | let arg = AE::nat(Nat::from(3u64), mk_addr("3")); |
| 1408 | |
| 1409 | // Two substitutions producing the same result should be pointer-equal after interning |
| 1410 | let r1 = subst(&mut env, &v2, &arg, 0); |