Definition subst{A} (x: var) (v: adr) (P: env -> A) : env -> A :=
   fun s => P (env_set s x v).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).