Skip to content

Commit 0f8b01d

Browse files
hyperpolymathclaude
andcommitted
fix(CNO,lib): typecheck CNO.agda under --safe + add agda-lib
Unblocks the Echo<->CNO content-bridge in hyperpolymath/echo-types#21. Three changes: 1. Adds top-level absolute-zero.agda-lib declaring this repo's Agda library so downstream consumers (currently echo-types, later VeriSim and others in the hyperpolymath ecosystem) can `depend: absolute-zero` and resolve `open import CNO` cleanly. 2. Adds `{-# OPTIONS --safe --without-K #-}` to proofs/agda/CNO.agda so it composes with the rest of the verification ecosystem (echo-types, VeriSim, etc.), all of which run --safe --without-K. Verified clean: `agda --safe CNO.agda` exits 0. 3. Closes three latent issues in CNO.agda that the --safe check surfaces: * Parse errors at lines 316/323 inside ternary-add and crazy-op: `using (_Data.Nat.%_)` is not valid Agda (qualifying an operator name inside `using` is rejected by the parser). Replaces both helpers with a self-contained structural-recursive `mod3` which terminates inside --safe --without-K without pulling in Data.Nat.DivMod._%_'s NonZero instance noise. * Two unfilled holes (`{!!}`) at lines 303/304 in cno-composition's cno-identity and cno-pure fields. The former filled via state-eq-trans + transport along eval-seq-comp. The latter required a new helper `pure-trans`, defined via componentwise `trans` on the I/O and memory equalities. Both holes now resolve into closed, postulate-free IsCNO-record values. Result: composing two CNO programs is now a constructive theorem rather than a goal, and cno-composition is a real reusable lemma for downstream content-bridges. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent abd5a3a commit 0f8b01d

2 files changed

Lines changed: 45 additions & 13 deletions

File tree

absolute-zero.agda-lib

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: absolute-zero
2+
include: proofs/agda
3+
depend: standard-library

proofs/agda/CNO.agda

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# OPTIONS --safe --without-K #-}
2+
13
{- Certified Null Operations: Agda Formalization
24
35
This file provides an Agda formalization of CNO theory.
@@ -13,7 +15,8 @@ module CNO where
1315
open import Data.Nat using (ℕ; zero; suc; _+_; _*_)
1416
open import Data.List using (List; []; _∷_; _++_; length)
1517
open import Data.Product using (_×_; _,_; proj₁; proj₂; Σ; ∃)
16-
open import Relation.Binary.PropositionalEquality using (_≡_; refl; sym; trans; cong)
18+
open import Relation.Binary.PropositionalEquality
19+
using (_≡_; refl; sym; trans; cong; subst)
1720
open import Data.Bool using (Bool; true; false; if_then_else_)
1821
open import Data.Maybe using (Maybe; just; nothing)
1922
open import Function using (_∘_; id)
@@ -293,34 +296,60 @@ state-eq-trans (m₁ , r₁ , i₁ , p₁) (m₂ , r₂ , i₂ , p₂) =
293296
trans i₁ i₂ ,
294297
trans p₁ p₂
295298

296-
-- Composition of CNOs is a CNO
299+
-- Pointwise-transitive purity: agree on I/O and on memory.
300+
-- Uses `proj₁`/`proj₂` rather than pattern-matching on `_,_`
301+
-- because `pure` is a definitional `_×_` and the unifier sometimes
302+
-- declines to unfold it in pattern positions.
303+
pure-trans : {s₁ s₂ s₃} pure s₁ s₂ pure s₂ s₃ pure s₁ s₃
304+
pure-trans p₁₂ p₂₃ =
305+
trans (proj₁ p₁₂) (proj₁ p₂₃) ,
306+
(λ addr trans (proj₂ p₁₂ addr) (proj₂ p₂₃ addr))
307+
308+
-- Composition of CNOs is a CNO. The two non-trivial fields
309+
-- (`cno-identity`, `cno-pure`) chain the per-program lemmas
310+
-- through `eval p₁ s` and transport along `eval-seq-comp` to the
311+
-- composite evaluation.
297312
cno-composition : {p₁ p₂} IsCNO p₁ IsCNO p₂ IsCNO (seq-comp p₁ p₂)
298313
cno-composition {p₁} {p₂} cno₁ cno₂ = record
299314
{ cno-terminates = λ s terminates-always (seq-comp p₁ p₂) s
300315
; cno-identity = λ s
301316
let eq₁ = IsCNO.cno-identity cno₁ s
302317
eq₂ = IsCNO.cno-identity cno₂ (eval p₁ s)
303-
in {!!} -- Requires more work with rewrite
304-
; cno-pure = λ s {!!}
318+
in subst (λ x state-eq x s) (sym (eval-seq-comp p₁ p₂ s))
319+
(state-eq-trans eq₂ eq₁)
320+
; cno-pure = λ s
321+
let pu₁ : pure s (eval p₁ s)
322+
pu₁ = IsCNO.cno-pure cno₁ s
323+
pu₂ : pure (eval p₁ s) (eval p₂ (eval p₁ s))
324+
pu₂ = IsCNO.cno-pure cno₂ (eval p₁ s)
325+
composed : pure s (eval p₂ (eval p₁ s))
326+
composed = pure-trans {s₁ = s} {s₂ = eval p₁ s}
327+
{s₃ = eval p₂ (eval p₁ s)} pu₁ pu₂
328+
in subst (pure s) (sym (eval-seq-comp p₁ p₂ s)) composed
305329
; cno-reversible = λ s refl
306330
}
307331

308332
----------------------------------------------------------------------------
309333
-- Malbolge-Specific
310334
----------------------------------------------------------------------------
311335

312-
-- Ternary operations
336+
-- Ternary operations: addition mod 3 (Malbolge-flavoured).
337+
-- Local `mod3` is structural-recursive on its argument, so it
338+
-- terminates and stays inside `--safe --without-K` without pulling
339+
-- in `Data.Nat.DivMod._%_` (whose `NonZero` instance lookup adds
340+
-- noise that this helper does not need).
341+
mod3 :
342+
mod3 zero = zero
343+
mod3 (suc zero) = suc zero
344+
mod3 (suc (suc zero)) = suc (suc zero)
345+
mod3 (suc (suc (suc n))) = mod3 n
346+
313347
ternary-add :
314-
ternary-add a b = (a + b) Data.Nat.% 3
315-
where
316-
open import Data.Nat.DivMod using (_Data.Nat.%_)
317-
-- Simplified for demonstration
348+
ternary-add a b = mod3 (a + b)
318349

319-
-- Crazy operation
350+
-- Crazy operation (Malbolge crazy op surface; placeholder semantics)
320351
crazy-op :
321-
crazy-op a b = (a + b) Data.Nat.% 3
322-
where
323-
open import Data.Nat.DivMod using (_Data.Nat.%_)
352+
crazy-op a b = mod3 (a + b)
324353

325354
----------------------------------------------------------------------------
326355
-- Absolute Zero

0 commit comments

Comments
 (0)