diff --git a/lean/Spa.lean b/lean/Spa.lean index 7abb39e..b1a0048 100644 --- a/lean/Spa.lean +++ b/lean/Spa.lean @@ -6,6 +6,7 @@ import Spa.Lattice.Prod import Spa.Lattice.AboveBelow import Spa.Lattice.IterProd import Spa.Lattice.FiniteMap +import Spa.Lattice.Bool import Spa.Language.Base import Spa.Language.Notation import Spa.Language.Semantics diff --git a/lean/Spa/Analysis/Reaching.lean b/lean/Spa/Analysis/Reaching.lean new file mode 100644 index 0000000..8a40e24 --- /dev/null +++ b/lean/Spa/Analysis/Reaching.lean @@ -0,0 +1,41 @@ +import Spa.Analysis.Forward +import Spa.Lattice.Bool +import Spa.Showable + +namespace Spa + +open Forward + +instance : Showable Bool := ⟨fun b => if b then "true" else "false"⟩ + +abbrev DefSet (prog : Program) : Type := FiniteMap prog.State Bool prog.states + +namespace ReachingAnalysis + +variable (prog : Program) + +def genSet (s : prog.State) : DefSet prog := + FiniteMap.updating (⊥ : DefSet prog) [s] (fun _ => true) + +def eval (s : prog.State) : + BasicStmt → VariableValues (DefSet prog) prog → VariableValues (DefSet prog) prog + | .assign k _, vs => + FiniteMap.generalizedUpdate id (fun _ _ => genSet prog s) [k] vs + | .noop, vs => vs + +theorem eval_mono (s : prog.State) (bs : BasicStmt) : + Monotone (eval prog s bs) := by + cases bs with + | assign k e => + exact FiniteMap.generalizedUpdate_monotone monotone_id (fun _ => monotone_const) + | noop => exact monotone_id + +instance stmtEvaluator : StmtEvaluator (DefSet prog) prog := + ⟨eval prog, eval_mono prog⟩ + +def output : String := + show' (result (DefSet prog) prog) + +end ReachingAnalysis + +end Spa diff --git a/lean/Spa/Lattice/Bool.lean b/lean/Spa/Lattice/Bool.lean new file mode 100644 index 0000000..fceea95 --- /dev/null +++ b/lean/Spa/Lattice/Bool.lean @@ -0,0 +1,42 @@ +import Spa.Lattice +import Mathlib.Order.BooleanAlgebra + +namespace Spa + +/-! ### `Bool` as a finite-height lattice + +`Bool` is the two-element lattice `false ≤ true` (with `⊥ = false`, `⊤ = true`). +It is the building block of the "power set" lattice `FiniteMap A Bool ks`, used by +the reaching-definitions analysis to represent sets of definition sites. -/ + +namespace Bool + +/-- Rank of a boolean: `false ↦ 0`, `true ↦ 1`. Used to bound chains, mirroring +`AboveBelow.rank`. -/ +def rank : Bool → ℕ + | false => 0 + | true => 1 + +theorem rank_strictMono : StrictMono rank := by + intro a b hab + cases a <;> cases b <;> revert hab <;> decide + +theorem boundedChains : BoundedChains Bool 1 := fun c => by + have h := LTSeries.head_add_length_le_nat (c.map rank rank_strictMono) + rw [LTSeries.head_map, LTSeries.last_map, LTSeries.map_length] at h + have h2 : rank c.last ≤ 1 := by cases c.last <;> simp [rank] + omega + +instance : FiniteHeightLattice Bool where + height := 1 + longestChain := + { series := (RelSeries.singleton _ (⊥ : Bool)).snoc (⊤ : Bool) + (by rw [RelSeries.last_singleton]; exact bot_lt_top) + head_series := by simp + last_series := by simp + length_series := by simp [RelSeries.snoc, RelSeries.append] } + chains_bounded := boundedChains + +end Bool + +end Spa