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

« back to all changes in this revision

Viewing changes to pretyping/reductionops.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: reductionops.ml 11897 2009-02-09 19:28:02Z barras $ *)
 
10
 
 
11
open Pp
 
12
open Util
 
13
open Names
 
14
open Term
 
15
open Termops
 
16
open Univ
 
17
open Evd
 
18
open Declarations
 
19
open Environ
 
20
open Closure
 
21
open Esubst
 
22
open Reduction
 
23
 
 
24
exception Elimconst
 
25
 
 
26
 
 
27
(**********************************************************************)
 
28
(* The type of (machine) stacks (= lambda-bar-calculus' contexts)     *) 
 
29
 
 
30
type 'a stack_member =
 
31
  | Zapp of 'a list
 
32
  | Zcase of case_info * 'a * 'a array
 
33
  | Zfix of 'a * 'a stack
 
34
  | Zshift of int
 
35
  | Zupdate of 'a
 
36
 
 
37
and 'a stack = 'a stack_member list
 
38
 
 
39
let empty_stack = []
 
40
let append_stack_list l s =
 
41
  match (l,s) with
 
42
  | ([],s) -> s
 
43
  | (l1, Zapp l :: s) -> Zapp (l1@l) :: s
 
44
  | (l1, s) -> Zapp l1 :: s
 
45
let append_stack v s = append_stack_list (Array.to_list v) s
 
46
 
 
47
(* Collapse the shifts in the stack *)
 
48
let zshift n s =
 
49
  match (n,s) with
 
50
      (0,_) -> s
 
51
    | (_,Zshift(k)::s) -> Zshift(n+k)::s
 
52
    | _ -> Zshift(n)::s
 
53
 
 
54
let rec stack_args_size = function
 
55
  | Zapp l::s -> List.length l + stack_args_size s
 
56
  | Zshift(_)::s -> stack_args_size s
 
57
  | Zupdate(_)::s -> stack_args_size s
 
58
  | _ -> 0
 
59
 
 
60
(* When used as an argument stack (only Zapp can appear) *)
 
61
let rec decomp_stack = function
 
62
  | Zapp[v]::s -> Some (v, s)
 
63
  | Zapp(v::l)::s -> Some (v, (Zapp l :: s))
 
64
  | Zapp [] :: s -> decomp_stack s
 
65
  | _ -> None
 
66
let rec decomp_stackn = function
 
67
  | Zapp [] :: s -> decomp_stackn s
 
68
  | Zapp l :: s -> (Array.of_list l, s)
 
69
  | _ -> assert false
 
70
let array_of_stack s =
 
71
  let rec stackrec = function
 
72
  | [] -> []
 
73
  | Zapp args :: s -> args :: (stackrec s)
 
74
  | _ -> assert false
 
75
  in Array.of_list (List.concat (stackrec s))
 
76
let rec list_of_stack = function
 
77
  | [] -> []
 
78
  | Zapp args :: s -> args @ (list_of_stack s)
 
79
  | _ -> assert false
 
80
let rec app_stack = function
 
81
  | f, [] -> f
 
82
  | f, (Zapp [] :: s) -> app_stack (f, s)
 
83
  | f, (Zapp args :: s) -> 
 
84
      app_stack (applist (f, args), s)
 
85
  | _ -> assert false
 
86
let rec stack_assign s p c = match s with
 
87
  | Zapp args :: s ->
 
88
      let q = List.length args in 
 
89
      if p >= q then
 
90
        Zapp args :: stack_assign s (p-q) c
 
91
      else
 
92
        (match list_chop p args with
 
93
            (bef, _::aft) -> Zapp (bef@c::aft) :: s
 
94
          | _ -> assert false)
 
95
  | _ -> s
 
96
let rec stack_tail p s =
 
97
  if p = 0 then s else
 
98
    match s with
 
99
      | Zapp args :: s ->
 
100
          let q = List.length args in
 
101
          if p >= q then stack_tail (p-q) s
 
102
          else Zapp (list_skipn p args) :: s
 
103
      | _ -> failwith "stack_tail"
 
104
let rec stack_nth s p = match s with
 
105
  | Zapp args :: s ->
 
106
      let q = List.length args in
 
107
      if p >= q then stack_nth s (p-q)
 
108
      else List.nth args p
 
109
  | _ -> raise Not_found
 
110
 
 
111
(**************************************************************)
 
112
(* The type of (machine) states (= lambda-bar-calculus' cuts) *) 
 
113
type state = constr * constr stack
 
114
 
 
115
type  contextual_reduction_function = env ->  evar_map -> constr -> constr
 
116
type  reduction_function =  contextual_reduction_function
 
117
type local_reduction_function = evar_map -> constr -> constr
 
118
 
 
119
type  contextual_stack_reduction_function = 
 
120
    env ->  evar_map -> constr -> constr * constr list
 
121
type  stack_reduction_function =  contextual_stack_reduction_function
 
122
type local_stack_reduction_function =
 
123
    evar_map -> constr -> constr * constr list
 
124
 
 
125
type  contextual_state_reduction_function = 
 
126
    env ->  evar_map -> state -> state
 
127
type  state_reduction_function =  contextual_state_reduction_function
 
128
type local_state_reduction_function = evar_map -> state -> state
 
129
 
 
130
(*************************************)
 
131
(*** Reduction Functions Operators ***)
 
132
(*************************************)
 
133
 
 
134
let safe_evar_value sigma ev =
 
135
  try Some (Evd.existential_value sigma ev)
 
136
  with NotInstantiatedEvar | Not_found -> None
 
137
 
 
138
let rec whd_state sigma (x, stack as s) =
 
139
  match kind_of_term x with
 
140
    | App (f,cl) -> whd_state sigma (f, append_stack cl stack)
 
141
    | Cast (c,_,_)  -> whd_state sigma (c, stack)
 
142
    | Evar ev ->
 
143
        (match safe_evar_value sigma ev with
 
144
            Some c -> whd_state sigma (c,stack)
 
145
          | _ -> s)
 
146
    | _             -> s
 
147
 
 
148
let appterm_of_stack (f,s) = (f,list_of_stack s)
 
149
 
 
150
let whd_stack sigma x =
 
151
  appterm_of_stack (whd_state sigma (x, empty_stack))
 
152
let whd_castapp_stack = whd_stack
 
153
 
 
154
let stack_reduction_of_reduction red_fun env sigma s =
 
155
  let t = red_fun env sigma (app_stack s) in
 
156
  whd_stack t
 
157
 
 
158
let strong whdfun env sigma t = 
 
159
  let rec strongrec env t =
 
160
    map_constr_with_full_binders push_rel strongrec env (whdfun env sigma t) in
 
161
  strongrec env t
 
162
 
 
163
let local_strong whdfun sigma = 
 
164
  let rec strongrec t = map_constr strongrec (whdfun sigma t) in
 
165
  strongrec
 
166
 
 
167
let rec strong_prodspine redfun sigma c = 
 
168
  let x = redfun sigma c in
 
169
  match kind_of_term x with
 
170
    | Prod (na,a,b) -> mkProd (na,a,strong_prodspine redfun sigma b)
 
171
    | _ -> x
 
172
 
 
173
(*************************************)
 
174
(*** Reduction using bindingss ***)
 
175
(*************************************)
 
176
 
 
177
(* This signature is very similar to Closure.RedFlagsSig except there
 
178
   is eta but no per-constant unfolding *)
 
179
 
 
180
module type RedFlagsSig = sig
 
181
  type flags
 
182
  type flag
 
183
  val fbeta : flag
 
184
  val fdelta : flag
 
185
  val feta : flag
 
186
  val fiota : flag
 
187
  val fzeta : flag
 
188
  val mkflags : flag list -> flags
 
189
  val red_beta : flags -> bool
 
190
  val red_delta : flags -> bool
 
191
  val red_eta : flags -> bool
 
192
  val red_iota : flags -> bool
 
193
  val red_zeta : flags -> bool
 
194
end
 
195
 
 
196
(* Naive Implementation 
 
197
module RedFlags = (struct
 
198
  type flag = BETA | DELTA | EVAR | IOTA | ZETA | ETA
 
199
  type flags = flag list
 
200
  let fbeta = BETA 
 
201
  let fdelta = DELTA
 
202
  let fevar = EVAR
 
203
  let fiota = IOTA
 
204
  let fzeta = ZETA
 
205
  let feta = ETA
 
206
  let mkflags l = l
 
207
  let red_beta = List.mem BETA
 
208
  let red_delta = List.mem DELTA
 
209
  let red_evar = List.mem EVAR
 
210
  let red_eta = List.mem ETA
 
211
  let red_iota = List.mem IOTA
 
212
  let red_zeta = List.mem ZETA
 
213
end : RedFlagsSig)
 
214
*)
 
215
 
 
216
(* Compact Implementation *)
 
217
module RedFlags = (struct
 
218
  type flag = int
 
219
  type flags = int
 
220
  let fbeta = 1
 
221
  let fdelta = 2
 
222
  let feta = 8 
 
223
  let fiota = 16
 
224
  let fzeta = 32
 
225
  let mkflags = List.fold_left (lor) 0
 
226
  let red_beta f = f land fbeta <> 0
 
227
  let red_delta f = f land fdelta <> 0
 
228
  let red_eta f = f land feta <> 0
 
229
  let red_iota f = f land fiota <> 0
 
230
  let red_zeta f = f land fzeta <> 0
 
231
end : RedFlagsSig)
 
232
 
 
233
open RedFlags
 
234
 
 
235
(* Local *)
 
236
let beta = mkflags [fbeta]
 
237
let eta = mkflags [feta]
 
238
let betaiota = mkflags [fiota; fbeta]
 
239
let betaiotazeta = mkflags [fiota; fbeta;fzeta]
 
240
 
 
241
(* Contextual *)
 
242
let delta = mkflags [fdelta]
 
243
let betadelta = mkflags [fbeta;fdelta;fzeta]
 
244
let betadeltaeta = mkflags [fbeta;fdelta;fzeta;feta]
 
245
let betadeltaiota = mkflags [fbeta;fdelta;fzeta;fiota]
 
246
let betadeltaiota_nolet = mkflags [fbeta;fdelta;fiota]
 
247
let betadeltaiotaeta = mkflags [fbeta;fdelta;fzeta;fiota;feta]
 
248
let betaetalet = mkflags [fbeta;feta;fzeta]
 
249
let betalet = mkflags [fbeta;fzeta]
 
250
 
 
251
(* Beta Reduction tools *)
 
252
 
 
253
let rec stacklam recfun env t stack =
 
254
  match (decomp_stack stack,kind_of_term t) with
 
255
    | Some (h,stacktl), Lambda (_,_,c) -> stacklam recfun (h::env) c stacktl
 
256
    | _ -> recfun (substl env t, stack)
 
257
 
 
258
let beta_applist (c,l) =
 
259
  stacklam app_stack [] c (append_stack_list l empty_stack)
 
260
 
 
261
(* Iota reduction tools *)
 
262
 
 
263
type 'a miota_args = {
 
264
  mP      : constr;     (* the result type *)
 
265
  mconstr : constr;     (* the constructor *)
 
266
  mci     : case_info;  (* special info to re-build pattern *)
 
267
  mcargs  : 'a list;    (* the constructor's arguments *)
 
268
  mlf     : 'a array }  (* the branch code vector *)
 
269
 
 
270
let reducible_mind_case c = match kind_of_term c with
 
271
  | Construct _ | CoFix _ -> true
 
272
  | _  -> false
 
273
 
 
274
let contract_cofix (bodynum,(types,names,bodies as typedbodies)) =
 
275
  let nbodies = Array.length bodies in
 
276
  let make_Fi j = mkCoFix (nbodies-j-1,typedbodies) in
 
277
  substl (list_tabulate make_Fi nbodies) bodies.(bodynum)
 
278
 
 
279
let reduce_mind_case mia =
 
280
  match kind_of_term mia.mconstr with
 
281
    | Construct (ind_sp,i) ->
 
282
(*      let ncargs = (fst mia.mci).(i-1) in*)
 
283
        let real_cargs = list_skipn mia.mci.ci_npar mia.mcargs in
 
284
        applist (mia.mlf.(i-1),real_cargs)
 
285
    | CoFix cofix ->
 
286
        let cofix_def = contract_cofix cofix in
 
287
        mkCase (mia.mci, mia.mP, applist(cofix_def,mia.mcargs), mia.mlf)
 
288
    | _ -> assert false
 
289
 
 
290
(* contracts fix==FIX[nl;i](A1...Ak;[F1...Fk]{B1....Bk}) to produce
 
291
   Bi[Fj --> FIX[nl;j](A1...Ak;[F1...Fk]{B1...Bk})] *)
 
292
 
 
293
let contract_fix ((recindices,bodynum),(types,names,bodies as typedbodies)) =
 
294
  let nbodies = Array.length recindices in
 
295
  let make_Fi j = mkFix ((recindices,nbodies-j-1),typedbodies) in
 
296
  substl (list_tabulate make_Fi nbodies) bodies.(bodynum)
 
297
 
 
298
let fix_recarg ((recindices,bodynum),_) stack =
 
299
  assert (0 <= bodynum & bodynum < Array.length recindices);
 
300
  let recargnum = Array.get recindices bodynum in
 
301
  try 
 
302
    Some (recargnum, stack_nth stack recargnum)
 
303
  with Not_found ->
 
304
    None
 
305
 
 
306
type fix_reduction_result = NotReducible | Reduced of state
 
307
 
 
308
let reduce_fix whdfun sigma fix stack =
 
309
  match fix_recarg fix stack with
 
310
    | None -> NotReducible
 
311
    | Some (recargnum,recarg) ->
 
312
        let (recarg'hd,_ as recarg') = whdfun sigma (recarg, empty_stack) in
 
313
        let stack' = stack_assign stack recargnum (app_stack recarg') in
 
314
        (match kind_of_term recarg'hd with
 
315
           | Construct _ -> Reduced (contract_fix fix, stack')
 
316
           | _ -> NotReducible)
 
317
 
 
318
(* Generic reduction function *)
 
319
 
 
320
(* Y avait un commentaire pour whd_betadeltaiota :
 
321
 
 
322
   NB : Cette fonction alloue peu c'est l'appel 
 
323
     ``let (c,cargs) = whfun (recarg, empty_stack)''
 
324
                              -------------------
 
325
   qui coute cher *)
 
326
 
 
327
let rec whd_state_gen flags env sigma = 
 
328
  let rec whrec (x, stack as s) =
 
329
    match kind_of_term x with
 
330
      | Rel n when red_delta flags ->
 
331
          (match lookup_rel n env with
 
332
             | (_,Some body,_) -> whrec (lift n body, stack)
 
333
             | _ -> s)
 
334
      | Var id when red_delta flags ->
 
335
          (match lookup_named id env with
 
336
             | (_,Some body,_) -> whrec (body, stack)
 
337
             | _ -> s)
 
338
      | Evar ev ->
 
339
          (match safe_evar_value sigma ev with
 
340
             | Some body -> whrec (body, stack)
 
341
             | None -> s)
 
342
      | Const const when red_delta flags ->
 
343
          (match constant_opt_value env const with
 
344
             | Some  body -> whrec (body, stack)
 
345
             | None -> s)
 
346
      | LetIn (_,b,_,c) when red_zeta flags -> stacklam whrec [b] c stack
 
347
      | Cast (c,_,_) -> whrec (c, stack)
 
348
      | App (f,cl)  -> whrec (f, append_stack cl stack)
 
349
      | Lambda (na,t,c) ->
 
350
          (match decomp_stack stack with
 
351
             | Some (a,m) when red_beta flags -> stacklam whrec [a] c m
 
352
             | None when red_eta flags ->
 
353
                 let env' = push_rel (na,None,t) env in
 
354
                 let whrec' = whd_state_gen flags env' sigma in
 
355
                 (match kind_of_term (app_stack (whrec' (c, empty_stack))) with
 
356
                    | App (f,cl) ->
 
357
                        let napp = Array.length cl in
 
358
                        if napp > 0 then
 
359
                          let x', l' = whrec' (array_last cl, empty_stack) in
 
360
                          match kind_of_term x', decomp_stack l' with
 
361
                            | Rel 1, None ->
 
362
                                let lc = Array.sub cl 0 (napp-1) in
 
363
                                let u = if napp=1 then f else appvect (f,lc) in
 
364
                                if noccurn 1 u then (pop u,empty_stack) else s
 
365
                            | _ -> s
 
366
                        else s
 
367
                    | _ -> s)
 
368
             | _ -> s)
 
369
 
 
370
      | Case (ci,p,d,lf) when red_iota flags ->
 
371
          let (c,cargs) = whrec (d, empty_stack) in
 
372
          if reducible_mind_case c then
 
373
            whrec (reduce_mind_case
 
374
                     {mP=p; mconstr=c; mcargs=list_of_stack cargs;
 
375
                      mci=ci; mlf=lf}, stack)
 
376
          else 
 
377
            (mkCase (ci, p, app_stack (c,cargs), lf), stack)
 
378
            
 
379
      | Fix fix when red_iota flags ->
 
380
          (match reduce_fix (fun _ -> whrec) sigma fix stack with
 
381
             | Reduced s' -> whrec s'
 
382
             | NotReducible -> s)
 
383
 
 
384
      | x -> s
 
385
  in 
 
386
  whrec
 
387
 
 
388
let local_whd_state_gen flags sigma = 
 
389
  let rec whrec (x, stack as s) =
 
390
    match kind_of_term x with
 
391
      | LetIn (_,b,_,c) when red_zeta flags -> stacklam whrec [b] c stack
 
392
      | Cast (c,_,_) -> whrec (c, stack)
 
393
      | App (f,cl)  -> whrec (f, append_stack cl stack)
 
394
      | Lambda (_,_,c) ->
 
395
          (match decomp_stack stack with
 
396
             | Some (a,m) when red_beta flags -> stacklam whrec [a] c m
 
397
             | None when red_eta flags ->
 
398
                 (match kind_of_term (app_stack (whrec (c, empty_stack))) with 
 
399
                    | App (f,cl) ->
 
400
                        let napp = Array.length cl in
 
401
                        if napp > 0 then
 
402
                          let x', l' = whrec (array_last cl, empty_stack) in
 
403
                          match kind_of_term x', decomp_stack l' with
 
404
                            | Rel 1, None ->
 
405
                                let lc = Array.sub cl 0 (napp-1) in
 
406
                                let u = if napp=1 then f else appvect (f,lc) in
 
407
                                if noccurn 1 u then (pop u,empty_stack) else s
 
408
                            | _ -> s
 
409
                        else s
 
410
                    | _ -> s)
 
411
             | _ -> s)
 
412
 
 
413
      | Case (ci,p,d,lf) when red_iota flags ->
 
414
          let (c,cargs) = whrec (d, empty_stack) in
 
415
          if reducible_mind_case c then
 
416
            whrec (reduce_mind_case
 
417
                     {mP=p; mconstr=c; mcargs=list_of_stack cargs;
 
418
                      mci=ci; mlf=lf}, stack)
 
419
          else 
 
420
            (mkCase (ci, p, app_stack (c,cargs), lf), stack)
 
421
            
 
422
      | Fix fix when red_iota flags ->
 
423
          (match reduce_fix (fun _ ->whrec) sigma fix stack with
 
424
             | Reduced s' -> whrec s'
 
425
             | NotReducible -> s)
 
426
 
 
427
      | Evar ev ->
 
428
          (match safe_evar_value sigma ev with
 
429
              Some c -> whrec (c,stack)
 
430
            | None -> s)
 
431
 
 
432
      | x -> s
 
433
  in 
 
434
  whrec
 
435
 
 
436
 
 
437
let stack_red_of_state_red f sigma x =
 
438
  appterm_of_stack (f sigma (x, empty_stack))
 
439
 
 
440
let red_of_state_red f sigma x =
 
441
  app_stack (f sigma (x,empty_stack))
 
442
 
 
443
(* 1. Beta Reduction Functions *)
 
444
 
 
445
let whd_beta_state = local_whd_state_gen beta
 
446
let whd_beta_stack = stack_red_of_state_red whd_beta_state
 
447
let whd_beta = red_of_state_red whd_beta_state
 
448
 
 
449
(* Nouveau ! *)
 
450
let whd_betaetalet_state = local_whd_state_gen betaetalet
 
451
let whd_betaetalet_stack = stack_red_of_state_red whd_betaetalet_state
 
452
let whd_betaetalet = red_of_state_red whd_betaetalet_state
 
453
 
 
454
let whd_betalet_state = local_whd_state_gen betalet
 
455
let whd_betalet_stack = stack_red_of_state_red whd_betalet_state
 
456
let whd_betalet = red_of_state_red whd_betalet_state
 
457
 
 
458
(* 2. Delta Reduction Functions *)
 
459
 
 
460
let whd_delta_state e = whd_state_gen delta e
 
461
let whd_delta_stack env = stack_red_of_state_red (whd_delta_state env)
 
462
let whd_delta env = red_of_state_red  (whd_delta_state env)
 
463
 
 
464
let whd_betadelta_state e = whd_state_gen betadelta e
 
465
let whd_betadelta_stack env =
 
466
  stack_red_of_state_red (whd_betadelta_state env)
 
467
let whd_betadelta env =
 
468
  red_of_state_red (whd_betadelta_state env)
 
469
 
 
470
 
 
471
let whd_betadeltaeta_state e = whd_state_gen betadeltaeta e
 
472
let whd_betadeltaeta_stack env =
 
473
  stack_red_of_state_red (whd_betadeltaeta_state env)
 
474
let whd_betadeltaeta env = 
 
475
  red_of_state_red (whd_betadeltaeta_state env)
 
476
 
 
477
(* 3. Iota reduction Functions *)
 
478
 
 
479
let whd_betaiota_state = local_whd_state_gen betaiota
 
480
let whd_betaiota_stack = stack_red_of_state_red whd_betaiota_state
 
481
let whd_betaiota = red_of_state_red whd_betaiota_state
 
482
 
 
483
let whd_betaiotazeta_state = local_whd_state_gen betaiotazeta
 
484
let whd_betaiotazeta_stack = stack_red_of_state_red whd_betaiotazeta_state
 
485
let whd_betaiotazeta = red_of_state_red whd_betaiotazeta_state
 
486
 
 
487
let whd_betadeltaiota_state e = whd_state_gen betadeltaiota e
 
488
let whd_betadeltaiota_stack env =
 
489
  stack_red_of_state_red (whd_betadeltaiota_state env)
 
490
let whd_betadeltaiota env = 
 
491
  red_of_state_red (whd_betadeltaiota_state env)
 
492
 
 
493
let whd_betadeltaiotaeta_state e = whd_state_gen betadeltaiotaeta e
 
494
let whd_betadeltaiotaeta_stack env =
 
495
  stack_red_of_state_red (whd_betadeltaiotaeta_state env)
 
496
let whd_betadeltaiotaeta env = 
 
497
  red_of_state_red (whd_betadeltaiotaeta_state env)
 
498
 
 
499
let whd_betadeltaiota_nolet_state e = whd_state_gen betadeltaiota_nolet e
 
500
let whd_betadeltaiota_nolet_stack env =
 
501
  stack_red_of_state_red (whd_betadeltaiota_nolet_state env)
 
502
let whd_betadeltaiota_nolet env = 
 
503
  red_of_state_red (whd_betadeltaiota_nolet_state env)
 
504
 
 
505
(* 3. Eta reduction Functions *)
 
506
 
 
507
let whd_eta c = app_stack (local_whd_state_gen eta Evd.empty (c,empty_stack))
 
508
 
 
509
(****************************************************************************)
 
510
(*                   Reduction Functions                                    *)
 
511
(****************************************************************************)
 
512
 
 
513
(* Replacing defined evars for error messages *)
 
514
let rec whd_evar sigma c =
 
515
  match kind_of_term c with
 
516
    | Evar ev ->
 
517
        (match safe_evar_value sigma ev with
 
518
            Some c -> whd_evar sigma c
 
519
          | None -> c)
 
520
    | Sort s when is_sort_variable sigma s -> whd_sort_variable sigma c
 
521
    | _ -> collapse_appl c
 
522
 
 
523
let nf_evar =
 
524
  local_strong whd_evar
 
525
 
 
526
(* lazy reduction functions. The infos must be created for each term *)
 
527
(* Note by HH [oct 08] : why would it be the job of clos_norm_flags to add
 
528
   a [nf_evar] here *)
 
529
let clos_norm_flags flgs env sigma t =
 
530
  norm_val
 
531
    (create_clos_infos ~evars:(safe_evar_value sigma) flgs env)
 
532
    (inject t)
 
533
 
 
534
let nf_beta = clos_norm_flags Closure.beta empty_env
 
535
let nf_betaiota = clos_norm_flags Closure.betaiota empty_env
 
536
let nf_betadeltaiota env sigma =
 
537
  clos_norm_flags Closure.betadeltaiota env sigma
 
538
 
 
539
 
 
540
(* Attention reduire un beta-redexe avec un argument qui n'est pas 
 
541
   une variable, peut changer enormement le temps de conversion lors
 
542
   du type checking :
 
543
     (fun x => x + x) M
 
544
*)
 
545
let rec whd_betaiota_preserving_vm_cast env sigma t =    
 
546
   let rec stacklam_var subst t stack =          
 
547
     match (decomp_stack stack,kind_of_term t) with      
 
548
     | Some (h,stacktl), Lambda (_,_,c) ->       
 
549
         begin match kind_of_term h with         
 
550
         | Rel i when not (evaluable_rel i env) ->       
 
551
             stacklam_var (h::subst) c stacktl   
 
552
         | Var id when  not (evaluable_named id env)->   
 
553
             stacklam_var (h::subst) c stacktl   
 
554
         | _ -> whrec (substl subst t, stack)    
 
555
         end     
 
556
     | _ -> whrec (substl subst t, stack)        
 
557
   and whrec (x, stack as s) =   
 
558
     match kind_of_term x with   
 
559
       | Evar ev ->      
 
560
           (match safe_evar_value sigma ev with          
 
561
              | Some body -> whrec (body, stack)         
 
562
              | None -> s)       
 
563
       | Cast (c,VMcast,t) ->    
 
564
           let c = app_stack (whrec (c,empty_stack)) in          
 
565
           let t = app_stack (whrec (t,empty_stack)) in          
 
566
           (mkCast(c,VMcast,t),stack)    
 
567
       | Cast (c,DEFAULTcast,_) ->       
 
568
           whrec (c, stack)      
 
569
       | App (f,cl)  -> whrec (f, append_stack cl stack)         
 
570
       | Lambda (na,t,c) ->      
 
571
           (match decomp_stack stack with        
 
572
            | Some (a,m) -> stacklam_var [a] c m         
 
573
            | _ -> s)    
 
574
       | Case (ci,p,d,lf) ->     
 
575
           let (c,cargs) = whrec (d, empty_stack) in     
 
576
           if reducible_mind_case c then         
 
577
             whrec (reduce_mind_case     
 
578
                      {mP=p; mconstr=c; mcargs=list_of_stack cargs;      
 
579
                       mci=ci; mlf=lf}, stack)   
 
580
           else          
 
581
             (mkCase (ci, p, app_stack (c,cargs), lf), stack)    
 
582
       | x -> s          
 
583
   in    
 
584
   app_stack (whrec (t,empty_stack))
 
585
 
 
586
let nf_betaiota_preserving_vm_cast = 
 
587
  strong whd_betaiota_preserving_vm_cast
 
588
 
 
589
(* lazy weak head reduction functions *)
 
590
let whd_flags flgs env sigma t =
 
591
  whd_val
 
592
    (create_clos_infos ~evars:(safe_evar_value sigma) flgs env)
 
593
    (inject t)
 
594
 
 
595
(********************************************************************)
 
596
(*                         Conversion                               *)
 
597
(********************************************************************)
 
598
(*
 
599
let fkey = Profile.declare_profile "fhnf";;
 
600
let fhnf info v = Profile.profile2 fkey fhnf info v;;
 
601
 
 
602
let fakey = Profile.declare_profile "fhnf_apply";;
 
603
let fhnf_apply info k h a = Profile.profile4 fakey fhnf_apply info k h a;;
 
604
*)
 
605
 
 
606
let is_transparent k =
 
607
  Conv_oracle.get_strategy k <> Conv_oracle.Opaque
 
608
 
 
609
(* Conversion utility functions *)
 
610
 
 
611
type conversion_test = constraints -> constraints
 
612
 
 
613
let pb_is_equal pb = pb = CONV
 
614
 
 
615
let pb_equal = function
 
616
  | CUMUL -> CONV
 
617
  | CONV -> CONV
 
618
 
 
619
let sort_cmp = sort_cmp
 
620
 
 
621
let test_conversion (f:?evars:'a->'b) env sigma x y =
 
622
  try let _ =
 
623
    f ~evars:(safe_evar_value sigma) env x y in true
 
624
  with NotConvertible -> false
 
625
 
 
626
let is_conv env sigma = test_conversion Reduction.conv env sigma
 
627
let is_conv_leq env sigma = test_conversion Reduction.conv_leq env sigma
 
628
let is_fconv = function | CONV -> is_conv | CUMUL -> is_conv_leq
 
629
 
 
630
let test_trans_conversion f reds env sigma x y =
 
631
  try let _ = f reds env (nf_evar sigma x) (nf_evar sigma y) in true
 
632
  with NotConvertible -> false
 
633
 
 
634
let is_trans_conv env sigma = test_trans_conversion Reduction.trans_conv env sigma
 
635
let is_trans_conv_leq env sigma = test_trans_conversion Reduction.trans_conv_leq env sigma
 
636
let is_trans_fconv = function | CONV -> is_trans_conv | CUMUL -> is_trans_conv_leq
 
637
 
 
638
(********************************************************************)
 
639
(*             Special-Purpose Reduction                            *)
 
640
(********************************************************************)
 
641
 
 
642
let whd_meta metamap c = match kind_of_term c with
 
643
  | Meta p -> (try List.assoc p metamap with Not_found -> c)
 
644
  | _ -> c
 
645
 
 
646
(* Try to replace all metas. Does not replace metas in the metas' values
 
647
 * Differs from (strong whd_meta). *)
 
648
let plain_instance s c = 
 
649
  let rec irec n u = match kind_of_term u with
 
650
    | Meta p -> (try lift n (List.assoc p s) with Not_found -> u)
 
651
    | App (f,l) when isCast f ->
 
652
        let (f,_,t) = destCast f in
 
653
        let l' = Array.map (irec n) l in 
 
654
        (match kind_of_term f with
 
655
        | Meta p ->
 
656
            (* Don't flatten application nodes: this is used to extract a
 
657
               proof-term from a proof-tree and we want to keep the structure
 
658
               of the proof-tree *)
 
659
            (try let g = List.assoc p s in
 
660
            match kind_of_term g with
 
661
            | App _ -> 
 
662
                let h = id_of_string "H" in
 
663
                mkLetIn (Name h,g,t,mkApp(mkRel 1,Array.map (lift 1) l'))
 
664
            | _ -> mkApp (g,l')
 
665
            with Not_found -> mkApp (f,l'))
 
666
        | _ -> mkApp (irec n f,l'))     
 
667
    | Cast (m,_,_) when isMeta m ->
 
668
        (try lift n (List.assoc (destMeta m) s) with Not_found -> u)
 
669
    | _ ->
 
670
        map_constr_with_binders succ irec n u
 
671
  in 
 
672
  if s = [] then c else irec 0 c
 
673
 
 
674
(* [instance] is used for [res_pf]; the call to [local_strong whd_betaiota]
 
675
   has (unfortunately) different subtle side effects: 
 
676
 
 
677
   - ** Order of subgoals **
 
678
     If the lemma is a case analysis with parameters, it will move the
 
679
     parameters as first subgoals (e.g. "case H" applied on
 
680
     "H:D->A/\B|-C" will present the subgoal |-D first while w/o
 
681
     betaiota the subgoal |-D would have come last).
 
682
 
 
683
   - ** Betaiota-contraction in statement **
 
684
     If the lemma has a parameter which is a function and this
 
685
     function is applied in the lemma, then the _strong_ betaiota will
 
686
     contract the application of the function to its argument (e.g.
 
687
     "apply (H (fun x => x))" in "H:forall f, f 0 = 0 |- 0=0" will
 
688
     result in applying the lemma 0=0 in which "(fun x => x) 0" has
 
689
     been contracted). A goal to rewrite may then fail or succeed
 
690
     differently.
 
691
 
 
692
   - ** Naming of hypotheses ** 
 
693
     If a lemma is a function of the form "fun H:(forall a:A, P a)
 
694
     => .. F H .." where the expected type of H is "forall b:A, P b",
 
695
     then, without reduction, the application of the lemma will
 
696
     generate a subgoal "forall a:A, P a" (and intro will use name
 
697
     "a"), while with reduction, it will generate a subgoal "forall
 
698
     b:A, P b" (and intro will use name "b").
 
699
 
 
700
   - ** First-order pattern-matching **
 
701
     If a lemma has the type "(fun x => p) t" then rewriting t may fail
 
702
     if the type of the lemma is first beta-reduced (this typically happens
 
703
     when rewriting a single variable and the type of the lemma is obtained
 
704
     by meta_instance (with empty map) which itself calls instance with this
 
705
     empty map).
 
706
 *)
 
707
 
 
708
let instance s c =
 
709
  (* if s = [] then c else *)
 
710
  local_strong whd_betaiota Evd.empty (plain_instance s c)
 
711
 
 
712
(* pseudo-reduction rule:
 
713
 * [hnf_prod_app env s (Prod(_,B)) N --> B[N]
 
714
 * with an HNF on the first argument to produce a product.
 
715
 * if this does not work, then we use the string S as part of our
 
716
 * error message. *)
 
717
 
 
718
let hnf_prod_app env sigma t n =
 
719
  match kind_of_term (whd_betadeltaiota env sigma t) with
 
720
    | Prod (_,_,b) -> subst1 n b
 
721
    | _ -> anomaly "hnf_prod_app: Need a product"
 
722
 
 
723
let hnf_prod_appvect env sigma t nl = 
 
724
  Array.fold_left (hnf_prod_app env sigma) t nl
 
725
 
 
726
let hnf_prod_applist env sigma t nl = 
 
727
  List.fold_left (hnf_prod_app env sigma) t nl
 
728
                                    
 
729
let hnf_lam_app env sigma t n =
 
730
  match kind_of_term (whd_betadeltaiota env sigma t) with
 
731
    | Lambda (_,_,b) -> subst1 n b
 
732
    | _ -> anomaly "hnf_lam_app: Need an abstraction"
 
733
 
 
734
let hnf_lam_appvect env sigma t nl = 
 
735
  Array.fold_left (hnf_lam_app env sigma) t nl
 
736
 
 
737
let hnf_lam_applist env sigma t nl = 
 
738
  List.fold_left (hnf_lam_app env sigma) t nl
 
739
 
 
740
let splay_prod env sigma = 
 
741
  let rec decrec env m c =
 
742
    let t = whd_betadeltaiota env sigma c in
 
743
    match kind_of_term t with
 
744
      | Prod (n,a,c0) ->
 
745
          decrec (push_rel (n,None,a) env)
 
746
            ((n,a)::m) c0
 
747
      | _ -> m,t
 
748
  in 
 
749
  decrec env []
 
750
 
 
751
let splay_lambda env sigma = 
 
752
  let rec decrec env m c =
 
753
    let t = whd_betadeltaiota env sigma c in
 
754
    match kind_of_term t with
 
755
      | Lambda (n,a,c0) ->
 
756
          decrec (push_rel (n,None,a) env)
 
757
            ((n,a)::m) c0
 
758
      | _ -> m,t
 
759
  in 
 
760
  decrec env []
 
761
 
 
762
let splay_prod_assum env sigma = 
 
763
  let rec prodec_rec env l c =
 
764
    let t = whd_betadeltaiota_nolet env sigma c in
 
765
    match kind_of_term t with
 
766
    | Prod (x,t,c)  ->
 
767
        prodec_rec (push_rel (x,None,t) env)
 
768
          (Sign.add_rel_decl (x, None, t) l) c
 
769
    | LetIn (x,b,t,c) ->
 
770
        prodec_rec (push_rel (x, Some b, t) env)
 
771
          (Sign.add_rel_decl (x, Some b, t) l) c
 
772
    | Cast (c,_,_)    -> prodec_rec env l c
 
773
    | _               -> l,t
 
774
  in
 
775
  prodec_rec env Sign.empty_rel_context
 
776
 
 
777
let splay_arity env sigma c =
 
778
  let l, c = splay_prod env sigma c in
 
779
  match kind_of_term c with
 
780
    | Sort s -> l,s
 
781
    | _ -> invalid_arg "splay_arity"
 
782
 
 
783
let sort_of_arity env c = snd (splay_arity env Evd.empty c)
 
784
 
 
785
let decomp_n_prod env sigma n = 
 
786
  let rec decrec env m ln c = if m = 0 then (ln,c) else 
 
787
    match kind_of_term (whd_betadeltaiota env sigma c) with
 
788
      | Prod (n,a,c0) ->
 
789
          decrec (push_rel (n,None,a) env)
 
790
            (m-1) (Sign.add_rel_decl (n,None,a) ln) c0
 
791
      | _                      -> invalid_arg "decomp_n_prod"
 
792
  in 
 
793
  decrec env n Sign.empty_rel_context
 
794
 
 
795
exception NotASort
 
796
 
 
797
let decomp_sort env sigma t =
 
798
  match kind_of_term (whd_betadeltaiota env sigma t) with
 
799
  | Sort s -> s
 
800
  | _ -> raise NotASort
 
801
 
 
802
let is_sort env sigma arity =
 
803
  try let _ = decomp_sort env sigma arity in true 
 
804
  with NotASort -> false
 
805
 
 
806
(* reduction to head-normal-form allowing delta/zeta only in argument
 
807
   of case/fix (heuristic used by evar_conv) *)
 
808
 
 
809
let whd_betaiota_deltazeta_for_iota_state env sigma s =
 
810
  let rec whrec s = 
 
811
    let (t, stack as s) = whd_betaiota_state sigma s in
 
812
    match kind_of_term t with
 
813
    | Case (ci,p,d,lf) ->
 
814
        let (cr,crargs) = whd_betadeltaiota_stack env sigma d in
 
815
        let rslt = mkCase (ci, p, applist (cr,crargs), lf) in
 
816
        if reducible_mind_case cr then 
 
817
          whrec (rslt, stack)
 
818
        else 
 
819
          s
 
820
    | Fix fix ->
 
821
          (match reduce_fix (whd_betadeltaiota_state env) sigma fix stack with
 
822
             | Reduced s -> whrec s
 
823
             | NotReducible -> s)
 
824
    | _ -> s
 
825
  in whrec s
 
826
 
 
827
(* A reduction function like whd_betaiota but which keeps casts
 
828
 * and does not reduce redexes containing existential variables.
 
829
 * Used in Correctness.
 
830
 * Added by JCF, 29/1/98. *)
 
831
 
 
832
let whd_programs_stack env sigma = 
 
833
  let rec whrec (x, stack as s) =
 
834
    match kind_of_term x with
 
835
      | App (f,cl) ->
 
836
          let n = Array.length cl - 1 in
 
837
          let c = cl.(n) in
 
838
          if occur_existential c then 
 
839
            s 
 
840
          else 
 
841
            whrec (mkApp (f, Array.sub cl 0 n), append_stack [|c|] stack)
 
842
      | LetIn (_,b,_,c) ->
 
843
          if occur_existential b then
 
844
            s
 
845
          else
 
846
            stacklam whrec [b] c stack
 
847
      | Lambda (_,_,c) ->
 
848
          (match decomp_stack stack with
 
849
             | None -> s
 
850
             | Some (a,m) -> stacklam whrec [a] c m)
 
851
      | Case (ci,p,d,lf) ->
 
852
          if occur_existential d then
 
853
            s
 
854
          else
 
855
            let (c,cargs) = whrec (d, empty_stack) in
 
856
            if reducible_mind_case c then
 
857
              whrec (reduce_mind_case
 
858
                       {mP=p; mconstr=c; mcargs=list_of_stack cargs;
 
859
                        mci=ci; mlf=lf}, stack)
 
860
            else
 
861
              (mkCase (ci, p, app_stack(c,cargs), lf), stack)
 
862
      | Fix fix ->
 
863
          (match reduce_fix (fun _ ->whrec) sigma  fix stack with
 
864
             | Reduced s' -> whrec s'
 
865
             | NotReducible -> s)
 
866
      | _ -> s
 
867
  in 
 
868
  whrec
 
869
 
 
870
let whd_programs env sigma x =
 
871
  app_stack (whd_programs_stack env sigma (x, empty_stack))
 
872
 
 
873
exception IsType
 
874
 
 
875
let find_conclusion env sigma =
 
876
  let rec decrec env c =
 
877
    let t = whd_betadeltaiota env sigma c in
 
878
    match kind_of_term t with
 
879
      | Prod (x,t,c0) -> decrec (push_rel (x,None,t) env) c0
 
880
      | Lambda (x,t,c0) -> decrec (push_rel (x,None,t) env) c0
 
881
      | t -> t
 
882
  in 
 
883
  decrec env
 
884
 
 
885
let is_arity env sigma c =
 
886
  match find_conclusion env sigma c with
 
887
    | Sort _ -> true
 
888
    | _ -> false
 
889
 
 
890
(*************************************)
 
891
(* Metas *)
 
892
 
 
893
let meta_value evd mv = 
 
894
  let rec valrec mv =
 
895
    match meta_opt_fvalue evd mv with
 
896
    | Some (b,_) -> 
 
897
      instance
 
898
        (List.map (fun mv' -> (mv',valrec mv')) (Metaset.elements b.freemetas))
 
899
        b.rebus
 
900
    | None -> mkMeta mv
 
901
  in 
 
902
  valrec mv
 
903
 
 
904
let meta_instance env b =
 
905
  let c_sigma =
 
906
    List.map 
 
907
      (fun mv -> (mv,meta_value env mv)) (Metaset.elements b.freemetas)
 
908
  in 
 
909
  if c_sigma = [] then b.rebus else instance c_sigma b.rebus
 
910
 
 
911
let nf_meta env c = meta_instance env (mk_freelisted c)
 
912
 
 
913
(* Instantiate metas that create beta/iota redexes *)
 
914
 
 
915
let meta_value evd mv = 
 
916
  let rec valrec mv =
 
917
    match meta_opt_fvalue evd mv with
 
918
    | Some (b,_) ->
 
919
      instance
 
920
        (List.map (fun mv' -> (mv',valrec mv')) (Metaset.elements b.freemetas))
 
921
        b.rebus
 
922
    | None -> mkMeta mv
 
923
  in 
 
924
  valrec mv
 
925
 
 
926
let meta_reducible_instance evd b =
 
927
  let fm = Metaset.elements b.freemetas in
 
928
  let metas = List.fold_left (fun l mv -> 
 
929
    match (try meta_opt_fvalue evd mv with Not_found -> None) with
 
930
    | Some (g,(_,s)) -> (mv,(g.rebus,s))::l 
 
931
    | None -> l) [] fm in
 
932
  let rec irec u =
 
933
    let u = whd_betaiota Evd.empty u in
 
934
    match kind_of_term u with
 
935
    | Case (ci,p,c,bl) when isMeta c or isCast c & isMeta (pi1 (destCast c)) ->
 
936
        let m = try destMeta c with _ -> destMeta (pi1 (destCast c)) in
 
937
        (match
 
938
          try
 
939
            let g,s = List.assoc m metas in
 
940
            if isConstruct g or s <> CoerceToType then Some g else None
 
941
          with Not_found -> None
 
942
          with
 
943
            | Some g -> irec (mkCase (ci,p,g,bl))
 
944
            | None -> mkCase (ci,irec p,c,Array.map irec bl))
 
945
    | App (f,l) when isMeta f or isCast f & isMeta (pi1 (destCast f)) ->
 
946
        let m = try destMeta f with _ -> destMeta (pi1 (destCast f)) in
 
947
        (match
 
948
          try
 
949
            let g,s = List.assoc m metas in
 
950
            if isLambda g or s <> CoerceToType then Some g else None
 
951
          with Not_found -> None
 
952
         with
 
953
           | Some g -> irec (mkApp (g,l))
 
954
           | None -> mkApp (f,Array.map irec l))
 
955
    | Meta m ->
 
956
        (try let g,s = List.assoc m metas in if s<>CoerceToType then irec g else u
 
957
         with Not_found -> u)
 
958
    | _ -> map_constr irec u
 
959
  in 
 
960
  if fm = [] then (* nf_betaiota? *) b.rebus else irec b.rebus