7 |
7 |
8 header {* Correctness of a simple expression compiler *}; |
8 header {* Correctness of a simple expression compiler *}; |
9 |
9 |
10 theory ExprCompiler = Main:; |
10 theory ExprCompiler = Main:; |
11 |
11 |
12 subsection {* Basics *}; |
12 text {* |
|
13 This is a (quite trivial) example of program verification. We model |
|
14 a compiler translating expressions to stack machine instructions, and |
|
15 prove its correctness wrt.\ evaluation semantics. |
|
16 *}; |
|
17 |
|
18 |
|
19 subsection {* Binary operations *}; |
13 |
20 |
14 text {* |
21 text {* |
15 First we define a type abbreviation for binary operations over some |
22 Binary operations are just functions over some type of values. This |
16 type of values. |
23 is both for syntax and semantics, i.e.\ we use a ``shallow |
|
24 embedding''. |
17 *}; |
25 *}; |
18 |
26 |
19 types |
27 types |
20 'val binop = "'val => 'val => 'val"; |
28 'val binop = "'val => 'val => 'val"; |
|
29 |
|
30 |
|
31 subsection {* Expressions *}; |
|
32 |
|
33 text {* |
|
34 The language of expressions is defined as an inductive type, |
|
35 consisting of variables, constants, and binary operations on |
|
36 expressions. |
|
37 *}; |
|
38 |
|
39 datatype ('adr, 'val) expr = |
|
40 Variable 'adr | |
|
41 Constant 'val | |
|
42 Binop "'val binop" "('adr, 'val) expr" "('adr, 'val) expr"; |
|
43 |
|
44 text {* |
|
45 Evaluation (wrt.\ an environment) is defined by primitive recursion |
|
46 over the structure of expressions. |
|
47 *}; |
|
48 |
|
49 consts |
|
50 eval :: "('adr, 'val) expr => ('adr => 'val) => 'val"; |
|
51 |
|
52 primrec |
|
53 "eval (Variable x) env = env x" |
|
54 "eval (Constant c) env = c" |
|
55 "eval (Binop f e1 e2) env = f (eval e1 env) (eval e2 env)"; |
21 |
56 |
22 |
57 |
23 subsection {* Machine *}; |
58 subsection {* Machine *}; |
24 |
59 |
25 text {* |
60 text {* |
52 constdefs |
87 constdefs |
53 execute :: "(('adr, 'val) instr) list => ('adr => 'val) => 'val" |
88 execute :: "(('adr, 'val) instr) list => ('adr => 'val) => 'val" |
54 "execute instrs env == hd (exec instrs [] env)"; |
89 "execute instrs env == hd (exec instrs [] env)"; |
55 |
90 |
56 |
91 |
57 subsection {* Expressions *}; |
|
58 |
|
59 text {* |
|
60 We introduce a simple language of expressions: variables, constants, |
|
61 binary operations. |
|
62 *}; |
|
63 |
|
64 datatype ('adr, 'val) expr = |
|
65 Variable 'adr | |
|
66 Constant 'val | |
|
67 Binop "'val binop" "('adr, 'val) expr" "('adr, 'val) expr"; |
|
68 |
|
69 text {* |
|
70 Evaluation of expressions does not do any unexpected things. |
|
71 *}; |
|
72 |
|
73 consts |
|
74 eval :: "('adr, 'val) expr => ('adr => 'val) => 'val"; |
|
75 |
|
76 primrec |
|
77 "eval (Variable x) env = env x" |
|
78 "eval (Constant c) env = c" |
|
79 "eval (Binop f e1 e2) env = f (eval e1 env) (eval e2 env)"; |
|
80 |
|
81 |
|
82 subsection {* Compiler *}; |
92 subsection {* Compiler *}; |
83 |
93 |
84 text {* |
94 text {* |
85 So we are ready to define the compilation function of expressions to |
95 We are ready to define the compilation function of expressions to |
86 lists of stack machine instructions. |
96 lists of stack machine instructions. |
87 *}; |
97 *}; |
88 |
98 |
89 consts |
99 consts |
90 comp :: "('adr, 'val) expr => (('adr, 'val) instr) list"; |
100 comp :: "('adr, 'val) expr => (('adr, 'val) instr) list"; |