/
mtype.ml
221 lines (199 loc) · 7.69 KB
/
mtype.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
(***********************************************************************)
(* *)
(* OCaml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed *)
(* under the terms of the Q Public License version 1.0. *)
(* *)
(***********************************************************************)
(* $Id: mtype.ml 12511 2012-05-30 13:29:48Z lefessan $ *)
(* Operations on module types *)
open Asttypes
open Path
open Types
let rec scrape env mty =
match mty with
Mty_ident p ->
begin try
scrape env (Env.find_modtype_expansion p env)
with Not_found ->
mty
end
| _ -> mty
let freshen mty =
Subst.modtype Subst.identity mty
let rec strengthen env mty p =
match scrape env mty with
Mty_signature sg ->
Mty_signature(strengthen_sig env sg p)
| Mty_functor(param, arg, res) when !Clflags.applicative_functors ->
Mty_functor(param, arg, strengthen env res (Papply(p, Pident param)))
| mty ->
mty
and strengthen_sig env sg p =
match sg with
[] -> []
| (Sig_value(id, desc) as sigelt) :: rem ->
sigelt :: strengthen_sig env rem p
| Sig_type(id, decl, rs) :: rem ->
let newdecl =
match decl.type_manifest, decl.type_private, decl.type_kind with
Some _, Public, _ -> decl
| Some _, Private, (Type_record _ | Type_variant _) -> decl
| _ ->
let manif =
Some(Btype.newgenty(Tconstr(Pdot(p, Ident.name id, nopos),
decl.type_params, ref Mnil))) in
if decl.type_kind = Type_abstract then
{ decl with type_private = Public; type_manifest = manif }
else
{ decl with type_manifest = manif }
in
Sig_type(id, newdecl, rs) :: strengthen_sig env rem p
| (Sig_exception(id, d) as sigelt) :: rem ->
sigelt :: strengthen_sig env rem p
| Sig_module(id, mty, rs) :: rem ->
Sig_module(id, strengthen env mty (Pdot(p, Ident.name id, nopos)), rs)
:: strengthen_sig (Env.add_module id mty env) rem p
(* Need to add the module in case it defines manifest module types *)
| Sig_modtype(id, decl) :: rem ->
let newdecl =
match decl with
Modtype_abstract ->
Modtype_manifest(Mty_ident(Pdot(p, Ident.name id, nopos)))
| Modtype_manifest _ ->
decl in
Sig_modtype(id, newdecl) ::
strengthen_sig (Env.add_modtype id decl env) rem p
(* Need to add the module type in case it is manifest *)
| (Sig_class(id, decl, rs) as sigelt) :: rem ->
sigelt :: strengthen_sig env rem p
| (Sig_class_type(id, decl, rs) as sigelt) :: rem ->
sigelt :: strengthen_sig env rem p
(* In nondep_supertype, env is only used for the type it assigns to id.
Hence there is no need to keep env up-to-date by adding the bindings
traversed. *)
type variance = Co | Contra | Strict
let nondep_supertype env mid mty =
let rec nondep_mty env va mty =
match mty with
Mty_ident p ->
if Path.isfree mid p then
nondep_mty env va (Env.find_modtype_expansion p env)
else mty
| Mty_signature sg ->
Mty_signature(nondep_sig env va sg)
| Mty_functor(param, arg, res) ->
let var_inv =
match va with Co -> Contra | Contra -> Co | Strict -> Strict in
Mty_functor(param, nondep_mty env var_inv arg,
nondep_mty (Env.add_module param arg env) va res)
and nondep_sig env va = function
[] -> []
| item :: rem ->
let rem' = nondep_sig env va rem in
match item with
Sig_value(id, d) ->
Sig_value(id, {val_type = Ctype.nondep_type env mid d.val_type;
val_kind = d.val_kind;
val_loc = d.val_loc;
}) :: rem'
| Sig_type(id, d, rs) ->
Sig_type(id, Ctype.nondep_type_decl env mid id (va = Co) d, rs)
:: rem'
| Sig_exception(id, d) ->
let d = {exn_args = List.map (Ctype.nondep_type env mid) d.exn_args;
exn_loc = d.exn_loc} in
Sig_exception(id, d) :: rem'
| Sig_module(id, mty, rs) ->
Sig_module(id, nondep_mty env va mty, rs) :: rem'
| Sig_modtype(id, d) ->
begin try
Sig_modtype(id, nondep_modtype_decl env d) :: rem'
with Not_found ->
match va with
Co -> Sig_modtype(id, Modtype_abstract) :: rem'
| _ -> raise Not_found
end
| Sig_class(id, d, rs) ->
Sig_class(id, Ctype.nondep_class_declaration env mid d, rs)
:: rem'
| Sig_class_type(id, d, rs) ->
Sig_class_type(id, Ctype.nondep_cltype_declaration env mid d, rs)
:: rem'
and nondep_modtype_decl env = function
Modtype_abstract -> Modtype_abstract
| Modtype_manifest mty -> Modtype_manifest(nondep_mty env Strict mty)
in
nondep_mty env Co mty
let enrich_typedecl env p decl =
match decl.type_manifest with
Some ty -> decl
| None ->
try
let orig_decl = Env.find_type p env in
if orig_decl.type_arity <> decl.type_arity
then decl
else {decl with type_manifest =
Some(Btype.newgenty(Tconstr(p, decl.type_params, ref Mnil)))}
with Not_found ->
decl
let rec enrich_modtype env p mty =
match mty with
Mty_signature sg ->
Mty_signature(List.map (enrich_item env p) sg)
| _ ->
mty
and enrich_item env p = function
Sig_type(id, decl, rs) ->
Sig_type(id,
enrich_typedecl env (Pdot(p, Ident.name id, nopos)) decl, rs)
| Sig_module(id, mty, rs) ->
Sig_module(id,
enrich_modtype env (Pdot(p, Ident.name id, nopos)) mty, rs)
| item -> item
let rec type_paths env p mty =
match scrape env mty with
Mty_ident p -> []
| Mty_signature sg -> type_paths_sig env p 0 sg
| Mty_functor(param, arg, res) -> []
and type_paths_sig env p pos sg =
match sg with
[] -> []
| Sig_value(id, decl) :: rem ->
let pos' = match decl.val_kind with Val_prim _ -> pos | _ -> pos + 1 in
type_paths_sig env p pos' rem
| Sig_type(id, decl, _) :: rem ->
Pdot(p, Ident.name id, nopos) :: type_paths_sig env p pos rem
| Sig_module(id, mty, _) :: rem ->
type_paths env (Pdot(p, Ident.name id, pos)) mty @
type_paths_sig (Env.add_module id mty env) p (pos+1) rem
| Sig_modtype(id, decl) :: rem ->
type_paths_sig (Env.add_modtype id decl env) p pos rem
| (Sig_exception _ | Sig_class _) :: rem ->
type_paths_sig env p (pos+1) rem
| (Sig_class_type _) :: rem ->
type_paths_sig env p pos rem
let rec no_code_needed env mty =
match scrape env mty with
Mty_ident p -> false
| Mty_signature sg -> no_code_needed_sig env sg
| Mty_functor(_, _, _) -> false
and no_code_needed_sig env sg =
match sg with
[] -> true
| Sig_value(id, decl) :: rem ->
begin match decl.val_kind with
| Val_prim _ -> no_code_needed_sig env rem
| _ -> false
end
| Sig_module(id, mty, _) :: rem ->
no_code_needed env mty &&
no_code_needed_sig (Env.add_module id mty env) rem
| (Sig_type _ | Sig_modtype _ | Sig_class_type _) :: rem ->
no_code_needed_sig env rem
| (Sig_exception _ | Sig_class _) :: rem ->
false