cubical-transport-hott-lean4/CubicalTransport/Syntax.lean
Maximus Gorog 31d19f655e
Some checks are pending
Lean Action CI / build (push) Waiting to run
Split: engine = cubical-transport HoTT only
Restructure to engine-only contents.  Application code (Topolei.*
namespace, canvas-rs / render Rust crates, Main / ProbeTest, naga IR
pipeline, Selection / Subobject / Trace / Obs.Ctx hypothesis stack,
cells-spec / HYPOTHESES / STATUS / NAGA_IR_PLAN docs) moves to the
sibling repo max/topolei.

What moved:
- `Topolei/Cubical/*.lean` (22 files) → `CubicalTransport/*.lean`
  with namespace `Topolei.Cubical.*` renamed to `CubicalTransport.*`.
  Fully-qualified test types `TopoleiCubical{FFI,Property}Test` →
  `CubicalTransport{FFI,Property}Test` for consistency.
- New root file `CubicalTransport.lean` re-exporting all 22 modules.
- Lakefile: package `cubicalTransport`; lib `CubicalTransport`; only
  `cubical-test` and `cubical-bench` exes (no GPU link path).

The split criterion: anything an AI shortcut could break that would
cascade-corrupt downstream proofs lives here.  Anything that would
only break the application stays in the topolei interface repo.

cubical-test passes 62/62 (smoke + properties) on the renamed engine.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:35:01 -06:00

184 lines
10 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Topolei.Cubical.Syntax
======================
Deep embedding of the cubical term language (CCHM §23).
Grammar:
A, B ::= U | Π A B | Path A a b
t, u ::= x | λx.t | t u | ⟨i⟩t | t@r | transpⁱ A φ t | compⁱ A φ u t
CType and CTerm are mutually inductive because path types carry endpoint
terms, and terms carry path applications over DimExprs.
transp and comp store (i : DimVar) (A : CType) inline rather than DimLine,
because DimLine is defined later in the import chain (Subst → DimLine).
The typing rules in Typing.lean use DimLine as a convenient wrapper.
The path β-rule (⟨i⟩ t) @ r ↝ t[i := r]
and the four "fully-reducing" transport/comp cases (T1, T2, C1, C2)
are NbE theorems in `Cubical/Readback.lean`. The residual step-level
axioms — T3, T5, C4 (subject reduction + face congruence) and T4
(path-line shape preservation) — live in `TransportLaws.lean` /
`CompLaws.lean`.
-/
import CubicalTransport.Face
-- ── Syntax ────────────────────────────────────────────────────────────────────
mutual
/-- Types in the cubical calculus. -/
inductive CType where
| univ : CType -- U
| pi (A : CType) (B : CType) : CType -- Π A B
| path (A : CType) (a b : CTerm) : CType -- Path A a b
/-- Non-dependent Σ type (cells-spec §6.2, §8.1, §9.2).
`Sigma A B` — pairs whose first component has type `A` and whose
second has type `B`. Non-dependent: `B` does not refer to the
first component. Dependent Σ (where `B : A → CType`) is deferred
for the same reason as dependent Π — requires a term evaluator
to apply `B` to a term. -/
| sigma (A B : CType) : CType -- Σ A B
/-- Glue type (CCHM §6).
`Glue [φ ↦ (T, e)] A` — on face `φ` the type is `T` with `e : T ≃ A`
as witness; off face `φ` the type is `A`. The equivalence `e` is
inlined as five `CTerm` fields (f, fInv, sec, ret, coh) rather than
a nested `EquivData` so that `CType` / `CTerm` remain a closed
mutual inductive block — `EquivData` lives in `Equiv.lean` and is
downstream in the import chain. Use `EquivData.toGlueType` in
`Equiv.lean` for an ergonomic wrapper. -/
| glue (φ : FaceFormula) (T : CType)
(f fInv sec ret coh : CTerm)
(A : CType) : CType -- Glue [φ ↦ (T, e)] A
deriving Repr
/-- Terms in the cubical calculus. -/
inductive CTerm where
| var (x : String) : CTerm -- x
| lam (x : String) (t : CTerm) : CTerm -- λx. t
| app (f a : CTerm) : CTerm -- f a
| plam (i : DimVar) (t : CTerm) : CTerm -- ⟨i⟩ t
| papp (t : CTerm) (r : DimExpr) : CTerm -- t @ r
| transp (i : DimVar) (A : CType) (φ : FaceFormula)
(t : CTerm) : CTerm -- transpⁱ A φ t
| comp (i : DimVar) (A : CType) (φ : FaceFormula)
(u t : CTerm) : CTerm -- compⁱ A φ u t
/-- Multi-clause heterogeneous composition.
`compⁱ A [φ₁ ↦ u₁, …, φₙ ↦ uₙ] t` — a partial element defined
over the union of the clause faces. Coherence (clauses agree
on overlaps and with `t` at `i = 0`) is a typing-level side
condition, not enforced syntactically. Used by CCHM path
transport and heterogeneous Π composition to express systems
that a single-clause `.comp` cannot represent. -/
| compN (i : DimVar) (A : CType)
(clauses : List (FaceFormula × CTerm))
(t : CTerm) : CTerm -- compⁱ A [φ₁↦u₁,…] t
/-- Glue introduction (CCHM §6.1).
`glueIn [φ ↦ t] a` — on face `φ`, equals `t : T`; off face `φ`,
equals `a : A`. Well-typedness requires `e.f t = a` on the
overlap (a typing-side condition, not enforced syntactically).
The equivalence `e` is carried by the type, not the term. -/
| glueIn (φ : FaceFormula) (t a : CTerm) : CTerm -- glue [φ↦t] a
/-- Glue elimination (CCHM §6.1).
`unglue [φ ↦ f] g` — extract the underlying `A`-value from a
glued term. On face `φ`, equals `f g` (apply the forward map);
off face `φ`, equals `g` (already an `A`-value). `f` is the
`f`-field of the equivalence witnessing `T ≃ A` — carried
explicitly at the term level because we don't have type
annotations on terms. -/
| unglue (φ : FaceFormula) (f g : CTerm) : CTerm -- unglue [φ↦f] g
/-- Σ introduction (pair). -/
| pair (a b : CTerm) : CTerm -- (a, b)
/-- Σ elimination (first projection). -/
| fst (t : CTerm) : CTerm -- t.1
/-- Σ elimination (second projection). -/
| snd (t : CTerm) : CTerm -- t.2
deriving Repr
end
-- ── Dimension substitution ────────────────────────────────────────────────────
-- Substitute dimension variable i with DimExpr r throughout a term.
--
-- Scope inside transp/comp:
-- · j is the binder of the transport line, bound in A and in φ.
-- · The base term t (and system u) are in outer scope — we substitute there.
--
-- Approximation: `substDim` does NOT descend into A or φ — even when j ≠ i
-- and i would be free under the binder. Consequence: this substitution is
-- only faithful for *endpoint* calls (`substDimBool`), where downstream
-- uses the dimension-absent predicate to justify correctness. Full
-- DimExpr-in-FaceFormula substitution is deferred (see cells-spec §5.5).
mutual
def CTerm.substDim (i : DimVar) (r : DimExpr) : CTerm → CTerm
| .var x => .var x
| .lam x t => .lam x (t.substDim i r)
| .app f a => .app (f.substDim i r) (a.substDim i r)
| .plam j t => if j = i then .plam j t -- i bound; stop
else .plam j (t.substDim i r)
| .papp t s => .papp (t.substDim i r) (DimExpr.subst i r s)
-- transp/comp: leave A alone (approximation); descend into t, u and
-- substitute in φ via the general DimExpr face-formula substitution.
| .transp j A φ t => .transp j A (φ.substDim i r) (t.substDim i r)
| .comp j A φ u t => .comp j A (φ.substDim i r) (u.substDim i r) (t.substDim i r)
-- Multi-clause comp: substitute in each clause's face and body, and in t.
-- Uses an explicit recursive helper `substDim.clauses` so Lean can see
-- structural termination through the clause list.
| .compN j A clauses t =>
.compN j A (CTerm.substDim.clauses i r clauses) (t.substDim i r)
-- Glue introduction / elimination: descend into all sub-terms and
-- substitute into the face formula. Same approximation for types
-- as transp/comp (A not touched — the `φ` face formula carries the
-- whole dim-dependency story; in our approximation we still don't
-- recurse into CType sub-trees here, matching `.transp`/`.comp`).
| .glueIn φ t a => .glueIn (φ.substDim i r) (t.substDim i r) (a.substDim i r)
| .unglue φ f g => .unglue (φ.substDim i r) (f.substDim i r) (g.substDim i r)
-- Σ constructors: structural recursion into sub-terms.
| .pair a b => .pair (a.substDim i r) (b.substDim i r)
| .fst t => .fst (t.substDim i r)
| .snd t => .snd (t.substDim i r)
/-- Helper: apply `CTerm.substDim i r` to each clause body (and
`FaceFormula.substDim` to each face) in a system's clause list.
Defined mutually with `substDim` so Lean can verify termination. -/
def CTerm.substDim.clauses (i : DimVar) (r : DimExpr) :
List (FaceFormula × CTerm) → List (FaceFormula × CTerm)
| [] => []
| (φ, u) :: rest =>
(φ.substDim i r, u.substDim i r) :: CTerm.substDim.clauses i r rest
end
-- ── One-step reduction ────────────────────────────────────────────────────────
-- `CTerm.step` is left *opaque*. Semantically it is what a CCHM-style
-- evaluator will compute. Keeping `step` opaque is required for
-- soundness: if `step` were a concrete `def` with a wildcard identity
-- arm, any axiom of the shape `step (.transp …) = t` would rfl-collapse
-- to `.transp … = t`, contradicting `CTerm.noConfusion`.
--
-- **Stage 4.4 decision (2026-04-23).** After the Phase 1 step↔eval
-- bridge + Stream B #2d + Stage 2.3, only one step-level axiom remains:
-- `transp_plam_is_plam_path` (T4, path-restricted form; Stage 4.2).
-- T1/T2/C1/C2/T5/`step_papp_plam` are NbE theorems in `Readback.lean`;
-- T3/C4 are theorems via `CTerm.step_preserves_type` (ValueTyping.lean);
-- glue β/η are theorems via `eval_unglue_of_glueIn`/`eval_glueIn_of_unglue`.
--
-- **Rust discharge flexibility.** The Rust backend has two valid
-- implementation strategies for `CTerm.step`:
--
-- · *Option A — native step*: implement `step` directly as a C ABI
-- entry point. The single T4 axiom is discharged by emitting the
-- CCHM comp-shaped body for path-typed transp-of-plam inputs, plus
-- identity behaviour on other shapes.
--
-- · *Option B — derived step*: define `step := readback ∘ eval .nil`
-- entirely in Rust (no separate `step` FFI entry). This matches
-- the Lean-side "bridge" intuition and keeps the Rust FFI surface
-- smaller by one function. Satisfies T4 on path-typed lines via
-- the `vPathTransp` → `.compN` readback arm.
--
-- The Lean-side spec is agnostic to which strategy Rust picks — both
-- satisfy the same axiom set. See FFI_DESIGN.md (Stage 4.5) for the
-- concrete recommendation.
opaque CTerm.step : CTerm → CTerm := id