exception Referenced_undefined_term
exception Empty_term_database
exception Term_removal_error
exception Ground_term_added_as_template
exception Pred_added_as_term_template

type term_template = {freevariables: Formula.variable_list;
                      term    : Formula.exprtype}

class term_db :
object
  (** returns true if the term_db has changed since the last call to enable term registration *)
  method term_db_has_been_updated_since_registration_enabled : bool

  (** Should be called when a round of term generation has been completed so that the new
      terms can be identified in the next round of term generation *)
  method mark_new_terms : unit
  
  (** Adds a new table of term ids for the new sort *)
  method add_term_sort : int -> unit

  (** Adds a [term_id] to the database. 
   If the [term_id] already has been added, does nothing. *)
  method add_term : int -> Global.term_id -> unit

  (** get the size of the largest term_db *)
  method get_largest_term_db_size : int

  (** get the size of the term_db for the specified type*)
  method get_term_db_size : Global.type_id -> int

  (** get the term indexed by [index]  from the term_db for sort_id *)
  method get_term_id : Global.type_id -> int -> Global.term_id

  (** Returns a random [term_id] of the  specified [type_id]*)
  method get_random_term: Global.type_id -> Global.term_id

  (** Call this method to allow new terms to be registered in the term database until disable_term_registration is called*)
  method enable_term_registration : unit 

  (** Call this method to prevent new terms from being registered in the term database until enable_term_registration is called*)
  method disable_term_registration : unit 
    
  (** returns the position of the first term added after the last call to mark_new_terms for to specified type *)
  method get_first_new_term_position: Global.type_id -> int 

  (** returns a list of nonground term templates *)
  method get_templates : term_template list

  (** call add_template whenever a new nonground term is found 
  (raises Ground_term_added_as_template if sent a ground term or
   raises Pred_added_as_term_template if sent a predicate) *)
  method add_template : Formula.exprtype -> unit

  (** clears the entire term database but leaves the list of term templates unchanged*)
  method clear : unit

  (** Removes the last term of the specified type from the term database.  
      Raises Term_removal_error if there are no terms to be removed from from the specified term type database *)
  method remove_term : Global.type_id -> unit

  (** prints the list of templates *)
  method print_templates : unit
  
  (** prints the entire database of known ground terms available for instantiation *)
  method print_term_db : unit
end

(** The term database used by the rest of sammy *)
val term_db: term_db
