1 (* Copyright (C) 2004, HELM Team.
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.
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.
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.
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,
22 * For details, see the HELM World-Wide-Web page,
23 * http://helm.cs.unibo.it/
30 open DisambiguateTypes
32 module Ast = NotationPt
34 exception NoWellTypedInterpretation of (Stdpp.location * string)
36 exception PathNotWellFormed
38 (** raised when an environment is not enough informative to decide *)
39 exception Try_again of string Lazy.t
41 type ('alias,'term) aliases =
42 bool * 'term DisambiguateTypes.codomain_item DisambiguateTypes.Environment.t
43 type 'a disambiguator_input = string * int * 'a
45 type domain = domain_tree list
46 and domain_tree = Node of Stdpp.location list * domain_item * domain
49 let mono_uris_callback ~selection_mode ?ok
50 ?(enable_button_for_non_vars = true) ~title ~msg ~id =
51 if Helm_registry.get_opt_default Helm_registry.get_bool ~default:true
52 "matita.auto_disambiguation"
58 let mono_interp_callback _ _ _ = assert false
59 let mono_disamb_callback _ = assert false
61 let _choose_uris_callback = ref mono_uris_callback
62 let _choose_interp_callback = ref mono_interp_callback
63 let _choose_disamb_callback = ref mono_disamb_callback
64 let set_choose_uris_callback f = _choose_uris_callback := f
65 let set_choose_interp_callback f = _choose_interp_callback := f
66 let set_choose_disamb_callback f = _choose_disamb_callback := f
68 let interactive_user_uri_choice = !_choose_uris_callback
69 let interactive_interpretation_choice interp = !_choose_interp_callback interp
70 let interactive_ast_choice interp = !_choose_disamb_callback interp
73 let input_or_locate_uri ~(title:string) ?id () = None
74 (* Zack: I try to avoid using this callback. I therefore assume that
75 * the presence of an identifier that can't be resolved via "locate"
76 * query is a syntax error *)
79 let rec string_of_domain =
82 | Node (_,domain_item,l)::tl ->
83 DisambiguateTypes.string_of_domain_item domain_item ^
84 " [ " ^ string_of_domain l ^ " ] " ^ string_of_domain tl
86 let rec filter_map_domain f =
89 | Node (locs,domain_item,l)::tl ->
90 match f locs domain_item with
91 None -> filter_map_domain f l @ filter_map_domain f tl
92 | Some res -> res :: filter_map_domain f l @ filter_map_domain f tl
94 let rec map_domain f =
97 | Node (locs,domain_item,l)::tl ->
98 f locs domain_item :: map_domain f l @ map_domain f tl
100 let uniq_domain dom =
104 | Node (locs,domain_item,l)::tl ->
105 if List.mem domain_item seen then
106 let seen,l = aux seen l in
107 let seen,tl = aux seen tl in
110 let seen,l = aux (domain_item::seen) l in
111 let seen,tl = aux seen tl in
112 seen, Node (locs,domain_item,l)::tl
117 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
120 (** print benchmark information *)
122 let max_refinements = ref 0 (* benchmarking is not thread safe *)
123 let actual_refinements = ref 0
124 let domain_size = ref 0
125 let choices_avg = ref 0.
128 type ('term,'metasenv,'subst,'graph) test_result =
129 | Ok of 'term * 'metasenv * 'subst * 'graph
130 | Ko of (Stdpp.location * string) Lazy.t
131 | Uncertain of (Stdpp.location * string) Lazy.t
133 type ('alias,'ast_thing,'metasenv,'subst,'thing,'ugraph) disamb_result =
134 | Disamb_success of ('ast_thing * 'metasenv * 'subst * 'thing * 'ugraph) list
135 (* each element of this list is a list of partially instantiated asts,
136 * sharing the last instantiated node, together with the location of that
137 * node; each ast is associated with the actual instantiation of the node,
138 * the refinement error, and the location at which refinement fails *)
140 (('ast_thing * 'alias option * Stdpp.location * string) list * Stdpp.location) list
142 let resolve ~env ~universe ~mk_choice item interpr arg =
143 (* let _ = (mk_choice : (GrafiteAst.alias_spec -> 'b
144 DisambiguateTypes.codomain_item)) in *)
148 | None -> InterprEnv.find item env
151 (* one, and only one interpretation is returned (or Not_found) *)
152 (*if (List.length interpr <> 1)
153 then (let strinterpr =
154 String.concat ", " (List.map GrafiteAst.description_of_alias interpr) in
155 prerr_endline (Printf.sprintf "choices for %s: %s"
156 (DisambiguateTypes.string_of_domain_item item) strinterpr);
159 let interpr = List.hd interpr in*)
160 match snd (mk_choice interpr), arg with
161 `Num_interp f, `Num_arg n -> f n
162 | `Sym_interp f, `Args l -> f l
163 | `Sym_interp f, `Num_arg n -> (* Implicit number! *) f []
164 | _,_ -> assert false
166 failwith (": InterprEnv.find failed")
168 (* TODO move it to Cic *)
169 let find_in_context name context =
170 let rec aux acc = function
171 | [] -> raise Not_found
172 | Some hd :: tl when hd = name -> acc
173 | _ :: tl -> aux (acc + 1) tl
179 | Ast.Ident (n, _) -> Some n
183 (* XXX: assuming the domain is composed of uninterpreted items only *)
184 let rec domain_of_term ?(loc = HExtlib.dummy_floc) ~context = function
185 | Ast.AttributedTerm (`Loc loc, term) ->
186 domain_of_term ~loc ~context term
187 | Ast.AttributedTerm (_, term) ->
188 domain_of_term ~loc ~context term
189 | Ast.Symbol (name, attr) ->
191 | None -> [ Node ([loc], Symbol name, []) ]
193 (* to be kept in sync with Ast.Appl (Ast.Symbol ...) *)
194 | Ast.Appl (Ast.Symbol (name, None) as hd :: args)
195 | Ast.Appl (Ast.AttributedTerm (_,Ast.Symbol (name,None)) as hd :: args)
199 (fun term acc -> domain_of_term ~loc ~context term @ acc)
203 Ast.AttributedTerm (`Loc loc,_) -> loc
206 [ Node ([loc], Symbol name, args_dom) ]
207 | Ast.Appl (Ast.Ident (id,`Ambiguous) as hd :: args)
208 | Ast.Appl (Ast.AttributedTerm (_,Ast.Ident (id,`Ambiguous)) as hd :: args) ->
211 (fun term acc -> domain_of_term ~loc ~context term @ acc)
215 Ast.AttributedTerm (`Loc loc,_) -> loc
219 (* the next line can raise Not_found *)
220 ignore(find_in_context id context);
223 [ Node ([loc], Id id, args_dom) ] )
226 (fun term acc -> domain_of_term ~loc ~context term @ acc)
228 | Ast.Binder (kind, (var, typ), body) ->
229 let type_dom = domain_of_term_option ~loc ~context typ in
232 ~context:(string_of_name var :: context) body in
234 | `Exists -> [ Node ([loc], Symbol "exists", (type_dom @ body_dom)) ]
235 | _ -> type_dom @ body_dom)
236 | Ast.Case (term, indty_ident, outtype, branches) ->
237 let term_dom = domain_of_term ~loc ~context term in
238 let outtype_dom = domain_of_term_option ~loc ~context outtype in
239 let rec get_first_constructor = function
241 | (Ast.Pattern (head, Some r, _), _) :: _ -> []
242 (* [ Node ([loc], Id (head,Some (NReference.string_of_reference r)), []) ] *)
243 | (Ast.Pattern (head, None, _), _) :: _ ->
244 [ Node ([loc], Id head, []) ]
245 | _ :: tl -> get_first_constructor tl in
248 Ast.Pattern (head, _, args), term ->
249 let (term_context, args_domain) =
251 (fun (cont, dom) (name, typ) ->
252 (string_of_name name :: cont,
255 | Some typ -> dom @ domain_of_term ~loc ~context:cont typ)))
258 domain_of_term ~loc ~context:term_context term @ args_domain
259 | Ast.Wildcard, term ->
260 domain_of_term ~loc ~context term
263 List.fold_left (fun dom branch -> dom @ do_branch branch) [] branches in
264 (match indty_ident with
265 | None -> get_first_constructor branches
266 | Some (ident, None) -> [ Node ([loc], Id ident , []) ]
267 | Some (ident, Some r) -> [])
268 (* [ Node ([loc], Id (ident,Some (NReference.string_of_reference r)), []) ]) *)
269 @ term_dom @ outtype_dom @ branches_dom
270 | Ast.Cast (term, ty) ->
271 let term_dom = domain_of_term ~loc ~context term in
272 let ty_dom = domain_of_term ~loc ~context ty in
274 | Ast.LetIn ((var, typ), body, where) ->
275 let body_dom = domain_of_term ~loc ~context body in
276 let type_dom = domain_of_term_option ~loc ~context typ in
278 domain_of_term ~loc ~context:(string_of_name var :: context) where in
279 body_dom @ type_dom @ where_dom
280 | Ast.LetRec (kind, defs, where) ->
281 let add_defs context =
283 (fun acc (_, (var, _), _, _) -> string_of_name var :: acc
285 let where_dom = domain_of_term ~loc ~context:(add_defs context) where in
288 (fun dom (params, (_, typ), body, _) ->
292 (fun acc (var,_) -> string_of_name var :: acc)
298 (fun (context,res) (var,ty) ->
299 string_of_name var :: context,
300 domain_of_term_option ~loc ~context ty @ res)
301 (add_defs context,[]) params))
303 @ domain_of_term_option ~loc ~context:context' typ
304 @ domain_of_term ~loc ~context:context' body
308 | Ast.Ident (name, _x) ->
309 (* let x = match x with
314 (* the next line can raise Not_found *)
315 ignore(find_in_context name context); []
319 | None -> [ Node ([loc], Id name, []) ]
323 (fun dom (_, term) ->
324 let dom' = domain_of_term ~loc ~context term in
327 [ Node ([loc], Id name, terms) ]))*)
328 [ Node ([loc], Id name, []) ])
331 | Ast.Implicit _ -> []
332 | Ast.Num (num, i) -> [ Node ([loc], Num, []) ]
333 | Ast.Meta (index, local_context) ->
335 (fun dom term -> dom @ domain_of_term_option ~loc ~context term)
342 | Ast.Variable _ -> assert false
344 and domain_of_term_option ~loc ~context = function
346 | Some t -> domain_of_term ~loc ~context t
348 let domain_of_term ~context term =
349 uniq_domain (domain_of_term ~context term)
351 let domain_of_obj ~context ast =
352 assert (context = []);
354 | Ast.Theorem (_,_,ty,bo,_) ->
358 | Some bo -> domain_of_term [] bo)
359 | Ast.Inductive (params,tyl) ->
362 (fun (context, dom) (var, ty) ->
363 let context' = string_of_name var :: context in
365 None -> context', dom
366 | Some ty -> context', dom @ domain_of_term context ty
368 let context_w_types =
369 List.rev_map (fun (var, _, _, _) -> Some var) tyl @ context in
374 domain_of_term context ty
377 (fun (_,ty) -> domain_of_term context_w_types ty) cl))
379 | Ast.Record (params,var,ty,fields) ->
382 (fun (context, dom) (var, ty) ->
383 let context' = string_of_name var :: context in
385 None -> context', dom
386 | Some ty -> context', dom @ domain_of_term context ty
388 let context_w_types = Some var :: context in
390 @ domain_of_term context ty
393 (fun (context,res) (name,ty,_,_) ->
394 Some name::context, res @ domain_of_term context ty
395 ) (context_w_types,[]) fields)
397 let domain_of_obj ~context obj =
398 uniq_domain (domain_of_obj ~context obj)
401 (* XXX: possibly should take into account locs? *)
402 let domain_diff dom1 dom2 =
403 (* let domain_diff = Domain.diff *)
409 Symbol symb' when symb = symb' -> true
421 | Node (_,elt,l)::tl when is_in_dom2 elt -> aux (l @ tl)
422 | Node (loc,elt,l)::tl -> Node (loc,elt,aux l)::(aux tl)
426 let refine_profiler = HExtlib.profile "disambiguate_thing.refine_thing"
428 (* generic function lifting splitting from type T to type (T list) *)
429 let rec list_split item_split ctx pre post =
433 (item_split (fun v1 -> ctx (pre@v1::post')) x)@
434 list_split item_split ctx (pre@[x]) post'
437 (* splits a 'term capture_variable *)
438 let var_split ctx = function
440 | (v,Some ty) -> [(fun x -> ctx (v,Some x)),ty]
443 let ity_split ctx (n,isind,ty,cl) =
444 [(fun x -> ctx (n,isind,x,cl)),ty]@
445 list_split (fun ctx0 (v,ty) -> [(fun x -> ctx0 (v,x)),ty])
446 (fun x -> ctx (n,isind,ty,x)) [] cl
449 let field_split ctx (n,ty,b,m) =
450 [(fun x -> ctx (n,x,b,m)),ty]
453 (* splits a defn. in a mutual LetRec block *)
454 let letrecaux_split ctx (args,f,bo,n) =
455 list_split var_split (fun x -> ctx (x,f,bo,n)) [] args@
456 var_split (fun x -> ctx (args,x,bo,n)) f@
457 [(fun x -> ctx (args,f,x,n)),bo]
460 let mk_ident s = function
461 | None -> Ast.Ident (s,`Ambiguous)
462 | Some u -> Ast.Ident (s,`Uri (NReference.string_of_reference u))
465 (* splits a pattern (for case analysis) *)
466 let pattern_split ctx = function
468 | Ast.Pattern (s,href,pl) ->
469 let rec auxpatt pre = function
471 | (x,Some y as x')::post' ->
472 ((fun v -> ctx (Ast.Pattern (s,href,pre@(x,Some v)::post'))),y)
473 ::auxpatt (pre@[x']) post'
474 | (x,None as x')::post' -> auxpatt (pre@[x']) post'
479 | Ast.Ident (id,`Ambiguous) -> id, None
480 | Ast.Ident (id,`Uri u) -> id, Some u
483 let href0 = HExtlib.map_option NReference.reference_of_string href0
484 in ctx (Ast.Pattern (id0,href0,pl))),
485 mk_ident s href)::auxpatt [] pl
488 (* this function is used to get the children of a given node, together with
489 * their context and their location
490 * contexts are expressed in the form of functions Ast -> Ast *)
491 (* split : location -> ('term -> 'a) -> 'term -> (('term -> 'a) * 'term * loc) list *)
492 let rec split loc ctx t =
493 let loc_of_attr oldloc = function
498 | Ast.AttributedTerm (attr,t) ->
499 [(fun x -> ctx (Ast.AttributedTerm(attr,x))),t, loc_of_attr loc attr]
500 | Ast.Appl tl -> list_split (*split*) (fun ctx0 t0 -> [ctx0,t0,loc]) (fun x -> ctx (Ast.Appl x)) [] tl
501 | Ast.Binder (k,((n,None) as n'),body) ->
502 [ (fun v -> ctx (Ast.Binder (k,n',v))),body, loc]
503 | Ast.Binder (k,((n,Some ty) as n'),body) ->
504 [(fun v -> ctx (Ast.Binder (k,(n,Some v),body))), ty, loc
505 ;(fun v -> ctx (Ast.Binder (k,n',v))),body, loc]
506 | Ast.Case (t,ity,outty,pl) ->
507 let outty_split = match outty with
509 | Some u -> [(fun x -> ctx (Ast.Case (t,ity,Some x,pl))),u]
511 List.map (fun (a,b) -> a,b,loc)
512 (((fun x -> ctx (Ast.Case (x,ity,outty,pl))),t)::
513 outty_split@list_split
515 ((fun y -> ctx0 (p,y)),x)::pattern_split
516 (fun y -> ctx0 (y,x)) p) (fun x -> ctx (Ast.Case(t,ity,outty,x)))
518 | Ast.Cast (u,v) -> [ (fun x -> ctx (Ast.Cast (x,v))),u,loc
519 ; (fun x -> ctx (Ast.Cast (u,x))),v,loc ]
520 | Ast.LetIn ((n,None) as n',u,v) ->
521 [ (fun x -> ctx (Ast.LetIn (n',x,v))), u,loc
522 ; (fun x -> ctx (Ast.LetIn (n',u,x))), v,loc ]
523 | Ast.LetIn ((n,Some t) as n',u,v) ->
524 [ (fun x -> ctx (Ast.LetIn ((n,Some x),u,v))), t,loc
525 ; (fun x -> ctx (Ast.LetIn (n',x,v))), u, loc
526 ; (fun x -> ctx (Ast.LetIn (n',u,x))), v, loc ]
527 | Ast.LetRec (k,funs,where) -> (* we do not use where any more?? *)
528 List.map (fun (a,b) -> a,b,loc)
529 (list_split letrecaux_split (fun x -> ctx (Ast.LetRec(k,x,where))) [] funs)
530 | _ -> [] (* leaves *)
533 type 'ast marked_ast =
534 (NotationPt.term -> 'ast) * NotationPt.term * Stdpp.location
536 (* top_split : 'a -> ((term -> 'a) * term * loc) list
537 * such that it returns all the possible top-level (ctx,t,dummy_loc) for its input *)
538 let bfvisit ~pp_term top_split test t =
539 let rec aux = function
541 | (ctx0,t0,loc as hd)::tl ->
542 (* prerr_endline ("ok! length tl = " ^ string_of_int (List.length tl)); *)
543 debug_print (lazy ("visiting t0 = " ^ pp_term t0));
544 if test t0 then (debug_print (lazy "t0 is ambiguous"); Some hd)
547 (prerr_endline ("splitting not ambiguous t0:");
548 let t0' = split ctx0 t0 in
549 List.iter (fun (ctx',t') -> prerr_endline ("-- subnode " ^
552 let t0' = split loc ctx0 t0 in
554 (* in aux [(fun x -> x),t] *)
558 let obj_split (o:Ast.term Ast.obj) = match o with
559 | Ast.Inductive (ls,itl) ->
560 List.map (fun (a,b) -> a,b,Stdpp.dummy_loc)
561 (list_split var_split (fun x -> Ast.Inductive (x,itl)) [] ls@
562 list_split ity_split (fun x -> Ast.Inductive (ls,x)) [] itl)
563 | Ast.Theorem (flav,n,ty,None,p) ->
564 [(fun x -> Ast.Theorem (flav,n,x,None,p)), ty, Stdpp.dummy_loc]
565 | Ast.Theorem (flav,n,ty,(Some bo as bo'),p) ->
566 [(fun x -> Ast.Theorem (flav,n,x,bo',p)), ty, Stdpp.dummy_loc
567 ;(fun x -> Ast.Theorem (flav,n,ty,Some x,p)), bo, Stdpp.dummy_loc]
568 | Ast.Record (ls,n,ty,fl) ->
569 List.map (fun (a,b) -> a,b,Stdpp.dummy_loc)
570 (list_split var_split (fun x -> Ast.Record (x,n,ty,fl)) [] ls@
571 [(fun x -> Ast.Record (ls,n,x,fl)),ty]@
572 list_split field_split (fun x -> Ast.Record (ls,n,ty,x)) [] fl)
575 let bfvisit_obj = bfvisit obj_split;;
577 let bfvisit = bfvisit (fun t -> [(fun x -> x),t,Stdpp.dummy_loc]) ;;
579 let domain_item_of_ast = function
580 | Ast.Ident (id,_) -> DisambiguateTypes.Id id
581 | Ast.Symbol (sym,_) -> DisambiguateTypes.Symbol sym
582 | Ast.Num (n,_) -> DisambiguateTypes.Num
583 | Ast.Case(_,Some (ityname,_),_,_) -> DisambiguateTypes.Id ityname
587 let ast_of_alias_spec t alias = match (t,alias) with
588 | Ast.Ident _, GrafiteAst.Ident_alias (id,uri) -> Ast.Ident(id,`Uri uri)
589 | Ast.Case (t,_,oty,pl), GrafiteAst.Ident_alias (id,uri) ->
590 Ast.Case (t,Some (id,Some (NReference.reference_of_string uri)),oty,pl)
591 | _, GrafiteAst.Symbol_alias (sym,uri,desc) -> Ast.Symbol (sym,Some (uri,desc))
592 | Ast.Num(m,_), GrafiteAst.Number_alias (uri,desc) -> Ast.Num(m,Some (uri,desc))
596 (* returns an optional (loc*string):
597 * - None means success (the ast is refinable)
598 * - Some (loc,err) means refinement has failed with error err at location loc
600 let test_interpr ~context ~metasenv ~subst ~use_coercions ~expty ~env ~universe ~uri
601 ~interpretate_thing ~refine_thing ~ugraph ~mk_localization_tbl t =
603 let localization_tbl = mk_localization_tbl 503 in
605 interpretate_thing ~context ~env ~universe
606 ~uri ~is_path:false t ~localization_tbl
609 refine_thing metasenv subst context uri
610 ~use_coercions cic_thing expty ugraph ~localization_tbl
611 in match (refine_profiler.HExtlib.profile foo ()) with
613 let loc,err = Lazy.force x in
614 debug_print (lazy ("test_interpr error: " ^ err));
618 (*| Try_again msg -> Uncertain (lazy (Stdpp.dummy_loc,Lazy.force msg))
619 | Invalid_choice loc_msg -> Ko loc_msg*)
620 | Invalid_choice x ->
621 let loc,err = Lazy.force x in
622 debug_print (lazy ("test_interpr invalid choice: " ^ err));
624 | e -> debug_print (lazy ("uncaught error: "^ Printexc.to_string e));None
627 exception Not_ambiguous;;
629 let rec disambiguate_list
630 ~context ~metasenv ~subst ~use_coercions ~expty ~env ~uri ~interpretate_thing
631 ~refine_thing ~ugraph ~visit ~universe ~mk_localization_tbl ~pp_thing ~pp_term
634 let disambiguate_list =
635 disambiguate_list ~context ~metasenv ~subst ~use_coercions ~expty ~env ~uri
636 ~interpretate_thing ~refine_thing ~ugraph ~visit ~universe
637 ~mk_localization_tbl ~pp_thing ~pp_term
639 let test_interpr = test_interpr ~context ~metasenv ~subst ~use_coercions ~expty
640 ~env ~universe ~uri ~interpretate_thing ~refine_thing ~ugraph ~mk_localization_tbl
642 let find_choices item =
644 | GrafiteAst.Ident_alias (_id,uri) -> uri
645 | GrafiteAst.Symbol_alias (_id,_,desc) -> desc
646 | GrafiteAst.Number_alias (_,desc) -> desc
654 Environment.find item universe
656 debug_print (lazy (Printf.sprintf "choices for %s :\n%s"
657 (d2s item) (String.concat ", " (List.map a2s res))));
661 let get_instances ctx t =
663 let choices = find_choices (domain_item_of_ast t) in
664 List.map (fun t0 -> ctx (ast_of_alias_spec t t0), t0) choices
672 (* debug_print (lazy ("disambiguate_list: t0 = " ^ pp_thing t0)); *)
673 let is_ambiguous = function
674 | Ast.Ident (_,`Ambiguous)
676 | Ast.Symbol (_,None) -> true
677 | Ast.Case (_,Some (ity,None),_,_) -> true
681 | Ast.Ident (id,_) -> "ID " ^ id
683 | Ast.Symbol (sym,_) -> "SYM " ^ sym
687 (* get first ambiguous subterm (or return disambiguated term) *)
688 match visit ~pp_term is_ambiguous t0 with
690 (* debug_print (lazy ("visit -- not ambiguous node:\n" ^ pp_thing
692 (* Some (t0,tl), errors *)
694 | Some (ctx, t, loc_t) ->
695 debug_print (lazy ("visit -- found ambiguous node: " ^ astpp t ^
696 "\nin " ^ pp_thing (ctx t)));
697 (* get possible instantiations of t *)
698 let instances = get_instances ctx t in
699 if instances = [] then
700 raise (NoWellTypedInterpretation (loc_t, "No choices for " ^ astpp t));
701 debug_print (lazy "-- possible instances:");
703 (fun u0 -> debug_print (lazy ("-- instance: " ^ (pp_thing u0))))
705 (* perforate ambiguous subterms and test refinement *)
706 let instances = List.map (fun (x,a) -> (x,Some a),test_interpr x) instances in
707 debug_print (lazy "-- survivors:");
708 let survivors, defuncts =
709 List.partition (fun (_,o) -> o = None) instances in
710 survivors, (defuncts, loc_t)
714 let ts', new_errors = List.split (List.map process_ast ts) in
715 let ts' = List.map (fun ((t,_),_) -> t) (List.flatten ts') in
716 let errors' = match new_errors with
719 List.map (fun (a,b) -> a, HExtlib.unopt b)
720 (List.flatten (List.map fst new_errors)) in
721 let ne' = List.map (fun ((x,a),(l,e)) -> x,a,l,e) ne' in
724 in disambiguate_list ts' errors'
725 with Not_ambiguous -> ts,errors
728 let disambiguate_thing
729 ~context ~metasenv ~subst ~use_coercions
730 ~string_context_of_context ~initial_ugraph:base_univ
731 ~expty ~mk_implicit ~description_of_alias
732 ~fix_instance ~aliases ~universe
733 ~lookup_in_library ~uri ~pp_thing ~pp_term
734 ~domain_of_thing ~interpretate_thing ~refine_thing
735 ~visit ~mk_localization_tbl
736 (thing_txt,thing_txt_prefix_len,thing)
740 let test_interpr = test_interpr ~context ~metasenv ~subst ~use_coercions ~expty
741 ~env ~universe ~uri ~interpretate_thing ~refine_thing ~ugraph:base_univ ~mk_localization_tbl
745 disambiguate_list ~mk_localization_tbl ~context ~metasenv ~subst
746 ~interpretate_thing ~refine_thing ~ugraph:base_univ ~visit
747 ~use_coercions ~expty ~uri ~env ~universe ~pp_thing
751 let localization_tbl = mk_localization_tbl 503 in
752 debug_print (lazy "before interpretate_thing");
754 interpretate_thing ~context ~env ~universe ~uri ~is_path:false t ~localization_tbl
756 debug_print (lazy "after interpretate_thing");
757 match refine_thing metasenv subst context uri ~use_coercions t' expty
758 base_univ ~localization_tbl with
759 | Ok (t',m',s',u') -> t,m',s',t',u'
760 | Uncertain x | Ko x ->
761 let loc,err = Lazy.force x in
762 debug_print (lazy ("refinement uncertain after disambiguation: " ^ err));
763 raise (NoWellTypedInterpretation (loc,err))
765 match (test_interpr thing) with
767 debug_print (lazy ("preliminary test fail: " ^ pp_thing thing));
768 Disamb_failure ([[thing,None,loc,err],loc])
770 let res,errors = aux [thing] in
771 let res,inner_errors =
774 try (Some (refine t), None)
775 (* this error is actually a singleton *)
776 with NoWellTypedInterpretation loc_err ->
777 debug_print (lazy ("can't interpretate/refine " ^ (pp_thing t)));
778 None, Some loc_err) res) in
779 let res = HExtlib.filter_map (fun x -> x) res in
782 (function Some (loc,err) -> Some (thing,None,loc,err) | None -> None)
786 if inner_errors <> [] then (inner_errors,Stdpp.dummy_loc)::errors
790 | [] -> prerr_endline ((string_of_int (List.length errors)) ^ " error frames");Disamb_failure errors
791 | _ -> Disamb_success res)