End WT_SWITCH.
Section PRESERVATION.
Variable prog: program.
Hypothesis WTPROG: wt_program prog.
Let ge := globalenv prog.
Let gtenv := bind_globdef (PTree.empty _) prog.(prog_defs).
Hypothesis WT_EXTERNAL:
forall id ef args res cc vargs m t vres m',
In (id, Gfun (External ef args res cc)) prog.(prog_defs) ->
external_call ef ge vargs m t vres m' ->
wt_val vres res.
Inductive wt_expr_cont: typenv -> function -> cont -> Prop :=
| wt_Kdo: forall te f k,
wt_stmt_cont te f k ->
wt_expr_cont te f (Kdo k)
| wt_Kifthenelse: forall te f s1 s2 k,
wt_stmt_cont te f k ->
wt_stmt ge te f.(fn_return) s1 -> wt_stmt ge te f.(fn_return) s2 ->
wt_expr_cont te f (Kifthenelse s1 s2 k)
| wt_Kwhile1: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_expr_cont te f (Kwhile1 r s k)
| wt_Kdowhile2: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_expr_cont te f (Kdowhile2 r s k)
| wt_Kfor2: forall te f r s2 s3 k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s2 -> wt_stmt ge te f.(fn_return) s3 ->
classify_bool (typeof r) <> bool_default ->
wt_expr_cont te f (Kfor2 r s2 s3 k)
| wt_Kswitch1: forall te f ls k,
wt_stmt_cont te f k ->
wt_lblstmts ge te f.(fn_return) ls ->
wt_expr_cont te f (Kswitch1 ls k)
| wt_Kreturn: forall te f k,
wt_stmt_cont te f k ->
wt_expr_cont te f (Kreturn k)
with wt_stmt_cont: typenv -> function -> cont -> Prop :=
| wt_Kseq: forall te f s k,
wt_stmt_cont te f k ->
wt_stmt ge te f.(fn_return) s ->
wt_stmt_cont te f (Kseq s k)
| wt_Kwhile2: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_stmt_cont te f (Kwhile2 r s k)
| wt_Kdowhile1: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_stmt_cont te f (Kdowhile1 r s k)
| wt_Kfor3: forall te f r s2 s3 k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s2 -> wt_stmt ge te f.(fn_return) s3 ->
wt_bool (typeof r) ->
wt_stmt_cont te f (Kfor3 r s2 s3 k)
| wt_Kfor4: forall te f r s2 s3 k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s2 -> wt_stmt ge te f.(fn_return) s3 ->
wt_bool (typeof r) ->
wt_stmt_cont te f (Kfor4 r s2 s3 k)
| wt_Kswitch2: forall te f k,
wt_stmt_cont te f k ->
wt_stmt_cont te f (Kswitch2 k)
| wt_Kstop': forall te f,
wt_stmt_cont te f Kstop
| wt_Kcall': forall te f f' e C ty k,
wt_call_cont (Kcall f' e C ty k) ty ->
ty = f.(fn_return) ->
wt_stmt_cont te f (Kcall f' e C ty k)
with wt_call_cont: cont -> type -> Prop :=
| wt_Kstop: forall ty,
wt_call_cont Kstop ty
| wt_Kcall: forall te f e C ty k,
wt_expr_cont te f k ->
wt_stmt ge te f.(fn_return) f.(fn_body) ->
(forall v, wt_val v ty -> wt_rvalue ge te (C (Eval v ty))) ->
wt_call_cont (Kcall f e C ty k) ty.

(* Specifications: *)
Lemma is_wt_call_cont:
forall te f k,
is_call_cont k -> wt_stmt_cont te f k -> wt_call_cont k f.(fn_return).
Lemma wt_call_cont_stmt_cont:
forall te f k, wt_call_cont k f.(fn_return) -> wt_stmt_cont te f k.
Lemma call_cont_wt:
forall e f k, wt_stmt_cont e f k -> wt_call_cont (call_cont k) f.(fn_return).
Lemma call_cont_wt':
forall e f k, wt_stmt_cont e f k -> wt_stmt_cont e f (call_cont k).