1 (* Copyright (C) 2000, 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://cs.unibo.it/helm/.
30 exception RefineFailure of string Lazy.t;;
31 exception Uncertain of string Lazy.t;;
32 exception AssertFailure of string Lazy.t;;
34 let insert_coercions = ref true
35 let pack_coercions = ref true
37 let debug_print = fun _ -> ()
38 (* let debug_print x = prerr_endline (Lazy.force x);; *)
40 let profiler_eat_prods2 = HExtlib.profile "CicRefine.fo_unif_eat_prods2"
42 let fo_unif_subst_eat_prods2 subst context metasenv t1 t2 ugraph =
45 CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
46 in profiler_eat_prods2.HExtlib.profile foo ()
48 (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
49 | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
52 let profiler_eat_prods = HExtlib.profile "CicRefine.fo_unif_eat_prods"
54 let fo_unif_subst_eat_prods subst context metasenv t1 t2 ugraph =
57 CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
58 in profiler_eat_prods.HExtlib.profile foo ()
60 (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
61 | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
64 let profiler = HExtlib.profile "CicRefine.fo_unif"
66 let fo_unif_subst subst context metasenv t1 t2 ugraph =
69 CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
70 in profiler.HExtlib.profile foo ()
72 (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
73 | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
76 let enrich localization_tbl t ?(f = fun msg -> msg) exn =
79 RefineFailure msg -> RefineFailure (f msg)
80 | Uncertain msg -> Uncertain (f msg)
81 | _ -> assert false in
84 Cic.CicHash.find localization_tbl t
86 prerr_endline ("!!! NOT LOCALIZED: " ^ CicPp.ppterm t);
89 raise (HExtlib.Localized (loc,exn'))
91 let relocalize localization_tbl oldt newt =
93 let infos = Cic.CicHash.find localization_tbl oldt in
94 Cic.CicHash.remove localization_tbl oldt;
95 Cic.CicHash.add localization_tbl newt infos;
103 | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
104 | (_,_) -> raise (AssertFailure (lazy "split: list too short"))
107 let exp_impl metasenv subst context =
110 let (metasenv', idx) =
111 CicMkImplicit.mk_implicit_type metasenv subst context in
113 CicMkImplicit.identity_relocation_list_for_metavariable context in
114 metasenv', Cic.Meta (idx, irl)
116 let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst [] in
117 metasenv', Cic.Meta (idx, [])
119 let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst context in
121 CicMkImplicit.identity_relocation_list_for_metavariable context in
122 metasenv', Cic.Meta (idx, irl)
126 let is_a_double_coercion t =
128 let rec aux acc = function
130 | x::tl -> aux (acc@[x]) tl
135 let imp = Cic.Implicit None in
136 let dummyres = false,imp, imp,imp,imp in
138 | Cic.Appl (c1::tl) when CoercGraph.is_a_coercion c1 ->
139 (match last_of tl with
140 | sib1,Cic.Appl (c2::tl2) when CoercGraph.is_a_coercion c2 ->
141 let sib2,head = last_of tl2 in
142 true, c1, c2, head,Cic.Appl (c1::sib1@[Cic.Appl
143 (c2::sib2@[Cic.Implicit None])])
147 let more_args_than_expected subst he context hetype' tlbody_and_type =
149 CicMetaSubst.ppterm_in_context subst he context ^
150 " (that has type " ^ CicMetaSubst.ppterm_in_context subst hetype' context ^
151 ") is here applied to " ^ string_of_int (List.length tlbody_and_type) ^
152 " arguments that are more than expected")
155 let mk_prod_of_metas metasenv context' subst args =
156 let rec mk_prod metasenv context' = function
158 let (metasenv, idx) =
159 CicMkImplicit.mk_implicit_type metasenv subst context'
162 CicMkImplicit.identity_relocation_list_for_metavariable context'
164 metasenv,Cic.Meta (idx, irl)
166 let (metasenv, idx) =
167 CicMkImplicit.mk_implicit_type metasenv subst context'
170 CicMkImplicit.identity_relocation_list_for_metavariable context'
172 let meta = Cic.Meta (idx,irl) in
174 (* The name must be fresh for context. *)
175 (* Nevertheless, argty is well-typed only in context. *)
176 (* Thus I generate a name (name_hint) in context and *)
177 (* then I generate a name --- using the hint name_hint *)
178 (* --- that is fresh in context'. *)
180 (* Cic.Name "pippo" *)
181 FreshNamesGenerator.mk_fresh_name ~subst metasenv
182 (* (CicMetaSubst.apply_subst_metasenv subst metasenv) *)
183 (CicMetaSubst.apply_subst_context subst context')
185 ~typ:(CicMetaSubst.apply_subst subst argty)
187 (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
188 FreshNamesGenerator.mk_fresh_name ~subst
189 [] context' name_hint ~typ:(Cic.Sort Cic.Prop)
191 let metasenv,target =
192 mk_prod metasenv ((Some (name, Cic.Decl meta))::context') tl
194 metasenv,Cic.Prod (name,meta,target)
196 mk_prod metasenv context' args
199 let rec type_of_constant uri ugraph =
200 let module C = Cic in
201 let module R = CicReduction in
202 let module U = UriManager in
203 let _ = CicTypeChecker.typecheck uri in
206 CicEnvironment.get_cooked_obj ugraph uri
207 with Not_found -> assert false
210 C.Constant (_,_,ty,_,_) -> ty,u
211 | C.CurrentProof (_,_,_,ty,_,_) -> ty,u
215 (lazy ("Unknown constant definition " ^ U.string_of_uri uri)))
217 and type_of_variable uri ugraph =
218 let module C = Cic in
219 let module R = CicReduction in
220 let module U = UriManager in
221 let _ = CicTypeChecker.typecheck uri in
224 CicEnvironment.get_cooked_obj ugraph uri
225 with Not_found -> assert false
228 C.Variable (_,_,ty,_,_) -> ty,u
232 (lazy ("Unknown variable definition " ^ UriManager.string_of_uri uri)))
234 and type_of_mutual_inductive_defs uri i ugraph =
235 let module C = Cic in
236 let module R = CicReduction in
237 let module U = UriManager in
238 let _ = CicTypeChecker.typecheck uri in
241 CicEnvironment.get_cooked_obj ugraph uri
242 with Not_found -> assert false
245 C.InductiveDefinition (dl,_,_,_) ->
246 let (_,_,arity,_) = List.nth dl i in
251 (lazy ("Unknown mutual inductive definition " ^ U.string_of_uri uri)))
253 and type_of_mutual_inductive_constr uri i j ugraph =
254 let module C = Cic in
255 let module R = CicReduction in
256 let module U = UriManager in
257 let _ = CicTypeChecker.typecheck uri in
260 CicEnvironment.get_cooked_obj ugraph uri
261 with Not_found -> assert false
264 C.InductiveDefinition (dl,_,_,_) ->
265 let (_,_,_,cl) = List.nth dl i in
266 let (_,ty) = List.nth cl (j-1) in
272 ("Unkown mutual inductive definition " ^ U.string_of_uri uri)))
275 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
277 (* the check_branch function checks if a branch of a case is refinable.
278 It returns a pair (outype_instance,args), a subst and a metasenv.
279 outype_instance is the expected result of applying the case outtype
281 The problem is that outype is in general unknown, and we should
282 try to synthesize it from the above information, that is in general
283 a second order unification problem. *)
285 and check_branch n context metasenv subst left_args_no actualtype term expectedtype ugraph =
286 let module C = Cic in
287 (* let module R = CicMetaSubst in *)
288 let module R = CicReduction in
289 match R.whd ~subst context expectedtype with
291 (n,context,actualtype, [term]), subst, metasenv, ugraph
292 | C.Appl (C.MutInd (_,_,_)::tl) ->
293 let (_,arguments) = split tl left_args_no in
294 (n,context,actualtype, arguments@[term]), subst, metasenv, ugraph
295 | C.Prod (name,so,de) ->
296 (* we expect that the actual type of the branch has the due
298 (match R.whd ~subst context actualtype with
299 C.Prod (name',so',de') ->
300 let subst, metasenv, ugraph1 =
301 fo_unif_subst subst context metasenv so so' ugraph in
303 (match CicSubstitution.lift 1 term with
304 C.Appl l -> C.Appl (l@[C.Rel 1])
305 | t -> C.Appl [t ; C.Rel 1]) in
306 (* we should also check that the name variable is anonymous in
307 the actual type de' ?? *)
309 ((Some (name,(C.Decl so)))::context)
310 metasenv subst left_args_no de' term' de ugraph1
311 | _ -> raise (AssertFailure (lazy "Wrong number of arguments")))
312 | _ -> raise (AssertFailure (lazy "Prod or MutInd expected"))
314 and type_of_aux' ?(localization_tbl = Cic.CicHash.create 1) metasenv context t
317 let rec type_of_aux subst metasenv context t ugraph =
318 let try_coercion t subst metasenv context ugraph coercion_tgt c =
319 let coerced = Cic.Appl[c;t] in
321 let newt,_,subst,metasenv,ugraph =
322 type_of_aux subst metasenv context coerced ugraph
324 let newt, tty, subst, metasenv, ugraph =
325 avoid_double_coercion context subst metasenv ugraph newt coercion_tgt
327 Some (newt, tty, subst, metasenv, ugraph)
329 | RefineFailure _ | Uncertain _ -> None
331 let module C = Cic in
332 let module S = CicSubstitution in
333 let module U = UriManager in
334 let (t',_,_,_,_) as res =
339 match List.nth context (n - 1) with
340 Some (_,C.Decl ty) ->
341 t,S.lift n ty,subst,metasenv, ugraph
342 | Some (_,C.Def (_,Some ty)) ->
343 t,S.lift n ty,subst,metasenv, ugraph
344 | Some (_,C.Def (bo,None)) ->
346 (* if it is in the context it must be already well-typed*)
347 CicTypeChecker.type_of_aux' ~subst metasenv context
350 t,ty,subst,metasenv,ugraph
352 enrich localization_tbl t
353 (RefineFailure (lazy "Rel to hidden hypothesis"))
356 enrich localization_tbl t
357 (RefineFailure (lazy "Not a close term")))
358 | C.Var (uri,exp_named_subst) ->
359 let exp_named_subst',subst',metasenv',ugraph1 =
360 check_exp_named_subst
361 subst metasenv context exp_named_subst ugraph
363 let ty_uri,ugraph1 = type_of_variable uri ugraph in
365 CicSubstitution.subst_vars exp_named_subst' ty_uri
367 C.Var (uri,exp_named_subst'),ty,subst',metasenv',ugraph1
370 let (canonical_context, term,ty) =
371 CicUtil.lookup_subst n subst
373 let l',subst',metasenv',ugraph1 =
374 check_metasenv_consistency n subst metasenv context
375 canonical_context l ugraph
377 (* trust or check ??? *)
378 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
379 subst', metasenv', ugraph1
380 (* type_of_aux subst metasenv
381 context (CicSubstitution.subst_meta l term) *)
382 with CicUtil.Subst_not_found _ ->
383 let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
384 let l',subst',metasenv', ugraph1 =
385 check_metasenv_consistency n subst metasenv context
386 canonical_context l ugraph
388 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
389 subst', metasenv',ugraph1)
390 | C.Sort (C.Type tno) ->
391 let tno' = CicUniv.fresh() in
392 let ugraph1 = CicUniv.add_gt tno' tno ugraph in
393 t,(C.Sort (C.Type tno')),subst,metasenv,ugraph1
395 t,C.Sort (C.Type (CicUniv.fresh())),subst,metasenv,ugraph
396 | C.Implicit infos ->
397 let metasenv',t' = exp_impl metasenv subst context infos in
398 type_of_aux subst metasenv' context t' ugraph
400 let ty',_,subst',metasenv',ugraph1 =
401 type_of_aux subst metasenv context ty ugraph
403 let te',inferredty,subst'',metasenv'',ugraph2 =
404 type_of_aux subst' metasenv' context te ugraph1
407 let subst''',metasenv''',ugraph3 =
408 fo_unif_subst subst'' context metasenv''
409 inferredty ty' ugraph2
411 C.Cast (te',ty'),ty',subst''',metasenv''',ugraph3
414 enrich localization_tbl te'
417 CicMetaSubst.ppterm_in_context subst'' te'
418 context ^ " has type " ^
419 CicMetaSubst.ppterm_in_context subst'' inferredty
420 context ^ " but is here used with type " ^
421 CicMetaSubst.ppterm_in_context subst'' ty' context)) exn
423 | C.Prod (name,s,t) ->
424 let carr t subst context = CicMetaSubst.apply_subst subst t in
425 let coerce_to_sort in_source tgt_sort t type_to_coerce
426 subst context metasenv uragph
428 if not !insert_coercions then
429 t,type_to_coerce,subst,metasenv,ugraph
431 let coercion_src = carr type_to_coerce subst context in
432 match coercion_src with
434 t,type_to_coerce,subst,metasenv,ugraph
435 | Cic.Meta _ as meta ->
436 t, meta, subst, metasenv, ugraph
437 | Cic.Cast _ as cast ->
438 t, cast, subst, metasenv, ugraph
440 let coercion_tgt = carr (Cic.Sort tgt_sort) subst context in
442 CoercGraph.look_for_coercion coercion_src coercion_tgt
445 | CoercGraph.NoCoercion
446 | CoercGraph.NotHandled _ ->
447 enrich localization_tbl t
450 CicMetaSubst.ppterm_in_context subst t context ^
451 " is not a type since it has type " ^
452 CicMetaSubst.ppterm_in_context
453 subst coercion_src context ^ " that is not a sort")))
454 | CoercGraph.NotMetaClosed ->
455 enrich localization_tbl t
458 CicMetaSubst.ppterm_in_context subst t context ^
459 " is not a type since it has type " ^
460 CicMetaSubst.ppterm_in_context
461 subst coercion_src context ^ " that is not a sort")))
462 | CoercGraph.SomeCoercion candidates ->
466 t subst metasenv context ugraph coercion_tgt)
472 enrich localization_tbl t
475 CicMetaSubst.ppterm_in_context
477 " is not a type since it has type " ^
478 CicMetaSubst.ppterm_in_context
479 subst coercion_src context ^
480 " that is not a sort"))))
482 let s',sort1,subst',metasenv',ugraph1 =
483 type_of_aux subst metasenv context s ugraph
485 let s',sort1,subst', metasenv',ugraph1 =
486 coerce_to_sort true (Cic.Type(CicUniv.fresh()))
487 s' sort1 subst' context metasenv' ugraph1
489 let context_for_t = ((Some (name,(C.Decl s')))::context) in
490 let t',sort2,subst'',metasenv'',ugraph2 =
491 type_of_aux subst' metasenv'
492 context_for_t t ugraph1
494 let t',sort2,subst'',metasenv'',ugraph2 =
495 coerce_to_sort false (Cic.Type(CicUniv.fresh()))
496 t' sort2 subst'' context_for_t metasenv'' ugraph2
498 let sop,subst''',metasenv''',ugraph3 =
499 sort_of_prod subst'' metasenv''
500 context (name,s') (sort1,sort2) ugraph2
502 C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
503 | C.Lambda (n,s,t) ->
505 let s',sort1,subst',metasenv',ugraph1 =
506 type_of_aux subst metasenv context s ugraph in
507 let s',sort1,subst',metasenv',ugraph1 =
508 if not !insert_coercions then
509 s',sort1, subst', metasenv', ugraph1
511 match CicReduction.whd ~subst:subst' context sort1 with
512 | C.Meta _ | C.Sort _ -> s',sort1, subst', metasenv', ugraph1
514 let coercion_tgt = Cic.Sort (Cic.Type (CicUniv.fresh())) in
516 CoercGraph.look_for_coercion coercion_src coercion_tgt
519 | CoercGraph.NoCoercion
520 | CoercGraph.NotHandled _ ->
521 enrich localization_tbl s'
524 CicMetaSubst.ppterm_in_context subst s' context ^
525 " is not a type since it has type " ^
526 CicMetaSubst.ppterm_in_context
527 subst coercion_src context ^ " that is not a sort")))
528 | CoercGraph.NotMetaClosed ->
529 enrich localization_tbl s'
532 CicMetaSubst.ppterm_in_context subst s' context ^
533 " is not a type since it has type " ^
534 CicMetaSubst.ppterm_in_context
535 subst coercion_src context ^ " that is not a sort")))
536 | CoercGraph.SomeCoercion candidates ->
540 s' subst' metasenv' context ugraph1 coercion_tgt)
546 enrich localization_tbl s'
549 CicMetaSubst.ppterm_in_context subst s' context ^
550 " is not a type since it has type " ^
551 CicMetaSubst.ppterm_in_context
552 subst coercion_src context ^
553 " that is not a sort")))
555 let context_for_t = ((Some (n,(C.Decl s')))::context) in
556 let t',type2,subst'',metasenv'',ugraph2 =
557 type_of_aux subst' metasenv' context_for_t t ugraph1
559 C.Lambda (n,s',t'),C.Prod (n,s',type2),
560 subst'',metasenv'',ugraph2
562 (* only to check if s is well-typed *)
563 let s',ty,subst',metasenv',ugraph1 =
564 type_of_aux subst metasenv context s ugraph
566 let context_for_t = ((Some (n,(C.Def (s',Some ty))))::context) in
568 let t',inferredty,subst'',metasenv'',ugraph2 =
569 type_of_aux subst' metasenv'
570 context_for_t t ugraph1
572 (* One-step LetIn reduction.
573 * Even faster than the previous solution.
574 * Moreover the inferred type is closer to the expected one.
576 C.LetIn (n,s',t'),CicSubstitution.subst s' inferredty,
577 subst'',metasenv'',ugraph2
578 | C.Appl (he::((_::_) as tl)) ->
579 let he',hetype,subst',metasenv',ugraph1 =
580 type_of_aux subst metasenv context he ugraph
582 let tlbody_and_type,subst'',metasenv'',ugraph2 =
583 typeof_list subst' metasenv' context ugraph1 tl
585 let coerced_he,coerced_args,applty,subst''',metasenv''',ugraph3 =
586 eat_prods true subst'' metasenv'' context
587 he' hetype tlbody_and_type ugraph2
589 let newappl = (C.Appl (coerced_he::coerced_args)) in
590 avoid_double_coercion
591 context subst''' metasenv''' ugraph3 newappl applty
592 | C.Appl _ -> assert false
593 | C.Const (uri,exp_named_subst) ->
594 let exp_named_subst',subst',metasenv',ugraph1 =
595 check_exp_named_subst subst metasenv context
596 exp_named_subst ugraph in
597 let ty_uri,ugraph2 = type_of_constant uri ugraph1 in
599 CicSubstitution.subst_vars exp_named_subst' ty_uri
601 C.Const (uri,exp_named_subst'),cty,subst',metasenv',ugraph2
602 | C.MutInd (uri,i,exp_named_subst) ->
603 let exp_named_subst',subst',metasenv',ugraph1 =
604 check_exp_named_subst subst metasenv context
605 exp_named_subst ugraph
607 let ty_uri,ugraph2 = type_of_mutual_inductive_defs uri i ugraph1 in
609 CicSubstitution.subst_vars exp_named_subst' ty_uri in
610 C.MutInd (uri,i,exp_named_subst'),cty,subst',metasenv',ugraph2
611 | C.MutConstruct (uri,i,j,exp_named_subst) ->
612 let exp_named_subst',subst',metasenv',ugraph1 =
613 check_exp_named_subst subst metasenv context
614 exp_named_subst ugraph
617 type_of_mutual_inductive_constr uri i j ugraph1
620 CicSubstitution.subst_vars exp_named_subst' ty_uri
622 C.MutConstruct (uri,i,j,exp_named_subst'),cty,subst',
624 | C.MutCase (uri, i, outtype, term, pl) ->
625 (* first, get the inductive type (and noparams)
626 * in the environment *)
627 let (_,b,arity,constructors), expl_params, no_left_params,ugraph =
628 let _ = CicTypeChecker.typecheck uri in
629 let obj,u = CicEnvironment.get_cooked_obj ugraph uri in
631 C.InductiveDefinition (l,expl_params,parsno,_) ->
632 List.nth l i , expl_params, parsno, u
634 enrich localization_tbl t
636 (lazy ("Unkown mutual inductive definition " ^
637 U.string_of_uri uri)))
639 let rec count_prod t =
640 match CicReduction.whd ~subst context t with
641 C.Prod (_, _, t) -> 1 + (count_prod t)
644 let no_args = count_prod arity in
645 (* now, create a "generic" MutInd *)
646 let metasenv,left_args =
647 CicMkImplicit.n_fresh_metas metasenv subst context no_left_params
649 let metasenv,right_args =
650 let no_right_params = no_args - no_left_params in
651 if no_right_params < 0 then assert false
652 else CicMkImplicit.n_fresh_metas
653 metasenv subst context no_right_params
655 let metasenv,exp_named_subst =
656 CicMkImplicit.fresh_subst metasenv subst context expl_params in
659 C.MutInd (uri,i,exp_named_subst)
662 (C.MutInd (uri,i,exp_named_subst)::(left_args @ right_args))
664 (* check consistency with the actual type of term *)
665 let term',actual_type,subst,metasenv,ugraph1 =
666 type_of_aux subst metasenv context term ugraph in
667 let expected_type',_, subst, metasenv,ugraph2 =
668 type_of_aux subst metasenv context expected_type ugraph1
670 let actual_type = CicReduction.whd ~subst context actual_type in
671 let subst,metasenv,ugraph3 =
673 fo_unif_subst subst context metasenv
674 expected_type' actual_type ugraph2
677 enrich localization_tbl term' exn
680 CicMetaSubst.ppterm_in_context subst term'
681 context ^ " has type " ^
682 CicMetaSubst.ppterm_in_context subst actual_type
683 context ^ " but is here used with type " ^
684 CicMetaSubst.ppterm_in_context subst expected_type' context))
686 let rec instantiate_prod t =
690 match CicReduction.whd ~subst context t with
692 instantiate_prod (CicSubstitution.subst he t') tl
695 let arity_instantiated_with_left_args =
696 instantiate_prod arity left_args in
697 (* TODO: check if the sort elimination
698 * is allowed: [(I q1 ... qr)|B] *)
699 let (pl',_,outtypeinstances,subst,metasenv,ugraph4) =
701 (fun (pl,j,outtypeinstances,subst,metasenv,ugraph) p ->
703 if left_args = [] then
704 (C.MutConstruct (uri,i,j,exp_named_subst))
707 (C.MutConstruct (uri,i,j,exp_named_subst)::left_args))
709 let p',actual_type,subst,metasenv,ugraph1 =
710 type_of_aux subst metasenv context p ugraph
712 let constructor',expected_type, subst, metasenv,ugraph2 =
713 type_of_aux subst metasenv context constructor ugraph1
715 let outtypeinstance,subst,metasenv,ugraph3 =
716 check_branch 0 context metasenv subst no_left_params
717 actual_type constructor' expected_type ugraph2
720 outtypeinstance::outtypeinstances,subst,metasenv,ugraph3))
721 ([],1,[],subst,metasenv,ugraph3) pl
724 (* we are left to check that the outype matches his instances.
725 The easy case is when the outype is specified, that amount
726 to a trivial check. Otherwise, we should guess a type from
730 let outtype,outtypety, subst, metasenv,ugraph4 =
731 type_of_aux subst metasenv context outtype ugraph4 in
734 (let candidate,ugraph5,metasenv,subst =
735 let exp_name_subst, metasenv =
737 CicEnvironment.get_cooked_obj CicUniv.empty_ugraph uri
739 let uris = CicUtil.params_of_obj o in
741 fun uri (acc,metasenv) ->
742 let metasenv',new_meta =
743 CicMkImplicit.mk_implicit metasenv subst context
746 CicMkImplicit.identity_relocation_list_for_metavariable
749 (uri, Cic.Meta(new_meta,irl))::acc, metasenv'
753 match left_args,right_args with
754 [],[] -> Cic.MutInd(uri, i, exp_name_subst)
756 let rec mk_right_args =
759 | n -> (Cic.Rel n)::(mk_right_args (n - 1))
761 let right_args_no = List.length right_args in
762 let lifted_left_args =
763 List.map (CicSubstitution.lift right_args_no) left_args
765 Cic.Appl (Cic.MutInd(uri,i,exp_name_subst)::
766 (lifted_left_args @ mk_right_args right_args_no))
769 FreshNamesGenerator.mk_fresh_name ~subst metasenv
770 context Cic.Anonymous ~typ:ty
772 match outtypeinstances with
774 let extended_context =
775 let rec add_right_args =
777 Cic.Prod (name,ty,t) ->
778 Some (name,Cic.Decl ty)::(add_right_args t)
781 (Some (fresh_name,Cic.Decl ty))::
783 (add_right_args arity_instantiated_with_left_args))@
786 let metasenv,new_meta =
787 CicMkImplicit.mk_implicit metasenv subst extended_context
790 CicMkImplicit.identity_relocation_list_for_metavariable
793 let rec add_lambdas b =
795 Cic.Prod (name,ty,t) ->
796 Cic.Lambda (name,ty,(add_lambdas b t))
797 | _ -> Cic.Lambda (fresh_name, ty, b)
800 add_lambdas (Cic.Meta (new_meta,irl))
801 arity_instantiated_with_left_args
803 (Some candidate),ugraph4,metasenv,subst
804 | (constructor_args_no,_,instance,_)::tl ->
806 let instance',subst,metasenv =
807 CicMetaSubst.delift_rels subst metasenv
808 constructor_args_no instance
810 let candidate,ugraph,metasenv,subst =
812 fun (candidate_oty,ugraph,metasenv,subst)
813 (constructor_args_no,_,instance,_) ->
814 match candidate_oty with
815 | None -> None,ugraph,metasenv,subst
818 let instance',subst,metasenv =
819 CicMetaSubst.delift_rels subst metasenv
820 constructor_args_no instance
822 let subst,metasenv,ugraph =
823 fo_unif_subst subst context metasenv
826 candidate_oty,ugraph,metasenv,subst
828 CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable
829 | CicUnification.UnificationFailure _
830 | CicUnification.Uncertain _ ->
831 None,ugraph,metasenv,subst
832 ) (Some instance',ugraph4,metasenv,subst) tl
835 | None -> None, ugraph,metasenv,subst
837 let rec add_lambdas n b =
839 Cic.Prod (name,ty,t) ->
840 Cic.Lambda (name,ty,(add_lambdas (n + 1) b t))
842 Cic.Lambda (fresh_name, ty,
843 CicSubstitution.lift (n + 1) t)
846 (add_lambdas 0 t arity_instantiated_with_left_args),
847 ugraph,metasenv,subst
848 with CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
849 None,ugraph4,metasenv,subst
852 | None -> raise (Uncertain (lazy "can't solve an higher order unification problem"))
854 let subst,metasenv,ugraph =
856 fo_unif_subst subst context metasenv
857 candidate outtype ugraph5
859 exn -> assert false(* unification against a metavariable *)
861 C.MutCase (uri, i, outtype, term', pl'),
862 CicReduction.head_beta_reduce
863 (CicMetaSubst.apply_subst subst
864 (Cic.Appl (outtype::right_args@[term']))),
865 subst,metasenv,ugraph)
866 | _ -> (* easy case *)
867 let tlbody_and_type,subst,metasenv,ugraph4 =
868 typeof_list subst metasenv context ugraph4 (right_args @ [term'])
870 let _,_,_,subst,metasenv,ugraph4 =
871 eat_prods false subst metasenv context
872 outtype outtypety tlbody_and_type ugraph4
874 let _,_, subst, metasenv,ugraph5 =
875 type_of_aux subst metasenv context
876 (C.Appl ((outtype :: right_args) @ [term'])) ugraph4
878 let (subst,metasenv,ugraph6) =
880 (fun (subst,metasenv,ugraph)
881 p (constructor_args_no,context,instance,args)
886 CicSubstitution.lift constructor_args_no outtype
888 C.Appl (outtype'::args)
890 CicReduction.whd ~subst context appl
893 fo_unif_subst subst context metasenv instance instance'
897 enrich localization_tbl p exn
900 CicMetaSubst.ppterm_in_context subst p
901 context ^ " has type " ^
902 CicMetaSubst.ppterm_in_context subst instance'
903 context ^ " but is here used with type " ^
904 CicMetaSubst.ppterm_in_context subst instance
906 (subst,metasenv,ugraph5) pl' outtypeinstances
908 C.MutCase (uri, i, outtype, term', pl'),
909 CicReduction.head_beta_reduce
910 (CicMetaSubst.apply_subst subst
911 (C.Appl(outtype::right_args@[term]))),
912 subst,metasenv,ugraph6)
914 let fl_ty',subst,metasenv,types,ugraph1 =
916 (fun (fl,subst,metasenv,types,ugraph) (n,_,ty,_) ->
917 let ty',_,subst',metasenv',ugraph1 =
918 type_of_aux subst metasenv context ty ugraph
920 fl @ [ty'],subst',metasenv',
921 Some (C.Name n,(C.Decl ty')) :: types, ugraph
922 ) ([],subst,metasenv,[],ugraph) fl
924 let len = List.length types in
925 let context' = types@context in
926 let fl_bo',subst,metasenv,ugraph2 =
928 (fun (fl,subst,metasenv,ugraph) ((name,x,_,bo),ty) ->
929 let bo',ty_of_bo,subst,metasenv,ugraph1 =
930 type_of_aux subst metasenv context' bo ugraph in
931 let expected_ty = CicSubstitution.lift len ty in
932 let subst',metasenv',ugraph' =
934 fo_unif_subst subst context' metasenv
935 ty_of_bo expected_ty ugraph1
938 enrich localization_tbl bo exn
941 CicMetaSubst.ppterm_in_context subst bo
942 context' ^ " has type " ^
943 CicMetaSubst.ppterm_in_context subst ty_of_bo
944 context' ^ " but is here used with type " ^
945 CicMetaSubst.ppterm_in_context subst expected_ty
948 fl @ [bo'] , subst',metasenv',ugraph'
949 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
951 let ty = List.nth fl_ty' i in
952 (* now we have the new ty in fl_ty', the new bo in fl_bo',
953 * and we want the new fl with bo' and ty' injected in the right
956 let rec map3 f l1 l2 l3 =
959 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
962 let fl'' = map3 (fun ty' bo' (name,x,ty,bo) -> (name,x,ty',bo') )
965 C.Fix (i,fl''),ty,subst,metasenv,ugraph2
967 let fl_ty',subst,metasenv,types,ugraph1 =
969 (fun (fl,subst,metasenv,types,ugraph) (n,ty,_) ->
970 let ty',_,subst',metasenv',ugraph1 =
971 type_of_aux subst metasenv context ty ugraph
973 fl @ [ty'],subst',metasenv',
974 Some (C.Name n,(C.Decl ty')) :: types, ugraph1
975 ) ([],subst,metasenv,[],ugraph) fl
977 let len = List.length types in
978 let context' = types@context in
979 let fl_bo',subst,metasenv,ugraph2 =
981 (fun (fl,subst,metasenv,ugraph) ((name,_,bo),ty) ->
982 let bo',ty_of_bo,subst,metasenv,ugraph1 =
983 type_of_aux subst metasenv context' bo ugraph in
984 let expected_ty = CicSubstitution.lift len ty in
985 let subst',metasenv',ugraph' =
987 fo_unif_subst subst context' metasenv
988 ty_of_bo expected_ty ugraph1
991 enrich localization_tbl bo exn
994 CicMetaSubst.ppterm_in_context subst bo
995 context' ^ " has type " ^
996 CicMetaSubst.ppterm_in_context subst ty_of_bo
997 context' ^ " but is here used with type " ^
998 CicMetaSubst.ppterm_in_context subst expected_ty
1001 fl @ [bo'],subst',metasenv',ugraph'
1002 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
1004 let ty = List.nth fl_ty' i in
1005 (* now we have the new ty in fl_ty', the new bo in fl_bo',
1006 * and we want the new fl with bo' and ty' injected in the right
1009 let rec map3 f l1 l2 l3 =
1012 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
1015 let fl'' = map3 (fun ty' bo' (name,ty,bo) -> (name,ty',bo') )
1018 C.CoFix (i,fl''),ty,subst,metasenv,ugraph2
1020 relocalize localization_tbl t t';
1023 (* check_metasenv_consistency checks that the "canonical" context of a
1024 metavariable is consitent - up to relocation via the relocation list l -
1025 with the actual context *)
1026 and check_metasenv_consistency
1027 metano subst metasenv context canonical_context l ugraph
1029 let module C = Cic in
1030 let module R = CicReduction in
1031 let module S = CicSubstitution in
1032 let lifted_canonical_context =
1036 | (Some (n,C.Decl t))::tl ->
1037 (Some (n,C.Decl (S.subst_meta l (S.lift i t))))::(aux (i+1) tl)
1038 | (Some (n,C.Def (t,None)))::tl ->
1039 (Some (n,C.Def ((S.subst_meta l (S.lift i t)),None)))::(aux (i+1) tl)
1040 | None::tl -> None::(aux (i+1) tl)
1041 | (Some (n,C.Def (t,Some ty)))::tl ->
1043 C.Def ((S.subst_meta l (S.lift i t)),
1044 Some (S.subst_meta l (S.lift i ty))))) :: (aux (i+1) tl)
1046 aux 1 canonical_context
1050 (fun (l,subst,metasenv,ugraph) t ct ->
1053 l @ [None],subst,metasenv,ugraph
1054 | Some t,Some (_,C.Def (ct,_)) ->
1055 let subst',metasenv',ugraph' =
1057 fo_unif_subst subst context metasenv t ct ugraph
1058 with e -> raise (RefineFailure (lazy (sprintf "The local context is not consistent with the canonical context, since %s cannot be unified with %s. Reason: %s" (CicMetaSubst.ppterm subst t) (CicMetaSubst.ppterm subst ct) (match e with AssertFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
1060 l @ [Some t],subst',metasenv',ugraph'
1061 | Some t,Some (_,C.Decl ct) ->
1062 let t',inferredty,subst',metasenv',ugraph1 =
1063 type_of_aux subst metasenv context t ugraph
1065 let subst'',metasenv'',ugraph2 =
1068 subst' context metasenv' inferredty ct ugraph1
1069 with e -> raise (RefineFailure (lazy (sprintf "The local context is not consistent with the canonical context, since the type %s of %s cannot be unified with the expected type %s. Reason: %s" (CicMetaSubst.ppterm subst' inferredty) (CicMetaSubst.ppterm subst' t) (CicMetaSubst.ppterm subst' ct) (match e with AssertFailure msg -> Lazy.force msg | RefineFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
1071 l @ [Some t'], subst'',metasenv'',ugraph2
1073 raise (RefineFailure (lazy (sprintf "Not well typed metavariable instance %s: the local context does not instantiate an hypothesis even if the hypothesis is not restricted in the canonical context %s" (CicMetaSubst.ppterm subst (Cic.Meta (metano, l))) (CicMetaSubst.ppcontext subst canonical_context))))) ([],subst,metasenv,ugraph) l lifted_canonical_context
1075 Invalid_argument _ ->
1079 "Not well typed metavariable instance %s: the length of the local context does not match the length of the canonical context %s"
1080 (CicMetaSubst.ppterm subst (Cic.Meta (metano, l)))
1081 (CicMetaSubst.ppcontext subst canonical_context))))
1083 and check_exp_named_subst metasubst metasenv context tl ugraph =
1084 let rec check_exp_named_subst_aux metasubst metasenv substs tl ugraph =
1086 [] -> [],metasubst,metasenv,ugraph
1088 let ty_uri,ugraph1 = type_of_variable uri ugraph in
1090 CicSubstitution.subst_vars substs ty_uri in
1091 (* CSC: why was this code here? it is wrong
1092 (match CicEnvironment.get_cooked_obj ~trust:false uri with
1093 Cic.Variable (_,Some bo,_,_) ->
1095 (RefineFailure (lazy
1096 "A variable with a body can not be explicit substituted"))
1097 | Cic.Variable (_,None,_,_) -> ()
1100 (RefineFailure (lazy
1101 ("Unkown variable definition " ^ UriManager.string_of_uri uri)))
1104 let t',typeoft,metasubst',metasenv',ugraph2 =
1105 type_of_aux metasubst metasenv context t ugraph1 in
1106 let subst = uri,t' in
1107 let metasubst'',metasenv'',ugraph3 =
1110 metasubst' context metasenv' typeoft typeofvar ugraph2
1112 raise (RefineFailure (lazy
1113 ("Wrong Explicit Named Substitution: " ^
1114 CicMetaSubst.ppterm metasubst' typeoft ^
1115 " not unifiable with " ^
1116 CicMetaSubst.ppterm metasubst' typeofvar)))
1118 (* FIXME: no mere tail recursive! *)
1119 let exp_name_subst, metasubst''', metasenv''', ugraph4 =
1120 check_exp_named_subst_aux
1121 metasubst'' metasenv'' (substs@[subst]) tl ugraph3
1123 ((uri,t')::exp_name_subst), metasubst''', metasenv''', ugraph4
1125 check_exp_named_subst_aux metasubst metasenv [] tl ugraph
1128 and sort_of_prod subst metasenv context (name,s) (t1, t2) ugraph =
1129 let module C = Cic in
1130 let context_for_t2 = (Some (name,C.Decl s))::context in
1131 let t1'' = CicReduction.whd ~subst context t1 in
1132 let t2'' = CicReduction.whd ~subst context_for_t2 t2 in
1133 match (t1'', t2'') with
1134 (C.Sort s1, C.Sort s2)
1135 when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) ->
1136 (* different than Coq manual!!! *)
1137 C.Sort s2,subst,metasenv,ugraph
1138 | (C.Sort (C.Type t1), C.Sort (C.Type t2)) ->
1139 let t' = CicUniv.fresh() in
1140 let ugraph1 = CicUniv.add_ge t' t1 ugraph in
1141 let ugraph2 = CicUniv.add_ge t' t2 ugraph1 in
1142 C.Sort (C.Type t'),subst,metasenv,ugraph2
1143 | (C.Sort _,C.Sort (C.Type t1)) ->
1144 C.Sort (C.Type t1),subst,metasenv,ugraph
1145 | (C.Meta _, C.Sort _) -> t2'',subst,metasenv,ugraph
1146 | (C.Sort _,C.Meta _) | (C.Meta _,C.Meta _) ->
1147 (* TODO how can we force the meta to become a sort? If we don't we
1148 * break the invariant that refine produce only well typed terms *)
1149 (* TODO if we check the non meta term and if it is a sort then we
1150 * are likely to know the exact value of the result e.g. if the rhs
1151 * is a Sort (Prop | Set | CProp) then the result is the rhs *)
1152 let (metasenv,idx) =
1153 CicMkImplicit.mk_implicit_sort metasenv subst in
1154 let (subst, metasenv,ugraph1) =
1156 fo_unif_subst subst context_for_t2 metasenv
1157 (C.Meta (idx,[])) t2'' ugraph
1158 with _ -> assert false (* unification against a metavariable *)
1160 t2'',subst,metasenv,ugraph1
1166 ("Two sorts were expected, found %s " ^^
1167 "(that reduces to %s) and %s (that reduces to %s)")
1168 (CicPp.ppterm t1) (CicPp.ppterm t1'') (CicPp.ppterm t2)
1169 (CicPp.ppterm t2''))))
1171 and avoid_double_coercion context subst metasenv ugraph t ty =
1172 let b, c1, c2, head, c1_c2_implicit = is_a_double_coercion t in
1174 let source_carr = CoercGraph.source_of c2 in
1175 let tgt_carr = CicMetaSubst.apply_subst subst ty in
1176 (match CoercGraph.look_for_coercion source_carr tgt_carr
1178 | CoercGraph.SomeCoercion candidates ->
1180 HExtlib.list_findopt
1182 | c when not (CoercGraph.is_composite c) ->
1183 debug_print (lazy ("\nNot a composite.."^CicPp.ppterm c));
1188 | Cic.Appl l -> Cic.Appl (l @ [head])
1189 | _ -> Cic.Appl [c;head]
1191 debug_print (lazy ("\nprovo" ^ CicPp.ppterm newt));
1196 CicPp.ppterm t ^ " ==> " ^ CicPp.ppterm newt));
1197 let newt,_,subst,metasenv,ugraph =
1198 type_of_aux subst metasenv context newt ugraph in
1199 debug_print (lazy "tipa...");
1200 let subst, metasenv, ugraph =
1201 (* COME MAI C'ERA UN IF su !pack_coercions ??? *)
1202 fo_unif_subst subst context metasenv newt t ugraph
1204 debug_print (lazy "unifica...");
1205 Some (newt, ty, subst, metasenv, ugraph)
1207 | RefineFailure s | Uncertain s when not !pack_coercions->
1208 debug_print s; debug_print (lazy "stop\n");None
1209 | RefineFailure s | Uncertain s ->
1210 debug_print s;debug_print (lazy "goon\n");
1212 pack_coercions := false; (* to avoid diverging *)
1213 let refined_c1_c2_implicit,ty,subst,metasenv,ugraph =
1214 type_of_aux subst metasenv context c1_c2_implicit ugraph
1216 pack_coercions := true;
1218 is_a_double_coercion refined_c1_c2_implicit
1224 match refined_c1_c2_implicit with
1225 | Cic.Appl l -> HExtlib.list_last l
1228 let subst, metasenv, ugraph =
1229 try fo_unif_subst subst context metasenv
1231 with RefineFailure s| Uncertain s->
1232 debug_print s;assert false
1234 let subst, metasenv, ugraph =
1235 fo_unif_subst subst context metasenv
1236 refined_c1_c2_implicit t ugraph
1238 Some (refined_c1_c2_implicit,ty,subst,metasenv,ugraph)
1240 | RefineFailure s | Uncertain s ->
1241 pack_coercions := true;debug_print s;None
1242 | exn -> pack_coercions := true; raise exn))
1245 (match selected with
1249 (lazy ("#### Coercion not packed: " ^ CicPp.ppterm t));
1250 t, ty, subst, metasenv, ugraph)
1251 | _ -> assert false) (* the composite coercion must exist *)
1253 t, ty, subst, metasenv, ugraph
1255 and typeof_list subst metasenv context ugraph l =
1256 let tlbody_and_type,subst,metasenv,ugraph =
1258 (fun x (res,subst,metasenv,ugraph) ->
1259 let x',ty,subst',metasenv',ugraph1 =
1260 type_of_aux subst metasenv context x ugraph
1262 (x', ty)::res,subst',metasenv',ugraph1
1263 ) l ([],subst,metasenv,ugraph)
1265 tlbody_and_type,subst,metasenv,ugraph
1268 allow_coercions subst metasenv context he hetype args_bo_and_ty ugraph
1270 (* aux function to add coercions to funclass *)
1271 let rec fix_arity metasenv context subst he hetype args_bo_and_ty ugraph =
1273 let pristinemenv = metasenv in
1274 let metasenv,hetype' =
1275 mk_prod_of_metas metasenv context subst args_bo_and_ty
1278 let subst,metasenv,ugraph =
1279 fo_unif_subst_eat_prods
1280 subst context metasenv hetype hetype' ugraph
1282 subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1283 with RefineFailure s | Uncertain s as exn
1284 when allow_coercions && !insert_coercions ->
1285 (* {{{ we search a coercion of the head (saturated) to funclass *)
1286 let metasenv = pristinemenv in
1288 ("Fixing arity of: "^CicMetaSubst.ppterm subst hetype ^
1289 " since unif failed with: " ^ CicMetaSubst.ppterm subst hetype' ^
1290 " cause: " ^ Lazy.force s));
1291 let how_many_args_are_needed =
1292 let rec aux n = function
1293 | Cic.Prod(_,_,t) -> aux (n+1) t
1296 aux 0 (CicMetaSubst.apply_subst subst hetype)
1298 let args, remainder =
1299 HExtlib.split_nth how_many_args_are_needed args_bo_and_ty
1301 let args = List.map fst args in
1305 | Cic.Appl l -> Cic.Appl (l@args)
1306 | _ -> Cic.Appl (he::args)
1310 let x,xty,subst,metasenv,ugraph =
1311 type_of_aux subst metasenv context x ugraph
1314 CoercDb.coerc_carr_of_term (CicMetaSubst.apply_subst subst xty)
1316 let carr_tgt = CoercDb.Fun 0 in
1317 match CoercGraph.look_for_coercion' carr_src carr_tgt with
1318 | CoercGraph.NoCoercion
1319 | CoercGraph.NotMetaClosed
1320 | CoercGraph.NotHandled _ -> raise exn
1321 | CoercGraph.SomeCoercion candidates ->
1323 HExtlib.list_findopt
1325 let t = Cic.Appl [coerc;x] in
1326 debug_print (lazy ("Tentative " ^ CicMetaSubst.ppterm subst t));
1328 (* we want this to be available in the error handler fo the
1329 * following (so it has its own try. *)
1330 let t,tty,subst,metasenv,ugraph =
1331 type_of_aux subst metasenv context t ugraph
1334 let metasenv, hetype' =
1335 mk_prod_of_metas metasenv context subst remainder
1338 (" unif: " ^ CicMetaSubst.ppterm subst tty ^ " = " ^
1339 CicMetaSubst.ppterm subst hetype'));
1340 let subst,metasenv,ugraph =
1341 fo_unif_subst_eat_prods
1342 subst context metasenv tty hetype' ugraph
1344 debug_print (lazy " success!");
1345 Some (subst,metasenv,ugraph,tty,t,remainder)
1347 | Uncertain _ | RefineFailure _
1348 | CicUnification.UnificationFailure _
1349 | CicUnification.Uncertain _ ->
1351 let subst,metasenv,ugraph,hetype',he,args_bo_and_ty =
1353 metasenv context subst t tty remainder ugraph
1355 Some (subst,metasenv,ugraph,hetype',he,args_bo_and_ty)
1360 | Some(subst,metasenv,ugraph,hetype',he,args_bo_and_ty)->
1361 subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1363 enrich localization_tbl he
1364 ~f:(fun _-> more_args_than_expected subst he context hetype
1366 (* }}} end coercion to funclass stuff *)
1367 (* }}} end fix_arity *)
1369 (* aux function to process the type of the head and the args in parallel *)
1370 let rec eat_prods_and_args
1371 pristinemenv metasenv subst context he hetype ugraph newargs
1375 | [] -> newargs,subst,metasenv,he,hetype,ugraph
1376 | (hete, hety)::tl ->
1377 match (CicReduction.whd ~subst context hetype) with
1378 | Cic.Prod (n,s,t) ->
1379 let arg,subst,metasenv,ugraph1 =
1381 let subst,metasenv,ugraph1 =
1382 fo_unif_subst_eat_prods2
1383 subst context metasenv hety s ugraph
1385 (hete,hety),subst,metasenv,ugraph1
1386 (* {{{ we search a coercion from hety to s if fails *)
1387 with RefineFailure _ | Uncertain _ as exn
1388 when allow_coercions && !insert_coercions ->
1389 let coer, tgt_carr =
1390 let carr t subst context =
1391 CicReduction.whd ~delta:false
1392 context (CicMetaSubst.apply_subst subst t )
1394 let c_hety = carr hety subst context in
1395 let c_s = carr s subst context in
1396 CoercGraph.look_for_coercion c_hety c_s, c_s
1399 | CoercGraph.NoCoercion
1400 | CoercGraph.NotHandled _ ->
1401 enrich localization_tbl hete
1403 (lazy ("The term " ^
1404 CicMetaSubst.ppterm_in_context subst hete
1405 context ^ " has type " ^
1406 CicMetaSubst.ppterm_in_context subst hety
1407 context ^ " but is here used with type " ^
1408 CicMetaSubst.ppterm_in_context subst s context
1409 (* "\nReason: " ^ Lazy.force e*))))
1410 | CoercGraph.NotMetaClosed ->
1411 enrich localization_tbl hete
1413 (lazy ("The term " ^
1414 CicMetaSubst.ppterm_in_context subst hete
1415 context ^ " has type " ^
1416 CicMetaSubst.ppterm_in_context subst hety
1417 context ^ " but is here used with type " ^
1418 CicMetaSubst.ppterm_in_context subst s context
1419 (* "\nReason: " ^ Lazy.force e*))))
1420 | CoercGraph.SomeCoercion candidates ->
1422 HExtlib.list_findopt
1425 let t = Cic.Appl[c;hete] in
1426 let newt,newhety,subst,metasenv,ugraph =
1427 type_of_aux subst metasenv context
1430 let newt, newty, subst, metasenv, ugraph =
1431 avoid_double_coercion context subst metasenv
1432 ugraph newt tgt_carr
1434 let subst,metasenv,ugraph1 =
1435 fo_unif_subst subst context metasenv
1438 Some ((newt,newty), subst, metasenv, ugraph)
1439 with Uncertain _ | RefineFailure _ -> None)
1442 (match selected with
1445 enrich localization_tbl hete
1447 (lazy ("The term " ^
1448 CicMetaSubst.ppterm_in_context subst hete
1449 context ^ " has type " ^
1450 CicMetaSubst.ppterm_in_context subst hety
1451 context ^ " but is here used with type " ^
1452 CicMetaSubst.ppterm_in_context subst s context
1453 (* "\nReason: " ^ Lazy.force e*)))) exn))
1455 enrich localization_tbl hete
1457 (lazy ("The term " ^
1458 CicMetaSubst.ppterm_in_context subst hete
1459 context ^ " has type " ^
1460 CicMetaSubst.ppterm_in_context subst hety
1461 context ^ " but is here used with type " ^
1462 CicMetaSubst.ppterm_in_context subst s context ^
1463 "\nReason: " ^ Printexc.to_string exn))) exn
1464 (* }}} end coercion stuff *)
1466 eat_prods_and_args pristinemenv metasenv subst context he
1467 (CicSubstitution.subst (fst arg) t)
1468 ugraph1 (newargs@[arg]) tl
1471 let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1473 pristinemenv context subst he hetype
1474 (newargs@[hete,hety]@tl) ugraph
1476 eat_prods_and_args metasenv
1477 metasenv subst context he hetype' ugraph [] args_bo_and_ty
1478 with RefineFailure s | Uncertain s ->
1479 (* unable to fix arity *)
1481 more_args_than_expected
1482 subst he context hetype args_bo_and_ty
1484 raise (RefineFailure msg)
1487 (* first we check if we are in the simple case of a meta closed term *)
1488 let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1489 if CicUtil.is_meta_closed hetype then
1490 (* this optimization is to postpone fix_arity (the most common case)*)
1491 subst,metasenv,ugraph,hetype,he,args_bo_and_ty
1493 (* this (says CSC) is also useful to infer dependent types *)
1494 fix_arity metasenv context subst he hetype args_bo_and_ty ugraph
1496 let coerced_args,subst,metasenv,he,t,ugraph =
1498 metasenv metasenv subst context he hetype' ugraph1 [] args_bo_and_ty
1500 he,(List.map fst coerced_args),t,subst,metasenv,ugraph
1503 (* eat prods ends here! *)
1505 let t',ty,subst',metasenv',ugraph1 =
1506 type_of_aux [] metasenv context t ugraph
1508 let substituted_t = CicMetaSubst.apply_subst subst' t' in
1509 let substituted_ty = CicMetaSubst.apply_subst subst' ty in
1510 (* Andrea: ho rimesso qui l'applicazione della subst al
1511 metasenv dopo che ho droppato l'invariante che il metsaenv
1512 e' sempre istanziato *)
1513 let substituted_metasenv =
1514 CicMetaSubst.apply_subst_metasenv subst' metasenv' in
1516 (* substituted_t,substituted_ty,substituted_metasenv *)
1517 (* ANDREA: spostare tutta questa robaccia da un altra parte *)
1519 FreshNamesGenerator.clean_dummy_dependent_types substituted_t in
1521 FreshNamesGenerator.clean_dummy_dependent_types substituted_ty in
1522 let cleaned_metasenv =
1524 (function (n,context,ty) ->
1525 let ty' = FreshNamesGenerator.clean_dummy_dependent_types ty in
1530 | Some (n, Cic.Decl t) ->
1532 Cic.Decl (FreshNamesGenerator.clean_dummy_dependent_types t))
1533 | Some (n, Cic.Def (bo,ty)) ->
1534 let bo' = FreshNamesGenerator.clean_dummy_dependent_types bo in
1539 Some (FreshNamesGenerator.clean_dummy_dependent_types ty)
1541 Some (n, Cic.Def (bo',ty'))
1545 ) substituted_metasenv
1547 (cleaned_t,cleaned_ty,cleaned_metasenv,ugraph1)
1550 let undebrujin uri typesno tys t =
1553 (fun (name,_,_,_) (i,t) ->
1554 (* here the explicit_named_substituion is assumed to be *)
1556 let t' = Cic.MutInd (uri,i,[]) in
1557 let t = CicSubstitution.subst t' t in
1559 ) tys (typesno - 1,t))
1561 let map_first_n n start f g l =
1562 let rec aux acc k l =
1565 | [] -> raise (Invalid_argument "map_first_n")
1566 | hd :: tl -> f hd k (aux acc (k+1) tl)
1572 (*CSC: this is a very rough approximation; to be finished *)
1573 let are_all_occurrences_positive metasenv ugraph uri tys leftno =
1574 let subst,metasenv,ugraph,tys =
1576 (fun (name,ind,arity,cl) (subst,metasenv,ugraph,acc) ->
1577 let subst,metasenv,ugraph,cl =
1579 (fun (name,ty) (subst,metasenv,ugraph,acc) ->
1580 let rec aux ctx k subst = function
1581 | Cic.Appl((Cic.MutInd (uri',_,_)as hd)::tl) when uri = uri'->
1582 let subst,metasenv,ugraph,tl =
1584 (subst,metasenv,ugraph,[])
1585 (fun t n (subst,metasenv,ugraph,acc) ->
1586 let subst,metasenv,ugraph =
1588 subst ctx metasenv t (Cic.Rel (k-n)) ugraph
1590 subst,metasenv,ugraph,(t::acc))
1591 (fun (s,m,g,acc) tl -> assert(acc=[]);(s,m,g,tl))
1594 subst,metasenv,ugraph,(Cic.Appl (hd::tl))
1595 | Cic.MutInd(uri',_,_) as t when uri = uri'->
1596 subst,metasenv,ugraph,t
1597 | Cic.Prod (name,s,t) ->
1598 let ctx = (Some (name,Cic.Decl s))::ctx in
1599 let subst,metasenv,ugraph,t = aux ctx (k+1) subst t in
1600 subst,metasenv,ugraph,Cic.Prod (name,s,t)
1604 (lazy "not well formed constructor type"))
1606 let subst,metasenv,ugraph,ty = aux [] 0 subst ty in
1607 subst,metasenv,ugraph,(name,ty) :: acc)
1608 cl (subst,metasenv,ugraph,[])
1610 subst,metasenv,ugraph,(name,ind,arity,cl)::acc)
1611 tys ([],metasenv,ugraph,[])
1613 let substituted_tys =
1615 (fun (name,ind,arity,cl) ->
1617 List.map (fun (name, ty) -> name,CicMetaSubst.apply_subst subst ty) cl
1619 name,ind,CicMetaSubst.apply_subst subst arity,cl)
1622 metasenv,ugraph,substituted_tys
1624 let typecheck metasenv uri obj ~localization_tbl =
1625 let ugraph = CicUniv.empty_ugraph in
1627 Cic.Constant (name,Some bo,ty,args,attrs) ->
1628 let bo',boty,metasenv,ugraph =
1629 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1630 let ty',_,metasenv,ugraph =
1631 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1632 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1633 let bo' = CicMetaSubst.apply_subst subst bo' in
1634 let ty' = CicMetaSubst.apply_subst subst ty' in
1635 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1636 Cic.Constant (name,Some bo',ty',args,attrs),metasenv,ugraph
1637 | Cic.Constant (name,None,ty,args,attrs) ->
1638 let ty',_,metasenv,ugraph =
1639 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1641 Cic.Constant (name,None,ty',args,attrs),metasenv,ugraph
1642 | Cic.CurrentProof (name,metasenv',bo,ty,args,attrs) ->
1643 assert (metasenv' = metasenv);
1644 (* Here we do not check the metasenv for correctness *)
1645 let bo',boty,metasenv,ugraph =
1646 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1647 let ty',sort,metasenv,ugraph =
1648 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1652 (* instead of raising Uncertain, let's hope that the meta will become
1655 | _ -> raise (RefineFailure (lazy "The term provided is not a type"))
1657 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1658 let bo' = CicMetaSubst.apply_subst subst bo' in
1659 let ty' = CicMetaSubst.apply_subst subst ty' in
1660 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1661 Cic.CurrentProof (name,metasenv,bo',ty',args,attrs),metasenv,ugraph
1662 | Cic.Variable _ -> assert false (* not implemented *)
1663 | Cic.InductiveDefinition (tys,args,paramsno,attrs) ->
1664 (*CSC: this code is greately simplified and many many checks are missing *)
1665 (*CSC: e.g. the constructors are not required to build their own types, *)
1666 (*CSC: the arities are not required to have as type a sort, etc. *)
1667 let uri = match uri with Some uri -> uri | None -> assert false in
1668 let typesno = List.length tys in
1669 (* first phase: we fix only the types *)
1670 let metasenv,ugraph,tys =
1672 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1673 let ty',_,metasenv,ugraph =
1674 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1676 metasenv,ugraph,(name,b,ty',cl)::res
1677 ) tys (metasenv,ugraph,[]) in
1679 List.rev_map (fun (name,_,ty,_)-> Some (Cic.Name name,Cic.Decl ty)) tys in
1680 (* second phase: we fix only the constructors *)
1681 let metasenv,ugraph,tys =
1683 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1684 let metasenv,ugraph,cl' =
1686 (fun (name,ty) (metasenv,ugraph,res) ->
1688 CicTypeChecker.debrujin_constructor
1689 ~cb:(relocalize localization_tbl) uri typesno ty in
1690 let ty',_,metasenv,ugraph =
1691 type_of_aux' ~localization_tbl metasenv con_context ty ugraph in
1692 let ty' = undebrujin uri typesno tys ty' in
1693 metasenv,ugraph,(name,ty')::res
1694 ) cl (metasenv,ugraph,[])
1696 metasenv,ugraph,(name,b,ty,cl')::res
1697 ) tys (metasenv,ugraph,[]) in
1698 (* third phase: we check the positivity condition *)
1699 let metasenv,ugraph,tys =
1700 are_all_occurrences_positive metasenv ugraph uri tys paramsno
1702 Cic.InductiveDefinition (tys,args,paramsno,attrs),metasenv,ugraph
1705 (* sara' piu' veloce che raffinare da zero? mah.... *)
1706 let pack_coercion metasenv ctx t =
1707 let module C = Cic in
1708 let rec merge_coercions ctx =
1709 let aux = (fun (u,t) -> u,merge_coercions ctx t) in
1711 | C.Rel _ | C.Sort _ | C.Implicit _ as t -> t
1712 | C.Meta (n,subst) ->
1715 (function None -> None | Some t -> Some (merge_coercions ctx t)) subst
1718 | C.Cast (te,ty) -> C.Cast (merge_coercions ctx te, merge_coercions ctx ty)
1719 | C.Prod (name,so,dest) ->
1720 let ctx' = (Some (name,C.Decl so))::ctx in
1721 C.Prod (name, merge_coercions ctx so, merge_coercions ctx' dest)
1722 | C.Lambda (name,so,dest) ->
1723 let ctx' = (Some (name,C.Decl so))::ctx in
1724 C.Lambda (name, merge_coercions ctx so, merge_coercions ctx' dest)
1725 | C.LetIn (name,so,dest) ->
1726 let ctx' = Some (name,(C.Def (so,None)))::ctx in
1727 C.LetIn (name, merge_coercions ctx so, merge_coercions ctx' dest)
1729 let l = List.map (merge_coercions ctx) l in
1731 let b,_,_,_,_ = is_a_double_coercion t in
1732 (* prerr_endline "CANDIDATO!!!!"; *)
1734 let ugraph = CicUniv.empty_ugraph in
1735 let old_insert_coercions = !insert_coercions in
1736 insert_coercions := false;
1737 let newt, _, menv, _ =
1739 type_of_aux' metasenv ctx t ugraph
1740 with RefineFailure _ | Uncertain _ ->
1741 prerr_endline (CicPp.ppterm t);
1744 insert_coercions := old_insert_coercions;
1745 if metasenv <> [] || menv = [] then
1748 (prerr_endline "PUO' SUCCEDERE!!!!!";t)
1751 | C.Var (uri,exp_named_subst) ->
1752 let exp_named_subst = List.map aux exp_named_subst in
1753 C.Var (uri, exp_named_subst)
1754 | C.Const (uri,exp_named_subst) ->
1755 let exp_named_subst = List.map aux exp_named_subst in
1756 C.Const (uri, exp_named_subst)
1757 | C.MutInd (uri,tyno,exp_named_subst) ->
1758 let exp_named_subst = List.map aux exp_named_subst in
1759 C.MutInd (uri,tyno,exp_named_subst)
1760 | C.MutConstruct (uri,tyno,consno,exp_named_subst) ->
1761 let exp_named_subst = List.map aux exp_named_subst in
1762 C.MutConstruct (uri,tyno,consno,exp_named_subst)
1763 | C.MutCase (uri,tyno,out,te,pl) ->
1764 let pl = List.map (merge_coercions ctx) pl in
1765 C.MutCase (uri,tyno,merge_coercions ctx out, merge_coercions ctx te, pl)
1766 | C.Fix (fno, fl) ->
1769 (fun l (n,_,ty,_) -> (Some (C.Name n,C.Decl ty))::l)
1774 (fun (name,idx,ty,bo) ->
1775 (name,idx,merge_coercions ctx ty,merge_coercions ctx' bo))
1779 | C.CoFix (fno, fl) ->
1782 (fun l (n,ty,_) -> (Some (C.Name n,C.Decl ty))::l)
1787 (fun (name,ty,bo) ->
1788 (name, merge_coercions ctx ty, merge_coercions ctx' bo))
1793 merge_coercions ctx t
1796 let pack_coercion_obj obj =
1797 let module C = Cic in
1799 | C.Constant (id, body, ty, params, attrs) ->
1803 | Some body -> Some (pack_coercion [] [] body)
1805 let ty = pack_coercion [] [] ty in
1806 C.Constant (id, body, ty, params, attrs)
1807 | C.Variable (name, body, ty, params, attrs) ->
1811 | Some body -> Some (pack_coercion [] [] body)
1813 let ty = pack_coercion [] [] ty in
1814 C.Variable (name, body, ty, params, attrs)
1815 | C.CurrentProof (name, conjectures, body, ty, params, attrs) ->
1818 (fun (i, ctx, ty) ->
1824 Some (name, C.Decl t) ->
1825 Some (name, C.Decl (pack_coercion conjectures ctx t))
1826 | Some (name, C.Def (t,None)) ->
1827 Some (name,C.Def (pack_coercion conjectures ctx t,None))
1828 | Some (name, C.Def (t,Some ty)) ->
1829 Some (name, C.Def (pack_coercion conjectures ctx t,
1830 Some (pack_coercion conjectures ctx ty)))
1836 ((i,ctx,pack_coercion conjectures ctx ty))
1839 let body = pack_coercion conjectures [] body in
1840 let ty = pack_coercion conjectures [] ty in
1841 C.CurrentProof (name, conjectures, body, ty, params, attrs)
1842 | C.InductiveDefinition (indtys, params, leftno, attrs) ->
1845 (fun (name, ind, arity, cl) ->
1846 let arity = pack_coercion [] [] arity in
1848 List.map (fun (name, ty) -> (name,pack_coercion [] [] ty)) cl
1850 (name, ind, arity, cl))
1853 C.InductiveDefinition (indtys, params, leftno, attrs)
1858 let type_of_aux' metasenv context term =
1861 type_of_aux' metasenv context term in
1863 ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty));
1865 ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []));
1868 | RefineFailure msg as e ->
1869 debug_print (lazy ("@@@ REFINE FAILED: " ^ msg));
1871 | Uncertain msg as e ->
1872 debug_print (lazy ("@@@ REFINE UNCERTAIN: " ^ msg));
1876 let profiler2 = HExtlib.profile "CicRefine"
1878 let type_of_aux' ?localization_tbl metasenv context term ugraph =
1879 profiler2.HExtlib.profile
1880 (type_of_aux' ?localization_tbl metasenv context term) ugraph
1882 let typecheck ~localization_tbl metasenv uri obj =
1883 profiler2.HExtlib.profile (typecheck ~localization_tbl metasenv uri) obj
1885 let _ = DoubleTypeInference.pack_coercion := pack_coercion;;
1886 (* vim:set foldmethod=marker: *)