Definition subst{A} (x: var) (v: adr) (P: env -> A) : env -> A :=
fun s => P (env_set s x v).
(* TYPE-CHECKING OF LOCAL VARIABLES *)
Require ListSet.
Definition varset : Type := ListSet.set var.
Definition vs_mem: var -> varset -> bool := ListSet.set_mem EqDec_var.
Definition vs_add: var -> varset -> varset := ListSet.set_add EqDec_var.
Definition varcompat (vars: varset) (s: locals) :=
forall i, vs_mem i vars = true -> table_get s i <> None.
Fixpoint expcheck (vars: varset) (e: expr) :=
match e with
| Const _ => true
| Var v => vs_mem v vars
| Offset e n => expcheck vars e
| Mem _ => false
end.
Fixpoint typecheck (vars: varset) (c: control) : bool :=
match c with
| Assign (Var v) (Mem e) c' => andb (expcheck vars e)
(typecheck (vs_add v vars) c')
| Assign (Var v) e c' => andb (expcheck vars e)
(typecheck (vs_add v vars) c')
| Assign (Mem e1) e2 c' => andb (andb (expcheck vars e1)  (expcheck vars e2))
(typecheck vars c')
| IfThenElse e c1 c2 => andb (expcheck vars e)
(andb (typecheck vars c1) (typecheck vars c2))
| Go e el => andb (expcheck vars e)  (forallb (expcheck vars) el)
| _ => false
end.

(* Specifications: *)
Lemma eval_expr_get:
forall vars s h e,
expcheck vars e = true ->
varcompat vars s ->
expr_get s h e = Some (eval e (locals2env s)).
Lemma eval_expr_get_list:
forall vars s h el,
forallb (expcheck vars) el = true ->
varcompat vars s ->
get_list s h el = Some (eval_list el (locals2env s)).
Lemma varcompat_add:
forall x vars z s, varcompat vars s -> varcompat (vs_add x vars) (table_set x z s).
Lemma varcompat_mk_locals:
forall xl vl, length xl <= length vl -> varcompat xl (mk_locals xl vl).