X-Git-Url: http://matita.cs.unibo.it/gitweb/?p=helm.git;a=blobdiff_plain;f=helm%2Focaml%2Fgrafite_engine%2FgrafiteEngine.ml;fp=helm%2Focaml%2Fgrafite_engine%2FgrafiteEngine.ml;h=c0a453c932e0eae3dee583458e3d07f76bc6d9d8;hp=0000000000000000000000000000000000000000;hb=792b5d29ebae8f917043d9dd226692919b5d6ca1;hpb=a14a8c7637fd0b95e9d4deccb20c6abc98e8f953 diff --git a/helm/ocaml/grafite_engine/grafiteEngine.ml b/helm/ocaml/grafite_engine/grafiteEngine.ml new file mode 100644 index 000000000..c0a453c93 --- /dev/null +++ b/helm/ocaml/grafite_engine/grafiteEngine.ml @@ -0,0 +1,714 @@ +(* Copyright (C) 2005, HELM Team. + * + * This file is part of HELM, an Hypertextual, Electronic + * Library of Mathematics, developed at the Computer Science + * Department, University of Bologna, Italy. + * + * HELM is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * HELM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with HELM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * For details, see the HELM World-Wide-Web page, + * http://helm.cs.unibo.it/ + *) + +(* $Id$ *) + +open Printf + +exception Drop +exception IncludedFileNotCompiled of string (* file name *) +exception Macro of + GrafiteAst.loc * + (Cic.context -> GrafiteTypes.status * Cic.term GrafiteAst.macro) +exception ReadOnlyUri of string + +type options = { + do_heavy_checks: bool ; + clean_baseuri: bool +} + +(** create a ProofEngineTypes.mk_fresh_name_type function which uses given + * names as long as they are available, then it fallbacks to name generation + * using FreshNamesGenerator module *) +let namer_of names = + let len = List.length names in + let count = ref 0 in + fun metasenv context name ~typ -> + if !count < len then begin + let name = Cic.Name (List.nth names !count) in + incr count; + name + end else + FreshNamesGenerator.mk_fresh_name ~subst:[] metasenv context name ~typ + +let tactic_of_ast ast = + let module PET = ProofEngineTypes in + match ast with + | GrafiteAst.Absurd (_, term) -> Tactics.absurd term + | GrafiteAst.Apply (_, term) -> Tactics.apply term + | GrafiteAst.Assumption _ -> Tactics.assumption + | GrafiteAst.Auto (_,depth,width,paramodulation,full) -> + AutoTactic.auto_tac ?depth ?width ?paramodulation ?full + ~dbd:(LibraryDb.instance ()) () + | GrafiteAst.Change (_, pattern, with_what) -> + Tactics.change ~pattern with_what + | GrafiteAst.Clear (_,id) -> Tactics.clear id + | GrafiteAst.ClearBody (_,id) -> Tactics.clearbody id + | GrafiteAst.Contradiction _ -> Tactics.contradiction + | GrafiteAst.Compare (_, term) -> Tactics.compare term + | GrafiteAst.Constructor (_, n) -> Tactics.constructor n + | GrafiteAst.Cut (_, ident, term) -> + let names = match ident with None -> [] | Some id -> [id] in + Tactics.cut ~mk_fresh_name_callback:(namer_of names) term + | GrafiteAst.DecideEquality _ -> Tactics.decide_equality + | GrafiteAst.Decompose (_, types, what, names) -> + let to_type = function + | GrafiteAst.Type (uri, typeno) -> uri, typeno + | GrafiteAst.Ident _ -> assert false + in + let user_types = List.rev_map to_type types in + let dbd = LibraryDb.instance () in + let mk_fresh_name_callback = namer_of names in + Tactics.decompose ~mk_fresh_name_callback ~dbd ~user_types what + | GrafiteAst.Discriminate (_,term) -> Tactics.discriminate term + | GrafiteAst.Elim (_, what, using, depth, names) -> + Tactics.elim_intros ?using ?depth ~mk_fresh_name_callback:(namer_of names) + what + | GrafiteAst.ElimType (_, what, using, depth, names) -> + Tactics.elim_type ?using ?depth ~mk_fresh_name_callback:(namer_of names) + what + | GrafiteAst.Exact (_, term) -> Tactics.exact term + | GrafiteAst.Exists _ -> Tactics.exists + | GrafiteAst.Fail _ -> Tactics.fail + | GrafiteAst.Fold (_, reduction_kind, term, pattern) -> + let reduction = + match reduction_kind with + | `Normalize -> + PET.const_lazy_reduction + (CicReduction.normalize ~delta:false ~subst:[]) + | `Reduce -> PET.const_lazy_reduction ProofEngineReduction.reduce + | `Simpl -> PET.const_lazy_reduction ProofEngineReduction.simpl + | `Unfold None -> + PET.const_lazy_reduction (ProofEngineReduction.unfold ?what:None) + | `Unfold (Some lazy_term) -> + (fun context metasenv ugraph -> + let what, metasenv, ugraph = lazy_term context metasenv ugraph in + ProofEngineReduction.unfold ~what, metasenv, ugraph) + | `Whd -> + PET.const_lazy_reduction (CicReduction.whd ~delta:false ~subst:[]) + in + Tactics.fold ~reduction ~term ~pattern + | GrafiteAst.Fourier _ -> Tactics.fourier + | GrafiteAst.FwdSimpl (_, hyp, names) -> + Tactics.fwd_simpl ~mk_fresh_name_callback:(namer_of names) + ~dbd:(LibraryDb.instance ()) hyp + | GrafiteAst.Generalize (_,pattern,ident) -> + let names = match ident with None -> [] | Some id -> [id] in + Tactics.generalize ~mk_fresh_name_callback:(namer_of names) pattern + | GrafiteAst.Goal (_, n) -> Tactics.set_goal n + | GrafiteAst.IdTac _ -> Tactics.id + | GrafiteAst.Injection (_,term) -> Tactics.injection term + | GrafiteAst.Intros (_, None, names) -> + PrimitiveTactics.intros_tac ~mk_fresh_name_callback:(namer_of names) () + | GrafiteAst.Intros (_, Some num, names) -> + PrimitiveTactics.intros_tac ~howmany:num + ~mk_fresh_name_callback:(namer_of names) () + | GrafiteAst.Inversion (_, term) -> + Tactics.inversion term + | GrafiteAst.LApply (_, how_many, to_what, what, ident) -> + let names = match ident with None -> [] | Some id -> [id] in + Tactics.lapply ~mk_fresh_name_callback:(namer_of names) ?how_many + ~to_what what + | GrafiteAst.Left _ -> Tactics.left + | GrafiteAst.LetIn (loc,term,name) -> + Tactics.letin term ~mk_fresh_name_callback:(namer_of [name]) + | GrafiteAst.Reduce (_, reduction_kind, pattern) -> + (match reduction_kind with + | `Normalize -> Tactics.normalize ~pattern + | `Reduce -> Tactics.reduce ~pattern + | `Simpl -> Tactics.simpl ~pattern + | `Unfold what -> Tactics.unfold ~pattern what + | `Whd -> Tactics.whd ~pattern) + | GrafiteAst.Reflexivity _ -> Tactics.reflexivity + | GrafiteAst.Replace (_, pattern, with_what) -> + Tactics.replace ~pattern ~with_what + | GrafiteAst.Rewrite (_, direction, t, pattern) -> + EqualityTactics.rewrite_tac ~direction ~pattern t + | GrafiteAst.Right _ -> Tactics.right + | GrafiteAst.Ring _ -> Tactics.ring + | GrafiteAst.Split _ -> Tactics.split + | GrafiteAst.Symmetry _ -> Tactics.symmetry + | GrafiteAst.Transitivity (_, term) -> Tactics.transitivity term + +(* maybe we only need special cases for apply and goal *) +let classify_tactic tactic = + match tactic with + (* tactics that can't close the goal (return a goal we want to "select") *) + | GrafiteAst.Rewrite _ + | GrafiteAst.Split _ + | GrafiteAst.Replace _ + | GrafiteAst.Reduce _ + | GrafiteAst.Injection _ + | GrafiteAst.IdTac _ + | GrafiteAst.Generalize _ + | GrafiteAst.Elim _ + | GrafiteAst.Cut _ + | GrafiteAst.Decompose _ -> true, true + (* tactics we don't want to reorder goals. I think only Goal needs this. *) + | GrafiteAst.Goal _ -> false, true + (* tactics like apply *) + | _ -> true, false + +let reorder_metasenv start refine tactic goals current_goal always_opens_a_goal= + let module PEH = ProofEngineHelpers in +(* let print_m name metasenv = + prerr_endline (">>>>> " ^ name); + prerr_endline (CicMetaSubst.ppmetasenv [] metasenv) + in *) + (* phase one calculates: + * new_goals_from_refine: goals added by refine + * head_goal: the first goal opened by ythe tactic + * other_goals: other goals opened by the tactic + *) + let new_goals_from_refine = PEH.compare_metasenvs start refine in + let new_goals_from_tactic = PEH.compare_metasenvs refine tactic in + let head_goal, other_goals, goals = + match goals with + | [] -> None,[],goals + | hd::tl -> + (* assert (List.mem hd new_goals_from_tactic); + * invalidato dalla goal_tac + * *) + Some hd, List.filter ((<>) hd) new_goals_from_tactic, List.filter ((<>) + hd) goals + in + let produced_goals = + match head_goal with + | None -> new_goals_from_refine @ other_goals + | Some x -> x :: new_goals_from_refine @ other_goals + in + (* extract the metas generated by refine and tactic *) + let metas_for_tactic_head = + match head_goal with + | None -> [] + | Some head_goal -> List.filter (fun (n,_,_) -> n = head_goal) tactic in + let metas_for_tactic_goals = + List.map + (fun x -> List.find (fun (metano,_,_) -> metano = x) tactic) + goals + in + let metas_for_refine_goals = + List.filter (fun (n,_,_) -> List.mem n new_goals_from_refine) tactic in + let produced_metas, goals = + let produced_metas = + if always_opens_a_goal then + metas_for_tactic_head @ metas_for_refine_goals @ + metas_for_tactic_goals + else begin +(* print_m "metas_for_refine_goals" metas_for_refine_goals; + print_m "metas_for_tactic_head" metas_for_tactic_head; + print_m "metas_for_tactic_goals" metas_for_tactic_goals; *) + metas_for_refine_goals @ metas_for_tactic_head @ + metas_for_tactic_goals + end + in + let goals = List.map (fun (metano, _, _) -> metano) produced_metas in + produced_metas, goals + in + (* residual metas, preserving the original order *) + let before, after = + let rec split e = + function + | [] -> [],[] + | (metano, _, _) :: tl when metano = e -> + [], List.map (fun (x,_,_) -> x) tl + | (metano, _, _) :: tl -> let b, a = split e tl in metano :: b, a + in + let find n metasenv = + try + Some (List.find (fun (metano, _, _) -> metano = n) metasenv) + with Not_found -> None + in + let extract l = + List.fold_right + (fun n acc -> + match find n tactic with + | Some x -> x::acc + | None -> acc + ) l [] in + let before_l, after_l = split current_goal start in + let before_l = + List.filter (fun x -> not (List.mem x produced_goals)) before_l in + let after_l = + List.filter (fun x -> not (List.mem x produced_goals)) after_l in + let before = extract before_l in + let after = extract after_l in + before, after + in +(* |+ DEBUG CODE +| + print_m "BEGIN" start; + prerr_endline ("goal was: " ^ string_of_int current_goal); + prerr_endline ("and metas from refine are:"); + List.iter + (fun t -> prerr_string (" " ^ string_of_int t)) + new_goals_from_refine; + prerr_endline ""; + print_m "before" before; + print_m "metas_for_tactic_head" metas_for_tactic_head; + print_m "metas_for_refine_goals" metas_for_refine_goals; + print_m "metas_for_tactic_goals" metas_for_tactic_goals; + print_m "produced_metas" produced_metas; + print_m "after" after; +|+ FINE DEBUG CODE +| *) + before @ produced_metas @ after, goals + +let apply_tactic ~disambiguate_tactic tactic (status, goal) = +(* prerr_endline "apply_tactic"; *) +(* prerr_endline (Continuationals.Stack.pp (GrafiteTypes.get_stack status)); *) + let starting_metasenv = GrafiteTypes.get_proof_metasenv status in + let before = List.map (fun g, _, _ -> g) starting_metasenv in +(* prerr_endline "disambiguate"; *) + let status, tactic = disambiguate_tactic status goal tactic in + let metasenv_after_refinement = GrafiteTypes.get_proof_metasenv status in + let proof = GrafiteTypes.get_current_proof status in + let proof_status = proof, goal in + let needs_reordering, always_opens_a_goal = classify_tactic tactic in + let tactic = tactic_of_ast tactic in + (* apply tactic will change the lexicon_status ... *) +(* prerr_endline "apply_tactic bassa"; *) + let (proof, opened) = ProofEngineTypes.apply_tactic tactic proof_status in + let after = ProofEngineTypes.goals_of_proof proof in + let opened_goals, closed_goals = Tacticals.goals_diff ~before ~after ~opened in +(* prerr_endline("before: " ^ String.concat ", " (List.map string_of_int before)); +prerr_endline("after: " ^ String.concat ", " (List.map string_of_int after)); +prerr_endline("opened: " ^ String.concat ", " (List.map string_of_int opened)); *) +(* prerr_endline("opened_goals: " ^ String.concat ", " (List.map string_of_int opened_goals)); +prerr_endline("closed_goals: " ^ String.concat ", " (List.map string_of_int closed_goals)); *) + let proof, opened_goals = + if needs_reordering then begin + let uri, metasenv_after_tactic, t, ty = proof in +(* prerr_endline ("goal prima del riordino: " ^ String.concat " " (List.map string_of_int (ProofEngineTypes.goals_of_proof proof))); *) + let reordered_metasenv, opened_goals = + reorder_metasenv + starting_metasenv + metasenv_after_refinement metasenv_after_tactic + opened goal always_opens_a_goal + in + let proof' = uri, reordered_metasenv, t, ty in +(* prerr_endline ("goal dopo il riordino: " ^ String.concat " " (List.map string_of_int (ProofEngineTypes.goals_of_proof proof'))); *) + proof', opened_goals + end + else + proof, opened_goals + in + let incomplete_proof = + match status.GrafiteTypes.proof_status with + | GrafiteTypes.Incomplete_proof p -> p + | _ -> assert false + in + { status with GrafiteTypes.proof_status = + GrafiteTypes.Incomplete_proof + { incomplete_proof with GrafiteTypes.proof = proof } }, + opened_goals, closed_goals + +type eval_ast = + {ea_go: + 'term 'lazy_term 'reduction 'obj 'ident. + disambiguate_tactic: + (GrafiteTypes.status -> + ProofEngineTypes.goal -> + ('term, 'lazy_term, 'reduction, 'ident) GrafiteAst.tactic -> + GrafiteTypes.status * + (Cic.term, Cic.lazy_term, Cic.lazy_term GrafiteAst.reduction, string) GrafiteAst.tactic) -> + + disambiguate_command: + (GrafiteTypes.status -> + 'obj GrafiteAst.command -> + GrafiteTypes.status * Cic.obj GrafiteAst.command) -> + + disambiguate_macro: + (GrafiteTypes.status -> + 'term GrafiteAst.macro -> + Cic.context -> GrafiteTypes.status * Cic.term GrafiteAst.macro) -> + + ?do_heavy_checks:bool -> + ?clean_baseuri:bool -> + GrafiteTypes.status -> + ('term, 'lazy_term, 'reduction, 'obj, 'ident) GrafiteAst.statement -> + GrafiteTypes.status * UriManager.uri list + } + +type 'a eval_command = + {ec_go: 'term 'obj. + disambiguate_command: + (GrafiteTypes.status -> + 'obj GrafiteAst.command -> + GrafiteTypes.status * Cic.obj GrafiteAst.command) -> + options -> GrafiteTypes.status -> 'obj GrafiteAst.command -> + GrafiteTypes.status * UriManager.uri list + } + +type 'a eval_executable = + {ee_go: 'term 'lazy_term 'reduction 'obj 'ident. + disambiguate_tactic: + (GrafiteTypes.status -> + ProofEngineTypes.goal -> + ('term, 'lazy_term, 'reduction, 'ident) GrafiteAst.tactic -> + GrafiteTypes.status * + (Cic.term, Cic.lazy_term, Cic.lazy_term GrafiteAst.reduction, string) GrafiteAst.tactic) -> + + disambiguate_command: + (GrafiteTypes.status -> + 'obj GrafiteAst.command -> + GrafiteTypes.status * Cic.obj GrafiteAst.command) -> + + disambiguate_macro: + (GrafiteTypes.status -> + 'term GrafiteAst.macro -> + Cic.context -> GrafiteTypes.status * Cic.term GrafiteAst.macro) -> + + options -> + GrafiteTypes.status -> + ('term, 'lazy_term, 'reduction, 'obj, 'ident) GrafiteAst.code -> + GrafiteTypes.status * UriManager.uri list + } + +type 'a eval_from_moo = + { efm_go: GrafiteTypes.status -> string -> GrafiteTypes.status } + +let coercion_moo_statement_of uri = + GrafiteAst.Coercion (HExtlib.dummy_floc, uri, false) + +let eval_coercion status ~add_composites uri = + let basedir = Helm_registry.get "matita.basedir" in + let status,compounds = + GrafiteSync.add_coercion ~basedir ~add_composites status uri in + let moo_content = coercion_moo_statement_of uri in + let status = GrafiteTypes.add_moo_content [moo_content] status in + {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof}, + compounds + +let eval_tactical ~disambiguate_tactic status tac = + let apply_tactic = apply_tactic ~disambiguate_tactic in + let module MatitaStatus = + struct + type input_status = GrafiteTypes.status * ProofEngineTypes.goal + + type output_status = + GrafiteTypes.status * ProofEngineTypes.goal list * ProofEngineTypes.goal list + + type tactic = input_status -> output_status + + let id_tactic = apply_tactic (GrafiteAst.IdTac HExtlib.dummy_floc) + let mk_tactic tac = tac + let apply_tactic tac = tac + let goals (_, opened, closed) = opened, closed + let set_goals (opened, closed) (status, _, _) = (status, opened, closed) + let get_stack (status, _) = GrafiteTypes.get_stack status + + let set_stack stack (status, opened, closed) = + GrafiteTypes.set_stack stack status, opened, closed + + let inject (status, _) = (status, [], []) + let focus goal (status, _, _) = (status, goal) + end + in + let module MatitaTacticals = Tacticals.Make (MatitaStatus) in + let rec tactical_of_ast l tac = + match tac with + | GrafiteAst.Tactic (loc, tactic) -> + MatitaTacticals.tactic (MatitaStatus.mk_tactic (apply_tactic tactic)) + | GrafiteAst.Seq (loc, tacticals) -> (* tac1; tac2; ... *) + assert (l > 0); + MatitaTacticals.seq ~tactics:(List.map (tactical_of_ast (l+1)) tacticals) + | GrafiteAst.Do (loc, n, tactical) -> + MatitaTacticals.do_tactic ~n ~tactic:(tactical_of_ast (l+1) tactical) + | GrafiteAst.Repeat (loc, tactical) -> + MatitaTacticals.repeat_tactic ~tactic:(tactical_of_ast (l+1) tactical) + | GrafiteAst.Then (loc, tactical, tacticals) -> (* tac; [ tac1 | ... ] *) + assert (l > 0); + MatitaTacticals.thens ~start:(tactical_of_ast (l+1) tactical) + ~continuations:(List.map (tactical_of_ast (l+1)) tacticals) + | GrafiteAst.First (loc, tacticals) -> + MatitaTacticals.first + ~tactics:(List.map (fun t -> "", tactical_of_ast (l+1) t) tacticals) + | GrafiteAst.Try (loc, tactical) -> + MatitaTacticals.try_tactic ~tactic:(tactical_of_ast (l+1) tactical) + | GrafiteAst.Solve (loc, tacticals) -> + MatitaTacticals.solve_tactics + ~tactics:(List.map (fun t -> "", tactical_of_ast (l+1) t) tacticals) + + | GrafiteAst.Skip loc -> MatitaTacticals.skip + | GrafiteAst.Dot loc -> MatitaTacticals.dot + | GrafiteAst.Semicolon loc -> MatitaTacticals.semicolon + | GrafiteAst.Branch loc -> MatitaTacticals.branch + | GrafiteAst.Shift loc -> MatitaTacticals.shift + | GrafiteAst.Pos (loc, i) -> MatitaTacticals.pos i + | GrafiteAst.Merge loc -> MatitaTacticals.merge + | GrafiteAst.Focus (loc, goals) -> MatitaTacticals.focus goals + | GrafiteAst.Unfocus loc -> MatitaTacticals.unfocus + in + let status, _, _ = tactical_of_ast 0 tac (status, ~-1) in + let status = (* is proof completed? *) + match status.GrafiteTypes.proof_status with + | GrafiteTypes.Incomplete_proof + { GrafiteTypes.stack = stack; proof = proof } + when Continuationals.Stack.is_empty stack -> + { status with GrafiteTypes.proof_status = GrafiteTypes.Proof proof } + | _ -> status + in + status + +let eval_comment status c = status + +(* since the record syntax allows to declare coercions, we have to put this + * information inside the moo *) +let add_coercions_of_record_to_moo obj lemmas status = + let attributes = CicUtil.attributes_of_obj obj in + let is_record = function `Class (`Record att) -> Some att | _-> None in + match HExtlib.list_findopt is_record attributes with + | None -> status,[] + | Some fields -> + let is_a_coercion uri = + try + let obj,_ = + CicEnvironment.get_cooked_obj CicUniv.empty_ugraph uri in + let attrs = CicUtil.attributes_of_obj obj in + List.mem (`Class `Projection) attrs + with Not_found -> assert false + in + (* looking at the fields we can know the 'wanted' coercions, but not the + * actually generated ones. So, only the intersection between the wanted + * and the actual should be in the moo as coercion, while everithing in + * lemmas should go as aliases *) + let wanted_coercions = + HExtlib.filter_map + (function + | (name,true) -> + Some + (UriManager.uri_of_string + (GrafiteTypes.qualify status name ^ ".con")) + | _ -> None) + fields + in + prerr_endline "wanted coercions:"; + List.iter + (fun u -> prerr_endline (UriManager.string_of_uri u)) + wanted_coercions; + let coercions, moo_content = + List.split + (HExtlib.filter_map + (fun uri -> + let is_a_wanted_coercion = + List.exists (UriManager.eq uri) wanted_coercions in + if is_a_coercion uri && is_a_wanted_coercion then + Some (uri, coercion_moo_statement_of uri) + else + None) + lemmas) + in + List.iter + (fun u -> prerr_endline (UriManager.string_of_uri u)) + coercions; + let status = GrafiteTypes.add_moo_content moo_content status in + let basedir = Helm_registry.get "matita.basedir" in + List.fold_left + (fun (status,lemmas) uri -> + let status,new_lemmas = + GrafiteSync.add_coercion ~basedir ~add_composites:true status uri + in + status,new_lemmas@lemmas + ) (status,[]) coercions + +let add_obj uri obj status = + let basedir = Helm_registry.get "matita.basedir" in + let status,lemmas = GrafiteSync.add_obj ~basedir uri obj status in + status, lemmas + +let rec eval_command = {ec_go = fun ~disambiguate_command opts status cmd -> + let status,cmd = disambiguate_command status cmd in + let basedir = Helm_registry.get "matita.basedir" in + let status,uris = + match cmd with + | GrafiteAst.Default (loc, what, uris) as cmd -> + LibraryObjects.set_default what uris; + GrafiteTypes.add_moo_content [cmd] status,[] + | GrafiteAst.Include (loc, baseuri) -> + let moopath = LibraryMisc.obj_file_of_baseuri ~basedir ~baseuri in + if not (Sys.file_exists moopath) then + raise (IncludedFileNotCompiled moopath); + let status = eval_from_moo.efm_go status moopath in + status,[] + | GrafiteAst.Set (loc, name, value) -> + if name = "baseuri" then begin + let value = + let v = Http_getter_misc.strip_trailing_slash value in + try + ignore (String.index v ' '); + GrafiteTypes.command_error "baseuri can't contain spaces" + with Not_found -> v + in + if Http_getter_storage.is_read_only value then begin + HLog.error (sprintf "uri %s belongs to a read-only repository" value); + raise (ReadOnlyUri value) + end; + if not (GrafiteMisc.is_empty value) && opts.clean_baseuri then begin + HLog.message ("baseuri " ^ value ^ " is not empty"); + HLog.message ("cleaning baseuri " ^ value); + LibraryClean.clean_baseuris ~basedir [value]; + end; + end; + GrafiteTypes.set_option status name value,[] + | GrafiteAst.Drop loc -> raise Drop + | GrafiteAst.Qed loc -> + let uri, metasenv, bo, ty = + match status.GrafiteTypes.proof_status with + | GrafiteTypes.Proof (Some uri, metasenv, body, ty) -> + uri, metasenv, body, ty + | GrafiteTypes.Proof (None, metasenv, body, ty) -> + raise (GrafiteTypes.Command_error + ("Someone allows to start a theorem without giving the "^ + "name/uri. This should be fixed!")) + | _-> + raise + (GrafiteTypes.Command_error "You can't Qed an incomplete theorem") + in + if metasenv <> [] then + raise + (GrafiteTypes.Command_error + "Proof not completed! metasenv is not empty!"); + let name = UriManager.name_of_uri uri in + let obj = Cic.Constant (name,Some bo,ty,[],[]) in + let status, lemmas = add_obj uri obj status in + {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof}, + uri::lemmas + | GrafiteAst.Coercion (loc, uri, add_composites) -> + eval_coercion status ~add_composites uri + | GrafiteAst.Obj (loc,obj) -> + let ext,name = + match obj with + Cic.Constant (name,_,_,_,_) + | Cic.CurrentProof (name,_,_,_,_,_) -> ".con",name + | Cic.InductiveDefinition (types,_,_,_) -> + ".ind", + (match types with (name,_,_,_)::_ -> name | _ -> assert false) + | _ -> assert false in + let uri = + UriManager.uri_of_string (GrafiteTypes.qualify status name ^ ext) + in + let metasenv = GrafiteTypes.get_proof_metasenv status in + match obj with + | Cic.CurrentProof (_,metasenv',bo,ty,_,_) -> + let name = UriManager.name_of_uri uri in + if not(CicPp.check name ty) then + HLog.error ("Bad name: " ^ name); + if opts.do_heavy_checks then + begin + let dbd = LibraryDb.instance () in + let similar = Whelp.match_term ~dbd ty in + let similar_len = List.length similar in + if similar_len> 30 then + (HLog.message + ("Duplicate check will compare your theorem with " ^ + string_of_int similar_len ^ + " theorems, this may take a while.")); + let convertible = + List.filter ( + fun u -> + let t = CicUtil.term_of_uri u in + let ty',g = + CicTypeChecker.type_of_aux' + metasenv' [] t CicUniv.empty_ugraph + in + fst(CicReduction.are_convertible [] ty' ty g)) + similar + in + (match convertible with + | [] -> () + | x::_ -> + HLog.warn + ("Theorem already proved: " ^ UriManager.string_of_uri x ^ + "\nPlease use a variant.")); + end; + assert (metasenv = metasenv'); + let initial_proof = (Some uri, metasenv, bo, ty) in + let initial_stack = Continuationals.Stack.of_metasenv metasenv in + { status with GrafiteTypes.proof_status = + GrafiteTypes.Incomplete_proof + { GrafiteTypes.proof = initial_proof; stack = initial_stack } }, + [] + | _ -> + if metasenv <> [] then + raise (GrafiteTypes.Command_error ( + "metasenv not empty while giving a definition with body: " ^ + CicMetaSubst.ppmetasenv [] metasenv)); + let status, lemmas = add_obj uri obj status in + let status,new_lemmas = + add_coercions_of_record_to_moo obj lemmas status + in + {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof}, + uri::new_lemmas@lemmas + in + match status.GrafiteTypes.proof_status with + GrafiteTypes.Intermediate _ -> + {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof},uris + | _ -> status,uris + +} and eval_executable = {ee_go = fun ~disambiguate_tactic ~disambiguate_command ~disambiguate_macro opts status ex -> + match ex with + | GrafiteAst.Tactical (_, tac, None) -> + eval_tactical ~disambiguate_tactic status tac,[] + | GrafiteAst.Tactical (_, tac, Some punct) -> + let status = eval_tactical ~disambiguate_tactic status tac in + eval_tactical ~disambiguate_tactic status punct,[] + | GrafiteAst.Command (_, cmd) -> + eval_command.ec_go ~disambiguate_command opts status cmd + | GrafiteAst.Macro (loc, macro) -> + raise (Macro (loc,disambiguate_macro status macro)) + +} and eval_from_moo = {efm_go = fun status fname -> + let ast_of_cmd cmd = + GrafiteAst.Executable (HExtlib.dummy_floc, + GrafiteAst.Command (HExtlib.dummy_floc, + cmd)) + in + let moo = GrafiteMarshal.load_moo fname in + List.fold_left + (fun status ast -> + let ast = ast_of_cmd ast in + let status,lemmas = + eval_ast.ea_go + ~disambiguate_tactic:(fun status _ tactic -> status,tactic) + ~disambiguate_command:(fun status cmd -> status,cmd) + ~disambiguate_macro:(fun _ _ -> assert false) + status ast + in + assert (lemmas=[]); + status) + status moo +} and eval_ast = {ea_go = fun ~disambiguate_tactic ~disambiguate_command ~disambiguate_macro ?(do_heavy_checks=false) ?(clean_baseuri=true) status st +-> + let opts = { + do_heavy_checks = do_heavy_checks ; + clean_baseuri = clean_baseuri } + in + match st with + | GrafiteAst.Executable (_,ex) -> + eval_executable.ee_go ~disambiguate_tactic ~disambiguate_command + ~disambiguate_macro opts status ex + | GrafiteAst.Comment (_,c) -> eval_comment status c,[] +} + +let eval_ast = eval_ast.ea_go