let make_indexes default  =   
  
  (** A hash table maps all known identifiers to integer values. It provides one direction of the global mapping. *)

  let table =
    Hashtbl.create 1023
  and
  
  (** An infinite array maps all known integer values to identifiers. It provides the other direction of the global mapping. *)

  array =
    InfiniteArray.make default (* Dummy data. *) 
    
    (** A global counter contains the next available integer label. *)

  and counter =
    ref 0
  in
  
  (** import s associates a unique label with the identifier s, possibly extending the global mapping if s was never encountered so far. Thus, if s and t are equal strings, possibly allocated in different memory locations, import s and import t return the same label. The identifier s is recorded and may be later recovered via export. *)

  let import s =
    try
      Hashtbl.find table s
    with Not_found ->
      let i = !counter in
      Hashtbl.add table s i;
      InfiniteArray.set array i s;
      counter := i + 1;
      i

  
  (** export i provides access to the inverse of the global mapping, that is, associates a unique identifier with every label. The identifier associated with a label is the one originally supplied to import. *)

  and export i =
    assert (i < !counter);
    InfiniteArray.get array i
      
  and find s = 
    Hashtbl.find table s
  in
    (import, export, find)