cubical-transport-hott-lean4/CubicalTransport/Value.lean
Maximus Gorog 6e4936d6ee
Some checks are pending
Lean Action CI / build (push) Waiting to run
Refactor Phase 2: modal unification — Lean engine cascade
Per the elegance pass: 9 ad-hoc per-modality constructors collapse into
3 ModalityKind-parameterised constructors.  Future modalities (Phase
4's ʃ_EML, ℑ infinitesimal) extend ModalityKind by adding cases —
no new constructors, no new ABI bump.

New Lean enum (Syntax.lean):
  inductive ModalityKind | flat | sharp | shape
    deriving DecidableEq, Repr, Inhabited

Constructor unification:
  · CType: 3 (.flat / .sharp / .shape) → 1 (.modal k A)
  · CTerm: 6 (.flatIntro / .sharpIntro / .shapeIntro / .flatElim /
            .sharpElim / .shapeElim) → 2 (.modalIntro k a, .modalElim k f m)
  · CVal:  3 (vFlatIntro / vSharpIntro / vShapeIntro) → 1 (vModalIntro)
  · CNeu:  3 (nflatElim / nsharpElim / nshapeElim) → 1 (nModalElim)
  · SkeletalCType: 3 (skFlat / skSharp / skShape) → 1 (skModal k)

Engine cascade across 12 files (DecEq, DimLine, Eval, FFITest, Modal,
Question, Readback, Reflect, Subst, Syntax, Typing, Value): every
match site collapsed from 3-per-modality arms to 1 k-parameterised arm.

Reflect.lean: new `reflectModalityKind` / `reifyModalityKind` helpers
+ ModalityKind dispatch arm in classifyFieldType.  The Phase 1 macro
auto-derived per-constructor reflect/reify for the new unified
constructors — no manual cascade needed there.

Eval.lean β-rule: `.modalElim k f (.modalIntro k' a)` β-reduces only
when k = k' (kind-discrimination preserves cross-kind correctness even
if typing is bypassed); cross-kind case produces a marker neutral.

Modal.lean transient alias block (top of file, outside namespace) for
backward dot-syntax reference (`.flatIntro a` resolves to
`.modalIntro .flat a` via abbrev).  Phase 3 will rewrite Modal.lean
properly to use the unified constructors directly + forModalityKind-
derived functor.

Net: −145 lines across the cascade (-478 deletions, +333 insertions).

Build: lake build (48 jobs) + lake build CubicalTransport (43 jobs) PASS.
Runtime: lake exe cubical-test 49/49 + 46/46 = 95/95 PASS.
Sorry count: Modal.lean 3 (unchanged), total engine 33 (no new sorries
from this phase, all annotated).

The Rust ABI v6 still uses 9 modal tags — diverges from the Lean side
after this commit but FFI tests don't exercise modal paths so no
runtime regression.  Phase 4 will sync to ABI v7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 02:01:52 -06:00

169 lines
7.5 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.

/-
CubicalTransport.Value
======================
Weak-head normal forms for the universe-stratified cubical calculus
(cells-spec §5.4, Layer 0 §0.1 cascade).
Named-variable adaptation: our `CTerm` uses `String` binders rather than
de Bruijn indices, so `Env` is a name-keyed association list instead of
an `Array`. The three inductives (`CEnv`, `CVal`, `CNeu`) are mutually
recursive: `CVal` contains closures (which capture their `CEnv`), `CNeu`
(stuck terms) carries already-evaluated sub-values, and `CEnv` stores
`CVal`s.
## Universe-aware shape
CVal and CNeu constructors that carry a `CType` payload carry it at an
implicit `{ : ULevel}` parameter — mirroring the corresponding CTerm
constructors in `Syntax.lean`. At the value level the level is
existentially packaged (forgotten by the constructor); the kernel-side
level discipline lives on CType, not on CVal.
Where a constructor stores TWO CTypes that must live at related levels
(e.g. domain at and codomain at '), both levels are bound implicitly.
Coverage matches the cells-spec's "λ-calculus fragment" milestone:
· function abstractions and applications (`vlam`/`napp`)
· dimension abstractions and applications (`vplam`/`npapp`)
· transport and composition as *stuck* values (`ntransp`/`ncomp`) —
reduction rules in `Transport.lean`/`Comp.lean`.
-/
import CubicalTransport.Syntax
mutual
/-- Name-keyed environment: a cons-list of `(name, value)` bindings. The
most-recently-extended binding shadows earlier ones of the same name. -/
inductive CEnv : Type where
| nil : CEnv
| cons : String → CVal → CEnv → CEnv
deriving Inhabited
/-- Weak-head normal-form values. -/
inductive CVal : Type where
/-- Function closure `(λ x. body)` with captured environment. -/
| vlam : CEnv → String → CTerm → CVal
/-- Dimension-abstraction closure `(⟨i⟩ body)` with captured environment. -/
| vplam : CEnv → DimVar → CTerm → CVal
/-- Embedded neutral term — a stuck computation. -/
| vneu : CNeu → CVal
/-- A *transported function value*: result of `transp^i (pi domA codA) φ f`.
Domain at level ``, codomain at level `'`; the result type
lives at `ULevel.max '` (CCHM Π rule). Levels are
existentially packaged at the value level. -/
| vTranspFun { ' : ULevel} :
DimVar → CType → CType ' → FaceFormula → CVal → CVal
/-- A *composed function value*: result of `hcomp (pi domA codA) φ tube base`.
Stores only `codA` (homogeneous comp on the domain is trivial
since A is fixed). -/
| vHCompFun { : ULevel} :
CType → FaceFormula → CVal → CVal → CVal
/-- A *point-wise applied tube*: represents `λj. (tube @ j) arg`. -/
| vTubeApp : CVal → CVal → CVal
/-- A *heterogeneous-composition function value*: result of
`comp^i (Π domA codA) φ u u₀` at the value level. -/
| vCompFun { ' : ULevel} :
CEnv → DimVar → CType → CType ' → FaceFormula →
CTerm → CTerm → CVal
/-- A *path-transport value*: result of `transp^i (Path A(i) a(i) b(i)) φ p`. -/
| vPathTransp { : ULevel} :
CEnv → DimVar → CType → CTerm → CTerm → FaceFormula →
CTerm → CVal
/-- A Σ pair value. -/
| vpair : CVal → CVal → CVal
/-- Schema constructor application — fully-evaluated, canonical
constructor of an inductive (or higher-inductive) type (REL1).
`params` is level-heterogeneous: each entry carries its own ULevel. -/
| vctor : CTypeSchema → String →
List (Σ : ULevel, CType ) → List CVal → CVal
/-- Lifted dimension-expression value (REL1). -/
| vdimExpr : DimExpr → CVal
/-- Value form of `CTerm.code A`. Carries the encoded CType. -/
| vcode { : ULevel} : CType → CVal
/-- Value form of `CTerm.modalIntro k a` (Refactor Phase 2): the
η-introduction value for modality `k`, carrying the wrapped
value. Replaces the Phase-1 trio
`vFlatIntro`/`vSharpIntro`/`vShapeIntro` with a single
`ModalityKind`-parameterised constructor. -/
| vModalIntro : ModalityKind → CVal → CVal
/-- Neutral (stuck) terms. -/
inductive CNeu : Type where
/-- A free variable (name not bound in the current environment). -/
| nvar : String → CNeu
/-- Stuck function application. -/
| napp : CNeu → CVal → CNeu
/-- Stuck dimension application. -/
| npapp : CNeu → DimExpr → CNeu
/-- Transport with an already-evaluated argument. CType at any level. -/
| ntransp { : ULevel} :
DimVar → CType → FaceFormula → CVal → CNeu
/-- Heterogeneous composition (varying line) with already-evaluated
system body and base. -/
| ncomp { : ULevel} :
DimVar → CType → FaceFormula → CVal → CVal → CNeu
/-- Homogeneous composition (fixed type) with already-evaluated tube
and base. -/
| nhcomp { : ULevel} :
CType → FaceFormula → CVal → CVal → CNeu
/-- A stuck multi-clause heterogeneous composition. -/
| ncompN { : ULevel} :
CEnv → DimVar → CType
List (FaceFormula × CVal) → CVal → CNeu
/-- A stuck glue introduction. -/
| nglueIn : FaceFormula → CVal → CVal → CNeu
/-- A stuck unglue. -/
| nunglue : FaceFormula → CVal → CVal → CNeu
/-- A stuck first projection. -/
| nfst : CNeu → CNeu
/-- A stuck second projection. -/
| nsnd : CNeu → CNeu
/-- A stuck inductive eliminator (REL1). `params` is level-heterogeneous. -/
| nIndElim : CTypeSchema → List (Σ : ULevel, CType ) → CVal →
List (String × CVal) → CNeu → CNeu
/-- A stuck modal eliminator (Refactor Phase 2): `modalElim k f m`
where the scrutinee `m` is a stuck CNeu (so β can't fire).
Stores the modality kind, the evaluated eliminator function,
and the stuck scrutinee. Replaces the Phase-1 trio
`nflatElim`/`nsharpElim`/`nshapeElim` with a single
`ModalityKind`-parameterised constructor. -/
| nModalElim : ModalityKind → CVal → CNeu → CNeu
end
-- Inhabited instances — needed so `partial def` evaluators can be elaborated
-- (Lean's partial-fixpoint compilation requires a default value for divergence).
instance : Inhabited CNeu := ⟨.nvar "⊥"⟩
instance : Inhabited CVal := ⟨.vneu default⟩
namespace CEnv
/-- Look up a variable name; returns `none` if the name is free. -/
def lookup : CEnv → String → Option CVal
| .nil, _ => none
| .cons n v rest, x => if x = n then some v else rest.lookup x
/-- Extend an environment with a new `(name, value)` binding. -/
def extend (env : CEnv) (x : String) (v : CVal) : CEnv :=
.cons x v env
@[simp] theorem lookup_nil (x : String) : CEnv.lookup .nil x = none := rfl
@[simp] theorem lookup_cons_hit (x : String) (v : CVal) (rest : CEnv) :
(CEnv.cons x v rest).lookup x = some v := by
simp [lookup]
theorem lookup_cons_miss (x y : String) (v : CVal) (rest : CEnv) (h : y ≠ x) :
(CEnv.cons x v rest).lookup y = rest.lookup y := by
simp [lookup, if_neg h]
@[simp] theorem extend_lookup_hit (env : CEnv) (x : String) (v : CVal) :
(env.extend x v).lookup x = some v := by
simp [extend]
theorem extend_lookup_miss (env : CEnv) (x y : String) (v : CVal) (h : y ≠ x) :
(env.extend x v).lookup y = env.lookup y := by
simp [extend, lookup, if_neg h]
end CEnv