-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathitem.ml
355 lines (316 loc) · 10.2 KB
/
item.ml
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
(* CR jfuruse: Elem or Item ?*)
open Spotlib.Spot
open List
(* open Asttypes *)
open Ocaml_conv
open Stype_core
type virtual_flag = Asttypes.virtual_flag = Virtual | Concrete with conv(ocaml)
type private_flag = Asttypes.private_flag = Private | Public with conv(ocaml)
type 'typ kind =
| Class
| ClassType
| ClassField of virtual_flag * 'typ
| Constr of 'typ
| Exception of 'typ
| Field of 'typ
| Method of private_flag * virtual_flag * 'typ
| ModType
| Module
| Type of 'typ list (** type params *) * 'typ option * [ `Abstract | `Record | `Variant ]
| Value of 'typ
| Package of OCamlFind.Package.t * string list (** Ex. [ "Dbm" ] *)
with conv(ocaml)
let kindkey_of_kind = function
| Class -> `Class
| ClassType -> `ClassType
| ClassField _ -> `ClassField
| Constr _ -> `Constr
| Exception _ -> `Exception
| Field _ -> `Field
| Method _ -> `Method
| ModType -> `ModType
| Module -> `Module
| Type _ -> `Type
| Value _ -> `Value
| Package _ -> `Package
let name_of_kind x = Kindkey.to_string & kindkey_of_kind x
let types_of_kind = function
| ClassField (_, ty)
| Constr ty
| Exception ty
| Field ty
| Value ty
| Method (_, _, ty) -> [ty]
| Type (tys, Some ty, _) -> ty :: tys
| Type (tys, None, _) -> tys
| Class
| ClassType
| ModType
| Module
| Package _ -> []
type ('packs, 'path, 'loc, 'doc, 'typ) record = {
packs : 'packs;
path : 'path;
loc : 'loc;
doc : 'doc;
kind : 'typ kind;
} with conv(ocaml)
type ('a, 'b) result_t = [ `Ok of 'a | `Error of 'b ] with conv(ocaml) (* = Result.t *)
let rebind_error x = function
| `Ok v -> `Ok v
| `Error s -> `Error (Meta_conv.Error.Primitive_decoding_failure s, x, [`Node x])
type spath_t = Spath.t
let ocaml_of_spath_t l = Ocaml_conv.ocaml_of_string & Spath.show l
let spath_t_of_ocaml ?trace x =
let open Result in
Ocaml_conv.string_of_ocaml ?trace x >>= fun y ->
rebind_error x (Spath.read y)
let _spath_t_of_ocaml_exn = Ocaml_conv.exn spath_t_of_ocaml
type stype_t = Stype.t
let ocaml_of_stype_t l = Ocaml_conv.ocaml_of_string & Stype_print.show l
let stype_t_of_ocaml ?trace x =
let open Result in
Ocaml_conv.string_of_ocaml ?trace x
>>= fun y -> rebind_error x (Stype_print.read y)
let _stype_t_of_ocaml_exn = Ocaml_conv.exn stype_t_of_ocaml
type pooled_type =
| Not_pooled of stype_t
| Pooled of int
with conv(ocaml)
type t = (OCamlFind.Packages.t,
spath_t,
Loc.t option,
(OCamlDoc.t option, unit) result_t,
stype_t) record
with conv(ocaml)
type pooled = (OCamlFind.Packages.t,
spath_t,
Loc.t option,
(OCamlDoc.t option, unit) result_t,
pooled_type) record
with conv(ocaml)
(* do not hcons itself: It is unlikely we have duped kinds throughout items *)
let rec_hcons_k p = function
| ClassField (vf, ty) -> ClassField (vf, Stype.rec_hcons ty)
| Constr ty -> Constr (Stype.rec_hcons ty)
| Exception ty -> Exception (Stype.rec_hcons ty)
| Field ty -> Field (Stype.rec_hcons ty)
| Method (pf, vf, ty) -> Method (pf, vf, Stype.rec_hcons ty)
| Type (tys, tyopt, attr) ->
let tys = map Stype.rec_hcons tys in
let tyopt = Option.map Stype.rec_hcons tyopt in
let {Stype_core.dt_aliases= alias} = Stype_hcons.rec_hcons_datatype {dt_path= Spath.rec_hcons p; dt_aliases= ref None} in
begin
let new_alias =
match tyopt with
| None -> None
| Some ty ->
(*
!!% "LOG: data type %a has an alias!@." (Spath.format ()) p;
*)
Some (tys, ty)
in
match !alias with
| None -> alias := Some new_alias
| Some _ ->
!!% "@[<2>WARNING: data type %a has more than one aliases!@."
(Spath.format ()) p;
(* CR jfuruse:
WARNING: data type {core_kernel#74}.Core_kernel.Std.Hashtbl_intf.Hashable.t has more than one aliases!
include Std_kernel
include Std_common
Both Std_kernel and Std_common has Hashtbl_intf.Hashable.t I guess. Shadowing must be implemented.
*)
alias := Some new_alias
end;
Type (tys, tyopt, attr)
| Value ty -> Value (Stype.rec_hcons ty)
| (Class | ClassType | ModType | Module as k) -> k
| Package (p, paths) -> Package (p, map Hcons.string paths)
let rec_hcons i =
let p = Spath.rec_hcons i.path in
{ i with
path= p;
loc= Option.map Loc.rec_hcons i.loc;
kind= rec_hcons_k p i.kind;
}
let format_gen ?(dont_omit_opened=false) ppf { packs; path; loc; doc; kind } =
let open Format in
let rec get_opened = function
| Spath.SPdot (p, _) -> Some p
| SPattr (_, p) -> get_opened p
| _ -> None
in
let opened =
if dont_omit_opened then None
else
match kind with
| Method _ ->
(* P.cls.m : P is opened *)
Option.bind (get_opened path) get_opened
| _ -> get_opened path
in
let format_stype = Stype.format_gen (fun x -> Spath.print ?opened x) in
let format_stype_param ppf = function
| VarNamed (_, "_") -> string ppf "_"
| ty -> format_stype ppf ty
in
let format_packs ppf ps =
fprintf ppf "@[Packs:@ @[%a@]@]"
(Format.list ",@ " Format.string)
(OCamlFind.Packages.to_strings ps)
in
let format_doc ppf = function
| `Ok None -> ()
| `Ok (Some info) -> fprintf ppf "Doc: @[%a@]" OCamlDoc.format info
| `Error () -> fprintf ppf "Doc: failed"
in
match kind with
| Value ty ->
fprintf ppf "@[<v>%a:@ val @[%a@ : @[%a@]@]@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_stype ty
format_packs packs
format_doc doc
| Exception ty ->
fprintf ppf "@[<v>%a:@ exception @[%a@ : @[%a@]@]@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_stype ty
format_packs packs
format_doc doc
| Module ->
fprintf ppf "@[<v>%a:@ module %a@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_packs packs
format_doc doc
| ModType ->
fprintf ppf "@[<v>%a:@ module type %a@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_packs packs
format_doc doc
| ClassType ->
fprintf ppf "@[<v>%a:@ class type %a@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_packs packs
format_doc doc
| Type (params, tyop, k) ->
fprintf ppf "@[<v>%a:@ @[<v2>type %a%a %t@]@ %a@ %a@]"
(Format.option Loc.format) loc
(fun ppf -> function
| [] -> ()
| [param] -> format_stype_param ppf param; string ppf " "
| params ->
fprintf ppf "(@[%a@]) "
(Format.list ",@ " format_stype) params) params
(Spath.format ()) path
(fun ppf ->
match tyop, k with
| None, `Abstract -> pp_print_string ppf "(* abstract *)"
| None, `Record -> pp_print_string ppf "= { .. }"
| None, `Variant -> pp_print_string ppf "= .. | .."
| Some ty, `Abstract ->
fprintf ppf "=@ @[%a@]" format_stype ty
| Some ty, `Record ->
fprintf ppf "= @[%a@] =@ { .. }" format_stype ty
| Some ty, `Variant ->
fprintf ppf "= @[%a@] =@ .. | .." format_stype ty)
format_packs packs
format_doc doc
| Constr ty ->
fprintf ppf "@[<v>%a:@ constr @[%a@ : @[%a@]@]@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_stype ty
format_packs packs
format_doc doc
| Field ty ->
fprintf ppf "@[<v>%a:@ field @[%a@ : @[%a@]@]@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_stype ty
format_packs packs
format_doc doc
| Class ->
fprintf ppf "@[<v>%a:@ class %a@ %a@ %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
format_packs packs
format_doc doc
| ClassField (v, ty) ->
fprintf ppf "@[<v>%a:@ class val%s @[%a@ : @[%a@]@]@ %a@ %a@]"
(Format.option Loc.format) loc
(match v with Virtual -> " virtual" | Concrete -> "")
(Spath.format ()) path
format_stype ty
format_packs packs
format_doc doc
| Method (p, v, ty) ->
fprintf ppf "@[<v>%a:@ method%s @[%a@ : @[%a@]@]@ %a@ %a@]"
(Format.option Loc.format) loc
(match p, v with
| Private, Virtual -> " private virtual"
| Private, Concrete -> " private"
| Public, Virtual -> " virtual"
| Public, Concrete -> ""
)
(Spath.format ()) path
format_stype ty
format_packs packs
format_doc doc
| Package (_p, _mods) -> (* CR jfuruse: todo *)
fprintf ppf "@[<v>%a:@ package %a@]"
(Format.option Loc.format) loc
(Spath.format ()) path
let format = format_gen ~dont_omit_opened:false
let type_of_item i = match i.kind with
| ClassField (_, ty)
| Constr ty
| Exception ty
| Field ty
| Value ty
| Method (_, _, ty)
| Type (_, Some ty, _) -> Some ty
| Type (_, None, _)
| Class
| ClassType
| ModType
| Module
| Package _ -> None
let arity_of_item i =
match type_of_item i with
| None -> -1
| Some ty -> length & fst & Stype.get_arrows ty
let sort_items_by_arity items =
Array.sort (fun x y ->
compare (arity_of_item x) (arity_of_item y)) items;
items
(* CR jfuruse: not used *)
let pack_types items =
let module M = struct
include Hashtbl.Make(Stype_hcons.HashedType)
let to_list t =
let r = ref [] in
iter (fun k v -> r +::= (k,v)) t;
!r
end in
let tbl = M.create 1023 in
let ids = UniqueID.create () in
Array.iter (fun i ->
match type_of_item i with
| None -> ()
| Some ty ->
try
let (id, count) = M.find tbl ty in
M.replace tbl ty (id, count+1)
with
| Not_found ->
let id = UniqueID.get ids in
M.add tbl ty (id, 1)) items;
!!% "%d different types@." & M.length tbl;
let sorted = List.sort (fun (_, (_,c)) (_, (_,c')) -> compare c' c) & M.to_list tbl in
iter (fun (_k, (_,c)) -> !!% "%d@." c) sorted