summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--typing/env.ml153
-rw-r--r--typing/env.mli11
-rw-r--r--typing/predef.ml6
3 files changed, 88 insertions, 82 deletions
diff --git a/typing/env.ml b/typing/env.ml
index 9e825d87a..e72272dcd 100644
--- a/typing/env.ml
+++ b/typing/env.ml
@@ -26,6 +26,7 @@ type error =
Not_an_interface of string
| Corrupted_interface of string
| Illegal_renaming of string * string
+ | Inconsistent_import of string * string * string
exception Error of error
@@ -86,8 +87,7 @@ type pers_struct =
{ ps_name: string;
ps_sig: signature;
ps_comps: module_components;
- ps_crc: Digest.t;
- mutable ps_used: bool }
+ ps_crcs: (string * Digest.t) list }
let persistent_structures =
(Hashtbl.create 17 : (string, pers_struct) Hashtbl.t)
@@ -102,15 +102,15 @@ let read_pers_struct modname filename =
raise(Error(Not_an_interface filename))
end;
let (name, sign, comps) = input_value ic in
+ let crcs = input_value ic in
+ close_in ic;
let ps = { ps_name = name;
ps_sig = sign;
ps_comps = comps;
- ps_crc = Digest.input ic;
- ps_used = false }
- in
- close_in ic;
+ ps_crcs = crcs } in
if ps.ps_name <> modname then
raise(Error(Illegal_renaming(ps.ps_name, filename)));
+ Hashtbl.add persistent_structures modname ps;
ps
with End_of_file | Failure _ ->
close_in ic;
@@ -120,13 +120,8 @@ let find_pers_struct name =
try
Hashtbl.find persistent_structures name
with Not_found ->
- let ps =
- read_pers_struct name
- (find_in_path !load_path (String.uncapitalize name ^ ".cmi")) in
- Hashtbl.add persistent_structures name ps;
- ps
-
-let mark_used = function None -> () | Some ps -> ps.ps_used <- true
+ read_pers_struct name
+ (find_in_path !load_path (String.uncapitalize name ^ ".cmi"))
let reset_cache() =
Hashtbl.clear persistent_structures
@@ -149,66 +144,62 @@ let rec find_module_descr path env =
Pident id ->
begin try
let (p, desc) = Ident.find_same id env.components
- in (desc, None)
+ in desc
with Not_found ->
- if Ident.persistent id then
- let ps = find_pers_struct (Ident.name id) in (ps.ps_comps, Some ps)
+ if Ident.persistent id
+ then (find_pers_struct (Ident.name id)).ps_comps
else raise Not_found
end
| Pdot(p, s, pos) ->
begin match find_module_descr p env with
- (Structure_comps c, ps) ->
+ Structure_comps c ->
let (descr, pos) = Tbl.find s c.comp_components in
- (descr, ps)
- | (Functor_comps f, _) ->
+ descr
+ | Functor_comps f ->
raise Not_found
end
| Papply(p1, p2) ->
begin match find_module_descr p1 env with
- (Functor_comps f, ps) ->
- (!components_of_functor_appl f p1 p2, ps)
- | (Structure_comps c, _) ->
+ Functor_comps f ->
+ !components_of_functor_appl f p1 p2
+ | Structure_comps c ->
raise Not_found
end
-let find proj1 proj2 filter path env =
+let find proj1 proj2 path env =
match path with
Pident id ->
let (p, data) = Ident.find_same id (proj1 env)
- in filter data None
+ in data
| Pdot(p, s, pos) ->
begin match find_module_descr p env with
- (Structure_comps c, ps) ->
- let (data, pos) = Tbl.find s (proj2 c) in filter data ps
- | (Functor_comps f, _) ->
+ Structure_comps c ->
+ let (data, pos) = Tbl.find s (proj2 c) in data
+ | Functor_comps f ->
raise Not_found
end
| Papply(p1, p2) ->
raise Not_found
-let strict_filter data ps =
- mark_used ps; data
-
let find_value =
- find (fun env -> env.values) (fun sc -> sc.comp_values) strict_filter
+ find (fun env -> env.values) (fun sc -> sc.comp_values)
and find_type =
- find (fun env -> env.types) (fun sc -> sc.comp_types) strict_filter
-and find_modtype =
- find (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes) strict_filter
-and find_class =
- find (fun env -> env.classes) (fun sc -> sc.comp_classes) strict_filter
-and find_type_expansion =
find (fun env -> env.types) (fun sc -> sc.comp_types)
- (fun decl ps ->
- match decl.type_manifest with
- None -> raise Not_found
- | Some body -> mark_used ps; (decl.type_params, body))
-and find_modtype_expansion =
+and find_modtype =
find (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes)
- (fun def ps ->
- match def with
- Tmodtype_abstract -> raise Not_found
- | Tmodtype_manifest mty -> mark_used ps; mty)
+and find_class =
+ find (fun env -> env.classes) (fun sc -> sc.comp_classes)
+
+let find_type_expansion path env =
+ let decl = find_type path env in
+ match decl.type_manifest with
+ None -> raise Not_found
+ | Some body -> (decl.type_params, body)
+
+let find_modtype_expansion path env =
+ match find_modtype path env with
+ Tmodtype_abstract -> raise Not_found
+ | Tmodtype_manifest mty -> mty
let find_module path env =
match path with
@@ -219,15 +210,14 @@ let find_module path env =
with Not_found ->
if Ident.persistent id then
let ps = find_pers_struct (Ident.name id) in
- ps.ps_used <- true; Tmty_signature(ps.ps_sig)
+ Tmty_signature(ps.ps_sig)
else raise Not_found
end
| Pdot(p, s, pos) ->
begin match find_module_descr p env with
- (Structure_comps c, ps) ->
- mark_used ps;
+ Structure_comps c ->
let (data, pos) = Tbl.find s c.comp_modules in data
- | (Functor_comps f, _) ->
+ | Functor_comps f ->
raise Not_found
end
| Papply(p1, p2) ->
@@ -242,7 +232,6 @@ let rec lookup_module_descr lid env =
Ident.find_name s env.components
with Not_found ->
let ps = find_pers_struct s in
- ps.ps_used <- true;
(Pident(Ident.create_persistent s), ps.ps_comps)
end
| Ldot(l, s) ->
@@ -272,7 +261,6 @@ and lookup_module lid env =
Ident.find_name s env.modules
with Not_found ->
let ps = find_pers_struct s in
- ps.ps_used <- true;
(Pident(Ident.create_persistent s), Tmty_signature ps.ps_sig)
end
| Ldot(l, s) ->
@@ -684,47 +672,58 @@ let open_signature root sg env =
let open_pers_signature name env =
let ps = find_pers_struct name in
- ps.ps_used <- true;
open_signature (Pident(Ident.create_persistent name)) ps.ps_sig env
(* Read a signature from a file *)
let read_signature modname filename =
- let ps = read_pers_struct modname filename in (ps.ps_sig, ps.ps_crc)
+ let ps = read_pers_struct modname filename in ps.ps_sig
-(* Save a signature to a file *)
+(* Return the list of imported interfaces with their CRCs *)
-let dummy_crc = Digest.string ""
+let imported_units() =
+ let imported_units =
+ ref ([] : (string * Digest.t) list) in
+ let units_xref =
+ (Hashtbl.create 13 : (string, Digest.t * string) Hashtbl.t) in
+ let add_unit source (name, crc) =
+ try
+ let (oldcrc, oldsource) = Hashtbl.find units_xref name in
+ if oldcrc <> crc then
+ raise(Error(Inconsistent_import(name, oldsource, source)))
+ with Not_found ->
+ Hashtbl.add units_xref name (crc, source);
+ imported_units := (name, crc) :: !imported_units in
+ Hashtbl.iter
+ (fun name ps -> List.iter (add_unit ps.ps_name) ps.ps_crcs)
+ persistent_structures;
+ !imported_units
+
+(* Save a signature to a file *)
let save_signature sg modname filename =
Btype.cleanup_abbrev ();
let oc = open_out_bin filename in
output_string oc cmi_magic_number;
- output_value oc
- (modname, sg,
- components_of_module empty Subst.identity
- (Pident(Ident.create_persistent modname)) (Tmty_signature sg));
+ let comps =
+ components_of_module empty Subst.identity
+ (Pident(Ident.create_persistent modname)) (Tmty_signature sg) in
+ output_value oc (modname, sg, comps);
flush oc;
let crc = Digest.file filename in
- Digest.output oc crc;
+ let crcs = (modname, crc) :: imported_units() in
+ output_value oc crcs;
close_out oc;
- crc
+ (* Enter signature in persistent table so that imported_unit()
+ will also return its crc *)
+ let ps =
+ { ps_name = modname; ps_sig = sg; ps_comps = comps; ps_crcs = crcs } in
+ Hashtbl.add persistent_structures modname ps
(* Make the initial environment *)
let initial = Predef.build_initial_env add_type add_exception empty
-(* Return the list of imported interfaces with their CRCs *)
-
-let imported_units() =
- let imported_units = ref [] in
- Hashtbl.iter
- (fun _ ps ->
- if ps.ps_used then
- imported_units := (ps.ps_name, ps.ps_crc) :: !imported_units)
- persistent_structures;
- !imported_units
-
(* Return the environment summary *)
let summary env = env.summary
@@ -743,4 +742,10 @@ let report_error = function
print_string filename; print_space();
print_string "contains the compiled interface for"; print_space();
print_string modname
-
+ | Inconsistent_import(name, source1, source2) ->
+ open_hvbox 0;
+ print_string "The compiled interfaces for "; print_string source1;
+ print_string " and "; print_string source2; print_space();
+ print_string "make inconsistent assumptions over interface ";
+ print_string name;
+ close_box()
diff --git a/typing/env.mli b/typing/env.mli
index fee611e8d..d3d0ee7f7 100644
--- a/typing/env.mli
+++ b/typing/env.mli
@@ -77,12 +77,10 @@ val reset_cache: unit -> unit
(* Read, save a signature to/from a file *)
-val read_signature: string -> string -> signature * Digest.t
- (* Arguments: module name, file name.
- Results: signature, CRC. *)
-val save_signature: signature -> string -> string -> Digest.t
- (* Arguments: signature, module name, file name.
- Result: CRC. *)
+val read_signature: string -> string -> signature
+ (* Arguments: module name, file name. Results: signature. *)
+val save_signature: signature -> string -> string -> unit
+ (* Arguments: signature, module name, file name. *)
(* Return the set of compilation units imported, with their CRC *)
@@ -109,6 +107,7 @@ type error =
Not_an_interface of string
| Corrupted_interface of string
| Illegal_renaming of string * string
+ | Inconsistent_import of string * string * string
exception Error of error
diff --git a/typing/predef.ml b/typing/predef.ml
index fc776a0ff..16223de7a 100644
--- a/typing/predef.ml
+++ b/typing/predef.ml
@@ -57,6 +57,7 @@ and ident_not_found = Ident.create "Not_found"
and ident_sys_error = Ident.create "Sys_error"
and ident_end_of_file = Ident.create "End_of_file"
and ident_division_by_zero = Ident.create "Division_by_zero"
+and ident_stack_overflow = Ident.create "Stack_overflow"
let path_match_failure = Pident ident_match_failure
@@ -102,6 +103,7 @@ let build_initial_env add_type add_exception empty_env =
add_exception ident_match_failure
[newgenty (Ttuple[type_string; type_int; type_int])] (
add_exception ident_out_of_memory [] (
+ add_exception ident_stack_overflow [] (
add_exception ident_invalid_argument [type_string] (
add_exception ident_failure [type_string] (
add_exception ident_not_found [] (
@@ -118,11 +120,11 @@ let build_initial_env add_type add_exception empty_env =
add_type ident_string decl_abstr (
add_type ident_char decl_abstr (
add_type ident_int decl_abstr (
- empty_env))))))))))))))))))
+ empty_env)))))))))))))))))))
let builtin_values =
List.map (fun id -> Ident.make_global id; (Ident.name id, id))
- [ident_match_failure; ident_out_of_memory;
+ [ident_match_failure; ident_out_of_memory; ident_stack_overflow;
ident_invalid_argument;
ident_failure; ident_not_found; ident_sys_error; ident_end_of_file;
ident_division_by_zero]