-rw-r--r-- 33473 holtrace-20250714/holtrace.ml raw
Printf.printf("===== loading holtrace_save and holtrace_restore\n");; (* XXX: should reject partial final line on restore XXX: could automatically rename constants etc. to avoid collisions but this would be two-pass, so easier as a separate tool XXX: could inject new theorems into Toploop bindings XXX: could do more extensive dedup here to save memory: rebuild types, rebuild terms, re-prove theorems XXX: but really want external hashcons to speed up hashing or at least caching hashes on object creation, even without dedup XXX: maybe should randomize hashing XXX: might encounter integer overflows on 32-bit machines XXX: inf_def now allows alpha-equivalent variants of existing def; maybe also allow alpha-equivalence for typedef? *) (* ===== save *) module Holtrace_save: sig val REFL: term -> thm val TRANS: thm -> thm -> thm val MK_COMB: thm * thm -> thm val ABS: term -> thm -> thm val BETA: term -> thm val ASSUME: term -> thm val EQ_MP: thm -> thm -> thm val DEDUCT_ANTISYM_RULE: thm -> thm -> thm val INST_TYPE: (hol_type * hol_type) list -> thm -> thm val INST: (term * term) list -> thm -> thm val new_axiom: term -> thm val new_basic_definition: term -> thm val new_basic_type_definition: string -> string * string -> thm -> thm * thm val holtrace_nameonethm: string * thm -> unit val holtrace_namethm: (string * thm) list -> unit val holtrace_stop: unit -> unit val holtrace_typedef_thms: unit -> thm list end = struct let orig_REFL = REFL let orig_TRANS = TRANS let orig_MK_COMB = MK_COMB let orig_ABS = ABS let orig_BETA = BETA let orig_ASSUME = ASSUME let orig_EQ_MP = EQ_MP let orig_DEDUCT_ANTISYM_RULE = DEDUCT_ANTISYM_RULE let orig_INST_TYPE = INST_TYPE let orig_INST = INST let orig_new_axiom = new_axiom let orig_new_basic_definition = new_basic_definition let orig_new_basic_type_definition = new_basic_type_definition let envvar = Sys.getenv_opt("HOLTRACE_SAVE") let enabled = Option.is_some envvar let fd = if enabled then open_out_bin (Option.get envvar) else (* presumably there is an easier way to do this *) let fd = open_out_bin "/dev/null" in Out_channel.close fd; fd let tracing = ref enabled let trace_flush() = if !tracing then Out_channel.flush fd let trace_char c = if !tracing then output_char fd c let trace_string s = if !tracing then output_string fd s let trace_stop() = if !tracing then begin Out_channel.close fd; tracing := false end (* ===== holtrace encoding *) let rec base32 n = if n < 0 then "-" ^ (base32(-n)) else if n == 0 then "" else let d = n mod 32 in let c = Char.chr(d + (if d < 10 then 48 else 55)) in base32(n/32) ^ String.make 1 c let is_base32char c = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'V') let simpleencode n = match n with | -1 -> "!" | -2 -> "@" | -3 -> "#" | -4 -> "$" | -5 -> "%" | -6 -> "^" | -7 -> "&" | -8 -> "*" | -9 -> "(" | -10 -> ")" | 0 -> "0" | _ -> base32 n let rec base32_len n = if n < 0 then 1 + base32_len(-n) else if n == 0 then 0 else 1 + base32_len(n/32) let simpleencode_len n = if n >= -10 && n <= 9 then 1 else base32_len n let is_printablenospaces s = String.for_all (fun c -> c > ' ' && c <= '~') s let need_version = ref true let trace tag idlist s = if not(is_printablenospaces s) then failwith "bad name" else if !need_version then begin trace_string "HOLTrace 1\n"; need_version := false end; trace_char tag; let idlist = map simpleencode idlist in let args = if String.length s = 0 then idlist else idlist@[s] in let lastbyte = ref ' ' in let doit s = ( (* s is nonempty now *) let firstbyte = s.[0] in if is_base32char !lastbyte && (is_base32char firstbyte || (firstbyte == ' ')) then trace_char ' '; trace_string s; lastbyte := s.[String.length s - 1] ) in List.iter doit args; trace_char '\n'; trace_flush() let compress reference id = if id < 0 then failwith "internal bug, negative integer" else let y = id-reference in if y >= 0 then id else if y >= -10 then y else if -y >= id then id else if -32*y <= id then y else if simpleencode_len y <= simpleencode_len id then y else id (* ===== types *) let some_type = bool_ty let id2type = Dynarray.make 0 some_type let type2id = Hashtbl.create 16384 let typeid2compress id = compress (Dynarray.length id2type) id let type2compress ty = typeid2compress (Hashtbl.find type2id ty) let rec dedup_trace_type_core ty = try let id = Hashtbl.find type2id ty in Dynarray.get id2type id,id with Not_found -> begin begin match ty with | Tyvar name -> assert(String.length name > 0); trace 'a' [] name | Tyapp(name,args) -> let args = map (snd o dedup_trace_type_core) args in assert(String.length name > 0); trace 'b' ((length args)::(map typeid2compress args)) name end; let id = Dynarray.length id2type in Dynarray.add_last id2type ty; Hashtbl.add type2id ty id; ty,id end let dedup_trace_type_calls = ref 0 let dedup_trace_type_time = ref 0.0 let dedup_trace_type tm = dedup_trace_type_time := !dedup_trace_type_time -. Sys.time(); let result = dedup_trace_type_core tm in dedup_trace_type_time := !dedup_trace_type_time +. Sys.time(); dedup_trace_type_calls := !dedup_trace_type_calls + 1; result (* ===== terms *) let some_constant = mk_const("=",[]) let id2term = Dynarray.make 0 some_constant let term2id = Hashtbl.create 16384 let termid2compress id = compress (Dynarray.length id2term) id let term2compress tm = termid2compress (Hashtbl.find term2id tm) let rec dedup_trace_term_core tm = try let id = Hashtbl.find term2id tm in Dynarray.get id2term id,id with Not_found -> begin begin match tm with | Const(s,ty) -> let _,tyid = dedup_trace_type ty in assert(String.length s > 0); trace 'c' [typeid2compress tyid] s | Var(s,ty) -> let _,tyid = dedup_trace_type ty in assert(String.length s > 0); trace 'd' [typeid2compress tyid] s | Comb(f,x) -> let _,fid = dedup_trace_term_core f in let _,xid = dedup_trace_term_core x in let _,tyid = dedup_trace_type(type_of tm) in trace 'e' [typeid2compress tyid;termid2compress fid;termid2compress xid] "" | Abs(v,b) -> let _,vid = dedup_trace_term_core v in let _,bid = dedup_trace_term_core b in let _,tyid = dedup_trace_type(type_of tm) in trace 'f' [typeid2compress tyid;termid2compress vid;termid2compress bid] "" end; let id = Dynarray.length id2term in Dynarray.add_last id2term tm; Hashtbl.add term2id tm id; tm,id end let dedup_trace_term_calls = ref 0 let dedup_trace_term_time = ref 0.0 let dedup_trace_term tm = dedup_trace_term_time := !dedup_trace_term_time -. Sys.time(); let result = dedup_trace_term_core tm in dedup_trace_term_time := !dedup_trace_term_time +. Sys.time(); dedup_trace_term_calls := !dedup_trace_term_calls + 1; result (* ===== theorems *) let some_thm = orig_REFL some_constant let id2thm = Dynarray.make 0 some_thm let thm2id = Hashtbl.create 16384 let knownthm th = Hashtbl.mem thm2id th let thmid2compress id = compress (Dynarray.length id2thm) id let thm2compress th = thmid2compress (Hashtbl.find thm2id th) let dedup_trace_thm_calls = ref 0 let dedup_trace_thm_time = ref 0.0 let dedup_trace_thm_core th = try let id = Hashtbl.find thm2id th in Dynarray.get id2thm id,id with Not_found -> begin let h,c = dest_thm th in let hc = h@[c] in dedup_trace_thm_time := !dedup_trace_thm_time +. Sys.time(); let hc = map (snd o dedup_trace_term) hc in dedup_trace_thm_time := !dedup_trace_thm_time -. Sys.time(); trace 't' (map termid2compress hc) ""; let id = Dynarray.length id2thm in Dynarray.add_last id2thm th; Hashtbl.add thm2id th id; th,id end let dedup_trace_thm th = dedup_trace_thm_time := !dedup_trace_thm_time -. Sys.time(); let result = dedup_trace_thm_core th in dedup_trace_thm_time := !dedup_trace_thm_time +. Sys.time(); dedup_trace_thm_calls := !dedup_trace_thm_calls + 1; if !dedup_trace_thm_calls mod 100000 = 0 then begin Printf.printf "Holtrace_save so far: %d -> %d thms %.2f s, %d -> %d terms %.2f s, %d -> %d types %.2f s\n%!" !dedup_trace_thm_calls (Dynarray.length id2thm) !dedup_trace_thm_time !dedup_trace_term_calls (Dynarray.length id2term) !dedup_trace_term_time !dedup_trace_type_calls (Dynarray.length id2type) !dedup_trace_type_time end; result let dedup_trace_thm_noid = fst o dedup_trace_thm (* ===== inferences *) let oneterm tag inf tm = if !tracing then let tm,tmid = dedup_trace_term tm in let result = inf tm in if knownthm result then result else begin trace tag [termid2compress tmid] ""; dedup_trace_thm_noid result end else inf tm let trace_BETA = oneterm 'B' orig_BETA let trace_REFL = oneterm 'R' orig_REFL let trace_ASSUME = oneterm 'U' orig_ASSUME let trace_new_axiom = oneterm 'X' orig_new_axiom let twothms tag inf th TH = if !tracing then let th,thid = dedup_trace_thm th in let TH,THid = dedup_trace_thm TH in let result = inf th TH in if knownthm result then result else begin trace tag (map thmid2compress [thid;THid]) ""; dedup_trace_thm_noid result end else inf th TH let trace_MK_COMB(th,TH) = twothms 'E' (fun th TH -> orig_MK_COMB(th,TH)) th TH let trace_EQ_MP = twothms 'P' orig_EQ_MP let trace_TRANS = twothms 'V' orig_TRANS let trace_DEDUCT_ANTISYM_RULE = twothms 'Z' orig_DEDUCT_ANTISYM_RULE let trace_ABS tm th = if !tracing then let tm,tmid = dedup_trace_term tm in let th,thid = dedup_trace_thm th in let result = orig_ABS tm th in if knownthm result then result else begin trace 'F' [termid2compress tmid;thmid2compress thid] ""; dedup_trace_thm_noid result end else orig_ABS tm th let trace_INST tmlist th = if !tracing then let th,thid = dedup_trace_thm th in let dedup_trace_termpair(w,v) = fst(dedup_trace_term w),fst(dedup_trace_term v) in let tmlist = map dedup_trace_termpair tmlist in let result = orig_INST tmlist th in if knownthm result then result else begin let listlist = map (fun(w,v) -> [v;w]) tmlist in let flat = List.flatten listlist in trace 'S' ((thmid2compress thid)::(map term2compress flat)) ""; dedup_trace_thm_noid result end else orig_INST tmlist th let trace_INST_TYPE tylist th = if !tracing then let th,thid = dedup_trace_thm th in let dedup_trace_typepair(z,y) = fst(dedup_trace_type z),fst(dedup_trace_type y) in let tylist = map dedup_trace_typepair tylist in let result = orig_INST_TYPE tylist th in if knownthm result then result else begin let listlist = map (fun(z,y) -> [y;z]) tylist in let flat = List.flatten listlist in trace 'T' ((thmid2compress thid)::(map type2compress flat)) ""; dedup_trace_thm_noid result end else orig_INST_TYPE tylist th let trace_new_basic_definition tm = if !tracing then let tm,tmid = dedup_trace_term tm in let result = orig_new_basic_definition tm in if knownthm result then result else begin let c,cdef = dest_eq tm in let cname,_ = dest_var c in assert(String.length cname > 0); trace 'C' [termid2compress tmid] cname; dedup_trace_thm_noid result end else orig_new_basic_definition tm let trace_new_basic_type_definition tyname (absname,repname) th = if !tracing then let th,thid = dedup_trace_thm th in let ath,rth = orig_new_basic_type_definition tyname (absname,repname) th in if knownthm ath && knownthm rth then ath,rth else begin let repprop,witness = dest_comb(concl th) in let reptype = type_of witness in let reptype,reptypeid = dedup_trace_type reptype in let repprop,reppropid = dedup_trace_term repprop in let tyvars = sort (<=) (type_vars_in_term repprop) in let tyvarnames = map dest_vartype tyvars in let words = tyname::absname::repname::tyvarnames in let text = "]" ^ (String.concat "]" words) ^ "]" in let compressed = [typeid2compress reptypeid;termid2compress reppropid;thmid2compress thid] in trace 'A' compressed text; let ath = dedup_trace_thm_noid ath in trace 'D' [-1] ""; let rth = dedup_trace_thm_noid rth in ath,rth end else orig_new_basic_type_definition tyname (absname,repname) th (* ===== theorem names *) let names_saved_already = Hashtbl.create 100 let trace_nameonethm(name,th) = if Hashtbl.mem names_saved_already name then () (* just ignore (whether old th or not) *) else if knownthm th then begin assert(String.length(name) > 0); trace '/' [thm2compress th] name; Hashtbl.add names_saved_already name true end else failwith "unknown theorem; was HOLTrace running?" let trace_namethm l = List.iter trace_nameonethm (List.rev l) (* ===== switch *) let REFL = if enabled then trace_REFL else orig_REFL let TRANS = if enabled then trace_TRANS else orig_TRANS let MK_COMB = if enabled then trace_MK_COMB else orig_MK_COMB let ABS = if enabled then trace_ABS else orig_ABS let BETA = if enabled then trace_BETA else orig_BETA let ASSUME = if enabled then trace_ASSUME else orig_ASSUME let EQ_MP = if enabled then trace_EQ_MP else orig_EQ_MP let DEDUCT_ANTISYM_RULE = if enabled then trace_DEDUCT_ANTISYM_RULE else orig_DEDUCT_ANTISYM_RULE let INST_TYPE = if enabled then trace_INST_TYPE else orig_INST_TYPE let INST = if enabled then trace_INST else orig_INST let new_axiom = if enabled then trace_new_axiom else orig_new_axiom let new_basic_definition = if enabled then trace_new_basic_definition else orig_new_basic_definition let almost_new_basic_type_definition = if enabled then trace_new_basic_type_definition else orig_new_basic_type_definition let holtrace_nameonethm = if enabled then trace_nameonethm else ignore let holtrace_namethm = if enabled then trace_namethm else ignore let holtrace_stop = if enabled then trace_stop else ignore (* ===== even if tracing is disabled, save typedef theorems *) let typedef_thms = ref ([]:thm list) let new_basic_type_definition tyname (absname,repname) th = let ath,rth = almost_new_basic_type_definition tyname (absname,repname) th in typedef_thms := rth::ath::!typedef_thms; ath,rth let holtrace_typedef_thms() = !typedef_thms end include Holtrace_save (* ===== restore *) module Holtrace_restore: sig val holtrace_restore: (string * thm) list -> string -> unit val holtrace_restore_time: (string * thm) list -> string -> unit val holtrace_restore_allownew: (string * thm) list -> string -> unit val holtrace_restore_skipthmchecks: (string * thm) list -> string -> unit val holtrace_restore_skipthmchecks_allownew: (string * thm) list -> string -> unit val holtrace_restore_worker: (unit -> float) -> bool -> bool -> bool -> (string * thm) list -> string -> unit val holtrace_restore_id2type: int -> hol_type val holtrace_restore_id2term: int -> term val holtrace_restore_id2thm: int -> thm val holtrace_restore_name2thm: string -> thm end = struct (* ===== parsing *) let parse_subid line pos id = let linelen = String.length line in let rec parse_nonneg pos result = assert(result < 288230376151711744); if pos >= linelen then pos,result else let c = line.[pos] in if c = ' ' then pos+1,result else if c >= '0' && c <= '9' then parse_nonneg (pos+1) (result*32+(Char.code c-48)) else if c >= 'A' && c <= 'V' then parse_nonneg (pos+1) (result*32+(Char.code c-55)) else pos,result in let parse_allowneg pos = if pos >= linelen then pos,0 else let c = line.[pos] in if c = '-' then let outpos,n = parse_nonneg (pos+1) 0 in outpos,id-n else let outpos,n = parse_nonneg pos 0 in assert(outpos > pos); outpos,n in let parse_core pos = if pos >= linelen then pos,0 else match line.[pos] with | '!' -> pos+1,id-1 | '@' -> pos+1,id-2 | '#' -> pos+1,id-3 | '$' -> pos+1,id-4 | '%' -> pos+1,id-5 | '^' -> pos+1,id-6 | '&' -> pos+1,id-7 | '*' -> pos+1,id-8 | '(' -> pos+1,id-9 | ')' -> pos+1,id-10 | _ -> parse_allowneg pos in let pos,n = parse_core pos in assert(n >= 0 && (n < id || id < 0)); pos,n let parse_name line pos = String.sub line pos (String.length line - pos) let parse_pairs line pos id xfrm = let rec work result pos = if pos = String.length(line) then result else let pos,idfrom = parse_subid line pos id in let pos,idto = parse_subid line pos id in work ((xfrm idto,xfrm idfrom)::result) pos in rev(work [] pos) let parse_many_subid_reverse many line pos id = let rec work result many pos = if many <= 0 then pos,result else let pos,n = parse_subid line pos id in work (n::result) (many-1) pos in work [] many pos (* ===== types *) let type_id = ref 0 let some_type = bool_ty let holtrace_types = Dynarray.make 0 some_type let holtrace_types_add x = assert(Dynarray.length holtrace_types = !type_id); Dynarray.add_last holtrace_types x; type_id := 1 + !type_id let holtrace_vartype line = holtrace_types_add (mk_vartype(parse_name line 1)) let holtrace_type line = let pos,n = parse_subid line 1 (-1) in let pos,revargs = parse_many_subid_reverse n line pos !type_id in let args = rev revargs in let prevtypes = map (Dynarray.get holtrace_types) args in let name = parse_name line pos in holtrace_types_add (mk_type(name,prevtypes)) (* ===== terms *) let term_id = ref 0 let some_term = mk_const("=",[]) let holtrace_terms = Dynarray.make 0 some_term let holtrace_terms_add x = assert(Dynarray.length holtrace_terms = !term_id); Dynarray.add_last holtrace_terms x; term_id := 1 + !term_id let holtrace_const line = let pos,tyid = parse_subid line 1 !type_id in let ty = Dynarray.get holtrace_types tyid in let name = parse_name line pos in holtrace_terms_add (mk_mconst(name,ty)) let holtrace_var line = let pos,tyid = parse_subid line 1 !type_id in let ty = Dynarray.get holtrace_types tyid in let name = parse_name line pos in holtrace_terms_add (mk_var(name,ty)) let holtrace_comb line = let pos,tyid = parse_subid line 1 !type_id in let pos,id0 = parse_subid line pos !term_id in let pos,id1 = parse_subid line pos !term_id in assert(pos = String.length line); let t0 = Dynarray.get holtrace_terms id0 in let t1 = Dynarray.get holtrace_terms id1 in holtrace_terms_add (mk_comb(t0,t1)) let holtrace_abs line = let pos,tyid = parse_subid line 1 !type_id in let pos,id0 = parse_subid line pos !term_id in let pos,id1 = parse_subid line pos !term_id in assert(pos = String.length line); let t0 = Dynarray.get holtrace_terms id0 in let t1 = Dynarray.get holtrace_terms id1 in holtrace_terms_add (mk_abs(t0,t1)) (* ===== axioms *) let stats_axiom_matching = ref 0 let stats_axiom_creating = ref 0 let holtrace_axiom allownewaxioms term = let target = [],term in let istarget f = (dest_thm f = target) in try let th = List.find istarget (axioms()) in Printf.printf "matching axiom\n%!"; stats_axiom_matching := 1 + !stats_axiom_matching; th with Not_found -> if allownewaxioms then begin Printf.printf "creating axiom\n%!"; stats_axiom_creating := 1 + !stats_axiom_creating; new_axiom term end else failwith "allownewaxioms not set, refusing new axiom" (* ===== theorems indexed by inf_id *) let thm_id = ref 0 let inf_id = ref 0 let typedef_id = ref 0 let some_thm = REFL some_term let holtrace_thms = Dynarray.make 0 some_thm let infs = Dynarray.make 0 some_thm let typedefs = Dynarray.make 0 some_thm let name2thm = Hashtbl.create 100 let infs_add x = assert(Dynarray.length infs = !inf_id); Dynarray.add_last infs x; inf_id := 1 + !inf_id let typedefs_add x = assert(Dynarray.length typedefs = !typedef_id); Dynarray.add_last typedefs x; typedef_id := 1 + !typedef_id let inf_term line inf = let pos,id0 = parse_subid line 1 !term_id in assert(pos = String.length line); let t0 = Dynarray.get holtrace_terms id0 in infs_add (inf t0) let inf_thTH line inf = let pos,id0 = parse_subid line 1 !thm_id in let pos,id1 = parse_subid line pos !thm_id in assert(pos = String.length line); let t0 = Dynarray.get holtrace_thms id0 in let t1 = Dynarray.get holtrace_thms id1 in infs_add (inf t0 t1) let inf_termth line inf = let pos,id0 = parse_subid line 1 !term_id in let pos,id1 = parse_subid line pos !thm_id in assert(pos = String.length line); let t0 = Dynarray.get holtrace_terms id0 in let t1 = Dynarray.get holtrace_thms id1 in infs_add (inf t0 t1) let constname2thm = Hashtbl.create 1009 let constname2thm_init() = Hashtbl.clear constname2thm; let doit th = let c,_ = dest_eq(concl th) in let cname,_ = dest_const c in Hashtbl.add constname2thm cname th in List.iter doit (definitions()) let stats_def_matching = ref 0 let stats_def_creating = ref 0 let inf_def allownewdefs line = let defC term name = let v,t = dest_eq term in let vname,vtype = dest_var v in if vname <> name then failwith "name mismatch" else if Hashtbl.mem constname2thm vname then begin Printf.printf "matching constant %s\n%!" vname; stats_def_matching := 1 + !stats_def_matching; let oldth = Hashtbl.find constname2thm vname in let c = mk_mconst(vname,vtype) in let newconcl = mk_eq(c,t) in let newconclrefl = REFL newconcl in EQ_MP newconclrefl oldth end else begin if allownewdefs then begin Printf.printf "creating constant %s\n%!" vname; stats_def_creating := 1 + !stats_def_creating; new_basic_definition term end else failwith("allownewdefs not set (maybe try holtrace_restore_allownew?), refusing new definition of "^vname) end in let pos,id0 = parse_subid line 1 !term_id in let name = parse_name line pos in let t0 = Dynarray.get holtrace_terms id0 in infs_add (defC t0 name) let is_known_type_theorem concl = let ok f = (dest_thm f = ([],concl)) in exists ok (holtrace_typedef_thms()) let find_type_theorem concl = let ok f = (dest_thm f = ([],concl)) in find ok (holtrace_typedef_thms()) let inf_typedef_retrieve reptype repprop abstypename absname repname tyvarnames = let tyvars = map mk_vartype tyvarnames in let abstype = mk_type(abstypename,tyvars) in let abs = mk_mconst(absname,mk_fun_ty reptype abstype) in let rep = mk_mconst(repname,mk_fun_ty abstype reptype) in let absvar = mk_var("a",abstype) in let repvar = mk_var("r",reptype) in let atarget = mk_eq(mk_comb(abs,mk_comb(rep,absvar)),absvar) in let rtarget = mk_eq(mk_comb(repprop,repvar),mk_eq(mk_comb(rep,mk_comb(abs,repvar)),repvar)) in let athm = find_type_theorem atarget in let rthm = find_type_theorem rtarget in athm,rthm let can_inf_typedef_retrieve reptype repprop abstypename absname repname tyvarnames = try let _,_ = inf_typedef_retrieve reptype repprop abstypename absname repname tyvarnames in true with Failure _ -> false let stats_typedef_matching = ref 0 let stats_typedef_creating = ref 0 let inf_typedef allownewdefs line = let pos,reptype = parse_subid line 1 !type_id in let pos,repprop = parse_subid line pos !term_id in let pos,repth = parse_subid line pos !thm_id in let word = parse_name line pos in let reptype = Dynarray.get holtrace_types reptype in let repprop = Dynarray.get holtrace_terms repprop in let repth = Dynarray.get holtrace_thms repth in let thconcl = match dest_thm repth with | [],concl -> concl | _ -> failwith line in let thprop,_ = try dest_comb thconcl with Failure _ -> failwith line in assert(repprop = thprop); assert(word.[0] = ']'); let args = String.split_on_char ']' word in assert(hd(rev args) = ""); let args = rev(tl(rev args)) in match args with | ""::abstypename::absname::repname::tyvarnames -> if can_inf_typedef_retrieve reptype repprop abstypename absname repname tyvarnames then begin Printf.printf "matching typedef %s\n%!" abstypename; stats_typedef_matching := 1 + !stats_typedef_matching; let athm,rthm = inf_typedef_retrieve reptype repprop abstypename absname repname tyvarnames in typedefs_add rthm; infs_add athm end else begin if allownewdefs then begin Printf.printf "creating typedef %s\n%!" abstypename; stats_typedef_creating := 1 + !stats_typedef_creating; let athm,rthm = new_basic_type_definition abstypename (absname,repname) repth in typedefs_add rthm; infs_add athm end else failwith("allownewdefs not set (maybe try holtrace_restore_allownew?), refusing new definition of "^abstypename) end | _ -> failwith line let inf_typedef_followup line = let pos,typedef = parse_subid line 1 !typedef_id in let rthm = Dynarray.get typedefs typedef in infs_add rthm let inf_inst line = let pos,id0 = parse_subid line 1 !thm_id in let xfrm = Dynarray.get holtrace_terms in let arg = parse_pairs line pos !term_id xfrm in let t0 = Dynarray.get holtrace_thms id0 in let thm = INST arg t0 in infs_add thm let inf_inst_type line = let pos,id0 = parse_subid line 1 !thm_id in let argmap = Dynarray.get holtrace_types in let arg = parse_pairs line pos !type_id argmap in let t0 = Dynarray.get holtrace_thms id0 in let thm = INST_TYPE arg t0 in infs_add thm let holtrace_thms_add x = while Dynarray.length holtrace_thms < !thm_id do Dynarray.add_last holtrace_thms some_thm done; assert(Dynarray.length holtrace_thms = !thm_id); Dynarray.add_last holtrace_thms x; thm_id := 1 + !thm_id let holtrace_thm checkthmstatements line = let linelen = String.length(line) in let rec all_subid result pos = if pos >= linelen then result else let pos,n = parse_subid line pos !term_id in all_subid (n::result) pos in let chhhid = all_subid [] 1 in let chhh = map (Dynarray.get holtrace_terms) chhhid in let c = hd chhh in let hhh = rev(tl chhh) in let thm = Dynarray.get infs (!inf_id-1) in if checkthmstatements then assert((hhh,c) = dest_thm(thm)); holtrace_thms_add thm let thmname_acceptable_firstchar c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_') let thmname_acceptable_char c = thmname_acceptable_firstchar c || (c == '\'') || (c == '.') let thmname_acceptable s = String.length s > 0 && thmname_acceptable_firstchar s.[0] && String.for_all thmname_acceptable_char s let stats_thm_matching = ref 0 let stats_thm_creating = ref 0 let holtrace_thmname previousthms line = let pos,id0 = parse_subid line 1 !thm_id in let name = parse_name line pos in if not(thmname_acceptable name) then failwith ("refusing unusual characters in theorem name "^name) else if Hashtbl.mem name2thm name then failwith "theorem name already used" else begin let th = Dynarray.get holtrace_thms id0 in Hashtbl.add name2thm name th; if exists (fun (n,t) -> n = name) previousthms then begin Printf.printf "matching thm %s\n%!" name; stats_thm_matching := 1 + !stats_thm_matching; let known = assoc name previousthms in assert(dest_thm known = dest_thm th) end else begin Printf.printf "creating thm %s\n%!" name; stats_thm_creating := 1 + !stats_thm_creating; end end (* ===== main *) let holtrace_restore_worker bench allownewaxioms allownewdefs checkthmstatements previousthms fn = let total_time = ref 0.0 in total_time := !total_time -. bench(); stats_axiom_matching := 0; stats_axiom_creating := 0; stats_def_matching := 0; stats_def_creating := 0; stats_typedef_matching := 0; stats_typedef_creating := 0; stats_thm_matching := 0; stats_thm_creating := 0; type_id := 0; term_id := 0; thm_id := 0; inf_id := 0; typedef_id := 0; Dynarray.clear holtrace_types; Dynarray.clear holtrace_terms; Dynarray.clear holtrace_thms; Dynarray.clear infs; Dynarray.clear typedefs; Hashtbl.clear name2thm; constname2thm_init(); let tag_occurrences = Array.make 256 0 in let tag_time = Array.make 256 0.0 in let linecount = ref 0 in let fd = open_in_bin fn in try while true do let line = input_line fd in linecount := !linecount + 1; if !linecount = 1 then assert(line = "HOLTrace 1") else let tag = line.[0] in let tagcode = Char.code(tag) in tag_occurrences.(tagcode) <- tag_occurrences.(tagcode) + 1; tag_time.(tagcode) <- tag_time.(tagcode) -. bench(); ( match tag with | 'a' -> holtrace_vartype line | 'b' -> holtrace_type line | 'c' -> holtrace_const line | 'd' -> holtrace_var line | 'e' -> holtrace_comb line | 'f' -> holtrace_abs line | 't' -> holtrace_thm checkthmstatements line | '/' -> holtrace_thmname previousthms line | 'X' -> inf_term line (holtrace_axiom allownewaxioms) | 'B' -> inf_term line BETA | 'R' -> inf_term line REFL | 'U' -> inf_term line ASSUME | 'F' -> inf_termth line ABS | 'P' -> inf_thTH line EQ_MP | 'V' -> inf_thTH line TRANS | 'Z' -> inf_thTH line DEDUCT_ANTISYM_RULE | 'E' -> inf_thTH line (fun t0 t1 -> MK_COMB(t0,t1)) | 'S' -> inf_inst line | 'T' -> inf_inst_type line | 'C' -> inf_def allownewdefs line | 'A' -> inf_typedef allownewdefs line | 'D' -> inf_typedef_followup line | ';' -> () | ',' -> () | _ -> failwith line ); tag_time.(tagcode) <- tag_time.(tagcode) +. bench(); done with End_of_file -> close_in fd; assert(!linecount >= 1); total_time := !total_time +. bench(); Printf.printf "types: %d\n" !type_id; Printf.printf "terms: %d\n" !term_id; Printf.printf "theorems: %d\n" !thm_id; Printf.printf "inferences: %d\n" !inf_id; Printf.printf "axioms: %d = matching %d + creating %d\n" (!stats_axiom_matching + !stats_axiom_creating) !stats_axiom_matching !stats_axiom_creating; Printf.printf "typedefs: %d = matching %d + creating %d\n" !typedef_id !stats_typedef_matching !stats_typedef_creating; Printf.printf "constants: %d = matching %d + creating %d\n" (!stats_def_matching + !stats_def_creating) !stats_def_matching !stats_def_creating; Printf.printf "named thms: %d = matching %d + creating %d\n" (!stats_thm_matching + !stats_thm_creating) !stats_thm_matching !stats_thm_creating; for c = 33 to 126 do if tag_occurrences.(c) > 0 then Printf.printf "tag %c %12f seconds %12d occurrences\n" (Char.chr(c)) tag_time.(c) tag_occurrences.(c) done; Printf.printf "total %12f seconds\n%!" !total_time let holtrace_restore = holtrace_restore_worker (fun x -> 0.0) false false true let holtrace_restore_time = holtrace_restore_worker Sys.time false false true let holtrace_restore_allownew = holtrace_restore_worker (fun x -> 0.0) true true true let holtrace_restore_skipthmchecks = holtrace_restore_worker (fun x -> 0.0) false false false let holtrace_restore_skipthmchecks_allownew = holtrace_restore_worker (fun x -> 0.0) true true false let holtrace_restore_id2type = Dynarray.get holtrace_types let holtrace_restore_id2term = Dynarray.get holtrace_terms let holtrace_restore_id2thm = Dynarray.get holtrace_thms let holtrace_restore_name2thm = Hashtbl.find name2thm end include Holtrace_restore Printf.printf("===== finished loading holtrace_save and holtrace_restore\n");;