Documentation

CatCryptCore.Relational.ForLoop

pRHL Loop-Congruence Rules #

Relational Hoare rules for List.forM and List.foldlM over SPComp, analogous to VCVio's rvcstep congruence steps for List.mapM/List.foldlM.

Instead of manually unrolling lists with repeated rHoare_bind/rHoare_ret, these rules discharge a synchronized loop in one application:

A unary companion section (in the CatCrypt.Core.SPComp namespace) provides the IsPure loop lemmas:

Usage sketch #

-- Both sides write the same key schedule; heap equality is invariant:
example (l : Location) (vs : List l.ty) :
    rHoare eqPre (vs.forM fun v => SPComp.set l v)
                 (vs.forM fun v => SPComp.set l v)
      (fun _ h₁ _ h₂ => eqPre h₁ h₂) :=
  rHoare_forM_same vs fun v _ => rHoare_set_sync l v ...

Unary IsPure loop lemmas #

theorem CatCrypt.Core.SPComp.mapM_isPure {α : Type u'} {β : Type v'} {f : αSPComp β} {xs : List α} (h : xxs, (f x).IsPure) :

List.mapM over SPComp is heap-pure when the body is heap-pure at every element of the list.

theorem CatCrypt.Core.SPComp.forM_isPure {α : Type u'} {f : αSPComp PUnit.{u_1 + 1}} {xs : List α} (h : xxs, (f x).IsPure) :
(xs.forM f).IsPure

List.forM over SPComp is heap-pure when the body is heap-pure at every element of the list.

theorem CatCrypt.Core.SPComp.foldlM_isPure {α : Type u'} {σ : Type w'} {f : σαSPComp σ} {xs : List α} (h : ∀ (s : σ), xxs, (f s x).IsPure) {s : σ} :

List.foldlM over SPComp is heap-pure when the step is heap-pure at every accumulator and every element of the list.

List.forM congruence #

theorem CatCrypt.Relational.rHoare_forM {α : Type u} {β : Type v} {R : αβProp} {I : RPre} {f : αCore.SPComp PUnit.{u_1 + 1}} {g : βCore.SPComp PUnit.{u_2 + 1}} {xs : List α} {ys : List β} (hR : List.Forall₂ R xs ys) (hbody : ∀ (x : α) (y : β), R x yrHoare I (f x) (g y) fun (x : PUnit.{u_1 + 1}) (h₁ : Core.Heap) (x_1 : PUnit.{u_2 + 1}) (h₂ : Core.Heap) => I h₁ h₂) :
rHoare I (xs.forM f) (ys.forM g) fun (x : PUnit.{u_1 + 1}) (h₁ : Core.Heap) (x_1 : PUnit.{u_2 + 1}) (h₂ : Core.Heap) => I h₁ h₂

Loop congruence for List.forM: if xs and ys are related pointwise by R and every related pair of loop bodies preserves the heap invariant I, then the two loops preserve I.

theorem CatCrypt.Relational.rHoare_forM_same {α : Type u} {I : RPre} {f : αCore.SPComp PUnit.{u_1 + 1}} {g : αCore.SPComp PUnit.{u_2 + 1}} (xs : List α) (hbody : xxs, rHoare I (f x) (g x) fun (x : PUnit.{u_1 + 1}) (h₁ : Core.Heap) (x_1 : PUnit.{u_2 + 1}) (h₂ : Core.Heap) => I h₁ h₂) :
rHoare I (xs.forM f) (xs.forM g) fun (x : PUnit.{u_1 + 1}) (h₁ : Core.Heap) (x_1 : PUnit.{u_2 + 1}) (h₂ : Core.Heap) => I h₁ h₂

Synchronous specialization of rHoare_forM: both sides iterate over the same list xs, with loop bodies f and g related pointwise on the elements of xs.

List.foldlM congruence #

theorem CatCrypt.Relational.rHoare_foldlM {α : Type u} {β : Type v} {σ₁ : Type w} {σ₂ : Type x} {R : αβProp} {V : σ₁σ₂Prop} {I : RPre} {f : σ₁αCore.SPComp σ₁} {g : σ₂βCore.SPComp σ₂} {xs : List α} {ys : List β} (hR : List.Forall₂ R xs ys) (hbody : ∀ (s₁ : σ₁) (s₂ : σ₂) (x : α) (y : β), R x yV s₁ s₂rHoare I (f s₁ x) (g s₂ y) fun (t₁ : σ₁) (h₁ : Core.Heap) (t₂ : σ₂) (h₂ : Core.Heap) => I h₁ h₂ V t₁ t₂) {s₁ : σ₁} {s₂ : σ₂} (hV : V s₁ s₂) :
rHoare I (List.foldlM f s₁ xs) (List.foldlM g s₂ ys) fun (t₁ : σ₁) (h₁ : Core.Heap) (t₂ : σ₂) (h₂ : Core.Heap) => I h₁ h₂ V t₁ t₂

Loop congruence for List.foldlM: in addition to the heap invariant I, a value relation V on the accumulators is threaded through every iteration. If the initial accumulators are V-related and each related step preserves both I and V, the folds end I-and-V-related.

theorem CatCrypt.Relational.rHoare_foldlM_same {α : Type u} {σ₁ : Type w} {σ₂ : Type x} {V : σ₁σ₂Prop} {I : RPre} {f : σ₁αCore.SPComp σ₁} {g : σ₂αCore.SPComp σ₂} (xs : List α) (hbody : ∀ (s₁ : σ₁) (s₂ : σ₂), xxs, V s₁ s₂rHoare I (f s₁ x) (g s₂ x) fun (t₁ : σ₁) (h₁ : Core.Heap) (t₂ : σ₂) (h₂ : Core.Heap) => I h₁ h₂ V t₁ t₂) {s₁ : σ₁} {s₂ : σ₂} (hV : V s₁ s₂) :
rHoare I (List.foldlM f s₁ xs) (List.foldlM g s₂ xs) fun (t₁ : σ₁) (h₁ : Core.Heap) (t₂ : σ₂) (h₂ : Core.Heap) => I h₁ h₂ V t₁ t₂

Synchronous specialization of rHoare_foldlM: both sides fold over the same list xs, with step functions related pointwise on elements of xs.

Examples #