/- Port of `Language/Semantics.agda`. Correspondence: Value (↑ᶻ) ↦ Value.int Env ↦ Env (= List (String × Value)) _∈_ (env lookup) ↦ Env.Mem _,_⇒ᵉ_ ↦ EvalExpr _,_⇒ᵇ_ ↦ EvalBasicStmt _,_⇒ᵇˢ_ ↦ EvalBasicStmts _,_⇒ˢ_ ↦ EvalStmt LatticeInterpretation: ⟦_⟧ ↦ interp ⟦⟧-respects-≈ ↦ (trivial with `=`; field dropped) ⟦⟧-⊔-∨ ↦ interp_sup ⟦⟧-⊓-∧ ↦ interp_inf (the `Utils` combinators `_⇒_`, `_∨_`, `_∧_` are inlined as plain logic) -/ import Spa.Language.Base import Spa.Lattice namespace Spa inductive Value where | int (z : ℤ) deriving DecidableEq def Env : Type := List (String × Value) /-- Agda: `_∈_` on environments — lookup respecting shadowing. -/ inductive Env.Mem : String × Value → Env → Prop | here (s : String) (v : Value) (ρ : Env) : Env.Mem (s, v) ((s, v) :: ρ) | there (s s' : String) (v v' : Value) (ρ : Env) : ¬(s = s') → Env.Mem (s, v) ρ → Env.Mem (s, v) ((s', v') :: ρ) /-- Agda: `_,_⇒ᵉ_`. -/ inductive EvalExpr : Env → Expr → Value → Prop | num (ρ : Env) (n : ℕ) : EvalExpr ρ (.num n) (.int n) | var (ρ : Env) (x : String) (v : Value) : Env.Mem (x, v) ρ → EvalExpr ρ (.var x) v | add (ρ : Env) (e₁ e₂ : Expr) (z₁ z₂ : ℤ) : EvalExpr ρ e₁ (.int z₁) → EvalExpr ρ e₂ (.int z₂) → EvalExpr ρ (.add e₁ e₂) (.int (z₁ + z₂)) | sub (ρ : Env) (e₁ e₂ : Expr) (z₁ z₂ : ℤ) : EvalExpr ρ e₁ (.int z₁) → EvalExpr ρ e₂ (.int z₂) → EvalExpr ρ (.sub e₁ e₂) (.int (z₁ - z₂)) /-- Agda: `_,_⇒ᵇ_`. -/ inductive EvalBasicStmt : Env → BasicStmt → Env → Prop | noop (ρ : Env) : EvalBasicStmt ρ .noop ρ | assign (ρ : Env) (x : String) (e : Expr) (v : Value) : EvalExpr ρ e v → EvalBasicStmt ρ (.assign x e) ((x, v) :: ρ) /-- Agda: `_,_⇒ᵇˢ_`. -/ inductive EvalBasicStmts : Env → List BasicStmt → Env → Prop | nil {ρ : Env} : EvalBasicStmts ρ [] ρ | cons {ρ₁ ρ₂ ρ₃ : Env} {bs : BasicStmt} {bss : List BasicStmt} : EvalBasicStmt ρ₁ bs ρ₂ → EvalBasicStmts ρ₂ bss ρ₃ → EvalBasicStmts ρ₁ (bs :: bss) ρ₃ /-- Agda: `_,_⇒ˢ_`. -/ inductive EvalStmt : Env → Stmt → Env → Prop | basic (ρ₁ ρ₂ : Env) (bs : BasicStmt) : EvalBasicStmt ρ₁ bs ρ₂ → EvalStmt ρ₁ (.basic bs) ρ₂ | andThen (ρ₁ ρ₂ ρ₃ : Env) (s₁ s₂ : Stmt) : EvalStmt ρ₁ s₁ ρ₂ → EvalStmt ρ₂ s₂ ρ₃ → EvalStmt ρ₁ (.andThen s₁ s₂) ρ₃ | ifTrue (ρ₁ ρ₂ : Env) (e : Expr) (z : ℤ) (s₁ s₂ : Stmt) : EvalExpr ρ₁ e (.int z) → ¬(z = 0) → EvalStmt ρ₁ s₁ ρ₂ → EvalStmt ρ₁ (.ifElse e s₁ s₂) ρ₂ | ifFalse (ρ₁ ρ₂ : Env) (e : Expr) (s₁ s₂ : Stmt) : EvalExpr ρ₁ e (.int 0) → EvalStmt ρ₁ s₂ ρ₂ → EvalStmt ρ₁ (.ifElse e s₁ s₂) ρ₂ | whileTrue (ρ₁ ρ₂ ρ₃ : Env) (e : Expr) (z : ℤ) (s : Stmt) : EvalExpr ρ₁ e (.int z) → ¬(z = 0) → EvalStmt ρ₁ s ρ₂ → EvalStmt ρ₂ (.whileLoop e s) ρ₃ → EvalStmt ρ₁ (.whileLoop e s) ρ₃ | whileFalse (ρ : Env) (e : Expr) (s : Stmt) : EvalExpr ρ e (.int 0) → EvalStmt ρ (.whileLoop e s) ρ /-- Agda: `LatticeInterpretation` (used there as an instance argument `⦃·⦄`, hence a typeclass here). -/ class LatticeInterpretation (L : Type*) [Lattice L] where interp : L → Value → Prop interp_sup : ∀ {l₁ l₂ : L} (v : Value), interp l₁ v ∨ interp l₂ v → interp (l₁ ⊔ l₂) v interp_inf : ∀ {l₁ l₂ : L} (v : Value), interp l₁ v ∧ interp l₂ v → interp (l₁ ⊓ l₂) v end Spa