open import DynamicallyChecked.Universe
open import Data.Nat
module HoareLogic.Completeness {n : ℕ} {F : Functor n} where
open import DynamicallyChecked.Utilities
open import DynamicallyChecked.Partiality
open import DynamicallyChecked.Lens
open import DynamicallyChecked.Case as Case
open import DynamicallyChecked.Rearrangement
open import DynamicallyChecked.BiGUL
open import HoareLogic.Semantics
open import HoareLogic.Rearrangement
open import HoareLogic.Case
open import HoareLogic.Triple
open import Function
open import Data.Product as Product
open import Data.Sum
open import Data.Bool
open import Data.Maybe
open import Data.List as List
open import Relation.Nullary
open import Relation.Binary.PropositionalEquality
skip-branch :
{S V : U n} (bs bs' : List (CaseBranch F S V)) (cont : ⟦ S ⟧ (μ F) → Par (⟦ S ⟧ (μ F)))
(s' s : ⟦ S ⟧ (μ F)) (v : ⟦ V ⟧ (μ F)) →
put-with-adaptation (⟦ S ⟧ (μ F)) (⟦ V ⟧ (μ F)) (interp-CaseBranch (revcat bs' bs)) [] s v cont ↦ s' →
OutOfDomain (List.map proj₁ bs') (s , v) →
put-with-adaptation (⟦ S ⟧ (μ F)) (⟦ V ⟧ (μ F)) (interp-CaseBranch bs) (interp-CaseBranch bs') s v cont ↦ s'
skip-branch bs [] cont s' s v seq out = seq
skip-branch bs ((p , normal b q) ∷ bs') cont s' s v seq (p-s-v≡false , out)
with skip-branch ((p , normal b q) ∷ bs) bs' cont s' s v seq out
... | c rewrite p-s-v≡false = c
skip-branch bs ((p , adaptive f) ∷ bs') cont s' s v seq (p-s-v≡false , out)
with skip-branch ((p , adaptive f) ∷ bs) bs' cont s' s v seq out
... | c rewrite p-s-v≡false = c
project-normal-branch :
{S V : U n} (bs bs' : List (CaseBranch F S V))
(p : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F) → Bool) (b : BiGUL F S V) (q : ⟦ S ⟧ (μ F) → Bool)
(cont : ⟦ S ⟧ (μ F) → Par (⟦ S ⟧ (μ F))) (s' s : ⟦ S ⟧ (μ F)) (v : ⟦ V ⟧ (μ F)) → p s v ≡ true →
put-with-adaptation (⟦ S ⟧ (μ F)) (⟦ V ⟧ (μ F))
(interp-CaseBranch ((p , normal b q) ∷ bs)) (interp-CaseBranch bs') s v cont ↦ s' →
Lens.put (interp b) s v ↦ s'
project-normal-branch bs bs' p b q cont s' s v p-s-v≡true seq rewrite p-s-v≡true with seq
... | c >>= assert _ then assert _ then _ >>= return refl = c
project-adaptive-branch :
{S V : U n} (bs bs' : List (CaseBranch F S V))
(p : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F) → Bool) (f : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F) → ⟦ S ⟧ (μ F))
(cont : ⟦ S ⟧ (μ F) → Par (⟦ S ⟧ (μ F))) (s' s : ⟦ S ⟧ (μ F)) (v : ⟦ V ⟧ (μ F)) → p s v ≡ true →
put-with-adaptation (⟦ S ⟧ (μ F)) (⟦ V ⟧ (μ F))
(interp-CaseBranch ((p , adaptive f) ∷ bs)) (interp-CaseBranch bs') s v cont ↦ s' →
cont (f s v) ↦ s'
project-adaptive-branch bs bs' p f cont s' s v p-s-v≡true c rewrite p-s-v≡true = c
mutual
semantics-triple :
{S V : U n} (b : BiGUL F S V) →
Triple (λ { (s , v) → Σ[ s' ∈ ⟦ S ⟧ (μ F) ] runPar (Lens.put (interp b) s v) ≡ just s' })
b
(λ { (s' , s , v) → runPar (Lens.put (interp b) s v) ≡ just s' })
semantics-triple fail = conseq (λ { (_ , ()) }) fail (λ { (() , _) })
semantics-triple (skip {S} {V} f) =
conseq (aux-pre ∘ toCompSeq ∘ proj₂)
skip
(λ { {.s , s , v} (refl , _ , eq) → fromCompSeq (aux-post (aux-pre (toCompSeq eq))) })
where
aux-pre : {s' s : ⟦ S ⟧ (μ F)} {v : ⟦ V ⟧ (μ F)} → Lens.put (interp (skip {S = S} {V} f)) s v ↦ s' → f s ≡ v
aux-pre {s'} {s} {v} c with U-dec V (f s) v
aux-pre (return refl) | yes f-s≡v = f-s≡v
aux-pre () | no _
aux-post : {s : ⟦ S ⟧ (μ F)} {v : ⟦ V ⟧ (μ F)} → f s ≡ v → Lens.put (interp (skip {S = S} {V} f)) s v ↦ s
aux-post {s} {v} f-s≡v with U-dec V (f s) v
aux-post {s} {v} f-s≡v | yes _ = return refl
aux-post {s} {v} f-s≡v | no f-s≢v with f-s≢v f-s≡v
aux-post {s} {v} f-s≡v | no f-s≢v | ()
semantics-triple replace = conseq (λ _ → tt) replace (λ { (eq , _) → cong just (sym eq) })
semantics-triple (prod {Sl} {Vl} {Sr} {Vr} l r) =
conseq (λ { ((sl' , sr') , eq) →
case toCompSeq {mx = Lens.put (interp (prod l r)) _ _} eq of λ {
(cl >>= cr >>= return refl) → (sl' , fromCompSeq {mx = Lens.put (interp l) _ _} cl) ,
(sr' , fromCompSeq {mx = Lens.put (interp r) _ _} cr) } })
(prod (semantics-triple l) (semantics-triple r))
(λ { ((eql , eqr) , _) →
fromCompSeq {mx = Lens.put (interp (prod l r)) _ _} (toCompSeq eql >>= toCompSeq eqr >>= return refl) })
semantics-triple (rearrS spat spat' expr c b) =
conseq (λ { {s , v} (s' , eq) →
case toCompSeq {mx = Lens.put (interp (rearrS spat spat' expr c b)) _ _} eq of λ {
((deconstruct↦ >>= return refl) >>= put-b↦ >>= put-iso↦) →
case Iso.from-to-inverse (rearrangement-iso spat spat' expr c) put-iso↦ of λ {
(_ >>= return eq') → _ , toMatch spat s deconstruct↦ ,
_ , trans (fromCompSeq put-b↦) (cong just (sym eq')) } } })
(rearrS (λ { (res , v) →
∃ λ res' → runPar (Lens.put (interp b) (construct spat' (eval spat spat' expr res)) v) ≡
just (construct spat' (eval spat spat' expr res')) })
(λ { (res' , res , v) →
runPar (Lens.put (interp b) (construct spat' (eval spat spat' expr res)) v) ≡
just (construct spat' (eval spat spat' expr res')) })
(conseq (λ { {t , v} (res , e , res' , eq) →
construct spat' (eval spat spat' expr res') ,
subst (λ x → runPar (Lens.put (interp b) x v) ≡
just (construct spat' (eval spat spat' expr res')))
(fromEval spat spat' expr t e) eq })
(semantics-triple b)
(λ { {t' , t , v} (eq , res , e , res' , eq') →
let eq'' = cong-from-just
(trans (sym (subst (λ x → runPar (Lens.put (interp b) x v) ≡
just (construct spat' (eval spat spat' expr res')))
(fromEval spat spat' expr _ e) eq'))
eq)
in (res' , res) , eq' , subst (λ x → Eval spat spat' expr (res' , x)) eq''
(toEval spat spat' expr) , e })))
(λ { {s' , s , v} (((res' , res) , eq , m' , m) , pre) →
fromCompSeq {mx = Lens.put (interp (rearrS spat spat' expr c b)) _ _}
((fromMatch spat s m >>= return refl) >>= toCompSeq eq >>=
Iso.to-from-inverse (rearrangement-iso spat spat' expr c) (fromMatch spat s' m' >>= return refl)) })
semantics-triple (rearrV vpat vpat' expr c b) =
conseq (λ { (s' , eq) →
case toCompSeq {mx = Lens.put (interp (rearrV vpat vpat' expr c b)) _ _} eq of λ {
((deconstruct↦ >>= return refl) >>= c) → _ , (_ , fromCompSeq c) , toMatch vpat _ deconstruct↦ } })
(rearrV (λ { (s , res) →
∃ λ s' → runPar (Lens.put (interp b) s (construct vpat' (eval vpat vpat' expr res))) ≡ just s' })
(λ { (s' , s , res) →
runPar (Lens.put (interp b) s (construct vpat' (eval vpat vpat' expr res))) ≡ just s' })
(conseq (λ { {s , w} (res , ((s' , eq) , e)) →
s' , subst (λ x → runPar (Lens.put (interp b) s x) ≡ just s')
(fromEval vpat vpat' expr w e) eq })
(semantics-triple b)
(λ { {s' , s , w} (eq , res , _ , e) →
res , subst (λ x → runPar (Lens.put (interp b) s x) ≡ just s')
(sym (fromEval vpat vpat' expr _ e)) eq , e })))
(λ { ((res , eq , m) , _) →
fromCompSeq {mx = Lens.put (interp (rearrV vpat vpat' expr c b)) _ _}
((fromMatch vpat _ m >>= return refl) >>= toCompSeq {mx = Lens.put (interp b) _ _} eq) })
semantics-triple (case bs) = case (semantics-triple-case bs [])
(λ { {sv} (s' , put-s-v≡just-s') →
subst (λ ps → CaseDomain ps sv) (sym (case-main-cond-lemma bs))
(inCaseDomain (interp-CaseBranch bs) [] (toCompSeq put-s-v≡just-s')) })
semantics-triple-case :
{S V : U n} (bs bs' : List (CaseBranch F S V)) →
CaseBranchTriple
(λ { (s , v) → Σ[ s' ∈ ⟦ S ⟧ (μ F) ] runPar (Lens.put (interp (case (revcat bs' bs))) s v) ≡ just s' })
(λ { (s' , s , v) → runPar (Lens.put (interp (case (revcat bs' bs))) s v) ≡ just s' })
(NormalCaseDomain (List.map (Product.map id (elimCaseBranchType (λ _ _ → true) (λ _ → false))) (revcat bs' bs)))
bs bs'
semantics-triple-case [] bs' = []
semantics-triple-case {S} {V} ((p , normal b q) ∷ bs) bs' =
conseq (λ { {s , v} ((s' , eq) , p-s-v≡true , OutOfDomain-bs'-s-v) →
s' , fromCompSeq {mx = Lens.put (interp b) s v}
(project-normal-branch bs bs' p b q _ s' s v p-s-v≡true
(skip-branch ((p , normal b q) ∷ bs) bs' _ s' s v
(toCompSeq {mx = Lens.put (interp (case (revcat bs' ((p , normal b q) ∷ bs)))) s v} eq)
OutOfDomain-bs'-s-v)) })
(semantics-triple b)
(λ { {s' , s , v} (put-b-s-v≡just-s' , (s'' , put-s-v≡just-s'') , p-s-v≡true , out-s-v) →
Product.map fromCompSeq id
(aux s' s'' s v (toCompSeq put-b-s-v≡just-s') (toCompSeq put-s-v≡just-s'') p-s-v≡true out-s-v) })
∷ᴺ semantics-triple-case bs ((p , normal b q) ∷ bs')
where
aux :
(s' s'' s : ⟦ S ⟧ (μ F)) (v : ⟦ V ⟧ (μ F)) →
Lens.put (interp b) s v ↦ s' → Lens.put (interp (case (revcat bs' ((p , normal b q) ∷ bs)))) s v ↦ s'' →
p s v ≡ true → OutOfDomain (List.map proj₁ bs') (s , v) →
Lens.put (interp (case (revcat bs' ((p , normal b q) ∷ bs)))) s v ↦ s' ×
(p s' v ≡ true × OutOfDomain (List.map proj₁ bs') (s' , v)) × (q s' ≡ true × OutOfRangeB bs' s')
aux s' s'' s v put-b-s-v↦s' put-s-v↦s'' p-s-v≡true out-s-v
with skip-branch ((p , normal b q) ∷ bs) bs' _ s'' s v put-s-v↦s'' out-s-v
aux s' s'' s v put-b-s-v↦s' put-s-v↦s'' p-s-v≡true out-s-v | c rewrite p-s-v≡true with c
aux s' s'' s v put-b-s-v↦s' put-s-v↦s'' p-s-v≡true out-s-v | _
| put-b-s-v↦s'' >>= assert p-s'-v≡true then assert q-s'≡true then check-diversion↦ >>= return refl
with CompSeq-deterministic put-b-s-v↦s' put-b-s-v↦s''
aux s' .s' s v put-b-s-v↦s' put-s-v↦s' p-s-v≡true out-s-v | _
| _ >>= assert p-s'-v≡true then assert q-s'≡true then check-diversion↦ >>= return refl | refl =
let (outd , outr) = check-diversion-inverse (interp-CaseBranch bs') s' v check-diversion↦
in put-s-v↦s' , (p-s'-v≡true , subst (λ cs → OutOfDomain cs (s' , v)) (sym (case-main-cond-lemma bs')) outd) ,
(q-s'≡true , case-out-of-range-inverse-lemma bs' outr)
semantics-triple-case {S} {V} ((p , adaptive f) ∷ bs) bs' =
(λ { s v ((s' , put-s-v≡just-s') , p-s-v≡true , out-s-v) →
let snd-seq =
fail-continuation (⟦ S ⟧ (μ F)) (⟦ V ⟧ (μ F)) (interp-CaseBranch (revcat bs' ((p , adaptive f) ∷ bs))) []
(project-adaptive-branch bs bs' p f _ s' s v p-s-v≡true
(skip-branch ((p , adaptive f) ∷ bs) bs' _ s' s v (toCompSeq put-s-v≡just-s') out-s-v))
in ((s' , fromCompSeq snd-seq) ,
subst (λ ps → NormalCaseDomain ps (f s v , v))
(sym (case-branch-type-lemma (revcat bs' ((p , adaptive f) ∷ bs))))
(inNormalCaseDomain (interp-CaseBranch (revcat bs' ((p , adaptive f) ∷ bs))) [] snd-seq)) ,
(λ s'' put-f-s-v-v≡just-s'' →
trans put-s-v≡just-s'
(cong just (CompSeq-deterministic snd-seq (toCompSeq put-f-s-v-v≡just-s'')))) })
∷ᴬ semantics-triple-case bs ((p , adaptive f) ∷ bs')
completeness :
{S V : U n} {R : ℙ (⟦ S ⟧ (μ F) × ⟦ V ⟧ (μ F))} (b : BiGUL F S V) {R' : ℙ (⟦ S ⟧ (μ F) × ⟦ S ⟧ (μ F) × ⟦ V ⟧ (μ F))} →
Sound R (Lens.put (interp b)) R' → Triple R b R'
completeness b {R'} sound =
conseq (λ {sv} r → Product.map id (fromCompSeq ∘ proj₁) (sound sv r))
(semantics-triple b)
(λ { {s' , s , v} (put-s-v≡just-s' , R-s-v) →
let (s'' , put-s-v↦s'' , R'-s''-s-v) = sound (s , v) R-s-v
in subst (λ x → R' (x , s , v))
(CompSeq-deterministic put-s-v↦s'' (toCompSeq put-s-v≡just-s'))
R'-s''-s-v })
interp-CaseBranch-revcat : {S V : U n} (bs bs' : List (CaseBranch F S V)) →
interp-CaseBranch (revcat bs' bs) ≡ revcat (interp-CaseBranch bs') (interp-CaseBranch bs)
interp-CaseBranch-revcat bs [] = refl
interp-CaseBranch-revcat bs ((p , normal b q) ∷ bs') = interp-CaseBranch-revcat ((p , normal b q) ∷ bs) bs'
interp-CaseBranch-revcat bs ((p , adaptive f) ∷ bs') = interp-CaseBranch-revcat ((p , adaptive f) ∷ bs) bs'
mutual
semantics-tripleR :
{S V : U n} (b : BiGUL F S V) →
TripleR (λ { (s , v) → runPar (Lens.get (interp b) s) ≡ just v })
b
(λ s → Σ[ v ∈ ⟦ V ⟧ (μ F) ] runPar (Lens.get (interp b) s) ≡ just v)
semantics-tripleR fail = conseq (λ { (() , _) }) fail (λ { (_ , ()) })
semantics-tripleR (skip f) = conseq (cong just ∘ proj₁) skip (λ _ → tt)
semantics-tripleR replace = conseq (cong just ∘ proj₁) replace (λ _ → tt)
semantics-tripleR (prod l r) =
conseq (λ { ((leq , req) , _) → fromCompSeq {mx = Lens.get (interp (prod l r)) _}
(toCompSeq leq >>= toCompSeq req >>= return refl) })
(prod (semantics-tripleR l) (semantics-tripleR r))
(λ { ((v , w) , eq) → case toCompSeq {mx = Lens.get (interp (prod l r)) _} eq of λ {
(l↦ >>= r↦ >>= return refl) → (v , fromCompSeq l↦) , (w , fromCompSeq r↦) } })
semantics-tripleR (rearrS spat tpat expr c b) =
conseq (λ { ((r , m , beq) , _) → fromCompSeq {mx = Lens.get (interp (rearrS spat tpat expr c b)) _}
((fromMatch spat _ m >>= return refl) >>= toCompSeq beq) })
(rearrS (λ { (r , v) → runPar (Lens.get (interp b) (construct tpat (eval spat tpat expr r))) ≡ just v })
(λ r → ∃ λ v → runPar (Lens.get (interp b) (construct tpat (eval spat tpat expr r))) ≡ just v)
(conseq (λ { {_ , v} (beq , r , _ , e) →
r , e , subst (λ t → runPar (Lens.get (interp b) t) ≡ just v)
(sym (fromEval spat tpat expr _ e)) beq })
(semantics-tripleR b)
(λ { (r , (v , beq) , e) →
v , subst (λ t → runPar (Lens.get (interp b) t) ≡ just v)
(fromEval spat tpat expr _ e) beq })))
(λ { (v , eq) →
case toCompSeq {mx = Lens.get (interp (rearrS spat tpat expr c b)) _} eq of λ {
((deconstruct↦ >>= return refl) >>= b↦) → _ , (v , fromCompSeq b↦) , toMatch spat _ deconstruct↦ } })
semantics-tripleR (rearrV vpat wpat expr c b) =
conseq (λ { ((r , beq , m) , _) →
fromCompSeq {mx = Lens.get (interp (rearrV vpat wpat expr c b)) _}
(toCompSeq beq >>=
Iso.to-from-inverse (rearrangement-iso vpat wpat expr c) (fromMatch vpat _ m >>= return refl)) })
(rearrV (λ { (s , r) → runPar (Lens.get (interp b) s) ≡ just (construct wpat (eval vpat wpat expr r)) })
{λ s → ∃ λ r → runPar (Lens.get (interp b) s) ≡ just (construct wpat (eval vpat wpat expr r))}
(conseq (λ { (beq , (r , beq')) →
r , beq' , subst (λ v → Eval vpat wpat expr (r , v))
(CompSeq-deterministic (toCompSeq {mx = Lens.get (interp b) _} beq')
(toCompSeq beq))
(toEval vpat wpat expr) })
(semantics-tripleR b)
(λ { (_ , beq) → _ , beq })))
(λ { {s} (v , eq) →
case toCompSeq {mx = Lens.get (interp (rearrV vpat wpat expr c b)) _} eq of λ {
(b↦ >>= seq) →
case Iso.from-to-inverse (rearrangement-iso vpat wpat expr c) seq of λ {
(_ >>= return refl) → _ , fromCompSeq b↦ } } })
semantics-tripleR (case bs) = conseq proj₁
(case (semantics-tripleR-case bs []))
(λ { (_ , eq) → semantics-tripleR-CaseRange bs [] (toCompSeq eq) tt tt })
semantics-tripleR-case :
{S V : U n} (bs bs' : List (CaseBranch F S V)) →
CaseBranchTripleR (λ { (s , v) → runPar (Lens.get (interp (case (revcat bs' bs))) s) ≡ just v }) bs bs'
semantics-tripleR-case [] bs' = []
semantics-tripleR-case {S} {V} ((p , normal b q) ∷ bs) bs' =
_∷ᴺ_ {P = λ s → ∃ λ v → runPar (Lens.get (interp b) s) ≡ just v ×
p s v ≡ true × OutOfDomain (List.map proj₁ bs') (s , v) × q s ≡ true × OutOfRangeB bs' s}
(conseq (λ { (beq , _ , beq' , peq , outd , qeq , outr) →
Product.map fromCompSeq id (aux (toCompSeq beq) (toCompSeq beq') peq outd qeq outr) })
(semantics-tripleR b)
(Product.map id proj₁))
(semantics-tripleR-case bs ((p , normal b q) ∷ bs'))
where
aux : {s : ⟦ S ⟧ (μ F)} {v v' : ⟦ V ⟧ (μ F)} →
Lens.get (interp b) s ↦ v → Lens.get (interp b) s ↦ v' →
p s v' ≡ true → OutOfDomain (List.map proj₁ bs') (s , v') → q s ≡ true → OutOfRangeB bs' s →
Lens.get (interp (case (revcat bs' ((p , normal b q) ∷ bs)))) s ↦ v ×
p s v ≡ true × OutOfDomain (List.map proj₁ bs') (s , v)
aux c c' peq outd qeq outr
with get-revcat _ _ ((p , normal (interp b) q) ∷ interp-CaseBranch bs) (interp-CaseBranch bs')
(check-diversion-success (interp-CaseBranch bs') _ _
(subst (λ ps → OutOfDomain ps _) (case-main-cond-lemma bs') outd) (case-out-of-range-lemma bs' outr))
aux c c' peq outd qeq outr | cont
rewrite CompSeq-deterministic c' c | interp-CaseBranch-revcat ((p , normal b q) ∷ bs) bs' | qeq =
cont (c >>= assert peq then return refl) , peq , outd
semantics-tripleR-case ((p , adaptive f) ∷ bs) bs' = •∷ᴬ semantics-tripleR-case bs ((p , adaptive f) ∷ bs')
semantics-tripleR-CaseRange :
{S V : U n} (bs bs' : List (CaseBranch F S V)) →
{s : ⟦ S ⟧ (μ F)} {v : ⟦ V ⟧ (μ F)} →
Lens.get (interp (case bs)) s ↦ v → OutOfDomain (List.map proj₁ bs') (s , v) → OutOfRangeB bs' s →
CaseRange (semantics-tripleR-case bs bs') s
semantics-tripleR-CaseRange [] bs' ()
semantics-tripleR-CaseRange ((p , normal b q) ∷ bs) bs' {s} c outd outr with q s | inspect q s
semantics-tripleR-CaseRange ((p , normal b q) ∷ bs) bs' (c >>= assert-not p-s-v≡false then return refl) outd outr
| false | [ q-s≡false ] =
inj₂ (semantics-tripleR-CaseRange bs ((p , normal b q) ∷ bs') c (p-s-v≡false , outd) (q-s≡false , outr))
semantics-tripleR-CaseRange ((p , normal b q) ∷ bs) bs' (c >>= assert p-s-v≡true then return refl) outd outr
| true | [ q-s≡true ] = inj₁ ((_ , fromCompSeq c , p-s-v≡true , outd , refl , outr) , refl , outr)
semantics-tripleR-CaseRange ((p , adaptive f) ∷ bs) bs' (c >>= assert-not p-s-v≡false then return refl) outd outr =
semantics-tripleR-CaseRange bs ((p , adaptive f) ∷ bs') c (p-s-v≡false , outd) outr
completenessR :
{S V : U n} {P : ℙ (⟦ S ⟧ (μ F))} (b : BiGUL F S V) {R : ℙ (⟦ S ⟧ (μ F) × ⟦ V ⟧ (μ F))} →
SoundG P (Lens.get (interp b)) R → TripleR R b P
completenessR b {R} soundG =
conseq (λ { {s , v} (get-s≡just-v , p) →
let (v' , get-s↦v' , r) = soundG s p
in subst (λ w → R (s , w)) (CompSeq-deterministic get-s↦v' (toCompSeq get-s≡just-v)) r })
(semantics-tripleR b)
(λ {s} p → Product.map id (fromCompSeq ∘ proj₁) (soundG s p))