{-
This second-order term syntax was created from the following second-order syntax description:

syntax Inception | IA

type
  L : 0-ary
  P : 0-ary
  A : 0-ary

term
  rec : L  P  ->  A
  inc : L.A  P.A  ->  A

theory
  (S) p : P   a : P.A |> inc (l. rec (l, p[]), x. a[x]) = a[p[]]
  (E) a : L.A  |> k : L |- inc (l. a[l], x. rec(k, x)) = a[k]
  (W) m : A  a : P.A  |> inc (l. m[], x. a[x]) = m[]
  (A) p : (L,L).A  a : (L,P).A  b : P.A |>         inc (l. inc (k. p[l, k], x. a[l,x]), y. b[y])       = inc (k. inc(l. p[l,k], y.b[y]), x. inc(l. a[l,x], y.b[y]))
-}


module Inception.Syntax where

open import SOAS.Common
open import SOAS.Context
open import SOAS.Variable
open import SOAS.Families.Core
open import SOAS.Construction.Structure
open import SOAS.ContextMaps.Inductive

open import SOAS.Metatheory.Syntax

open import Inception.Signature

private
  variable
    Ξ“ Ξ” Ξ  : Ctx
    Ξ± : IAT
    𝔛 : Familyβ‚›

-- Inductive term declaration
module IA:Terms (𝔛 : Familyβ‚›) where

  data IA : Familyβ‚› where
    var  : ℐ β‡ΎΜ£ IA
    mvar : 𝔛 Ξ± Ξ  β†’ Sub IA Ξ  Ξ“ β†’ IA Ξ± Ξ“

    rec : IA L Ξ“ β†’ IA P Ξ“ β†’ IA A Ξ“
    inc : IA A (L βˆ™ Ξ“) β†’ IA A (P βˆ™ Ξ“) β†’ IA A Ξ“



  open import SOAS.Metatheory.MetaAlgebra β…€F 𝔛

  IAᡃ : MetaAlg IA
  IAᡃ = record
    { π‘Žπ‘™π‘” = Ξ» where
      (recβ‚’ β…‹ a , b) β†’ rec a b
      (incβ‚’ β…‹ a , b) β†’ inc a b
    ; π‘£π‘Žπ‘Ÿ = var ; π‘šπ‘£π‘Žπ‘Ÿ = Ξ» π”ͺ mΞ΅ β†’ mvar π”ͺ (tabulate mΞ΅) }

  module IAᡃ = MetaAlg IAᡃ

  module _ {π’œ : Familyβ‚›}(π’œα΅ƒ : MetaAlg π’œ) where

    open MetaAlg π’œα΅ƒ

    π•€π•–π•ž : IA β‡ΎΜ£ π’œ
    π•Š : Sub IA Ξ  Ξ“ β†’ Ξ  ~[ π’œ ]↝ Ξ“
    π•Š (t β—‚ Οƒ) new = π•€π•–π•ž t
    π•Š (t β—‚ Οƒ) (old v) = π•Š Οƒ v
    π•€π•–π•ž (mvar π”ͺ mΞ΅) = π‘šπ‘£π‘Žπ‘Ÿ π”ͺ (π•Š mΞ΅)
    π•€π•–π•ž (var v) = π‘£π‘Žπ‘Ÿ v

    π•€π•–π•ž (rec a b) = π‘Žπ‘™π‘” (recβ‚’ β…‹ π•€π•–π•ž a , π•€π•–π•ž b)
    π•€π•–π•ž (inc a b) = π‘Žπ‘™π‘” (incβ‚’ β…‹ π•€π•–π•ž a , π•€π•–π•ž b)

    π•€π•–π•žα΅ƒβ‡’ : MetaAlgβ‡’ IAᡃ π’œα΅ƒ π•€π•–π•ž
    π•€π•–π•žα΅ƒβ‡’ = record
      { βŸ¨π‘Žπ‘™π‘”βŸ© = Ξ»{ {t = t} β†’ βŸ¨π‘Žπ‘™π‘”βŸ© t }
      ; βŸ¨π‘£π‘Žπ‘ŸβŸ© = refl
      ; βŸ¨π‘šπ‘£π‘Žπ‘ŸβŸ© = Ξ»{ {π”ͺ = π”ͺ}{mΞ΅} β†’ cong (π‘šπ‘£π‘Žπ‘Ÿ π”ͺ) (dext (π•Š-tab mΞ΅)) }  }
      where
      open ≑-Reasoning
      βŸ¨π‘Žπ‘™π‘”βŸ© : (t : β…€ IA Ξ± Ξ“) β†’ π•€π•–π•ž (IAᡃ.π‘Žπ‘™π‘” t) ≑ π‘Žπ‘™π‘” (⅀₁ π•€π•–π•ž t)
      βŸ¨π‘Žπ‘™π‘”βŸ© (recβ‚’ β…‹ _) = refl
      βŸ¨π‘Žπ‘™π‘”βŸ© (incβ‚’ β…‹ _) = refl

      π•Š-tab : (mΞ΅ : Ξ  ~[ IA ]↝ Ξ“)(v : ℐ Ξ± Ξ ) β†’ π•Š (tabulate mΞ΅) v ≑ π•€π•–π•ž (mΞ΅ v)
      π•Š-tab mΞ΅ new = refl
      π•Š-tab mΞ΅ (old v) = π•Š-tab (mΞ΅ ∘ old) v

    module _ (g : IA β‡ΎΜ£ π’œ)(gᡃ⇒ : MetaAlgβ‡’ IAᡃ π’œα΅ƒ g) where

      open MetaAlgβ‡’ gᡃ⇒

      π•€π•–π•ž! : (t : IA Ξ± Ξ“) β†’ π•€π•–π•ž t ≑ g t
      π•Š-ix : (mΞ΅ : Sub IA Ξ  Ξ“)(v : ℐ Ξ± Ξ ) β†’ π•Š mΞ΅ v ≑ g (index mΞ΅ v)
      π•Š-ix (x β—‚ mΞ΅) new = π•€π•–π•ž! x
      π•Š-ix (x β—‚ mΞ΅) (old v) = π•Š-ix mΞ΅ v
      π•€π•–π•ž! (mvar π”ͺ mΞ΅) rewrite cong (π‘šπ‘£π‘Žπ‘Ÿ π”ͺ) (dext (π•Š-ix mΞ΅))
        = trans (sym βŸ¨π‘šπ‘£π‘Žπ‘ŸβŸ©) (cong (g ∘ mvar π”ͺ) (tab∘ixβ‰ˆid mΞ΅))
      π•€π•–π•ž! (var v) = sym βŸ¨π‘£π‘Žπ‘ŸβŸ©

      π•€π•–π•ž! (rec a b) rewrite π•€π•–π•ž! a | π•€π•–π•ž! b = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! (inc a b) rewrite π•€π•–π•ž! a | π•€π•–π•ž! b = sym βŸ¨π‘Žπ‘™π‘”βŸ©


-- Syntax instance for the signature
IA:Syn : Syntax
IA:Syn = record
  { β…€F = β…€F
  ; β…€:CS = β…€:CompatStr
  ; mvarα΅’ = IA:Terms.mvar
  ; 𝕋:Init = Ξ» 𝔛 β†’ let open IA:Terms 𝔛 in record
    { βŠ₯ = IA ⋉ IAᡃ
    ; βŠ₯-is-initial = record { ! = Ξ»{ {π’œ ⋉ π’œα΅ƒ} β†’ π•€π•–π•ž π’œα΅ƒ ⋉ π•€π•–π•žα΅ƒβ‡’ π’œα΅ƒ }
    ; !-unique = Ξ»{ {π’œ ⋉ π’œα΅ƒ} (f ⋉ fᡃ⇒) {x = t} β†’ π•€π•–π•ž! π’œα΅ƒ f fᡃ⇒ t } } } }

-- Instantiation of the syntax and metatheory
open Syntax IA:Syn public
open IA:Terms public
open import SOAS.Families.Build public
open import SOAS.Syntax.Shorthands IAᡃ public
open import SOAS.Metatheory IA:Syn public