Lean migration: Phase 5 (language, CFGs, traces, Program)

- Spa.Language.Base: Expr/BasicStmt/Stmt + HasVar relations; StringSet
  lifts to Finset String
- Spa.Language.Semantics: Value/Env/Env.Mem, big-step relations,
  LatticeInterpretation (respects-≈ field drops out with =)
- Spa.Language.Graphs: Graph with nodes : Fin size → List BasicStmt
  (Vec lookup lemmas lift to Fin.append_left/right), comp/link/loop/
  skipto/singleton/wrap/buildCfg, predecessors via List.finRange
- Spa.Language.Traces: Trace + EndToEndTrace (Prop-valued)
- Spa.Language.Properties: trace embeddings, loop lemmas,
  buildCfg_sufficient; the 80-line Fin-disjointness block reduces to
  castAdd_ne_natAdd + mathlib list lemmas
- Spa.Language: Program (vars via Finset.sort — toList is noncomputable)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 19:30:42 -07:00
parent 781d7947e0
commit 2cfd0a2fb7
9 changed files with 763 additions and 1 deletions

View File

@@ -0,0 +1,78 @@
/-
Port of `Language/Base.agda`.
`StringSet` (built on `Lattice/MapSet.agda`, itself on `Lattice/Map.agda`) is
lifted to mathlib's `Finset String`: `insertˢ ↦ insert`, `emptyˢ ↦ ∅`,
`singletonˢ ↦ {·}`, `_⊔ˢ_ ↦ `, `to-List ↦ Finset.toList` (with
`Finset.nodup_toList` standing in for the intrinsic `Unique` proof).
Constructor renaming (Agda mixfix has no direct Lean counterpart):
_+_ ↦ Expr.add _-_ ↦ Expr.sub `_ ↦ Expr.var #_ ↦ Expr.num
_←_ ↦ BasicStmt.assign noop ↦ BasicStmt.noop
⟨_⟩ ↦ Stmt.basic _then_ ↦ Stmt.andThen
if_then_else_ ↦ Stmt.ifElse while_repeat_ ↦ Stmt.whileLoop
The `_∈ᵉ_` / `_∈ᵇ_` variable-occurrence relations are ported as
`Expr.HasVar` / `BasicStmt.HasVar`; the commented-out lemmas relating them to
`Expr-vars` remain unported (they were commented out in the Agda, too).
-/
import Mathlib.Data.Finset.Basic
namespace Spa
inductive Expr where
| add (e₁ e₂ : Expr)
| sub (e₁ e₂ : Expr)
| var (x : String)
| num (n : )
deriving DecidableEq
inductive BasicStmt where
| assign (x : String) (e : Expr)
| noop
deriving DecidableEq
inductive Stmt where
| basic (bs : BasicStmt)
| andThen (s₁ s₂ : Stmt)
| ifElse (e : Expr) (s₁ s₂ : Stmt)
| whileLoop (e : Expr) (s : Stmt)
deriving DecidableEq
/-- Agda: `_∈ᵉ_`. -/
inductive Expr.HasVar : String Expr Prop
| addLeft {e₁ e₂ k} : Expr.HasVar k e₁ Expr.HasVar k (.add e₁ e₂)
| addRight {e₁ e₂ k} : Expr.HasVar k e₂ Expr.HasVar k (.add e₁ e₂)
| subLeft {e₁ e₂ k} : Expr.HasVar k e₁ Expr.HasVar k (.sub e₁ e₂)
| subRight {e₁ e₂ k} : Expr.HasVar k e₂ Expr.HasVar k (.sub e₁ e₂)
| here {k} : Expr.HasVar k (.var k)
/-- Agda: `_∈ᵇ_`. -/
inductive BasicStmt.HasVar : String BasicStmt Prop
| assignLeft {k e} : BasicStmt.HasVar k (.assign k e)
| assignRight {k k' e} : Expr.HasVar k e BasicStmt.HasVar k (.assign k' e)
/-- Agda: `Expr-vars`. -/
def Expr.vars : Expr Finset String
| .add l r => l.vars r.vars
| .sub l r => l.vars r.vars
| .var s => {s}
| .num _ =>
/-- Agda: `BasicStmt-vars`. -/
def BasicStmt.vars : BasicStmt Finset String
| .assign x e => {x} e.vars
| .noop =>
/-- Agda: `Stmt-vars`. -/
def Stmt.vars : Stmt Finset String
| .basic bs => bs.vars
| .andThen s₁ s₂ => s₁.vars s₂.vars
| .ifElse e s₁ s₂ => (e.vars s₁.vars) s₂.vars
| .whileLoop e s => e.vars s.vars
/-- Agda: `Stmts-vars`. -/
def Stmt.varsList (ss : List Stmt) : Finset String :=
ss.foldr (fun s acc => s.vars acc)
end Spa