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

syntax Combinatory | CL

type
  * : 0-ary

term
  app : *  *  ->  * | _$_ l20
  i   : *
  k   : *
  s   : *

theory
  (IA) x     |> app (i, x) = x
  (KA) x y   |> app (app(k, x), y) = x
  (SA) x y z |> app (app (app (s, x), y), z) = app (app(x, z), app(y, z))
-}


module Combinatory.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 Combinatory.Signature

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

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

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

    _$_ : CL * Ξ“ β†’ CL * Ξ“ β†’ CL * Ξ“
    I   : CL * Ξ“
    K   : CL * Ξ“
    S   : CL * Ξ“

  infixl 20 _$_

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

  CLᡃ : MetaAlg CL
  CLᡃ = record
    { π‘Žπ‘™π‘” = Ξ» where
      (appβ‚’ β…‹ a , b) β†’ _$_ a b
      (iβ‚’   β…‹ _)     β†’ I
      (kβ‚’   β…‹ _)     β†’ K
      (sβ‚’   β…‹ _)     β†’ S
    ; π‘£π‘Žπ‘Ÿ = var ; π‘šπ‘£π‘Žπ‘Ÿ = Ξ» π”ͺ mΞ΅ β†’ mvar π”ͺ (tabulate mΞ΅) }

  module CLᡃ = MetaAlg CLᡃ

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

    open MetaAlg π’œα΅ƒ

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

    π•€π•–π•ž (_$_ a b) = π‘Žπ‘™π‘” (appβ‚’ β…‹ π•€π•–π•ž a , π•€π•–π•ž b)
    π•€π•–π•ž  I        = π‘Žπ‘™π‘” (iβ‚’   β…‹ tt)
    π•€π•–π•ž  K        = π‘Žπ‘™π‘” (kβ‚’   β…‹ tt)
    π•€π•–π•ž  S        = π‘Žπ‘™π‘” (sβ‚’   β…‹ tt)

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

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

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

      open MetaAlgβ‡’ gᡃ⇒

      π•€π•–π•ž! : (t : CL Ξ± Ξ“) β†’ π•€π•–π•ž t ≑ g t
      π•Š-ix : (mΞ΅ : Sub CL Ξ  Ξ“)(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 βŸ¨π‘£π‘Žπ‘ŸβŸ©

      π•€π•–π•ž! (_$_ a b) rewrite π•€π•–π•ž! a | π•€π•–π•ž! b = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! I = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! K = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! S = sym βŸ¨π‘Žπ‘™π‘”βŸ©


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

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