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

« back to all changes in this revision

Viewing changes to pretyping/detyping.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: detyping.ml 11309 2008-08-06 10:30:35Z herbelin $ *)
 
10
 
 
11
open Pp
 
12
open Util
 
13
open Univ
 
14
open Names
 
15
open Term
 
16
open Declarations
 
17
open Inductive
 
18
open Inductiveops
 
19
open Environ
 
20
open Sign
 
21
open Rawterm
 
22
open Nameops
 
23
open Termops
 
24
open Libnames
 
25
open Nametab
 
26
open Evd
 
27
open Mod_subst
 
28
 
 
29
let dl = dummy_loc
 
30
 
 
31
(****************************************************************************)
 
32
(* Tools for printing of Cases                                              *)
 
33
 
 
34
let encode_inductive r =
 
35
  let indsp = inductive_of_reference r in
 
36
  let constr_lengths = mis_constr_nargs indsp in
 
37
  (indsp,constr_lengths)
 
38
 
 
39
(* Parameterization of the translation from constr to ast      *)
 
40
 
 
41
(* Tables for Cases printing under a "if" form, a "let" form,  *)
 
42
 
 
43
let has_two_constructors lc =
 
44
  Array.length lc = 2 (* & lc.(0) = 0 & lc.(1) = 0 *)
 
45
 
 
46
let isomorphic_to_tuple lc = (Array.length lc = 1)
 
47
 
 
48
let encode_bool r =
 
49
  let (_,lc as x) = encode_inductive r in
 
50
  if not (has_two_constructors lc) then
 
51
    user_err_loc (loc_of_reference r,"encode_if",
 
52
      str "This type has not exactly two constructors.");
 
53
  x
 
54
 
 
55
let encode_tuple r =
 
56
  let (_,lc as x) = encode_inductive r in
 
57
  if not (isomorphic_to_tuple lc) then
 
58
    user_err_loc (loc_of_reference r,"encode_tuple",
 
59
      str "This type cannot be seen as a tuple type.");
 
60
  x
 
61
 
 
62
module PrintingCasesMake =
 
63
  functor (Test : sig 
 
64
     val encode : reference -> inductive * int array
 
65
     val member_message : std_ppcmds -> bool -> std_ppcmds
 
66
     val field : string
 
67
     val title : string
 
68
  end) ->
 
69
  struct
 
70
    type t = inductive * int array
 
71
    let encode = Test.encode
 
72
    let subst subst ((kn,i), ints as obj) =
 
73
      let kn' = subst_kn subst kn in
 
74
        if kn' == kn then obj else
 
75
          (kn',i), ints
 
76
    let printer (ind,_) = pr_global_env Idset.empty (IndRef ind)
 
77
    let key = Goptions.SecondaryTable ("Printing",Test.field)
 
78
    let title = Test.title
 
79
    let member_message x = Test.member_message (printer x)
 
80
    let synchronous = true
 
81
  end
 
82
 
 
83
module PrintingCasesIf =
 
84
  PrintingCasesMake (struct 
 
85
    let encode = encode_bool
 
86
    let field = "If"
 
87
    let title = "Types leading to pretty-printing of Cases using a `if' form: "
 
88
    let member_message s b =
 
89
      str "Cases on elements of " ++ s ++ 
 
90
      str
 
91
        (if b then " are printed using a `if' form"
 
92
         else " are not printed using a `if' form")
 
93
  end)
 
94
 
 
95
module PrintingCasesLet =
 
96
  PrintingCasesMake (struct 
 
97
    let encode = encode_tuple
 
98
    let field = "Let"
 
99
    let title = 
 
100
      "Types leading to a pretty-printing of Cases using a `let' form:"
 
101
    let member_message s b =
 
102
      str "Cases on elements of " ++ s ++
 
103
      str
 
104
        (if b then " are printed using a `let' form"
 
105
         else " are not printed using a `let' form")
 
106
  end)
 
107
 
 
108
module PrintingIf  = Goptions.MakeRefTable(PrintingCasesIf)
 
109
module PrintingLet = Goptions.MakeRefTable(PrintingCasesLet)
 
110
 
 
111
(* Flags.for printing or not wildcard and synthetisable types *)
 
112
 
 
113
open Goptions
 
114
 
 
115
let wildcard_value = ref true
 
116
let force_wildcard () = !wildcard_value
 
117
 
 
118
let _ = declare_bool_option 
 
119
          { optsync  = true;
 
120
            optname  = "forced wildcard";
 
121
            optkey   = SecondaryTable ("Printing","Wildcard");
 
122
            optread  = force_wildcard;
 
123
            optwrite = (:=) wildcard_value }
 
124
 
 
125
let synth_type_value = ref true
 
126
let synthetize_type () = !synth_type_value
 
127
 
 
128
let _ = declare_bool_option 
 
129
          { optsync  = true;
 
130
            optname  = "pattern matching return type synthesizability";
 
131
            optkey   = SecondaryTable ("Printing","Synth");
 
132
            optread  = synthetize_type;
 
133
            optwrite = (:=) synth_type_value }
 
134
 
 
135
let reverse_matching_value = ref true
 
136
let reverse_matching () = !reverse_matching_value
 
137
 
 
138
let _ = declare_bool_option 
 
139
          { optsync  = true;
 
140
            optname  = "pattern-matching reversibility";
 
141
            optkey   = SecondaryTable ("Printing","Matching");
 
142
            optread  = reverse_matching;
 
143
            optwrite = (:=) reverse_matching_value }
 
144
 
 
145
(* Auxiliary function for MutCase printing *)
 
146
(* [computable] tries to tell if the predicate typing the result is inferable*)
 
147
 
 
148
let computable p k =
 
149
    (* We first remove as many lambda as the arity, then we look
 
150
       if it remains a lambda for a dependent elimination. This function
 
151
       works for normal eta-expanded term. For non eta-expanded or
 
152
       non-normal terms, it may affirm the pred is synthetisable
 
153
       because of an undetected ultimate dependent variable in the second
 
154
       clause, or else, it may affirms the pred non synthetisable
 
155
       because of a non normal term in the fourth clause.
 
156
       A solution could be to store, in the MutCase, the eta-expanded
 
157
       normal form of pred to decide if it depends on its variables
 
158
 
 
159
       Lorsque le pr�dicat est d�pendant de mani�re certaine, on
 
160
       ne d�clare pas le pr�dicat synth�tisable (m�me si la
 
161
       variable d�pendante ne l'est pas effectivement) parce que
 
162
       sinon on perd la r�ciprocit� de la synth�se (qui, lui,
 
163
       engendrera un pr�dicat non d�pendant) *)
 
164
 
 
165
  (nb_lam p = k+1)
 
166
  &&
 
167
  let _,ccl = decompose_lam p in 
 
168
  noccur_between 1 (k+1) ccl
 
169
 
 
170
let avoid_flag isgoal = if isgoal then Some true else None
 
171
 
 
172
let lookup_name_as_renamed env t s =
 
173
  let rec lookup avoid env_names n c = match kind_of_term c with
 
174
    | Prod (name,_,c') ->
 
175
        (match concrete_name (Some true) avoid env_names name c' with
 
176
           | (Name id,avoid') -> 
 
177
               if id=s then (Some n) 
 
178
               else lookup avoid' (add_name (Name id) env_names) (n+1) c'
 
179
           | (Anonymous,avoid')    -> lookup avoid' env_names (n+1) (pop c'))
 
180
    | LetIn (name,_,_,c') ->
 
181
        (match concrete_name (Some true) avoid env_names name c' with
 
182
           | (Name id,avoid') -> 
 
183
               if id=s then (Some n) 
 
184
               else lookup avoid' (add_name (Name id) env_names) (n+1) c'
 
185
           | (Anonymous,avoid')    -> lookup avoid' env_names (n+1) (pop c'))
 
186
    | Cast (c,_,_) -> lookup avoid env_names n c
 
187
    | _ -> None
 
188
  in lookup (ids_of_named_context (named_context env)) empty_names_context 1 t
 
189
 
 
190
let lookup_index_as_renamed env t n =
 
191
  let rec lookup n d c = match kind_of_term c with
 
192
    | Prod (name,_,c') ->
 
193
          (match concrete_name (Some true) [] empty_names_context name c' with
 
194
               (Name _,_) -> lookup n (d+1) c'
 
195
             | (Anonymous,_) -> 
 
196
                 if n=0 then
 
197
                   Some (d-1)
 
198
                 else if n=1 then 
 
199
                   Some d 
 
200
                 else 
 
201
                   lookup (n-1) (d+1) c')
 
202
    | LetIn (name,_,_,c') ->
 
203
          (match concrete_name (Some true) [] empty_names_context name c' with
 
204
             | (Name _,_) -> lookup n (d+1) c'
 
205
             | (Anonymous,_) -> 
 
206
                 if n=0 then 
 
207
                   Some (d-1) 
 
208
                 else if n=1 then 
 
209
                   Some d 
 
210
                 else 
 
211
                   lookup (n-1) (d+1) c'
 
212
          )
 
213
    | Cast (c,_,_) -> lookup n d c
 
214
    | _ -> if n=0 then Some (d-1) else None
 
215
  in lookup n 1 t
 
216
 
 
217
(**********************************************************************)
 
218
(* Fragile algorithm to reverse pattern-matching compilation          *)
 
219
 
 
220
let update_name na ((_,e),c) =
 
221
  match na with
 
222
  | Name _ when force_wildcard () & noccurn (list_index na e) c ->
 
223
      Anonymous
 
224
  | _ ->
 
225
      na
 
226
 
 
227
let rec decomp_branch n nal b (avoid,env as e) c =
 
228
  if n=0 then (List.rev nal,(e,c))
 
229
  else
 
230
    let na,c,f =
 
231
      match kind_of_term (strip_outer_cast c) with
 
232
        | Lambda (na,_,c) -> na,c,concrete_let_name
 
233
        | LetIn (na,_,_,c) -> na,c,concrete_name
 
234
        | _ -> 
 
235
            Name (id_of_string "x"),(applist (lift 1 c, [mkRel 1])), 
 
236
            concrete_name in
 
237
    let na',avoid' = f (Some b) avoid env na c in
 
238
    decomp_branch (n-1) (na'::nal) b (avoid',add_name na' env) c
 
239
 
 
240
let rec build_tree na isgoal e ci cl =
 
241
  let mkpat n rhs pl = PatCstr(dl,(ci.ci_ind,n+1),pl,update_name na rhs) in
 
242
  let cnl = ci.ci_cstr_nargs in
 
243
  List.flatten
 
244
    (list_tabulate (fun i -> contract_branch isgoal e (cnl.(i),mkpat i,cl.(i)))
 
245
       (Array.length cl))
 
246
 
 
247
and align_tree nal isgoal (e,c as rhs) = match nal with
 
248
  | [] -> [[],rhs]
 
249
  | na::nal ->
 
250
    match kind_of_term c with
 
251
    | Case (ci,p,c,cl) when c = mkRel (list_index na (snd e)) 
 
252
        & (* don't contract if p dependent *)
 
253
        computable p (ci.ci_pp_info.ind_nargs) ->
 
254
        let clauses = build_tree na isgoal e ci cl in
 
255
        List.flatten
 
256
          (List.map (fun (pat,rhs) ->
 
257
              let lines = align_tree nal isgoal rhs in
 
258
              List.map (fun (hd,rest) -> pat::hd,rest) lines) 
 
259
            clauses)
 
260
    | _ ->
 
261
        let pat = PatVar(dl,update_name na rhs) in
 
262
        let mat = align_tree nal isgoal rhs in
 
263
        List.map (fun (hd,rest) -> pat::hd,rest) mat
 
264
 
 
265
and contract_branch isgoal e (cn,mkpat,b) =
 
266
  let nal,rhs = decomp_branch cn [] isgoal e b in
 
267
  let mat = align_tree nal isgoal rhs in
 
268
  List.map (fun (hd,rhs) -> (mkpat rhs hd,rhs)) mat
 
269
 
 
270
(**********************************************************************)
 
271
(* Transform internal representation of pattern-matching into list of *)
 
272
(* clauses                                                            *)
 
273
 
 
274
let is_nondep_branch c n =
 
275
  try
 
276
    let sign,ccl = decompose_lam_n_assum n c in
 
277
    noccur_between 1 (rel_context_length sign) ccl
 
278
  with _ -> (* Not eta-expanded or not reduced *)
 
279
    false
 
280
 
 
281
let extract_nondep_branches test c b n =
 
282
  let rec strip n r = if n=0 then r else
 
283
    match r with
 
284
      | RLambda (_,_,_,_,t) -> strip (n-1) t
 
285
      | RLetIn (_,_,_,t) -> strip (n-1) t
 
286
      | _ -> assert false in
 
287
  if test c n then Some (strip n b) else None
 
288
 
 
289
let it_destRLambda_or_LetIn_names n c =
 
290
  let rec aux n nal c =
 
291
    if n=0 then (List.rev nal,c) else match c with
 
292
      | RLambda (_,na,_,_,c) -> aux (n-1) (na::nal) c
 
293
      | RLetIn (_,na,_,c) -> aux (n-1) (na::nal) c
 
294
      | _ ->
 
295
          (* eta-expansion *)
 
296
          let rec next l =
 
297
            let x = Nameops.next_ident_away (id_of_string "x") l in
 
298
            (* Not efficient but unusual and no function to get free rawvars *)
 
299
(*          if occur_rawconstr x c then next (x::l) else x in *)
 
300
            x
 
301
          in
 
302
          let x = next (free_rawvars c) in 
 
303
          let a = RVar (dl,x) in
 
304
          aux (n-1) (Name x :: nal) 
 
305
            (match c with
 
306
              | RApp (loc,p,l) -> RApp (loc,c,l@[a])
 
307
              | _ -> (RApp (dl,c,[a])))
 
308
  in aux n [] c
 
309
 
 
310
let detype_case computable detype detype_eqns testdep avoid data p c bl =
 
311
  let (indsp,st,nparams,consnargsl,k) = data in
 
312
  let synth_type = synthetize_type () in
 
313
  let tomatch = detype c in
 
314
  let alias, aliastyp, pred= 
 
315
    if (not !Flags.raw_print) & synth_type & computable & Array.length bl<>0 
 
316
    then 
 
317
      Anonymous, None, None
 
318
    else
 
319
      match Option.map detype p with
 
320
        | None -> Anonymous, None, None
 
321
        | Some p ->
 
322
            let nl,typ = it_destRLambda_or_LetIn_names k p in
 
323
            let n,typ = match typ with 
 
324
              | RLambda (_,x,_,t,c) -> x, c
 
325
              | _ -> Anonymous, typ in
 
326
            let aliastyp =
 
327
              if List.for_all ((=) Anonymous) nl then None
 
328
              else Some (dl,indsp,nparams,nl) in
 
329
            n, aliastyp, Some typ
 
330
  in
 
331
  let constructs = Array.init (Array.length bl) (fun i -> (indsp,i+1)) in
 
332
  let eqnl = detype_eqns constructs consnargsl bl in
 
333
  let tag =
 
334
    try 
 
335
      if !Flags.raw_print then
 
336
        RegularStyle
 
337
      else if st = LetPatternStyle then 
 
338
        st
 
339
      else if PrintingLet.active (indsp,consnargsl) then
 
340
        LetStyle
 
341
      else if PrintingIf.active (indsp,consnargsl) then 
 
342
        IfStyle
 
343
      else 
 
344
        st
 
345
    with Not_found -> st
 
346
  in
 
347
  match tag with
 
348
  | LetStyle when aliastyp = None -> 
 
349
      let bl' = Array.map detype bl in
 
350
      let (nal,d) = it_destRLambda_or_LetIn_names consnargsl.(0) bl'.(0) in
 
351
      RLetTuple (dl,nal,(alias,pred),tomatch,d)
 
352
  | IfStyle when aliastyp = None ->
 
353
      let bl' = Array.map detype bl in
 
354
      let nondepbrs =
 
355
        array_map3 (extract_nondep_branches testdep) bl bl' consnargsl in
 
356
      if array_for_all ((<>) None) nondepbrs then
 
357
        RIf (dl,tomatch,(alias,pred),
 
358
             Option.get nondepbrs.(0),Option.get nondepbrs.(1))
 
359
      else
 
360
        RCases (dl,tag,pred,[tomatch,(alias,aliastyp)],eqnl)
 
361
  | _ ->
 
362
      RCases (dl,tag,pred,[tomatch,(alias,aliastyp)],eqnl)
 
363
 
 
364
let detype_sort = function
 
365
  | Prop c -> RProp c
 
366
  | Type u -> RType (Some u)
 
367
 
 
368
(**********************************************************************)
 
369
(* Main detyping function                                             *)
 
370
 
 
371
let detype_anonymous = ref (fun loc n -> anomaly "detype: index to an anonymous variable")
 
372
let set_detype_anonymous f = detype_anonymous := f
 
373
 
 
374
let rec detype (isgoal:bool) avoid env t =
 
375
  match kind_of_term (collapse_appl t) with
 
376
    | Rel n ->
 
377
      (try match lookup_name_of_rel n env with
 
378
         | Name id   -> RVar (dl, id)
 
379
         | Anonymous -> !detype_anonymous dl n
 
380
       with Not_found ->
 
381
         let s = "_UNBOUND_REL_"^(string_of_int n)
 
382
         in RVar (dl, id_of_string s))
 
383
    | Meta n ->
 
384
        (* Meta in constr are not user-parsable and are mapped to Evar *)
 
385
        REvar (dl, n, None)
 
386
    | Var id ->
 
387
        (try
 
388
          let _ = Global.lookup_named id in RRef (dl, VarRef id)
 
389
         with _ ->
 
390
          RVar (dl, id))
 
391
    | Sort s -> RSort (dl,detype_sort s)
 
392
    | Cast (c1,k,c2) ->
 
393
        RCast(dl,detype isgoal avoid env c1, CastConv (k, detype isgoal avoid env c2))
 
394
    | Prod (na,ty,c) -> detype_binder isgoal BProd avoid env na ty c
 
395
    | Lambda (na,ty,c) -> detype_binder isgoal BLambda avoid env na ty c
 
396
    | LetIn (na,b,_,c) -> detype_binder isgoal BLetIn avoid env na b c
 
397
    | App (f,args) ->
 
398
        RApp (dl,detype isgoal avoid env f,
 
399
              array_map_to_list (detype isgoal avoid env) args)
 
400
    | Const sp -> RRef (dl, ConstRef sp)
 
401
    | Evar (ev,cl) ->
 
402
        REvar (dl, ev, 
 
403
               Some (List.map (detype isgoal avoid env) (Array.to_list cl)))
 
404
    | Ind ind_sp ->
 
405
        RRef (dl, IndRef ind_sp)
 
406
    | Construct cstr_sp ->
 
407
        RRef (dl, ConstructRef cstr_sp)
 
408
    | Case (ci,p,c,bl) ->
 
409
        let comp = computable p (ci.ci_pp_info.ind_nargs) in
 
410
        detype_case comp (detype isgoal avoid env)
 
411
          (detype_eqns isgoal avoid env ci comp)
 
412
          is_nondep_branch avoid 
 
413
          (ci.ci_ind,ci.ci_pp_info.style,ci.ci_npar,
 
414
           ci.ci_cstr_nargs,ci.ci_pp_info.ind_nargs)
 
415
          (Some p) c bl
 
416
    | Fix (nvn,recdef) -> detype_fix isgoal avoid env nvn recdef
 
417
    | CoFix (n,recdef) -> detype_cofix isgoal avoid env n recdef
 
418
 
 
419
and detype_fix isgoal avoid env (vn,_ as nvn) (names,tys,bodies) =
 
420
  let def_avoid, def_env, lfi =
 
421
    Array.fold_left
 
422
      (fun (avoid, env, l) na ->
 
423
         let id = next_name_away na avoid in 
 
424
         (id::avoid, add_name (Name id) env, id::l))
 
425
      (avoid, env, []) names in
 
426
  let n = Array.length tys in
 
427
  let v = array_map3
 
428
    (fun c t i -> share_names isgoal (i+1) [] def_avoid def_env c (lift n t))
 
429
    bodies tys vn in
 
430
  RRec(dl,RFix (Array.map (fun i -> Some i, RStructRec) (fst nvn), snd nvn),Array.of_list (List.rev lfi),
 
431
       Array.map (fun (bl,_,_) -> bl) v,
 
432
       Array.map (fun (_,_,ty) -> ty) v,
 
433
       Array.map (fun (_,bd,_) -> bd) v)
 
434
 
 
435
and detype_cofix isgoal avoid env n (names,tys,bodies) =
 
436
  let def_avoid, def_env, lfi =
 
437
    Array.fold_left
 
438
      (fun (avoid, env, l) na ->
 
439
         let id = next_name_away na avoid in 
 
440
         (id::avoid, add_name (Name id) env, id::l))
 
441
      (avoid, env, []) names in
 
442
  let ntys = Array.length tys in
 
443
  let v = array_map2
 
444
    (fun c t -> share_names isgoal 0 [] def_avoid def_env c (lift ntys t))
 
445
    bodies tys in
 
446
  RRec(dl,RCoFix n,Array.of_list (List.rev lfi),
 
447
       Array.map (fun (bl,_,_) -> bl) v,
 
448
       Array.map (fun (_,_,ty) -> ty) v,
 
449
       Array.map (fun (_,bd,_) -> bd) v)
 
450
 
 
451
and share_names isgoal n l avoid env c t =
 
452
  match kind_of_term c, kind_of_term t with
 
453
    (* factorize even when not necessary to have better presentation *)
 
454
    | Lambda (na,t,c), Prod (na',t',c') ->
 
455
        let na = match (na,na') with
 
456
            Name _, _ -> na
 
457
          | _, Name _ -> na'
 
458
          | _ -> na in 
 
459
        let t = detype isgoal avoid env t in
 
460
        let id = next_name_away na avoid in 
 
461
        let avoid = id::avoid and env = add_name (Name id) env in
 
462
        share_names isgoal (n-1) ((Name id,Explicit,None,t)::l) avoid env c c'
 
463
    (* May occur for fix built interactively *)
 
464
    | LetIn (na,b,t',c), _ when n > 0 ->
 
465
        let t' = detype isgoal avoid env t' in
 
466
        let b = detype isgoal avoid env b in
 
467
        let id = next_name_away na avoid in 
 
468
        let avoid = id::avoid and env = add_name (Name id) env in
 
469
        share_names isgoal n ((Name id,Explicit,Some b,t')::l) avoid env c t
 
470
    (* Only if built with the f/n notation or w/o let-expansion in types *)
 
471
    | _, LetIn (_,b,_,t) when n > 0 ->
 
472
        share_names isgoal n l avoid env c (subst1 b t)
 
473
    (* If it is an open proof: we cheat and eta-expand *)
 
474
    | _, Prod (na',t',c') when n > 0 ->
 
475
        let t' = detype isgoal avoid env t' in
 
476
        let id = next_name_away na' avoid in 
 
477
        let avoid = id::avoid and env = add_name (Name id) env in
 
478
        let appc = mkApp (lift 1 c,[|mkRel 1|]) in
 
479
        share_names isgoal (n-1) ((Name id,Explicit,None,t')::l) avoid env appc c'
 
480
    (* If built with the f/n notation: we renounce to share names *)
 
481
    | _ ->
 
482
        if n>0 then warning "Detyping.detype: cannot factorize fix enough";
 
483
        let c = detype isgoal avoid env c in
 
484
        let t = detype isgoal avoid env t in
 
485
        (List.rev l,c,t)
 
486
 
 
487
and detype_eqns isgoal avoid env ci computable constructs consnargsl bl =
 
488
  try
 
489
    if !Flags.raw_print or not (reverse_matching ()) then raise Exit;
 
490
    let mat = build_tree Anonymous isgoal (avoid,env) ci bl in
 
491
    List.map (fun (pat,((avoid,env),c)) -> (dl,[],[pat],detype isgoal avoid env c))
 
492
      mat
 
493
  with _ ->
 
494
    Array.to_list
 
495
      (array_map3 (detype_eqn isgoal avoid env) constructs consnargsl bl)
 
496
 
 
497
and detype_eqn isgoal avoid env constr construct_nargs branch =
 
498
  let make_pat x avoid env b ids =
 
499
    if force_wildcard () & noccurn 1 b then
 
500
      PatVar (dl,Anonymous),avoid,(add_name Anonymous env),ids
 
501
    else 
 
502
      let id = next_name_away_in_cases_pattern x avoid in
 
503
      PatVar (dl,Name id),id::avoid,(add_name (Name id) env),id::ids
 
504
  in
 
505
  let rec buildrec ids patlist avoid env n b =
 
506
    if n=0 then
 
507
      (dl, ids, 
 
508
       [PatCstr(dl, constr, List.rev patlist,Anonymous)],
 
509
       detype isgoal avoid env b)
 
510
    else
 
511
      match kind_of_term b with
 
512
        | Lambda (x,_,b) -> 
 
513
            let pat,new_avoid,new_env,new_ids = make_pat x avoid env b ids in
 
514
            buildrec new_ids (pat::patlist) new_avoid new_env (n-1) b
 
515
 
 
516
        | LetIn (x,_,_,b) -> 
 
517
            let pat,new_avoid,new_env,new_ids = make_pat x avoid env b ids in
 
518
            buildrec new_ids (pat::patlist) new_avoid new_env (n-1) b
 
519
 
 
520
        | Cast (c,_,_) ->    (* Oui, il y a parfois des cast *)
 
521
            buildrec ids patlist avoid env n c
 
522
 
 
523
        | _ -> (* eta-expansion : n'arrivera plus lorsque tous les
 
524
                  termes seront construits � partir de la syntaxe Cases *)
 
525
            (* nommage de la nouvelle variable *)
 
526
            let new_b = applist (lift 1 b, [mkRel 1]) in
 
527
            let pat,new_avoid,new_env,new_ids =
 
528
              make_pat Anonymous avoid env new_b ids in
 
529
            buildrec new_ids (pat::patlist) new_avoid new_env (n-1) new_b
 
530
          
 
531
  in 
 
532
  buildrec [] [] avoid env construct_nargs branch
 
533
 
 
534
and detype_binder isgoal bk avoid env na ty c =
 
535
  let na',avoid' =
 
536
    if bk = BLetIn then
 
537
      concrete_let_name (avoid_flag isgoal) avoid env na c
 
538
    else
 
539
      concrete_name (avoid_flag isgoal) avoid env na c in
 
540
  let r =  detype isgoal avoid' (add_name na' env) c in
 
541
  match bk with
 
542
  | BProd -> RProd (dl, na',Explicit,detype isgoal avoid env ty, r)
 
543
  | BLambda -> RLambda (dl, na',Explicit,detype isgoal avoid env ty, r)
 
544
  | BLetIn -> RLetIn (dl, na',detype isgoal avoid env ty, r)
 
545
 
 
546
let rec detype_rel_context where avoid env sign =
 
547
  let where = Option.map (fun c -> it_mkLambda_or_LetIn c sign) where in
 
548
  let rec aux avoid env = function
 
549
  | [] -> []
 
550
  | (na,b,t)::rest ->
 
551
      let na',avoid' =
 
552
        match where with
 
553
        | None -> na,avoid
 
554
        | Some c ->
 
555
            if b<>None then concrete_let_name None avoid env na c
 
556
            else concrete_name None avoid env na c in
 
557
      let b = Option.map (detype false avoid env) b in
 
558
      let t = detype false avoid env t in
 
559
      (na',Explicit,b,t) :: aux avoid' (add_name na' env) rest
 
560
  in aux avoid env (List.rev sign)
 
561
 
 
562
(**********************************************************************)
 
563
(* Module substitution: relies on detyping                            *)
 
564
 
 
565
let rec subst_cases_pattern subst pat = 
 
566
  match pat with
 
567
  | PatVar _ -> pat
 
568
  | PatCstr (loc,((kn,i),j),cpl,n) -> 
 
569
      let kn' = subst_kn subst kn 
 
570
      and cpl' = list_smartmap (subst_cases_pattern subst) cpl in
 
571
        if kn' == kn && cpl' == cpl then pat else
 
572
          PatCstr (loc,((kn',i),j),cpl',n)
 
573
 
 
574
let rec subst_rawconstr subst raw = 
 
575
  match raw with
 
576
  | RRef (loc,ref) -> 
 
577
      let ref',t = subst_global subst ref in 
 
578
        if ref' == ref then raw else
 
579
         detype false [] [] t
 
580
 
 
581
  | RVar _ -> raw
 
582
  | REvar _ -> raw
 
583
  | RPatVar _ -> raw
 
584
 
 
585
  | RApp (loc,r,rl) -> 
 
586
      let r' = subst_rawconstr subst r 
 
587
      and rl' = list_smartmap (subst_rawconstr subst) rl in
 
588
        if r' == r && rl' == rl then raw else
 
589
          RApp(loc,r',rl')
 
590
 
 
591
  | RLambda (loc,n,bk,r1,r2) -> 
 
592
      let r1' = subst_rawconstr subst r1 and r2' = subst_rawconstr subst r2 in
 
593
        if r1' == r1 && r2' == r2 then raw else
 
594
          RLambda (loc,n,bk,r1',r2')
 
595
 
 
596
  | RProd (loc,n,bk,r1,r2) -> 
 
597
      let r1' = subst_rawconstr subst r1 and r2' = subst_rawconstr subst r2 in
 
598
        if r1' == r1 && r2' == r2 then raw else
 
599
          RProd (loc,n,bk,r1',r2')
 
600
 
 
601
  | RLetIn (loc,n,r1,r2) -> 
 
602
      let r1' = subst_rawconstr subst r1 and r2' = subst_rawconstr subst r2 in
 
603
        if r1' == r1 && r2' == r2 then raw else
 
604
          RLetIn (loc,n,r1',r2')
 
605
 
 
606
  | RCases (loc,sty,rtno,rl,branches) -> 
 
607
      let rtno' = Option.smartmap (subst_rawconstr subst) rtno
 
608
      and rl' = list_smartmap (fun (a,x as y) ->
 
609
        let a' = subst_rawconstr subst a in
 
610
        let (n,topt) = x in 
 
611
        let topt' = Option.smartmap
 
612
          (fun (loc,(sp,i),x,y as t) ->
 
613
            let sp' = subst_kn subst sp in
 
614
            if sp == sp' then t else (loc,(sp',i),x,y)) topt in
 
615
        if a == a' && topt == topt' then y else (a',(n,topt'))) rl
 
616
      and branches' = list_smartmap 
 
617
                        (fun (loc,idl,cpl,r as branch) ->
 
618
                           let cpl' =
 
619
                             list_smartmap (subst_cases_pattern subst) cpl
 
620
                           and r' = subst_rawconstr subst r in
 
621
                             if cpl' == cpl && r' == r then branch else
 
622
                               (loc,idl,cpl',r'))
 
623
                        branches
 
624
      in
 
625
        if rtno' == rtno && rl' == rl && branches' == branches then raw else
 
626
          RCases (loc,sty,rtno',rl',branches')
 
627
 
 
628
  | RLetTuple (loc,nal,(na,po),b,c) ->
 
629
      let po' = Option.smartmap (subst_rawconstr subst) po
 
630
      and b' = subst_rawconstr subst b 
 
631
      and c' = subst_rawconstr subst c in
 
632
        if po' == po && b' == b && c' == c then raw else
 
633
          RLetTuple (loc,nal,(na,po'),b',c')
 
634
                
 
635
  | RIf (loc,c,(na,po),b1,b2) ->
 
636
      let po' = Option.smartmap (subst_rawconstr subst) po
 
637
      and b1' = subst_rawconstr subst b1 
 
638
      and b2' = subst_rawconstr subst b2 
 
639
      and c' = subst_rawconstr subst c in
 
640
        if c' == c & po' == po && b1' == b1 && b2' == b2 then raw else
 
641
          RIf (loc,c',(na,po'),b1',b2')
 
642
 
 
643
  | RRec (loc,fix,ida,bl,ra1,ra2) -> 
 
644
      let ra1' = array_smartmap (subst_rawconstr subst) ra1
 
645
      and ra2' = array_smartmap (subst_rawconstr subst) ra2 in
 
646
      let bl' = array_smartmap
 
647
        (list_smartmap (fun (na,k,obd,ty as dcl) ->
 
648
          let ty' = subst_rawconstr subst ty in
 
649
          let obd' = Option.smartmap (subst_rawconstr subst) obd in
 
650
          if ty'==ty & obd'==obd then dcl else (na,k,obd',ty')))
 
651
        bl in
 
652
        if ra1' == ra1 && ra2' == ra2 && bl'==bl then raw else
 
653
          RRec (loc,fix,ida,bl',ra1',ra2')
 
654
 
 
655
  | RSort _ -> raw
 
656
 
 
657
  | RHole (loc,ImplicitArg (ref,i)) ->
 
658
      let ref',_ = subst_global subst ref in 
 
659
        if ref' == ref then raw else
 
660
          RHole (loc,InternalHole)
 
661
  | RHole (loc, (BinderType _ | QuestionMark _ | CasesType | InternalHole |
 
662
      TomatchTypeParameter _ | GoalEvar | ImpossibleCase)) -> raw
 
663
 
 
664
  | RCast (loc,r1,k) -> 
 
665
      (match k with 
 
666
           CastConv (k,r2) ->
 
667
             let r1' = subst_rawconstr subst r1 and r2' = subst_rawconstr subst r2 in
 
668
               if r1' == r1 && r2' == r2 then raw else
 
669
                 RCast (loc,r1', CastConv (k,r2'))
 
670
         | CastCoerce -> 
 
671
             let r1' = subst_rawconstr subst r1 in
 
672
               if r1' == r1 then raw else RCast (loc,r1',k))
 
673
  | RDynamic _ -> raw
 
674
 
 
675
(* Utilities to transform kernel cases to simple pattern-matching problem *)
 
676
 
 
677
let simple_cases_matrix_of_branches ind brns brs =
 
678
  list_map2_i (fun i n b ->
 
679
      let nal,c = it_destRLambda_or_LetIn_names n b in
 
680
      let mkPatVar na = PatVar (dummy_loc,na) in
 
681
      let p = PatCstr (dummy_loc,(ind,i+1),List.map mkPatVar nal,Anonymous) in
 
682
      let ids = map_succeed Nameops.out_name nal in
 
683
      (dummy_loc,ids,[p],c))
 
684
    0 brns brs
 
685
 
 
686
let return_type_of_predicate ind nparams n pred =
 
687
  let nal,p = it_destRLambda_or_LetIn_names (n+1) pred in
 
688
  (List.hd nal, Some (dummy_loc, ind, nparams, List.tl nal)), Some p