start_function.
forward.
pose (Inv := (EX b : bool, PROP () LOCAL (temp _i (Vint (Int.repr (if b then 1 else 0)))) SEP ())).
forward_while Inv. (** FAILS WITH THE FORMER VERSION OF forward_while **)
*)
simpl typeof;
[ reflexivity
| special_intros_EX
| (do_compute_expr1 Delta Pre e; eassumption) ||
fail "The loop invariant is not strong enough to guarantee evaluation of the loop-test expression.
Loop invariant:" Pre
"
Loop test expression:" e
| special_intros_EX;
let HRE := fresh "HRE" in apply semax_extract_PROP; intro HRE;
do_repr_inj HRE;
repeat (apply semax_extract_PROP; intro);
normalize in HRE
]
end
| apply extract_exists_pre; special_intros_EX;
let HRE := fresh "HRE" in apply semax_extract_PROP; intro HRE;
do_repr_inj HRE;
repeat (apply semax_extract_PROP; intro);
normalize in HRE
]
]; abbreviate_semax;
simpl_ret_assert (*autorewrite with ret_assert*).
Inductive Type_of_invariant_in_forward_for_should_be_environ_arrow_mpred_but_is : Type -> Prop := .
Inductive Type_of_bound_in_forward_for_should_be_Z_but_is : Type -> Prop := .
Ltac check_type_forward_for_simple_bound :=
match goal with |- semax _ _ ?c _ =>
let x := constr:(match c with (Ssequence _ (Sloop _ (Sset _ e))) => Some (typeof e) | _ => None end) in let x := eval hnf in x in let x := eval simpl in x in
match x with
| None => idtac
| Some ?t =>
unify (is_int32_type t) true
+ fail 100 "At present, forward_for_simple_bound works only on iteration variables that are (signed or unsigned) int, but your iteration variable has type" t
end
end.
Ltac forward_for_simple_bound n Pre :=
check_Delta; check_POSTCONDITION;
repeat match goal with |-
semax _ _ (Ssequence (Ssequence (Ssequence _ _) _) _) _ =>
apply -> seq_assoc; abbreviate_semax
end;
match goal with |-
semax _ _ (Ssequence (Ssequence (Sfor _ _ _ _) _) _) _ =>
apply -> seq_assoc; abbreviate_semax
| _ => idtac
end;
first [
match type of n with
?t => first [ unify t Z | elimtype (Type_of_bound_in_forward_for_should_be_Z_but_is t)]
end;
match type of Pre with
?t => first [unify t (environ -> mpred); fail 1 | elimtype (Type_of_invariant_in_forward_for_should_be_environ_arrow_mpred_but_is t)]
end
| match goal with
| |- semax _ _ (Sfor _ _ _ _) _ =>
rewrite semax_seq_skip
| |- semax _ _ (Ssequence _ (Sloop _ _)) _ =>
rewrite semax_seq_skip
| |- semax _ _ (Ssequence _ ?MORE_COMMANDS) _ =>
revert MORE_COMMANDS;
match goal with
| |- let MORE_COMMANDS := @abbreviate _ (Sloop _ _) in _ =>
intros MORE_COMMANDS;
rewrite semax_seq_skip
end
| _ => idtac
end;
forward_for_simple_bound'' n Pre; [.. | abbreviate_semax; cbv beta; try fwd_skip]
].
Ltac forward_for3 Inv PreInc Postcond :=
apply semax_seq with Postcond;
[ eapply semax_for_3g1 with (PQR:=PreInc);
[ reflexivity
|intro
| intro ;
match goal with |- ENTAIL ?Delta, ?Pre |-- local (liftx (eq _) (eval_expr ?e)) =>
do_compute_expr1 Delta Pre e;
match goal with v := _ : val , H: ENTAIL _ , _ |-- _ |- _ => subst v; apply H end
end
| intro; let HRE := fresh in
apply semax_extract_PROP; intro HRE;
repeat (apply semax_extract_PROP; fancy_intro true);
do_repr_inj HRE
| intro; let HRE := fresh in
apply semax_extract_PROP; intro HRE;
repeat (apply semax_extract_PROP; fancy_intro true);
do_repr_inj HRE
| intro; let HRE := fresh in
apply derives_extract_PROP; intro HRE;
repeat (apply derives_extract_PROP; fancy_intro true);
do_repr_inj HRE;
match goal with
| |- context [RA_normal (overridePost ?P ?Post)] => change (RA_normal (overridePost ?P ?Post)) with P
end ]
| abbreviate_semax;
repeat (apply semax_extract_PROP; fancy_intro true)
].
Fixpoint no_breaks (s: statement) : bool :=
match s with
| Sbreak => false
| Ssequence a b => andb (no_breaks a) (no_breaks b)
| Sifthenelse _ a b => andb (no_breaks a) (no_breaks b)
| Sloop _ _ => true (* breaks within the inner loop are OK *)
| _ => true
end.
Ltac forward_for2 Inv PreInc :=
repeat  match goal with P := @abbreviate ret_assert _ |- semax _ _ _ ?P' =>
constr_eq P P'; unfold abbreviate in P; subst P
end;
match goal with |- semax _ _ (Sloop (Ssequence (Sifthenelse _ Sskip Sbreak) ?body) _) _ =>
(tryif unify (no_breaks body) true
then idtac
else fail "Since there is a break in the loop body, you need to supply an explicit postcondition using the 3-argument form of forward_for.");
eapply semax_for_3g2 with (PQR:=PreInc);
[ reflexivity
|intro
| intro ;
match goal with |- ENTAIL ?Delta, ?Pre |-- local (liftx (eq _) (eval_expr ?e)) =>
do_compute_expr1 Delta Pre e;
match goal with v := _ : val , H: ENTAIL _ , _ |-- _ |- _ => subst v; apply H end
end
| intro; let HRE := fresh in
apply semax_extract_PROP; intro HRE;
repeat (apply semax_extract_PROP; fancy_intro true);
do_repr_inj HRE
| intro; let HRE := fresh in
apply semax_extract_PROP; intro HRE;
repeat (apply semax_extract_PROP; fancy_intro true);
do_repr_inj HRE
]
end.

Lemma semax_post1_flipped: forall R' Espec {cs: compspecs} Delta R P c,
@semax cs Espec Delta P c (overridePost R' R) ->
ENTAIL Delta, R' |-- RA_normal R ->
@semax cs Espec Delta P c R.