-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathImpCEvalFun.v
361 lines (330 loc) · 10.2 KB
/
ImpCEvalFun.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
From Coq Require Import omega.Omega.
From Coq Require Import Arith.Arith.
From LF Require Import Imp Maps.
(** Here was our first try at an evaluation function for commands,
omitting [WHILE]. *)
Open Scope imp_scope.
Fixpoint ceval_step1 (st : state) (c : com) : state :=
match c with
| SKIP =>
st
| l ::= a1 =>
(l !-> aeval st a1 ; st)
| c1 ;; c2 =>
let st' := ceval_step1 st c1 in
ceval_step1 st' c2
| TEST b THEN c1 ELSE c2 FI =>
if (beval st b)
then ceval_step1 st c1
else ceval_step1 st c2
| WHILE b1 DO c1 END =>
st (* bogus *)
end.
Close Scope imp_scope.
(*然而这样的定义不会被Coq接受,因为任何有可能不会停机的函数都会被Coq拒绝*)
(*一个改进技巧是将一个附加参数传入求值函数中来告诉它要运行多久*)
Open Scope imp_scope.
Fixpoint ceval_step2 (st : state) (c : com) (i : nat) : state :=
match i with
| O => empty_st
| S i' =>
match c with
| SKIP =>
st
| l ::= a1 =>
(l !-> aeval st a1 ; st)
| c1 ;; c2 =>
let st' := ceval_step2 st c1 i' in
ceval_step2 st' c2 i'
| TEST b THEN c1 ELSE c2 FI =>
if (beval st b)
then ceval_step2 st c1 i'
else ceval_step2 st c2 i'
| WHILE b1 DO c1 END =>
if (beval st b1)
then let st' := ceval_step2 st c1 i' in
ceval_step2 st' c i'
else st
end
end.
Close Scope imp_scope.
(*为了区分正常停机和异常停机,将返回参数由state替换为option state*)
Open Scope imp_scope.
Fixpoint ceval_step3 (st : state) (c : com) (i : nat)
: option state :=
match i with
| O => None
| S i' =>
match c with
| SKIP =>
Some st
| l ::= a1 =>
Some (l !-> aeval st a1 ; st)
| c1 ;; c2 =>
match (ceval_step3 st c1 i') with
| Some st' => ceval_step3 st' c2 i'
| None => None
end
| TEST b THEN c1 ELSE c2 FI =>
if (beval st b)
then ceval_step3 st c1 i'
else ceval_step3 st c2 i'
| WHILE b1 DO c1 END =>
if (beval st b1)
then match (ceval_step3 st c1 i') with
| Some st' => ceval_step3 st' c i'
| None => None
end
else Some st
end
end.
Close Scope imp_scope.
Notation "'LETOPT' x <== e1 'IN' e2"
:= (match e1 with
| Some x => e2
| None => None
end)
(right associativity, at level 60).
Open Scope imp_scope.
Fixpoint ceval_step (st : state) (c : com) (i : nat)
: option state :=
match i with
| O => None
| S i' =>
match c with
| SKIP =>
Some st
| l ::= a1 =>
Some (l !-> aeval st a1 ; st)
| c1 ;; c2 =>
LETOPT st' <== ceval_step st c1 i' IN
ceval_step st' c2 i'
| TEST b THEN c1 ELSE c2 FI =>
if (beval st b)
then ceval_step st c1 i'
else ceval_step st c2 i'
| WHILE b1 DO c1 END =>
if (beval st b1)
then LETOPT st' <== ceval_step st c1 i' IN
ceval_step st' c i'
else Some st
end
end.
Close Scope imp_scope.
Definition test_ceval (st:state) (c:com) :=
match ceval_step st c 500 with
| None => None
| Some st => Some (st X, st Y, st Z)
end.
Compute
(test_ceval empty_st
(X ::= 2;;
TEST (X <= 1)
THEN Y ::= 3
ELSE Z ::= 4
FI)).
(* ====>
Some (2, 0, 4) *)
(** **** Exercise: 2 stars, standard, recommended (pup_to_n)
Write an Imp program that sums the numbers from [1] to
[X] (inclusive: [1 + 2 + ... + X]) in the variable [Y]. Make sure
your solution satisfies the test that follows. *)
Definition pup_to_n : com :=
(X ::= X;;
WHILE ~(X = 0)
DO Y ::=Y+X;;
X ::= X-1
END).
Example pup_to_n_1 :
test_ceval (X !-> 5) pup_to_n
= Some (0, 15, 0).
Proof. reflexivity. Qed.
(** **** Exercise: 2 stars, standard, optional (peven) *)
Fixpoint evenb (n:nat) : bool :=
match n with
| O => true
| S O => false
| S (S n') => evenb n'
end.
Definition evenb_or_not : com :=
(X ::= X;;
WHILE ~(X <= 2)
DO X ::= X-2
END;;
TEST (X=0)
THEN Z ::= 0
ELSE Z ::= 1
FI).
Example pup_to_n_2 :
test_ceval (X !-> 5) evenb_or_not
= Some (1, 0, 1).
Proof. reflexivity. Qed.
(* ################################################################# *)
(** * Relational vs. Step-Indexed Evaluation *)
Theorem ceval_step__ceval: forall c st st',
(exists i, ceval_step st c i = Some st') ->
st =[ c ]=> st'.
Proof.
intros c st st' H.
inversion H as [i E].
clear H.
generalize dependent st'.
generalize dependent st.
generalize dependent c.
induction i as [| i' ].
- (* i = 0 -- contradictory *)
intros c st st' H. discriminate H.
- (* i = S i' *)
intros c st st' H.
destruct c;
simpl in H; inversion H; subst; clear H.
+ (* SKIP *) apply E_Skip.
+ (* ::= *) apply E_Ass. reflexivity.
+ (* ;; *)
destruct (ceval_step st c1 i') eqn:Heqr1.
* (* Evaluation of r1 terminates normally *)
apply E_Seq with s.
apply IHi'. rewrite Heqr1. reflexivity.
apply IHi'. simpl in H1. assumption.
* (* Otherwise -- contradiction *)
discriminate H1.
+ (* TEST *)
destruct (beval st b) eqn:Heqr.
* (* r = true *)
apply E_IfTrue. rewrite Heqr. reflexivity.
apply IHi'. assumption.
* (* r = false *)
apply E_IfFalse. rewrite Heqr. reflexivity.
apply IHi'. assumption.
+ (* WHILE *) destruct (beval st b) eqn :Heqr.
* (* r = true *)
destruct (ceval_step st c i') eqn:Heqr1.
{ (* r1 = Some s *)
apply E_WhileTrue with s. rewrite Heqr.
reflexivity.
apply IHi'. rewrite Heqr1. reflexivity.
apply IHi'. simpl in H1. assumption. }
{ (* r1 = None *) discriminate H1. }
* (* r = false *)
injection H1. intros H2. rewrite <- H2.
apply E_WhileFalse. apply Heqr. Qed.
(* Do not modify the following line: *)
Definition manual_grade_for_ceval_step__ceval_inf : option (nat*string) := None.
(** [] *)
Theorem ceval_step_more: forall i1 i2 st st' c,
i1 <= i2 ->
ceval_step st c i1 = Some st' ->
ceval_step st c i2 = Some st'.
Proof.
induction i1 as [|i1']; intros i2 st st' c Hle Hceval.
- (* i1 = 0 *)
simpl in Hceval. discriminate Hceval.
- (* i1 = S i1' *)
destruct i2 as [|i2']. inversion Hle.
assert (Hle': i1' <= i2') by omega.
destruct c.
+ (* SKIP *)
simpl in Hceval. inversion Hceval.
reflexivity.
+ (* ::= *)
simpl in Hceval. inversion Hceval.
reflexivity.
+ (* ;; *)
simpl in Hceval. simpl.
destruct (ceval_step st c1 i1') eqn:Heqst1'o.
* (* st1'o = Some *)
apply (IHi1' i2') in Heqst1'o; try assumption.
rewrite Heqst1'o. simpl. simpl in Hceval.
apply (IHi1' i2') in Hceval; try assumption.
* (* st1'o = None *)
discriminate Hceval.
+ (* TEST *)
simpl in Hceval. simpl.
destruct (beval st b); apply (IHi1' i2') in Hceval;
assumption.
+ (* WHILE *)
simpl in Hceval. simpl.
destruct (beval st b); try assumption.
destruct (ceval_step st c i1') eqn: Heqst1'o.
* (* st1'o = Some *)
apply (IHi1' i2') in Heqst1'o; try assumption.
rewrite -> Heqst1'o. simpl. simpl in Hceval.
apply (IHi1' i2') in Hceval; try assumption.
* (* i1'o = None *)
simpl in Hceval. discriminate Hceval. Qed.
(** **** Exercise: 3 stars, standard, recommended (ceval__ceval_step) *)
Lemma i1_leq_i1i2 :forall i1 i2,
i1<=i1+i2.
Proof.
induction i2.
-rewrite<-plus_n_O. reflexivity.
-rewrite plus_comm. simpl. apply le_S. rewrite plus_comm. apply IHi2.
Qed.
Theorem ceval__ceval_step: forall c st st',
st =[ c ]=> st' ->
exists i, ceval_step st c i = Some st'.
Proof.
intros c st st' Hce.
induction Hce.
-exists 1. reflexivity.
-exists 1. simpl;rewrite H; reflexivity.
-destruct IHHce1 as [i1 H1]. destruct IHHce2 as [i2 H2].
exists (1+i1+i2). simpl.
destruct (ceval_step st c1 (i1 + i2)) eqn: Heqst1.
+assert (H1': ceval_step st c1 (i1+i2) =Some st'). {
apply ceval_step_more with (i1:=i1) (i2:= i1+i2).
*apply i1_leq_i1i2.
*apply H1. }
assert (H': s=st'). { rewrite Heqst1 in H1'.
inversion H1'. reflexivity. }
subst.
apply(ceval_step_more i2 (i1+i2)).
*rewrite plus_comm. apply i1_leq_i1i2.
*apply H2.
+assert (H1': ceval_step st c1 (i1+i2) =Some st'). {
apply ceval_step_more with (i1:=i1) (i2:= i1+i2).
*apply i1_leq_i1i2.
*apply H1. }
rewrite H1' in Heqst1. inversion Heqst1.
-destruct IHHce as [i H1]. exists (1+i). simpl.
rewrite H. apply H1.
-destruct IHHce as [i H1]. exists (1+i). simpl.
rewrite H. apply H1.
-exists 1. simpl. rewrite H. reflexivity.
-destruct IHHce1 as [i1 H1]. destruct IHHce2 as [i2 H2].
exists (1+i1+i2). simpl.
rewrite H.
assert (H1': ceval_step st c (i1+i2) =Some st'). {
apply ceval_step_more with (i1:=i1) (i2:= i1+i2).
*apply i1_leq_i1i2.
*apply H1. }
rewrite H1'.
rewrite plus_comm.
apply (ceval_step_more i2 (i2+i1)) .
*apply i1_leq_i1i2.
*apply H2.
Qed.
Theorem ceval_and_ceval_step_coincide: forall c st st',
st =[ c ]=> st'
<-> exists i, ceval_step st c i = Some st'.
Proof.
intros c st st'.
split. apply ceval__ceval_step. apply ceval_step__ceval.
Qed.
(* ################################################################# *)
(** * Determinism of Evaluation Again *)
Theorem ceval_deterministic' : forall c st st1 st2,
st =[ c ]=> st1 ->
st =[ c ]=> st2 ->
st1 = st2.
Proof.
intros c st st1 st2 He1 He2.
apply ceval__ceval_step in He1.
apply ceval__ceval_step in He2.
inversion He1 as [i1 E1].
inversion He2 as [i2 E2].
apply ceval_step_more with (i2 := i1 + i2) in E1.
apply ceval_step_more with (i2 := i1 + i2) in E2.
rewrite E1 in E2. inversion E2. reflexivity.
omega. omega. Qed.
(* Wed Jan 9 12:02:46 EST 2019 *)