liquid-fixpoint-0.1.0.0: external/fixpoint/hornToInterproc.ml
module F = Format
module BS = BNstats
module Co = Constants
module SM = Misc.StringMap
module H = Ast.Horn
module Misc = FixMisc open Misc.Ops
let tmpname1 = "tmp"
(***************************************************************************)
(************************* Parse Horn Clauses ******************************)
(***************************************************************************)
let clean f =
Misc.map_lines_of_file f tmpname1 begin fun s ->
if String.length s > 3 && String.sub s 0 3 = "hc(" then
let ss = Misc.chop s ", " in
match ss with
| [s1; s2; _] -> Printf.sprintf "%s, %s).\n\n" s1 s2
| ss -> assertf "bad string: %s" (String.concat "####" ss)
else ""
end;
tmpname1
let parse f : H.t list =
let ic = f |> clean >> Errorline.startFile |> open_in in
let rv = Lexing.from_channel ic |> HornParse.horns HornLex.token in
let _ = close_in ic in
rv
(****************************************************************************)
(******************* Preprocess HC to get global information ****************)
(****************************************************************************)
type t = {
aritym : int SM.t; (* k -> arity *)
bindm : string list SM.t; (* k -> local bindings *)
argn : int; (* max-fun-args across all ks *)
cm : H.t list SM.t; (* k -> cs *)
}
let create (cs: H.t list) : t =
let cm = cs |> Misc.kgroupby (fun ((k,_),_) -> k)
|> List.fold_left (fun cm (k,cs) -> SM.add k cs cm) SM.empty in
let aritym = SM.map (function ((k, xs),_)::_ ->
let n = List.length xs in
(* let _ = Printf.printf "Arity(%s) using %s is %d \n" k
(String.concat "," xs) n in *)
n) cm in
let bindm = SM.map ((Misc.flap H.support) <+> Misc.sort_and_compact) cm in
let argn = SM.fold (fun _ a n -> max a n) aritym 0 in
{ aritym = aritym; bindm = bindm; argn = argn; cm = cm }
(****************************************************************************)
(**************************** Generic Sequencers ****************************)
(****************************************************************************)
let gen f sep xs =
xs |> Misc.map f |> String.concat sep
let geni f sep xs =
xs |> Misc.mapi f |> String.concat sep
let defn x n =
geni (fun i _ -> Printf.sprintf "%s%d : int" x i) ", " (Misc.range 0 n)
(****************************************************************************)
(********************************* Translation ******************************)
(****************************************************************************)
let tx_gd = function
| H.C p -> Printf.sprintf " assume %s;" (Misc.fsprintf Ast.Predicate.print p)
| H.K (k, xs) -> Printf.sprintf "%s\n () = %s(%s);"
(geni (Printf.sprintf " a%d = %s;") "\n" xs)
k
(geni (fun i _ -> Printf.sprintf "a%d" i) "," xs)
let tx_hd = function
| "error", _ -> " fail;"
| _, xs -> Printf.sprintf " assume %s;"
(geni (fun i x -> Printf.sprintf " z%d == %s " i x) " and " xs)
let tx_t k (head, guards) : string =
Printf.sprintf " if brandom then\n%s\n%s\n else" (gen tx_gd "\n" guards) (tx_hd head)
let tx_def me = function
| "error" ->
""
| k ->
let n = try SM.find k me.aritym with Not_found -> assertf "ERROR:no arity for %s" k in
let _ = Printf.printf "Arity(%s) := %d \n" k n in
Printf.sprintf "proc %s(%s) returns ()" k (defn "z" n)
let tx_k me (k, cs) =
Printf.sprintf
"
%s
var %s, %s;
begin
%s
halt;
%s
end
"
(tx_def me k)
(defn "a" me.argn)
(gen (Printf.sprintf "%s : int") ", " (SM.find k me.bindm))
(gen (tx_t me) "\n" cs)
(gen (fun _ -> "endif;") " " cs)
let rewrite_eq s =
if Misc.is_substring s "assume" then
Misc.replace_substring " = " " == " s
else s
let tx cs =
let me = create cs in
me.cm
|> Misc.sm_to_list
|> List.map (tx_k me)
|> String.concat "\n\n"
|> Misc.flip Misc.chop "\n"
|> List.map rewrite_eq
|> String.concat "\n"
(***************************************************************************)
(***************************** Output Clauses ******************************)
(***************************************************************************)
let dump f cs =
cs >> Format.printf "*************Horn Clauses************\n\n%a\n\n\n" (Misc.pprint_many true "\n" H.print)
|> tx
>> Format.printf "***********Interproc Program*********\n\n%s\n\n\n"
|> Misc.write_to_file (f^".ipc")
let usage = "hornToInterproc.native [filename.pl]"
let main usage =
print_now "\n \n \n \n \n";
print_now "========================================================\n";
print_now "© Copyright 2009 Regents of the University of California.\n";
print_now "All Rights Reserved.\n";
print_now "========================================================\n";
print_now (Sys.argv |> Array.to_list |> String.concat " ");
print_now "\n========================================================\n";
let fs = ref [] in
let _ = Arg.parse Co.arg_spec (fun s -> fs := s::!fs) usage in
match !fs with
| [f] -> parse f |> dump f
| _ -> assertf "I choke on too many/few files!"
let _ = main usage