module A201607.Common.UntypedContext where

open import A201607.Common.Context public


-- Naturals, as a projection of contexts.

ᴺ⌊_⌋ :  {U}  Cx U  
ᴺ⌊       = zero
ᴺ⌊ Γ , A  = suc ᴺ⌊ Γ 


-- Inversion principle for naturals.

invsuc :  {n n′}  ℕ.suc n  suc n′  n  n′
invsuc refl = refl


-- Finite naturals, or nameless untyped de Bruijn indices, as a projection of context membership.

ⁱ⌊_⌋ :  {U} {A : U} {Γ}  A  Γ  Fin ᴺ⌊ Γ 
ⁱ⌊ top    = zero
ⁱ⌊ pop i  = suc ⁱ⌊ i 


-- Preorder on naturals, as a projection of context inclusion.

infix 3 _≤_
data _≤_ :     Set where
  done : zero  zero
  skip :  {n n′}  n  n′  n  suc n′
  keep :  {n n′}  n  n′  suc n  suc n′

≤⌊_⌋ :  {U} {Γ Γ′ : Cx U}  Γ  Γ′  ᴺ⌊ Γ   ᴺ⌊ Γ′ 
≤⌊ done    = done
≤⌊ skip η  = skip ≤⌊ η 
≤⌊ keep η  = keep ≤⌊ η 

refl≤ :  {n}  n  n
refl≤ {zero}  = done
refl≤ {suc n} = keep refl≤

trans≤ :  {n n′ n″}  n  n′  n′  n″  n  n″
trans≤ η        done      = η
trans≤ η        (skip η′) = skip (trans≤ η η′)
trans≤ (skip η) (keep η′) = skip (trans≤ η η′)
trans≤ (keep η) (keep η′) = keep (trans≤ η η′)

unskip≤ :  {n n′}  suc n  n′  n  n′
unskip≤ (skip η) = skip (unskip≤ η)
unskip≤ (keep η) = skip η

unkeep≤ :  {n n′}  suc n  suc n′  n  n′
unkeep≤ (skip η) = unskip≤ η
unkeep≤ (keep η) = η

weak≤ :  {n}  n  suc n
weak≤ = skip refl≤

bot≤ :  {n}  zero  n
bot≤ {zero}  = done
bot≤ {suc n} = skip bot≤


-- Monotonicity of finite naturals with respect to preorder on naturals.

monoFin :  {n n′}  n  n′  Fin n  Fin n′
monoFin done     ()
monoFin (skip η) i       = suc (monoFin η i)
monoFin (keep η) zero    = zero
monoFin (keep η) (suc i) = suc (monoFin η i)

reflmonoFin :  {n}  (i : Fin n)  i  monoFin refl≤ i
reflmonoFin zero    = refl
reflmonoFin (suc i) = cong suc (reflmonoFin i)

transmonoFin :  {n n′ n″}  (η : n  n′) (η′ : n′  n″) (i : Fin n)
                monoFin η′ (monoFin η i)  monoFin (trans≤ η η′) i
transmonoFin done     η′        ()
transmonoFin η        (skip η′) i       = cong suc (transmonoFin η η′ i)
transmonoFin (skip η) (keep η′) i       = cong suc (transmonoFin η η′ i)
transmonoFin (keep η) (keep η′) zero    = refl
transmonoFin (keep η) (keep η′) (suc i) = cong suc (transmonoFin η η′ i)


-- Addition of naturals, as a projection of context concatenation.

_+_ :     
n + zero     = n
n + (suc n′) = suc (n + n′)

id+₁ :  {n}  n + zero  n
id+₁ = refl

id+₂ :  {n}  zero + n  n
id+₂ {zero}  = refl
id+₂ {suc n} = cong suc id+₂

weak≤+₁ :  {n} n′  n  n + n′
weak≤+₁ zero     = refl≤
weak≤+₁ (suc n′) = skip (weak≤+₁ n′)

weak≤+₂ :  {n n′}  n′  n + n′
weak≤+₂ {n} {zero}   = bot≤
weak≤+₂ {n} {suc n′} = keep weak≤+₂


-- Subtraction of naturals, as a projection of context thinning.

_-_ : (n : )  Fin n  
zero  - ()
suc n - zero  = n
suc n - suc i = suc (n - i)

thin≤ :  {n}  (i : Fin n)  n - i  n
thin≤ zero    = weak≤
thin≤ (suc i) = keep (thin≤ i)


-- Decidable equality of finite naturals.

data _=Fin_ {n} (i : Fin n) : Fin n  Set where
  same : i =Fin i
  diff : (j : Fin (n - i))  i =Fin monoFin (thin≤ i) j

_≟Fin_ :  {n}  (i j : Fin n)  i =Fin j
zero  ≟Fin zero   = same
zero  ≟Fin suc j  rewrite reflmonoFin j = diff j
suc i ≟Fin zero   = diff zero
suc i ≟Fin suc j  with i ≟Fin j
suc i ≟Fin suc .i | same   = same
suc i ≟Fin suc ._ | diff j = diff (suc j)