Sys.Signals module for a Variant type of signals (and a set_signal function that...
[ocaml.git] / typing / env.ml
blob3d7f041648ecf69862676545c8c90376880187fc
1 (***********************************************************************)
2 (* *)
3 (* Objective Caml *)
4 (* *)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
6 (* *)
7 (* Copyright 1996 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
10 (* *)
11 (***********************************************************************)
13 (* $Id$ *)
15 (* Environment handling *)
17 open Config
18 open Misc
19 open Asttypes
20 open Longident
21 open Path
22 open Types
25 type error =
26 Not_an_interface of string
27 | Corrupted_interface of string
28 | Illegal_renaming of string * string
29 | Inconsistent_import of string * string * string
30 | Need_recursive_types of string * string
32 exception Error of error
34 type summary =
35 Env_empty
36 | Env_value of summary * Ident.t * value_description
37 | Env_type of summary * Ident.t * type_declaration
38 | Env_exception of summary * Ident.t * exception_declaration
39 | Env_module of summary * Ident.t * module_type
40 | Env_modtype of summary * Ident.t * modtype_declaration
41 | Env_class of summary * Ident.t * class_declaration
42 | Env_cltype of summary * Ident.t * cltype_declaration
43 | Env_open of summary * Path.t
45 type t = {
46 values: (Path.t * value_description) Ident.tbl;
47 constrs: constructor_description Ident.tbl;
48 labels: label_description Ident.tbl;
49 types: (Path.t * type_declaration) Ident.tbl;
50 modules: (Path.t * module_type) Ident.tbl;
51 modtypes: (Path.t * modtype_declaration) Ident.tbl;
52 components: (Path.t * module_components) Ident.tbl;
53 classes: (Path.t * class_declaration) Ident.tbl;
54 cltypes: (Path.t * cltype_declaration) Ident.tbl;
55 summary: summary
58 and module_components = module_components_repr Lazy.t
60 and module_components_repr =
61 Structure_comps of structure_components
62 | Functor_comps of functor_components
64 and structure_components = {
65 mutable comp_values: (string, (value_description * int)) Tbl.t;
66 mutable comp_constrs: (string, (constructor_description * int)) Tbl.t;
67 mutable comp_labels: (string, (label_description * int)) Tbl.t;
68 mutable comp_types: (string, (type_declaration * int)) Tbl.t;
69 mutable comp_modules: (string, (module_type Lazy.t * int)) Tbl.t;
70 mutable comp_modtypes: (string, (modtype_declaration * int)) Tbl.t;
71 mutable comp_components: (string, (module_components * int)) Tbl.t;
72 mutable comp_classes: (string, (class_declaration * int)) Tbl.t;
73 mutable comp_cltypes: (string, (cltype_declaration * int)) Tbl.t
76 and functor_components = {
77 fcomp_param: Ident.t; (* Formal parameter *)
78 fcomp_arg: module_type; (* Argument signature *)
79 fcomp_res: module_type; (* Result signature *)
80 fcomp_env: t; (* Environment in which the result signature makes sense *)
81 fcomp_subst: Subst.t; (* Prefixing substitution for the result signature *)
82 fcomp_cache: (Path.t, module_components) Hashtbl.t (* For memoization *)
85 let empty = {
86 values = Ident.empty; constrs = Ident.empty;
87 labels = Ident.empty; types = Ident.empty;
88 modules = Ident.empty; modtypes = Ident.empty;
89 components = Ident.empty; classes = Ident.empty;
90 cltypes = Ident.empty;
91 summary = Env_empty }
93 let diff_keys tbl1 tbl2 =
94 let keys2 = Ident.keys tbl2 in
95 List.filter
96 (fun id ->
97 match Ident.find_same id tbl2 with Pident _, _ ->
98 (try ignore (Ident.find_same id tbl1); false with Not_found -> true)
99 | _ -> false)
100 keys2
102 let diff env1 env2 =
103 diff_keys env1.values env2.values @
104 diff_keys env1.modules env2.modules @
105 diff_keys env1.classes env2.classes
107 (* Forward declarations *)
109 let components_of_module' =
110 ref ((fun env sub path mty -> assert false) :
111 t -> Subst.t -> Path.t -> module_type -> module_components)
112 let components_of_functor_appl' =
113 ref ((fun f p1 p2 -> assert false) :
114 functor_components -> Path.t -> Path.t -> module_components)
115 let check_modtype_inclusion =
116 (* to be filled with Includemod.check_modtype_inclusion *)
117 ref ((fun env mty1 path1 mty2 -> assert false) :
118 t -> module_type -> Path.t -> module_type -> unit)
120 (* The name of the compilation unit currently compiled.
121 "" if outside a compilation unit. *)
123 let current_unit = ref ""
125 (* Persistent structure descriptions *)
127 type pers_flags = Rectypes
129 type pers_struct =
130 { ps_name: string;
131 ps_sig: signature;
132 ps_comps: module_components;
133 ps_crcs: (string * Digest.t) list;
134 ps_filename: string;
135 ps_flags: pers_flags list }
137 let persistent_structures =
138 (Hashtbl.create 17 : (string, pers_struct) Hashtbl.t)
140 (* Consistency between persistent structures *)
142 let crc_units = Consistbl.create()
144 let check_consistency filename crcs =
146 List.iter
147 (fun (name, crc) -> Consistbl.check crc_units name crc filename)
148 crcs
149 with Consistbl.Inconsistency(name, source, auth) ->
150 raise(Error(Inconsistent_import(name, auth, source)))
152 (* Reading persistent structures from .cmi files *)
154 let read_pers_struct modname filename =
155 let ic = open_in_bin filename in
157 let buffer = String.create (String.length cmi_magic_number) in
158 really_input ic buffer 0 (String.length cmi_magic_number);
159 if buffer <> cmi_magic_number then begin
160 close_in ic;
161 raise(Error(Not_an_interface filename))
162 end;
163 let (name, sign) = input_value ic in
164 let crcs = input_value ic in
165 let flags = input_value ic in
166 close_in ic;
167 let comps =
168 !components_of_module' empty Subst.identity
169 (Pident(Ident.create_persistent name))
170 (Tmty_signature sign) in
171 let ps = { ps_name = name;
172 ps_sig = sign;
173 ps_comps = comps;
174 ps_crcs = crcs;
175 ps_filename = filename;
176 ps_flags = flags } in
177 if ps.ps_name <> modname then
178 raise(Error(Illegal_renaming(ps.ps_name, filename)));
179 check_consistency filename ps.ps_crcs;
180 List.iter
181 (function Rectypes ->
182 if not !Clflags.recursive_types then
183 raise(Error(Need_recursive_types(ps.ps_name, !current_unit))))
184 ps.ps_flags;
185 Hashtbl.add persistent_structures modname ps;
187 with End_of_file | Failure _ ->
188 close_in ic;
189 raise(Error(Corrupted_interface(filename)))
191 let find_pers_struct name =
193 Hashtbl.find persistent_structures name
194 with Not_found ->
195 read_pers_struct name (find_in_path_uncap !load_path (name ^ ".cmi"))
197 let reset_cache () =
198 current_unit := "";
199 Hashtbl.clear persistent_structures;
200 Consistbl.clear crc_units
202 let set_unit_name name =
203 current_unit := name
205 (* Lookup by identifier *)
207 let rec find_module_descr path env =
208 match path with
209 Pident id ->
210 begin try
211 let (p, desc) = Ident.find_same id env.components
212 in desc
213 with Not_found ->
214 if Ident.persistent id
215 then (find_pers_struct (Ident.name id)).ps_comps
216 else raise Not_found
218 | Pdot(p, s, pos) ->
219 begin match Lazy.force(find_module_descr p env) with
220 Structure_comps c ->
221 let (descr, pos) = Tbl.find s c.comp_components in
222 descr
223 | Functor_comps f ->
224 raise Not_found
226 | Papply(p1, p2) ->
227 begin match Lazy.force(find_module_descr p1 env) with
228 Functor_comps f ->
229 !components_of_functor_appl' f p1 p2
230 | Structure_comps c ->
231 raise Not_found
234 let find proj1 proj2 path env =
235 match path with
236 Pident id ->
237 let (p, data) = Ident.find_same id (proj1 env)
238 in data
239 | Pdot(p, s, pos) ->
240 begin match Lazy.force(find_module_descr p env) with
241 Structure_comps c ->
242 let (data, pos) = Tbl.find s (proj2 c) in data
243 | Functor_comps f ->
244 raise Not_found
246 | Papply(p1, p2) ->
247 raise Not_found
249 let find_value =
250 find (fun env -> env.values) (fun sc -> sc.comp_values)
251 and find_type =
252 find (fun env -> env.types) (fun sc -> sc.comp_types)
253 and find_modtype =
254 find (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes)
255 and find_class =
256 find (fun env -> env.classes) (fun sc -> sc.comp_classes)
257 and find_cltype =
258 find (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes)
260 let find_type_expansion path env =
261 let decl = find_type path env in
262 match decl.type_manifest with
263 None -> raise Not_found
264 | Some body -> (decl.type_params, body)
266 let find_modtype_expansion path env =
267 match find_modtype path env with
268 Tmodtype_abstract -> raise Not_found
269 | Tmodtype_manifest mty -> mty
271 let find_module path env =
272 match path with
273 Pident id ->
274 begin try
275 let (p, data) = Ident.find_same id env.modules
276 in data
277 with Not_found ->
278 if Ident.persistent id then
279 let ps = find_pers_struct (Ident.name id) in
280 Tmty_signature(ps.ps_sig)
281 else raise Not_found
283 | Pdot(p, s, pos) ->
284 begin match Lazy.force (find_module_descr p env) with
285 Structure_comps c ->
286 let (data, pos) = Tbl.find s c.comp_modules in Lazy.force data
287 | Functor_comps f ->
288 raise Not_found
290 | Papply(p1, p2) ->
291 raise Not_found (* not right *)
293 (* Lookup by name *)
295 let rec lookup_module_descr lid env =
296 match lid with
297 Lident s ->
298 begin try
299 Ident.find_name s env.components
300 with Not_found ->
301 if s = !current_unit then raise Not_found;
302 let ps = find_pers_struct s in
303 (Pident(Ident.create_persistent s), ps.ps_comps)
305 | Ldot(l, s) ->
306 let (p, descr) = lookup_module_descr l env in
307 begin match Lazy.force descr with
308 Structure_comps c ->
309 let (descr, pos) = Tbl.find s c.comp_components in
310 (Pdot(p, s, pos), descr)
311 | Functor_comps f ->
312 raise Not_found
314 | Lapply(l1, l2) ->
315 let (p1, desc1) = lookup_module_descr l1 env in
316 let (p2, mty2) = lookup_module l2 env in
317 begin match Lazy.force desc1 with
318 Functor_comps f ->
319 !check_modtype_inclusion env mty2 p2 f.fcomp_arg;
320 (Papply(p1, p2), !components_of_functor_appl' f p1 p2)
321 | Structure_comps c ->
322 raise Not_found
325 and lookup_module lid env =
326 match lid with
327 Lident s ->
328 begin try
329 Ident.find_name s env.modules
330 with Not_found ->
331 if s = !current_unit then raise Not_found;
332 let ps = find_pers_struct s in
333 (Pident(Ident.create_persistent s), Tmty_signature ps.ps_sig)
335 | Ldot(l, s) ->
336 let (p, descr) = lookup_module_descr l env in
337 begin match Lazy.force descr with
338 Structure_comps c ->
339 let (data, pos) = Tbl.find s c.comp_modules in
340 (Pdot(p, s, pos), Lazy.force data)
341 | Functor_comps f ->
342 raise Not_found
344 | Lapply(l1, l2) ->
345 let (p1, desc1) = lookup_module_descr l1 env in
346 let (p2, mty2) = lookup_module l2 env in
347 let p = Papply(p1, p2) in
348 begin match Lazy.force desc1 with
349 Functor_comps f ->
350 !check_modtype_inclusion env mty2 p2 f.fcomp_arg;
351 (p, Subst.modtype (Subst.add_module f.fcomp_param p2 f.fcomp_subst)
352 f.fcomp_res)
353 | Structure_comps c ->
354 raise Not_found
357 let lookup proj1 proj2 lid env =
358 match lid with
359 Lident s ->
360 Ident.find_name s (proj1 env)
361 | Ldot(l, s) ->
362 let (p, desc) = lookup_module_descr l env in
363 begin match Lazy.force desc with
364 Structure_comps c ->
365 let (data, pos) = Tbl.find s (proj2 c) in
366 (Pdot(p, s, pos), data)
367 | Functor_comps f ->
368 raise Not_found
370 | Lapply(l1, l2) ->
371 raise Not_found
373 let lookup_simple proj1 proj2 lid env =
374 match lid with
375 Lident s ->
376 Ident.find_name s (proj1 env)
377 | Ldot(l, s) ->
378 let (p, desc) = lookup_module_descr l env in
379 begin match Lazy.force desc with
380 Structure_comps c ->
381 let (data, pos) = Tbl.find s (proj2 c) in
382 data
383 | Functor_comps f ->
384 raise Not_found
386 | Lapply(l1, l2) ->
387 raise Not_found
389 let lookup_value =
390 lookup (fun env -> env.values) (fun sc -> sc.comp_values)
391 and lookup_constructor =
392 lookup_simple (fun env -> env.constrs) (fun sc -> sc.comp_constrs)
393 and lookup_label =
394 lookup_simple (fun env -> env.labels) (fun sc -> sc.comp_labels)
395 and lookup_type =
396 lookup (fun env -> env.types) (fun sc -> sc.comp_types)
397 and lookup_modtype =
398 lookup (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes)
399 and lookup_class =
400 lookup (fun env -> env.classes) (fun sc -> sc.comp_classes)
401 and lookup_cltype =
402 lookup (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes)
404 (* Expand manifest module type names at the top of the given module type *)
406 let rec scrape_modtype mty env =
407 match mty with
408 Tmty_ident path ->
409 begin try
410 scrape_modtype (find_modtype_expansion path env) env
411 with Not_found ->
414 | _ -> mty
416 (* Compute constructor descriptions *)
418 let constructors_of_type ty_path decl =
419 match decl.type_kind with
420 Type_variant(cstrs, priv) ->
421 Datarepr.constructor_descrs
422 (Btype.newgenty (Tconstr(ty_path, decl.type_params, ref Mnil)))
423 cstrs priv
424 | Type_record _ | Type_abstract -> []
426 (* Compute label descriptions *)
428 let labels_of_type ty_path decl =
429 match decl.type_kind with
430 Type_record(labels, rep, priv) ->
431 Datarepr.label_descrs
432 (Btype.newgenty (Tconstr(ty_path, decl.type_params, ref Mnil)))
433 labels rep priv
434 | Type_variant _ | Type_abstract -> []
436 (* Given a signature and a root path, prefix all idents in the signature
437 by the root path and build the corresponding substitution. *)
439 let rec prefix_idents root pos sub = function
440 [] -> ([], sub)
441 | Tsig_value(id, decl) :: rem ->
442 let p = Pdot(root, Ident.name id, pos) in
443 let nextpos = match decl.val_kind with Val_prim _ -> pos | _ -> pos+1 in
444 let (pl, final_sub) = prefix_idents root nextpos sub rem in
445 (p::pl, final_sub)
446 | Tsig_type(id, decl, _) :: rem ->
447 let p = Pdot(root, Ident.name id, nopos) in
448 let (pl, final_sub) =
449 prefix_idents root pos (Subst.add_type id p sub) rem in
450 (p::pl, final_sub)
451 | Tsig_exception(id, decl) :: rem ->
452 let p = Pdot(root, Ident.name id, pos) in
453 let (pl, final_sub) = prefix_idents root (pos+1) sub rem in
454 (p::pl, final_sub)
455 | Tsig_module(id, mty, _) :: rem ->
456 let p = Pdot(root, Ident.name id, pos) in
457 let (pl, final_sub) =
458 prefix_idents root (pos+1) (Subst.add_module id p sub) rem in
459 (p::pl, final_sub)
460 | Tsig_modtype(id, decl) :: rem ->
461 let p = Pdot(root, Ident.name id, nopos) in
462 let (pl, final_sub) =
463 prefix_idents root pos
464 (Subst.add_modtype id (Tmty_ident p) sub) rem in
465 (p::pl, final_sub)
466 | Tsig_class(id, decl, _) :: rem ->
467 let p = Pdot(root, Ident.name id, pos) in
468 let (pl, final_sub) = prefix_idents root (pos + 1) sub rem in
469 (p::pl, final_sub)
470 | Tsig_cltype(id, decl, _) :: rem ->
471 let p = Pdot(root, Ident.name id, nopos) in
472 let (pl, final_sub) = prefix_idents root pos sub rem in
473 (p::pl, final_sub)
475 (* Compute structure descriptions *)
477 let rec components_of_module env sub path mty =
478 lazy(match scrape_modtype mty env with
479 Tmty_signature sg ->
480 let c =
481 { comp_values = Tbl.empty; comp_constrs = Tbl.empty;
482 comp_labels = Tbl.empty; comp_types = Tbl.empty;
483 comp_modules = Tbl.empty; comp_modtypes = Tbl.empty;
484 comp_components = Tbl.empty; comp_classes = Tbl.empty;
485 comp_cltypes = Tbl.empty } in
486 let (pl, sub) = prefix_idents path 0 sub sg in
487 let env = ref env in
488 let pos = ref 0 in
489 List.iter2 (fun item path ->
490 match item with
491 Tsig_value(id, decl) ->
492 let decl' = Subst.value_description sub decl in
493 c.comp_values <-
494 Tbl.add (Ident.name id) (decl', !pos) c.comp_values;
495 begin match decl.val_kind with
496 Val_prim _ -> () | _ -> incr pos
498 | Tsig_type(id, decl, _) ->
499 let decl' = Subst.type_declaration sub decl in
500 c.comp_types <-
501 Tbl.add (Ident.name id) (decl', nopos) c.comp_types;
502 List.iter
503 (fun (name, descr) ->
504 c.comp_constrs <- Tbl.add name (descr, nopos) c.comp_constrs)
505 (constructors_of_type path decl');
506 List.iter
507 (fun (name, descr) ->
508 c.comp_labels <- Tbl.add name (descr, nopos) c.comp_labels)
509 (labels_of_type path decl');
510 env := store_type_infos id path decl !env
511 | Tsig_exception(id, decl) ->
512 let decl' = Subst.exception_declaration sub decl in
513 let cstr = Datarepr.exception_descr path decl' in
514 c.comp_constrs <-
515 Tbl.add (Ident.name id) (cstr, !pos) c.comp_constrs;
516 incr pos
517 | Tsig_module(id, mty, _) ->
518 let mty' = lazy (Subst.modtype sub mty) in
519 c.comp_modules <-
520 Tbl.add (Ident.name id) (mty', !pos) c.comp_modules;
521 let comps = components_of_module !env sub path mty in
522 c.comp_components <-
523 Tbl.add (Ident.name id) (comps, !pos) c.comp_components;
524 env := store_module id path mty !env;
525 incr pos
526 | Tsig_modtype(id, decl) ->
527 let decl' = Subst.modtype_declaration sub decl in
528 c.comp_modtypes <-
529 Tbl.add (Ident.name id) (decl', nopos) c.comp_modtypes;
530 env := store_modtype id path decl !env
531 | Tsig_class(id, decl, _) ->
532 let decl' = Subst.class_declaration sub decl in
533 c.comp_classes <-
534 Tbl.add (Ident.name id) (decl', !pos) c.comp_classes;
535 incr pos
536 | Tsig_cltype(id, decl, _) ->
537 let decl' = Subst.cltype_declaration sub decl in
538 c.comp_cltypes <-
539 Tbl.add (Ident.name id) (decl', !pos) c.comp_cltypes)
540 sg pl;
541 Structure_comps c
542 | Tmty_functor(param, ty_arg, ty_res) ->
543 Functor_comps {
544 fcomp_param = param;
545 (* fcomp_arg must be prefixed eagerly, because it is interpreted
546 in the outer environment, not in env *)
547 fcomp_arg = Subst.modtype sub ty_arg;
548 (* fcomp_res is prefixed lazily, because it is interpreted in env *)
549 fcomp_res = ty_res;
550 fcomp_env = env;
551 fcomp_subst = sub;
552 fcomp_cache = Hashtbl.create 17 }
553 | Tmty_ident p ->
554 Structure_comps {
555 comp_values = Tbl.empty; comp_constrs = Tbl.empty;
556 comp_labels = Tbl.empty; comp_types = Tbl.empty;
557 comp_modules = Tbl.empty; comp_modtypes = Tbl.empty;
558 comp_components = Tbl.empty; comp_classes = Tbl.empty;
559 comp_cltypes = Tbl.empty })
561 (* Insertion of bindings by identifier + path *)
563 and store_value id path decl env =
564 { env with
565 values = Ident.add id (path, decl) env.values;
566 summary = Env_value(env.summary, id, decl) }
568 and store_type id path info env =
569 { env with
570 constrs =
571 List.fold_right
572 (fun (name, descr) constrs ->
573 Ident.add (Ident.create name) descr constrs)
574 (constructors_of_type path info)
575 env.constrs;
576 labels =
577 List.fold_right
578 (fun (name, descr) labels ->
579 Ident.add (Ident.create name) descr labels)
580 (labels_of_type path info)
581 env.labels;
582 types = Ident.add id (path, info) env.types;
583 summary = Env_type(env.summary, id, info) }
585 and store_type_infos id path info env =
586 (* Simplified version of store_type that doesn't compute and store
587 constructor and label infos, but simply record the arity and
588 manifest-ness of the type. Used in components_of_module to
589 keep track of type abbreviations (e.g. type t = float) in the
590 computation of label representations. *)
591 { env with
592 types = Ident.add id (path, info) env.types;
593 summary = Env_type(env.summary, id, info) }
595 and store_exception id path decl env =
596 { env with
597 constrs = Ident.add id (Datarepr.exception_descr path decl) env.constrs;
598 summary = Env_exception(env.summary, id, decl) }
600 and store_module id path mty env =
601 { env with
602 modules = Ident.add id (path, mty) env.modules;
603 components =
604 Ident.add id (path, components_of_module env Subst.identity path mty)
605 env.components;
606 summary = Env_module(env.summary, id, mty) }
608 and store_modtype id path info env =
609 { env with
610 modtypes = Ident.add id (path, info) env.modtypes;
611 summary = Env_modtype(env.summary, id, info) }
613 and store_class id path desc env =
614 { env with
615 classes = Ident.add id (path, desc) env.classes;
616 summary = Env_class(env.summary, id, desc) }
618 and store_cltype id path desc env =
619 { env with
620 cltypes = Ident.add id (path, desc) env.cltypes;
621 summary = Env_cltype(env.summary, id, desc) }
623 (* Compute the components of a functor application in a path. *)
625 let components_of_functor_appl f p1 p2 =
627 Hashtbl.find f.fcomp_cache p2
628 with Not_found ->
629 let p = Papply(p1, p2) in
630 let mty =
631 Subst.modtype (Subst.add_module f.fcomp_param p2 Subst.identity)
632 f.fcomp_res in
633 let comps = components_of_module f.fcomp_env f.fcomp_subst p mty in
634 Hashtbl.add f.fcomp_cache p2 comps;
635 comps
637 (* Define forward functions *)
639 let _ =
640 components_of_module' := components_of_module;
641 components_of_functor_appl' := components_of_functor_appl
643 (* Insertion of bindings by identifier *)
645 let add_value id desc env =
646 store_value id (Pident id) desc env
648 and add_type id info env =
649 store_type id (Pident id) info env
651 and add_exception id decl env =
652 store_exception id (Pident id) decl env
654 and add_module id mty env =
655 store_module id (Pident id) mty env
657 and add_modtype id info env =
658 store_modtype id (Pident id) info env
660 and add_class id ty env =
661 store_class id (Pident id) ty env
663 and add_cltype id ty env =
664 store_cltype id (Pident id) ty env
666 (* Insertion of bindings by name *)
668 let enter store_fun name data env =
669 let id = Ident.create name in (id, store_fun id (Pident id) data env)
671 let enter_value = enter store_value
672 and enter_type = enter store_type
673 and enter_exception = enter store_exception
674 and enter_module = enter store_module
675 and enter_modtype = enter store_modtype
676 and enter_class = enter store_class
677 and enter_cltype = enter store_cltype
679 (* Insertion of all components of a signature *)
681 let add_item comp env =
682 match comp with
683 Tsig_value(id, decl) -> add_value id decl env
684 | Tsig_type(id, decl, _) -> add_type id decl env
685 | Tsig_exception(id, decl) -> add_exception id decl env
686 | Tsig_module(id, mty, _) -> add_module id mty env
687 | Tsig_modtype(id, decl) -> add_modtype id decl env
688 | Tsig_class(id, decl, _) -> add_class id decl env
689 | Tsig_cltype(id, decl, _) -> add_cltype id decl env
691 let rec add_signature sg env =
692 match sg with
693 [] -> env
694 | comp :: rem -> add_signature rem (add_item comp env)
696 (* Open a signature path *)
698 let open_signature root sg env =
699 (* First build the paths and substitution *)
700 let (pl, sub) = prefix_idents root 0 Subst.identity sg in
701 (* Then enter the components in the environment after substitution *)
702 let newenv =
703 List.fold_left2
704 (fun env item p ->
705 match item with
706 Tsig_value(id, decl) ->
707 store_value (Ident.hide id) p
708 (Subst.value_description sub decl) env
709 | Tsig_type(id, decl, _) ->
710 store_type (Ident.hide id) p
711 (Subst.type_declaration sub decl) env
712 | Tsig_exception(id, decl) ->
713 store_exception (Ident.hide id) p
714 (Subst.exception_declaration sub decl) env
715 | Tsig_module(id, mty, _) ->
716 store_module (Ident.hide id) p (Subst.modtype sub mty) env
717 | Tsig_modtype(id, decl) ->
718 store_modtype (Ident.hide id) p
719 (Subst.modtype_declaration sub decl) env
720 | Tsig_class(id, decl, _) ->
721 store_class (Ident.hide id) p
722 (Subst.class_declaration sub decl) env
723 | Tsig_cltype(id, decl, _) ->
724 store_cltype (Ident.hide id) p
725 (Subst.cltype_declaration sub decl) env)
726 env sg pl in
727 { newenv with summary = Env_open(env.summary, root) }
729 (* Open a signature from a file *)
731 let open_pers_signature name env =
732 let ps = find_pers_struct name in
733 open_signature (Pident(Ident.create_persistent name)) ps.ps_sig env
735 (* Read a signature from a file *)
737 let read_signature modname filename =
738 let ps = read_pers_struct modname filename in ps.ps_sig
740 (* Return the CRC of the interface of the given compilation unit *)
742 let crc_of_unit name =
743 let ps = find_pers_struct name in
745 List.assoc name ps.ps_crcs
746 with Not_found ->
747 assert false
749 (* Return the list of imported interfaces with their CRCs *)
751 let imported_units() =
752 Consistbl.extract crc_units
754 (* Save a signature to a file *)
756 let save_signature_with_imports sg modname filename imports =
757 Btype.cleanup_abbrev ();
758 Subst.reset_for_saving ();
759 let sg = Subst.signature (Subst.for_saving Subst.identity) sg in
760 let oc = open_out_bin filename in
762 output_string oc cmi_magic_number;
763 output_value oc (modname, sg);
764 flush oc;
765 let crc = Digest.file filename in
766 let crcs = (modname, crc) :: imports in
767 output_value oc crcs;
768 let flags = if !Clflags.recursive_types then [Rectypes] else [] in
769 output_value oc flags;
770 close_out oc;
771 (* Enter signature in persistent table so that imported_unit()
772 will also return its crc *)
773 let comps =
774 components_of_module empty Subst.identity
775 (Pident(Ident.create_persistent modname)) (Tmty_signature sg) in
776 let ps =
777 { ps_name = modname;
778 ps_sig = sg;
779 ps_comps = comps;
780 ps_crcs = crcs;
781 ps_filename = filename;
782 ps_flags = flags } in
783 Hashtbl.add persistent_structures modname ps;
784 Consistbl.set crc_units modname crc filename
785 with exn ->
786 close_out oc;
787 remove_file filename;
788 raise exn
790 let save_signature sg modname filename =
791 save_signature_with_imports sg modname filename (imported_units())
793 (* Make the initial environment *)
795 let initial = Predef.build_initial_env add_type add_exception empty
797 (* Return the environment summary *)
799 let summary env = env.summary
801 (* Error report *)
803 open Format
805 let report_error ppf = function
806 | Not_an_interface filename -> fprintf ppf
807 "%s@ is not a compiled interface" filename
808 | Corrupted_interface filename -> fprintf ppf
809 "Corrupted compiled interface@ %s" filename
810 | Illegal_renaming(modname, filename) -> fprintf ppf
811 "Wrong file naming: %s@ contains the compiled interface for@ %s"
812 filename modname
813 | Inconsistent_import(name, source1, source2) -> fprintf ppf
814 "@[<hov>The files %s@ and %s@ \
815 make inconsistent assumptions@ over interface %s@]"
816 source1 source2 name
817 | Need_recursive_types(import, export) ->
818 fprintf ppf
819 "@[<hov>Unit %s imports from %s, which uses recursive types.@ %s@]"
820 import export "The compilation flag -rectypes is required"