]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/grafite_engine/grafiteEngine.ml
Bug fixed: macros in the middle of a goto cursor or goto end-of-script were
[helm.git] / helm / ocaml / grafite_engine / grafiteEngine.ml
1 (* Copyright (C) 2005, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://helm.cs.unibo.it/
24  *)
25
26 (* $Id$ *)
27
28 exception Drop
29 exception IncludedFileNotCompiled of string (* file name *)
30 exception Macro of
31  GrafiteAst.loc *
32   (Cic.context -> GrafiteTypes.status * Cic.term GrafiteAst.macro)
33
34 type options = { 
35   do_heavy_checks: bool ; 
36   clean_baseuri: bool
37 }
38
39 (** create a ProofEngineTypes.mk_fresh_name_type function which uses given
40   * names as long as they are available, then it fallbacks to name generation
41   * using FreshNamesGenerator module *)
42 let namer_of names =
43   let len = List.length names in
44   let count = ref 0 in
45   fun metasenv context name ~typ ->
46     if !count < len then begin
47       let name = Cic.Name (List.nth names !count) in
48       incr count;
49       name
50     end else
51       FreshNamesGenerator.mk_fresh_name ~subst:[] metasenv context name ~typ
52
53 let tactic_of_ast ast =
54   let module PET = ProofEngineTypes in
55   match ast with
56   | GrafiteAst.Absurd (_, term) -> Tactics.absurd term
57   | GrafiteAst.Apply (_, term) -> Tactics.apply term
58   | GrafiteAst.Assumption _ -> Tactics.assumption
59   | GrafiteAst.Auto (_,depth,width,paramodulation,full) ->
60       AutoTactic.auto_tac ?depth ?width ?paramodulation ?full
61         ~dbd:(LibraryDb.instance ()) ()
62   | GrafiteAst.Change (_, pattern, with_what) ->
63      Tactics.change ~pattern with_what
64   | GrafiteAst.Clear (_,id) -> Tactics.clear id
65   | GrafiteAst.ClearBody (_,id) -> Tactics.clearbody id
66   | GrafiteAst.Contradiction _ -> Tactics.contradiction
67   | GrafiteAst.Compare (_, term) -> Tactics.compare term
68   | GrafiteAst.Constructor (_, n) -> Tactics.constructor n
69   | GrafiteAst.Cut (_, ident, term) ->
70      let names = match ident with None -> [] | Some id -> [id] in
71      Tactics.cut ~mk_fresh_name_callback:(namer_of names) term
72   | GrafiteAst.DecideEquality _ -> Tactics.decide_equality
73   | GrafiteAst.Decompose (_, types, what, names) -> 
74       let to_type = function
75          | GrafiteAst.Type (uri, typeno) -> uri, typeno
76          | GrafiteAst.Ident _            -> assert false
77       in
78       let user_types = List.rev_map to_type types in
79       let dbd = LibraryDb.instance () in
80       let mk_fresh_name_callback = namer_of names in
81       Tactics.decompose ~mk_fresh_name_callback ~dbd ~user_types what
82   | GrafiteAst.Discriminate (_,term) -> Tactics.discriminate term
83   | GrafiteAst.Elim (_, what, using, depth, names) ->
84       Tactics.elim_intros ?using ?depth ~mk_fresh_name_callback:(namer_of names)
85         what
86   | GrafiteAst.ElimType (_, what, using, depth, names) ->
87       Tactics.elim_type ?using ?depth ~mk_fresh_name_callback:(namer_of names)
88         what
89   | GrafiteAst.Exact (_, term) -> Tactics.exact term
90   | GrafiteAst.Exists _ -> Tactics.exists
91   | GrafiteAst.Fail _ -> Tactics.fail
92   | GrafiteAst.Fold (_, reduction_kind, term, pattern) ->
93       let reduction =
94         match reduction_kind with
95         | `Normalize ->
96             PET.const_lazy_reduction
97               (CicReduction.normalize ~delta:false ~subst:[])
98         | `Reduce -> PET.const_lazy_reduction ProofEngineReduction.reduce
99         | `Simpl -> PET.const_lazy_reduction ProofEngineReduction.simpl
100         | `Unfold None ->
101             PET.const_lazy_reduction (ProofEngineReduction.unfold ?what:None)
102         | `Unfold (Some lazy_term) ->
103            (fun context metasenv ugraph ->
104              let what, metasenv, ugraph = lazy_term context metasenv ugraph in
105              ProofEngineReduction.unfold ~what, metasenv, ugraph)
106         | `Whd ->
107             PET.const_lazy_reduction (CicReduction.whd ~delta:false ~subst:[])
108       in
109       Tactics.fold ~reduction ~term ~pattern
110   | GrafiteAst.Fourier _ -> Tactics.fourier
111   | GrafiteAst.FwdSimpl (_, hyp, names) -> 
112      Tactics.fwd_simpl ~mk_fresh_name_callback:(namer_of names)
113       ~dbd:(LibraryDb.instance ()) hyp
114   | GrafiteAst.Generalize (_,pattern,ident) ->
115      let names = match ident with None -> [] | Some id -> [id] in
116      Tactics.generalize ~mk_fresh_name_callback:(namer_of names) pattern 
117   | GrafiteAst.Goal (_, n) -> Tactics.set_goal n
118   | GrafiteAst.IdTac _ -> Tactics.id
119   | GrafiteAst.Injection (_,term) -> Tactics.injection term
120   | GrafiteAst.Intros (_, None, names) ->
121       PrimitiveTactics.intros_tac ~mk_fresh_name_callback:(namer_of names) ()
122   | GrafiteAst.Intros (_, Some num, names) ->
123       PrimitiveTactics.intros_tac ~howmany:num
124         ~mk_fresh_name_callback:(namer_of names) ()
125   | GrafiteAst.Inversion (_, term) ->
126       Tactics.inversion term
127   | GrafiteAst.LApply (_, how_many, to_what, what, ident) ->
128       let names = match ident with None -> [] | Some id -> [id] in
129       Tactics.lapply ~mk_fresh_name_callback:(namer_of names) ?how_many
130         ~to_what what
131   | GrafiteAst.Left _ -> Tactics.left
132   | GrafiteAst.LetIn (loc,term,name) ->
133       Tactics.letin term ~mk_fresh_name_callback:(namer_of [name])
134   | GrafiteAst.Reduce (_, reduction_kind, pattern) ->
135       (match reduction_kind with
136       | `Normalize -> Tactics.normalize ~pattern
137       | `Reduce -> Tactics.reduce ~pattern  
138       | `Simpl -> Tactics.simpl ~pattern 
139       | `Unfold what -> Tactics.unfold ~pattern what
140       | `Whd -> Tactics.whd ~pattern)
141   | GrafiteAst.Reflexivity _ -> Tactics.reflexivity
142   | GrafiteAst.Replace (_, pattern, with_what) ->
143      Tactics.replace ~pattern ~with_what
144   | GrafiteAst.Rewrite (_, direction, t, pattern) ->
145      EqualityTactics.rewrite_tac ~direction ~pattern t
146   | GrafiteAst.Right _ -> Tactics.right
147   | GrafiteAst.Ring _ -> Tactics.ring
148   | GrafiteAst.Split _ -> Tactics.split
149   | GrafiteAst.Symmetry _ -> Tactics.symmetry
150   | GrafiteAst.Transitivity (_, term) -> Tactics.transitivity term
151
152 (* maybe we only need special cases for apply and goal *)
153 let classify_tactic tactic = 
154   match tactic with
155   (* tactics that can't close the goal (return a goal we want to "select") *)
156   | GrafiteAst.Rewrite _ 
157   | GrafiteAst.Split _ 
158   | GrafiteAst.Replace _ 
159   | GrafiteAst.Reduce _
160   | GrafiteAst.Injection _ 
161   | GrafiteAst.IdTac _ 
162   | GrafiteAst.Generalize _ 
163   | GrafiteAst.Elim _ 
164   | GrafiteAst.Cut _
165   | GrafiteAst.Decompose _ -> true, true
166   (* tactics we don't want to reorder goals. I think only Goal needs this. *)
167   | GrafiteAst.Goal _ -> false, true
168   (* tactics like apply *)
169   | _ -> true, false
170   
171 let reorder_metasenv start refine tactic goals current_goal always_opens_a_goal=
172   let module PEH = ProofEngineHelpers in
173 (*   let print_m name metasenv =
174     prerr_endline (">>>>> " ^ name);
175     prerr_endline (CicMetaSubst.ppmetasenv [] metasenv)
176   in *)
177   (* phase one calculates:
178    *   new_goals_from_refine:  goals added by refine
179    *   head_goal:              the first goal opened by ythe tactic 
180    *   other_goals:            other goals opened by the tactic
181    *)
182   let new_goals_from_refine = PEH.compare_metasenvs start refine in
183   let new_goals_from_tactic = PEH.compare_metasenvs refine tactic in
184   let head_goal, other_goals, goals = 
185     match goals with
186     | [] -> None,[],goals
187     | hd::tl -> 
188         (* assert (List.mem hd new_goals_from_tactic);
189          * invalidato dalla goal_tac
190          * *)
191         Some hd, List.filter ((<>) hd) new_goals_from_tactic, List.filter ((<>)
192         hd) goals
193   in
194   let produced_goals = 
195     match head_goal with
196     | None -> new_goals_from_refine @ other_goals
197     | Some x -> x :: new_goals_from_refine @ other_goals
198   in
199   (* extract the metas generated by refine and tactic *)
200   let metas_for_tactic_head = 
201     match head_goal with
202     | None -> []
203     | Some head_goal -> List.filter (fun (n,_,_) -> n = head_goal) tactic in
204   let metas_for_tactic_goals = 
205     List.map 
206       (fun x -> List.find (fun (metano,_,_) -> metano = x) tactic)
207     goals 
208   in
209   let metas_for_refine_goals = 
210     List.filter (fun (n,_,_) -> List.mem n new_goals_from_refine) tactic in
211   let produced_metas, goals = 
212     let produced_metas =
213       if always_opens_a_goal then
214         metas_for_tactic_head @ metas_for_refine_goals @ 
215           metas_for_tactic_goals
216       else begin
217 (*         print_m "metas_for_refine_goals" metas_for_refine_goals;
218         print_m "metas_for_tactic_head" metas_for_tactic_head;
219         print_m "metas_for_tactic_goals" metas_for_tactic_goals; *)
220         metas_for_refine_goals @ metas_for_tactic_head @ 
221           metas_for_tactic_goals
222       end
223     in
224     let goals = List.map (fun (metano, _, _) -> metano)  produced_metas in
225     produced_metas, goals
226   in
227   (* residual metas, preserving the original order *)
228   let before, after = 
229     let rec split e =
230       function 
231       | [] -> [],[]
232       | (metano, _, _) :: tl when metano = e -> 
233           [], List.map (fun (x,_,_) -> x) tl
234       | (metano, _, _) :: tl -> let b, a = split e tl in metano :: b, a
235     in
236     let find n metasenv =
237       try
238         Some (List.find (fun (metano, _, _) -> metano = n) metasenv)
239       with Not_found -> None
240     in
241     let extract l =
242       List.fold_right 
243         (fun n acc -> 
244           match find n tactic with
245           | Some x -> x::acc
246           | None -> acc
247         ) l [] in
248     let before_l, after_l = split current_goal start in
249     let before_l = 
250       List.filter (fun x -> not (List.mem x produced_goals)) before_l in
251     let after_l = 
252       List.filter (fun x -> not (List.mem x produced_goals)) after_l in
253     let before = extract before_l in
254     let after = extract after_l in
255       before, after
256   in
257 (* |+   DEBUG CODE  +|
258   print_m "BEGIN" start;
259   prerr_endline ("goal was: " ^ string_of_int current_goal);
260   prerr_endline ("and metas from refine are:");
261   List.iter 
262     (fun t -> prerr_string (" " ^ string_of_int t)) 
263   new_goals_from_refine;
264   prerr_endline "";
265   print_m "before" before;
266   print_m "metas_for_tactic_head" metas_for_tactic_head;
267   print_m "metas_for_refine_goals" metas_for_refine_goals;
268   print_m "metas_for_tactic_goals" metas_for_tactic_goals;
269   print_m "produced_metas" produced_metas;
270   print_m "after" after; 
271 |+   FINE DEBUG CODE +| *)
272   before @ produced_metas @ after, goals 
273   
274 let apply_tactic ~disambiguate_tactic tactic (status, goal) =
275 (* prerr_endline "apply_tactic"; *)
276 (* prerr_endline (Continuationals.Stack.pp (GrafiteTypes.get_stack status)); *)
277  let starting_metasenv = GrafiteTypes.get_proof_metasenv status in
278  let before = List.map (fun g, _, _ -> g) starting_metasenv in
279 (* prerr_endline "disambiguate"; *)
280  let status, tactic = disambiguate_tactic status goal tactic in
281  let metasenv_after_refinement =  GrafiteTypes.get_proof_metasenv status in
282  let proof = GrafiteTypes.get_current_proof status in
283  let proof_status = proof, goal in
284  let needs_reordering, always_opens_a_goal = classify_tactic tactic in
285  let tactic = tactic_of_ast tactic in
286  (* apply tactic will change the lexicon_status ... *)
287 (* prerr_endline "apply_tactic bassa"; *)
288  let (proof, opened) = ProofEngineTypes.apply_tactic tactic proof_status in
289  let after = ProofEngineTypes.goals_of_proof proof in
290  let opened_goals, closed_goals = Tacticals.goals_diff ~before ~after ~opened in
291 (* prerr_endline("before: " ^ String.concat ", " (List.map string_of_int before));
292 prerr_endline("after: " ^ String.concat ", " (List.map string_of_int after));
293 prerr_endline("opened: " ^ String.concat ", " (List.map string_of_int opened)); *)
294 (* prerr_endline("opened_goals: " ^ String.concat ", " (List.map string_of_int opened_goals));
295 prerr_endline("closed_goals: " ^ String.concat ", " (List.map string_of_int closed_goals)); *)
296  let proof, opened_goals = 
297    if needs_reordering then begin
298      let uri, metasenv_after_tactic, t, ty = proof in
299 (* prerr_endline ("goal prima del riordino: " ^ String.concat " " (List.map string_of_int (ProofEngineTypes.goals_of_proof proof))); *)
300      let reordered_metasenv, opened_goals = 
301        reorder_metasenv
302         starting_metasenv
303         metasenv_after_refinement metasenv_after_tactic
304         opened goal always_opens_a_goal
305      in
306      let proof' = uri, reordered_metasenv, t, ty in
307 (* prerr_endline ("goal dopo il riordino: " ^ String.concat " " (List.map string_of_int (ProofEngineTypes.goals_of_proof proof'))); *)
308      proof', opened_goals
309    end
310       else
311         proof, opened_goals
312  in
313  let incomplete_proof =
314    match status.GrafiteTypes.proof_status with
315    | GrafiteTypes.Incomplete_proof p -> p
316    | _ -> assert false
317  in
318  { status with GrafiteTypes.proof_status =
319     GrafiteTypes.Incomplete_proof
320      { incomplete_proof with GrafiteTypes.proof = proof } },
321  opened_goals, closed_goals
322
323 type eval_ast =
324  {ea_go:
325   'term 'lazy_term 'reduction 'obj 'ident.
326   disambiguate_tactic:
327    (GrafiteTypes.status ->
328     ProofEngineTypes.goal ->
329     ('term, 'lazy_term, 'reduction, 'ident) GrafiteAst.tactic ->
330     GrafiteTypes.status *
331    (Cic.term, Cic.lazy_term, Cic.lazy_term GrafiteAst.reduction, string) GrafiteAst.tactic) ->
332
333   disambiguate_command:
334    (GrafiteTypes.status ->
335     'obj GrafiteAst.command ->
336     GrafiteTypes.status * Cic.obj GrafiteAst.command) ->
337
338   disambiguate_macro:
339    (GrafiteTypes.status ->
340     'term GrafiteAst.macro ->
341     Cic.context -> GrafiteTypes.status * Cic.term GrafiteAst.macro) ->
342
343   ?do_heavy_checks:bool ->
344   ?clean_baseuri:bool ->
345   GrafiteTypes.status ->
346   ('term, 'lazy_term, 'reduction, 'obj, 'ident) GrafiteAst.statement ->
347   GrafiteTypes.status * UriManager.uri list
348  }
349
350 type 'a eval_command =
351  {ec_go: 'term 'obj.
352   disambiguate_command:
353    (GrafiteTypes.status ->
354     'obj GrafiteAst.command ->
355     GrafiteTypes.status * Cic.obj GrafiteAst.command) ->
356   options -> GrafiteTypes.status -> 'obj GrafiteAst.command ->
357    GrafiteTypes.status * UriManager.uri list
358  }
359
360 type 'a eval_executable =
361  {ee_go: 'term 'lazy_term 'reduction 'obj 'ident.
362   disambiguate_tactic:
363    (GrafiteTypes.status ->
364     ProofEngineTypes.goal ->
365     ('term, 'lazy_term, 'reduction, 'ident) GrafiteAst.tactic ->
366     GrafiteTypes.status *
367    (Cic.term, Cic.lazy_term, Cic.lazy_term GrafiteAst.reduction, string) GrafiteAst.tactic) ->
368
369   disambiguate_command:
370    (GrafiteTypes.status ->
371     'obj GrafiteAst.command ->
372     GrafiteTypes.status * Cic.obj GrafiteAst.command) ->
373
374   disambiguate_macro:
375    (GrafiteTypes.status ->
376     'term GrafiteAst.macro ->
377     Cic.context -> GrafiteTypes.status * Cic.term GrafiteAst.macro) ->
378
379   options ->
380   GrafiteTypes.status ->
381   ('term, 'lazy_term, 'reduction, 'obj, 'ident) GrafiteAst.code ->
382   GrafiteTypes.status * UriManager.uri list
383  }
384
385 type 'a eval_from_moo =
386  { efm_go: GrafiteTypes.status -> string -> GrafiteTypes.status }
387       
388 let coercion_moo_statement_of uri =
389   GrafiteAst.Coercion (HExtlib.dummy_floc, uri, false)
390
391 let eval_coercion status ~add_composites uri =
392  let basedir = Helm_registry.get "matita.basedir" in
393  let status,compounds =
394   GrafiteSync.add_coercion ~basedir ~add_composites status uri in
395  let moo_content = coercion_moo_statement_of uri in
396  let status = GrafiteTypes.add_moo_content [moo_content] status in
397   {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof},
398    compounds
399
400 let eval_tactical ~disambiguate_tactic status tac =
401  let apply_tactic = apply_tactic ~disambiguate_tactic in
402  let module MatitaStatus =
403   struct
404    type input_status = GrafiteTypes.status * ProofEngineTypes.goal
405  
406    type output_status =
407      GrafiteTypes.status * ProofEngineTypes.goal list * ProofEngineTypes.goal list
408  
409    type tactic = input_status -> output_status
410  
411    let id_tactic = apply_tactic (GrafiteAst.IdTac HExtlib.dummy_floc)
412    let mk_tactic tac = tac
413    let apply_tactic tac = tac
414    let goals (_, opened, closed) = opened, closed
415    let set_goals (opened, closed) (status, _, _) = (status, opened, closed)
416    let get_stack (status, _) = GrafiteTypes.get_stack status
417  
418    let set_stack stack (status, opened, closed) = 
419      GrafiteTypes.set_stack stack status, opened, closed
420  
421    let inject (status, _) = (status, [], [])
422    let focus goal (status, _, _) = (status, goal)
423   end
424  in
425  let module MatitaTacticals = Tacticals.Make (MatitaStatus) in
426   let rec tactical_of_ast l tac =
427     match tac with
428     | GrafiteAst.Tactic (loc, tactic) ->
429         MatitaTacticals.tactic (MatitaStatus.mk_tactic (apply_tactic tactic))
430     | GrafiteAst.Seq (loc, tacticals) ->  (* tac1; tac2; ... *)
431        assert (l > 0);
432        MatitaTacticals.seq ~tactics:(List.map (tactical_of_ast (l+1)) tacticals)
433     | GrafiteAst.Do (loc, n, tactical) ->
434         MatitaTacticals.do_tactic ~n ~tactic:(tactical_of_ast (l+1) tactical)
435     | GrafiteAst.Repeat (loc, tactical) ->
436         MatitaTacticals.repeat_tactic ~tactic:(tactical_of_ast (l+1) tactical)
437     | GrafiteAst.Then (loc, tactical, tacticals) ->  (* tac; [ tac1 | ... ] *)
438         assert (l > 0);
439         MatitaTacticals.thens ~start:(tactical_of_ast (l+1) tactical)
440           ~continuations:(List.map (tactical_of_ast (l+1)) tacticals)
441     | GrafiteAst.First (loc, tacticals) ->
442         MatitaTacticals.first
443           ~tactics:(List.map (fun t -> "", tactical_of_ast (l+1) t) tacticals)
444     | GrafiteAst.Try (loc, tactical) ->
445         MatitaTacticals.try_tactic ~tactic:(tactical_of_ast (l+1) tactical)
446     | GrafiteAst.Solve (loc, tacticals) ->
447         MatitaTacticals.solve_tactics
448          ~tactics:(List.map (fun t -> "", tactical_of_ast (l+1) t) tacticals)
449
450     | GrafiteAst.Skip loc -> MatitaTacticals.skip
451     | GrafiteAst.Dot loc -> MatitaTacticals.dot
452     | GrafiteAst.Semicolon loc -> MatitaTacticals.semicolon
453     | GrafiteAst.Branch loc -> MatitaTacticals.branch
454     | GrafiteAst.Shift loc -> MatitaTacticals.shift
455     | GrafiteAst.Pos (loc, i) -> MatitaTacticals.pos i
456     | GrafiteAst.Merge loc -> MatitaTacticals.merge
457     | GrafiteAst.Focus (loc, goals) -> MatitaTacticals.focus goals
458     | GrafiteAst.Unfocus loc -> MatitaTacticals.unfocus
459   in
460   let status, _, _ = tactical_of_ast 0 tac (status, ~-1) in
461   let status =  (* is proof completed? *)
462     match status.GrafiteTypes.proof_status with
463     | GrafiteTypes.Incomplete_proof
464        { GrafiteTypes.stack = stack; proof = proof }
465       when Continuationals.Stack.is_empty stack ->
466         { status with GrafiteTypes.proof_status = GrafiteTypes.Proof proof }
467     | _ -> status
468   in
469   status
470
471 let eval_comment status c = status
472
473 (* since the record syntax allows to declare coercions, we have to put this
474  * information inside the moo *)
475 let add_coercions_of_record_to_moo obj lemmas status =
476   let attributes = CicUtil.attributes_of_obj obj in
477   let is_record = function `Class (`Record att) -> Some att | _-> None in
478   match HExtlib.list_findopt is_record attributes with
479   | None -> status,[]
480   | Some fields -> 
481       let is_a_coercion uri =
482         try
483           let obj,_ = 
484             CicEnvironment.get_cooked_obj  CicUniv.empty_ugraph uri in
485           let attrs = CicUtil.attributes_of_obj obj in
486           List.mem (`Class `Projection) attrs
487         with Not_found -> assert false
488       in
489       (* looking at the fields we can know the 'wanted' coercions, but not the 
490        * actually generated ones. So, only the intersection between the wanted
491        * and the actual should be in the moo as coercion, while everithing in
492        * lemmas should go as aliases *)
493       let wanted_coercions = 
494         HExtlib.filter_map 
495           (function 
496             | (name,true) -> 
497                Some 
498                  (UriManager.uri_of_string 
499                    (GrafiteTypes.qualify status name ^ ".con"))
500             | _ -> None) 
501           fields
502       in
503       prerr_endline "wanted coercions:";
504       List.iter 
505         (fun u -> prerr_endline (UriManager.string_of_uri u)) 
506         wanted_coercions;
507       let coercions, moo_content = 
508         List.split
509           (HExtlib.filter_map 
510             (fun uri ->
511               let is_a_wanted_coercion = 
512                 List.exists (UriManager.eq uri) wanted_coercions in
513               if is_a_coercion uri && is_a_wanted_coercion then
514                 Some (uri, coercion_moo_statement_of uri)
515               else
516                 None) 
517             lemmas)
518       in
519       List.iter 
520         (fun u -> prerr_endline (UriManager.string_of_uri u)) 
521         coercions;
522       let status = GrafiteTypes.add_moo_content moo_content status in
523       let basedir = Helm_registry.get "matita.basedir" in
524       List.fold_left 
525         (fun (status,lemmas) uri ->
526           let status,new_lemmas =
527            GrafiteSync.add_coercion ~basedir ~add_composites:true status uri
528           in
529            status,new_lemmas@lemmas
530         ) (status,[]) coercions
531
532 let add_obj uri obj status =
533  let basedir = Helm_registry.get "matita.basedir" in
534  let status,lemmas = GrafiteSync.add_obj ~basedir uri obj status in
535  status, lemmas 
536       
537 let rec eval_command = {ec_go = fun ~disambiguate_command opts status cmd ->
538  let status,cmd = disambiguate_command status cmd in
539  let basedir = Helm_registry.get "matita.basedir" in
540  let status,uris =
541   match cmd with
542   | GrafiteAst.Default (loc, what, uris) as cmd ->
543      LibraryObjects.set_default what uris;
544      GrafiteTypes.add_moo_content [cmd] status,[]
545   | GrafiteAst.Include (loc, baseuri) ->
546      let moopath = LibraryMisc.obj_file_of_baseuri ~basedir ~baseuri in
547      let metadatapath= LibraryMisc.metadata_file_of_baseuri ~basedir ~baseuri in
548      if not (Sys.file_exists moopath) then
549        raise (IncludedFileNotCompiled moopath);
550      let status = eval_from_moo.efm_go status moopath in
551      status,[]
552   | GrafiteAst.Set (loc, name, value) -> 
553       if name = "baseuri" then begin
554         let value = 
555           let v = Http_getter_misc.strip_trailing_slash value in
556           try
557             ignore (String.index v ' ');
558             raise (GrafiteTypes.Command_error "baseuri can't contain spaces")
559           with Not_found -> v
560         in
561         if not (GrafiteMisc.is_empty value) && opts.clean_baseuri then begin
562           HLog.warn ("baseuri " ^ value ^ " is not empty");
563           HLog.message ("cleaning baseuri " ^ value);
564           LibraryClean.clean_baseuris ~basedir [value];
565         end;
566       end;
567       GrafiteTypes.set_option status name value,[]
568   | GrafiteAst.Drop loc -> raise Drop
569   | GrafiteAst.Qed loc ->
570       let uri, metasenv, bo, ty =
571         match status.GrafiteTypes.proof_status with
572         | GrafiteTypes.Proof (Some uri, metasenv, body, ty) ->
573             uri, metasenv, body, ty
574         | GrafiteTypes.Proof (None, metasenv, body, ty) -> 
575             raise (GrafiteTypes.Command_error 
576               ("Someone allows to start a theorem without giving the "^
577                "name/uri. This should be fixed!"))
578         | _->
579           raise
580            (GrafiteTypes.Command_error "You can't Qed an incomplete theorem")
581       in
582       if metasenv <> [] then 
583         raise
584          (GrafiteTypes.Command_error
585            "Proof not completed! metasenv is not empty!");
586       let name = UriManager.name_of_uri uri in
587       let obj = Cic.Constant (name,Some bo,ty,[],[]) in
588       let status, lemmas = add_obj uri obj status in
589        {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof},
590         uri::lemmas
591   | GrafiteAst.Coercion (loc, uri, add_composites) ->
592      eval_coercion status ~add_composites uri
593   | GrafiteAst.Obj (loc,obj) ->
594      let ext,name =
595       match obj with
596          Cic.Constant (name,_,_,_,_)
597        | Cic.CurrentProof (name,_,_,_,_,_) -> ".con",name
598        | Cic.InductiveDefinition (types,_,_,_) ->
599           ".ind",
600           (match types with (name,_,_,_)::_ -> name | _ -> assert false)
601        | _ -> assert false in
602      let uri = 
603        UriManager.uri_of_string (GrafiteTypes.qualify status name ^ ext) 
604      in
605      let metasenv = GrafiteTypes.get_proof_metasenv status in
606      match obj with
607      | Cic.CurrentProof (_,metasenv',bo,ty,_,_) ->
608          let name = UriManager.name_of_uri uri in
609          if not(CicPp.check name ty) then
610            HLog.error ("Bad name: " ^ name);
611          if opts.do_heavy_checks then
612            begin
613              let dbd = LibraryDb.instance () in
614              let similar = Whelp.match_term ~dbd ty in
615              let similar_len = List.length similar in
616              if similar_len> 30 then
617                (HLog.message
618                  ("Duplicate check will compare your theorem with " ^ 
619                    string_of_int similar_len ^ 
620                    " theorems, this may take a while."));
621              let convertible =
622                List.filter (
623                  fun u ->
624                    let t = CicUtil.term_of_uri u in
625                    let ty',g = 
626                      CicTypeChecker.type_of_aux' 
627                        metasenv' [] t CicUniv.empty_ugraph
628                    in
629                    fst(CicReduction.are_convertible [] ty' ty g)) 
630                similar 
631              in
632              (match convertible with
633              | [] -> ()
634              | x::_ -> 
635                  HLog.warn  
636                  ("Theorem already proved: " ^ UriManager.string_of_uri x ^ 
637                   "\nPlease use a variant."));
638            end;
639          assert (metasenv = metasenv');
640          let goalno =
641            match metasenv' with (goalno,_,_)::_ -> goalno | _ -> assert false 
642          in
643          let initial_proof = (Some uri, metasenv, bo, ty) in
644          let initial_stack = Continuationals.Stack.of_metasenv metasenv in
645          { status with GrafiteTypes.proof_status =
646             GrafiteTypes.Incomplete_proof
647              { GrafiteTypes.proof = initial_proof; stack = initial_stack } },
648           []
649      | _ ->
650          if metasenv <> [] then
651           raise (GrafiteTypes.Command_error (
652             "metasenv not empty while giving a definition with body: " ^
653             CicMetaSubst.ppmetasenv [] metasenv));
654          let status, lemmas = add_obj uri obj status in 
655          let status,new_lemmas =
656           add_coercions_of_record_to_moo obj lemmas status
657          in
658           {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof},
659            uri::new_lemmas@lemmas
660  in
661   match status.GrafiteTypes.proof_status with
662      GrafiteTypes.Intermediate _ ->
663       {status with GrafiteTypes.proof_status = GrafiteTypes.No_proof},uris
664    | _ -> status,uris
665
666 } and eval_executable = {ee_go = fun ~disambiguate_tactic ~disambiguate_command ~disambiguate_macro opts status ex ->
667   match ex with
668   | GrafiteAst.Tactical (_, tac, None) ->
669      eval_tactical ~disambiguate_tactic status tac,[]
670   | GrafiteAst.Tactical (_, tac, Some punct) ->
671      let status = eval_tactical ~disambiguate_tactic status tac in
672       eval_tactical ~disambiguate_tactic status punct,[]
673   | GrafiteAst.Command (_, cmd) ->
674       eval_command.ec_go ~disambiguate_command opts status cmd
675   | GrafiteAst.Macro (loc, macro) ->
676      raise (Macro (loc,disambiguate_macro status macro))
677
678 } and eval_from_moo = {efm_go = fun status fname ->
679   let ast_of_cmd cmd =
680     GrafiteAst.Executable (HExtlib.dummy_floc,
681       GrafiteAst.Command (HExtlib.dummy_floc,
682         cmd))
683   in
684   let moo = GrafiteMarshal.load_moo fname in
685   List.fold_left 
686     (fun status ast -> 
687       let ast = ast_of_cmd ast in
688       let status,lemmas =
689        eval_ast.ea_go
690          ~disambiguate_tactic:(fun status _ tactic -> status,tactic)
691          ~disambiguate_command:(fun status cmd -> status,cmd)
692          ~disambiguate_macro:(fun _ _ -> assert false)
693          status ast
694       in
695        assert (lemmas=[]);
696        status)
697     status moo
698 } and eval_ast = {ea_go = fun ~disambiguate_tactic ~disambiguate_command ~disambiguate_macro ?(do_heavy_checks=false) ?(clean_baseuri=true) status st 
699 ->
700   let opts = {
701     do_heavy_checks = do_heavy_checks ; 
702     clean_baseuri = clean_baseuri }
703   in
704   match st with
705   | GrafiteAst.Executable (_,ex) ->
706      eval_executable.ee_go ~disambiguate_tactic ~disambiguate_command
707       ~disambiguate_macro opts status ex
708   | GrafiteAst.Comment (_,c) -> eval_comment status c,[]
709 }
710
711 let eval_ast = eval_ast.ea_go