type counter = Counter.counter
type sort =
| Predicate
| Function
| Skolem
| Connection
| FD_Relation
| FD_Size_Marker
| FD_Element
| FD_Symbol
type symbol = {
name: string;
pretty: string;
arity: int;
id: int;
sort: sort;
}
type symbol_table = {
id_counter: counter;
symbols: symbol Tools.StringTable.t;
}
let global =
{
id_counter = Counter.create ();
symbols = Tools.StringTable.create 128;
}
let name (symbol: symbol) : string =
symbol.name
let pretty_name (symbol: symbol) : string =
symbol.pretty
let arity (symbol: symbol) : int =
symbol.arity
let id (symbol: symbol) : int =
symbol.id
let sort (symbol: symbol) : sort =
symbol.sort
let to_string ?(pretty: bool = true) (symbol: symbol) : string =
if pretty then
pretty_name symbol
else
name symbol
let sort_to_string (sort: sort) : string =
match sort with
| Predicate -> "Predicate"
| Function -> "Function"
| Skolem -> "Skolem"
| Connection -> "Connection"
| FD_Relation -> "FD_Relation"
| FD_Size_Marker -> "FD_Size_Marker"
| FD_Element -> "FD_Element"
| FD_Symbol -> "FD_Symbol"
let equal (symbol1: symbol) (symbol2: symbol) : bool =
if Const.debug then begin
if
(symbol1 == symbol2)
!=
(symbol1.id = symbol2.id)
then begin
print_endline (symbol1.name ^ "/" ^ string_of_int symbol1.arity ^ ": " ^ string_of_int symbol1.id);
print_endline (symbol2.name ^ "/" ^ string_of_int symbol2.arity ^ ": " ^ string_of_int symbol2.id);
failwith "Symbol.equal";
end
end;
symbol1 == symbol2
let compare (symbol1: symbol) (symbol2: symbol) : int =
Tools.compare_int (id symbol1) (id symbol2)
let compare_name (symbol1: symbol) (symbol2: symbol) : int =
Pervasives.compare (name symbol1) (name symbol2)
module SymbolTable =
Hashtbl.Make (
struct
type t = symbol
let equal = equal
let hash = id
end
)
let is_predicate (symbol: symbol) : bool =
symbol.sort == Predicate
let is_function (symbol: symbol) : bool =
symbol.sort == Function
let is_input (symbol: symbol) : bool =
is_function symbol || is_predicate symbol
let is_skolem (symbol: symbol) : bool =
symbol.sort == Skolem
let is_connection (symbol: symbol) : bool =
symbol.sort == Connection
let is_fd_relation (symbol: symbol) : bool =
symbol.sort == FD_Relation
let is_fd_element (symbol: symbol) : bool =
symbol.sort == FD_Element
let is_fd_size_marker (symbol: symbol) : bool =
symbol.sort == FD_Size_Marker
let is_fd_symbol (symbol: symbol) : bool =
symbol.sort == FD_Symbol
let create_symbol (sort: sort) (name: string) (pretty: string) (arity: int) : symbol =
try
let symbol =
Tools.StringTable.find global.symbols name
in
if Const.debug && symbol.arity != arity then begin
failwith ("Symbol.create_symbol: " ^ name ^ " to be registered with arity " ^ string_of_int arity
^ " but already registered with arity " ^ string_of_int symbol.arity);
end;
if Const.debug && symbol.sort != sort then begin
failwith ("Symbol.create_symbol: " ^ name ^ " to be registered with sort " ^ sort_to_string sort
^ " but already registered with sort " ^ sort_to_string symbol.sort);
end;
symbol
with
| Not_found ->
let id =
try
Counter.next global.id_counter
with
| Counter.OVERFLOW ->
raise (Const.NO_SOLUTION "Symbol.create_symbol: symbol id overflow")
in
let symbol = {
name = name;
pretty = pretty;
arity = arity;
id = id;
sort = sort;
}
in
Tools.StringTable.add global.symbols name symbol;
symbol
let create_predicate (name: string) (arity: int) : symbol =
create_symbol Predicate name name arity
let create_function (name: string) (arity: int) : symbol =
create_symbol Function name name arity
let create_skolem ?(arity: int = 0) ?(name: string option = None) () : symbol =
let name =
match name with
| None ->
"__sko" ^ (string_of_int (Counter.value global.id_counter + 1))
| Some name->
name
in
create_symbol Skolem name name arity
let create_connection (arity: int) : symbol =
let name =
"__con" ^ (string_of_int (Counter.value global.id_counter + 1))
in
create_symbol Connection name name arity
let get_fd_relation (arity: int) : symbol =
let name =
"__fd_r" ^ string_of_int (arity - 2)
in
let pretty =
"r_"
in
create_symbol FD_Relation name pretty arity
let get_fd_size_marker (size: int) : symbol =
let name =
"__fd_m" ^ string_of_int size
in
let pretty =
"more" ^ string_of_int size
in
create_symbol FD_Size_Marker name pretty 0
let get_fd_element (number: int) : symbol =
let name =
("__fd_e" ^ string_of_int number)
in
let pretty =
string_of_int number
in
create_symbol FD_Element name pretty 0
let create_fd_symbol (symbol: symbol) : symbol =
create_symbol FD_Symbol ("__fd_s_" ^ (name symbol)) (name symbol) 0
let get_symbol_from_fd_symbol (symbol: symbol) : symbol =
if is_fd_symbol symbol then begin
try
Tools.StringTable.find global.symbols symbol.pretty
with
| Not_found ->
failwith ("Symbol.get_symbol_from_fd_symbol: unknown: " ^ symbol.name)
end
else
failwith ("Symbol.get_symbol_from_fd_symbol: no fd symbol: " ^ symbol.name)
let equality =
create_symbol Predicate "=" "=" 2
let diff =
create_symbol Skolem "diff" "diff" 2
let lemma_root =
create_symbol Predicate "__lm_regr_root__" "__lm_regr_root__" 0