2 Copyright (C) 1999-2006, HELM Team.
4 This file is part of HELM, an Hypertextual, Electronic
5 Library of Mathematics, developed at the Computer Science
6 Department, University of Bologna, Italy.
8 HELM is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 HELM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 For details, see the HELM web site: http://helm.cs.unibo.it/
27 module Ast = CicNotationPt
30 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
32 let refine_term metasenv subst context uri term ugraph ~localization_tbl =
33 (* if benchmark then incr actual_refinements; *)
35 debug_print (lazy (sprintf "TEST_INTERPRETATION: %s" (CicPp.ppterm term)));
37 let term', _, metasenv',ugraph1 =
38 CicRefine.type_of_aux' metasenv context term ugraph ~localization_tbl in
39 (Disambiguate.Ok (term', metasenv',[],ugraph1))
42 let rec process_exn loc =
44 HExtlib.Localized (loc,exn) -> process_exn loc exn
45 | CicRefine.Uncertain msg ->
46 debug_print (lazy ("UNCERTAIN!!! [" ^ (Lazy.force msg) ^ "] " ^ CicPp.ppterm term)) ;
47 Disambiguate.Uncertain (lazy (loc,Lazy.force msg))
48 | CicRefine.RefineFailure msg ->
49 debug_print (lazy (sprintf "PRUNED!!!\nterm%s\nmessage:%s"
50 (CicPp.ppterm term) (Lazy.force msg)));
51 Disambiguate.Ko (lazy (loc,Lazy.force msg))
54 process_exn Stdpp.dummy_loc exn
56 let refine_obj metasenv subst context uri obj ugraph ~localization_tbl =
57 assert (context = []);
58 assert (metasenv = []);
60 debug_print (lazy (sprintf "TEST_INTERPRETATION: %s" (CicPp.ppobj obj))) ;
62 let obj', metasenv,ugraph =
63 CicRefine.typecheck metasenv uri obj ~localization_tbl
65 (Disambiguate.Ok (obj', metasenv,[],ugraph))
68 let rec process_exn loc =
70 HExtlib.Localized (loc,exn) -> process_exn loc exn
71 | CicRefine.Uncertain msg ->
72 debug_print (lazy ("UNCERTAIN!!! [" ^
73 (Lazy.force msg) ^ "] " ^ CicPp.ppobj obj)) ;
74 Disambiguate.Uncertain (lazy (loc,Lazy.force msg))
75 | CicRefine.RefineFailure msg ->
76 debug_print (lazy (sprintf "PRUNED!!!\nterm%s\nmessage:%s"
77 (CicPp.ppobj obj) (Lazy.force msg))) ;
78 Disambiguate.Ko (lazy (loc,Lazy.force msg))
81 process_exn Stdpp.dummy_loc exn
84 let interpretate_term ?(create_dummy_ids=false) ~context ~env ~uri ~is_path ast
87 (* create_dummy_ids shouldbe used only for interpretating patterns *)
89 let rec aux ~localize loc context = function
90 | CicNotationPt.AttributedTerm (`Loc loc, term) ->
91 let res = aux ~localize loc context term in
92 if localize then Cic.CicHash.add localization_tbl res loc;
94 | CicNotationPt.AttributedTerm (_, term) -> aux ~localize loc context term
95 | CicNotationPt.Appl (CicNotationPt.Symbol (symb, i) :: args) ->
96 let cic_args = List.map (aux ~localize loc context) args in
97 Disambiguate.resolve env
98 (DisambiguateTypes.Symbol (symb, i)) ~args:cic_args ()
99 | CicNotationPt.Appl terms ->
100 Cic.Appl (List.map (aux ~localize loc context) terms)
101 | CicNotationPt.Binder (binder_kind, (var, typ), body) ->
102 let cic_type = aux_option ~localize loc context (Some `Type) typ in
103 let cic_name = CicNotationUtil.cic_name_of_name var in
104 let cic_body = aux ~localize loc (cic_name :: context) body in
105 (match binder_kind with
106 | `Lambda -> Cic.Lambda (cic_name, cic_type, cic_body)
108 | `Forall -> Cic.Prod (cic_name, cic_type, cic_body)
110 Disambiguate.resolve env (DisambiguateTypes.Symbol ("exists", 0))
111 ~args:[ cic_type; Cic.Lambda (cic_name, cic_type, cic_body) ] ())
112 | CicNotationPt.Case (term, indty_ident, outtype, branches) ->
113 let cic_term = aux ~localize loc context term in
114 let cic_outtype = aux_option ~localize loc context None outtype in
115 let do_branch ((head, _, args), term) =
116 let rec do_branch' context = function
117 | [] -> aux ~localize loc context term
118 | (name, typ) :: tl ->
119 let cic_name = CicNotationUtil.cic_name_of_name name in
120 let cic_body = do_branch' (cic_name :: context) tl in
123 | None -> Cic.Implicit (Some `Type)
124 | Some typ -> aux ~localize loc context typ
126 Cic.Lambda (cic_name, typ, cic_body)
128 do_branch' context args
130 let indtype_uri, indtype_no =
131 if create_dummy_ids then
132 (UriManager.uri_of_string "cic:/fake_indty.con", 0)
134 match indty_ident with
135 | Some (indty_ident, _) ->
137 Disambiguate.resolve env
138 (DisambiguateTypes.Id indty_ident) ()
140 | Cic.MutInd (uri, tyno, _) -> (uri, tyno)
142 raise (Disambiguate.Try_again
143 (lazy "The type of the term to be matched
146 raise (DisambiguateTypes.Invalid_choice (lazy (loc,"The type of the term to be matched is not (co)inductive!"))))
148 let rec fst_constructor =
150 (Ast.Pattern (head, _, _), _) :: _ -> head
151 | (Ast.Wildcard, _) :: tl -> fst_constructor tl
152 | [] -> raise (DisambiguateTypes.Invalid_choice (lazy (loc,"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")))
154 (match Disambiguate.resolve env
155 (DisambiguateTypes.Id (fst_constructor branches)) () with
156 | Cic.MutConstruct (indtype_uri, indtype_no, _, _) ->
157 (indtype_uri, indtype_no)
159 raise (Disambiguate.Try_again (lazy "The type of the term to be matched
162 raise (DisambiguateTypes.Invalid_choice (lazy (loc,"The type of the term to be matched is not (co)inductive!"))))
165 if create_dummy_ids then
168 Ast.Wildcard,term -> ("wildcard",None,[]), term
170 raise (DisambiguateTypes.Invalid_choice (lazy (loc, "Syntax error: the left hand side of a branch patterns must be \"_\"")))
173 match fst(CicEnvironment.get_obj CicUniv.oblivion_ugraph indtype_uri) with
174 Cic.InductiveDefinition (il,_,leftsno,_) ->
177 List.nth il indtype_no
178 with _ -> assert false
180 let rec count_prod t =
181 match CicReduction.whd [] t with
182 Cic.Prod (_, _, t) -> 1 + (count_prod t)
185 let rec sort branches cl =
188 let rec analyze unused unrecognized useless =
191 if unrecognized != [] then
192 raise (DisambiguateTypes.Invalid_choice
194 ("Unrecognized constructors: " ^
195 String.concat " " unrecognized))))
196 else if useless > 0 then
197 raise (DisambiguateTypes.Invalid_choice
199 ("The last " ^ string_of_int useless ^
200 "case" ^ if useless > 1 then "s are" else " is" ^
204 | (Ast.Wildcard,_)::tl when not unused ->
205 analyze true unrecognized useless tl
206 | (Ast.Pattern (head,_,_),_)::tl when not unused ->
207 analyze unused (head::unrecognized) useless tl
208 | _::tl -> analyze unused unrecognized (useless + 1) tl
210 analyze false [] 0 branches
212 let rec find_and_remove =
216 (DisambiguateTypes.Invalid_choice
217 (lazy (loc, ("Missing case: " ^ name))))
218 | ((Ast.Wildcard, _) as branch :: _) as branches ->
220 | (Ast.Pattern (name',_,_),_) as branch :: tl
224 let found,rest = find_and_remove tl in
227 let branch,tl = find_and_remove branches in
229 Ast.Pattern (name,y,args),term ->
230 if List.length args = count_prod ty - leftsno then
231 ((name,y,args),term)::sort tl cltl
234 (DisambiguateTypes.Invalid_choice
235 (lazy (loc,"Wrong number of arguments for " ^
237 | Ast.Wildcard,term ->
243 (`Lambda, (CicNotationPt.Ident ("_", None), None),
246 (("wildcard",None,[]),
247 mk_lambdas (count_prod ty - leftsno)) :: sort tl cltl
252 Cic.MutCase (indtype_uri, indtype_no, cic_outtype, cic_term,
253 (List.map do_branch branches))
254 | CicNotationPt.Cast (t1, t2) ->
255 let cic_t1 = aux ~localize loc context t1 in
256 let cic_t2 = aux ~localize loc context t2 in
257 Cic.Cast (cic_t1, cic_t2)
258 | CicNotationPt.LetIn ((name, typ), def, body) ->
259 let cic_def = aux ~localize loc context def in
260 let cic_name = CicNotationUtil.cic_name_of_name name in
263 | None -> Cic.Implicit (Some `Type)
264 | Some t -> aux ~localize loc context t
266 let cic_body = aux ~localize loc (cic_name :: context) body in
267 Cic.LetIn (cic_name, cic_def, cic_typ, cic_body)
268 | CicNotationPt.LetRec (kind, defs, body) ->
271 (fun acc (_, (name, _), _, _) ->
272 CicNotationUtil.cic_name_of_name name :: acc)
276 let unlocalized_body = aux ~localize:false loc context' body in
277 match unlocalized_body with
278 Cic.Rel n when n <= List.length defs -> `AvoidLetInNoAppl n
279 | Cic.Appl (Cic.Rel n::l) when n <= List.length defs ->
284 let t',subst,metasenv =
285 CicMetaSubst.delift_rels [] [] (List.length defs) t
288 assert (metasenv=[]);
291 (* We can avoid the LetIn. But maybe we need to recompute l'
292 so that it is localized *)
295 CicNotationPt.AttributedTerm (_,CicNotationPt.Appl(_::l)) ->
296 (* since we avoid the letin, the context has no
298 let l' = List.map (aux ~localize loc context) l in
304 CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
306 `AddLetIn (aux ~localize loc context' body)
308 `AddLetIn unlocalized_body)
311 `AddLetIn (aux ~localize loc context' body)
313 `AddLetIn unlocalized_body
317 (fun (params, (name, typ), body, decr_idx) ->
318 let add_binders kind t =
320 (fun var t -> CicNotationPt.Binder (kind, var, t)) params t
323 aux ~localize loc context' (add_binders `Lambda body) in
325 aux_option ~localize loc context (Some `Type)
326 (HExtlib.map_option (add_binders `Pi) typ) in
328 match CicNotationUtil.cic_name_of_name name with
330 CicNotationPt.fail loc
331 "Recursive functions cannot be anonymous"
332 | Cic.Name name -> name
334 (name, decr_idx, cic_type, cic_body))
339 `Inductive -> Cic.Fix (n,inductiveFuns)
341 let coinductiveFuns =
343 (fun (name, _, typ, body) -> name, typ, body)
346 Cic.CoFix (n,coinductiveFuns)
348 let counter = ref ~-1 in
349 let build_term funs (var,_,ty,_) t =
351 Cic.LetIn (Cic.Name var, fix_or_cofix !counter, ty, t)
354 `AvoidLetInNoAppl n ->
355 let n' = List.length inductiveFuns - n in
357 | `AvoidLetIn (n,l) ->
358 let n' = List.length inductiveFuns - n in
359 Cic.Appl (fix_or_cofix n'::l)
360 | `AddLetIn cic_body ->
361 List.fold_right (build_term inductiveFuns) inductiveFuns
363 | CicNotationPt.Ident _
364 | CicNotationPt.Uri _ when is_path -> raise Disambiguate.PathNotWellFormed
365 | CicNotationPt.Ident (name, subst)
366 | CicNotationPt.Uri (name, subst) as ast ->
367 let is_uri = function CicNotationPt.Uri _ -> true | _ -> false in
369 if is_uri ast then raise Not_found;(* don't search the env for URIs *)
370 let index = Disambiguate.find_in_context name context in
371 if subst <> None then
372 CicNotationPt.fail loc "Explicit substitutions not allowed here";
376 if is_uri ast then (* we have the URI, build the term out of it *)
378 CicUtil.term_of_uri (UriManager.uri_of_string name)
379 with UriManager.IllFormedUri _ ->
380 CicNotationPt.fail loc "Ill formed URI"
382 Disambiguate.resolve env (DisambiguateTypes.Id name) ()
386 List.map (fun uri -> UriManager.name_of_uri uri, uri) uris
393 List.assoc s ids_to_uris, aux ~localize loc context term
395 raise (DisambiguateTypes.Invalid_choice (lazy (loc, "The provided explicit named substitution is trying to instantiate a named variable the object is not abstracted on")))))
397 | None -> List.map (fun uri -> uri, Cic.Implicit None) uris)
401 | Cic.Const (uri, []) ->
402 let o,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph uri in
403 let uris = CicUtil.params_of_obj o in
404 Cic.Const (uri, mk_subst uris)
405 | Cic.Var (uri, []) ->
406 let o,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph uri in
407 let uris = CicUtil.params_of_obj o in
408 Cic.Var (uri, mk_subst uris)
409 | Cic.MutInd (uri, i, []) ->
411 let o,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph uri in
412 let uris = CicUtil.params_of_obj o in
413 Cic.MutInd (uri, i, mk_subst uris)
415 CicEnvironment.Object_not_found _ ->
416 (* if we are here it is probably the case that during the
417 definition of a mutual inductive type we have met an
418 occurrence of the type in one of its constructors.
419 However, the inductive type is not yet in the environment
421 (*here the explicit_named_substituion is assumed to be of length 0 *)
422 Cic.MutInd (uri,i,[]))
423 | Cic.MutConstruct (uri, i, j, []) ->
424 let o,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph uri in
425 let uris = CicUtil.params_of_obj o in
426 Cic.MutConstruct (uri, i, j, mk_subst uris)
427 | Cic.Meta _ | Cic.Implicit _ as t ->
429 debug_print (lazy (sprintf
430 "Warning: %s must be instantiated with _[%s] but we do not enforce it"
434 (fun (s, term) -> s ^ " := " ^ CicNotationPtPp.pp_term term)
439 raise (DisambiguateTypes.Invalid_choice (lazy (loc, "??? Can this happen?")))
441 CicEnvironment.CircularDependency _ ->
442 raise (DisambiguateTypes.Invalid_choice (lazy (loc,"Circular dependency in the environment")))))
443 | CicNotationPt.Implicit -> Cic.Implicit None
444 | CicNotationPt.UserInput -> Cic.Implicit (Some `Hole)
445 | CicNotationPt.Num (num, i) -> Disambiguate.resolve env (DisambiguateTypes.Num i) ~num ()
446 | CicNotationPt.Meta (index, subst) ->
451 | Some term -> Some (aux ~localize loc context term))
454 Cic.Meta (index, cic_subst)
455 | CicNotationPt.Sort `Prop -> Cic.Sort Cic.Prop
456 | CicNotationPt.Sort `Set -> Cic.Sort Cic.Set
457 | CicNotationPt.Sort (`Type u) -> Cic.Sort (Cic.Type u)
458 | CicNotationPt.Sort (`CProp u) -> Cic.Sort (Cic.CProp u)
459 | CicNotationPt.Symbol (symbol, instance) ->
460 Disambiguate.resolve env (DisambiguateTypes.Symbol (symbol, instance)) ()
461 | _ -> assert false (* god bless Bologna *)
462 and aux_option ~localize loc context annotation = function
463 | None -> Cic.Implicit annotation
464 | Some term -> aux ~localize loc context term
466 aux ~localize:true HExtlib.dummy_floc context ast
468 let interpretate_path ~context path =
469 let localization_tbl = Cic.CicHash.create 23 in
470 (* here we are throwing away useful localization informations!!! *)
472 interpretate_term ~create_dummy_ids:true
473 ~context ~env:DisambiguateTypes.Environment.empty ~uri:None ~is_path:true
474 path ~localization_tbl, localization_tbl)
476 let interpretate_obj ~context ~env ~uri ~is_path obj ~localization_tbl =
477 assert (context = []);
478 assert (is_path = false);
479 let interpretate_term = interpretate_term ~localization_tbl in
481 | CicNotationPt.Inductive (params,tyl) ->
482 let uri = match uri with Some uri -> uri | None -> assert false in
486 (fun (context,res) (name,t) ->
489 None -> CicNotationPt.Implicit
491 let name = CicNotationUtil.cic_name_of_name name in
492 name::context,(name, interpretate_term context env None false t)::res
495 context,List.rev res in
497 List.fold_right (fun (name,ty) t -> Cic.Prod (name,ty,t)) params in
501 (*here the explicit_named_substituion is assumed to be of length 0 *)
502 (fun (i,res) (name,_,_,_) ->
503 i + 1,(name,name,Cic.MutInd (uri,i,[]))::res
505 let con_env = DisambiguateTypes.env_of_list name_to_uris env in
508 (fun (name,b,ty,cl) ->
509 let ty' = add_params (interpretate_term context env None false ty) in
514 add_params (interpretate_term context con_env None false ty)
522 Cic.InductiveDefinition (tyl,[],List.length params,[])
523 | CicNotationPt.Record (params,name,ty,fields) ->
524 let uri = match uri with Some uri -> uri | None -> assert false in
528 (fun (context,res) (name,t) ->
531 None -> CicNotationPt.Implicit
533 let name = CicNotationUtil.cic_name_of_name name in
534 name::context,(name, interpretate_term context env None false t)::res
537 context,List.rev res in
540 (fun (name,ty) t -> Cic.Prod (name,ty,t)) params in
541 let ty' = add_params (interpretate_term context env None false ty) in
545 (fun (context,res) (name,ty,_coercion,arity) ->
546 let context' = Cic.Name name :: context in
547 context',(name,interpretate_term context env None false ty)::res
548 ) (context,[]) fields) in
550 (*here the explicit_named_substituion is assumed to be of length 0 *)
551 let mutind = Cic.MutInd (uri,0,[]) in
552 if params = [] then mutind
555 (mutind::CicUtil.mk_rels (List.length params) (List.length fields)) in
558 (fun t (name,ty) -> Cic.Prod (Cic.Name name,ty,t))
560 let con' = add_params con in
561 let tyl = [name,true,ty',["mk_" ^ name,con']] in
562 let field_names = List.map (fun (x,_,y,z) -> x,y,z) fields in
563 Cic.InductiveDefinition
564 (tyl,[],List.length params,[`Class (`Record field_names)])
565 | CicNotationPt.Theorem (flavour, name, ty, bo) ->
566 let attrs = [`Flavour flavour] in
567 let ty' = interpretate_term [] env None false ty in
568 (match bo,flavour with
570 Cic.Constant (name,None,ty',[],attrs)
571 | Some bo,`Axiom -> assert false
573 Cic.CurrentProof (name,[],Cic.Implicit None,ty',[],attrs)
575 let bo' = Some (interpretate_term [] env None false bo) in
576 Cic.Constant (name,bo',ty',[],attrs))
579 let interpretate_term ?(create_dummy_ids=false) ~context ~env ~uri ~is_path ast
582 let context = List.map (function None -> Cic.Anonymous | Some (n,_) -> n) context in
583 interpretate_term ~create_dummy_ids ~context ~env ~uri ~is_path ast
590 module type CicDisambiguator =
592 val disambiguate_term :
593 ?fresh_instances:bool ->
594 context:Cic.context ->
595 metasenv:Cic.metasenv ->
596 subst:Cic.substitution ->
598 ?initial_ugraph:CicUniv.universe_graph ->
599 aliases:Cic.term DisambiguateTypes.environment ->
600 universe:Cic.term DisambiguateTypes.multiple_environment option ->
602 DisambiguateTypes.interactive_user_uri_choice_type ->
603 DisambiguateTypes.input_or_locate_uri_type ->
604 DisambiguateTypes.Environment.key ->
605 Cic.term DisambiguateTypes.codomain_item list) ->
606 CicNotationPt.term Disambiguate.disambiguator_input ->
607 ((DisambiguateTypes.domain_item *
608 Cic.term DisambiguateTypes.codomain_item) list *
612 CicUniv.universe_graph) list *
615 val disambiguate_obj :
616 ?fresh_instances:bool ->
617 aliases:Cic.term DisambiguateTypes.environment ->
618 universe:Cic.term DisambiguateTypes.multiple_environment option ->
619 uri:UriManager.uri option -> (* required only for inductive types *)
621 DisambiguateTypes.interactive_user_uri_choice_type ->
622 DisambiguateTypes.input_or_locate_uri_type ->
623 DisambiguateTypes.Environment.key ->
624 Cic.term DisambiguateTypes.codomain_item list) ->
625 CicNotationPt.term CicNotationPt.obj Disambiguate.disambiguator_input ->
626 ((DisambiguateTypes.domain_item *
627 Cic.term DisambiguateTypes.codomain_item) list *
631 CicUniv.universe_graph) list *
635 module Make (C: DisambiguateTypes.Callbacks) =
637 module Disambiguator = Disambiguate.Make(C)
640 function true -> Cic.Implicit (Some `Closed)
641 | _ -> Cic.Implicit None
644 let disambiguate_term ?(fresh_instances=false) ~context ~metasenv
646 ?(initial_ugraph = CicUniv.oblivion_ugraph) ~aliases ~universe
648 (text,prefix_len,term)
651 if fresh_instances then CicNotationUtil.freshen_term term else term
653 let hint = match goal with
654 | None -> (fun _ x -> x), fun k -> k
657 let _,c,ty = CicUtil.lookup_meta i metasenv in
661 | Disambiguate.Ok (t,m,s,ug) ->
663 | Cic.Cast(t,_) -> Disambiguate.Ok (t,m,s,ug)
667 let localization_tbl = Cic.CicHash.create 503 in
668 Disambiguator.disambiguate_thing ~context ~metasenv ~subst
669 ~initial_ugraph ~aliases ~mk_implicit
670 ~universe ~lookup_in_library
671 ~uri:None ~pp_thing:CicNotationPp.pp_term
672 ~domain_of_thing:Disambiguate.domain_of_term
673 ~interpretate_thing:(interpretate_term (?create_dummy_ids:None))
674 ~refine_thing:refine_term (text,prefix_len,term)
679 ?(fresh_instances=false) ~aliases ~universe ~uri ~lookup_in_library
680 (text,prefix_len,obj)
683 if fresh_instances then CicNotationUtil.freshen_obj obj else obj
689 let localization_tbl = Cic.CicHash.create 503 in
690 Disambiguator.disambiguate_thing ~context:[] ~metasenv:[] ~subst:[]
691 ~aliases ~universe ~uri ~mk_implicit
692 ~pp_thing:(CicNotationPp.pp_obj CicNotationPp.pp_term)
693 ~domain_of_thing:Disambiguate.domain_of_obj
695 ~initial_ugraph:CicUniv.empty_ugraph
696 ~interpretate_thing:interpretate_obj
697 ~refine_thing:refine_obj
700 (text,prefix_len,obj)