104 "compile (Constant c) = [Const c]" |
104 "compile (Constant c) = [Const c]" |
105 "compile (Binop f e1 e2) = compile e2 @ compile e1 @ [Apply f]"; |
105 "compile (Binop f e1 e2) = compile e2 @ compile e1 @ [Apply f]"; |
106 |
106 |
107 |
107 |
108 text {* |
108 text {* |
109 The main result of this development is the correctness theorem for |
109 The main result of this development is the correctness theorem for |
110 $\idt{compile}$. We first establish some lemmas about $\idt{exec}$. |
110 $\idt{compile}$. We first establish a lemma about $\idt{exec}$ and |
|
111 list append. |
111 *}; |
112 *}; |
112 |
113 |
113 lemma exec_append: |
114 lemma exec_append: |
114 "ALL stack. exec (xs @ ys) stack env = |
115 "ALL stack. exec (xs @ ys) stack env = |
115 exec ys (exec xs stack env) env" (is "?P xs"); |
116 exec ys (exec xs stack env) env" (is "?P xs"); |
116 proof (induct ?P xs type: list); |
117 proof (induct ?P xs type: list); |
117 show "?P []"; by simp; |
118 show "?P []"; by simp; |
118 |
119 |
119 fix x xs; |
120 fix x xs; assume "?P xs"; |
120 assume "?P xs"; |
|
121 show "?P (x # xs)" (is "?Q x"); |
121 show "?P (x # xs)" (is "?Q x"); |
122 proof (induct ?Q x type: instr); |
122 proof (induct ?Q x type: instr); |
123 fix val; show "?Q (Const val)"; by (simp!); |
123 fix val; show "?Q (Const val)"; by (simp!); |
124 next; |
124 next; |
125 fix adr; show "?Q (Load adr)"; by (simp!); |
125 fix adr; show "?Q (Load adr)"; by (simp!); |
126 next; |
126 next; |
127 fix fun; show "?Q (Apply fun)"; by (simp!); |
127 fix fun; show "?Q (Apply fun)"; by (simp!); |
128 qed; |
128 qed; |
129 qed; |
129 qed; |
130 |
130 |
131 lemma exec_compile: |
131 |
132 "ALL stack. exec (compile e) stack env = |
132 theorem correctness: "execute (compile e) env = eval e env"; |
|
133 proof -; |
|
134 have "ALL stack. exec (compile e) stack env = |
133 eval e env # stack" (is "?P e"); |
135 eval e env # stack" (is "?P e"); |
134 proof (induct ?P e type: expr); |
136 proof (induct ?P e type: expr); |
135 fix adr; show "?P (Variable adr)"; by (simp!); |
137 fix adr; show "?P (Variable adr)"; by (simp!); |
136 next; |
138 next; |
137 fix val; show "?P (Constant val)"; by (simp!); |
139 fix val; show "?P (Constant val)"; by (simp!); |
138 next; |
140 next; |
139 fix fun e1 e2; assume "?P e1" "?P e2"; show "?P (Binop fun e1 e2)"; |
141 fix fun e1 e2; assume "?P e1" "?P e2"; show "?P (Binop fun e1 e2)"; |
140 by (simp! add: exec_append); |
142 by (simp! add: exec_append); |
141 qed; |
143 qed; |
142 |
144 thus ?thesis; by (simp add: execute_def); |
143 |
145 qed; |
144 text {* Main theorem ahead. *}; |
146 |
|
147 |
|
148 text {* |
|
149 \bigskip In the proofs above, the \name{simp} method does quite a lot |
|
150 of work behind the scenes (mostly ``functional program execution''). |
|
151 Subsequently, the same reasoning is elaborated in detail --- at most |
|
152 one recursive function definition is used at a time. Thus we get a |
|
153 better idea of what is actually going on. |
|
154 *}; |
|
155 |
|
156 lemma exec_append: |
|
157 "ALL stack. exec (xs @ ys) stack env |
|
158 = exec ys (exec xs stack env) env" (is "?P xs"); |
|
159 proof (induct ?P xs); |
|
160 show "?P []" (is "ALL s. ?Q s"); |
|
161 proof; |
|
162 fix s; have "exec ([] @ ys) s env = exec ys s env"; by simp; |
|
163 also; have "... = exec ys (exec [] s env) env"; by simp; |
|
164 finally; show "?Q s"; .; |
|
165 qed; |
|
166 fix x xs; assume hyp: "?P xs"; |
|
167 show "?P (x # xs)"; |
|
168 proof (induct x); |
|
169 fix val; |
|
170 show "?P (Const val # xs)" (is "ALL s. ?Q s"); |
|
171 proof; |
|
172 fix s; |
|
173 have "exec ((Const val # xs) @ ys) s env = exec (Const val # xs @ ys) s env"; |
|
174 by simp; |
|
175 also; have "... = exec (xs @ ys) (val # s) env"; by simp; |
|
176 also; from hyp; have "... = exec ys (exec xs (val # s) env) env"; ..; |
|
177 also; have "... = exec ys (exec (Const val # xs) s env) env"; by simp; |
|
178 finally; show "?Q s"; .; |
|
179 qed; |
|
180 next; |
|
181 fix adr; from hyp; show "?P (Load adr # xs)"; by simp -- {* same as above *}; |
|
182 next; |
|
183 fix fun; |
|
184 show "?P (Apply fun # xs)" (is "ALL s. ?Q s"); |
|
185 proof; |
|
186 fix s; |
|
187 have "exec ((Apply fun # xs) @ ys) s env = exec (Apply fun # xs @ ys) s env"; |
|
188 by simp; |
|
189 also; have "... = exec (xs @ ys) (fun (hd s) (hd (tl s)) # (tl (tl s))) env"; |
|
190 by simp; |
|
191 also; from hyp; have "... |
|
192 = exec ys (exec xs (fun (hd s) (hd (tl s)) # tl (tl s)) env) env"; ..; |
|
193 also; have "... = exec ys (exec (Apply fun # xs) s env) env"; by simp; |
|
194 finally; show "?Q s"; .; |
|
195 qed; |
|
196 qed; |
|
197 qed; |
145 |
198 |
146 theorem correctness: "execute (compile e) env = eval e env"; |
199 theorem correctness: "execute (compile e) env = eval e env"; |
147 by (simp add: execute_def exec_compile); |
200 proof -; |
|
201 have exec_compile: |
|
202 "ALL stack. exec (compile e) stack env = eval e env # stack" (is "?P e"); |
|
203 proof (induct e); |
|
204 fix adr; show "?P (Variable adr)" (is "ALL s. ?Q s"); |
|
205 proof; |
|
206 fix s; |
|
207 have "exec (compile (Variable adr)) s env = exec [Load adr] s env"; by simp; |
|
208 also; have "... = env adr # s"; by simp; |
|
209 also; have "env adr = eval (Variable adr) env"; by simp; |
|
210 finally; show "?Q s"; .; |
|
211 qed; |
|
212 next; |
|
213 fix val; show "?P (Constant val)"; by simp -- {* same as above *}; |
|
214 next; |
|
215 fix fun e1 e2; assume hyp1: "?P e1" and hyp2: "?P e2"; |
|
216 show "?P (Binop fun e1 e2)" (is "ALL s. ?Q s"); |
|
217 proof; |
|
218 fix s; have "exec (compile (Binop fun e1 e2)) s env |
|
219 = exec (compile e2 @ compile e1 @ [Apply fun]) s env"; by simp; |
|
220 also; have "... |
|
221 = exec [Apply fun] (exec (compile e1) (exec (compile e2) s env) env) env"; |
|
222 by (simp only: exec_append); |
|
223 also; from hyp2; have "exec (compile e2) s env = eval e2 env # s"; ..; |
|
224 also; from hyp1; have "exec (compile e1) ... env = eval e1 env # ..."; ..; |
|
225 also; have "exec [Apply fun] ... env |
|
226 = fun (hd ...) (hd (tl ...)) # (tl (tl ...))"; by simp; |
|
227 also; have "... = fun (eval e1 env) (eval e2 env) # s"; by simp; |
|
228 also; have "fun (eval e1 env) (eval e2 env) = eval (Binop fun e1 e2) env"; |
|
229 by simp; |
|
230 finally; show "?Q s"; .; |
|
231 qed; |
|
232 qed; |
|
233 |
|
234 have "execute (compile e) env = hd (exec (compile e) [] env)"; |
|
235 by (simp add: execute_def); |
|
236 also; from exec_compile; have "exec (compile e) [] env = [eval e env]"; ..; |
|
237 also; have "hd ... = eval e env"; by simp; |
|
238 finally; show ?thesis; .; |
|
239 qed; |
148 |
240 |
149 end; |
241 end; |