Section TREES.
Variable V : Type.
Variable default: V.
Definition key := Z.
Inductive tree : Type :=
| E : tree
| T: tree -> key -> V -> tree -> tree.
Definition empty_tree : tree := E.
(* insert if it is new *)
Fixpoint insert (x: key) (v: V) (s: tree) : tree :=
match s with
| E => T E x v E
| T a y v' b => if  x <? y then T (insert x v a) y v' b
else if y <? x then T a y v' (insert x v b)
else T a x v' b
end.
Fixpoint tree_inb (x: key) (s: tree) : bool :=
match s with
| E => false
| T a y v' b => if  x <? y then tree_inb x a
else if y <? x then tree_inb x b
else true
end.
Fixpoint pushdown_left (a: tree) (bc: tree) : tree :=
match bc with
| E => a
| T b y vy c => T (pushdown_left a b) y vy c
end.
Fixpoint delete (x: key) (s: tree) : tree :=
match s with
| E => E
| T a y v' b => if  x <? y then T (delete x a) y v' b
else if y <? x then T a y v' (delete x b)
else pushdown_left a b
end.
End TREES.
Arguments E {V}.
Arguments T {V} _ _ _ _.
Arguments insert {V} x v s.
Arguments tree_inb {V} x s.
Arguments pushdown_left {V} a bc.
Arguments delete {V} x s.
Fixpoint treebox_rep (t: tree val) (b: val) : mpred :=
match t with
| E => data_at Tsh (tptr t_struct_tree) nullval b
| T l x p r =>
!! (Int.min_signed <= x <= Int.max_signed) &&
data_at Tsh (tptr t_struct_tree) p b *
field_at Tsh t_struct_tree [StructField _key] (Vint (Int.repr x)) p *
treebox_rep l (field_address t_struct_tree [StructField _left] p) *
treebox_rep r (field_address t_struct_tree [StructField _right] p)
end.
Fixpoint key_store (s: tree val) (x: key) (q: val): Prop :=
match s with
| E => False
| T a y p b => if  x <? y then key_store a x q
else if y <? x then key_store b x q
else q = field_address t_struct_tree [StructField _value] p
end.
Definition key_store_ (s: tree val) (x: key): Prop :=
exists v, key_store s x v.
Definition value_at (t: tree val) (v: val) (x: Z): mpred :=
EX q: val,
!! (key_store t x q) &&
data_at Tsh (tptr Tvoid) v q.

(* TODO: maybe not useful *)
Lemma treebox_rep_spec: forall (t: tree val) (b: val),
treebox_rep t b =
data_at Tsh (tptr t_struct_tree)
match t return val with
| E => nullval
| T _ _ p _ => p
end b *
match t with
| E => emp
| T l x p r =>
!! (Int.min_signed <= x <= Int.max_signed) &&
field_at Tsh t_struct_tree [StructField _key] (Vint (Int.repr x)) p *
treebox_rep l (field_address t_struct_tree [StructField _left] p) *
treebox_rep r (field_address t_struct_tree [StructField _right] p)
end.