module CoercionExpr.SimBackCastUp 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.CatchUpBack


sim-back-cast-↑ :  { ℓ′ g′}
    {c̅₁ : CExpr l   l low} {c̅₁′ : CExpr l ℓ′  g′}
    {c′ :  g′  l high}
    c̅₁  low !  c̅₁′
   CVal c̅₁
    --------------------------------------------
   ∃[ c̅₂′ ] (c̅₁′  c′ —↠ c̅₂′) × ( c̅₁    c̅₂′)
sim-back-cast-↑ {c′ = c′} c̅₁⨾!⊑c̅₁′ id
  with catchup-back _ _ (inj id) c̅₁⨾!⊑c̅₁′ | c′
... |  id (l low) , c̅₁⨾!↠c̅₂′ , v-v id x  |  =
   id (l low)   , plug-cong c̅₁⨾!↠c̅₂′ , ⊑-cast (⊑-id l⊑l) l⊑l l⊑l 
... |  id (l high) , c̅₁⨾!↠c̅₂′ , v-v id x  | c′ =
  case prec→⊑ _ _ x of λ where  () , _ 
... |  id (l low)   , c̅₁⨾!↠c̅₂′ , v-v (up id) x  | id (l high) =
   id (l low)   , ↠-trans (plug-cong c̅₁⨾!↠c̅₂′)
    (_ —→⟨ id (up id)  id (l low)   ) , ⊑-cast (⊑-id l⊑l) l⊑l l⊑l 
... |  id (l low)  low ! , c̅₁⨾!↠c̅₂′ , v-v (inj id) x  | high ?? _ =
   id (l low)   , ↠-trans (plug-cong c̅₁⨾!↠c̅₂′)
    (id (l low)  (low !)  (high ?? _) —→⟨ ?-↑ id  id (l low)   ) , ⊑-cast (⊑-id l⊑l) l⊑l l⊑l 
... |  id (l high)  high ! , c̅₁⨾!↠c̅₂′ , v-v (inj id) x  | high ?? _ =
  case prec→⊑ _ _ x of λ where  () , _ 
... |  id (l low)    high ! , c̅₁⨾!↠c̅₂′ , v-v (inj (up id)) x  | high ?? _ =
   id (l low)   , ↠-trans (plug-cong c̅₁⨾!↠c̅₂′)
    (_ —→⟨ ?-id (up id)  id (l low)   ) , ⊑-cast (⊑-id l⊑l) l⊑l l⊑l 
... |   _ _ _ , c̅₁⨾!↠⊥ , v-⊥ x  | _ =
  let  ℓ⊑ℓ′ , _  = prec→⊑ _ _ x in
    _ _ _ , ↠-trans (plug-cong c̅₁⨾!↠⊥) (_ —→⟨ ξ-⊥  _ ) , ⊑-⊥ ℓ⊑ℓ′ l⊑l