needs "miz3.ml";;
type script_step =
| Tac of string * tactic
| Par of script_step list list;;
type prooftree =
| Prooftree of goal * (string * tactic) * prooftree list
| Open_goal of goal;;
let read_script filename lemmaname =
let rec check_semisemi l =
match l with
| ";"::";"::_ -> true
| " "::l' -> check_semisemi l'
| _ -> false in
let file = open_in filename in
let lemma_string = "let "^lemmaname^" = prove" in
let n = String.length lemma_string in
let rec read_script1 () =
let s = input_line file in
if String.length s >= n & String.sub s 0 n = lemma_string
then (explode s)@"\n"::read_script2 () else read_script1 ()
and read_script2 () =
let l = explode (input_line file) in
if check_semisemi (rev l) then l else l@"\n"::read_script2 () in
let l = read_script1 () in
close_in file;
l;;
let rec tokenize l =
match l with
| [] -> []
| c::l' ->
let l1,l23 = if isalnum c then many (some isalnum) l else [c],l' in
let l2,l3 = many (some isspace) l23 in
(implode l1,if l2 = [] then "" else " ")::tokenize l3;;
let parse_script l =
let rec parse_statement s l =
match l with
| ("`",_)::(",",_)::l' -> s,l'
| (x,y)::l' -> parse_statement (s^x^y) l'
| [] -> failwith "parse_statement" in
let rec parse_tactic b n s y' l =
match l with
| ("\\",y)::l' when not b -> parse_tactic b n (s^y'^"\\\\") y l'
| (x,y)::l' ->
if n = 0 & (x = "THEN" or x = "THENL" or x = ";" or x = "]" or x = ")")
then (Tac(s,exec_tactic s)),l else
let n' = if x = "[" or x = "(" then n + 1 else
if x = "]" or x = ")" then n - 1 else n in
let x',b' =
if x = "`" then
if b then "(parse_term \"",(not b) else "\")",(not b)
else x,b in
parse_tactic b' n' (s^y'^x') y l'
| [] -> failwith "parse_tactic" in
let rec parse_tactics tacs l =
let tac,l' = parse_tactic true 0 "" "" l in
parse_tactics1 (tac::tacs) l'
and parse_tactics1 tacs l =
match l with
| ("THEN",_)::l' -> parse_tactics tacs l'
| ("THENL",_)::("[",_)::l' ->
let tac,l'' = parse_par_tactics [] l' in
parse_tactics1 (tac::tacs) l''
| _ -> (rev tacs),l
and parse_par_tactics tacss l =
let tacs,l' = parse_tactics [] l in
match l' with
| (";",_)::l'' -> parse_par_tactics (tacs::tacss) l''
| ("]",_)::l'' -> (Par (rev (tacs::tacss))),l''
| _ -> failwith "parse_par_tactics" in
match l with
| ("let",_)::_::("=",_)::("prove",_)::("(",_)::("`",_)::l' ->
let s,l'' = parse_statement "" l' in
let tacs,l''' = parse_tactics [] l'' in
(match l''' with
| [")",_; ";",_; ";",_] -> parse_term s,tacs
| _ -> failwith "parse_script")
| _ -> failwith "parse_script";;
let read_script1 filename lemmaname =
parse_script (tokenize (read_script filename lemmaname));;
let tactic_of_script l =
let rec tactic_of_script1 l =
match l with
| [] -> ALL_TAC
| [Tac(_,tac)] -> tac
| (Tac(_,tac))::l' -> tactic_of_script1 l' THEN tac
| (Par ll)::l' ->
tactic_of_script1 l' THENL (map (tactic_of_script1 o rev) ll) in
tactic_of_script1 (rev l);;
let run_script (tm,l) = prove(tm,tactic_of_script l);;
let prooftree_of_script g l =
let rec prooftrees_of gltl tl =
match gltl with
| [] -> []
| (gl,t)::rst ->
let tl1,tl' = chop_list (length gl) tl in
(t tl1)::prooftrees_of rst tl' in
let prooftree_of_script2 t gltl =
flat (map fst gltl),(fun tl -> t (prooftrees_of gltl tl)) in
let rec prooftree_of_script1 g l =
match l with
| [] -> [g],(function [t] -> t | _ -> failwith "prooftree_of_script1")
| (Tac(s,tac))::l' ->
let gl,t = prooftree_of_script1 g l' in
let gltl = map (fun g' -> let _,x,_ = tac g' in
x,(fun tl -> Prooftree(g',(s,tac),tl))) gl in
prooftree_of_script2 t gltl
| (Par ll)::l' ->
let gl,t = prooftree_of_script1 g l' in
let gltl = map2 prooftree_of_script1 gl (map rev ll) in
prooftree_of_script2 t gltl in
let gl,t = prooftree_of_script1 g (rev l) in
t (map (fun x -> Open_goal x) gl);;
let goal_of_prooftree t =
match t with
| Prooftree(g,_,_) -> g
| Open_goal(g) -> g;;
let rec step_of_prooftree prefix n context t =
let frees_of_goal (asl,w) =
union (flat (map (frees o concl o snd) asl)) (frees w) in
let rec extra_ass ass' ass =
if subset ass' ass then [] else (hd ass')::(extra_ass (tl ass') ass) in
let rec lets prefix l =
match l with
| [] -> []
| t::_ ->
let l',l'' = partition ((=) (type_of t) o type_of) l in
step_of_substep prefix (Let l')::lets prefix l'' in
let rec intros prefix n ass =
match ass with
| [] -> [],n,[]
| a::ass' ->
let steps,n',context = intros prefix (n + 1) ass' in
let lab = string_of_int n in
(step_of_substep prefix (Assume(a,[lab]))::steps),
n',((a,lab)::context) in
let shift_labels steps =
let labels = rev (labels_of_steps [] [] steps) in
let labels' =
map ((fun s -> [s],[string_of_int (int_of_string s - 1)]) o hd o fst)
labels in
snd (renumber_steps labels' [] steps) in
let rec steps_of_prooftrees prefix n context (asl,_ as g) tl =
match tl with
| [] -> [],[],n,context
| t'::tl' ->
let (asl',w' as g') = goal_of_prooftree t' in
let prefix' = prefix^(!proof_indent) in
let ll =
lets prefix' (subtract (frees_of_goal g') (frees_of_goal g)) in
let vars = flat (map (function (_,_,Let l) -> l | _ -> []) ll) in
let ass =
extra_ass (map (concl o snd) asl') (map (concl o snd) asl) in
let w'' = list_mk_forall(vars, itlist (curry mk_imp) ass w') in
try
let lab = assoc w'' context in
let steps,labs,n',context' =
steps_of_prooftrees prefix n context g tl' in
steps,Label lab::labs,n',context'
with Failure "find" ->
if vars = [] & ass = [] then
let steps,just,n',context' =
steps_of_prooftree prefix n context t' in
try
let lab = assoc w'' context' in
let steps',labs,n'',context'' =
steps_of_prooftrees prefix n' context' g tl' in
(steps@steps'),Label lab::labs,n'',context''
with Failure "find" ->
let lab = string_of_int n' in
let steps',labs,n'',context'' =
steps_of_prooftrees prefix (n' + 1)
((w',lab)::context') g tl' in
(steps@
[rewrap_step (step_of_substep prefix (Have(w'',[lab],just)))]@
steps'),Label lab::labs,n'',context''
else
let lab = string_of_int n in
let steps,n',context' = intros prefix' (n + 1) ass in
let steps',just,n'',context'' =
steps_of_prooftree prefix' n' (rev context'@context) t' in
let qed = [rewrap_step (step_of_substep prefix (Qed just))] in
let steps'',n''' =
if steps' = [] then (steps'@qed),n'' else
match last steps' with
| _,_,Have(w''',_,Proof(_,steps''',_)) when w''' = w' ->
(butlast steps'@
map (outdent (String.length !proof_indent))
(shift_labels steps''')),n''
| _ -> (steps'@qed),n'' in
let steps''',labs,n'''',context''' =
steps_of_prooftrees prefix n''' ((w'',lab)::context'') g tl' in
(step_of_substep prefix
(Have(w'',[lab],
Proof (Some (step_of_substep prefix Bracket_proof),
(ll@steps@steps''), None)))::
steps'''),Label lab::labs,n'''',context'''
and steps_of_prooftree prefix n context t =
match t with
| Prooftree((_,w as g),(s,tac),tl) ->
let steps,f_labs,n',context' =
steps_of_prooftrees prefix n context g tl in
let b_labs = map ((fun x -> Label x) o C assoc context o concl o snd)
(rev (fst g)) in
steps,By((Tactic(s,K tac))::b_labs,f_labs,false),n',context'
| Open_goal(g) -> [],By([Hole],[],false),n,context in
let prefix' = prefix^(!proof_indent) in
match t with
| Prooftree((_,w as g),_,_) ->
let steps,_,_,_ =
steps_of_prooftrees prefix n context g [t] in
(match last steps with
| _,_,Have(_,_,just) ->
step_of_substep prefix (Have(w,[string_of_int n],
if length steps = 1 then just else
let steps',_,_,_ =
steps_of_prooftrees prefix' (n + 1) context g [t] in
Proof (Some (step_of_substep prefix Bracket_proof),
(butlast steps'@
[rewrap_step (step_of_substep prefix (Qed just))]), None)))
| _ -> failwith "step_of_prooftree")
| _ -> failwith "step_of_prooftree";;
let miz3_of_hol filename lemmaname =
let tm,l = read_script1 filename lemmaname in
step_of_prooftree "" 1 [] (prooftree_of_script ([],tm) l);;