/- Topolei.Cubical.FFITest ======================= Phase C.3 smoke test (2026-04-24). Exercises the FFI wiring by running simple cubical terms through `eval` / `readback` / the normalizers. With `@[implemented_by]` attached, these execute in the Rust backend at runtime. **Why not `#eval`?** `#eval` runs at Lean's compile-time in the interpreter, which does not link our Rust staticlib. Calling a Rust-backed function under the interpreter raises "Could not find native implementation of external declaration ..." The tests here are `def`s + a `runSmokeTests : IO Unit` entry point that exercises them inside a compiled binary where Rust IS linked. Invoke from a compiled executable. `Main.lean` can optionally route to `CubicalTransportFFITest.runSmokeTests` when passed `--cubical-test`. Or a dedicated test exe target. -/ import CubicalTransport.Readback import CubicalTransport.FFI import CubicalTransport.Inductive open CubicalTransport.Inductive open CubicalTransport.Inductive.CTerm namespace CubicalTransportFFITest -- ── Summarisers ──────────────────────────────────────────────────────────── def cvalSummary : CVal → String | .vneu (.nvar s) => s!"vneu nvar {s}" | .vneu (.napp _ _) => "vneu napp" | .vneu (.npapp _ _) => "vneu npapp" | .vneu (.ntransp _ _ _ _) => "vneu ntransp" | .vneu (.nhcomp _ _ _ _) => "vneu nhcomp" | .vneu (.ncomp _ _ _ _ _) => "vneu ncomp" | .vneu (.ncompN _ _ _ _ _) => "vneu ncompN" | .vneu (.nglueIn _ _ _) => "vneu nglueIn" | .vneu (.nunglue _ _ _) => "vneu nunglue" | .vneu (.nfst _) => "vneu nfst" | .vneu (.nsnd _) => "vneu nsnd" | .vneu (.nIndElim _ _ _ _ _) => "vneu nIndElim" | .vlam _ x _ => s!"vlam {x} ..." | .vplam _ i _ => s!"vplam {i.name} ..." | .vpair _ _ => "vpair ..." | .vTranspFun _ _ _ _ _ => "vTranspFun" | .vHCompFun _ _ _ _ => "vHCompFun" | .vCompFun _ _ _ _ _ _ _ => "vCompFun" | .vTubeApp _ _ => "vTubeApp" | .vPathTransp _ _ _ _ _ _ _ => "vPathTransp" | .vctor _ c _ _ => s!"vctor {c} ..." | .vdimExpr _ => "vdimExpr ..." def ctermSummary : CTerm → String | .var x => s!"var {x}" | .lam x _ => s!"lam {x} ..." | .app _ _ => "app ..." | .plam i _ => s!"plam {i.name} ..." | .pair _ _ => "pair ..." | .fst _ => "fst ..." | .snd _ => "snd ..." | .dimExpr _ => "dimExpr ..." | .ctor _ c _ _ => s!"ctor {c} ..." | .indElim _ _ _ _ _ => "indElim ..." | _ => "" -- ── Individual test definitions ──────────────────────────────────────────── -- Each returns (description, actual, expected) for runSmokeTests to print. def tests : List (String × String × String) := [ ("eval .nil (.var \"x\")", cvalSummary (eval .nil (.var "x")), "vneu nvar x"), ("eval .nil (.lam \"x\" (.var \"x\"))", cvalSummary (eval .nil (.lam "x" (.var "x"))), "vlam x ..."), ("(λx. x) y ⇓ y", cvalSummary (eval .nil (.app (.lam "x" (.var "x")) (.var "y"))), "vneu nvar y"), ("(a, b).fst ⇓ a", cvalSummary (eval .nil (.fst (.pair (.var "a") (.var "b")))), "vneu nvar a"), ("(a, b).snd ⇓ b", cvalSummary (eval .nil (.snd (.pair (.var "a") (.var "b")))), "vneu nvar b"), ("readback (eval .nil (.lam \"x\" (.var \"x\"))) ≡ .lam \"x\" ...", ctermSummary (readback (eval .nil (.lam "x" (.var "x")))), "lam x ..."), ("DimExpr.normalize (.inv .zero) ≡ .one", match DimExpr.normalize (.inv .zero) with | .one => "one" | _ => "", "one"), ("DimExpr.normalize (.inv (.inv (.var i))) ≡ .var i", match DimExpr.normalize (.inv (.inv (.var ⟨"i"⟩))) with | .var j => s!"var {j.name}" | _ => "", "var i"), ("FaceFormula.normalize (.meet .top (.eq0 i)) ≡ .eq0 i", match FaceFormula.normalize (.meet .top (.eq0 ⟨"i"⟩)) with | .eq0 j => s!"eq0 {j.name}" | _ => "", "eq0 i"), -- ── β-rules: discharge the five cubical-closure axioms ───────────────── -- Each test exercises the path `Lean constructs a CVal closure → -- vApp/vPApp routes through Rust @[implemented_by] → forcer unfolds -- the CCHM RHS → result is no longer a stuck marker`. ("β vApp vTranspFun (const line, via beta::force_transp_fun)", cvalSummary (vApp (.vTranspFun ⟨"i"⟩ .univ .univ .bot (.vneu (.nvar "f"))) (.vneu (.nvar "y"))), "vneu napp"), ("β vApp vHCompFun (stuck on .univ codA, via beta::force_hcomp_fun)", cvalSummary (vApp (.vHCompFun .univ .bot (.vplam .nil ⟨"j"⟩ (.var "tube_body")) (.vneu (.nvar "b"))) (.vneu (.nvar "x"))), "vneu nhcomp"), ("β vApp vCompFun (φ=.bot collapses via C2, via beta::force_comp_fun)", cvalSummary (vApp (.vCompFun .nil ⟨"i"⟩ .univ .univ .bot (.var "u") (.var "t")) (.vneu (.nvar "y"))), "vneu napp"), ("β vPApp vTubeApp (via beta::force_tube_app)", cvalSummary (vPApp (.vTubeApp (.vplam .nil ⟨"j"⟩ (.var "tube_body")) (.vneu (.nvar "x"))) (.var ⟨"r"⟩)), "vneu napp"), ("β vPApp vPathTransp at .zero ⇓ a(1) (via beta::force_path_transp)", cvalSummary (vPApp (.vPathTransp .nil ⟨"i"⟩ .univ (.var "a0") (.var "b0") .bot (.var "p")) .zero), "vneu nvar a0"), ("β vPApp vPathTransp at .one ⇓ b(1)", cvalSummary (vPApp (.vPathTransp .nil ⟨"i"⟩ .univ (.var "a0") (.var "b0") .bot (.var "p")) .one), "vneu nvar b0"), ("β vPApp vPathTransp at var r ⇓ compN (CCHM 3-clause system)", cvalSummary (vPApp (.vPathTransp .nil ⟨"i"⟩ .univ (.var "a0") (.var "b0") .bot (.var "p")) (.var ⟨"r"⟩)), "vneu ncompN"), -- ── REL1 inductive-type smoke tests ───────────────────────────────────── ("eval (zero : Nat) ⇓ vctor zero", cvalSummary (eval .nil zeroC), "vctor zero ..."), ("eval (succ (succ zero) : Nat) ⇓ vctor succ", cvalSummary (eval .nil (succC (succC zeroC))), "vctor succ ..."), ("eval (false : Bool) ⇓ vctor false", cvalSummary (eval .nil falseC), "vctor false ..."), ("eval (cons true nil : List Bool) ⇓ vctor cons", cvalSummary (eval .nil (consC CType.boolC trueC (nilC CType.boolC))), "vctor cons ..."), ("readback ∘ eval (succ zero : Nat) ≡ ctor succ", ctermSummary (readback (eval .nil (succC zeroC))), "ctor succ ..."), ("eval (base : S¹) ⇓ vctor base", cvalSummary (eval .nil baseC), "vctor base ..."), ("eval (loop @ r : S¹) ⇓ vctor loop", cvalSummary (eval .nil (loopC (.var ⟨"r"⟩))), "vctor loop ..."), ("indElim Bool false-case (true → \"yes\") on true ⇓ \"yes\"", cvalSummary (eval .nil (boolElim (.lam "x" (.var "M")) (.var "no") (.var "yes") trueC)), "vneu nvar yes"), ("indElim Bool true-case on false ⇓ \"no\"", cvalSummary (eval .nil (boolElim (.lam "x" (.var "M")) (.var "no") (.var "yes") falseC)), "vneu nvar no"), ("transp_ind T1: φ=.top is identity", cvalSummary (eval .nil (.transp ⟨"i"⟩ CType.natC .top zeroC)), "vctor zero ..."), ("transp_ind T2: constant Nat line is identity", cvalSummary (eval .nil (.transp ⟨"i"⟩ CType.natC (.eq0 ⟨"j"⟩) (succC zeroC))), "vctor succ ..."), ("comp_ind C1: φ=.top reduces to u[i:=1]", cvalSummary (eval .nil (.comp ⟨"i"⟩ CType.natC .top (succC zeroC) zeroC)), "vctor succ ...") ] /-- Run every smoke test, print its actual vs expected. Returns the number of failures. -/ def runSmokeTests : IO UInt32 := do IO.println "── Topolei cubical FFI smoke tests ──" let mut fails : UInt32 := 0 for (desc, actual, expected) in tests do if actual == expected then IO.println s!" ✅ {desc}" else IO.println s!" ❌ {desc}" IO.println s!" expected: {expected}" IO.println s!" actual: {actual}" fails := fails + 1 IO.println s!"── {tests.length - fails.toNat} / {tests.length} passed ──" return fails end CubicalTransportFFITest