1(* hh_write module: write a given problem to various TPTP formats:
2   fof, tff1, thf0 and full thf *)
3
4open Lib;;
5open Fusion;;
6open Basics;;
7open Bool;;
8open Equal;;
9open Hl_parser;;
10open Pervasives;;
11open Tactics;;
12open Simp;;
13(*open Theorems;;*)
14open Hh_symbols;;
15open Hh_tac;;
16
17module Sm = Map.Make(struct type t = string let compare = compare end);;
18module Tmm = Map.Make(struct type t = term let compare = compare end);;
19
20let variant_name_hash s used =
21  try let i = Hashtbl.find used s in
22    let rec new_name s i =
23      let si = s ^ string_of_int i in
24      if Hashtbl.mem used si then new_name s (i + 1)
25      else (Hashtbl.replace used si 0; Hashtbl.replace used si (i + 1); si)
26    in new_name s i
27  with Not_found -> Hashtbl.replace used s 0; s
28
29let variant_name_map s used =
30  try let i = Sm.find s used in
31    let rec new_name s i =
32      let si = s ^ string_of_int i in
33      if Sm.mem si used then new_name s (i + 1)
34      else (si, Sm.add s (i + 1) (Sm.add si 0 used))
35    in new_name s i
36  with Not_found -> (s, Sm.add s 0 used)
37
38let print_vartype t =
39  let s = String.copy (dest_vartype t) in
40  escape_tyvar s 
41
42let os = output_string;;
43let rec oiter oc fn sep = function
44    [] -> ()
45  | [e] -> fn oc e
46  | h :: t -> fn oc h; os oc sep; oiter oc fn sep t;;
47
48let string_list_of_string str sep =
49  let rec slos_aux str ans =
50    if str = "" then ans else
51    try
52      let first_space = String.index str sep in
53      if first_space = 0 then
54        slos_aux (String.sub str 1 (String.length str - 1)) ans
55      else
56        slos_aux
57          (String.sub str (first_space + 1)(String.length str - 1 - first_space))
58          ((String.sub str 0 (first_space)) :: ans)
59    with
60      Not_found ->
61        List.rev (str :: ans)
62  in slos_aux str []
63;;
64
65let rec chop_listnok acc n = function
66    [] -> (List.rev acc, [])
67  | h :: t -> if n = 0 then (List.rev acc, h :: t) else chop_listnok (h :: acc) (n - 1) t;;
68
69let rec chop_listn acc n = function
70    [] -> failwith "chop_listn"
71  | h :: t -> if n = 0 then (List.rev acc, h :: t) else chop_listn (h :: acc) (n - 1) t;;
72
73(* The HO-funtype `:(A -> B) list` will be lost *)
74let name_tscs_mono_fold ho (tys, cs, used) tm () =
75  let ctys = if not ho then [type_of tm] else striplist dest_fun_ty (type_of tm) in
76  let rec name_ty ty =
77    if Hashtbl.mem tys ty then () else
78    let n =
79      if is_type ty then
80        let s, stys = dest_type ty in
81        List.iter name_ty stys;
82        String.concat "" (escape_const s :: (map (fun x -> Hashtbl.find tys x) stys))
83      else print_vartype ty in
84    let n = variant_name_hash n used in Hashtbl.replace tys ty n
85  in
86  List.iter name_ty ctys;
87  if Hashtbl.mem cs tm || is_var tm then () else
88  let n = escape_const (fst (dest_const tm)) in
89  let n = variant_name_hash n used in
90  Hashtbl.replace cs tm n
91;;
92
93let name_tscs_poly_fold (tys, cs, used) tm () =
94  let rec name_ty ty =
95    if is_type ty then
96      let s, stys = dest_type ty in
97      (if Hashtbl.mem tys s then () else
98      Hashtbl.replace tys s (variant_name_hash (escape_const s) used));
99      List.iter name_ty stys;
100    else
101      let s = dest_vartype ty in
102      (if Hashtbl.mem tys s then () else
103      Hashtbl.replace tys s (variant_name_hash (print_vartype ty) used));
104  in
105  name_ty (type_of tm);
106  if is_var tm then
107    let s = fst (dest_var tm) in
108    if Hashtbl.mem cs ("`" ^ s) then () else 
109    let n = variant_name_hash (escape_const s) used in
110    Hashtbl.replace cs ("`" ^ s) n
111  else
112  let s, _ = dest_const tm in
113  if Hashtbl.mem cs s then () else
114  let n = variant_name_hash (escape_const s) used in
115  Hashtbl.replace cs s n
116;;
117
118let rec fold_cs_vs fn tm sofar =
119  try let l,r = try dest_forall tm with Failure _ ->
120                try dest_exists tm with Failure _ ->
121                    dest_abs tm in
122      fold_cs_vs fn r (fold_cs_vs fn l sofar)
123  with Failure _ -> try
124      let l,r = try dest_conj tm with Failure _ ->
125                try dest_disj tm with Failure _ ->
126                try dest_eq tm with Failure _ ->
127                    dest_imp tm in
128      fold_cs_vs fn r (fold_cs_vs fn l sofar)
129  with Failure _ -> try
130      let tm = dest_neg tm in fold_cs_vs fn tm sofar
131  with Failure _ -> try
132      let l, r = dest_comb tm in
133      fold_cs_vs fn r (fold_cs_vs fn l sofar)
134  with Failure _ -> fn tm sofar;;
135
136let name_tscs_mono ho data tm =
137  fold_cs_vs (name_tscs_mono_fold ho data) tm ();;
138let name_tscs_poly data tm =
139  fold_cs_vs (name_tscs_poly_fold data) tm ();;
140
141let is_fun_ty = function Tyapp("fun",[ty1;ty2]) -> true | _ -> false;;
142
143let rec oty_mono ts order oc ty =
144  if is_fun_ty ty then
145    match order with
146      0 -> os oc (Hashtbl.find ts ty)
147    | 1 ->
148        let t1, t2 = dest_fun_ty ty in
149        os oc "("; oty_mono ts 0 oc t1; os oc " > "; oty_mono ts 0 oc t2; os oc ")"
150    | _ ->
151        let args, res = splitlist dest_fun_ty ty in
152        os oc "("; oiter oc (oty_mono ts (order - 1)) " > " args; os oc " > ";
153        oty_mono ts (order - 1) oc res; os oc ")"
154  else os oc (Hashtbl.find ts ty);;
155
156let rec oty_poly ts order oc ty =
157  (* try is needed for constant types in TFF *)
158  if is_vartype ty then os oc (try Hashtbl.find ts (dest_vartype ty) with Not_found -> print_vartype ty) else
159  let pr_br ty =
160    let (s, tys) = dest_type ty in
161    if order < 0 then begin
162      if tys <> [] then os oc "(";
163      os oc (Hashtbl.find ts s);
164      List.iter (fun ty -> os oc " @ "; oty_poly ts order oc ty) tys;
165      if tys <> [] then os oc ")";
166    end else begin
167      os oc (Hashtbl.find ts s);
168      if tys = [] then () else (os oc "("; oiter oc (oty_poly ts 0) "," tys; os oc ")")
169    end in
170  if is_fun_ty ty then
171    (match order with
172      0 -> pr_br ty
173    | 1 ->
174        let args, res = splitlist dest_fun_ty ty in
175        (match args with
176          [a] -> oty_poly ts 0 oc a; os oc " > "; oty_poly ts 0 oc res
177        | _ -> os oc "("; oiter oc (oty_poly ts 0) " * " args; os oc " > "; oty_poly ts 0 oc res)
178    | _ ->
179        let args, res = splitlist dest_fun_ty ty in
180        os oc "("; oiter oc (oty_poly ts (order - 1)) " > " args; os oc " > ";
181        oty_poly ts (order - 1) oc res; os oc ")")
182  else pr_br ty;;
183
184let inst_const tm =
185  if is_const tm then
186    let (n, ty) = dest_const tm in
187    let gty = get_const_type n in
188    let inst = type_match gty ty [] in
189    let rinst = map (fun (a, b) -> (b, a)) inst in
190    let tvs = tyvars gty in
191    map (fun x -> assoc x rinst) tvs
192  else [];;
193
194let rec tff_tm oc (bnd, used) cs ts tm =
195  if is_var tm then begin
196    os oc (try Tmm.find tm bnd with Not_found -> Hashtbl.find cs ("`" ^ (o fst dest_var) tm))
197  end else begin
198    let (f, args) = strip_comb tm in
199    os oc (Hashtbl.find cs (fst (dest_const f)));
200    let insts = inst_const f in
201    if args <> [] || insts <> [] then begin
202      os oc "(";
203      oiter oc (fun oc ty -> oty_poly ts 0 oc ty) "," insts;
204      (if args <> [] && insts <> [] then os oc "," else ());
205      oiter oc (fun oc e -> tff_tm oc (bnd, used) cs ts e) "," args;
206      os oc ")"
207    end
208  end;;
209
210let bindv v (bnd, used) =
211  if Tmm.mem v bnd then (bnd, used) else
212  let n = escape_var (fst (dest_var v)) in
213  let (n, used) = variant_name_map n used in
214  (Tmm.add v n bnd, used)
215;;
216
217let pr_bs_poly oc order bnd ts bs =
218  (os oc "["; oiter oc (fun oc v -> os oc (Tmm.find v bnd); os oc ":"; oty_poly ts order oc (type_of v)) "," bs;
219   os oc "]:");;
220
221let rec tff_pred oc (bnd, used) cs ts tm =
222  if is_forall tm then
223    let bs, bod = strip_forall tm in
224    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
225    os oc "!"; pr_bs_poly oc 0 bnd ts bs; tff_pred oc (bnd, used) cs ts bod
226  else if is_exists tm then
227    let bs, bod = strip_exists tm in
228    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
229    os oc "?"; pr_bs_poly oc 0 bnd ts bs; tff_pred oc (bnd, used) cs ts bod
230  else if is_conj tm then
231    (os oc "("; oiter oc (fun oc e -> tff_pred oc (bnd, used) cs ts e) " & " (conjuncts tm); os oc ")")
232  else if is_disj tm then
233    (os oc "("; oiter oc (fun oc e -> tff_pred oc (bnd, used) cs ts e) " | " (disjuncts tm); os oc ")")
234  else if is_imp tm then let l, r = dest_imp tm in
235    (os oc "("; tff_pred oc (bnd, used) cs ts l; os oc " => ";
236               tff_pred oc (bnd, used) cs ts r; os oc ")")
237  else if is_neg tm then
238    let t = dest_neg tm in (os oc "~ ("; tff_pred oc (bnd,used) cs ts t; os oc ")")
239  else if is_eq tm then let l,r = dest_eq tm in
240    if must_pred l || must_pred r then
241      (os oc "("; tff_pred oc (bnd, used) cs ts l; os oc " <=> ";
242      tff_pred oc (bnd, used) cs ts r; os oc ")")
243    else
244      (tff_tm oc (bnd, used) cs ts l; os oc " = "; tff_tm oc (bnd, used) cs ts r)
245  else
246    (os oc "p("; tff_tm oc (bnd, used) cs ts tm; os oc ")");;
247
248let tff_pred oc cs ts used_map t =
249  let tvs = type_vars_in_term t in
250  let stvs = map dest_vartype tvs in
251  let used_map = itlist (fun s m -> Sm.add s 0 m) stvs used_map in
252  (if tvs <> [] then (os oc "!["; oiter oc (fun oc e -> oty_poly ts 0 oc e; os oc " : $tType") "," tvs; os oc "]: "));
253  tff_pred oc (Tmm.empty, used_map) cs ts t
254;;
255
256let pr_bs_mono oc order bnd ts bs =
257  (os oc "["; oiter oc (fun oc v -> os oc (Tmm.find v bnd); os oc ":"; oty_mono ts order oc (type_of v)) "," bs;
258   os oc "]:");;
259
260let rec thf_tm oc (bnd, used) cs ts tm =
261  if is_forall tm then
262    let bs, bod = strip_forall tm in
263    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
264    os oc "!"; pr_bs_mono oc (-1) bnd ts bs; thf_tm oc (bnd, used) cs ts bod
265  else if is_exists tm then
266    let bs, bod = strip_exists tm in
267    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
268    os oc "?"; pr_bs_mono oc (-1) bnd ts bs; thf_tm oc (bnd, used) cs ts bod
269  else if is_abs tm then
270    let bs, bod = strip_abs tm in
271    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
272    os oc "^"; pr_bs_mono oc (-1) bnd ts bs; thf_tm oc (bnd, used) cs ts bod
273  else if is_conj tm then
274    (os oc "("; oiter oc (fun oc e -> thf_tm oc (bnd, used) cs ts e) " & " (conjuncts tm); os oc ")")
275  else if is_disj tm then
276    (os oc "("; oiter oc (fun oc e -> thf_tm oc (bnd, used) cs ts e) " | " (disjuncts tm); os oc ")")
277  else if is_imp tm then let l, r = dest_imp tm in
278    (os oc "("; thf_tm oc (bnd, used) cs ts l; os oc " => ";
279               thf_tm oc (bnd, used) cs ts r; os oc ")")
280  else if is_neg tm then
281    let t = dest_neg tm in (os oc "~ ("; thf_tm oc (bnd,used) cs ts t; os oc ")")
282  else if is_eq tm then let l,r = dest_eq tm in
283    (os oc "("; thf_tm oc (bnd, used) cs ts l;
284    os oc (if type_of l = bool_ty then " <=> " else " = ");
285    thf_tm oc (bnd, used) cs ts r; os oc ")")
286  else if is_comb tm then let hop, args = strip_comb tm in
287    (os oc "("; oiter oc (fun oc e -> thf_tm oc (bnd, used) cs ts e) " @ " (hop :: args); os oc ")")
288  else if is_const tm then os oc (Hashtbl.find cs tm)
289  else os oc (try Tmm.find tm bnd with Not_found -> failwith "thf_tm");;
290
291let output_gs oc (asms, gl) =
292  let iter (s, thm) = os oc "% Assm ["; os oc s; os oc "]: "; os oc (lstring_of_term (concl thm)); os oc "\n" in
293  List.iter iter asms;
294  os oc "% Goal: "; os oc (lstring_of_term gl); os oc "\n";;
295
296let oi oc i = os oc (string_of_int i);;
297
298let thf_gl oc ls asms gl n =
299  let ts, cs, used = Hashtbl.create 20, Hashtbl.create 50, Hashtbl.create 50 in
300  Hashtbl.add used "lambda" 0; (* LeoII throws syntax errors with 'lambda' *)
301  List.iter (name_tscs_mono true (ts, cs, used)) (gl :: asms);
302  let ohdr s1 s2 = os oc "thf("; os oc s1; os oc ", "; os oc s2; os oc ", " in
303  let otl () = os oc ").\n" in
304  os oc "%  TYPES\n";
305  Hashtbl.remove ts (parse_type "bool");
306  Hashtbl.iter (fun _ ty -> ohdr ty "type"; os oc ty; os oc " : $tType"; otl ()) ts;
307  Hashtbl.add ts (parse_type "bool") "$o";
308  os oc "%  CONSTS\n";
309  Hashtbl.remove cs (parse_term "T"); Hashtbl.remove cs (parse_term "F");
310  Hashtbl.iter (fun t s -> ohdr s "type"; os oc s; os oc " : "; oty_mono ts (-1) oc (type_of t); otl ()) cs;
311  Hashtbl.add cs (parse_term "T") "$true"; Hashtbl.add cs (parse_term "F") "$false";
312  os oc "%  AXIOMS\n";
313  List.iter2 (fun n t -> ohdr n "axiom"; thf_tm oc (Tmm.empty, Sm.empty) cs ts t; otl ()) ls asms;
314  ohdr n "conjecture"; thf_tm oc (Tmm.empty, Sm.empty) cs ts gl; otl ()
315;;
316
317let rec thff_tm oc (bnd, used) cs ts tm =
318  if is_forall tm then
319    let bs, bod = strip_forall tm in
320    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
321    os oc "!"; pr_bs_poly oc (-1) bnd ts bs; thff_tm oc (bnd, used) cs ts bod
322  else if is_exists tm then
323    let bs, bod = strip_exists tm in
324    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
325    os oc "?"; pr_bs_poly oc (-1) bnd ts bs; thff_tm oc (bnd, used) cs ts bod
326  else if is_abs tm then
327    let bs, bod = strip_abs tm in
328    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
329    os oc "^"; pr_bs_poly oc (-1) bnd ts bs; thff_tm oc (bnd, used) cs ts bod
330  else if is_conj tm then
331    (os oc "("; oiter oc (fun oc e -> thff_tm oc (bnd, used) cs ts e) " & " (conjuncts tm); os oc ")")
332  else if is_disj tm then
333    (os oc "("; oiter oc (fun oc e -> thff_tm oc (bnd, used) cs ts e) " | " (disjuncts tm); os oc ")")
334  else if is_imp tm then let l, r = dest_imp tm in
335    (os oc "("; thff_tm oc (bnd, used) cs ts l; os oc " => ";
336                thff_tm oc (bnd, used) cs ts r; os oc ")")
337  else if is_neg tm then
338    let t = dest_neg tm in (os oc "~ ("; thff_tm oc (bnd,used) cs ts t; os oc ")")
339  else if is_eq tm then let l,r = dest_eq tm in
340    (os oc "("; thff_tm oc (bnd, used) cs ts l;
341    os oc (if type_of l = bool_ty then " <=> " else " = ");
342    thff_tm oc (bnd, used) cs ts r; os oc ")")
343  else if is_comb tm then let hop, args = strip_comb tm in
344    (os oc "("; oiter oc (fun oc e -> thff_tm oc (bnd, used) cs ts e) " @ " (hop :: args); os oc ")")
345  else if is_const tm then begin
346    let insts = inst_const tm in
347    if insts <> [] then os oc "(";
348    os oc (Hashtbl.find cs (fst (dest_const tm)));
349    if insts <> [] then (List.iter (fun ty -> os oc " @ "; oty_poly ts (-1) oc ty) insts; os oc ")");
350  end
351  else os oc (try Tmm.find tm bnd with Not_found -> failwith "thff_tm");;
352
353
354let thff_pred oc used_map cs ts tm =
355  let tvs = type_vars_in_term tm in
356  (if tvs <> [] then (os oc "!["; oiter oc (fun oc e -> oty_poly ts (-1) oc e; os oc ":$tType") "," tvs; os oc "]: "));
357  thff_tm oc (Tmm.empty, used_map) cs ts tm
358;;
359
360let used_to_map h = Hashtbl.fold Sm.add h Sm.empty;;
361
362let otyquant oc ts tys =
363  if tys <> [] then begin
364    os oc "!>["; oiter oc (fun oc t -> os oc (print_vartype t); os oc ":$tType")
365      "," tys; os oc "]: " end;;
366
367let thff_gl oc ls asms gl =
368  let ts, cs, used = Hashtbl.create 20, Hashtbl.create 50, Hashtbl.create 50 in
369  List.iter (name_tscs_poly (ts, cs, used)) (gl :: asms);
370  let ohdr s1 s2 = os oc "thf("; os oc s1; os oc ", "; os oc s2; os oc ", " in
371  let otl () = os oc ").\n" in
372  os oc "%  TYPES\n";
373  Hashtbl.remove ts "bool";
374  Hashtbl.remove ts "fun";
375  Hashtbl.iter (fun t s ->
376    try
377      let ar = get_type_arity t in
378      ohdr t "type"; os oc s; os oc ":";
379      let rec prty n = if n = 0 then os oc "$tType" else (os oc "$tType > "; prty (n - 1)) in
380      prty ar; otl ()
381    with Failure _ -> ()) ts; (* Failure in get_type_arity for ` *)
382  Hashtbl.add ts "bool" "$o";
383  os oc "%  CONSTS\n";
384  Hashtbl.remove cs "T"; Hashtbl.remove cs "F";
385  (* only print constants and not types *)
386  Hashtbl.iter (fun t s -> if t.[0] <> '`' then (ohdr s "type"; os oc s; os oc " : ";
387    let ty = get_const_type t in
388    let tvs = tyvars ty in
389    otyquant oc ts tvs;
390    oty_poly ts (-1) oc ty; otl ())) cs;
391  Hashtbl.add cs "T" "$true"; Hashtbl.add cs "F" "$false";
392  os oc "%  AXIOMS\n";
393  let used_map = used_to_map used in
394  List.iter2 (fun n t -> ohdr n "axiom"; thff_pred oc used_map cs ts t; otl ()) ls asms;
395  (* Something is wrong here (I may have erased something) *)
396  ohdr ("c") "conjecture"; thff_pred oc used_map cs ts gl; otl ()
397;;
398
399
400let rec oty_isa ts oc ty =
401  if is_vartype ty then (os oc "'"; os oc (try Hashtbl.find ts (dest_vartype ty)
402    with Not_found -> print_vartype ty)) else
403  let (s, tys) = dest_type ty in
404  (if tys = [] then () else (os oc "("; oiter oc (oty_isa ts) "," tys; os oc ")"));
405  os oc (Hashtbl.find ts s);;
406
407let pr_bs_isa oc bnd ts bs =
408  os oc "(";
409  oiter oc (fun oc v -> os oc (Tmm.find v bnd); os oc "::"; oty_isa ts oc (type_of v)) ") (" bs;
410  os oc ").";;
411
412let rec otm_isa oc (bnd, used) cs ts tm =
413  if is_forall tm then
414    let bs, bod = strip_forall tm in
415    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
416    os oc "(ALL"; pr_bs_isa oc bnd ts bs; otm_isa oc (bnd, used) cs ts bod; os oc ")"
417  else if is_exists tm then
418    let bs, bod = strip_exists tm in
419    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
420    os oc "(EX"; pr_bs_isa oc bnd ts bs; otm_isa oc (bnd, used) cs ts bod; os oc ")"
421  else if is_abs tm then
422    let bs, bod = strip_abs tm in
423    let (bnd, used) = rev_itlist bindv bs (bnd, used) in
424    os oc "(%"; pr_bs_isa oc bnd ts bs; otm_isa oc (bnd, used) cs ts bod; os oc ")"
425  else if is_conj tm then
426    (os oc "("; oiter oc (fun oc e -> otm_isa oc (bnd, used) cs ts e) " & " (conjuncts tm); os oc ")")
427  else if is_disj tm then
428    (os oc "("; oiter oc (fun oc e -> otm_isa oc (bnd, used) cs ts e) " | " (disjuncts tm); os oc ")")
429  else if is_imp tm then let l, r = dest_imp tm in
430    (os oc "("; otm_isa oc (bnd, used) cs ts l; os oc " --> ";
431               otm_isa oc (bnd, used) cs ts r; os oc ")")
432  else if is_neg tm then
433    let t = dest_neg tm in (os oc "(~"; otm_isa oc (bnd,used) cs ts t; os oc ")")
434  else if is_eq tm then let l,r = dest_eq tm in
435    (os oc "("; otm_isa oc (bnd, used) cs ts l; os oc " = ";
436    otm_isa oc (bnd, used) cs ts r; os oc ")")
437  else if is_comb tm then let hop, args = strip_comb tm in
438    (os oc "("; oiter oc (fun oc e -> otm_isa oc (bnd, used) cs ts e) " " (hop :: args); os oc ")")
439  else if is_const tm then os oc (Hashtbl.find cs (fst (dest_const tm)))
440  else os oc (try Tmm.find tm bnd with Not_found -> failwith ("tm_isa:" ^ (fst (dest_var tm))));;
441
442let hash_to_list h = Hashtbl.fold (fun a b l -> (a,b) :: l) h [];;
443
444let isa_fix_names h u =
445  let l = Hashtbl.fold (fun a b c -> (a, b) :: c) h [] in
446  let itr (k, v) =
447    if v.[String.length v - 1] = '_' then
448      let n = variant_name_hash v u in
449      Hashtbl.replace h k n
450  in List.iter itr l
451;;
452
453let isa_gl oc names asms gl =
454  os oc "theory Bla imports \"~~/src/HOL/TPTP/ATP_Problem_Import\" begin\n";
455  let ts, cs, used = Hashtbl.create 20, Hashtbl.create 50, Hashtbl.create 50 in
456  Hashtbl.add used "bool" 0; Hashtbl.add used "fun" 0;
457  Hashtbl.add used "True" 0; Hashtbl.add used "False" 0;
458  Hashtbl.add used "in" 0;
459  List.iter (name_tscs_poly (ts, cs, used)) (gl :: asms);
460  isa_fix_names ts used; isa_fix_names cs used;
461  Hashtbl.remove ts "bool"; Hashtbl.remove ts "fun";
462  Hashtbl.remove cs "T"; Hashtbl.remove cs "F";
463  Hashtbl.iter (fun hty sty ->
464    try
465      let a = get_type_arity hty in
466      os oc "typedecl ";
467      (if a > 0 then (os oc "("; os oc
468                        (String.concat "," (Array.to_list (Array.init a (fun i -> "'" ^ (String.make 1 (Char.chr (65 + i))))))); os oc ") ") else ());
469      os oc sty; os oc "\n"
470    with Failure "find" -> ()
471  ) ts;
472  Hashtbl.replace ts "bool" "bool"; Hashtbl.replace ts "fun" "fun";
473  os oc "axiomatization\n";
474  oiter oc (fun oc (t, s) -> os oc s; os oc " :: \""; oty_isa ts oc (get_const_type t); os oc "\"\n") "and " (hash_to_list cs);
475  Hashtbl.replace cs "T" "True"; Hashtbl.replace cs "F" "False";
476  os oc "axiomatization where\n";
477  oiter oc (fun oc (n, t) -> os oc n; os oc ": \""; otm_isa oc (Tmm.empty, Sm.empty) cs ts t; os oc "\"\n") "and " (zip (rev names) asms);
478  os oc "lemma conjecture:\n  \"";
479  otm_isa oc (Tmm.empty, Sm.empty) cs ts gl; os oc "\"\n"
480;;
481
482
483let fileno = ref 0;;
484
485let rec fullsplitlist dest x =
486  try let l,r = dest x in
487      let ls = fullsplitlist dest r in (l::ls)
488  with Failure _ -> ([x]);;
489
490let rec otff_funtype oc ts t min =
491  if min = 0 then oty_poly ts 0 oc t else
492  let tys = fullsplitlist dest_fun_ty t in
493  let (tys1, tys2) = chop_listn [] min tys in
494  let ty2 = end_itlist mk_fun_ty tys2 in
495  os oc "("; (if List.length tys1 > 1 then os oc "(" else ());
496  oiter oc (fun oc e -> oty_poly ts 0 oc e) " * " tys1;
497  (if List.length tys1 > 1 then os oc ")" else ());
498  os oc " > "; oty_poly ts 0 oc ty2; os oc ")"
499;;
500
501let funtys_of_tm tm =
502  let mergel l = setify (List.concat l) in
503  let tys tm = map type_of (find_terms (fun x -> is_var x || is_const x) tm) in
504  let rec funtypes t =
505    if is_vartype t then [] else
506    let (s, l) = dest_type t in
507    mergel ([s]::(map funtypes l)) in
508  mergel (map funtypes (tys tm))
509;;
510
511let funtys_of_tms tms = setify (List.concat (map funtys_of_tm tms));;
512
513let tff_gl_mk_hash terms =
514  let ts, cs, used = Hashtbl.create 20, Hashtbl.create 50, Hashtbl.create 50 in
515  Hashtbl.add used "p" 0; Hashtbl.add cs "happ" "i"; Hashtbl.add used "i" 0;
516  Hashtbl.add ts "fun" "fn"; Hashtbl.add used "fn" 0; Hashtbl.add used "fun" 0;
517  List.iter (name_tscs_poly (ts, cs, used)) terms;
518  (ts,cs,used_to_map used)
519;;
520
521let tff_gl_hash oc names name asms gl (ts,cs,used) =
522  let ohdr s1 s2 = os oc "tff("; os oc s1; os oc ", "; os oc s2; os oc ", " in
523  let otl () = os oc ").\n" in
524  os oc "%   TYPES\n";
525  List.iter (fun t ->
526    let s = Hashtbl.find ts t in
527    ohdr t "type"; os oc s; os oc ":";
528    begin match get_type_arity t with
529      0 -> os oc "$tType"
530    | 1 -> os oc "$tType > $tType"
531    | n -> os oc "("; oiter oc (fun oc _ -> os oc "$tType") " * " (Array.to_list (Array.make n ()));
532        os oc ") > $tType" end; otl ()) (funtys_of_tms (gl::asms));
533  os oc "%   CONSTS\n";
534  ohdr "cp" "type"; os oc "p : (bool > $o)"; otl ();
535  let output_const (c, argno) =
536    let ty = get_const_type c in let tvs = tyvars ty in
537    ohdr c "type"; os oc (Hashtbl.find cs c); os oc ":";
538    otyquant oc ts tvs; otff_funtype oc ts ty argno; otl ()
539  in
540  List.iter output_const (fst (get_mindata (asms, gl)));
541  os oc "%   AXIOMS\n";
542  List.iter2 (fun n t -> ohdr n "axiom"; tff_pred oc cs ts used t; otl ()) names asms;
543  ohdr (escape_thm name) "conjecture"; tff_pred oc cs ts used gl; otl ();
544;;
545
546let tff_gl oc names name asms gl =
547  let tcu = tff_gl_mk_hash (gl :: asms) in
548  tff_gl_hash oc names name asms gl tcu
549;;
550
551let oorig oc n ls ts gl g2 =
552  output_string oc ("%   ORIGINAL: " ^ n ^ "\n");
553  List.iter2 (fun n t ->
554    output_string oc ("% Assm: " ^ n ^ ": " ^ lstring_of_term (concl t) ^ "\n")) ls ts;
555  output_string oc ("% Goal: " ^ lstring_of_term gl ^ "\n");
556  output_string oc "%   PROCESSED\n";
557  output_gs oc g2
558;;
559
560let rec fof_tm oc (bnd, used) cs ts tm =
561  if is_var tm then begin
562    os oc "s("; oty_poly ts 0 oc (type_of tm); os oc ","; os oc (
563      try Tmm.find tm bnd with Not_found -> Hashtbl.find cs ("`" ^ (o fst dest_var) tm));
564    os oc ")"
565  end else begin
566    let (f, args) = strip_comb tm in
567    os oc "s("; oty_poly ts 0 oc (type_of tm); os oc ","; os oc (
568      try Hashtbl.find cs (fst (dest_const f)) with _ -> Hashtbl.find cs ("`" ^ (o fst dest_var) f));
569    (if args <> [] then
570      (os oc "("; oiter oc (fun oc e -> fof_tm oc (bnd, used) cs ts e) "," args; os oc ")"));
571    os oc ")"
572  end;;
573
574(* Type unsafe version, currently not used *)
575let rec fof_tm_unsafe oc (bnd, used) cs ts tm =
576  if is_var tm then os oc (Tmm.find tm bnd)
577  else
578    let (f, args) = strip_comb tm in
579    os oc (Hashtbl.find cs (fst (dest_const f)));
580    (if args <> [] then
581      (os oc "("; oiter oc (fun oc e -> fof_tm_unsafe oc (bnd, used) cs ts e) "," args; os oc ")"));;
582
583let rec fof_pred oc (bnd, used) cs ts tm =
584  if is_forall tm then
585    let vs, bod = strip_forall tm in
586    let (bnd, used) = rev_itlist bindv vs (bnd, used) in
587    os oc "![";oiter oc (fun oc v -> os oc (Tmm.find v bnd)) ", " vs;os oc "]: ";fof_pred oc (bnd, used) cs ts bod
588  else if is_exists tm then
589    let vs, bod = strip_exists tm in
590    let (bnd, used) = rev_itlist bindv vs (bnd, used) in
591    os oc "?[";oiter oc (fun oc v -> os oc (Tmm.find v bnd)) ", " vs;os oc "]: ";fof_pred oc (bnd, used) cs ts bod
592  else if is_conj tm then let l, r = dest_conj tm in
593    (os oc "("; fof_pred oc (bnd, used) cs ts l; os oc " & "; fof_pred oc (bnd, used) cs ts r; os oc ")")
594  else if is_disj tm then let l, r = dest_disj tm in
595    (os oc "("; fof_pred oc (bnd, used) cs ts l; os oc " | "; fof_pred oc (bnd, used) cs ts r; os oc ")")
596  else if is_imp tm then let l, r = dest_imp tm in
597    (os oc "("; fof_pred oc (bnd, used) cs ts l; os oc " => "; fof_pred oc (bnd, used) cs ts r; os oc ")")
598  else if is_neg tm then
599    let t = dest_neg tm in (os oc "~ ("; fof_pred oc (bnd,used) cs ts t; os oc ")")
600  else if is_eq tm then let l,r = dest_eq tm in
601    if must_pred l || must_pred r then
602      (os oc "("; fof_pred oc (bnd, used) cs ts l; os oc " <=> ";
603      fof_pred oc (bnd, used) cs ts r; os oc ")")
604    else
605      (fof_tm oc (bnd, used) cs ts l; os oc " = "; fof_tm oc (bnd, used) cs ts r)
606  else
607    (os oc "p("; fof_tm oc (bnd, used) cs ts tm; os oc ")");;
608
609let fof_pred oc cs ts used_map t =
610  let tvs = type_vars_in_term t in
611  (if tvs <> [] then (os oc "!["; oiter oc (fun oc e -> oty_poly ts 0 oc e) "," tvs; os oc "]: "));
612  fof_pred oc (Tmm.empty, used_map) cs ts t
613;;
614
615let fof_gl_hash oc names name asms gl (ts,cs,used) =
616  let ohdr s1 s2 = os oc "fof("; os oc s1; os oc ", "; os oc s2; os oc ", " in
617  let otl () = os oc ").\n" in
618  List.iter2 (fun n t -> ohdr n "axiom"; fof_pred oc cs ts used t; otl ()) names asms;
619  ohdr (escape_thm name) "conjecture"; fof_pred oc cs ts used gl; otl ();
620;;
621
622let fof_gl_mk_hash terms =
623  let ts, cs, used = Hashtbl.create 20, Hashtbl.create 50, Hashtbl.create 50 in
624  Hashtbl.add used "p" 0; Hashtbl.add used "s" 0;
625  Hashtbl.add cs "happ" "i"; Hashtbl.add used "i" 0;
626  List.iter (name_tscs_poly (ts, cs, used)) terms;
627  (ts,cs,used_to_map used)
628;;
629
630let fof_gl oc names name asms gl =
631  let (ts,cs,used) = fof_gl_mk_hash (gl :: asms) in
632  fof_gl_hash oc names name asms gl (ts,cs,used);
633  (ts,cs)
634;;
635
636let pRE_HH_TAC =
637  eVERY_ASSUM (fun th -> if frees(concl th) = []
638    then aLL_TAC else uNDISCH_TAC (concl th)) ++++
639  www (fun (asl,w) -> mAP_EVERY (fun v -> sPEC_TAC(v,v)) (frees w))
640;;
641
642let pREP_HH_TAC names need_mono ths =
643  pURE_REWRITE_TAC [eXISTS_UNIQUE_THM; eXISTS_UNIQUE_DEF] ++++
644  ((if need_mono then pOLY_ASSUME_TAC else lABEL_ASSUME_TAC) (rev names) (rev ths)) ++++
645  rULE_ASSUM_TAC (pURE_REWRITE_RULE [eXISTS_UNIQUE_THM; eXISTS_UNIQUE_DEF])
646;;
647
648let pREP_TFF_TAC =
649  let tOP_DEPTH_CONV c tm = genvarreset (); tOP_DEPTH_CONV c tm in
650(*  sELECT_ELIM_TAC ++++*)
651  cONV_TAC(tOP_SWEEP_QCONV eLIM_LAMBDA_EQ) ++++
652  rULE_ASSUM_TAC (cONV_RULE (tOP_SWEEP_QCONV eLIM_LAMBDA_EQ)) ++++
653  cONV_TAC(tHENC (tOP_DEPTH_CONV bETA_CONV) (tHENC lAMBDA_ELIM_CONV2 lAMBDA_ELIM_CONV)) ++++
654  rULE_ASSUM_TAC((cONV_RULE(tHENC (tOP_DEPTH_CONV bETA_CONV) (tHENC lAMBDA_ELIM_CONV2 lAMBDA_ELIM_CONV))))
655;;
656
657let write_atp_proof filen (ts, names) n gl =
658  let (_, [g], _) = mk_goalstate ([],gl) in
659  begin match (pREP_HH_TAC names false ts ++++ pREP_TFF_TAC ++++ fOL_IT_TAC) g with
660    (_, [g2], _) ->
661      let oc = open_out filen in
662      oorig oc n names ts gl g2;
663      let names = map fst (fst g2) in
664      ignore (fof_gl oc names n (map (o concl snd) (fst g2)) (snd g2));
665      (*tff_gl oc names (map (o concl snd) (fst g2)) (snd g2);*)
666      close_out oc;
667    | _ -> failwith ("PREP_HH_TAC created more goals: " ^ n)
668  end;;
669
670let write_thf_proof filen (ts, names) n gl =
671  let (_, [g], _) = mk_goalstate ([],gl) in
672  begin match (pREP_HH_TAC names true ts) g with
673    (_, [g2], _) ->
674      let oc = open_out filen in
675      oorig oc n names ts gl g2;
676      ignore (thf_gl oc (map fst (fst g2)) (map (o concl snd) (fst g2)) (snd g2) n);
677      close_out oc
678    | _ -> failwith "PREP_HH_TAC created more goals"
679  end;;
680
681let write_isa_proof filen (ts, names) n gl =
682  let (_, [g], _) = mk_goalstate ([],gl) in
683  begin match (www(fun (asl,w) -> mAP_EVERY (fun v -> sPEC_TAC(v,v)) (frees w)) ++++
684    lABEL_ASSUME_TAC names (map (o gEN_ALL dISCH_ALL) ts)) g with
685    (_, [g2], _) ->
686      let oc = open_out filen in
687      isa_gl oc names (map (o concl snd) (fst g2)) (snd g2);
688      close_out oc
689  | _ -> failwith "PREP_HH_TAC created more goals"
690  end
691;;
692
693let rec cut_list md n = function
694    [] -> []
695  | h :: t -> if n mod md = 0 then h :: (cut_list md (n + 1) t) else cut_list md (n + 1) t;;
696
697let normalize_th th = gEN_ALL (dISCH_ALL th);;
698