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
148 localization_tbl subst he context hetype' tlbody_and_type exn
152 CicMetaSubst.ppterm_in_context subst he context ^
153 " (that has type "^CicMetaSubst.ppterm_in_context subst hetype' context ^
154 ") is here applied to " ^ string_of_int (List.length tlbody_and_type) ^
155 " arguments that are more than expected")
157 enrich localization_tbl he ~f:(fun _-> msg) exn
160 let mk_prod_of_metas metasenv context' subst args =
161 let rec mk_prod metasenv context' = function
163 let (metasenv, idx) =
164 CicMkImplicit.mk_implicit_type metasenv subst context'
167 CicMkImplicit.identity_relocation_list_for_metavariable context'
169 metasenv,Cic.Meta (idx, irl)
171 let (metasenv, idx) =
172 CicMkImplicit.mk_implicit_type metasenv subst context'
175 CicMkImplicit.identity_relocation_list_for_metavariable context'
177 let meta = Cic.Meta (idx,irl) in
179 (* The name must be fresh for context. *)
180 (* Nevertheless, argty is well-typed only in context. *)
181 (* Thus I generate a name (name_hint) in context and *)
182 (* then I generate a name --- using the hint name_hint *)
183 (* --- that is fresh in context'. *)
185 (* Cic.Name "pippo" *)
186 FreshNamesGenerator.mk_fresh_name ~subst metasenv
187 (* (CicMetaSubst.apply_subst_metasenv subst metasenv) *)
188 (CicMetaSubst.apply_subst_context subst context')
190 ~typ:(CicMetaSubst.apply_subst subst argty)
192 (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
193 FreshNamesGenerator.mk_fresh_name ~subst
194 [] context' name_hint ~typ:(Cic.Sort Cic.Prop)
196 let metasenv,target =
197 mk_prod metasenv ((Some (name, Cic.Decl meta))::context') tl
199 metasenv,Cic.Prod (name,meta,target)
201 mk_prod metasenv context' args
204 let rec type_of_constant uri ugraph =
205 let module C = Cic in
206 let module R = CicReduction in
207 let module U = UriManager in
208 let _ = CicTypeChecker.typecheck uri in
211 CicEnvironment.get_cooked_obj ugraph uri
212 with Not_found -> assert false
215 C.Constant (_,_,ty,_,_) -> ty,u
216 | C.CurrentProof (_,_,_,ty,_,_) -> ty,u
220 (lazy ("Unknown constant definition " ^ U.string_of_uri uri)))
222 and type_of_variable uri ugraph =
223 let module C = Cic in
224 let module R = CicReduction in
225 let module U = UriManager in
226 let _ = CicTypeChecker.typecheck uri in
229 CicEnvironment.get_cooked_obj ugraph uri
230 with Not_found -> assert false
233 C.Variable (_,_,ty,_,_) -> ty,u
237 (lazy ("Unknown variable definition " ^ UriManager.string_of_uri uri)))
239 and type_of_mutual_inductive_defs uri i ugraph =
240 let module C = Cic in
241 let module R = CicReduction in
242 let module U = UriManager in
243 let _ = CicTypeChecker.typecheck uri in
246 CicEnvironment.get_cooked_obj ugraph uri
247 with Not_found -> assert false
250 C.InductiveDefinition (dl,_,_,_) ->
251 let (_,_,arity,_) = List.nth dl i in
256 (lazy ("Unknown mutual inductive definition " ^ U.string_of_uri uri)))
258 and type_of_mutual_inductive_constr uri i j ugraph =
259 let module C = Cic in
260 let module R = CicReduction in
261 let module U = UriManager in
262 let _ = CicTypeChecker.typecheck uri in
265 CicEnvironment.get_cooked_obj ugraph uri
266 with Not_found -> assert false
269 C.InductiveDefinition (dl,_,_,_) ->
270 let (_,_,_,cl) = List.nth dl i in
271 let (_,ty) = List.nth cl (j-1) in
277 ("Unkown mutual inductive definition " ^ U.string_of_uri uri)))
280 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
282 (* the check_branch function checks if a branch of a case is refinable.
283 It returns a pair (outype_instance,args), a subst and a metasenv.
284 outype_instance is the expected result of applying the case outtype
286 The problem is that outype is in general unknown, and we should
287 try to synthesize it from the above information, that is in general
288 a second order unification problem. *)
290 and check_branch n context metasenv subst left_args_no actualtype term expectedtype ugraph =
291 let module C = Cic in
292 (* let module R = CicMetaSubst in *)
293 let module R = CicReduction in
294 match R.whd ~subst context expectedtype with
296 (n,context,actualtype, [term]), subst, metasenv, ugraph
297 | C.Appl (C.MutInd (_,_,_)::tl) ->
298 let (_,arguments) = split tl left_args_no in
299 (n,context,actualtype, arguments@[term]), subst, metasenv, ugraph
300 | C.Prod (name,so,de) ->
301 (* we expect that the actual type of the branch has the due
303 (match R.whd ~subst context actualtype with
304 C.Prod (name',so',de') ->
305 let subst, metasenv, ugraph1 =
306 fo_unif_subst subst context metasenv so so' ugraph in
308 (match CicSubstitution.lift 1 term with
309 C.Appl l -> C.Appl (l@[C.Rel 1])
310 | t -> C.Appl [t ; C.Rel 1]) in
311 (* we should also check that the name variable is anonymous in
312 the actual type de' ?? *)
314 ((Some (name,(C.Decl so)))::context)
315 metasenv subst left_args_no de' term' de ugraph1
316 | _ -> raise (AssertFailure (lazy "Wrong number of arguments")))
317 | _ -> raise (AssertFailure (lazy "Prod or MutInd expected"))
319 and type_of_aux' ?(localization_tbl = Cic.CicHash.create 1) metasenv context t
322 let rec type_of_aux subst metasenv context t ugraph =
323 let try_coercion t subst metasenv context ugraph coercion_tgt c =
324 let coerced = Cic.Appl[c;t] in
326 let newt,_,subst,metasenv,ugraph =
327 type_of_aux subst metasenv context coerced ugraph
329 let newt, tty, subst, metasenv, ugraph =
330 avoid_double_coercion context subst metasenv ugraph newt coercion_tgt
332 Some (newt, tty, subst, metasenv, ugraph)
334 | RefineFailure _ | Uncertain _ -> None
336 let module C = Cic in
337 let module S = CicSubstitution in
338 let module U = UriManager in
339 let (t',_,_,_,_) as res =
344 match List.nth context (n - 1) with
345 Some (_,C.Decl ty) ->
346 t,S.lift n ty,subst,metasenv, ugraph
347 | Some (_,C.Def (_,Some ty)) ->
348 t,S.lift n ty,subst,metasenv, ugraph
349 | Some (_,C.Def (bo,None)) ->
351 (* if it is in the context it must be already well-typed*)
352 CicTypeChecker.type_of_aux' ~subst metasenv context
355 t,ty,subst,metasenv,ugraph
357 enrich localization_tbl t
358 (RefineFailure (lazy "Rel to hidden hypothesis"))
361 enrich localization_tbl t
362 (RefineFailure (lazy "Not a close term")))
363 | C.Var (uri,exp_named_subst) ->
364 let exp_named_subst',subst',metasenv',ugraph1 =
365 check_exp_named_subst
366 subst metasenv context exp_named_subst ugraph
368 let ty_uri,ugraph1 = type_of_variable uri ugraph in
370 CicSubstitution.subst_vars exp_named_subst' ty_uri
372 C.Var (uri,exp_named_subst'),ty,subst',metasenv',ugraph1
375 let (canonical_context, term,ty) =
376 CicUtil.lookup_subst n subst
378 let l',subst',metasenv',ugraph1 =
379 check_metasenv_consistency n subst metasenv context
380 canonical_context l ugraph
382 (* trust or check ??? *)
383 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
384 subst', metasenv', ugraph1
385 (* type_of_aux subst metasenv
386 context (CicSubstitution.subst_meta l term) *)
387 with CicUtil.Subst_not_found _ ->
388 let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
389 let l',subst',metasenv', ugraph1 =
390 check_metasenv_consistency n subst metasenv context
391 canonical_context l ugraph
393 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
394 subst', metasenv',ugraph1)
395 | C.Sort (C.Type tno) ->
396 let tno' = CicUniv.fresh() in
397 let ugraph1 = CicUniv.add_gt tno' tno ugraph in
398 t,(C.Sort (C.Type tno')),subst,metasenv,ugraph1
400 t,C.Sort (C.Type (CicUniv.fresh())),subst,metasenv,ugraph
401 | C.Implicit infos ->
402 let metasenv',t' = exp_impl metasenv subst context infos in
403 type_of_aux subst metasenv' context t' ugraph
405 let ty',_,subst',metasenv',ugraph1 =
406 type_of_aux subst metasenv context ty ugraph
408 let te',inferredty,subst'',metasenv'',ugraph2 =
409 type_of_aux subst' metasenv' context te ugraph1
412 let subst''',metasenv''',ugraph3 =
413 fo_unif_subst subst'' context metasenv''
414 inferredty ty' ugraph2
416 C.Cast (te',ty'),ty',subst''',metasenv''',ugraph3
419 enrich localization_tbl te'
422 CicMetaSubst.ppterm_in_context subst'' te'
423 context ^ " has type " ^
424 CicMetaSubst.ppterm_in_context subst'' inferredty
425 context ^ " but is here used with type " ^
426 CicMetaSubst.ppterm_in_context subst'' ty' context)) exn
428 | C.Prod (name,s,t) ->
429 let carr t subst context = CicMetaSubst.apply_subst subst t in
430 let coerce_to_sort in_source tgt_sort t type_to_coerce
431 subst context metasenv uragph
433 if not !insert_coercions then
434 t,type_to_coerce,subst,metasenv,ugraph
436 let coercion_src = carr type_to_coerce subst context in
437 match coercion_src with
439 t,type_to_coerce,subst,metasenv,ugraph
440 | Cic.Meta _ as meta ->
441 t, meta, subst, metasenv, ugraph
442 | Cic.Cast _ as cast ->
443 t, cast, subst, metasenv, ugraph
445 let coercion_tgt = carr (Cic.Sort tgt_sort) subst context in
447 CoercGraph.look_for_coercion coercion_src coercion_tgt
450 | CoercGraph.NoCoercion
451 | CoercGraph.NotHandled _ ->
452 enrich localization_tbl t
455 CicMetaSubst.ppterm_in_context subst t context ^
456 " is not a type since it has type " ^
457 CicMetaSubst.ppterm_in_context
458 subst coercion_src context ^ " that is not a sort")))
459 | CoercGraph.NotMetaClosed ->
460 enrich localization_tbl t
463 CicMetaSubst.ppterm_in_context subst t context ^
464 " is not a type since it has type " ^
465 CicMetaSubst.ppterm_in_context
466 subst coercion_src context ^ " that is not a sort")))
467 | CoercGraph.SomeCoercion candidates ->
471 t subst metasenv context ugraph coercion_tgt)
477 enrich localization_tbl t
480 CicMetaSubst.ppterm_in_context
482 " is not a type since it has type " ^
483 CicMetaSubst.ppterm_in_context
484 subst coercion_src context ^
485 " that is not a sort"))))
487 let s',sort1,subst',metasenv',ugraph1 =
488 type_of_aux subst metasenv context s ugraph
490 let s',sort1,subst', metasenv',ugraph1 =
491 coerce_to_sort true (Cic.Type(CicUniv.fresh()))
492 s' sort1 subst' context metasenv' ugraph1
494 let context_for_t = ((Some (name,(C.Decl s')))::context) in
495 let t',sort2,subst'',metasenv'',ugraph2 =
496 type_of_aux subst' metasenv'
497 context_for_t t ugraph1
499 let t',sort2,subst'',metasenv'',ugraph2 =
500 coerce_to_sort false (Cic.Type(CicUniv.fresh()))
501 t' sort2 subst'' context_for_t metasenv'' ugraph2
503 let sop,subst''',metasenv''',ugraph3 =
504 sort_of_prod subst'' metasenv''
505 context (name,s') (sort1,sort2) ugraph2
507 C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
508 | C.Lambda (n,s,t) ->
510 let s',sort1,subst',metasenv',ugraph1 =
511 type_of_aux subst metasenv context s ugraph in
512 let s',sort1,subst',metasenv',ugraph1 =
513 if not !insert_coercions then
514 s',sort1, subst', metasenv', ugraph1
516 match CicReduction.whd ~subst:subst' context sort1 with
517 | C.Meta _ | C.Sort _ -> s',sort1, subst', metasenv', ugraph1
519 let coercion_tgt = Cic.Sort (Cic.Type (CicUniv.fresh())) in
521 CoercGraph.look_for_coercion coercion_src coercion_tgt
524 | CoercGraph.NoCoercion
525 | CoercGraph.NotHandled _ ->
526 enrich localization_tbl s'
529 CicMetaSubst.ppterm_in_context subst s' context ^
530 " is not a type since it has type " ^
531 CicMetaSubst.ppterm_in_context
532 subst coercion_src context ^ " that is not a sort")))
533 | CoercGraph.NotMetaClosed ->
534 enrich localization_tbl s'
537 CicMetaSubst.ppterm_in_context subst s' context ^
538 " is not a type since it has type " ^
539 CicMetaSubst.ppterm_in_context
540 subst coercion_src context ^ " that is not a sort")))
541 | CoercGraph.SomeCoercion candidates ->
545 s' subst' metasenv' context ugraph1 coercion_tgt)
551 enrich localization_tbl s'
554 CicMetaSubst.ppterm_in_context subst s' context ^
555 " is not a type since it has type " ^
556 CicMetaSubst.ppterm_in_context
557 subst coercion_src context ^
558 " that is not a sort")))
560 let context_for_t = ((Some (n,(C.Decl s')))::context) in
561 let t',type2,subst'',metasenv'',ugraph2 =
562 type_of_aux subst' metasenv' context_for_t t ugraph1
564 C.Lambda (n,s',t'),C.Prod (n,s',type2),
565 subst'',metasenv'',ugraph2
567 (* only to check if s is well-typed *)
568 let s',ty,subst',metasenv',ugraph1 =
569 type_of_aux subst metasenv context s ugraph
571 let context_for_t = ((Some (n,(C.Def (s',Some ty))))::context) in
573 let t',inferredty,subst'',metasenv'',ugraph2 =
574 type_of_aux subst' metasenv'
575 context_for_t t ugraph1
577 (* One-step LetIn reduction.
578 * Even faster than the previous solution.
579 * Moreover the inferred type is closer to the expected one.
581 C.LetIn (n,s',t'),CicSubstitution.subst s' inferredty,
582 subst'',metasenv'',ugraph2
583 | C.Appl (he::((_::_) as tl)) ->
584 let he',hetype,subst',metasenv',ugraph1 =
585 type_of_aux subst metasenv context he ugraph
587 let tlbody_and_type,subst'',metasenv'',ugraph2 =
588 typeof_list subst' metasenv' context ugraph1 tl
590 let coerced_he,coerced_args,applty,subst''',metasenv''',ugraph3 =
591 eat_prods true subst'' metasenv'' context
592 he' hetype tlbody_and_type ugraph2
594 let newappl = (C.Appl (coerced_he::coerced_args)) in
595 avoid_double_coercion
596 context subst''' metasenv''' ugraph3 newappl applty
597 | C.Appl _ -> assert false
598 | C.Const (uri,exp_named_subst) ->
599 let exp_named_subst',subst',metasenv',ugraph1 =
600 check_exp_named_subst subst metasenv context
601 exp_named_subst ugraph in
602 let ty_uri,ugraph2 = type_of_constant uri ugraph1 in
604 CicSubstitution.subst_vars exp_named_subst' ty_uri
606 C.Const (uri,exp_named_subst'),cty,subst',metasenv',ugraph2
607 | C.MutInd (uri,i,exp_named_subst) ->
608 let exp_named_subst',subst',metasenv',ugraph1 =
609 check_exp_named_subst subst metasenv context
610 exp_named_subst ugraph
612 let ty_uri,ugraph2 = type_of_mutual_inductive_defs uri i ugraph1 in
614 CicSubstitution.subst_vars exp_named_subst' ty_uri in
615 C.MutInd (uri,i,exp_named_subst'),cty,subst',metasenv',ugraph2
616 | C.MutConstruct (uri,i,j,exp_named_subst) ->
617 let exp_named_subst',subst',metasenv',ugraph1 =
618 check_exp_named_subst subst metasenv context
619 exp_named_subst ugraph
622 type_of_mutual_inductive_constr uri i j ugraph1
625 CicSubstitution.subst_vars exp_named_subst' ty_uri
627 C.MutConstruct (uri,i,j,exp_named_subst'),cty,subst',
629 | C.MutCase (uri, i, outtype, term, pl) ->
630 (* first, get the inductive type (and noparams)
631 * in the environment *)
632 let (_,b,arity,constructors), expl_params, no_left_params,ugraph =
633 let _ = CicTypeChecker.typecheck uri in
634 let obj,u = CicEnvironment.get_cooked_obj ugraph uri in
636 C.InductiveDefinition (l,expl_params,parsno,_) ->
637 List.nth l i , expl_params, parsno, u
639 enrich localization_tbl t
641 (lazy ("Unkown mutual inductive definition " ^
642 U.string_of_uri uri)))
644 let rec count_prod t =
645 match CicReduction.whd ~subst context t with
646 C.Prod (_, _, t) -> 1 + (count_prod t)
649 let no_args = count_prod arity in
650 (* now, create a "generic" MutInd *)
651 let metasenv,left_args =
652 CicMkImplicit.n_fresh_metas metasenv subst context no_left_params
654 let metasenv,right_args =
655 let no_right_params = no_args - no_left_params in
656 if no_right_params < 0 then assert false
657 else CicMkImplicit.n_fresh_metas
658 metasenv subst context no_right_params
660 let metasenv,exp_named_subst =
661 CicMkImplicit.fresh_subst metasenv subst context expl_params in
664 C.MutInd (uri,i,exp_named_subst)
667 (C.MutInd (uri,i,exp_named_subst)::(left_args @ right_args))
669 (* check consistency with the actual type of term *)
670 let term',actual_type,subst,metasenv,ugraph1 =
671 type_of_aux subst metasenv context term ugraph in
672 let expected_type',_, subst, metasenv,ugraph2 =
673 type_of_aux subst metasenv context expected_type ugraph1
675 let actual_type = CicReduction.whd ~subst context actual_type in
676 let subst,metasenv,ugraph3 =
678 fo_unif_subst subst context metasenv
679 expected_type' actual_type ugraph2
682 enrich localization_tbl term' exn
685 CicMetaSubst.ppterm_in_context subst term'
686 context ^ " has type " ^
687 CicMetaSubst.ppterm_in_context subst actual_type
688 context ^ " but is here used with type " ^
689 CicMetaSubst.ppterm_in_context subst expected_type' context))
691 let rec instantiate_prod t =
695 match CicReduction.whd ~subst context t with
697 instantiate_prod (CicSubstitution.subst he t') tl
700 let arity_instantiated_with_left_args =
701 instantiate_prod arity left_args in
702 (* TODO: check if the sort elimination
703 * is allowed: [(I q1 ... qr)|B] *)
704 let (pl',_,outtypeinstances,subst,metasenv,ugraph4) =
706 (fun (pl,j,outtypeinstances,subst,metasenv,ugraph) p ->
708 if left_args = [] then
709 (C.MutConstruct (uri,i,j,exp_named_subst))
712 (C.MutConstruct (uri,i,j,exp_named_subst)::left_args))
714 let p',actual_type,subst,metasenv,ugraph1 =
715 type_of_aux subst metasenv context p ugraph
717 let constructor',expected_type, subst, metasenv,ugraph2 =
718 type_of_aux subst metasenv context constructor ugraph1
720 let outtypeinstance,subst,metasenv,ugraph3 =
721 check_branch 0 context metasenv subst no_left_params
722 actual_type constructor' expected_type ugraph2
725 outtypeinstance::outtypeinstances,subst,metasenv,ugraph3))
726 ([],1,[],subst,metasenv,ugraph3) pl
729 (* we are left to check that the outype matches his instances.
730 The easy case is when the outype is specified, that amount
731 to a trivial check. Otherwise, we should guess a type from
735 let outtype,outtypety, subst, metasenv,ugraph4 =
736 type_of_aux subst metasenv context outtype ugraph4 in
739 (let candidate,ugraph5,metasenv,subst =
740 let exp_name_subst, metasenv =
742 CicEnvironment.get_cooked_obj CicUniv.empty_ugraph uri
744 let uris = CicUtil.params_of_obj o in
746 fun uri (acc,metasenv) ->
747 let metasenv',new_meta =
748 CicMkImplicit.mk_implicit metasenv subst context
751 CicMkImplicit.identity_relocation_list_for_metavariable
754 (uri, Cic.Meta(new_meta,irl))::acc, metasenv'
758 match left_args,right_args with
759 [],[] -> Cic.MutInd(uri, i, exp_name_subst)
761 let rec mk_right_args =
764 | n -> (Cic.Rel n)::(mk_right_args (n - 1))
766 let right_args_no = List.length right_args in
767 let lifted_left_args =
768 List.map (CicSubstitution.lift right_args_no) left_args
770 Cic.Appl (Cic.MutInd(uri,i,exp_name_subst)::
771 (lifted_left_args @ mk_right_args right_args_no))
774 FreshNamesGenerator.mk_fresh_name ~subst metasenv
775 context Cic.Anonymous ~typ:ty
777 match outtypeinstances with
779 let extended_context =
780 let rec add_right_args =
782 Cic.Prod (name,ty,t) ->
783 Some (name,Cic.Decl ty)::(add_right_args t)
786 (Some (fresh_name,Cic.Decl ty))::
788 (add_right_args arity_instantiated_with_left_args))@
791 let metasenv,new_meta =
792 CicMkImplicit.mk_implicit metasenv subst extended_context
795 CicMkImplicit.identity_relocation_list_for_metavariable
798 let rec add_lambdas b =
800 Cic.Prod (name,ty,t) ->
801 Cic.Lambda (name,ty,(add_lambdas b t))
802 | _ -> Cic.Lambda (fresh_name, ty, b)
805 add_lambdas (Cic.Meta (new_meta,irl))
806 arity_instantiated_with_left_args
808 (Some candidate),ugraph4,metasenv,subst
809 | (constructor_args_no,_,instance,_)::tl ->
811 let instance',subst,metasenv =
812 CicMetaSubst.delift_rels subst metasenv
813 constructor_args_no instance
815 let candidate,ugraph,metasenv,subst =
817 fun (candidate_oty,ugraph,metasenv,subst)
818 (constructor_args_no,_,instance,_) ->
819 match candidate_oty with
820 | None -> None,ugraph,metasenv,subst
823 let instance',subst,metasenv =
824 CicMetaSubst.delift_rels subst metasenv
825 constructor_args_no instance
827 let subst,metasenv,ugraph =
828 fo_unif_subst subst context metasenv
831 candidate_oty,ugraph,metasenv,subst
833 CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable
834 | CicUnification.UnificationFailure _
835 | CicUnification.Uncertain _ ->
836 None,ugraph,metasenv,subst
837 ) (Some instance',ugraph4,metasenv,subst) tl
840 | None -> None, ugraph,metasenv,subst
842 let rec add_lambdas n b =
844 Cic.Prod (name,ty,t) ->
845 Cic.Lambda (name,ty,(add_lambdas (n + 1) b t))
847 Cic.Lambda (fresh_name, ty,
848 CicSubstitution.lift (n + 1) t)
851 (add_lambdas 0 t arity_instantiated_with_left_args),
852 ugraph,metasenv,subst
853 with CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
854 None,ugraph4,metasenv,subst
857 | None -> raise (Uncertain (lazy "can't solve an higher order unification problem"))
859 let subst,metasenv,ugraph =
861 fo_unif_subst subst context metasenv
862 candidate outtype ugraph5
864 exn -> assert false(* unification against a metavariable *)
866 C.MutCase (uri, i, outtype, term', pl'),
867 CicReduction.head_beta_reduce
868 (CicMetaSubst.apply_subst subst
869 (Cic.Appl (outtype::right_args@[term']))),
870 subst,metasenv,ugraph)
871 | _ -> (* easy case *)
872 let tlbody_and_type,subst,metasenv,ugraph4 =
873 typeof_list subst metasenv context ugraph4 (right_args @ [term'])
875 let _,_,_,subst,metasenv,ugraph4 =
876 eat_prods false subst metasenv context
877 outtype outtypety tlbody_and_type ugraph4
879 let _,_, subst, metasenv,ugraph5 =
880 type_of_aux subst metasenv context
881 (C.Appl ((outtype :: right_args) @ [term'])) ugraph4
883 let (subst,metasenv,ugraph6) =
885 (fun (subst,metasenv,ugraph)
886 p (constructor_args_no,context,instance,args)
891 CicSubstitution.lift constructor_args_no outtype
893 C.Appl (outtype'::args)
895 CicReduction.whd ~subst context appl
898 fo_unif_subst subst context metasenv instance instance'
902 enrich localization_tbl p exn
905 CicMetaSubst.ppterm_in_context subst p
906 context ^ " has type " ^
907 CicMetaSubst.ppterm_in_context subst instance'
908 context ^ " but is here used with type " ^
909 CicMetaSubst.ppterm_in_context subst instance
911 (subst,metasenv,ugraph5) pl' outtypeinstances
913 C.MutCase (uri, i, outtype, term', pl'),
914 CicReduction.head_beta_reduce
915 (CicMetaSubst.apply_subst subst
916 (C.Appl(outtype::right_args@[term]))),
917 subst,metasenv,ugraph6)
919 let fl_ty',subst,metasenv,types,ugraph1 =
921 (fun (fl,subst,metasenv,types,ugraph) (n,_,ty,_) ->
922 let ty',_,subst',metasenv',ugraph1 =
923 type_of_aux subst metasenv context ty ugraph
925 fl @ [ty'],subst',metasenv',
926 Some (C.Name n,(C.Decl ty')) :: types, ugraph
927 ) ([],subst,metasenv,[],ugraph) fl
929 let len = List.length types in
930 let context' = types@context in
931 let fl_bo',subst,metasenv,ugraph2 =
933 (fun (fl,subst,metasenv,ugraph) ((name,x,_,bo),ty) ->
934 let bo',ty_of_bo,subst,metasenv,ugraph1 =
935 type_of_aux subst metasenv context' bo ugraph in
936 let expected_ty = CicSubstitution.lift len ty in
937 let subst',metasenv',ugraph' =
939 fo_unif_subst subst context' metasenv
940 ty_of_bo expected_ty ugraph1
943 enrich localization_tbl bo exn
946 CicMetaSubst.ppterm_in_context subst bo
947 context' ^ " has type " ^
948 CicMetaSubst.ppterm_in_context subst ty_of_bo
949 context' ^ " but is here used with type " ^
950 CicMetaSubst.ppterm_in_context subst expected_ty
953 fl @ [bo'] , subst',metasenv',ugraph'
954 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
956 let ty = List.nth fl_ty' i in
957 (* now we have the new ty in fl_ty', the new bo in fl_bo',
958 * and we want the new fl with bo' and ty' injected in the right
961 let rec map3 f l1 l2 l3 =
964 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
967 let fl'' = map3 (fun ty' bo' (name,x,ty,bo) -> (name,x,ty',bo') )
970 C.Fix (i,fl''),ty,subst,metasenv,ugraph2
972 let fl_ty',subst,metasenv,types,ugraph1 =
974 (fun (fl,subst,metasenv,types,ugraph) (n,ty,_) ->
975 let ty',_,subst',metasenv',ugraph1 =
976 type_of_aux subst metasenv context ty ugraph
978 fl @ [ty'],subst',metasenv',
979 Some (C.Name n,(C.Decl ty')) :: types, ugraph1
980 ) ([],subst,metasenv,[],ugraph) fl
982 let len = List.length types in
983 let context' = types@context in
984 let fl_bo',subst,metasenv,ugraph2 =
986 (fun (fl,subst,metasenv,ugraph) ((name,_,bo),ty) ->
987 let bo',ty_of_bo,subst,metasenv,ugraph1 =
988 type_of_aux subst metasenv context' bo ugraph in
989 let expected_ty = CicSubstitution.lift len ty in
990 let subst',metasenv',ugraph' =
992 fo_unif_subst subst context' metasenv
993 ty_of_bo expected_ty ugraph1
996 enrich localization_tbl bo exn
999 CicMetaSubst.ppterm_in_context subst bo
1000 context' ^ " has type " ^
1001 CicMetaSubst.ppterm_in_context subst ty_of_bo
1002 context' ^ " but is here used with type " ^
1003 CicMetaSubst.ppterm_in_context subst expected_ty
1006 fl @ [bo'],subst',metasenv',ugraph'
1007 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
1009 let ty = List.nth fl_ty' i in
1010 (* now we have the new ty in fl_ty', the new bo in fl_bo',
1011 * and we want the new fl with bo' and ty' injected in the right
1014 let rec map3 f l1 l2 l3 =
1017 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
1020 let fl'' = map3 (fun ty' bo' (name,ty,bo) -> (name,ty',bo') )
1023 C.CoFix (i,fl''),ty,subst,metasenv,ugraph2
1025 relocalize localization_tbl t t';
1028 (* check_metasenv_consistency checks that the "canonical" context of a
1029 metavariable is consitent - up to relocation via the relocation list l -
1030 with the actual context *)
1031 and check_metasenv_consistency
1032 metano subst metasenv context canonical_context l ugraph
1034 let module C = Cic in
1035 let module R = CicReduction in
1036 let module S = CicSubstitution in
1037 let lifted_canonical_context =
1041 | (Some (n,C.Decl t))::tl ->
1042 (Some (n,C.Decl (S.subst_meta l (S.lift i t))))::(aux (i+1) tl)
1043 | (Some (n,C.Def (t,None)))::tl ->
1044 (Some (n,C.Def ((S.subst_meta l (S.lift i t)),None)))::(aux (i+1) tl)
1045 | None::tl -> None::(aux (i+1) tl)
1046 | (Some (n,C.Def (t,Some ty)))::tl ->
1048 C.Def ((S.subst_meta l (S.lift i t)),
1049 Some (S.subst_meta l (S.lift i ty))))) :: (aux (i+1) tl)
1051 aux 1 canonical_context
1055 (fun (l,subst,metasenv,ugraph) t ct ->
1058 l @ [None],subst,metasenv,ugraph
1059 | Some t,Some (_,C.Def (ct,_)) ->
1060 let subst',metasenv',ugraph' =
1062 fo_unif_subst subst context metasenv t ct ugraph
1063 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))))))
1065 l @ [Some t],subst',metasenv',ugraph'
1066 | Some t,Some (_,C.Decl ct) ->
1067 let t',inferredty,subst',metasenv',ugraph1 =
1068 type_of_aux subst metasenv context t ugraph
1070 let subst'',metasenv'',ugraph2 =
1073 subst' context metasenv' inferredty ct ugraph1
1074 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))))))
1076 l @ [Some t'], subst'',metasenv'',ugraph2
1078 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
1080 Invalid_argument _ ->
1084 "Not well typed metavariable instance %s: the length of the local context does not match the length of the canonical context %s"
1085 (CicMetaSubst.ppterm subst (Cic.Meta (metano, l)))
1086 (CicMetaSubst.ppcontext subst canonical_context))))
1088 and check_exp_named_subst metasubst metasenv context tl ugraph =
1089 let rec check_exp_named_subst_aux metasubst metasenv substs tl ugraph =
1091 [] -> [],metasubst,metasenv,ugraph
1093 let ty_uri,ugraph1 = type_of_variable uri ugraph in
1095 CicSubstitution.subst_vars substs ty_uri in
1096 (* CSC: why was this code here? it is wrong
1097 (match CicEnvironment.get_cooked_obj ~trust:false uri with
1098 Cic.Variable (_,Some bo,_,_) ->
1100 (RefineFailure (lazy
1101 "A variable with a body can not be explicit substituted"))
1102 | Cic.Variable (_,None,_,_) -> ()
1105 (RefineFailure (lazy
1106 ("Unkown variable definition " ^ UriManager.string_of_uri uri)))
1109 let t',typeoft,metasubst',metasenv',ugraph2 =
1110 type_of_aux metasubst metasenv context t ugraph1 in
1111 let subst = uri,t' in
1112 let metasubst'',metasenv'',ugraph3 =
1115 metasubst' context metasenv' typeoft typeofvar ugraph2
1117 raise (RefineFailure (lazy
1118 ("Wrong Explicit Named Substitution: " ^
1119 CicMetaSubst.ppterm metasubst' typeoft ^
1120 " not unifiable with " ^
1121 CicMetaSubst.ppterm metasubst' typeofvar)))
1123 (* FIXME: no mere tail recursive! *)
1124 let exp_name_subst, metasubst''', metasenv''', ugraph4 =
1125 check_exp_named_subst_aux
1126 metasubst'' metasenv'' (substs@[subst]) tl ugraph3
1128 ((uri,t')::exp_name_subst), metasubst''', metasenv''', ugraph4
1130 check_exp_named_subst_aux metasubst metasenv [] tl ugraph
1133 and sort_of_prod subst metasenv context (name,s) (t1, t2) ugraph =
1134 let module C = Cic in
1135 let context_for_t2 = (Some (name,C.Decl s))::context in
1136 let t1'' = CicReduction.whd ~subst context t1 in
1137 let t2'' = CicReduction.whd ~subst context_for_t2 t2 in
1138 match (t1'', t2'') with
1139 (C.Sort s1, C.Sort s2)
1140 when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) ->
1141 (* different than Coq manual!!! *)
1142 C.Sort s2,subst,metasenv,ugraph
1143 | (C.Sort (C.Type t1), C.Sort (C.Type t2)) ->
1144 let t' = CicUniv.fresh() in
1145 let ugraph1 = CicUniv.add_ge t' t1 ugraph in
1146 let ugraph2 = CicUniv.add_ge t' t2 ugraph1 in
1147 C.Sort (C.Type t'),subst,metasenv,ugraph2
1148 | (C.Sort _,C.Sort (C.Type t1)) ->
1149 C.Sort (C.Type t1),subst,metasenv,ugraph
1150 | (C.Meta _, C.Sort _) -> t2'',subst,metasenv,ugraph
1151 | (C.Sort _,C.Meta _) | (C.Meta _,C.Meta _) ->
1152 (* TODO how can we force the meta to become a sort? If we don't we
1153 * break the invariant that refine produce only well typed terms *)
1154 (* TODO if we check the non meta term and if it is a sort then we
1155 * are likely to know the exact value of the result e.g. if the rhs
1156 * is a Sort (Prop | Set | CProp) then the result is the rhs *)
1157 let (metasenv,idx) =
1158 CicMkImplicit.mk_implicit_sort metasenv subst in
1159 let (subst, metasenv,ugraph1) =
1161 fo_unif_subst subst context_for_t2 metasenv
1162 (C.Meta (idx,[])) t2'' ugraph
1163 with _ -> assert false (* unification against a metavariable *)
1165 t2'',subst,metasenv,ugraph1
1171 ("Two sorts were expected, found %s " ^^
1172 "(that reduces to %s) and %s (that reduces to %s)")
1173 (CicPp.ppterm t1) (CicPp.ppterm t1'') (CicPp.ppterm t2)
1174 (CicPp.ppterm t2''))))
1176 and avoid_double_coercion context subst metasenv ugraph t ty =
1177 let b, c1, c2, head, c1_c2_implicit = is_a_double_coercion t in
1179 let source_carr = CoercGraph.source_of c2 in
1180 let tgt_carr = CicMetaSubst.apply_subst subst ty in
1181 (match CoercGraph.look_for_coercion source_carr tgt_carr
1183 | CoercGraph.SomeCoercion candidates ->
1185 HExtlib.list_findopt
1187 | c when not (CoercGraph.is_composite c) ->
1188 debug_print (lazy ("\nNot a composite.."^CicPp.ppterm c));
1193 | Cic.Appl l -> Cic.Appl (l @ [head])
1194 | _ -> Cic.Appl [c;head]
1196 debug_print (lazy ("\nprovo" ^ CicPp.ppterm newt));
1201 CicPp.ppterm t ^ " ==> " ^ CicPp.ppterm newt));
1202 let newt,_,subst,metasenv,ugraph =
1203 type_of_aux subst metasenv context newt ugraph in
1204 debug_print (lazy "tipa...");
1205 let subst, metasenv, ugraph =
1206 (* COME MAI C'ERA UN IF su !pack_coercions ??? *)
1207 fo_unif_subst subst context metasenv newt t ugraph
1209 debug_print (lazy "unifica...");
1210 Some (newt, ty, subst, metasenv, ugraph)
1212 | RefineFailure s | Uncertain s when not !pack_coercions->
1213 debug_print s; debug_print (lazy "stop\n");None
1214 | RefineFailure s | Uncertain s ->
1215 debug_print s;debug_print (lazy "goon\n");
1217 pack_coercions := false; (* to avoid diverging *)
1218 let refined_c1_c2_implicit,ty,subst,metasenv,ugraph =
1219 type_of_aux subst metasenv context c1_c2_implicit ugraph
1221 pack_coercions := true;
1223 is_a_double_coercion refined_c1_c2_implicit
1229 match refined_c1_c2_implicit with
1230 | Cic.Appl l -> HExtlib.list_last l
1233 let subst, metasenv, ugraph =
1234 try fo_unif_subst subst context metasenv
1236 with RefineFailure s| Uncertain s->
1237 debug_print s;assert false
1239 let subst, metasenv, ugraph =
1240 fo_unif_subst subst context metasenv
1241 refined_c1_c2_implicit t ugraph
1243 Some (refined_c1_c2_implicit,ty,subst,metasenv,ugraph)
1245 | RefineFailure s | Uncertain s ->
1246 pack_coercions := true;debug_print s;None
1247 | exn -> pack_coercions := true; raise exn))
1250 (match selected with
1254 (lazy ("#### Coercion not packed: " ^ CicPp.ppterm t));
1255 t, ty, subst, metasenv, ugraph)
1256 | _ -> t, ty, subst, metasenv, ugraph)
1258 t, ty, subst, metasenv, ugraph
1260 and typeof_list subst metasenv context ugraph l =
1261 let tlbody_and_type,subst,metasenv,ugraph =
1263 (fun x (res,subst,metasenv,ugraph) ->
1264 let x',ty,subst',metasenv',ugraph1 =
1265 type_of_aux subst metasenv context x ugraph
1267 (x', ty)::res,subst',metasenv',ugraph1
1268 ) l ([],subst,metasenv,ugraph)
1270 tlbody_and_type,subst,metasenv,ugraph
1273 allow_coercions subst metasenv context he hetype args_bo_and_ty ugraph
1275 (* aux function to add coercions to funclass *)
1276 let rec fix_arity metasenv context subst he hetype args_bo_and_ty ugraph =
1278 let pristinemenv = metasenv in
1279 let metasenv,hetype' =
1280 mk_prod_of_metas metasenv context subst args_bo_and_ty
1283 let subst,metasenv,ugraph =
1284 fo_unif_subst_eat_prods
1285 subst context metasenv hetype hetype' ugraph
1287 subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1288 with RefineFailure s | Uncertain s as exn
1289 when allow_coercions && !insert_coercions ->
1290 (* {{{ we search a coercion of the head (saturated) to funclass *)
1291 let metasenv = pristinemenv in
1293 ("Fixing arity of: "^CicMetaSubst.ppterm subst hetype ^
1294 " since unif failed with: " ^ CicMetaSubst.ppterm subst hetype'
1295 (* ^ " cause: " ^ Lazy.force s *)));
1296 let how_many_args_are_needed =
1297 let rec aux n = function
1298 | Cic.Prod(_,_,t) -> aux (n+1) t
1301 aux 0 (CicMetaSubst.apply_subst subst hetype)
1303 let args, remainder =
1304 HExtlib.split_nth how_many_args_are_needed args_bo_and_ty
1306 let args = List.map fst args in
1310 | Cic.Appl l -> Cic.Appl (l@args)
1311 | _ -> Cic.Appl (he::args)
1315 let x,xty,subst,metasenv,ugraph =
1316 type_of_aux subst metasenv context x ugraph
1319 CoercDb.coerc_carr_of_term (CicMetaSubst.apply_subst subst xty)
1321 let carr_tgt = CoercDb.Fun 0 in
1322 match CoercGraph.look_for_coercion' carr_src carr_tgt with
1323 | CoercGraph.NoCoercion
1324 | CoercGraph.NotMetaClosed
1325 | CoercGraph.NotHandled _ -> raise exn
1326 | CoercGraph.SomeCoercion candidates ->
1328 HExtlib.list_findopt
1330 let t = Cic.Appl [coerc;x] in
1331 debug_print (lazy ("Tentative " ^ CicMetaSubst.ppterm subst t));
1333 (* we want this to be available in the error handler fo the
1334 * following (so it has its own try. *)
1335 let t,tty,subst,metasenv,ugraph =
1336 type_of_aux subst metasenv context t ugraph
1339 let metasenv, hetype' =
1340 mk_prod_of_metas metasenv context subst remainder
1343 (" unif: " ^ CicMetaSubst.ppterm subst tty ^ " = " ^
1344 CicMetaSubst.ppterm subst hetype'));
1345 let subst,metasenv,ugraph =
1346 fo_unif_subst_eat_prods
1347 subst context metasenv tty hetype' ugraph
1349 debug_print (lazy " success!");
1350 Some (subst,metasenv,ugraph,tty,t,remainder)
1352 | Uncertain _ | RefineFailure _
1353 | CicUnification.UnificationFailure _
1354 | CicUnification.Uncertain _ ->
1356 let subst,metasenv,ugraph,hetype',he,args_bo_and_ty =
1358 metasenv context subst t tty remainder ugraph
1360 Some (subst,metasenv,ugraph,hetype',he,args_bo_and_ty)
1361 with Uncertain _ | RefineFailure _ -> None
1362 with Uncertain _ | RefineFailure _ -> None)
1365 | Some(subst,metasenv,ugraph,hetype',he,args_bo_and_ty)->
1366 subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1368 more_args_than_expected localization_tbl
1369 subst he context hetype args_bo_and_ty exn
1370 (* }}} end coercion to funclass stuff *)
1371 (* }}} end fix_arity *)
1373 (* aux function to process the type of the head and the args in parallel *)
1374 let rec eat_prods_and_args
1375 pristinemenv metasenv subst context pristinehe he hetype ugraph newargs
1379 | [] -> newargs,subst,metasenv,he,hetype,ugraph
1380 | (hete, hety)::tl ->
1381 match (CicReduction.whd ~subst context hetype) with
1382 | Cic.Prod (n,s,t) ->
1383 let arg,subst,metasenv,ugraph1 =
1385 let subst,metasenv,ugraph1 =
1386 fo_unif_subst_eat_prods2
1387 subst context metasenv hety s ugraph
1389 (hete,hety),subst,metasenv,ugraph1
1390 (* {{{ we search a coercion from hety to s if fails *)
1391 with RefineFailure _ | Uncertain _ as exn
1392 when allow_coercions && !insert_coercions ->
1393 let coer, tgt_carr =
1394 let carr t subst context =
1395 CicReduction.whd ~delta:false
1396 context (CicMetaSubst.apply_subst subst t )
1398 let c_hety = carr hety subst context in
1399 let c_s = carr s subst context in
1400 CoercGraph.look_for_coercion c_hety c_s, c_s
1403 | CoercGraph.NoCoercion
1404 | CoercGraph.NotHandled _ ->
1405 enrich localization_tbl hete
1407 (lazy ("The term " ^
1408 CicMetaSubst.ppterm_in_context subst hete
1409 context ^ " has type " ^
1410 CicMetaSubst.ppterm_in_context subst hety
1411 context ^ " but is here used with type " ^
1412 CicMetaSubst.ppterm_in_context subst s context
1413 (* "\nReason: " ^ Lazy.force e*))))
1414 | CoercGraph.NotMetaClosed ->
1415 enrich localization_tbl hete
1417 (lazy ("The term " ^
1418 CicMetaSubst.ppterm_in_context subst hete
1419 context ^ " has type " ^
1420 CicMetaSubst.ppterm_in_context subst hety
1421 context ^ " but is here used with type " ^
1422 CicMetaSubst.ppterm_in_context subst s context
1423 (* "\nReason: " ^ Lazy.force e*))))
1424 | CoercGraph.SomeCoercion candidates ->
1426 HExtlib.list_findopt
1429 let t = Cic.Appl[c;hete] in
1430 let newt,newhety,subst,metasenv,ugraph =
1431 type_of_aux subst metasenv context
1434 let newt, newty, subst, metasenv, ugraph =
1435 avoid_double_coercion context subst metasenv
1436 ugraph newt tgt_carr
1438 let subst,metasenv,ugraph1 =
1439 fo_unif_subst subst context metasenv
1442 Some ((newt,newty), subst, metasenv, ugraph)
1443 with Uncertain _ | RefineFailure _ -> None)
1446 (match selected with
1449 enrich localization_tbl hete
1451 (lazy ("The term " ^
1452 CicMetaSubst.ppterm_in_context subst hete
1453 context ^ " has type " ^
1454 CicMetaSubst.ppterm_in_context subst hety
1455 context ^ " but is here used with type " ^
1456 CicMetaSubst.ppterm_in_context subst s context
1457 (* "\nReason: " ^ Lazy.force e*)))) exn))
1459 enrich localization_tbl hete
1461 (lazy ("The term " ^
1462 CicMetaSubst.ppterm_in_context subst hete
1463 context ^ " has type " ^
1464 CicMetaSubst.ppterm_in_context subst hety
1465 context ^ " but is here used with type " ^
1466 CicMetaSubst.ppterm_in_context subst s context ^
1467 "\nReason: " ^ Printexc.to_string exn))) exn
1468 (* }}} end coercion stuff *)
1470 eat_prods_and_args pristinemenv metasenv subst context pristinehe he
1471 (CicSubstitution.subst (fst arg) t)
1472 ugraph1 (newargs@[arg]) tl
1475 let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1477 pristinemenv context subst he hetype
1478 (newargs@[hete,hety]@tl) ugraph
1480 eat_prods_and_args metasenv
1481 metasenv subst context pristinehe he hetype' ugraph [] args_bo_and_ty
1482 with RefineFailure _ | Uncertain _ as exn ->
1483 (* unable to fix arity *)
1484 more_args_than_expected localization_tbl
1485 subst he context hetype args_bo_and_ty exn
1488 (* first we check if we are in the simple case of a meta closed term *)
1489 let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1490 if CicUtil.is_meta_closed hetype then
1491 (* this optimization is to postpone fix_arity (the most common case)*)
1492 subst,metasenv,ugraph,hetype,he,args_bo_and_ty
1494 (* this (says CSC) is also useful to infer dependent types *)
1496 fix_arity metasenv context subst he hetype args_bo_and_ty ugraph
1497 with RefineFailure _ | Uncertain _ as exn ->
1498 (* unable to fix arity *)
1499 more_args_than_expected localization_tbl
1500 subst he context hetype args_bo_and_ty exn
1502 let coerced_args,subst,metasenv,he,t,ugraph =
1504 metasenv metasenv subst context he he hetype' ugraph1 [] args_bo_and_ty
1506 he,(List.map fst coerced_args),t,subst,metasenv,ugraph
1509 (* eat prods ends here! *)
1511 let t',ty,subst',metasenv',ugraph1 =
1512 type_of_aux [] metasenv context t ugraph
1514 let substituted_t = CicMetaSubst.apply_subst subst' t' in
1515 let substituted_ty = CicMetaSubst.apply_subst subst' ty in
1516 (* Andrea: ho rimesso qui l'applicazione della subst al
1517 metasenv dopo che ho droppato l'invariante che il metsaenv
1518 e' sempre istanziato *)
1519 let substituted_metasenv =
1520 CicMetaSubst.apply_subst_metasenv subst' metasenv' in
1522 (* substituted_t,substituted_ty,substituted_metasenv *)
1523 (* ANDREA: spostare tutta questa robaccia da un altra parte *)
1525 FreshNamesGenerator.clean_dummy_dependent_types substituted_t in
1527 FreshNamesGenerator.clean_dummy_dependent_types substituted_ty in
1528 let cleaned_metasenv =
1530 (function (n,context,ty) ->
1531 let ty' = FreshNamesGenerator.clean_dummy_dependent_types ty in
1536 | Some (n, Cic.Decl t) ->
1538 Cic.Decl (FreshNamesGenerator.clean_dummy_dependent_types t))
1539 | Some (n, Cic.Def (bo,ty)) ->
1540 let bo' = FreshNamesGenerator.clean_dummy_dependent_types bo in
1545 Some (FreshNamesGenerator.clean_dummy_dependent_types ty)
1547 Some (n, Cic.Def (bo',ty'))
1551 ) substituted_metasenv
1553 (cleaned_t,cleaned_ty,cleaned_metasenv,ugraph1)
1556 let undebrujin uri typesno tys t =
1559 (fun (name,_,_,_) (i,t) ->
1560 (* here the explicit_named_substituion is assumed to be *)
1562 let t' = Cic.MutInd (uri,i,[]) in
1563 let t = CicSubstitution.subst t' t in
1565 ) tys (typesno - 1,t))
1567 let map_first_n n start f g l =
1568 let rec aux acc k l =
1571 | [] -> raise (Invalid_argument "map_first_n")
1572 | hd :: tl -> f hd k (aux acc (k+1) tl)
1578 (*CSC: this is a very rough approximation; to be finished *)
1579 let are_all_occurrences_positive metasenv ugraph uri tys leftno =
1580 let subst,metasenv,ugraph,tys =
1582 (fun (name,ind,arity,cl) (subst,metasenv,ugraph,acc) ->
1583 let subst,metasenv,ugraph,cl =
1585 (fun (name,ty) (subst,metasenv,ugraph,acc) ->
1586 let rec aux ctx k subst = function
1587 | Cic.Appl((Cic.MutInd (uri',_,_)as hd)::tl) when uri = uri'->
1588 let subst,metasenv,ugraph,tl =
1590 (subst,metasenv,ugraph,[])
1591 (fun t n (subst,metasenv,ugraph,acc) ->
1592 let subst,metasenv,ugraph =
1594 subst ctx metasenv t (Cic.Rel (k-n)) ugraph
1596 subst,metasenv,ugraph,(t::acc))
1597 (fun (s,m,g,acc) tl -> assert(acc=[]);(s,m,g,tl))
1600 subst,metasenv,ugraph,(Cic.Appl (hd::tl))
1601 | Cic.MutInd(uri',_,_) as t when uri = uri'->
1602 subst,metasenv,ugraph,t
1603 | Cic.Prod (name,s,t) ->
1604 let ctx = (Some (name,Cic.Decl s))::ctx in
1605 let subst,metasenv,ugraph,t = aux ctx (k+1) subst t in
1606 subst,metasenv,ugraph,Cic.Prod (name,s,t)
1610 (lazy "not well formed constructor type"))
1612 let subst,metasenv,ugraph,ty = aux [] 0 subst ty in
1613 subst,metasenv,ugraph,(name,ty) :: acc)
1614 cl (subst,metasenv,ugraph,[])
1616 subst,metasenv,ugraph,(name,ind,arity,cl)::acc)
1617 tys ([],metasenv,ugraph,[])
1619 let substituted_tys =
1621 (fun (name,ind,arity,cl) ->
1623 List.map (fun (name, ty) -> name,CicMetaSubst.apply_subst subst ty) cl
1625 name,ind,CicMetaSubst.apply_subst subst arity,cl)
1628 metasenv,ugraph,substituted_tys
1630 let typecheck metasenv uri obj ~localization_tbl =
1631 let ugraph = CicUniv.empty_ugraph in
1633 Cic.Constant (name,Some bo,ty,args,attrs) ->
1634 let bo',boty,metasenv,ugraph =
1635 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1636 let ty',_,metasenv,ugraph =
1637 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1638 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1639 let bo' = CicMetaSubst.apply_subst subst bo' in
1640 let ty' = CicMetaSubst.apply_subst subst ty' in
1641 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1642 Cic.Constant (name,Some bo',ty',args,attrs),metasenv,ugraph
1643 | Cic.Constant (name,None,ty,args,attrs) ->
1644 let ty',_,metasenv,ugraph =
1645 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1647 Cic.Constant (name,None,ty',args,attrs),metasenv,ugraph
1648 | Cic.CurrentProof (name,metasenv',bo,ty,args,attrs) ->
1649 assert (metasenv' = metasenv);
1650 (* Here we do not check the metasenv for correctness *)
1651 let bo',boty,metasenv,ugraph =
1652 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1653 let ty',sort,metasenv,ugraph =
1654 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1658 (* instead of raising Uncertain, let's hope that the meta will become
1661 | _ -> raise (RefineFailure (lazy "The term provided is not a type"))
1663 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1664 let bo' = CicMetaSubst.apply_subst subst bo' in
1665 let ty' = CicMetaSubst.apply_subst subst ty' in
1666 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1667 Cic.CurrentProof (name,metasenv,bo',ty',args,attrs),metasenv,ugraph
1668 | Cic.Variable _ -> assert false (* not implemented *)
1669 | Cic.InductiveDefinition (tys,args,paramsno,attrs) ->
1670 (*CSC: this code is greately simplified and many many checks are missing *)
1671 (*CSC: e.g. the constructors are not required to build their own types, *)
1672 (*CSC: the arities are not required to have as type a sort, etc. *)
1673 let uri = match uri with Some uri -> uri | None -> assert false in
1674 let typesno = List.length tys in
1675 (* first phase: we fix only the types *)
1676 let metasenv,ugraph,tys =
1678 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1679 let ty',_,metasenv,ugraph =
1680 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1682 metasenv,ugraph,(name,b,ty',cl)::res
1683 ) tys (metasenv,ugraph,[]) in
1685 List.rev_map (fun (name,_,ty,_)-> Some (Cic.Name name,Cic.Decl ty)) tys in
1686 (* second phase: we fix only the constructors *)
1687 let metasenv,ugraph,tys =
1689 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1690 let metasenv,ugraph,cl' =
1692 (fun (name,ty) (metasenv,ugraph,res) ->
1694 CicTypeChecker.debrujin_constructor
1695 ~cb:(relocalize localization_tbl) uri typesno ty in
1696 let ty',_,metasenv,ugraph =
1697 type_of_aux' ~localization_tbl metasenv con_context ty ugraph in
1698 let ty' = undebrujin uri typesno tys ty' in
1699 metasenv,ugraph,(name,ty')::res
1700 ) cl (metasenv,ugraph,[])
1702 metasenv,ugraph,(name,b,ty,cl')::res
1703 ) tys (metasenv,ugraph,[]) in
1704 (* third phase: we check the positivity condition *)
1705 let metasenv,ugraph,tys =
1706 are_all_occurrences_positive metasenv ugraph uri tys paramsno
1708 Cic.InductiveDefinition (tys,args,paramsno,attrs),metasenv,ugraph
1711 (* sara' piu' veloce che raffinare da zero? mah.... *)
1712 let pack_coercion metasenv ctx t =
1713 let module C = Cic in
1714 let rec merge_coercions ctx =
1715 let aux = (fun (u,t) -> u,merge_coercions ctx t) in
1717 | C.Rel _ | C.Sort _ | C.Implicit _ as t -> t
1718 | C.Meta (n,subst) ->
1721 (function None -> None | Some t -> Some (merge_coercions ctx t)) subst
1724 | C.Cast (te,ty) -> C.Cast (merge_coercions ctx te, merge_coercions ctx ty)
1725 | C.Prod (name,so,dest) ->
1726 let ctx' = (Some (name,C.Decl so))::ctx in
1727 C.Prod (name, merge_coercions ctx so, merge_coercions ctx' dest)
1728 | C.Lambda (name,so,dest) ->
1729 let ctx' = (Some (name,C.Decl so))::ctx in
1730 C.Lambda (name, merge_coercions ctx so, merge_coercions ctx' dest)
1731 | C.LetIn (name,so,dest) ->
1732 let ctx' = Some (name,(C.Def (so,None)))::ctx in
1733 C.LetIn (name, merge_coercions ctx so, merge_coercions ctx' dest)
1735 let l = List.map (merge_coercions ctx) l in
1737 let b,_,_,_,_ = is_a_double_coercion t in
1738 (* prerr_endline "CANDIDATO!!!!"; *)
1740 let ugraph = CicUniv.empty_ugraph in
1741 let old_insert_coercions = !insert_coercions in
1742 insert_coercions := false;
1743 let newt, _, menv, _ =
1745 type_of_aux' metasenv ctx t ugraph
1746 with RefineFailure _ | Uncertain _ ->
1747 prerr_endline (CicPp.ppterm t);
1750 insert_coercions := old_insert_coercions;
1751 if metasenv <> [] || menv = [] then
1754 (prerr_endline "PUO' SUCCEDERE!!!!!";t)
1757 | C.Var (uri,exp_named_subst) ->
1758 let exp_named_subst = List.map aux exp_named_subst in
1759 C.Var (uri, exp_named_subst)
1760 | C.Const (uri,exp_named_subst) ->
1761 let exp_named_subst = List.map aux exp_named_subst in
1762 C.Const (uri, exp_named_subst)
1763 | C.MutInd (uri,tyno,exp_named_subst) ->
1764 let exp_named_subst = List.map aux exp_named_subst in
1765 C.MutInd (uri,tyno,exp_named_subst)
1766 | C.MutConstruct (uri,tyno,consno,exp_named_subst) ->
1767 let exp_named_subst = List.map aux exp_named_subst in
1768 C.MutConstruct (uri,tyno,consno,exp_named_subst)
1769 | C.MutCase (uri,tyno,out,te,pl) ->
1770 let pl = List.map (merge_coercions ctx) pl in
1771 C.MutCase (uri,tyno,merge_coercions ctx out, merge_coercions ctx te, pl)
1772 | C.Fix (fno, fl) ->
1775 (fun l (n,_,ty,_) -> (Some (C.Name n,C.Decl ty))::l)
1780 (fun (name,idx,ty,bo) ->
1781 (name,idx,merge_coercions ctx ty,merge_coercions ctx' bo))
1785 | C.CoFix (fno, fl) ->
1788 (fun l (n,ty,_) -> (Some (C.Name n,C.Decl ty))::l)
1793 (fun (name,ty,bo) ->
1794 (name, merge_coercions ctx ty, merge_coercions ctx' bo))
1799 merge_coercions ctx t
1802 let pack_coercion_obj obj =
1803 let module C = Cic in
1805 | C.Constant (id, body, ty, params, attrs) ->
1809 | Some body -> Some (pack_coercion [] [] body)
1811 let ty = pack_coercion [] [] ty in
1812 C.Constant (id, body, ty, params, attrs)
1813 | C.Variable (name, body, ty, params, attrs) ->
1817 | Some body -> Some (pack_coercion [] [] body)
1819 let ty = pack_coercion [] [] ty in
1820 C.Variable (name, body, ty, params, attrs)
1821 | C.CurrentProof (name, conjectures, body, ty, params, attrs) ->
1824 (fun (i, ctx, ty) ->
1830 Some (name, C.Decl t) ->
1831 Some (name, C.Decl (pack_coercion conjectures ctx t))
1832 | Some (name, C.Def (t,None)) ->
1833 Some (name,C.Def (pack_coercion conjectures ctx t,None))
1834 | Some (name, C.Def (t,Some ty)) ->
1835 Some (name, C.Def (pack_coercion conjectures ctx t,
1836 Some (pack_coercion conjectures ctx ty)))
1842 ((i,ctx,pack_coercion conjectures ctx ty))
1845 let body = pack_coercion conjectures [] body in
1846 let ty = pack_coercion conjectures [] ty in
1847 C.CurrentProof (name, conjectures, body, ty, params, attrs)
1848 | C.InductiveDefinition (indtys, params, leftno, attrs) ->
1851 (fun (name, ind, arity, cl) ->
1852 let arity = pack_coercion [] [] arity in
1854 List.map (fun (name, ty) -> (name,pack_coercion [] [] ty)) cl
1856 (name, ind, arity, cl))
1859 C.InductiveDefinition (indtys, params, leftno, attrs)
1864 let type_of_aux' metasenv context term =
1867 type_of_aux' metasenv context term in
1869 ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty));
1871 ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []));
1874 | RefineFailure msg as e ->
1875 debug_print (lazy ("@@@ REFINE FAILED: " ^ msg));
1877 | Uncertain msg as e ->
1878 debug_print (lazy ("@@@ REFINE UNCERTAIN: " ^ msg));
1882 let profiler2 = HExtlib.profile "CicRefine"
1884 let type_of_aux' ?localization_tbl metasenv context term ugraph =
1885 profiler2.HExtlib.profile
1886 (type_of_aux' ?localization_tbl metasenv context term) ugraph
1888 let typecheck ~localization_tbl metasenv uri obj =
1889 profiler2.HExtlib.profile (typecheck ~localization_tbl metasenv uri) obj
1891 let _ = DoubleTypeInference.pack_coercion := pack_coercion;;
1892 (* vim:set foldmethod=marker: *)