src/HOL/Isar_examples/ExprCompiler.thy
changeset 8051 5724bea1da53
parent 8031 826c6222cca2
child 8052 6ae3ca78a558
equal deleted inserted replaced
8050:ad6440cd84be 8051:5724bea1da53
   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;