import Spa.Analysis.Reaching import Spa.Language.TraceProperties namespace Spa namespace ReachingAnalysis /-- The most recent assignment occurs in the history being searched. -/ lemma LastAssign.mem {prog : Program} {x : String} {run : Run prog} {d : prog.State} (h : LastAssign prog x run d) : d ∈ run := by induction h <;> aesop /-- Appending older history cannot displace an already-found assignment. -/ lemma LastAssign.append {prog : Program} {x : String} {new : Run prog} {d : prog.State} (h : LastAssign prog x new d) (old : Run prog) : LastAssign prog x (new ++ old) d := by induction h with | here s rhs rest hc => exact .here s rhs _ hc | there s rest hn h ih => exact .there s _ hn ih /-- A history containing a write to `x` has a most recent assignment to `x`. -/ lemma lastAssign_of_write {prog : Program} {x : String} {run : Run prog} (hw : ∃ d ∈ run, ∃ rhs, prog.code d = some (.assign x rhs)) : ∃ d, LastAssign prog x run d := by induction run with | nil => simp at hw | cons d rest ih => by_cases hx : ∃ rhs, prog.code d = some (.assign x rhs) · obtain ⟨rhs, hc⟩ := hx exact ⟨d, .here d rhs rest hc⟩ · have hw' : ∃ j ∈ rest, ∃ rhs, prog.code j = some (.assign x rhs) := by obtain ⟨j, hm, rhs, hc⟩ := hw rcases List.mem_cons.mp hm with rfl | hm · exact False.elim (hx ⟨rhs, hc⟩) · exact ⟨j, hm, rhs, hc⟩ obtain ⟨j, hj⟩ := ih hw' exact ⟨j, .there d rest (by simpa using hx) hj⟩ /-- Outside reaching definitions rule out any write in a confined intervening path. No equality of static sites is used to infer equality of events. -/ lemma Path.preserves_of_lastAssign_outside {prog : Program} {a b c : Configuration prog.cfg} (pre : Path prog.cfg a b) (seg : Path prog.cfg b c) {x : String} (sites : Set prog.State) (hin : ∀ d ∈ seg.steps, d ∈ sites) (hout : ∀ d, LastAssign prog x (runOfPath prog (pre.append seg)) d → d ∉ sites) : ∀ v, Env.Mem (x, v) b.2 ↔ Env.Mem (x, v) c.2 := by apply seg.preserves_unwritten intro d hm rhs hc obtain ⟨j, hl⟩ := lastAssign_of_write ⟨d, List.mem_reverse.mpr hm, rhs, hc⟩ apply hout j · simpa [runOfPath, List.reverse_append] using hl.append (runOfPath prog pre) · exact hin j (List.mem_reverse.mp hl.mem) end ReachingAnalysis end Spa