Switch steps to not redundantly include code

This commit is contained in:
2026-10-06 19:30:35 -05:00
parent 234d17394e
commit 655b7de684
2 changed files with 24 additions and 23 deletions

View File

@@ -40,20 +40,20 @@ instance stmtEvaluator : StmtEvaluator (DefSet prog) prog :=
def output : String := def output : String :=
show' (result (DefSet prog) prog) show' (result (DefSet prog) prog)
/-- The statements a trace executed, paired with the state each executed at, /-- Executed nodes, most recent first. Instructions are read from `prog.code`.
most recent first (matching `LastAssign`, which scans for the most recent This is `Path.steps` (chronological) reversed, so facts about concatenating
assignment). This is `Path.steps` (chronological) reversed, so facts about traces reduce to mathlib's `List.append`/`List.reverse` lemmas. -/
concatenating traces reduce to mathlib's `List.append`/`List.reverse` lemmas. -/ abbrev Run (prog : Program) : Type := List prog.State
abbrev Run (prog : Program) : Type := List (prog.State × BasicStmt)
/-- The first node in a newest-first history whose instruction assigns `x`. -/
@[aesop unsafe cases] @[aesop unsafe cases]
inductive LastAssign (prog : Program) (x : String) : Run prog → prog.State → Prop inductive LastAssign (prog : Program) (x : String) : Run prog → prog.State → Prop
| here (s : prog.State) (e : Expr) (rest : Run prog) : | here (s : prog.State) (e : Expr) (rest : Run prog)
LastAssign prog x ((s, .assign x e) :: rest) s (hc : prog.code s = some (.assign x e)) :
| there (s : prog.State) (bs : BasicStmt) (hc : prog.code s = some bs) LastAssign prog x (s :: rest) s
(rest : Run prog) {n : prog.State} : | there (s : prog.State) (rest : Run prog) {n : prog.State} :
(∀ e, bs ≠ .assign x e) → LastAssign prog x rest n → (∀ e, prog.code s ≠ some (.assign x e)) → LastAssign prog x rest n →
LastAssign prog x ((s, bs) :: rest) n LastAssign prog x (s :: rest) n
def runOfPath {a b : Configuration prog.cfg} (p : Path prog.cfg a b) : Run prog := def runOfPath {a b : Configuration prog.cfg} (p : Path prog.cfg a b) : Run prog :=
p.steps.reverse p.steps.reverse
@@ -97,16 +97,16 @@ private lemma valid_step (s : prog.State) {ρ₁ ρ₂ : Env}
cases hbs with cases hbs with
| noop => | noop =>
simp [eval, hcode, EvalBasicStmtOpt.steps] simp [eval, hcode, EvalBasicStmtOpt.steps]
intro x assigners hmem n hla; aesop intro x assigners hmem n hla; aesop (add simp hcode)
| assign x e v hev => | assign x e v hev =>
simp [eval, hcode, EvalBasicStmtOpt.steps]; intro k assigners hmem n hla simp [eval, hcode, EvalBasicStmtOpt.steps]; intro k assigners hmem n hla
by_cases hx : k = x by_cases hx : k = x
· subst hx · subst hx
have hd := FiniteMap.generalizedUpdate_mem_eq (List.mem_singleton.mpr rfl) hmem have hd := FiniteMap.generalizedUpdate_mem_eq (List.mem_singleton.mpr rfl) hmem
rcases hla <;> simp [hd] <;> aesop rcases hla <;> simp [hd] <;> aesop (add simp hcode)
· have hmem' := FiniteMap.generalizedUpdate_not_mem_backward · have hmem' := FiniteMap.generalizedUpdate_not_mem_backward
(fun hc => hx (List.mem_singleton.mp hc)) hmem (fun hc => hx (List.mem_singleton.mp hc)) hmem
aesop aesop (add simp hcode)
instance validStateEvaluator : ValidStateEvaluator (DefSet prog) prog where instance validStateEvaluator : ValidStateEvaluator (DefSet prog) prog where
valid := by valid := by

View File

@@ -186,27 +186,28 @@ instance {g : Graph} {idx₁ idx₂ : g.Index} {ρ₁ ρ₂ ρ₃ : Env} :
HAppend (Traceₗ g idx₁ idx₂ ρ₁ ρ₂) (EvalBasicStmtOpt ρ₂ (g.nodes idx₂) ρ₃) HAppend (Traceₗ g idx₁ idx₂ ρ₁ ρ₂) (EvalBasicStmtOpt ρ₂ (g.nodes idx₂) ρ₃)
(Trace g idx₁ idx₂ ρ₁ ρ₃) := ⟨Traceₗ.appendStep⟩ (Trace g idx₁ idx₂ ρ₁ ρ₃) := ⟨Traceₗ.appendStep⟩
/-- The (index, statement) pairs executed by a single optional-statement step. -/ /-- The node executed by an optional-statement step; empty nodes are omitted. -/
def EvalBasicStmtOpt.steps {α : Type*} (idx : α) {ρ₁ ρ₂ : Env} {obs : Option BasicStmt} : def EvalBasicStmtOpt.steps {α : Type*} (idx : α) {ρ₁ ρ₂ : Env} {obs : Option BasicStmt} :
EvalBasicStmtOpt ρ₁ obs ρ₂ → List (α × BasicStmt) EvalBasicStmtOpt ρ₁ obs ρ₂ → List α
| .none => [] | .none => []
| .some (bs := bs) _ => [(idx, bs)] | .some _ => [idx]
def Step.steps {g : Graph} {a b : Configuration g} : Step g a b → List (g.Index × BasicStmt) def Step.steps {g : Graph} {a b : Configuration g} : Step g a b → List g.Index
| .execute (i := i) h => h.steps i | .execute (i := i) h => h.steps i
| .edge _ => [] | .edge _ => []
/-- Executed statements in chronological order; edges and empty nodes contribute nothing. -/ /-- Executed nodes in chronological order; edges and empty nodes contribute nothing.
def Path.steps {g : Graph} {a b : Configuration g} : Path g a b → List (g.Index × BasicStmt) The instruction at each node is given by `g.nodes`, rather than copied into the history. -/
def Path.steps {g : Graph} {a b : Configuration g} : Path g a b → List g.Index
| .nil => [] | .nil => []
| .cons s p => s.steps ++ p.steps | .cons s p => s.steps ++ p.steps
abbrev Trace.steps {g : Graph} {i j : g.Index} {ρ₁ ρ₂ : Env} abbrev Trace.steps {g : Graph} {i j : g.Index} {ρ₁ ρ₂ : Env}
(p : Trace g i j ρ₁ ρ₂) : List (g.Index × BasicStmt) := Path.steps p (p : Trace g i j ρ₁ ρ₂) : List g.Index := Path.steps p
abbrev Traceₗ.steps {g : Graph} {i j : g.Index} {ρ₁ ρ₂ : Env} abbrev Traceₗ.steps {g : Graph} {i j : g.Index} {ρ₁ ρ₂ : Env}
(p : Traceₗ g i j ρ₁ ρ₂) : List (g.Index × BasicStmt) := Path.steps p (p : Traceₗ g i j ρ₁ ρ₂) : List g.Index := Path.steps p
abbrev Traceᵣ.steps {g : Graph} {i j : g.Index} {ρ₁ ρ₂ : Env} abbrev Traceᵣ.steps {g : Graph} {i j : g.Index} {ρ₁ ρ₂ : Env}
(p : Traceᵣ g i j ρ₁ ρ₂) : List (g.Index × BasicStmt) := Path.steps p (p : Traceᵣ g i j ρ₁ ρ₂) : List g.Index := Path.steps p
@[simp] lemma Path.steps_append {g : Graph} {a b c : Configuration g} @[simp] lemma Path.steps_append {g : Graph} {a b c : Configuration g}
(p : Path g a b) (q : Path g b c) : (p : Path g a b) (q : Path g b c) :