]> matita.cs.unibo.it Git - helm.git/blob - matitaB/components/disambiguation/disambiguate.ml
a65dd3e5f78b55a4825141f2a5a5003fe626576c
[helm.git] / matitaB / components / disambiguation / disambiguate.ml
1 (* Copyright (C) 2004, 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 open Printf
29
30 open DisambiguateTypes
31
32 module Ast = NotationPt
33
34 exception NoWellTypedInterpretation of
35  int *
36  ((Stdpp.location list * string * string) list *
37   (DisambiguateTypes.domain_item * string) list *
38   (Stdpp.location * string) Lazy.t * bool) list
39 exception PathNotWellFormed
40
41   (** raised when an environment is not enough informative to decide *)
42 exception Try_again of string Lazy.t
43
44 type ('alias,'term) aliases =
45  bool * 'term DisambiguateTypes.codomain_item DisambiguateTypes.Environment.t
46 type 'a disambiguator_input = string * int * 'a
47
48 type domain = domain_tree list
49 and domain_tree = Node of Stdpp.location list * domain_item * domain
50
51 (*
52 let mono_uris_callback ~selection_mode ?ok
53           ?(enable_button_for_non_vars = true) ~title ~msg ~id =
54  if Helm_registry.get_opt_default Helm_registry.get_bool ~default:true
55       "matita.auto_disambiguation"
56  then
57   function l -> l
58  else
59   raise Ambiguous_input
60
61 let mono_interp_callback _ _ _ = assert false
62 let mono_disamb_callback _ = assert false
63
64 let _choose_uris_callback = ref mono_uris_callback
65 let _choose_interp_callback = ref mono_interp_callback
66 let _choose_disamb_callback = ref mono_disamb_callback
67 let set_choose_uris_callback f = _choose_uris_callback := f
68 let set_choose_interp_callback f = _choose_interp_callback := f
69 let set_choose_disamb_callback f = _choose_disamb_callback := f
70
71 let interactive_user_uri_choice = !_choose_uris_callback
72 let interactive_interpretation_choice interp = !_choose_interp_callback interp
73 let interactive_ast_choice interp = !_choose_disamb_callback interp
74 *)
75
76 let input_or_locate_uri ~(title:string) ?id () = None
77   (* Zack: I try to avoid using this callback. I therefore assume that
78   * the presence of an identifier that can't be resolved via "locate"
79   * query is a syntax error *)
80   
81
82 let rec string_of_domain =
83  function
84     [] -> ""
85   | Node (_,domain_item,l)::tl ->
86      DisambiguateTypes.string_of_domain_item domain_item ^
87       " [ " ^ string_of_domain l ^ " ] " ^ string_of_domain tl
88
89 let rec filter_map_domain f =
90  function
91     [] -> []
92   | Node (locs,domain_item,l)::tl ->
93      match f locs domain_item with
94         None -> filter_map_domain f l @ filter_map_domain f tl
95       | Some res -> res :: filter_map_domain f l @ filter_map_domain f tl
96
97 let rec map_domain f =
98  function
99     [] -> []
100   | Node (locs,domain_item,l)::tl ->
101      f locs domain_item :: map_domain f l @ map_domain f tl
102
103 let uniq_domain dom =
104  let rec aux seen =
105   function
106      [] -> seen,[]
107    | Node (locs,domain_item,l)::tl ->
108       if List.mem domain_item seen then
109        let seen,l = aux seen l in
110        let seen,tl = aux seen tl in
111         seen, l @ tl
112       else
113        let seen,l = aux (domain_item::seen) l in
114        let seen,tl = aux seen tl in
115         seen, Node (locs,domain_item,l)::tl
116  in
117   snd (aux [] dom)
118
119 let debug = false
120 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
121
122 (*
123   (** print benchmark information *)
124 let benchmark = true
125 let max_refinements = ref 0       (* benchmarking is not thread safe *)
126 let actual_refinements = ref 0
127 let domain_size = ref 0
128 let choices_avg = ref 0.
129 *)
130
131 type ('term,'metasenv,'subst,'graph) test_result =
132   | Ok of 'term * 'metasenv * 'subst * 'graph
133   | Ko of (Stdpp.location * string) Lazy.t
134   | Uncertain of (Stdpp.location * string) Lazy.t
135
136 let resolve ~env ~universe ~mk_choice item interpr arg =
137   (* let _ = (mk_choice : (GrafiteAst.alias_spec -> 'b
138      DisambiguateTypes.codomain_item)) in *)
139   try
140    let interpr = 
141      match interpr with
142      | None -> InterprEnv.find item env 
143      | Some i -> i 
144    in
145    (* one, and only one interpretation is returned (or Not_found) *)
146    (*if (List.length interpr <> 1)
147    then (let strinterpr = 
148           String.concat ", " (List.map GrafiteAst.description_of_alias interpr) in
149            prerr_endline (Printf.sprintf "choices for %s: %s"
150              (DisambiguateTypes.string_of_domain_item item) strinterpr);
151           assert false)
152      else
153    let interpr = List.hd interpr in*)
154    match snd (mk_choice interpr), arg with
155       `Num_interp f, `Num_arg n -> f n
156     | `Sym_interp f, `Args l -> f l
157     | `Sym_interp f, `Num_arg n -> (* Implicit number! *) f []
158     | _,_ -> assert false
159   with Not_found -> 
160     failwith (": InterprEnv.find failed")
161
162   (* TODO move it to Cic *)
163 let find_in_context name context =
164   let rec aux acc = function
165     | [] -> raise Not_found
166     | Some hd :: tl when hd = name -> acc
167     | _ :: tl ->  aux (acc + 1) tl
168   in
169   aux 1 context
170
171 let string_of_name =
172  function
173   | Ast.Ident (n, _) -> Some n
174   | _ -> assert false
175 ;;
176
177 (* XXX: assuming the domain is composed of uninterpreted items only *)
178 let rec domain_of_term ?(loc = HExtlib.dummy_floc) ~context = function
179   | Ast.AttributedTerm (`Loc loc, term) ->
180      domain_of_term ~loc ~context term
181   | Ast.AttributedTerm (_, term) ->
182       domain_of_term ~loc ~context term
183   | Ast.Symbol (name, attr) ->
184       (match attr with
185        | None ->  [ Node ([loc], Symbol name, []) ]
186        | _ -> [])
187       (* to be kept in sync with Ast.Appl (Ast.Symbol ...) *)
188   | Ast.Appl (Ast.Symbol (name, None)  as hd :: args)
189   | Ast.Appl (Ast.AttributedTerm (_,Ast.Symbol (name,None)) as hd :: args)
190      ->
191       let args_dom =
192         List.fold_right
193           (fun term acc -> domain_of_term ~loc ~context term @ acc)
194           args [] in
195       let loc =
196        match hd with
197           Ast.AttributedTerm (`Loc loc,_)  -> loc
198         | _ -> loc
199       in
200        [ Node ([loc], Symbol name, args_dom) ]
201   | Ast.Appl (Ast.Ident (id,`Ambiguous) as hd :: args)
202   | Ast.Appl (Ast.AttributedTerm (_,Ast.Ident (id,`Ambiguous)) as hd :: args) ->
203       let args_dom =
204         List.fold_right
205           (fun term acc -> domain_of_term ~loc ~context term @ acc)
206           args [] in
207       let loc =
208        match hd with
209           Ast.AttributedTerm (`Loc loc,_)  -> loc
210         | _ -> loc
211       in
212       (try
213         (* the next line can raise Not_found *)
214         ignore(find_in_context id context);
215           args_dom
216       with Not_found ->
217         [ Node ([loc], Id id, args_dom) ] )
218   | Ast.Appl terms ->
219       List.fold_right
220         (fun term acc -> domain_of_term ~loc ~context term @ acc)
221         terms []
222   | Ast.Binder (kind, (var, typ), body) ->
223       let type_dom = domain_of_term_option ~loc ~context typ in
224       let body_dom =
225         domain_of_term ~loc
226           ~context:(string_of_name var :: context) body in
227       (match kind with
228       | `Exists -> [ Node ([loc], Symbol "exists", (type_dom @ body_dom)) ]
229       | _ -> type_dom @ body_dom)
230   | Ast.Case (term, indty_ident, outtype, branches) ->
231       let term_dom = domain_of_term ~loc ~context term in
232       let outtype_dom = domain_of_term_option ~loc ~context outtype in
233       let rec get_first_constructor = function
234         | [] -> []
235         | (Ast.Pattern (head, Some r, _), _) :: _ -> []
236              (* [ Node ([loc], Id (head,Some (NReference.string_of_reference r)), []) ] *)
237         | (Ast.Pattern (head, None, _), _) :: _ -> 
238              [ Node ([loc], Id head, []) ]
239         | _ :: tl -> get_first_constructor tl in
240       let do_branch =
241        function
242           Ast.Pattern (head, _, args), term ->
243            let (term_context, args_domain) =
244              List.fold_left
245                (fun (cont, dom) (name, typ) ->
246                  (string_of_name name :: cont,
247                   (match typ with
248                   | None -> dom
249                   | Some typ -> dom @ domain_of_term ~loc ~context:cont typ)))
250                (context, []) args
251            in
252             domain_of_term ~loc ~context:term_context term @ args_domain
253         | Ast.Wildcard, term ->
254             domain_of_term ~loc ~context term
255       in
256       let branches_dom =
257         List.fold_left (fun dom branch -> dom @ do_branch branch) [] branches in
258       (match indty_ident with
259        | None -> get_first_constructor branches
260        | Some (ident, None) -> [ Node ([loc], Id ident , []) ]
261        | Some (ident, Some r) -> [])
262            (* [ Node ([loc], Id (ident,Some (NReference.string_of_reference r)), []) ]) *)
263       @ term_dom @ outtype_dom @ branches_dom
264   | Ast.Cast (term, ty) ->
265       let term_dom = domain_of_term ~loc ~context term in
266       let ty_dom = domain_of_term ~loc ~context ty in
267       term_dom @ ty_dom
268   | Ast.LetIn ((var, typ), body, where) ->
269       let body_dom = domain_of_term ~loc ~context body in
270       let type_dom = domain_of_term_option ~loc ~context typ in
271       let where_dom =
272         domain_of_term ~loc ~context:(string_of_name var :: context) where in
273       body_dom @ type_dom @ where_dom
274   | Ast.LetRec (kind, defs, where) ->
275       let add_defs context =
276         List.fold_left
277           (fun acc (_, (var, _), _, _) -> string_of_name var :: acc
278           ) context defs in
279       let where_dom = domain_of_term ~loc ~context:(add_defs context) where in
280       let defs_dom =
281         List.fold_left
282           (fun dom (params, (_, typ), body, _) ->
283             let context' =
284              add_defs
285               (List.fold_left
286                 (fun acc (var,_) -> string_of_name var :: acc)
287                 context params)
288             in
289             List.rev
290              (snd
291                (List.fold_left
292                 (fun (context,res) (var,ty) ->
293                   string_of_name var :: context,
294                   domain_of_term_option ~loc ~context ty @ res)
295                 (add_defs context,[]) params))
296             @ dom
297             @ domain_of_term_option ~loc ~context:context' typ
298             @ domain_of_term ~loc ~context:context' body
299           ) [] defs
300       in
301       defs_dom @ where_dom
302   | Ast.Ident (name, x) ->
303       let x = match x with
304         | `Uri u -> Some u
305         | _ -> None
306       in
307       (try
308         (* the next line can raise Not_found *)
309         ignore(find_in_context name context); []
310       with Not_found ->
311         (*
312         (match subst with
313         | None -> [ Node ([loc], Id name, []) ]
314         | Some subst ->
315             let terms =
316               List.fold_left
317                 (fun dom (_, term) ->
318                   let dom' = domain_of_term ~loc ~context term in
319                   dom @ dom')
320                 [] subst in
321             [ Node ([loc], Id name, terms) ]))*)
322         [ Node ([loc], Id name, []) ])
323   | Ast.NRef _ -> []
324   | Ast.NCic _ -> []
325   | Ast.Implicit _ -> []
326   | Ast.Num (num, i) -> [ Node ([loc], Num, []) ]
327   | Ast.Meta (index, local_context) ->
328       List.fold_left
329        (fun dom term -> dom @ domain_of_term_option ~loc ~context term)
330        [] local_context
331   | Ast.Sort _ -> []
332   | Ast.UserInput
333   | Ast.Literal _
334   | Ast.Layout _
335   | Ast.Magic _
336   | Ast.Variable _ -> assert false
337
338 and domain_of_term_option ~loc ~context = function
339   | None -> []
340   | Some t -> domain_of_term ~loc ~context t
341
342 let domain_of_term ~context term = 
343  uniq_domain (domain_of_term ~context term)
344
345 let domain_of_obj ~context ast =
346  assert (context = []);
347   match ast with
348    | Ast.Theorem (_,_,ty,bo,_) ->
349       domain_of_term [] ty
350       @ (match bo with
351           None -> []
352         | Some bo -> domain_of_term [] bo)
353    | Ast.Inductive (params,tyl) ->
354       let context, dom = 
355        List.fold_left
356         (fun (context, dom) (var, ty) ->
357           let context' = string_of_name var :: context in
358           match ty with
359              None -> context', dom
360            | Some ty -> context', dom @ domain_of_term context ty
361         ) ([], []) params in
362       let context_w_types =
363         List.rev_map (fun (var, _, _, _) -> Some var) tyl @ context in
364       dom
365       @ List.flatten (
366          List.map
367           (fun (_,_,ty,cl) ->
368             domain_of_term context ty
369             @ List.flatten (
370                List.map
371                 (fun (_,ty) -> domain_of_term context_w_types ty) cl))
372                 tyl)
373    | Ast.Record (params,var,ty,fields) ->
374       let context, dom = 
375        List.fold_left
376         (fun (context, dom) (var, ty) ->
377           let context' = string_of_name var :: context in
378           match ty with
379              None -> context', dom
380            | Some ty -> context', dom @ domain_of_term context ty
381         ) ([], []) params in
382       let context_w_types = Some var :: context in
383       dom
384       @ domain_of_term context ty
385       @ snd
386          (List.fold_left
387           (fun (context,res) (name,ty,_,_) ->
388             Some name::context, res @ domain_of_term context ty
389           ) (context_w_types,[]) fields)
390
391 let domain_of_obj ~context obj = 
392  uniq_domain (domain_of_obj ~context obj)
393
394   (* dom1 \ dom2 *)
395 (* XXX: possibly should take into account locs? *)
396 let domain_diff dom1 dom2 =
397 (* let domain_diff = Domain.diff *)
398   let is_in_dom2 elt =
399     List.exists
400      (function
401        | Symbol symb ->
402           (match elt with
403               Symbol symb' when symb = symb' -> true
404             | _ -> false)
405        | Num ->
406           (match elt with
407               Num -> true
408             | _ -> false)
409        | item -> elt = item
410      ) dom2
411   in
412    let rec aux =
413     function
414        [] -> []
415      | Node (_,elt,l)::tl when is_in_dom2 elt -> aux (l @ tl)
416      | Node (loc,elt,l)::tl -> Node (loc,elt,aux l)::(aux tl)
417    in
418     aux dom1
419
420 let refine_profiler = HExtlib.profile "disambiguate_thing.refine_thing"
421
422 (* generic function lifting splitting from type T to type (T list) *) 
423 let rec list_split item_split ctx pre post =
424   match post with
425   | [] -> []
426   | x :: post' ->
427       (item_split (fun v1 -> ctx (pre@v1::post')) x)@
428         list_split item_split ctx (pre@[x]) post'
429 ;;
430
431 (* splits a 'term capture_variable *)
432 let var_split ctx = function
433   | (_,None) -> []
434   | (v,Some ty) -> [(fun x -> ctx (v,Some x)),ty]
435 ;;
436
437 let ity_split ctx (n,isind,ty,cl) = 
438   [(fun x -> ctx (n,isind,x,cl)),ty]@
439   list_split (fun ctx0 (v,ty) -> [(fun x -> ctx0 (v,x)),ty]) 
440     (fun x -> ctx (n,isind,ty,x)) [] cl
441 ;;
442
443 let field_split ctx (n,ty,b,m) =
444         [(fun x -> ctx (n,x,b,m)),ty]
445 ;;
446
447 (* splits a defn. in a mutual LetRec block *)
448 let letrecaux_split ctx (args,f,bo,n) =
449         list_split var_split (fun x -> ctx (x,f,bo,n)) [] args@
450         var_split (fun x -> ctx (args,x,bo,n)) f@
451         [(fun x -> ctx (args,f,x,n)),bo]
452 ;;
453
454 let mk_ident s = function
455 | None -> Ast.Ident (s,`Ambiguous)
456 | Some u -> Ast.Ident (s,`Uri (NReference.string_of_reference u))
457 ;;
458
459 (* splits a pattern (for case analysis) *)
460 let pattern_split ctx = function
461   | Ast.Wildcard -> []
462   | Ast.Pattern (s,href,pl) -> 
463      let rec auxpatt pre = function
464      | [] -> []
465      | (x,Some y as x')::post' ->
466          ((fun v -> ctx (Ast.Pattern (s,href,pre@(x,Some v)::post'))),y)
467          ::auxpatt (pre@[x']) post'
468      | (x,None as x')::post' -> auxpatt (pre@[x']) post'
469      in 
470      ((fun x -> 
471        let id0, href0 = 
472          match x with
473          | Ast.Ident (id,`Ambiguous) -> id, None
474          | Ast.Ident (id,`Uri u) -> id, Some u
475          | _ -> assert false
476        in
477        let href0 = HExtlib.map_option NReference.reference_of_string href0 
478        in ctx (Ast.Pattern (id0,href0,pl))),
479        mk_ident s href)::auxpatt [] pl
480 ;;
481
482   (* this function is used to get the children of a given node, together with
483    * their context 
484    * contexts are expressed in the form of functions Ast -> Ast *)
485 (* split : ('term -> 'a) -> 'term -> (('term -> 'a) * 'term) list *)
486 let rec split ctx = function
487   | Ast.AttributedTerm (attr,t) -> 
488      [(fun x -> ctx (Ast.AttributedTerm(attr,x))),t]
489   | Ast.Appl tl -> list_split (*split*) (fun ctx0 t0 -> [ctx0,t0]) (fun x -> ctx (Ast.Appl x)) [] tl
490   | Ast.Binder (k,((n,None) as n'),body) -> 
491      [ (fun v -> ctx (Ast.Binder (k,n',v))),body]
492   | Ast.Binder (k,((n,Some ty) as n'),body) -> 
493      [(fun v -> ctx (Ast.Binder (k,(n,Some v),body))), ty 
494      ;(fun v -> ctx (Ast.Binder (k,n',v))),body]
495   | Ast.Case (t,ity,outty,pl) -> 
496      let outty_split = match outty with
497      | None -> []
498      | Some u -> [(fun x -> ctx (Ast.Case (t,ity,Some x,pl))),u]
499      in
500      ((fun x -> ctx (Ast.Case (x,ity,outty,pl))),t)::
501        outty_split@list_split
502          (fun ctx0 (p,x) -> 
503             ((fun y -> ctx0 (p,y)),x)::pattern_split 
504               (fun y -> ctx0 (y,x)) p) (fun x -> ctx (Ast.Case(t,ity,outty,x)))
505               [] pl
506   | Ast.Cast (u,v) -> [ (fun x -> ctx (Ast.Cast (x,v))),u
507                   ; (fun x -> ctx (Ast.Cast (u,x))),v ]
508   | Ast.LetIn ((n,None) as n',u,v) ->
509                   [ (fun x -> ctx (Ast.LetIn (n',x,v))), u
510                   ; (fun x -> ctx (Ast.LetIn (n',u,x))), v ]
511   | Ast.LetIn ((n,Some t) as n',u,v) ->
512                   [ (fun x -> ctx (Ast.LetIn ((n,Some x),u,v))), t
513                   ; (fun x -> ctx (Ast.LetIn (n',x,v))), u
514                   ; (fun x -> ctx (Ast.LetIn (n',u,x))), v ]
515   | Ast.LetRec (k,funs,where) -> (* we do not use where any more?? *)
516       list_split letrecaux_split (fun x -> ctx (Ast.LetRec(k,x,where))) [] funs
517   | _ -> [] (* leaves *)
518 ;;
519
520
521 (* top_split : 'a -> ((term -> 'a) * term) list
522  * returns all the possible top-level (ctx,t) for its input *)
523 let bfvisit ~pp_term top_split test t = 
524   let rec aux = function
525   | [] -> None
526   | (ctx0,t0 as hd)::tl ->
527 (*      prerr_endline ("ok! length tl = " ^ string_of_int (List.length tl)); *)
528       debug_print (lazy ("visiting t0 = " ^ pp_term t0)); 
529       if test t0 then (debug_print (lazy "t0 is ambiguous"); Some hd)
530       else 
531       (*
532          (prerr_endline ("splitting not ambiguous t0:");
533           let t0' = split ctx0 t0 in
534           List.iter (fun (ctx',t') -> prerr_endline ("-- subnode " ^
535              (pp_term t'))) t0';
536           aux (tl@t0')) *)
537           let t0' = split ctx0 t0 in
538           aux (tl@t0')
539   (* in aux [(fun x -> x),t] *)
540   in aux (top_split t)
541 ;;
542
543 let obj_split (o:Ast.term Ast.obj) = match o with
544   | Ast.Inductive (ls,itl) -> 
545       list_split var_split (fun x -> Ast.Inductive (x,itl)) [] ls@
546       list_split ity_split (fun x -> Ast.Inductive (ls,x)) [] itl 
547   | Ast.Theorem (flav,n,ty,None,p) ->
548       [(fun x -> Ast.Theorem (flav,n,x,None,p)), ty]
549   | Ast.Theorem (flav,n,ty,(Some bo as bo'),p) ->
550       [(fun x -> Ast.Theorem (flav,n,x,bo',p)), ty
551       ;(fun x -> Ast.Theorem (flav,n,ty,Some x,p)), bo]
552   | Ast.Record (ls,n,ty,fl) ->
553       list_split var_split (fun x -> Ast.Record (x,n,ty,fl)) [] ls@
554       [(fun x -> Ast.Record (ls,n,x,fl)),ty]@
555       list_split field_split (fun x -> Ast.Record (ls,n,ty,x)) [] fl 
556 ;;
557
558 let bfvisit_obj = bfvisit obj_split;;
559
560 let bfvisit = bfvisit (fun t -> [(fun x -> x),t]) ;;
561
562 let domain_item_of_ast = function
563   | Ast.Ident (id,_) -> DisambiguateTypes.Id id
564   | Ast.Symbol (sym,_) -> DisambiguateTypes.Symbol sym
565   | Ast.Num (n,_) -> DisambiguateTypes.Num 
566   | Ast.Case(_,Some (ityname,_),_,_) -> DisambiguateTypes.Id ityname
567   | _ -> assert false
568 ;;
569
570 let ast_of_alias_spec t alias = match (t,alias) with
571   | Ast.Ident _, GrafiteAst.Ident_alias (id,uri) -> Ast.Ident(id,`Uri uri)
572   | Ast.Case (t,_,oty,pl), GrafiteAst.Ident_alias (id,uri) -> 
573       Ast.Case (t,Some (id,Some (NReference.reference_of_string uri)),oty,pl)
574   | _, GrafiteAst.Symbol_alias (sym,uri,desc) -> Ast.Symbol (sym,Some (uri,desc))
575   | Ast.Num(m,_), GrafiteAst.Number_alias (uri,desc) -> Ast.Num(m,Some (uri,desc))
576   | _ -> assert false
577 ;;
578
579 let test_interpr ~context ~metasenv ~subst ~use_coercions ~expty ~env ~universe ~uri 
580   ~interpretate_thing ~refine_thing ~ugraph ~mk_localization_tbl t =
581   try
582    let localization_tbl = mk_localization_tbl 503 in
583     let cic_thing =
584       interpretate_thing ~context ~env ~universe
585        ~uri ~is_path:false t ~localization_tbl
586     in
587     let foo () =
588            refine_thing metasenv subst context uri
589             ~use_coercions cic_thing expty ugraph ~localization_tbl
590     in match (refine_profiler.HExtlib.profile foo ()) with
591     | Ko x ->
592         let _,err = Lazy.force x in
593         debug_print (lazy ("test_interpr error: " ^ err)); 
594         false
595     | _ -> true
596   with
597      (*| Try_again msg -> Uncertain (lazy (Stdpp.dummy_loc,Lazy.force msg))
598      | Invalid_choice loc_msg -> Ko loc_msg*)
599      | Invalid_choice _ -> false
600      | _ -> true
601 ;;
602
603 let rec disambiguate_list
604   ~context ~metasenv ~subst ~use_coercions ~expty ~env ~uri ~interpretate_thing
605   ~refine_thing ~ugraph ~visit ~universe ~mk_localization_tbl ~pp_thing ~pp_term ts =
606   let disambiguate_list = 
607     disambiguate_list ~context ~metasenv ~subst ~use_coercions ~expty ~env ~uri
608       ~interpretate_thing ~refine_thing ~ugraph ~visit ~universe
609       ~mk_localization_tbl ~pp_thing ~pp_term
610   in
611   let test_interpr = test_interpr ~context ~metasenv ~subst ~use_coercions ~expty 
612     ~env ~universe ~uri ~interpretate_thing ~refine_thing ~ugraph ~mk_localization_tbl
613   in
614   let find_choices item = 
615     let a2s = function
616     | GrafiteAst.Ident_alias (_id,uri) -> uri
617     | GrafiteAst.Symbol_alias (_id,_,desc) -> desc
618     | GrafiteAst.Number_alias (_,desc) -> desc
619     in
620     let d2s = function
621     | Id id
622     | Symbol id -> id
623     | Num -> "NUM"
624     in
625     let res =
626       Environment.find item universe 
627     in
628     debug_print (lazy (Printf.sprintf "choices for %s :\n%s"
629       (d2s item) (String.concat ", " (List.map a2s res))));
630     res
631   in
632
633   let get_instances ctx t = 
634     try 
635       let choices = find_choices (domain_item_of_ast t) in
636       List.map (fun t0 -> ctx (ast_of_alias_spec t t0)) choices
637     with
638     | Not_found -> []
639   in
640
641   match ts with
642   | [] -> None
643   | t0 :: tl ->
644       debug_print (lazy ("disambiguate_list: t0 = " ^ pp_thing t0)); 
645       let is_ambiguous = function
646       | Ast.Ident (_,`Ambiguous)
647       | Ast.Num (_,None)
648       | Ast.Symbol (_,None) -> true
649       | Ast.Case (_,Some (ity,None),_,_) -> true
650       | _ -> false
651       in
652       let astpp = function
653               | Ast.Ident (id,_) -> "ID " ^ id
654               | Ast.Num _ -> "NUM"
655               | Ast.Symbol (sym,_) -> "SYM " ^ sym
656               | _ -> "ERROR!"
657       in
658       (* get first ambiguous subterm (or return disambiguated term) *)
659       match visit ~pp_term is_ambiguous t0 with
660       | None -> 
661           debug_print (lazy ("visit -- not ambiguous node:\n" ^ pp_thing t0));
662           Some (t0,tl)
663       | Some (ctx, t) -> 
664         debug_print (lazy ("visit -- found ambiguous node: " ^ astpp t ^
665         "\nin " ^ pp_thing (ctx t)));
666         (* get possible instantiations of t *)
667         let instances = get_instances ctx t in
668         debug_print (lazy "-- possible instances:");
669         List.iter 
670          (fun u0 -> debug_print (lazy ("-- instance: " ^ (pp_thing u0)))) instances;
671         (* perforate ambiguous subterms and test refinement *)
672         debug_print (lazy "-- survivors:");
673         let survivors = List.filter test_interpr instances in
674         List.iter 
675          (fun u0 -> debug_print (lazy ("-- survivor: " ^ (pp_thing u0)))) survivors;
676         disambiguate_list (survivors@tl) 
677 ;;
678
679 let disambiguate_thing 
680   ~context ~metasenv ~subst ~use_coercions
681   ~string_context_of_context
682   ~initial_ugraph:base_univ ~expty
683   ~mk_implicit ~description_of_alias ~fix_instance
684   ~aliases ~universe ~lookup_in_library 
685   ~uri ~pp_thing ~pp_term ~domain_of_thing ~interpretate_thing ~refine_thing 
686   ~visit ~mk_localization_tbl
687   (thing_txt,thing_txt_prefix_len,thing)
688 =
689   let env = aliases in
690
691   let test_interpr = test_interpr ~context ~metasenv ~subst ~use_coercions ~expty 
692     ~env ~universe ~uri ~interpretate_thing ~refine_thing ~ugraph:base_univ ~mk_localization_tbl
693   in
694 (* real function *)
695   let rec aux tl =
696     match disambiguate_list ~mk_localization_tbl ~context ~metasenv ~subst
697       ~interpretate_thing ~refine_thing ~ugraph:base_univ ~visit
698       ~use_coercions ~expty ~uri ~env ~universe ~pp_thing
699       ~pp_term tl with
700     | None -> []
701     | Some (t,tl') -> t::aux tl'
702   in
703
704   let refine t = 
705     let localization_tbl = mk_localization_tbl 503 in
706     debug_print (lazy "before interpretate_thing");
707     let t' = 
708       interpretate_thing ~context ~env ~universe ~uri ~is_path:false t ~localization_tbl
709     in 
710     debug_print (lazy "after interpretate_thing");
711      match refine_thing metasenv subst context uri ~use_coercions t' expty
712           base_univ ~localization_tbl with
713     | Ok (t',m',s',u') -> t,m',s',t',u'
714     | Uncertain x ->
715         let _,err = Lazy.force x in
716         debug_print (lazy ("refinement uncertain after disambiguation: " ^ err));
717         assert false
718     | _ -> assert false
719   in
720   if not (test_interpr thing) then 
721     (debug_print (lazy ("preliminary test fail: " ^ pp_thing thing));
722      raise (NoWellTypedInterpretation (0,[])))
723   else
724     let res = aux [thing] in
725     let res =
726       HExtlib.filter_map (fun t -> 
727         try Some (refine t) 
728         with _ -> 
729           debug_print (lazy ("can't interpretate/refine " ^ (pp_thing t)));None) res
730     in
731     match res with
732     | [] -> raise (NoWellTypedInterpretation (0,[]))
733     (* XXX : the boolean seems not to play a role any longer *)
734     | [t] -> res,false
735     | _ -> res, true
736        (* let choices = List.map (fun (t,_,_,_,_) -> pp_thing t) res in
737        let user_choice = interactive_ast_choice choices in
738        [ List.nth res user_choice ], true
739        (* let pp_thing (t,_,_,_,_,_) = prerr_endline ("interpretation: " ^ (pp_thing t)) in
740          List.iter pp_thing res; res,true *) *)
741 ;;
742