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 | UnificationFailure of CicUnification.failure_msg
35 | UnificationFailure msg -> CicUnification.explain_error msg
37 exception RefineFailure of failure_msg;;
38 exception Uncertain of string;;
39 exception AssertFailure of string;;
41 let debug_print = fun _ -> ()
43 let profiler = HExtlib.profile "CicRefine.fo_unif"
45 let fo_unif_subst subst context metasenv t1 t2 ugraph =
48 CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
49 in profiler.HExtlib.profile foo ()
51 (CicUnification.UnificationFailure msg) -> raise (RefineFailure (UnificationFailure msg))
52 | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
58 | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
59 | (_,_) -> raise (AssertFailure "split: list too short")
62 let rec type_of_constant uri ugraph =
64 let module R = CicReduction in
65 let module U = UriManager in
66 let _ = CicTypeChecker.typecheck uri in
69 CicEnvironment.get_cooked_obj ugraph uri
70 with Not_found -> assert false
73 C.Constant (_,_,ty,_,_) -> ty,u
74 | C.CurrentProof (_,_,_,ty,_,_) -> ty,u
77 (RefineFailure (Reason ("Unknown constant definition " ^ U.string_of_uri uri)))
79 and type_of_variable uri ugraph =
81 let module R = CicReduction in
82 let module U = UriManager in
83 let _ = CicTypeChecker.typecheck uri in
86 CicEnvironment.get_cooked_obj ugraph uri
87 with Not_found -> assert false
90 C.Variable (_,_,ty,_,_) -> ty,u
94 (Reason ("Unknown variable definition " ^ UriManager.string_of_uri uri)))
96 and type_of_mutual_inductive_defs uri i ugraph =
98 let module R = CicReduction in
99 let module U = UriManager in
100 let _ = CicTypeChecker.typecheck uri in
103 CicEnvironment.get_cooked_obj ugraph uri
104 with Not_found -> assert false
107 C.InductiveDefinition (dl,_,_,_) ->
108 let (_,_,arity,_) = List.nth dl i in
113 (Reason ("Unknown mutual inductive definition " ^ U.string_of_uri uri)))
115 and type_of_mutual_inductive_constr uri i j ugraph =
116 let module C = Cic in
117 let module R = CicReduction in
118 let module U = UriManager in
119 let _ = CicTypeChecker.typecheck uri in
122 CicEnvironment.get_cooked_obj ugraph uri
123 with Not_found -> assert false
126 C.InductiveDefinition (dl,_,_,_) ->
127 let (_,_,_,cl) = List.nth dl i in
128 let (_,ty) = List.nth cl (j-1) in
133 (Reason ("Unkown mutual inductive definition " ^ U.string_of_uri uri)))
136 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
138 (* the check_branch function checks if a branch of a case is refinable.
139 It returns a pair (outype_instance,args), a subst and a metasenv.
140 outype_instance is the expected result of applying the case outtype
142 The problem is that outype is in general unknown, and we should
143 try to synthesize it from the above information, that is in general
144 a second order unification problem. *)
146 and check_branch n context metasenv subst left_args_no actualtype term expectedtype ugraph =
147 let module C = Cic in
148 (* let module R = CicMetaSubst in *)
149 let module R = CicReduction in
150 match R.whd ~subst context expectedtype with
152 (n,context,actualtype, [term]), subst, metasenv, ugraph
153 | C.Appl (C.MutInd (_,_,_)::tl) ->
154 let (_,arguments) = split tl left_args_no in
155 (n,context,actualtype, arguments@[term]), subst, metasenv, ugraph
156 | C.Prod (name,so,de) ->
157 (* we expect that the actual type of the branch has the due
159 (match R.whd ~subst context actualtype with
160 C.Prod (name',so',de') ->
161 let subst, metasenv, ugraph1 =
162 fo_unif_subst subst context metasenv so so' ugraph in
164 (match CicSubstitution.lift 1 term with
165 C.Appl l -> C.Appl (l@[C.Rel 1])
166 | t -> C.Appl [t ; C.Rel 1]) in
167 (* we should also check that the name variable is anonymous in
168 the actual type de' ?? *)
170 ((Some (name,(C.Decl so)))::context)
171 metasenv subst left_args_no de' term' de ugraph1
172 | _ -> raise (AssertFailure "Wrong number of arguments"))
173 | _ -> raise (AssertFailure "Prod or MutInd expected")
175 and type_of_aux' metasenv context t ugraph =
176 let rec type_of_aux subst metasenv context t ugraph =
177 let module C = Cic in
178 let module S = CicSubstitution in
179 let module U = UriManager in
184 match List.nth context (n - 1) with
185 Some (_,C.Decl ty) ->
186 t,S.lift n ty,subst,metasenv, ugraph
187 | Some (_,C.Def (_,Some ty)) ->
188 t,S.lift n ty,subst,metasenv, ugraph
189 | Some (_,C.Def (bo,None)) ->
191 (* if it is in the context it must be already well-typed*)
192 CicTypeChecker.type_of_aux' ~subst metasenv context
195 t,ty,subst,metasenv,ugraph
196 | None -> raise (RefineFailure (Reason "Rel to hidden hypothesis"))
198 _ -> raise (RefineFailure (Reason "Not a close term"))
200 | C.Var (uri,exp_named_subst) ->
201 let exp_named_subst',subst',metasenv',ugraph1 =
202 check_exp_named_subst
203 subst metasenv context exp_named_subst ugraph
205 let ty_uri,ugraph1 = type_of_variable uri ugraph in
207 CicSubstitution.subst_vars exp_named_subst' ty_uri
209 C.Var (uri,exp_named_subst'),ty,subst',metasenv',ugraph1
212 let (canonical_context, term,ty) =
213 CicUtil.lookup_subst n subst
215 let l',subst',metasenv',ugraph1 =
216 check_metasenv_consistency n subst metasenv context
217 canonical_context l ugraph
219 (* trust or check ??? *)
220 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
221 subst', metasenv', ugraph1
222 (* type_of_aux subst metasenv
223 context (CicSubstitution.subst_meta l term) *)
224 with CicUtil.Subst_not_found _ ->
225 let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
226 let l',subst',metasenv', ugraph1 =
227 check_metasenv_consistency n subst metasenv context
228 canonical_context l ugraph
230 C.Meta (n,l'),CicSubstitution.subst_meta l' ty,
231 subst', metasenv',ugraph1)
232 | C.Sort (C.Type tno) ->
233 let tno' = CicUniv.fresh() in
234 let ugraph1 = CicUniv.add_gt tno' tno ugraph in
235 t,(C.Sort (C.Type tno')),subst,metasenv,ugraph1
237 t,C.Sort (C.Type (CicUniv.fresh())),subst,metasenv,ugraph
238 | C.Implicit _ -> raise (AssertFailure "21")
240 let ty',_,subst',metasenv',ugraph1 =
241 type_of_aux subst metasenv context ty ugraph
243 let te',inferredty,subst'',metasenv'',ugraph2 =
244 type_of_aux subst' metasenv' context te ugraph1
247 let subst''',metasenv''',ugraph3 =
248 fo_unif_subst subst'' context metasenv''
249 inferredty ty ugraph2
251 C.Cast (te',ty'),ty',subst''',metasenv''',ugraph3
253 _ -> raise (RefineFailure (Reason "Cast")))
254 | C.Prod (name,s,t) ->
255 let s',sort1,subst',metasenv',ugraph1 =
256 type_of_aux subst metasenv context s ugraph
258 let t',sort2,subst'',metasenv'',ugraph2 =
259 type_of_aux subst' metasenv'
260 ((Some (name,(C.Decl s')))::context) t ugraph1
263 let sop,subst''',metasenv''',ugraph3 =
264 sort_of_prod subst'' metasenv''
265 context (name,s') (sort1,sort2) ugraph2
267 C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
269 | RefineFailure _ as exn ->
270 (* given [t] of type [type_to_coerce] returns
271 * a term that has type [tgt_sort] eventually
272 * derived from (coercion [t]) *)
273 let refined_target = t' in
274 let sort_of_refined_target = sort2 in
275 let carr t subst context = CicMetaSubst.apply_subst subst t in
276 let coerce_to_sort tgt_sort t type_to_coerce subst ctx =
277 match type_to_coerce with
280 let coercion_src = carr type_to_coerce subst ctx in
281 let coercion_tgt = carr (Cic.Sort tgt_sort) subst ctx in
282 let search = CoercGraph.look_for_coercion in
283 (match search coercion_src coercion_tgt with
284 | CoercGraph.NoCoercion
285 | CoercGraph.NotHandled _ -> raise exn
286 | CoercGraph.NotMetaClosed ->
287 raise (Uncertain "Coercions on metas")
288 | CoercGraph.SomeCoercion c -> Cic.Appl [c;t])
290 (* this is probably not the best... *)
291 let tgt_sort_for_pi_source = Cic.Type(CicUniv.fresh()) in
292 let tgt_sort_for_pi_target = Cic.Type(CicUniv.fresh()) in
294 coerce_to_sort tgt_sort_for_pi_source s sort1 subst context
296 let context_with_new_src =
297 ((Some (name,(C.Decl new_src)))::context)
301 tgt_sort_for_pi_target
302 refined_target sort_of_refined_target
303 subst context_with_new_src
305 let newprod = C.Prod (name,new_src,new_tgt) in
306 let _,sort_of_refined_prod,subst,metasenv,ugraph3 =
307 type_of_aux subst metasenv context newprod ugraph2
309 (* this if for a coercion on the tail of the arrow *)
311 match sort_of_refined_target with
312 | Cic.Sort _ -> refined_target
315 C.Prod(name,new_src,new_target),
316 sort_of_refined_prod,subst,metasenv,ugraph3)
317 | C.Lambda (n,s,t) ->
318 let s',sort1,subst',metasenv',ugraph1 =
319 type_of_aux subst metasenv context s ugraph
321 (match CicReduction.whd ~subst:subst' context sort1 with
325 raise (RefineFailure (Reason (sprintf
326 "Not well-typed lambda-abstraction: the source %s should be a type;
327 instead it is a term of type %s" (CicPp.ppterm s)
328 (CicPp.ppterm sort1))))
330 let t',type2,subst'',metasenv'',ugraph2 =
331 type_of_aux subst' metasenv'
332 ((Some (n,(C.Decl s')))::context) t ugraph1
334 C.Lambda (n,s',t'),C.Prod (n,s',type2),
335 subst'',metasenv'',ugraph2
337 (* only to check if s is well-typed *)
338 let s',ty,subst',metasenv',ugraph1 =
339 type_of_aux subst metasenv context s ugraph
341 let t',inferredty,subst'',metasenv'',ugraph2 =
342 type_of_aux subst' metasenv'
343 ((Some (n,(C.Def (s',Some ty))))::context) t ugraph1
345 (* One-step LetIn reduction.
346 * Even faster than the previous solution.
347 * Moreover the inferred type is closer to the expected one.
349 C.LetIn (n,s',t'),CicSubstitution.subst s' inferredty,
350 subst'',metasenv'',ugraph2
351 | C.Appl (he::((_::_) as tl)) ->
352 let he',hetype,subst',metasenv',ugraph1 =
353 type_of_aux subst metasenv context he ugraph
355 let tlbody_and_type,subst'',metasenv'',ugraph2 =
357 (fun x (res,subst,metasenv,ugraph) ->
358 let x',ty,subst',metasenv',ugraph1 =
359 type_of_aux subst metasenv context x ugraph
361 (x', ty)::res,subst',metasenv',ugraph1
362 ) tl ([],subst',metasenv',ugraph1)
364 let tl',applty,subst''',metasenv''',ugraph3 =
365 eat_prods subst'' metasenv'' context
366 hetype tlbody_and_type ugraph2
368 C.Appl (he'::tl'), applty,subst''',metasenv''',ugraph3
369 | C.Appl _ -> raise (RefineFailure (Reason "Appl: no arguments"))
370 | C.Const (uri,exp_named_subst) ->
371 let exp_named_subst',subst',metasenv',ugraph1 =
372 check_exp_named_subst subst metasenv context
373 exp_named_subst ugraph in
374 let ty_uri,ugraph2 = type_of_constant uri ugraph1 in
376 CicSubstitution.subst_vars exp_named_subst' ty_uri
378 C.Const (uri,exp_named_subst'),cty,subst',metasenv',ugraph2
379 | C.MutInd (uri,i,exp_named_subst) ->
380 let exp_named_subst',subst',metasenv',ugraph1 =
381 check_exp_named_subst subst metasenv context
382 exp_named_subst ugraph
384 let ty_uri,ugraph2 = type_of_mutual_inductive_defs uri i ugraph1 in
386 CicSubstitution.subst_vars exp_named_subst' ty_uri in
387 C.MutInd (uri,i,exp_named_subst'),cty,subst',metasenv',ugraph2
388 | C.MutConstruct (uri,i,j,exp_named_subst) ->
389 let exp_named_subst',subst',metasenv',ugraph1 =
390 check_exp_named_subst subst metasenv context
391 exp_named_subst ugraph
394 type_of_mutual_inductive_constr uri i j ugraph1
397 CicSubstitution.subst_vars exp_named_subst' ty_uri
399 C.MutConstruct (uri,i,j,exp_named_subst'),cty,subst',
401 | C.MutCase (uri, i, outtype, term, pl) ->
402 (* first, get the inductive type (and noparams)
403 * in the environment *)
404 let (_,b,arity,constructors), expl_params, no_left_params,ugraph =
405 let _ = CicTypeChecker.typecheck uri in
406 let obj,u = CicEnvironment.get_cooked_obj ugraph uri in
408 C.InductiveDefinition (l,expl_params,parsno,_) ->
409 List.nth l i , expl_params, parsno, u
413 (Reason ("Unkown mutual inductive definition " ^
414 U.string_of_uri uri)))
416 let rec count_prod t =
417 match CicReduction.whd ~subst context t with
418 C.Prod (_, _, t) -> 1 + (count_prod t)
421 let no_args = count_prod arity in
422 (* now, create a "generic" MutInd *)
423 let metasenv,left_args =
424 CicMkImplicit.n_fresh_metas metasenv subst context no_left_params
426 let metasenv,right_args =
427 let no_right_params = no_args - no_left_params in
428 if no_right_params < 0 then assert false
429 else CicMkImplicit.n_fresh_metas
430 metasenv subst context no_right_params
432 let metasenv,exp_named_subst =
433 CicMkImplicit.fresh_subst metasenv subst context expl_params in
436 C.MutInd (uri,i,exp_named_subst)
439 (C.MutInd (uri,i,exp_named_subst)::(left_args @ right_args))
441 (* check consistency with the actual type of term *)
442 let term',actual_type,subst,metasenv,ugraph1 =
443 type_of_aux subst metasenv context term ugraph in
444 let expected_type',_, subst, metasenv,ugraph2 =
445 type_of_aux subst metasenv context expected_type ugraph1
447 let actual_type = CicReduction.whd ~subst context actual_type in
448 let subst,metasenv,ugraph3 =
449 fo_unif_subst subst context metasenv
450 expected_type' actual_type ugraph2
452 let rec instantiate_prod t =
456 match CicReduction.whd ~subst context t with
458 instantiate_prod (CicSubstitution.subst he t') tl
461 let arity_instantiated_with_left_args =
462 instantiate_prod arity left_args in
463 (* TODO: check if the sort elimination
464 * is allowed: [(I q1 ... qr)|B] *)
465 let (pl',_,outtypeinstances,subst,metasenv,ugraph4) =
467 (fun (pl,j,outtypeinstances,subst,metasenv,ugraph) p ->
469 if left_args = [] then
470 (C.MutConstruct (uri,i,j,exp_named_subst))
473 (C.MutConstruct (uri,i,j,exp_named_subst)::left_args))
475 let p',actual_type,subst,metasenv,ugraph1 =
476 type_of_aux subst metasenv context p ugraph
478 let constructor',expected_type, subst, metasenv,ugraph2 =
479 type_of_aux subst metasenv context constructor ugraph1
481 let outtypeinstance,subst,metasenv,ugraph3 =
482 check_branch 0 context metasenv subst no_left_params
483 actual_type constructor' expected_type ugraph2
486 outtypeinstance::outtypeinstances,subst,metasenv,ugraph3))
487 ([],1,[],subst,metasenv,ugraph3) pl
490 (* we are left to check that the outype matches his instances.
491 The easy case is when the outype is specified, that amount
492 to a trivial check. Otherwise, we should guess a type from
498 (let candidate,ugraph5,metasenv,subst =
499 let exp_name_subst, metasenv =
501 CicEnvironment.get_cooked_obj CicUniv.empty_ugraph uri
503 let uris = CicUtil.params_of_obj o in
505 fun uri (acc,metasenv) ->
506 let metasenv',new_meta =
507 CicMkImplicit.mk_implicit metasenv subst context
510 CicMkImplicit.identity_relocation_list_for_metavariable
513 (uri, Cic.Meta(new_meta,irl))::acc, metasenv'
517 match left_args,right_args with
518 [],[] -> Cic.MutInd(uri, i, exp_name_subst)
520 let rec mk_right_args =
523 | n -> (Cic.Rel n)::(mk_right_args (n - 1))
525 let right_args_no = List.length right_args in
526 let lifted_left_args =
527 List.map (CicSubstitution.lift right_args_no) left_args
529 Cic.Appl (Cic.MutInd(uri,i,exp_name_subst)::
530 (lifted_left_args @ mk_right_args right_args_no))
533 FreshNamesGenerator.mk_fresh_name ~subst metasenv
534 context Cic.Anonymous ~typ:ty
536 match outtypeinstances with
538 let extended_context =
539 let rec add_right_args =
541 Cic.Prod (name,ty,t) ->
542 Some (name,Cic.Decl ty)::(add_right_args t)
545 (Some (fresh_name,Cic.Decl ty))::
547 (add_right_args arity_instantiated_with_left_args))@
550 let metasenv,new_meta =
551 CicMkImplicit.mk_implicit metasenv subst extended_context
554 CicMkImplicit.identity_relocation_list_for_metavariable
557 let rec add_lambdas b =
559 Cic.Prod (name,ty,t) ->
560 Cic.Lambda (name,ty,(add_lambdas b t))
561 | _ -> Cic.Lambda (fresh_name, ty, b)
564 add_lambdas (Cic.Meta (new_meta,irl))
565 arity_instantiated_with_left_args
567 (Some candidate),ugraph4,metasenv,subst
568 | (constructor_args_no,_,instance,_)::tl ->
570 let instance',subst,metasenv =
571 CicMetaSubst.delift_rels subst metasenv
572 constructor_args_no instance
574 let candidate,ugraph,metasenv,subst =
576 fun (candidate_oty,ugraph,metasenv,subst)
577 (constructor_args_no,_,instance,_) ->
578 match candidate_oty with
579 | None -> None,ugraph,metasenv,subst
582 let instance',subst,metasenv =
583 CicMetaSubst.delift_rels subst metasenv
584 constructor_args_no instance
586 let subst,metasenv,ugraph =
587 fo_unif_subst subst context metasenv
590 candidate_oty,ugraph,metasenv,subst
592 CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable
593 | CicUnification.UnificationFailure _
594 | CicUnification.Uncertain _ ->
595 None,ugraph,metasenv,subst
596 ) (Some instance',ugraph4,metasenv,subst) tl
599 | None -> None, ugraph,metasenv,subst
601 let rec add_lambdas n b =
603 Cic.Prod (name,ty,t) ->
604 Cic.Lambda (name,ty,(add_lambdas (n + 1) b t))
606 Cic.Lambda (fresh_name, ty,
607 CicSubstitution.lift (n + 1) t)
610 (add_lambdas 0 t arity_instantiated_with_left_args),
611 ugraph,metasenv,subst
612 with CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
613 None,ugraph4,metasenv,subst
616 | None -> raise (Uncertain "can't solve an higher order unification problem")
618 let subst,metasenv,ugraph =
619 fo_unif_subst subst context metasenv
620 candidate outtype ugraph5
622 C.MutCase (uri, i, outtype, term', pl'),
623 CicReduction.head_beta_reduce
624 (CicMetaSubst.apply_subst subst
625 (Cic.Appl (outtype::right_args@[term']))),
626 subst,metasenv,ugraph)
627 | _ -> (* easy case *)
628 let _,_, subst, metasenv,ugraph5 =
629 type_of_aux subst metasenv context
630 (C.Appl ((outtype :: right_args) @ [term'])) ugraph4
632 let (subst,metasenv,ugraph6) =
634 (fun (subst,metasenv,ugraph)
635 (constructor_args_no,context,instance,args) ->
639 CicSubstitution.lift constructor_args_no outtype
641 C.Appl (outtype'::args)
643 CicReduction.whd ~subst context appl
645 fo_unif_subst subst context metasenv
646 instance instance' ugraph)
647 (subst,metasenv,ugraph5) outtypeinstances
649 C.MutCase (uri, i, outtype, term', pl'),
650 CicReduction.head_beta_reduce
651 (CicMetaSubst.apply_subst subst
652 (C.Appl(outtype::right_args@[term]))),
653 subst,metasenv,ugraph6)
655 let fl_ty',subst,metasenv,types,ugraph1 =
657 (fun (fl,subst,metasenv,types,ugraph) (n,_,ty,_) ->
658 let ty',_,subst',metasenv',ugraph1 =
659 type_of_aux subst metasenv context ty ugraph
661 fl @ [ty'],subst',metasenv',
662 Some (C.Name n,(C.Decl ty')) :: types, ugraph
663 ) ([],subst,metasenv,[],ugraph) fl
665 let len = List.length types in
666 let context' = types@context in
667 let fl_bo',subst,metasenv,ugraph2 =
669 (fun (fl,subst,metasenv,ugraph) (name,x,ty,bo) ->
670 let bo',ty_of_bo,subst,metasenv,ugraph1 =
671 type_of_aux subst metasenv context' bo ugraph
673 let subst',metasenv',ugraph' =
674 fo_unif_subst subst context' metasenv
675 ty_of_bo (CicSubstitution.lift len ty) ugraph1
677 fl @ [bo'] , subst',metasenv',ugraph'
678 ) ([],subst,metasenv,ugraph1) fl
680 let (_,_,ty,_) = List.nth fl i in
681 (* now we have the new ty in fl_ty', the new bo in fl_bo',
682 * and we want the new fl with bo' and ty' injected in the right
685 let rec map3 f l1 l2 l3 =
688 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
691 let fl'' = map3 (fun ty' bo' (name,x,ty,bo) -> (name,x,ty',bo') )
694 C.Fix (i,fl''),ty,subst,metasenv,ugraph2
696 let fl_ty',subst,metasenv,types,ugraph1 =
698 (fun (fl,subst,metasenv,types,ugraph) (n,ty,_) ->
699 let ty',_,subst',metasenv',ugraph1 =
700 type_of_aux subst metasenv context ty ugraph
702 fl @ [ty'],subst',metasenv',
703 Some (C.Name n,(C.Decl ty')) :: types, ugraph1
704 ) ([],subst,metasenv,[],ugraph) fl
706 let len = List.length types in
707 let context' = types@context in
708 let fl_bo',subst,metasenv,ugraph2 =
710 (fun (fl,subst,metasenv,ugraph) (name,ty,bo) ->
711 let bo',ty_of_bo,subst,metasenv,ugraph1 =
712 type_of_aux subst metasenv context' bo ugraph
714 let subst',metasenv',ugraph' =
715 fo_unif_subst subst context' metasenv
716 ty_of_bo (CicSubstitution.lift len ty) ugraph1
718 fl @ [bo'],subst',metasenv',ugraph'
719 ) ([],subst,metasenv,ugraph1) fl
721 let (_,ty,_) = List.nth fl i in
722 (* now we have the new ty in fl_ty', the new bo in fl_bo',
723 * and we want the new fl with bo' and ty' injected in the right
726 let rec map3 f l1 l2 l3 =
729 | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
732 let fl'' = map3 (fun ty' bo' (name,ty,bo) -> (name,ty',bo') )
735 C.CoFix (i,fl''),ty,subst,metasenv,ugraph2
737 (* check_metasenv_consistency checks that the "canonical" context of a
738 metavariable is consitent - up to relocation via the relocation list l -
739 with the actual context *)
740 and check_metasenv_consistency
741 metano subst metasenv context canonical_context l ugraph
743 let module C = Cic in
744 let module R = CicReduction in
745 let module S = CicSubstitution in
746 let lifted_canonical_context =
750 | (Some (n,C.Decl t))::tl ->
751 (Some (n,C.Decl (S.subst_meta l (S.lift i t))))::(aux (i+1) tl)
752 | (Some (n,C.Def (t,None)))::tl ->
753 (Some (n,C.Def ((S.subst_meta l (S.lift i t)),None)))::(aux (i+1) tl)
754 | None::tl -> None::(aux (i+1) tl)
755 | (Some (n,C.Def (t,Some ty)))::tl ->
757 C.Def ((S.subst_meta l (S.lift i t)),
758 Some (S.subst_meta l (S.lift i ty))))) :: (aux (i+1) tl)
760 aux 1 canonical_context
764 (fun (l,subst,metasenv,ugraph) t ct ->
767 l @ [None],subst,metasenv,ugraph
768 | Some t,Some (_,C.Def (ct,_)) ->
769 let subst',metasenv',ugraph' =
771 fo_unif_subst subst context metasenv t ct ugraph
772 with e -> raise (RefineFailure (Reason (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 -> msg | _ -> (Printexc.to_string e))))))
774 l @ [Some t],subst',metasenv',ugraph'
775 | Some t,Some (_,C.Decl ct) ->
776 let t',inferredty,subst',metasenv',ugraph1 =
777 type_of_aux subst metasenv context t ugraph
779 let subst'',metasenv'',ugraph2 =
782 subst' context metasenv' inferredty ct ugraph1
783 with e -> raise (RefineFailure (Reason (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 -> msg | _ -> (Printexc.to_string e))))))
785 l @ [Some t'], subst'',metasenv'',ugraph2
787 raise (RefineFailure (Reason (sprintf
788 "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"
789 (CicMetaSubst.ppterm subst (Cic.Meta (metano, l)))
790 (CicMetaSubst.ppcontext subst canonical_context))))
791 ) ([],subst,metasenv,ugraph) l lifted_canonical_context
793 Invalid_argument _ ->
797 "Not well typed metavariable instance %s: the length of the local context does not match the length of the canonical context %s"
798 (CicMetaSubst.ppterm subst (Cic.Meta (metano, l)))
799 (CicMetaSubst.ppcontext subst canonical_context))))
801 and check_exp_named_subst metasubst metasenv context tl ugraph =
802 let rec check_exp_named_subst_aux metasubst metasenv substs tl ugraph =
804 [] -> [],metasubst,metasenv,ugraph
805 | ((uri,t) as subst)::tl ->
806 let ty_uri,ugraph1 = type_of_variable uri ugraph in
808 CicSubstitution.subst_vars substs ty_uri in
809 (* CSC: why was this code here? it is wrong
810 (match CicEnvironment.get_cooked_obj ~trust:false uri with
811 Cic.Variable (_,Some bo,_,_) ->
813 (RefineFailure (Reason
814 "A variable with a body can not be explicit substituted"))
815 | Cic.Variable (_,None,_,_) -> ()
818 (RefineFailure (Reason
819 ("Unkown variable definition " ^ UriManager.string_of_uri uri)))
822 let t',typeoft,metasubst',metasenv',ugraph2 =
823 type_of_aux metasubst metasenv context t ugraph1
825 let metasubst'',metasenv'',ugraph3 =
828 metasubst' context metasenv' typeoft typeofvar ugraph2
830 raise (RefineFailure (Reason
831 ("Wrong Explicit Named Substitution: " ^
832 CicMetaSubst.ppterm metasubst' typeoft ^
833 " not unifiable with " ^
834 CicMetaSubst.ppterm metasubst' typeofvar)))
836 (* FIXME: no mere tail recursive! *)
837 let exp_name_subst, metasubst''', metasenv''', ugraph4 =
838 check_exp_named_subst_aux
839 metasubst'' metasenv'' (substs@[subst]) tl ugraph3
841 ((uri,t')::exp_name_subst), metasubst''', metasenv''', ugraph4
843 check_exp_named_subst_aux metasubst metasenv [] tl ugraph
846 and sort_of_prod subst metasenv context (name,s) (t1, t2) ugraph =
847 let module C = Cic in
848 let context_for_t2 = (Some (name,C.Decl s))::context in
849 let t1'' = CicReduction.whd ~subst context t1 in
850 let t2'' = CicReduction.whd ~subst context_for_t2 t2 in
851 match (t1'', t2'') with
852 (C.Sort s1, C.Sort s2)
853 when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) ->
854 (* different than Coq manual!!! *)
855 C.Sort s2,subst,metasenv,ugraph
856 | (C.Sort (C.Type t1), C.Sort (C.Type t2)) ->
857 let t' = CicUniv.fresh() in
858 let ugraph1 = CicUniv.add_ge t' t1 ugraph in
859 let ugraph2 = CicUniv.add_ge t' t2 ugraph1 in
860 C.Sort (C.Type t'),subst,metasenv,ugraph2
861 | (C.Sort _,C.Sort (C.Type t1)) ->
862 C.Sort (C.Type t1),subst,metasenv,ugraph
863 | (C.Meta _, C.Sort _) -> t2'',subst,metasenv,ugraph
864 | (C.Sort _,C.Meta _) | (C.Meta _,C.Meta _) ->
865 (* TODO how can we force the meta to become a sort? If we don't we
866 * brake the invariant that refine produce only well typed terms *)
867 (* TODO if we check the non meta term and if it is a sort then we
868 * are likely to know the exact value of the result e.g. if the rhs
869 * is a Sort (Prop | Set | CProp) then the result is the rhs *)
871 CicMkImplicit.mk_implicit_sort metasenv subst in
872 let (subst, metasenv,ugraph1) =
873 fo_unif_subst subst context_for_t2 metasenv
874 (C.Meta (idx,[])) t2'' ugraph
876 t2'',subst,metasenv,ugraph1
882 ("Two sorts were expected, found %s " ^^
883 "(that reduces to %s) and %s (that reduces to %s)")
884 (CicPp.ppterm t1) (CicPp.ppterm t1'') (CicPp.ppterm t2)
885 (CicPp.ppterm t2''))))
887 and eat_prods subst metasenv context hetype tlbody_and_type ugraph =
888 let rec mk_prod metasenv context =
891 let (metasenv, idx) =
892 CicMkImplicit.mk_implicit_type metasenv subst context
895 CicMkImplicit.identity_relocation_list_for_metavariable context
897 metasenv,Cic.Meta (idx, irl)
899 let (metasenv, idx) =
900 CicMkImplicit.mk_implicit_type metasenv subst context
903 CicMkImplicit.identity_relocation_list_for_metavariable context
905 let meta = Cic.Meta (idx,irl) in
907 (* The name must be fresh for context. *)
908 (* Nevertheless, argty is well-typed only in context. *)
909 (* Thus I generate a name (name_hint) in context and *)
910 (* then I generate a name --- using the hint name_hint *)
911 (* --- that is fresh in (context'@context). *)
913 (* Cic.Name "pippo" *)
914 FreshNamesGenerator.mk_fresh_name ~subst metasenv
915 (* (CicMetaSubst.apply_subst_metasenv subst metasenv) *)
916 (CicMetaSubst.apply_subst_context subst context)
918 ~typ:(CicMetaSubst.apply_subst subst argty)
920 (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
921 FreshNamesGenerator.mk_fresh_name ~subst
922 [] context name_hint ~typ:(Cic.Sort Cic.Prop)
924 let metasenv,target =
925 mk_prod metasenv ((Some (name, Cic.Decl meta))::context) tl
927 metasenv,Cic.Prod (name,meta,target)
929 let metasenv,hetype' = mk_prod metasenv context tlbody_and_type in
930 let (subst, metasenv,ugraph1) =
932 fo_unif_subst subst context metasenv hetype hetype' ugraph
934 debug_print (lazy (Printf.sprintf "hetype=%s\nhetype'=%s\nmetasenv=%s\nsubst=%s"
935 (CicPp.ppterm hetype)
936 (CicPp.ppterm hetype')
937 (CicMetaSubst.ppmetasenv [] metasenv)
938 (CicMetaSubst.ppsubst subst)));
942 let rec eat_prods metasenv subst context hetype ugraph =
944 | [] -> [],metasenv,subst,hetype,ugraph
945 | (hete, hety)::tl ->
948 let arg,subst,metasenv,ugraph1 =
950 let subst,metasenv,ugraph1 =
951 fo_unif_subst subst context metasenv hety s ugraph
953 hete,subst,metasenv,ugraph1
955 (* we search a coercion from hety to s *)
957 let carr t subst context =
958 CicMetaSubst.apply_subst subst t
960 let c_hety = carr hety subst context in
961 let c_s = carr s subst context in
962 CoercGraph.look_for_coercion c_hety c_s
965 | CoercGraph.NoCoercion
966 | CoercGraph.NotHandled _ -> raise exn
967 | CoercGraph.NotMetaClosed ->
968 raise (Uncertain "Coercions on meta")
969 | CoercGraph.SomeCoercion c ->
970 (Cic.Appl [ c ; hete ]), subst, metasenv, ugraph
972 let coerced_args,metasenv',subst',t',ugraph2 =
973 eat_prods metasenv subst context
974 (* (CicMetaSubst.subst subst hete t) tl *)
975 (CicSubstitution.subst hete t) ugraph1 tl
977 arg::coerced_args,metasenv',subst',t',ugraph2
981 let coerced_args,metasenv,subst,t,ugraph2 =
982 eat_prods metasenv subst context hetype' ugraph1 tlbody_and_type
984 coerced_args,t,subst,metasenv,ugraph2
987 (* eat prods ends here! *)
989 let t',ty,subst',metasenv',ugraph1 =
990 type_of_aux [] metasenv context t ugraph
992 let substituted_t = CicMetaSubst.apply_subst subst' t' in
993 let substituted_ty = CicMetaSubst.apply_subst subst' ty in
994 (* Andrea: ho rimesso qui l'applicazione della subst al
995 metasenv dopo che ho droppato l'invariante che il metsaenv
996 e' sempre istanziato *)
997 let substituted_metasenv =
998 CicMetaSubst.apply_subst_metasenv subst' metasenv' in
1000 (* substituted_t,substituted_ty,substituted_metasenv *)
1001 (* ANDREA: spostare tutta questa robaccia da un altra parte *)
1003 FreshNamesGenerator.clean_dummy_dependent_types substituted_t in
1005 FreshNamesGenerator.clean_dummy_dependent_types substituted_ty in
1006 let cleaned_metasenv =
1008 (function (n,context,ty) ->
1009 let ty' = FreshNamesGenerator.clean_dummy_dependent_types ty in
1014 | Some (n, Cic.Decl t) ->
1016 Cic.Decl (FreshNamesGenerator.clean_dummy_dependent_types t))
1017 | Some (n, Cic.Def (bo,ty)) ->
1018 let bo' = FreshNamesGenerator.clean_dummy_dependent_types bo in
1023 Some (FreshNamesGenerator.clean_dummy_dependent_types ty)
1025 Some (n, Cic.Def (bo',ty'))
1029 ) substituted_metasenv
1031 (cleaned_t,cleaned_ty,cleaned_metasenv,ugraph1)
1034 let type_of_aux' metasenv context term ugraph =
1036 type_of_aux' metasenv context term ugraph
1038 CicUniv.UniverseInconsistency msg -> raise (RefineFailure (Reason msg))
1040 (*CSC: this is a very very rough approximation; to be finished *)
1041 let are_all_occurrences_positive uri =
1043 (*CSC: here we should do a whd; but can we do that? *)
1045 Cic.Appl (Cic.MutInd (uri',_,_)::_) when uri = uri' -> ()
1046 | Cic.MutInd (uri',_,_) when uri = uri' -> ()
1047 | Cic.Prod (_,_,t) -> aux t
1048 | _ -> raise (RefineFailure (Reason "not well formed constructor type"))
1052 let typecheck metasenv uri obj =
1053 let ugraph = CicUniv.empty_ugraph in
1055 Cic.Constant (name,Some bo,ty,args,attrs) ->
1056 let bo',boty,metasenv,ugraph = type_of_aux' metasenv [] bo ugraph in
1057 let ty',_,metasenv,ugraph = type_of_aux' metasenv [] ty ugraph in
1058 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1059 let bo' = CicMetaSubst.apply_subst subst bo' in
1060 let ty' = CicMetaSubst.apply_subst subst ty' in
1061 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1062 Cic.Constant (name,Some bo',ty',args,attrs),metasenv,ugraph
1063 | Cic.Constant (name,None,ty,args,attrs) ->
1064 let ty',_,metasenv,ugraph = type_of_aux' metasenv [] ty ugraph in
1065 Cic.Constant (name,None,ty',args,attrs),metasenv,ugraph
1066 | Cic.CurrentProof (name,metasenv',bo,ty,args,attrs) ->
1067 assert (metasenv' = metasenv);
1068 (* Here we do not check the metasenv for correctness *)
1069 let bo',boty,metasenv,ugraph = type_of_aux' metasenv [] bo ugraph in
1070 let ty',sort,metasenv,ugraph = type_of_aux' metasenv [] ty ugraph in
1074 (* instead of raising Uncertain, let's hope that the meta will become
1077 | _ -> raise (RefineFailure (Reason "The term provided is not a type"))
1079 let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1080 let bo' = CicMetaSubst.apply_subst subst bo' in
1081 let ty' = CicMetaSubst.apply_subst subst ty' in
1082 let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1083 Cic.CurrentProof (name,metasenv,bo',ty',args,attrs),metasenv,ugraph
1084 | Cic.Variable _ -> assert false (* not implemented *)
1085 | Cic.InductiveDefinition (tys,args,paramsno,attrs) ->
1086 (*CSC: this code is greately simplified and many many checks are missing *)
1087 (*CSC: e.g. the constructors are not required to build their own types, *)
1088 (*CSC: the arities are not required to have as type a sort, etc. *)
1089 let uri = match uri with Some uri -> uri | None -> assert false in
1090 let typesno = List.length tys in
1091 (* first phase: we fix only the types *)
1092 let metasenv,ugraph,tys =
1094 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1095 let ty',_,metasenv,ugraph = type_of_aux' metasenv [] ty ugraph in
1096 metasenv,ugraph,(name,b,ty',cl)::res
1097 ) tys (metasenv,ugraph,[]) in
1099 List.rev_map (fun (name,_,ty,_)-> Some (Cic.Name name,Cic.Decl ty)) tys in
1100 (* second phase: we fix only the constructors *)
1101 let metasenv,ugraph,tys =
1103 (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1104 let metasenv,ugraph,cl' =
1106 (fun (name,ty) (metasenv,ugraph,res) ->
1107 let ty = CicTypeChecker.debrujin_constructor uri typesno ty in
1108 let ty',_,metasenv,ugraph =
1109 type_of_aux' metasenv con_context ty ugraph in
1113 (fun (name,_,_,_) (i,t) ->
1114 (* here the explicit_named_substituion is assumed to be *)
1116 let t' = Cic.MutInd (uri,i,[]) in
1117 let t = CicSubstitution.subst t' t in
1119 ) tys (typesno - 1,t)) in
1120 let ty' = undebrujin ty' in
1121 metasenv,ugraph,(name,ty')::res
1122 ) cl (metasenv,ugraph,[])
1124 metasenv,ugraph,(name,b,ty,cl')::res
1125 ) tys (metasenv,ugraph,[]) in
1126 (* third phase: we check the positivity condition *)
1129 List.iter (fun (_,ty) -> are_all_occurrences_positive uri ty) cl
1131 Cic.InductiveDefinition (tys,args,paramsno,attrs),metasenv,ugraph
1134 let type_of_aux' metasenv context term =
1137 type_of_aux' metasenv context term in
1139 ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty));
1141 ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []));
1144 | RefineFailure msg as e ->
1145 debug_print (lazy ("@@@ REFINE FAILED: " ^ msg));
1147 | Uncertain msg as e ->
1148 debug_print (lazy ("@@@ REFINE UNCERTAIN: " ^ msg));
1152 let profiler2 = HExtlib.profile "CicRefine"
1154 let type_of_aux' metasenv context term ugraph =
1155 profiler2.HExtlib.profile (type_of_aux' metasenv context term) ugraph
1157 let typecheck metasenv uri obj =
1158 profiler2.HExtlib.profile (typecheck metasenv uri) obj