(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*          Xavier Leroy, INRIA Paris-Rocquencourt                     *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the GNU General Public License as published by  *)
(*  the Free Software Foundation, either version 2 of the License, or  *)
(*  (at your option) any later version.  This file is also distributed *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)
(** Applicative finite maps are the main data structure used in this project.  A finite map associates data to keys.  The two main operations are [set k d m], which returns a map identical to [m] except that [d] is associated to [k], and [get k m] which returns the data associated to key [k] in map [m].  In this library, we distinguish two kinds of maps: - Trees: the [get] operation returns an option type, either [None] if no data is associated to the key, or [Some d] otherwise. - Maps: the [get] operation always returns a data.  If no data was explicitly associated with the key, a default data provided at map initialization time is returned.  In this library, we provide efficient implementations of trees and maps whose keys range over the type [positive] of binary positive integers or any type that can be injected into [positive].  The implementation is based on radix-2 search trees (uncompressed Patricia trees) and guarantees logarithmic-time operations.  An inefficient implementation of maps as functions is also provided. *)
(* To avoid useless definitions of inductors in extracted code. *)
Local Unset Elimination Schemes.
Local Unset Case Analysis Schemes.
Set Implicit Arguments.
(** * The abstract signatures of trees *)
Module Type TREE.
Parameter elt: Type.
Parameter elt_eq: forall (a b: elt), {a = b} + {a <> b}.
Parameter t: Type -> Type.
Parameter empty: forall (A: Type), t A.
Parameter get: forall (A: Type), elt -> t A -> option A.
Parameter set: forall (A: Type), elt -> A -> t A -> t A.
Parameter remove: forall (A: Type), elt -> t A -> t A.

(* Specifications: *)
(** The ``good variables'' properties for trees, expressing commutations between [get], [set] and [remove]. *)
Axiom gempty:
forall (A: Type) (i: elt), get i (empty A) = None.
Axiom gss:
forall (A: Type) (i: elt) (x: A) (m: t A), get i (set i x m) = Some x.
Axiom gso:
forall (A: Type) (i j: elt) (x: A) (m: t A),
i <> j -> get i (set j x m) = get i m.
Axiom gsspec:
forall (A: Type) (i j: elt) (x: A) (m: t A),
get i (set j x m) = if elt_eq i j then Some x else get i m.
(* We could implement the following, but it's not needed for the moment. Hypothesis gsident: forall (A: Type) (i: elt) (m: t A) (v: A), get i m = Some v -> set i v m = m. Hypothesis grident: forall (A: Type) (i: elt) (m: t A) (v: A), get i m = None -> remove i m = m. *)
Axiom grs:
forall (A: Type) (i: elt) (m: t A), get i (remove i m) = None.
Axiom gro:
forall (A: Type) (i j: elt) (m: t A),
i <> j -> get i (remove j m) = get i m.
Axiom grspec:
forall (A: Type) (i j: elt) (m: t A),
get i (remove j m) = if elt_eq i j then None else get i m.
(** The ``good variables'' properties for trees, expressing commutations between [get], [set] and [remove]. *)
Axiom gempty:
forall (A: Type) (i: elt), get i (empty A) = None.
Axiom gss:
forall (A: Type) (i: elt) (x: A) (m: t A), get i (set i x m) = Some x.
Axiom gso:
forall (A: Type) (i j: elt) (x: A) (m: t A),
i <> j -> get i (set j x m) = get i m.
Axiom gsspec:
forall (A: Type) (i j: elt) (x: A) (m: t A),
get i (set j x m) = if elt_eq i j then Some x else get i m.
(* We could implement the following, but it's not needed for the moment. Hypothesis gsident: forall (A: Type) (i: elt) (m: t A) (v: A), get i m = Some v -> set i v m = m. Hypothesis grident: forall (A: Type) (i: elt) (m: t A) (v: A), get i m = None -> remove i m = m. *)
Axiom grs:
forall (A: Type) (i: elt) (m: t A), get i (remove i m) = None.
Axiom gro:
forall (A: Type) (i j: elt) (m: t A),
i <> j -> get i (remove j m) = get i m.
Axiom grspec:
forall (A: Type) (i j: elt) (m: t A),
get i (remove j m) = if elt_eq i j then None else get i m.