Download forth/Forth/Eval.lean from Snapkitty/ai-free: direct link, hf CLI and curl.
- Browser
- Download file 10.4 kB
-
https://huggingface.co/Snapkitty/ai-free/resolve/main/forth/Forth/Eval.lean
- Command line
-
hf download hf://Snapkitty/ai-free/forth/Forth/Eval.lean
-
curl -L -o Eval.lean https://huggingface.co/Snapkitty/ai-free/resolve/main/forth/Forth/Eval.lean
10.4 kB
| import Forth.Semantics | |
| /-! | |
| # Forth.Eval | |
| A fuel-bounded executable interpreter for the Forth reference semantics, proved sound | |
| against `Run`: if it returns a result, `Run` derives that result. It lets concrete facts about | |
| the reference semantics (including recursive words) be established by evaluation. | |
| -/ | |
| namespace WordDialect | |
| namespace Forth | |
| /-- Run `b` from `st` with at most `fuel` nested evaluation steps; `none` means out of fuel. -/ | |
| def eval {n : Nat} (defs : List Block) : Nat → Block → FState n → Option (Res n) | |
| | 0, _, _ => none | |
| | _ + 1, .nil, st => some (.ok st) | |
| | _ + 1, .exit _, st => some (.exit st) | |
| | _ + 1, .leave _, ⟨d, m, _ :: _ :: rs⟩ => some (.leave ⟨d, m, rs⟩) | |
| | _ + 1, .leave _, _ => some (.error .returnUnderflow) | |
| | f + 1, .op o rest, st => | |
| match o.sem st with | |
| | .ok st' => eval defs f rest st' | |
| | .error t => some (.error t) | |
| | _ + 1, .ite _ _ _, ⟨[], _, _⟩ => some (.error .stackUnderflow) | |
| | f + 1, .ite t e rest, ⟨c :: d, m, rs⟩ => | |
| match eval defs f (if Word.isTrue c then t else e) ⟨d, m, rs⟩ with | |
| | none => none | |
| | some (.error x) => some (.error x) | |
| | some (.exit st1) => some (.exit st1) | |
| | some (.leave st1) => some (.leave st1) | |
| | some (.ok st1) => eval defs f rest st1 | |
| | f + 1, .untilL body rest, st => | |
| match eval defs f body st with | |
| | none => none | |
| | some (.error x) => some (.error x) | |
| | some (.exit st1) => some (.exit st1) | |
| | some (.leave st1) => some (.leave st1) | |
| | some (.ok ⟨[], _, _⟩) => some (.error .stackUnderflow) | |
| | some (.ok ⟨c :: d, m, rs⟩) => | |
| if Word.isTrue c then eval defs f rest ⟨d, m, rs⟩ | |
| else eval defs f (.untilL body rest) ⟨d, m, rs⟩ | |
| | f + 1, .whileL cond body rest, st => | |
| match eval defs f cond st with | |
| | none => none | |
| | some (.error x) => some (.error x) | |
| | some (.exit st1) => some (.exit st1) | |
| | some (.leave st1) => some (.leave st1) | |
| | some (.ok ⟨[], _, _⟩) => some (.error .stackUnderflow) | |
| | some (.ok ⟨c :: d, m, rs⟩) => | |
| if Word.isTrue c then | |
| match eval defs f body ⟨d, m, rs⟩ with | |
| | none => none | |
| | some (.error x) => some (.error x) | |
| | some (.exit st2) => some (.exit st2) | |
| | some (.leave st2) => some (.leave st2) | |
| | some (.ok st2) => eval defs f (.whileL cond body rest) st2 | |
| else eval defs f rest ⟨d, m, rs⟩ | |
| | f + 1, .call i rest, st => | |
| match defs[i]? with | |
| | none => some (.error .badPc) | |
| | some body => | |
| match eval defs f body st with | |
| | none => none | |
| | some (.error x) => some (.error x) | |
| | some (.exit st1) => eval defs f rest st1 | |
| | some (.leave st1) => eval defs f rest st1 | |
| | some (.ok st1) => eval defs f rest st1 | |
| | f + 1, .doLoop body rest, ⟨i :: l :: d, m, rs⟩ => | |
| match eval defs f body ⟨d, m, i :: l :: rs⟩ with | |
| | none => none | |
| | some (.error x) => some (.error x) | |
| | some (.exit st1) => some (.exit st1) | |
| | some (.leave st1) => eval defs f rest st1 | |
| | some (.ok ⟨d1, m1, i1 :: l1 :: rs1⟩) => | |
| if i1 + 1#n = l1 then eval defs f rest ⟨d1, m1, rs1⟩ | |
| else eval defs f (.doLoop body rest) ⟨(i1 + 1#n) :: l1 :: d1, m1, rs1⟩ | |
| | some (.ok _) => some (.error .returnUnderflow) | |
| | _ + 1, .doLoop _ _, _ => some (.error .stackUnderflow) | |
| | f + 1, .plusLoop body rest, ⟨i :: l :: d, m, rs⟩ => | |
| match eval defs f body ⟨d, m, i :: l :: rs⟩ with | |
| | none => none | |
| | some (.error x) => some (.error x) | |
| | some (.exit st1) => some (.exit st1) | |
| | some (.leave st1) => eval defs f rest st1 | |
| | some (.ok ⟨k :: d1, m1, i1 :: l1 :: rs1⟩) => | |
| if loopCrossed i1 l1 k then eval defs f rest ⟨d1, m1, rs1⟩ | |
| else eval defs f (.plusLoop body rest) ⟨(i1 + k) :: l1 :: d1, m1, rs1⟩ | |
| | some (.ok ⟨[], _, _ :: _ :: _⟩) => some (.error .stackUnderflow) | |
| | some (.ok _) => some (.error .returnUnderflow) | |
| | _ + 1, .plusLoop _ _, _ => some (.error .stackUnderflow) | |
| theorem eval_sound {n : Nat} {defs : List Block} : | |
| ∀ (fuel : Nat) (b : Block) (st : FState n) (r : Res n), | |
| eval defs fuel b st = some r → Run defs b st r := by | |
| intro fuel | |
| induction fuel with | |
| | zero => intro b st r h; simp [eval] at h | |
| | succ f ih => | |
| intro b st r h | |
| cases b with | |
| | nil => simp only [eval, Option.some.injEq] at h; subst h; exact .nil | |
| | exit rest => simp only [eval, Option.some.injEq] at h; subst h; exact .exit | |
| | leave rest => | |
| obtain ⟨d, m, rs⟩ := st | |
| rcases rs with _ | ⟨a, _ | ⟨b, rs⟩⟩ | |
| · simp only [eval, Option.some.injEq] at h; subst h; exact .leaveUnder (by simp) | |
| · simp only [eval, Option.some.injEq] at h; subst h; exact .leaveUnder (by simp) | |
| · simp only [eval, Option.some.injEq] at h; subst h; exact .leaveOk | |
| | op o rest => | |
| simp only [eval] at h | |
| split at h | |
| · exact .opOk ‹_› (ih _ _ _ h) | |
| · cases h; exact .opErr ‹_› | |
| | ite t e rest => | |
| obtain ⟨d, m, rs⟩ := st | |
| cases d with | |
| | nil => simp only [eval, Option.some.injEq] at h; subst h; exact .iteUnder | |
| | cons c d => | |
| simp only [eval] at h | |
| split at h | |
| · cases h | |
| · rename_i x hx | |
| cases h | |
| cases hc : Word.isTrue c | |
| · rw [hc] at hx; exact .iteFalseStop hc (ih _ _ _ hx) rfl | |
| · rw [hc] at hx; exact .iteTrueStop hc (ih _ _ _ hx) rfl | |
| · rename_i x hx | |
| cases h | |
| cases hc : Word.isTrue c | |
| · rw [hc] at hx; exact .iteFalseStop hc (ih _ _ _ hx) rfl | |
| · rw [hc] at hx; exact .iteTrueStop hc (ih _ _ _ hx) rfl | |
| · rename_i x hx | |
| cases h | |
| cases hc : Word.isTrue c | |
| · rw [hc] at hx; exact .iteFalseStop hc (ih _ _ _ hx) rfl | |
| · rw [hc] at hx; exact .iteTrueStop hc (ih _ _ _ hx) rfl | |
| · rename_i st1 hx | |
| cases hc : Word.isTrue c | |
| · rw [hc] at hx; exact .iteFalse hc (ih _ _ _ hx) (ih _ _ _ h) | |
| · rw [hc] at hx; exact .iteTrue hc (ih _ _ _ hx) (ih _ _ _ h) | |
| | untilL body rest => | |
| simp only [eval] at h | |
| split at h | |
| · cases h | |
| · rename_i x hx; cases h; exact .untilBodyStop (ih _ _ _ hx) rfl | |
| · rename_i x hx; cases h; exact .untilBodyStop (ih _ _ _ hx) rfl | |
| · rename_i x hx; cases h; exact .untilBodyStop (ih _ _ _ hx) rfl | |
| · rename_i m rs hx; cases h; exact .untilUnder (ih _ _ _ hx) | |
| · rename_i c d m rs hx | |
| cases hc : Word.isTrue c | |
| · rw [hc] at h; exact .untilAgain (ih _ _ _ hx) hc (ih _ _ _ h) | |
| · rw [hc] at h; exact .untilDone (ih _ _ _ hx) hc (ih _ _ _ h) | |
| | whileL cond body rest => | |
| simp only [eval] at h | |
| split at h | |
| · cases h | |
| · rename_i x hx; cases h; exact .whileCondStop (ih _ _ _ hx) rfl | |
| · rename_i x hx; cases h; exact .whileCondStop (ih _ _ _ hx) rfl | |
| · rename_i x hx; cases h; exact .whileCondStop (ih _ _ _ hx) rfl | |
| · rename_i m rs hx; cases h; exact .whileUnder (ih _ _ _ hx) | |
| · rename_i c d m rs hx | |
| split at h | |
| · rename_i hc | |
| split at h | |
| · cases h | |
| · rename_i x hb; cases h; exact .whileBodyStop (ih _ _ _ hx) hc (ih _ _ _ hb) rfl | |
| · rename_i x hb; cases h; exact .whileBodyStop (ih _ _ _ hx) hc (ih _ _ _ hb) rfl | |
| · rename_i x hb; cases h; exact .whileBodyStop (ih _ _ _ hx) hc (ih _ _ _ hb) rfl | |
| · rename_i st2 hb; exact .whileAgain (ih _ _ _ hx) hc (ih _ _ _ hb) (ih _ _ _ h) | |
| · rename_i hc | |
| exact .whileExit (ih _ _ _ hx) (by simpa using hc) (ih _ _ _ h) | |
| | call i rest => | |
| simp only [eval] at h | |
| split at h | |
| · cases h; exact .callUndef ‹_› | |
| · rename_i body hi | |
| split at h | |
| · cases h | |
| · rename_i x hx; cases h; exact .callErr hi (ih _ _ _ hx) | |
| · rename_i st1 hx; exact .callOk hi (ih _ _ _ hx) rfl (ih _ _ _ h) | |
| · rename_i st1 hx; exact .callOk hi (ih _ _ _ hx) rfl (ih _ _ _ h) | |
| · rename_i st1 hx; exact .callOk hi (ih _ _ _ hx) rfl (ih _ _ _ h) | |
| | doLoop body rest => | |
| obtain ⟨d, m, rs⟩ := st | |
| rcases d with _ | ⟨i, _ | ⟨l, d⟩⟩ | |
| · simp only [eval, Option.some.injEq] at h; subst h; exact .doUnder (by simp) | |
| · simp only [eval, Option.some.injEq] at h; subst h; exact .doUnder (by simp) | |
| simp only [eval] at h | |
| split at h | |
| · cases h | |
| · rename_i x hx; cases h; exact .doBodyStop (ih _ _ _ hx) rfl | |
| · rename_i x hx; cases h; exact .doBodyStop (ih _ _ _ hx) rfl | |
| · rename_i st1 hx; exact .doLeave (ih _ _ _ hx) (ih _ _ _ h) | |
| · rename_i d1 m1 i1 l1 rs1 hx | |
| split at h | |
| · exact .doDone (ih _ _ _ hx) ‹_› (ih _ _ _ h) | |
| · exact .doAgain (ih _ _ _ hx) ‹_› (ih _ _ _ h) | |
| · rename_i st1 hne hx | |
| cases h | |
| obtain ⟨d1, m1, rs1⟩ := st1 | |
| rcases rs1 with _ | ⟨a, _ | ⟨b, rs1⟩⟩ | |
| · exact .doTestUnder (ih _ _ _ hx) (by simp) | |
| · exact .doTestUnder (ih _ _ _ hx) (by simp) | |
| · exact absurd rfl (hne d1 m1 a b rs1) | |
| | plusLoop body rest => | |
| obtain ⟨d, m, rs⟩ := st | |
| rcases d with _ | ⟨i, _ | ⟨l, d⟩⟩ | |
| · simp only [eval, Option.some.injEq] at h; subst h; exact .plusUnder (by simp) | |
| · simp only [eval, Option.some.injEq] at h; subst h; exact .plusUnder (by simp) | |
| simp only [eval] at h | |
| split at h | |
| · cases h | |
| · rename_i x hx; cases h; exact .plusBodyStop (ih _ _ _ hx) rfl | |
| · rename_i x hx; cases h; exact .plusBodyStop (ih _ _ _ hx) rfl | |
| · rename_i st1 hx; exact .plusLeave (ih _ _ _ hx) (ih _ _ _ h) | |
| · rename_i k d1 m1 i1 l1 rs1 hx | |
| split at h | |
| · exact .plusDone (ih _ _ _ hx) ‹_› (ih _ _ _ h) | |
| · rename_i hc; exact .plusAgain (ih _ _ _ hx) (by simpa using hc) (ih _ _ _ h) | |
| · rename_i m1 i1 l1 rs1 hx; cases h; exact .plusStepUnder (ih _ _ _ hx) | |
| · rename_i st1 hne1 hne2 hx | |
| cases h | |
| obtain ⟨d1, m1, rs1⟩ := st1 | |
| rcases rs1 with _ | ⟨a, _ | ⟨b, rs1⟩⟩ | |
| · exact .plusTestUnder (ih _ _ _ hx) (by simp) | |
| · exact .plusTestUnder (ih _ _ _ hx) (by simp) | |
| · cases d1 with | |
| | nil => exact absurd rfl (hne2 m1 a b rs1) | |
| | cons k d1 => exact absurd rfl (hne1 k d1 m1 a b rs1) | |
| end Forth | |
| end WordDialect | |