(*
A polymorphic symbol table. 
A symbol table is a data structure associating names (strings) with values. It
is useful for keeping track of binidngs. Bindings can be shadowed --- the
active binding is the one made most recently.
*)

module SymTab
  (* A symbol table with values of type 'a. *)
  //type SymTab<'a> = SymTab of (string * 'a) list    
  //  when 'a : equality

  (* Create an empty symbol table. *)
  val empty : unit -> SymTab<'a> when 'a : equality 

  (* Look up the active binding for the name. *)
  val lookup : string -> SymTab<'a> -> Option<'a>

  (* Bind the name to a value, shadowing any existing
     binidngs with the same name. *)
  val bind : string -> 'a -> SymTab<'a> -> SymTab<'a>

  (* Remove all existing bindings of the given name. *)
  val remove : string -> SymTab<'a > -> SymTab<'a>

  (* Remove all existing bindings of all the given names. *)
  val removeMany : string list -> SymTab<'a > -> SymTab<'a >

  (* Combine two symbol tables. The first table shadows the second. *)
  val combine : SymTab<'a > -> SymTab<'a > -> SymTab<'a >

  (* Create a symbol table from a list of name-value pairs.       
       In case of duplicates, the bindings are shadowed in reverse order from
       the head of the list. That is, the active binding will ne the one
       closest to the head of the list. *)
  val fromList : (string * 'a) list -> SymTab<'a >
  val toList   : SymTab<'a > -> (string * 'a) list

