Inductive.lean (new module): schema combinators (mkSchema, mkCtor,
mkPath) and canonical schema instances:
- Plain inductives: natSchema, boolSchema, listSchema
- HITs: s1Schema, intervalSchema, propTruncSchema
Plus type-level helpers (CType.natC, listC, s1C, …) and term-level
ergonomic builders (zeroC, succC, nilC, consC, baseC, loopC, …,
natLit, natElim, boolElim, listElim).
Rust kernel (native/cubical/src/):
· tags.rs — TY_IND, TERM_DIMEXPR/CTOR/INDELIM, VAL_VCTOR/VDIMEXPR,
NEU_NINDELIM tag constants per docs/INDUCTIVE_TYPES.md §6.
· value.rs — mk_vctor, mk_vdimexpr, mk_nindelim builders.
· eval.rs — TERM_DIMEXPR / TERM_CTOR / TERM_INDELIM dispatch
arms; full β-reduction on canonical vctor target
(find matching branch by name, vapp chain over
ctor args); stuck nIndElim build for vneu target;
eval_term_list / eval_branches / find_branch_body
helpers (recursive list walking).
· readback.rs — VAL_VCTOR / VAL_VDIMEXPR readback arms;
readback_val_list, map_readback_branches helpers;
NEU_NINDELIM neutral readback; mk_term_dimexpr,
mk_term_ctor, mk_term_indelim builders.
Tests (CubicalTransport/FFITest.lean): nine new smoke arms exercising
canonical-form eval (zero, succ-of-succ, false, cons-true-nil, base,
loop@r), readback round-trip on succ zero, and indElim β on Bool with
both branch directions. Result: 25/25 smoke + 46/46 properties =
71/71 passing.
Existing tests untouched (constructor tags preserved per REL1 freeze).
Rust ABI version is now de facto v2 (new tags); update the
TOPOLEI_FFI_ABI_VERSION constant in a follow-up commit.
Remaining REL1 work (per task list):
- #4 HasType arms for ctor / indElim
- #8 transport over .ind axioms
- #9 composition over .ind axioms
- Path-ctor boundary firing (REL1.1)
- Recursive-arg IH wiring in indElim β (REL1.1)
- Topolei migration (sibling repo) per docs/INDUCTIVE_TYPES.md §9.1
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| include | ||
| src | ||
| test | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
| shim.c | ||
| WASM.md | ||
topolei-cubical — Rust backend
Rust implementation of the cubical-transport HoTT evaluator for topolei — Lean 4's cubical-HoTT kernel extension.
See FFI_DESIGN.md and FFI_COMPLETENESS.md at the project root for
the full C ABI contract and per-function axiom audit.
Build
# Native staticlib + cdylib (linux / macos / windows):
cargo build --release
# wasm32-unknown-unknown (for Lean-wasm composite artifacts):
cargo build --release --target wasm32-unknown-unknown
Artifacts:
| Target | Path |
|---|---|
| Native staticlib | target/release/libtopolei_cubical.a |
| Native cdylib | target/release/libtopolei_cubical.so (linux), .dylib (macos), .dll (windows) |
| Wasm cdylib | target/wasm32-unknown-unknown/release/topolei_cubical.wasm |
| Wasm staticlib | target/wasm32-unknown-unknown/release/libtopolei_cubical.a |
Discipline
no_stdthroughout — wasm32-unknown-unknown has no std, and native uses the same source for ABI uniformity.- Pure-functional evaluator — no IO, no threads, no allocator. All
objects live in Lean's heap; Rust operates via
lean_object*pointers. - Hand-rolled
lean_runtime.rs— ~12extern "C"declarations for the Lean runtime primitives we need. Nolean-sysdependency (that crate isn't wasm-ready).
Phase tracker
- Phase A ✅: crate skeleton + stubs.
- Phase B ✅: full evaluator implementation (14 FFI entries).
- Phase C ✅:
@[implemented_by]wiring + native staticlib linkage- smoke tests (9/9 passing via
lake build cubical-test).
- smoke tests (9/9 passing via
- Phase D.wasm ✅: wasm32 target + JS test harness (10/10 passing
via
node test/wasm_harness.mjs). SeeWASM.mdfor integration with a Lean-wasm composite artifact. - Phase D.properties ✅: 46 property-based tests in
CubicalTransport/PropertyTest.leancovering λ β-rules, Σ β-rules, eval determinism, DimExpr idempotence + literals, FaceFormula absorption, readback roundtrip. 55/55 total (9 smoke + 46 property). - Phase D.bench ✅: baseline perf benchmarks via
cubical-benchexe: λ β & Σ projections 11 ns/iter, normalizers ~50 ns/op, readback 11 ns/iter (100k iters, accumulator prevents DCE).
Testing
Two test surfaces, both currently passing:
Native smoke tests (Lean-side)
lake build cubical-test
./.lake/build/bin/cubical-test
Expected output: ── 9 / 9 passed ──, covering λ-fragment eval,
Σ β-rules, readback, and normalizer reductions. Source:
CubicalTransport/FFITest.lean + CubicalTest.lean.
Wasm smoke tests (Node.js harness)
cargo build --release --target wasm32-unknown-unknown
node test/wasm_harness.mjs
Expected output: ── 10 / 10 tests passed ──. The harness
implements a minimal JS version of Lean's runtime (bump allocator +
object header helpers) to exercise both scalar and heap-allocating
reductions. See WASM.md for the full ABI contract and integration
with a Lean-wasm composite artifact.
Layout
native/cubical/
├── Cargo.toml
├── README.md — this file
├── include/
│ └── topolei_cubical.h — C declarations (ABI v1)
└── src/
├── lib.rs — crate root; panic handler
├── lean_runtime.rs — hand-rolled Lean C ABI
└── ffi.rs — #[no_mangle] exports (stubs in Phase A)
Future expansion (Phases B–C):
└── src/
├── cubical/
│ ├── mod.rs
│ ├── eval.rs
│ ├── transport.rs
│ ├── comp.rs
│ ├── glue.rs
│ └── readback.rs
├── subst/
│ ├── mod.rs
│ ├── dim_expr.rs
│ └── face.rs
└── ...