Vince and Freek, I was wrong and you were right!  First I used Vince's 

let get = Obj.magic o Toploop.getvalue;;

but then I switched over to Freek's much more complicated exec_thm, as I could 
not see how to test for theorems with get, as I didn't know how to handle a get 
exception. 

My low-tech solution using the reference theorems of database.ml fell apart as 
soon as I wanted to refer to a theorem I proved.  That would probably require 
the techniques of update_database.ml, similar to yours and Freek's:

 let exec = ignore o Toploop.execute_phrase false Format.std_formatter
   o !Toploop.parse_toplevel_phrase o Lexing.from_string;;
 [...] 
   Obj.magic (Toploop.getvalue "buf__");;
 [...]
     let env = Obj.magic !Toploop.toplevel_env in

I'm including my new code, hoping that someone knows how to simplify Freek's 
work with the simple get, and maybe to admit that my code might end up as 
complicated as Freek's miz3.ml or John's mizar.ml.   That's OK as long as I can 
read it: my aim was only to get modify miz3 to use tactics proofs instead of 
the unordered by list.  Progress report: I still haven't coded up SUBGOAL_THEN, 
needed when a proof is quite long, and haven't handled terms which are lists, 
as they have semicolons.  But I ported the first 185 lines of proofs in 
RichterHilbertAxiomGeometry/FontHilbertAxiom.ml, so I think the code below is 
solid.  

-- 
Best,
Bill 

#load "str.cma";;

(* ========================================================================= *)
(* Miz3 interface for tactics proof, so the syntax before the keyword "by"   *)
(* emulates miz3.ml, with the aim of improved readability of formal proofs,  *)
(* with few type annotations, doublequotes, backquotes and semicolons in     *)
(* lists.  Uses a version of INTRO_TAC, consider, case_split.  Statements    *)
(* to be proved are merely written, with the SUBGOAL_TAC hidden.  Semicolons *)
(* are used essentially as THEN connecting tactics.  THENL is currently      *)
(* only allowed implicitly in case_split.  More general tactics proofs could *)
(* be allowed than are presently, but allowing completely arbitrary proofs   *)
(* will impede readability, so there's a tradeoff.  An interactive mode is   *)
(* useful in debugging proofs.  An advantage over miz3 is that REWRITE_TAC   *)
(* and SIMP_TAC can be used intelligently, as we have structured proofs, and *)
(* not an  unordered commma separated "by" list.  Miz3 proofs are primarily  *)
(* done by MESON_TAC.  Another advantage is that the semantics are obvious,  *)
(* there's a straightforward translation to HOL Light tactics proofs.        *)

(* parse_qproof uses system.ml quotexpander feature designed for miz3.ml to  *)
(* turn backquoted expression `;[...]` into a string with no newline or      *)
(* backslash problems.  This miz3 emulation can not be used simultaneously   *)
(* with miz3, which defines parse_qproof differently.                        *)

let parse_qproof s = (String.sub s 1 (String.length s - 1));;

(* exec_thm, taken from miz3.ml, maps a string to its theorem, and defines   *)
(* the predicate is_thm which tests if a string represents a theorem.        *)

let exec_phrase b s =
  let lexbuf = Lexing.from_string s in
  let ok = Toploop.execute_phrase b Format.std_formatter
    (!Toploop.parse_toplevel_phrase lexbuf) in
  Format.pp_print_flush Format.std_formatter ();
  (ok,
   let i = lexbuf.Lexing.lex_curr_pos in
   String.sub lexbuf.Lexing.lex_buffer
     i (lexbuf.Lexing.lex_buffer_len - i));;

let exec_thm_out = ref TRUTH;;

let exec_thm s =
  try
    let ok,rst = exec_phrase false
      ("exec_thm_out := (("^s^") : thm);;") in
    if not ok or rst <> "" then raise Noparse;
    !exec_thm_out
  with _ -> raise Noparse;;

let exec_thmlist_tactic_out = ref REWRITE_TAC;;

let exec_thmlist_tactic s =
  try
    let ok,rst = exec_phrase false
      ("exec_thmlist_tactic_out := (("^s^") : thm list -> tactic);;") in
    if not ok or rst <> "" then raise Noparse;
    !exec_thmlist_tactic_out
  with _ -> raise Noparse;;

let exec_thmtactic_out = ref MATCH_MP_TAC;;

let exec_thmtactic s =
  try
    let ok,rst = exec_phrase false
      ("exec_thmtactic_out := (("^s^") : thm -> tactic);;") in
    if not ok or rst <> "" then raise Noparse;
    !exec_thmtactic_out
  with _ -> raise Noparse;;

let exec_tactic_out = ref ALL_TAC;;

let exec_tactic s =
  try
    let ok,rst = exec_phrase false
      ("exec_tactic_out := (("^s^") : tactic);;") in
    if not ok or rst <> "" then raise Noparse;
    !exec_tactic_out
  with _ -> raise Noparse;;

let is_thm s =
  try let thm = exec_thm s in true
  with _ -> false;;

let is_tactic s =
  try let tactic = exec_tactic s in true
  with _ -> false;;

let is_thmtactic s =
  try let ttac = exec_thmtactic s in true
  with _ -> false;;

let is_thmlist_tactic s =
  try let thmlist_tactic = exec_thmlist_tactic s in true
  with _ -> false;;

(* make_env and parse_env_string, following Mizarlight/miz2a.ml and Vince    *)
(* Aravantinos's https://github.com/aravantv/HOL-Light-Q, turn a string to a *) 
(* term with types inferred by the goal and assumption list. The versions    *)
(* of SUBGOAL_THEN, SUBGOAL_TAC, EXISTS_TAC, X_GEN_TAC, case_split and       *)
(* consider can be used generally, especially with _split and consider use   *)
(* DESTRUCT_TAC, so the labels sDestruct and lab must be nonempty strings; a *)
(* warning holds for case_split and consider in our miz3 emulation.          *)

let (make_env: goal -> (string * pretype) list) =
  fun (asl,w) -> map ((fun (s,ty) -> s,pretype_of_type ty) o dest_var)
                   (freesl (w::(map (concl o snd) asl)));;

let parse_env_string env s = (term_of_preterm o retypecheck env)
  ((fst o parse_preterm o lex o explode) s);;

let (subgoal_THEN: string -> thm_tactic -> tactic) =
  fun stm ttac (asl,w) ->
    let wa = parse_env_string (make_env (asl,w)) stm in
    let meta,gl,just = ttac (ASSUME wa) (asl,w) in
    meta,(asl,wa)::gl,fun i l -> PROVE_HYP (hd l) (just i (tl l));;

let subgoal_TAC s stm prfs =
  match prfs with
    p::ps -> (warn (ps <> []) "subgoal_TAC: additional subproofs ignored";
             subgoal_THEN stm (LABEL_TAC s) THENL [p; ALL_TAC])
  | [] -> failwith "subgoal_TAC: no subproof given";;

let (exists_TAC: string -> tactic) =
  fun stm (asl,w) -> let env = make_env (asl,w) in
    EXISTS_TAC (parse_env_string env stm) (asl,w);;

let (X_gen_TAC: string -> tactic) =
  fun svar (asl,w) ->
    let vartype = (snd o dest_var o fst o dest_forall) w in
    X_GEN_TAC (mk_var (svar,vartype)) (asl,w);;

let case_split sDestruct sDisjlist tac =
  let rec list_mk_string_disj = function
      [] -> ""
    | s::[] -> "(" ^ s ^ ")"
    | s::ls -> "(" ^ s ^ ") \\/ " ^ list_mk_string_disj ls in
  subgoal_TAC "" (list_mk_string_disj sDisjlist) tac THEN
  FIRST_X_ASSUM (DESTRUCT_TAC sDestruct);;

let consider vars_t prfs lab =
  let noSuchThat = Str.bounded_split (Str.regexp
    "[ \t\n]+such[ \t\n]+that[ \t\n]+") vars_t 2 in
  let vars = hd noSuchThat and
  t = hd (tl noSuchThat) in
  match prfs with
    p::ps -> (warn (ps <> []) "consider: additional subproofs ignored";
    subgoal_THEN ("?" ^ vars ^ ". " ^ t)
    (DESTRUCT_TAC ("@" ^ vars ^ "." ^ lab)) THENL [p; ALL_TAC])
  | [] -> failwith "consider: no subproof given";;

let raa lab st tac = subgoal_THEN (st ^ " ==> F") (LABEL_TAC lab) THENL
  [INTRO_TAC lab; tac];;

(* Basically from the HOL Light tutorial "Towards more readable proofs."     *)

let TACtoThmTactic tac = fun  ths -> MAP_EVERY MP_TAC ths THEN tac;;
let NUM_RING_thmTAC = TACtoThmTactic (CONV_TAC NUM_RING);;
let ARITH_thmTAC = TACtoThmTactic ARITH_TAC;;
let so = fun tac -> FIRST_ASSUM MP_TAC THEN tac;;
let fol = MESON_TAC;;
let arithmetic = ARITH_TAC;;
let set_RULE = CONV_TAC SET_RULE;;

(* Allows HOL4 and Isabelle style math characters, via parse_qproof.         *)

let CleanMathFontsForHOL_Light s =
  let rec clean s loStringPairs =
    match loStringPairs with
      [] -> s
    | (hd :: tl) ->
      let symbol = fst hd and ascii = snd hd in
        let s = Str.global_replace (Str.regexp symbol) ascii s in
        clean s tl in
  clean s ["⇒","==>"; "⇔","<=>"; "∧","/\\ "; "∨","\\/"; "¬","~";
    "∀","!"; "∃","?"; "∈","IN"; "∉","NOTIN";
    "α","alpha"; "β","beta"; "γ","gamma"; "λ","\\"; "θ","theta"; "μ","mu";
    "⊂","SUBSET"; "∩","INTER"; "∪","UNION"; "∅","{}"; "━","DELETE"];;

(* StringToTacticsProof uses regexp functions from the Str library to turn   *)
(* string into a tactics proof.  Most of the work is in ConvertToHOL, which  *)
(* recognizes and converts pieces of the proof as string version of either:  *)
(* a one-word tactic, e.g. ARITH_TAC;                                        *)
(* a one-word thm_tactic and a thm, e.g. MATCH_MP_TAC num_WF;                *)
(* intro_TAC followed by a nonempty comma-separated intro string;            *)
(* exists_TAC term, the term of a string with few type annotations;          *)
(* consider vars such that t  [label] by tactic;                             *)
(* statement [label] by tactic; a typical proof of a statement or consider   *)
(* thmlist->tactic labels [theorems], where the lists labels and theorems    *)
(* are space- and comma-separated resp.  Unlike miz3, there must be a label, *)
(* but the empty label [] is fine.  The tactic obtained is                   *)
(* HYP thmlist->tactic "labels" [theorems] unless - occurs in labels, and    *)
(* then so (using FIRST_ASSUM) references the previous statement.            *)

let ws = "[ \t\n]+";;
let ws0 = "[ \t\n]*";;

let StringRegexpEqual r s = Str.string_match r s 0 &&
  s = Str.matched_string s;;

let rec ConvertToHOL s =
  if StringRegexpEqual (Str.regexp (ws0^ "\([^ \t\n]+\)" ^ws0)) s &&
    is_tactic (Str.matched_group 1 s)
  then
    exec_tactic (Str.matched_group 1 s)
  else
  if StringRegexpEqual (Str.regexp
    (ws0^ "\([^][ \t\n]+\)" ^ws0^ "\([^][ \t\n]+\)" ^ws0)) s &&
    is_thmtactic (Str.matched_group 1 s) &&
    is_thm (Str.matched_group 2 s)
  then
    let ttac = (Str.matched_group 1 s) and
    thm = (Str.matched_group 2 s) in
    (exec_thmtactic ttac) (exec_thm thm)
  else
  if Str.string_match (Str.regexp (ws0^ "intro_TAC" ^ws)) s 0
  then
    let intro_string = (Str.global_replace (Str.regexp ",") ";"
      (Str.string_after s (String.length (Str.matched_string s)))) in
      INTRO_TAC intro_string
  else
  if Str.string_match (Str.regexp (ws0^ "exists_TAC" ^ws)) s 0
  then
    exists_TAC (Str.string_after s (String.length (Str.matched_string s)))
  else
  if Str.string_match (Str.regexp (ws0^ "consider" ^ws^ "\(\(.\|\n\)+\)" ^ws^ 
"such"
    ^ws^ "that" ^ws^ "\(\(.\|\n\)+\)" ^ws^ "\[\(\(.\|\n\)*\)\]" ^ws^ "by" ^ws)) 
s 0
  then
    let vars = Str.matched_group 1 s and
    t = Str.matched_group 3 s and
    lab = Str.matched_group 5 s and
    tac = Str.string_after s (String.length (Str.matched_string s)) in
    subgoal_THEN ("?" ^ vars ^ ". " ^ t)
    (DESTRUCT_TAC ("@" ^ vars ^ "." ^ lab)) THENL [ConvertToHOL tac; ALL_TAC]
 else
  if Str.string_match (Str.regexp
      ("\(\(.\|\n\)+\)\[\([^]]*\)\]" ^ws^ "by" ^ws)) s 0
  then
    let statement = Str.matched_group 1 s and
    lab = Str.matched_group 3 s and
    tac = (Str.string_after s (String.length (Str.matched_string s))) in
    subgoal_TAC lab statement [ConvertToHOL tac]
  else
  if StringRegexpEqual (Str.regexp (ws0^ "\([^ \t\n]+\)\(" ^ws^ "[^[]*"
    ^ws0^ "\)\[\(\(.\|\n\)*\)\]" ^ws0)) s &&
    is_thmlist_tactic (Str.matched_group 1 s)
  then
    try
      let ttac = exec_thmlist_tactic (Str.matched_group 1 s) and
      labs = Str.matched_group 2 s and
      thms = Str.global_replace (Str.regexp ws) "" (Str.matched_group 3 s) in
      let listofThms = map exec_thm (Str.split (Str.regexp ",") thms) in
      if Str.string_match (Str.regexp ("[^-]*" ^ws^ "-" ^ws)) labs 0
      then
        let labs_minus = Str.global_replace (Str.regexp (ws^ "-")) "" labs in
        so (HYP ttac labs_minus listofThms)
      else HYP ttac labs listofThms
    with  _ -> warn (true) "square-brace following thm_list->tactic is not a 
comma-separated list of theorems"; ALL_TAC
  else ALL_TAC;;

let organizeTHEN s =
  let rec THENify listofString =
    match listofString with
      [] -> ALL_TAC
    | hd::tl -> (ConvertToHOL hd) THEN (THENify tl) in
  THENify (Str.split (Str.regexp "[ \t\n]*;[ \t\n]*") s);;

(* StringToTacticsProof only handles case_split, which has semicolons:       *)
(* case_split sDestruct by tactic;                                           *)
(* suppose dj1;                                                              *)
(* <proof1>                                                                  *)
(* suppose dj2;                                                              *)
(* <proof2>                                                                  *)
(* ...                                                                       *)
(* where tactic is a proof of the disjunction dj1 \/ dj2 \/ ..., and proof1  *)
(* is a proof of the goal with the added assumptions dj1, etc.               *)

let StringToTacticsProof s =
  try
    let start = Str.search_forward (Str.regexp
      (ws0^ "case_split" ^ws)) s 0 in
    organizeTHEN (Str.string_before s start) THEN
    let s = (Str.string_after s (Str.match_end())) in
    let start = Str.search_forward (Str.regexp (ws ^ "by" ^ ws)) s 0 in
    let sDestruct = (Str.string_before s start) and
    rest = (Str.string_after s (Str.match_end())) in
    let start = Str.search_forward (Str.regexp (";" ^ ws)) rest 0 in
    let tac = (Str.string_before rest start) and
    loCase = Str.split (Str.regexp ("suppose" ^ws))
      (Str.string_after rest (Str.match_end())) in
    let suppose_proof case =
      let start = Str.search_forward (Str.regexp ";") case 0 in
        (Str.string_before case start, Str.string_after case
        (Str.match_end())) in
    let pairCase = map suppose_proof loCase in
    let listofDisj = map fst pairCase and
    listofTac = map snd pairCase in
    (case_split sDestruct listofDisj [ConvertToHOL tac])
    THENL (map organizeTHEN listofTac)
  with Not_found -> organizeTHEN s;;

let theorem s =
  let s = CleanMathFontsForHOL_Light s in
  let start = Str.search_forward (Str.regexp (ws ^ "proof" ^ ws)) s 0 in
  let thm = (Str.string_before s start) and
  proof = (Str.string_after s (Str.match_end())) in
  prove (parse_env_string [] thm,   StringToTacticsProof proof);;

let interactive_proof s =
  let proof = CleanMathFontsForHOL_Light s in
  e (StringToTacticsProof proof);;

let interactive_goal s =
  let thm = CleanMathFontsForHOL_Light s in
  g (parse_env_string [] thm);;

(* Two versions of proofs in the HOL Light tutorial.  First from p 93,  then 
our version of the p 81 readable proof of the irrationality of sqrt 2.  *)

let AXIOM_OF_CHOICE = theorem `;
  ∀P. (∀x. ∃y. P x y) ==> ∃f. ∀x. P x (f x)

  proof
    intro_TAC ∀P, H1;
    exists_TAC \x. @y. P x y;
    fol H1 [];
`;;

let NSQRT_2 = theorem `;
  ∀p q. p * p = 2 * q * q  ⇒  q = 0
  
  proof
    MATCH_MP_TAC num_WF;
    intro_TAC ∀p, A, ∀q, B;
    EVEN(p * p) ⇔ EVEN(2 * q * q)     [] by fol B [];
    EVEN(p)     [] by fol - [ARITH, EVEN_MULT];
    consider m such that p = 2 * m     [C] by fol - [EVEN_EXISTS];
    case_split qp | pq by arithmetic;
    suppose q < p;
    q * q = 2 * m * m ⇒ m = 0     [] by fol qp A [];
    NUM_RING_thmTAC - B C [];
    suppose      p <= q;
    p * p <= q * q     [] by fol - [LE_MULT2];
    q * q = 0     [] by ARITH_thmTAC - B [];
    NUM_RING_thmTAC - [];
`;;

interactive_goal `;∀p q. p * p = 2 * q * q  ⇒  q = 0
`;;
interactive_proof `;
    MATCH_MP_TAC num_WF;
    intro_TAC ∀p, A, ∀q, B;
    EVEN(p * p) ⇔ EVEN(2 * q * q)     [] by fol B [];
    EVEN(p)     [] by fol - [ARITH, EVEN_MULT];
    consider m such that p = 2 * m     [C] by fol - [EVEN_EXISTS]
`;;
interactive_proof `;
    case_split qp | pq by arithmetic;
    suppose q < p;
    q * q = 2 * m * m ⇒ m = 0     [] by fol qp A [];
    NUM_RING_thmTAC - B C [];
    suppose      p <= q;
    p * p <= q * q     [] by fol - [LE_MULT2];
    q * q = 0     [] by ARITH_thmTAC - B [];
    NUM_RING_thmTAC - []
`;;

------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and 
their applications. This 200-page book is written by three acclaimed 
leaders in the field. The early access version is available now. 
Download your free book today! http://p.sf.net/sfu/neotech_d2d_may
_______________________________________________
hol-info mailing list
hol-info@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/hol-info

Reply via email to