module CoercionExpr.GG where

open import Data.Nat
open import Data.Unit using (āŠ¤; tt)
open import Data.Bool using (true; false) renaming (Bool to š”¹)
open import Data.List hiding ([_])
open import Data.Product renaming (_,_ to āŸØ_,_āŸ©)
open import Data.Sum using (_āŠŽ_)
open import Data.Maybe
open import Relation.Nullary using (Ā¬_; Dec; yes; no)
open import Relation.Binary.PropositionalEquality using (_ā‰”_; refl)
open import Function using (case_of_)

open import Common.Utils
open import Common.SecurityLabels
open import Common.BlameLabels
open import CoercionExpr.CoercionExpr
open import CoercionExpr.Precision

open import CoercionExpr.CatchUp     using (catchup) public
open import CoercionExpr.Simulation  using (sim) public
open import CoercionExpr.CatchUpBack using (InSync; v-v; v-āŠ„; catchup-back) public
open import CoercionExpr.SimBack     using (sim-back) public
open import CoercionExpr.SimBackBlame


sim-mult : āˆ€ {gā‚ gā‚ā€² gā‚‚ gā‚‚ā€²} {cĢ…ā‚ : CExpr gā‚ ā‡’ gā‚‚} {cĢ…ā‚ā€² cĢ…ā‚‚ā€² : CExpr gā‚ā€² ā‡’ gā‚‚ā€²}
  ā†’ āŠ¢ cĢ…ā‚ āŠ‘ cĢ…ā‚ā€²
  ā†’ CVal cĢ…ā‚‚ā€²
  ā†’ cĢ…ā‚ā€² ā€”ā†  cĢ…ā‚‚ā€²
    ---------------------------------------------------
  ā†’ āˆƒ[ cĢ…ā‚‚ ] (CVal cĢ…ā‚‚) Ɨ (cĢ…ā‚ ā€”ā†  cĢ…ā‚‚) Ɨ (āŠ¢ cĢ…ā‚‚ āŠ‘ cĢ…ā‚‚ā€²)
sim-mult cĢ…ā‚āŠ‘cĢ…ā‚ā€² š“‹ā€² (_ āˆŽ) = catchup _ _ š“‹ā€² cĢ…ā‚āŠ‘cĢ…ā‚ā€²
sim-mult {cĢ…ā‚ = cĢ…ā‚} cĢ…ā‚āŠ‘cĢ…ā‚ā€² š“‹ā€² (_ ā€”ā†’āŸØ cĢ…ā‚ā€²ā†’cĢ…ā€² āŸ© cĢ…ā€²ā† cĢ…ā‚‚ā€²) =
  let āŸØ cĢ…ā‚‚ ,     cĢ…ā‚ā† cĢ…ā‚‚ , cĢ…ā‚‚āŠ‘cĢ…ā€² āŸ©  = sim cĢ…ā‚āŠ‘cĢ…ā‚ā€² cĢ…ā‚ā€²ā†’cĢ…ā€² in
  let āŸØ cĢ…ā‚ƒ , š“‹ , cĢ…ā‚‚ā† cĢ…ā‚ƒ , cĢ…ā‚ƒāŠ‘cĢ…ā‚‚ā€² āŸ© = sim-mult cĢ…ā‚‚āŠ‘cĢ…ā€² š“‹ā€² cĢ…ā€²ā† cĢ…ā‚‚ā€² in
  āŸØ cĢ…ā‚ƒ , š“‹ , ā† -trans cĢ…ā‚ā† cĢ…ā‚‚ cĢ…ā‚‚ā† cĢ…ā‚ƒ , cĢ…ā‚ƒāŠ‘cĢ…ā‚‚ā€² āŸ©


sim-back-success : āˆ€ {ā„“ ā„“ā€² g gā€²} {cĢ…ā‚ cĢ…ā‚‚ : CExpr l ā„“ ā‡’ g} {cĢ…ā‚ā€² : CExpr l ā„“ā€² ā‡’ gā€²}
  ā†’ āŠ¢ cĢ…ā‚ āŠ‘ cĢ…ā‚ā€²
  ā†’ CVal cĢ…ā‚‚
  ā†’ cĢ…ā‚ ā€”ā†  cĢ…ā‚‚
    ---------------------------------------------------
  ā†’ āˆƒ[ cĢ…ā‚‚ā€² ] (cĢ…ā‚ā€² ā€”ā†  cĢ…ā‚‚ā€²) Ɨ (InSync cĢ…ā‚‚ cĢ…ā‚‚ā€²)
sim-back-success cĢ…ā‚āŠ‘cĢ…ā‚ā€² š“‹ (_ āˆŽ) = catchup-back _ _ š“‹ cĢ…ā‚āŠ‘cĢ…ā‚ā€²
sim-back-success {cĢ…ā‚ = cĢ…ā‚} cĢ…ā‚āŠ‘cĢ…ā‚ā€² š“‹ (_ ā€”ā†’āŸØ cĢ…ā‚ā†’cĢ… āŸ© cĢ…ā† cĢ…ā‚‚) =
  let āŸØ cĢ…ā‚‚ā€² , cĢ…ā‚ā€²ā† cĢ…ā‚‚ā€² , prec āŸ© = sim-back cĢ…ā‚āŠ‘cĢ…ā‚ā€² cĢ…ā‚ā†’cĢ… in
  let āŸØ cĢ…ā‚ƒā€² , cĢ…ā‚‚ā€²ā† cĢ…ā‚ƒā€² , sync āŸ© = sim-back-success prec š“‹ cĢ…ā† cĢ…ā‚‚ in
  āŸØ cĢ…ā‚ƒā€² , ā† -trans cĢ…ā‚ā€²ā† cĢ…ā‚‚ā€² cĢ…ā‚‚ā€²ā† cĢ…ā‚ƒā€² , sync āŸ©

sim-back-fail : āˆ€ {ā„“ ā„“ā€² g gā€²} {cĢ… : CExpr l ā„“ ā‡’ g} {cĢ…ā€² : CExpr l ā„“ā€² ā‡’ gā€²} {p}
  ā†’ āŠ¢ cĢ… āŠ‘ cĢ…ā€²
  ā†’ cĢ… ā€”ā†  āŠ„ (l ā„“) g p
    ---------------------------------------------------
  ā†’ āˆƒ[ q ] (cĢ…ā€² ā€”ā†  āŠ„ (l ā„“ā€²) gā€² q) Ɨ (āŠ¢ āŠ„ (l ā„“) g p āŠ‘ āŠ„ (l ā„“ā€²) gā€² q)
sim-back-fail cĢ…āŠ‘cĢ…ā€² (_ āˆŽ) = sim-back-blame cĢ…āŠ‘cĢ…ā€²
sim-back-fail {cĢ… = cĢ…ā‚} cĢ…ā‚āŠ‘cĢ…ā‚ā€² (_ ā€”ā†’āŸØ cĢ…ā‚ā†’cĢ… āŸ© cĢ…ā† cĢ…ā‚‚) =
  let āŸØ cĢ…ā‚‚ā€² , cĢ…ā‚ā€²ā† cĢ…ā‚‚ā€² , prec āŸ© = sim-back cĢ…ā‚āŠ‘cĢ…ā‚ā€² cĢ…ā‚ā†’cĢ… in
  let āŸØ cĢ…ā‚ƒā€² , cĢ…ā‚‚ā€²ā† cĢ…ā‚ƒā€² , sync āŸ© = sim-back-fail prec cĢ…ā† cĢ…ā‚‚ in
  āŸØ cĢ…ā‚ƒā€² , ā† -trans cĢ…ā‚ā€²ā† cĢ…ā‚‚ā€² cĢ…ā‚‚ā€²ā† cĢ…ā‚ƒā€² , sync āŸ©