------------------------------------------------------------------------
-- INCREMENTAL λ-CALCULUS
--
-- Change evaluation with the Nehemiah plugin.
------------------------------------------------------------------------

module Nehemiah.Change.Specification where

open import Nehemiah.Syntax.Type
open import Nehemiah.Syntax.Term
open import Nehemiah.Denotation.Value
open import Nehemiah.Denotation.Evaluation
open import Nehemiah.Change.Validity

open import Relation.Binary.PropositionalEquality
open import Data.Integer
open import Theorem.Groups-Nehemiah

import Parametric.Change.Specification
  Const ⟦_⟧Base ⟦_⟧Const change-algebra-base-family as Specification

private
  ⟦_⟧ΔConst : ∀ {Σ τ} → (c  : Const Σ τ) (ρ : ⟦ Σ ⟧) → Δ₍ Σ ₎ ρ → Δ₍ τ ₎ (⟦ c ⟧Const ρ)
  ⟦ intlit-const n ⟧ΔConst ∅ ∅ = + 0
  ⟦ add-const ⟧ΔConst (n₁ • n₂ • ∅) (dn₁ • dn₂ • ∅) = dn₁ + dn₂
  ⟦ minus-const ⟧ΔConst (n • ∅) (dn • ∅) = - dn
  ⟦ empty-const ⟧ΔConst ∅ ∅ = emptyBag
  ⟦ insert-const ⟧ΔConst (n • b • ∅) (dn • db • ∅) =
      (singletonBag (n + dn) ++ (b ++ db)) \\ (singletonBag n ++ b)
  ⟦ union-const ⟧ΔConst (b₁ • b₂ • ∅) (db₁ • db₂ • ∅) = db₁ ++ db₂
  ⟦ negate-const ⟧ΔConst (b • ∅) (db • ∅) = negateBag db
  ⟦ flatmap-const ⟧ΔConst (f • b • ∅) (df • db • ∅) =
      flatmapBag (f ⊞₍ int ⇒ bag ₎ df) (b ++ db) \\ flatmapBag f b
  ⟦ sum-const ⟧ΔConst (b • ∅) (db • ∅) = sumBag db

  correctness-const : ∀ {Σ τ} (c : Const Σ τ) →
    Derivative₍ Σ , τ ₎ ⟦ c ⟧Const ⟦ c ⟧ΔConst
  correctness-const (intlit-const n) ∅ ∅ = right-id-int n
  correctness-const add-const (n₁ • n₂ • ∅) (dn₁ • dn₂ • ∅) =
    mn·pq=mp·nq {n₁} {n₂} {dn₁} {dn₂}
  correctness-const minus-const (n • ∅) (dn • ∅) = -m·-n=-mn {n} {dn}
  correctness-const empty-const ∅ ∅ = right-id-bag emptyBag
  correctness-const insert-const (n • b • ∅) (dn • db • ∅) = a++[b\\a]=b
  correctness-const union-const (b₁ • b₂ • ∅) (db₁ • db₂ • ∅) = ab·cd=ac·bd
  correctness-const negate-const (b • ∅) (db • ∅) = -a·-b=-ab
  correctness-const flatmap-const (f • b • ∅) (df • db • ∅) = a++[b\\a]=b
  correctness-const sum-const (b • ∅) (db • ∅) = sym homo-sum

specification-structure : Specification.Structure
specification-structure = record
    { ⟦_⟧ΔConst = ⟦_⟧ΔConst
    ; correctness-const = correctness-const
    }

open Specification.Structure specification-structure public