]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/grafite_engine/grafiteEngine.ml
test branch
[helm.git] / helm / ocaml / grafite_engine / grafiteEngine.ml
diff --git a/helm/ocaml/grafite_engine/grafiteEngine.ml b/helm/ocaml/grafite_engine/grafiteEngine.ml
new file mode 100644 (file)
index 0000000..c0a453c
--- /dev/null
@@ -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