open import DynamicallyChecked.Universe
open import Data.Nat
module HoareLogic.Rearrangement {n : ℕ} {F : Functor n} where
open import DynamicallyChecked.Utilities
open import DynamicallyChecked.Partiality
open import DynamicallyChecked.Lens
open import DynamicallyChecked.Universe
open import DynamicallyChecked.Rearrangement
open DynamicallyChecked.Rearrangement.Components
open import HoareLogic.Semantics
open import Function
open import Data.Product
open import Data.Sum
open import Data.Fin
open import Relation.Nullary
open import Relation.Binary.PropositionalEquality
Match : {G : U n} (pat : Pattern F G) → ℙ (⟦ G ⟧ (μ F) × PatResult pat)
Match var (x , res) = x ≡ res
Match (k y) (x , res) = x ≡ y
Match (left pat) (inj₁ x , res) = Match pat (x , res)
Match (left pat) (inj₂ x , res) = ⊥
Match (right pat) (inj₁ x , res) = ⊥
Match (right pat) (inj₂ x , res) = Match pat (x , res)
Match (prod lpat rpat) ((lx , rx) , (lres , rres)) = Match lpat (lx , lres) × Match rpat (rx , rres)
Match (con pat) (con x , res) = Match pat (x , res)
Eval-path : {G H : U n} (pat : Pattern F G) (path : VarPath pat H) → ℙ (PatResult pat × ⟦ H ⟧ (μ F))
Eval-path var refl (res , y) = res ≡ y
Eval-path (k x) () (res , y)
Eval-path (left pat) path (res , y) = Eval-path pat path (res , y)
Eval-path (right pat) path (res , y) = Eval-path pat path (res , y)
Eval-path (prod lpat rpat) (inj₁ path) ((lres , rres) , y) = Eval-path lpat path (lres , y)
Eval-path (prod lpat rpat) (inj₂ path) ((lres , rres) , y) = Eval-path rpat path (rres , y)
Eval-path (con pat) path (res , y) = Eval-path pat path (res , y)
Eval : {G H : U n} (pat : Pattern F G) (pat' : Pattern F H) (expr : Expr pat pat') → ℙ (PatResult pat × ⟦ H ⟧ (μ F))
Eval pat var path (res , y) = Eval-path pat path (res , y)
Eval pat (k x) expr (res , y) = x ≡ y
Eval pat (left pat') expr (res , inj₁ y) = Eval pat pat' expr (res , y)
Eval pat (left pat') expr (res , inj₂ y) = ⊥
Eval pat (right pat') expr (res , inj₁ y) = ⊥
Eval pat (right pat') expr (res , inj₂ y) = Eval pat pat' expr (res , y)
Eval pat (prod lpat' rpat') (lexpr , rexpr) (res , (ly , ry)) = Eval pat lpat' lexpr (res , ly) ×
Eval pat rpat' rexpr (res , ry)
Eval pat (con pat') expr (res , con y) = Eval pat pat' expr (res , y)
Rearr : {G H : U n} (pat : Pattern F G) (pat' : Pattern F H) (expr : Expr pat pat') → ℙ (⟦ G ⟧ (μ F) × ⟦ H ⟧ (μ F))
Rearr pat pat' expr = Match pat • Eval pat pat' expr
toMatch : {G : U n} (pat : Pattern F G) (x : ⟦ G ⟧ (μ F)) {res : PatResult pat} →
deconstruct pat x ↦ res → Match pat (x , res)
toMatch var x (return eq) = eq
toMatch {G} (k y) x deconstruct↦ with U-dec G y x
toMatch (k y) x deconstruct↦ | yes eq = sym eq
toMatch (k y) x () | no neq
toMatch (left pat) (inj₁ x) deconstruct↦ = toMatch pat x deconstruct↦
toMatch (left pat) (inj₂ x) ()
toMatch (right pat) (inj₁ x) ()
toMatch (right pat) (inj₂ x) deconstruct↦ = toMatch pat x deconstruct↦
toMatch (prod lpat rpat) (x , y) (deconstruct-lpat↦ >>= deconstruct-rpat↦ >>= return refl) =
toMatch lpat x deconstruct-lpat↦ , toMatch rpat y deconstruct-rpat↦
toMatch (con pat) (con x) deconstruct↦ = toMatch pat x deconstruct↦
toEval-path : {G H : U n} (pat : Pattern F G) (path : VarPath pat H)
{res : PatResult pat} → Eval-path pat path (res , eval-path pat path res)
toEval-path var refl = refl
toEval-path (k x) ()
toEval-path (left pat) path = toEval-path pat path
toEval-path (right pat) path = toEval-path pat path
toEval-path (prod lpat rpat) (inj₁ path) = toEval-path lpat path
toEval-path (prod lpat rpat) (inj₂ path) = toEval-path rpat path
toEval-path (con pat) path = toEval-path pat path
toEval : {G H : U n} (pat : Pattern F G) (pat' : Pattern F H) (expr : Expr pat pat')
{res : PatResult pat} → Eval pat pat' expr (res , construct pat' (eval pat pat' expr res))
toEval pat var path = toEval-path pat path
toEval pat (k x) expr = refl
toEval pat (left pat') expr = toEval pat pat' expr
toEval pat (right pat') expr = toEval pat pat' expr
toEval pat (prod lpat' rpat') (lexpr , rexpr) = toEval pat lpat' lexpr , toEval pat rpat' rexpr
toEval pat (con pat') expr = toEval pat pat' expr
toRearr : {G H : U n} (pat : Pattern F G) (pat' : Pattern F H) (expr : Expr pat pat')
{x : ⟦ G ⟧ (μ F)} {y : ⟦ H ⟧ (μ F)} → to pat pat' expr x ↦ y → Rearr pat pat' expr (x , y)
toRearr pat pat' expr (deconstruct↦ >>= return refl) = , toMatch pat _ deconstruct↦ , toEval pat pat' expr
fromEval-path : {G H : U n} (pat : Pattern F G) (path : VarPath pat H)
{res : PatResult pat} {y : ⟦ H ⟧ (μ F)} → Eval-path pat path (res , y) → eval-path pat path res ≡ y
fromEval-path var refl eval = eval
fromEval-path (k x) () eval
fromEval-path (left pat) path eval = fromEval-path pat path eval
fromEval-path (right pat) path eval = fromEval-path pat path eval
fromEval-path (prod lpat rpat) (inj₁ path) eval = fromEval-path lpat path eval
fromEval-path (prod lpat rpat) (inj₂ path) eval = fromEval-path rpat path eval
fromEval-path (con pat) path eval = fromEval-path pat path eval
fromMatch : {G : U n} (pat : Pattern F G) (x : ⟦ G ⟧ (μ F)) {res : PatResult pat} →
Match pat (x , res) → deconstruct pat x ↦ res
fromMatch var x match = return match
fromMatch {G} (k y) x match with U-dec G y x
fromMatch {G} (k y) x match | yes eq = return refl
fromMatch {G} (k y) x match | no neq with neq (sym match)
fromMatch {G} (k y) x match | no neq | ()
fromMatch (left pat) (inj₁ x) match = fromMatch pat x match
fromMatch (left pat) (inj₂ x) ()
fromMatch (right pat) (inj₁ x) ()
fromMatch (right pat) (inj₂ x) match = fromMatch pat x match
fromMatch (prod lpat rpat) (x , y) (lmatch , rmatch) = fromMatch lpat x lmatch >>= fromMatch rpat y rmatch >>= return refl
fromMatch (con pat) (con x) match = fromMatch pat x match
fromEval : {G H : U n} (pat : Pattern F G) (pat' : Pattern F H) (expr : Expr pat pat')
{res : PatResult pat} (y : ⟦ H ⟧ (μ F)) → Eval pat pat' expr (res , y) → construct pat' (eval pat pat' expr res) ≡ y
fromEval pat var path y eval = fromEval-path pat path eval
fromEval pat (k x) expr y eval = eval
fromEval pat (left pat') expr (inj₁ y) eval = cong inj₁ (fromEval pat pat' expr y eval)
fromEval pat (left pat') expr (inj₂ y) ()
fromEval pat (right pat') expr (inj₁ y) ()
fromEval pat (right pat') expr (inj₂ y) eval = cong inj₂ (fromEval pat pat' expr y eval)
fromEval pat (prod lpat' rpat') (lexpr , rexpr) (y , z) (leval , reval) = cong₂ _,_ (fromEval pat lpat' lexpr y leval)
(fromEval pat rpat' rexpr z reval)
fromEval pat (con pat') expr (con y) eval = cong con (fromEval pat pat' expr y eval)
fromRearr : {G H : U n} (pat : Pattern F G) (pat' : Pattern F H) (expr : Expr pat pat')
{x : ⟦ G ⟧ (μ F)} {y : ⟦ H ⟧ (μ F)} → Rearr pat pat' expr (x , y) → to pat pat' expr x ↦ y
fromRearr pat pat' expr (_ , match , eval) = fromMatch pat _ match >>= return (fromEval pat pat' expr _ eval)
rearrV-soundness :
{S : Set} {G H : U n} (vpat : Pattern F G) (vpat' : Pattern F H) (expr : Expr vpat vpat')
(c : CompleteExpr vpat vpat' expr) (l : S ⇆ ⟦ H ⟧ (μ F)) →
(R : ℙ (S × PatResult vpat)) (R' : ℙ (S × S × PatResult vpat)) →
Sound (R • Eval vpat vpat' expr) (Lens.put l)
(λ { (s' , s , v) → ∃ λ r → R' (s' , s , r) × Eval vpat vpat' expr (r , v) }) →
Sound (R • (Match vpat ∘ swap)) (Lens.put (l ◂ sym-iso (rearrangement-iso vpat vpat' expr c)))
(λ { (s' , s , v) → ∃ λ r → R' (s' , s , r) × Match vpat (v , r) })
rearrV-soundness vpat vpat' expr c l R R' l-sound (s , v) (r , R-s-r , Match-v-r) =
let v' = construct vpat' (eval vpat vpat' expr r)
(s' , l-s-v'↦s' , r' , R'-s'-s-r' , Eval-r'-v') = l-sound (s , v') (r , R-s-r , toEval vpat vpat' expr)
in s' , ((fromMatch vpat v Match-v-r >>= return refl) >>= l-s-v'↦s') ,
(r' , R'-s'-s-r' ,
subst (λ r → Match vpat (v , r))
(sym (eval-injective vpat vpat' expr c
(construct-injective vpat' (fromEval vpat vpat' expr v' Eval-r'-v'))))
Match-v-r)
rearrV-soundnessG :
{S : Set} {G H : U n} (vpat : Pattern F G) (vpat' : Pattern F H) (expr : Expr vpat vpat')
(c : CompleteExpr vpat vpat' expr) (l : S ⇆ ⟦ H ⟧ (μ F)) (P : ℙ S) (R : ℙ (S × PatResult vpat)) →
SoundG P (Lens.get l) (R • Eval vpat vpat' expr) →
SoundG P (Lens.get (l ◂ sym-iso (rearrangement-iso vpat vpat' expr c))) (R • (Match vpat ∘ swap))
rearrV-soundnessG vpat vpat' expr c l P R l-sound s Ps =
let (v' , get-l-s↦v' , env , R-s-env , Eval-env-v') = l-sound s Ps
in construct vpat env ,
(get-l-s↦v' >>=
Iso.to-from-inverse (rearrangement-iso vpat vpat' expr c)
(construct-deconstruct-inverse vpat _ >>= return (fromEval vpat vpat' expr v' Eval-env-v'))) ,
env , R-s-env , toMatch vpat (construct vpat env) (construct-deconstruct-inverse vpat _)
rearrS-soundness :
{V : Set} {G H : U n} (spat : Pattern F G) (tpat : Pattern F H) (expr : Expr spat tpat)
(c : CompleteExpr spat tpat expr) (l : ⟦ H ⟧ (μ F) ⇆ V) →
(R : ℙ (PatResult spat × V)) (R' : ℙ (PatResult spat × PatResult spat × V)) →
Sound ((Eval spat tpat expr ∘ swap) • R) (Lens.put l)
(λ { (t' , t , v) → ∃ λ { (r' , r) → R' (r' , r , v) × Eval spat tpat expr (r' , t') × Eval spat tpat expr (r , t) } }) →
Sound (Match spat • R) (Lens.put (rearrangement-iso spat tpat expr c ▸ l))
(λ { (s' , s , v) → ∃ λ { (r' , r) → R' (r' , r , v) × Match spat (s' , r') × Match spat (s , r) } })
rearrS-soundness spat tpat expr c l R R' l-sound (s , v) (r , Match-s-r , R-r-v) =
let t = construct tpat (eval spat tpat expr r)
(t' , l-t-v↦t' , (rr' , rr) , R'-rr'-rr-v , Eval-rr'-t' , Eval-rr-t) =
l-sound (t , v) (r , toEval spat tpat expr , R-r-v)
in construct spat rr' ,
((fromMatch spat s Match-s-r >>= return refl) >>= l-t-v↦t' >>=
Lens.GetPut (iso-lens (rearrangement-iso spat tpat expr c))
(construct-deconstruct-inverse spat rr' >>= (return (fromEval spat tpat expr t' Eval-rr'-t')))) ,
(rr' , rr) , R'-rr'-rr-v , (toMatch spat (construct spat rr') (construct-deconstruct-inverse spat rr')) ,
subst (λ r → Match spat (s , r))
(sym (eval-injective spat tpat expr c (construct-injective tpat (fromEval spat tpat expr t Eval-rr-t))))
Match-s-r
rearrS-soundnessG :
{V : Set} {G H : U n} (spat : Pattern F G) (tpat : Pattern F H) (expr : Expr spat tpat)
(c : CompleteExpr spat tpat expr) (l : ⟦ H ⟧ (μ F) ⇆ V) →
(P : ℙ (PatResult spat)) (R : ℙ (PatResult spat × V)) →
SoundG (λ s → ∃ λ env → P env × Eval spat tpat expr (env , s)) (Lens.get l) ((Eval spat tpat expr ∘ swap) • R) →
SoundG (λ s → ∃ λ env → P env × Match spat (s , env)) (Lens.get (rearrangement-iso spat tpat expr c ▸ l)) (Match spat • R)
rearrS-soundnessG spat tpat expr c l P R l-sound s (env , P-env , Match-s-env) =
let t = construct tpat (eval spat tpat expr env)
(v , get↦v , env' , Eval-env'-t , R-env'-v) =
l-sound t (env , P-env , toEval spat tpat expr)
in v , ((fromMatch spat s Match-s-env >>= return refl) >>= get↦v) , env , Match-s-env ,
subst (λ e → R (e , v))
(eval-injective spat tpat expr c (construct-injective tpat (fromEval spat tpat expr t Eval-env'-t))) R-env'-v