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 CannotSubstInMeta;;
29 exception RelToHiddenHypothesis;;
30 exception ReferenceToVariable;;
31 exception ReferenceToConstant;;
32 exception ReferenceToCurrentProof;;
33 exception ReferenceToInductiveDefinition;;
38 fun m -> prerr_endline (Lazy.force m)
52 | C.Var (uri,exp_named_subst) ->
53 let exp_named_subst' =
54 List.map (function (uri,t) -> (uri,liftaux k t)) exp_named_subst
56 C.Var (uri,exp_named_subst')
62 | Some t -> Some (liftaux k t)
67 | C.Implicit _ as t -> t
68 | C.Cast (te,ty) -> C.Cast (liftaux k te, liftaux k ty)
69 | C.Prod (n,s,t) -> C.Prod (n, liftaux k s, liftaux (k+1) t)
70 | C.Lambda (n,s,t) -> C.Lambda (n, liftaux k s, liftaux (k+1) t)
71 | C.LetIn (n,s,ty,t) ->
72 C.LetIn (n, liftaux k s, liftaux k ty, liftaux (k+1) t)
73 | C.Appl l -> C.Appl (List.map (liftaux k) l)
74 | C.Const (uri,exp_named_subst) ->
75 let exp_named_subst' =
76 List.map (function (uri,t) -> (uri,liftaux k t)) exp_named_subst
78 C.Const (uri,exp_named_subst')
79 | C.MutInd (uri,tyno,exp_named_subst) ->
80 let exp_named_subst' =
81 List.map (function (uri,t) -> (uri,liftaux k t)) exp_named_subst
83 C.MutInd (uri,tyno,exp_named_subst')
84 | C.MutConstruct (uri,tyno,consno,exp_named_subst) ->
85 let exp_named_subst' =
86 List.map (function (uri,t) -> (uri,liftaux k t)) exp_named_subst
88 C.MutConstruct (uri,tyno,consno,exp_named_subst')
89 | C.MutCase (sp,i,outty,t,pl) ->
90 C.MutCase (sp, i, liftaux k outty, liftaux k t,
91 List.map (liftaux k) pl)
93 let len = List.length fl in
96 (fun (name, i, ty, bo) -> (name, i, liftaux k ty, liftaux (k+len) bo))
101 let len = List.length fl in
104 (fun (name, ty, bo) -> (name, liftaux k ty, liftaux (k+len) bo))
107 C.CoFix (i, liftedfl)
112 lift_map k (fun _ m -> m + n)
122 (* substitutes [t1] for [Rel 1] in [t2] *)
123 (* if avoid_beta_redexes is true (default: false) no new beta redexes *)
124 (* are generated. WARNING: the substitution can diverge when t2 is not *)
125 (* well typed and avoid_beta_redexes is true. *)
126 let rec subst ?(avoid_beta_redexes=false) arg =
128 let module C = Cic in
132 n when n = k -> lift (k - 1) arg
136 | C.Var (uri,exp_named_subst) ->
137 let exp_named_subst' =
138 List.map (function (uri,t) -> (uri,substaux k t)) exp_named_subst
140 C.Var (uri,exp_named_subst')
146 | Some t -> Some (substaux k t)
151 | C.Implicit _ as t -> t
152 | C.Cast (te,ty) -> C.Cast (substaux k te, substaux k ty)
153 | C.Prod (n,s,t) -> C.Prod (n, substaux k s, substaux (k + 1) t)
154 | C.Lambda (n,s,t) -> C.Lambda (n, substaux k s, substaux (k + 1) t)
155 | C.LetIn (n,s,ty,t) ->
156 C.LetIn (n, substaux k s, substaux k ty, substaux (k + 1) t)
158 (* Invariant: no Appl applied to another Appl *)
159 let tl' = List.map (substaux k) tl in
161 match substaux k he with
162 C.Appl l -> C.Appl (l@tl')
164 | C.Lambda (_,_,bo) when avoid_beta_redexes ->
167 | [he] -> subst ~avoid_beta_redexes he bo
168 | he::tl -> C.Appl (subst he bo::tl))
169 | _ as he' -> C.Appl (he'::tl')
171 | C.Appl _ -> assert false
172 | C.Const (uri,exp_named_subst) ->
173 let exp_named_subst' =
174 List.map (function (uri,t) -> (uri,substaux k t)) exp_named_subst
176 C.Const (uri,exp_named_subst')
177 | C.MutInd (uri,typeno,exp_named_subst) ->
178 let exp_named_subst' =
179 List.map (function (uri,t) -> (uri,substaux k t)) exp_named_subst
181 C.MutInd (uri,typeno,exp_named_subst')
182 | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
183 let exp_named_subst' =
184 List.map (function (uri,t) -> (uri,substaux k t)) exp_named_subst
186 C.MutConstruct (uri,typeno,consno,exp_named_subst')
187 | C.MutCase (sp,i,outt,t,pl) ->
188 C.MutCase (sp,i,substaux k outt, substaux k t,
189 List.map (substaux k) pl)
191 let len = List.length fl in
194 (fun (name,i,ty,bo) -> (name, i, substaux k ty, substaux (k+len) bo))
197 C.Fix (i, substitutedfl)
199 let len = List.length fl in
202 (fun (name,ty,bo) -> (name, substaux k ty, substaux (k+len) bo))
205 C.CoFix (i, substitutedfl)
210 (*CSC: i controlli di tipo debbono essere svolti da destra a *)
211 (*CSC: sinistra: i{B/A;b/a} ==> a{B/A;b/a} ==> a{b/a{B/A}} ==> b *)
212 (*CSC: la sostituzione ora e' implementata in maniera simultanea, ma *)
213 (*CSC: dovrebbe diventare da sinistra verso destra: *)
214 (*CSC: t{a=a/A;b/a} ==> \H:a=a.H{b/a} ==> \H:b=b.H *)
215 (*CSC: per la roba che proviene da Coq questo non serve! *)
216 let subst_vars exp_named_subst t =
218 debug_print (lazy ("@@@POSSIBLE BUG: SUBSTITUTION IS NOT SIMULTANEOUS")) ;
221 let module C = Cic in
224 | C.Var (uri,exp_named_subst') ->
228 (function (varuri,_) -> UriManager.eq uri varuri) exp_named_subst
234 let obj,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
236 C.Constant _ -> raise ReferenceToConstant
237 | C.Variable (_,_,_,params,_) -> params
238 | C.CurrentProof _ -> raise ReferenceToCurrentProof
239 | C.InductiveDefinition _ -> raise ReferenceToInductiveDefinition
242 let exp_named_subst'' =
243 substaux_in_exp_named_subst uri k exp_named_subst' params
245 C.Var (uri,exp_named_subst'')
252 | Some t -> Some (substaux k t)
257 | C.Implicit _ as t -> t
258 | C.Cast (te,ty) -> C.Cast (substaux k te, substaux k ty)
259 | C.Prod (n,s,t) -> C.Prod (n, substaux k s, substaux (k + 1) t)
260 | C.Lambda (n,s,t) -> C.Lambda (n, substaux k s, substaux (k + 1) t)
261 | C.LetIn (n,s,ty,t) ->
262 C.LetIn (n, substaux k s, substaux k ty, substaux (k + 1) t)
264 (* Invariant: no Appl applied to another Appl *)
265 let tl' = List.map (substaux k) tl in
267 match substaux k he with
268 C.Appl l -> C.Appl (l@tl')
269 | _ as he' -> C.Appl (he'::tl')
271 | C.Appl _ -> assert false
272 | C.Const (uri,exp_named_subst') ->
274 let obj,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
276 C.Constant (_,_,_,params,_) -> params
277 | C.Variable _ -> raise ReferenceToVariable
278 | C.CurrentProof (_,_,_,_,params,_) -> params
279 | C.InductiveDefinition _ -> raise ReferenceToInductiveDefinition
282 let exp_named_subst'' =
283 substaux_in_exp_named_subst uri k exp_named_subst' params
285 C.Const (uri,exp_named_subst'')
286 | C.MutInd (uri,typeno,exp_named_subst') ->
288 let obj,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
290 C.Constant _ -> raise ReferenceToConstant
291 | C.Variable _ -> raise ReferenceToVariable
292 | C.CurrentProof _ -> raise ReferenceToCurrentProof
293 | C.InductiveDefinition (_,params,_,_) -> params
296 let exp_named_subst'' =
297 substaux_in_exp_named_subst uri k exp_named_subst' params
299 C.MutInd (uri,typeno,exp_named_subst'')
300 | C.MutConstruct (uri,typeno,consno,exp_named_subst') ->
302 let obj,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
304 C.Constant _ -> raise ReferenceToConstant
305 | C.Variable _ -> raise ReferenceToVariable
306 | C.CurrentProof _ -> raise ReferenceToCurrentProof
307 | C.InductiveDefinition (_,params,_,_) -> params
310 let exp_named_subst'' =
311 substaux_in_exp_named_subst uri k exp_named_subst' params
313 if (List.map fst exp_named_subst'' <> List.map fst (List.filter (fun (uri,_) -> List.mem uri params) exp_named_subst) @ List.map fst exp_named_subst') then (
314 debug_print (lazy "\n\n---- BEGIN ") ;
315 debug_print (lazy ("----params: " ^ String.concat " ; " (List.map UriManager.string_of_uri params))) ;
316 debug_print (lazy ("----S(" ^ UriManager.string_of_uri uri ^ "): " ^ String.concat " ; " (List.map (function (uri,_) -> UriManager.string_of_uri uri) exp_named_subst))) ;
317 debug_print (lazy ("----P: " ^ String.concat " ; " (List.map (function (uri,_) -> UriManager.string_of_uri uri) exp_named_subst'))) ;
318 debug_print (lazy ("----D: " ^ String.concat " ; " (List.map (function (uri,_) -> UriManager.string_of_uri uri) exp_named_subst''))) ;
319 debug_print (lazy "---- END\n\n ") ;
321 C.MutConstruct (uri,typeno,consno,exp_named_subst'')
322 | C.MutCase (sp,i,outt,t,pl) ->
323 C.MutCase (sp,i,substaux k outt, substaux k t,
324 List.map (substaux k) pl)
326 let len = List.length fl in
329 (fun (name,i,ty,bo) -> (name, i, substaux k ty, substaux (k+len) bo))
332 C.Fix (i, substitutedfl)
334 let len = List.length fl in
337 (fun (name,ty,bo) -> (name, substaux k ty, substaux (k+len) bo))
340 C.CoFix (i, substitutedfl)
341 and substaux_in_exp_named_subst uri k exp_named_subst' params =
342 let rec filter_and_lift =
347 (function (uri',_) -> not (UriManager.eq uri uri')) exp_named_subst'
351 (uri,lift (k-1) t)::(filter_and_lift tl)
352 | _::tl -> filter_and_lift tl
355 List.map (function (uri,t) -> (uri,substaux k t)) exp_named_subst' @
356 (filter_and_lift exp_named_subst)
364 [uri,List.assoc uri res]
372 if exp_named_subst = [] then t
376 (* subst_meta [t_1 ; ... ; t_n] t *)
377 (* returns the term [t] where [Rel i] is substituted with [t_i] *)
378 (* [t_i] is lifted as usual when it crosses an abstraction *)
380 let module C = Cic in
381 if l = [] then t else
382 let rec aux k = function
384 if n <= k then t else
386 match List.nth l (n-k-1) with
387 None -> raise RelToHiddenHypothesis
390 (Failure _) -> assert false
392 | C.Var (uri,exp_named_subst) ->
393 let exp_named_subst' =
394 List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
396 C.Var (uri,exp_named_subst')
406 RelToHiddenHypothesis -> None
411 | C.Implicit _ as t -> t
412 | C.Cast (te,ty) -> C.Cast (aux k te, aux k ty) (*CSC ??? *)
413 | C.Prod (n,s,t) -> C.Prod (n, aux k s, aux (k + 1) t)
414 | C.Lambda (n,s,t) -> C.Lambda (n, aux k s, aux (k + 1) t)
415 | C.LetIn (n,s,ty,t) -> C.LetIn (n, aux k s, aux k ty, aux (k + 1) t)
416 | C.Appl l -> C.Appl (List.map (aux k) l)
417 | C.Const (uri,exp_named_subst) ->
418 let exp_named_subst' =
419 List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
421 C.Const (uri,exp_named_subst')
422 | C.MutInd (uri,typeno,exp_named_subst) ->
423 let exp_named_subst' =
424 List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
426 C.MutInd (uri,typeno,exp_named_subst')
427 | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
428 let exp_named_subst' =
429 List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
431 C.MutConstruct (uri,typeno,consno,exp_named_subst')
432 | C.MutCase (sp,i,outt,t,pl) ->
433 C.MutCase (sp,i,aux k outt, aux k t, List.map (aux k) pl)
435 let len = List.length fl in
438 (fun (name,i,ty,bo) -> (name, i, aux k ty, aux (k+len) bo))
441 C.Fix (i, substitutedfl)
443 let len = List.length fl in
446 (fun (name,ty,bo) -> (name, aux k ty, aux (k+len) bo))
449 C.CoFix (i, substitutedfl)
454 Deannotate.lift := lift;;