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/
26 (* $Id: disambiguate.ml 7760 2007-10-26 12:37:21Z sacerdot $ *)
30 open DisambiguateTypes
33 module Ast = CicNotationPt
35 (* the integer is an offset to be added to each location *)
36 exception NoWellTypedInterpretation of
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
43 (** raised when an environment is not enough informative to decide *)
44 exception Try_again of string Lazy.t
46 type aliases = bool * DisambiguateTypes.environment
47 type 'a disambiguator_input = string * int * 'a
49 type domain = domain_tree list
50 and domain_tree = Node of Stdpp.location list * domain_item * domain
52 let rec string_of_domain =
55 | Node (_,domain_item,l)::tl ->
56 DisambiguateTypes.string_of_domain_item domain_item ^
57 " [ " ^ string_of_domain l ^ " ] " ^ string_of_domain tl
59 let rec filter_map_domain f =
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
67 let rec map_domain f =
70 | Node (locs,domain_item,l)::tl ->
71 f locs domain_item :: map_domain f l @ map_domain f tl
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
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
90 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
93 (** print benchmark information *)
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.
101 let descr_of_domain_item = function
104 | Num i -> string_of_int i
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
111 let refine_term metasenv context uri term ugraph ~localization_tbl =
112 (* if benchmark then incr actual_refinements; *)
114 debug_print (lazy (sprintf "TEST_INTERPRETATION: %s" (CicPp.ppterm term)));
116 let term', _, metasenv',ugraph1 =
117 CicRefine.type_of_aux' metasenv context term ugraph ~localization_tbl in
118 debug_print (lazy (sprintf "OK!!!"));
119 (Ok (term', metasenv')),ugraph1
122 let rec process_exn loc =
124 HExtlib.Localized (loc,exn) -> process_exn (Some loc) exn
125 | CicRefine.Uncertain msg ->
126 debug_print (lazy ("UNCERTAIN!!! [" ^ (Lazy.force msg) ^ "] " ^ CicPp.ppterm term)) ;
127 Uncertain (loc,msg),ugraph
128 | CicRefine.RefineFailure msg ->
129 debug_print (lazy (sprintf "PRUNED!!!\nterm%s\nmessage:%s"
130 (CicPp.ppterm term) (Lazy.force msg)));
136 let refine_obj metasenv context uri obj ugraph ~localization_tbl =
137 assert (context = []);
138 debug_print (lazy (sprintf "TEST_INTERPRETATION: %s" (CicPp.ppobj obj))) ;
140 let obj', metasenv,ugraph =
141 CicRefine.typecheck metasenv uri obj ~localization_tbl
143 debug_print (lazy (sprintf "OK!!!"));
144 (Ok (obj', metasenv)),ugraph
147 let rec process_exn loc =
149 HExtlib.Localized (loc,exn) -> process_exn (Some loc) exn
150 | CicRefine.Uncertain msg ->
151 debug_print (lazy ("UNCERTAIN!!! [" ^ (Lazy.force msg) ^ "] " ^ CicPp.ppobj obj)) ;
152 Uncertain (loc,msg),ugraph
153 | CicRefine.RefineFailure msg ->
154 debug_print (lazy (sprintf "PRUNED!!!\nterm%s\nmessage:%s"
155 (CicPp.ppobj obj) (Lazy.force msg))) ;
161 let resolve (env: codomain_item Environment.t) (item: domain_item) ?(num = "") ?(args = []) () =
163 snd (Environment.find item env) env num args
165 failwith ("Domain item not found: " ^
166 (DisambiguateTypes.string_of_domain_item item))
168 (* TODO move it to Cic *)
169 let find_in_context name context =
170 let rec aux acc = function
171 | [] -> raise Not_found
172 | Cic.Name hd :: tl when hd = name -> acc
173 | _ :: tl -> aux (acc + 1) tl
177 let interpretate_term ?(create_dummy_ids=false) ~(context: Cic.name list) ~env ~uri ~is_path ast
180 (* create_dummy_ids shouldbe used only for interpretating patterns *)
182 let rec aux ~localize loc (context: Cic.name list) = function
183 | CicNotationPt.AttributedTerm (`Loc loc, term) ->
184 let res = aux ~localize loc context term in
185 if localize then Cic.CicHash.add localization_tbl res loc;
187 | CicNotationPt.AttributedTerm (_, term) -> aux ~localize loc context term
188 | CicNotationPt.Appl (CicNotationPt.Symbol (symb, i) :: args) ->
189 let cic_args = List.map (aux ~localize loc context) args in
190 resolve env (Symbol (symb, i)) ~args:cic_args ()
191 | CicNotationPt.Appl terms ->
192 Cic.Appl (List.map (aux ~localize loc context) terms)
193 | CicNotationPt.Binder (binder_kind, (var, typ), body) ->
194 let cic_type = aux_option ~localize loc context (Some `Type) typ in
195 let cic_name = CicNotationUtil.cic_name_of_name var in
196 let cic_body = aux ~localize loc (cic_name :: context) body in
197 (match binder_kind with
198 | `Lambda -> Cic.Lambda (cic_name, cic_type, cic_body)
200 | `Forall -> Cic.Prod (cic_name, cic_type, cic_body)
202 resolve env (Symbol ("exists", 0))
203 ~args:[ cic_type; Cic.Lambda (cic_name, cic_type, cic_body) ] ())
204 | CicNotationPt.Case (term, indty_ident, outtype, branches) ->
205 let cic_term = aux ~localize loc context term in
206 let cic_outtype = aux_option ~localize loc context None outtype in
207 let do_branch ((head, _, args), term) =
208 let rec do_branch' context = function
209 | [] -> aux ~localize loc context term
210 | (name, typ) :: tl ->
211 let cic_name = CicNotationUtil.cic_name_of_name name in
212 let cic_body = do_branch' (cic_name :: context) tl in
215 | None -> Cic.Implicit (Some `Type)
216 | Some typ -> aux ~localize loc context typ
218 Cic.Lambda (cic_name, typ, cic_body)
220 do_branch' context args
222 let indtype_uri, indtype_no =
223 if create_dummy_ids then
224 (UriManager.uri_of_string "cic:/fake_indty.con", 0)
226 match indty_ident with
227 | Some (indty_ident, _) ->
228 (match resolve env (Id indty_ident) () with
229 | Cic.MutInd (uri, tyno, _) -> (uri, tyno)
231 raise (Try_again (lazy "The type of the term to be matched
234 raise (Invalid_choice (Some loc, lazy "The type of the term to be matched is not (co)inductive!")))
236 let rec fst_constructor =
238 (Ast.Pattern (head, _, _), _) :: _ -> head
239 | (Ast.Wildcard, _) :: tl -> fst_constructor tl
240 | [] -> raise (Invalid_choice (Some loc, lazy "The type of the term to be matched cannot be determined because it is an inductive type without constructors or because all patterns use wildcards"))
242 (match resolve env (Id (fst_constructor branches)) () with
243 | Cic.MutConstruct (indtype_uri, indtype_no, _, _) ->
244 (indtype_uri, indtype_no)
246 raise (Try_again (lazy "The type of the term to be matched
249 raise (Invalid_choice (Some loc, lazy "The type of the term to be matched is not (co)inductive!")))
252 if create_dummy_ids then
255 Ast.Wildcard,term -> ("wildcard",None,[]), term
257 raise (Invalid_choice (Some loc, lazy "Syntax error: the left hand side of a branch patterns must be \"_\""))
260 match fst(CicEnvironment.get_obj CicUniv.empty_ugraph indtype_uri) with
261 Cic.InductiveDefinition (il,_,leftsno,_) ->
264 List.nth il indtype_no
265 with _ -> assert false
267 let rec count_prod t =
268 match CicReduction.whd [] t with
269 Cic.Prod (_, _, t) -> 1 + (count_prod t)
272 let rec sort branches cl =
275 let rec analyze unused unrecognized useless =
278 if unrecognized != [] then
279 raise (Invalid_choice
282 ("Unrecognized constructors: " ^
283 String.concat " " unrecognized)))
284 else if useless > 0 then
285 raise (Invalid_choice
288 ("The last " ^ string_of_int useless ^
289 "case" ^ if useless > 1 then "s are" else " is" ^
293 | (Ast.Wildcard,_)::tl when not unused ->
294 analyze true unrecognized useless tl
295 | (Ast.Pattern (head,_,_),_)::tl when not unused ->
296 analyze unused (head::unrecognized) useless tl
297 | _::tl -> analyze unused unrecognized (useless + 1) tl
299 analyze false [] 0 branches
301 let rec find_and_remove =
306 (Some loc, lazy ("Missing case: " ^ name)))
307 | ((Ast.Wildcard, _) as branch :: _) as branches ->
309 | (Ast.Pattern (name',_,_),_) as branch :: tl
313 let found,rest = find_and_remove tl in
316 let branch,tl = find_and_remove branches in
318 Ast.Pattern (name,y,args),term ->
319 if List.length args = count_prod ty - leftsno then
320 ((name,y,args),term)::sort tl cltl
325 lazy ("Wrong number of arguments for " ^ name)))
326 | Ast.Wildcard,term ->
332 (`Lambda, (CicNotationPt.Ident ("_", None), None),
335 (("wildcard",None,[]),
336 mk_lambdas (count_prod ty - leftsno)) :: sort tl cltl
341 Cic.MutCase (indtype_uri, indtype_no, cic_outtype, cic_term,
342 (List.map do_branch branches))
343 | CicNotationPt.Cast (t1, t2) ->
344 let cic_t1 = aux ~localize loc context t1 in
345 let cic_t2 = aux ~localize loc context t2 in
346 Cic.Cast (cic_t1, cic_t2)
347 | CicNotationPt.LetIn ((name, typ), def, body) ->
348 let cic_def = aux ~localize loc context def in
349 let cic_name = CicNotationUtil.cic_name_of_name name in
353 | Some t -> Cic.Cast (cic_def, aux ~localize loc context t)
355 let cic_body = aux ~localize loc (cic_name :: context) body in
356 Cic.LetIn (cic_name, cic_def, cic_body)
357 | CicNotationPt.LetRec (kind, defs, body) ->
360 (fun acc (_, (name, _), _, _) ->
361 CicNotationUtil.cic_name_of_name name :: acc)
365 let unlocalized_body = aux ~localize:false loc context' body in
366 match unlocalized_body with
367 Cic.Rel n when n <= List.length defs -> `AvoidLetInNoAppl n
368 | Cic.Appl (Cic.Rel n::l) when n <= List.length defs ->
373 let t',subst,metasenv =
374 CicMetaSubst.delift_rels [] [] (List.length defs) t
377 assert (metasenv=[]);
380 (* We can avoid the LetIn. But maybe we need to recompute l'
381 so that it is localized *)
384 CicNotationPt.AttributedTerm (_,CicNotationPt.Appl(_::l)) ->
385 let l' = List.map (aux ~localize loc context) l in
391 CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
393 `AddLetIn (aux ~localize loc context' body)
395 `AddLetIn unlocalized_body)
398 `AddLetIn (aux ~localize loc context' body)
400 `AddLetIn unlocalized_body
404 (fun (params, (name, typ), body, decr_idx) ->
405 let add_binders kind t =
407 (fun var t -> CicNotationPt.Binder (kind, var, t)) params t
410 aux ~localize loc context' (add_binders `Lambda body) in
412 aux_option ~localize loc context (Some `Type)
413 (HExtlib.map_option (add_binders `Pi) typ) in
415 match CicNotationUtil.cic_name_of_name name with
417 CicNotationPt.fail loc
418 "Recursive functions cannot be anonymous"
419 | Cic.Name name -> name
421 (name, decr_idx, cic_type, cic_body))
426 `Inductive -> Cic.Fix (n,inductiveFuns)
428 let coinductiveFuns =
430 (fun (name, _, typ, body) -> name, typ, body)
433 Cic.CoFix (n,coinductiveFuns)
435 let counter = ref ~-1 in
436 let build_term funs (var,_,_,_) t =
438 Cic.LetIn (Cic.Name var, fix_or_cofix !counter, t)
441 `AvoidLetInNoAppl n ->
442 let n' = List.length inductiveFuns - n in
444 | `AvoidLetIn (n,l) ->
445 let n' = List.length inductiveFuns - n in
446 Cic.Appl (fix_or_cofix n'::l)
447 | `AddLetIn cic_body ->
448 List.fold_right (build_term inductiveFuns) inductiveFuns
450 | CicNotationPt.Ident _
451 | CicNotationPt.Uri _ when is_path -> raise PathNotWellFormed
452 | CicNotationPt.Ident (name, subst)
453 | CicNotationPt.Uri (name, subst) as ast ->
454 let is_uri = function CicNotationPt.Uri _ -> true | _ -> false in
456 if is_uri ast then raise Not_found;(* don't search the env for URIs *)
457 let index = find_in_context name context in
458 if subst <> None then
459 CicNotationPt.fail loc "Explicit substitutions not allowed here";
463 if is_uri ast then (* we have the URI, build the term out of it *)
465 CicUtil.term_of_uri (UriManager.uri_of_string name)
466 with UriManager.IllFormedUri _ ->
467 CicNotationPt.fail loc "Ill formed URI"
469 resolve env (Id name) ()
473 List.map (fun uri -> UriManager.name_of_uri uri, uri) uris
480 List.assoc s ids_to_uris, aux ~localize loc context term
482 raise (Invalid_choice (Some loc, lazy "The provided explicit named substitution is trying to instantiate a named variable the object is not abstracted on"))))
484 | None -> List.map (fun uri -> uri, Cic.Implicit None) uris)
488 | Cic.Const (uri, []) ->
489 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
490 let uris = CicUtil.params_of_obj o in
491 Cic.Const (uri, mk_subst uris)
492 | Cic.Var (uri, []) ->
493 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
494 let uris = CicUtil.params_of_obj o in
495 Cic.Var (uri, mk_subst uris)
496 | Cic.MutInd (uri, i, []) ->
498 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
499 let uris = CicUtil.params_of_obj o in
500 Cic.MutInd (uri, i, mk_subst uris)
502 CicEnvironment.Object_not_found _ ->
503 (* if we are here it is probably the case that during the
504 definition of a mutual inductive type we have met an
505 occurrence of the type in one of its constructors.
506 However, the inductive type is not yet in the environment
508 (*here the explicit_named_substituion is assumed to be of length 0 *)
509 Cic.MutInd (uri,i,[]))
510 | Cic.MutConstruct (uri, i, j, []) ->
511 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
512 let uris = CicUtil.params_of_obj o in
513 Cic.MutConstruct (uri, i, j, mk_subst uris)
514 | Cic.Meta _ | Cic.Implicit _ as t ->
516 debug_print (lazy (sprintf
517 "Warning: %s must be instantiated with _[%s] but we do not enforce it"
521 (fun (s, term) -> s ^ " := " ^ CicNotationPtPp.pp_term term)
526 raise (Invalid_choice (Some loc, lazy "??? Can this happen?"))
528 CicEnvironment.CircularDependency _ ->
529 raise (Invalid_choice (None, lazy "Circular dependency in the environment"))))
530 | CicNotationPt.Implicit -> Cic.Implicit None
531 | CicNotationPt.UserInput -> Cic.Implicit (Some `Hole)
532 | CicNotationPt.Num (num, i) -> resolve env (Num i) ~num ()
533 | CicNotationPt.Meta (index, subst) ->
538 | Some term -> Some (aux ~localize loc context term))
541 Cic.Meta (index, cic_subst)
542 | CicNotationPt.Sort `Prop -> Cic.Sort Cic.Prop
543 | CicNotationPt.Sort `Set -> Cic.Sort Cic.Set
544 | CicNotationPt.Sort (`Type u) -> Cic.Sort (Cic.Type u)
545 | CicNotationPt.Sort `CProp -> Cic.Sort Cic.CProp
546 | CicNotationPt.Symbol (symbol, instance) ->
547 resolve env (Symbol (symbol, instance)) ()
548 | _ -> assert false (* god bless Bologna *)
549 and aux_option ~localize loc (context: Cic.name list) annotation = function
550 | None -> Cic.Implicit annotation
551 | Some term -> aux ~localize loc context term
553 aux ~localize:true HExtlib.dummy_floc context ast
555 let interpretate_path ~context path =
556 let localization_tbl = Cic.CicHash.create 23 in
557 (* here we are throwing away useful localization informations!!! *)
559 interpretate_term ~create_dummy_ids:true
560 ~context ~env:Environment.empty ~uri:None ~is_path:true
561 path ~localization_tbl, localization_tbl)
563 let interpretate_obj ~context ~env ~uri ~is_path obj ~localization_tbl =
564 assert (context = []);
565 assert (is_path = false);
566 let interpretate_term = interpretate_term ~localization_tbl in
568 | CicNotationPt.Inductive (params,tyl) ->
569 let uri = match uri with Some uri -> uri | None -> assert false in
573 (fun (context,res) (name,t) ->
576 None -> CicNotationPt.Implicit
578 let name = CicNotationUtil.cic_name_of_name name in
579 name::context,(name, interpretate_term context env None false t)::res
582 context,List.rev res in
584 List.fold_right (fun (name,ty) t -> Cic.Prod (name,ty,t)) params in
588 (*here the explicit_named_substituion is assumed to be of length 0 *)
589 (fun (i,res) (name,_,_,_) ->
590 i + 1,(name,name,Cic.MutInd (uri,i,[]))::res
592 let con_env = DisambiguateTypes.env_of_list name_to_uris env in
595 (fun (name,b,ty,cl) ->
596 let ty' = add_params (interpretate_term context env None false ty) in
601 add_params (interpretate_term context con_env None false ty)
609 Cic.InductiveDefinition (tyl,[],List.length params,[])
610 | CicNotationPt.Record (params,name,ty,fields) ->
611 let uri = match uri with Some uri -> uri | None -> assert false in
615 (fun (context,res) (name,t) ->
618 None -> CicNotationPt.Implicit
620 let name = CicNotationUtil.cic_name_of_name name in
621 name::context,(name, interpretate_term context env None false t)::res
624 context,List.rev res in
627 (fun (name,ty) t -> Cic.Prod (name,ty,t)) params in
628 let ty' = add_params (interpretate_term context env None false ty) in
632 (fun (context,res) (name,ty,_coercion,arity) ->
633 let context' = Cic.Name name :: context in
634 context',(name,interpretate_term context env None false ty)::res
635 ) (context,[]) fields) in
637 (*here the explicit_named_substituion is assumed to be of length 0 *)
638 let mutind = Cic.MutInd (uri,0,[]) in
639 if params = [] then mutind
642 (mutind::CicUtil.mk_rels (List.length params) (List.length fields)) in
645 (fun t (name,ty) -> Cic.Prod (Cic.Name name,ty,t))
647 let con' = add_params con in
648 let tyl = [name,true,ty',["mk_" ^ name,con']] in
649 let field_names = List.map (fun (x,_,y,z) -> x,y,z) fields in
650 Cic.InductiveDefinition
651 (tyl,[],List.length params,[`Class (`Record field_names)])
652 | CicNotationPt.Theorem (flavour, name, ty, bo) ->
653 let attrs = [`Flavour flavour] in
654 let ty' = interpretate_term [] env None false ty in
655 (match bo,flavour with
657 Cic.Constant (name,None,ty',[],attrs)
658 | Some bo,`Axiom -> assert false
660 Cic.CurrentProof (name,[],Cic.Implicit None,ty',[],attrs)
662 let bo' = Some (interpretate_term [] env None false bo) in
663 Cic.Constant (name,bo',ty',[],attrs))
665 let rec domain_of_term ?(loc = HExtlib.dummy_floc) ~context = function
666 | Ast.AttributedTerm (`Loc loc, term) ->
667 domain_of_term ~loc ~context term
668 | Ast.AttributedTerm (_, term) ->
669 domain_of_term ~loc ~context term
670 | Ast.Symbol (symbol, instance) ->
671 [ Node ([loc], Symbol (symbol, instance), []) ]
672 (* to be kept in sync with Ast.Appl (Ast.Symbol ...) *)
673 | Ast.Appl (Ast.Symbol (symbol, instance) as hd :: args)
674 | Ast.Appl (Ast.AttributedTerm (_,Ast.Symbol (symbol, instance)) as hd :: args)
678 (fun term acc -> domain_of_term ~loc ~context term @ acc)
682 Ast.AttributedTerm (`Loc loc,_) -> loc
685 [ Node ([loc], Symbol (symbol, instance), args_dom) ]
686 | Ast.Appl (Ast.Ident (name, subst) as hd :: args)
687 | Ast.Appl (Ast.AttributedTerm (_,Ast.Ident (name, subst)) as hd :: args) ->
690 (fun term acc -> domain_of_term ~loc ~context term @ acc)
694 Ast.AttributedTerm (`Loc loc,_) -> loc
698 (* the next line can raise Not_found *)
699 ignore(find_in_context name context);
700 if subst <> None then
701 Ast.fail loc "Explicit substitutions not allowed here"
706 | None -> [ Node ([loc], Id name, args_dom) ]
710 (fun dom (_, term) ->
711 let dom' = domain_of_term ~loc ~context term in
714 [ Node ([loc], Id name, terms @ args_dom) ]))
717 (fun term acc -> domain_of_term ~loc ~context term @ acc)
719 | Ast.Binder (kind, (var, typ), body) ->
720 let type_dom = domain_of_term_option ~loc ~context typ in
723 ~context:(CicNotationUtil.cic_name_of_name var :: context) body in
725 | `Exists -> [ Node ([loc], Symbol ("exists", 0), (type_dom @ body_dom)) ]
726 | _ -> type_dom @ body_dom)
727 | Ast.Case (term, indty_ident, outtype, branches) ->
728 let term_dom = domain_of_term ~loc ~context term in
729 let outtype_dom = domain_of_term_option ~loc ~context outtype in
730 let rec get_first_constructor = function
732 | (Ast.Pattern (head, _, _), _) :: _ -> [ Node ([loc], Id head, []) ]
733 | _ :: tl -> get_first_constructor tl in
736 Ast.Pattern (head, _, args), term ->
737 let (term_context, args_domain) =
739 (fun (cont, dom) (name, typ) ->
740 (CicNotationUtil.cic_name_of_name name :: cont,
743 | Some typ -> dom @ domain_of_term ~loc ~context:cont typ)))
746 domain_of_term ~loc ~context:term_context term @ args_domain
747 | Ast.Wildcard, term ->
748 domain_of_term ~loc ~context term
751 List.fold_left (fun dom branch -> dom @ do_branch branch) [] branches in
752 (match indty_ident with
753 | None -> get_first_constructor branches
754 | Some (ident, _) -> [ Node ([loc], Id ident, []) ])
755 @ term_dom @ outtype_dom @ branches_dom
756 | Ast.Cast (term, ty) ->
757 let term_dom = domain_of_term ~loc ~context term in
758 let ty_dom = domain_of_term ~loc ~context ty in
760 | Ast.LetIn ((var, typ), body, where) ->
761 let body_dom = domain_of_term ~loc ~context body in
762 let type_dom = domain_of_term_option ~loc ~context typ in
765 ~context:(CicNotationUtil.cic_name_of_name var :: context) where in
766 body_dom @ type_dom @ where_dom
767 | Ast.LetRec (kind, defs, where) ->
768 let add_defs context =
770 (fun acc (_, (var, _), _, _) ->
771 CicNotationUtil.cic_name_of_name var :: acc
773 let where_dom = domain_of_term ~loc ~context:(add_defs context) where in
776 (fun dom (params, (_, typ), body, _) ->
780 (fun acc (var,_) -> CicNotationUtil.cic_name_of_name var :: acc)
786 (fun (context,res) (var,ty) ->
787 CicNotationUtil.cic_name_of_name var :: context,
788 domain_of_term_option ~loc ~context ty @ res)
789 (add_defs context,[]) params))
790 @ domain_of_term_option ~loc ~context:context' typ
791 @ domain_of_term ~loc ~context:context' body
795 | Ast.Ident (name, subst) ->
797 (* the next line can raise Not_found *)
798 ignore(find_in_context name context);
799 if subst <> None then
800 Ast.fail loc "Explicit substitutions not allowed here"
805 | None -> [ Node ([loc], Id name, []) ]
809 (fun dom (_, term) ->
810 let dom' = domain_of_term ~loc ~context term in
813 [ Node ([loc], Id name, terms) ]))
816 | Ast.Num (num, i) -> [ Node ([loc], Num i, []) ]
817 | Ast.Meta (index, local_context) ->
819 (fun dom term -> dom @ domain_of_term_option ~loc ~context term)
826 | Ast.Variable _ -> assert false
828 and domain_of_term_option ~loc ~context = function
830 | Some t -> domain_of_term ~loc ~context t
832 let domain_of_term ~context term =
833 uniq_domain (domain_of_term ~context term)
835 let domain_of_obj ~context ast =
836 assert (context = []);
838 | Ast.Theorem (_,_,ty,bo) ->
842 | Some bo -> domain_of_term [] bo)
843 | Ast.Inductive (params,tyl) ->
846 (fun (context, dom) (var, ty) ->
847 let context' = CicNotationUtil.cic_name_of_name var :: context in
849 None -> context', dom
850 | Some ty -> context', dom @ domain_of_term context ty
852 let context_w_types =
854 (fun (var, _, _, _) -> Cic.Name var) tyl
860 domain_of_term context ty
863 (fun (_,ty) -> domain_of_term context_w_types ty) cl))
865 | CicNotationPt.Record (params,var,ty,fields) ->
868 (fun (context, dom) (var, ty) ->
869 let context' = CicNotationUtil.cic_name_of_name var :: context in
871 None -> context', dom
872 | Some ty -> context', dom @ domain_of_term context ty
874 let context_w_types = Cic.Name var :: context in
876 @ domain_of_term context ty
879 (fun (context,res) (name,ty,_,_) ->
880 Cic.Name name::context, res @ domain_of_term context ty
881 ) (context_w_types,[]) fields)
883 let domain_of_obj ~context obj =
884 uniq_domain (domain_of_obj ~context obj)
887 let domain_diff dom1 dom2 =
888 (* let domain_diff = Domain.diff *)
892 | Symbol (symb, 0) ->
894 Symbol (symb',_) when symb = symb' -> true
906 | Node (_,elt,l)::tl when is_in_dom2 elt -> aux (l @ tl)
907 | Node (loc,elt,l)::tl -> Node (loc,elt,aux l)::(aux tl)
911 module type Disambiguator =
913 val disambiguate_term :
914 ?fresh_instances:bool ->
916 context:Cic.context ->
917 metasenv:Cic.metasenv ->
918 ?initial_ugraph:CicUniv.universe_graph ->
919 aliases:DisambiguateTypes.environment ->(* previous interpretation status *)
920 universe:DisambiguateTypes.multiple_environment option ->
921 CicNotationPt.term disambiguator_input ->
922 ((DisambiguateTypes.domain_item * DisambiguateTypes.codomain_item) list *
923 Cic.metasenv * (* new metasenv *)
925 CicUniv.universe_graph) list * (* disambiguated term *)
928 val disambiguate_obj :
929 ?fresh_instances:bool ->
931 aliases:DisambiguateTypes.environment ->(* previous interpretation status *)
932 universe:DisambiguateTypes.multiple_environment option ->
933 uri:UriManager.uri option -> (* required only for inductive types *)
934 CicNotationPt.term CicNotationPt.obj disambiguator_input ->
935 ((DisambiguateTypes.domain_item * DisambiguateTypes.codomain_item) list *
936 Cic.metasenv * (* new metasenv *)
938 CicUniv.universe_graph) list * (* disambiguated obj *)
942 module Make (C: Callbacks) =
944 let choices_of_id dbd id =
945 let uris = Whelp.locate ~dbd id in
950 (C.input_or_locate_uri
951 ~title:("URI matching \"" ^ id ^ "\" unknown.") ~id ())
957 C.interactive_user_uri_choice ~selection_mode:`MULTIPLE
958 ~ok:"Try selected." ~enable_button_for_non_vars:true
959 ~title:"Ambiguous input." ~id
960 ~msg: ("Ambiguous input \"" ^ id ^
961 "\". Please, choose one or more interpretations:")
966 (UriManager.string_of_uri uri,
969 CicUtil.term_of_uri uri
971 debug_print (lazy (UriManager.string_of_uri uri));
972 debug_print (lazy (Printexc.to_string exn));
978 let refine_profiler = HExtlib.profile "disambiguate_thing.refine_thing"
980 let disambiguate_thing ~dbd ~context ~metasenv
981 ?(initial_ugraph = CicUniv.empty_ugraph) ~aliases ~universe
982 ~uri ~pp_thing ~domain_of_thing ~interpretate_thing ~refine_thing
983 (thing_txt,thing_txt_prefix_len,thing)
985 debug_print (lazy "DISAMBIGUATE INPUT");
986 let disambiguate_context = (* cic context -> disambiguate context *)
988 (function None -> Cic.Anonymous | Some (name, _) -> name)
991 debug_print (lazy ("TERM IS: " ^ (pp_thing thing)));
992 let thing_dom = domain_of_thing ~context:disambiguate_context thing in
994 (lazy (sprintf "DISAMBIGUATION DOMAIN: %s"(string_of_domain thing_dom)));
996 debug_print (lazy (sprintf "DISAMBIGUATION ENVIRONMENT: %s"
997 (DisambiguatePp.pp_environment aliases)));
998 debug_print (lazy (sprintf "DISAMBIGUATION UNIVERSE: %s"
999 (match universe with None -> "None" | Some _ -> "Some _")));
1002 Environment.fold (fun item _ dom -> item :: dom) aliases [] in
1003 let todo_dom = domain_diff thing_dom current_dom in
1005 (lazy (sprintf "DISAMBIGUATION DOMAIN AFTER DIFF: %s"(string_of_domain todo_dom)));
1006 (* (2) lookup function for any item (Id/Symbol/Num) *)
1007 let lookup_choices =
1010 let lookup_in_library () =
1012 | Id id -> choices_of_id dbd id
1013 | Symbol (symb, _) ->
1015 List.map DisambiguateChoices.mk_choice
1016 (TermAcicContent.lookup_interpretations symb)
1018 TermAcicContent.Interpretation_not_found -> [])
1020 DisambiguateChoices.lookup_num_choices ()
1023 | None -> lookup_in_library ()
1028 | Symbol (symb, _) -> Symbol (symb, 0)
1031 Environment.find item e
1032 with Not_found -> lookup_in_library ())
1039 if benchmark then begin
1040 let per_item_choices =
1044 let len = List.length (lookup_choices dom_item) in
1045 debug_print (lazy (sprintf "BENCHMARK %s: %d"
1046 (string_of_domain_item dom_item) len));
1048 with No_choices _ -> 0)
1051 max_refinements := List.fold_left ( * ) 1 per_item_choices;
1052 actual_refinements := 0;
1053 domain_size := List.length thing_dom;
1055 (float_of_int !max_refinements) ** (1. /. float_of_int !domain_size)
1061 (* (3) test an interpretation filling with meta uninterpreted identifiers
1063 let test_env aliases todo_dom ugraph =
1064 let rec aux env = function
1066 | Node (_, item, l) :: tl ->
1068 Environment.add item
1072 (fun _ _ _ -> Cic.Implicit (Some `Closed))
1073 | Symbol _ -> (fun _ _ _ -> Cic.Implicit None)))
1075 aux (aux env l) tl in
1076 let filled_env = aux aliases todo_dom in
1078 let localization_tbl = Cic.CicHash.create 503 in
1080 interpretate_thing ~context:disambiguate_context ~env:filled_env
1081 ~uri ~is_path:false thing ~localization_tbl
1085 refine_thing metasenv context uri cic_thing ugraph ~localization_tbl
1088 in refine_profiler.HExtlib.profile foo ()
1090 | Try_again msg -> Uncertain (None,msg), ugraph
1091 | Invalid_choice (loc,msg) -> Ko (loc,msg), ugraph
1093 (* (4) build all possible interpretations *)
1094 let (@@) (l1,l2,l3) (l1',l2',l3') = l1@l1', l2@l2', l3@l3' in
1095 (* aux returns triples Ok/Uncertain/Ko *)
1096 (* rem_dom is the concatenation of all the remaining domains *)
1097 let rec aux aliases diff lookup_in_todo_dom todo_dom rem_dom base_univ =
1098 (* debug_print (lazy ("ZZZ: " ^ string_of_domain todo_dom)); *)
1100 | Node (locs,item,inner_dom) ->
1101 debug_print (lazy (sprintf "CHOOSED ITEM: %s"
1102 (string_of_domain_item item)));
1104 match lookup_in_todo_dom with
1105 None -> lookup_choices item
1106 | Some choices -> choices in
1110 [aliases, diff, Some (List.hd locs),
1111 lazy ("No choices for " ^ string_of_domain_item item),
1114 | [codomain_item] ->
1115 (* just one choice. We perform a one-step look-up and
1116 if the next set of choices is also a singleton we
1117 skip this refinement step *)
1118 debug_print(lazy (sprintf "%s CHOSEN" (fst codomain_item)));
1119 let new_env = Environment.add item codomain_item aliases in
1120 let new_diff = (item,codomain_item)::diff in
1121 let lookup_in_todo_dom,next_choice_is_single =
1122 match remaining_dom with
1125 let choices = lookup_choices he in
1126 Some choices,List.length choices = 1
1128 if next_choice_is_single then
1129 aux new_env new_diff lookup_in_todo_dom remaining_dom
1132 (match test_env new_env remaining_dom base_univ with
1133 | Ok (thing, metasenv),new_univ ->
1134 (match remaining_dom with
1136 [ new_env, new_diff, metasenv, thing, new_univ ], []
1138 aux new_env new_diff lookup_in_todo_dom
1139 remaining_dom new_univ)
1140 | Uncertain (loc,msg),new_univ ->
1141 (match remaining_dom with
1142 | [] -> [], [new_env,new_diff,loc,msg,true]
1144 aux new_env new_diff lookup_in_todo_dom
1145 remaining_dom new_univ)
1146 | Ko (loc,msg),_ -> [], [new_env,new_diff,loc,msg,true])
1151 (function codomain_item ->
1152 debug_print(lazy (sprintf "%s CHOSEN" (fst codomain_item)));
1153 let new_env = Environment.add item codomain_item aliases in
1154 let new_diff = (item,codomain_item)::diff in
1155 test_env new_env (inner_dom@rem_dom) base_univ,
1158 let some_outcome_ok =
1162 | (Uncertain (_,_),_),_,_ -> true
1165 let rec filter univ = function
1167 | (outcome,new_env,new_diff) :: tl ->
1169 | Ok (thing, metasenv),new_univ ->
1171 (match inner_dom with
1173 [new_env,new_diff,metasenv,thing,new_univ], [], []
1175 visit_children new_env new_diff new_univ rem_dom inner_dom)
1177 res @@ filter univ tl
1178 | Uncertain (loc,msg),new_univ ->
1180 (match inner_dom with
1181 | [] -> [],[new_env,new_diff,loc,msg,new_univ],[]
1183 visit_children new_env new_diff new_univ rem_dom inner_dom)
1185 res @@ filter univ tl
1188 [],[],[new_env,new_diff,loc,msg,not some_outcome_ok]
1190 res @@ filter univ tl
1192 filter base_univ outcomes
1193 and visit_children env diff univ rem_dom =
1196 | [dom] -> aux env diff None dom rem_dom univ
1197 | dom::remaining_dom ->
1198 let ok_l,uncertain_l,error_l =
1199 aux env diff None dom (remaining_dom@rem_dom) univ
1201 let res_after_ok_l =
1203 (fun (env,diff,_,_,univ) res ->
1204 visit_children env diff univ rem_dom remaining_dom
1206 ) ok_l ([],[],error_l)
1209 (fun (env,diff,_,_,univ) res ->
1210 visit_children env diff univ rem_dom remaining_dom
1212 ) uncertain_l res_after_ok_l
1214 let aux' aliases diff lookup_in_todo_dom todo_dom base_univ =
1215 match test_env aliases todo_dom base_univ with
1216 | Ok (thing, metasenv),new_univ ->
1217 if todo_dom = [] then
1218 [ aliases, diff, metasenv, thing, new_univ ], [], []
1220 visit_children aliases diff base_univ [] todo_dom
1222 _lookup_in_todo_dom_
1224 | Uncertain (loc,msg),new_univ ->
1225 if todo_dom = [] then
1226 [],[aliases,diff,loc,msg,new_univ],[]
1228 visit_children aliases diff base_univ [] todo_dom
1230 _lookup_in_todo_dom_
1232 | Ko (loc,msg),_ -> [],[],[aliases,diff,loc,msg,true] in
1233 let base_univ = initial_ugraph in
1236 match aux' aliases [] None todo_dom base_univ with
1237 | [],uncertain,errors ->
1238 debug_print (lazy "NO INTERPRETATIONS");
1241 (fun (env,diff,loc,msg,_) -> (env,diff,loc,msg,true)
1242 ) uncertain @ errors
1246 (fun (env,diff,loc,msg,significant) ->
1249 (fun locs domain_item ->
1252 fst (Environment.find domain_item env)
1254 Some (locs,descr_of_domain_item domain_item,description)
1259 env',diff,loc,msg,significant
1262 raise (NoWellTypedInterpretation (0,errors))
1263 | [_,diff,metasenv,t,ugraph],_,_ ->
1264 debug_print (lazy "SINGLE INTERPRETATION");
1265 [diff,metasenv,t,ugraph], false
1268 (lazy (sprintf "MANY INTERPRETATIONS (%d)" (List.length l)));
1271 (fun (env, _, _, _, _) ->
1273 (fun locs domain_item ->
1275 fst (Environment.find domain_item env)
1277 locs,descr_of_domain_item domain_item, description)
1282 C.interactive_interpretation_choice
1283 thing_txt thing_txt_prefix_len choices
1285 (List.map (fun n->let _,d,m,t,u= List.nth l n in d,m,t,u) choosed),
1290 CicEnvironment.CircularDependency s ->
1291 failwith "Disambiguate: circular dependency"
1293 let disambiguate_term ?(fresh_instances=false) ~dbd ~context ~metasenv
1294 ?(initial_ugraph = CicUniv.empty_ugraph) ~aliases ~universe
1295 (text,prefix_len,term)
1298 if fresh_instances then CicNotationUtil.freshen_term term else term
1300 disambiguate_thing ~dbd ~context ~metasenv ~initial_ugraph ~aliases
1301 ~universe ~uri:None ~pp_thing:CicNotationPp.pp_term
1302 ~domain_of_thing:domain_of_term
1303 ~interpretate_thing:(interpretate_term (?create_dummy_ids:None))
1304 ~refine_thing:refine_term (text,prefix_len,term)
1306 let disambiguate_obj ?(fresh_instances=false) ~dbd ~aliases ~universe ~uri
1307 (text,prefix_len,obj)
1310 if fresh_instances then CicNotationUtil.freshen_obj obj else obj
1312 disambiguate_thing ~dbd ~context:[] ~metasenv:[] ~aliases ~universe ~uri
1313 ~pp_thing:(CicNotationPp.pp_obj CicNotationPp.pp_term) ~domain_of_thing:domain_of_obj
1314 ~interpretate_thing:interpretate_obj ~refine_thing:refine_obj
1315 (text,prefix_len,obj)