1 needs "Examples/holby.ml";;
5 let default_prover = ref ("HOL_BY", CONV_TAC o HOL_BY);;
6 let renumber_labels = ref true;;
7 let extra_labels = ref 0;;
8 let start_label = ref 1;;
9 let growth_mode = ref true;;
10 let proof_indent = ref " ";;
11 let proof_width = ref 72;;
12 let grow_haves = ref true;;
13 let grow_duplicates = ref 0;;
14 let indent_continued = ref false;;
15 let sketch_mode = ref false;;
16 let silent_server = ref 1;;
17 let explain_errors = ref 1;;
18 let miz3_pid = ref "/tmp/miz3_pid";;
19 let miz3_filename = ref "/tmp/miz3_filename";;
22 ["1: inference error";
23 "2: inference time-out";
26 "5: error ocaml (or justification)";
27 "6: underspecified types hol";
28 "7: unbound free variables hol";
29 "8: syntax or type error hol";
30 "9: syntax error mizar"];;
32 let mizar_step_words =
33 ["assume"; "cases"; "case"; "consider"; "end"; "let"; "now"; "proof";
34 "qed"; "set"; "suppose"; "take"; "thus"];;
36 let mizar_step_words = mizar_step_words @
39 let mizar_words = mizar_step_words @
40 ["be"; "being"; "by"; "from"; "such"; "that"];;
42 let mizar_skip_bracketed =
45 reserve_words (subtract mizar_words (reserved_words()));;
50 | Tactic of string * (thm list -> tactic)
51 | Grow of string * (thm list -> tactic)
55 int * (string * lexcode * string) list list * substep
58 | Have of term * string list * just
59 | Now of string list * just
61 | Assume of term * string list
62 | Thus of term * string list * just
67 | Consider of term list * term * string list * just
68 | Set of term * string list
69 | Cases of just * just list
71 | Suppose of term * string list
72 | Exec of string * tactic
73 | Error of string * just
78 | By of by_item list * by_item list * bool
79 | Proof of step option * step list * step option
80 | Proof_expected of bool
85 let system_ok = Unix.WEXITED 0;;
86 let wronly = Unix.O_WRONLY;;
87 let usr2_handler = ref (fun () -> print_string "usr2_handler\n");;
88 Sys.signal Sys.sigusr2 (Sys.Signal_handle (fun _ -> !usr2_handler ()));;
93 let collect (h,t) = end_itlist (^) (h::t) in
94 let stringof p = atleast 1 p >> end_itlist (^) in
95 let simple_ident = stringof(some isalnum) || stringof(some issymb) in
96 let undertail = stringof (a "_") ++ possibly simple_ident >> collect in
97 let ident = (undertail || simple_ident) ++ many undertail >> collect in
98 let septok = stringof(some issep) in
100 some (fun i -> i <> "\\" & i <> "\"")
101 || (a "\\" ++ some (fun _ -> true) >> fun (_,x) -> "\\"^x) in
102 let string = a "\"" ++ many stringchar ++ ((a "\"" >> K 0) || finished) >>
103 (fun ((_,s),_) -> "\""^implode s^"\"") in
104 (string || some isbra || septok || ident || a "`");;
106 let rec whitespace e i =
108 if i <> [] & hd i <> "\n" then hd i,tl i else raise Noparse in
109 let rest_of_line = many non_newline ++ (a "\n" || (finished >> K "")) >>
110 fun x,y -> itlist (^) x y in
112 match !comment_token with
116 | [] -> if e then "",i else raise Noparse
117 | (" " as c)::rst | ("\t" as c)::rst | ("\r" as c)::rst ->
118 let s,rst1 = whitespace true rst in c^s,rst1
119 | ("\n" as c)::rst -> c,rst
121 let t,rst = rawtoken i in
122 if t = comment_string then (rest_of_line >> fun x -> t^x) rst
123 else if String.length t >= 2 && String.sub t 0 2 = "::" then
124 (rest_of_line >> fun x -> if e then t^x else "") rst
125 else if e then "",i else raise Noparse;;
129 if is_reserved_word n then Resword n else Ident n in
131 try (many (whitespace false) ++ rawtoken ++ whitespace true
133 fun (((x,y),z),w) -> (implode x,reserve1 y,z)::w) i
134 with Noparse -> [],i in
136 let (toks,rst) = tokens l in
137 let rst',rst'' = many (whitespace false) rst in
138 if rst'' <> [] then failwith "lex1" else
139 if toks = [] then toks else
140 let (x,y,z) = last toks in
141 butlast toks@[x,y,z^implode rst'];;
143 let lex2 = lex1 o explode;;
145 let middle (_,x,_) = x;;
149 | ((_,Resword t',_) as tok)::rst when t = t' -> tok,rst
150 | ((_,Ident t',_) as tok)::rst when t = t' -> tok,rst
151 | _ -> raise Noparse;;
153 let a_semi = a' ";";;
157 | (_,Ident s,_)::rst -> s,rst
158 | (_,Resword "(",_)::(_,Ident s,_)::(_,Resword ")",_)::rst -> s,rst
159 | _ -> raise Noparse;;
162 if parses_as_binder s or can get_infix_status s or is_prefix s
163 then ["",Resword "(",""; "",Ident s,""; "",Resword ")",""]
164 else ["",Ident s,""];;
166 let rec cut_to b n c l toks =
168 | [] -> if b then [],[] else raise Noparse
171 | _,Resword s,_ | _,Ident s,_ ->
172 let x = not (n > 0 & mem s mizar_skip_bracketed) in
173 if mem s c & x then [tok],rst else
174 if b & mem s l & x then [],toks else
177 | "(" | "[" -> cut_to true (n + 1) c l rst
178 | ")" | "]" -> cut_to true (if n > 0 then n - 1 else 0) c l rst
179 | _ -> cut_to true n c l rst) in
184 | (_,Resword "proof",_ as tok)::rst -> [tok],rst
185 | (_,Resword "now",_)::rst ->
187 (many (a' "[" ++ cut_to false 0 ["]"] mizar_step_words >>
188 fun x,y -> x::y)) >> fun x,y -> x::(itlist (@) y [])) toks
189 | _ -> cut_to false 0 [";"] mizar_step_words toks;;
191 let rec cut_steps toks =
192 let steps,rst = many cut_step toks in
193 if rst = [] then steps else steps@[rst];;
195 let strings_of_toks toks =
196 let rec string_of_toks1 toks =
199 | [x,Ident y,z] | [x,Resword y,z] -> x^y,z
200 | (x,Ident y,z)::rst | (x,Resword y,z)::rst ->
201 let u,v = string_of_toks1 rst in x^y^z^u,v in
204 | [x,Ident y,z] | [x,Resword y,z] -> x,y,z
205 | (x,Ident y,z)::rst | (x,Resword y,z)::rst ->
206 let u,v = string_of_toks1 rst in x,y^z^u,v;;
208 let string_of_toks = middle o strings_of_toks;;
210 let split_string = map string_of_toks o cut_steps o lex2;;
212 let tok_of_toks toks =
213 let x,y,z = strings_of_toks toks in
216 let exec_phrase b s =
217 let lexbuf = Lexing.from_string s in
218 let ok = Toploop.execute_phrase b Format.std_formatter
219 (!Toploop.parse_toplevel_phrase lexbuf) in
220 Format.pp_print_flush Format.std_formatter ();
222 let i = lexbuf.Lexing.lex_curr_pos in
223 String.sub lexbuf.Lexing.lex_buffer
224 i (lexbuf.Lexing.lex_buffer_len - i));;
226 let exec_thm_out = ref TRUTH;;
230 let ok,rst = exec_phrase false
231 ("exec_thm_out := (("^s^") : thm);;") in
232 if not ok or rst <> "" then raise Noparse;
234 with _ -> raise Noparse;;
236 let exec_thmlist_tactic_out = ref REWRITE_TAC;;
238 let exec_thmlist_tactic s =
240 let ok,rst = exec_phrase false
241 ("exec_thmlist_tactic_out := (("^s^") : thm list -> tactic);;") in
242 if not ok or rst <> "" then raise Noparse;
243 !exec_thmlist_tactic_out
244 with _ -> raise Noparse;;
246 let exec_thmtactic_out = ref MATCH_MP_TAC;;
248 let exec_thmtactic s =
250 let ok,rst = exec_phrase false
251 ("exec_thmtactic_out := (("^s^") : thm -> tactic);;") in
252 if not ok or rst <> "" then raise Noparse;
254 with _ -> raise Noparse;;
256 let exec_tactic_out = ref ALL_TAC;;
260 let ok,rst = exec_phrase false
261 ("exec_tactic_out := (("^s^") : tactic);;") in
262 if not ok or rst <> "" then raise Noparse;
264 with _ -> raise Noparse;;
266 let exec_conv_out = ref NUM_REDUCE_CONV;;
270 let ok,rst = exec_phrase false
271 ("exec_conv_out := (("^s^") : conv);;") in
272 if not ok or rst <> "" then raise Noparse;
274 with _ -> raise Noparse;;
276 let (MP_ALL : tactic -> thm list -> tactic) =
278 MAP_EVERY MP_TAC ths THEN tac;;
281 fun ths -> tac ORELSE MP_ALL tac ths;;
283 let by_item_cache = ref undefined;;
285 let rec by_item_of_toks toks =
287 | [_,Ident "#",_] -> Hole
288 | (_,Ident "#",_)::toks' ->
289 (match by_item_of_toks toks' with
290 | Tactic(s,tac) -> Grow(s,tac)
291 | _ -> failwith "by_item_of_toks")
292 | [_,Ident "*",_] -> Label "*"
294 let s = string_of_toks toks in
295 try apply (!by_item_cache) s with _ ->
297 try Thm (s, exec_thm s) with _ ->
298 try Tactic (s, exec_thmlist_tactic s) with _ ->
299 try Tactic (s, (exec_thmtactic s) o hd) with _ ->
300 try Tactic (s, use_thms (exec_tactic s)) with _ ->
301 try Tactic (s, use_thms (CONV_TAC (exec_conv s))) with _ ->
303 | [_,Ident s,_] -> Label s
304 | _ -> failwith "by_item_of_toks" in
305 by_item_cache := (s |-> i) !by_item_cache;
309 let parse_by_item toks =
311 | (_,Ident "#",_ as tok1)::(_,Ident s,_ as tok2)::toks when s <> "," ->
313 | (_,Ident _,_ as tok)::toks -> [tok],toks
314 | _ -> raise Noparse in
316 ((a' "by" ++ many (parse_by_item ++ a' "," >> fst) >> snd) ++
320 and parse_from_part =
321 ((a' "from" ++ many (parse_by_item ++ a' "," >> fst) >> snd) ++
323 (fun (x,y) -> (x@[y]),true)
324 || (nothing >> K ([],false)) in
325 let rec will_grow l =
328 | Tactic _::_ -> false
330 | _::l' -> will_grow l'
332 ((parse_by_part ++ parse_from_part) ++ a_semi ++ finished >>
333 fun (((x,(y,z)),_),_) ->
334 let x' = map by_item_of_toks x in
335 let y' = map by_item_of_toks y in
336 By(x',y',z or will_grow (x'@y')))
337 || (finished >> K (Proof_expected true));;
339 let rec parse_labels toks =
342 | (_,Resword "[",_)::(_,Ident s,_)::(_,Resword "]",_)::rst ->
343 s::(parse_labels rst)
344 | _ -> raise Noparse;;
346 let rec type_of_pretype1 ty =
348 Stv n -> failwith "type_of_pretype1"
349 | Utv(v) -> mk_vartype(v)
350 | Ptycon(con,args) -> mk_type(con,map type_of_pretype1 args);;
352 let term_of_preterm1 =
353 let rec term_of_preterm1 ptm =
355 Varp(s,pty) -> mk_var(s,type_of_pretype1 pty)
356 | Constp(s,pty) -> mk_mconst(s,type_of_pretype1 pty)
357 | Combp(l,r) -> mk_comb(term_of_preterm1 l,term_of_preterm1 r)
358 | Absp(v,bod) -> mk_gabs(term_of_preterm1 v,term_of_preterm1 bod)
359 | Typing(ptm,pty) -> term_of_preterm1 ptm in
360 fun ptm -> term_of_preterm1 ptm;;
363 let error = mk_var("error",`:error`) in
364 let term_of_hol1 env toks =
365 let env' = ("thesis",Ptycon("bool",[]))::
366 (map ((fun (s,ty) -> s,pretype_of_type ty) o dest_var) env) in
368 let ptm,l = (parse_preterm o map middle) toks in
369 if l <> [] then (8,error) else
371 let tm = (term_of_preterm1 o retypecheck env') ptm in
374 (fun v -> not (mem (fst (dest_var v)) ["..."; "thesis"]))
377 if b && type_of tm <> bool_ty then (8,error) else
380 let tiw = !type_invention_warning in
381 type_invention_warning := false;
383 try (term_of_preterm o retypecheck env') ptm
384 with e -> type_invention_warning := tiw; raise e in
385 type_invention_warning := tiw;
386 if not (subset (frees tm) env) then (7,error) else (6,error)
387 with _ -> (8,error) in
390 | (x,Ident ".=",y)::rest ->
391 term_of_hol1 env ((x,Ident "..."," ")::("",Ident "=",y)::rest)
392 | _ -> term_of_hol1 env toks;;
395 let error = `:error` in
397 try (0,(parse_type o middle o strings_of_toks) toks)
398 with _ -> (8,error);;
400 let split_step toks =
403 | (_,Resword ";",_ as tok)::rst -> rev rst,[tok]
404 | _ -> rev toks,[] in
405 let rec cut_by_part rev_front toks =
407 | [] | (_,Resword "by",_)::_ | (_,Resword "from",_)::_ -> rev_front,toks
408 | tok::rst -> cut_by_part (tok::rev_front) rst in
409 let rec group_by_items toks =
412 | (_,Resword "by",_ as tok)::rst
413 | (_,Resword "from",_ as tok)::rst
414 | (_,Ident ",",_ as tok)::rst
415 | (_,Resword ";",_ as tok)::rst -> tok::group_by_items rst
416 | (_,Ident "#",_ as tok)::toks' ->
418 if toks' = [] then [],[]
419 else cut_to false 0 [] ([","; ";"]@mizar_words) toks' in
420 tok::(if toks1 = [] then [] else [tok_of_toks toks1])@
423 let toks1,toks2 = cut_to false 0 [] ([","; ";"]@mizar_words) toks in
424 if toks1 = [] then tok::group_by_items rst else
425 (tok_of_toks toks1)::group_by_items toks2 in
426 let rec cut_labs toks labs =
428 | (_,Resword "]",_ as tok1)::(_,Ident _,_ as tok2)::
429 (_,Resword "[",_ as tok3)::rst ->
430 cut_labs rst (tok3::tok2::tok1::labs)
432 let rec cut_front toks tail =
435 | (_,Resword s,_)::rst when mem s mizar_words -> rev toks,tail
436 | tok::rst -> cut_front rst (tok::tail) in
437 let toks1,semi_part = cut_semi (rev toks) in
438 let toks2,by_part = cut_by_part [] toks1 in
439 let toks3,labs_part = cut_labs toks2 [] in
440 let front_part,hol_part = cut_front toks3 [] in
441 if front_part <> [] & middle (hd front_part) = Resword "exec" then
442 let ml_tok = tok_of_toks ((tl front_part)@hol_part@labs_part@by_part) in
443 [[hd front_part]; [ml_tok]; []; []; semi_part]
445 [front_part; hol_part; labs_part; group_by_items by_part; semi_part];;
447 let parse_step env toks =
448 let src = split_step toks in
451 | [front_part; hol_part; labs_part; by_part; semi_part] ->
452 let labs = parse_labels labs_part in
453 let just,_ = parse_by (by_part@semi_part) in
454 (match front_part with
457 | [_,Resword ";",_] ->
460 let n,t = term_of_hol true env hol_part in
461 if n <> 0 then n,src,Error(string_of_toks toks,just) else
462 -1,src,Have(t,labs,just))
463 | (_,Resword key,_)::_ ->
464 (match key,(tl front_part),(string_of_toks semi_part) with
466 if hol_part <> [] or by_part <> [] then raise Noparse else
467 -1,src,Now(labs,Proof_expected false)
469 if labs_part <> [] or by_part <> [] then raise Noparse else
470 let x = (fst o fst o fst o
471 many ident' ++ a' "be" ++ finished) rst in
472 let n,t = type_of_hol hol_part in
473 if n <> 0 then n,src,Error(string_of_toks toks,No_steps) else
474 -1,src,Let(map (fun s -> mk_var(s,t)) x)
476 if by_part <> [] then raise Noparse else
477 let n,t = term_of_hol true env hol_part in
478 if n <> 0 then n,src,Error(string_of_toks toks,No_steps) else
479 -1,src,Assume(t,labs)
481 let n,t = term_of_hol true env hol_part in
482 if n <> 0 then n,src,Error(string_of_toks toks,just) else
483 -1,src,Thus(t,labs,just)
485 if hol_part <> [] or labs_part <> [] then raise Noparse else
488 if hol_part <> [] or labs_part <> [] or by_part <> [] then
492 if hol_part <> [] or labs_part <> [] or by_part <> [] then
496 if labs_part <> [] or by_part <> [] then raise Noparse else
497 let n,t = term_of_hol false env hol_part in
498 if n <> 0 then n,src,Error(string_of_toks toks,No_steps) else
500 | "consider",rst,_ ->
501 let cut_suchthat toks =
503 | (_,Resword "that",_)::(_,Resword "such",_)::rst -> rst
504 | _ -> raise Not_found in
505 let rec cut_being toks tail =
507 | [] -> raise Not_found
508 | (_,Resword "being",_)::rst -> (rev rst),(rev tail)
509 | tok::rst -> cut_being rst (tok::tail) in
511 let rst1,rst2 = cut_being (cut_suchthat (rev rst)) [] in
512 let n,t = type_of_hol rst2 in
513 if n <> 0 then n,src,Error(string_of_toks toks,just) else
514 let x = (fst o fst o many ident' ++ finished) rst1 in
515 let vars = map (fun s -> mk_var(s,t)) x in
516 let n,tm' = term_of_hol true (vars@env) hol_part in
517 if n <> 0 then n,src,Error(string_of_toks toks,just) else
518 -1,src,Consider(vars,tm',labs,just)
520 let x = (fst o fst o fst o fst o
521 many ident' ++ a' "such" ++ a' "that" ++ finished) rst in
522 let xy = (("",Ident "?","")::((flat (map unident' x))@
523 (("",Resword ".","")::hol_part))) in
524 let n,tm = term_of_hol true env xy in
525 if n <> 0 then n,src,Error(string_of_toks toks,just) else
526 let vars,tm' = nsplit dest_exists x tm in
527 -1,src,Consider(vars,tm',labs,just))
529 if by_part <> [] then raise Noparse else
530 let (w,_),rst = (ident' ++ a' "=") hol_part in
531 let n,t = term_of_hol false env rst in
532 if n <> 0 then n,src,Error(string_of_toks toks,No_steps) else
533 -1,src,Set(mk_eq(mk_var(w,type_of t),t),labs)
535 if hol_part <> [] or labs_part <> [] then raise Noparse else
536 -1,src,Cases(just,[])
538 if hol_part <> [] or labs_part <> [] or by_part <> [] then
541 | "suppose",[],";" ->
542 if by_part <> [] then raise Noparse else
543 let n,t = term_of_hol true env hol_part in
545 n,src,Error(string_of_toks toks,Proof_expected false) else
546 -1,src,Suppose(t,labs)
548 let s = string_of_toks hol_part in
549 -1,src,Exec(s,exec_tactic s)
550 | _ -> raise Noparse)
551 | _ -> raise Noparse)
554 | Failure "by_item_of_toks" -> 5,src,Error(string_of_toks toks,No_steps)
555 | _ -> 9,src,Error(string_of_toks toks,No_steps);;
557 let rec steps_of_toks1 q e env toks =
558 let prefix x (y,w,z) = (x@y),w,z in
560 if e then [9,[],Error_point],None,[] else [],None,[]
562 let stoks,rst = cut_step toks in
563 let (status,src,substep as step) = parse_step env stoks in
565 | Have (tm, labs, Proof_expected _) ->
566 let just,rst1 = just_of_toks env rst in
569 | Proof(_, _, _) -> (status,src,Have (tm, labs, just)),rst1
570 | _ -> (9,src,Error(string_of_toks stoks, No_steps)),rst) in
571 prefix [step] (steps_of_toks1 q e env rst2)
572 | Thus (tm, labs, Proof_expected _) ->
573 let just,rst1 = just_of_toks env rst in
576 | Proof(_, _, _) -> (status,src,Thus (tm, labs, just)),rst1
577 | _ -> (9,src,Error(string_of_toks stoks, No_steps)),rst) in
578 prefix [step] (steps_of_toks1 q e env rst2)
579 | Let vars -> prefix [step] (steps_of_toks1 q e ((rev vars)@env) rst)
580 | Now (labs, Proof_expected _) ->
581 let just,rst1 = now_of_toks env rst in
582 prefix [status,src,Now (labs, just)] (steps_of_toks1 q e env rst1)
583 | Consider (vars, _, _, By _) ->
584 prefix [step] (steps_of_toks1 q e ((rev vars)@env) rst)
585 | Consider (vars, tm, labs, Proof_expected _) ->
586 let just,rst1 = just_of_toks env rst in
589 | Proof(_, _, _) -> (status,src,Consider(vars, tm, labs, just)),rst1
590 | _ -> (9,src,Error(string_of_toks stoks, No_steps)),rst) in
591 prefix [step] (steps_of_toks1 q e ((rev vars)@env) rst2)
593 prefix [step] (steps_of_toks1 q e ((fst (dest_eq tm))::env) rst)
594 | Cases ((By _ as just), []) ->
596 let justs,rst1 = many (case_of_toks env q) rst in
597 let final,step1,rst2 = steps_of_toks1 false e env rst1 in
598 let cases = status,src,Cases(just, justs) in
600 prefix [cases; 9,[],Error_point]
601 (steps_of_toks1 q e env rst1)
602 else [cases],step1,rst2
604 prefix [9,src,Error(string_of_toks stoks, No_steps)]
605 (steps_of_toks1 q e env rst))
607 if q then [step],None,rst else
608 prefix [(if e then 3 else 9),src,Error(string_of_toks stoks, No_steps)]
609 (steps_of_toks1 q e env rst)
611 if e then [],Some step,rst else
612 prefix [9,src,Error(string_of_toks stoks, No_steps)]
613 (steps_of_toks1 q e env rst)
614 | Bracket_proof | Cases (_, _) | Bracket_case | Suppose (_, _) ->
615 prefix [9,src,Error(string_of_toks stoks, No_steps)]
616 (steps_of_toks1 q e env rst)
617 | Error (s, Proof_expected true) ->
618 let just,rst1 = just_of_toks env rst in
621 prefix [status,src,Error(s, just)] (steps_of_toks1 q e env rst1)
623 prefix [status,src,Error(string_of_toks stoks, No_steps)]
624 (steps_of_toks1 q e env rst))
625 | Error (s, Proof_expected false) ->
626 let steps,step1,rst1 = steps_of_toks1 true true env rst in
627 prefix [status,src,Error(s, Proof(None,steps,step1))]
628 (steps_of_toks1 q e env rst)
630 prefix [status,src,Error(string_of_toks stoks, No_steps)]
631 (steps_of_toks1 q e env rst)
632 | _ -> prefix [step] (steps_of_toks1 q e env rst)
634 and just_of_toks env toks =
636 let stoks,rst = cut_step toks in
637 let (_,_,substep as step) = parse_step env stoks in
638 if substep = Bracket_proof then
639 let steps,step1,rst1 = steps_of_toks1 true true env rst in
640 (Proof(Some step,steps,step1)),rst1
642 with Noparse -> (No_steps),toks
644 and now_of_toks env toks =
645 let steps,step1,rst = steps_of_toks1 false true env toks in
646 (Proof(None,steps,step1)),rst
648 and case_of_toks env q toks =
649 let stoks,rst = cut_step toks in
650 let (_,_,substep as step) = parse_step env stoks in
653 let steps,step1,rst1 = steps_of_toks1 q true env rst in
654 (Proof(Some step,steps,step1)),rst1
656 let steps,step1,rst1 = steps_of_toks1 q true env rst in
657 (Proof(None,step::steps,step1)),rst1
658 | _ -> raise Noparse;;
660 let steps_of_toks toks =
661 let proof,_,rst = steps_of_toks1 false false [] toks in
662 if rst = [] then proof else
663 proof@[9,[rst],Error (string_of_toks rst, No_steps)];;
666 if toks = [] then toks else
668 | _,Resword ";",_ -> toks
669 | _ -> toks@["\n",Resword ";",""];;
671 let parse_proof = steps_of_toks o fix_semi o lex2;;
675 Sys.set_signal Sys.sigalrm (Sys.Signal_handle (fun _ -> raise Timeout));;
677 let TIMED_TAC n tac g =
678 let _ = Unix.alarm n in
681 let _ = Unix.alarm 0 in
684 let _ = Unix.alarm 0 in
687 let FAKE_TAC : bool -> thm list -> tactic =
688 fun fake thl (asl,w as g) ->
690 let tm' = itlist (curry mk_imp) (map concl thl) w in
691 let vl = frees tm' in
692 let tm = itlist (curry mk_forall) vl tm' in
693 let th = itlist (C MP) (rev thl) (itlist SPEC (rev vl) (ASSUME tm)) in
694 null_meta,[],(fun i _ -> INSTANTIATE_ALL i th)
697 let MIZAR_NEXT : (goal -> step * goalstate) -> (goal -> step * goalstate) =
699 fun tac (asl,_ as g) ->
700 let e,((mvs,insts),gls,just as gs) = tac g in
702 | [] -> e,((mvs,insts),[asl,t],(fun _ _ -> just null_inst []))
704 | _ -> failwith "MIZAR_NEXT";;
706 let MIZAR_NEXT' : tactic -> tactic =
708 fun tac (asl,_ as g) ->
709 let ((mvs,insts),gls,just as gs) = tac g in
712 ((mvs,insts),[asl,t],(fun _ _ -> just null_inst []))
714 | _ -> failwith "MIZAR_NEXT'";;
716 let fix_dots prevs tm =
718 let lhs,_ = dest_eq (hd prevs) in
719 vsubst [lhs, mk_var("...",type_of lhs)] tm
722 let fix_dots' asl tm =
724 let th = snd (hd asl) in
725 let lhs,_ = dest_eq (concl th) in
726 let dots = mk_var("...",type_of lhs) in
727 let rec fix_dots1 tm =
729 | Var _ when tm = dots -> th
730 | Comb(t1,t2) -> MK_COMB(fix_dots1 t1,fix_dots1 t2)
731 | Abs(x,t) -> ABS x (fix_dots1 t)
733 if vfree_in dots tm then fix_dots1 tm else REFL tm
736 let rec terms_of_step prevs (_,_,substep) =
738 | Have (tm, _, _) -> [fix_dots prevs tm]
739 | Now (_, just) -> [term_of_now just]
740 | Assume (tm, _) -> [fix_dots prevs tm]
741 | Thus (tm, _, _) -> [fix_dots prevs tm]
742 | Consider (_, tm, _, _) -> [fix_dots prevs tm]
743 | Set (tm, _) -> [fix_dots prevs tm]
744 | Suppose (tm, _) -> [fix_dots prevs tm]
749 let rec term_of_steps prevs steps =
752 | (_,_,substep as step)::rst ->
753 let tm' = term_of_steps ((terms_of_step prevs step)@prevs) rst in
755 | Let vars -> list_mk_forall(vars,tm')
756 | Assume (tm, _) -> mk_imp(fix_dots prevs tm,tm')
757 | Thus (tm, _, _) -> mk_conj(fix_dots prevs tm,tm')
759 let var = genvar (type_of tm) in mk_exists(var,subst [var,tm] tm')
760 | Consider (vars, _, _, _) ->
761 if intersect (frees tm') vars <> [] then failwith "term_of_now"
763 | Cases (_, _) -> failwith "term_of_now"
767 | Proof(_, steps, _) ->
768 (rand o concl o PURE_REWRITE_CONV[AND_CLAUSES])
769 (term_of_steps [] steps)
770 | _ -> failwith "term_of_now";;
774 let rec terms_of_cases cases =
778 let l',tm' = terms_of_cases rst in
780 | (_,_,Suppose (tm, _))::_ -> (()::l'),mk_disj(tm,tm')
781 | _ -> failwith "terms_of_cases") in
782 terms_of_cases o (map
785 | Proof(_, case, _) -> case
786 | _ -> failwith "terms_of_cases"));;
788 let print_to_string1 printer =
789 let sbuff = ref "" in
790 let output s m n = sbuff := (!sbuff)^(String.sub s m n) and flush() = () in
791 let fmt = make_formatter output flush in
792 ignore(pp_set_max_boxes fmt 100);
794 let prefix = prefix'^(implode (replicate " " n)) in
795 let m = String.length prefix in
796 pp_set_margin fmt ((!proof_width) - m);
797 ignore(printer fmt i);
798 ignore(pp_print_flush fmt ());
799 let s = !sbuff in sbuff := "";
800 implode (map (fun x -> if x = "\n" then "\n"^prefix else x) (explode s));;
802 let string_of_term1 = print_to_string1 pp_print_term;;
803 let string_of_type1 = print_to_string1 pp_print_type;;
805 let string_of_substep prefix substep =
806 let string_of_vars tl = implode (map (fun v -> " "^fst (dest_var v)) tl) in
807 let string_of_labs l = implode (map (fun s -> " ["^s^"]") l) in
808 let rec string_of_by_items x l =
811 | i::l' -> x^(match i with
812 | Label s | Thm(s,_) | Tactic(s,_) | Grow(s,_) -> s
813 | Hole -> "#")^string_of_by_items "," l' in
814 let string_of_just just =
817 (if l = [] then "" else " by"^string_of_by_items " " l)^
818 (if l' = [] then "" else " from"^string_of_by_items " " l')^";"
823 string_of_term1 prefix
824 (if !indent_continued then String.length !proof_indent else 0) tm^
825 string_of_labs l^string_of_just just
826 | Now(l,just) -> "now"^string_of_labs l
828 let s = "let"^string_of_vars tl^" be " in
829 s^string_of_type1 prefix (String.length s) (type_of (hd tl))^";"
832 s^string_of_term1 prefix (String.length s) tm^string_of_labs l^";"
835 s^string_of_term1 prefix (String.length s) tm^string_of_labs l^
837 | Qed(just) -> "qed"^string_of_just just
838 | Bracket_proof -> "proof"
839 | Bracket_end -> "end;"
842 s^string_of_term1 prefix (String.length s) tm^";"
843 | Consider(tl,tm,l,just) ->
844 let s = "consider"^string_of_vars tl^" such that " in
845 s^string_of_term1 prefix (String.length s) tm^
846 string_of_labs l^string_of_just just
849 s^string_of_term1 prefix (String.length s) tm^string_of_labs l^";"
850 | Cases(just,_) -> "cases"^string_of_just just
851 | Bracket_case -> "case;"
853 let s = "suppose " in
854 s^string_of_term1 prefix (String.length s) tm^string_of_labs l^";"
855 | Exec(s,_) -> "exec "^s^";"
858 | Error_point -> "")^
861 let step_of_substep prefix substep =
862 (-1,split_step (lex2 (string_of_substep prefix substep)),substep :step);;
864 let step_of_obligation prefix lab tl ass tm =
865 let hole = By([Hole],[],false) in
866 let prefix' = prefix^ !proof_indent in
870 | t::_ -> let l',l'' = partition ((=) (type_of t) o type_of) l in
871 step_of_substep prefix' (Let l')::lets l'' in
872 step_of_substep prefix
873 (if tl = [] & ass = [] then Have(tm,[lab],hole) else
875 let intros = ll@(map (fun a ->
876 step_of_substep prefix' (Assume(a,[]))) ass) in
878 Have(list_mk_forall(flat
879 (map (function (_,_,Let l) -> l | _ -> []) ll),
880 itlist (curry mk_imp) ass tm), [lab],
881 Proof (Some (step_of_substep prefix Bracket_proof),
883 [step_of_substep prefix (Qed(hole))], None))
885 Now([lab], Proof (None,
887 [step_of_substep prefix' (Thus(tm,[],hole))],
888 Some (step_of_substep prefix Bracket_end))));;
890 let steps_of_goals (asl,w :goal) (_,gl,_ :goalstate) prefix n =
891 let ass = map (concl o snd) asl in
892 let fv = union (flat (map frees ass)) (frees w) in
893 let rec extra_ass l l' =
894 if subset l ass then l' else extra_ass (tl l) ((hd l)::l') in
895 let rec steps_of_goals1 n gl =
899 let ass' = map (concl o snd) asl' in
900 let steps',labs',n' = steps_of_goals1 (n + 1) gl' in
901 let lab = string_of_int n in
902 ((step_of_obligation prefix lab
903 (subtract (union (flat (map frees ass')) (frees w')) fv)
904 (extra_ass ass' []) w')::steps'),lab::labs',n' in
905 steps_of_goals1 n gl;;
907 let next_growth_label = ref 0;;
909 let connect_step (step:step) labs =
910 let comma = "",Ident ",","" in
911 let from_key = " ",Resword "from"," " in
912 let rec ungrow_by src l =
915 | Grow(name,tac)::l' ->
917 | tok1::(_,Ident "#",_)::tok2::src' ->
918 let src'',l'' = ungrow_by src' l' in
919 (tok1::tok2::src''),(Tactic(name,tac)::l')
920 | _ -> failwith "ungrow_by")
921 | x::l' -> let toks,src' = chop_list 2 src in
922 let src'',l'' = ungrow_by src' l' in
923 (toks@src''),(x::l'') in
924 let rec extra_from sep labs =
927 | lab::labs' -> sep::("",Ident lab,"")::extra_from comma labs' in
928 let connect_just src4 just =
931 let src4',l'' = ungrow_by src4 l in
932 let src4'',l''' = ungrow_by src4' l' in
933 (src4''@if labs = [] then [] else
934 extra_from (if l' = [] then from_key else comma) labs),
935 By(l'',(l'''@map (fun s -> Label s) labs),b)
938 | (e,[src1; src2; src3; src4; src5],substep) ->
941 let src4',just' = connect_just src4 just in
942 (e,[src1; src2; src3; src4'; src5],Have(x,y,just'))
944 let src4',just' = connect_just src4 just in
945 (e,[src1; src2; src3; src4'; src5],Thus(x,y,just'))
947 let src4',just' = connect_just src4 just in
948 (e,[src1; src2; src3; src4'; src5],Qed just')
949 | Consider(x,y,z,just) ->
950 let src4',just' = connect_just src4 just in
951 (e,[src1; src2; src3; src4'; src5],Consider(x,y,z,just'))
953 let src4',just' = connect_just src4 just in
954 (e,[src1; src2; src3; src4'; src5],Cases(just',x))
955 | _ -> failwith "connect_step" :step)
956 | _ -> failwith "connect_step";;
959 let rec add_width1 n s =
962 | "\t"::s' -> add_width1 ((n/8 + 1)*8) s'
963 | "\n"::s' -> add_width1 0 s'
964 | _::s' -> add_width1 (n + 1) s' in
965 add_width1 n (explode s);;
967 let rewrap_step (e,src,substep as step:step) =
968 let rec rewrap_from x1 src4a src4b =
971 | (x,y,z)::(x',(Resword "from" as y'),z')::rst ->
972 (rev src4a)@(x,y,"\n")::(x1,y',z')::rst
973 | tok::rst -> rewrap_from x1 (tok::src4a) rst in
975 | [src1; src2; src3; src4; src5] ->
976 if src4 = [] then step else
977 let src123 = src1@src2@src3 in
978 let x,y,z = strings_of_toks src123 in
979 let x',y',_ = strings_of_toks src4 in
980 if add_width 0 (x^y^z^x'^y') > !proof_width then
981 let a,b,_ = last src123 in
982 let src123' = (butlast src123)@[a,b,"\n"] in
983 let src1',src23' = chop_list (length src1) src123' in
984 let src2',src3' = chop_list (length src2) src23' in
985 let _,b',c' = hd src4 in
986 let x1 = x^ !proof_indent in
987 let src4' = (x1,b',c')::tl src4 in
989 if add_width 0 (x1^y') > !proof_width then
990 rewrap_from x1 [] src4' else src4' in
991 (e,[src1'; src2'; src3'; src4''; src5],substep)
993 | _ -> failwith "rewrap_step";;
995 let rec pp_step prefix step =
996 let (e,_,substep) = step in
997 let (_,src,substep') =
998 rewrap_step (step_of_substep prefix substep) in
1000 (match substep' with
1001 | Have(x,y,just) -> Have(x,y,pp_just prefix just)
1002 | Now(x,just) -> Now(x,pp_just prefix just)
1003 | Thus(x,y,just) -> Thus(x,y,pp_just prefix just)
1004 | Qed(just) -> Qed(pp_just prefix just)
1005 | Consider(x,y,z,just) -> Consider(x,y,z,pp_just prefix just)
1006 | Cases(just,justl) ->
1007 Cases(pp_just prefix just,map (pp_just prefix) justl)
1008 | Error(x,just) -> Error(x,pp_just prefix just)
1011 and pp_just prefix just =
1012 let pp_step' step' =
1014 | Some step -> Some (pp_step prefix step)
1016 let prefix' = (!proof_indent)^prefix in
1017 let pp_step'' step =
1019 | (_,_,Qed _) -> pp_step prefix step
1020 | (_,_,Suppose _) -> pp_step prefix step
1021 | _ -> pp_step prefix' step in
1023 | Proof(step',stepl,step'') ->
1024 Proof(pp_step' step',map (pp_step'') stepl,pp_step' step'')
1027 let outdent n step =
1028 let (_,src,_) = step in
1031 let x' = explode x in
1032 if length x' < n then step else
1033 let _,x'' = chop_list n x' in
1034 pp_step (implode x'') step
1037 let replacement_steps (asl,w) f step =
1038 let n = String.length !proof_indent in
1039 let indent_of (_,src,substep) =
1040 let x,_,_ = hd (flat src) in
1042 | Qed _ -> x^ !proof_indent
1044 let shift src2 src3 just =
1048 let (x,y,z) = last src3 in
1049 src2,((butlast src3)@[x,y,"\n"])
1050 else if src2 <> [] then
1051 let (x,y,z) = last src2 in
1052 ((butlast src2)@[x,y,"\n"]),src3
1055 let steps,labs,n = f (indent_of step) (!next_growth_label) in
1056 next_growth_label := n;
1057 if !grow_duplicates > 1 then
1058 steps@[rewrap_step (connect_step step labs)]
1060 match steps,step with
1061 | [e,[src1'; src2'; src3'; src4'; src5'],Have(tm',_,just')],
1062 (_,[src1; src2; src3; src4; src5],Have(tm,labs,_)) when tm' = tm ->
1063 let src2'',src3'' = shift src2 src3 just' in
1064 [e,[src1; src2''; src3''; src4'; src5'],Have(tm,labs,just')]
1065 | [e,[src1'; src2'; src3'; src4'; src5'],Have(tm',_,just')],
1066 (_,[src1; src2; src3; src4; src5],Thus(tm,labs,_)) when tm' = tm ->
1067 let src2'',src3'' = shift src2 src3 just' in
1068 [e,[src1; src2''; src3''; src4'; src5'],Thus(tm,labs,just')]
1069 | [e,_,Have(tm',_,Proof(_,y,_))],
1070 (_,_,Qed(_)) when tm' = w ->
1072 | [e,[src1'; src2'; src3'; src4'; src5'],Have(tm',_,(By _ as just'))],
1073 (_,[src1; src2; src3; src4; src5],Qed(_)) when tm' = w ->
1074 [e,[src1; src2; src3; src4'; src5'],Qed(just')]
1076 if !grow_duplicates > 0 then
1077 steps@[rewrap_step (connect_step step labs)]
1079 let al = map (fun x,y -> concl y,x) asl in
1080 let rec filter_growth steps labs steps' labs' =
1082 | [] -> (rev steps'),(rev labs')
1083 | ((_,_,Have(tm,_,_)) as step')::rst ->
1084 (try let lab' = assoc tm al in
1086 filter_growth rst (tl labs) steps' (lab'::labs')
1088 filter_growth rst (tl labs) (step'::steps') ((hd labs)::labs')
1090 filter_growth rst (tl labs) (step'::steps') ((hd labs)::labs'))
1092 filter_growth rst (tl labs) (step'::steps') ((hd labs)::labs') in
1093 let steps',labs' = filter_growth steps labs [] [] in
1094 steps'@[rewrap_step (connect_step step labs')];;
1096 exception Grown of (string -> int -> step list * string list * int);;
1098 let (FILTER_ASSUMS : (int * (string * thm) -> bool) -> tactic) =
1099 let rec filter' f n l =
1103 let t' = filter' f (n + 1) t in
1104 if f (n,h) then h::t' else t' in
1106 null_meta,[filter' f 0 asl,w],(fun i ths -> hd ths);;
1108 let (MAP_ASSUMS : (string * thm -> string * thm) -> tactic) =
1109 let FIRST_ASSUM' ttac' (asl,w as g) =
1110 tryfind (fun lth -> ttac' lth g) asl in
1113 (FIRST_ASSUM' (fun (l,th as lth) ->
1114 UNDISCH_THEN (concl th) (fun th ->
1115 recurse THEN uncurry LABEL_TAC (f lth))) ORELSE ALL_TAC) g in
1116 recurse ORELSE FAIL_TAC "MAP_ASSUMS";;
1119 tactic -> (goal -> 'a * goalstate) list -> goal -> 'a list * goalstate) =
1120 let propagate_empty i _ = [] in
1121 let propagate_thm th i _ = INSTANTIATE_ALL i th in
1122 let compose_justs n just1 just2 i ths =
1123 let ths1,ths2 = chop_list n ths in
1124 (just1 i ths1)::(just2 i ths2) in
1125 let rec seqapply l1 l2 =
1127 | ([],[]) -> [],(null_meta,[],propagate_empty)
1128 | (tac::tacs),(goal::goals) ->
1129 let a,((mvs1,insts1),gls1,just1) = tac goal in
1130 let goals' = map (inst_goal insts1) goals in
1131 let aa',((mvs2,insts2),gls2,just2) = seqapply tacs goals' in
1132 (a::aa'),((union mvs1 mvs2,compose_insts insts1 insts2),
1133 gls1@gls2,compose_justs (length gls1) just1 just2)
1134 | _,_ -> failwith "seqapply: Length mismatch" in
1135 let justsequence just1 just2 insts2 i ths =
1136 just1 (compose_insts insts2 i) (just2 i ths) in
1137 let tacsequence ((mvs1,insts1),gls1,just1) tacl =
1138 let aa,((mvs2,insts2),gls2,just2) = seqapply tacl gls1 in
1139 let jst = justsequence just1 just2 insts2 in
1140 let just = if gls2 = [] then propagate_thm (jst null_inst []) else jst in
1141 aa,((union mvs1 mvs2,compose_insts insts1 insts2),gls2,just) in
1143 let _,gls,_ as gstate = tac1 g in
1144 if gls = [] then tacsequence gstate [] else tacsequence gstate tac2l;;
1146 let just_cache = ref undefined;;
1148 let tactic_of_by fake l l' b =
1149 (fun (asl,_ as g) ->
1150 let hor = if b then 0 else !horizon in
1151 let rec find_tactic l =
1153 | [] -> !default_prover,false
1154 | (Tactic (name, tac))::l' -> (name,tac),false
1155 | (Grow (name, tac))::l' -> (name,tac),true
1156 | _::l' -> find_tactic l' in
1157 let sets = BETA_THM::map snd (filter (fun x,_ -> x = "=") asl) in
1158 let asl' = filter (fun x,_ -> x <> "=") asl in
1159 let rec find_thms l b =
1163 map (PURE_REWRITE_RULE sets o snd)
1164 (try fst (chop_list hor asl') with _ -> asl')
1165 | (Thm (_, th))::l' -> th::(find_thms l' b)
1166 | (Label "*")::l' ->
1167 (map (PURE_REWRITE_RULE sets o snd) asl')@(find_thms l' b)
1169 (PURE_REWRITE_RULE sets
1170 (if s = "-" then snd (hd asl') else assoc s asl'))::(find_thms l' b)
1171 | _::l' -> find_thms l' b in
1172 let rec find_labs l =
1175 | (Label s)::l' -> s::(find_labs l')
1176 | _::l' -> find_labs l' in
1178 let thms = find_thms l b in
1179 let thms' = find_thms l' true in
1180 let thms'' = thms@thms' in
1181 let (name,tac),grow = find_tactic (l@l') in
1182 if fake & (mem Hole l or mem Hole l') or not (!growth_mode) & grow then
1183 -2,FAKE_TAC fake thms'' g else
1184 let labs = find_labs l in
1185 let full_asl = hor < 0 or mem "*" labs in
1187 0,((FILTER_ASSUMS (fun _,(x,_) -> x <> "=") THEN
1190 mem x labs or n < hor or (n = 0 & mem "-" labs) or full_asl) THEN
1191 MAP_ASSUMS (fun l,th -> l,PURE_REWRITE_RULE sets th) THEN
1192 MIZAR_NEXT' (PURE_REWRITE_TAC sets) THEN
1193 (fun (asl',w' as g') ->
1194 let key = name,(map concl thms,map concl thms'),w' in
1196 if grow then failwith "apply";
1197 let e,th = apply (!just_cache) key in
1198 if e = 0 then (ACCEPT_TAC th THEN NO_TAC) g' else
1199 if e = 2 then raise Timeout else failwith "cached by"
1201 | Failure "apply" ->
1203 let (_,_,just as gs) =
1205 let gs' = TIMED_TAC (!timeout) (tac thms) g'' in
1206 if grow then raise (Grown (steps_of_goals g gs'))
1208 REPEAT (fun (asl'',_ as g'') ->
1209 if subset asl'' asl' then NO_TAC g''
1210 else FIRST_ASSUM (UNDISCH_TAC o concl) g'') THEN
1211 TRY (FIRST (map ACCEPT_TAC thms'')) THEN
1212 REWRITE_TAC thms'' THEN NO_TAC) g' in
1213 let th = just null_inst [] in
1214 just_cache := (key |-> (0,th)) !just_cache;
1217 | Grown _ as x -> raise x
1218 | x -> if name <> "GOAL_TAC" then just_cache :=
1219 (key |-> ((if x = Timeout then 2 else 1),TRUTH))
1224 | Grown _ as x -> raise x
1225 | x -> (if x = Timeout then 2 else 1),(FAKE_TAC fake thms'' g))
1226 with Failure "find" | Failure "hd" -> 4,(FAKE_TAC fake [] g)
1227 : goal -> int * goalstate);;
1229 let LABELS_TAC ls th =
1230 if ls = [] then ASSUME_TAC th else
1231 EVERY (map (fun l -> LABEL_TAC l th) ls);;
1233 let PURE_EXACTLY_ONCE_REWRITE_TAC =
1234 let ONCE_COMB_QCONV conv tm =
1235 let l,r = dest_comb tm in
1236 try let th1 = conv l in AP_THM th1 r
1237 with Failure _ -> AP_TERM l (conv r) in
1238 let ONCE_SUB_QCONV conv tm =
1239 if is_abs tm then ABS_CONV conv tm
1240 else ONCE_COMB_QCONV conv tm in
1241 let rec EXACTLY_ONCE_DEPTH_QCONV conv tm =
1242 (conv ORELSEC (ONCE_SUB_QCONV (EXACTLY_ONCE_DEPTH_QCONV conv))) tm in
1243 let PURE_EXACTLY_ONCE_REWRITE_CONV thl =
1244 GENERAL_REWRITE_CONV false EXACTLY_ONCE_DEPTH_QCONV empty_net thl in
1246 CONV_TAC(PURE_EXACTLY_ONCE_REWRITE_CONV thl);;
1249 let lemma = TAUT `(~t <=> T) <=> (t <=> F)` in
1251 PURE_ONCE_REWRITE_RULE[lemma] (EQT_INTRO th);;
1253 let REWRITE_THESIS_TAC =
1254 let PROP_REWRITE_TAC =
1255 PURE_REWRITE_TAC[AND_CLAUSES; IMP_CLAUSES; NOT_CLAUSES; OR_CLAUSES;
1256 prop_2; TAUT `!t. (t <=> t) <=> T`] in
1258 PURE_EXACTLY_ONCE_REWRITE_TAC[EQTF_INTRO th] THEN PROP_REWRITE_TAC;;
1260 let thesis_var = `thesis:bool`;;
1262 let rec tactic_of_step fake step (asl,w as g) =
1263 let justify tac just g =
1264 let (mvs,inst),gls,jst = tac g in
1267 let (e,just'),((mvs',inst'),gls',jst') =
1268 tactic_of_just fake just g1 in
1269 let mvs'' = union mvs' mvs in
1270 let inst'' = compose_insts inst' inst in
1271 let gls'' = gls'@[g2] in
1273 jst (compose_insts inst'' i) [jst' i (butlast ths); last ths] in
1274 (e,just'),((mvs'',inst''),gls'',jst'')
1275 | _ -> failwith "justify") in
1276 let SUBGOAL_THEN' tm tac =
1277 let th = fix_dots' asl tm in
1278 let lhs,_ = dest_eq (concl th) in
1279 SUBGOAL_THEN lhs tac THENL [MIZAR_NEXT' (CONV_TAC (K th)); ALL_TAC] in
1280 let fix_thesis tm = vsubst [w,thesis_var] tm in
1281 let e,src,substep = step in
1284 (try (0,src,substep),(MAP_EVERY X_GEN_TAC tl g)
1285 with x -> if fake then (3,src,substep),(ALL_TAC g) else raise x)
1286 | Assume (tm, l) | Suppose (tm, l) ->
1287 (try (0,src,substep),(DISJ_CASES_THEN2
1288 (fun th -> MIZAR_NEXT' (REWRITE_THESIS_TAC th) THEN
1291 let th' = PURE_REWRITE_RULE[NOT_CLAUSES; IMP_CLAUSES] th in
1292 REWRITE_TAC[th'] THEN CONTR_TAC th' THEN NO_TAC)
1293 (SPEC (fix_thesis tm) EXCLUDED_MIDDLE) g)
1294 with x -> if fake then (3,src,substep),(ALL_TAC g) else raise x)
1295 | Have (tm, l, just) ->
1296 (try let (e,just'),gs =
1297 justify (SUBGOAL_THEN' (fix_thesis tm) (LABELS_TAC l)) just g in
1298 (e,src,Have(tm, l, just')),gs
1301 (try let (e,just'),gs =
1302 justify (SUBGOAL_THEN (term_of_now just) (LABELS_TAC l)) just g in
1303 (e,src,Now(l, just')),gs
1305 | Thus (tm, l, just) ->
1306 (try let (e,just'),gs =
1307 justify (SUBGOAL_THEN' (fix_thesis tm) (LABELS_TAC l) THENL
1308 [ALL_TAC; MIZAR_NEXT'
1309 (FIRST_ASSUM (fun th ->
1310 EVERY (map (fun th' -> REWRITE_THESIS_TAC th')
1313 (e,src,Thus(tm, l, just')),gs
1314 with x -> if fake then (3,src,substep),(ALL_TAC g) else raise x)
1316 (try let (e,just'),gs = tactic_of_just fake just g in
1320 (try (0,src,substep),(EXISTS_TAC tm g)
1321 with x -> if fake then (3,src,substep),(ALL_TAC g) else raise x)
1322 | Consider (tl, tm, l, just) ->
1323 let tm' = itlist (curry mk_exists) tl (fix_thesis tm) in
1324 (try let (e,just'),gs =
1325 justify (SUBGOAL_THEN tm'
1326 ((EVERY_TCL (map X_CHOOSE_THEN tl)) (LABELS_TAC l))) just g in
1327 (e,src,Consider(tl, tm, l, just')),gs
1328 with x -> if fake then (3,src,substep),(ALL_TAC g) else raise x)
1331 let v,_ = dest_eq tm in
1332 let tm' = mk_exists(v,tm) in
1333 let l' = if l = [] then ["="] else l in
1335 ((SUBGOAL_THEN tm' (X_CHOOSE_THEN v (LABELS_TAC l')) THENL
1336 [REWRITE_TAC[EXISTS_REFL] ORELSE FAKE_TAC fake []; ALL_TAC]) g)
1338 | Cases (just, cases) ->
1340 let l,tm = terms_of_cases cases in
1342 (thenl' (SUBGOAL_THEN tm
1344 (map (K (DISJ_CASES_THEN2
1345 (fun th -> ASSUME_TAC th THEN
1346 FIRST_ASSUM (UNDISCH_TAC o concl)))) l) CONTR_TAC))
1347 ((tactic_of_just fake just)::
1348 (map (fun just -> tactic_of_just fake just) cases)) g) in
1350 | (e,just')::ecases' -> (e,src,Cases(just',map snd ecases')),gs
1351 | _ -> failwith "tactic_of_step")
1353 | Bracket_proof | Bracket_end | Bracket_case ->
1354 (3,src,substep),(ALL_TAC g)
1356 (try (0,src,substep),(TIMED_TAC (!timeout) tac THENL [ALL_TAC]) g
1358 | Timeout as x -> if fake then (2,src,substep),(ALL_TAC g) else raise x
1359 | x -> if fake then (3,src,substep),(ALL_TAC g) else raise x)
1360 | Error (_,_) | Error_point ->
1361 if fake then (e,src,substep),(ALL_TAC g) else failwith "tactic_of_step"
1363 (0,src,substep),(ALL_TAC g)
1365 and tactic_of_just fake just g =
1366 let bracket_step step e =
1368 | None -> if e = 0 then None else Some (e, [], Error_point)
1369 | Some (_, src, substep) -> Some (e, src, substep) in
1370 let rec tactic_of_just1 l (_,w as g) =
1373 if is_const w && fst (dest_const w) = "T"
1374 then [],0,ACCEPT_TAC TRUTH g
1375 else [],3,FAKE_TAC fake (map snd (fst g)) g
1378 let step',((mvs,inst),gls,just) =
1379 MIZAR_NEXT (tactic_of_step fake step) g in
1382 let l'',e,((mvs',inst'),gls',just') = tactic_of_just1 l' g' in
1383 let mvs'' = union mvs' mvs in
1384 let inst'' = compose_insts inst' inst in
1386 let just'' i ths = just (compose_insts inst'' i) [just' i ths] in
1387 step'::l'',e,((mvs'',inst''),gls'',just'')
1388 | _ -> failwith "tactic_of_just")
1390 tactic_of_just1 (replacement_steps g f step@l') g) in
1392 | By(l,l',b) -> let e,gs = tactic_of_by fake l l' b g in (e,just),gs
1393 | Proof(step1, l, step2) ->
1394 let l',e,gs = tactic_of_just1 l g in
1395 (0,Proof(bracket_step step1 0, l', bracket_step step2 e)),gs
1396 | _ -> failwith "tactic_of_just";;
1398 let parse_qproof s = steps_of_toks (fix_semi (tl (lex2 s)));;
1400 let rec src_of_step (e,src,substep) =
1401 [e,strings_of_toks (flat src)]@
1403 | Have(_, _, just) -> src_of_just just
1404 | Now(_, just) -> src_of_just just
1405 | Thus(_, _, just) -> src_of_just just
1406 | Qed just -> src_of_just just
1407 | Consider(_, _, _, just) -> src_of_just just
1408 | Cases(just, cases) ->
1409 (src_of_just just)@(itlist (@) (map src_of_just cases) [])
1410 | Error(_, just) -> src_of_just just
1413 and src_of_just just =
1416 | Some step -> src_of_step step
1419 | Proof(step1, steps, step2) ->
1420 (unpack step1)@(itlist (@) (map src_of_step steps) [])@(unpack step2)
1423 let src_of_steps steps = itlist (@) (map src_of_step steps) [];;
1425 let count_errors src =
1426 let rec count_errors1 src (n1,n2,n3) =
1429 | (e,_)::src' -> count_errors1 src'
1430 (if e > 2 then (n1 + 1,n2,n3) else
1431 if e > 0 then (n1,n2 + 1,n3) else
1432 if e = -2 then (n1,n2,n3 + 1) else
1434 count_errors1 src (0,0,0);;
1436 let error_line l ee =
1437 let rec error_line1 s1 s2 n l ee =
1439 | [] -> (s1^"\n"),s2,ee
1441 let d = m - n - 1 in
1442 let d' = if d > 0 then d else 0 in
1443 let s' = "#"^string_of_int e in
1444 error_line1 (s1^(implode (replicate " " d'))^s')
1445 (if !explain_errors > 0 then
1446 if mem e ee then s2 else s2^":: "^(el (e - 1) ERRORS)^"\n"
1448 (add_width (n + d') s') l' (union ee [e]) in
1450 error_line1 "::" "" 2 l (if !explain_errors > 1 then [] else ee) in
1453 let insert_errors n s l ee =
1454 let rec insert_errors1 n s l ee =
1457 | ("\n" as c)::s' ->
1458 let s1,ee' = if l = [] then "",ee else error_line l ee in
1459 let s2,n1,l1,ee' = insert_errors1 0 s' [] ee' in
1460 (c::s1::s2),n1,l1,ee'
1462 let s1,n1,l1,ee' = insert_errors1 (add_width n c) s' l ee in
1463 (c::s1),n1,l1,ee' in
1464 let s1,n1,l1,ee' = insert_errors1 n (explode s) l ee in
1465 (implode s1),n1,l1,ee';;
1467 let string_of_src m steps =
1468 let add_error l n e =
1469 if e > (if !sketch_mode then 2 else 0) then l@[n,e] else l in
1470 let rec string_of_src1 s n l s3' steps ee =
1473 let s',n',l',ee' = insert_errors n s3' l ee in
1474 if l' = [] then s^s' else
1475 let s'',_,_,_ = insert_errors n' "\n" l' ee' in
1477 | (e,(s1,"",s3))::steps' ->
1478 string_of_src1 s n (add_error l n e) (s3'^s1^s3) steps' ee
1479 | (e,(s1,s2,s3))::steps' ->
1480 let s',n',l',ee' = insert_errors n (s3'^s1) l ee in
1481 let n'' = add_width n' s2 in
1482 string_of_src1 (s^s'^s2) n'' (add_error l' n'' e) s3 steps' ee' in
1483 string_of_src1 "" m [] "" steps [];;
1485 let print_boxed f s =
1486 let print_boxed_char c =
1488 then Format.pp_print_cut f ()
1489 else Format.pp_print_string f c in
1490 Format.pp_open_vbox f 0;
1491 do_list print_boxed_char (explode s);
1492 Format.pp_close_box f ();;
1494 let print_step f x =
1495 print_boxed f (string_of_src 0 (src_of_step x));;
1497 let print_qsteps f x =
1498 print_boxed f ("`;\n"^(string_of_src 0 (src_of_steps x))^"`");;
1500 #install_printer print_step;;
1501 #install_printer print_qsteps;;
1504 current_goalstack := (mk_goalstate g)::!current_goalstack;
1507 let GOAL_FROM x = fun y -> x y THEN GOAL_TAC;;
1510 let toks = lex2 s in
1511 let l,t = top_goal() in
1512 let env = itlist union (map frees l) (frees t) in
1513 let proof,step1,rst = steps_of_toks1 true false env toks in
1514 if rst <> [] or step1 <> None then failwith "ee" else
1515 (e o EVERY o map (fun step -> snd o tactic_of_step false step)) proof;;
1517 let check_proof steps =
1520 | [_,_,Have (_, _, _) as step] -> step
1521 | [_,_,Now (_, _) as step] -> step
1523 -1,[],Now([], Proof(None,steps,
1524 Some(-1,[],Bracket_end))) in
1525 let step',gs = tactic_of_step true step ([],thesis_var) in
1528 | _,[],Now(_, Proof(_,steps',_)) -> steps'
1529 | step' -> [step'] in
1531 if length gl <> 1 then failwith "thm" else
1532 let (asl,w) = hd gl in
1533 if length asl <> 1 or w <> thesis_var then failwith "thm" else
1534 let a = (concl o snd o hd) asl in
1535 let src' = src_of_steps steps' in
1536 steps',count_errors src',j ([],[a,thesis_var],[]) [ASSUME a];;
1538 exception Mizar_error of step list * (int * int * int);;
1541 let steps',(n1,n2,n3 as n),th = check_proof steps in
1542 if n1 + n2 + n3 = 0 then th else raise (Mizar_error(steps',n));;
1544 let thm_of_string = thm o parse_proof;;
1546 let rec labels_of_steps labels context steps =
1549 | (_,_,substep)::rst ->
1551 | Assume(_,labs) | Suppose(_,labs) | Set(_,(_::_ as labs)) ->
1552 let label = (labs,ref 0) in
1553 labels_of_steps (label::labels) (label::context) rst
1554 | Have(_,labs,just) | Thus(_,labs,just) | Consider(_,_,labs,just)
1556 let label = (labs,ref 0) in
1557 let labels1 = labels_of_just (label::labels) context just in
1558 labels_of_steps labels1 (label::context) rst
1560 let labels1 = labels_of_just labels context just in
1561 labels_of_steps labels1 context rst
1562 | Cases(just,justl) ->
1564 (fun just' labels' -> labels_of_just labels' context just')
1565 (rev justl) (labels_of_just labels context just)
1566 | Error(_,_) -> raise Noparse
1567 | _ -> labels_of_steps labels context rst)
1569 and labels_of_just labels context just =
1570 let rec collect_strings l =
1573 | Label(s)::l' -> s::collect_strings l'
1574 | _::l' -> collect_strings l' in
1576 | Proof(_,steps,_) -> labels_of_steps labels context steps
1579 do_list (fun _,n -> n := !n + 1) (filter (mem s o fst) context))
1580 (subtract (collect_strings (x@y)) ["-"; "*"]);
1584 let isnumber = forall isnum o explode;;
1586 let max_label labels = itlist max
1587 (map int_of_string (filter isnumber (flat (map fst labels)))) (-1);;
1589 let rec number_labels n labels =
1592 | (oldlabs,count)::rst ->
1594 (if !extra_labels > 1 or !count > 0 or
1595 (!extra_labels > 0 & exists isnumber oldlabs)
1596 then [string_of_int n],(n + 1) else [],n) in
1597 (oldlabs,newlabs)::(number_labels n' rst);;
1599 let rec renumber_steps labels context steps =
1600 let make_lab x1 y1 x2 y2 x3 y3 s =
1601 ([x1,Resword "[",y1; x2,Ident s,y2; x3,Resword "]",y3],[s]) in
1602 let rec renumber_labs b w src labs label =
1605 if b then (make_lab "" "" "" "" "" w (hd (snd label)))," "
1607 | lab::rst when isnumber lab ->
1609 | (x1,Resword "[",y1)::(x2,Ident s',y2)::(x3,Resword "]",y3)::rstsrc ->
1610 let (src',labs'),w' = renumber_labs false y3 rstsrc rst label in
1611 let newsrc,newlabs =
1612 if b then make_lab x1 y1 x2 y2 x3 w' (hd (snd label))
1614 ((newsrc@src'),(newlabs@labs')),if b then w else y3
1615 | _ -> failwith "renumber_labs")
1618 | tok1::tok2::(x3,y3,z3)::rstsrc ->
1619 let (src',labs'),w' = renumber_labs b z3 rstsrc rst label in
1620 ((tok1::tok2::(x3,y3,w')::src'),(lab::labs')),w
1621 | _ -> failwith "renumber_labs") in
1622 let renumber_labs1 b src1 src labs label =
1623 let (x,y,w) = last src1 in
1624 let (src',labs'),w' = renumber_labs b w src labs label in
1625 let src1' = if w' <> w then (butlast src1)@[x,y,w'] else src1 in
1629 | (e,src,substep)::rst ->
1631 | [src1; src2; src3; src4; src5] ->
1634 let label = hd labels in
1635 let src2',src3',labs' =
1636 renumber_labs1 (snd label <> []) src2 src3 labs label in
1638 renumber_steps (tl labels) (label::context) rst in
1640 (e,[src1; src2'; src3'; src4; src5],Assume(x,labs'))::rst'
1641 | Suppose(x,labs) ->
1642 let label = hd labels in
1643 let src2',src3',labs' =
1644 renumber_labs1 (snd label <> []) src2 src3 labs label in
1646 renumber_steps (tl labels) (label::context) rst in
1648 (e,[src1; src2'; src3'; src4; src5],Suppose(x,labs'))::rst'
1649 | Set(x,(_::_ as labs)) ->
1650 let label = hd labels in
1651 let src2',src3',labs' =
1652 renumber_labs1 (snd label <> []) src2 src3 labs label in
1654 renumber_steps (tl labels) (label::context) rst in
1656 (e,[src1; src2'; src3'; src4; src5],Set(x,labs'))::rst'
1657 | Have(x,labs,just) ->
1658 let label = hd labels in
1659 let src2',src3',labs' =
1660 renumber_labs1 (snd label <> []) src2 src3 labs label in
1661 let labels',src4',just' =
1662 renumber_just (tl labels) context src4 just in
1664 renumber_steps labels' (label::context) rst in
1666 ((e,[src1; src2'; src3'; src4'; src5],Have(x,labs',just'))::
1668 | Thus(x,labs,just) ->
1669 let label = hd labels in
1670 let src2',src3',labs' =
1671 renumber_labs1 (snd label <> []) src2 src3 labs label in
1672 let labels',src4',just' =
1673 renumber_just (tl labels) context src4 just in
1675 renumber_steps labels' (label::context) rst in
1677 ((e,[src1; src2'; src3'; src4'; src5],Thus(x,labs',just'))::
1680 let labels',src4',just' =
1681 renumber_just labels context src4 just in
1683 renumber_steps labels' context rst in
1685 ((e,[src1; src2; src3; src4'; src5],Qed(just'))::
1687 | Consider(x,y,labs,just) ->
1688 let label = hd labels in
1689 let src2',src3',labs' =
1690 renumber_labs1 (snd label <> []) src2 src3 labs label in
1691 let labels',src4',just' =
1692 renumber_just (tl labels) context src4 just in
1694 renumber_steps labels' (label::context) rst in
1696 ((e,[src1; src2'; src3'; src4'; src5],
1697 Consider(x,y,labs',just'))::
1700 let label = hd labels in
1701 let src1',src3',labs' =
1702 renumber_labs1 (snd label <> []) src1 src3 labs label in
1703 let labels',src4',just' =
1704 renumber_just (tl labels) context src4 just in
1706 renumber_steps labels' (label::context) rst in
1708 ((e,[src1'; src2; src3'; src4'; src5],Now(labs',just'))::
1710 | Cases(just,justl) ->
1711 let labels',src4',just' =
1712 renumber_just labels context src4 just in
1713 let labels'',justl'' =
1715 (fun just' (labels',justl') ->
1716 let labels'',_,just'' =
1717 renumber_just labels' context [] just' in
1718 labels'',(just''::justl'))
1719 (rev justl) (labels',[]) in
1720 let labels''',rst' =
1721 renumber_steps labels'' context rst in
1723 ((e,[src1; src2; src3; src4'; src5],Cases(just',rev justl''))::
1725 | Error(_,_) -> raise Noparse
1727 let labels',rst' = renumber_steps labels context rst in
1728 labels',((e,src,substep)::rst'))
1729 | _ -> failwith "renumber_steps")
1731 and renumber_just labels context src just =
1732 let rec renumber_by src l =
1735 | (Label s as x)::l' when isnumber s ->
1737 | tok::(x1,Ident _,x2 as tok')::src23 ->
1738 let labs = flat (map snd (filter (mem s o fst) context)) in
1739 let src2,src3,l'' = renumber_by src23 l' in
1740 if labs = [] then (tok::tok'::src2),src3,(x::l'') else
1741 let items = map (fun s -> Label s) labs in
1742 let labs' = tl labs in
1743 let src1 = flat (map
1744 (fun s -> ["",Ident ",",""; "",Ident s,x2]) labs') in
1745 (tok::(x1,Ident (hd labs),
1746 if labs' = [] then x2 else "")::src1@src2),src3,(items@l'')
1747 | _ -> failwith "renumber_by")
1751 | tok::(_,Ident "#",_ as tok1)::(_,Ident s,_ as tok2)::src23
1752 when s <> "," -> [tok;tok1;tok2],src23
1753 | tok::(_,Ident _,_ as tok')::src23 -> [tok;tok'],src23
1754 | _ -> failwith "renumber_by") in
1755 let src2,src3,l'' = renumber_by src23 l' in
1756 (src1@src2),src3,(x::l'') in
1758 | Proof(x,steps,z) ->
1759 let labels',steps' = renumber_steps labels context steps in
1760 labels',src,Proof(x,steps',z)
1762 let src1',src2,x' = renumber_by src x in
1763 let src2',_,y' = renumber_by src2 y in
1764 labels,(src1'@src2'),By(x',y',z)
1765 | _ -> labels,src,just;;
1767 let renumber_steps1 steps =
1768 let labels = rev (labels_of_steps [] [] steps) in
1769 let labels' = number_labels (!start_label) labels in
1770 snd (renumber_steps labels' [] steps);;
1772 let VERBOSE_TAC : bool -> tactic -> tactic =
1775 let v' = !verbose in verbose := v;
1776 let y = (try f x with e -> verbose := v'; raise e) in
1778 let (mvs,insts),gls,just = call tac g in
1779 (mvs,insts),gls,(call just);;
1781 let last_thm_internal = ref None;;
1782 let last_thm_internal' = ref None;;
1785 match !last_thm_internal with
1786 | Some th -> last_thm_internal := None; th
1787 | None -> failwith "last_thm";;
1789 let check_file_verbose name lemma =
1790 let l = String.length name in
1791 if l >= 3 & String.sub name (l - 3) 3 = ".ml" then
1792 (let _ = exec_phrase false ("loadt \""^name^"\";;") in
1795 (last_thm_internal := None;
1796 let file = Pervasives.open_in name in
1797 let n = in_channel_length file in
1798 let s = String.create n in
1799 really_input file s 0 n;
1802 let steps = parse_proof s in
1803 (if !growth_mode then
1804 try next_growth_label := 1 + max_label (labels_of_steps [] [] steps)
1806 let steps',((n1,n2,n3) as x),y = if !silent_server > 0 then
1807 let oldstdout = Unix.dup Unix.stdout in
1808 let cleanup () = Unix.dup2 oldstdout Unix.stdout in
1809 let newstdout = Unix.openfile "/dev/null" [wronly] 0 in
1810 Unix.dup2 newstdout Unix.stdout;
1812 let x = check_proof steps in cleanup(); x
1813 with e -> cleanup(); raise e
1814 else check_proof steps in
1815 let steps'' = if !renumber_labels then
1816 try renumber_steps1 steps' with Noparse -> steps' else steps' in
1817 let y' = if n1 + n2 + n3 = 0 then y else ASSUME (concl y) in
1818 last_thm_internal := Some y;
1819 last_thm_internal' := Some y';
1822 let _ = exec_phrase (!silent_server < 2 & n1 + n2 + n3 = 0)
1824 "match !last_thm_internal' with Some y -> y | None -> TRUTH;;") in
1825 by_item_cache := undefined;
1827 string_of_src 0 (src_of_steps steps''),x,y
1828 with _ -> ("::#"^"10\n:: 10: MIZ3 EXCEPTION\n"^s),(1,0,0),TRUTH in
1829 let file = open_out name in
1830 output_string file t;
1834 let check_file name =
1835 let (n1,n2,n3),th = check_file_verbose name None in
1836 if n1 + n2 + n3 = 0 then th else
1837 failwith (string_of_int n1^"+"^string_of_int n2^"+"^string_of_int n3^
1842 let cleanup () = let _ = Unix.system ("rm -f "^(!miz3_filename)) in () in
1844 let namefile = Pervasives.open_in !miz3_filename in
1845 let name = input_line namefile in
1846 let lemma = try Some (input_line namefile) with End_of_file -> None in
1848 let _ = check_file_verbose name lemma in cleanup()
1849 with _ -> cleanup();;
1851 let exit_proc = ref (fun () -> ());;
1854 if Unix.fork() = 0 then
1855 (exit_proc := (fun () -> ());
1857 let pidfile = open_out !miz3_pid in
1858 output_string pidfile ((string_of_int (Unix.getppid()))^"\n");
1860 with _ -> print_string "server_up failed\n");
1862 else let _ = Unix.wait() in ();;
1864 let server_down () =
1865 if Unix.fork() = 0 then
1866 (exit_proc := (fun () -> ());
1868 let pidfile = Pervasives.open_in !miz3_pid in
1869 let pid_string = input_line pidfile in
1871 if pid_string <> string_of_int (Unix.getppid())
1872 then failwith "server_down" else
1873 let _ = Unix.system ("rm -f "^(!miz3_pid)) in ()
1874 with _ -> print_string "server_down failed\n");
1876 else let _ = Unix.wait() in ();;
1879 exit_proc := server_down;;
1880 at_exit (fun _ -> !exit_proc ());;
1885 default_prover := ("HOL_BY", CONV_TAC o HOL_BY);
1886 sketch_mode := false;
1887 just_cache := undefined;
1888 by_item_cache := undefined;
1889 current_goalstack := [];