~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to pretyping/termops.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(************************************************************************)
 
2
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
4
(*   \VV/  **************************************************************)
 
5
(*    //   *      This file is distributed under the terms of the       *)
 
6
(*         *       GNU Lesser General Public License Version 2.1        *)
 
7
(************************************************************************)
 
8
 
 
9
(* $Id: termops.ml 12058 2009-04-08 10:54:59Z herbelin $ *)
 
10
 
 
11
open Pp
 
12
open Util
 
13
open Names
 
14
open Nameops
 
15
open Term
 
16
open Sign
 
17
open Environ
 
18
open Libnames
 
19
open Nametab
 
20
 
 
21
(* Sorts and sort family *)
 
22
 
 
23
let print_sort = function
 
24
  | Prop Pos -> (str "Set")
 
25
  | Prop Null -> (str "Prop")
 
26
  | Type u -> (str "Type(" ++ Univ.pr_uni u ++ str ")")
 
27
 
 
28
let pr_sort_family = function
 
29
  | InSet -> (str "Set")
 
30
  | InProp -> (str "Prop")
 
31
  | InType -> (str "Type")
 
32
 
 
33
let pr_name = function
 
34
  | Name id -> pr_id id
 
35
  | Anonymous -> str "_"
 
36
 
 
37
let pr_sp sp = str(string_of_kn sp)
 
38
let pr_con sp = str(string_of_con sp)
 
39
 
 
40
let rec pr_constr c = match kind_of_term c with
 
41
  | Rel n -> str "#"++int n
 
42
  | Meta n -> str "Meta(" ++ int n ++ str ")"
 
43
  | Var id -> pr_id id
 
44
  | Sort s -> print_sort s
 
45
  | Cast (c,_, t) -> hov 1 
 
46
      (str"(" ++ pr_constr c ++ cut() ++
 
47
       str":" ++ pr_constr t ++ str")")
 
48
  | Prod (Name(id),t,c) -> hov 1
 
49
      (str"forall " ++ pr_id id ++ str":" ++ pr_constr t ++ str"," ++
 
50
       spc() ++ pr_constr c)
 
51
  | Prod (Anonymous,t,c) -> hov 0
 
52
      (str"(" ++ pr_constr t ++ str " ->" ++ spc() ++
 
53
       pr_constr c ++ str")")
 
54
  | Lambda (na,t,c) -> hov 1
 
55
      (str"fun " ++ pr_name na ++ str":" ++
 
56
       pr_constr t ++ str" =>" ++ spc() ++ pr_constr c)
 
57
  | LetIn (na,b,t,c) -> hov 0
 
58
      (str"let " ++ pr_name na ++ str":=" ++ pr_constr b ++
 
59
       str":" ++ brk(1,2) ++ pr_constr t ++ cut() ++
 
60
       pr_constr c)
 
61
  | App (c,l) ->  hov 1
 
62
      (str"(" ++ pr_constr c ++ spc() ++
 
63
       prlist_with_sep spc pr_constr (Array.to_list l) ++ str")")
 
64
  | Evar (e,l) -> hov 1
 
65
      (str"Evar#" ++ int e ++ str"{" ++
 
66
       prlist_with_sep spc pr_constr (Array.to_list l) ++str"}")
 
67
  | Const c -> str"Cst(" ++ pr_con c ++ str")"
 
68
  | Ind (sp,i) -> str"Ind(" ++ pr_sp sp ++ str"," ++ int i ++ str")"
 
69
  | Construct ((sp,i),j) ->
 
70
      str"Constr(" ++ pr_sp sp ++ str"," ++ int i ++ str"," ++ int j ++ str")"
 
71
  | Case (ci,p,c,bl) -> v 0
 
72
      (hv 0 (str"<"++pr_constr p++str">"++ cut() ++ str"Case " ++
 
73
             pr_constr c ++ str"of") ++ cut() ++
 
74
       prlist_with_sep (fun _ -> brk(1,2)) pr_constr (Array.to_list bl) ++
 
75
      cut() ++ str"end")
 
76
  | Fix ((t,i),(lna,tl,bl)) ->
 
77
      let fixl = Array.mapi (fun i na -> (na,t.(i),tl.(i),bl.(i))) lna in
 
78
      hov 1
 
79
        (str"fix " ++ int i ++ spc() ++  str"{" ++
 
80
         v 0 (prlist_with_sep spc (fun (na,i,ty,bd) ->
 
81
           pr_name na ++ str"/" ++ int i ++ str":" ++ pr_constr ty ++
 
82
           cut() ++ str":=" ++ pr_constr bd) (Array.to_list fixl)) ++
 
83
         str"}")
 
84
  | CoFix(i,(lna,tl,bl)) ->
 
85
      let fixl = Array.mapi (fun i na -> (na,tl.(i),bl.(i))) lna in
 
86
      hov 1
 
87
        (str"cofix " ++ int i ++ spc() ++  str"{" ++
 
88
         v 0 (prlist_with_sep spc (fun (na,ty,bd) ->
 
89
           pr_name na ++ str":" ++ pr_constr ty ++
 
90
           cut() ++ str":=" ++ pr_constr bd) (Array.to_list fixl)) ++
 
91
         str"}")
 
92
 
 
93
let term_printer = ref (fun _ -> pr_constr)
 
94
let print_constr_env t = !term_printer t
 
95
let print_constr t = !term_printer (Global.env()) t
 
96
let set_print_constr f = term_printer := f
 
97
 
 
98
let pr_var_decl env (id,c,typ) =
 
99
  let pbody = match c with
 
100
    | None ->  (mt ())
 
101
    | Some c ->
 
102
        (* Force evaluation *) 
 
103
        let pb = print_constr_env env c in
 
104
          (str" := " ++ pb ++ cut () ) in
 
105
  let pt = print_constr_env env typ in
 
106
  let ptyp = (str" : " ++ pt) in
 
107
    (pr_id id ++ hov 0 (pbody ++ ptyp))
 
108
 
 
109
let pr_rel_decl env (na,c,typ) =
 
110
  let pbody = match c with
 
111
    | None -> mt ()
 
112
    | Some c ->
 
113
        (* Force evaluation *) 
 
114
        let pb = print_constr_env env c in
 
115
          (str":=" ++ spc () ++ pb ++ spc ()) in
 
116
  let ptyp = print_constr_env env typ in
 
117
    match na with
 
118
      | Anonymous -> hov 0 (str"<>" ++ spc () ++ pbody ++ str":" ++ spc () ++ ptyp)
 
119
      | Name id -> hov 0 (pr_id id ++ spc () ++ pbody ++ str":" ++ spc () ++ ptyp)
 
120
 
 
121
let print_named_context env =
 
122
  hv 0 (fold_named_context
 
123
          (fun env d pps -> 
 
124
            pps ++ ws 2 ++ pr_var_decl env d)
 
125
          env ~init:(mt ()))
 
126
 
 
127
let print_rel_context env = 
 
128
  hv 0 (fold_rel_context
 
129
          (fun env d pps -> pps ++ ws 2 ++ pr_rel_decl env d)
 
130
          env ~init:(mt ()))
 
131
    
 
132
let print_env env =
 
133
  let sign_env =
 
134
    fold_named_context
 
135
      (fun env d pps ->
 
136
         let pidt =  pr_var_decl env d in
 
137
         (pps ++ fnl () ++ pidt))
 
138
      env ~init:(mt ()) 
 
139
  in
 
140
  let db_env =
 
141
    fold_rel_context
 
142
      (fun env d pps ->
 
143
         let pnat = pr_rel_decl env d in (pps ++ fnl () ++ pnat))
 
144
      env ~init:(mt ())
 
145
  in 
 
146
    (sign_env ++ db_env)
 
147
    
 
148
(*let current_module = ref empty_dirpath
 
149
 
 
150
let set_module m = current_module := m*)
 
151
 
 
152
let new_univ = 
 
153
  let univ_gen = ref 0 in
 
154
  (fun sp ->
 
155
    incr univ_gen; 
 
156
    Univ.make_univ (Lib.library_dp(),!univ_gen))
 
157
let new_Type () = mkType (new_univ ())
 
158
let new_Type_sort () = Type (new_univ ())
 
159
 
 
160
(* This refreshes universes in types; works only for inferred types (i.e. for
 
161
   types of the form (x1:A1)...(xn:An)B with B a sort or an atom in
 
162
   head normal form) *)
 
163
let refresh_universes_gen strict t =
 
164
  let modified = ref false in
 
165
  let rec refresh t = match kind_of_term t with
 
166
    | Sort (Type u) when strict or u <> Univ.type0m_univ ->
 
167
        modified := true; new_Type ()
 
168
    | Prod (na,u,v) -> mkProd (na,u,refresh v)
 
169
    | _ -> t in
 
170
  let t' = refresh t in
 
171
  if !modified then t' else t
 
172
 
 
173
let refresh_universes = refresh_universes_gen false
 
174
let refresh_universes_strict = refresh_universes_gen true
 
175
 
 
176
let new_sort_in_family = function 
 
177
  | InProp -> prop_sort
 
178
  | InSet -> set_sort
 
179
  | InType -> Type (new_univ ())
 
180
 
 
181
 
 
182
 
 
183
(* prod_it b [xn:Tn;..;x1:T1] = (x1:T1)..(xn:Tn)b *)
 
184
let prod_it ~init = List.fold_left (fun c (n,t)  -> mkProd (n, t, c)) init
 
185
 
 
186
(* lam_it b [xn:Tn;..;x1:T1] = [x1:T1]..[xn:Tn]b *)
 
187
let lam_it ~init = List.fold_left (fun c (n,t)  -> mkLambda (n, t, c)) init
 
188
 
 
189
(* [Rel (n+m);...;Rel(n+1)] *)
 
190
let rel_vect n m = Array.init m (fun i -> mkRel(n+m-i))
 
191
 
 
192
let rel_list n m = 
 
193
  let rec reln l p = 
 
194
    if p>m then l else reln (mkRel(n+p)::l) (p+1)
 
195
  in 
 
196
  reln [] 1
 
197
 
 
198
(* Same as [rel_list] but takes a context as argument and skips let-ins *)
 
199
let extended_rel_list n hyps =
 
200
  let rec reln l p = function
 
201
    | (_,None,_) :: hyps -> reln (mkRel (n+p) :: l) (p+1) hyps
 
202
    | (_,Some _,_) :: hyps -> reln l (p+1) hyps
 
203
    | [] -> l
 
204
  in 
 
205
  reln [] 1 hyps
 
206
 
 
207
let extended_rel_vect n hyps = Array.of_list (extended_rel_list n hyps)
 
208
 
 
209
 
 
210
 
 
211
let push_rel_assum (x,t) env = push_rel (x,None,t) env
 
212
 
 
213
let push_rels_assum assums =
 
214
  push_rel_context (List.map (fun (x,t) -> (x,None,t)) assums)
 
215
 
 
216
let push_named_rec_types (lna,typarray,_) env =
 
217
  let ctxt =
 
218
    array_map2_i
 
219
      (fun i na t ->
 
220
         match na with
 
221
           | Name id -> (id, None, lift i t)
 
222
           | Anonymous -> anomaly "Fix declarations must be named")
 
223
      lna typarray in
 
224
  Array.fold_left
 
225
    (fun e assum -> push_named assum e) env ctxt
 
226
 
 
227
let rec lookup_rel_id id sign = 
 
228
  let rec lookrec = function
 
229
    | (n, (Anonymous,_,_)::l) -> lookrec (n+1,l)
 
230
    | (n, (Name id',_,t)::l)  -> if id' = id then (n,t) else lookrec (n+1,l)
 
231
    | (_, [])                 -> raise Not_found
 
232
  in 
 
233
  lookrec (1,sign)
 
234
 
 
235
(* Constructs either [(x:t)c] or [[x=b:t]c] *)
 
236
let mkProd_or_LetIn (na,body,t) c =
 
237
  match body with
 
238
    | None -> mkProd (na, t, c)
 
239
    | Some b -> mkLetIn (na, b, t, c)
 
240
 
 
241
(* Constructs either [(x:t)c] or [c] where [x] is replaced by [b] *)
 
242
let mkProd_wo_LetIn (na,body,t) c =
 
243
  match body with
 
244
    | None -> mkProd (na,  t, c)
 
245
    | Some b -> subst1 b c
 
246
 
 
247
let it_mkProd_wo_LetIn ~init = 
 
248
  List.fold_left (fun c d -> mkProd_wo_LetIn d c) init
 
249
 
 
250
let it_mkProd_or_LetIn ~init = 
 
251
  List.fold_left (fun c d -> mkProd_or_LetIn d c) init
 
252
 
 
253
let it_mkLambda_or_LetIn ~init =
 
254
  List.fold_left (fun c d -> mkLambda_or_LetIn d c) init
 
255
 
 
256
let it_named_context_quantifier f ~init = 
 
257
  List.fold_left (fun c d -> f d c) init
 
258
 
 
259
let it_mkNamedProd_or_LetIn = it_named_context_quantifier mkNamedProd_or_LetIn
 
260
let it_mkNamedLambda_or_LetIn = it_named_context_quantifier mkNamedLambda_or_LetIn
 
261
 
 
262
let it_mkNamedProd_wo_LetIn = it_named_context_quantifier mkNamedProd_wo_LetIn
 
263
 
 
264
(* *)
 
265
 
 
266
(* strips head casts and flattens head applications *)
 
267
let rec strip_head_cast c = match kind_of_term c with
 
268
  | App (f,cl) -> 
 
269
      let rec collapse_rec f cl2 = match kind_of_term f with
 
270
        | App (g,cl1) -> collapse_rec g (Array.append cl1 cl2)
 
271
        | Cast (c,_,_) -> collapse_rec c cl2
 
272
        | _ -> if Array.length cl2 = 0 then f else mkApp (f,cl2)
 
273
      in 
 
274
      collapse_rec f cl
 
275
  | Cast (c,_,_) -> strip_head_cast c
 
276
  | _ -> c
 
277
 
 
278
(* Get the last arg of an application *)
 
279
let last_arg c = match kind_of_term c with
 
280
  | App (f,cl) -> array_last cl
 
281
  | _ -> anomaly "last_arg"
 
282
 
 
283
(* [map_constr_with_named_binders g f l c] maps [f l] on the immediate
 
284
   subterms of [c]; it carries an extra data [l] (typically a name
 
285
   list) which is processed by [g na] (which typically cons [na] to
 
286
   [l]) at each binder traversal (with name [na]); it is not recursive
 
287
   and the order with which subterms are processed is not specified *)
 
288
 
 
289
let map_constr_with_named_binders g f l c = match kind_of_term c with
 
290
  | (Rel _ | Meta _ | Var _   | Sort _ | Const _ | Ind _
 
291
    | Construct _) -> c
 
292
  | Cast (c,k,t) -> mkCast (f l c, k, f l t)
 
293
  | Prod (na,t,c) -> mkProd (na, f l t, f (g na l) c)
 
294
  | Lambda (na,t,c) -> mkLambda (na, f l t, f (g na l) c)
 
295
  | LetIn (na,b,t,c) -> mkLetIn (na, f l b, f l t, f (g na l) c)
 
296
  | App (c,al) -> mkApp (f l c, Array.map (f l) al)
 
297
  | Evar (e,al) -> mkEvar (e, Array.map (f l) al)
 
298
  | Case (ci,p,c,bl) -> mkCase (ci, f l p, f l c, Array.map (f l) bl)
 
299
  | Fix (ln,(lna,tl,bl)) ->
 
300
      let l' = Array.fold_left (fun l na -> g na l) l lna in
 
301
      mkFix (ln,(lna,Array.map (f l) tl,Array.map (f l') bl))
 
302
  | CoFix(ln,(lna,tl,bl)) ->
 
303
      let l' = Array.fold_left (fun l na -> g na l) l lna in
 
304
      mkCoFix (ln,(lna,Array.map (f l) tl,Array.map (f l') bl))
 
305
 
 
306
(* [map_constr_with_binders_left_to_right g f n c] maps [f n] on the
 
307
   immediate subterms of [c]; it carries an extra data [n] (typically
 
308
   a lift index) which is processed by [g] (which typically add 1 to
 
309
   [n]) at each binder traversal; the subterms are processed from left
 
310
   to right according to the usual representation of the constructions
 
311
   (this may matter if [f] does a side-effect); it is not recursive;
 
312
   in fact, the usual representation of the constructions is at the
 
313
   time being almost those of the ML representation (except for
 
314
   (co-)fixpoint) *)
 
315
 
 
316
let fold_rec_types g (lna,typarray,_) e =
 
317
  let ctxt = array_map2_i (fun i na t -> (na, None, lift i t)) lna typarray in
 
318
  Array.fold_left (fun e assum -> g assum e) e ctxt
 
319
 
 
320
 
 
321
let map_constr_with_binders_left_to_right g f l c = match kind_of_term c with
 
322
  | (Rel _ | Meta _ | Var _   | Sort _ | Const _ | Ind _
 
323
    | Construct _) -> c
 
324
  | Cast (c,k,t) -> let c' = f l c in mkCast (c',k,f l t)
 
325
  | Prod (na,t,c) ->
 
326
      let t' = f l t in
 
327
      mkProd (na, t', f (g (na,None,t) l) c)
 
328
  | Lambda (na,t,c) ->
 
329
      let t' = f l t in
 
330
      mkLambda (na, t', f (g (na,None,t) l) c)
 
331
  | LetIn (na,b,t,c) ->
 
332
      let b' = f l b in
 
333
      let t' = f l t in
 
334
      let c' = f (g (na,Some b,t) l) c in
 
335
      mkLetIn (na, b', t', c')
 
336
  | App (c,[||]) -> assert false
 
337
  | App (c,al) ->
 
338
      (*Special treatment to be able to recognize partially applied subterms*)
 
339
      let a = al.(Array.length al - 1) in
 
340
      let hd = f l (mkApp (c, Array.sub al 0 (Array.length al - 1))) in
 
341
      mkApp (hd, [| f l a |])
 
342
  | Evar (e,al) -> mkEvar (e, array_map_left (f l) al)
 
343
  | Case (ci,p,c,bl) ->
 
344
      (* In v8 concrete syntax, predicate is after the term to match! *)
 
345
      let c' = f l c in
 
346
      let p' = f l p in
 
347
      mkCase (ci, p', c', array_map_left (f l) bl)
 
348
  | Fix (ln,(lna,tl,bl as fx)) ->
 
349
      let l' = fold_rec_types g fx l in
 
350
      let (tl',bl') = array_map_left_pair (f l) tl (f l') bl in
 
351
      mkFix (ln,(lna,tl',bl'))
 
352
  | CoFix(ln,(lna,tl,bl as fx)) ->
 
353
      let l' = fold_rec_types g fx l in
 
354
      let (tl',bl') = array_map_left_pair (f l) tl (f l') bl in
 
355
      mkCoFix (ln,(lna,tl',bl'))
 
356
 
 
357
(* strong *)
 
358
let map_constr_with_full_binders g f l cstr = match kind_of_term cstr with
 
359
  | (Rel _ | Meta _ | Var _   | Sort _ | Const _ | Ind _
 
360
    | Construct _) -> cstr
 
361
  | Cast (c,k, t) -> 
 
362
      let c' = f l c in
 
363
      let t' = f l t in
 
364
      if c==c' && t==t' then cstr else mkCast (c', k, t')
 
365
  | Prod (na,t,c) ->
 
366
      let t' = f l t in
 
367
      let c' = f (g (na,None,t) l) c in
 
368
      if t==t' && c==c' then cstr else mkProd (na, t', c')
 
369
  | Lambda (na,t,c) ->
 
370
      let t' = f l t in
 
371
      let c' = f (g (na,None,t) l) c in
 
372
      if t==t' && c==c' then cstr else  mkLambda (na, t', c')
 
373
  | LetIn (na,b,t,c) ->
 
374
      let b' = f l b in
 
375
      let t' = f l t in
 
376
      let c' = f (g (na,Some b,t) l) c in
 
377
      if b==b' && t==t' && c==c' then cstr else mkLetIn (na, b', t', c')
 
378
  | App (c,al) ->
 
379
      let c' = f l c in
 
380
      let al' = Array.map (f l) al in
 
381
      if c==c' && array_for_all2 (==) al al' then cstr else mkApp (c', al')
 
382
  | Evar (e,al) ->
 
383
      let al' = Array.map (f l) al in
 
384
      if array_for_all2 (==) al al' then cstr else mkEvar (e, al')
 
385
  | Case (ci,p,c,bl) ->
 
386
      let p' = f l p in
 
387
      let c' = f l c in
 
388
      let bl' = Array.map (f l) bl in
 
389
      if p==p' && c==c' && array_for_all2 (==) bl bl' then cstr else
 
390
        mkCase (ci, p', c', bl')
 
391
  | Fix (ln,(lna,tl,bl)) ->
 
392
      let tl' = Array.map (f l) tl in
 
393
      let l' =
 
394
        array_fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
 
395
      let bl' = Array.map (f l') bl in
 
396
      if array_for_all2 (==) tl tl' && array_for_all2 (==) bl bl'
 
397
      then cstr
 
398
      else mkFix (ln,(lna,tl',bl'))
 
399
  | CoFix(ln,(lna,tl,bl)) ->
 
400
      let tl' = Array.map (f l) tl in
 
401
      let l' =
 
402
        array_fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
 
403
      let bl' = Array.map (f l') bl in
 
404
      if array_for_all2 (==) tl tl' && array_for_all2 (==) bl bl'
 
405
      then cstr
 
406
      else mkCoFix (ln,(lna,tl',bl'))
 
407
 
 
408
(* [fold_constr_with_binders g f n acc c] folds [f n] on the immediate
 
409
   subterms of [c] starting from [acc] and proceeding from left to
 
410
   right according to the usual representation of the constructions as
 
411
   [fold_constr] but it carries an extra data [n] (typically a lift
 
412
   index) which is processed by [g] (which typically add 1 to [n]) at
 
413
   each binder traversal; it is not recursive *)
 
414
 
 
415
let fold_constr_with_binders g f n acc c = match kind_of_term c with
 
416
  | (Rel _ | Meta _ | Var _   | Sort _ | Const _ | Ind _
 
417
    | Construct _) -> acc
 
418
  | Cast (c,_, t) -> f n (f n acc c) t
 
419
  | Prod (_,t,c) -> f (g n) (f n acc t) c
 
420
  | Lambda (_,t,c) -> f (g n) (f n acc t) c
 
421
  | LetIn (_,b,t,c) -> f (g n) (f n (f n acc b) t) c
 
422
  | App (c,l) -> Array.fold_left (f n) (f n acc c) l
 
423
  | Evar (_,l) -> Array.fold_left (f n) acc l
 
424
  | Case (_,p,c,bl) -> Array.fold_left (f n) (f n (f n acc p) c) bl
 
425
  | Fix (_,(lna,tl,bl)) -> 
 
426
      let n' = iterate g (Array.length tl) n in
 
427
      let fd = array_map2 (fun t b -> (t,b)) tl bl in
 
428
      Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
 
429
  | CoFix (_,(lna,tl,bl)) ->
 
430
      let n' = iterate g (Array.length tl) n in
 
431
      let fd = array_map2 (fun t b -> (t,b)) tl bl in
 
432
      Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
 
433
 
 
434
(* [iter_constr_with_full_binders g f acc c] iters [f acc] on the immediate
 
435
   subterms of [c]; it carries an extra data [acc] which is processed by [g] at
 
436
   each binder traversal; it is not recursive and the order with which
 
437
   subterms are processed is not specified *)
 
438
 
 
439
let iter_constr_with_full_binders g f l c = match kind_of_term c with
 
440
  | (Rel _ | Meta _ | Var _   | Sort _ | Const _ | Ind _
 
441
    | Construct _) -> ()
 
442
  | Cast (c,_, t) -> f l c; f l t
 
443
  | Prod (na,t,c) -> f l t; f (g (na,None,t) l) c
 
444
  | Lambda (na,t,c) -> f l t; f (g (na,None,t) l) c
 
445
  | LetIn (na,b,t,c) -> f l b; f l t; f (g (na,Some b,t) l) c
 
446
  | App (c,args) -> f l c; Array.iter (f l) args
 
447
  | Evar (_,args) -> Array.iter (f l) args
 
448
  | Case (_,p,c,bl) -> f l p; f l c; Array.iter (f l) bl
 
449
  | Fix (_,(lna,tl,bl)) -> 
 
450
      let l' = array_fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
 
451
      Array.iter (f l) tl;
 
452
      Array.iter (f l') bl
 
453
  | CoFix (_,(lna,tl,bl)) ->
 
454
      let l' = array_fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
 
455
      Array.iter (f l) tl;
 
456
      Array.iter (f l') bl
 
457
 
 
458
(***************************)
 
459
(* occurs check functions  *)                         
 
460
(***************************)
 
461
 
 
462
exception Occur
 
463
 
 
464
let occur_meta c =
 
465
  let rec occrec c = match kind_of_term c with
 
466
    | Meta _ -> raise Occur
 
467
    | _ -> iter_constr occrec c
 
468
  in try occrec c; false with Occur -> true
 
469
 
 
470
let occur_existential c = 
 
471
  let rec occrec c = match kind_of_term c with
 
472
    | Evar _ -> raise Occur
 
473
    | _ -> iter_constr occrec c
 
474
  in try occrec c; false with Occur -> true
 
475
 
 
476
let occur_meta_or_existential c = 
 
477
  let rec occrec c = match kind_of_term c with
 
478
    | Evar _ -> raise Occur
 
479
    | Meta _ -> raise Occur
 
480
    | _ -> iter_constr occrec c
 
481
  in try occrec c; false with Occur -> true
 
482
 
 
483
let occur_const s c = 
 
484
  let rec occur_rec c = match kind_of_term c with
 
485
    | Const sp when sp=s -> raise Occur
 
486
    | _ -> iter_constr occur_rec c
 
487
  in 
 
488
  try occur_rec c; false with Occur -> true
 
489
 
 
490
let occur_evar n c = 
 
491
  let rec occur_rec c = match kind_of_term c with
 
492
    | Evar (sp,_) when sp=n -> raise Occur
 
493
    | _ -> iter_constr occur_rec c
 
494
  in 
 
495
  try occur_rec c; false with Occur -> true
 
496
 
 
497
let occur_in_global env id constr =
 
498
  let vars = vars_of_global env constr in
 
499
  if List.mem id vars then raise Occur
 
500
 
 
501
let occur_var env s c = 
 
502
  let rec occur_rec c =
 
503
    occur_in_global env s c;
 
504
    iter_constr occur_rec c
 
505
  in 
 
506
  try occur_rec c; false with Occur -> true
 
507
 
 
508
let occur_var_in_decl env hyp (_,c,typ) =
 
509
  match c with
 
510
    | None -> occur_var env hyp typ
 
511
    | Some body ->
 
512
        occur_var env hyp typ ||
 
513
        occur_var env hyp body
 
514
 
 
515
(* Tests that t is a subterm of c *)
 
516
let occur_term t c = 
 
517
  let eq_constr_fail c = if eq_constr t c then raise Occur
 
518
  in let rec occur_rec c = eq_constr_fail c; iter_constr occur_rec c
 
519
  in try occur_rec c; false with Occur -> true
 
520
 
 
521
(* returns the list of free debruijn indices in a term *)
 
522
 
 
523
let free_rels m = 
 
524
  let rec frec depth acc c = match kind_of_term c with
 
525
    | Rel n       -> if n >= depth then Intset.add (n-depth+1) acc else acc
 
526
    | _ -> fold_constr_with_binders succ frec depth acc c
 
527
  in 
 
528
  frec 1 Intset.empty m
 
529
 
 
530
(* collects all metavar occurences, in left-to-right order, preserving
 
531
 * repetitions and all. *)
 
532
 
 
533
let collect_metas c = 
 
534
  let rec collrec acc c =
 
535
    match kind_of_term c with
 
536
      | Meta mv -> list_add_set mv acc
 
537
      | _       -> fold_constr collrec acc c
 
538
  in
 
539
  List.rev (collrec [] c)
 
540
 
 
541
(* (dependent M N) is true iff M is eq_term with a subterm of N 
 
542
   M is appropriately lifted through abstractions of N *)
 
543
 
 
544
let dependent m t =
 
545
  let rec deprec m t =
 
546
    if eq_constr m t then
 
547
      raise Occur
 
548
    else
 
549
      match kind_of_term m, kind_of_term t with
 
550
        | App (fm,lm), App (ft,lt) when Array.length lm < Array.length lt ->
 
551
            deprec m (mkApp (ft,Array.sub lt 0 (Array.length lm)));
 
552
            Array.iter (deprec m)
 
553
              (Array.sub lt 
 
554
                (Array.length lm) ((Array.length lt) - (Array.length lm)))
 
555
        | _ -> iter_constr_with_binders (lift 1) deprec m t
 
556
  in 
 
557
  try deprec m t; false with Occur -> true
 
558
 
 
559
let pop t = lift (-1) t
 
560
 
 
561
(***************************)
 
562
(*  bindings functions *)                         
 
563
(***************************)
 
564
 
 
565
type metamap = (metavariable * constr) list 
 
566
 
 
567
let rec subst_meta bl c = 
 
568
  match kind_of_term c with
 
569
    | Meta i -> (try List.assoc i bl with Not_found -> c)
 
570
    | _ -> map_constr (subst_meta bl) c
 
571
 
 
572
(* First utilities for avoiding telescope computation for subst_term *)
 
573
 
 
574
let prefix_application eq_fun (k,c) (t : constr) = 
 
575
  let c' = collapse_appl c and t' = collapse_appl t in
 
576
  match kind_of_term c', kind_of_term t' with
 
577
    | App (f1,cl1), App (f2,cl2) ->
 
578
        let l1 = Array.length cl1
 
579
        and l2 = Array.length cl2 in
 
580
        if l1 <= l2
 
581
           && eq_fun c' (mkApp (f2, Array.sub cl2 0 l1)) then
 
582
          Some (mkApp (mkRel k, Array.sub cl2 l1 (l2 - l1)))
 
583
        else 
 
584
          None
 
585
    | _ -> None
 
586
 
 
587
let my_prefix_application eq_fun (k,c) (by_c : constr) (t : constr) = 
 
588
  let c' = collapse_appl c and t' = collapse_appl t in
 
589
  match kind_of_term c', kind_of_term t' with
 
590
    | App (f1,cl1), App (f2,cl2) ->
 
591
        let l1 = Array.length cl1
 
592
        and l2 = Array.length cl2 in
 
593
        if l1 <= l2
 
594
           && eq_fun c' (mkApp (f2, Array.sub cl2 0 l1)) then
 
595
          Some (mkApp ((lift k by_c), Array.sub cl2 l1 (l2 - l1)))
 
596
        else 
 
597
          None
 
598
    | _ -> None
 
599
 
 
600
(* Recognizing occurrences of a given (closed) subterm in a term for Pattern :
 
601
   [subst_term c t] substitutes [(Rel 1)] for all occurrences of (closed)
 
602
   term [c] in a term [t] *)
 
603
(*i Bizarre : si on cherche un sous terme clos, pourquoi le lifter ? i*)
 
604
 
 
605
let subst_term_gen eq_fun c t = 
 
606
  let rec substrec (k,c as kc) t =
 
607
    match prefix_application eq_fun kc t with
 
608
      | Some x -> x
 
609
      | None ->
 
610
    if eq_fun c t then mkRel k
 
611
    else
 
612
      map_constr_with_binders (fun (k,c) -> (k+1,lift 1 c)) substrec kc t
 
613
  in 
 
614
  substrec (1,c) t
 
615
 
 
616
(* Recognizing occurrences of a given (closed) subterm in a term :
 
617
   [replace_term c1 c2 t] substitutes [c2] for all occurrences of (closed)
 
618
   term [c1] in a term [t] *)
 
619
(*i Meme remarque : a priori [c] n'est pas forcement clos i*)
 
620
 
 
621
let replace_term_gen eq_fun c by_c in_t = 
 
622
  let rec substrec (k,c as kc) t =
 
623
    match my_prefix_application eq_fun kc by_c t with
 
624
      | Some x -> x
 
625
      | None ->
 
626
    (if eq_fun c t then (lift k by_c) else
 
627
      map_constr_with_binders (fun (k,c) -> (k+1,lift 1 c))
 
628
        substrec kc t)
 
629
  in 
 
630
  substrec (0,c) in_t
 
631
 
 
632
let subst_term = subst_term_gen eq_constr
 
633
 
 
634
let replace_term = replace_term_gen eq_constr
 
635
 
 
636
(* Substitute only at a list of locations or excluding a list of
 
637
   locations; in the occurrences list (b,l), b=true means no
 
638
   occurrence except the ones in l and b=false, means all occurrences
 
639
   except the ones in l *)
 
640
 
 
641
type occurrences = bool * int list
 
642
let all_occurrences = (false,[])
 
643
let no_occurrences_in_set = (true,[])
 
644
 
 
645
let error_invalid_occurrence l =
 
646
  let l = list_uniquize (List.sort Pervasives.compare l) in
 
647
  errorlabstrm ""
 
648
    (str ("Invalid occurrence " ^ plural (List.length l) "number" ^": ") ++ 
 
649
     prlist_with_sep spc int l ++ str ".")
 
650
 
 
651
let subst_term_occ_gen (nowhere_except_in,locs) occ c t =
 
652
  let maxocc = List.fold_right max locs 0 in
 
653
  let pos = ref occ in
 
654
  assert (List.for_all (fun x -> x >= 0) locs);
 
655
  let rec substrec (k,c as kc) t =
 
656
    if nowhere_except_in & !pos > maxocc then t
 
657
    else
 
658
    if eq_constr c t then
 
659
      let r = 
 
660
        if nowhere_except_in then
 
661
          if List.mem !pos locs then (mkRel k) else t
 
662
        else 
 
663
          if List.mem !pos locs then t else (mkRel k)
 
664
      in incr pos; r
 
665
    else
 
666
      map_constr_with_binders_left_to_right
 
667
        (fun d (k,c) -> (k+1,lift 1 c))
 
668
        substrec kc t
 
669
  in
 
670
  let t' = substrec (1,c) t in
 
671
  (!pos, t')
 
672
 
 
673
let subst_term_occ (nowhere_except_in,locs as plocs) c t = 
 
674
  if locs = [] then if nowhere_except_in then t else subst_term c t
 
675
  else 
 
676
    let (nbocc,t') = subst_term_occ_gen plocs 1 c t in
 
677
    let rest = List.filter (fun o -> o >= nbocc) locs in
 
678
    if rest <> [] then error_invalid_occurrence rest;
 
679
    t'
 
680
 
 
681
type hyp_location_flag = (* To distinguish body and type of local defs *)
 
682
  | InHyp
 
683
  | InHypTypeOnly
 
684
  | InHypValueOnly
 
685
 
 
686
let subst_term_occ_decl ((nowhere_except_in,locs as plocs),hloc) c (id,bodyopt,typ as d) =
 
687
  match bodyopt,hloc with
 
688
  | None, InHypValueOnly -> errorlabstrm "" (pr_id id ++ str " has no value")
 
689
  | None, _ -> (id,None,subst_term_occ plocs c typ)
 
690
  | Some body, InHypTypeOnly -> (id,Some body,subst_term_occ plocs c typ)
 
691
  | Some body, InHypValueOnly -> (id,Some (subst_term_occ plocs c body),typ)
 
692
  | Some body, InHyp ->
 
693
        if locs = [] then
 
694
          if nowhere_except_in then d
 
695
          else (id,Some (subst_term c body),subst_term c typ)
 
696
        else 
 
697
          let (nbocc,body') = subst_term_occ_gen plocs 1 c body in
 
698
          let (nbocc',t') = subst_term_occ_gen plocs nbocc c typ in
 
699
          let rest = List.filter (fun o -> o >= nbocc') locs in
 
700
          if rest <> [] then error_invalid_occurrence rest;
 
701
          (id,Some body',t')
 
702
 
 
703
(* First character of a constr *)
 
704
 
 
705
let lowercase_first_char id =
 
706
  lowercase_first_char_utf8 (string_of_id id)
 
707
 
 
708
let vars_of_env env =
 
709
  let s = 
 
710
    Sign.fold_named_context (fun (id,_,_) s -> Idset.add id s)
 
711
      (named_context env) ~init:Idset.empty in
 
712
  Sign.fold_rel_context
 
713
    (fun (na,_,_) s -> match na with Name id -> Idset.add id s | _ -> s)
 
714
    (rel_context env) ~init:s
 
715
 
 
716
let add_vname vars = function
 
717
    Name id -> Idset.add id vars
 
718
  | _ -> vars
 
719
 
 
720
let id_of_global = Nametab.id_of_global
 
721
 
 
722
let sort_hdchar = function
 
723
  | Prop(_) -> "P"
 
724
  | Type(_) -> "T"
 
725
 
 
726
let hdchar env c = 
 
727
  let rec hdrec k c =
 
728
    match kind_of_term c with
 
729
    | Prod (_,_,c)       -> hdrec (k+1) c
 
730
    | Lambda (_,_,c)     -> hdrec (k+1) c
 
731
    | LetIn (_,_,_,c)    -> hdrec (k+1) c
 
732
    | Cast (c,_,_)         -> hdrec k c
 
733
    | App (f,l)         -> hdrec k f
 
734
    | Const kn       ->
 
735
        lowercase_first_char (id_of_label (con_label kn))
 
736
    | Ind ((kn,i) as x) ->
 
737
        if i=0 then 
 
738
          lowercase_first_char (id_of_label (label kn))
 
739
        else 
 
740
          lowercase_first_char (id_of_global (IndRef x))
 
741
    | Construct ((sp,i) as x) ->
 
742
        lowercase_first_char (id_of_global (ConstructRef x))
 
743
    | Var id  -> lowercase_first_char id
 
744
    | Sort s -> sort_hdchar s
 
745
    | Rel n ->
 
746
        (if n<=k then "p" (* the initial term is flexible product/function *)
 
747
         else
 
748
           try match Environ.lookup_rel (n-k) env with
 
749
             | (Name id,_,_)   -> lowercase_first_char id
 
750
             | (Anonymous,_,t) -> hdrec 0 (lift (n-k) t)
 
751
           with Not_found -> "y")
 
752
    | Fix ((_,i),(lna,_,_)) -> 
 
753
        let id = match lna.(i) with Name id -> id | _ -> assert false in
 
754
        lowercase_first_char id
 
755
    | CoFix (i,(lna,_,_)) -> 
 
756
        let id = match lna.(i) with Name id -> id | _ -> assert false in
 
757
        lowercase_first_char id
 
758
    | Meta _|Evar _|Case (_, _, _, _) -> "y"
 
759
  in 
 
760
  hdrec 0 c
 
761
 
 
762
let id_of_name_using_hdchar env a = function
 
763
  | Anonymous -> id_of_string (hdchar env a) 
 
764
  | Name id   -> id
 
765
 
 
766
let named_hd env a = function
 
767
  | Anonymous -> Name (id_of_string (hdchar env a)) 
 
768
  | x         -> x
 
769
 
 
770
let mkProd_name   env (n,a,b) = mkProd (named_hd env a n, a, b)
 
771
let mkLambda_name env (n,a,b) = mkLambda (named_hd env a n, a, b)
 
772
 
 
773
let lambda_name = mkLambda_name
 
774
let prod_name = mkProd_name
 
775
 
 
776
let prod_create   env (a,b) = mkProd (named_hd env a Anonymous, a, b)
 
777
let lambda_create env (a,b) =  mkLambda (named_hd env a Anonymous, a, b)
 
778
 
 
779
let name_assumption env (na,c,t) =
 
780
  match c with
 
781
    | None      -> (named_hd env t na, None, t)
 
782
    | Some body -> (named_hd env body na, c, t)
 
783
 
 
784
let name_context env hyps =
 
785
  snd
 
786
    (List.fold_left
 
787
       (fun (env,hyps) d -> 
 
788
          let d' = name_assumption env d in (push_rel d' env, d' :: hyps))
 
789
       (env,[]) (List.rev hyps))
 
790
 
 
791
let mkProd_or_LetIn_name env b d = mkProd_or_LetIn (name_assumption env d) b 
 
792
let mkLambda_or_LetIn_name env b d = mkLambda_or_LetIn (name_assumption env d)b
 
793
 
 
794
let it_mkProd_or_LetIn_name env b hyps =
 
795
  it_mkProd_or_LetIn b (name_context env hyps)
 
796
let it_mkLambda_or_LetIn_name env b hyps =
 
797
  it_mkLambda_or_LetIn b (name_context env hyps)
 
798
 
 
799
(*************************)
 
800
(*   Names environments  *)
 
801
(*************************)
 
802
type names_context = name list
 
803
let add_name n nl = n::nl
 
804
let lookup_name_of_rel p names =
 
805
  try List.nth names (p-1)
 
806
  with Invalid_argument _ | Failure _ -> raise Not_found
 
807
let rec lookup_rel_of_name id names = 
 
808
  let rec lookrec n = function
 
809
    | Anonymous :: l  -> lookrec (n+1) l
 
810
    | (Name id') :: l -> if id' = id then n else lookrec (n+1) l
 
811
    | []            -> raise Not_found
 
812
  in 
 
813
  lookrec 1 names
 
814
let empty_names_context = []
 
815
 
 
816
let ids_of_rel_context sign =
 
817
  Sign.fold_rel_context
 
818
    (fun (na,_,_) l -> match na with Name id -> id::l | Anonymous -> l)
 
819
    sign ~init:[]
 
820
 
 
821
let ids_of_named_context sign =
 
822
  Sign.fold_named_context (fun (id,_,_) idl -> id::idl) sign ~init:[]
 
823
 
 
824
let ids_of_context env = 
 
825
  (ids_of_rel_context (rel_context env))
 
826
  @ (ids_of_named_context (named_context env))
 
827
 
 
828
 
 
829
let names_of_rel_context env =
 
830
  List.map (fun (na,_,_) -> na) (rel_context env)
 
831
 
 
832
(**** Globality of identifiers *)
 
833
 
 
834
let rec is_imported_modpath = function
 
835
  | MPfile dp -> true
 
836
  | p -> false
 
837
 
 
838
let is_imported_ref = function
 
839
  | VarRef _ -> false
 
840
  | IndRef (kn,_)
 
841
  | ConstructRef ((kn,_),_) ->
 
842
      let (mp,_,_) = repr_kn kn in is_imported_modpath mp
 
843
  | ConstRef kn ->
 
844
      let (mp,_,_) = repr_con kn in is_imported_modpath mp
 
845
 
 
846
let is_global id =
 
847
  try 
 
848
    let ref = locate (make_short_qualid id) in
 
849
    not (is_imported_ref ref)
 
850
  with Not_found -> 
 
851
    false
 
852
 
 
853
let is_constructor id =
 
854
  try 
 
855
    match locate (make_short_qualid id) with 
 
856
      | ConstructRef _ as ref -> not (is_imported_ref ref)
 
857
      | _ -> false
 
858
  with Not_found -> 
 
859
    false
 
860
 
 
861
let is_section_variable id =
 
862
  try let _ = Global.lookup_named id in true
 
863
  with Not_found -> false
 
864
 
 
865
let next_global_ident_from allow_secvar id avoid = 
 
866
  let rec next_rec id =
 
867
    let id = next_ident_away_from id avoid in
 
868
    if (allow_secvar && is_section_variable id) || not (is_global id) then
 
869
      id
 
870
    else  
 
871
      next_rec (lift_ident id)
 
872
  in 
 
873
  next_rec id
 
874
 
 
875
let next_global_ident_away allow_secvar id avoid =
 
876
  let id  = next_ident_away id avoid in
 
877
  if (allow_secvar && is_section_variable id) || not (is_global id) then
 
878
    id
 
879
  else  
 
880
    next_global_ident_from allow_secvar (lift_ident id) avoid
 
881
 
 
882
let isGlobalRef c = 
 
883
  match kind_of_term c with
 
884
  | Const _ | Ind _ | Construct _ | Var _ -> true
 
885
  | _ -> false
 
886
 
 
887
let has_polymorphic_type c =
 
888
  match (Global.lookup_constant c).Declarations.const_type with
 
889
  | Declarations.PolymorphicArity _ -> true
 
890
  | _ -> false
 
891
 
 
892
(* nouvelle version de renommage des variables (DEC 98) *)
 
893
(* This is the algorithm to display distinct bound variables 
 
894
 
 
895
    - R�gle 1 : un nom non anonyme, m�me non affich�, contribue � la liste
 
896
      des noms � �viter 
 
897
    - R�gle 2 : c'est la d�pendance qui d�cide si on affiche ou pas
 
898
 
 
899
    Exemple : 
 
900
    si bool_ind = (P:bool->Prop)(f:(P true))(f:(P false))(b:bool)(P b), alors
 
901
    il est affich� (P:bool->Prop)(P true)->(P false)->(b:bool)(P b)
 
902
    mais f et f0 contribue � la liste des variables � �viter (en supposant 
 
903
    que les noms f et f0 ne sont pas d�j� pris)
 
904
    Int�r�t : noms homog�nes dans un but avant et apr�s Intro
 
905
*)
 
906
 
 
907
type used_idents = identifier list
 
908
 
 
909
let occur_rel p env id = 
 
910
  try lookup_name_of_rel p env = Name id
 
911
  with Not_found -> false (* Unbound indice : may happen in debug *)
 
912
 
 
913
let occur_id nenv id0 c =
 
914
  let rec occur n c = match kind_of_term c with
 
915
    | Var id when  id=id0 -> raise Occur
 
916
    | Const kn when id_of_global (ConstRef kn) = id0 -> raise Occur
 
917
    | Ind ind_sp
 
918
        when id_of_global (IndRef ind_sp) = id0 ->
 
919
        raise Occur
 
920
    | Construct cstr_sp
 
921
        when id_of_global (ConstructRef cstr_sp) = id0 ->
 
922
        raise Occur
 
923
    | Rel p when p>n & occur_rel (p-n) nenv id0 -> raise Occur
 
924
    | _ -> iter_constr_with_binders succ occur n c
 
925
  in 
 
926
  try occur 1 c; false
 
927
  with Occur -> true
 
928
    | Not_found -> false (* Case when a global is not in the env *)
 
929
 
 
930
type avoid_flags = bool option
 
931
 
 
932
let next_name_not_occuring avoid_flags name l env_names t =
 
933
  let rec next id =
 
934
    if List.mem id l or occur_id env_names id t or 
 
935
      (* Further restrictions ? *)
 
936
      match avoid_flags with None -> false | Some not_only_cstr ->
 
937
      (if not_only_cstr then
 
938
        (* To be consistent with the intro mechanism *)
 
939
        is_global id & not (is_section_variable id)
 
940
      else
 
941
        (* To avoid constructors in pattern-matchings *)
 
942
        is_constructor id)
 
943
    then next (lift_ident id)
 
944
    else id
 
945
  in 
 
946
  match name with
 
947
    | Name id   -> next id
 
948
    | Anonymous -> 
 
949
        (* Normally, an anonymous name is not dependent and will not be *)
 
950
        (* taken into account by the function concrete_name; just in case *)
 
951
        (* invent a valid name *)
 
952
        next (id_of_string "H")
 
953
 
 
954
let base_sort_cmp pb s0 s1 =
 
955
  match (s0,s1) with
 
956
    | (Prop c1, Prop c2) -> c1 = Null or c2 = Pos  (* Prop <= Set *)
 
957
    | (Prop c1, Type u)  -> pb = Reduction.CUMUL
 
958
    | (Type u1, Type u2) -> true
 
959
    | _ -> false
 
960
 
 
961
(* eq_constr extended with universe erasure *)
 
962
let rec constr_cmp cv_pb t1 t2 =
 
963
  (match kind_of_term t1, kind_of_term t2 with
 
964
      Sort s1, Sort s2 -> base_sort_cmp cv_pb s1 s2
 
965
    | _ -> false)
 
966
  || compare_constr (constr_cmp cv_pb) t1 t2
 
967
 
 
968
let eq_constr = constr_cmp Reduction.CONV
 
969
 
 
970
(* On reduit une serie d'eta-redex de tete ou rien du tout  *)
 
971
(* [x1:c1;...;xn:cn]@(f;a1...an;x1;...;xn) --> @(f;a1...an) *)
 
972
(* Remplace 2 versions pr�c�dentes bugg�es                  *)
 
973
 
 
974
let rec eta_reduce_head c =
 
975
  match kind_of_term c with
 
976
    | Lambda (_,c1,c') ->
 
977
        (match kind_of_term (eta_reduce_head c') with
 
978
           | App (f,cl) ->
 
979
               let lastn = (Array.length cl) - 1 in 
 
980
               if lastn < 1 then anomaly "application without arguments"
 
981
               else
 
982
                 (match kind_of_term cl.(lastn) with
 
983
                    | Rel 1 ->
 
984
                        let c' =
 
985
                          if lastn = 1 then f
 
986
                          else mkApp (f, Array.sub cl 0 lastn)
 
987
                        in
 
988
                        if noccurn 1 c'
 
989
                        then lift (-1) c'
 
990
                        else c
 
991
                    | _   -> c)
 
992
           | _ -> c)
 
993
    | _ -> c
 
994
 
 
995
 
 
996
(* alpha-eta conversion : ignore print names and casts *)
 
997
let eta_eq_constr =
 
998
  let rec aux t1 t2 =
 
999
    let t1 = eta_reduce_head (strip_head_cast t1)
 
1000
    and t2 = eta_reduce_head (strip_head_cast t2) in
 
1001
    t1=t2 or compare_constr aux t1 t2
 
1002
  in aux
 
1003
 
 
1004
 
 
1005
(* iterator on rel context *)
 
1006
let process_rel_context f env =
 
1007
  let sign = named_context_val env in
 
1008
  let rels = rel_context env in
 
1009
  let env0 = reset_with_named_context sign env in
 
1010
  Sign.fold_rel_context f rels ~init:env0
 
1011
 
 
1012
let assums_of_rel_context sign =
 
1013
  Sign.fold_rel_context
 
1014
    (fun (na,c,t) l ->
 
1015
      match c with
 
1016
          Some _ -> l
 
1017
        | None -> (na, t)::l)
 
1018
    sign ~init:[]
 
1019
 
 
1020
let fold_map_rel_context f env sign =
 
1021
  let rec aux env acc = function
 
1022
    | d::sign ->
 
1023
        aux (push_rel d env) (map_rel_declaration (f env) d :: acc) sign
 
1024
    | [] ->
 
1025
        acc
 
1026
  in
 
1027
  aux env [] (List.rev sign)
 
1028
 
 
1029
let map_rel_context_with_binders f sign =
 
1030
  let rec aux k = function
 
1031
    | d::sign -> map_rel_declaration (f k) d :: aux (k-1) sign
 
1032
    | [] -> []
 
1033
  in
 
1034
  aux (rel_context_length sign) sign
 
1035
 
 
1036
let substl_rel_context l =
 
1037
  map_rel_context_with_binders (fun k -> substnl l (k-1))
 
1038
 
 
1039
let lift_rel_context n =
 
1040
  map_rel_context_with_binders (liftn n)
 
1041
 
 
1042
let fold_named_context_both_sides f l ~init = list_fold_right_and_left f l init
 
1043
 
 
1044
let rec mem_named_context id = function
 
1045
  | (id',_,_) :: _ when id=id' -> true
 
1046
  | _ :: sign -> mem_named_context id sign
 
1047
  | [] -> false
 
1048
 
 
1049
let make_all_name_different env =
 
1050
  let avoid = ref (ids_of_named_context (named_context env)) in
 
1051
  process_rel_context
 
1052
    (fun (na,c,t) newenv -> 
 
1053
       let id = next_name_away na !avoid in
 
1054
       avoid := id::!avoid;
 
1055
       push_rel (Name id,c,t) newenv)
 
1056
    env
 
1057
 
 
1058
let global_vars env ids = Idset.elements (global_vars_set env ids)
 
1059
 
 
1060
let global_vars_set_of_decl env = function
 
1061
  | (_,None,t) -> global_vars_set env t
 
1062
  | (_,Some c,t) ->
 
1063
      Idset.union (global_vars_set env t)
 
1064
        (global_vars_set env c)
 
1065
 
 
1066
let dependency_closure env sign hyps =
 
1067
  if Idset.is_empty hyps then [] else
 
1068
    let (_,lh) =
 
1069
      Sign.fold_named_context_reverse
 
1070
        (fun (hs,hl) (x,_,_ as d) ->
 
1071
          if Idset.mem x hs then
 
1072
            (Idset.union (global_vars_set_of_decl env d) (Idset.remove x hs),
 
1073
            x::hl)
 
1074
          else (hs,hl))
 
1075
        ~init:(hyps,[])
 
1076
        sign in
 
1077
    List.rev lh
 
1078
 
 
1079
let default_x = id_of_string "x"
 
1080
 
 
1081
let rec next_name_away_in_cases_pattern id avoid =
 
1082
  let id = match id with Name id -> id | Anonymous -> default_x in
 
1083
  let rec next id =
 
1084
    if List.mem id avoid or is_constructor id then next (lift_ident id)
 
1085
    else id in
 
1086
  next id
 
1087
 
 
1088
(* Remark: Anonymous var may be dependent in Evar's contexts *)
 
1089
let concrete_name avoid_flags l env_names n c =
 
1090
  if n = Anonymous & noccurn 1 c then
 
1091
    (Anonymous,l)
 
1092
  else
 
1093
    let fresh_id = next_name_not_occuring avoid_flags n l env_names c in
 
1094
    let idopt = if noccurn 1 c then Anonymous else Name fresh_id in
 
1095
    (idopt, fresh_id::l)
 
1096
 
 
1097
let concrete_let_name avoid_flags l env_names n c =
 
1098
  let fresh_id = next_name_not_occuring avoid_flags n l env_names c in
 
1099
  (Name fresh_id, fresh_id::l)
 
1100
 
 
1101
let rec rename_bound_var env avoid c =
 
1102
  let env_names = names_of_rel_context env in
 
1103
  let rec rename avoid c =
 
1104
    match kind_of_term c with
 
1105
    | Prod (na,c1,c2)  ->
 
1106
        let na',avoid' = concrete_name None avoid env_names na c2 in
 
1107
        mkProd (na', c1, rename avoid' c2)
 
1108
    | LetIn (na,c1,t,c2) ->
 
1109
        let na',avoid' = concrete_let_name None avoid env_names na c2 in
 
1110
        mkLetIn (na',c1,t, rename avoid' c2)
 
1111
    | Cast (c,k,t) -> mkCast (rename avoid c, k,t)
 
1112
    | _ -> c
 
1113
  in
 
1114
  rename avoid c
 
1115
 
 
1116
(* Combinators on judgments *)
 
1117
 
 
1118
let on_judgment f j = { uj_val = f j.uj_val; uj_type = f j.uj_type }
 
1119
let on_judgment_value f j = { j with uj_val = f j.uj_val }
 
1120
let on_judgment_type f j = { j with uj_type = f j.uj_type }
 
1121
 
 
1122
(* Cut a context ctx in 2 parts (ctx1,ctx2) with ctx1 containing k 
 
1123
     variables *)
 
1124
let context_chop k ctx =
 
1125
  let rec chop_aux acc = function
 
1126
    | (0, l2) -> (List.rev acc, l2)
 
1127
    | (n, ((_,Some _,_ as h)::t)) -> chop_aux (h::acc) (n, t)
 
1128
    | (n, (h::t)) -> chop_aux (h::acc) (pred n, t)
 
1129
    | (_, []) -> anomaly "context_chop"
 
1130
  in chop_aux [] (k,ctx)
 
1131