(* given a key and a search tree, we return either an associated value
   or the proof of its non-existence *)

 Definition occ_dec_spec (k : key) (t : btree) :=
   search_tree t -> {v : data | occ v k t} + {(forall v : data, ~ occ v k t)}.Definition occ_dec : forall (k : key) (t : btree), occ_dec_spec k t.(* t' is obtained by inserting (n,v) into t *)

 Inductive INSERT (n : key) (v : data) (t t' : btree) : Prop :=
     insert_intro :
       (forall (p : key) (v' : data), occ v' p t -> p = n \/ occ v' p t') ->
       occ v n t' ->
       (forall (p : key) (v' : data),
        occ v' p t' -> occ v' p t \/ n = p /\ v = v') ->
       search_tree t' -> INSERT n v t t'.(* t' is obtained by inserting (n,v) into t *)

 Inductive INSERT (n : key) (v : data) (t t' : btree) : Prop :=
     insert_intro :
       (forall (p : key) (v' : data), occ v' p t -> p = n \/ occ v' p t') ->
       occ v n t' ->
       (forall (p : key) (v' : data),
        occ v' p t' -> occ v' p t \/ n = p /\ v = v') ->
       search_tree t' -> INSERT n v t t'.Definition insert_spec (n : key) (v : data) (t : btree) : Set :=
   search_tree t -> {t' : btree | INSERT n v t t'}.

(* Specifications: *)
Lemma insert_leaf : forall (n : key) (v : data), INSERT n v leaf (bnode n v leaf leaf).
Lemma insert_l : forall (n p : key) (v v' : data) (t1 t'1 t2 : btree), Key.lt n p -> search_tree (bnode p v' t1 t2) -> INSERT n v t1 t'1 -> INSERT n v (bnode p v' t1 t2) (bnode p v' t'1 t2).
Lemma insert_r : forall (n p : key) (v v' : data) (t1 t2 t'2 : btree), Key.lt p n -> search_tree (bnode p v' t1 t2) -> INSERT n v t2 t'2 -> INSERT n v (bnode p v' t1 t2) (bnode p v' t1 t'2).
Lemma insert_eq : forall (n : key) (v v' : data) (t1 t2 : btree), search_tree (bnode n v t1 t2) -> INSERT n v' (bnode n v t1 t2) (bnode n v' t1 t2).