Modal cascade Phase 2: Rust ABI v5 → v6 (modal constructors)
Some checks are pending
Lean Action CI / build (push) Waiting to run
Some checks are pending
Lean Action CI / build (push) Waiting to run
Mirrors the 9 Lean-side modal constructors landed in b9ca1d8
(Phase 1). ABI version constant CUBICAL_TRANSPORT_ABI_VERSION = 6.
Tag additions (separate namespaces — no cross-namespace collision):
· TY_FLAT=9, TY_SHARP=10, TY_SHAPE=11
· TERM_FLAT_INTRO=17 .. TERM_SHAPE_ELIM=22
· VAL_VFLAT_INTRO=12, VAL_VSHARP_INTRO=13, VAL_VSHAPE_INTRO=14
· NEU_NFLAT_ELIM=12, NEU_NSHARP_ELIM=13, NEU_NSHAPE_ELIM=14
Marshalling cascade across:
· cubical_transport.h — version bump + ABI v6 layout-table entries
documenting runtime field layout for all 15 new constructors
(modal CType carry implicit ULevel at runtime per Lean's encoding;
modal CTerm intros/elims are level-free)
· tags.rs — 15 new pub const u32
· value.rs — CVal::VFlatIntro/VSharpIntro/VShapeIntro variants and
CNeu::NFlatElim/NSharpElim/NShapeElim variants + from/to_tag
arms
· eval.rs — 6 CTerm arms (3 intros lift inner value through eval;
3 elims β-reduce on vM-Intro, push to nM-Elim on vneu, marker-
neutral fallback with Lean-identical strings for differential-
fuzzing parity)
· subst.rs — 3 CType + 6 CTerm substDim arms
· readback.rs — 3 vIntro + 3 nElim arms
· dim_absent.rs — 3 CType + 6 CTerm dim-absence arms
Files NOT changed (verified): transport.rs, composition.rs, glue.rs,
beta.rs, ffi.rs. Their existing dispatch correctly produces stuck
ntransp/nhcomp/ncomp neutrals for any non-Π CType — modal types
fall through. Modal-cohesion-driven transport reductions are Phase 3.
Verification:
· cargo build --release: clean
· cargo test --release: 0 failed (no in-crate tests)
· lake build: 48 jobs PASS
· lake build CubicalTransport: 42 jobs PASS
· lake exe cubical-test: 49/49 FFI smoke + 46/46 properties PASS
+448 lines across 7 files in native/cubical/. Zero new unsafe blocks.
Zero new unimplemented!()/todo!()/panic!. No Lean files touched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b9ca1d8875
commit
c6bc0aa68f
7 changed files with 456 additions and 2 deletions
|
|
@ -9,6 +9,43 @@
|
|||
// 2 — REL1: schema-based inductive types (CType.ind, CTerm.{dimExpr,
|
||||
// ctor, indElim}, CVal.vctor / vdimExpr, CNeu.nIndElim).
|
||||
// 3 — REL2: cubical interval primitive (CType.interval, tag 6).
|
||||
// 6 — Modal cascade Phase 2 (cohesive triple ♭ ⊣ ♯ ⊣ ʃ). Adds:
|
||||
// CType.flat / .sharp / .shape (tags 9 / 10 / 11)
|
||||
// CTerm.{flat,sharp,shape}Intro (tags 17 / 18 / 19)
|
||||
// CTerm.{flat,sharp,shape}Elim (tags 20 / 21 / 22)
|
||||
// CVal.v{Flat,Sharp,Shape}Intro (tags 12 / 13 / 14)
|
||||
// CNeu.n{flat,sharp,shape}Elim (tags 12 / 13 / 14)
|
||||
// Layouts (Lean keeps implicit `{ℓ}` at runtime — same v4 rule):
|
||||
// CType.flat {ℓ} A : 2 fields — [ℓ, A]
|
||||
// CType.sharp {ℓ} A : 2 fields — [ℓ, A]
|
||||
// CType.shape {ℓ} A : 2 fields — [ℓ, A]
|
||||
// CTerm.flatIntro a : 1 field — [a] (no implicit ℓ)
|
||||
// CTerm.sharpIntro a : 1 field — [a]
|
||||
// CTerm.shapeIntro a : 1 field — [a]
|
||||
// CTerm.flatElim f m : 2 fields — [f, m]
|
||||
// CTerm.sharpElim f m : 2 fields — [f, m]
|
||||
// CTerm.shapeElim f m : 2 fields — [f, m]
|
||||
// CVal.vFlatIntro v : 1 field — [v] (CVal payload)
|
||||
// CVal.vSharpIntro v : 1 field — [v]
|
||||
// CVal.vShapeIntro v : 1 field — [v]
|
||||
// CNeu.nflatElim f n : 2 fields — [f, n] (eliminator
|
||||
// value, stuck CNeu)
|
||||
// CNeu.nsharpElim f n : 2 fields — [f, n]
|
||||
// CNeu.nshapeElim f n : 2 fields — [f, n]
|
||||
// Reductions (mirror Cubical/Eval.lean exactly):
|
||||
// eval env (.flatIntro a)
|
||||
// = .vFlatIntro (eval env a) (similarly sharp/shape)
|
||||
// eval env (.flatElim f m) =
|
||||
// match eval env m with
|
||||
// | .vFlatIntro a → vApp (eval env f) a (β)
|
||||
// | .vneu n → .vneu (.nflatElim (eval env f) n)
|
||||
// | _ → marker neutral (.nvar "<...>")
|
||||
// Modal-type-driven transport / composition reductions are
|
||||
// intentionally absent: a `transp i {flat A} φ t` falls through
|
||||
// to the existing stuck-neutral path (transport.rs / composition.rs
|
||||
// only have explicit arms for TY_PI; everything else stucks via
|
||||
// ntransp / nhcomp / ncomp). Modal cohesion-driven reductions
|
||||
// (`flat`-transport, `shape`-shape law) land in Phase 3.
|
||||
// 5 — CType.El (decoder) and CTerm.code (encoder) constructors for
|
||||
// universe-coding. Adds CVal.vcode value form. Layouts:
|
||||
// CType.El {ℓ} P : 2 fields — [ℓ, P]
|
||||
|
|
@ -57,6 +94,21 @@
|
|||
// CType.El {ℓ} P → 2 slots: [ℓ, P] (v5)
|
||||
// CTerm.code {ℓ} A → 2 slots: [ℓ, A] (v5)
|
||||
// CVal.vcode {ℓ} A → 2 slots: [ℓ, A] (v5)
|
||||
// CType.flat {ℓ} A → 2 slots: [ℓ, A] (v6)
|
||||
// CType.sharp {ℓ} A → 2 slots: [ℓ, A] (v6)
|
||||
// CType.shape {ℓ} A → 2 slots: [ℓ, A] (v6)
|
||||
// CTerm.flatIntro a → 1 slot: [a] (v6)
|
||||
// CTerm.sharpIntro a → 1 slot: [a] (v6)
|
||||
// CTerm.shapeIntro a → 1 slot: [a] (v6)
|
||||
// CTerm.flatElim f m → 2 slots: [f, m] (v6)
|
||||
// CTerm.sharpElim f m → 2 slots: [f, m] (v6)
|
||||
// CTerm.shapeElim f m → 2 slots: [f, m] (v6)
|
||||
// CVal.vFlatIntro v → 1 slot: [v] (v6)
|
||||
// CVal.vSharpIntro v → 1 slot: [v] (v6)
|
||||
// CVal.vShapeIntro v → 1 slot: [v] (v6)
|
||||
// CNeu.nflatElim f n → 2 slots: [f, n] (v6)
|
||||
// CNeu.nsharpElim f n → 2 slots: [f, n] (v6)
|
||||
// CNeu.nshapeElim f n → 2 slots: [f, n] (v6)
|
||||
// CTerm.transp i {ℓ} A φ t → 5 slots: [i, ℓ, A, φ, t]
|
||||
// CTerm.comp i {ℓ} A φ u t → 6 slots: [i, ℓ, A, φ, u, t]
|
||||
// CTerm.compN i {ℓ} A clauses t → 5 slots: [i, ℓ, A, clauses, t]
|
||||
|
|
@ -76,7 +128,7 @@
|
|||
#pragma once
|
||||
#include <lean/lean.h>
|
||||
|
||||
#define CUBICAL_TRANSPORT_ABI_VERSION 5
|
||||
#define CUBICAL_TRANSPORT_ABI_VERSION 6
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -124,6 +124,21 @@ pub(crate) fn cterm_absent(i: LeanObj, t: LeanObj) -> bool {
|
|||
// ABI v5: universe-code encoder. Same approximation as
|
||||
// transp/comp — A (the CType payload) is not recursed into.
|
||||
TERM_CODE => true,
|
||||
// ABI v6: modal introductions — dim-absence preserved through
|
||||
// the wrapper. Layout: [a]. Mirrors Lean CTerm.dimAbsent arms
|
||||
// for .flatIntro / .sharpIntro / .shapeIntro.
|
||||
TERM_FLAT_INTRO | TERM_SHARP_INTRO | TERM_SHAPE_INTRO => {
|
||||
let a = ctor_field(t, 0);
|
||||
cterm_absent(i, a)
|
||||
}
|
||||
// ABI v6: modal eliminations — check both eliminator and
|
||||
// scrutinee. Layout: [f, m]. Mirrors Lean CTerm.dimAbsent
|
||||
// arms for .flatElim / .sharpElim / .shapeElim.
|
||||
TERM_FLAT_ELIM | TERM_SHARP_ELIM | TERM_SHAPE_ELIM => {
|
||||
let f = ctor_field(t, 0);
|
||||
let m = ctor_field(t, 1);
|
||||
cterm_absent(i, f) && cterm_absent(i, m)
|
||||
}
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
|
@ -217,6 +232,13 @@ pub(crate) fn ctype_absent(i: LeanObj, a: LeanObj) -> bool {
|
|||
let p = ctor_field(a, 1);
|
||||
cterm_absent(i, p)
|
||||
}
|
||||
// ABI v6: cohesive modalities — recurse into the wrapped CType.
|
||||
// Layout: [ℓ, A]. Mirrors Lean CType.dimAbsent arms for
|
||||
// .flat / .sharp / .shape.
|
||||
TY_FLAT | TY_SHARP | TY_SHAPE => {
|
||||
let inner = ctor_field(a, 1);
|
||||
ctype_absent(i, inner)
|
||||
}
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,6 +238,117 @@ pub fn eval(env: LeanObj, t: LeanObj) -> LeanObjMut {
|
|||
retain(l); retain(a);
|
||||
mk_vcode(l, a)
|
||||
}
|
||||
TERM_FLAT_INTRO => {
|
||||
// .flatIntro a — ABI v6: η_♭ intro. Layout: [a] (1 field, no ℓ).
|
||||
// eval env (.flatIntro a) = .vFlatIntro (eval env a)
|
||||
// (mirror Cubical/Eval.lean axiom eval_flatIntro).
|
||||
let a = ctor_field(t, 0);
|
||||
let va = eval(env, a);
|
||||
mk_vflat_intro(va as LeanObj)
|
||||
}
|
||||
TERM_SHARP_INTRO => {
|
||||
let a = ctor_field(t, 0);
|
||||
let va = eval(env, a);
|
||||
mk_vsharp_intro(va as LeanObj)
|
||||
}
|
||||
TERM_SHAPE_INTRO => {
|
||||
let a = ctor_field(t, 0);
|
||||
let va = eval(env, a);
|
||||
mk_vshape_intro(va as LeanObj)
|
||||
}
|
||||
TERM_FLAT_ELIM => {
|
||||
// .flatElim f m — ABI v6: ♭.rec. Layout: [f, m] (2 fields).
|
||||
// eval env (.flatElim f m) =
|
||||
// match eval env m with
|
||||
// | .vFlatIntro a → vApp (eval env f) a (β-rule)
|
||||
// | .vneu n → .vneu (.nflatElim (eval env f) n)
|
||||
// | _ → marker neutral
|
||||
// (mirror Cubical/Eval.lean axioms eval_flatElim_beta /
|
||||
// eval_flatElim_stuck.)
|
||||
let f = ctor_field(t, 0);
|
||||
let m = ctor_field(t, 1);
|
||||
let vm = eval(env, m);
|
||||
let vm_ro = vm as LeanObj;
|
||||
match ctor_tag(vm_ro) {
|
||||
VAL_VFLAT_INTRO => {
|
||||
// β-reduce: extract the wrapped value, drop the
|
||||
// outer .vFlatIntro, and apply f to it.
|
||||
let inner = ctor_field(vm_ro, 0);
|
||||
retain(inner);
|
||||
release(vm_ro);
|
||||
let vf = eval(env, f);
|
||||
vapp(vf, inner as LeanObjMut)
|
||||
}
|
||||
VAL_VNEU => {
|
||||
// Stuck: extract the inner CNeu, build .nflatElim
|
||||
// with the evaluated eliminator function.
|
||||
let inner_neu = ctor_field(vm_ro, 0);
|
||||
retain(inner_neu);
|
||||
release(vm_ro);
|
||||
let vf = eval(env, f);
|
||||
let nelim = mk_nflat_elim(vf as LeanObj, inner_neu);
|
||||
mk_vneu(nelim as LeanObj)
|
||||
}
|
||||
_ => {
|
||||
release(vm_ro);
|
||||
stuck_marker(b"<flatElim: scrutinee is not flat-canonical>\0")
|
||||
}
|
||||
}
|
||||
}
|
||||
TERM_SHARP_ELIM => {
|
||||
let f = ctor_field(t, 0);
|
||||
let m = ctor_field(t, 1);
|
||||
let vm = eval(env, m);
|
||||
let vm_ro = vm as LeanObj;
|
||||
match ctor_tag(vm_ro) {
|
||||
VAL_VSHARP_INTRO => {
|
||||
let inner = ctor_field(vm_ro, 0);
|
||||
retain(inner);
|
||||
release(vm_ro);
|
||||
let vf = eval(env, f);
|
||||
vapp(vf, inner as LeanObjMut)
|
||||
}
|
||||
VAL_VNEU => {
|
||||
let inner_neu = ctor_field(vm_ro, 0);
|
||||
retain(inner_neu);
|
||||
release(vm_ro);
|
||||
let vf = eval(env, f);
|
||||
let nelim = mk_nsharp_elim(vf as LeanObj, inner_neu);
|
||||
mk_vneu(nelim as LeanObj)
|
||||
}
|
||||
_ => {
|
||||
release(vm_ro);
|
||||
stuck_marker(b"<sharpElim: scrutinee is not sharp-canonical>\0")
|
||||
}
|
||||
}
|
||||
}
|
||||
TERM_SHAPE_ELIM => {
|
||||
let f = ctor_field(t, 0);
|
||||
let m = ctor_field(t, 1);
|
||||
let vm = eval(env, m);
|
||||
let vm_ro = vm as LeanObj;
|
||||
match ctor_tag(vm_ro) {
|
||||
VAL_VSHAPE_INTRO => {
|
||||
let inner = ctor_field(vm_ro, 0);
|
||||
retain(inner);
|
||||
release(vm_ro);
|
||||
let vf = eval(env, f);
|
||||
vapp(vf, inner as LeanObjMut)
|
||||
}
|
||||
VAL_VNEU => {
|
||||
let inner_neu = ctor_field(vm_ro, 0);
|
||||
retain(inner_neu);
|
||||
release(vm_ro);
|
||||
let vf = eval(env, f);
|
||||
let nelim = mk_nshape_elim(vf as LeanObj, inner_neu);
|
||||
mk_vneu(nelim as LeanObj)
|
||||
}
|
||||
_ => {
|
||||
release(vm_ro);
|
||||
stuck_marker(b"<shapeElim: scrutinee is not shape-canonical>\0")
|
||||
}
|
||||
}
|
||||
}
|
||||
TERM_INDELIM => {
|
||||
// .indElim S params motive branches target — β-reduce on a
|
||||
// canonical vctor target; otherwise build .nIndElim stuck.
|
||||
|
|
@ -402,8 +513,12 @@ pub fn vapp(f: LeanObjMut, a: LeanObjMut) -> LeanObjMut {
|
|||
release(f_ro);
|
||||
result
|
||||
}
|
||||
VAL_VPLAM | VAL_VTUBEAPP | VAL_VPATHTRANSP | VAL_VPAIR | VAL_VCODE => {
|
||||
VAL_VPLAM | VAL_VTUBEAPP | VAL_VPATHTRANSP | VAL_VPAIR | VAL_VCODE
|
||||
| VAL_VFLAT_INTRO | VAL_VSHARP_INTRO | VAL_VSHAPE_INTRO => {
|
||||
// Ill-typed application; marker neutral per FFI_DESIGN §6.
|
||||
// ABI v6: modal intros are not functions either — they
|
||||
// mirror the Lean `eval`'s explicit arm for vFlat/Sharp/
|
||||
// ShapeIntro applied as a function.
|
||||
release(f_ro);
|
||||
release(a as LeanObj);
|
||||
stuck_marker(b"<vApp: non-function value applied>\0")
|
||||
|
|
|
|||
|
|
@ -583,6 +583,30 @@ pub fn readback(v: LeanObj) -> LeanObjMut {
|
|||
retain(l); retain(a);
|
||||
mk_term_code(l, a)
|
||||
}
|
||||
// ABI v6: modal-introduction values. Layout: [v] (1 field).
|
||||
// Mirrors Cubical/Readback.lean axioms readback_vFlatIntro etc.
|
||||
VAL_VFLAT_INTRO => {
|
||||
// readback (.vFlatIntro a) = .flatIntro (readback a)
|
||||
let inner = ctor_field(v, 0);
|
||||
let inner_term = readback(inner);
|
||||
let ctor = alloc_ctor(TERM_FLAT_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, inner_term as LeanObj);
|
||||
ctor
|
||||
}
|
||||
VAL_VSHARP_INTRO => {
|
||||
let inner = ctor_field(v, 0);
|
||||
let inner_term = readback(inner);
|
||||
let ctor = alloc_ctor(TERM_SHARP_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, inner_term as LeanObj);
|
||||
ctor
|
||||
}
|
||||
VAL_VSHAPE_INTRO => {
|
||||
let inner = ctor_field(v, 0);
|
||||
let inner_term = readback(inner);
|
||||
let ctor = alloc_ctor(TERM_SHAPE_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, inner_term as LeanObj);
|
||||
ctor
|
||||
}
|
||||
_ => {
|
||||
// Malformed — return a marker var.
|
||||
let msg = unsafe {
|
||||
|
|
@ -712,6 +736,41 @@ pub fn readback_neu(n: LeanObj) -> LeanObjMut {
|
|||
mk_term_indelim(schema, params, motive_term as LeanObj,
|
||||
branches_term as LeanObj, target_term as LeanObj)
|
||||
}
|
||||
// ABI v6: modal-elimination stuck neutrals. Layout: [f, n] —
|
||||
// field 0 is the evaluated eliminator function (a CVal),
|
||||
// field 1 is the stuck scrutinee (a CNeu). Mirrors
|
||||
// Cubical/Readback.lean readbackNeu_nflatElim etc.
|
||||
NEU_NFLAT_ELIM => {
|
||||
// readbackNeu (.nflatElim f n) = .flatElim (readback f) (readbackNeu n)
|
||||
let f = ctor_field(n, 0);
|
||||
let inner_neu = ctor_field(n, 1);
|
||||
let f_term = readback(f);
|
||||
let inner_term = readback_neu(inner_neu);
|
||||
let ctor = alloc_ctor(TERM_FLAT_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, f_term as LeanObj);
|
||||
ctor_set_field(ctor, 1, inner_term as LeanObj);
|
||||
ctor
|
||||
}
|
||||
NEU_NSHARP_ELIM => {
|
||||
let f = ctor_field(n, 0);
|
||||
let inner_neu = ctor_field(n, 1);
|
||||
let f_term = readback(f);
|
||||
let inner_term = readback_neu(inner_neu);
|
||||
let ctor = alloc_ctor(TERM_SHARP_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, f_term as LeanObj);
|
||||
ctor_set_field(ctor, 1, inner_term as LeanObj);
|
||||
ctor
|
||||
}
|
||||
NEU_NSHAPE_ELIM => {
|
||||
let f = ctor_field(n, 0);
|
||||
let inner_neu = ctor_field(n, 1);
|
||||
let f_term = readback(f);
|
||||
let inner_term = readback_neu(inner_neu);
|
||||
let ctor = alloc_ctor(TERM_SHAPE_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, f_term as LeanObj);
|
||||
ctor_set_field(ctor, 1, inner_term as LeanObj);
|
||||
ctor
|
||||
}
|
||||
_ => {
|
||||
let msg = unsafe {
|
||||
lean_mk_string(b"<readbackNeu: unknown CNeu>\0".as_ptr() as *const core::ffi::c_char)
|
||||
|
|
|
|||
|
|
@ -552,6 +552,61 @@ pub(crate) fn cterm_subst_dim(i: LeanObj, r: LeanObj, t: LeanObj) -> LeanObjMut
|
|||
retain(t);
|
||||
t as LeanObjMut
|
||||
}
|
||||
// ABI v6: modal introductions — recurse into the wrapped CTerm.
|
||||
// Layout: [a] (1 field, no implicit ℓ).
|
||||
TERM_FLAT_INTRO => {
|
||||
let a = ctor_field(t, 0);
|
||||
let na = cterm_subst_dim(i, r, a);
|
||||
let ctor = alloc_ctor(TERM_FLAT_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, na as LeanObj);
|
||||
ctor
|
||||
}
|
||||
TERM_SHARP_INTRO => {
|
||||
let a = ctor_field(t, 0);
|
||||
let na = cterm_subst_dim(i, r, a);
|
||||
let ctor = alloc_ctor(TERM_SHARP_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, na as LeanObj);
|
||||
ctor
|
||||
}
|
||||
TERM_SHAPE_INTRO => {
|
||||
let a = ctor_field(t, 0);
|
||||
let na = cterm_subst_dim(i, r, a);
|
||||
let ctor = alloc_ctor(TERM_SHAPE_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, na as LeanObj);
|
||||
ctor
|
||||
}
|
||||
// ABI v6: modal eliminations — recurse into both subterms.
|
||||
// Layout: [f, m] (2 fields).
|
||||
TERM_FLAT_ELIM => {
|
||||
let f = ctor_field(t, 0);
|
||||
let m = ctor_field(t, 1);
|
||||
let nf = cterm_subst_dim(i, r, f);
|
||||
let nm = cterm_subst_dim(i, r, m);
|
||||
let ctor = alloc_ctor(TERM_FLAT_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, nf as LeanObj);
|
||||
ctor_set_field(ctor, 1, nm as LeanObj);
|
||||
ctor
|
||||
}
|
||||
TERM_SHARP_ELIM => {
|
||||
let f = ctor_field(t, 0);
|
||||
let m = ctor_field(t, 1);
|
||||
let nf = cterm_subst_dim(i, r, f);
|
||||
let nm = cterm_subst_dim(i, r, m);
|
||||
let ctor = alloc_ctor(TERM_SHARP_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, nf as LeanObj);
|
||||
ctor_set_field(ctor, 1, nm as LeanObj);
|
||||
ctor
|
||||
}
|
||||
TERM_SHAPE_ELIM => {
|
||||
let f = ctor_field(t, 0);
|
||||
let m = ctor_field(t, 1);
|
||||
let nf = cterm_subst_dim(i, r, f);
|
||||
let nm = cterm_subst_dim(i, r, m);
|
||||
let ctor = alloc_ctor(TERM_SHAPE_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, nf as LeanObj);
|
||||
ctor_set_field(ctor, 1, nm as LeanObj);
|
||||
ctor
|
||||
}
|
||||
_ => {
|
||||
// Unknown tag — preserve identity by retaining + boxing as
|
||||
// raw object (no malformed-CTerm corruption).
|
||||
|
|
@ -731,6 +786,33 @@ fn mk_ty_el(l: LeanObj, p: LeanObj) -> LeanObjMut {
|
|||
ctor
|
||||
}
|
||||
|
||||
/// `.flat {ℓ} A` — ABI v6 cohesive-modality (♭). Layout: [ℓ, A].
|
||||
#[inline]
|
||||
fn mk_ty_flat(l: LeanObj, a: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(TY_FLAT, 2);
|
||||
ctor_set_field(ctor, 0, l);
|
||||
ctor_set_field(ctor, 1, a);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.sharp {ℓ} A` — ABI v6 cohesive-modality (♯). Layout: [ℓ, A].
|
||||
#[inline]
|
||||
fn mk_ty_sharp(l: LeanObj, a: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(TY_SHARP, 2);
|
||||
ctor_set_field(ctor, 0, l);
|
||||
ctor_set_field(ctor, 1, a);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.shape {ℓ} A` — ABI v6 cohesive-modality (ʃ). Layout: [ℓ, A].
|
||||
#[inline]
|
||||
fn mk_ty_shape(l: LeanObj, a: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(TY_SHAPE, 2);
|
||||
ctor_set_field(ctor, 0, l);
|
||||
ctor_set_field(ctor, 1, a);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.glue {ℓ} φ T f fInv sec ret coh A` — 9 fields.
|
||||
#[inline]
|
||||
fn mk_ty_glue(
|
||||
|
|
@ -868,6 +950,30 @@ pub(crate) fn ctype_subst_dim_bool(i: LeanObj, b: bool, a: LeanObj) -> LeanObjMu
|
|||
let new_p = cterm_subst_dim_bool(i, b, p);
|
||||
mk_ty_el(l, new_p as LeanObj)
|
||||
}
|
||||
// ABI v6: cohesive modalities — recurse into the wrapped CType.
|
||||
// Layout: [ℓ, A]. Mirrors Lean's CType.substDim arms for
|
||||
// .flat / .sharp / .shape.
|
||||
TY_FLAT => {
|
||||
let l = ctor_field(a, 0);
|
||||
let inner = ctor_field(a, 1);
|
||||
retain(l);
|
||||
let new_inner = ctype_subst_dim_bool(i, b, inner);
|
||||
mk_ty_flat(l, new_inner as LeanObj)
|
||||
}
|
||||
TY_SHARP => {
|
||||
let l = ctor_field(a, 0);
|
||||
let inner = ctor_field(a, 1);
|
||||
retain(l);
|
||||
let new_inner = ctype_subst_dim_bool(i, b, inner);
|
||||
mk_ty_sharp(l, new_inner as LeanObj)
|
||||
}
|
||||
TY_SHAPE => {
|
||||
let l = ctor_field(a, 0);
|
||||
let inner = ctor_field(a, 1);
|
||||
retain(l);
|
||||
let new_inner = ctype_subst_dim_bool(i, b, inner);
|
||||
mk_ty_shape(l, new_inner as LeanObj)
|
||||
}
|
||||
_ => {
|
||||
// Synthetic fallback at level zero.
|
||||
mk_ty_univ(lean_box_mut(0) as LeanObj)
|
||||
|
|
@ -1008,6 +1114,29 @@ pub(crate) fn ctype_subst_dim_expr(i: LeanObj, r: LeanObj, a: LeanObj) -> LeanOb
|
|||
let new_p = cterm_subst_dim(i, r, p);
|
||||
mk_ty_el(l, new_p as LeanObj)
|
||||
}
|
||||
// ABI v6: cohesive modalities — recurse into the wrapped CType.
|
||||
// Layout: [ℓ, A]. Mirrors Lean's CType.substDimExpr arms.
|
||||
TY_FLAT => {
|
||||
let l = ctor_field(a, 0);
|
||||
let inner = ctor_field(a, 1);
|
||||
retain(l);
|
||||
let new_inner = ctype_subst_dim_expr(i, r, inner);
|
||||
mk_ty_flat(l, new_inner as LeanObj)
|
||||
}
|
||||
TY_SHARP => {
|
||||
let l = ctor_field(a, 0);
|
||||
let inner = ctor_field(a, 1);
|
||||
retain(l);
|
||||
let new_inner = ctype_subst_dim_expr(i, r, inner);
|
||||
mk_ty_sharp(l, new_inner as LeanObj)
|
||||
}
|
||||
TY_SHAPE => {
|
||||
let l = ctor_field(a, 0);
|
||||
let inner = ctor_field(a, 1);
|
||||
retain(l);
|
||||
let new_inner = ctype_subst_dim_expr(i, r, inner);
|
||||
mk_ty_shape(l, new_inner as LeanObj)
|
||||
}
|
||||
_ => {
|
||||
mk_ty_univ(lean_box_mut(0) as LeanObj)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ pub const TY_IND: u32 = 5; // REL1: schema-based inductive type
|
|||
pub const TY_INTERVAL: u32 = 6; // REL2: cubical interval primitive
|
||||
pub const TY_LIFT: u32 = 7; // ABI v4: cumulativity constructor
|
||||
pub const TY_EL: u32 = 8; // ABI v5: universe-code decoder `El P`
|
||||
pub const TY_FLAT: u32 = 9; // ABI v6: cohesive modality `♭ A` (flat)
|
||||
pub const TY_SHARP: u32 = 10; // ABI v6: cohesive modality `♯ A` (sharp)
|
||||
pub const TY_SHAPE: u32 = 11; // ABI v6: cohesive modality `ʃ A` (shape)
|
||||
|
||||
// ── CTerm (Cubical/Syntax.lean) ────────────────────────────────────────────
|
||||
|
||||
|
|
@ -66,6 +69,12 @@ pub const TERM_DIMEXPR: u32 = 13; // REL1: dim expression lifted to CTerm
|
|||
pub const TERM_CTOR: u32 = 14; // REL1: schema constructor application
|
||||
pub const TERM_INDELIM: u32 = 15; // REL1: inductive eliminator
|
||||
pub const TERM_CODE: u32 = 16; // ABI v5: universe-code encoder `code A`
|
||||
pub const TERM_FLAT_INTRO: u32 = 17; // ABI v6: η_♭ — flatIntro a
|
||||
pub const TERM_SHARP_INTRO: u32 = 18; // ABI v6: η_♯ — sharpIntro a
|
||||
pub const TERM_SHAPE_INTRO: u32 = 19; // ABI v6: η_ʃ — shapeIntro a
|
||||
pub const TERM_FLAT_ELIM: u32 = 20; // ABI v6: ♭.rec — flatElim f m
|
||||
pub const TERM_SHARP_ELIM: u32 = 21; // ABI v6: ♯.rec — sharpElim f m
|
||||
pub const TERM_SHAPE_ELIM: u32 = 22; // ABI v6: ʃ.rec — shapeElim f m
|
||||
|
||||
// ── CEnv (Cubical/Value.lean) ──────────────────────────────────────────────
|
||||
|
||||
|
|
@ -86,6 +95,9 @@ pub const VAL_VPAIR: u32 = 8;
|
|||
pub const VAL_VCTOR: u32 = 9; // REL1: canonical schema-ctor value
|
||||
pub const VAL_VDIMEXPR: u32 = 10; // REL1: lifted dim-expression value
|
||||
pub const VAL_VCODE: u32 = 11; // ABI v5: universe-code value `vcode A`
|
||||
pub const VAL_VFLAT_INTRO: u32 = 12; // ABI v6: vFlatIntro v — η_♭ value
|
||||
pub const VAL_VSHARP_INTRO: u32 = 13; // ABI v6: vSharpIntro v — η_♯ value
|
||||
pub const VAL_VSHAPE_INTRO: u32 = 14; // ABI v6: vShapeIntro v — η_ʃ value
|
||||
|
||||
// ── CNeu (Cubical/Value.lean) ──────────────────────────────────────────────
|
||||
|
||||
|
|
@ -101,3 +113,6 @@ pub const NEU_NUNGLUE: u32 = 8;
|
|||
pub const NEU_NFST: u32 = 9;
|
||||
pub const NEU_NSND: u32 = 10;
|
||||
pub const NEU_NINDELIM: u32 = 11; // REL1: stuck inductive eliminator
|
||||
pub const NEU_NFLAT_ELIM: u32 = 12; // ABI v6: stuck nflatElim f n
|
||||
pub const NEU_NSHARP_ELIM: u32 = 13; // ABI v6: stuck nsharpElim f n
|
||||
pub const NEU_NSHAPE_ELIM: u32 = 14; // ABI v6: stuck nshapeElim f n
|
||||
|
|
|
|||
|
|
@ -322,6 +322,68 @@ pub(crate) fn mk_term_code(l: LeanObj, a: LeanObj) -> LeanObjMut {
|
|||
ctor
|
||||
}
|
||||
|
||||
// ── ABI v6: cohesive modality value/neutral builders ───────────────────────
|
||||
//
|
||||
// Three intro values (vFlatIntro / vSharpIntro / vShapeIntro) carry one
|
||||
// CVal payload. Three stuck-elim neutrals (nflatElim / nsharpElim /
|
||||
// nshapeElim) carry the evaluated eliminator function (CVal) and the
|
||||
// stuck scrutinee (CNeu). No implicit ULevel — modal intros and
|
||||
// elims are CTerm/CVal-typed, not CType-typed (the modal's ULevel
|
||||
// lives on the surrounding CType.flat/.sharp/.shape, not here).
|
||||
|
||||
/// `.vFlatIntro v` — η_♭ value (ABI v6). Layout: `[v]` (1 field).
|
||||
#[inline]
|
||||
pub(crate) fn mk_vflat_intro(v: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(VAL_VFLAT_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, v);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.vSharpIntro v` — η_♯ value (ABI v6). Layout: `[v]` (1 field).
|
||||
#[inline]
|
||||
pub(crate) fn mk_vsharp_intro(v: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(VAL_VSHARP_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, v);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.vShapeIntro v` — η_ʃ value (ABI v6). Layout: `[v]` (1 field).
|
||||
#[inline]
|
||||
pub(crate) fn mk_vshape_intro(v: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(VAL_VSHAPE_INTRO, 1);
|
||||
ctor_set_field(ctor, 0, v);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.nflatElim f n` — stuck flat-eliminator neutral (ABI v6).
|
||||
/// Layout: `[f, n]` (2 fields): the evaluated eliminator function and
|
||||
/// the stuck scrutinee.
|
||||
#[inline]
|
||||
pub(crate) fn mk_nflat_elim(f: LeanObj, n: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(NEU_NFLAT_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, f);
|
||||
ctor_set_field(ctor, 1, n);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.nsharpElim f n` — stuck sharp-eliminator neutral (ABI v6).
|
||||
#[inline]
|
||||
pub(crate) fn mk_nsharp_elim(f: LeanObj, n: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(NEU_NSHARP_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, f);
|
||||
ctor_set_field(ctor, 1, n);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.nshapeElim f n` — stuck shape-eliminator neutral (ABI v6).
|
||||
#[inline]
|
||||
pub(crate) fn mk_nshape_elim(f: LeanObj, n: LeanObj) -> LeanObjMut {
|
||||
let ctor = alloc_ctor(NEU_NSHAPE_ELIM, 2);
|
||||
ctor_set_field(ctor, 0, f);
|
||||
ctor_set_field(ctor, 1, n);
|
||||
ctor
|
||||
}
|
||||
|
||||
/// `.nIndElim S params motive branches target` — stuck eliminator
|
||||
/// neutral. Five fields per the Lean definition. No implicit ULevel.
|
||||
#[inline]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue