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


(** Defines a number of types and functions related to formula construction 
   and representation.
*)

open Sys_state

type quant = FORALL
       |EXISTS

type binder = quant * Global.var_id * Global.type_id

type relationtype =
    GT
  | GTE
  | LT
  | LTE
  | EQ
  | NEQ

type binoptype =
    PLUS
  | MINUS
  | MULT
  | DIV
  | INTDIV
  | MOD
  | POW

type variable_list = (Global.var_id * Global.type_id) list
(** stores a list of variables with their associated type ids (used to store free variable lists, and bound variable lists) *)

type expression_variables = {freevars               : variable_list;
                             existential_bound_vars : variable_list;
                             universal_bound_vars   : variable_list}
(** used to store the information on variables in an expression *)

type exprtype =
    E of Global.pred_id option * expression_variables* Global.type_id * expression * Escjava_label.label
and expression =
    REL of relationtype * exprtype * exprtype  (*bool*) (*reals as inputs*)
  | AND of exprtype list(*bool*)
  | OR of exprtype list(*bool*)
  | NOT of exprtype(*bool*)
  | XOR of exprtype * exprtype
  | IFF of exprtype * exprtype(*bool*)
  | SYM of string (* either boolean or not(do a lookup)*)
  | VAR of Global.var_id
  | INT of int(*real*)
  | STRING of string
  | FUN of string * exprtype list (*non boolean(handled by us)*)
  | PRED of string * exprtype list(*boolean (handled by us)*)
  | BINOP of binoptype * exprtype * exprtype(*real*)
  | UMINUS of exprtype(*real*)
  | ID of int * string * Escjava_label.label list (* the label list holds all the labels that were in the terms that collapsed into this ID*)
  | ITE of exprtype * exprtype * exprtype (*either boolean or not*)
  | QUANT of binder list * exprtype

type polarity = POS | NEG | BOTH

exception Referenced_noninstantiated_variable

exception Referenced_nullterm_id

(** an expression_variables variable that has an empty list for each of the fields *)
val empty_expression_variables : expression_variables

(** new_expr_vars free_vars existential_vars universal_vars
    Creates a new expression_variables var with free_vars, existential_vars and universal_vars*)
val new_expr_vars : variable_list -> variable_list -> variable_list -> expression_variables

(** takes as input an expression_vars type and changes the existentials to universal and vice versa, the free variables are unchanged *)
val reverse_variable_polarity: expression_variables -> expression_variables

(** returns an exprtype of a string*)
val string_expr : string -> exprtype

(** returns an exprtype of an int*)
val int_expr : int -> exprtype

(** returns the complement of a relation *)
val relcompl : relationtype -> relationtype

(** contains a freelist 
returns true if a is in freelist*)
val contains_var : Global.var_id -> (Global.var_id *Global.term_id)  list -> bool

(** returns a freelist without the specified variable*)
val remove_var : Global.var_id -> (Global.var_id *Global.term_id) list -> (Global.var_id *Global.term_id) list

val remove_var_from_binder_list : Global.var_id -> binder list -> binder list

(** merges two freelists so that no variable in list 1 or list 2 is repeated*)
val merge_free_lists : variable_list -> variable_list -> variable_list 

val term_list_to_string_of_term_ids : exprtype list -> string

val print_binder_list : binder list -> unit 

val print_binder : binder -> unit

val variable_list_to_string : variable_list -> string 

(* translates an exprtype into a string with full debugging information *)
val debugging_exprtype_to_string : exprtype -> string

(* print out an exprtype *)
val print_exprtype : exprtype -> unit

(* conversion of exprtype to a string representation *)
val exprtype_to_string : exprtype -> string

val expr_to_string : expression -> string

val negate : polarity -> polarity

val flip_binder : binder -> binder 

val is_forall : binder -> bool

val term_ids : exprtype list -> Global.term_id list

val printlist : int list -> unit

val printlists : int list list -> unit

val is_lit : exprtype -> bool

val add_label_to_expr : exprtype -> Escjava_label.label -> exprtype

val set_expr_guard : exprtype -> bool -> exprtype

val make_not_expr : exprtype -> exprtype

val gather_labels_from_exprlist : exprtype list -> Escjava_label.label list

val gather_labels_from_expr : exprtype -> Escjava_label.label list

val register_predicate_label_from_expr: exprtype -> unit

val is_guarded_expr : exprtype -> bool

val is_term : exprtype -> bool
