1 (***********************************************************************)
4 (* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
6 (* Copyright 2001 Institut National de Recherche en Informatique et *)
7 (* en Automatique. All rights reserved. This file is distributed *)
8 (* under the terms of the Q Public License version 1.0. *)
10 (***********************************************************************)
14 (** Representation and manipulation of modules and module types. *)
16 let print_DEBUG s
= print_string s
; print_newline
()
18 module Name
= Odoc_name
20 (** To keep the order of elements in a module. *)
22 Element_module
of t_module
23 | Element_module_type
of t_module_type
24 | Element_included_module
of included_module
25 | Element_class
of Odoc_class.t_class
26 | Element_class_type
of Odoc_class.t_class_type
27 | Element_value
of Odoc_value.t_value
28 | Element_exception
of Odoc_exception.t_exception
29 | Element_type
of Odoc_type.t_type
30 | Element_module_comment
of Odoc_types.text
32 (** Used where we can reference t_module or t_module_type *)
35 | Modtype
of t_module_type
37 and included_module
= {
38 im_name
: Name.t
; (** the name of the included module *)
39 mutable im_module
: mmt
option ; (** the included module or module type *)
40 mutable im_info
: Odoc_types.info
option ; (** comment associated to the includ directive *)
45 mutable ma_module
: mmt
option ; (** the real module or module type if we could associate it *)
48 and module_parameter
= {
49 mp_name
: string ; (** the name *)
50 mp_type
: Types.module_type
; (** the type *)
51 mp_type_code
: string ; (** the original code *)
52 mp_kind
: module_type_kind
; (** the way the parameter was built *)
55 (** Different kinds of module. *)
57 | Module_struct
of module_element list
58 | Module_alias
of module_alias
(** complete name and corresponding module if we found it *)
59 | Module_functor
of module_parameter
* module_kind
60 | Module_apply
of module_kind
* module_kind
61 | Module_with
of module_type_kind
* string
62 | Module_constraint
of module_kind
* module_type_kind
64 (** Representation of a module. *)
67 mutable m_type
: Types.module_type
;
68 mutable m_info
: Odoc_types.info
option ;
69 m_is_interface
: bool ; (** true for modules read from interface files *)
70 m_file
: string ; (** the file the module is defined in. *)
71 mutable m_kind
: module_kind
;
72 mutable m_loc
: Odoc_types.location
;
73 mutable m_top_deps
: Name.t list
; (** The toplevels module names this module depends on. *)
74 mutable m_code
: string option ; (** The whole code of the module *)
75 mutable m_code_intf
: string option ; (** The whole code of the interface of the module *)
76 m_text_only
: bool ; (** [true] if the module comes from a text file *)
79 and module_type_alias
= {
81 mutable mta_module
: t_module_type
option ; (** the real module type if we could associate it *)
84 (** Different kinds of module type. *)
85 and module_type_kind
=
86 | Module_type_struct
of module_element list
87 | Module_type_functor
of module_parameter
* module_type_kind
88 | Module_type_alias
of module_type_alias
(** complete name and corresponding module type if we found it *)
89 | Module_type_with
of module_type_kind
* string (** the module type kind and the code of the with constraint *)
91 (** Representation of a module type. *)
94 mutable mt_info
: Odoc_types.info
option ;
95 mutable mt_type
: Types.module_type
option ; (** [None] = abstract module type *)
96 mt_is_interface
: bool ; (** true for modules read from interface files *)
97 mt_file
: string ; (** the file the module type is defined in. *)
98 mutable mt_kind
: module_type_kind
option ; (** [None] = abstract module type if mt_type = None ;
99 Always [None] when the module type was extracted from the implementation file. *)
100 mutable mt_loc
: Odoc_types.location
;
106 (** Returns the list of values from a list of module_element. *)
109 (fun acc
-> fun ele
->
111 Element_value v
-> acc
@ [v
]
117 (** Returns the list of types from a list of module_element. *)
120 (fun acc
-> fun ele
->
122 Element_type t
-> acc
@ [t
]
128 (** Returns the list of exceptions from a list of module_element. *)
131 (fun acc
-> fun ele
->
133 Element_exception e
-> acc
@ [e
]
139 (** Returns the list of classes from a list of module_element. *)
142 (fun acc
-> fun ele
->
144 Element_class c
-> acc
@ [c
]
150 (** Returns the list of class types from a list of module_element. *)
153 (fun acc
-> fun ele
->
155 Element_class_type ct
-> acc
@ [ct
]
161 (** Returns the list of modules from a list of module_element. *)
164 (fun acc
-> fun ele
->
166 Element_module m
-> acc
@ [m
]
172 (** Returns the list of module types from a list of module_element. *)
175 (fun acc
-> fun ele
->
177 Element_module_type mt
-> acc
@ [mt
]
183 (** Returns the list of module comment from a list of module_element. *)
186 (fun acc
-> fun ele
->
188 Element_module_comment t
-> acc
@ [t
]
194 (** Returns the list of included modules from a list of module_element. *)
195 let included_modules l
=
197 (fun acc
-> fun ele
->
199 Element_included_module m
-> acc
@ [m
]
205 (** Returns the list of elements of a module.
206 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
207 let rec module_elements ?
(trans
=true) m
=
208 let rec iter_kind = function
210 print_DEBUG "Odoc_module.module_element: Module_struct";
213 print_DEBUG "Odoc_module.module_element: Module_alias";
215 match ma
.ma_module
with
217 | Some
(Mod m
) -> module_elements m
218 | Some
(Modtype mt
) -> module_type_elements mt
221 | Module_functor
(_
, k
)
222 | Module_apply
(k
, _
) ->
223 print_DEBUG "Odoc_module.module_element: Module_functor ou Module_apply";
225 | Module_with
(tk
,_
) ->
226 print_DEBUG "Odoc_module.module_element: Module_with";
227 module_type_elements ~trans
: trans
228 { mt_name
= "" ; mt_info
= None
; mt_type
= None
;
229 mt_is_interface
= false ; mt_file
= "" ; mt_kind
= Some tk
;
230 mt_loc
= Odoc_types.dummy_loc
;
232 | Module_constraint
(k
, tk
) ->
233 print_DEBUG "Odoc_module.module_element: Module_constraint";
234 (* A VOIR : utiliser k ou tk ? *)
235 module_elements ~trans
: trans
238 m_type
= Types.Tmty_signature
[] ;
239 m_is_interface
= false ; m_file
= "" ; m_kind
= k
;
240 m_loc
= Odoc_types.dummy_loc
;
244 m_text_only
= false ;
247 module_type_elements ~trans: trans
248 { mt_name = "" ; mt_info = None ; mt_type = None ;
249 mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
250 mt_loc = Odoc_types.dummy_loc }
255 (** Returns the list of elements of a module type.
256 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
257 and module_type_elements ?
(trans
=true) mt
=
258 let rec iter_kind = function
260 | Some
(Module_type_struct l
) -> l
261 | Some
(Module_type_functor
(_
, k
)) -> iter_kind (Some k
)
262 | Some
(Module_type_with
(k
, _
)) ->
267 | Some
(Module_type_alias mta
) ->
269 match mta
.mta_module
with
271 | Some mt
-> module_type_elements mt
277 (** Returns the list of values of a module.
278 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
279 let module_values ?
(trans
=true) m
= values (module_elements ~trans m
)
281 (** Returns the list of functional values of a module.
282 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
283 let module_functions ?
(trans
=true) m
=
285 (fun v
-> Odoc_value.is_function v
)
286 (values (module_elements ~trans m
))
288 (** Returns the list of non-functional values of a module.
289 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
290 let module_simple_values ?
(trans
=true) m
=
292 (fun v
-> not
(Odoc_value.is_function v
))
293 (values (module_elements ~trans m
))
295 (** Returns the list of types of a module.
296 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
297 let module_types ?
(trans
=true) m
= types (module_elements ~trans m
)
299 (** Returns the list of excptions of a module.
300 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
301 let module_exceptions ?
(trans
=true) m
= exceptions (module_elements ~trans m
)
303 (** Returns the list of classes of a module.
304 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
305 let module_classes ?
(trans
=true) m
= classes (module_elements ~trans m
)
307 (** Returns the list of class types of a module.
308 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
309 let module_class_types ?
(trans
=true) m
= class_types (module_elements ~trans m
)
311 (** Returns the list of modules of a module.
312 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
313 let module_modules ?
(trans
=true) m
= modules (module_elements ~trans m
)
315 (** Returns the list of module types of a module.
316 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
317 let module_module_types ?
(trans
=true) m
= mod_types (module_elements ~trans m
)
319 (** Returns the list of included module of a module.
320 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
321 let module_included_modules ?
(trans
=true) m
= included_modules (module_elements ~trans m
)
323 (** Returns the list of comments of a module.
324 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
325 let module_comments ?
(trans
=true) m
= comments (module_elements ~trans m
)
327 (** Access to the parameters, for a functor type.
328 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
329 let rec module_type_parameters ?
(trans
=true) mt
=
332 Some
(Module_type_functor
(p
, k2
)) ->
334 (* we create the couple (parameter, description opt), using
335 the description of the parameter if we can find it in the comment.*)
336 match mt
.mt_info
with
340 let d = List.assoc p
.mp_name i
.Odoc_types.i_params
in
346 param :: (iter (Some k2
))
347 | Some
(Module_type_alias mta
) ->
349 match mta
.mta_module
with
351 | Some mt2
-> module_type_parameters ~trans mt2
354 | Some
(Module_type_with
(k
, _
)) ->
359 | Some
(Module_type_struct _
) ->
366 (** Access to the parameters, for a functor.
367 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
368 and module_parameters ?
(trans
=true) m
=
369 let rec iter = function
370 Module_functor
(p
, k
) ->
372 (* we create the couple (parameter, description opt), using
373 the description of the parameter if we can find it in the comment.*)
378 let d = List.assoc p
.mp_name i
.Odoc_types.i_params
in
388 match ma
.ma_module
with
390 | Some
(Mod m
) -> module_parameters ~trans m
391 | Some
(Modtype mt
) -> module_type_parameters ~trans mt
394 | Module_constraint
(k
, tk
) ->
395 module_type_parameters ~trans
: trans
396 { mt_name
= "" ; mt_info
= None
; mt_type
= None
;
397 mt_is_interface
= false ; mt_file
= "" ; mt_kind
= Some tk
;
398 mt_loc
= Odoc_types.dummy_loc
}
406 (** access to all submodules and sudmobules of submodules ... of the given module.
407 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
408 let rec module_all_submodules ?
(trans
=true) m
=
409 let l = module_modules ~trans m
in
411 (fun acc
-> fun m
-> acc
@ (module_all_submodules ~trans m
))
415 (** The module type is a functor if is defined as a functor or if it is an alias for a functor. *)
416 let rec module_type_is_functor mt
=
419 Some
(Module_type_functor _
) -> true
420 | Some
(Module_type_alias mta
) ->
422 match mta
.mta_module
with
424 | Some mtyp
-> module_type_is_functor mtyp
426 | Some
(Module_type_with
(k
, _
)) ->
428 | Some
(Module_type_struct _
)
433 (** The module is a functor if is defined as a functor or if it is an alias for a functor. *)
434 let module_is_functor m
=
435 let rec iter = function
436 Module_functor _
-> true
439 match ma
.ma_module
with
441 | Some
(Mod mo
) -> iter mo
.m_kind
442 | Some
(Modtype mt
) -> module_type_is_functor mt
444 | Module_constraint
(k
, _
) ->
450 (** Returns the list of values of a module type.
451 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
452 let module_type_values ?
(trans
=true) m
= values (module_type_elements ~trans m
)
454 (** Returns the list of types of a module.
455 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
456 let module_type_types ?
(trans
=true) m
= types (module_type_elements ~trans m
)
458 (** Returns the list of excptions of a module.
459 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
460 let module_type_exceptions ?
(trans
=true) m
= exceptions (module_type_elements ~trans m
)
462 (** Returns the list of classes of a module.
463 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
464 let module_type_classes ?
(trans
=true) m
= classes (module_type_elements ~trans m
)
466 (** Returns the list of class types of a module.
467 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
468 let module_type_class_types ?
(trans
=true) m
= class_types (module_type_elements ~trans m
)
470 (** Returns the list of modules of a module.
471 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
472 let module_type_modules ?
(trans
=true) m
= modules (module_type_elements ~trans m
)
474 (** Returns the list of module types of a module.
475 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
476 let module_type_module_types ?
(trans
=true) m
= mod_types (module_type_elements ~trans m
)
478 (** Returns the list of included module of a module.
479 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
480 let module_type_included_modules ?
(trans
=true) m
= included_modules (module_type_elements ~trans m
)
482 (** Returns the list of comments of a module.
483 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
484 let module_type_comments ?
(trans
=true) m
= comments (module_type_elements ~trans m
)
486 (** Returns the list of functional values of a module type.
487 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
488 let module_type_functions ?
(trans
=true) mt
=
490 (fun v
-> Odoc_value.is_function v
)
491 (values (module_type_elements ~trans mt
))
493 (** Returns the list of non-functional values of a module type.
494 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
495 let module_type_simple_values ?
(trans
=true) mt
=
497 (fun v
-> not
(Odoc_value.is_function v
))
498 (values (module_type_elements ~trans mt
))
500 (** {2 Functions for modules and module types} *)
502 (** The list of classes defined in this module and all its modules, functors, ....
503 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
504 let rec module_all_classes ?
(trans
=true) m
=
506 (fun acc
-> fun m
-> acc
@ (module_all_classes ~trans m
))
509 (fun acc
-> fun mtyp
-> acc
@ (module_type_all_classes ~trans mtyp
))
510 (module_classes ~trans m
)
511 (module_module_types ~trans m
)
513 (module_modules ~trans m
)
515 (** The list of classes defined in this module type and all its modules, functors, ....
516 @param trans indicates if, for aliased modules, we must perform a transitive search.*)
517 and module_type_all_classes ?
(trans
=true) mt
=
519 (fun acc
-> fun m
-> acc
@ (module_all_classes ~trans m
))
522 (fun acc
-> fun mtyp
-> acc
@ (module_type_all_classes ~trans mtyp
))
523 (module_type_classes ~trans mt
)
524 (module_type_module_types ~trans mt
)
526 (module_type_modules ~trans mt
)