(*
This file is part of the dpll(t) engine sammy
Copyright (C) 2004  The University of Iowa
Michael Decoster
                                                                                
This program is free software; you can redistribute it and/or
modify it 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 program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
                                                                                
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*)

(** Database of predefined background theories. *)                                                                                

(** should be raised if a duplicate sort is attempted to be declared*)
exception No_duplicate_sorts_allowed

(** should be raised if a function is redeclared with a different signature*)
exception No_function_overloading

(** should be raised if a predicate is redeclared with a different signature*)
exception No_predicate_overloading

(** should be raised if we attempt to load an unrecognized logic *)
exception LogicNotFound of string


(** groups a sort name with its id to be used as an object *)
class sort : string ->
object
  method set_sort_id : Global.type_id -> unit
  method get_name : string (** @return the name of the sort *)
  method get_id : Global.type_id (** @return the id of the sort *)
end

(** a predefined sort for the real numbers *)
val real_sort : sort

(** a predefined sort for the arrays from reals to reals *)
val real_real_array_sort : sort

(** a predefined sort for the integer numbers *)
val int_sort : sort

(** a predefined sort for the arrays from ints to ints *)
val int_int_array_sort : sort

val theory_initialized : bool ref

val get_function_id : string -> Global.term_id  (** returns a declared function/predicate symbol's term id *)
val get_function_type : string -> Global.type_id (** returns a declared function/predicate symbol's type id *)

(** stores everything needed to know about a background theory and for building a background theory*)
class theory_spec : unit ->
object

  method initialize_theory : unit (** gets the current theory ready to be used.  Once the theory has been initialized, no more changes may be made to the main theory*)

  method print_sorts :  unit (** debuging function to see what the current values in all the theory's sorts are *)

  method get_real_sort_name : string -> string (** provides a mapping between the input languages sorts to actual interpreted sorts *)

  method get_real_function_name : string -> string (** provides a mapping between the input language's functions to actual interpreted functions *)

  method get_real_predicate_name : string -> string (** provides a mapping between the input language's predicates to actual interpreted predicates *)

  method get_numeral_sort : sort                    (** provides the sort that numerals should be interpreted with *)

  method set_numeral_sort : sort -> unit            (** sets the sort that numerals should be interpreted with *)

  method add_sort_synonym : string -> string -> unit (** adds a mapping from the input language's sorts to an interpreted sort name *)

  method add_predicate_synonym : string -> string -> unit (** adds a mapping from the input language's predicates to an interpreted predicate name *)

  method add_function_synonym : string -> string -> unit (** adds a mapping from the input language's functions to an interpreted function name *)

  method is_sort : string -> bool (** returns true if the specified sort name has been declared *) 

  method get_sort_ts : string -> sort (** takes in a sort name and returns the corresponding sort*)

  method get_sort_by_id : Global.type_id -> sort (** takes in a sort id and returns the corresponding sort*)

  method add_sort : string -> unit (** adds a new uninterpreted sort to the theory *)

  method is_function : string -> bool (** returns true if the specified function name has been declared*)

  method get_function : string -> (int*sort list*sort) (** takes in a function name and returns its id, a list of its argument sorts, and its return sort *)

  method add_function : string -> sort list -> sort -> unit (** adds a function with the specified name, argument sorts, and return sort to the theory *)

  method is_predicate : string -> bool (** returns true if the specified predicate name has been declared*)

  method get_predicate : string -> (int * sort list) (** takes in a predicate name and returns its id, and a list of its argument sorts*)

  method add_predicate : string -> sort list -> unit (** adds a predicate with the specified name, and argument sorts to the theory *)

end

(** changes the current theory to one which has been declared by the specified name*)
val change_current_theory : string -> unit

val initialize_current_theory : unit -> unit

val print_all_sorts : unit -> unit

val get_real_sort_name : string -> string 
(** translates input language to theory equivalent *)

val get_real_function_name : string -> string
(** translates input language to theory equivalent *)

val get_real_predicate_name : string -> string
(** translates input language to theory equivalent *)

(** adds a theory to the set of defined theories*)
val add_theory : string -> theory_spec -> unit 

(** adds an extra sort that is not in the original theory*)
val add_extra_sort : string -> unit

(** adds an extra predicate that is not in the original theory using the specified name and the argument sort list given*)
val add_extra_pred : string -> sort list -> unit

(** adds an extra function that is not in the original theory using the specified name, the given argument sort list, and the given return sort *)
val add_extra_func : string -> sort list -> sort -> unit

(** returns the sort that numerals should be interpreted as according to the current theory*)
val get_numeral_sort : unit -> sort

(** returns the corresponding sort from either the theory or from the extra sorts that have been declared*)
val get_sort : string -> sort

(** returns the corresponding sort from either the theory or from the extra sorts that have been declared*)
val get_sort_by_id : Global.type_id -> sort

(** takes the function name and returns the function id, argument sort list, and return sort 
from either the theory or from the extra functions that have been declared*)
val get_fun_sorts : string -> (int*sort list*sort)

(** takes the predicate name and returns the predicate id, and the argument sort list
from either the theory or from the extra predicates that have been declared*)
val get_pred_sorts : string -> (int*sort list)
