Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
We saw in the Imp chapter how a naive approach to defining a
function representing evaluation for Imp runs into difficulties.
There, we adopted the solution of changing from a functional to a
relational definition of evaluation. In this optional chapter, we
consider strategies for getting the functional approach to
work.
(* ################################################################# *)
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.
As we remarked in chapter Imp, in a traditional functional
programming language like ML or Haskell we could write the WHILE
case as follows:
| WHILE b1 DO c1 END =>
if (beval st b1) then
ceval_step1 st (c1;; WHILE b1 DO c1 END)
else st
Coq doesn't accept such a definition (Error: Cannot guess
decreasing argument of fix) because the function we want to
define is not guaranteed to terminate. Indeed, the changed
ceval_step1 function applied to the loop program from Imp.v
would never terminate. Since Coq is not just a functional
programming language, but also a consistent logic, any potentially
non-terminating function needs to be rejected. Here is an
invalid(!) Coq program showing what would go wrong if Coq allowed
non-terminating recursive functions:
Fixpoint loop_false (n : nat) : False := loop_false n.
That is, propositions like False would become
provable (e.g., loop_false 0 would be a proof of False), which
would be a disaster for Coq's logical consistency.
Thus, because it doesn't terminate on all inputs, the full version
of ceval_step1 cannot be written in Coq -- at least not without
one additional trick...
(* ################################################################# *)
The trick we need is to pass an additional parameter to the
evaluation function that tells it how long to run. Informally, we
start the evaluator with a certain amount of "gas" in its tank,
and we allow it to run until either it terminates in the usual way
or it runs out of gas, at which point we simply stop evaluating
and say that the final result is the empty memory. (We could also
say that the result is the current state at the point where the
evaluator runs out of gas -- it doesn't really matter because the
result is going to be wrong in either case!)
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.
Note: It is tempting to think that the index i here is
counting the "number of steps of evaluation." But if you look
closely you'll see that this is not the case: for example, in the
rule for sequencing, the same i is passed to both recursive
calls. Understanding the exact way that i is treated will be
important in the proof of ceval__ceval_step, which is given as
an exercise below.
One thing that is not so nice about this evaluator is that we
can't tell, from its result, whether it stopped because the
program terminated normally or because it ran out of gas. Our
next version returns an option state instead of just a state,
so that we can distinguish between normal and abnormal
termination.
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.
We can improve the readability of this version by introducing a
bit of auxiliary notation to hide the plumbing involved in
repeatedly matching against optional states.
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)
Admitted. (* Example pup_to_n_1 : test_ceval (X !-> 5) pup_to_n = Some (0, 15, 0). Proof. reflexivity. Qed. [] *)com
Exercise: 2 stars, standard, optional (peven)
(* FILL IN HERE
[] *)
(* ################################################################# *)
As for arithmetic and boolean expressions, we'd hope that
the two alternative definitions of evaluation would actually
amount to the same thing in the end. This section shows that this
is the case.
forall (c : com) (st st' : state), (exists i : nat, ceval_step st c i = Some st') -> st =[ c ]=> st'forall (c : com) (st st' : state), (exists i : nat, ceval_step st c i = Some st') -> st =[ c ]=> st'c:comst, st':stateH:exists i : nat, ceval_step st c i = Some st'st =[ c ]=> st'c:comst, st':stateH:exists i0 : nat, ceval_step st c i0 = Some st'i:natE:ceval_step st c i = Some st'st =[ c ]=> st'c:comst, st':statei:natE:ceval_step st c i = Some st'st =[ c ]=> st'c:comst:statei:natforall st' : state, ceval_step st c i = Some st' -> st =[ c ]=> st'c:comi:natforall st st' : state, ceval_step st c i = Some st' -> st =[ c ]=> st'i:natforall (c : com) (st st' : state), ceval_step st c i = Some st' -> st =[ c ]=> st'forall (c : com) (st st' : state), ceval_step st c 0 = Some st' -> st =[ c ]=> st'i':natIHi':forall (c : com) (st st' : state), ceval_step st c i' = Some st' -> st =[ c ]=> st'forall (c : com) (st st' : state), ceval_step st c (S i') = Some st' -> st =[ c ]=> st'forall (c : com) (st st' : state), ceval_step st c 0 = Some st' -> st =[ c ]=> st'discriminate H.c:comst, st':stateH:ceval_step st c 0 = Some st'st =[ c ]=> st'i':natIHi':forall (c : com) (st st' : state), ceval_step st c i' = Some st' -> st =[ c ]=> st'forall (c : com) (st st' : state), ceval_step st c (S i') = Some st' -> st =[ c ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0c:comst, st':stateH:ceval_step st c (S i') = Some st'st =[ c ]=> st'i':natIHi':forall (c : com) (st st'0 : state), ceval_step st c i' = Some st'0 -> st =[ c ]=> st'0st':statest' =[ SKIP ]=> st'i':natIHi':forall (c : com) (st0 st' : state), ceval_step st0 c i' = Some st' -> st0 =[ c ]=> st'x:stringa:aexpst:statest =[ x ::= a ]=> (x !-> aeval st a; st)i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st':stateH1:LETOPT st'0 <== ceval_step st c1 i' IN ceval_step st'0 c2 i' = Some st'st =[ c1;; c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateH1:(if beval st b then ceval_step st c1 i' else ceval_step st c2 i') = Some st'st =[ TEST b THEN c1 ELSE c2 FI ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateH1:(if beval st b then LETOPT st'0 <== ceval_step st c i' IN ceval_step st'0 (WHILE b DO c END) i' else Some st) = Some st'st =[ WHILE b DO c END ]=> st'apply E_Skip.i':natIHi':forall (c : com) (st st'0 : state), ceval_step st c i' = Some st'0 -> st =[ c ]=> st'0st':statest' =[ SKIP ]=> st'i':natIHi':forall (c : com) (st0 st' : state), ceval_step st0 c i' = Some st' -> st0 =[ c ]=> st'x:stringa:aexpst:statest =[ x ::= a ]=> (x !-> aeval st a; st)reflexivity.i':natIHi':forall (c : com) (st0 st' : state), ceval_step st0 c i' = Some st' -> st0 =[ c ]=> st'x:stringa:aexpst:stateaeval st a = aeval st ai':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st':stateH1:LETOPT st'0 <== ceval_step st c1 i' IN ceval_step st'0 c2 i' = Some st'st =[ c1;; c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st'st =[ c1;; c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st':stateHeqr1:ceval_step st c1 i' = NoneH1:None = Some st'st =[ c1;; c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st'st =[ c1;; c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st'st =[ c1 ]=> si':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st's =[ c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st'ceval_step st c1 i' = Some si':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st's =[ c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st'Some s = Some si':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st's =[ c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st's =[ c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st'ceval_step s c2 i' = Some st'assumption.i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st', s:stateHeqr1:ceval_step st c1 i' = Some sH1:ceval_step s c2 i' = Some st'ceval_step s c2 i' = Some st'discriminate H1.i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0c1, c2:comst, st':stateHeqr1:ceval_step st c1 i' = NoneH1:None = Some st'st =[ c1;; c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateH1:(if beval st b then ceval_step st c1 i' else ceval_step st c2 i') = Some st'st =[ TEST b THEN c1 ELSE c2 FI ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'st =[ TEST b THEN c1 ELSE c2 FI ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'st =[ TEST b THEN c1 ELSE c2 FI ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'st =[ TEST b THEN c1 ELSE c2 FI ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'beval st b = truei':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'st =[ c1 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'true = truei':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'st =[ c1 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'st =[ c1 ]=> st'assumption.i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = trueH1:ceval_step st c1 i' = Some st'ceval_step st c1 i' = Some st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'st =[ TEST b THEN c1 ELSE c2 FI ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'beval st b = falsei':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'st =[ c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'false = falsei':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'st =[ c2 ]=> st'i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'st =[ c2 ]=> st'assumption.i':natIHi':forall (c : com) (st0 st'0 : state), ceval_step st0 c i' = Some st'0 -> st0 =[ c ]=> st'0b:bexpc1, c2:comst, st':stateHeqr:beval st b = falseH1:ceval_step st c2 i' = Some st'ceval_step st c2 i' = Some st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateH1:(if beval st b then LETOPT st'0 <== ceval_step st c i' IN ceval_step st'0 (WHILE b DO c END) i' else Some st) = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trueH1:LETOPT st'0 <== ceval_step st c i' IN ceval_step st'0 (WHILE b DO c END) i' = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = falseH1:Some st = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trueH1:LETOPT st'0 <== ceval_step st c i' IN ceval_step st'0 (WHILE b DO c END) i' = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trueHeqr1:ceval_step st c i' = NoneH1:None = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'beval st b = truei':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'st =[ c ]=> si':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st's =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'true = truei':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'st =[ c ]=> si':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st's =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'st =[ c ]=> si':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st's =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'ceval_step st c i' = Some si':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st's =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'Some s = Some si':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st's =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st's =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'ceval_step s (WHILE b DO c END) i' = Some st'assumption.i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trues:stateHeqr1:ceval_step st c i' = Some sH1:ceval_step s (WHILE b DO c END) i' = Some st'ceval_step s (WHILE b DO c END) i' = Some st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trueHeqr1:ceval_step st c i' = NoneH1:None = Some st'st =[ WHILE b DO c END ]=> st'discriminate H1. }i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = trueHeqr1:ceval_step st c i' = NoneH1:None = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = falseH1:Some st = Some st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = falseH1:Some st = Some st'st = st' -> st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = falseH1:Some st = Some st'H2:st = st'st =[ WHILE b DO c END ]=> st'i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = falseH1:Some st = Some st'H2:st = st'st =[ WHILE b DO c END ]=> stapply Heqr. Qed.i':natIHi':forall (c0 : com) (st0 st'0 : state), ceval_step st0 c0 i' = Some st'0 -> st0 =[ c0 ]=> st'0b:bexpc:comst, st':stateHeqr:beval st b = falseH1:Some st = Some st'H2:st = st'beval st b = false
Exercise: 4 stars, standard (ceval_step__ceval_inf)
(* FILL IN HERE *) (* Do not modify the following line: *) Definition manual_grade_for_ceval_step__ceval_inf : option (nat*string) := None.
☐
forall (i1 i2 : nat) (st st' : state) (c : com), i1 <= i2 -> ceval_step st c i1 = Some st' -> ceval_step st c i2 = Some st'forall (i1 i2 : nat) (st st' : state) (c : com), i1 <= i2 -> ceval_step st c i1 = Some st' -> ceval_step st c i2 = Some st'i2:natst, st':statec:comHle:0 <= i2Hceval:ceval_step st c 0 = Some st'ceval_step st c i2 = Some st'i1':natIHi1':forall (i0 : nat) (st0 st'0 : state) (c0 : com), i1' <= i0 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i0 = Some st'0i2:natst, st':statec:comHle:S i1' <= i2Hceval:ceval_step st c (S i1') = Some st'ceval_step st c i2 = Some st'i2:natst, st':statec:comHle:0 <= i2Hceval:ceval_step st c 0 = Some st'ceval_step st c i2 = Some st'discriminate Hceval.i2:natst, st':statec:comHle:0 <= i2Hceval:None = Some st'ceval_step st c i2 = Some st'i1':natIHi1':forall (i0 : nat) (st0 st'0 : state) (c0 : com), i1' <= i0 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i0 = Some st'0i2:natst, st':statec:comHle:S i1' <= i2Hceval:ceval_step st c (S i1') = Some st'ceval_step st c i2 = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0st, st':statec:comHle:S i1' <= 0Hceval:ceval_step st c (S i1') = Some st'ceval_step st c 0 = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':statec:comHle:S i1' <= S i2'Hceval:ceval_step st c (S i1') = Some st'ceval_step st c (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':statec:comHle:S i1' <= S i2'Hceval:ceval_step st c (S i1') = Some st'ceval_step st c (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':statec:comHle:S i1' <= S i2'Hceval:ceval_step st c (S i1') = Some st'Hle':i1' <= i2'ceval_step st c (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateHle:S i1' <= S i2'Hceval:ceval_step st SKIP (S i1') = Some st'Hle':i1' <= i2'ceval_step st SKIP (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statex:stringa:aexpHle:S i1' <= S i2'Hceval:ceval_step st (x ::= a) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (x ::= a) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2'Hceval:ceval_step st (c1;; c2) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (c1;; c2) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateb:bexpc1, c2:comHle:S i1' <= S i2'Hceval:ceval_step st (TEST b THEN c1 ELSE c2 FI) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (TEST b THEN c1 ELSE c2 FI) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Hceval:ceval_step st (WHILE b DO c END) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (WHILE b DO c END) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateHle:S i1' <= S i2'Hceval:ceval_step st SKIP (S i1') = Some st'Hle':i1' <= i2'ceval_step st SKIP (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateHle:S i1' <= S i2'Hceval:Some st = Some st'Hle':i1' <= i2'ceval_step st SKIP (S i2') = Some st'reflexivity.i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateHle:S i1' <= S i2'Hceval:Some st = Some st'Hle':i1' <= i2'H0:st = st'ceval_step st' SKIP (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statex:stringa:aexpHle:S i1' <= S i2'Hceval:ceval_step st (x ::= a) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (x ::= a) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statex:stringa:aexpHle:S i1' <= S i2'Hceval:Some (x !-> aeval st a; st) = Some st'Hle':i1' <= i2'ceval_step st (x ::= a) (S i2') = Some st'reflexivity.i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statex:stringa:aexpHle:S i1' <= S i2'Hceval:Some (x !-> aeval st a; st) = Some st'Hle':i1' <= i2'H0:(x !-> aeval st a; st) = st'ceval_step st (x ::= a) (S i2') = Some (x !-> aeval st a; st)i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2'Hceval:ceval_step st (c1;; c2) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (c1;; c2) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2'Hceval:LETOPT st'0 <== ceval_step st c1 i1' IN ceval_step st'0 c2 i1' = Some st'Hle':i1' <= i2'ceval_step st (c1;; c2) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2'Hceval:LETOPT st'0 <== ceval_step st c1 i1' IN ceval_step st'0 c2 i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c1 i2' IN ceval_step st'0 c2 i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c1 i1' = Some sHceval:ceval_step s c2 i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c1 i2' IN ceval_step st'0 c2 i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2'Heqst1'o:ceval_step st c1 i1' = NoneHceval:None = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c1 i2' IN ceval_step st'0 c2 i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c1 i1' = Some sHceval:ceval_step s c2 i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c1 i2' IN ceval_step st'0 c2 i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c1 i2' = Some sHceval:ceval_step s c2 i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c1 i2' IN ceval_step st'0 c2 i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c1 i2' = Some sHceval:ceval_step s c2 i1' = Some st'Hle':i1' <= i2'ceval_step s c2 i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c1 i2' = Some sHceval:ceval_step s c2 i1' = Some st'Hle':i1' <= i2'ceval_step s c2 i2' = Some st'apply (IHi1' i2') in Hceval; try assumption.i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c1 i2' = Some sHceval:ceval_step s c2 i1' = Some st'Hle':i1' <= i2'ceval_step s c2 i2' = Some st'discriminate Hceval.i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':statec1, c2:comHle:S i1' <= S i2'Heqst1'o:ceval_step st c1 i1' = NoneHceval:None = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c1 i2' IN ceval_step st'0 c2 i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateb:bexpc1, c2:comHle:S i1' <= S i2'Hceval:ceval_step st (TEST b THEN c1 ELSE c2 FI) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (TEST b THEN c1 ELSE c2 FI) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateb:bexpc1, c2:comHle:S i1' <= S i2'Hceval:(if beval st b then ceval_step st c1 i1' else ceval_step st c2 i1') = Some st'Hle':i1' <= i2'ceval_step st (TEST b THEN c1 ELSE c2 FI) (S i2') = Some st'destruct (beval st b); apply (IHi1' i2') in Hceval; assumption.i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c : com), i1' <= i2 -> ceval_step st0 c i1' = Some st'0 -> ceval_step st0 c i2 = Some st'0i2':natst, st':stateb:bexpc1, c2:comHle:S i1' <= S i2'Hceval:(if beval st b then ceval_step st c1 i1' else ceval_step st c2 i1') = Some st'Hle':i1' <= i2'(if beval st b then ceval_step st c1 i2' else ceval_step st c2 i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Hceval:ceval_step st (WHILE b DO c END) (S i1') = Some st'Hle':i1' <= i2'ceval_step st (WHILE b DO c END) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Hceval:(if beval st b then LETOPT st'0 <== ceval_step st c i1' IN ceval_step st'0 (WHILE b DO c END) i1' else Some st) = Some st'Hle':i1' <= i2'ceval_step st (WHILE b DO c END) (S i2') = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Hceval:(if beval st b then LETOPT st'0 <== ceval_step st c i1' IN ceval_step st'0 (WHILE b DO c END) i1' else Some st) = Some st'Hle':i1' <= i2'(if beval st b then LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' else Some st) = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Hceval:LETOPT st'0 <== ceval_step st c i1' IN ceval_step st'0 (WHILE b DO c END) i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c i1' = Some sHceval:ceval_step s (WHILE b DO c END) i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Heqst1'o:ceval_step st c i1' = NoneHceval:None = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c i1' = Some sHceval:ceval_step s (WHILE b DO c END) i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c i2' = Some sHceval:ceval_step s (WHILE b DO c END) i1' = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c i2' = Some sHceval:ceval_step s (WHILE b DO c END) i1' = Some st'Hle':i1' <= i2'ceval_step s (WHILE b DO c END) i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c i2' = Some sHceval:ceval_step s (WHILE b DO c END) i1' = Some st'Hle':i1' <= i2'ceval_step s (WHILE b DO c END) i2' = Some st'apply (IHi1' i2') in Hceval; try assumption.i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2's:stateHeqst1'o:ceval_step st c i2' = Some sHceval:ceval_step s (WHILE b DO c END) i1' = Some st'Hle':i1' <= i2'ceval_step s (WHILE b DO c END) i2' = Some st'i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Heqst1'o:ceval_step st c i1' = NoneHceval:None = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' = Some st'discriminate Hceval. Qed.i1':natIHi1':forall (i2 : nat) (st0 st'0 : state) (c0 : com), i1' <= i2 -> ceval_step st0 c0 i1' = Some st'0 -> ceval_step st0 c0 i2 = Some st'0i2':natst, st':stateb:bexpc:comHle:S i1' <= S i2'Heqst1'o:ceval_step st c i1' = NoneHceval:None = Some st'Hle':i1' <= i2'LETOPT st'0 <== ceval_step st c i2' IN ceval_step st'0 (WHILE b DO c END) i2' = Some st'
Exercise: 3 stars, standard, recommended (ceval__ceval_step)
forall (c : com) (st st' : state), st =[ c ]=> st' -> exists i : nat, ceval_step st c i = Some st'forall (c : com) (st st' : state), st =[ c ]=> st' -> exists i : nat, ceval_step st c i = Some st'c:comst, st':stateHce:st =[ c ]=> st'exists i : nat, ceval_step st c i = Some st'(* FILL IN HERE *) Admitted.st:stateexists i : nat, ceval_step st SKIP i = Some stst:statea1:aexpn:natx:stringH:aeval st a1 = nexists i : nat, ceval_step st (x ::= a1) i = Some (x !-> n; st)c1, c2:comst, st', st'':stateHce1:st =[ c1 ]=> st'Hce2:st' =[ c2 ]=> st''IHHce1:exists i : nat, ceval_step st c1 i = Some st'IHHce2:exists i : nat, ceval_step st' c2 i = Some st''exists i : nat, ceval_step st (c1;; c2) i = Some st''st, st':stateb:bexpc1, c2:comH:beval st b = trueHce:st =[ c1 ]=> st'IHHce:exists i : nat, ceval_step st c1 i = Some st'exists i : nat, ceval_step st (TEST b THEN c1 ELSE c2 FI) i = Some st'st, st':stateb:bexpc1, c2:comH:beval st b = falseHce:st =[ c2 ]=> st'IHHce:exists i : nat, ceval_step st c2 i = Some st'exists i : nat, ceval_step st (TEST b THEN c1 ELSE c2 FI) i = Some st'b:bexpst:statec:comH:beval st b = falseexists i : nat, ceval_step st (WHILE b DO c END) i = Some stst, st', st'':stateb:bexpc:comH:beval st b = trueHce1:st =[ c ]=> st'Hce2:st' =[ WHILE b DO c END ]=> st''IHHce1:exists i : nat, ceval_step st c i = Some st'IHHce2:exists i : nat, ceval_step st' (WHILE b DO c END) i = Some st''exists i : nat, ceval_step st (WHILE b DO c END) i = Some st''
☐
forall (c : com) (st st' : state), st =[ c ]=> st' <-> (exists i : nat, ceval_step st c i = Some st')forall (c : com) (st st' : state), st =[ c ]=> st' <-> (exists i : nat, ceval_step st c i = Some st')c:comst, st':statest =[ c ]=> st' <-> (exists i : nat, ceval_step st c i = Some st')c:comst, st':statest =[ c ]=> st' -> exists i : nat, ceval_step st c i = Some st'c:comst, st':state(exists i : nat, ceval_step st c i = Some st') -> st =[ c ]=> st'apply ceval_step__ceval. Qed. (* ################################################################# *)c:comst, st':state(exists i : nat, ceval_step st c i = Some st') -> st =[ c ]=> st'
Using the fact that the relational and step-indexed definition of
evaluation are the same, we can give a slicker proof that the
evaluation relation is deterministic.
forall (c : com) (st st1 st2 : state), st =[ c ]=> st1 -> st =[ c ]=> st2 -> st1 = st2forall (c : com) (st st1 st2 : state), st =[ c ]=> st1 -> st =[ c ]=> st2 -> st1 = st2c:comst, st1, st2:stateHe1:st =[ c ]=> st1He2:st =[ c ]=> st2st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:st =[ c ]=> st2st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1i2:natE2:ceval_step st c i2 = Some st2st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:ceval_step st c i2 = Some st2st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1i2:natE2:ceval_step st c i2 = Some st2i1 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:ceval_step st c (i1 + i2) = Some st2st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:ceval_step st c i2 = Some st2i2 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1i2:natE2:ceval_step st c i2 = Some st2i1 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:Some st1 = Some st2st1 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:ceval_step st c i2 = Some st2i2 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1i2:natE2:ceval_step st c i2 = Some st2i1 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:Some st1 = Some st2H0:st1 = st2st2 = st2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:ceval_step st c i2 = Some st2i2 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1i2:natE2:ceval_step st c i2 = Some st2i1 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1, i2:natE1:ceval_step st c (i1 + i2) = Some st1E2:ceval_step st c i2 = Some st2i2 <= i1 + i2c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1i2:natE2:ceval_step st c i2 = Some st2i1 <= i1 + i2omega. Qed. (* Wed Jan 9 12:02:46 EST 2019 *)c:comst, st1, st2:stateHe1:exists i : nat, ceval_step st c i = Some st1He2:exists i : nat, ceval_step st c i = Some st2i1:natE1:ceval_step st c i1 = Some st1i2:natE2:ceval_step st c i2 = Some st2i1 <= i1 + i2