]> matita.cs.unibo.it Git - helm.git/blob - components/cic_disambiguation/disambiguate.ml
6dd82cc288c42731702bd8b94220d31b5502e8a9
[helm.git] / components / cic_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 open UriManager
32
33 module Ast = CicNotationPt
34
35 (* the integer is an offset to be added to each location *)
36 exception NoWellTypedInterpretation of
37  int *
38  ((Stdpp.location list * string * string) list *
39   (DisambiguateTypes.domain_item * DisambiguateTypes.codomain_item) list *
40   Stdpp.location option * string Lazy.t * bool) list
41 exception PathNotWellFormed
42
43   (** raised when an environment is not enough informative to decide *)
44 exception Try_again of string Lazy.t
45
46 type aliases = bool * DisambiguateTypes.environment
47 type 'a disambiguator_input = string * int * 'a
48
49 type domain = domain_tree list
50 and domain_tree = Node of Stdpp.location list * domain_item * domain
51
52 let rec string_of_domain =
53  function
54     [] -> ""
55   | Node (_,domain_item,l)::tl ->
56      DisambiguateTypes.string_of_domain_item domain_item ^
57       " [ " ^ string_of_domain l ^ " ] " ^ string_of_domain tl
58
59 let rec filter_map_domain f =
60  function
61     [] -> []
62   | Node (locs,domain_item,l)::tl ->
63      match f locs domain_item with
64         None -> filter_map_domain f l @ filter_map_domain f tl
65       | Some res -> res :: filter_map_domain f l @ filter_map_domain f tl
66
67 let rec map_domain f =
68  function
69     [] -> []
70   | Node (locs,domain_item,l)::tl ->
71      f locs domain_item :: map_domain f l @ map_domain f tl
72
73 let uniq_domain dom =
74  let rec aux seen =
75   function
76      [] -> seen,[]
77    | Node (locs,domain_item,l)::tl ->
78       if List.mem domain_item seen then
79        let seen,l = aux seen l in
80        let seen,tl = aux seen tl in
81         seen, l @ tl
82       else
83        let seen,l = aux (domain_item::seen) l in
84        let seen,tl = aux seen tl in
85         seen, Node (locs,domain_item,l)::tl
86  in
87   snd (aux [] dom)
88
89 let debug = false
90 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
91
92 (*
93   (** print benchmark information *)
94 let benchmark = true
95 let max_refinements = ref 0       (* benchmarking is not thread safe *)
96 let actual_refinements = ref 0
97 let domain_size = ref 0
98 let choices_avg = ref 0.
99 *)
100
101 let descr_of_domain_item = function
102  | Id s -> s
103  | Symbol (s, _) -> s
104  | Num i -> string_of_int i
105
106 type 'a test_result =
107   | Ok of 'a * Cic.metasenv
108   | Ko of Stdpp.location option * string Lazy.t
109   | Uncertain of Stdpp.location option * string Lazy.t
110
111 let refine_term metasenv context uri term ugraph ~localization_tbl =
112 (*   if benchmark then incr actual_refinements; *)
113   assert (uri=None);
114     debug_print (lazy (sprintf "TEST_INTERPRETATION: %s" (CicPp.ppterm term)));
115     try
116       let term', _, metasenv',ugraph1 = 
117         CicRefine.type_of_aux' metasenv context term ugraph ~localization_tbl in
118         (Ok (term', metasenv')),ugraph1
119     with
120      exn ->
121       let rec process_exn loc =
122        function
123           HExtlib.Localized (loc,exn) -> process_exn (Some loc) exn
124         | CicRefine.Uncertain msg ->
125             debug_print (lazy ("UNCERTAIN!!! [" ^ (Lazy.force msg) ^ "] " ^ CicPp.ppterm term)) ;
126             Uncertain (loc,msg),ugraph
127         | CicRefine.RefineFailure msg ->
128             debug_print (lazy (sprintf "PRUNED!!!\nterm%s\nmessage:%s"
129               (CicPp.ppterm term) (Lazy.force msg)));
130             Ko (loc,msg),ugraph
131        | exn -> raise exn
132       in
133        process_exn None exn
134
135 let refine_obj metasenv context uri obj ugraph ~localization_tbl =
136  assert (context = []);
137    debug_print (lazy (sprintf "TEST_INTERPRETATION: %s" (CicPp.ppobj obj))) ;
138    try
139      let obj', metasenv,ugraph =
140       CicRefine.typecheck metasenv uri obj ~localization_tbl
141      in
142        (Ok (obj', metasenv)),ugraph
143    with
144      exn ->
145       let rec process_exn loc =
146        function
147           HExtlib.Localized (loc,exn) -> process_exn (Some loc) exn
148         | CicRefine.Uncertain msg ->
149             debug_print (lazy ("UNCERTAIN!!! [" ^ (Lazy.force msg) ^ "] " ^ CicPp.ppobj obj)) ;
150             Uncertain (loc,msg),ugraph
151         | CicRefine.RefineFailure msg ->
152             debug_print (lazy (sprintf "PRUNED!!!\nterm%s\nmessage:%s"
153               (CicPp.ppobj obj) (Lazy.force msg))) ;
154             Ko (loc,msg),ugraph
155        | exn -> raise exn
156       in
157        process_exn None exn
158
159 let resolve (env: codomain_item Environment.t) (item: domain_item) ?(num = "") ?(args = []) () =
160   try
161     snd (Environment.find item env) env num args
162   with Not_found -> 
163     failwith ("Domain item not found: " ^ 
164       (DisambiguateTypes.string_of_domain_item item))
165
166   (* TODO move it to Cic *)
167 let find_in_context name context =
168   let rec aux acc = function
169     | [] -> raise Not_found
170     | Cic.Name hd :: tl when hd = name -> acc
171     | _ :: tl ->  aux (acc + 1) tl
172   in
173   aux 1 context
174
175 let interpretate_term ?(create_dummy_ids=false) ~(context: Cic.name list) ~env ~uri ~is_path ast
176      ~localization_tbl
177 =
178   (* create_dummy_ids shouldbe used only for interpretating patterns *)
179   assert (uri = None);
180   let rec aux ~localize loc (context: Cic.name list) = function
181     | CicNotationPt.AttributedTerm (`Loc loc, term) ->
182         let res = aux ~localize loc context term in
183          if localize then Cic.CicHash.add localization_tbl res loc;
184          res
185     | CicNotationPt.AttributedTerm (_, term) -> aux ~localize loc context term
186     | CicNotationPt.Appl (CicNotationPt.Symbol (symb, i) :: args) ->
187         let cic_args = List.map (aux ~localize loc context) args in
188         resolve env (Symbol (symb, i)) ~args:cic_args ()
189     | CicNotationPt.Appl terms ->
190        Cic.Appl (List.map (aux ~localize loc context) terms)
191     | CicNotationPt.Binder (binder_kind, (var, typ), body) ->
192         let cic_type = aux_option ~localize loc context (Some `Type) typ in
193         let cic_name = CicNotationUtil.cic_name_of_name var in
194         let cic_body = aux ~localize loc (cic_name :: context) body in
195         (match binder_kind with
196         | `Lambda -> Cic.Lambda (cic_name, cic_type, cic_body)
197         | `Pi
198         | `Forall -> Cic.Prod (cic_name, cic_type, cic_body)
199         | `Exists ->
200             resolve env (Symbol ("exists", 0))
201               ~args:[ cic_type; Cic.Lambda (cic_name, cic_type, cic_body) ] ())
202     | CicNotationPt.Case (term, indty_ident, outtype, branches) ->
203         let cic_term = aux ~localize loc context term in
204         let cic_outtype = aux_option ~localize loc context None outtype in
205         let do_branch ((head, _, args), term) =
206           let rec do_branch' context = function
207             | [] -> aux ~localize loc context term
208             | (name, typ) :: tl ->
209                 let cic_name = CicNotationUtil.cic_name_of_name name in
210                 let cic_body = do_branch' (cic_name :: context) tl in
211                 let typ =
212                   match typ with
213                   | None -> Cic.Implicit (Some `Type)
214                   | Some typ -> aux ~localize loc context typ
215                 in
216                 Cic.Lambda (cic_name, typ, cic_body)
217           in
218           do_branch' context args
219         in
220         let indtype_uri, indtype_no =
221           if create_dummy_ids then
222             (UriManager.uri_of_string "cic:/fake_indty.con", 0)
223           else
224           match indty_ident with
225           | Some (indty_ident, _) ->
226              (match resolve env (Id indty_ident) () with
227               | Cic.MutInd (uri, tyno, _) -> (uri, tyno)
228               | Cic.Implicit _ ->
229                  raise (Try_again (lazy "The type of the term to be matched
230                   is still unknown"))
231               | _ ->
232                 raise (Invalid_choice (Some loc, lazy "The type of the term to be matched is not (co)inductive!")))
233           | None ->
234               let fst_constructor =
235                 match branches with
236                 | ((head, _, _), _) :: _ -> head
237                 | [] -> raise (Invalid_choice (Some loc, lazy "The type of the term to be matched is an inductive type without constructors that cannot be determined"))
238               in
239               (match resolve env (Id fst_constructor) () with
240               | Cic.MutConstruct (indtype_uri, indtype_no, _, _) ->
241                   (indtype_uri, indtype_no)
242               | Cic.Implicit _ ->
243                  raise (Try_again (lazy "The type of the term to be matched
244                   is still unknown"))
245               | _ ->
246                 raise (Invalid_choice (Some loc, lazy "The type of the term to be matched is not (co)inductive!")))
247         in
248         let branches =
249          match fst(CicEnvironment.get_obj CicUniv.empty_ugraph indtype_uri) with
250             Cic.InductiveDefinition (il,_,_,_) ->
251              let _,_,_,cl =
252               try
253                List.nth il indtype_no
254               with _ -> assert false
255              in
256               let rec count_prod t =
257                 match CicReduction.whd [] t with
258                     Cic.Prod (_, _, t) -> 1 + (count_prod t)
259                   | _ -> 0 
260               in 
261               let rec sort branches cl =
262                match cl with
263                   [] ->
264                    if branches = [] then []
265                    else
266                     raise (Invalid_choice
267                      (Some loc,
268                       lazy
269                        ("Unrecognized constructors: " ^
270                         String.concat " "
271                          (List.map (fun ((head,_,_),_) -> head) branches))))
272                 | (name,ty)::cltl ->
273                    let rec find_and_remove =
274                     function
275                        [] ->
276                         raise
277                          (Invalid_choice
278                           (Some loc, lazy ("Missing case: " ^ name)))
279                      | ((name',_,_),_) as branch :: tl when name = name' ->
280                         branch,tl
281                      | branch::tl ->
282                         let found,rest = find_and_remove tl in
283                          found, branch::rest
284                    in
285                     let branch,tl = find_and_remove branches in
286                     let (_,_,args),_ = branch in
287                      if List.length args = count_prod ty then
288                       branch::sort tl cltl
289                      else
290                       raise
291                        (Invalid_choice
292                         (Some loc,
293                           lazy ("Wrong number of arguments for " ^ name)))
294               in
295                sort branches cl
296           | _ -> assert false
297         in
298         Cic.MutCase (indtype_uri, indtype_no, cic_outtype, cic_term,
299           (List.map do_branch branches))
300     | CicNotationPt.Cast (t1, t2) ->
301         let cic_t1 = aux ~localize loc context t1 in
302         let cic_t2 = aux ~localize loc context t2 in
303         Cic.Cast (cic_t1, cic_t2)
304     | CicNotationPt.LetIn ((name, typ), def, body) ->
305         let cic_def = aux ~localize loc context def in
306         let cic_name = CicNotationUtil.cic_name_of_name name in
307         let cic_def =
308           match typ with
309           | None -> cic_def
310           | Some t -> Cic.Cast (cic_def, aux ~localize loc context t)
311         in
312         let cic_body = aux ~localize loc (cic_name :: context) body in
313         Cic.LetIn (cic_name, cic_def, cic_body)
314     | CicNotationPt.LetRec (kind, defs, body) ->
315         let context' =
316           List.fold_left
317             (fun acc (_, (name, _), _, _) ->
318               CicNotationUtil.cic_name_of_name name :: acc)
319             context defs
320         in
321         let cic_body =
322          let unlocalized_body = aux ~localize:false loc context' body in
323          match unlocalized_body with
324             Cic.Rel n when n <= List.length defs -> `AvoidLetInNoAppl n
325           | Cic.Appl (Cic.Rel n::l) when n <= List.length defs ->
326              (try
327                let l' =
328                 List.map
329                  (function t ->
330                    let t',subst,metasenv =
331                     CicMetaSubst.delift_rels [] [] (List.length defs) t
332                    in
333                     assert (subst=[]);
334                     assert (metasenv=[]);
335                     t') l
336                in
337                 (* We can avoid the LetIn. But maybe we need to recompute l'
338                    so that it is localized *)
339                 if localize then
340                  match body with
341                     CicNotationPt.AttributedTerm (_,CicNotationPt.Appl(_::l)) ->
342                      let l' = List.map (aux ~localize loc context) l in
343                       `AvoidLetIn (n,l')
344                   | _ -> assert false
345                 else
346                  `AvoidLetIn (n,l')
347               with
348                CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
349                 if localize then
350                  `AddLetIn (aux ~localize loc context' body)
351                 else
352                  `AddLetIn unlocalized_body)
353           | _ ->
354              if localize then
355               `AddLetIn (aux ~localize loc context' body)
356              else
357               `AddLetIn unlocalized_body
358         in
359         let inductiveFuns =
360           List.map
361             (fun (params, (name, typ), body, decr_idx) ->
362               let add_binders kind t =
363                List.fold_right
364                 (fun var t -> CicNotationPt.Binder (kind, var, t)) params t
365               in
366               let cic_body =
367                aux ~localize loc context' (add_binders `Lambda body) in
368               let cic_type =
369                aux_option ~localize loc context (Some `Type)
370                 (HExtlib.map_option (add_binders `Pi) typ) in
371               let name =
372                 match CicNotationUtil.cic_name_of_name name with
373                 | Cic.Anonymous ->
374                     CicNotationPt.fail loc
375                       "Recursive functions cannot be anonymous"
376                 | Cic.Name name -> name
377               in
378               (name, decr_idx, cic_type, cic_body))
379             defs
380         in
381         let fix_or_cofix n =
382          match kind with
383             `Inductive -> Cic.Fix (n,inductiveFuns)
384           | `CoInductive ->
385               let coinductiveFuns =
386                 List.map
387                  (fun (name, _, typ, body) -> name, typ, body)
388                  inductiveFuns
389               in
390                Cic.CoFix (n,coinductiveFuns)
391         in
392          let counter = ref ~-1 in
393          let build_term funs (var,_,_,_) t =
394           incr counter;
395           Cic.LetIn (Cic.Name var, fix_or_cofix !counter, t)
396          in
397           (match cic_body with
398               `AvoidLetInNoAppl n ->
399                 let n' = List.length inductiveFuns - n in
400                  fix_or_cofix n'
401             | `AvoidLetIn (n,l) ->
402                 let n' = List.length inductiveFuns - n in
403                  Cic.Appl (fix_or_cofix n'::l)
404             | `AddLetIn cic_body ->         
405                 List.fold_right (build_term inductiveFuns) inductiveFuns
406                  cic_body)
407     | CicNotationPt.Ident _
408     | CicNotationPt.Uri _ when is_path -> raise PathNotWellFormed
409     | CicNotationPt.Ident (name, subst)
410     | CicNotationPt.Uri (name, subst) as ast ->
411         let is_uri = function CicNotationPt.Uri _ -> true | _ -> false in
412         (try
413           if is_uri ast then raise Not_found;(* don't search the env for URIs *)
414           let index = find_in_context name context in
415           if subst <> None then
416             CicNotationPt.fail loc "Explicit substitutions not allowed here";
417           Cic.Rel index
418         with Not_found ->
419           let cic =
420             if is_uri ast then  (* we have the URI, build the term out of it *)
421               try
422                 CicUtil.term_of_uri (UriManager.uri_of_string name)
423               with UriManager.IllFormedUri _ ->
424                 CicNotationPt.fail loc "Ill formed URI"
425             else
426               resolve env (Id name) ()
427           in
428           let mk_subst uris =
429             let ids_to_uris =
430               List.map (fun uri -> UriManager.name_of_uri uri, uri) uris
431             in
432             (match subst with
433             | Some subst ->
434                 List.map
435                   (fun (s, term) ->
436                     (try
437                       List.assoc s ids_to_uris, aux ~localize loc context term
438                      with Not_found ->
439                        raise (Invalid_choice (Some loc, lazy "The provided explicit named substitution is trying to instantiate a named variable the object is not abstracted on"))))
440                   subst
441             | None -> List.map (fun uri -> uri, Cic.Implicit None) uris)
442           in
443           (try 
444             match cic with
445             | Cic.Const (uri, []) ->
446                 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
447                 let uris = CicUtil.params_of_obj o in
448                 Cic.Const (uri, mk_subst uris)
449             | Cic.Var (uri, []) ->
450                 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
451                 let uris = CicUtil.params_of_obj o in
452                 Cic.Var (uri, mk_subst uris)
453             | Cic.MutInd (uri, i, []) ->
454                (try
455                  let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
456                  let uris = CicUtil.params_of_obj o in
457                  Cic.MutInd (uri, i, mk_subst uris)
458                 with
459                  CicEnvironment.Object_not_found _ ->
460                   (* if we are here it is probably the case that during the
461                      definition of a mutual inductive type we have met an
462                      occurrence of the type in one of its constructors.
463                      However, the inductive type is not yet in the environment
464                   *)
465                   (*here the explicit_named_substituion is assumed to be of length 0 *)
466                   Cic.MutInd (uri,i,[]))
467             | Cic.MutConstruct (uri, i, j, []) ->
468                 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
469                 let uris = CicUtil.params_of_obj o in
470                 Cic.MutConstruct (uri, i, j, mk_subst uris)
471             | Cic.Meta _ | Cic.Implicit _ as t ->
472 (*
473                 debug_print (lazy (sprintf
474                   "Warning: %s must be instantiated with _[%s] but we do not enforce it"
475                   (CicPp.ppterm t)
476                   (String.concat "; "
477                     (List.map
478                       (fun (s, term) -> s ^ " := " ^ CicNotationPtPp.pp_term term)
479                       subst))));
480 *)
481                 t
482             | _ ->
483               raise (Invalid_choice (Some loc, lazy "??? Can this happen?"))
484            with 
485              CicEnvironment.CircularDependency _ -> 
486                raise (Invalid_choice (None, lazy "Circular dependency in the environment"))))
487     | CicNotationPt.Implicit -> Cic.Implicit None
488     | CicNotationPt.UserInput -> Cic.Implicit (Some `Hole)
489     | CicNotationPt.Num (num, i) -> resolve env (Num i) ~num ()
490     | CicNotationPt.Meta (index, subst) ->
491         let cic_subst =
492           List.map
493             (function
494                 None -> None
495               | Some term -> Some (aux ~localize loc context term))
496             subst
497         in
498         Cic.Meta (index, cic_subst)
499     | CicNotationPt.Sort `Prop -> Cic.Sort Cic.Prop
500     | CicNotationPt.Sort `Set -> Cic.Sort Cic.Set
501     | CicNotationPt.Sort (`Type u) -> Cic.Sort (Cic.Type u)
502     | CicNotationPt.Sort `CProp -> Cic.Sort Cic.CProp
503     | CicNotationPt.Symbol (symbol, instance) ->
504         resolve env (Symbol (symbol, instance)) ()
505     | _ -> assert false (* god bless Bologna *)
506   and aux_option ~localize loc (context: Cic.name list) annotation = function
507     | None -> Cic.Implicit annotation
508     | Some term -> aux ~localize loc context term
509   in
510    aux ~localize:true HExtlib.dummy_floc context ast
511
512 let interpretate_path ~context path =
513  let localization_tbl = Cic.CicHash.create 23 in
514   (* here we are throwing away useful localization informations!!! *)
515   fst (
516    interpretate_term ~create_dummy_ids:true 
517     ~context ~env:Environment.empty ~uri:None ~is_path:true
518     path ~localization_tbl, localization_tbl)
519
520 let interpretate_obj ~context ~env ~uri ~is_path obj ~localization_tbl =
521  assert (context = []);
522  assert (is_path = false);
523  let interpretate_term = interpretate_term ~localization_tbl in
524  match obj with
525   | CicNotationPt.Inductive (params,tyl) ->
526      let uri = match uri with Some uri -> uri | None -> assert false in
527      let context,params =
528       let context,res =
529        List.fold_left
530         (fun (context,res) (name,t) ->
531           let t =
532            match t with
533               None -> CicNotationPt.Implicit
534             | Some t -> t in
535           let name = CicNotationUtil.cic_name_of_name name in
536            name::context,(name, interpretate_term context env None false t)::res
537         ) ([],[]) params
538       in
539        context,List.rev res in
540      let add_params =
541       List.fold_right (fun (name,ty) t -> Cic.Prod (name,ty,t)) params in
542      let name_to_uris =
543       snd (
544        List.fold_left
545         (*here the explicit_named_substituion is assumed to be of length 0 *)
546         (fun (i,res) (name,_,_,_) ->
547           i + 1,(name,name,Cic.MutInd (uri,i,[]))::res
548         ) (0,[]) tyl) in
549      let con_env = DisambiguateTypes.env_of_list name_to_uris env in
550      let tyl =
551       List.map
552        (fun (name,b,ty,cl) ->
553          let ty' = add_params (interpretate_term context env None false ty) in
554          let cl' =
555           List.map
556            (fun (name,ty) ->
557              let ty' =
558               add_params (interpretate_term context con_env None false ty)
559              in
560               name,ty'
561            ) cl
562          in
563           name,b,ty',cl'
564        ) tyl
565      in
566       Cic.InductiveDefinition (tyl,[],List.length params,[])
567   | CicNotationPt.Record (params,name,ty,fields) ->
568      let uri = match uri with Some uri -> uri | None -> assert false in
569      let context,params =
570       let context,res =
571        List.fold_left
572         (fun (context,res) (name,t) ->
573           let t =
574            match t with
575               None -> CicNotationPt.Implicit
576             | Some t -> t in
577           let name = CicNotationUtil.cic_name_of_name name in
578            name::context,(name, interpretate_term context env None false t)::res
579         ) ([],[]) params
580       in
581        context,List.rev res in
582      let add_params =
583       List.fold_right
584        (fun (name,ty) t -> Cic.Prod (name,ty,t)) params in
585      let ty' = add_params (interpretate_term context env None false ty) in
586      let fields' =
587       snd (
588        List.fold_left
589         (fun (context,res) (name,ty,_coercion,arity) ->
590           let context' = Cic.Name name :: context in
591            context',(name,interpretate_term context env None false ty)::res
592         ) (context,[]) fields) in
593      let concl =
594       (*here the explicit_named_substituion is assumed to be of length 0 *)
595       let mutind = Cic.MutInd (uri,0,[]) in
596       if params = [] then mutind
597       else
598        Cic.Appl
599         (mutind::CicUtil.mk_rels (List.length params) (List.length fields)) in
600      let con =
601       List.fold_left
602        (fun t (name,ty) -> Cic.Prod (Cic.Name name,ty,t))
603        concl fields' in
604      let con' = add_params con in
605      let tyl = [name,true,ty',["mk_" ^ name,con']] in
606      let field_names = List.map (fun (x,_,y,z) -> x,y,z) fields in
607       Cic.InductiveDefinition
608        (tyl,[],List.length params,[`Class (`Record field_names)])
609   | CicNotationPt.Theorem (flavour, name, ty, bo) ->
610      let attrs = [`Flavour flavour] in
611      let ty' = interpretate_term [] env None false ty in
612      (match bo,flavour with
613         None,`Axiom ->
614          Cic.Constant (name,None,ty',[],attrs)
615       | Some bo,`Axiom -> assert false
616       | None,_ ->
617          Cic.CurrentProof (name,[],Cic.Implicit None,ty',[],attrs)
618       | Some bo,_ ->
619          let bo' = Some (interpretate_term [] env None false bo) in
620           Cic.Constant (name,bo',ty',[],attrs))
621           
622 let rec domain_of_term ?(loc = HExtlib.dummy_floc) ~context = function
623   | Ast.AttributedTerm (`Loc loc, term) ->
624      domain_of_term ~loc ~context term
625   | Ast.AttributedTerm (_, term) ->
626       domain_of_term ~loc ~context term
627   | Ast.Symbol (symbol, instance) ->
628       [ Node ([loc], Symbol (symbol, instance), []) ]
629       (* to be kept in sync with Ast.Appl (Ast.Symbol ...) *)
630   | Ast.Appl (Ast.Symbol (symbol, instance) as hd :: args)
631   | Ast.Appl (Ast.AttributedTerm (_,Ast.Symbol (symbol, instance)) as hd :: args)
632      ->
633       let args_dom =
634         List.fold_right
635           (fun term acc -> domain_of_term ~loc ~context term @ acc)
636           args [] in
637       let loc =
638        match hd with
639           Ast.AttributedTerm (`Loc loc,_)  -> loc
640         | _ -> loc
641       in
642        [ Node ([loc], Symbol (symbol, instance), args_dom) ]
643   | Ast.Appl (Ast.Ident (name, subst) as hd :: args)
644   | Ast.Appl (Ast.AttributedTerm (_,Ast.Ident (name, subst)) as hd :: args) ->
645       let args_dom =
646         List.fold_right
647           (fun term acc -> domain_of_term ~loc ~context term @ acc)
648           args [] in
649       let loc =
650        match hd with
651           Ast.AttributedTerm (`Loc loc,_)  -> loc
652         | _ -> loc
653       in
654       (try
655         (* the next line can raise Not_found *)
656         ignore(find_in_context name context);
657         if subst <> None then
658           Ast.fail loc "Explicit substitutions not allowed here"
659         else
660           args_dom
661       with Not_found ->
662         (match subst with
663         | None -> [ Node ([loc], Id name, args_dom) ]
664         | Some subst ->
665             let terms =
666               List.fold_left
667                 (fun dom (_, term) ->
668                   let dom' = domain_of_term ~loc ~context term in
669                   dom @ dom')
670                 [] subst in
671             [ Node ([loc], Id name, terms @ args_dom) ]))
672   | Ast.Appl terms ->
673       List.fold_right
674         (fun term acc -> domain_of_term ~loc ~context term @ acc)
675         terms []
676   | Ast.Binder (kind, (var, typ), body) ->
677       let type_dom = domain_of_term_option ~loc ~context typ in
678       let body_dom =
679         domain_of_term ~loc
680           ~context:(CicNotationUtil.cic_name_of_name var :: context) body in
681       (match kind with
682       | `Exists -> [ Node ([loc], Symbol ("exists", 0), (type_dom @ body_dom)) ]
683       | _ -> type_dom @ body_dom)
684   | Ast.Case (term, indty_ident, outtype, branches) ->
685       let term_dom = domain_of_term ~loc ~context term in
686       let outtype_dom = domain_of_term_option ~loc ~context outtype in
687       let get_first_constructor = function
688         | [] -> []
689         | ((head, _, _), _) :: _ -> [ Node ([loc], Id head, []) ] in
690       let do_branch ((head, _, args), term) =
691         let (term_context, args_domain) =
692           List.fold_left
693             (fun (cont, dom) (name, typ) ->
694               (CicNotationUtil.cic_name_of_name name :: cont,
695                (match typ with
696                | None -> dom
697                | Some typ -> dom @ domain_of_term ~loc ~context:cont typ)))
698             (context, []) args
699         in
700         domain_of_term ~loc ~context:term_context term @ args_domain
701       in
702       let branches_dom =
703         List.fold_left (fun dom branch -> dom @ do_branch branch) [] branches in
704       (match indty_ident with
705        | None -> get_first_constructor branches
706        | Some (ident, _) -> [ Node ([loc], Id ident, []) ])
707       @ term_dom @ outtype_dom @ branches_dom
708   | Ast.Cast (term, ty) ->
709       let term_dom = domain_of_term ~loc ~context term in
710       let ty_dom = domain_of_term ~loc ~context ty in
711       term_dom @ ty_dom
712   | Ast.LetIn ((var, typ), body, where) ->
713       let body_dom = domain_of_term ~loc ~context body in
714       let type_dom = domain_of_term_option ~loc ~context typ in
715       let where_dom =
716         domain_of_term ~loc
717           ~context:(CicNotationUtil.cic_name_of_name var :: context) where in
718       body_dom @ type_dom @ where_dom
719   | Ast.LetRec (kind, defs, where) ->
720       let add_defs context =
721         List.fold_left
722           (fun acc (_, (var, _), _, _) ->
723             CicNotationUtil.cic_name_of_name var :: acc
724           ) context defs in
725       let where_dom = domain_of_term ~loc ~context:(add_defs context) where in
726       let defs_dom =
727         List.fold_left
728           (fun dom (params, (_, typ), body, _) ->
729             let context' =
730              add_defs
731               (List.fold_left
732                 (fun acc (var,_) -> CicNotationUtil.cic_name_of_name var :: acc)
733                 context params)
734             in
735             List.rev
736              (snd
737                (List.fold_left
738                 (fun (context,res) (var,ty) ->
739                   CicNotationUtil.cic_name_of_name var :: context,
740                   domain_of_term_option ~loc ~context ty @ res)
741                 (add_defs context,[]) params))
742             @ domain_of_term_option ~loc ~context:context' typ
743             @ domain_of_term ~loc ~context:context' body
744           ) [] defs
745       in
746       defs_dom @ where_dom
747   | Ast.Ident (name, subst) ->
748       (try
749         (* the next line can raise Not_found *)
750         ignore(find_in_context name context);
751         if subst <> None then
752           Ast.fail loc "Explicit substitutions not allowed here"
753         else
754           []
755       with Not_found ->
756         (match subst with
757         | None -> [ Node ([loc], Id name, []) ]
758         | Some subst ->
759             let terms =
760               List.fold_left
761                 (fun dom (_, term) ->
762                   let dom' = domain_of_term ~loc ~context term in
763                   dom @ dom')
764                 [] subst in
765             [ Node ([loc], Id name, terms) ]))
766   | Ast.Uri _ -> []
767   | Ast.Implicit -> []
768   | Ast.Num (num, i) -> [ Node ([loc], Num i, []) ]
769   | Ast.Meta (index, local_context) ->
770       List.fold_left
771        (fun dom term -> dom @ domain_of_term_option ~loc ~context term)
772        [] local_context
773   | Ast.Sort _ -> []
774   | Ast.UserInput
775   | Ast.Literal _
776   | Ast.Layout _
777   | Ast.Magic _
778   | Ast.Variable _ -> assert false
779
780 and domain_of_term_option ~loc ~context = function
781   | None -> []
782   | Some t -> domain_of_term ~loc ~context t
783
784 let domain_of_term ~context term = 
785  uniq_domain (domain_of_term ~context term)
786
787 let domain_of_obj ~context ast =
788  assert (context = []);
789   match ast with
790    | Ast.Theorem (_,_,ty,bo) ->
791       domain_of_term [] ty
792       @ (match bo with
793           None -> []
794         | Some bo -> domain_of_term [] bo)
795    | Ast.Inductive (params,tyl) ->
796       let context, dom = 
797        List.fold_left
798         (fun (context, dom) (var, ty) ->
799           let context' = CicNotationUtil.cic_name_of_name var :: context in
800           match ty with
801              None -> context', dom
802            | Some ty -> context', dom @ domain_of_term context ty
803         ) ([], []) params in
804       let context_w_types =
805         List.rev_map
806           (fun (var, _, _, _) -> Cic.Name var) tyl
807         @ context in
808       dom
809       @ List.flatten (
810          List.map
811           (fun (_,_,ty,cl) ->
812             domain_of_term context ty
813             @ List.flatten (
814                List.map
815                 (fun (_,ty) -> domain_of_term context_w_types ty) cl))
816                 tyl)
817    | CicNotationPt.Record (params,var,ty,fields) ->
818       let context, dom = 
819        List.fold_left
820         (fun (context, dom) (var, ty) ->
821           let context' = CicNotationUtil.cic_name_of_name var :: context in
822           match ty with
823              None -> context', dom
824            | Some ty -> context', dom @ domain_of_term context ty
825         ) ([], []) params in
826       let context_w_types = Cic.Name var :: context in
827       dom
828       @ domain_of_term context ty
829       @ snd
830          (List.fold_left
831           (fun (context,res) (name,ty,_,_) ->
832             Cic.Name name::context, res @ domain_of_term context ty
833           ) (context_w_types,[]) fields)
834
835 let domain_of_obj ~context obj = 
836  uniq_domain (domain_of_obj ~context obj)
837
838   (* dom1 \ dom2 *)
839 let domain_diff dom1 dom2 =
840 (* let domain_diff = Domain.diff *)
841   let is_in_dom2 elt =
842     List.exists
843      (function
844        | Symbol (symb, 0) ->
845           (match elt with
846               Symbol (symb',_) when symb = symb' -> true
847             | _ -> false)
848        | Num i ->
849           (match elt with
850               Num _ -> true
851             | _ -> false)
852        | item -> elt = item
853      ) dom2
854   in
855    let rec aux =
856     function
857        [] -> []
858      | Node (_,elt,l)::tl when is_in_dom2 elt -> aux (l @ tl)
859      | Node (loc,elt,l)::tl -> Node (loc,elt,aux l)::(aux tl)
860    in
861     aux dom1
862
863 module type Disambiguator =
864 sig
865   val disambiguate_term :
866     ?fresh_instances:bool ->
867     dbd:HSql.dbd ->
868     context:Cic.context ->
869     metasenv:Cic.metasenv ->
870     ?initial_ugraph:CicUniv.universe_graph -> 
871     aliases:DisambiguateTypes.environment ->(* previous interpretation status *)
872     universe:DisambiguateTypes.multiple_environment option ->
873     CicNotationPt.term disambiguator_input ->
874     ((DisambiguateTypes.domain_item * DisambiguateTypes.codomain_item) list *
875      Cic.metasenv *                  (* new metasenv *)
876      Cic.term*
877      CicUniv.universe_graph) list *  (* disambiguated term *)
878     bool
879
880   val disambiguate_obj :
881     ?fresh_instances:bool ->
882     dbd:HSql.dbd ->
883     aliases:DisambiguateTypes.environment ->(* previous interpretation status *)
884     universe:DisambiguateTypes.multiple_environment option ->
885     uri:UriManager.uri option ->     (* required only for inductive types *)
886     CicNotationPt.term CicNotationPt.obj disambiguator_input ->
887     ((DisambiguateTypes.domain_item * DisambiguateTypes.codomain_item) list *
888      Cic.metasenv *                  (* new metasenv *)
889      Cic.obj *
890      CicUniv.universe_graph) list *  (* disambiguated obj *)
891     bool
892 end
893
894 module Make (C: Callbacks) =
895   struct
896     let choices_of_id dbd id =
897       let uris = Whelp.locate ~dbd id in
898       let uris =
899        match uris with
900         | [] ->
901            (match 
902              (C.input_or_locate_uri 
903                ~title:("URI matching \"" ^ id ^ "\" unknown.") ~id ()) 
904            with
905            | None -> []
906            | Some uri -> [uri])
907         | [uri] -> [uri]
908         | _ ->
909             C.interactive_user_uri_choice ~selection_mode:`MULTIPLE
910              ~ok:"Try selected." ~enable_button_for_non_vars:true
911              ~title:"Ambiguous input." ~id
912              ~msg: ("Ambiguous input \"" ^ id ^
913                 "\". Please, choose one or more interpretations:")
914              uris
915       in
916       List.map
917         (fun uri ->
918           (UriManager.string_of_uri uri,
919            let term =
920              try
921                CicUtil.term_of_uri uri
922              with exn ->
923                debug_print (lazy (UriManager.string_of_uri uri));
924                debug_print (lazy (Printexc.to_string exn));
925                assert false
926             in
927            fun _ _ _ -> term))
928         uris
929
930 let refine_profiler = HExtlib.profile "disambiguate_thing.refine_thing"
931
932     let disambiguate_thing ~dbd ~context ~metasenv
933       ?(initial_ugraph = CicUniv.empty_ugraph) ~aliases ~universe
934       ~uri ~pp_thing ~domain_of_thing ~interpretate_thing ~refine_thing 
935       (thing_txt,thing_txt_prefix_len,thing)
936     =
937       debug_print (lazy "DISAMBIGUATE INPUT");
938       let disambiguate_context =  (* cic context -> disambiguate context *)
939         List.map
940           (function None -> Cic.Anonymous | Some (name, _) -> name)
941           context
942       in
943       debug_print (lazy ("TERM IS: " ^ (pp_thing thing)));
944       let thing_dom = domain_of_thing ~context:disambiguate_context thing in
945       debug_print
946        (lazy (sprintf "DISAMBIGUATION DOMAIN: %s"(string_of_domain thing_dom)));
947 (*
948       debug_print (lazy (sprintf "DISAMBIGUATION ENVIRONMENT: %s"
949         (DisambiguatePp.pp_environment aliases)));
950       debug_print (lazy (sprintf "DISAMBIGUATION UNIVERSE: %s"
951         (match universe with None -> "None" | Some _ -> "Some _")));
952 *)
953       let current_dom =
954         Environment.fold (fun item _ dom -> item :: dom) aliases [] in
955       let todo_dom = domain_diff thing_dom current_dom in
956       debug_print
957        (lazy (sprintf "DISAMBIGUATION DOMAIN AFTER DIFF: %s"(string_of_domain todo_dom)));
958       (* (2) lookup function for any item (Id/Symbol/Num) *)
959       let lookup_choices =
960         fun item ->
961           let choices =
962             let lookup_in_library () =
963               match item with
964               | Id id -> choices_of_id dbd id
965               | Symbol (symb, _) ->
966                  (try
967                    List.map DisambiguateChoices.mk_choice
968                     (TermAcicContent.lookup_interpretations symb)
969                   with
970                    TermAcicContent.Interpretation_not_found -> [])
971               | Num instance ->
972                   DisambiguateChoices.lookup_num_choices ()
973             in
974             match universe with
975             | None -> lookup_in_library ()
976             | Some e ->
977                 (try
978                   let item =
979                     match item with
980                     | Symbol (symb, _) -> Symbol (symb, 0)
981                     | item -> item
982                   in
983                   Environment.find item e
984                 with Not_found -> lookup_in_library ())
985           in
986           choices
987       in
988 (*
989       (* <benchmark> *)
990       let _ =
991         if benchmark then begin
992           let per_item_choices =
993             List.map
994               (fun dom_item ->
995                 try
996                   let len = List.length (lookup_choices dom_item) in
997                   debug_print (lazy (sprintf "BENCHMARK %s: %d"
998                     (string_of_domain_item dom_item) len));
999                   len
1000                 with No_choices _ -> 0)
1001               thing_dom
1002           in
1003           max_refinements := List.fold_left ( * ) 1 per_item_choices;
1004           actual_refinements := 0;
1005           domain_size := List.length thing_dom;
1006           choices_avg :=
1007             (float_of_int !max_refinements) ** (1. /. float_of_int !domain_size)
1008         end
1009       in
1010       (* </benchmark> *)
1011 *)
1012
1013       (* (3) test an interpretation filling with meta uninterpreted identifiers
1014        *)
1015       let test_env aliases todo_dom ugraph = 
1016         let rec aux env = function
1017           | [] -> env
1018           | Node (_, item, l) :: tl ->
1019               let env =
1020                 Environment.add item
1021                  ("Implicit",
1022                    (match item with
1023                       | Id _ | Num _ ->
1024                           (fun _ _ _ -> Cic.Implicit (Some `Closed))
1025                       | Symbol _ -> (fun _ _ _ -> Cic.Implicit None)))
1026                  env in
1027               aux (aux env l) tl in
1028         let filled_env = aux aliases todo_dom in
1029         try
1030           let localization_tbl = Cic.CicHash.create 503 in
1031           let cic_thing =
1032             interpretate_thing ~context:disambiguate_context ~env:filled_env
1033              ~uri ~is_path:false thing ~localization_tbl
1034           in
1035 let foo () =
1036           let k,ugraph1 =
1037            refine_thing metasenv context uri cic_thing ugraph ~localization_tbl
1038           in
1039             (k , ugraph1 )
1040 in refine_profiler.HExtlib.profile foo ()
1041         with
1042         | Try_again msg -> Uncertain (None,msg), ugraph
1043         | Invalid_choice (loc,msg) -> Ko (loc,msg), ugraph
1044       in
1045       (* (4) build all possible interpretations *)
1046       let (@@) (l1,l2,l3) (l1',l2',l3') = l1@l1', l2@l2', l3@l3' in
1047       (* aux returns triples Ok/Uncertain/Ko *)
1048       (* rem_dom is the concatenation of all the remainin domains *)
1049       let rec aux aliases diff lookup_in_todo_dom todo_dom rem_dom base_univ =
1050         debug_print (lazy ("ZZZ: " ^ string_of_domain todo_dom));
1051         match todo_dom with
1052         | [] ->
1053             assert (lookup_in_todo_dom = None);
1054             (match test_env aliases rem_dom base_univ with
1055             | Ok (thing, metasenv),new_univ -> 
1056                [ aliases, diff, metasenv, thing, new_univ ], [], []
1057             | Ko (loc,msg),_ -> [],[],[aliases,diff,loc,msg,true]
1058             | Uncertain (loc,msg),new_univ ->
1059                [],[aliases,diff,loc,msg,new_univ],[])
1060         | Node (locs,item,inner_dom) :: remaining_dom ->
1061             debug_print (lazy (sprintf "CHOOSED ITEM: %s"
1062              (string_of_domain_item item)));
1063             let choices =
1064              match lookup_in_todo_dom with
1065                 None -> lookup_choices item
1066               | Some choices -> choices in
1067             match choices with
1068                [] ->
1069                 [], [],
1070                  [aliases, diff, Some (List.hd locs),
1071                   lazy ("No choices for " ^ string_of_domain_item item),
1072                   true]
1073 (*
1074              | [codomain_item] ->
1075                  (* just one choice. We perform a one-step look-up and
1076                     if the next set of choices is also a singleton we
1077                     skip this refinement step *)
1078                  debug_print(lazy (sprintf "%s CHOSEN" (fst codomain_item)));
1079                  let new_env = Environment.add item codomain_item aliases in
1080                  let new_diff = (item,codomain_item)::diff in
1081                  let lookup_in_todo_dom,next_choice_is_single =
1082                   match remaining_dom with
1083                      [] -> None,false
1084                    | (_,he)::_ ->
1085                       let choices = lookup_choices he in
1086                        Some choices,List.length choices = 1
1087                  in
1088                   if next_choice_is_single then
1089                    aux new_env new_diff lookup_in_todo_dom remaining_dom
1090                     base_univ
1091                   else
1092                     (match test_env new_env remaining_dom base_univ with
1093                     | Ok (thing, metasenv),new_univ ->
1094                         (match remaining_dom with
1095                         | [] ->
1096                            [ new_env, new_diff, metasenv, thing, new_univ ], []
1097                         | _ ->
1098                            aux new_env new_diff lookup_in_todo_dom
1099                             remaining_dom new_univ)
1100                     | Uncertain (loc,msg),new_univ ->
1101                         (match remaining_dom with
1102                         | [] -> [], [new_env,new_diff,loc,msg,true]
1103                         | _ ->
1104                            aux new_env new_diff lookup_in_todo_dom
1105                             remaining_dom new_univ)
1106                     | Ko (loc,msg),_ -> [], [new_env,new_diff,loc,msg,true])
1107 *)
1108              | _::_ ->
1109                  let mark_not_significant failures =
1110                    List.map
1111                     (fun (env, diff, loc, msg, _b) ->
1112                       env, diff, loc, msg, false)
1113                     failures in
1114                  let classify_errors ((ok_l,uncertain_l,error_l) as outcome) =
1115                   if ok_l <> [] || uncertain_l <> [] then
1116                    ok_l,uncertain_l,mark_not_significant error_l
1117                   else
1118                    outcome in
1119                let rec filter univ = function 
1120                 | [] -> [],[],[]
1121                 | codomain_item :: tl ->
1122                     debug_print(lazy (sprintf "%s CHOSEN" (fst codomain_item)));
1123                     let new_env = Environment.add item codomain_item aliases in
1124                     let new_diff = (item,codomain_item)::diff in
1125                     (match
1126                       test_env new_env (inner_dom@remaining_dom@rem_dom) univ
1127                      with
1128                     | Ok (thing, metasenv),new_univ ->
1129                         let res = 
1130                           (match inner_dom with
1131                           | [] ->
1132                              [new_env,new_diff,metasenv,thing,new_univ], [], []
1133                           | _ ->
1134                              aux new_env new_diff None inner_dom
1135                               (remaining_dom@rem_dom) new_univ
1136                           ) 
1137                         in
1138                          res @@ filter univ tl
1139                     | Uncertain (loc,msg),new_univ ->
1140                         let res =
1141                           (match inner_dom with
1142                           | [] -> [],[new_env,new_diff,loc,msg,new_univ],[]
1143                           | _ ->
1144                              aux new_env new_diff None inner_dom
1145                               (remaining_dom@rem_dom) new_univ
1146                           )
1147                         in
1148                          res @@ filter univ tl
1149                     | Ko (loc,msg),_ ->
1150                         let res = [],[],[new_env,new_diff,loc,msg,true] in
1151                          res @@ filter univ tl)
1152                in
1153                 let ok_l,uncertain_l,error_l =
1154                  classify_errors (filter base_univ choices)
1155                 in
1156                  let res_after_ok_l =
1157                   List.fold_right
1158                    (fun (env,diff,_,_,univ) res ->
1159                      aux env diff None remaining_dom rem_dom univ @@ res
1160                    ) ok_l ([],[],error_l)
1161                 in
1162                  List.fold_right
1163                   (fun (env,diff,_,_,univ) res ->
1164                     aux env diff None remaining_dom rem_dom univ @@ res
1165                   ) uncertain_l res_after_ok_l
1166       in
1167       let aux' aliases diff lookup_in_todo_dom todo_dom base_univ =
1168        match test_env aliases todo_dom base_univ with
1169         | Ok _,_
1170         | Uncertain _,_ ->
1171            aux aliases diff lookup_in_todo_dom todo_dom [] base_univ
1172         | Ko (loc,msg),_ -> [],[],[aliases,diff,loc,msg,true] in
1173       let base_univ = initial_ugraph in
1174       try
1175         let res =
1176          match aux' aliases [] None todo_dom base_univ with
1177          | [],uncertain,errors ->
1178             let errors =
1179              List.map
1180               (fun (env,diff,loc,msg,_) -> (env,diff,loc,msg,true)
1181               ) uncertain @ errors
1182             in
1183             let errors =
1184              List.map
1185               (fun (env,diff,loc,msg,significant) ->
1186                 let env' =
1187                  filter_map_domain
1188                    (fun locs domain_item ->
1189                      try
1190                       let description =
1191                        fst (Environment.find domain_item env)
1192                       in
1193                        Some (locs,descr_of_domain_item domain_item,description)
1194                      with
1195                       Not_found -> None)
1196                    thing_dom
1197                 in
1198                  env',diff,loc,msg,significant
1199               ) errors
1200             in
1201              raise (NoWellTypedInterpretation (0,errors))
1202          | [_,diff,metasenv,t,ugraph],_,_ ->
1203              debug_print (lazy "SINGLE INTERPRETATION");
1204              [diff,metasenv,t,ugraph], false
1205          | l,_,_ ->
1206              debug_print 
1207                (lazy (sprintf "MANY INTERPRETATIONS (%d)" (List.length l)));
1208              let choices =
1209                List.map
1210                  (fun (env, _, _, _, _) ->
1211                    map_domain
1212                      (fun locs domain_item ->
1213                        let description =
1214                          fst (Environment.find domain_item env)
1215                        in
1216                        locs,descr_of_domain_item domain_item, description)
1217                      thing_dom)
1218                  l
1219              in
1220              let choosed = 
1221                C.interactive_interpretation_choice 
1222                  thing_txt thing_txt_prefix_len choices 
1223              in
1224              (List.map (fun n->let _,d,m,t,u= List.nth l n in d,m,t,u) choosed),
1225               true
1226         in
1227          res
1228      with
1229       CicEnvironment.CircularDependency s -> 
1230         failwith "Disambiguate: circular dependency"
1231
1232     let disambiguate_term ?(fresh_instances=false) ~dbd ~context ~metasenv
1233       ?(initial_ugraph = CicUniv.empty_ugraph) ~aliases ~universe 
1234       (text,prefix_len,term)
1235     =
1236       let term =
1237         if fresh_instances then CicNotationUtil.freshen_term term else term
1238       in
1239       disambiguate_thing ~dbd ~context ~metasenv ~initial_ugraph ~aliases
1240         ~universe ~uri:None ~pp_thing:CicNotationPp.pp_term
1241         ~domain_of_thing:domain_of_term
1242         ~interpretate_thing:(interpretate_term (?create_dummy_ids:None))
1243         ~refine_thing:refine_term (text,prefix_len,term)
1244
1245     let disambiguate_obj ?(fresh_instances=false) ~dbd ~aliases ~universe ~uri
1246      (text,prefix_len,obj)
1247     =
1248       let obj =
1249         if fresh_instances then CicNotationUtil.freshen_obj obj else obj
1250       in
1251       disambiguate_thing ~dbd ~context:[] ~metasenv:[] ~aliases ~universe ~uri
1252         ~pp_thing:(CicNotationPp.pp_obj CicNotationPp.pp_term) ~domain_of_thing:domain_of_obj
1253         ~interpretate_thing:interpretate_obj ~refine_thing:refine_obj
1254         (text,prefix_len,obj)
1255   end
1256