{- Syntactical composition of coercion expressions -}

module CoercionExpr.SyntacComp 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.Nullary.Negation using (contradiction)
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


_⨟_ : βˆ€ {g₁ gβ‚‚ g₃} (c̅₁ : CExpr g₁ β‡’ gβ‚‚) (cΜ…β‚‚ : CExpr gβ‚‚ β‡’ g₃) β†’ CExpr g₁ β‡’ g₃
c̅₁ ⨟ βŠ₯ gβ‚‚ g₃ p = βŠ₯ _ g₃ p
c̅₁ ⨟ id g      = c̅₁ β¨Ύ id g
c̅₁ ⨟ (cΜ…β‚‚ β¨Ύ c)  = (c̅₁ ⨟ cΜ…β‚‚) β¨Ύ c


comp-pres-βŠ‘ : βˆ€ {g₁ g₁′ gβ‚‚ gβ‚‚β€² g₃ g₃′}
     {c̅₁ : CExpr g₁ β‡’ gβ‚‚}    {cΜ…β‚‚ : CExpr gβ‚‚ β‡’ g₃}
     {c̅₁′ : CExpr g₁′ β‡’ gβ‚‚β€²} {cΜ…β‚‚β€² : CExpr gβ‚‚β€² β‡’ g₃′}
  β†’ ⊒ c̅₁ βŠ‘ c̅₁′
  β†’ ⊒ cΜ…β‚‚ βŠ‘ cΜ…β‚‚β€²
    -----------------------------
  β†’ ⊒ c̅₁ ⨟ cΜ…β‚‚ βŠ‘ c̅₁′ ⨟ cΜ…β‚‚β€²
comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ (βŠ‘-βŠ₯ x gβ‚ƒβŠ‘g₃′) =
  let ⟨ gβ‚βŠ‘g₁′ , _ ⟩ = precβ†’βŠ‘ _ _ cΜ…β‚βŠ‘c̅₁′ in
  βŠ‘-βŠ₯ gβ‚βŠ‘g₁′ gβ‚ƒβŠ‘g₃′
comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-cast cΜ…β‚βŠ‘c̅₁′ gβŠ‘gβ€² gβŠ‘gβ€²
comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ (βŠ‘-cast cΜ…β‚‚βŠ‘cΜ…β‚‚β€² gβŠ‘g₃ gβ€²βŠ‘g₃′) =
  βŠ‘-cast (comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ cΜ…β‚‚βŠ‘cΜ…β‚‚β€²) gβŠ‘g₃ gβ€²βŠ‘g₃′
comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ (βŠ‘-castl cΜ…β‚‚βŠ‘cΜ…β‚‚β€² gβŠ‘g₃′ gβ‚ƒβŠ‘g₃′) =
  βŠ‘-castl (comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ cΜ…β‚‚βŠ‘cΜ…β‚‚β€²) gβŠ‘g₃′ gβ‚ƒβŠ‘g₃′
comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ (βŠ‘-castr cΜ…β‚‚βŠ‘cΜ…β‚‚β€² gβ‚ƒβŠ‘gβ€² gβ‚ƒβŠ‘g₃′) =
  βŠ‘-castr (comp-pres-βŠ‘ cΜ…β‚βŠ‘c̅₁′ cΜ…β‚‚βŠ‘cΜ…β‚‚β€²) gβ‚ƒβŠ‘gβ€² gβ‚ƒβŠ‘g₃′


comp-pres-βŠ‘-ll : βˆ€ {g₁ gβ‚‚ g₃ gβ€²}
     {c̅₁ : CExpr g₁ β‡’ gβ‚‚}    {cΜ…β‚‚ : CExpr gβ‚‚ β‡’ g₃}
  β†’ ⊒l c̅₁ βŠ‘ gβ€²
  β†’ ⊒l cΜ…β‚‚ βŠ‘ gβ€²
    -----------------------------
  β†’ ⊒l c̅₁ ⨟ cΜ…β‚‚ βŠ‘ gβ€²
comp-pres-βŠ‘-ll cΜ…β‚βŠ‘c̅₁′ (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-cast cΜ…β‚βŠ‘c̅₁′ gβŠ‘gβ€² gβŠ‘gβ€²
comp-pres-βŠ‘-ll cΜ…β‚βŠ‘c̅₁′ (βŠ‘-cast cΜ…β‚‚βŠ‘cΜ…β‚‚β€² gβŠ‘g₃′ gβ‚ƒβŠ‘g₃′) =
  βŠ‘-cast (comp-pres-βŠ‘-ll cΜ…β‚βŠ‘c̅₁′ cΜ…β‚‚βŠ‘cΜ…β‚‚β€²) gβŠ‘g₃′ gβ‚ƒβŠ‘g₃′

comp-pres-βŠ‘-rr : βˆ€ {g g₁′ gβ‚‚β€² g₃′}
     {c̅₁′ : CExpr g₁′ β‡’ gβ‚‚β€²} {cΜ…β‚‚β€² : CExpr gβ‚‚β€² β‡’ g₃′}
  β†’ ⊒r g βŠ‘ c̅₁′
  β†’ ⊒r g βŠ‘ cΜ…β‚‚β€²
    -----------------------------
  β†’ ⊒r g βŠ‘ c̅₁′ ⨟ cΜ…β‚‚β€²
comp-pres-βŠ‘-rr gβŠ‘c̅₁′ (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-cast gβŠ‘c̅₁′ gβŠ‘gβ€² gβŠ‘gβ€²
comp-pres-βŠ‘-rr gβŠ‘c̅₁′ (βŠ‘-cast gβŠ‘cΜ…β€² x y) = βŠ‘-cast (comp-pres-βŠ‘-rr gβŠ‘c̅₁′ gβŠ‘cΜ…β€²) x y
comp-pres-βŠ‘-rr gβŠ‘c̅₁′ (βŠ‘-βŠ₯ _ x) = βŠ‘-βŠ₯ (proj₁ (prec-rightβ†’βŠ‘ _ gβŠ‘c̅₁′)) x

comp-pres-βŠ‘-lr : βˆ€ {g₁ g₁′ gβ‚‚ gβ‚‚β€²}
     {cΜ… : CExpr g₁ β‡’ gβ‚‚}    {cΜ…β€² : CExpr g₁′ β‡’ gβ‚‚β€²}
  β†’ ⊒l cΜ… βŠ‘ g₁′
  β†’ ⊒r gβ‚‚ βŠ‘ cΜ…β€²
    -----------------------------
  β†’ ⊒ cΜ… βŠ‘ cΜ…β€²
comp-pres-βŠ‘-lr cΜ…βŠ‘g₁′ (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-left-expand cΜ…βŠ‘g₁′
comp-pres-βŠ‘-lr cΜ…βŠ‘g₁′ (βŠ‘-cast gβ‚‚βŠ‘cΜ…β€² x y) = βŠ‘-castr (comp-pres-βŠ‘-lr cΜ…βŠ‘g₁′ gβ‚‚βŠ‘cΜ…β€²) x y
comp-pres-βŠ‘-lr cΜ…βŠ‘g₁′ (βŠ‘-βŠ₯ x y) = βŠ‘-βŠ₯ (proj₁ (prec-leftβ†’βŠ‘ _ cΜ…βŠ‘g₁′)) y

comp-pres-βŠ‘-rl : βˆ€ {g₁ g₁′ gβ‚‚ gβ‚‚β€²}
     {cΜ… : CExpr g₁ β‡’ gβ‚‚}    {cΜ…β€² : CExpr g₁′ β‡’ gβ‚‚β€²}
  β†’ ⊒r g₁ βŠ‘ cΜ…β€²
  β†’ ⊒l cΜ… βŠ‘ gβ‚‚β€²
    -----------------------------
  β†’ ⊒ cΜ… βŠ‘ cΜ…β€²
comp-pres-βŠ‘-rl gβ‚βŠ‘cΜ…β€² (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-right-expand gβ‚βŠ‘cΜ…β€²
comp-pres-βŠ‘-rl gβ‚βŠ‘cΜ…β€² (βŠ‘-cast cΜ…βŠ‘gβ‚‚β€² gβ‚βŠ‘gβ‚‚β€² gβ‚‚βŠ‘gβ‚‚β€²) = βŠ‘-castl (comp-pres-βŠ‘-rl gβ‚βŠ‘cΜ…β€² cΜ…βŠ‘gβ‚‚β€²) gβ‚βŠ‘gβ‚‚β€² gβ‚‚βŠ‘gβ‚‚β€²

comp-pres-βŠ‘-lb : βˆ€ {g₁ g₁′ gβ‚‚ gβ‚‚β€² g₃}
     {c̅₁ : CExpr g₁ β‡’ gβ‚‚}    {cΜ…β‚‚ : CExpr gβ‚‚ β‡’ g₃}
     {cΜ…β€² : CExpr g₁′ β‡’ gβ‚‚β€²}
  β†’ ⊒l c̅₁ βŠ‘ g₁′
  β†’ ⊒  cΜ…β‚‚ βŠ‘ cΜ…β€²
    -----------------------------
  β†’ ⊒ c̅₁ ⨟ cΜ…β‚‚ βŠ‘ cΜ…β€²
comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-castl (βŠ‘-left-expand cΜ…β‚βŠ‘g₁) gβŠ‘gβ€² gβŠ‘gβ€²
comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ (βŠ‘-cast cΜ…βŠ‘cΜ…β€² gβ‚βŠ‘g₁′ gβ‚‚βŠ‘gβ‚‚β€²) = βŠ‘-cast (comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ cΜ…βŠ‘cΜ…β€²) gβ‚βŠ‘g₁′ gβ‚‚βŠ‘gβ‚‚β€²
comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ (βŠ‘-castl cΜ…βŠ‘cΜ…β€² gβ‚βŠ‘gβ€² gβ‚‚βŠ‘gβ€²) = βŠ‘-castl (comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ cΜ…βŠ‘cΜ…β€²) gβ‚βŠ‘gβ€² gβ‚‚βŠ‘gβ€²
comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ (βŠ‘-castr cΜ…βŠ‘cΜ…β€² gβŠ‘g₁′ gβŠ‘gβ‚‚β€²) = βŠ‘-castr (comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ cΜ…βŠ‘cΜ…β€²) gβŠ‘g₁′ gβŠ‘gβ‚‚β€²
comp-pres-βŠ‘-lb cΜ…β‚βŠ‘g₁ (βŠ‘-βŠ₯ gβ‚βŠ‘g₁′ gβ‚‚βŠ‘gβ‚‚β€²) = βŠ‘-βŠ₯ (proj₁ (prec-leftβ†’βŠ‘ _ cΜ…β‚βŠ‘g₁)) gβ‚‚βŠ‘gβ‚‚β€²

comp-pres-βŠ‘-rb : βˆ€ {g₁ g₁′ gβ‚‚ gβ‚‚β€² g₃′}
     {cΜ…   : CExpr g₁  β‡’ gβ‚‚}
     {c̅₁′ : CExpr g₁′ β‡’ gβ‚‚β€²}    {cΜ…β‚‚β€² : CExpr gβ‚‚β€² β‡’ g₃′}
  β†’ ⊒r g₁ βŠ‘ c̅₁′
  β†’ ⊒  cΜ…  βŠ‘ cΜ…β‚‚β€²
    -----------------------------
  β†’ ⊒ cΜ… βŠ‘ c̅₁′ ⨟ cΜ…β‚‚β€²
comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-castr (βŠ‘-right-expand gβ‚βŠ‘c̅₁′) gβŠ‘gβ€² gβŠ‘gβ€²
comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ (βŠ‘-cast cΜ…βŠ‘cΜ…β‚‚β€² x y) = βŠ‘-cast (comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ cΜ…βŠ‘cΜ…β‚‚β€²) x y
comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ (βŠ‘-castl cΜ…βŠ‘cΜ…β‚‚β€² x y) = βŠ‘-castl (comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ cΜ…βŠ‘cΜ…β‚‚β€²) x y
comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ (βŠ‘-castr cΜ…βŠ‘cΜ…β‚‚β€² x y) = βŠ‘-castr (comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ cΜ…βŠ‘cΜ…β‚‚β€²) x y
comp-pres-βŠ‘-rb gβ‚βŠ‘c̅₁′ (βŠ‘-βŠ₯ x y) = βŠ‘-βŠ₯ (proj₁ (prec-rightβ†’βŠ‘ _ gβ‚βŠ‘c̅₁′)) y

comp-pres-βŠ‘-bl : βˆ€ {g₁ g₁′ gβ‚‚ gβ‚‚β€² g₃}
     {c̅₁ : CExpr g₁ β‡’ gβ‚‚}    {cΜ…β‚‚ : CExpr gβ‚‚ β‡’ g₃}
     {cΜ…β€² : CExpr g₁′ β‡’ gβ‚‚β€²}
  β†’ ⊒  c̅₁ βŠ‘ cΜ…β€²
  β†’ ⊒l cΜ…β‚‚ βŠ‘ gβ‚‚β€²
    -----------------------------
  β†’ ⊒ c̅₁ ⨟ cΜ…β‚‚ βŠ‘ cΜ…β€²
comp-pres-βŠ‘-bl cΜ…β‚βŠ‘cΜ…β€² (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-castl cΜ…β‚βŠ‘cΜ…β€² gβŠ‘gβ€² gβŠ‘gβ€²
comp-pres-βŠ‘-bl cΜ…β‚βŠ‘cΜ…β€² (βŠ‘-cast cΜ…β‚‚βŠ‘gβ‚‚β€² gβ‚βŠ‘gβ‚‚β€² gβ‚‚βŠ‘gβ‚‚β€²) =
  βŠ‘-castl (comp-pres-βŠ‘-bl cΜ…β‚βŠ‘cΜ…β€² cΜ…β‚‚βŠ‘gβ‚‚β€²) gβ‚βŠ‘gβ‚‚β€² gβ‚‚βŠ‘gβ‚‚β€²

comp-pres-βŠ‘-br : βˆ€ {g₁ g₁′ gβ‚‚ gβ‚‚β€² g₃′}
     {cΜ… : CExpr g₁ β‡’ gβ‚‚}
     {c̅₁′ : CExpr g₁′ β‡’ gβ‚‚β€²} {cΜ…β‚‚β€² : CExpr gβ‚‚β€² β‡’ g₃′}
  β†’ ⊒  cΜ…  βŠ‘ c̅₁′
  β†’ ⊒r gβ‚‚ βŠ‘ cΜ…β‚‚β€²
    -----------------------------
  β†’ ⊒ cΜ… βŠ‘ c̅₁′ ⨟ cΜ…β‚‚β€²
comp-pres-βŠ‘-br cΜ…βŠ‘c̅₁′ (βŠ‘-id gβŠ‘gβ€²) = βŠ‘-castr cΜ…βŠ‘c̅₁′ gβŠ‘gβ€² gβŠ‘gβ€²
comp-pres-βŠ‘-br cΜ…βŠ‘c̅₁′ (βŠ‘-cast x y z) = βŠ‘-castr (comp-pres-βŠ‘-br cΜ…βŠ‘c̅₁′ x) y z
comp-pres-βŠ‘-br cΜ…βŠ‘c̅₁′ (βŠ‘-βŠ₯ _ x) = βŠ‘-βŠ₯ (proj₁ (precβ†’βŠ‘ _ _ cΜ…βŠ‘c̅₁′)) x

{- syntactical composition won't get a value -}
comp-not-val : βˆ€ {β„“ g₁ gβ‚‚}
  β†’ (cΜ… : CExpr l β„“ β‡’ g₁)
  β†’ (dΜ… : CExpr g₁ β‡’ gβ‚‚)
  β†’ Β¬ (CVal (cΜ… ⨟ dΜ…))
comp-not-val c (id _) = Ξ» ()
comp-not-val c (d β¨Ύ _ !) (inj v) = contradiction v (comp-not-val c d)
comp-not-val c (d β¨Ύ ↑)  (up v)  = contradiction v (comp-not-val c d)
comp-not-val c (βŠ₯ _ _ p) = Ξ» ()

{- (as a result, ) reducing the syntactical comp of two exprs to a value
   takes one or more steps -}
comp-→⁺ : βˆ€ {β„“ g₁ gβ‚‚} {c̅₁ : CExpr l β„“ β‡’ g₁} {cΜ…β‚‚ : CExpr g₁ β‡’ gβ‚‚} {dΜ…}
  β†’ (c̅₁ ⨟ cΜ…β‚‚) β€”β†   dΜ…
  β†’ CVal dΜ…
  β†’ (c̅₁ ⨟ cΜ…β‚‚) —→⁺ dΜ…
comp-→⁺ {cΜ…β‚‚ = cΜ… β¨Ύ _ !} (_ ∎) (inj 𝓋) = contradiction 𝓋 (comp-not-val _ cΜ…)
comp-→⁺ {cΜ…β‚‚ = cΜ… β¨Ύ ↑}  (_ ∎) (up 𝓋)  = contradiction 𝓋 (comp-not-val _ cΜ…)
comp-→⁺ (_ β€”β†’βŸ¨ x ⟩ r) _ = _ β€”β†’βŸ¨ x ⟩ r