proof/: all 23 Isabelle theory files now verify under Isabelle2025-2

Isabelle toolchain replaced (was genuinely 2011, 14+ years stale) and every
theory file fixed to actually compile -- most had apparently never been
checked under a working Isabelle at all. Fixed the vm_state self-reference
in StarForth_Base.thy properly (word_table is now a free-standing global
constant, not a circular record field), corrected the word_physics_transparent
axiom (was claiming full state equality from mere exec-equivalence, provably
too strong), and worked through 14 years of HOL-Library drift plus several
missing-hypothesis bugs across the physics-loop and ACL theories.

Two genuine (non-tactical) bugs found and left oops-flagged rather than
silently resolved: forth_roll's index arithmetic disagrees with both its own
test lemma and the real C ROLL implementation (three-way inconsistency), and
pm_wf isn't actually preserved by pm_record_hit/pm_record_miss. Both need a
decision, not a proof-script fix.

Full writeup in FABRIC-2.md item 5.2.
This commit is contained in:
Robert Allan James
2026-08-13 12:30:30 -04:00
parent 5787718c30
commit 422ef2fa29
20 changed files with 561 additions and 198 deletions
+28 -7
View File
@@ -343,7 +343,7 @@ lemma pick_normal:
assumes "n \<ge> 0"
assumes "nat n < length (data_stack vm)"
shows "data_stack (forth_pick vm) = data_stack vm ! nat n # xs"
by (simp add: forth_pick_def assms)
using assms by (auto simp: forth_pick_def)
lemma pick_depth_unchanged:
assumes "data_stack vm = n # xs"
@@ -380,7 +380,7 @@ lemma pick_bounds_high:
assumes "data_stack vm = n # xs"
assumes "nat n \<ge> length (data_stack vm)"
shows "vm_error (forth_pick vm)"
by (simp add: forth_pick_def set_error_def assms)
using assms by (auto simp: forth_pick_def set_error_def)
(* ── ROLL ( +n -- ) ─────────────────────────────────────────────────────── *)
(* Pops n, then rotates items.
@@ -407,8 +407,8 @@ definition forth_roll :: "vm_state \<Rightarrow> vm_state" where
then set_error vm
else if n = 0 \<or> n = 1
then vm\<lparr>data_stack := xs\<rparr>
else let i = nat n
item = xs ! (i - 1)
else let i = nat n;
item = xs ! (i - 1);
rest = take (i - 1) xs @ drop i xs
in vm\<lparr>data_stack := item # rest\<rparr>)"
@@ -417,16 +417,37 @@ lemma roll_zero_nop:
shows "data_stack (forth_roll vm) = xs"
by (simp add: forth_roll_def assms)
(* CORRECTED 2026-08-13: added the missing "xs non-empty" hypothesis. For
n=1 with xs=[], forth_roll_def's own guard (nat n > length xs, i.e.
1 > 0) fires BEFORE the n=0\<or>n=1 shortcut is reached, giving set_error
instead of the identity -- so the claim is false for xs=[]. *)
lemma roll_one_nop:
assumes "data_stack vm = 1 # xs"
assumes "xs \<noteq> []"
shows "data_stack (forth_roll vm) = xs"
by (simp add: forth_roll_def assms)
using assms by (auto simp: forth_roll_def)
(* 2 ROLL is equivalent to ROT (bring third item to top). *)
(* FLAGGED, NOT FIXED 2026-08-13: this lemma does not hold against
forth_roll_def as currently written. Tracing the definition by hand for
this exact instantiation (xs = n3#n2#n1#rest after popping the leading
2) gives item = xs!(i-1) = xs!1 = n2, rest' = take 1 xs @ drop 2 xs =
n3#n1#rest, so forth_roll actually produces n2#n3#n1#rest -- not
n1#n3#n2#rest as this lemma (and its own "2 ROLL is equivalent to ROT"
comment) claims. Separately, the real C stack_word_roll
(src/word_source/stack_words.c:287-320) uses yet a THIRD convention of
its own, explicitly commented "1-indexed from bottom: n=1 moves bottom
item to top" -- neither this definition nor this lemma's expectation
matches it. Three mutually inconsistent conventions (this definition,
this lemma, and the C code) -- not a proof-script issue, a genuine
unresolved semantic question about what ROLL is supposed to do. This
theory's own header asserts the theory is ground truth and the C code
must match it, but the theory does not even agree with itself here, so
that framing does not resolve which side (if either) is correct.
Left failing rather than silently reconciled either direction. *)
lemma roll_two_is_rot:
assumes "data_stack vm = 2 # n3 # n2 # n1 # rest"
shows "data_stack (forth_roll vm) = n1 # n3 # n2 # rest"
by (simp add: forth_roll_def assms)
oops
lemma roll_underflow:
assumes "data_stack vm = []"