Source file ptyp_of_type.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
open Std
open Typedtree
open Types
let var_of_id id = Location.mknoloc @@ Ident.name id
type signature_elt =
| Item of Types.signature_item
| Type of Asttypes.rec_flag * Parsetree.type_declaration list
let rec module_type =
let open Ast_helper in
function
| Mty_for_hole -> failwith "Holes are not allowed in module types"
| Mty_signature signature_items -> Mty.signature @@ signature signature_items
| Mty_ident path ->
Ast_helper.Mty.ident (Location.mknoloc (Untypeast.lident_of_path path))
| Mty_alias path ->
Ast_helper.Mty.alias (Location.mknoloc (Untypeast.lident_of_path path))
| Mty_functor (param, type_out) ->
let param =
match param with
| Unit -> Parsetree.Unit
| Named (id, type_in) ->
Parsetree.Named
(Location.mknoloc (Option.map ~f:Ident.name id), module_type type_in)
in
let out = module_type type_out in
Mty.functor_ param out
and core_type type_expr =
let open Ast_helper in
match Types.get_desc type_expr with
| Tvar None | Tunivar None -> Typ.any ()
| Tvar (Some s) | Tunivar (Some s) -> Typ.var s
| Tarrow (label, type_expr, type_expr_out, _commutable) ->
Typ.arrow label (core_type type_expr) (core_type type_expr_out)
| Ttuple type_exprs -> Typ.tuple @@ List.map ~f:core_type type_exprs
| Tconstr (path, type_exprs, _abbrev) ->
let loc = Untypeast.lident_of_path path |> Location.mknoloc in
Typ.constr loc @@ List.map ~f:core_type type_exprs
| Tobject (type_expr, _class_) ->
let rec aux acc type_expr =
match get_desc type_expr with
| Tnil -> (acc, Asttypes.Closed)
| Tvar None | Tunivar None -> (acc, Asttypes.Open)
| Tfield ("*dummy method*", _, _, fields) -> aux acc fields
| Tfield (name, _, type_expr, fields) ->
let open Ast_helper in
let core_type = core_type type_expr in
let core_type = Of.tag (Location.mknoloc name) core_type in
aux (core_type :: acc) fields
| _ ->
failwith
@@ Format.asprintf "Unexpected type constructor in fields list: %a"
Printtyp.type_expr type_expr
in
let fields, closed = aux [] type_expr in
Typ.object_ fields closed
| Tfield _ -> failwith "Found object field outside of object."
| Tnil -> Typ.object_ [] Closed
| Tlink type_expr | Tsubst (type_expr, _) -> core_type type_expr
| Tvariant row ->
let row_fields = row_fields row in
let row_closed = row_closed row in
let field (label, row_field) =
let label = Location.mknoloc label in
match row_field_repr row_field with
| Rpresent None | Reither (true, _, _) -> Rf.tag label true []
| Rpresent (Some type_expr) ->
let core_type = core_type type_expr in
Rf.tag label false [ core_type ]
| Reither (false, type_exprs, _) ->
Rf.tag label false @@ List.map ~f:core_type type_exprs
| Rabsent -> assert false
in
let closed = if row_closed then Asttypes.Closed else Asttypes.Open in
let fields = List.map ~f:field row_fields in
Typ.variant fields closed None
| Tpoly (type_expr, type_exprs) ->
let names =
List.map
~f:(fun v ->
match get_desc v with
| Tunivar (Some name) | Tvar (Some name) -> mknoloc name
| _ -> failwith "poly: not a var")
type_exprs
in
Typ.poly names @@ core_type type_expr
| Tpackage (path, lids_type_exprs) ->
let loc = mknoloc (Untypeast.lident_of_path path) in
let args =
List.map lids_type_exprs ~f:(fun (id, t) -> (mknoloc id, core_type t))
in
Typ.package loc args
and modtype_declaration id { mtd_type; mtd_attributes; _ } =
Ast_helper.Mtd.mk ~attrs:mtd_attributes
?typ:(Option.map ~f:module_type mtd_type)
(var_of_id id)
and module_declaration id { md_type; md_attributes; _ } =
let name = Location.mknoloc (Some (Ident.name id)) in
Ast_helper.Md.mk ~attrs:md_attributes name @@ module_type md_type
and extension_constructor id { ext_args; ext_ret_type; ext_attributes; _ } =
Ast_helper.Te.decl ~attrs:ext_attributes
~args:(constructor_arguments ext_args)
?res:(Option.map ~f:core_type ext_ret_type)
(var_of_id id)
and value_description id { val_type; val_kind = _; val_loc; val_attributes; _ }
=
let type_ = core_type val_type in
{ Parsetree.pval_name = var_of_id id;
pval_type = type_;
pval_prim = [];
pval_attributes = val_attributes;
pval_loc = val_loc
}
and label_declaration { ld_id; ld_mutable; ld_type; ld_attributes; _ } =
Ast_helper.Type.field ~attrs:ld_attributes ~mut:ld_mutable (var_of_id ld_id)
(core_type ld_type)
and constructor_arguments = function
| Cstr_tuple type_exprs ->
Parsetree.Pcstr_tuple (List.map ~f:core_type type_exprs)
| Cstr_record label_decls ->
Parsetree.Pcstr_record (List.map ~f:label_declaration label_decls)
and constructor_declaration { cd_id; cd_args; cd_res; cd_attributes; _ } =
Ast_helper.Type.constructor ~attrs:cd_attributes
~args:(constructor_arguments cd_args)
?res:(Option.map ~f:core_type cd_res)
@@ var_of_id cd_id
and type_declaration id
{ type_params;
type_variance;
type_manifest;
type_kind;
type_attributes;
type_private;
_
} =
let params =
List.map2 type_params type_variance ~f:(fun type_ variance ->
let core_type = core_type type_ in
let pos, neg, inj = Types.Variance.get_lower variance in
let v =
if pos then Asttypes.Covariant
else if neg then Contravariant
else NoVariance
in
let i = if inj then Asttypes.Injective else NoInjectivity in
(core_type, (v, i)))
in
let kind =
match type_kind with
| Type_abstract -> Parsetree.Ptype_abstract
| Type_open -> Ptype_open
| Type_variant (constrs, _) ->
Ptype_variant (List.map ~f:constructor_declaration constrs)
| Type_record (labels, _repr) ->
Ptype_record (List.map ~f:label_declaration labels)
in
let manifest = Option.map ~f:core_type type_manifest in
Ast_helper.Type.mk ~attrs:type_attributes ~params ~kind ~priv:type_private
?manifest (var_of_id id)
and signature_item (str_item : Types.signature_item) =
let open Ast_helper in
match str_item with
| Sig_value (id, vd, _visibility) ->
let vd = value_description id vd in
Sig.value vd
| Sig_type (id, type_decl, rec_flag, _visibility) ->
let rec_flag =
match rec_flag with
| Trec_first -> Asttypes.Recursive
| Trec_next -> Asttypes.Recursive
| Trec_not -> Nonrecursive
in
Sig.type_ rec_flag [ type_declaration id type_decl ]
| Sig_modtype (id, modtype_decl, _visibility) ->
Sig.modtype @@ modtype_declaration id modtype_decl
| Sig_module (id, _, mod_decl, _, _) ->
Sig.module_ @@ module_declaration id mod_decl
| Sig_typext (id, ext_constructor, _, _) ->
let ext =
Te.mk
(Location.mknoloc @@ Longident.Lident (Ident.name id))
[ extension_constructor id ext_constructor ]
in
Sig.type_extension ext
| Sig_class_type (id, _, _, _) ->
let str =
Format.asprintf
"Construct does not handle class types yet. Please replace this \
comment by [%s]'s definition."
(Ident.name id)
in
Sig.text [ Docstrings.docstring str Location.none ] |> List.hd
| Sig_class (id, _, _, _) ->
let str =
Format.asprintf
"Construct does not handle classes yet. Please replace this comment by \
[%s]'s definition."
(Ident.name id)
in
Sig.text [ Docstrings.docstring str Location.none ] |> List.hd
and signature (items : Types.signature_item list) =
List.map (group_items items) ~f:(function
| Item item -> signature_item item
| Type (rec_flag, type_decls) -> Ast_helper.Sig.type_ rec_flag type_decls)
and group_items (items : Types.signature_item list) =
let rec read_type type_acc items =
match items with
| Sig_type (id, type_decl, Trec_next, _) :: rest ->
let td = type_declaration id type_decl in
read_type (td :: type_acc) rest
| _ -> (List.rev type_acc, items)
in
let rec group acc items =
match items with
| Sig_type (id, type_decl, Trec_first, _) :: rest ->
let type_, rest = read_type [ type_declaration id type_decl ] rest in
group (Type (Asttypes.Recursive, type_) :: acc) rest
| Sig_type (id, type_decl, Trec_not, _) :: rest ->
let type_, rest = read_type [ type_declaration id type_decl ] rest in
group (Type (Asttypes.Nonrecursive, type_) :: acc) rest
| (Sig_class _ as item) :: _ :: _ :: rest -> group (Item item :: acc) rest
| (Sig_class_type _ as item) :: _ :: rest -> group (Item item :: acc) rest
| item :: rest -> group (Item item :: acc) rest
| [] -> List.rev acc
in
group [] items