(*
This file is part of the dpll(t) engine sammy
Copyright (C) 2004  The University of Iowa
Michael Decoster
George Hagen
                                                                                
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.
*)
                                                                                

let debug=Global.debug

let pred_db=Sys_state.pred_db
let cstore=Sys_state.cstore
let theory=cstore#theory

let add_pred = pred_db#add_pred
let add_uninterpreted_pred = pred_db#add_uninterpreted_pred
let add_quant_abs_pred = pred_db#add_quantified_abstraction_pred
let add_abs_pred = pred_db#add_uninterpreted_abstract_pred
let get_lit = pred_db#get_lit

let bool_type_id=theory#boolType
let true_id=theory#true_id

let remove_pred idopt= 
      match idopt with 
        Some id->pred_db#remove_pred cstore#unregister_pred id
      | _ -> ()


let is_pred id = try pred_db#get_pred id; true
                 with Pred_db.Pred_not_found(_) -> false

(*******************)

(* makes an interpreted propositional (non-functional) predicate *)
let make_proposition_pred (sym:string) =
  let new_id = theory#decVariable sym bool_type_id in
  add_pred new_id sym;
  new_id

(* makes an uninterpreted, abstract pred, returns its id *)
(* note the unit parameter *)
let make_abs_pred () =
  let new_id = theory#next_id in
    add_abs_pred new_id;
    new_id
  
(* makes an quantified uninterpreted, abstract pred, returns its id *)
(* note the unit parameter *)
let make_quant_abs_pred () =
  let new_id = theory#next_id in
    add_quant_abs_pred new_id;
    new_id

(* makes an unnamed boolean pred object, returns its id *)
let make_uninterpreted_pred () =
  let new_id = theory#next_id in
  add_uninterpreted_pred new_id ("_"^(string_of_int new_id));
  new_id

(* marks an existing predicate as interpreted (safe to do after construction) *)
(* also declares it to the theory (in case it wasn't previously) *)
let mark_interpreted (pid:Global.pred_id) =
  let pred = pred_db#get_pred pid in
  theory#decOldPred (Pred.formula pred) pid;
  Pred.set_interpreted pred true

(* makes an uninterpreted pred object, returns its id *)
let make_named_uninterpreted_pred (sym:string) =
  let new_id = theory#next_id in
    add_uninterpreted_pred new_id sym;
    new_id

let make_true_pred () =
  if not (is_pred true_id) then
    begin
      let true_pred = pred_db#get_pred (make_proposition_pred "TRUE") in 
      let true_lit = pred_db#get_lit true_id in
      Satbox.insert_clause [Pred.id true_pred]
    end


let appDiv = theory#appDiv
(** Returns term_id for x/y *)

let appFunction = theory#appFunction
(** Returns term_id for f(t1,...,tn) *)

let appIntDiv = theory#appIntDiv
(** Returns term_id for x DIV y *)

let appMinus = theory#appMinus
(** Returns term_id for x-y *)

let appMod = theory#appMod
(** Returns term_id for x%y *)

let appMult = theory#appMult
(** Returns term_id for x*y *)

let appPlus = theory#appPlus
(** Returns term_id for x+y *)

let appPow = theory#appPow
(** Returns term_id for x^y *)

let appUnaryMinus = theory#appUnaryMinus
(** Returns term_id for -x *)

let create_equals = theory#create_equals
(** Returns the id for x=y *)

let create_greater_than = theory#create_greater_than
(** Returns the id for x>y *)

let create_greater_than_or_equals = theory#create_greater_than_or_equals
(** Returns the id for x>=y *)

let create_less_than = theory#create_less_than
(** Returns the id for x<y *)

let create_less_than_or_equals = theory#create_less_than_or_equals
(** Returns the id for x=<y *)
