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

syntax CommRing | CR

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
  (βŠ—C) a b |> mult(a, b) = mult(b, a)
-}


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

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

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

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

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

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

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

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

  module CRᡃ = MetaAlg CRᡃ

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

    open MetaAlg π’œα΅ƒ

    π•€π•–π•ž : CR β‡ΎΜ£ π’œ
    π•Š : Sub CR Ξ  Ξ“ β†’ Ξ  ~[ π’œ ]↝ Ξ“
    π•Š (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β‡’ CRᡃ π’œα΅ƒ π•€π•–π•ž
    π•€π•–π•žα΅ƒβ‡’ = record
      { βŸ¨π‘Žπ‘™π‘”βŸ© = Ξ»{ {t = t} β†’ βŸ¨π‘Žπ‘™π‘”βŸ© t }
      ; βŸ¨π‘£π‘Žπ‘ŸβŸ© = refl
      ; βŸ¨π‘šπ‘£π‘Žπ‘ŸβŸ© = Ξ»{ {π”ͺ = π”ͺ}{mΞ΅} β†’ cong (π‘šπ‘£π‘Žπ‘Ÿ π”ͺ) (dext (π•Š-tab mΞ΅)) }  }
      where
      open ≑-Reasoning
      βŸ¨π‘Žπ‘™π‘”βŸ© : (t : β…€ CR Ξ± Ξ“) β†’ π•€π•–π•ž (CRᡃ.π‘Žπ‘™π‘” t) ≑ π‘Žπ‘™π‘” (⅀₁ π•€π•–π•ž t)
      βŸ¨π‘Žπ‘™π‘”βŸ© (zeroβ‚’ β…‹ _) = refl
      βŸ¨π‘Žπ‘™π‘”βŸ© (addβ‚’  β…‹ _) = refl
      βŸ¨π‘Žπ‘™π‘”βŸ© (oneβ‚’  β…‹ _) = refl
      βŸ¨π‘Žπ‘™π‘”βŸ© (multβ‚’ β…‹ _) = refl
      βŸ¨π‘Žπ‘™π‘”βŸ© (negβ‚’  β…‹ _) = refl

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

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

      open MetaAlgβ‡’ gᡃ⇒

      π•€π•–π•ž! : (t : CR Ξ± Ξ“) β†’ π•€π•–π•ž t ≑ g t
      π•Š-ix : (mΞ΅ : Sub CR Ξ  Ξ“)(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
CR:Syn : Syntax
CR:Syn = record
  { β…€F = β…€F
  ; β…€:CS = β…€:CompatStr
  ; mvarα΅’ = CR:Terms.mvar
  ; 𝕋:Init = Ξ» 𝔛 β†’ let open CR:Terms 𝔛 in record
    { βŠ₯ = CR ⋉ CRᡃ
    ; βŠ₯-is-initial = record { ! = Ξ»{ {π’œ ⋉ π’œα΅ƒ} β†’ π•€π•–π•ž π’œα΅ƒ ⋉ π•€π•–π•žα΅ƒβ‡’ π’œα΅ƒ }
    ; !-unique = Ξ»{ {π’œ ⋉ π’œα΅ƒ} (f ⋉ fᡃ⇒) {x = t} β†’ π•€π•–π•ž! π’œα΅ƒ f fᡃ⇒ t } } } }

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