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

syntax Ring | R

type
  * : 0-ary

term
  zero : * | 𝟘
  add  : *  *  ->  * | _βŠ•_ l20
  one  : * | πŸ™
  mult : *  *  ->  * | _βŠ—_ l30
  neg  : *  ->  * | βŠ–_ r50

theory
  (𝟘UβŠ•α΄Έ) a |> add (zero, a) = a
  (𝟘UβŠ•α΄Ώ) a |> add (a, zero) = a
  (βŠ•A) a b c |> add (add(a, b), c) = add (a, add(b, c))
  (βŠ•C) a b |> add(a, b) = add(b, a)
  (πŸ™UβŠ—α΄Έ) a |> mult (one, a) = a
  (πŸ™UβŠ—α΄Ώ) a |> mult (a, one) = a
  (βŠ—A) a b c |> mult (mult(a, b), c) = mult (a, mult(b, c))
  (βŠ—DβŠ•α΄Έ) a b c |> mult (a, add (b, c)) = add (mult(a, b), mult(a, c))
  (βŠ—DβŠ•α΄Ώ) a b c |> mult (add (a, b), c) = add (mult(a, c), mult(b, c))
  (𝟘XβŠ—α΄Έ) a |> mult (zero, a) = zero
  (𝟘XβŠ—α΄Ώ) a |> mult (a, zero) = zero
  (βŠ–NβŠ•α΄Έ) a |> add (neg (a), a) = zero
  (βŠ–NβŠ•α΄Ώ) a |> add (a, neg (a)) = zero
-}


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

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

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

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

    𝟘   : R * Ξ“
    _βŠ•_ : R * Ξ“ β†’ R * Ξ“ β†’ R * Ξ“
    πŸ™   : R * Ξ“
    _βŠ—_ : R * Ξ“ β†’ R * Ξ“ β†’ R * Ξ“
    βŠ–_  : R * Ξ“ β†’ R * Ξ“

  infixl 20 _βŠ•_
  infixl 30 _βŠ—_
  infixr 50 βŠ–_

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

  Rᡃ : MetaAlg R
  Rᡃ = record
    { π‘Žπ‘™π‘” = Ξ» where
      (zeroβ‚’ β…‹ _)     β†’ 𝟘
      (addβ‚’  β…‹ a , b) β†’ _βŠ•_ a b
      (oneβ‚’  β…‹ _)     β†’ πŸ™
      (multβ‚’ β…‹ a , b) β†’ _βŠ—_ a b
      (negβ‚’  β…‹ a)     β†’ βŠ–_  a
    ; π‘£π‘Žπ‘Ÿ = var ; π‘šπ‘£π‘Žπ‘Ÿ = Ξ» π”ͺ mΞ΅ β†’ mvar π”ͺ (tabulate mΞ΅) }

  module Rᡃ = MetaAlg Rᡃ

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

    open MetaAlg π’œα΅ƒ

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

    π•€π•–π•ž  𝟘        = π‘Žπ‘™π‘” (zeroβ‚’ β…‹ tt)
    π•€π•–π•ž (_βŠ•_ a b) = π‘Žπ‘™π‘” (addβ‚’  β…‹ π•€π•–π•ž a , π•€π•–π•ž b)
    π•€π•–π•ž  πŸ™        = π‘Žπ‘™π‘” (oneβ‚’  β…‹ tt)
    π•€π•–π•ž (_βŠ—_ a b) = π‘Žπ‘™π‘” (multβ‚’ β…‹ π•€π•–π•ž a , π•€π•–π•ž b)
    π•€π•–π•ž (βŠ–_  a)   = π‘Žπ‘™π‘” (negβ‚’  β…‹ π•€π•–π•ž a)

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

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

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

      open MetaAlgβ‡’ gᡃ⇒

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

      π•€π•–π•ž! 𝟘 = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! (_βŠ•_ a b) rewrite π•€π•–π•ž! a | π•€π•–π•ž! b = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! πŸ™ = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! (_βŠ—_ a b) rewrite π•€π•–π•ž! a | π•€π•–π•ž! b = sym βŸ¨π‘Žπ‘™π‘”βŸ©
      π•€π•–π•ž! (βŠ–_ a) rewrite π•€π•–π•ž! a = sym βŸ¨π‘Žπ‘™π‘”βŸ©


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

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