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

« back to all changes in this revision

Viewing changes to pretyping/classops.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: classops.ml 11897 2009-02-09 19:28:02Z barras $ *)
 
10
 
 
11
open Util
 
12
open Pp
 
13
open Flags
 
14
open Names
 
15
open Libnames
 
16
open Nametab
 
17
open Environ
 
18
open Libobject
 
19
open Library
 
20
open Term
 
21
open Termops
 
22
open Rawterm
 
23
open Decl_kinds
 
24
open Mod_subst
 
25
 
 
26
(* usage qque peu general: utilise aussi dans record *)
 
27
 
 
28
(* A class is a type constructor, its type is an arity whose number of
 
29
   arguments is cl_param (0 for CL_SORT and CL_FUN) *)
 
30
 
 
31
type cl_typ = 
 
32
  | CL_SORT 
 
33
  | CL_FUN
 
34
  | CL_SECVAR of variable
 
35
  | CL_CONST of constant
 
36
  | CL_IND of inductive
 
37
 
 
38
type cl_info_typ = {
 
39
  cl_param : int
 
40
}
 
41
 
 
42
type coe_typ = global_reference
 
43
 
 
44
type coe_info_typ = {
 
45
  coe_value : constr;
 
46
  coe_type : types;
 
47
  coe_strength : locality;
 
48
  coe_is_identity : bool;
 
49
  coe_param : int }
 
50
 
 
51
type cl_index = int
 
52
 
 
53
type coe_index = coe_info_typ
 
54
 
 
55
type inheritance_path = coe_index list
 
56
 
 
57
(* table des classes, des coercions et graphe d'heritage *)
 
58
 
 
59
module Bijint = struct
 
60
  type ('a,'b) t = { v : ('a * 'b) array; s : int; inv : ('a,int) Gmap.t }
 
61
  let empty = { v = [||]; s = 0; inv = Gmap.empty }
 
62
  let mem y b = Gmap.mem y b.inv
 
63
  let map x b = if 0 <= x & x < b.s then b.v.(x) else raise Not_found
 
64
  let revmap y b = let n = Gmap.find y b.inv in (n, snd (b.v.(n)))
 
65
  let add x y b =
 
66
    let v =
 
67
      if b.s = Array.length b.v then
 
68
        (let v = Array.make (b.s + 8) (x,y) in Array.blit b.v 0 v 0 b.s; v)
 
69
      else b.v in
 
70
    v.(b.s) <- (x,y); { v = v; s = b.s+1; inv = Gmap.add x b.s b.inv }
 
71
  let replace n x y b =
 
72
    let v = Array.copy b.v in v.(n) <- (x,y); { b with v = v }
 
73
  let dom b = Gmap.dom b.inv
 
74
end
 
75
 
 
76
let class_tab =
 
77
  ref (Bijint.empty : (cl_typ, cl_info_typ) Bijint.t)
 
78
 
 
79
let coercion_tab =
 
80
  ref (Gmap.empty : (coe_typ, coe_info_typ) Gmap.t)
 
81
 
 
82
let inheritance_graph =
 
83
  ref (Gmap.empty : (cl_index * cl_index, inheritance_path) Gmap.t)
 
84
 
 
85
let freeze () = (!class_tab, !coercion_tab, !inheritance_graph)
 
86
 
 
87
let unfreeze (fcl,fco,fig) = 
 
88
  class_tab:=fcl;
 
89
  coercion_tab:=fco;
 
90
  inheritance_graph:=fig
 
91
 
 
92
(* ajout de nouveaux "objets" *)
 
93
 
 
94
let add_new_class cl s =
 
95
  if not (Bijint.mem cl !class_tab) then
 
96
    class_tab := Bijint.add cl s !class_tab
 
97
 
 
98
let add_new_coercion coe s = 
 
99
  coercion_tab := Gmap.add coe s !coercion_tab
 
100
 
 
101
let add_new_path x y =
 
102
  inheritance_graph := Gmap.add x y !inheritance_graph
 
103
 
 
104
let init () =
 
105
  class_tab:= Bijint.empty; 
 
106
  add_new_class CL_FUN  { cl_param = 0 };
 
107
  add_new_class CL_SORT { cl_param = 0 };
 
108
  coercion_tab:= Gmap.empty;
 
109
  inheritance_graph:= Gmap.empty
 
110
 
 
111
let _ = 
 
112
  Summary.declare_summary "inh_graph"
 
113
    { Summary.freeze_function = freeze;
 
114
      Summary.unfreeze_function = unfreeze;
 
115
      Summary.init_function = init;
 
116
      Summary.survive_module = false;
 
117
      Summary.survive_section = false }
 
118
 
 
119
let _ = init()
 
120
 
 
121
(* class_info : cl_typ -> int * cl_info_typ *)
 
122
 
 
123
let class_info cl = Bijint.revmap cl !class_tab
 
124
 
 
125
let class_exists cl = Bijint.mem cl !class_tab
 
126
 
 
127
(* class_info_from_index : int -> cl_typ * cl_info_typ *)
 
128
 
 
129
let class_info_from_index i = Bijint.map i !class_tab
 
130
 
 
131
let cl_fun_index = fst(class_info CL_FUN)
 
132
 
 
133
let cl_sort_index = fst(class_info CL_SORT)
 
134
 
 
135
(* coercion_info : coe_typ -> coe_info_typ *)
 
136
 
 
137
let coercion_info coe = Gmap.find coe !coercion_tab
 
138
 
 
139
let coercion_exists coe = Gmap.mem coe !coercion_tab
 
140
 
 
141
let coercion_params coe_info = coe_info.coe_param
 
142
 
 
143
(* find_class_type : env -> evar_map -> constr -> cl_typ * int *)
 
144
 
 
145
let find_class_type env sigma t =
 
146
  let t', args = Reductionops.whd_betaiotazeta_stack sigma t in
 
147
  match kind_of_term t' with
 
148
    | Var id -> CL_SECVAR id, args
 
149
    | Const sp -> CL_CONST sp, args
 
150
    | Ind ind_sp -> CL_IND ind_sp, args
 
151
    | Prod (_,_,_) -> CL_FUN, []
 
152
    | Sort _ -> CL_SORT, []
 
153
    |  _ -> raise Not_found
 
154
 
 
155
 
 
156
let subst_cl_typ subst ct = match ct with
 
157
    CL_SORT
 
158
  | CL_FUN
 
159
  | CL_SECVAR _ -> ct
 
160
  | CL_CONST kn -> 
 
161
      let kn',t = subst_con subst kn in 
 
162
        if kn' == kn then ct else
 
163
         fst (find_class_type (Global.env()) Evd.empty t)
 
164
  | CL_IND (kn,i) ->
 
165
      let kn' = subst_kn subst kn in 
 
166
        if kn' == kn then ct else
 
167
          CL_IND (kn',i)
 
168
 
 
169
(*CSC: here we should change the datatype for coercions: it should be possible
 
170
       to declare any term as a coercion *)
 
171
let subst_coe_typ subst t = fst (subst_global subst t)
 
172
 
 
173
(* class_of : Term.constr -> int *)
 
174
 
 
175
let class_of env sigma t = 
 
176
  let (t, n1, i, args) = 
 
177
    try
 
178
      let (cl,args) = find_class_type env sigma t in
 
179
      let (i, { cl_param = n1 } ) = class_info cl in
 
180
      (t, n1, i, args)
 
181
    with Not_found ->
 
182
      let t = Tacred.hnf_constr env sigma t in
 
183
      let (cl, args) = find_class_type env sigma t in 
 
184
      let (i, { cl_param = n1 } ) = class_info cl in
 
185
      (t, n1, i, args)
 
186
  in
 
187
  if List.length args = n1 then t, i else raise Not_found
 
188
 
 
189
let inductive_class_of ind = fst (class_info (CL_IND ind))
 
190
 
 
191
let class_args_of env sigma c = snd (find_class_type env sigma c)
 
192
 
 
193
let string_of_class = function
 
194
  | CL_FUN -> "Funclass"
 
195
  | CL_SORT -> "Sortclass"
 
196
  | CL_CONST sp ->
 
197
      string_of_qualid (shortest_qualid_of_global Idset.empty (ConstRef sp))
 
198
  | CL_IND sp ->
 
199
      string_of_qualid (shortest_qualid_of_global Idset.empty (IndRef sp))
 
200
  | CL_SECVAR sp ->
 
201
      string_of_qualid (shortest_qualid_of_global Idset.empty (VarRef sp))
 
202
 
 
203
let pr_class x = str (string_of_class x)
 
204
 
 
205
(* lookup paths *)
 
206
 
 
207
let lookup_path_between_class (s,t) =
 
208
  Gmap.find (s,t) !inheritance_graph
 
209
 
 
210
let lookup_path_to_fun_from_class s =
 
211
  lookup_path_between_class (s,cl_fun_index)
 
212
 
 
213
let lookup_path_to_sort_from_class s =
 
214
  lookup_path_between_class (s,cl_sort_index)
 
215
 
 
216
(* advanced path lookup *)
 
217
 
 
218
let apply_on_class_of env sigma t cont =
 
219
  try
 
220
    let (cl,args) = find_class_type env sigma t in
 
221
    let (i, { cl_param = n1 } ) = class_info cl in
 
222
    if List.length args <> n1 then raise Not_found;
 
223
    t, cont i
 
224
  with Not_found ->
 
225
    (* Is it worth to be more incremental on the delta steps? *)
 
226
    let t = Tacred.hnf_constr env sigma t in
 
227
    let (cl, args) = find_class_type env sigma t in 
 
228
    let (i, { cl_param = n1 } ) = class_info cl in
 
229
    if List.length args <> n1 then raise Not_found;
 
230
    t, cont i
 
231
 
 
232
let lookup_path_between env sigma (s,t) =
 
233
  let (s,(t,p)) =
 
234
    apply_on_class_of env sigma s (fun i ->
 
235
      apply_on_class_of env sigma t (fun j ->
 
236
        lookup_path_between_class (i,j))) in
 
237
  (s,t,p)
 
238
 
 
239
let lookup_path_to_fun_from env sigma s =
 
240
  apply_on_class_of env sigma s lookup_path_to_fun_from_class
 
241
 
 
242
let lookup_path_to_sort_from env sigma s = 
 
243
  apply_on_class_of env sigma s lookup_path_to_sort_from_class
 
244
 
 
245
let get_coercion_constructor coe =
 
246
  let c, _ =
 
247
    Reductionops.whd_betadeltaiota_stack (Global.env()) Evd.empty coe.coe_value
 
248
  in
 
249
  match kind_of_term c with
 
250
  | Construct cstr -> 
 
251
      (cstr, Inductiveops.constructor_nrealargs (Global.env()) cstr -1)
 
252
  | _ ->
 
253
      raise Not_found
 
254
 
 
255
let lookup_pattern_path_between (s,t) =
 
256
  let i = inductive_class_of s in
 
257
  let j = inductive_class_of t in
 
258
  List.map get_coercion_constructor (Gmap.find (i,j) !inheritance_graph)
 
259
 
 
260
(* coercion_value : coe_index -> unsafe_judgment * bool *)
 
261
 
 
262
let coercion_value { coe_value = c; coe_type = t; coe_is_identity = b } =
 
263
  (make_judge c t, b)
 
264
 
 
265
(* pretty-print functions are now in Pretty *)
 
266
(* rajouter une coercion dans le graphe *)
 
267
 
 
268
let path_printer = ref (fun _ -> str "<a class path>"
 
269
                        : (int * int) * inheritance_path -> std_ppcmds)
 
270
 
 
271
let install_path_printer f = path_printer := f
 
272
 
 
273
let print_path x = !path_printer x
 
274
 
 
275
let message_ambig l = 
 
276
  (str"Ambiguous paths:" ++ spc () ++
 
277
   prlist_with_sep pr_fnl (fun ijp -> print_path ijp) l)
 
278
 
 
279
(* add_coercion_in_graph : coe_index * cl_index * cl_index -> unit 
 
280
                         coercion,source,target *)
 
281
 
 
282
let different_class_params i j =
 
283
  (snd (class_info_from_index i)).cl_param > 0
 
284
 
 
285
let add_coercion_in_graph (ic,source,target) =
 
286
  let old_inheritance_graph = !inheritance_graph in
 
287
  let ambig_paths =
 
288
    (ref [] : ((cl_index * cl_index) * inheritance_path) list ref) in
 
289
  let try_add_new_path (i,j as ij) p =
 
290
    try 
 
291
      if i=j then begin
 
292
        if different_class_params i j then begin
 
293
          let _ = lookup_path_between_class ij in
 
294
          ambig_paths := (ij,p)::!ambig_paths
 
295
        end
 
296
      end else begin
 
297
        let _ = lookup_path_between_class (i,j) in
 
298
        ambig_paths := (ij,p)::!ambig_paths
 
299
      end;
 
300
      false
 
301
    with Not_found -> begin
 
302
      add_new_path ij p;
 
303
      true
 
304
    end
 
305
  in
 
306
  let try_add_new_path1 ij p = 
 
307
    let _ = try_add_new_path ij p in () 
 
308
  in
 
309
  if try_add_new_path (source,target) [ic] then begin
 
310
    Gmap.iter 
 
311
      (fun (s,t) p ->
 
312
         if s<>t then begin
 
313
           if t = source then begin
 
314
             try_add_new_path1 (s,target) (p@[ic]);
 
315
             Gmap.iter
 
316
               (fun (u,v) q ->
 
317
                  if u<>v & (u = target) & (p <> q) then 
 
318
                    try_add_new_path1 (s,v) (p@[ic]@q))
 
319
               old_inheritance_graph
 
320
           end;
 
321
           if s = target then try_add_new_path1 (source,t) (ic::p)
 
322
         end)
 
323
      old_inheritance_graph 
 
324
  end;
 
325
  if (!ambig_paths <> []) && is_verbose () then 
 
326
    ppnl (message_ambig !ambig_paths)
 
327
 
 
328
type coercion = coe_typ * locality * bool * cl_typ * cl_typ * int
 
329
 
 
330
(* Calcul de l'arit� d'une classe *)
 
331
 
 
332
let reference_arity_length ref =
 
333
  let t = Global.type_of_global ref in
 
334
  List.length (fst (Reductionops.splay_arity (Global.env()) Evd.empty t))
 
335
 
 
336
let class_params = function
 
337
  | CL_FUN | CL_SORT -> 0
 
338
  | CL_CONST sp -> reference_arity_length (ConstRef sp)
 
339
  | CL_SECVAR sp -> reference_arity_length (VarRef sp)
 
340
  | CL_IND sp  -> reference_arity_length (IndRef sp)
 
341
 
 
342
(* add_class : cl_typ -> locality_flag option -> bool -> unit *)
 
343
 
 
344
let add_class cl =
 
345
  add_new_class cl { cl_param = class_params cl }
 
346
 
 
347
let load_coercion i (_,(coe,stre,isid,cls,clt,ps)) =
 
348
  add_class cls;
 
349
  add_class clt;
 
350
  let is,_ = class_info cls in
 
351
  let it,_ = class_info clt in
 
352
  let xf = 
 
353
    { coe_value = constr_of_global coe;
 
354
      coe_type = Global.type_of_global coe;
 
355
      coe_strength = stre;
 
356
      coe_is_identity = isid;
 
357
      coe_param = ps } in
 
358
  add_new_coercion coe xf;
 
359
  add_coercion_in_graph (xf,is,it)
 
360
 
 
361
let cache_coercion o =
 
362
  load_coercion 1 o
 
363
 
 
364
let subst_coercion (_,subst,(coe,stre,isid,cls,clt,ps as obj)) =
 
365
  let coe' = subst_coe_typ subst coe in
 
366
  let cls' = subst_cl_typ subst cls in
 
367
  let clt' = subst_cl_typ subst clt in
 
368
    if coe' == coe && cls' == cls & clt' == clt then obj else
 
369
      (coe',stre,isid,cls',clt',ps)
 
370
 
 
371
let discharge_cl = function
 
372
  | CL_CONST kn -> CL_CONST (Lib.discharge_con kn)
 
373
  | CL_IND ind -> CL_IND (Lib.discharge_inductive ind)
 
374
  | cl -> cl
 
375
 
 
376
let discharge_coercion (_,(coe,stre,isid,cls,clt,ps)) =
 
377
  if stre = Local then None else 
 
378
    let n = try Array.length (Lib.section_instance coe) with Not_found -> 0 in
 
379
    Some (Lib.discharge_global coe,
 
380
          stre,
 
381
          isid,
 
382
          discharge_cl cls,
 
383
          discharge_cl clt,
 
384
          n + ps)
 
385
 
 
386
let (inCoercion,outCoercion) =
 
387
  declare_object {(default_object "COERCION") with 
 
388
    load_function = load_coercion;
 
389
    cache_function = cache_coercion;
 
390
    subst_function = subst_coercion;
 
391
    classify_function = (fun (_,x) -> Substitute x);
 
392
    discharge_function = discharge_coercion;
 
393
    export_function = (function x -> Some x)  }
 
394
 
 
395
let declare_coercion coef stre ~isid ~src:cls ~target:clt ~params:ps =
 
396
  Lib.add_anonymous_leaf (inCoercion (coef,stre,isid,cls,clt,ps))
 
397
 
 
398
let coercion_strength v = v.coe_strength
 
399
let coercion_identity v = v.coe_is_identity
 
400
 
 
401
(* For printing purpose *)
 
402
let get_coercion_value v = v.coe_value
 
403
 
 
404
let pr_cl_index n = int n
 
405
 
 
406
let classes () = Bijint.dom !class_tab
 
407
let coercions () = Gmap.rng !coercion_tab
 
408
let inheritance_graph () = Gmap.to_list !inheritance_graph
 
409
 
 
410
let coercion_of_reference r =
 
411
  let ref = Nametab.global r in
 
412
  if not (coercion_exists ref) then
 
413
    errorlabstrm "try_add_coercion" 
 
414
      (Nametab.pr_global_env Idset.empty ref ++ str" is not a coercion.");
 
415
  ref
 
416
 
 
417
module CoercionPrinting =
 
418
  struct
 
419
    type t = coe_typ
 
420
    let encode = coercion_of_reference
 
421
    let subst = subst_coe_typ
 
422
    let printer x = pr_global_env Idset.empty x
 
423
    let key = Goptions.SecondaryTable ("Printing","Coercion")
 
424
    let title = "Explicitly printed coercions: "
 
425
    let member_message x b =
 
426
      str "Explicit printing of coercion " ++ printer x ++
 
427
      str (if b then " is set" else " is unset")
 
428
    let synchronous = true
 
429
  end
 
430
 
 
431
module PrintingCoercion  = Goptions.MakeRefTable(CoercionPrinting)
 
432
 
 
433
let hide_coercion coe =
 
434
  if not (PrintingCoercion.active coe) then
 
435
    let coe_info = coercion_info coe in
 
436
    Some coe_info.coe_param
 
437
  else None