Skip to content

Latest commit

 

History

History
390 lines (305 loc) · 16.4 KB

File metadata and controls

390 lines (305 loc) · 16.4 KB

Ephapax — Show Me The Receipts

The README makes claims. This file backs them up — every assertion in README.adoc is tied to a specific file, test, or proof obligation.

A dyadic linear+affine type system for compile-time WebAssembly memory safety. Resources are tracked through the type system so the compiler can guarantee — without a garbage collector — that no value is used after being freed, no resource is leaked, and region-scoped allocations are deallocated in bulk at scope exit.

— README

Claim: Dyadic Type System (L2)

The dyad is L2 in the four-layer architecture (see README.adoc#the-four-layers and docs/vision/EPHAPAX-VISION.adoc). This section presents the Rust-side evidence for the L2 discipline; L1 / L3 / L4 evidence follows below.

Evidence: The type checker (src/ephapax-typing/src/lib.rs) tracks BindingForm per context entry:

  • BindingForm::Let — affine discipline, demands_consumption() returns false

  • BindingForm::LetBang — linear discipline, demands_consumption() returns true

  • BindingForm::Param — follows type linearity

Tests test_let_allows_unconsumed_linear and test_let_bang_rejects_unconsumed verify the distinction. test_let_bang_rejects_unconsumed_unrestricted proves that let! enforces exactly-once even for unrestricted types like I32.

The Coq-side L2 evidence is linear_to_affine : Linear ≤ Affine (Qed, zero axioms) in formal/Modality.v.

Claim: Two-Layer AST (Surface + Core)

Evidence: Two separate crates:

  • src/ephapax-surface/ — Surface AST with DataDecl, Match, Construct, Pattern, SurfaceTy::Named

  • src/ephapax-syntax/ — Core AST with binary sums, case/inl/inr

  • src/ephapax-desugar/ — Transforms surface to core

The Coq formal proofs (formal/) reason about the core AST only. New surface features (pattern matching, named constructors) never invalidate the proofs.

Test integration_desugar_typecheck_no_parser in ephapax-desugar verifies the full pipeline: surface AST → desugar → core AST → type check.

Claim: Pattern Matching Desugars to Binary Sums

Evidence: src/ephapax-desugar/src/lib.rs implements:

  • data Option(a) = None | Some(a) → type () + a (right-nested binary sums)

  • Noneinl(()), Some(x)inr(x) (constructor injection chains)

  • match …​ of → nested case/inl/inr (case tree generation)

Tests: desugar_option_i32, desugar_color_green, desugar_color_blue, desugar_match_color (verifies nested case for 3-variant match), desugar_non_exhaustive_match (rejects incomplete patterns).

Claim: Dual Substructural Grammars

Evidence: ephapax-linear/ contains two EBNF grammar specifications:

  • grammar/linear.ebnf — no weakening, no contraction, branch agreement required

  • grammar/affine.ebnf — weakening OK, no contraction, branches may disagree

LinearChecker and AffineChecker in Rust enforce these grammars. 14 tests demonstrate where they diverge on identical programs (e.g. linear_rejects_unconsumed_let_bang vs affine_allows_unconsumed_let).

Claim: Region-Based Memory

Evidence: check_region in src/ephapax-typing/src/lib.rs enforces:

  1. NoRegionInType — return type must not reference the region (no escape)

  2. Consumption at region exit — only bindings that demands_consumption() must be consumed; affine bindings are implicitly dropped

Test test_region_non_escaping verifies escape detection. Test test_region_string_allocation verifies in-region allocation.

Claim: Sibling-safe region capabilities (L1)

Evidence: Region capabilities are threaded as input/output environments through every compound typing rule. A sibling cannot reference a region a previous sibling has exited — this is the soundness invariant the legacy judgment was missing.

  • Counterexample at formal/Counterexample.v (all five lemmas Qed) demonstrates the soundness gap the threading fixes.

  • The new has_type_l1 judgment lives in formal/TypingL1.v and carries the R-threading directly. Step relation at formal/Semantics_L1.v.

  • Design rationale at formal/PRESERVATION-DESIGN.md §3-§4.

  • Status: judgment landed; Semantics_L1.v carries 3 outer Admitted. markers covering 5 inner admit. cases — pre-existing L1 structural debt + parallel mirrors (file:line breakdown in PROOF-NEEDS.md §4).

Claim: Irreversibility residue is first-class (L3, wired)

Evidence: Operations that erase information (region exit, drop) produce typed residue witnesses, following the echo-types formulation. Linear mode requires the residue to be observed; Affine mode permits silent lowering.

  • Upstream theory at ~/developer/repos/echo-types/proofs/agda/EchoLinear.agda (lines 30–101), already mechanised.

  • Local mirror at formal/Echo.v — the L3 calculus is mechanised here (modes, LEcho, weaken, degrade_mode, all Qed).

  • Forward-looking design at formal/PRESERVATION-DESIGN.md §6.

  • Status: wiring landed (slice 4, 2026-05-27). preservation_l3_region_active_echo, preservation_l3_drop_echo, and the preservation_l3 umbrella in Semantics_L1.v are all Qed, each conditional on the region_shrink_preserves_typing_l1_gen_m L1 structural admit. Remaining L3 work is unconditional preservation_l3 (Phase 3b Stage 2).

Claim: Dyadic mode is project-level only (L4)

Evidence: L4 is a labelling discipline, not a proof layer. formal/L4.v carries ProgramMode (three-constructor enum) and program_mode_to_modality (total mapping to L2’s modality). No theorems, no admits, no axioms — by design.

  • Companion design note: formal/L4-DYADIC.md.

  • Canonical design source: formal/PRESERVATION-DESIGN.md §7.

  • Surface syntax for the L4 declaration (![ephapax_linear] / ![ephapax_affine] / #![module_boundary_mix(…​)]) is not yet wired into the parser or borrow checker; the mechanical scaffold is a citable type for downstream tools (Idris2 ABI, Rust borrow checker, surface parser).

Technology Choices

Technology Why

Rust

Compiler implementation language

Pest (PEG)

Parser generator — surface + core grammars

WASM

Compilation target — portable, sandboxed, near-native

Coq

Formal proofs of core calculus soundness

Idris 2

ABI definitions with dependent type proofs

Zig

FFI implementation (C-compatible, cross-compilation)

Dogfooded Across The Account

Technology / Pattern Role in Ephapax Also Used In

Dyadic type discipline (let / let!)

Core language design — affine (let) and linear (let!) bindings enforced by the type checker in src/ephapax-typing/src/lib.rs

gossamer (src/core/Bridge.eph uses let! for window handles and IPC channels); all Ephapax-backed applications in the account

Coq formal proofs

formal/ — progress and preservation theorems for the core calculus; two-layer AST keeps proofs stable as surface language grows

ephapax-pipewire proving ground (PipeWire filter-node linearity); proven repo (formal/coq/ — 48 Qed / 1 Admitted estate-wide)

Idris2 ABI + Zig FFI standard

idris2/ ABI definitions; Zig FFI layer per the hyperpolymath ABI/FFI universal standard

gossamer (HandleLinearity.idr, IPCIntegrity.idr), burble (src/Burble/ABI/), verisimdb, typed-wasm, standards monorepo

Two-layer AST (Surface / Core)

src/ephapax-surface/src/ephapax-desugar/src/ephapax-syntax/; proofs target core only so new surface features never invalidate them

AffineScript (surface/core split in the OCaml compiler); 007 (dual-AST safety design pattern)

Pattern matching desugared to binary sums

src/ephapax-desugar/ encodes N-variant ADTs as right-nested () + a + b + …​; match becomes nested case/inl/inr

Tangle language (braid-word case trees); k9-rs (sum-type dispatch)

File Map

Path What’s There

src/ephapax-syntax/

Core AST (minimal, Coq-proven)

src/ephapax-surface/

Surface AST (data, match, patterns)

src/ephapax-desugar/

Surface → Core transformation

src/ephapax-typing/

Dyadic type checker (let/let!/BindingForm)

src/ephapax-parser/

PEG parser (core + surface module)

src/ephapax-wasm/

WASM code generator with closure conversion

src/ephapax-runtime/

no_std WASM runtime with regions

src/ephapax-interp/

Tree-walking interpreter

src/ephapax-cli/

Command-line interface

src/ephapax-lsp/

Language server (completion, diagnostics)

src/ephapax-analysis/

Escape analysis, free vars, liveness

src/ephapax-stdlib/

Standard library (Prelude, Region, IO)

ephapax-linear/

Dual discipline checker (linear + affine grammars)

formal/

Coq proofs (Typing.v, progress/preservation)

idris2/

Idris 2 ABI definitions

spec/

Language specification (v2 grammar, specs)

docs/specs/

Design decisions, language comparison

examples/

Example programs (pattern_matching.eph)

conformance/

Conformance test suite (valid/invalid programs)

Claim: Mechanically Proved Soundness

Evidence: Two complementary formalisations, both run on every push.

Coq (formal/)

Important
Post-counterexample 2026-05-26 — read this before any older proof claim

The legacy preservation theorem in formal/Semantics.v is provably false. formal/Counterexample.v (5 Qed lemmas) demonstrates a configuration that types under the legacy judgment, steps via the operational semantics, and lands at an untypable post-state. The Admitted. on Theorem preservation is correct — no proof closes it.

The post-discovery work is the four-layer principled redesign documented in formal/PRESERVATION-DESIGN.md, where preservation is re-derived per layer from explicit invariants. Any earlier-in-this- README counts of "910 → 22 → 12 open goals" are archaeology, not instructions. See STATUS.adoc for the past/present/future map.

The Coq formalisation is now layered. Each layer has its own judgment, its own invariants, and its own per-layer preservation theorem.

Component Status Where

Counterexample regression (5 Qed)

✅ Pinned

formal/Counterexample.vbad_input_untypable_l1 Qed under both modes

L1 judgment (has_type_l1)

✅ 100% (2 Qed, 0 admits)

formal/TypingL1.v — modality-indexed, R-threaded

L1 semantics

🟡 37 Qed, 3 Admitted (5 inner admits — pre-existing L1 structural debt + parallel mirrors)

formal/Semantics_L1.v — 3 outer Admitted. markers cover 5 internal admit. cases. Per PROOF-NEEDS.md §4: pre-existing L1 structural debt (multiset/list-perm bridge + L2 effect-typed TFun per PRESERVATION-DESIGN.md §5.1 + lambda-rigidity at preservation_l1 body) and two parallel mirrors that close mechanically when their originals close.

L2 modality (Modality.v)

✅ Core landed (1 Qed, 0 axioms)

formal/Modality.v + m : Modality in has_type_l1. PRs #176 + #177. linear_to_affine Qed with zero axioms.

L3 echo / residue calculus

✅ Calculus 12 Qed + wiring landed (slice 4, 2026-05-27)

formal/Echo.v — one type former (fiber Echo f y := Σ x. f x ≡ y) + degrade map + no-section-collapse-to-residue proof. Wiring lemmas (preservation_l3_region_active_echo, preservation_l3_drop_echo, preservation_l3 umbrella) in Semantics_L1.v — all Qed, conditional on region_shrink_preserves_typing_l1_gen_m.

L4 dyadic interaction

✅ Phase A scaffold landed (formal/L4.v, 2026-05-28); definitions only

PModeLinear / PModeAffine / PModeBoundaryMix enum + program_mode_to_modality round-trip. No theorems by design. Design in formal/PRESERVATION-DESIGN.md §7.

Legacy Theorem preservation (formal/Semantics.v)

🛑 Provably false (Admitted)

Pinned by Counterexample.v. Do not attempt closure. Archaeology.

What’s done = Modality.linear_to_affine (Linear ⇒ Affine weakening, zero axioms), the L1 judgment, L3 fiber + degrade calculus, L3 wiring into the L1 step rules (slice 4 — preservation_l3 umbrella Qed conditional on the L1 structural admit), L4 Phase A scaffold (definitions only), and the counterexample regression witness. What’s todo = close the 3 Semantics_L1 outer Admitteds (pre-existing L1 structural debt: multiset/list-perm bridge + L2-effect-typed TFun + lambda-rigidity at preservation_l1), then state unconditional preservation_l3 (Phase 3b Stage 2). What’s banned = closing the legacy theorem, adding new Axiom declarations to discharge L1/L2 gaps, conflating ephapax-affine (this repo’s sublanguage) with AffineScript (a separate language at hyperpolymath/affinescript). Full per-sublanguage breakdown in PROOF-NEEDS.md.

Idris2 (idris2/src/Ephapax/ + src/formal/)

Two Idris2 developments:

Frontend (parser / typechecker / IR codec)idris2/src/Ephapax/ is the actual Idris2-side of the two-phase pipeline. As of 2026-05-20, all 9 files compile under %default total (8 files) or %default covering (1 file, the recursive- descent parser).

Module Default Notes

IR/SExpr, Parse/Stream, Parse/Util, Parse/Lexer, Affine/Typecheck

%default total

Fueled mutual recursion where Idris2 SCT couldn’t trace structural decrease through Stream-indexed parsers.

IR/AST, IR/Decode, Affine/Emit

%default total + 14 covering

covering markers are documented Idris2 0.8.0 SCT limits (showPrec / (/=) interface-dispatch loops, map/traverse through recursive types). Strictly stronger than the previous %default partial state.

Parse/Parser

%default covering

LL(k) recursive descent through ~30 mutually-recursive Stream- indexed parser combinators. Fueling all of them is a substantial separate refactor, deferred to a later campaign.

Zero believe_me, zero assert_total, zero assert_smaller in the entire frontend. The campaign that achieved this (PRs #89, #90, #91, #93, #94, #96, #97, #99, #100, all merged 2026-05-20) is documented in the project memory.

Region-linearity theoremssrc/formal/ proves structural properties of the region-linear calculus:

Theorem Where

noEscapeTheorem

src/formal/Ephapax/Formal/RegionLinear.idr:129

regionSafetyExtract

src/formal/Ephapax/Formal/RegionLinear.idr:139

noGCExtract

src/formal/Ephapax/Formal/RegionLinear.idr:151

orthogonalityLemma

src/formal/Ephapax/Formal/RegionLinear.idr:164

splitLinearCoverage

src/formal/Ephapax/Formal/Qualifier.idr (PR #85, 2026-05-19) — generalises nonDiminishment from head-position to all linear bindings.

All five with zero believe_me, zero postulates, under %default total.

Test Evidence

357 tests across 17 active workspace crates + tests/fuzz, 0 failures (per cargo test --all-targets; see TEST-NEEDS.md for the per-crate breakdown). Key test categories:

  • Type checker dyadic tests: let vs let! semantics, branch agreement, region exit (ephapax-typing)

  • Desugar tests: constructor encoding, match desugaring, exhaustiveness (ephapax-desugar)

  • Parser tests: surface syntax (data, match, constructors, named types) (ephapax-parser)

  • Discipline tests: linear vs affine checker divergence (ephapax-linear)

  • Integration tests: parse → desugar → typecheck end-to-end

  • Conformance tests: conformance/valid/ programs must type-check, conformance/invalid/ programs must be rejected

Design Documents

  • spec/ephapax-v2-grammar.ebnf — complete v2 grammar (modules, generics, effects, traits, comptime, contracts) — work in flight on feat/v2-grammar-* branches

  • docs/specs/DESIGN-DECISIONS.adoc — 17 ADRs with rationale

  • docs/specs/LANGUAGE-COMPARISON.adoc — comparison against 10 languages

  • docs/vision/EPHAPAX-VISION.adoc — design rationale, why dyadic
    regions + WASM

  • formal/PRESERVATION-HANDOFF.mdarchaeology only: per-case checklist from the pre-2026-05-26 legacy-judgment closure plan, retained for historical context. The legacy preservation is provably false; the path forward is the per-layer theorems documented in formal/PRESERVATION-DESIGN.md.

  • PROOF-NEEDS.md — outstanding proof obligations + leverage

Questions?

Open an issue or reach out directly.