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

« back to all changes in this revision

Viewing changes to kernel/mod_subst.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: mod_subst.ml 11924 2009-02-13 13:51:54Z soubiran $ *)
 
10
 
 
11
open Pp
 
12
open Util
 
13
open Names
 
14
open Term
 
15
 
 
16
(* WARNING: not every constant in the associative list domain used to exist
 
17
   in the environment. This allows a simple implementation of the join
 
18
   operation. However, iterating over the associative list becomes a non-sense
 
19
*)
 
20
type resolver = (constant * constr option) list
 
21
 
 
22
let make_resolver resolve = resolve
 
23
 
 
24
let apply_opt_resolver resolve kn =
 
25
 match resolve with
 
26
    None -> None
 
27
  | Some resolve ->
 
28
     try List.assoc kn resolve with Not_found -> None
 
29
 
 
30
type substitution_domain = 
 
31
    MSI of mod_self_id 
 
32
  | MBI of mod_bound_id
 
33
  | MPI of module_path
 
34
 
 
35
let string_of_subst_domain = function
 
36
   MSI msid -> debug_string_of_msid msid
 
37
 | MBI mbid -> debug_string_of_mbid mbid
 
38
 | MPI mp -> string_of_mp mp
 
39
 
 
40
module Umap = Map.Make(struct 
 
41
                         type t = substitution_domain
 
42
                         let compare = Pervasives.compare
 
43
                       end)
 
44
 
 
45
type substitution = (module_path * resolver option) Umap.t
 
46
 
 
47
let empty_subst = Umap.empty
 
48
 
 
49
let add_msid msid mp =
 
50
  Umap.add (MSI msid) (mp,None)
 
51
let add_mbid mbid mp resolve =
 
52
  Umap.add (MBI mbid) (mp,resolve)
 
53
let add_mp mp1 mp2  =
 
54
  Umap.add (MPI mp1) (mp2,None)
 
55
 
 
56
 
 
57
let map_msid msid mp = add_msid msid mp empty_subst
 
58
let map_mbid mbid mp resolve = add_mbid mbid mp resolve empty_subst
 
59
let map_mp mp1 mp2 = add_mp mp1 mp2 empty_subst
 
60
 
 
61
let list_contents sub = 
 
62
  let one_pair uid (mp,_) l =
 
63
    (string_of_subst_domain uid, string_of_mp mp)::l
 
64
  in
 
65
    Umap.fold one_pair sub []
 
66
 
 
67
let debug_string_of_subst sub = 
 
68
  let l = List.map (fun (s1,s2) -> s1^"|->"^s2) (list_contents sub) in
 
69
    "{" ^ String.concat "; " l ^ "}"
 
70
 
 
71
let debug_pr_subst sub = 
 
72
  let l = list_contents sub in
 
73
  let f (s1,s2) = hov 2 (str s1 ++ spc () ++ str "|-> " ++ str s2) 
 
74
  in
 
75
    str "{" ++ hov 2 (prlist_with_sep pr_coma f l) ++ str "}" 
 
76
 
 
77
 
 
78
let subst_mp0 sub mp = (* 's like subst *)
 
79
 let rec aux mp =
 
80
  match mp with
 
81
    | MPself sid -> 
 
82
        let mp',resolve = Umap.find (MSI sid) sub in
 
83
         mp',resolve
 
84
    | MPbound bid ->
 
85
        let mp',resolve = Umap.find (MBI bid) sub in
 
86
          mp',resolve
 
87
    | MPdot (mp1,l) as mp2 ->
 
88
        begin
 
89
          try  
 
90
            let mp',resolve = Umap.find (MPI mp2) sub in
 
91
              mp',resolve
 
92
          with Not_found ->    
 
93
            let mp1',resolve = aux mp1 in
 
94
              MPdot (mp1',l),resolve
 
95
        end
 
96
    | _ -> raise Not_found
 
97
 in
 
98
  try
 
99
    Some (aux mp) 
 
100
  with Not_found -> None
 
101
 
 
102
let subst_mp sub mp =
 
103
 match subst_mp0 sub mp with
 
104
    None -> mp
 
105
  | Some (mp',_) -> mp'
 
106
 
 
107
 
 
108
let subst_kn0 sub kn =
 
109
 let mp,dir,l = repr_kn kn in
 
110
  match subst_mp0 sub mp with
 
111
     Some (mp',_) ->
 
112
      Some (make_kn mp' dir l)
 
113
   | None -> None
 
114
 
 
115
let subst_kn sub kn =
 
116
 match subst_kn0 sub kn with
 
117
    None -> kn
 
118
  | Some kn' -> kn'
 
119
 
 
120
let subst_con sub con =
 
121
 let mp,dir,l = repr_con con in
 
122
  match subst_mp0 sub mp with
 
123
     None -> con,mkConst con
 
124
   | Some (mp',resolve) ->
 
125
      let con' = make_con mp' dir l in
 
126
       match apply_opt_resolver resolve con with
 
127
          None -> con',mkConst con'
 
128
        | Some t -> con',t
 
129
 
 
130
let subst_con0 sub con =
 
131
 let mp,dir,l = repr_con con in
 
132
  match subst_mp0 sub mp with
 
133
      None -> None
 
134
    | Some (mp',resolve) ->
 
135
        let con' = make_con mp' dir l in
 
136
       match apply_opt_resolver resolve con with
 
137
           None -> Some (mkConst con')
 
138
         | Some t -> Some t
 
139
 
 
140
(* Here the semantics is completely unclear.
 
141
   What does "Hint Unfold t" means when "t" is a parameter?
 
142
   Does the user mean "Unfold X.t" or does she mean "Unfold y"
 
143
   where X.t is later on instantiated with y? I choose the first
 
144
   interpretation (i.e. an evaluable reference is never expanded). *)
 
145
let subst_evaluable_reference subst = function
 
146
  | EvalVarRef id -> EvalVarRef id
 
147
  | EvalConstRef kn -> EvalConstRef (fst (subst_con subst kn))
 
148
 
 
149
 
 
150
 
 
151
let rec map_kn f f' c = 
 
152
  let func = map_kn f f' in
 
153
    match kind_of_term c with
 
154
      | Const kn -> 
 
155
          (match f' kn with
 
156
               None -> c
 
157
             | Some const ->const)
 
158
      | Ind (kn,i) -> 
 
159
         (match f kn with
 
160
             None -> c
 
161
           | Some kn' ->
 
162
              mkInd (kn',i))
 
163
      | Construct ((kn,i),j) -> 
 
164
         (match f kn with
 
165
             None -> c
 
166
           | Some kn' ->
 
167
               mkConstruct ((kn',i),j))
 
168
      | Case (ci,p,ct,l) -> 
 
169
          let ci_ind =
 
170
            let (kn,i) = ci.ci_ind in
 
171
              (match f kn with None -> ci.ci_ind | Some kn' -> kn',i ) in
 
172
          let p' = func p in
 
173
          let ct' = func ct in
 
174
          let l' = array_smartmap func l in
 
175
            if (ci.ci_ind==ci_ind && p'==p 
 
176
                && l'==l && ct'==ct)then c
 
177
            else 
 
178
              mkCase ({ci with ci_ind = ci_ind},
 
179
                      p',ct', l')  
 
180
      | Cast (ct,k,t) -> 
 
181
          let ct' = func ct in
 
182
          let t'= func t in
 
183
            if (t'==t && ct'==ct) then c 
 
184
            else mkCast (ct', k, t')
 
185
      | Prod (na,t,ct) -> 
 
186
          let ct' = func ct in
 
187
          let t'= func t in
 
188
            if (t'==t && ct'==ct) then c 
 
189
            else mkProd (na, t', ct')
 
190
      | Lambda (na,t,ct) -> 
 
191
          let ct' = func ct in
 
192
          let t'= func t in
 
193
            if (t'==t && ct'==ct) then c 
 
194
            else mkLambda (na, t', ct')
 
195
      | LetIn (na,b,t,ct) -> 
 
196
          let ct' = func ct in
 
197
          let t'= func t in
 
198
          let b'= func b in
 
199
            if (t'==t && ct'==ct && b==b') then c 
 
200
            else mkLetIn (na, b', t', ct')
 
201
      | App (ct,l) -> 
 
202
          let ct' = func ct in
 
203
          let l' = array_smartmap func l in
 
204
            if (ct'== ct && l'==l) then c
 
205
            else mkApp (ct',l')
 
206
      | Evar (e,l) -> 
 
207
          let l' = array_smartmap func l in
 
208
            if (l'==l) then c
 
209
            else mkEvar (e,l')
 
210
      | Fix (ln,(lna,tl,bl)) ->
 
211
          let tl' = array_smartmap func tl in
 
212
          let bl' = array_smartmap func bl in
 
213
            if (bl == bl'&& tl == tl') then c  
 
214
            else mkFix (ln,(lna,tl',bl'))
 
215
      | CoFix(ln,(lna,tl,bl)) ->
 
216
          let tl' = array_smartmap func tl in
 
217
          let bl' = array_smartmap func bl in
 
218
            if (bl == bl'&& tl == tl') then c  
 
219
            else mkCoFix (ln,(lna,tl',bl'))
 
220
      | _ -> c
 
221
 
 
222
let subst_mps sub = 
 
223
  map_kn (subst_kn0 sub) (subst_con0 sub)
 
224
 
 
225
let rec replace_mp_in_mp mpfrom mpto mp =
 
226
  match mp with
 
227
    | _ when mp = mpfrom -> mpto
 
228
    | MPdot (mp1,l) -> 
 
229
        let mp1' = replace_mp_in_mp mpfrom mpto mp1 in
 
230
          if mp1==mp1' then mp
 
231
          else MPdot (mp1',l)
 
232
    | _ -> mp
 
233
 
 
234
let replace_mp_in_con mpfrom mpto kn =
 
235
 let mp,dir,l = repr_con kn in
 
236
  let mp'' = replace_mp_in_mp mpfrom mpto mp in
 
237
    if mp==mp'' then kn
 
238
    else make_con mp'' dir l
 
239
 
 
240
exception BothSubstitutionsAreIdentitySubstitutions
 
241
exception ChangeDomain of resolver
 
242
 
 
243
let join (subst1 : substitution) (subst2 : substitution) =
 
244
  let apply_subst (sub : substitution) key (mp,resolve) =
 
245
    let mp',resolve' =
 
246
      match subst_mp0 sub mp with
 
247
          None -> mp, None
 
248
        | Some (mp',resolve') -> mp',resolve' in
 
249
    let resolve'' : resolver option =
 
250
      try
 
251
        let res =
 
252
          match resolve with
 
253
            |None -> begin
 
254
                match resolve' with
 
255
                    None -> raise BothSubstitutionsAreIdentitySubstitutions
 
256
                  | Some res -> raise (ChangeDomain res) end
 
257
            | Some res -> res
 
258
        in
 
259
          Some
 
260
            (List.map
 
261
               (fun (kn,topt) ->
 
262
                  kn,
 
263
                  match topt with
 
264
                      None ->
 
265
                        (match key with
 
266
                             MSI msid ->
 
267
                               let kn' = replace_mp_in_con (MPself msid) mp kn in
 
268
                                 apply_opt_resolver resolve' kn'
 
269
                           | MBI mbid ->
 
270
                               let kn' = replace_mp_in_con (MPbound mbid) mp kn in
 
271
                                 apply_opt_resolver resolve' kn'
 
272
                           | MPI mp1 ->
 
273
                               let kn' = replace_mp_in_con mp1 mp kn in
 
274
                                 apply_opt_resolver resolve' kn')
 
275
                    | Some t -> Some (subst_mps sub t)) res)
 
276
      with
 
277
          BothSubstitutionsAreIdentitySubstitutions -> None
 
278
        | ChangeDomain res ->
 
279
            let rec changeDom = function
 
280
              | [] -> []
 
281
              | (kn,topt)::r ->
 
282
                  let key' =
 
283
                    match key with
 
284
                        MSI msid -> MPself msid
 
285
                      | MBI mbid -> MPbound mbid 
 
286
                      | MPI mp1 -> mp1 in
 
287
                  let kn' = replace_mp_in_con mp key' kn in
 
288
                    if kn==kn' then
 
289
                      (*the key does not appear in kn, we remove it
 
290
                        from the resolver that we are building*)
 
291
                      changeDom r
 
292
                    else
 
293
                      (kn',topt)::(changeDom r)
 
294
            in
 
295
              Some (changeDom res)
 
296
    in
 
297
      mp',resolve'' in
 
298
  let subst = Umap.mapi (apply_subst subst2) subst1 in
 
299
    (Umap.fold Umap.add subst2 subst)
 
300
      
 
301
let subst_key subst1 subst2 =
 
302
  let replace_in_key key (mp,resolve) sub=
 
303
    let newkey = 
 
304
      match key with
 
305
        | MPI mp1 -> 
 
306
            begin
 
307
              match subst_mp0 subst1 mp1 with
 
308
                | None -> None
 
309
                | Some (mp2,_) -> Some (MPI mp2)
 
310
            end
 
311
        | _ -> None
 
312
    in
 
313
      match newkey with
 
314
        | None -> Umap.add key (mp,resolve) sub
 
315
        | Some mpi -> Umap.add mpi (mp,resolve) sub
 
316
  in
 
317
    Umap.fold replace_in_key subst2 empty_subst
 
318
 
 
319
let update_subst_alias subst1 subst2 =
 
320
 let subst_inv key (mp,resolve) sub =
 
321
    let newmp = 
 
322
      match key with 
 
323
        | MBI msid -> MPbound msid
 
324
        | MSI msid -> MPself msid
 
325
        | MPI mp -> mp
 
326
    in
 
327
   match mp with 
 
328
     | MPbound mbid -> Umap.add (MBI mbid) (newmp,None) sub
 
329
     | MPself msid -> Umap.add (MSI msid) (newmp,None) sub
 
330
     | _ ->  Umap.add (MPI mp) (newmp,None) sub
 
331
  in 
 
332
  let subst_mbi = Umap.fold subst_inv subst2 empty_subst in
 
333
  let alias_subst key (mp,resolve) sub=
 
334
    let newkey = 
 
335
      match key with
 
336
        | MPI mp1 -> 
 
337
            begin
 
338
              match subst_mp0 subst_mbi mp1 with
 
339
                | None -> None
 
340
                | Some (mp2,_) -> Some (MPI mp2)
 
341
            end
 
342
        | _ -> None
 
343
    in
 
344
      match newkey with
 
345
        | None -> Umap.add key (mp,resolve) sub
 
346
        | Some mpi -> Umap.add mpi (mp,resolve) sub
 
347
  in
 
348
    Umap.fold alias_subst subst1 empty_subst
 
349
 
 
350
let update_subst subst1 subst2 =
 
351
 let subst_inv key (mp,resolve) l =
 
352
    let newmp = 
 
353
      match key with 
 
354
        | MBI msid -> MPbound msid
 
355
        | MSI msid -> MPself msid
 
356
        | MPI mp -> mp
 
357
    in
 
358
   match mp with 
 
359
     | MPbound mbid ->  ((MBI mbid),newmp,resolve)::l
 
360
     | MPself msid ->  ((MSI msid),newmp,resolve)::l
 
361
     | _ ->   ((MPI mp),newmp,resolve)::l
 
362
  in 
 
363
  let subst_mbi = Umap.fold subst_inv subst2 [] in
 
364
  let alias_subst key (mp,resolve) sub=
 
365
    let newsetkey = 
 
366
      match key with
 
367
        | MPI mp1 -> 
 
368
            let compute_set_newkey l (k,mp',resolve) = 
 
369
              let mp_from_key = match k with
 
370
                        | MBI msid -> MPbound msid
 
371
                        | MSI msid -> MPself msid
 
372
                        | MPI mp -> mp
 
373
              in
 
374
              let new_mp1 = replace_mp_in_mp mp_from_key mp' mp1 in
 
375
                if new_mp1 == mp1 then l else (MPI new_mp1,resolve)::l
 
376
            in
 
377
            begin
 
378
              match List.fold_left compute_set_newkey [] subst_mbi with
 
379
                | [] -> None
 
380
                | l -> Some (l)
 
381
            end
 
382
        | _ -> None
 
383
    in
 
384
      match newsetkey with
 
385
        | None -> sub
 
386
        | Some l -> 
 
387
            List.fold_left (fun s (k,r) -> Umap.add k (mp,r) s)
 
388
              sub l
 
389
  in
 
390
    Umap.fold alias_subst subst1 empty_subst
 
391
 
 
392
let join_alias (subst1 : substitution) (subst2 : substitution) =
 
393
  let apply_subst (sub : substitution) key (mp,resolve) =
 
394
    let mp',resolve' =
 
395
      match subst_mp0 sub mp with
 
396
          None -> mp, None
 
397
        | Some (mp',resolve') -> mp',resolve' in
 
398
    let resolve'' : resolver option =
 
399
      try
 
400
        let res =
 
401
          match resolve with
 
402
              Some res -> res
 
403
            | None ->
 
404
                match resolve' with
 
405
                    None -> raise BothSubstitutionsAreIdentitySubstitutions
 
406
                  | Some res -> raise (ChangeDomain res)
 
407
        in
 
408
          Some
 
409
            (List.map
 
410
               (fun (kn,topt) ->
 
411
                  kn,
 
412
                  match topt with
 
413
                      None ->
 
414
                        (match key with
 
415
                             MSI msid ->
 
416
                               let kn' = replace_mp_in_con (MPself msid) mp kn in
 
417
                                 apply_opt_resolver resolve' kn'
 
418
                           | MBI mbid ->
 
419
                               let kn' = replace_mp_in_con (MPbound mbid) mp kn in
 
420
                                 apply_opt_resolver resolve' kn'
 
421
                           | MPI mp1 ->
 
422
                               let kn' = replace_mp_in_con mp1 mp kn in
 
423
                                 apply_opt_resolver resolve' kn')
 
424
                    | Some t -> Some (subst_mps sub t)) res)
 
425
      with
 
426
          BothSubstitutionsAreIdentitySubstitutions -> None
 
427
        | ChangeDomain res ->
 
428
            let rec changeDom = function
 
429
              | [] -> []
 
430
              | (kn,topt)::r ->
 
431
                  let key' =
 
432
                    match key with
 
433
                        MSI msid -> MPself msid
 
434
                      | MBI mbid -> MPbound mbid 
 
435
                      | MPI mp1 -> mp1 in
 
436
                  let kn' = replace_mp_in_con mp key' kn in
 
437
                    if kn==kn' then
 
438
                      (*the key does not appear in kn, we remove it
 
439
                        from the resolver that we are building*)
 
440
                      changeDom r
 
441
                    else
 
442
                      (kn',topt)::(changeDom r)
 
443
            in
 
444
              Some (changeDom res)
 
445
    in
 
446
      mp',resolve'' in
 
447
  Umap.mapi (apply_subst subst2) subst1 
 
448
 
 
449
let remove_alias subst =
 
450
  let rec remove key (mp,resolve) sub =
 
451
    match key with
 
452
        MPI _ -> sub
 
453
      | _ -> Umap.add key (mp,resolve) sub
 
454
  in
 
455
    Umap.fold remove subst empty_subst
 
456
      
 
457
 
 
458
let rec occur_in_path uid path =
 
459
 match uid,path with
 
460
  | MSI sid,MPself sid' -> sid = sid'
 
461
  | MBI bid,MPbound bid' -> bid = bid'
 
462
  | _,MPdot (mp1,_) -> occur_in_path uid mp1
 
463
  | _ -> false
 
464
    
 
465
let occur_uid uid sub = 
 
466
  let check_one uid' (mp,_) =
 
467
    if uid = uid' || occur_in_path uid mp then raise Exit
 
468
  in
 
469
    try 
 
470
      Umap.iter check_one sub;
 
471
      false
 
472
    with Exit -> true
 
473
 
 
474
let occur_msid uid = occur_uid (MSI uid)
 
475
let occur_mbid uid = occur_uid (MBI uid)
 
476
    
 
477
type 'a lazy_subst =
 
478
  | LSval of 'a
 
479
  | LSlazy of substitution * 'a
 
480
        
 
481
type 'a substituted = 'a lazy_subst ref
 
482
      
 
483
let from_val a = ref (LSval a)
 
484
    
 
485
let force fsubst r = 
 
486
  match !r with
 
487
  | LSval a -> a
 
488
  | LSlazy(s,a) -> 
 
489
      let a' = fsubst s a in
 
490
      r := LSval a';
 
491
      a' 
 
492
 
 
493
let subst_substituted s r =
 
494
  match !r with
 
495
    | LSval a -> ref (LSlazy(s,a))
 
496
    | LSlazy(s',a) ->
 
497
        let s'' = join s' s in
 
498
          ref (LSlazy(s'',a))
 
499