Fixpoint esize (a: expr) : nat :=
  match a with
  | Eloc _ _ _ => 1%nat
  | Evar _ _ => 1%nat
  | Ederef r1 _ => S(esize r1)
  | Efield l1 _ _ => S(esize l1)
  | Eval _ _ => O
  | Evalof l1 _ => S(esize l1)
  | Eaddrof l1 _ => S(esize l1)
  | Eunop _ r1 _ => S(esize r1)
  | Ebinop _ r1 r2 _ => S(esize r1 + esize r2)%nat
  | Ecast r1 _ => S(esize r1)
  | Eseqand r1 r2 _ => S(esize r1)
  | Eseqor r1 r2 _ => S(esize r1)
  | Econdition r1 _ _ _ => S(esize r1)
  | Esizeof _ _ => 1%nat
  | Ealignof _ _ => 1%nat
  | Eassign l1 r2 _ => S(esize l1 + esize r2)%nat
  | Eassignop _ l1 r2 _ _ => S(esize l1 + esize r2)%nat
  | Epostincr _ l1 _ => S(esize l1)
  | Ecomma r1 r2 _ => S(esize r1 + esize r2)%nat
  | Ecall r1 rl2 _ => S(esize r1 + esizelist rl2)%nat
  | Ebuiltin ef tyargs rl _ => S(esizelist rl)
  | Eparen r1 _ _ => S(esize r1)
  end

with esizelist (el: exprlist) : nat :=
  match el with
  | Enil => O
  | Econs r1 rl2 => S(esize r1 + esizelist rl2)%nat
  end.

(* Specifications: *)
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.
Lemma evalinf_funcall_steps: forall m fd args t k, evalinf_funcall m fd args t -> forever_N step lt ge O (Callstate fd args k m) t.
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.
Lemma evalinf_funcall_steps: forall m fd args t k, evalinf_funcall m fd args t -> forever_N step lt ge O (Callstate fd args k m) t.