(* Title: A Shorter Compiler Correctness Proof for Language IMP Author:PasqualeNoce SoftwareEngineeratHIDGlobal,Italy pasqualedotnocedotlavoroatgmaildotcom pasqualedotnoceathidglobaldotcom
*)
section"Compiler correctness"
theory Compiler2 imports Compiler begin
subsection"Preliminary definitions and lemmas"
text‹
everything is ready for the compiler correctness proof. First, two predicates are introduced,
{text execl} and @{text execl_all}, both taking as inputs a program, i.e. a list of instructions,
{text P} and a list of program configurations @{text cfs}, and respectively denoted using notations
{text "P ⊨ cfs"} and @{text "P ⊨ cfs◻"}. In more detail:
▪ @{text "P ⊨ cfs"} means that program @{text P} \emph{may} transform each configuration within
{text cfs} into the subsequent one, if any (word \emph{may} reflects the fact that programs can be
-deterministic in this case study). \Thus, @{text execl} formalizes the notion of a \emph{small-step} program execution.
▪ @{text "P ⊨ cfs◻"} reinforces @{text "P ⊨ cfs"} by additionally requiring that @{text cfs} be
, the initial program counter be zero (viz. execution starts from the first instruction in
{text P}), and the final program counter falls outside @{text P} (viz. execution terminates). \Thus, @{text execl_all} formalizes the notion of a \emph{complete small-step} program execution,
that assumptions @{text "acomp a ⊨ cfs◻"}, @{text "bcomp x ⊨ cfs◻"}, @{text "ccomp c ⊨ cfs◻"}
be used in the compiler correctness proofs for arithmetic/boolean expressions and commands.
, predicates @{text apred}, @{text bpred}, and @{text cpred} are defined to capture the link
the initial and the final configuration upon the execution of an arithmetic expression, a
expression, and a whole program, respectively, and abbreviation @{text off} is introduced as
commodity to shorten the subsequent formal text.
null ›
fun execl :: "instr list ==> config list ==> bool" (infix‹⊨›55) where "P ⊨ cf # cf' # cfs = (P ⊨ cf → cf' ∧ P ⊨ cf' # cfs)" | "P ⊨ _ = True"
abbreviation off :: "instr list ==> config ==> config"where "off P cf ≡ (fst cf - size P, snd cf)"
text‹
null
, some lemmas about @{const [source] execl} and @{const execl_all} are proven. In more detail,
a program @{text P} and a list of configurations @{text cfs} such that @{prop "P ⊨ cfs"}:
▪ Lemma @{text execl_next} states that for any configuration in @{text cfs} but the last one, the
configuration must result from the execution of the referenced instruction of @{text P}
that configuration. \Thus, @{text execl_next} permits to reproduce the execution of a single instruction.
▪ Lemma @{text execl_last} states that a configuration in @{text cfs} whose program counter falls
@{text P} must be the last one in @{text cfs}. \Thus, @{text execl_last} permits to infer the completion of program execution.
▪ Lemma @{text execl_drop} states that @{prop "P ⊨ drop n cfs"} for any natural number @{text n},
will be used to prove compiler correctness for loops by induction over the length of the list of
@{text cfs}.
, some other lemmas enabling to prove compiler correctness automatically for constructors
{const N}, @{const V} (arithmetic expressions), @{const Bc} (boolean expressions) and @{const SKIP}
commands) are also proven.
null ›
lemma iexec_offset_aux: "(i :: int) + 1 - j = i - j + 1 ∧ i + j - k + 1 = i - k + j + 1" by simp
lemma iexec_offset [intro]: "(ins, pc, s, stk) ↦ (pc', s', stk') ==> (ins, pc - i, s, stk) ↦ (pc' - i, s', stk')" by (erule iexec.cases, auto simp: iexec_offset_aux)
lemma execl_next: "[P ⊨ cfs; k < length cfs; k ≠ length cfs - 1]==> (P !! fst (cfs ! k), cfs ! k) ↦ cfs ! Suc k" by (induction cfs arbitrary: k rule: execl.induct, auto
simp: nth_Cons exec1_def split: nat.split)
lemma execl_last: "[P ⊨ cfs; k < length cfs; fst (cfs ! k) ∉ {0..<size P}]==> length cfs - 1 = k" by (induction cfs arbitrary: k rule: execl.induct, auto
simp: nth_Cons exec1_def split: nat.split_asm)
lemma execl_drop: "P ⊨ cfs ==> P ⊨ drop n cfs" by (induction cfs arbitrary: n rule: execl.induct,
simp_all add: drop_Cons split: nat.split)
, lemma @{text execl_all_sub} is proven. It states that, if @{prop "P @ P' x @ P'' ⊨ cfs◻"},
@{text cf} within @{text cfs} refers to the start of program @{text "P' x"}, and the
and the final configuration in every complete execution of @{text "P' x"} satisfy predicate
{text "Q x"}, then there exists a configuration @{text cf'} in @{text cfs} such that @{text cf} and
{text cf'} satisfy @{text "Q x"}. \Thus, this lemma permits to reproduce the execution of a subprogram, particularly:
▪ a compiled arithmetic expression @{text a}, where @{prop "Q = apred"} and @{prop "x = a"},
▪ a compiled boolean expression @{text b}, where @{prop "Q = bpred"} and @{prop "x = (b, f, i)"}
given a flag @{text f} and a jump offset @{text i}), and
▪ a compiled command @{text c}, where @{prop "Q = cpred"} and @{prop "x = c"}.
, lemma @{text execl_all_sub2} is derived from @{text execl_all_sub} to enable a shorter
execution of two consecutive subprograms.
null ›
lemma execl_sub_aux: "[∧m n. ∀k ∈ {m..<n}. Q P' (((pc, s, stk) # cfs) ! k) ==> P' ⊨ map (off P) (case m of 0 ==> (pc, s, stk) # take n cfs | Suc m ==> F cfs m n); ∀k ∈ {m..<n+m+length cfs'}. Q P' ((cfs' @ (pc, s, stk) # cfs) ! (k-m))]==> P' ⊨ (pc - size P, s, stk) # map (off P) (take n cfs)"
(is"[∧_ _. ∀k ∈ _. Q P' (?F k) ==> _; ∀k ∈ ?A. Q P' (?G k)]==> _") by (subgoal_tac "∀k ∈ {0..<n}. Q P' (?F k)", fastforce, subgoal_tac "∀k ∈ {0..<n}. k + m + length cfs' ∈ ?A ∧ ?F k = ?G (k + m + length cfs')",
fastforce, simp add: nth_append)
lemma execl_sub: "[P @ P' @ P'' ⊨ cfs; ∀k ∈ {m..<n}. size P ≤ fst (cfs ! k) ∧ fst (cfs ! k) - size P < size P']==> P' ⊨ map (off P) (drop m (take (Suc n) cfs))"
(is"[_; ∀k ∈ _. ?P P' cfs k]==> P' ⊨ map _ (?F cfs m (Suc n))") proof (induction cfs arbitrary: m n rule: execl.induct [of _ P'], auto
simp: take_Cons drop_Cons exec1_def split: nat.split, force, force, force,
erule execl_sub_aux [where m = 0], subst append_Cons [of _ "[]"], simp,
erule execl_sub_aux [where m = "Suc 0"and cfs' = "[]"], simp) fix P' pc s stk cfs m n let ?cf = "(pc, s, stk) :: config" assume"∧m n. ∀k ∈ {m..<n}. ?P P' (?cf # cfs) k ==> P' ⊨ map (off P) (case m of 0 ==> ?cf # take n cfs | Suc m ==> ?F cfs m n)" moreoverassume"∀k ∈ {Suc (Suc m)..<Suc n}. ?P P' cfs (k - Suc (Suc 0))" hence"∀k ∈ {Suc m..<n}. ?P P' (?cf # cfs) k" by force ultimatelyshow"P' ⊨ map (off P) (?F cfs m n)" by fastforce qed
lemma execl_all_sub [rule_format]: assumes
A: "P @ P' x @ P'' ⊨ cfs◻"and
B: "k < length cfs"and
C: "fst (cfs ! k) = size P"and
D: "∀cfs. P' x ⊨ cfs◻⟶ Q x (cfs ! 0) (cfs ! (length cfs - 1))" shows"∃k' < length cfs. Q x (off P (cfs ! k)) (off P (cfs ! k'))" proof - let ?P = "λk. size P ≤ fst (cfs ! k) ∧ fst (cfs ! k) - size P < size (P' x)" let ?A = "{k'. k' ∈ {k..<length cfs} ∧¬ ?P k'}" have E: "Min ?A ∈ ?A" using A and B by (rule_tac Min_in, simp_all add: execl_all_def,
rule_tac exI [of _ "length cfs - 1"], auto) hence"map (off P) (drop k (take (Suc (Min ?A)) cfs)) ! 0 = off P (cfs ! k)"
(is"?cfs ! _ = _") by auto moreoverhave"length cfs ≤ Suc (Min ?A) ⟶ Min ?A = length cfs - 1" using E by auto with A and B and E have F: "?cfs ! (length ?cfs - 1) = off P (cfs ! Min ?A)" by (subst nth_map, auto simp: min_def execl_all_def, arith) hence"?cfs ≠ [] ∧ fst (?cfs ! (length ?cfs - 1)) ∉ {0..<size (P' x)}" using E by (auto simp: min_def) moreoverhave"¬ (∃k'. k' ∈ {k'. k' ∈ {k..<Min ?A} ∧¬ ?P k'})" by (rule notI, erule exE, frule rev_subsetD [of _ _ ?A], rule subsetI,
insert E, simp, subgoal_tac "finite ?A", drule Min_le, force+) hence"P' x ⊨ ?cfs" using A by (subst (asm) execl_all_def, rule_tac execl_sub, blast+) ultimatelyhave"Q x (?cfs ! 0) (?cfs ! (length ?cfs - 1))" using C and D by (auto simp: execl_all_def) thus ?thesis using E and F by (rule_tac exI [of _ "Min ?A"], auto) qed
lemma execl_all_sub2: assumes
A: "P x @ P' x' @ P'' ⊨ cfs◻"
(is"?P ⊨ _◻") and
B: "∧cfs. P x ⊨ cfs◻==> (λ(pc, s, stk) (pc', s', stk'). pc' = pc + size (P x) + I s ∧ Q s s' ∧ stk' = F s stk) (cfs ! 0) (cfs ! (length cfs - 1))"
(is"∧cfs. _ ==> ?Q x (cfs ! 0) (cfs ! (length cfs - 1))") and
C: "∧cfs. P' x' ⊨ cfs◻==> (λ(pc, s, stk) (pc', s', stk'). pc' = pc + size (P' x') + I' s ∧ Q' s s' ∧ stk' = F' s stk) (cfs ! 0) (cfs ! (length cfs - 1))"
(is"∧cfs. _ ==> ?Q' x' (cfs ! 0) (cfs ! (length cfs - 1))") and
D: "I (fst (snd (cfs ! 0))) = 0" shows"∃k < length cfs. ∃t. (λ(pc, s, stk) (pc', s', stk'). pc = 0 ∧ pc' = size (P x) + size (P' x') + I' t ∧ Q s t ∧ Q' t s' ∧ stk' = F' t (F s stk)) (cfs ! 0) (cfs ! k)" by (subgoal_tac "[] @ ?P ⊨ cfs◻", drule execl_all_sub [where k = 0and Q = ?Q],
insert A B, (clarsimp simp: execl_all_def)+, insert A C D, drule execl_all_sub
[where Q = ?Q'], simp+, clarify, rule exI, rule conjI, simp, rule exI, auto)
subsection"Main theorem"
text‹
is time to prove compiler correctness. First, lemmas @{text acomp_acomp}, @{text bcomp_bcomp} are
from @{thm [source] execl_all_sub2} to reproduce the execution of two consecutive compiled
expressions (possibly generated by both @{const acomp} and @{const bcomp}) and boolean
(possibly generated by @{const bcomp}), respectively. Subsequently, the correctness of
{const acomp} and @{const bcomp} is proven in lemmas @{text acomp_correct}, @{text bcomp_correct}.
null ›
lemma acomp_acomp: "[acomp a1 @ acomp a2 @ P ⊨ cfs◻; ∧cfs. acomp a1⊨ cfs◻==> apred a1 (cfs ! 0) (cfs ! (length cfs - 1)); ∧cfs. acomp a2⊨ cfs◻==> apred a2 (cfs ! 0) (cfs ! (length cfs - 1))]==> case cfs ! 0 of (pc, s, stk) ==> pc = 0 ∧ (∃k < length cfs. cfs ! k = (size (acomp a1 @ acomp a2), s, aval a2 s # aval a1 s # stk))" by (drule execl_all_sub2 [where I = "λs. 0"and I' = "λs. 0"and Q = "λs s'. s' = s" and Q' = "λs s'. s' = s"and F = "λs stk. aval a1 s # stk" and F' = "λs stk. aval a2 s # stk"], auto simp: apred_def)
lemma bcomp_bcomp: "[bcomp (b1, f1, i1) @ bcomp (b2, f2, i2) ⊨ cfs◻; ∧cfs. bcomp (b1, f1, i1) ⊨ cfs◻==> bpred (b1, f1, i1) (cfs ! 0) (cfs ! (length cfs - 1)); ∧cfs. bcomp (b2, f2, i2) ⊨ cfs◻==> bpred (b2, f2, i2) (cfs ! 0) (cfs ! (length cfs - 1))]==> case cfs ! 0 of (pc, s, stk) ==> pc = 0 ∧ (bval b1 s ≠ f1⟶ (∃k < length cfs. cfs ! k = (size (bcomp (b1, f1, i1) @ bcomp (b2, f2, i2)) + (if bval b2 s = f2 then i2 else 0), s, stk)))" by (clarify, rule conjI, simp add: execl_all_def, rule impI, subst (asm) append_Nil2
[symmetric], drule execl_all_sub2 [where I = "λs. if bval b1 s = f1 then i1 else 0" and I' = "λs. if bval b2 s = f2 then i2 else 0"and Q = "λs s'. s' = s" and Q' = "λs s'. s' = s"and F = "λs stk. stk"and F' = "λs stk. stk"],
auto simp: bpred_def)
lemma acomp_correct [simplified, intro]: "acomp a ⊨ cfs◻==> apred a (cfs ! 0) (cfs ! (length cfs - 1))" proof (induction a arbitrary: cfs, simp_all, frule_tac [3] acomp_acomp, auto) fix a1 a2 cfs s stk k assume A: "acomp a1 @ acomp a2 @ [ADD] ⊨ cfs◻"
(is"?ca1 @ ?ca2 @ ?i ⊨ _◻") assume B: "k < length cfs"and
C: "cfs ! k = (size ?ca1 + size ?ca2, s, aval a2 s # aval a1 s # stk)" hence"cfs ! Suc k = (size (?ca1 @ ?ca2 @ ?i), s, aval (Plus a1 a2) s # stk)" using A by (insert execl_next [of "?ca1 @ ?ca2 @ ?i" cfs k],
simp add: execl_all_def, drule_tac impI, auto) thus"apred (Plus a1 a2) (0, s, stk) (cfs ! (length cfs - Suc 0))" using A and B and C by (insert execl_last [of "?ca1 @ ?ca2 @ ?i" cfs "Suc k"],
simp add: execl_all_def apred_def, drule_tac impI, auto) qed
lemma bcomp_correct [simplified, intro]: "[bcomp x ⊨ cfs◻; 0 ≤ snd (snd x)]==> bpred x (cfs ! 0) (cfs ! (length cfs - 1))" proof (induction x arbitrary: cfs rule: bcomp.induct, simp_all add: Let_def,
frule_tac [4] acomp_acomp, frule_tac [3] bcomp_bcomp, auto, force simp: bpred_def) fix b1 b2 f i cfs s stk assume A: "bcomp (b1, False, size (bcomp (b2, f, i)) + (if f then 0 else i)) @ bcomp (b2, f, i) ⊨ cfs◻"
(is"bcomp (_, _, ?n + ?i) @ ?cb ⊨ _◻") moreoverassume B: "cfs ! 0 = (0, s, stk)"and "∧cb cfs. [cb = ?cb; bcomp (b1, False, ?n + ?i) ⊨ cfs◻]==> bpred (b1, False, ?n + ?i) (cfs ! 0) (cfs ! (length cfs - Suc 0))" ultimatelyhave"∃k < length cfs. bpred (b1, False, ?n + ?i) (off [] (cfs ! 0)) (off [] (cfs ! k))" by (rule_tac execl_all_sub, auto simp: execl_all_def) moreoverassume C: "¬ bval b1 s" ultimatelyobtain k where D: "k < length cfs"and
E: "cfs ! k = (size (bcomp (b1, False, ?n + ?i)) + ?n + ?i, s, stk)" using B by (auto simp: bpred_def) assume"0 ≤ i" thus"bpred (And b1 b2, f, i) (0, s, stk) (cfs ! (length cfs - Suc 0))" using A and C and D and E by (insert execl_last, auto simp:
execl_all_def bpred_def Let_def) next fix b1 b2 f i cfs s stk k assume A: "bcomp (b1, False, size (bcomp (b2, f, i)) + (if f then 0 else i)) @ bcomp (b2, f, i) ⊨ cfs◻"
(is"?cb1 @ ?cb2⊨ _◻") assume"k < length cfs"and"0 ≤ i"and"bval b1 s"and "cfs ! k = (size ?cb1 + size ?cb2 + (if bval b2 s = f then i else 0), s, stk)" thus"bpred (And b1 b2, f, i) (0, s, stk) (cfs ! (length cfs - Suc 0))" using A by (insert execl_last, auto simp: execl_all_def bpred_def Let_def) next fix a1 a2 f i cfs s stk k assume A: "acomp a1 @ acomp a2 @ (if f then [JMPLESS i] else [JMPGE i]) ⊨ cfs◻"
(is"?ca1 @ ?ca2 @ ?i ⊨ _◻") assume B: "k < length cfs"and
C: "cfs ! k = (size ?ca1 + size ?ca2, s, aval a2 s # aval a1 s # stk)" hence D: "cfs ! Suc k = (size (?ca1 @ ?ca2 @ ?i) + (if bval (Less a1 a2) s = f then i else 0), s, stk)" using A by (insert execl_next [of "?ca1 @ ?ca2 @ ?i" cfs k],
simp add: execl_all_def, drule_tac impI, auto split: if_split_asm) assume"0 ≤ i" with A and B and C and D have"length cfs - 1 = Suc k" by (rule_tac execl_last, auto simp: execl_all_def, simp split: if_split_asm) thus"bpred (Less a1 a2, f, i) (0, s, stk) (cfs ! (length cfs - Suc 0))" using D by (simp add: bpred_def) qed
text‹
null
, lemmas @{text bcomp_ccomp}, @{text ccomp_ccomp} are derived to reproduce the execution of a
boolean expression followed by a compiled command and of two consecutive compiled commands,
(possibly generated by @{const ccomp}). Then, compiler correctness for loops and for
commands is proven in lemmas @{text while_correct} and @{text ccomp_correct}, respectively by
over the length of the list of configurations and by structural induction over commands.
null ›
lemma bcomp_ccomp: "[bcomp (b, f, i) @ ccomp c @ P ⊨ cfs◻; 0 ≤ i; ∧cfs. ccomp c ⊨ cfs◻==> cpred c (cfs ! 0) (cfs ! (length cfs - 1))]==> case cfs ! 0 of (pc, s, stk) ==> pc = 0 ∧ (bval b s ≠ f ⟶ (∃k < length cfs. case cfs ! k of (pc', s', stk') ==> pc' = size (bcomp (b, f, i) @ ccomp c) ∧ (c, s) ==> s' ∧ stk' = stk))" by (clarify, rule conjI, simp add: execl_all_def, rule impI, drule execl_all_sub2
[where I = "λs. if bval b s = f then i else 0"and I' = "λs. 0" and Q = "λs s'. s' = s"and Q' = "λs s'. (c, s) ==> s'"and F = "λs stk. stk" and F' = "λs stk. stk"], insert bcomp_correct [of "(b, f, i)"],
auto simp: bpred_def cpred_def)
lemma ccomp_ccomp: "[ccomp c1 @ ccomp c2⊨ cfs◻; ∧cfs. ccomp c1⊨ cfs◻==> cpred c1 (cfs ! 0) (cfs ! (length cfs - 1)); ∧cfs. ccomp c2⊨ cfs◻==> cpred c2 (cfs ! 0) (cfs ! (length cfs - 1))]==> case cfs ! 0 of (pc, s, stk) ==> pc = 0 ∧ (∃k < length cfs. ∃t. case cfs ! k of (pc', s', stk') ==> pc' = size (ccomp c1 @ ccomp c2) ∧ (c1, s) ==> t ∧ (c2, t) ==> s' ∧ stk' = stk)" by (subst (asm) append_Nil2 [symmetric], drule execl_all_sub2 [where I = "λs. 0" and I' = "λs. 0"and Q = "λs s'. (c1, s) ==> s'"and Q' = "λs s'. (c2, s) ==> s'" and F = "λs stk. stk"and F' = "λs stk. stk"], auto simp: cpred_def, force)
lemma while_correct [simplified, intro]: "[bcomp (b, False, size (ccomp c) + 1) @ ccomp c @ [JMP (- (size (bcomp (b, False, size (ccomp c) + 1) @ ccomp c) + 1))] ⊨ cfs◻; ∧cfs. ccomp c ⊨ cfs◻==> cpred c (cfs ! 0) (cfs ! (length cfs - 1))]==> cpred (WHILE b DO c) (cfs ! 0) (cfs ! (length cfs - Suc 0))"
(is"[?cb @ ?cc @ [JMP (- ?n)] ⊨ _◻; ∧_. _ ==> _]==> ?Q cfs") proof (induction cfs rule: length_induct, frule bcomp_ccomp, auto) fix cfs s stk assume A: "?cb @ ?cc @ [JMP (- size ?cb - size ?cc - 1)] ⊨ cfs◻" hence"∃k < length cfs. bpred (b, False, size (ccomp c) + 1) (off [] (cfs ! 0)) (off [] (cfs ! k))" by (rule_tac execl_all_sub, auto simp: execl_all_def) moreoverassume B: "¬ bval b s"and"cfs ! 0 = (0, s, stk)" ultimatelyobtain k where"k < length cfs"and"cfs ! k = (?n, s, stk)" by (auto simp: bpred_def) thus"cpred (WHILE b DO c) (0, s, stk) (cfs ! (length cfs - Suc 0))" using A and B by (insert execl_last, auto simp: execl_all_def cpred_def Let_def) next fix cfs s s' stk k assume A: "?cb @ ?cc @ [JMP (- size ?cb - size ?cc - 1)] ⊨ cfs◻"
(is"?P ⊨ _◻") assume B: "k < length cfs"and"cfs ! k = (size ?cb + size ?cc, s', stk)" moreoverfrom this have C: "k ≠ length cfs - 1" using A by (rule_tac notI, simp add: execl_all_def) ultimatelyhave D: "cfs ! Suc k = (0, s', stk)" using A by (insert execl_next [of ?P cfs k], auto simp: execl_all_def) moreoverhave E: "Suc k + (length (drop (Suc k) cfs) - 1) = length cfs - 1"
(is"Suc k + (length ?cfs - 1) = _") using B and C by simp ultimatelyhave"?P ⊨ ?cfs◻" using A and B and C by (auto simp: execl_all_def intro: execl_drop) moreoverassume"∀cfs'. length cfs' < length cfs ⟶ ?P ⊨ cfs'◻⟶ ?Q cfs'" hence"length ?cfs < length cfs ⟶ ?P ⊨ ?cfs◻⟶ ?Q ?cfs" .. ultimatelyhave"cpred (WHILE b DO c) (cfs ! Suc k) (cfs ! (length cfs - 1))" using B and C and E by simp moreoverassume"bval b s"and"(c, s) ==> s'" ultimatelyshow"cpred (WHILE b DO c) (0, s, stk) (cfs ! (length cfs - Suc 0))" using D by (auto simp: cpred_def) qed
lemma ccomp_correct: "ccomp c ⊨ cfs◻==> cpred c (cfs ! 0) (cfs ! (length cfs - 1))" proof (induction c arbitrary: cfs, simp_all add: Let_def, frule_tac [4] bcomp_ccomp,
frule_tac [3] ccomp_ccomp, auto) fix a x cfs assume A: "acomp a @ [STORE x] ⊨ cfs◻" hence"∃k < length cfs. apred a (off [] (cfs ! 0)) (off [] (cfs ! k))" by (rule_tac execl_all_sub, auto simp: execl_all_def) moreoverobtain s stk where B: "cfs ! 0 = (0, s, stk)" using A by (cases "cfs ! 0", simp add: execl_all_def) ultimatelyobtain k where C: "k < length cfs"and
D: "cfs ! k = (size (acomp a), s, aval a s # stk)" by (auto simp: apred_def) hence"cfs ! Suc k = (size (acomp a) + 1, s(x := aval a s), stk)" using A by (insert execl_next [of "acomp a @ [STORE x]" cfs k],
simp add: execl_all_def, drule_tac impI, auto) thus"cpred (x ::= a) (cfs ! 0) (cfs ! (length cfs - Suc 0))" using A and B and C and D by (insert execl_last [of "acomp a @ [STORE x]"
cfs "Suc k"], simp add: execl_all_def cpred_def, drule_tac impI, auto) next fix c1 c2 cfs s s' t stk k assume"ccomp c1 @ ccomp c2⊨ cfs◻"and"k < length cfs"and "cfs ! k = (size (ccomp c1) + size (ccomp c2), s', stk)" moreoverassume"(c1, s) ==> t"and"(c2, t) ==> s'" ultimatelyshow"cpred (c1;; c2) (0, s, stk) (cfs ! (length cfs - Suc 0))" by (insert execl_last, auto simp: execl_all_def cpred_def) next fix b c1 c2 cfs s stk assume A: "bcomp (b, False, size (ccomp c1) + 1) @ ccomp c1 @ JMP (size (ccomp c2)) # ccomp c2⊨ cfs◻"
(is"bcomp ?x @ ?cc1 @ _ # ?cc2⊨ _◻") let ?P = "bcomp ?x @ ?cc1 @ [JMP (size ?cc2)]" have"∃k < length cfs. bpred ?x (off [] (cfs ! 0)) (off [] (cfs ! k))" using A by (rule_tac execl_all_sub, auto simp: execl_all_def) moreoverassume B: "¬ bval b s"and"cfs ! 0 = (0, s, stk)" ultimatelyobtain k where C: "k < length cfs"and D: "cfs ! k = (size ?P, s, stk)" by (force simp: bpred_def) assume"∧cfs. ?cc2⊨ cfs◻==> cpred c2 (cfs ! 0) (cfs ! (length cfs - Suc 0))" hence"∃k' < length cfs. cpred c2 (off ?P (cfs ! k)) (off ?P (cfs ! k'))" using A and C and D by (rule_tac execl_all_sub [where P'' = "[]"], auto) thenobtain k' where"k' < length cfs"and"case cfs ! k' of (pc', s', stk') ==> pc' = size (?P @ ?cc2) ∧ (c2, s) ==> s' ∧ stk' = stk" using D by (fastforce simp: cpred_def) thus"cpred (IF b THEN c1 ELSE c2) (0, s, stk) (cfs ! (length cfs - Suc 0))" using A and B by (insert execl_last, auto simp: execl_all_def cpred_def Let_def) next fix b c1 c2 cfs s s' stk k assume A: "bcomp (b, False, size (ccomp c1) + 1) @ ccomp c1 @ JMP (size (ccomp c2)) # ccomp c2⊨ cfs◻"
(is"?cb @ ?cc1 @ ?i # ?cc2⊨ _◻") assume B: "k < length cfs"and C: "cfs ! k = (size ?cb + size ?cc1, s', stk)" hence D: "cfs ! Suc k = (size (?cb @ ?cc1 @ ?i # ?cc2), s', stk)"
(is"_ = (size ?P, _, _)") using A by (insert execl_next [of ?P cfs k], simp add: execl_all_def,
drule_tac impI, auto) assume"bval b s"and"(c1, s) ==> s'" thus"cpred (IF b THEN c1 ELSE c2) (0, s, stk) (cfs ! (length cfs - Suc 0))" using A and B and C and D by (insert execl_last [of ?P cfs "Suc k"],
simp add: execl_all_def cpred_def Let_def, drule_tac impI, auto) next fix c1 c2 cfs assume A: "JMPND (size (ccomp c1) + 1) # ccomp c1 @ JMP (size (ccomp c2)) # ccomp c2⊨ cfs◻"
(is"JMPND (?n1 + 1) # ?cc1 @ JMP ?n2 # ?cc2⊨ _◻") let ?P = "JMPND (?n1 + 1) # ?cc1 @ [JMP ?n2]" assume
B: "∧cfs. ?cc1⊨ cfs◻==> cpred c1 (cfs ! 0) (cfs ! (length cfs - Suc 0))"and
C: "∧cfs. ?cc2⊨ cfs◻==> cpred c2 (cfs ! 0) (cfs ! (length cfs - Suc 0))" from A obtain s stk where D: "cfs ! 0 = (0, s, stk)" by (cases "cfs ! 0", simp add: execl_all_def) with A have"cfs ! 1 = (1, s, stk) ∨ cfs ! 1 = (?n1 + 2, s, stk)" by (insert execl_next [of "?P @ ?cc2" cfs 0], simp add: execl_all_def,
drule_tac impI, auto) moreover { assume E: "cfs ! 1 = (1, s, stk)" hence"∃k < length cfs. cpred c1 (off [hd ?P] (cfs ! 1)) (off [hd ?P] (cfs ! k))" using A and B by (rule_tac execl_all_sub, auto simp: execl_all_def) thenobtain k where"k < length cfs"and"case cfs ! k of (pc', s', stk') ==> pc' = ?n1 + 1 ∧ (c1, s) ==> s' ∧ stk' = stk" using E by (fastforce simp: cpred_def) moreoverfrom this have"case cfs ! Suc k of (pc', s', stk') ==> pc' = ?n1 + ?n2 + 2 ∧ (c1, s) ==> s' ∧ stk' = stk" using A by (insert execl_next [of "?P @ ?cc2" cfs k], simp add: execl_all_def,
drule_tac impI, auto) ultimatelyhave"cpred (c1 OR c2) (cfs ! 0) (cfs ! (length cfs - Suc 0))" using A and D by (insert execl_last [of "?P @ ?cc2" cfs "Suc k"],
simp add: execl_all_def cpred_def split_def Let_def, drule_tac impI, auto)
} moreover { assume E: "cfs ! 1 = (?n1 + 2, s, stk)" with A and C have"∃k<length cfs. cpred c2 (off ?P (cfs!1)) (off ?P (cfs!k))" by (rule_tac execl_all_sub [where P'' = "[]"], auto simp: execl_all_def) thenobtain k where"k < length cfs"and"case cfs ! k of (pc', s', stk') ==> pc' = ?n1 + ?n2 + 2 ∧ (c2, s) ==> s' ∧ stk' = stk" using E by (fastforce simp: cpred_def) with A and D have"cpred (c1 OR c2) (cfs ! 0) (cfs ! (length cfs - Suc 0))" by (insert execl_last, auto simp: execl_all_def cpred_def Let_def)
} ultimatelyshow"cpred (c1 OR c2) (cfs ! 0) (cfs ! (length cfs - Suc 0))" .. qed
text‹
null
, the main compiler correctness theorem, expressed using predicate @{const exec}, is proven.
, @{prop "P ⊨ cf →* cf'"} is shown to imply the existence of a nonempty list of configurations
{text cfs} such that @{prop "P ⊨ cfs"}, whose initial and final configurations match @{text cf}
@{text cf'}, respectively. Then, the main theorem is derived as a straightforward consequence of
lemma and of the previous lemma @{thm [source] ccomp_correct}.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.