module CC.CanonicalErased 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
open import Data.Product using (_×_; ∃-syntax; proj₁; proj₂) renaming (_,_ to ⟨_,_⟩)
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; sym; trans; subst; subst₂)
open import Function using (case_of_)

open import Common.Utils
open import Common.Types
open import Memory.Heap
open import CC.CCStatics
open import CC.WellTyped
open import CC.Erasure


data ErasedFun : Term  Set where

  ϵ-fun-● : ErasedFun 

  ϵ-fun-ƛ :  {pc A N}  ErasedFun (ƛ⟦ pc  A ˙ N of low)

canonical-fun-erase :  {Σ gc gc′ pc A B g V}
   [] ; Σ ; gc ; pc  V   gc′  A  B of g
   Value V
   ∃[ V′ ] V′  erase V × ErasedFun V′
canonical-fun-erase {gc = gc} {pc = pc} ⊢V v =
  case canonical-fun ⊢V v of λ where
  (Fun-ƛ { = low}  _ _)   _ , refl , ϵ-fun-ƛ 
  (Fun-ƛ { = high} _ _)   _ , refl , ϵ-fun-● 
  (Fun-proxy fun i sub) 
    case v of λ where
    (V-cast w _) 
      canonical-fun-erase {gc = gc} {pc = pc} (fun-wt fun) w

data ErasedRef : Term  Set where

  ϵ-ref-● : ErasedRef 

  ϵ-ref-addr :  {n}  ErasedRef (addr a⟦ low  n of low)

canonical-ref-erase :  {Σ gc pc A g V}
   [] ; Σ ; gc ; pc  V  Ref A of g
   Value V
   ∃[ V′ ] V′  erase V × ErasedRef V′
canonical-ref-erase {gc = gc} {pc} ⊢V v =
  case canonical-ref ⊢V v of λ where
  (Ref-addr { = low}  {low}  _ _)   _ , refl , ϵ-ref-addr 
  (Ref-addr { = low}  {high} _ _)   _ , refl , ϵ-ref-● 
  (Ref-addr { = high} {low}  _ _)   _ , refl , ϵ-ref-● 
  (Ref-addr { = high} {high} _ _)   _ , refl , ϵ-ref-● 
  (Ref-proxy ref i sub) 
    case v of λ where
    (V-cast w _) 
      canonical-ref-erase {gc = gc} {pc} (ref-wt ref) w