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/.
26 exception UnificationFailed;;
28 exception OccurCheck;;
29 exception RelToHiddenHypothesis;;
34 (* the delift function takes in input an ordered list of integers [n1,...,nk]
35 and a term t, and relocates rel(nk) to k. Typically, the list of integers
36 is a parameter of a metavariable occurrence. *)
38 exception NotInTheList;;
43 [] -> raise NotInTheList
44 | (Some (Cic.Rel m))::_ when m=n -> k
45 | _::tl -> aux (k+1) tl in
49 let restrict to_be_restricted =
53 | _::tl when List.mem (n,i) to_be_restricted ->
54 None::(erase (i+1) n tl)
55 | he::tl -> he::(erase (i+1) n tl) in
59 | (n,context,t)::tl -> (n,erase 1 n context,t)::(aux tl) in
64 let delift context metasenv l t =
65 let module S = CicSubstitution in
66 let to_be_restricted = ref [] in
72 C.Rel m (*CSC: che succede se c'e' un Def? Dovrebbe averlo gia' *)
73 (*CSC: deliftato la regola per il LetIn *)
75 (match List.nth context (m-k-1) with
76 Some (_,C.Def t) -> deliftaux k (S.lift m t)
77 | Some (_,C.Decl t) ->
78 (* It may augment to_be_restricted *)
79 ignore (deliftaux k (S.lift m t)) ;
80 C.Rel ((position (m-k) l) + k)
81 | None -> raise RelToHiddenHypothesis)
83 | C.Meta (i, l1) as t ->
87 | None::tl -> None::(deliftl (j+1) tl)
89 let l1' = (deliftl (j+1) tl) in
91 Some (deliftaux k t)::l1'
95 to_be_restricted := (i,j)::!to_be_restricted ; None::l1'
97 let l' = deliftl 1 l1 in
100 | C.Implicit as t -> t
101 | C.Cast (te,ty) -> C.Cast (deliftaux k te, deliftaux k ty)
102 | C.Prod (n,s,t) -> C.Prod (n, deliftaux k s, deliftaux (k+1) t)
103 | C.Lambda (n,s,t) -> C.Lambda (n, deliftaux k s, deliftaux (k+1) t)
104 | C.LetIn (n,s,t) -> C.LetIn (n, deliftaux k s, deliftaux (k+1) t)
105 | C.Appl l -> C.Appl (List.map (deliftaux k) l)
106 | C.Const _ as t -> t
108 | C.MutInd _ as t -> t
109 | C.MutConstruct _ as t -> t
110 | C.MutCase (sp,cookingsno,i,outty,t,pl) ->
111 C.MutCase (sp, cookingsno, i, deliftaux k outty, deliftaux k t,
112 List.map (deliftaux k) pl)
114 let len = List.length fl in
117 (fun (name, i, ty, bo) ->
118 (name, i, deliftaux k ty, deliftaux (k+len) bo))
123 let len = List.length fl in
126 (fun (name, ty, bo) -> (name, deliftaux k ty, deliftaux (k+len) bo))
129 C.CoFix (i, liftedfl)
131 let res = deliftaux 0 t in
132 res, restrict !to_be_restricted metasenv
135 (**** END OF DELIFT ****)
137 type substitution = (int * Cic.term) list
139 (* NUOVA UNIFICAZIONE *)
140 (* A substitution is a (int * Cic.term) list that associates a
141 metavariable i with its body.
142 A metaenv is a (int * Cic.term) list that associate a metavariable
144 fo_unif_new takes a metasenv, a context, two terms t1 and t2 and gives back
145 a new substitution which is _NOT_ unwinded. It must be unwinded before
148 let fo_unif_new metasenv context t1 t2 =
149 let module C = Cic in
150 let module R = CicReduction in
151 let module S = CicSubstitution in
152 let rec fo_unif_aux subst context metasenv t1 t2 =
154 (C.Meta (n,ln), C.Meta (m,lm)) when n=m ->
162 | Some t1', Some t2' ->
163 (* First possibility: restriction *)
164 (* Second possibility: unification *)
165 (* Third possibility: convertibility *)
166 R.are_convertible context t1' t2'
169 if ok then subst,metasenv else
170 raise UnificationFailed
171 | (C.Meta (n,l), C.Meta (m,_)) when n>m ->
172 fo_unif_aux subst context metasenv t2 t1
174 | (t, C.Meta (n,l)) ->
175 let subst',metasenv' =
177 let oldt = (List.assoc n subst) in
178 let lifted_oldt = S.lift_meta l oldt in
179 fo_unif_aux subst context metasenv lifted_oldt t
181 prerr_endline ("DELIFT2(" ^ CicPp.ppterm t ^ ")") ; flush stderr ;
182 List.iter (function (Some t) -> prerr_endline ("l: " ^ CicPp.ppterm t) | None -> prerr_endline " _ ") l ; flush stderr ;
183 prerr_endline "<DELIFT2" ; flush stderr ;
184 let t',metasenv' = delift context metasenv l t in
185 (n, t')::subst, metasenv'
187 let (_,_,meta_type) =
188 List.find (function (m,_,_) -> m=n) metasenv' in
189 let tyt = CicTypeChecker.type_of_aux' metasenv' context t in
190 fo_unif_aux subst' context metasenv' (S.lift_meta l meta_type) tyt
199 if R.are_convertible context t1 t2 then subst, metasenv
200 else raise UnificationFailed
201 | (C.Cast (te,ty), t2) -> fo_unif_aux subst context metasenv te t2
202 | (t1, C.Cast (te,ty)) -> fo_unif_aux subst context metasenv t1 te
203 | (C.Prod (n1,s1,t1), C.Prod (_,s2,t2)) ->
204 let subst',metasenv' = fo_unif_aux subst context metasenv s1 s2 in
205 fo_unif_aux subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2
206 | (C.Lambda (n1,s1,t1), C.Lambda (_,s2,t2)) ->
207 let subst',metasenv' = fo_unif_aux subst context metasenv s1 s2 in
208 fo_unif_aux subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2
209 | (C.LetIn (_,s1,t1), t2)
210 | (t2, C.LetIn (_,s1,t1)) ->
211 fo_unif_aux subst context metasenv t2 (S.subst s1 t1)
212 | (C.Appl l1, C.Appl l2) ->
213 let lr1 = List.rev l1 in
214 let lr2 = List.rev l2 in
215 let rec fo_unif_l subst metasenv = function
217 | _,[] -> assert false
219 fo_unif_aux subst context metasenv h1 h2
222 fo_unif_aux subst context metasenv h (C.Appl (List.rev l))
223 | ((h1::l1),(h2::l2)) ->
224 let subst', metasenv' =
225 fo_unif_aux subst context metasenv h1 h2
227 fo_unif_l subst' metasenv' (l1,l2)
229 fo_unif_l subst metasenv (lr1, lr2)
236 | (C.MutConstruct _, _)
237 | (_, C.MutConstruct _) ->
238 if R.are_convertible context t1 t2 then subst, metasenv
239 else raise UnificationFailed
240 | (C.MutCase (_,_,_,outt1,t1,pl1), C.MutCase (_,_,_,outt2,t2,pl2))->
241 let subst', metasenv' =
242 fo_unif_aux subst context metasenv outt1 outt2 in
243 let subst'',metasenv'' =
244 fo_unif_aux subst' context metasenv' t1 t2 in
246 (function (subst,metasenv) ->
247 fo_unif_aux subst context metasenv
248 ) (subst'',metasenv'') pl1 pl2
253 if R.are_convertible context t1 t2 then subst, metasenv
254 else raise UnificationFailed
255 | (_,_) -> raise UnificationFailed
256 in fo_unif_aux [] context metasenv t1 t2;;
258 (*CSC: ???????????????
259 (* m is the index of a metavariable to restrict, k is nesting depth
260 of the occurrence m, and l is its relocation list. canonical_context
261 is the context of the metavariable we are instantiating - containing
262 m - Only rel in the domain of canonical_context are accessible.
263 This function takes in input a metasenv and gives back a metasenv.
264 A rel(j) in the canonical context of m, is rel(List.nth l j) for the
265 instance of m under consideration, that is rel (List.nth l j) - k
266 in canonical_context. *)
268 let restrict canonical_context m k l =
272 | None::tl -> None::(erase (i+1) tl)
274 let i' = (List.nth l (i-1)) in
276 then he::(erase (i+1) tl) (* local variable *)
279 (try List.nth canonical_context (i'-k-1)
280 with Failure _ -> None) in
282 then None::(erase (i+1) tl)
283 else he::(erase (i+1) tl) in
287 | (n,context,t)::tl when n=m -> (n,erase 1 context,t)::tl
288 | hd::tl -> hd::(aux tl)
294 let check_accessibility metasenv i =
295 let module C = Cic in
296 let module S = CicSubstitution in
297 let (_,canonical_context,_) =
298 List.find (function (m,_,_) -> m=i) metasenv in
302 delift canonical_context metasenv ? t
308 let rec aux metasenv k =
315 match List.nth canonical_context (i-k-1) with
317 | Some (_,C.Def t) -> aux metasenv k (S.lift i t)
318 | None -> raise RelToHiddenHypothesis
320 Failure _ -> raise OpenTerm
322 | C.Var _ -> metasenv
323 | C.Meta (i,l) -> restrict canonical_context i k l metasenv
324 | C.Sort _ -> metasenv
325 | C.Implicit -> metasenv
327 let metasenv' = aux metasenv k te in
332 let metasenv' = aux metasenv k s in
333 aux metasenv' (k+1) t
336 (function metasenv -> aux metasenv k) metasenv l
340 | C.MutConstruct _ -> metasenv
341 | C.MutCase (_,_,_,outty,t,pl) ->
342 let metasenv' = aux metasenv k outty in
343 let metasenv'' = aux metasenv' k t in
345 (function metasenv -> aux metasenv k) metasenv'' pl
347 let len = List.length fl in
350 let (_,_,ty,bo) = f in
351 let metasenv' = aux metasenv k ty in
352 aux metasenv' (k+len) bo
355 let len = List.length fl in
359 let metasenv' = aux metasenv k ty in
360 aux metasenv' (k+len) bo
367 let unwind metasenv subst unwinded t =
368 let unwinded = ref unwinded in
369 let frozen = ref [] in
370 let rec um_aux metasenv =
371 let module C = Cic in
372 let module S = CicSubstitution in
374 C.Rel _ as t -> t,metasenv
375 | C.Var _ as t -> t,metasenv
378 S.lift_meta l (List.assoc i !unwinded), metasenv
380 if List.mem i !frozen then raise OccurCheck
382 let saved_frozen = !frozen in
383 frozen := i::!frozen ;
386 let t = List.assoc i subst in
387 let t',metasenv' = um_aux metasenv t in
389 let (_,canonical_context,_) =
390 List.find (function (m,_,_) -> m=i) metasenv
392 prerr_endline ("DELIFT(" ^ CicPp.ppterm t' ^ ")") ; flush stderr ;
393 List.iter (function (Some t) -> prerr_endline ("l: " ^ CicPp.ppterm t) | None -> prerr_endline " _ ") l ; flush stderr ;
394 prerr_endline "<DELIFT" ; flush stderr ;
395 delift canonical_context metasenv' l t'
397 unwinded := (i,t')::!unwinded ;
398 S.lift_meta l t', metasenv'
401 (* not constrained variable, i.e. free in subst*)
404 (fun t (tl,metasenv) ->
406 None -> None::tl,metasenv
408 let t',metasenv' = um_aux metasenv t in
409 (Some t')::tl, metasenv'
412 C.Meta (i,l'), metasenv'
414 frozen := saved_frozen ;
418 | C.Implicit as t -> t,metasenv
420 let te',metasenv' = um_aux metasenv te in
421 let ty',metasenv'' = um_aux metasenv' ty in
422 C.Cast (te',ty'),metasenv''
424 let s',metasenv' = um_aux metasenv s in
425 let t',metasenv'' = um_aux metasenv' t in
426 C.Prod (n, s', t'), metasenv''
427 | C.Lambda (n,s,t) ->
428 let s',metasenv' = um_aux metasenv s in
429 let t',metasenv'' = um_aux metasenv' t in
430 C.Lambda (n, s', t'), metasenv''
432 let s',metasenv' = um_aux metasenv s in
433 let t',metasenv'' = um_aux metasenv' t in
434 C.LetIn (n, s', t'), metasenv''
438 (fun t (tl,metasenv) ->
439 let t',metasenv' = um_aux metasenv t in
444 match um_aux metasenv' he with
445 (C.Appl l, metasenv'') -> C.Appl (l@tl'),metasenv''
446 | (he', metasenv'') -> C.Appl (he'::tl'),metasenv''
448 | C.Appl _ -> assert false
452 | C.MutConstruct _ as t -> t,metasenv
453 | C.MutCase (sp,cookingsno,i,outty,t,pl) ->
454 let outty',metasenv' = um_aux metasenv outty in
455 let t',metasenv'' = um_aux metasenv' t in
456 let pl',metasenv''' =
458 (fun p (pl,metasenv) ->
459 let p',metasenv' = um_aux metasenv p in
463 C.MutCase (sp, cookingsno, i, outty', t', pl'),metasenv'''
465 let len = List.length fl in
466 let liftedfl,metasenv' =
468 (fun (name, i, ty, bo) (fl,metasenv) ->
469 let ty',metasenv' = um_aux metasenv ty in
470 let bo',metasenv'' = um_aux metasenv' bo in
471 (name, i, ty', bo')::fl,metasenv''
474 C.Fix (i, liftedfl),metasenv'
476 let len = List.length fl in
477 let liftedfl,metasenv' =
479 (fun (name, ty, bo) (fl,metasenv) ->
480 let ty',metasenv' = um_aux metasenv ty in
481 let bo',metasenv'' = um_aux metasenv' bo in
482 (name, ty', bo')::fl,metasenv''
485 C.CoFix (i, liftedfl),metasenv'
487 let t',metasenv' = um_aux metasenv t in
488 t',metasenv',!unwinded
491 (* apply_subst_reducing subst (Some (mtr,reductions_no)) t *)
492 (* performs as (apply_subst subst t) until it finds an application of *)
493 (* (META [meta_to_reduce]) that, once unwinding is performed, creates *)
494 (* a new beta-redex; in this case up to [reductions_no] consecutive *)
495 (* beta-reductions are performed. *)
496 (* Hint: this function is usually called when [reductions_no] *)
497 (* eta-expansions have been performed and the head of the new *)
498 (* application has been unified with (META [meta_to_reduce]): *)
499 (* during the unwinding the eta-expansions are undone. *)
501 let apply_subst_reducing subst meta_to_reduce t =
502 let unwinded = ref subst in
504 let module C = Cic in
505 let module S = CicSubstitution in
509 | C.Meta (i,l) as t ->
511 S.lift_meta l (List.assoc i !unwinded)
515 | C.Implicit as t -> t
516 | C.Cast (te,ty) -> C.Cast (um_aux te, um_aux ty)
517 | C.Prod (n,s,t) -> C.Prod (n, um_aux s, um_aux t)
518 | C.Lambda (n,s,t) -> C.Lambda (n, um_aux s, um_aux t)
519 | C.LetIn (n,s,t) -> C.LetIn (n, um_aux s, um_aux t)
521 let tl' = List.map um_aux tl in
524 C.Appl l -> C.Appl (l@tl')
525 | _ as he' -> C.Appl (he'::tl')
528 match meta_to_reduce,he with
529 Some (mtr,reductions_no), C.Meta (m,_) when m = mtr ->
530 let rec beta_reduce =
532 (n,(C.Appl (C.Lambda (_,_,t)::he'::tl'))) when n > 0 ->
533 let he'' = CicSubstitution.subst he' t in
537 beta_reduce (n-1,C.Appl(he''::tl'))
540 beta_reduce (reductions_no,t')
543 | C.Appl _ -> assert false
544 | C.Const _ as t -> t
546 | C.MutInd _ as t -> t
547 | C.MutConstruct _ as t -> t
548 | C.MutCase (sp,cookingsno,i,outty,t,pl) ->
549 C.MutCase (sp, cookingsno, i, um_aux outty, um_aux t,
552 let len = List.length fl in
555 (fun (name, i, ty, bo) -> (name, i, um_aux ty, um_aux bo))
560 let len = List.length fl in
563 (fun (name, ty, bo) -> (name, um_aux ty, um_aux bo))
566 C.CoFix (i, liftedfl)
571 (* UNWIND THE MGU INSIDE THE MGU *)
572 let unwind_subst metasenv subst =
573 let identity_relocation_list_for_metavariable i =
574 let (_,canonical_context,_) =
575 List.find (function (m,_,_) -> m=i) metasenv
577 let canonical_context_length = List.length canonical_context in
580 n when n > canonical_context_length -> []
581 | n -> (Some (Cic.Rel n))::(aux (n+1))
586 (fun (unwinded,metasenv) (i,_) ->
587 let identity_relocation_list =
588 identity_relocation_list_for_metavariable i
590 let (_,metasenv',subst') =
591 unwind metasenv subst unwinded (Cic.Meta (i,identity_relocation_list))
594 ) ([],metasenv) subst
597 let apply_subst subst t =
598 (* metasenv will not be used nor modified. So, let's use a dummy empty one *)
600 let (t',_,_) = unwind metasenv [] subst t in
604 (* A substitution is a (int * Cic.term) list that associates a *)
605 (* metavariable i with its body. *)
606 (* metasenv is of type Cic.metasenv *)
607 (* fo_unif takes a metasenv, a context, two terms t1 and t2 and gives back *)
608 (* a new substitution which is already unwinded and ready to be applied and *)
609 (* a new metasenv in which some hypothesis in the contexts of the *)
610 (* metavariables may have been restricted. *)
611 let fo_unif metasenv context t1 t2 =
612 prerr_endline "INIZIO FASE 1" ; flush stderr ;
613 let subst_to_unwind,metasenv' = fo_unif_new metasenv context t1 t2 in
614 prerr_endline "FINE FASE 1" ; flush stderr ;
616 unwind_subst metasenv' subst_to_unwind
618 prerr_endline "FINE FASE 2" ; flush stderr ; res