Definition table (A B : Type) := list (A*B).
Fixpoint table_get {A B}{H: EqDec A} (rho: table A B) (x: A) : option B :=
match rho with
| (y,v)::ys => if eq_dec x y then Some v else table_get ys x
| nil => None
end.
Definition table_set {A B}{H: EqDec A} (x: A) (v: B) (rho: table A B)  : table A B := (x,v)::rho.
Definition var := nat.
Instance EqDec_var: EqDec var := _.
Opaque var.
Definition adr := nat.
Instance EqDec_adr : EqDec adr := _.
Opaque adr.
Definition locals := table var adr.
Definition heap := adr -> option adr.
Inductive expr :=
| Const: adr -> expr
| Var: var -> expr
| Offset: expr -> nat -> expr
| Mem: expr -> expr.
Coercion Var : var >-> expr.
Coercion Const: adr >-> expr.
Notation " a '.+' n " := (Offset a n) (at level 87, no associativity).
Inductive control :=
| Assign: expr -> expr -> control -> control
| IfThenElse: expr -> control -> control -> control
| Go: expr -> list expr -> control.
Definition program := table adr (list var * control).
Definition bind_option (A B: Type) (f: option A) (g: A -> option B) : option B :=
match f with None => None | Some x => g x end.
Implicit Arguments bind_option [A B].
Notation "'do1' X '<-' A ';' B" := (bind_option A (fun X => B))
(at level 200, X ident, A at level 100, B at level 200).
Definition emptyheap : heap := fun _ => None.
Definition heap_get (h: heap) (a: adr) : option adr := h a.
Definition heap_set (a v: adr) (h: heap) :=
fun i => if eq_dec i a then Some v else h i.

Lemma heap_gso: forall h x y v, x<>y -> heap_get (heap_set x v h) y = heap_get h y.