{-# OPTIONS --safe --sized-types #-}

open import Relation.Binary using (Decidable)
open import Relation.Binary.PropositionalEquality

open import Generic.Syntax

module Generic.Scopecheck {E I : Set} (_≟I_ : Decidable {A = I} _≡_) where

open import Category.Monad

open import Level
open import Size
open import Data.List.Base using (List; []; _∷_)
open import Data.List.Relation.Unary.All using (All; []; _∷_)
open import Data.List.Relation.Unary.All.Properties
  using () renaming (++⁺ to _++_)

open import Data.Product
open import Data.String using (String; _≟_)
open import Data.Sum
import Data.Sum.Categorical.Left as SC
open import Function
open import Relation.Nullary

open import Data.Var hiding (_<$>_)

private
  variable
    σ : I
    Γ Δ : List I
    i : Size
    A : Set


Names : List I  Set
Names = All (const String)

WithNames : (I  Set)  List I  I ─Scoped
WithNames T []  j Γ = T j
WithNames T Δ   j Γ = Names Δ × T j

data Raw (d : Desc I) : Size  I  Set where
  `var  : E  String  Raw d ( i) σ
  `con  :  d  (WithNames (Raw d i)) σ []  Raw d ( i) σ



data Error : Set where
  OutOfScope  : Error
  WrongSort   : (σ τ : I)  σ  τ  Error


private

 Fail : Set  Set
 Fail A = (Error × E × String)  A

 fail : Error  E  String  Fail A
 fail err e str = inj₁ (err , e , str)

open RawMonad (SC.monad (Error × E × String) zero)

instance _ =  rawIApplicative


toVar : E  String   σ Γ  Names Γ  Fail (Var σ Γ)
toVar e x σ [] [] = fail OutOfScope e x
toVar e x σ (τ  Γ) (y  scp) with x  y | σ ≟I τ
... | yes _  | yes refl  = pure z
... | yes _  | no ¬eq    = fail (WrongSort σ τ ¬eq) e x
... | no ¬p  | _         = s <$> toVar e x σ Γ scp

module _ {d : Desc I} where

 toTm     : Names Γ  Raw d i σ  Fail (Tm d i σ Γ)

 toScope  : Names Γ   Δ σ  WithNames (Raw d i) Δ σ [] 
            Fail (Scope (Tm d i) Δ σ Γ)

 toTm scp (`var e v)  = `var <$> toVar e v _ _ scp
 toTm scp (`con b)    = `con <$> mapA d (toScope scp) b

 toScope scp []         σ b          = toTm scp b
 toScope scp Δ@(_  _)  σ (bnd , b)  = toTm (bnd ++ scp) b