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

« back to all changes in this revision

Viewing changes to interp/constrextern.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: constrextern.ml 11576 2008-11-10 19:13:15Z msozeau $ *)
 
10
 
 
11
(*i*)
 
12
open Pp
 
13
open Util
 
14
open Univ
 
15
open Names
 
16
open Nameops
 
17
open Term
 
18
open Termops
 
19
open Inductive
 
20
open Sign
 
21
open Environ
 
22
open Libnames
 
23
open Impargs
 
24
open Topconstr
 
25
open Rawterm
 
26
open Pattern
 
27
open Nametab
 
28
open Notation
 
29
open Reserve
 
30
open Detyping
 
31
(*i*)
 
32
 
 
33
(* Translation from rawconstr to front constr *)
 
34
 
 
35
(**********************************************************************)
 
36
(* Parametrization                                                    *)
 
37
 
 
38
(* This governs printing of local context of references *)
 
39
let print_arguments = ref false
 
40
 
 
41
(* If true, prints local context of evars, whatever print_arguments *)
 
42
let print_evar_arguments = ref false
 
43
 
 
44
(* This governs printing of implicit arguments.  When
 
45
   [print_implicits] is on then [print_implicits_explicit_args] tells
 
46
   how implicit args are printed. If on, implicit args are printed
 
47
   with the form (id:=arg) otherwise arguments are printed normally and
 
48
   the function is prefixed by "@" *)
 
49
let print_implicits = ref false
 
50
let print_implicits_explicit_args = ref false
 
51
 
 
52
(* Tells if implicit arguments not known to be inferable from a rigid
 
53
   position are systematically printed *)
 
54
let print_implicits_defensive = ref true
 
55
 
 
56
(* This forces printing of coercions *)
 
57
let print_coercions = ref false
 
58
 
 
59
(* This forces printing universe names of Type{.} *)
 
60
let print_universes = ref false
 
61
 
 
62
(* This suppresses printing of primitive tokens (e.g. numeral) and symbols *)
 
63
let print_no_symbol = ref false
 
64
 
 
65
(* This governs printing of projections using the dot notation symbols *)
 
66
let print_projections = ref false
 
67
 
 
68
let print_meta_as_hole = ref false
 
69
 
 
70
let with_arguments f = Flags.with_option print_arguments f
 
71
let with_implicits f = Flags.with_option print_implicits f
 
72
let with_coercions f = Flags.with_option print_coercions f
 
73
let with_universes f = Flags.with_option print_universes f
 
74
let without_symbols f = Flags.with_option print_no_symbol f
 
75
let with_meta_as_hole f = Flags.with_option print_meta_as_hole f
 
76
 
 
77
(**********************************************************************)
 
78
(* Various externalisation functions *)
 
79
 
 
80
let insert_delimiters e = function
 
81
  | None -> e
 
82
  | Some sc -> CDelimiters (dummy_loc,sc,e)
 
83
 
 
84
let insert_pat_delimiters loc p = function
 
85
  | None -> p
 
86
  | Some sc -> CPatDelimiters (loc,sc,p)
 
87
 
 
88
let insert_pat_alias loc p = function
 
89
  | Anonymous -> p
 
90
  | Name id -> CPatAlias (loc,p,id)
 
91
 
 
92
(**********************************************************************)
 
93
(* conversion of references                                           *)
 
94
 
 
95
let ids_of_ctxt ctxt =
 
96
  Array.to_list
 
97
    (Array.map
 
98
       (function c -> match kind_of_term c with
 
99
          | Var id -> id
 
100
          | _ ->
 
101
       error "Arbitrary substitution of references not implemented.")
 
102
     ctxt)
 
103
 
 
104
let idopt_of_name = function 
 
105
  | Name id -> Some id
 
106
  | Anonymous -> None
 
107
 
 
108
let extern_evar loc n l =
 
109
  if !print_evar_arguments then CEvar (loc,n,l) else CEvar (loc,n,None)
 
110
 
 
111
let debug_global_reference_printer =
 
112
  ref (fun _ -> failwith "Cannot print a global reference")
 
113
 
 
114
let set_debug_global_reference_printer f =
 
115
  debug_global_reference_printer := f
 
116
 
 
117
let extern_reference loc vars r =
 
118
  try Qualid (loc,shortest_qualid_of_global vars r)
 
119
  with Not_found ->
 
120
    (* happens in debugger *)
 
121
    !debug_global_reference_printer loc r
 
122
 
 
123
(************************************************************************)
 
124
(* Equality up to location (useful for translator v8) *)
 
125
 
 
126
let rec check_same_pattern p1 p2 =
 
127
  match p1, p2 with
 
128
    | CPatAlias(_,a1,i1), CPatAlias(_,a2,i2) when i1=i2 ->
 
129
        check_same_pattern a1 a2
 
130
    | CPatCstr(_,c1,a1), CPatCstr(_,c2,a2) when c1=c2 ->
 
131
        List.iter2 check_same_pattern a1 a2
 
132
    | CPatAtom(_,r1), CPatAtom(_,r2) when r1=r2 -> ()
 
133
    | CPatPrim(_,i1), CPatPrim(_,i2) when i1=i2 -> ()
 
134
    | CPatDelimiters(_,s1,e1), CPatDelimiters(_,s2,e2) when s1=s2 ->
 
135
        check_same_pattern e1 e2
 
136
    | _ -> failwith "not same pattern"
 
137
 
 
138
let check_same_ref r1 r2 =
 
139
  match r1,r2 with
 
140
  | Qualid(_,q1), Qualid(_,q2) when q1=q2 -> ()
 
141
  | Ident(_,i1), Ident(_,i2) when i1=i2 -> ()
 
142
  | _ -> failwith "not same ref"
 
143
 
 
144
let rec check_same_type ty1 ty2 =
 
145
  match ty1, ty2 with
 
146
  | CRef r1, CRef r2 -> check_same_ref r1 r2
 
147
  | CFix(_,(_,id1),fl1), CFix(_,(_,id2),fl2) when id1=id2 ->
 
148
      List.iter2 (fun (id1,i1,bl1,a1,b1) (id2,i2,bl2,a2,b2) ->
 
149
        if id1<>id2 || i1<>i2 then failwith "not same fix";
 
150
        check_same_fix_binder bl1 bl2;
 
151
        check_same_type a1 a2;
 
152
        check_same_type b1 b2)
 
153
        fl1 fl2
 
154
  | CCoFix(_,(_,id1),fl1), CCoFix(_,(_,id2),fl2) when id1=id2 ->
 
155
      List.iter2 (fun (id1,bl1,a1,b1) (id2,bl2,a2,b2) ->
 
156
        if id1<>id2 then failwith "not same fix";
 
157
        check_same_fix_binder bl1 bl2;
 
158
        check_same_type a1 a2;
 
159
        check_same_type b1 b2)
 
160
        fl1 fl2
 
161
  | CArrow(_,a1,b1), CArrow(_,a2,b2) ->
 
162
      check_same_type a1 a2;
 
163
      check_same_type b1 b2
 
164
  | CProdN(_,bl1,a1), CProdN(_,bl2,a2) ->
 
165
      List.iter2 check_same_binder bl1 bl2;
 
166
      check_same_type a1 a2
 
167
  | CLambdaN(_,bl1,a1), CLambdaN(_,bl2,a2) ->
 
168
      List.iter2 check_same_binder bl1 bl2;
 
169
      check_same_type a1 a2
 
170
  | CLetIn(_,(_,na1),a1,b1), CLetIn(_,(_,na2),a2,b2) when na1=na2 ->
 
171
      check_same_type a1 a2;
 
172
      check_same_type b1 b2
 
173
  | CAppExpl(_,r1,al1), CAppExpl(_,r2,al2) when r1=r2 ->
 
174
      List.iter2 check_same_type al1 al2
 
175
  | CApp(_,(_,e1),al1), CApp(_,(_,e2),al2) ->
 
176
      check_same_type e1 e2;
 
177
      List.iter2 (fun (a1,e1) (a2,e2) ->
 
178
                    if e1<>e2 then failwith "not same expl";
 
179
                    check_same_type a1 a2) al1 al2
 
180
  | CCases(_,_,_,a1,brl1), CCases(_,_,_,a2,brl2) ->
 
181
      List.iter2 (fun (tm1,_) (tm2,_) -> check_same_type tm1 tm2) a1 a2;
 
182
      List.iter2 (fun (_,pl1,r1) (_,pl2,r2) ->
 
183
        List.iter2 (located_iter2 (List.iter2 check_same_pattern)) pl1 pl2;
 
184
        check_same_type r1 r2) brl1 brl2
 
185
  | CHole _, CHole _ -> ()
 
186
  | CPatVar(_,i1), CPatVar(_,i2) when i1=i2 -> ()
 
187
  | CSort(_,s1), CSort(_,s2) when s1=s2 -> ()
 
188
  | CCast(_,a1,CastConv (_,b1)), CCast(_,a2, CastConv(_,b2)) ->
 
189
      check_same_type a1 a2;
 
190
      check_same_type b1 b2
 
191
  | CCast(_,a1,CastCoerce), CCast(_,a2, CastCoerce) ->
 
192
      check_same_type a1 a2
 
193
  | CNotation(_,n1,(e1,el1)), CNotation(_,n2,(e2,el2)) when n1=n2 ->
 
194
      List.iter2 check_same_type e1 e2;
 
195
      List.iter2 (List.iter2 check_same_type) el1 el2
 
196
  | CPrim(_,i1), CPrim(_,i2) when i1=i2 -> ()
 
197
  | CDelimiters(_,s1,e1), CDelimiters(_,s2,e2) when s1=s2 ->
 
198
      check_same_type e1 e2
 
199
  | _ when ty1=ty2 -> ()
 
200
  | _ -> failwith "not same type"
 
201
 
 
202
and check_same_binder (nal1,_,e1) (nal2,_,e2) =
 
203
  List.iter2 (fun (_,na1) (_,na2) ->
 
204
    if na1<>na2 then failwith "not same name") nal1 nal2;
 
205
  check_same_type e1 e2
 
206
 
 
207
and check_same_fix_binder bl1 bl2 =
 
208
  List.iter2 (fun b1 b2 ->
 
209
    match b1,b2 with
 
210
        LocalRawAssum(nal1,k,ty1), LocalRawAssum(nal2,k',ty2) ->
 
211
          check_same_binder (nal1,k,ty1) (nal2,k',ty2)
 
212
      | LocalRawDef(na1,def1), LocalRawDef(na2,def2) ->
 
213
          check_same_binder ([na1],default_binder_kind,def1) ([na2],default_binder_kind,def2)
 
214
      | _ -> failwith "not same binder") bl1 bl2
 
215
 
 
216
let same c d = try check_same_type c d; true with _ -> false
 
217
 
 
218
(* Idem for rawconstr *)
 
219
 
 
220
let array_iter2 f v1 v2 =
 
221
  List.iter2 f (Array.to_list v1) (Array.to_list v2)
 
222
 
 
223
let rec same_patt p1 p2 =
 
224
  match p1, p2 with
 
225
      PatVar(_,na1), PatVar(_,na2) -> if na1<>na2 then failwith "PatVar"
 
226
    | PatCstr(_,c1,pl1,al1), PatCstr(_,c2,pl2,al2) ->
 
227
        if c1<>c2 || al1 <> al2 then failwith "PatCstr";
 
228
        List.iter2 same_patt pl1 pl2
 
229
    | _ -> failwith "same_patt"
 
230
 
 
231
let rec same_raw c d =
 
232
  match c,d with
 
233
   | RRef(_,gr1), RRef(_,gr2) -> if gr1<>gr2 then failwith "RRef"
 
234
   | RVar(_,id1), RVar(_,id2) -> if id1<>id2 then failwith "RVar"
 
235
   | REvar(_,e1,a1), REvar(_,e2,a2) ->
 
236
       if e1 <> e2 then failwith "REvar";
 
237
       Option.iter2(List.iter2 same_raw) a1 a2
 
238
  | RPatVar(_,pv1), RPatVar(_,pv2) -> if pv1<>pv2 then failwith "RPatVar"
 
239
  | RApp(_,f1,a1), RApp(_,f2,a2) ->
 
240
      List.iter2 same_raw (f1::a1) (f2::a2)
 
241
  | RLambda(_,na1,bk1,t1,m1), RLambda(_,na2,bk2,t2,m2) ->
 
242
      if na1 <> na2 then failwith "RLambda";
 
243
      same_raw t1 t2; same_raw m1 m2
 
244
  | RProd(_,na1,bk1,t1,m1), RProd(_,na2,bk2,t2,m2) ->
 
245
      if na1 <> na2 then failwith "RProd";
 
246
      same_raw t1 t2; same_raw m1 m2
 
247
  | RLetIn(_,na1,t1,m1), RLetIn(_,na2,t2,m2) ->
 
248
      if na1 <> na2 then failwith "RLetIn";
 
249
      same_raw t1 t2; same_raw m1 m2
 
250
  | RCases(_,_,_,c1,b1), RCases(_,_,_,c2,b2) ->
 
251
      List.iter2
 
252
        (fun (t1,(al1,oind1)) (t2,(al2,oind2)) ->
 
253
          same_raw t1 t2;
 
254
          if al1 <> al2 then failwith "RCases";
 
255
          Option.iter2(fun (_,i1,_,nl1) (_,i2,_,nl2) ->
 
256
            if i1<>i2 || nl1 <> nl2 then failwith "RCases") oind1 oind2) c1 c2;
 
257
      List.iter2 (fun (_,_,pl1,b1) (_,_,pl2,b2) ->
 
258
        List.iter2 same_patt pl1 pl2;
 
259
        same_raw b1 b2) b1 b2
 
260
  | RLetTuple(_,nl1,_,b1,c1), RLetTuple(_,nl2,_,b2,c2) ->
 
261
      if nl1<>nl2 then failwith "RLetTuple";
 
262
      same_raw b1 b2;
 
263
      same_raw c1 c2
 
264
  | RIf(_,b1,_,t1,e1),RIf(_,b2,_,t2,e2) ->
 
265
      same_raw b1 b2; same_raw t1 t2; same_raw e1 e2
 
266
  | RRec(_,fk1,na1,bl1,ty1,def1), RRec(_,fk2,na2,bl2,ty2,def2) ->
 
267
      if fk1 <> fk2 || na1 <> na2 then failwith "RRec";
 
268
      array_iter2
 
269
        (List.iter2 (fun (na1,bk1,bd1,ty1) (na2,bk2,bd2,ty2) ->
 
270
          if na1<>na2 then failwith "RRec";
 
271
          Option.iter2 same_raw bd1 bd2;
 
272
          same_raw ty1 ty2)) bl1 bl2;
 
273
      array_iter2 same_raw ty1 ty2;
 
274
      array_iter2 same_raw def1 def2
 
275
  | RSort(_,s1), RSort(_,s2) -> if s1<>s2 then failwith "RSort"
 
276
  | RHole _, _ -> ()
 
277
  | _, RHole _ -> ()
 
278
  | RCast(_,c1,_),r2 -> same_raw c1 r2
 
279
  | r1, RCast(_,c2,_) -> same_raw r1 c2
 
280
  | RDynamic(_,d1), RDynamic(_,d2) -> if d1<>d2 then failwith"RDynamic"
 
281
  | _ -> failwith "same_raw"
 
282
     
 
283
let same_rawconstr c d = 
 
284
  try same_raw c d; true
 
285
  with Failure _ | Invalid_argument _ -> false
 
286
 
 
287
(**********************************************************************)
 
288
(* mapping patterns to cases_pattern_expr                                *)
 
289
 
 
290
let has_curly_brackets ntn =
 
291
  String.length ntn >= 6 & (String.sub ntn 0 6 = "{ _ } " or
 
292
    String.sub ntn (String.length ntn - 6) 6 = " { _ }" or
 
293
    string_string_contains ntn " { _ } ")
 
294
 
 
295
let rec wildcards ntn n =
 
296
  if n = String.length ntn then []
 
297
  else let l = spaces ntn (n+1) in if ntn.[n] = '_' then n::l else l
 
298
and spaces ntn n =
 
299
  if n = String.length ntn then []
 
300
  else if ntn.[n] = ' ' then wildcards ntn (n+1) else spaces ntn (n+1)
 
301
 
 
302
let expand_curly_brackets loc mknot ntn (l,ll) =
 
303
  let ntn' = ref ntn in
 
304
  let rec expand_ntn i =
 
305
    function
 
306
    | [] -> []
 
307
    | a::l ->
 
308
        let a' = 
 
309
          let p = List.nth (wildcards !ntn' 0) i - 2 in
 
310
          if p>=0 & p+5 <= String.length !ntn' & String.sub !ntn' p 5 = "{ _ }"
 
311
          then begin
 
312
            ntn' := 
 
313
              String.sub !ntn' 0 p ^ "_" ^ 
 
314
              String.sub !ntn' (p+5) (String.length !ntn' -p-5);
 
315
            mknot (loc,"{ _ }",([a],[])) end
 
316
          else a in
 
317
        a' :: expand_ntn (i+1) l in
 
318
  let l = expand_ntn 0 l in
 
319
  (* side effect *)
 
320
  mknot (loc,!ntn',(l,ll))
 
321
 
 
322
let destPrim = function CPrim(_,t) -> Some t | _ -> None
 
323
let destPatPrim = function CPatPrim(_,t) -> Some t | _ -> None
 
324
 
 
325
let make_notation_gen loc ntn mknot mkprim destprim l =
 
326
  if has_curly_brackets ntn
 
327
  then expand_curly_brackets loc mknot ntn l
 
328
  else match ntn,List.map destprim (fst l),(snd l) with
 
329
    (* Special case to avoid writing "- 3" for e.g. (Zopp 3) *)
 
330
    | "- _", [Some (Numeral p)],[] when Bigint.is_strictly_pos p ->
 
331
        mknot (loc,ntn,([mknot (loc,"( _ )",l)],[]))
 
332
    | _ -> 
 
333
        match decompose_notation_key ntn, l with
 
334
        | [Terminal "-"; Terminal x], ([],[]) ->
 
335
            (try mkprim (loc, Numeral (Bigint.neg (Bigint.of_string x)))
 
336
             with _ -> mknot (loc,ntn,([],[])))
 
337
        | [Terminal x], ([],[]) ->
 
338
            (try mkprim (loc, Numeral (Bigint.of_string x))
 
339
             with _ -> mknot (loc,ntn,([],[])))
 
340
        | _ ->
 
341
            mknot (loc,ntn,l)
 
342
 
 
343
let make_notation loc ntn l =
 
344
  make_notation_gen loc ntn
 
345
    (fun (loc,ntn,l) -> CNotation (loc,ntn,l))
 
346
    (fun (loc,p) -> CPrim (loc,p))
 
347
    destPrim l
 
348
 
 
349
let make_pat_notation loc ntn l =
 
350
  make_notation_gen loc ntn
 
351
    (fun (loc,ntn,l) -> CPatNotation (loc,ntn,l))
 
352
    (fun (loc,p) -> CPatPrim (loc,p))
 
353
    destPatPrim l
 
354
 
 
355
let bind_env (sigma,sigmalist as fullsigma) var v =
 
356
  try
 
357
    let vvar = List.assoc var sigma in
 
358
    if v=vvar then fullsigma else raise No_match
 
359
  with Not_found ->
 
360
    (* TODO: handle the case of multiple occs in different scopes *)
 
361
    (var,v)::sigma,sigmalist
 
362
 
 
363
let rec match_cases_pattern metas sigma a1 a2 = match (a1,a2) with
 
364
  | r1, AVar id2 when List.mem id2 metas -> bind_env sigma id2 r1
 
365
  | PatVar (_,Anonymous), AHole _ -> sigma
 
366
  | a, AHole _ -> sigma
 
367
  | PatCstr (loc,(ind,_ as r1),args1,_), _ ->
 
368
      let nparams =
 
369
        (fst (Global.lookup_inductive ind)).Declarations.mind_nparams in
 
370
      let l2 =
 
371
        match a2 with
 
372
          | ARef (ConstructRef r2) when r1 = r2 -> []
 
373
          | AApp (ARef (ConstructRef r2),l2)  when r1 = r2 -> l2
 
374
          | _ -> raise No_match in
 
375
      if List.length l2 <> nparams + List.length args1
 
376
      then raise No_match
 
377
      else
 
378
        let (p2,args2) = list_chop nparams l2 in
 
379
        (* All parameters must be _ *)
 
380
        List.iter (function AHole _ -> () | _ -> raise No_match) p2;
 
381
        List.fold_left2 (match_cases_pattern metas) sigma args1 args2
 
382
  (* TODO: use recursive notations *)
 
383
  | _ -> raise No_match
 
384
 
 
385
let match_aconstr_cases_pattern c ((metas_scl,metaslist_scl),pat) =
 
386
  let vars = List.map fst metas_scl @ List.map fst metaslist_scl in
 
387
  let subst,substlist = match_cases_pattern vars ([],[]) c pat in
 
388
  (* Reorder canonically the substitution *)
 
389
  let find x subst =
 
390
    try List.assoc x subst 
 
391
    with Not_found -> anomaly "match_aconstr_cases_pattern" in
 
392
  List.map (fun (x,scl) -> (find x subst,scl)) metas_scl,
 
393
  List.map (fun (x,scl) -> (find x substlist,scl)) metaslist_scl
 
394
 
 
395
 (* Better to use extern_rawconstr composed with injection/retraction ?? *)
 
396
let rec extern_cases_pattern_in_scope (scopes:local_scopes) vars pat =
 
397
  try 
 
398
    if !Flags.raw_print or !print_no_symbol then raise No_match;
 
399
    let (na,sc,p) = uninterp_prim_token_cases_pattern pat in
 
400
    match availability_of_prim_token sc scopes with
 
401
    | None -> raise No_match
 
402
    | Some key ->
 
403
      let loc = cases_pattern_loc pat in
 
404
      insert_pat_alias loc (insert_pat_delimiters loc (CPatPrim(loc,p)) key) na
 
405
  with No_match ->
 
406
  try 
 
407
    if !Flags.raw_print or !print_no_symbol then raise No_match;
 
408
    extern_symbol_pattern scopes vars pat
 
409
      (uninterp_cases_pattern_notations pat)
 
410
  with No_match ->
 
411
  match pat with
 
412
  | PatVar (loc,Name id) -> CPatAtom (loc,Some (Ident (loc,id)))
 
413
  | PatVar (loc,Anonymous) -> CPatAtom (loc, None) 
 
414
  | PatCstr(loc,cstrsp,args,na) ->
 
415
      let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
 
416
      let p = CPatCstr
 
417
        (loc,extern_reference loc vars (ConstructRef cstrsp),args) in
 
418
      insert_pat_alias loc p na
 
419
        
 
420
and extern_symbol_pattern (tmp_scope,scopes as allscopes) vars t = function
 
421
  | [] -> raise No_match
 
422
  | (keyrule,pat,n as _rule)::rules ->
 
423
      try
 
424
        (* Check the number of arguments expected by the notation *)
 
425
        let loc,na = match t,n with
 
426
          | PatCstr (_,f,l,_), Some n when List.length l > n ->
 
427
              raise No_match
 
428
          | PatCstr (loc,_,_,na),_ -> loc,na
 
429
          | PatVar (loc,na),_ -> loc,na in
 
430
        (* Try matching ... *)
 
431
        let subst,substlist = match_aconstr_cases_pattern t pat in
 
432
        (* Try availability of interpretation ... *)
 
433
        let p = match keyrule with
 
434
          | NotationRule (sc,ntn) ->
 
435
              (match availability_of_notation (sc,ntn) allscopes with
 
436
                  (* Uninterpretation is not allowed in current context *)
 
437
              | None -> raise No_match
 
438
                  (* Uninterpretation is allowed in current context *)
 
439
              | Some (scopt,key) ->
 
440
                  let scopes' = Option.List.cons scopt scopes in
 
441
                  let l =
 
442
                    List.map (fun (c,(scopt,scl)) ->
 
443
                      extern_cases_pattern_in_scope (scopt,scl@scopes') vars c)
 
444
                      subst in
 
445
                  let ll =
 
446
                    List.map (fun (c,(scopt,scl)) ->
 
447
                      let subscope = (scopt,scl@scopes') in
 
448
                      List.map (extern_cases_pattern_in_scope subscope vars) c)
 
449
                      substlist in
 
450
                  insert_pat_delimiters loc 
 
451
                    (make_pat_notation loc ntn (l,ll)) key)
 
452
          | SynDefRule kn ->
 
453
              let qid = shortest_qualid_of_syndef vars kn in
 
454
              CPatAtom (loc,Some (Qualid (loc, qid))) in
 
455
        insert_pat_alias loc p na
 
456
      with
 
457
          No_match -> extern_symbol_pattern allscopes vars t rules
 
458
 
 
459
let extern_cases_pattern vars p = 
 
460
  extern_cases_pattern_in_scope (None,[]) vars p
 
461
 
 
462
(**********************************************************************)
 
463
(* Externalising applications *)
 
464
 
 
465
let occur_name na aty =
 
466
  match na with
 
467
    | Name id -> occur_var_constr_expr id aty
 
468
    | Anonymous -> false
 
469
 
 
470
let is_projection nargs = function
 
471
  | Some r when not !Flags.raw_print & !print_projections ->
 
472
      (try 
 
473
        let n = Recordops.find_projection_nparams r + 1 in
 
474
        if n <= nargs then Some n else None
 
475
      with Not_found -> None)
 
476
  | _ -> None
 
477
 
 
478
let is_hole = function CHole _ -> true | _ -> false
 
479
 
 
480
let is_significant_implicit a impl tail =
 
481
  not (is_hole a) or (tail = [] & not (List.for_all is_status_implicit impl))
 
482
 
 
483
(* Implicit args indexes are in ascending order *)
 
484
(* inctx is useful only if there is a last argument to be deduced from ctxt *)
 
485
let explicitize loc inctx impl (cf,f) args =
 
486
  let n = List.length args in
 
487
  let rec exprec q = function
 
488
    | a::args, imp::impl when is_status_implicit imp ->
 
489
        let tail = exprec (q+1) (args,impl) in
 
490
        let visible =
 
491
          !Flags.raw_print or
 
492
          (!print_implicits & !print_implicits_explicit_args) or 
 
493
          (!print_implicits_defensive &
 
494
           is_significant_implicit a impl tail &
 
495
           not (is_inferable_implicit inctx n imp))
 
496
        in
 
497
        if visible then 
 
498
          (a,Some (dummy_loc, ExplByName (name_of_implicit imp))) :: tail 
 
499
        else
 
500
          tail
 
501
    | a::args, _::impl -> (a,None) :: exprec (q+1) (args,impl)
 
502
    | args, [] -> List.map (fun a -> (a,None)) args (*In case of polymorphism*)
 
503
    | [], _ -> [] in
 
504
  match is_projection (List.length args) cf with
 
505
    | Some i as ip ->
 
506
        if impl <> [] & is_status_implicit (List.nth impl (i-1)) then
 
507
          let f' = match f with CRef f -> f | _ -> assert false in
 
508
          CAppExpl (loc,(ip,f'),args)
 
509
        else
 
510
          let (args1,args2) = list_chop i args in
 
511
          let (impl1,impl2) = if impl=[] then [],[] else list_chop i impl in
 
512
          let args1 = exprec 1 (args1,impl1) in
 
513
          let args2 = exprec (i+1) (args2,impl2) in
 
514
          CApp (loc,(Some (List.length args1),f),args1@args2)
 
515
    | None -> 
 
516
        let args = exprec 1 (args,impl) in
 
517
        if args = [] then f else CApp (loc, (None, f), args)
 
518
 
 
519
let extern_global loc impl f =
 
520
  if impl <> [] & List.for_all is_status_implicit impl then
 
521
    CAppExpl (loc, (None, f), [])
 
522
  else
 
523
    CRef f
 
524
 
 
525
let extern_app loc inctx impl (cf,f) args =
 
526
  if args = [] (* maybe caused by a hidden coercion *) then
 
527
    extern_global loc impl f
 
528
  else
 
529
  if 
 
530
    ((!Flags.raw_print or
 
531
      (!print_implicits & not !print_implicits_explicit_args)) &
 
532
     List.exists is_status_implicit impl)
 
533
  then 
 
534
    CAppExpl (loc, (is_projection (List.length args) cf, f), args)
 
535
  else
 
536
    explicitize loc inctx impl (cf,CRef f) args
 
537
 
 
538
let rec extern_args extern scopes env args subscopes =
 
539
  match args with
 
540
    | [] -> []
 
541
    | a::args ->
 
542
        let argscopes, subscopes = match subscopes with
 
543
          | [] -> (None,scopes), []
 
544
          | scopt::subscopes -> (scopt,scopes), subscopes in
 
545
        extern argscopes env a :: extern_args extern scopes env args subscopes
 
546
 
 
547
let rec remove_coercions inctx = function
 
548
  | RApp (loc,RRef (_,r),args) as c
 
549
      when  not (!Flags.raw_print or !print_coercions)
 
550
      ->
 
551
      let nargs = List.length args in
 
552
      (try match Classops.hide_coercion r with
 
553
          | Some n when n < nargs && (inctx or n+1 < nargs) ->
 
554
              (* We skip a coercion *) 
 
555
              let l = list_skipn n args in
 
556
              let (a,l) = match l with a::l -> (a,l) | [] -> assert false in
 
557
              (* Recursively remove the head coercions *)
 
558
              (match remove_coercions true a with
 
559
              | RApp (_,a,l') -> RApp (loc,a,l'@l)
 
560
              | a -> RApp (loc,a,l))
 
561
          | _ -> c
 
562
      with Not_found -> c)
 
563
  | c -> c
 
564
 
 
565
let rec rename_rawconstr_var id0 id1 = function
 
566
    RRef(loc,VarRef id) when id=id0 -> RRef(loc,VarRef id1)
 
567
  | RVar(loc,id) when id=id0 -> RVar(loc,id1)
 
568
  | c -> map_rawconstr (rename_rawconstr_var id0 id1) c
 
569
 
 
570
let rec share_fix_binders n rbl ty def =
 
571
  match ty,def with
 
572
      RProd(_,na0,bk0,t0,b), RLambda(_,na1,bk1,t1,m) ->
 
573
        if not(same_rawconstr t0 t1) then List.rev rbl, ty, def
 
574
        else
 
575
          let (na,b,m) =
 
576
            match na0, na1 with
 
577
                Name id0, Name id1 ->
 
578
                  if id0=id1 then (na0,b,m)
 
579
                  else if not (occur_rawconstr id1 b) then
 
580
                    (na1,rename_rawconstr_var id0 id1 b,m)
 
581
                  else if not (occur_rawconstr id0 m) then
 
582
                    (na1,b,rename_rawconstr_var id1 id0 m)
 
583
                  else (* vraiment pas de chance! *)
 
584
                    failwith "share_fix_binders: capture"
 
585
              | Name id, Anonymous ->
 
586
                  if not (occur_rawconstr id m) then (na0,b,m)
 
587
                  else
 
588
                    failwith "share_fix_binders: capture"
 
589
              | Anonymous, Name id -> 
 
590
                  if not (occur_rawconstr id b) then (na1,b,m)
 
591
                  else
 
592
                    failwith "share_fix_binders: capture"
 
593
              | _ -> (na1,b,m) in
 
594
          share_fix_binders (n-1) ((na,None,t0)::rbl) b m
 
595
    | _ -> List.rev rbl, ty, def
 
596
 
 
597
(**********************************************************************)
 
598
(* mapping rawterms to numerals (in presence of coercions, choose the *)
 
599
(* one with no delimiter if possible)                                 *)
 
600
 
 
601
let extern_possible_prim_token scopes r =
 
602
  try
 
603
    let (sc,n) = uninterp_prim_token r in
 
604
    match availability_of_prim_token sc scopes with
 
605
    | None -> None
 
606
    | Some key -> Some (insert_delimiters (CPrim (loc_of_rawconstr r,n)) key)
 
607
  with No_match ->
 
608
    None
 
609
 
 
610
let extern_optimal_prim_token scopes r r' =
 
611
  let c = extern_possible_prim_token scopes r in
 
612
  let c' = if r==r' then None else extern_possible_prim_token scopes r' in
 
613
  match c,c' with
 
614
  | Some n, (Some (CDelimiters _) | None) | _, Some n -> n
 
615
  | _ -> raise No_match
 
616
 
 
617
(**********************************************************************)
 
618
(* mapping rawterms to constr_expr                                    *)
 
619
 
 
620
let extern_rawsort = function
 
621
  | RProp _ as s -> s
 
622
  | RType (Some _) as s when !print_universes -> s
 
623
  | RType _ -> RType None
 
624
 
 
625
let rec extern inctx scopes vars r =
 
626
  let r' = remove_coercions inctx r in
 
627
  try 
 
628
    if !Flags.raw_print or !print_no_symbol then raise No_match;
 
629
    extern_optimal_prim_token scopes r r'
 
630
  with No_match ->
 
631
  try 
 
632
    if !Flags.raw_print or !print_no_symbol then raise No_match;
 
633
    extern_symbol scopes vars r' (uninterp_notations r')
 
634
  with No_match -> match r' with
 
635
  | RRef (loc,ref) ->
 
636
      extern_global loc (implicits_of_global ref)
 
637
        (extern_reference loc vars ref)
 
638
 
 
639
  | RVar (loc,id) -> CRef (Ident (loc,id))
 
640
 
 
641
  | REvar (loc,n,None) when !print_meta_as_hole -> CHole (loc, None)
 
642
 
 
643
  | REvar (loc,n,l) ->
 
644
      extern_evar loc n (Option.map (List.map (extern false scopes vars)) l)
 
645
 
 
646
  | RPatVar (loc,n) ->
 
647
      if !print_meta_as_hole then CHole (loc, None) else CPatVar (loc,n)
 
648
 
 
649
  | RApp (loc,f,args) ->
 
650
      (match f with
 
651
         | RRef (rloc,ref) ->
 
652
             let subscopes = find_arguments_scope ref in
 
653
             let args =
 
654
               extern_args (extern true) (snd scopes) vars args subscopes in
 
655
             extern_app loc inctx (implicits_of_global ref)
 
656
               (Some ref,extern_reference rloc vars ref)
 
657
               args
 
658
         | _       -> 
 
659
             explicitize loc inctx [] (None,sub_extern false scopes vars f)
 
660
               (List.map (sub_extern true scopes vars) args))
 
661
 
 
662
  | RProd (loc,Anonymous,_,t,c) ->
 
663
      (* Anonymous product are never factorized *)
 
664
      CArrow (loc,extern_typ scopes vars t, extern_typ scopes vars c)
 
665
 
 
666
  | RLetIn (loc,na,t,c) ->
 
667
      CLetIn (loc,(loc,na),sub_extern false scopes vars t,
 
668
              extern inctx scopes (add_vname vars na) c)
 
669
 
 
670
  | RProd (loc,na,bk,t,c) ->
 
671
      let t = extern_typ scopes vars (anonymize_if_reserved na t) in
 
672
      let (idl,c) = factorize_prod scopes (add_vname vars na) t c in
 
673
      CProdN (loc,[(dummy_loc,na)::idl,Default bk,t],c)
 
674
 
 
675
  | RLambda (loc,na,bk,t,c) ->
 
676
      let t = extern_typ scopes vars (anonymize_if_reserved na t) in
 
677
      let (idl,c) = factorize_lambda inctx scopes (add_vname vars na) t c in
 
678
      CLambdaN (loc,[(dummy_loc,na)::idl,Default bk,t],c)
 
679
        
 
680
  | RCases (loc,sty,rtntypopt,tml,eqns) ->
 
681
      let vars' = 
 
682
        List.fold_right (name_fold Idset.add)
 
683
          (cases_predicate_names tml) vars in
 
684
      let rtntypopt' = Option.map (extern_typ scopes vars') rtntypopt in
 
685
      let tml = List.map (fun (tm,(na,x)) ->
 
686
        let na' = match na,tm with
 
687
            Anonymous, RVar (_,id) when 
 
688
              rtntypopt<>None & occur_rawconstr id (Option.get rtntypopt)
 
689
              -> Some Anonymous
 
690
          | Anonymous, _ -> None
 
691
          | Name id, RVar (_,id') when id=id' -> None
 
692
          | Name _, _ -> Some na in
 
693
        (sub_extern false scopes vars tm,
 
694
        (na',Option.map (fun (loc,ind,n,nal) ->
 
695
          let params = list_tabulate
 
696
            (fun _ -> RHole (dummy_loc,Evd.InternalHole)) n in
 
697
          let args = List.map (function
 
698
            | Anonymous -> RHole (dummy_loc,Evd.InternalHole) 
 
699
            | Name id -> RVar (dummy_loc,id)) nal in
 
700
          let t = RApp (dummy_loc,RRef (dummy_loc,IndRef ind),params@args) in
 
701
          (extern_typ scopes vars t)) x))) tml in
 
702
      let eqns = List.map (extern_eqn inctx scopes vars) eqns in 
 
703
      CCases (loc,sty,rtntypopt',tml,eqns)
 
704
 
 
705
  | RLetTuple (loc,nal,(na,typopt),tm,b) ->
 
706
      CLetTuple (loc,nal,
 
707
        (Option.map (fun _ -> na) typopt,
 
708
         Option.map (extern_typ scopes (add_vname vars na)) typopt),
 
709
        sub_extern false scopes vars tm,
 
710
        extern inctx scopes (List.fold_left add_vname vars nal) b)
 
711
 
 
712
  | RIf (loc,c,(na,typopt),b1,b2) ->
 
713
      CIf (loc,sub_extern false scopes vars c,
 
714
        (Option.map (fun _ -> na) typopt,
 
715
         Option.map (extern_typ scopes (add_vname vars na)) typopt),
 
716
        sub_extern inctx scopes vars b1, sub_extern inctx scopes vars b2)
 
717
 
 
718
  | RRec (loc,fk,idv,blv,tyv,bv) ->
 
719
      let vars' = Array.fold_right Idset.add idv vars in
 
720
      (match fk with
 
721
         | RFix (nv,n) ->
 
722
             let listdecl = 
 
723
               Array.mapi (fun i fi ->
 
724
                 let (bl,ty,def) = blv.(i), tyv.(i), bv.(i) in
 
725
                 let (ids,bl) = extern_local_binder scopes vars bl in
 
726
                 let vars0 = List.fold_right (name_fold Idset.add) ids vars in
 
727
                 let vars1 = List.fold_right (name_fold Idset.add) ids vars' in
 
728
                 let n = 
 
729
                   match fst nv.(i) with
 
730
                     | None -> None
 
731
                     | Some x -> Some (dummy_loc, out_name (List.nth ids x))
 
732
                 in 
 
733
                 let ro = extern_recursion_order scopes vars (snd nv.(i)) in
 
734
                 ((dummy_loc, fi), (n, ro), bl, extern_typ scopes vars0 ty,
 
735
                  extern false scopes vars1 def)) idv
 
736
             in 
 
737
             CFix (loc,(loc,idv.(n)),Array.to_list listdecl)
 
738
         | RCoFix n -> 
 
739
             let listdecl =
 
740
               Array.mapi (fun i fi ->
 
741
                 let (ids,bl) = extern_local_binder scopes vars blv.(i) in
 
742
                 let vars0 = List.fold_right (name_fold Idset.add) ids vars in
 
743
                 let vars1 = List.fold_right (name_fold Idset.add) ids vars' in
 
744
                 ((dummy_loc, fi),bl,extern_typ scopes vars0 tyv.(i),
 
745
                  sub_extern false scopes vars1 bv.(i))) idv
 
746
             in
 
747
             CCoFix (loc,(loc,idv.(n)),Array.to_list listdecl))
 
748
 
 
749
  | RSort (loc,s) -> CSort (loc,extern_rawsort s)
 
750
 
 
751
  | RHole (loc,e) -> CHole (loc, Some e)
 
752
 
 
753
  | RCast (loc,c, CastConv (k,t)) ->
 
754
      CCast (loc,sub_extern true scopes vars c, CastConv (k,extern_typ scopes vars t))
 
755
  | RCast (loc,c, CastCoerce) ->
 
756
      CCast (loc,sub_extern true scopes vars c, CastCoerce)
 
757
 
 
758
  | RDynamic (loc,d) -> CDynamic (loc,d)
 
759
 
 
760
and extern_typ (_,scopes) = 
 
761
  extern true (Some Notation.type_scope,scopes)
 
762
 
 
763
and sub_extern inctx (_,scopes) = extern inctx (None,scopes)
 
764
 
 
765
and factorize_prod scopes vars aty c =
 
766
  try 
 
767
    if !Flags.raw_print or !print_no_symbol then raise No_match;
 
768
    ([],extern_symbol scopes vars c (uninterp_notations c))
 
769
  with No_match -> match c with
 
770
  | RProd (loc,(Name id as na),bk,ty,c)
 
771
      when same aty (extern_typ scopes vars (anonymize_if_reserved na ty))
 
772
        & not (occur_var_constr_expr id aty) (* avoid na in ty escapes scope *)
 
773
        -> let (nal,c) = factorize_prod scopes (Idset.add id vars) aty c in
 
774
           ((loc,Name id)::nal,c)
 
775
  | c -> ([],extern_typ scopes vars c)
 
776
 
 
777
and factorize_lambda inctx scopes vars aty c =
 
778
  try 
 
779
    if !Flags.raw_print or !print_no_symbol then raise No_match;
 
780
    ([],extern_symbol scopes vars c (uninterp_notations c))
 
781
  with No_match -> match c with
 
782
  | RLambda (loc,na,bk,ty,c)
 
783
      when same aty (extern_typ scopes vars (anonymize_if_reserved na ty))
 
784
        & not (occur_name na aty) (* To avoid na in ty' escapes scope *)
 
785
        -> let (nal,c) =
 
786
             factorize_lambda inctx scopes (add_vname vars na) aty c in
 
787
           ((loc,na)::nal,c)
 
788
  | c -> ([],sub_extern inctx scopes vars c)
 
789
 
 
790
and extern_local_binder scopes vars = function
 
791
    [] -> ([],[])
 
792
  | (na,bk,Some bd,ty)::l ->
 
793
      let (ids,l) =
 
794
        extern_local_binder scopes (name_fold Idset.add na vars) l in
 
795
      (na::ids,
 
796
       LocalRawDef((dummy_loc,na), extern false scopes vars bd) :: l)
 
797
      
 
798
  | (na,bk,None,ty)::l ->
 
799
      let ty = extern_typ scopes vars (anonymize_if_reserved na ty) in
 
800
      (match extern_local_binder scopes (name_fold Idset.add na vars) l with
 
801
          (ids,LocalRawAssum(nal,k,ty')::l)
 
802
            when same ty ty' &
 
803
              match na with Name id -> not (occur_var_constr_expr id ty')
 
804
                | _ -> true ->
 
805
              (na::ids,
 
806
               LocalRawAssum((dummy_loc,na)::nal,k,ty')::l)
 
807
        | (ids,l) ->
 
808
            (na::ids,
 
809
             LocalRawAssum([(dummy_loc,na)],Default bk,ty) :: l))
 
810
 
 
811
and extern_eqn inctx scopes vars (loc,ids,pl,c) =
 
812
  (loc,[loc,List.map (extern_cases_pattern_in_scope scopes vars) pl],
 
813
   extern inctx scopes vars c)
 
814
 
 
815
and extern_symbol (tmp_scope,scopes as allscopes) vars t = function
 
816
  | [] -> raise No_match
 
817
  | (keyrule,pat,n as _rule)::rules ->
 
818
      let loc = Rawterm.loc_of_rawconstr t in
 
819
      try
 
820
        (* Adjusts to the number of arguments expected by the notation *)
 
821
        let (t,args) = match t,n with
 
822
          | RApp (_,(RRef _ as f),args), Some n when List.length args >= n ->
 
823
              let args1, args2 = list_chop n args in
 
824
              (if n = 0 then f else RApp (dummy_loc,f,args1)), args2
 
825
          | RApp (_,(RRef _ as f),args), None -> f, args
 
826
          | RRef _, Some 0 -> RApp (dummy_loc,t,[]), []
 
827
          | _, None -> t,[]
 
828
          | _ -> raise No_match in
 
829
        (* Try matching ... *)
 
830
        let subst,substlist = match_aconstr t pat in
 
831
        (* Try availability of interpretation ... *)
 
832
        let e =
 
833
          match keyrule with
 
834
          | NotationRule (sc,ntn) ->
 
835
              (match availability_of_notation (sc,ntn) allscopes with
 
836
                  (* Uninterpretation is not allowed in current context *)
 
837
              | None -> raise No_match
 
838
                  (* Uninterpretation is allowed in current context *)
 
839
              | Some (scopt,key) ->
 
840
                  let scopes' = Option.List.cons scopt scopes in
 
841
                  let l =
 
842
                    List.map (fun (c,(scopt,scl)) ->
 
843
                      extern (* assuming no overloading: *) true
 
844
                        (scopt,scl@scopes') vars c)
 
845
                      subst in
 
846
                  let ll =
 
847
                    List.map (fun (c,(scopt,scl)) ->
 
848
                      List.map (extern true (scopt,scl@scopes') vars) c)
 
849
                      substlist in
 
850
                  insert_delimiters (make_notation loc ntn (l,ll)) key)
 
851
          | SynDefRule kn ->
 
852
              let l =
 
853
                List.map (fun (c,(scopt,scl)) ->
 
854
                  extern true (scopt,scl@scopes) vars c, None)
 
855
                  subst in
 
856
              let a = CRef (Qualid (loc, shortest_qualid_of_syndef vars kn)) in
 
857
              if l = [] then a else CApp (loc,(None,a),l) in
 
858
        if args = [] then e 
 
859
        else
 
860
          (* TODO: compute scopt for the extra args, in case, head is a ref *)
 
861
          explicitize loc false [] (None,e)
 
862
          (List.map (extern true allscopes vars) args)
 
863
      with
 
864
          No_match -> extern_symbol allscopes vars t rules
 
865
 
 
866
and extern_recursion_order scopes vars = function
 
867
    RStructRec -> CStructRec
 
868
  | RWfRec c -> CWfRec (extern true scopes vars c)
 
869
  | RMeasureRec c -> CMeasureRec (extern true scopes vars c)
 
870
 
 
871
 
 
872
let extern_rawconstr vars c =
 
873
  extern false (None,[]) vars c
 
874
 
 
875
let extern_rawtype vars c =
 
876
  extern_typ (None,[]) vars c
 
877
 
 
878
(******************************************************************)
 
879
(* Main translation function from constr -> constr_expr *)
 
880
 
 
881
let loc = dummy_loc (* for constr and pattern, locations are lost *)
 
882
 
 
883
let extern_constr_gen at_top scopt env t =
 
884
  let avoid = if at_top then ids_of_context env else [] in
 
885
  let r = Detyping.detype at_top avoid (names_of_rel_context env) t in
 
886
  let vars = vars_of_env env in
 
887
  extern false (scopt,[]) vars r
 
888
 
 
889
let extern_constr_in_scope at_top scope env t =
 
890
  extern_constr_gen at_top (Some scope) env t
 
891
 
 
892
let extern_constr at_top env t =
 
893
  extern_constr_gen at_top None env t
 
894
 
 
895
let extern_type at_top env t =
 
896
  let avoid = if at_top then ids_of_context env else [] in
 
897
  let r = Detyping.detype at_top avoid (names_of_rel_context env) t in
 
898
  extern_rawtype (vars_of_env env) r
 
899
 
 
900
let extern_sort s = extern_rawsort (detype_sort s)
 
901
 
 
902
(******************************************************************)
 
903
(* Main translation function from pattern -> constr_expr *)
 
904
 
 
905
let it_destPLambda n c =
 
906
  let rec aux n nal c =
 
907
    if n=0 then (nal,c) else match c with
 
908
      | PLambda (na,_,c) -> aux (n-1) (na::nal) c
 
909
      | _ -> anomaly "it_destPLambda" in
 
910
  aux n [] c
 
911
 
 
912
let rec raw_of_pat env = function
 
913
  | PRef ref -> RRef (loc,ref)
 
914
  | PVar id -> RVar (loc,id)
 
915
  | PEvar (n,l) -> REvar (loc,n,Some (array_map_to_list (raw_of_pat env) l))
 
916
  | PRel n ->
 
917
      let id = try match lookup_name_of_rel n env with
 
918
        | Name id   -> id
 
919
        | Anonymous ->
 
920
            anomaly "rawconstr_of_pattern: index to an anonymous variable"
 
921
      with Not_found -> id_of_string ("_UNBOUND_REL_"^(string_of_int n)) in
 
922
      RVar (loc,id)
 
923
  | PMeta None -> RHole (loc,Evd.InternalHole)
 
924
  | PMeta (Some n) -> RPatVar (loc,(false,n))
 
925
  | PApp (f,args) ->
 
926
      RApp (loc,raw_of_pat env f,array_map_to_list (raw_of_pat env) args)
 
927
  | PSoApp (n,args) ->
 
928
      RApp (loc,RPatVar (loc,(true,n)),
 
929
        List.map (raw_of_pat env) args)
 
930
  | PProd (na,t,c) ->
 
931
      RProd (loc,na,Explicit,raw_of_pat env t,raw_of_pat (na::env) c)
 
932
  | PLetIn (na,t,c) ->
 
933
      RLetIn (loc,na,raw_of_pat env t, raw_of_pat (na::env) c)
 
934
  | PLambda (na,t,c) ->
 
935
      RLambda (loc,na,Explicit,raw_of_pat env t, raw_of_pat (na::env) c)
 
936
  | PIf (c,b1,b2) ->
 
937
      RIf (loc, raw_of_pat env c, (Anonymous,None), 
 
938
           raw_of_pat env b1, raw_of_pat env b2)
 
939
  | PCase ((LetStyle,[|n|],ind,None),PMeta None,tm,[|b|]) ->
 
940
      let nal,b = it_destRLambda_or_LetIn_names n (raw_of_pat env b) in
 
941
      RLetTuple (loc,nal,(Anonymous,None),raw_of_pat env tm,b)
 
942
  | PCase (_,PMeta None,tm,[||]) ->
 
943
      RCases (loc,RegularStyle,None,[raw_of_pat env tm,(Anonymous,None)],[])
 
944
  | PCase ((_,cstr_nargs,indo,ind_nargs),p,tm,bv) ->
 
945
      let brs = Array.to_list (Array.map (raw_of_pat env) bv) in
 
946
      let brns = Array.to_list cstr_nargs in
 
947
        (* ind is None only if no branch and no return type *)
 
948
      let ind = Option.get indo in
 
949
      let mat = simple_cases_matrix_of_branches ind brns brs in
 
950
      let indnames,rtn =
 
951
        if p = PMeta None then (Anonymous,None),None
 
952
        else 
 
953
          let nparams,n = Option.get ind_nargs in
 
954
          return_type_of_predicate ind nparams n (raw_of_pat env p) in
 
955
      RCases (loc,RegularStyle,rtn,[raw_of_pat env tm,indnames],mat)
 
956
  | PFix f -> Detyping.detype false [] env (mkFix f)
 
957
  | PCoFix c -> Detyping.detype false [] env (mkCoFix c)
 
958
  | PSort s -> RSort (loc,s)
 
959
 
 
960
and raw_of_eqns env constructs consnargsl bl =
 
961
  Array.to_list (array_map3 (raw_of_eqn env) constructs consnargsl bl)
 
962
 
 
963
and raw_of_eqn env constr construct_nargs branch =
 
964
  let make_pat x env b ids =
 
965
    let avoid = List.fold_right (name_fold (fun x l -> x::l)) env [] in
 
966
    let id = next_name_away_with_default "x" x avoid in
 
967
    PatVar (dummy_loc,Name id),(Name id)::env,id::ids
 
968
  in
 
969
  let rec buildrec ids patlist env n b =
 
970
    if n=0 then
 
971
      (dummy_loc, ids, 
 
972
       [PatCstr(dummy_loc, constr, List.rev patlist,Anonymous)],
 
973
       raw_of_pat env b)
 
974
    else
 
975
      match b with
 
976
        | PLambda (x,_,b) -> 
 
977
            let pat,new_env,new_ids = make_pat x env b ids in
 
978
            buildrec new_ids (pat::patlist) new_env (n-1) b
 
979
 
 
980
        | PLetIn (x,_,b) -> 
 
981
            let pat,new_env,new_ids = make_pat x env b ids in
 
982
            buildrec new_ids (pat::patlist) new_env (n-1) b
 
983
 
 
984
        | _ ->
 
985
            error "Unsupported branch in case-analysis while printing pattern."
 
986
  in 
 
987
  buildrec [] [] env construct_nargs branch
 
988
 
 
989
let extern_constr_pattern env pat =
 
990
  extern true (None,[]) Idset.empty (raw_of_pat env pat)
 
991
 
 
992
let extern_rel_context where env sign =
 
993
  let a = detype_rel_context where [] (names_of_rel_context env) sign in
 
994
  let vars = vars_of_env env in
 
995
  snd (extern_local_binder (None,[]) vars a)