Section FIND_LABEL.
Variable lbl: label.
Definition nolabel (s: statement) : Prop :=
forall k, find_label lbl s k = None.
Fixpoint nolabel_list (sl: list statement) : Prop :=
match sl with
| nil => True
| s1 :: sl' => nolabel s1 /\ nolabel_list sl'
end.
Ltac NoLabelTac :=
match goal with
| [ |- nolabel_list nil ] => exact I
| [ |- nolabel_list (final _ _) ] => apply nolabel_final (*; NoLabelTac*)
| [ |- nolabel_list (_ :: _) ] => simpl; split; NoLabelTac
| [ |- nolabel_list (_ ++ _) ] => apply nolabel_list_app; NoLabelTac
| [ H: _ -> nolabel_list ?x |- nolabel_list ?x ] => apply H; NoLabelTac
| [ |- nolabel (makeseq _) ] => apply makeseq_nolabel; NoLabelTac
| [ |- nolabel (makeif _ _ _) ] => apply makeif_nolabel; NoLabelTac
| [ |- nolabel (make_set _ _) ] => apply make_set_nolabel
| [ |- nolabel (make_assign _ _) ] => apply make_assign_nolabel
| [ |- nolabel _ ] => red; intros; simpl; auto
| [ |- _ /\ _ ] => split; NoLabelTac
| _ => auto
end.
End FIND_LABEL.
(** Anti-stuttering measure *)
(** There are some stuttering steps in the translation: - The execution of [Sdo a] where [a] is side-effect free, which is three transitions in the source: << Sdo a, k  --->  a, Kdo k ---> rval v, Kdo k ---> Sskip, k >> but the translation, which is [Sskip], makes no transitions. - The reduction [Ecomma (Eval v) r2 --> r2]. - The reduction [Eparen (Eval v) --> Eval v] in a [For_effects] context.  The following measure decreases for these stuttering steps. *)
Fixpoint esize (a: Csyntax.expr) : nat :=
match a with
| Csyntax.Eloc _ _ _ => 1%nat
| Csyntax.Evar _ _ => 1%nat
| Csyntax.Ederef r1 _ => S(esize r1)
| Csyntax.Efield l1 _ _ => S(esize l1)
| Csyntax.Eval _ _ => O
| Csyntax.Evalof l1 _ => S(esize l1)
| Csyntax.Eaddrof l1 _ => S(esize l1)
| Csyntax.Eunop _ r1 _ => S(esize r1)
| Csyntax.Ebinop _ r1 r2 _ => S(esize r1 + esize r2)%nat
| Csyntax.Ecast r1 _ => S(esize r1)
| Csyntax.Eseqand r1 _ _ => S(esize r1)
| Csyntax.Eseqor r1 _ _ => S(esize r1)
| Csyntax.Econdition r1 _ _ _ => S(esize r1)
| Csyntax.Esizeof _ _ => 1%nat
| Csyntax.Ealignof _ _ => 1%nat
| Csyntax.Eassign l1 r2 _ => S(esize l1 + esize r2)%nat
| Csyntax.Eassignop _ l1 r2 _ _ => S(esize l1 + esize r2)%nat
| Csyntax.Epostincr _ l1 _ => S(esize l1)
| Csyntax.Ecomma r1 r2 _ => S(esize r1 + esize r2)%nat
| Csyntax.Ecall r1 rl2 _ => S(esize r1 + esizelist rl2)%nat
| Csyntax.Ebuiltin ef _ rl _ => S(esizelist rl)%nat
| Csyntax.Eparen r1 _ _ => S(esize r1)
end
with esizelist (el: Csyntax.exprlist) : nat :=
match el with
| Csyntax.Enil => O
| Csyntax.Econs r1 rl2 => (esize r1 + esizelist rl2)%nat
end.
Definition measure (st: Csem.state) : nat :=
match st with
| Csem.ExprState _ r _ _ _ => (esize r + 1)%nat
| Csem.State _ Csyntax.Sskip _ _ _ => 0%nat
| Csem.State _ (Csyntax.Sdo r) _ _ _ => (esize r + 2)%nat
| Csem.State _ (Csyntax.Sifthenelse r _ _) _ _ _ => (esize r + 2)%nat
| _ => 0%nat
end.

Lemma leftcontext_size:
forall from to C,
leftcontext from to C ->
forall e1 e2,
(esize e1 < esize e2)%nat ->
(esize (C e1) < esize (C e2))%nat
with leftcontextlist_size:
forall from C,
leftcontextlist from C ->
forall e1 e2,
(esize e1 < esize e2)%nat ->
(esizelist (C e1) < esizelist (C e2))%nat.