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 | Sys.Break -> raise exn
82 | _ -> assert false in
85 Cic.CicHash.find localization_tbl t
87 prerr_endline ("!!! NOT LOCALIZED: " ^ CicPp.ppterm t);
90 raise (HExtlib.Localized (loc,exn'))
92 let relocalize localization_tbl oldt newt =
94 let infos = Cic.CicHash.find localization_tbl oldt in
95 Cic.CicHash.remove localization_tbl oldt;
96 Cic.CicHash.add localization_tbl newt infos;
104 | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
105 | (_,_) -> raise (AssertFailure (lazy "split: list too short"))
108 let exp_impl metasenv subst context =
111 let (metasenv', idx) =
112 CicMkImplicit.mk_implicit_type metasenv subst context in
114 CicMkImplicit.identity_relocation_list_for_metavariable context in
115 metasenv', Cic.Meta (idx, irl)
117 let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst [] in
118 metasenv', Cic.Meta (idx, [])
120 let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst context in
122 CicMkImplicit.identity_relocation_list_for_metavariable context in
123 metasenv', Cic.Meta (idx, irl)
127 let is_a_double_coercion t =
129 let rec aux acc = function
131 | x::tl -> aux (acc@[x]) tl
136 let imp = Cic.Implicit None in
137 let dummyres = false,imp, imp,imp,imp in
139 | Cic.Appl (c1::tl) when CoercDb.is_a_coercion' c1 ->
140 (match last_of tl with
141 | sib1,Cic.Appl (c2::tl2) when CoercDb.is_a_coercion' c2 ->
142 let sib2,head = last_of tl2 in
143 true, c1, c2, head,Cic.Appl (c1::sib1@[Cic.Appl
148 let more_args_than_expected
149 localization_tbl metasenv subst he context hetype' tlbody_and_type exn
153 CicMetaSubst.ppterm_in_context ~metasenv subst he context ^
154 " (that has type "^CicMetaSubst.ppterm_in_context ~metasenv subst hetype' context ^
155 ") is here applied to " ^ string_of_int (List.length tlbody_and_type) ^
156 " arguments that are more than expected")
158 enrich localization_tbl he ~f:(fun _-> msg) exn
161 let mk_prod_of_metas metasenv context' subst args =
162 let rec mk_prod metasenv context' = function
164 let (metasenv, idx) =
165 CicMkImplicit.mk_implicit_type metasenv subst context'
168 CicMkImplicit.identity_relocation_list_for_metavariable context'
170 metasenv,Cic.Meta (idx, irl)
172 let (metasenv, idx) =
173 CicMkImplicit.mk_implicit_type metasenv subst context'
176 CicMkImplicit.identity_relocation_list_for_metavariable context'
178 let meta = Cic.Meta (idx,irl) in
180 (* The name must be fresh for context. *)
181 (* Nevertheless, argty is well-typed only in context. *)
182 (* Thus I generate a name (name_hint) in context and *)
183 (* then I generate a name --- using the hint name_hint *)
184 (* --- that is fresh in context'. *)
186 (* Cic.Name "pippo" *)
187 FreshNamesGenerator.mk_fresh_name ~subst metasenv
188 (* (CicMetaSubst.apply_subst_metasenv subst metasenv) *)
189 (CicMetaSubst.apply_subst_context subst context')
191 ~typ:(CicMetaSubst.apply_subst subst argty)
193 (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
194 FreshNamesGenerator.mk_fresh_name ~subst
195 [] context' name_hint ~typ:(Cic.Sort Cic.Prop)
197 let metasenv,target =
198 mk_prod metasenv ((Some (name, Cic.Decl meta))::context') tl
200 metasenv,Cic.Prod (name,meta,target)
202 mk_prod metasenv context' args
205 let rec type_of_constant uri ugraph =
206 let module C = Cic in
207 let module R = CicReduction in
208 let module U = UriManager in
209 let _ = CicTypeChecker.typecheck uri in
212 CicEnvironment.get_cooked_obj ugraph uri
213 with Not_found -> assert false
216 C.Constant (_,_,ty,_,_) -> ty,u
217 | C.CurrentProof (_,_,_,ty,_,_) -> ty,u
221 (lazy ("Unknown constant definition " ^ U.string_of_uri uri)))
223 and type_of_variable uri ugraph =
224 let module C = Cic in
225 let module R = CicReduction in
226 let module U = UriManager in
227 let _ = CicTypeChecker.typecheck uri in
230 CicEnvironment.get_cooked_obj ugraph uri
231 with Not_found -> assert false
234 C.Variable (_,_,ty,_,_) -> ty,u
238 (lazy ("Unknown variable definition " ^ UriManager.string_of_uri uri)))
240 and type_of_mutual_inductive_defs uri i ugraph =
241 let module C = Cic in
242 let module R = CicReduction in
243 let module U = UriManager in
244 let _ = CicTypeChecker.typecheck uri in
247 CicEnvironment.get_cooked_obj ugraph uri
248 with Not_found -> assert false
251 C.InductiveDefinition (dl,_,_,_) ->
252 let (_,_,arity,_) = List.nth dl i in
257 (lazy ("Unknown mutual inductive definition " ^ U.string_of_uri uri)))
259 and type_of_mutual_inductive_constr uri i j ugraph =
260 let module C = Cic in
261 let module R = CicReduction in
262 let module U = UriManager in
263 let _ = CicTypeChecker.typecheck uri in
266 CicEnvironment.get_cooked_obj ugraph uri
267 with Not_found -> assert false
270 C.InductiveDefinition (dl,_,_,_) ->
271 let (_,_,_,cl) = List.nth dl i in
272 let (_,ty) = List.nth cl (j-1) in
278 ("Unkown mutual inductive definition " ^ U.string_of_uri uri)))
281 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
283 (* the check_branch function checks if a branch of a case is refinable.
284 It returns a pair (outype_instance,args), a subst and a metasenv.
285 outype_instance is the expected result of applying the case outtype
287 The problem is that outype is in general unknown, and we should
288 try to synthesize it from the above information, that is in general
289 a second order unification problem. *)
291 and check_branch n context metasenv subst left_args_no actualtype term expectedtype ugraph =
292 let module C = Cic in
293 (* let module R = CicMetaSubst in *)
294 let module R = CicReduction in
295 match R.whd ~subst context expectedtype with
297 (n,context,actualtype, [term]), subst, metasenv, ugraph
298 | C.Appl (C.MutInd (_,_,_)::tl) ->
299 let (_,arguments) = split tl left_args_no in
300 (n,context,actualtype, arguments@[term]), subst, metasenv, ugraph
301 | C.Prod (name,so,de) ->
302 (* we expect that the actual type of the branch has the due
304 (match R.whd ~subst context actualtype with
305 C.Prod (name',so',de') ->
306 let subst, metasenv, ugraph1 =
307 fo_unif_subst subst context metasenv so so' ugraph in
309 (match CicSubstitution.lift 1 term with
310 C.Appl l -> C.Appl (l@[C.Rel 1])
311 | t -> C.Appl [t ; C.Rel 1]) in
312 (* we should also check that the name variable is anonymous in
313 the actual type de' ?? *)
315 ((Some (name,(C.Decl so)))::context)
316 metasenv subst left_args_no de' term' de ugraph1
317 | _ -> raise (AssertFailure (lazy "Wrong number of arguments")))
318 | _ -> raise (AssertFailure (lazy "Prod or MutInd expected"))
320 and type_of_aux' ?(localization_tbl = Cic.CicHash.create 1) metasenv context t
323 let rec type_of_aux subst metasenv context t ugraph =
324 let module C = Cic in
325 let module S = CicSubstitution in
326 let module U = UriManager in
327 let try_coercion t subst context ugraph coercion_tgt (metasenv,last,coerced) =
328 let subst,metasenv,ugraph =
329 fo_unif_subst subst context metasenv last t ugraph
332 let newt, tty, subst, metasenv, ugraph =
333 avoid_double_coercion context subst metasenv ugraph coerced
336 Some (newt, tty, subst, metasenv, ugraph)
338 | RefineFailure _ | Uncertain _ -> None
340 let (t',_,_,_,_) as res =
345 match List.nth context (n - 1) with
346 Some (_,C.Decl ty) ->
347 t,S.lift n ty,subst,metasenv, ugraph
348 | Some (_,C.Def (_,Some ty)) ->
349 t,S.lift n ty,subst,metasenv, ugraph
350 | Some (_,C.Def (bo,None)) ->
352 (* if it is in the context it must be already well-typed*)
353 CicTypeChecker.type_of_aux' ~subst metasenv context
356 t,ty,subst,metasenv,ugraph
358 enrich localization_tbl t
359 (RefineFailure (lazy "Rel to hidden hypothesis"))
362 enrich localization_tbl t
363 (RefineFailure (lazy "Not a closed term")))
364 | C.Var (uri,exp_named_subst) ->
365 let exp_named_subst',subst',metasenv',ugraph1 =
366 check_exp_named_subst
367 subst metasenv context exp_named_subst ugraph
369 let ty_uri,ugraph1 = type_of_variable uri ugraph in
371 CicSubstitution.subst_vars exp_named_subst' ty_uri
373 C.Var (uri,exp_named_subst'),ty,subst',metasenv',ugraph1
376 let (canonical_context, term,ty) =
377 CicUtil.lookup_subst n subst
379 let l',subst',metasenv',ugraph1 =
380 check_metasenv_consistency n subst metasenv context
381 canonical_context l ugraph
383 (* trust or check ??? *)
384 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
385 subst', metasenv', ugraph1
386 (* type_of_aux subst metasenv
387 context (CicSubstitution.subst_meta l term) *)
388 with CicUtil.Subst_not_found _ ->
389 let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
390 let l',subst',metasenv', ugraph1 =
391 check_metasenv_consistency n subst metasenv context
392 canonical_context l ugraph
394 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
395 subst', metasenv',ugraph1)
396 | C.Sort (C.Type tno) ->
397 let tno' = CicUniv.fresh() in
399 let ugraph1 = CicUniv.add_gt tno' tno ugraph in
400 t,(C.Sort (C.Type tno')),subst,metasenv,ugraph1
402 CicUniv.UniverseInconsistency msg -> raise (RefineFailure msg))
404 t,C.Sort (C.Type (CicUniv.fresh())),subst,metasenv,ugraph
405 | C.Implicit infos ->
406 let metasenv',t' = exp_impl metasenv subst context infos in
407 type_of_aux subst metasenv' context t' ugraph
409 let ty',_,subst',metasenv',ugraph1 =
410 type_of_aux subst metasenv context ty ugraph
412 let te',inferredty,subst'',metasenv'',ugraph2 =
413 type_of_aux subst' metasenv' context te ugraph1
416 let subst''',metasenv''',ugraph3 =
417 fo_unif_subst subst'' context metasenv''
418 inferredty ty' ugraph2
420 C.Cast (te',ty'),ty',subst''',metasenv''',ugraph3
423 enrich localization_tbl te'
426 CicMetaSubst.ppterm_in_context metasenv'' subst'' te'
427 context ^ " has type " ^
428 CicMetaSubst.ppterm_in_context metasenv'' subst'' inferredty
429 context ^ " but is here used with type " ^
430 CicMetaSubst.ppterm_in_context metasenv'' subst'' ty' context)) exn
432 | C.Prod (name,s,t) ->
433 let carr t subst context = CicMetaSubst.apply_subst subst t in
434 let coerce_to_sort in_source tgt_sort t type_to_coerce
435 subst context metasenv uragph
437 if not !insert_coercions then
438 t,type_to_coerce,subst,metasenv,ugraph
440 let coercion_src = carr type_to_coerce subst context in
441 match coercion_src with
443 t,type_to_coerce,subst,metasenv,ugraph
444 | Cic.Meta _ as meta ->
445 t, meta, subst, metasenv, ugraph
446 | Cic.Cast _ as cast ->
447 t, cast, subst, metasenv, ugraph
449 let coercion_tgt = carr (Cic.Sort tgt_sort) subst context in
451 CoercGraph.look_for_coercion metasenv subst context coercion_src coercion_tgt
454 | CoercGraph.NoCoercion
455 | CoercGraph.NotHandled _ ->
456 enrich localization_tbl t
459 CicMetaSubst.ppterm_in_context ~metasenv subst t context ^
460 " is not a type since it has type " ^
461 CicMetaSubst.ppterm_in_context ~metasenv
462 subst coercion_src context ^ " that is not a sort")))
463 | CoercGraph.NotMetaClosed ->
464 enrich localization_tbl t
467 CicMetaSubst.ppterm_in_context ~metasenv subst t context ^
468 " is not a type since it has type " ^
469 CicMetaSubst.ppterm_in_context ~metasenv
470 subst coercion_src context ^ " that is not a sort")))
471 | CoercGraph.SomeCoercion candidates ->
474 (try_coercion t subst context ugraph coercion_tgt)
480 enrich localization_tbl t
483 CicMetaSubst.ppterm_in_context ~metasenv
485 " is not a type since it has type " ^
486 CicMetaSubst.ppterm_in_context ~metasenv
487 subst coercion_src context ^
488 " that is not a sort"))))
490 let s',sort1,subst',metasenv',ugraph1 =
491 type_of_aux subst metasenv context s ugraph
493 let s',sort1,subst', metasenv',ugraph1 =
494 coerce_to_sort true (Cic.Type(CicUniv.fresh()))
495 s' sort1 subst' context metasenv' ugraph1
497 let context_for_t = ((Some (name,(C.Decl s')))::context) in
498 let t',sort2,subst'',metasenv'',ugraph2 =
499 type_of_aux subst' metasenv'
500 context_for_t t ugraph1
502 let t',sort2,subst'',metasenv'',ugraph2 =
503 coerce_to_sort false (Cic.Type(CicUniv.fresh()))
504 t' sort2 subst'' context_for_t metasenv'' ugraph2
506 let sop,subst''',metasenv''',ugraph3 =
507 sort_of_prod localization_tbl subst'' metasenv''
508 context (name,s') t' (sort1,sort2) ugraph2
510 C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
511 | C.Lambda (n,s,t) ->
512 let s',sort1,subst',metasenv',ugraph1 =
513 type_of_aux subst metasenv context s ugraph in
514 let s',sort1,subst',metasenv',ugraph1 =
515 if not !insert_coercions then
516 s',sort1, subst', metasenv', ugraph1
518 match CicReduction.whd ~subst:subst' context sort1 with
519 | C.Meta _ | C.Sort _ -> s',sort1, subst', metasenv', ugraph1
521 let coercion_tgt = Cic.Sort (Cic.Type (CicUniv.fresh())) in
523 CoercGraph.look_for_coercion metasenv subst context coercion_src coercion_tgt
526 | CoercGraph.NoCoercion
527 | CoercGraph.NotHandled _ ->
528 enrich localization_tbl s'
531 CicMetaSubst.ppterm_in_context ~metasenv subst s' context ^
532 " is not a type since it has type " ^
533 CicMetaSubst.ppterm_in_context ~metasenv
534 subst coercion_src context ^ " that is not a sort")))
535 | CoercGraph.NotMetaClosed ->
536 enrich localization_tbl s'
539 CicMetaSubst.ppterm_in_context ~metasenv subst s' context ^
540 " is not a type since it has type " ^
541 CicMetaSubst.ppterm_in_context ~metasenv
542 subst coercion_src context ^ " that is not a sort")))
543 | CoercGraph.SomeCoercion candidates ->
546 (try_coercion s' subst' context ugraph1 coercion_tgt)
552 enrich localization_tbl s'
555 CicMetaSubst.ppterm_in_context ~metasenv subst s' context ^
556 " is not a type since it has type " ^
557 CicMetaSubst.ppterm_in_context ~metasenv
558 subst coercion_src context ^
559 " that is not a sort")))
561 let context_for_t = ((Some (n,(C.Decl s')))::context) in
562 let t',type2,subst'',metasenv'',ugraph2 =
563 type_of_aux subst' metasenv' context_for_t t ugraph1
565 C.Lambda (n,s',t'),C.Prod (n,s',type2),
566 subst'',metasenv'',ugraph2
568 (* only to check if s is well-typed *)
569 let s',ty,subst',metasenv',ugraph1 =
570 type_of_aux subst metasenv context s ugraph
572 let context_for_t = ((Some (n,(C.Def (s',Some ty))))::context) in
574 let t',inferredty,subst'',metasenv'',ugraph2 =
575 type_of_aux subst' metasenv'
576 context_for_t t ugraph1
578 (* One-step LetIn reduction.
579 * Even faster than the previous solution.
580 * Moreover the inferred type is closer to the expected one.
583 CicSubstitution.subst ~avoid_beta_redexes:true s' inferredty,
584 subst'',metasenv'',ugraph2
585 | C.Appl (he::((_::_) as tl)) ->
586 let he',hetype,subst',metasenv',ugraph1 =
587 type_of_aux subst metasenv context he ugraph
589 let tlbody_and_type,subst'',metasenv'',ugraph2 =
590 typeof_list subst' metasenv' context ugraph1 tl
592 let coerced_he,coerced_args,applty,subst''',metasenv''',ugraph3 =
593 eat_prods true subst'' metasenv'' context
594 he' hetype tlbody_and_type ugraph2
596 let newappl = (C.Appl (coerced_he::coerced_args)) in
597 avoid_double_coercion
598 context subst''' metasenv''' ugraph3 newappl applty
599 | C.Appl _ -> assert false
600 | C.Const (uri,exp_named_subst) ->
601 let exp_named_subst',subst',metasenv',ugraph1 =
602 check_exp_named_subst subst metasenv context
603 exp_named_subst ugraph in
604 let ty_uri,ugraph2 = type_of_constant uri ugraph1 in
606 CicSubstitution.subst_vars exp_named_subst' ty_uri
608 C.Const (uri,exp_named_subst'),cty,subst',metasenv',ugraph2
609 | C.MutInd (uri,i,exp_named_subst) ->
610 let exp_named_subst',subst',metasenv',ugraph1 =
611 check_exp_named_subst subst metasenv context
612 exp_named_subst ugraph
614 let ty_uri,ugraph2 = type_of_mutual_inductive_defs uri i ugraph1 in
616 CicSubstitution.subst_vars exp_named_subst' ty_uri in
617 C.MutInd (uri,i,exp_named_subst'),cty,subst',metasenv',ugraph2
618 | C.MutConstruct (uri,i,j,exp_named_subst) ->
619 let exp_named_subst',subst',metasenv',ugraph1 =
620 check_exp_named_subst subst metasenv context
621 exp_named_subst ugraph
624 type_of_mutual_inductive_constr uri i j ugraph1
627 CicSubstitution.subst_vars exp_named_subst' ty_uri
629 C.MutConstruct (uri,i,j,exp_named_subst'),cty,subst',
631 | C.MutCase (uri, i, outtype, term, pl) ->
632 (* first, get the inductive type (and noparams)
633 * in the environment *)
634 let (_,b,arity,constructors), expl_params, no_left_params,ugraph =
635 let _ = CicTypeChecker.typecheck uri in
636 let obj,u = CicEnvironment.get_cooked_obj ugraph uri in
638 C.InductiveDefinition (l,expl_params,parsno,_) ->
639 List.nth l i , expl_params, parsno, u
641 enrich localization_tbl t
643 (lazy ("Unkown mutual inductive definition " ^
644 U.string_of_uri uri)))
646 let rec count_prod t =
647 match CicReduction.whd ~subst context t with
648 C.Prod (_, _, t) -> 1 + (count_prod t)
651 let no_args = count_prod arity in
652 (* now, create a "generic" MutInd *)
653 let metasenv,left_args =
654 CicMkImplicit.n_fresh_metas metasenv subst context no_left_params
656 let metasenv,right_args =
657 let no_right_params = no_args - no_left_params in
658 if no_right_params < 0 then assert false
659 else CicMkImplicit.n_fresh_metas
660 metasenv subst context no_right_params
662 let metasenv,exp_named_subst =
663 CicMkImplicit.fresh_subst metasenv subst context expl_params in
666 C.MutInd (uri,i,exp_named_subst)
669 (C.MutInd (uri,i,exp_named_subst)::(left_args @ right_args))
671 (* check consistency with the actual type of term *)
672 let term',actual_type,subst,metasenv,ugraph1 =
673 type_of_aux subst metasenv context term ugraph in
674 let expected_type',_, subst, metasenv,ugraph2 =
675 type_of_aux subst metasenv context expected_type ugraph1
677 let actual_type = CicReduction.whd ~subst context actual_type in
678 let subst,metasenv,ugraph3 =
680 fo_unif_subst subst context metasenv
681 expected_type' actual_type ugraph2
684 enrich localization_tbl term' exn
687 CicMetaSubst.ppterm_in_context ~metasenv subst term'
688 context ^ " has type " ^
689 CicMetaSubst.ppterm_in_context ~metasenv subst actual_type
690 context ^ " but is here used with type " ^
691 CicMetaSubst.ppterm_in_context ~metasenv subst expected_type' context))
693 let rec instantiate_prod t =
697 match CicReduction.whd ~subst context t with
699 instantiate_prod (CicSubstitution.subst he t') tl
702 let arity_instantiated_with_left_args =
703 instantiate_prod arity left_args in
704 (* TODO: check if the sort elimination
705 * is allowed: [(I q1 ... qr)|B] *)
706 let (pl',_,outtypeinstances,subst,metasenv,ugraph4) =
708 (fun p (pl,j,outtypeinstances,subst,metasenv,ugraph) ->
710 if left_args = [] then
711 (C.MutConstruct (uri,i,j,exp_named_subst))
714 (C.MutConstruct (uri,i,j,exp_named_subst)::left_args))
716 let p',actual_type,subst,metasenv,ugraph1 =
717 type_of_aux subst metasenv context p ugraph
719 let constructor',expected_type, subst, metasenv,ugraph2 =
720 type_of_aux subst metasenv context constructor ugraph1
722 let outtypeinstance,subst,metasenv,ugraph3 =
724 check_branch 0 context metasenv subst
725 no_left_params actual_type constructor' expected_type
729 enrich localization_tbl constructor'
732 CicMetaSubst.ppterm_in_context metasenv subst p'
733 context ^ " has type " ^
734 CicMetaSubst.ppterm_in_context metasenv subst actual_type
735 context ^ " but is here used with type " ^
736 CicMetaSubst.ppterm_in_context metasenv subst expected_type
740 outtypeinstances@[outtypeinstance],subst,metasenv,ugraph3))
741 pl ([],List.length pl,[],subst,metasenv,ugraph3)
744 (* we are left to check that the outype matches his instances.
745 The easy case is when the outype is specified, that amount
746 to a trivial check. Otherwise, we should guess a type from
750 let outtype,outtypety, subst, metasenv,ugraph4 =
751 type_of_aux subst metasenv context outtype ugraph4 in
754 (let candidate,ugraph5,metasenv,subst =
755 let exp_name_subst, metasenv =
757 CicEnvironment.get_cooked_obj CicUniv.empty_ugraph uri
759 let uris = CicUtil.params_of_obj o in
761 fun uri (acc,metasenv) ->
762 let metasenv',new_meta =
763 CicMkImplicit.mk_implicit metasenv subst context
766 CicMkImplicit.identity_relocation_list_for_metavariable
769 (uri, Cic.Meta(new_meta,irl))::acc, metasenv'
773 match left_args,right_args with
774 [],[] -> Cic.MutInd(uri, i, exp_name_subst)
776 let rec mk_right_args =
779 | n -> (Cic.Rel n)::(mk_right_args (n - 1))
781 let right_args_no = List.length right_args in
782 let lifted_left_args =
783 List.map (CicSubstitution.lift right_args_no) left_args
785 Cic.Appl (Cic.MutInd(uri,i,exp_name_subst)::
786 (lifted_left_args @ mk_right_args right_args_no))
789 FreshNamesGenerator.mk_fresh_name ~subst metasenv
790 context Cic.Anonymous ~typ:ty
792 match outtypeinstances with
794 let extended_context =
795 let rec add_right_args =
797 Cic.Prod (name,ty,t) ->
798 Some (name,Cic.Decl ty)::(add_right_args t)
801 (Some (fresh_name,Cic.Decl ty))::
803 (add_right_args arity_instantiated_with_left_args))@
806 let metasenv,new_meta =
807 CicMkImplicit.mk_implicit metasenv subst extended_context
810 CicMkImplicit.identity_relocation_list_for_metavariable
813 let rec add_lambdas b =
815 Cic.Prod (name,ty,t) ->
816 Cic.Lambda (name,ty,(add_lambdas b t))
817 | _ -> Cic.Lambda (fresh_name, ty, b)
820 add_lambdas (Cic.Meta (new_meta,irl))
821 arity_instantiated_with_left_args
823 (Some candidate),ugraph4,metasenv,subst
824 | (constructor_args_no,_,instance,_)::tl ->
826 let instance',subst,metasenv =
827 CicMetaSubst.delift_rels subst metasenv
828 constructor_args_no instance
830 let candidate,ugraph,metasenv,subst =
832 fun (candidate_oty,ugraph,metasenv,subst)
833 (constructor_args_no,_,instance,_) ->
834 match candidate_oty with
835 | None -> None,ugraph,metasenv,subst
838 let instance',subst,metasenv =
839 CicMetaSubst.delift_rels subst metasenv
840 constructor_args_no instance
842 let subst,metasenv,ugraph =
843 fo_unif_subst subst context metasenv
846 candidate_oty,ugraph,metasenv,subst
848 CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable
849 | CicUnification.UnificationFailure _
850 | CicUnification.Uncertain _ ->
851 None,ugraph,metasenv,subst
852 ) (Some instance',ugraph4,metasenv,subst) tl
855 | None -> None, ugraph,metasenv,subst
857 let rec add_lambdas n b =
859 Cic.Prod (name,ty,t) ->
860 Cic.Lambda (name,ty,(add_lambdas (n + 1) b t))
862 Cic.Lambda (fresh_name, ty,
863 CicSubstitution.lift (n + 1) t)
866 (add_lambdas 0 t arity_instantiated_with_left_args),
867 ugraph,metasenv,subst
868 with CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
869 None,ugraph4,metasenv,subst
872 | None -> raise (Uncertain (lazy "can't solve an higher order unification problem"))
874 let subst,metasenv,ugraph =
876 fo_unif_subst subst context metasenv
877 candidate outtype ugraph5
879 exn -> assert false(* unification against a metavariable *)
881 C.MutCase (uri, i, outtype, term', pl'),
882 CicReduction.head_beta_reduce
883 (CicMetaSubst.apply_subst subst
884 (Cic.Appl (outtype::right_args@[term']))),
885 subst,metasenv,ugraph)
886 | _ -> (* easy case *)
887 let tlbody_and_type,subst,metasenv,ugraph4 =
888 typeof_list subst metasenv context ugraph4 (right_args @ [term'])
890 let _,_,_,subst,metasenv,ugraph4 =
891 eat_prods false subst metasenv context
892 outtype outtypety tlbody_and_type ugraph4
894 let _,_, subst, metasenv,ugraph5 =
895 type_of_aux subst metasenv context
896 (C.Appl ((outtype :: right_args) @ [term'])) ugraph4
898 let (subst,metasenv,ugraph6) =
900 (fun (subst,metasenv,ugraph)
901 p (constructor_args_no,context,instance,args)
906 CicSubstitution.lift constructor_args_no outtype
908 C.Appl (outtype'::args)
910 CicReduction.whd ~subst context appl
913 fo_unif_subst subst context metasenv instance instance'
917 enrich localization_tbl p exn
920 CicMetaSubst.ppterm_in_context ~metasenv subst p
921 context ^ " has type " ^
922 CicMetaSubst.ppterm_in_context ~metasenv subst instance'
923 context ^ " but is here used with type " ^
924 CicMetaSubst.ppterm_in_context ~metasenv subst instance
926 (subst,metasenv,ugraph5) pl' outtypeinstances
928 C.MutCase (uri, i, outtype, term', pl'),
929 CicReduction.head_beta_reduce
930 (CicMetaSubst.apply_subst subst
931 (C.Appl(outtype::right_args@[term]))),
932 subst,metasenv,ugraph6)
934 let fl_ty',subst,metasenv,types,ugraph1,len =
936 (fun (fl,subst,metasenv,types,ugraph,len) (n,_,ty,_) ->
937 let ty',_,subst',metasenv',ugraph1 =
938 type_of_aux subst metasenv context ty ugraph
940 fl @ [ty'],subst',metasenv',
941 Some (C.Name n,(C.Decl (CicSubstitution.lift len ty')))
942 :: types, ugraph, len+1
943 ) ([],subst,metasenv,[],ugraph,0) fl
945 let context' = types@context in
946 let fl_bo',subst,metasenv,ugraph2 =
948 (fun (fl,subst,metasenv,ugraph) ((name,x,_,bo),ty) ->
949 let bo',ty_of_bo,subst,metasenv,ugraph1 =
950 type_of_aux subst metasenv context' bo ugraph in
951 let expected_ty = CicSubstitution.lift len ty in
952 let subst',metasenv',ugraph' =
954 fo_unif_subst subst context' metasenv
955 ty_of_bo expected_ty ugraph1
958 enrich localization_tbl bo exn
961 CicMetaSubst.ppterm_in_context ~metasenv subst bo
962 context' ^ " has type " ^
963 CicMetaSubst.ppterm_in_context ~metasenv subst ty_of_bo
964 context' ^ " but is here used with type " ^
965 CicMetaSubst.ppterm_in_context ~metasenv subst expected_ty
968 fl @ [bo'] , subst',metasenv',ugraph'
969 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
971 let ty = List.nth fl_ty' i in
972 (* now we have the new ty in fl_ty', the new bo in fl_bo',
973 * and we want the new fl with bo' and ty' injected in the right
976 let rec map3 f l1 l2 l3 =
979 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
982 let fl'' = map3 (fun ty' bo' (name,x,ty,bo) -> (name,x,ty',bo') )
985 C.Fix (i,fl''),ty,subst,metasenv,ugraph2
987 let fl_ty',subst,metasenv,types,ugraph1,len =
989 (fun (fl,subst,metasenv,types,ugraph,len) (n,ty,_) ->
990 let ty',_,subst',metasenv',ugraph1 =
991 type_of_aux subst metasenv context ty ugraph
993 fl @ [ty'],subst',metasenv',
994 Some (C.Name n,(C.Decl (CicSubstitution.lift len ty'))) ::
995 types, ugraph1, len+1
996 ) ([],subst,metasenv,[],ugraph,0) fl
998 let context' = types@context in
999 let fl_bo',subst,metasenv,ugraph2 =
1001 (fun (fl,subst,metasenv,ugraph) ((name,_,bo),ty) ->
1002 let bo',ty_of_bo,subst,metasenv,ugraph1 =
1003 type_of_aux subst metasenv context' bo ugraph in
1004 let expected_ty = CicSubstitution.lift len ty in
1005 let subst',metasenv',ugraph' =
1007 fo_unif_subst subst context' metasenv
1008 ty_of_bo expected_ty ugraph1
1011 enrich localization_tbl bo exn
1014 CicMetaSubst.ppterm_in_context ~metasenv subst bo
1015 context' ^ " has type " ^
1016 CicMetaSubst.ppterm_in_context ~metasenv subst ty_of_bo
1017 context' ^ " but is here used with type " ^
1018 CicMetaSubst.ppterm_in_context ~metasenv subst expected_ty
1021 fl @ [bo'],subst',metasenv',ugraph'
1022 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
1024 let ty = List.nth fl_ty' i in
1025 (* now we have the new ty in fl_ty', the new bo in fl_bo',
1026 * and we want the new fl with bo' and ty' injected in the right
1029 let rec map3 f l1 l2 l3 =
1032 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
1035 let fl'' = map3 (fun ty' bo' (name,ty,bo) -> (name,ty',bo') )
1038 C.CoFix (i,fl''),ty,subst,metasenv,ugraph2
1040 relocalize localization_tbl t t';
1043 (* check_metasenv_consistency checks that the "canonical" context of a
1044 metavariable is consitent - up to relocation via the relocation list l -
1045 with the actual context *)
1046 and check_metasenv_consistency
1047 metano subst metasenv context canonical_context l ugraph
1049 let module C = Cic in
1050 let module R = CicReduction in
1051 let module S = CicSubstitution in
1052 let lifted_canonical_context =
1056 | (Some (n,C.Decl t))::tl ->
1057 (Some (n,C.Decl (S.subst_meta l (S.lift i t))))::(aux (i+1) tl)
1058 | (Some (n,C.Def (t,None)))::tl ->
1059 (Some (n,C.Def ((S.subst_meta l (S.lift i t)),None)))::(aux (i+1) tl)
1060 | None::tl -> None::(aux (i+1) tl)
1061 | (Some (n,C.Def (t,Some ty)))::tl ->
1063 C.Def ((S.subst_meta l (S.lift i t)),
1064 Some (S.subst_meta l (S.lift i ty))))) :: (aux (i+1) tl)
1066 aux 1 canonical_context
1070 (fun (l,subst,metasenv,ugraph) t ct ->
1073 l @ [None],subst,metasenv,ugraph
1074 | Some t,Some (_,C.Def (ct,_)) ->
1075 let subst',metasenv',ugraph' =
1077 prerr_endline ("poco geniale: nel caso di IRL basterebbe sapere che questo e' il Rel corrispondente. Si puo' ottimizzare il caso t = rel.");
1078 fo_unif_subst subst context metasenv t ct ugraph
1079 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 ~metasenv subst t) (CicMetaSubst.ppterm ~metasenv subst ct) (match e with AssertFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
1081 l @ [Some t],subst',metasenv',ugraph'
1082 | Some t,Some (_,C.Decl ct) ->
1083 let t',inferredty,subst',metasenv',ugraph1 =
1084 type_of_aux subst metasenv context t ugraph
1086 let subst'',metasenv'',ugraph2 =
1089 subst' context metasenv' inferredty ct ugraph1
1090 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 metasenv' subst' inferredty) (CicMetaSubst.ppterm metasenv' subst' t) (CicMetaSubst.ppterm metasenv' subst' ct) (match e with AssertFailure msg -> Lazy.force msg | RefineFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
1092 l @ [Some t'], subst'',metasenv'',ugraph2
1094 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 ~metasenv subst (Cic.Meta (metano, l))) (CicMetaSubst.ppcontext ~metasenv subst canonical_context))))) ([],subst,metasenv,ugraph) l lifted_canonical_context
1096 Invalid_argument _ ->
1100 "Not well typed metavariable instance %s: the length of the local context does not match the length of the canonical context %s"
1101 (CicMetaSubst.ppterm ~metasenv subst (Cic.Meta (metano, l)))
1102 (CicMetaSubst.ppcontext ~metasenv subst canonical_context))))
1104 and check_exp_named_subst metasubst metasenv context tl ugraph =
1105 let rec check_exp_named_subst_aux metasubst metasenv substs tl ugraph =
1107 [] -> [],metasubst,metasenv,ugraph
1109 let ty_uri,ugraph1 = type_of_variable uri ugraph in
1111 CicSubstitution.subst_vars substs ty_uri in
1112 (* CSC: why was this code here? it is wrong
1113 (match CicEnvironment.get_cooked_obj ~trust:false uri with
1114 Cic.Variable (_,Some bo,_,_) ->
1116 (RefineFailure (lazy
1117 "A variable with a body can not be explicit substituted"))
1118 | Cic.Variable (_,None,_,_) -> ()
1121 (RefineFailure (lazy
1122 ("Unkown variable definition " ^ UriManager.string_of_uri uri)))
1125 let t',typeoft,metasubst',metasenv',ugraph2 =
1126 type_of_aux metasubst metasenv context t ugraph1 in
1127 let subst = uri,t' in
1128 let metasubst'',metasenv'',ugraph3 =
1131 metasubst' context metasenv' typeoft typeofvar ugraph2
1133 raise (RefineFailure (lazy
1134 ("Wrong Explicit Named Substitution: " ^
1135 CicMetaSubst.ppterm metasenv' metasubst' typeoft ^
1136 " not unifiable with " ^
1137 CicMetaSubst.ppterm metasenv' metasubst' typeofvar)))
1139 (* FIXME: no mere tail recursive! *)
1140 let exp_name_subst, metasubst''', metasenv''', ugraph4 =
1141 check_exp_named_subst_aux
1142 metasubst'' metasenv'' (substs@[subst]) tl ugraph3
1144 ((uri,t')::exp_name_subst), metasubst''', metasenv''', ugraph4
1146 check_exp_named_subst_aux metasubst metasenv [] tl ugraph
1149 and sort_of_prod localization_tbl subst metasenv context (name,s) t (t1, t2)
1152 let module C = Cic in
1153 let context_for_t2 = (Some (name,C.Decl s))::context in
1154 let t1'' = CicReduction.whd ~subst context t1 in
1155 let t2'' = CicReduction.whd ~subst context_for_t2 t2 in
1156 match (t1'', t2'') with
1157 (C.Sort s1, C.Sort s2)
1158 when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) ->
1159 (* different than Coq manual!!! *)
1160 C.Sort s2,subst,metasenv,ugraph
1161 | (C.Sort (C.Type t1), C.Sort (C.Type t2)) ->
1162 let t' = CicUniv.fresh() in
1164 let ugraph1 = CicUniv.add_ge t' t1 ugraph in
1165 let ugraph2 = CicUniv.add_ge t' t2 ugraph1 in
1166 C.Sort (C.Type t'),subst,metasenv,ugraph2
1168 CicUniv.UniverseInconsistency msg -> raise (RefineFailure msg))
1169 | (C.Sort _,C.Sort (C.Type t1)) ->
1170 C.Sort (C.Type t1),subst,metasenv,ugraph
1171 | (C.Meta _, C.Sort _) -> t2'',subst,metasenv,ugraph
1172 | (C.Sort _,C.Meta _) | (C.Meta _,C.Meta _) ->
1173 (* TODO how can we force the meta to become a sort? If we don't we
1174 * break the invariant that refine produce only well typed terms *)
1175 (* TODO if we check the non meta term and if it is a sort then we
1176 * are likely to know the exact value of the result e.g. if the rhs
1177 * is a Sort (Prop | Set | CProp) then the result is the rhs *)
1178 let (metasenv,idx) =
1179 CicMkImplicit.mk_implicit_sort metasenv subst in
1180 let (subst, metasenv,ugraph1) =
1182 fo_unif_subst subst context_for_t2 metasenv
1183 (C.Meta (idx,[])) t2'' ugraph
1184 with _ -> assert false (* unification against a metavariable *)
1186 t2'',subst,metasenv,ugraph1
1189 enrich localization_tbl s
1193 "%s is supposed to be a type, but its type is %s"
1194 (CicMetaSubst.ppterm_in_context ~metasenv subst t context)
1195 (CicMetaSubst.ppterm_in_context ~metasenv subst t2 context))))
1197 enrich localization_tbl t
1201 "%s is supposed to be a type, but its type is %s"
1202 (CicMetaSubst.ppterm_in_context ~metasenv subst s context)
1203 (CicMetaSubst.ppterm_in_context ~metasenv subst t1 context))))
1205 and avoid_double_coercion context subst metasenv ugraph t ty =
1206 if not !pack_coercions then
1207 t,ty,subst,metasenv,ugraph
1209 let b, c1, c2, head, c1_c2_implicit = is_a_double_coercion t in
1211 let source_carr = CoercGraph.source_of c2 in
1212 let tgt_carr = CicMetaSubst.apply_subst subst ty in
1213 (match CoercGraph.look_for_coercion metasenv subst context source_carr tgt_carr
1215 | CoercGraph.SomeCoercion candidates ->
1217 HExtlib.list_findopt
1218 (function (metasenv,last,c) ->
1220 | c when not (CoercGraph.is_composite c) ->
1221 debug_print (lazy ("\nNot a composite.."^CicPp.ppterm c));
1224 let subst,metasenv,ugraph =
1225 fo_unif_subst subst context metasenv last head ugraph in
1226 debug_print (lazy ("\nprovo" ^ CicPp.ppterm c));
1231 CicPp.ppterm t ^ " ==> " ^ CicPp.ppterm c));
1232 let newt,_,subst,metasenv,ugraph =
1233 type_of_aux subst metasenv context c ugraph in
1234 debug_print (lazy "tipa...");
1235 let subst, metasenv, ugraph =
1236 (* COME MAI C'ERA UN IF su !pack_coercions ??? *)
1237 fo_unif_subst subst context metasenv newt t ugraph
1239 debug_print (lazy "unifica...");
1240 Some (newt, ty, subst, metasenv, ugraph)
1242 | RefineFailure s | Uncertain s when not !pack_coercions->
1243 debug_print s; debug_print (lazy "stop\n");None
1244 | RefineFailure s | Uncertain s ->
1245 debug_print s;debug_print (lazy "goon\n");
1247 let old_pack_coercions = !pack_coercions in
1248 pack_coercions := false; (* to avoid diverging *)
1249 let refined_c1_c2_implicit,ty,subst,metasenv,ugraph =
1250 type_of_aux subst metasenv context c1_c2_implicit ugraph
1252 pack_coercions := old_pack_coercions;
1254 is_a_double_coercion refined_c1_c2_implicit
1260 match refined_c1_c2_implicit with
1261 | Cic.Appl l -> HExtlib.list_last l
1264 let subst, metasenv, ugraph =
1265 try fo_unif_subst subst context metasenv
1267 with RefineFailure s| Uncertain s->
1268 debug_print s;assert false
1270 let subst, metasenv, ugraph =
1271 fo_unif_subst subst context metasenv
1272 refined_c1_c2_implicit t ugraph
1274 Some (refined_c1_c2_implicit,ty,subst,metasenv,ugraph)
1276 | RefineFailure s | Uncertain s ->
1277 pack_coercions := true;debug_print s;None
1278 | exn -> pack_coercions := true; raise exn))
1281 (match selected with
1285 (lazy ("#### Coercion not packed: " ^ CicPp.ppterm t));
1286 t, ty, subst, metasenv, ugraph)
1287 | _ -> t, ty, subst, metasenv, ugraph)
1289 t, ty, subst, metasenv, ugraph
1291 and typeof_list subst metasenv context ugraph l =
1292 let tlbody_and_type,subst,metasenv,ugraph =
1294 (fun x (res,subst,metasenv,ugraph) ->
1295 let x',ty,subst',metasenv',ugraph1 =
1296 type_of_aux subst metasenv context x ugraph
1298 (x', ty)::res,subst',metasenv',ugraph1
1299 ) l ([],subst,metasenv,ugraph)
1301 tlbody_and_type,subst,metasenv,ugraph
1304 allow_coercions subst metasenv context he hetype args_bo_and_ty ugraph
1306 (* aux function to add coercions to funclass *)
1307 let rec fix_arity metasenv context subst he hetype args_bo_and_ty ugraph =
1309 let pristinemenv = metasenv in
1310 let metasenv,hetype' =
1311 mk_prod_of_metas metasenv context subst args_bo_and_ty
1314 let subst,metasenv,ugraph =
1315 fo_unif_subst_eat_prods
1316 subst context metasenv hetype hetype' ugraph
1318 subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1319 with RefineFailure s | Uncertain s as exn
1320 when allow_coercions && !insert_coercions ->
1321 (* {{{ we search a coercion of the head (saturated) to funclass *)
1322 let metasenv = pristinemenv in
1324 ("Fixing arity of: "^CicMetaSubst.ppterm ~metasenv subst hetype ^
1325 " since unif failed with: " ^ CicMetaSubst.ppterm ~metasenv subst hetype'
1326 (* ^ " cause: " ^ Lazy.force s *)));
1327 let how_many_args_are_needed =
1328 let rec aux n = function
1329 | Cic.Prod(_,_,t) -> aux (n+1) t
1332 aux 0 (CicMetaSubst.apply_subst subst hetype)
1334 let args, remainder =
1335 HExtlib.split_nth how_many_args_are_needed args_bo_and_ty
1337 let args = List.map fst args in
1341 | Cic.Appl l -> Cic.Appl (l@args)
1342 | _ -> Cic.Appl (he::args)
1346 let x,xty,subst,metasenv,ugraph =
1347 (*CSC: here unsharing is necessary to avoid an unwanted
1348 relocalization. However, this also shows a great source of
1349 inefficiency: "x" is refined twice (once now and once in the
1350 subsequent eat_prods_and_args). Morevoer, how is divergence avoided?
1352 type_of_aux subst metasenv context (Unshare.unshare x) ugraph
1355 CoercDb.coerc_carr_of_term (CicMetaSubst.apply_subst subst xty)
1357 let carr_tgt = CoercDb.Fun 0 in
1358 match CoercGraph.look_for_coercion' metasenv subst context carr_src carr_tgt with
1359 | CoercGraph.NoCoercion
1360 | CoercGraph.NotMetaClosed
1361 | CoercGraph.NotHandled _ -> raise exn
1362 | CoercGraph.SomeCoercion candidates ->
1364 HExtlib.list_findopt
1365 (fun (metasenv,last,coerc) ->
1366 let subst,metasenv,ugraph =
1367 fo_unif_subst subst context metasenv last x ugraph in
1368 debug_print (lazy ("Tentative " ^ CicMetaSubst.ppterm ~metasenv subst coerc));
1370 (* we want this to be available in the error handler fo the
1371 * following (so it has its own try. *)
1372 let t,tty,subst,metasenv,ugraph =
1373 type_of_aux subst metasenv context coerc ugraph
1376 let metasenv, hetype' =
1377 mk_prod_of_metas metasenv context subst remainder
1380 (" unif: " ^ CicMetaSubst.ppterm ~metasenv subst tty ^ " = " ^
1381 CicMetaSubst.ppterm ~metasenv subst hetype'));
1382 let subst,metasenv,ugraph =
1383 fo_unif_subst_eat_prods
1384 subst context metasenv tty hetype' ugraph
1386 debug_print (lazy " success!");
1387 Some (subst,metasenv,ugraph,tty,t,remainder)
1389 | Uncertain _ | RefineFailure _
1390 | CicUnification.UnificationFailure _
1391 | CicUnification.Uncertain _ ->
1393 let subst,metasenv,ugraph,hetype',he,args_bo_and_ty =
1395 metasenv context subst t tty remainder ugraph
1397 Some (subst,metasenv,ugraph,hetype',he,args_bo_and_ty)
1398 with Uncertain _ | RefineFailure _ -> None
1402 | HExtlib.Localized (_,Uncertain _)
1403 | HExtlib.Localized (_,RefineFailure _) -> None
1404 | exn -> assert false) (* ritornare None, e' un localized *)
1407 | Some(subst,metasenv,ugraph,hetype',he,args_bo_and_ty)->
1408 subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1410 more_args_than_expected localization_tbl metasenv
1411 subst he context hetype args_bo_and_ty exn
1412 (* }}} end coercion to funclass stuff *)
1413 (* }}} end fix_arity *)
1415 (* aux function to process the type of the head and the args in parallel *)
1416 let rec eat_prods_and_args
1417 pristinemenv metasenv subst context pristinehe he hetype ugraph newargs
1421 | [] -> newargs,subst,metasenv,he,hetype,ugraph
1422 | (hete, hety)::tl ->
1423 match (CicReduction.whd ~subst context hetype) with
1424 | Cic.Prod (n,s,t) ->
1425 let arg,subst,metasenv,ugraph1 =
1427 let subst,metasenv,ugraph1 =
1428 fo_unif_subst_eat_prods2
1429 subst context metasenv hety s ugraph
1431 (hete,hety),subst,metasenv,ugraph1
1432 (* {{{ we search a coercion from hety to s if fails *)
1433 with RefineFailure _ | Uncertain _ as exn
1434 when allow_coercions && !insert_coercions ->
1435 let coer, tgt_carr =
1436 let carr t subst context =
1437 CicReduction.whd ~delta:false
1438 context (CicMetaSubst.apply_subst subst t )
1440 let c_hety = carr hety subst context in
1441 let c_s = carr s subst context in
1442 CoercGraph.look_for_coercion metasenv subst context c_hety c_s, c_s
1445 | CoercGraph.NoCoercion
1446 | CoercGraph.NotHandled _ ->
1447 enrich localization_tbl hete exn
1449 (lazy ("The term " ^
1450 CicMetaSubst.ppterm_in_context ~metasenv subst hete
1451 context ^ " has type " ^
1452 CicMetaSubst.ppterm_in_context ~metasenv subst hety
1453 context ^ " but is here used with type " ^
1454 CicMetaSubst.ppterm_in_context ~metasenv subst s context
1455 (* "\nReason: " ^ Lazy.force e*))))
1456 | CoercGraph.NotMetaClosed ->
1457 enrich localization_tbl hete exn
1459 (lazy ("The term " ^
1460 CicMetaSubst.ppterm_in_context ~metasenv subst hete
1461 context ^ " has type " ^
1462 CicMetaSubst.ppterm_in_context ~metasenv subst hety
1463 context ^ " but is here used with type " ^
1464 CicMetaSubst.ppterm_in_context ~metasenv subst s context
1465 (* "\nReason: " ^ Lazy.force e*))))
1466 | CoercGraph.SomeCoercion candidates ->
1468 HExtlib.list_findopt
1469 (fun (metasenv,last,c) ->
1471 let subst,metasenv,ugraph =
1472 fo_unif_subst subst context metasenv last hete
1474 let newt,newhety,subst,metasenv,ugraph =
1475 type_of_aux subst metasenv context
1478 let newt, newty, subst, metasenv, ugraph =
1479 avoid_double_coercion context subst metasenv
1480 ugraph newt tgt_carr
1482 let subst,metasenv,ugraph1 =
1483 fo_unif_subst subst context metasenv
1486 Some ((newt,newty), subst, metasenv, ugraph)
1487 with Uncertain _ | RefineFailure _ -> None)
1490 (match selected with
1493 enrich localization_tbl hete
1495 (lazy ("The term " ^
1496 CicMetaSubst.ppterm_in_context ~metasenv subst hete
1497 context ^ " has type " ^
1498 CicMetaSubst.ppterm_in_context ~metasenv subst hety
1499 context ^ " but is here used with type " ^
1500 CicMetaSubst.ppterm_in_context ~metasenv subst s context
1501 (* "\nReason: " ^ Lazy.force e*)))) exn))
1503 enrich localization_tbl hete
1505 (lazy ("The term " ^
1506 CicMetaSubst.ppterm_in_context ~metasenv subst hete
1507 context ^ " has type " ^
1508 CicMetaSubst.ppterm_in_context ~metasenv subst hety
1509 context ^ " but is here used with type " ^
1510 CicMetaSubst.ppterm_in_context ~metasenv subst s context
1511 (* "\nReason: " ^ Printexc.to_string exn*)))) exn
1512 (* }}} end coercion stuff *)
1514 eat_prods_and_args pristinemenv metasenv subst context pristinehe he
1515 (CicSubstitution.subst (fst arg) t)
1516 ugraph1 (newargs@[arg]) tl
1519 let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1521 pristinemenv context subst he hetype
1522 (newargs@[hete,hety]@tl) ugraph
1524 eat_prods_and_args metasenv
1525 metasenv subst context pristinehe he hetype' ugraph [] args_bo_and_ty
1526 with RefineFailure _ | Uncertain _ as exn ->
1527 (* unable to fix arity *)
1528 more_args_than_expected localization_tbl metasenv
1529 subst he context hetype args_bo_and_ty exn
1532 (* first we check if we are in the simple case of a meta closed term *)
1533 let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1534 if CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst hetype) then
1535 (* this optimization is to postpone fix_arity (the most common case)*)
1536 subst,metasenv,ugraph,hetype,he,args_bo_and_ty
1538 (* this (says CSC) is also useful to infer dependent types *)
1540 fix_arity metasenv context subst he hetype args_bo_and_ty ugraph
1541 with RefineFailure _ | Uncertain _ as exn ->
1542 (* unable to fix arity *)
1543 more_args_than_expected localization_tbl metasenv
1544 subst he context hetype args_bo_and_ty exn
1546 let coerced_args,subst,metasenv,he,t,ugraph =
1548 metasenv metasenv subst context he he hetype' ugraph1 [] args_bo_and_ty
1550 he,(List.map fst coerced_args),t,subst,metasenv,ugraph
1553 (* eat prods ends here! *)
1555 let t',ty,subst',metasenv',ugraph1 =
1556 type_of_aux [] metasenv context t ugraph
1558 let substituted_t = CicMetaSubst.apply_subst subst' t' in
1559 let substituted_ty = CicMetaSubst.apply_subst subst' ty in
1560 (* Andrea: ho rimesso qui l'applicazione della subst al
1561 metasenv dopo che ho droppato l'invariante che il metsaenv
1562 e' sempre istanziato *)
1563 let substituted_metasenv =
1564 CicMetaSubst.apply_subst_metasenv subst' metasenv' in
1566 (* substituted_t,substituted_ty,substituted_metasenv *)
1567 (* ANDREA: spostare tutta questa robaccia da un altra parte *)
1569 FreshNamesGenerator.clean_dummy_dependent_types substituted_t in
1571 FreshNamesGenerator.clean_dummy_dependent_types substituted_ty in
1572 let cleaned_metasenv =
1574 (function (n,context,ty) ->
1575 let ty' = FreshNamesGenerator.clean_dummy_dependent_types ty in
1580 | Some (n, Cic.Decl t) ->
1582 Cic.Decl (FreshNamesGenerator.clean_dummy_dependent_types t))
1583 | Some (n, Cic.Def (bo,ty)) ->
1584 let bo' = FreshNamesGenerator.clean_dummy_dependent_types bo in
1589 Some (FreshNamesGenerator.clean_dummy_dependent_types ty)
1591 Some (n, Cic.Def (bo',ty'))
1595 ) substituted_metasenv
1597 (cleaned_t,cleaned_ty,cleaned_metasenv,ugraph1)
1600 let undebrujin uri typesno tys t =
1603 (fun (name,_,_,_) (i,t) ->
1604 (* here the explicit_named_substituion is assumed to be *)
1606 let t' = Cic.MutInd (uri,i,[]) in
1607 let t = CicSubstitution.subst t' t in
1609 ) tys (typesno - 1,t))
1611 let map_first_n n start f g l =
1612 let rec aux acc k l =
1615 | [] -> raise (Invalid_argument "map_first_n")
1616 | hd :: tl -> f hd k (aux acc (k+1) tl)
1622 (*CSC: this is a very rough approximation; to be finished *)
1623 let are_all_occurrences_positive metasenv ugraph uri tys leftno =
1624 let subst,metasenv,ugraph,tys =
1626 (fun (name,ind,arity,cl) (subst,metasenv,ugraph,acc) ->
1627 let subst,metasenv,ugraph,cl =
1629 (fun (name,ty) (subst,metasenv,ugraph,acc) ->
1630 let rec aux ctx k subst = function
1631 | Cic.Appl((Cic.MutInd (uri',_,_)as hd)::tl) when uri = uri'->
1632 let subst,metasenv,ugraph,tl =
1634 (subst,metasenv,ugraph,[])
1635 (fun t n (subst,metasenv,ugraph,acc) ->
1636 let subst,metasenv,ugraph =
1638 subst ctx metasenv t (Cic.Rel (k-n)) ugraph
1640 subst,metasenv,ugraph,(t::acc))
1641 (fun (s,m,g,acc) tl -> assert(acc=[]);(s,m,g,tl))
1644 subst,metasenv,ugraph,(Cic.Appl (hd::tl))
1645 | Cic.MutInd(uri',_,_) as t when uri = uri'->
1646 subst,metasenv,ugraph,t
1647 | Cic.Prod (name,s,t) ->
1648 let ctx = (Some (name,Cic.Decl s))::ctx in
1649 let subst,metasenv,ugraph,t = aux ctx (k+1) subst t in
1650 subst,metasenv,ugraph,Cic.Prod (name,s,t)
1654 (lazy "not well formed constructor type"))
1656 let subst,metasenv,ugraph,ty = aux [] 0 subst ty in
1657 subst,metasenv,ugraph,(name,ty) :: acc)
1658 cl (subst,metasenv,ugraph,[])
1660 subst,metasenv,ugraph,(name,ind,arity,cl)::acc)
1661 tys ([],metasenv,ugraph,[])
1663 let substituted_tys =
1665 (fun (name,ind,arity,cl) ->
1667 List.map (fun (name, ty) -> name,CicMetaSubst.apply_subst subst ty) cl
1669 name,ind,CicMetaSubst.apply_subst subst arity,cl)
1672 metasenv,ugraph,substituted_tys
1674 let typecheck metasenv uri obj ~localization_tbl =
1675 let ugraph = CicUniv.empty_ugraph in
1677 Cic.Constant (name,Some bo,ty,args,attrs) ->
1678 let bo',boty,metasenv,ugraph =
1679 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1680 let ty',_,metasenv,ugraph =
1681 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1682 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1683 let bo' = CicMetaSubst.apply_subst subst bo' in
1684 let ty' = CicMetaSubst.apply_subst subst ty' in
1685 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1686 Cic.Constant (name,Some bo',ty',args,attrs),metasenv,ugraph
1687 | Cic.Constant (name,None,ty,args,attrs) ->
1688 let ty',_,metasenv,ugraph =
1689 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1691 Cic.Constant (name,None,ty',args,attrs),metasenv,ugraph
1692 | Cic.CurrentProof (name,metasenv',bo,ty,args,attrs) ->
1693 assert (metasenv' = metasenv);
1694 (* Here we do not check the metasenv for correctness *)
1695 let bo',boty,metasenv,ugraph =
1696 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1697 let ty',sort,metasenv,ugraph =
1698 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1702 (* instead of raising Uncertain, let's hope that the meta will become
1705 | _ -> raise (RefineFailure (lazy "The term provided is not a type"))
1707 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1708 let bo' = CicMetaSubst.apply_subst subst bo' in
1709 let ty' = CicMetaSubst.apply_subst subst ty' in
1710 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1711 Cic.CurrentProof (name,metasenv,bo',ty',args,attrs),metasenv,ugraph
1712 | Cic.Variable _ -> assert false (* not implemented *)
1713 | Cic.InductiveDefinition (tys,args,paramsno,attrs) ->
1714 (*CSC: this code is greately simplified and many many checks are missing *)
1715 (*CSC: e.g. the constructors are not required to build their own types, *)
1716 (*CSC: the arities are not required to have as type a sort, etc. *)
1717 let uri = match uri with Some uri -> uri | None -> assert false in
1718 let typesno = List.length tys in
1719 (* first phase: we fix only the types *)
1720 let metasenv,ugraph,tys =
1722 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1723 let ty',_,metasenv,ugraph =
1724 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1726 metasenv,ugraph,(name,b,ty',cl)::res
1727 ) tys (metasenv,ugraph,[]) in
1729 List.rev_map (fun (name,_,ty,_)-> Some (Cic.Name name,Cic.Decl ty)) tys in
1730 (* second phase: we fix only the constructors *)
1731 let metasenv,ugraph,tys =
1733 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1734 let metasenv,ugraph,cl' =
1736 (fun (name,ty) (metasenv,ugraph,res) ->
1738 CicTypeChecker.debrujin_constructor
1739 ~cb:(relocalize localization_tbl) uri typesno ty in
1740 let ty',_,metasenv,ugraph =
1741 type_of_aux' ~localization_tbl metasenv con_context ty ugraph in
1742 let ty' = undebrujin uri typesno tys ty' in
1743 metasenv,ugraph,(name,ty')::res
1744 ) cl (metasenv,ugraph,[])
1746 metasenv,ugraph,(name,b,ty,cl')::res
1747 ) tys (metasenv,ugraph,[]) in
1748 (* third phase: we check the positivity condition *)
1749 let metasenv,ugraph,tys =
1750 are_all_occurrences_positive metasenv ugraph uri tys paramsno
1752 Cic.InductiveDefinition (tys,args,paramsno,attrs),metasenv,ugraph
1755 (* sara' piu' veloce che raffinare da zero? mah.... *)
1756 let pack_coercion metasenv ctx t =
1757 let module C = Cic in
1758 let rec merge_coercions ctx =
1759 let aux = (fun (u,t) -> u,merge_coercions ctx t) in
1761 | C.Rel _ | C.Sort _ | C.Implicit _ as t -> t
1762 | C.Meta (n,subst) ->
1765 (function None -> None | Some t -> Some (merge_coercions ctx t)) subst
1768 | C.Cast (te,ty) -> C.Cast (merge_coercions ctx te, merge_coercions ctx ty)
1769 | C.Prod (name,so,dest) ->
1770 let ctx' = (Some (name,C.Decl so))::ctx in
1771 C.Prod (name, merge_coercions ctx so, merge_coercions ctx' dest)
1772 | C.Lambda (name,so,dest) ->
1773 let ctx' = (Some (name,C.Decl so))::ctx in
1774 C.Lambda (name, merge_coercions ctx so, merge_coercions ctx' dest)
1775 | C.LetIn (name,so,dest) ->
1776 let _,ty,metasenv,ugraph =
1777 pack_coercions := false;
1778 type_of_aux' metasenv ctx so CicUniv.oblivion_ugraph in
1779 pack_coercions := true;
1780 let ctx' = Some (name,(C.Def (so,Some ty)))::ctx in
1781 C.LetIn (name, merge_coercions ctx so, merge_coercions ctx' dest)
1783 let l = List.map (merge_coercions ctx) l in
1785 let b,_,_,_,_ = is_a_double_coercion t in
1786 (* prerr_endline "CANDIDATO!!!!"; *)
1788 let ugraph = CicUniv.oblivion_ugraph in
1789 let old_insert_coercions = !insert_coercions in
1790 insert_coercions := false;
1791 let newt, _, menv, _ =
1793 type_of_aux' metasenv ctx t ugraph
1794 with RefineFailure _ | Uncertain _ ->
1797 insert_coercions := old_insert_coercions;
1798 if metasenv <> [] || menv = [] then
1801 (prerr_endline "PUO' SUCCEDERE!!!!!";t)
1804 | C.Var (uri,exp_named_subst) ->
1805 let exp_named_subst = List.map aux exp_named_subst in
1806 C.Var (uri, exp_named_subst)
1807 | C.Const (uri,exp_named_subst) ->
1808 let exp_named_subst = List.map aux exp_named_subst in
1809 C.Const (uri, exp_named_subst)
1810 | C.MutInd (uri,tyno,exp_named_subst) ->
1811 let exp_named_subst = List.map aux exp_named_subst in
1812 C.MutInd (uri,tyno,exp_named_subst)
1813 | C.MutConstruct (uri,tyno,consno,exp_named_subst) ->
1814 let exp_named_subst = List.map aux exp_named_subst in
1815 C.MutConstruct (uri,tyno,consno,exp_named_subst)
1816 | C.MutCase (uri,tyno,out,te,pl) ->
1817 let pl = List.map (merge_coercions ctx) pl in
1818 C.MutCase (uri,tyno,merge_coercions ctx out, merge_coercions ctx te, pl)
1819 | C.Fix (fno, fl) ->
1822 (fun l (n,_,ty,_) -> (Some (C.Name n,C.Decl ty))::l)
1827 (fun (name,idx,ty,bo) ->
1828 (name,idx,merge_coercions ctx ty,merge_coercions ctx' bo))
1832 | C.CoFix (fno, fl) ->
1835 (fun l (n,ty,_) -> (Some (C.Name n,C.Decl ty))::l)
1840 (fun (name,ty,bo) ->
1841 (name, merge_coercions ctx ty, merge_coercions ctx' bo))
1846 merge_coercions ctx t
1849 let pack_coercion_metasenv conjectures =
1850 let module C = Cic in
1852 (fun (i, ctx, ty) ->
1858 Some (name, C.Decl t) ->
1859 Some (name, C.Decl (pack_coercion conjectures ctx t))
1860 | Some (name, C.Def (t,None)) ->
1861 Some (name,C.Def (pack_coercion conjectures ctx t,None))
1862 | Some (name, C.Def (t,Some ty)) ->
1863 Some (name, C.Def (pack_coercion conjectures ctx t,
1864 Some (pack_coercion conjectures ctx ty)))
1870 ((i,ctx,pack_coercion conjectures ctx ty))
1874 let pack_coercion_obj obj =
1875 let module C = Cic in
1877 | C.Constant (id, body, ty, params, attrs) ->
1881 | Some body -> Some (pack_coercion [] [] body)
1883 let ty = pack_coercion [] [] ty in
1884 C.Constant (id, body, ty, params, attrs)
1885 | C.Variable (name, body, ty, params, attrs) ->
1889 | Some body -> Some (pack_coercion [] [] body)
1891 let ty = pack_coercion [] [] ty in
1892 C.Variable (name, body, ty, params, attrs)
1893 | C.CurrentProof (name, conjectures, body, ty, params, attrs) ->
1894 let conjectures = pack_coercion_metasenv conjectures in
1895 let body = pack_coercion conjectures [] body in
1896 let ty = pack_coercion conjectures [] ty in
1897 C.CurrentProof (name, conjectures, body, ty, params, attrs)
1898 | C.InductiveDefinition (indtys, params, leftno, attrs) ->
1901 (fun (name, ind, arity, cl) ->
1902 let arity = pack_coercion [] [] arity in
1904 List.map (fun (name, ty) -> (name,pack_coercion [] [] ty)) cl
1906 (name, ind, arity, cl))
1909 C.InductiveDefinition (indtys, params, leftno, attrs)
1914 let type_of_aux' metasenv context term =
1917 type_of_aux' metasenv context term in
1919 ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty));
1921 ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []));
1924 | RefineFailure msg as e ->
1925 debug_print (lazy ("@@@ REFINE FAILED: " ^ msg));
1927 | Uncertain msg as e ->
1928 debug_print (lazy ("@@@ REFINE UNCERTAIN: " ^ msg));
1932 let profiler2 = HExtlib.profile "CicRefine"
1934 let type_of_aux' ?localization_tbl metasenv context term ugraph =
1935 profiler2.HExtlib.profile
1936 (type_of_aux' ?localization_tbl metasenv context term) ugraph
1938 let typecheck ~localization_tbl metasenv uri obj =
1939 profiler2.HExtlib.profile (typecheck ~localization_tbl metasenv uri) obj
1941 let _ = DoubleTypeInference.pack_coercion := pack_coercion;;
1942 (* vim:set foldmethod=marker: *)