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/.
28 exception RefineFailure of string Lazy.t;;
29 exception Uncertain of string Lazy.t;;
30 exception AssertFailure of string Lazy.t;;
32 let debug_print = fun _ -> ()
34 let profiler = HExtlib.profile "CicRefine.fo_unif"
36 let fo_unif_subst subst context metasenv t1 t2 ugraph =
39 CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
40 in profiler.HExtlib.profile foo ()
42 (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
43 | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
46 let enrich localization_tbl t ?(f = fun msg -> msg) exn =
49 RefineFailure msg -> RefineFailure (f msg)
50 | Uncertain msg -> Uncertain (f msg)
51 | _ -> assert false in
54 Cic.CicHash.find localization_tbl t
56 prerr_endline ("!!! NOT LOCALIZED: " ^ CicPp.ppterm t);
59 raise (HExtlib.Localized (loc,exn'))
61 let relocalize localization_tbl oldt newt =
63 let infos = Cic.CicHash.find localization_tbl oldt in
64 Cic.CicHash.remove localization_tbl oldt;
65 Cic.CicHash.add localization_tbl newt infos;
73 | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
74 | (_,_) -> raise (AssertFailure (lazy "split: list too short"))
77 let exp_impl metasenv subst context =
80 let (metasenv', idx) = CicMkImplicit.mk_implicit_type metasenv subst context in
81 let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
82 metasenv', Cic.Meta (idx, irl)
84 let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst [] in
85 metasenv', Cic.Meta (idx, [])
87 let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst context in
88 let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
89 metasenv', Cic.Meta (idx, irl)
93 let rec type_of_constant uri ugraph =
95 let module R = CicReduction in
96 let module U = UriManager in
97 let _ = CicTypeChecker.typecheck uri in
100 CicEnvironment.get_cooked_obj ugraph uri
101 with Not_found -> assert false
104 C.Constant (_,_,ty,_,_) -> ty,u
105 | C.CurrentProof (_,_,_,ty,_,_) -> ty,u
108 (RefineFailure (lazy ("Unknown constant definition " ^ U.string_of_uri uri)))
110 and type_of_variable uri ugraph =
111 let module C = Cic in
112 let module R = CicReduction in
113 let module U = UriManager in
114 let _ = CicTypeChecker.typecheck uri in
117 CicEnvironment.get_cooked_obj ugraph uri
118 with Not_found -> assert false
121 C.Variable (_,_,ty,_,_) -> ty,u
125 (lazy ("Unknown variable definition " ^ UriManager.string_of_uri uri)))
127 and type_of_mutual_inductive_defs uri i ugraph =
128 let module C = Cic in
129 let module R = CicReduction in
130 let module U = UriManager in
131 let _ = CicTypeChecker.typecheck uri in
134 CicEnvironment.get_cooked_obj ugraph uri
135 with Not_found -> assert false
138 C.InductiveDefinition (dl,_,_,_) ->
139 let (_,_,arity,_) = List.nth dl i in
144 (lazy ("Unknown mutual inductive definition " ^ U.string_of_uri uri)))
146 and type_of_mutual_inductive_constr uri i j ugraph =
147 let module C = Cic in
148 let module R = CicReduction in
149 let module U = UriManager in
150 let _ = CicTypeChecker.typecheck uri in
153 CicEnvironment.get_cooked_obj ugraph uri
154 with Not_found -> assert false
157 C.InductiveDefinition (dl,_,_,_) ->
158 let (_,_,_,cl) = List.nth dl i in
159 let (_,ty) = List.nth cl (j-1) in
165 ("Unkown mutual inductive definition " ^ U.string_of_uri uri)))
168 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
170 (* the check_branch function checks if a branch of a case is refinable.
171 It returns a pair (outype_instance,args), a subst and a metasenv.
172 outype_instance is the expected result of applying the case outtype
174 The problem is that outype is in general unknown, and we should
175 try to synthesize it from the above information, that is in general
176 a second order unification problem. *)
178 and check_branch n context metasenv subst left_args_no actualtype term expectedtype ugraph =
179 let module C = Cic in
180 (* let module R = CicMetaSubst in *)
181 let module R = CicReduction in
182 match R.whd ~subst context expectedtype with
184 (n,context,actualtype, [term]), subst, metasenv, ugraph
185 | C.Appl (C.MutInd (_,_,_)::tl) ->
186 let (_,arguments) = split tl left_args_no in
187 (n,context,actualtype, arguments@[term]), subst, metasenv, ugraph
188 | C.Prod (name,so,de) ->
189 (* we expect that the actual type of the branch has the due
191 (match R.whd ~subst context actualtype with
192 C.Prod (name',so',de') ->
193 let subst, metasenv, ugraph1 =
194 fo_unif_subst subst context metasenv so so' ugraph in
196 (match CicSubstitution.lift 1 term with
197 C.Appl l -> C.Appl (l@[C.Rel 1])
198 | t -> C.Appl [t ; C.Rel 1]) in
199 (* we should also check that the name variable is anonymous in
200 the actual type de' ?? *)
202 ((Some (name,(C.Decl so)))::context)
203 metasenv subst left_args_no de' term' de ugraph1
204 | _ -> raise (AssertFailure (lazy "Wrong number of arguments")))
205 | _ -> raise (AssertFailure (lazy "Prod or MutInd expected"))
207 and type_of_aux' ?(localization_tbl = Cic.CicHash.create 1) metasenv context t
210 let rec type_of_aux subst metasenv context t ugraph =
211 let module C = Cic in
212 let module S = CicSubstitution in
213 let module U = UriManager in
214 let (t',_,_,_,_) as res =
219 match List.nth context (n - 1) with
220 Some (_,C.Decl ty) ->
221 t,S.lift n ty,subst,metasenv, ugraph
222 | Some (_,C.Def (_,Some ty)) ->
223 t,S.lift n ty,subst,metasenv, ugraph
224 | Some (_,C.Def (bo,None)) ->
226 (* if it is in the context it must be already well-typed*)
227 CicTypeChecker.type_of_aux' ~subst metasenv context
230 t,ty,subst,metasenv,ugraph
232 enrich localization_tbl t
233 (RefineFailure (lazy "Rel to hidden hypothesis"))
236 enrich localization_tbl t
237 (RefineFailure (lazy "Not a close term")))
238 | C.Var (uri,exp_named_subst) ->
239 let exp_named_subst',subst',metasenv',ugraph1 =
240 check_exp_named_subst
241 subst metasenv context exp_named_subst ugraph
243 let ty_uri,ugraph1 = type_of_variable uri ugraph in
245 CicSubstitution.subst_vars exp_named_subst' ty_uri
247 C.Var (uri,exp_named_subst'),ty,subst',metasenv',ugraph1
250 let (canonical_context, term,ty) =
251 CicUtil.lookup_subst n subst
253 let l',subst',metasenv',ugraph1 =
254 check_metasenv_consistency n subst metasenv context
255 canonical_context l ugraph
257 (* trust or check ??? *)
258 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
259 subst', metasenv', ugraph1
260 (* type_of_aux subst metasenv
261 context (CicSubstitution.subst_meta l term) *)
262 with CicUtil.Subst_not_found _ ->
263 let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
264 let l',subst',metasenv', ugraph1 =
265 check_metasenv_consistency n subst metasenv context
266 canonical_context l ugraph
268 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
269 subst', metasenv',ugraph1)
270 | C.Sort (C.Type tno) ->
271 let tno' = CicUniv.fresh() in
272 let ugraph1 = CicUniv.add_gt tno' tno ugraph in
273 t,(C.Sort (C.Type tno')),subst,metasenv,ugraph1
275 t,C.Sort (C.Type (CicUniv.fresh())),subst,metasenv,ugraph
276 | C.Implicit infos ->
277 let metasenv',t' = exp_impl metasenv subst context infos in
278 type_of_aux subst metasenv' context t' ugraph
280 let ty',_,subst',metasenv',ugraph1 =
281 type_of_aux subst metasenv context ty ugraph
283 let te',inferredty,subst'',metasenv'',ugraph2 =
284 type_of_aux subst' metasenv' context te ugraph1
287 let subst''',metasenv''',ugraph3 =
288 fo_unif_subst subst'' context metasenv''
289 inferredty ty' ugraph2
291 C.Cast (te',ty'),ty',subst''',metasenv''',ugraph3
294 enrich localization_tbl t
297 CicMetaSubst.ppterm_in_context subst'' te
298 context ^ " has type " ^
299 CicMetaSubst.ppterm_in_context subst'' inferredty
300 context ^ " but is here used with type " ^
301 CicMetaSubst.ppterm_in_context subst'' ty context)) exn
303 | C.Prod (name,s,t) ->
304 let carr t subst context = CicMetaSubst.apply_subst subst t in
306 in_source tgt_sort t type_to_coerce subst ctx metasenv uragph
308 let coercion_src = carr type_to_coerce subst ctx in
309 match coercion_src with
311 t,type_to_coerce,subst,metasenv,ugraph
313 | Cic.Meta _ as meta when not in_source ->
314 let coercion_tgt = carr (Cic.Sort tgt_sort) subst ctx in
315 let subst, metasenv, ugraph =
317 subst ctx metasenv meta coercion_tgt ugraph
319 t, Cic.Sort tgt_sort, subst, metasenv, ugraph
321 | Cic.Meta _ as meta ->
322 t, meta, subst, metasenv, ugraph
323 | Cic.Cast _ as cast ->
324 t, cast, subst, metasenv, ugraph
326 let coercion_tgt = carr (Cic.Sort tgt_sort) subst ctx in
327 let search = CoercGraph.look_for_coercion in
328 let boh = search coercion_src coercion_tgt in
330 | CoercGraph.NoCoercion
331 | CoercGraph.NotHandled _ ->
332 enrich localization_tbl s
333 (RefineFailure (lazy (CicMetaSubst.ppterm subst coercion_src ^ " is not a sort and cannoted be coerced to a sort")))
334 | CoercGraph.NotMetaClosed ->
335 enrich localization_tbl s
336 (Uncertain (lazy (CicMetaSubst.ppterm subst coercion_src ^ " is not a sort and cannoted be coerced to a sort")))
337 | CoercGraph.SomeCoercion c ->
338 Cic.Appl [c;t],Cic.Sort tgt_sort,subst, metasenv, ugraph)
340 let s',sort1,subst',metasenv',ugraph1 =
341 type_of_aux subst metasenv context s ugraph
343 let s',sort1,subst', metasenv',ugraph1 =
344 coerce_to_sort true (Cic.Type(CicUniv.fresh()))
345 s' sort1 subst' context metasenv' ugraph1
347 let context_for_t = ((Some (name,(C.Decl s')))::context) in
348 let t',sort2,subst'',metasenv'',ugraph2 =
349 type_of_aux subst' metasenv'
350 context_for_t t ugraph1
352 let t',sort2,subst'',metasenv'',ugraph2 =
353 coerce_to_sort false (Cic.Type(CicUniv.fresh()))
354 t' sort2 subst'' context_for_t metasenv'' ugraph2
356 let sop,subst''',metasenv''',ugraph3 =
357 sort_of_prod subst'' metasenv''
358 context (name,s') (sort1,sort2) ugraph2
360 C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
361 | C.Lambda (n,s,t) ->
363 let s',sort1,subst',metasenv',ugraph1 =
364 type_of_aux subst metasenv context s ugraph in
366 match CicReduction.whd ~subst:subst' context sort1 with
368 | C.Sort _ -> s',sort1
370 let coercion_tgt = Cic.Sort (Cic.Type (CicUniv.fresh ())) in
371 let search = CoercGraph.look_for_coercion in
372 let boh = search coercion_src coercion_tgt in
374 | CoercGraph.SomeCoercion c ->
375 Cic.Appl [c;s'], coercion_tgt
376 | CoercGraph.NoCoercion
377 | CoercGraph.NotHandled _
378 | CoercGraph.NotMetaClosed ->
379 raise (RefineFailure (lazy (sprintf
380 "Not well-typed lambda-abstraction: the source %s should be a type; instead it is a term of type %s" (CicPp.ppterm s) (CicPp.ppterm sort1))))
382 let context_for_t = ((Some (n,(C.Decl s')))::context) in
383 let t',type2,subst'',metasenv'',ugraph2 =
384 type_of_aux subst' metasenv' context_for_t t ugraph1
386 C.Lambda (n,s',t'),C.Prod (n,s',type2),
387 subst'',metasenv'',ugraph2
389 (* only to check if s is well-typed *)
390 let s',ty,subst',metasenv',ugraph1 =
391 type_of_aux subst metasenv context s ugraph
393 let context_for_t = ((Some (n,(C.Def (s',Some ty))))::context) in
395 let t',inferredty,subst'',metasenv'',ugraph2 =
396 type_of_aux subst' metasenv'
397 context_for_t t ugraph1
399 (* One-step LetIn reduction.
400 * Even faster than the previous solution.
401 * Moreover the inferred type is closer to the expected one.
403 C.LetIn (n,s',t'),CicSubstitution.subst s' inferredty,
404 subst'',metasenv'',ugraph2
405 | C.Appl (he::((_::_) as tl)) ->
406 let he',hetype,subst',metasenv',ugraph1 =
407 type_of_aux subst metasenv context he ugraph
409 let tlbody_and_type,subst'',metasenv'',ugraph2 =
411 (fun x (res,subst,metasenv,ugraph) ->
412 let x',ty,subst',metasenv',ugraph1 =
413 type_of_aux subst metasenv context x ugraph
415 (x', ty)::res,subst',metasenv',ugraph1
416 ) tl ([],subst',metasenv',ugraph1)
418 let tl',applty,subst''',metasenv''',ugraph3 =
419 eat_prods true subst'' metasenv'' context
420 hetype tlbody_and_type ugraph2
422 C.Appl (he'::tl'), applty,subst''',metasenv''',ugraph3
423 | C.Appl _ -> raise (RefineFailure (lazy "Appl: no arguments"))
424 | C.Const (uri,exp_named_subst) ->
425 let exp_named_subst',subst',metasenv',ugraph1 =
426 check_exp_named_subst subst metasenv context
427 exp_named_subst ugraph in
428 let ty_uri,ugraph2 = type_of_constant uri ugraph1 in
430 CicSubstitution.subst_vars exp_named_subst' ty_uri
432 C.Const (uri,exp_named_subst'),cty,subst',metasenv',ugraph2
433 | C.MutInd (uri,i,exp_named_subst) ->
434 let exp_named_subst',subst',metasenv',ugraph1 =
435 check_exp_named_subst subst metasenv context
436 exp_named_subst ugraph
438 let ty_uri,ugraph2 = type_of_mutual_inductive_defs uri i ugraph1 in
440 CicSubstitution.subst_vars exp_named_subst' ty_uri in
441 C.MutInd (uri,i,exp_named_subst'),cty,subst',metasenv',ugraph2
442 | C.MutConstruct (uri,i,j,exp_named_subst) ->
443 let exp_named_subst',subst',metasenv',ugraph1 =
444 check_exp_named_subst subst metasenv context
445 exp_named_subst ugraph
448 type_of_mutual_inductive_constr uri i j ugraph1
451 CicSubstitution.subst_vars exp_named_subst' ty_uri
453 C.MutConstruct (uri,i,j,exp_named_subst'),cty,subst',
455 | C.MutCase (uri, i, outtype, term, pl) ->
456 (* first, get the inductive type (and noparams)
457 * in the environment *)
458 let (_,b,arity,constructors), expl_params, no_left_params,ugraph =
459 let _ = CicTypeChecker.typecheck uri in
460 let obj,u = CicEnvironment.get_cooked_obj ugraph uri in
462 C.InductiveDefinition (l,expl_params,parsno,_) ->
463 List.nth l i , expl_params, parsno, u
467 (lazy ("Unkown mutual inductive definition " ^
468 U.string_of_uri uri)))
470 let rec count_prod t =
471 match CicReduction.whd ~subst context t with
472 C.Prod (_, _, t) -> 1 + (count_prod t)
475 let no_args = count_prod arity in
476 (* now, create a "generic" MutInd *)
477 let metasenv,left_args =
478 CicMkImplicit.n_fresh_metas metasenv subst context no_left_params
480 let metasenv,right_args =
481 let no_right_params = no_args - no_left_params in
482 if no_right_params < 0 then assert false
483 else CicMkImplicit.n_fresh_metas
484 metasenv subst context no_right_params
486 let metasenv,exp_named_subst =
487 CicMkImplicit.fresh_subst metasenv subst context expl_params in
490 C.MutInd (uri,i,exp_named_subst)
493 (C.MutInd (uri,i,exp_named_subst)::(left_args @ right_args))
495 (* check consistency with the actual type of term *)
496 let term',actual_type,subst,metasenv,ugraph1 =
497 type_of_aux subst metasenv context term ugraph in
498 let expected_type',_, subst, metasenv,ugraph2 =
499 type_of_aux subst metasenv context expected_type ugraph1
501 let actual_type = CicReduction.whd ~subst context actual_type in
502 let subst,metasenv,ugraph3 =
503 fo_unif_subst subst context metasenv
504 expected_type' actual_type ugraph2
506 let rec instantiate_prod t =
510 match CicReduction.whd ~subst context t with
512 instantiate_prod (CicSubstitution.subst he t') tl
515 let arity_instantiated_with_left_args =
516 instantiate_prod arity left_args in
517 (* TODO: check if the sort elimination
518 * is allowed: [(I q1 ... qr)|B] *)
519 let (pl',_,outtypeinstances,subst,metasenv,ugraph4) =
521 (fun (pl,j,outtypeinstances,subst,metasenv,ugraph) p ->
523 if left_args = [] then
524 (C.MutConstruct (uri,i,j,exp_named_subst))
527 (C.MutConstruct (uri,i,j,exp_named_subst)::left_args))
529 let p',actual_type,subst,metasenv,ugraph1 =
530 type_of_aux subst metasenv context p ugraph
532 let constructor',expected_type, subst, metasenv,ugraph2 =
533 type_of_aux subst metasenv context constructor ugraph1
535 let outtypeinstance,subst,metasenv,ugraph3 =
536 check_branch 0 context metasenv subst no_left_params
537 actual_type constructor' expected_type ugraph2
540 outtypeinstance::outtypeinstances,subst,metasenv,ugraph3))
541 ([],1,[],subst,metasenv,ugraph3) pl
544 (* we are left to check that the outype matches his instances.
545 The easy case is when the outype is specified, that amount
546 to a trivial check. Otherwise, we should guess a type from
550 let outtype,outtypety, subst, metasenv,ugraph4 =
551 type_of_aux subst metasenv context outtype ugraph4 in
554 (let candidate,ugraph5,metasenv,subst =
555 let exp_name_subst, metasenv =
557 CicEnvironment.get_cooked_obj CicUniv.empty_ugraph uri
559 let uris = CicUtil.params_of_obj o in
561 fun uri (acc,metasenv) ->
562 let metasenv',new_meta =
563 CicMkImplicit.mk_implicit metasenv subst context
566 CicMkImplicit.identity_relocation_list_for_metavariable
569 (uri, Cic.Meta(new_meta,irl))::acc, metasenv'
573 match left_args,right_args with
574 [],[] -> Cic.MutInd(uri, i, exp_name_subst)
576 let rec mk_right_args =
579 | n -> (Cic.Rel n)::(mk_right_args (n - 1))
581 let right_args_no = List.length right_args in
582 let lifted_left_args =
583 List.map (CicSubstitution.lift right_args_no) left_args
585 Cic.Appl (Cic.MutInd(uri,i,exp_name_subst)::
586 (lifted_left_args @ mk_right_args right_args_no))
589 FreshNamesGenerator.mk_fresh_name ~subst metasenv
590 context Cic.Anonymous ~typ:ty
592 match outtypeinstances with
594 let extended_context =
595 let rec add_right_args =
597 Cic.Prod (name,ty,t) ->
598 Some (name,Cic.Decl ty)::(add_right_args t)
601 (Some (fresh_name,Cic.Decl ty))::
603 (add_right_args arity_instantiated_with_left_args))@
606 let metasenv,new_meta =
607 CicMkImplicit.mk_implicit metasenv subst extended_context
610 CicMkImplicit.identity_relocation_list_for_metavariable
613 let rec add_lambdas b =
615 Cic.Prod (name,ty,t) ->
616 Cic.Lambda (name,ty,(add_lambdas b t))
617 | _ -> Cic.Lambda (fresh_name, ty, b)
620 add_lambdas (Cic.Meta (new_meta,irl))
621 arity_instantiated_with_left_args
623 (Some candidate),ugraph4,metasenv,subst
624 | (constructor_args_no,_,instance,_)::tl ->
626 let instance',subst,metasenv =
627 CicMetaSubst.delift_rels subst metasenv
628 constructor_args_no instance
630 let candidate,ugraph,metasenv,subst =
632 fun (candidate_oty,ugraph,metasenv,subst)
633 (constructor_args_no,_,instance,_) ->
634 match candidate_oty with
635 | None -> None,ugraph,metasenv,subst
638 let instance',subst,metasenv =
639 CicMetaSubst.delift_rels subst metasenv
640 constructor_args_no instance
642 let subst,metasenv,ugraph =
643 fo_unif_subst subst context metasenv
646 candidate_oty,ugraph,metasenv,subst
648 CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable
649 | CicUnification.UnificationFailure _
650 | CicUnification.Uncertain _ ->
651 None,ugraph,metasenv,subst
652 ) (Some instance',ugraph4,metasenv,subst) tl
655 | None -> None, ugraph,metasenv,subst
657 let rec add_lambdas n b =
659 Cic.Prod (name,ty,t) ->
660 Cic.Lambda (name,ty,(add_lambdas (n + 1) b t))
662 Cic.Lambda (fresh_name, ty,
663 CicSubstitution.lift (n + 1) t)
666 (add_lambdas 0 t arity_instantiated_with_left_args),
667 ugraph,metasenv,subst
668 with CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
669 None,ugraph4,metasenv,subst
672 | None -> raise (Uncertain (lazy "can't solve an higher order unification problem"))
674 let subst,metasenv,ugraph =
675 fo_unif_subst subst context metasenv
676 candidate outtype ugraph5
678 C.MutCase (uri, i, outtype, term', pl'),
679 CicReduction.head_beta_reduce
680 (CicMetaSubst.apply_subst subst
681 (Cic.Appl (outtype::right_args@[term']))),
682 subst,metasenv,ugraph)
683 | _ -> (* easy case *)
684 let tlbody_and_type,subst,metasenv,ugraph4 =
686 (fun x (res,subst,metasenv,ugraph) ->
687 let x',ty,subst',metasenv',ugraph1 =
688 type_of_aux subst metasenv context x ugraph
690 (x', ty)::res,subst',metasenv',ugraph1
691 ) (right_args @ [term']) ([],subst,metasenv,ugraph4)
693 let _,_,subst,metasenv,ugraph4 =
694 eat_prods false subst metasenv context
695 outtypety tlbody_and_type ugraph4
697 let _,_, subst, metasenv,ugraph5 =
698 type_of_aux subst metasenv context
699 (C.Appl ((outtype :: right_args) @ [term'])) ugraph4
701 let (subst,metasenv,ugraph6) =
703 (fun (subst,metasenv,ugraph)
704 (constructor_args_no,context,instance,args) ->
708 CicSubstitution.lift constructor_args_no outtype
710 C.Appl (outtype'::args)
712 CicReduction.whd ~subst context appl
714 fo_unif_subst subst context metasenv
715 instance instance' ugraph)
716 (subst,metasenv,ugraph5) outtypeinstances
718 C.MutCase (uri, i, outtype, term', pl'),
719 CicReduction.head_beta_reduce
720 (CicMetaSubst.apply_subst subst
721 (C.Appl(outtype::right_args@[term]))),
722 subst,metasenv,ugraph6)
724 let fl_ty',subst,metasenv,types,ugraph1 =
726 (fun (fl,subst,metasenv,types,ugraph) (n,_,ty,_) ->
727 let ty',_,subst',metasenv',ugraph1 =
728 type_of_aux subst metasenv context ty ugraph
730 fl @ [ty'],subst',metasenv',
731 Some (C.Name n,(C.Decl ty')) :: types, ugraph
732 ) ([],subst,metasenv,[],ugraph) fl
734 let len = List.length types in
735 let context' = types@context in
736 let fl_bo',subst,metasenv,ugraph2 =
738 (fun (fl,subst,metasenv,ugraph) ((name,x,_,bo),ty) ->
739 let bo',ty_of_bo,subst,metasenv,ugraph1 =
740 type_of_aux subst metasenv context' bo ugraph
742 let subst',metasenv',ugraph' =
743 fo_unif_subst subst context' metasenv
744 ty_of_bo (CicSubstitution.lift len ty) ugraph1
746 fl @ [bo'] , subst',metasenv',ugraph'
747 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
749 let ty = List.nth fl_ty' i in
750 (* now we have the new ty in fl_ty', the new bo in fl_bo',
751 * and we want the new fl with bo' and ty' injected in the right
754 let rec map3 f l1 l2 l3 =
757 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
760 let fl'' = map3 (fun ty' bo' (name,x,ty,bo) -> (name,x,ty',bo') )
763 C.Fix (i,fl''),ty,subst,metasenv,ugraph2
765 let fl_ty',subst,metasenv,types,ugraph1 =
767 (fun (fl,subst,metasenv,types,ugraph) (n,ty,_) ->
768 let ty',_,subst',metasenv',ugraph1 =
769 type_of_aux subst metasenv context ty ugraph
771 fl @ [ty'],subst',metasenv',
772 Some (C.Name n,(C.Decl ty')) :: types, ugraph1
773 ) ([],subst,metasenv,[],ugraph) fl
775 let len = List.length types in
776 let context' = types@context in
777 let fl_bo',subst,metasenv,ugraph2 =
779 (fun (fl,subst,metasenv,ugraph) ((name,_,bo),ty) ->
780 let bo',ty_of_bo,subst,metasenv,ugraph1 =
781 type_of_aux subst metasenv context' bo ugraph
783 let subst',metasenv',ugraph' =
784 fo_unif_subst subst context' metasenv
785 ty_of_bo (CicSubstitution.lift len ty) ugraph1
787 fl @ [bo'],subst',metasenv',ugraph'
788 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
790 let ty = List.nth fl_ty' i in
791 (* now we have the new ty in fl_ty', the new bo in fl_bo',
792 * and we want the new fl with bo' and ty' injected in the right
795 let rec map3 f l1 l2 l3 =
798 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
801 let fl'' = map3 (fun ty' bo' (name,ty,bo) -> (name,ty',bo') )
804 C.CoFix (i,fl''),ty,subst,metasenv,ugraph2
806 relocalize localization_tbl t t';
809 (* check_metasenv_consistency checks that the "canonical" context of a
810 metavariable is consitent - up to relocation via the relocation list l -
811 with the actual context *)
812 and check_metasenv_consistency
813 metano subst metasenv context canonical_context l ugraph
815 let module C = Cic in
816 let module R = CicReduction in
817 let module S = CicSubstitution in
818 let lifted_canonical_context =
822 | (Some (n,C.Decl t))::tl ->
823 (Some (n,C.Decl (S.subst_meta l (S.lift i t))))::(aux (i+1) tl)
824 | (Some (n,C.Def (t,None)))::tl ->
825 (Some (n,C.Def ((S.subst_meta l (S.lift i t)),None)))::(aux (i+1) tl)
826 | None::tl -> None::(aux (i+1) tl)
827 | (Some (n,C.Def (t,Some ty)))::tl ->
829 C.Def ((S.subst_meta l (S.lift i t)),
830 Some (S.subst_meta l (S.lift i ty))))) :: (aux (i+1) tl)
832 aux 1 canonical_context
836 (fun (l,subst,metasenv,ugraph) t ct ->
839 l @ [None],subst,metasenv,ugraph
840 | Some t,Some (_,C.Def (ct,_)) ->
841 let subst',metasenv',ugraph' =
843 fo_unif_subst subst context metasenv t ct ugraph
844 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))))))
846 l @ [Some t],subst',metasenv',ugraph'
847 | Some t,Some (_,C.Decl ct) ->
848 let t',inferredty,subst',metasenv',ugraph1 =
849 type_of_aux subst metasenv context t ugraph
851 let subst'',metasenv'',ugraph2 =
854 subst' context metasenv' inferredty ct ugraph1
855 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))))))
857 l @ [Some t'], subst'',metasenv'',ugraph2
859 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
861 Invalid_argument _ ->
865 "Not well typed metavariable instance %s: the length of the local context does not match the length of the canonical context %s"
866 (CicMetaSubst.ppterm subst (Cic.Meta (metano, l)))
867 (CicMetaSubst.ppcontext subst canonical_context))))
869 and check_exp_named_subst metasubst metasenv context tl ugraph =
870 let rec check_exp_named_subst_aux metasubst metasenv substs tl ugraph =
872 [] -> [],metasubst,metasenv,ugraph
874 let ty_uri,ugraph1 = type_of_variable uri ugraph in
876 CicSubstitution.subst_vars substs ty_uri in
877 (* CSC: why was this code here? it is wrong
878 (match CicEnvironment.get_cooked_obj ~trust:false uri with
879 Cic.Variable (_,Some bo,_,_) ->
882 "A variable with a body can not be explicit substituted"))
883 | Cic.Variable (_,None,_,_) -> ()
887 ("Unkown variable definition " ^ UriManager.string_of_uri uri)))
890 let t',typeoft,metasubst',metasenv',ugraph2 =
891 type_of_aux metasubst metasenv context t ugraph1 in
892 let subst = uri,t' in
893 let metasubst'',metasenv'',ugraph3 =
896 metasubst' context metasenv' typeoft typeofvar ugraph2
898 raise (RefineFailure (lazy
899 ("Wrong Explicit Named Substitution: " ^
900 CicMetaSubst.ppterm metasubst' typeoft ^
901 " not unifiable with " ^
902 CicMetaSubst.ppterm metasubst' typeofvar)))
904 (* FIXME: no mere tail recursive! *)
905 let exp_name_subst, metasubst''', metasenv''', ugraph4 =
906 check_exp_named_subst_aux
907 metasubst'' metasenv'' (substs@[subst]) tl ugraph3
909 ((uri,t')::exp_name_subst), metasubst''', metasenv''', ugraph4
911 check_exp_named_subst_aux metasubst metasenv [] tl ugraph
914 and sort_of_prod subst metasenv context (name,s) (t1, t2) ugraph =
915 let module C = Cic in
916 let context_for_t2 = (Some (name,C.Decl s))::context in
917 let t1'' = CicReduction.whd ~subst context t1 in
918 let t2'' = CicReduction.whd ~subst context_for_t2 t2 in
919 match (t1'', t2'') with
920 (C.Sort s1, C.Sort s2)
921 when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) ->
922 (* different than Coq manual!!! *)
923 C.Sort s2,subst,metasenv,ugraph
924 | (C.Sort (C.Type t1), C.Sort (C.Type t2)) ->
925 let t' = CicUniv.fresh() in
926 let ugraph1 = CicUniv.add_ge t' t1 ugraph in
927 let ugraph2 = CicUniv.add_ge t' t2 ugraph1 in
928 C.Sort (C.Type t'),subst,metasenv,ugraph2
929 | (C.Sort _,C.Sort (C.Type t1)) ->
930 C.Sort (C.Type t1),subst,metasenv,ugraph
931 | (C.Meta _, C.Sort _) -> t2'',subst,metasenv,ugraph
932 | (C.Sort _,C.Meta _) | (C.Meta _,C.Meta _) ->
933 (* TODO how can we force the meta to become a sort? If we don't we
934 * brake the invariant that refine produce only well typed terms *)
935 (* TODO if we check the non meta term and if it is a sort then we
936 * are likely to know the exact value of the result e.g. if the rhs
937 * is a Sort (Prop | Set | CProp) then the result is the rhs *)
939 CicMkImplicit.mk_implicit_sort metasenv subst in
940 let (subst, metasenv,ugraph1) =
941 fo_unif_subst subst context_for_t2 metasenv
942 (C.Meta (idx,[])) t2'' ugraph
944 t2'',subst,metasenv,ugraph1
950 ("Two sorts were expected, found %s " ^^
951 "(that reduces to %s) and %s (that reduces to %s)")
952 (CicPp.ppterm t1) (CicPp.ppterm t1'') (CicPp.ppterm t2)
953 (CicPp.ppterm t2''))))
956 allow_coercions subst metasenv context hetype tlbody_and_type ugraph
958 let rec mk_prod metasenv context =
961 let (metasenv, idx) =
962 CicMkImplicit.mk_implicit_type metasenv subst context
965 CicMkImplicit.identity_relocation_list_for_metavariable context
967 metasenv,Cic.Meta (idx, irl)
969 let (metasenv, idx) =
970 CicMkImplicit.mk_implicit_type metasenv subst context
973 CicMkImplicit.identity_relocation_list_for_metavariable context
975 let meta = Cic.Meta (idx,irl) in
977 (* The name must be fresh for context. *)
978 (* Nevertheless, argty is well-typed only in context. *)
979 (* Thus I generate a name (name_hint) in context and *)
980 (* then I generate a name --- using the hint name_hint *)
981 (* --- that is fresh in (context'@context). *)
983 (* Cic.Name "pippo" *)
984 FreshNamesGenerator.mk_fresh_name ~subst metasenv
985 (* (CicMetaSubst.apply_subst_metasenv subst metasenv) *)
986 (CicMetaSubst.apply_subst_context subst context)
988 ~typ:(CicMetaSubst.apply_subst subst argty)
990 (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
991 FreshNamesGenerator.mk_fresh_name ~subst
992 [] context name_hint ~typ:(Cic.Sort Cic.Prop)
994 let metasenv,target =
995 mk_prod metasenv ((Some (name, Cic.Decl meta))::context) tl
997 metasenv,Cic.Prod (name,meta,target)
999 let metasenv,hetype' = mk_prod metasenv context tlbody_and_type in
1000 let (subst, metasenv,ugraph1) =
1002 fo_unif_subst subst context metasenv hetype hetype' ugraph
1004 debug_print (lazy (Printf.sprintf "hetype=%s\nhetype'=%s\nmetasenv=%s\nsubst=%s"
1005 (CicPp.ppterm hetype)
1006 (CicPp.ppterm hetype')
1007 (CicMetaSubst.ppmetasenv [] metasenv)
1008 (CicMetaSubst.ppsubst subst)));
1012 let rec eat_prods metasenv subst context hetype ugraph =
1014 | [] -> [],metasenv,subst,hetype,ugraph
1015 | (hete, hety)::tl ->
1018 let arg,subst,metasenv,ugraph1 =
1020 let subst,metasenv,ugraph1 =
1021 fo_unif_subst subst context metasenv hety s ugraph
1023 hete,subst,metasenv,ugraph1
1024 with exn when allow_coercions ->
1025 (* we search a coercion from hety to s *)
1027 let carr t subst context =
1028 CicMetaSubst.apply_subst subst t
1030 let c_hety = carr hety subst context in
1031 let c_s = carr s subst context in
1032 CoercGraph.look_for_coercion c_hety c_s
1035 | CoercGraph.NoCoercion
1036 | CoercGraph.NotHandled _ ->
1039 CicMetaSubst.ppterm_in_context subst hete
1040 context ^ " has type " ^
1041 CicMetaSubst.ppterm_in_context subst hety
1042 context ^ " but is here used with type " ^
1043 CicMetaSubst.ppterm_in_context subst s context
1044 (* "\nReason: " ^ Lazy.force e*))
1046 enrich localization_tbl hete ~f:msg exn
1047 | CoercGraph.NotMetaClosed ->
1048 raise (Uncertain (lazy "Coercions on meta"))
1049 | CoercGraph.SomeCoercion c ->
1050 (Cic.Appl [ c ; hete ]), subst, metasenv, ugraph
1052 let coerced_args,metasenv',subst',t',ugraph2 =
1053 eat_prods metasenv subst context
1054 (CicSubstitution.subst arg t) ugraph1 tl
1056 arg::coerced_args,metasenv',subst',t',ugraph2
1060 let coerced_args,metasenv,subst,t,ugraph2 =
1061 eat_prods metasenv subst context hetype' ugraph1 tlbody_and_type
1063 coerced_args,t,subst,metasenv,ugraph2
1066 (* eat prods ends here! *)
1068 let t',ty,subst',metasenv',ugraph1 =
1069 type_of_aux [] metasenv context t ugraph
1071 let substituted_t = CicMetaSubst.apply_subst subst' t' in
1072 let substituted_ty = CicMetaSubst.apply_subst subst' ty in
1073 (* Andrea: ho rimesso qui l'applicazione della subst al
1074 metasenv dopo che ho droppato l'invariante che il metsaenv
1075 e' sempre istanziato *)
1076 let substituted_metasenv =
1077 CicMetaSubst.apply_subst_metasenv subst' metasenv' in
1079 (* substituted_t,substituted_ty,substituted_metasenv *)
1080 (* ANDREA: spostare tutta questa robaccia da un altra parte *)
1082 FreshNamesGenerator.clean_dummy_dependent_types substituted_t in
1084 FreshNamesGenerator.clean_dummy_dependent_types substituted_ty in
1085 let cleaned_metasenv =
1087 (function (n,context,ty) ->
1088 let ty' = FreshNamesGenerator.clean_dummy_dependent_types ty in
1093 | Some (n, Cic.Decl t) ->
1095 Cic.Decl (FreshNamesGenerator.clean_dummy_dependent_types t))
1096 | Some (n, Cic.Def (bo,ty)) ->
1097 let bo' = FreshNamesGenerator.clean_dummy_dependent_types bo in
1102 Some (FreshNamesGenerator.clean_dummy_dependent_types ty)
1104 Some (n, Cic.Def (bo',ty'))
1108 ) substituted_metasenv
1110 (cleaned_t,cleaned_ty,cleaned_metasenv,ugraph1)
1113 let type_of_aux' ?localization_tbl metasenv context term ugraph =
1115 type_of_aux' ?localization_tbl metasenv context term ugraph
1117 CicUniv.UniverseInconsistency msg -> raise (RefineFailure (lazy msg))
1119 let undebrujin uri typesno tys t =
1122 (fun (name,_,_,_) (i,t) ->
1123 (* here the explicit_named_substituion is assumed to be *)
1125 let t' = Cic.MutInd (uri,i,[]) in
1126 let t = CicSubstitution.subst t' t in
1128 ) tys (typesno - 1,t))
1130 let map_first_n n start f g l =
1131 let rec aux acc k l =
1134 | [] -> raise (Invalid_argument "map_first_n")
1135 | hd :: tl -> f hd k (aux acc (k+1) tl)
1141 (*CSC: this is a very rough approximation; to be finished *)
1142 let are_all_occurrences_positive metasenv ugraph uri tys leftno =
1143 let subst,metasenv,ugraph,tys =
1145 (fun (name,ind,arity,cl) (subst,metasenv,ugraph,acc) ->
1146 let subst,metasenv,ugraph,cl =
1148 (fun (name,ty) (subst,metasenv,ugraph,acc) ->
1149 let rec aux ctx k subst = function
1150 | Cic.Appl((Cic.MutInd (uri',_,_)as hd)::tl) when uri = uri'->
1151 let subst,metasenv,ugraph,tl =
1153 (subst,metasenv,ugraph,[])
1154 (fun t n (subst,metasenv,ugraph,acc) ->
1155 let subst,metasenv,ugraph =
1157 subst ctx metasenv t (Cic.Rel (k-n)) ugraph
1159 subst,metasenv,ugraph,(t::acc))
1160 (fun (s,m,g,acc) tl -> assert(acc=[]);(s,m,g,tl))
1163 subst,metasenv,ugraph,(Cic.Appl (hd::tl))
1164 | Cic.MutInd(uri',_,_) as t when uri = uri'->
1165 subst,metasenv,ugraph,t
1166 | Cic.Prod (name,s,t) ->
1167 let ctx = (Some (name,Cic.Decl s))::ctx in
1168 let subst,metasenv,ugraph,t = aux ctx (k+1) subst t in
1169 subst,metasenv,ugraph,Cic.Prod (name,s,t)
1173 (lazy "not well formed constructor type"))
1175 let subst,metasenv,ugraph,ty = aux [] 0 subst ty in
1176 subst,metasenv,ugraph,(name,ty) :: acc)
1177 cl (subst,metasenv,ugraph,[])
1179 subst,metasenv,ugraph,(name,ind,arity,cl)::acc)
1180 tys ([],metasenv,ugraph,[])
1182 let substituted_tys =
1184 (fun (name,ind,arity,cl) ->
1186 List.map (fun (name, ty) -> name,CicMetaSubst.apply_subst subst ty) cl
1188 name,ind,CicMetaSubst.apply_subst subst arity,cl)
1191 metasenv,ugraph,substituted_tys
1193 let typecheck metasenv uri obj ~localization_tbl =
1194 let ugraph = CicUniv.empty_ugraph in
1196 Cic.Constant (name,Some bo,ty,args,attrs) ->
1197 let bo',boty,metasenv,ugraph =
1198 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1199 let ty',_,metasenv,ugraph =
1200 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1201 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1202 let bo' = CicMetaSubst.apply_subst subst bo' in
1203 let ty' = CicMetaSubst.apply_subst subst ty' in
1204 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1205 Cic.Constant (name,Some bo',ty',args,attrs),metasenv,ugraph
1206 | Cic.Constant (name,None,ty,args,attrs) ->
1207 let ty',_,metasenv,ugraph =
1208 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1210 Cic.Constant (name,None,ty',args,attrs),metasenv,ugraph
1211 | Cic.CurrentProof (name,metasenv',bo,ty,args,attrs) ->
1212 assert (metasenv' = metasenv);
1213 (* Here we do not check the metasenv for correctness *)
1214 let bo',boty,metasenv,ugraph =
1215 type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1216 let ty',sort,metasenv,ugraph =
1217 type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1221 (* instead of raising Uncertain, let's hope that the meta will become
1224 | _ -> raise (RefineFailure (lazy "The term provided is not a type"))
1226 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1227 let bo' = CicMetaSubst.apply_subst subst bo' in
1228 let ty' = CicMetaSubst.apply_subst subst ty' in
1229 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1230 Cic.CurrentProof (name,metasenv,bo',ty',args,attrs),metasenv,ugraph
1231 | Cic.Variable _ -> assert false (* not implemented *)
1232 | Cic.InductiveDefinition (tys,args,paramsno,attrs) ->
1233 (*CSC: this code is greately simplified and many many checks are missing *)
1234 (*CSC: e.g. the constructors are not required to build their own types, *)
1235 (*CSC: the arities are not required to have as type a sort, etc. *)
1236 let uri = match uri with Some uri -> uri | None -> assert false in
1237 let typesno = List.length tys in
1238 (* first phase: we fix only the types *)
1239 let metasenv,ugraph,tys =
1241 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1242 let ty',_,metasenv,ugraph =
1243 type_of_aux' ~localization_tbl metasenv [] ty ugraph
1245 metasenv,ugraph,(name,b,ty',cl)::res
1246 ) tys (metasenv,ugraph,[]) in
1248 List.rev_map (fun (name,_,ty,_)-> Some (Cic.Name name,Cic.Decl ty)) tys in
1249 (* second phase: we fix only the constructors *)
1250 let metasenv,ugraph,tys =
1252 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1253 let metasenv,ugraph,cl' =
1255 (fun (name,ty) (metasenv,ugraph,res) ->
1256 let ty = CicTypeChecker.debrujin_constructor uri typesno ty in
1257 let ty',_,metasenv,ugraph =
1258 type_of_aux' ~localization_tbl metasenv con_context ty ugraph in
1259 let ty' = undebrujin uri typesno tys ty' in
1260 metasenv,ugraph,(name,ty')::res
1261 ) cl (metasenv,ugraph,[])
1263 metasenv,ugraph,(name,b,ty,cl')::res
1264 ) tys (metasenv,ugraph,[]) in
1265 (* third phase: we check the positivity condition *)
1266 let metasenv,ugraph,tys =
1267 are_all_occurrences_positive metasenv ugraph uri tys paramsno
1269 Cic.InductiveDefinition (tys,args,paramsno,attrs),metasenv,ugraph
1272 let type_of_aux' metasenv context term =
1275 type_of_aux' metasenv context term in
1277 ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty));
1279 ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []));
1282 | RefineFailure msg as e ->
1283 debug_print (lazy ("@@@ REFINE FAILED: " ^ msg));
1285 | Uncertain msg as e ->
1286 debug_print (lazy ("@@@ REFINE UNCERTAIN: " ^ msg));
1290 let profiler2 = HExtlib.profile "CicRefine"
1292 let type_of_aux' ?localization_tbl metasenv context term ugraph =
1293 profiler2.HExtlib.profile
1294 (type_of_aux' ?localization_tbl metasenv context term) ugraph
1296 let typecheck ~localization_tbl metasenv uri obj =
1297 profiler2.HExtlib.profile (typecheck ~localization_tbl metasenv uri) obj