summaryrefslogtreecommitdiff
path: root/ocamldoc/odoc_value.ml
blob: ee15ace48e14cb1d578603a8ab9a912ce9251959 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
(**************************************************************************)
(*                                                                        *)
(*                                 OCaml                                  *)
(*                                                                        *)
(*             Maxence Guesdon, projet Cristal, INRIA Rocquencourt        *)
(*                                                                        *)
(*   Copyright 2001 Institut National de Recherche en Informatique et     *)
(*     en Automatique.                                                    *)
(*                                                                        *)
(*   All rights reserved.  This file is distributed under the terms of    *)
(*   the GNU Lesser General Public License version 2.1, with the          *)
(*   special exception on linking described in the file LICENSE.          *)
(*                                                                        *)
(**************************************************************************)

(** Representation and manipulation of values, class attributes and class methods. *)

module Name = Odoc_name

(** Types *)

(** Representation of a value. *)
type t_value = {
    val_name : Name.t ;
    mutable val_info : Odoc_types.info option ;
    val_type : Types.type_expr ;
    val_recursive : bool ;
    mutable val_parameters : Odoc_parameter.parameter list ;
    mutable val_code : string option ;
    mutable val_loc : Odoc_types.location ;
  }

(** Representation of a class attribute. *)
type t_attribute = {
    att_value : t_value ; (** an attribute has almost all the same information
                             as a value *)
    att_mutable : bool ;
    att_virtual : bool ;
  }

(** Representation of a class method. *)
type t_method = {
    met_value : t_value ; (** a method has almost all the same information
                             as a value *)
    met_private : bool ;
    met_virtual : bool ;
  }

(** Functions *)

(** Returns the text associated to the given parameter name
   in the given value, or None. *)
let value_parameter_text_by_name v name =
  match v.val_info with
    None -> None
  | Some i ->
      try
        let t = List.assoc name i.Odoc_types.i_params in
        Some t
      with
        Not_found ->
          None

(** Update the parameters text of a t_value, according to the val_info field. *)
let update_value_parameters_text v =
  let f p =
    Odoc_parameter.update_parameter_text (value_parameter_text_by_name v) p
  in
  List.iter f v.val_parameters

(** Create a list of (parameter name, typ) from a type, according to the arrows.
   [parameter_list_from_arrows t = [ a ; b ]] if t = a -> b -> c.*)
let parameter_list_from_arrows typ =
  let rec iter t =
    match Types.get_desc t with
      Types.Tarrow (l, t1, t2, _) ->
        (l, t1) :: (iter t2)
    | Types.Tlink texp
    | Types.Tpoly (texp, _) -> iter texp
    | Types.Tvar _
    | Types.Ttuple _
    | Types.Tconstr _
    | Types.Tobject _
    | Types.Tfield _
    | Types.Tnil
    | Types.Tunivar _
    | Types.Tpackage _
    | Types.Tvariant _ ->
        []
    | Types.Tsubst _ ->
        assert false
  in
  iter typ

(** Create a list of parameters with dummy names "??" from a type list.
   Used when we want to merge the parameters of a value, from the .ml
   and the .mli file. In the .mli file we don't have parameter names
   so there is nothing to merge. With this dummy list we can merge the
   parameter names from the .ml and the type from the .mli file. *)
let dummy_parameter_list typ =
  let normal_name = Odoc_misc.label_name in
  let liste_param = parameter_list_from_arrows typ in
  let rec iter (label, t) =
    match Types.get_desc t with
    | Types.Ttuple l ->
        let open Asttypes in
        if label = Nolabel then
          Odoc_parameter.Tuple
            (List.map (fun t2 -> iter (Nolabel, t2)) l, t)
        else
          (* if there is a label, then we don't want to decompose the tuple *)
          Odoc_parameter.Simple_name
            { Odoc_parameter.sn_name = normal_name label ;
              Odoc_parameter.sn_type = t ;
              Odoc_parameter.sn_text = None }
    | Types.Tlink t2 ->
        (iter (label, t2))
    | Types.Tsubst _ ->
        assert false
    | _ ->
        Odoc_parameter.Simple_name
          { Odoc_parameter.sn_name = normal_name label ;
             Odoc_parameter.sn_type = t ;
            Odoc_parameter.sn_text = None }
  in
  List.map iter liste_param

(** Return true if the value is a function, i.e. has a functional type.*)
let is_function v =
  let rec f t =
    match Types.get_desc t with
      Types.Tarrow _ ->
        true
    | Types.Tlink t ->
        f t
        | _ ->
            false
      in
  f v.val_type