- 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>
91 lines
3.0 KiB
Lean4
91 lines
3.0 KiB
Lean4
/-
|
||
Port of `Language.agda` (the `Program` record and re-exports).
|
||
|
||
Correspondence:
|
||
Program record ↦ structure Program (defs in the `Program` namespace)
|
||
graph ↦ Program.graph
|
||
State ↦ Program.State
|
||
initialState ↦ Program.initialState
|
||
finalState ↦ Program.finalState
|
||
trace ↦ Program.trace
|
||
vars, vars-Unique ↦ Program.vars, Program.vars_nodup
|
||
(Finset.toList + Finset.nodup_toList replace
|
||
`to-Listˢ` and the intrinsic MapSet uniqueness)
|
||
states, states-complete, states-Unique
|
||
↦ Program.states, .states_complete, .states_nodup
|
||
code ↦ Program.code
|
||
_≟_, _≟ᵉ_ ↦ (instances, automatic for Fin/products)
|
||
incoming ↦ Program.incoming
|
||
initialState-pred-∅ ↦ Program.incoming_initialState_eq_nil
|
||
edge⇒incoming ↦ Program.mem_incoming_of_edge
|
||
-/
|
||
import Spa.Language.Base
|
||
import Spa.Language.Semantics
|
||
import Spa.Language.Graphs
|
||
import Spa.Language.Traces
|
||
import Spa.Language.Properties
|
||
import Mathlib.Data.Finset.Sort
|
||
import Mathlib.Data.String.Basic
|
||
|
||
namespace Spa
|
||
|
||
structure Program where
|
||
rootStmt : Stmt
|
||
|
||
namespace Program
|
||
|
||
variable (p : Program)
|
||
|
||
def graph : Graph := Graph.wrap (buildCfg p.rootStmt)
|
||
|
||
abbrev State : Type := p.graph.Index
|
||
|
||
def initialState : p.State := (buildCfg p.rootStmt).wrapInput
|
||
|
||
def finalState : p.State := (buildCfg p.rootStmt).wrapOutput
|
||
|
||
/-- Agda: `Program.trace`. -/
|
||
theorem trace {ρ : Env} (h : EvalStmt [] p.rootStmt ρ) :
|
||
Trace p.graph p.initialState p.finalState [] ρ := by
|
||
obtain ⟨i₁, h₁, i₂, h₂, tr⟩ := EndToEndTrace.wrap (buildCfg_sufficient h)
|
||
rw [Graph.wrap_inputs, List.mem_singleton] at h₁
|
||
rw [Graph.wrap_outputs, List.mem_singleton] at h₂
|
||
subst h₁; subst h₂
|
||
exact tr
|
||
|
||
/-- Agda: `vars` (via `vars-Set = Stmt-vars rootStmt`). `Finset.toList` is
|
||
noncomputable, so the variables are listed in sorted order instead — this is
|
||
the computable stand-in for MapSet's `to-List`. -/
|
||
def vars : List String := p.rootStmt.vars.sort (· ≤ ·)
|
||
|
||
/-- Agda: `vars-Unique`. -/
|
||
theorem vars_nodup : p.vars.Nodup := Finset.sort_nodup _ _
|
||
|
||
def states : List p.State := p.graph.indices
|
||
|
||
/-- Agda: `states-complete`. -/
|
||
theorem states_complete (s : p.State) : s ∈ p.states := p.graph.mem_indices s
|
||
|
||
/-- Agda: `states-Unique`. -/
|
||
theorem states_nodup : p.states.Nodup := p.graph.nodup_indices
|
||
|
||
/-- Agda: `code`. -/
|
||
def code (st : p.State) : List BasicStmt := p.graph.nodes st
|
||
|
||
/-- Agda: `incoming`. -/
|
||
def incoming (s : p.State) : List p.State := p.graph.predecessors s
|
||
|
||
/-- Agda: `initialState-pred-∅`. -/
|
||
theorem incoming_initialState_eq_nil : p.incoming p.initialState = [] :=
|
||
Graph.wrap_predecessors_eq_nil (buildCfg p.rootStmt) p.initialState
|
||
(by rw [Graph.wrap_inputs]; exact List.mem_singleton_self _)
|
||
|
||
/-- Agda: `edge⇒incoming`. -/
|
||
theorem mem_incoming_of_edge {s₁ s₂ : p.State}
|
||
(h : (s₁, s₂) ∈ p.graph.edges) : s₁ ∈ p.incoming s₂ :=
|
||
p.graph.mem_predecessors_of_edge h
|
||
|
||
end Program
|
||
|
||
end Spa
|