1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Type-checking of the module language *)
|
|
|
|
|
|
|
|
open Misc
|
1995-09-28 03:42:38 -07:00
|
|
|
open Longident
|
1995-05-04 03:15:53 -07:00
|
|
|
open Path
|
2006-04-04 19:28:13 -07:00
|
|
|
open Asttypes
|
1995-05-04 03:15:53 -07:00
|
|
|
open Parsetree
|
1996-09-23 04:33:27 -07:00
|
|
|
open Types
|
1995-05-04 03:15:53 -07:00
|
|
|
open Typedtree
|
2000-03-06 14:12:09 -08:00
|
|
|
open Format
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
type error =
|
2010-05-18 10:18:24 -07:00
|
|
|
Cannot_apply of module_type
|
1995-05-04 03:15:53 -07:00
|
|
|
| Not_included of Includemod.error list
|
|
|
|
| Cannot_eliminate_dependency of module_type
|
|
|
|
| Signature_expected
|
|
|
|
| Structure_expected of module_type
|
1995-10-01 06:39:43 -07:00
|
|
|
| With_no_component of Longident.t
|
1996-07-25 06:18:53 -07:00
|
|
|
| With_mismatch of Longident.t * Includemod.error list
|
1995-08-28 04:23:33 -07:00
|
|
|
| Repeated_name of string * string
|
1995-09-02 11:55:37 -07:00
|
|
|
| Non_generalizable of type_expr
|
1998-06-24 12:22:26 -07:00
|
|
|
| Non_generalizable_class of Ident.t * class_declaration
|
1996-05-22 09:22:33 -07:00
|
|
|
| Non_generalizable_module of module_type
|
2004-04-09 06:32:28 -07:00
|
|
|
| Implementation_is_required of string
|
2004-06-13 05:48:01 -07:00
|
|
|
| Interface_not_compiled of string
|
2009-10-26 03:53:16 -07:00
|
|
|
| Not_allowed_in_functor_body
|
2010-04-17 07:45:12 -07:00
|
|
|
| With_need_typeconstr
|
2010-10-21 16:59:33 -07:00
|
|
|
| Not_a_packed_module of type_expr
|
|
|
|
| Incomplete_packed_module of type_expr
|
2011-12-14 02:26:15 -08:00
|
|
|
| Scoping_pack of Longident.t * type_expr
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
exception Error of Location.t * error
|
|
|
|
|
|
|
|
(* Extract a signature from a module type *)
|
|
|
|
|
|
|
|
let extract_sig env loc mty =
|
|
|
|
match Mtype.scrape env mty with
|
|
|
|
Tmty_signature sg -> sg
|
|
|
|
| _ -> raise(Error(loc, Signature_expected))
|
|
|
|
|
|
|
|
let extract_sig_open env loc mty =
|
|
|
|
match Mtype.scrape env mty with
|
|
|
|
Tmty_signature sg -> sg
|
|
|
|
| _ -> raise(Error(loc, Structure_expected mty))
|
|
|
|
|
2009-11-01 13:52:29 -08:00
|
|
|
(* Compute the environment after opening a module *)
|
|
|
|
|
|
|
|
let type_open env loc lid =
|
2010-05-18 10:14:31 -07:00
|
|
|
let (path, mty) = Typetexp.find_module env loc lid in
|
2009-11-01 13:52:29 -08:00
|
|
|
let sg = extract_sig_open env loc mty in
|
2011-12-22 03:04:20 -08:00
|
|
|
Env.open_signature ~loc path sg env
|
2009-11-01 13:52:29 -08:00
|
|
|
|
2003-04-01 22:57:15 -08:00
|
|
|
(* Record a module type *)
|
|
|
|
let rm node =
|
|
|
|
Stypes.record (Stypes.Ti_mod node);
|
|
|
|
node
|
|
|
|
|
2010-04-02 05:53:33 -07:00
|
|
|
(* Forward declaration, to be filled in by type_module_type_of *)
|
|
|
|
let type_module_type_of_fwd
|
|
|
|
: (Env.t -> Parsetree.module_expr -> module_type) ref
|
|
|
|
= ref (fun env m -> assert false)
|
|
|
|
|
1995-09-28 03:42:38 -07:00
|
|
|
(* Merge one "with" constraint in a signature *)
|
|
|
|
|
2005-03-22 19:08:37 -08:00
|
|
|
let rec add_rec_types env = function
|
|
|
|
Tsig_type(id, decl, Trec_next) :: rem ->
|
|
|
|
add_rec_types (Env.add_type id decl env) rem
|
|
|
|
| _ -> env
|
|
|
|
|
|
|
|
let check_type_decl env id row_id newdecl decl rs rem =
|
|
|
|
let env = Env.add_type id newdecl env in
|
|
|
|
let env =
|
|
|
|
match row_id with None -> env | Some id -> Env.add_type id newdecl env in
|
|
|
|
let env = if rs = Trec_not then env else add_rec_types env rem in
|
|
|
|
Includemod.type_declarations env id newdecl decl
|
|
|
|
|
2010-04-17 07:45:12 -07:00
|
|
|
let rec make_params n = function
|
|
|
|
[] -> []
|
|
|
|
| _ :: l -> ("a" ^ string_of_int n) :: make_params (n+1) l
|
|
|
|
|
|
|
|
let wrap_param s = {ptyp_desc=Ptyp_var s; ptyp_loc=Location.none}
|
|
|
|
|
2011-07-20 02:17:07 -07:00
|
|
|
let make_next_first rs rem =
|
|
|
|
if rs = Trec_first then
|
|
|
|
match rem with
|
|
|
|
Tsig_type (id, decl, Trec_next) :: rem ->
|
|
|
|
Tsig_type (id, decl, Trec_first) :: rem
|
|
|
|
| Tsig_module (id, mty, Trec_next) :: rem ->
|
|
|
|
Tsig_module (id, mty, Trec_first) :: rem
|
|
|
|
| _ -> rem
|
|
|
|
else rem
|
|
|
|
|
1996-07-25 06:18:53 -07:00
|
|
|
let merge_constraint initial_env loc sg lid constr =
|
2010-04-17 07:45:12 -07:00
|
|
|
let real_id = ref None in
|
2005-03-22 19:08:37 -08:00
|
|
|
let rec merge env sg namelist row_id =
|
1995-10-01 06:39:43 -07:00
|
|
|
match (sg, namelist, constr) with
|
|
|
|
([], _, _) ->
|
|
|
|
raise(Error(loc, With_no_component lid))
|
2005-03-22 19:08:37 -08:00
|
|
|
| (Tsig_type(id, decl, rs) :: rem, [s],
|
2007-10-09 03:29:37 -07:00
|
|
|
Pwith_type ({ptype_kind = Ptype_abstract} as sdecl))
|
|
|
|
when Ident.name id = s && Typedecl.is_fixed_type sdecl ->
|
2006-09-20 04:14:37 -07:00
|
|
|
let decl_row =
|
|
|
|
{ type_params =
|
|
|
|
List.map (fun _ -> Btype.newgenvar()) sdecl.ptype_params;
|
|
|
|
type_arity = List.length sdecl.ptype_params;
|
|
|
|
type_kind = Type_abstract;
|
2007-10-09 03:29:37 -07:00
|
|
|
type_private = Private;
|
2006-09-20 04:14:37 -07:00
|
|
|
type_manifest = None;
|
|
|
|
type_variance =
|
|
|
|
List.map (fun (c,n) -> (not n, not c, not c))
|
2010-10-07 00:12:50 -07:00
|
|
|
sdecl.ptype_variance;
|
2010-05-21 08:06:01 -07:00
|
|
|
type_loc = Location.none;
|
2011-10-20 20:26:35 -07:00
|
|
|
type_newtype_level = None }
|
2006-09-20 04:14:37 -07:00
|
|
|
and id_row = Ident.create (s^"#row") in
|
|
|
|
let initial_env = Env.add_type id_row decl_row initial_env in
|
2005-03-22 19:08:37 -08:00
|
|
|
let newdecl = Typedecl.transl_with_constraint
|
2011-07-20 02:17:07 -07:00
|
|
|
initial_env id (Some(Pident id_row)) decl sdecl in
|
2005-03-22 19:08:37 -08:00
|
|
|
check_type_decl env id row_id newdecl decl rs rem;
|
2006-09-20 04:14:37 -07:00
|
|
|
let decl_row = {decl_row with type_params = newdecl.type_params} in
|
2005-03-22 19:08:37 -08:00
|
|
|
let rs' = if rs = Trec_first then Trec_not else rs in
|
|
|
|
Tsig_type(id_row, decl_row, rs') :: Tsig_type(id, newdecl, rs) :: rem
|
2004-06-12 01:55:49 -07:00
|
|
|
| (Tsig_type(id, decl, rs) :: rem, [s], Pwith_type sdecl)
|
1995-10-01 06:39:43 -07:00
|
|
|
when Ident.name id = s ->
|
2006-11-01 17:10:04 -08:00
|
|
|
let newdecl =
|
2011-07-20 02:17:07 -07:00
|
|
|
Typedecl.transl_with_constraint initial_env id None decl sdecl in
|
2005-03-22 19:08:37 -08:00
|
|
|
check_type_decl env id row_id newdecl decl rs rem;
|
2004-06-12 01:55:49 -07:00
|
|
|
Tsig_type(id, newdecl, rs) :: rem
|
2010-04-17 07:45:12 -07:00
|
|
|
| (Tsig_type(id, decl, rs) :: rem, [s], (Pwith_type _ | Pwith_typesubst _))
|
2005-03-22 19:08:37 -08:00
|
|
|
when Ident.name id = s ^ "#row" ->
|
|
|
|
merge env rem namelist (Some id)
|
2010-04-17 07:45:12 -07:00
|
|
|
| (Tsig_type(id, decl, rs) :: rem, [s], Pwith_typesubst sdecl)
|
|
|
|
when Ident.name id = s ->
|
|
|
|
(* Check as for a normal with constraint, but discard definition *)
|
|
|
|
let newdecl =
|
2011-07-20 02:17:07 -07:00
|
|
|
Typedecl.transl_with_constraint initial_env id None decl sdecl in
|
2010-04-17 07:45:12 -07:00
|
|
|
check_type_decl env id row_id newdecl decl rs rem;
|
|
|
|
real_id := Some id;
|
2011-07-20 02:17:07 -07:00
|
|
|
make_next_first rs rem
|
2004-06-12 01:55:49 -07:00
|
|
|
| (Tsig_module(id, mty, rs) :: rem, [s], Pwith_module lid)
|
1995-10-01 06:39:43 -07:00
|
|
|
when Ident.name id = s ->
|
2010-05-18 10:14:31 -07:00
|
|
|
let (path, mty') = Typetexp.find_module initial_env loc lid in
|
1996-07-25 06:18:53 -07:00
|
|
|
let newmty = Mtype.strengthen env mty' path in
|
1999-02-24 07:21:50 -08:00
|
|
|
ignore(Includemod.modtypes env newmty mty);
|
2004-06-12 01:55:49 -07:00
|
|
|
Tsig_module(id, newmty, rs) :: rem
|
2010-04-17 07:45:12 -07:00
|
|
|
| (Tsig_module(id, mty, rs) :: rem, [s], Pwith_modsubst lid)
|
|
|
|
when Ident.name id = s ->
|
2010-05-18 10:14:31 -07:00
|
|
|
let (path, mty') = Typetexp.find_module initial_env loc lid in
|
2010-04-17 07:45:12 -07:00
|
|
|
let newmty = Mtype.strengthen env mty' path in
|
|
|
|
ignore(Includemod.modtypes env newmty mty);
|
|
|
|
real_id := Some id;
|
2011-07-20 02:17:07 -07:00
|
|
|
make_next_first rs rem
|
2004-06-12 01:55:49 -07:00
|
|
|
| (Tsig_module(id, mty, rs) :: rem, s :: namelist, _)
|
|
|
|
when Ident.name id = s ->
|
2005-03-22 19:08:37 -08:00
|
|
|
let newsg = merge env (extract_sig env loc mty) namelist None in
|
2004-06-12 01:55:49 -07:00
|
|
|
Tsig_module(id, Tmty_signature newsg, rs) :: rem
|
1995-10-01 06:39:43 -07:00
|
|
|
| (item :: rem, _, _) ->
|
2005-03-22 19:08:37 -08:00
|
|
|
item :: merge (Env.add_item item env) rem namelist row_id in
|
1996-07-25 06:18:53 -07:00
|
|
|
try
|
2010-04-17 07:45:12 -07:00
|
|
|
let names = Longident.flatten lid in
|
|
|
|
let sg = merge initial_env sg names None in
|
|
|
|
match names, constr with
|
|
|
|
[s], Pwith_typesubst sdecl ->
|
|
|
|
let id =
|
|
|
|
match !real_id with None -> assert false | Some id -> id in
|
|
|
|
let lid =
|
|
|
|
try match sdecl.ptype_manifest with
|
|
|
|
| Some {ptyp_desc = Ptyp_constr (lid, stl)} ->
|
|
|
|
let params =
|
|
|
|
List.map
|
|
|
|
(function {ptyp_desc=Ptyp_var s} -> s | _ -> raise Exit)
|
|
|
|
stl in
|
2010-11-10 02:38:18 -08:00
|
|
|
if List.map (fun x -> Some x) params <> sdecl.ptype_params
|
|
|
|
then raise Exit;
|
2010-04-17 07:45:12 -07:00
|
|
|
lid
|
|
|
|
| _ -> raise Exit
|
|
|
|
with Exit -> raise (Error (sdecl.ptype_loc, With_need_typeconstr))
|
|
|
|
in
|
|
|
|
let (path, _) =
|
|
|
|
try Env.lookup_type lid initial_env with Not_found -> assert false
|
|
|
|
in
|
|
|
|
let sub = Subst.add_type id path Subst.identity in
|
|
|
|
Subst.signature sub sg
|
|
|
|
| [s], Pwith_modsubst lid ->
|
|
|
|
let id =
|
|
|
|
match !real_id with None -> assert false | Some id -> id in
|
2010-05-18 10:14:31 -07:00
|
|
|
let (path, _) = Typetexp.find_module initial_env loc lid in
|
2010-04-17 07:45:12 -07:00
|
|
|
let sub = Subst.add_module id path Subst.identity in
|
|
|
|
Subst.signature sub sg
|
|
|
|
| _ ->
|
|
|
|
sg
|
1996-07-25 06:18:53 -07:00
|
|
|
with Includemod.Error explanation ->
|
|
|
|
raise(Error(loc, With_mismatch(lid, explanation)))
|
1995-09-28 03:42:38 -07:00
|
|
|
|
2004-06-12 01:55:49 -07:00
|
|
|
(* Add recursion flags on declarations arising from a mutually recursive
|
|
|
|
block. *)
|
|
|
|
|
|
|
|
let map_rec fn decls rem =
|
|
|
|
match decls with
|
|
|
|
| [] -> rem
|
|
|
|
| d1 :: dl -> fn Trec_first d1 :: map_end (fn Trec_next) dl rem
|
|
|
|
|
2005-03-22 19:08:37 -08:00
|
|
|
let rec map_rec' fn decls rem =
|
|
|
|
match decls with
|
|
|
|
| (id,_ as d1) :: dl when Btype.is_row_name (Ident.name id) ->
|
|
|
|
fn Trec_not d1 :: map_rec' fn dl rem
|
|
|
|
| _ -> map_rec fn decls rem
|
|
|
|
|
2003-06-19 08:53:53 -07:00
|
|
|
(* Auxiliary for translating recursively-defined module types.
|
|
|
|
Return a module type that approximates the shape of the given module
|
|
|
|
type AST. Retain only module, type, and module type
|
|
|
|
components of signatures. For types, retain only their arity,
|
|
|
|
making them abstract otherwise. *)
|
|
|
|
|
2008-08-07 01:25:09 -07:00
|
|
|
let rec approx_modtype env smty =
|
|
|
|
match smty.pmty_desc with
|
|
|
|
Pmty_ident lid ->
|
2010-05-18 10:18:24 -07:00
|
|
|
let (path, info) = Typetexp.find_modtype env smty.pmty_loc lid in
|
|
|
|
Tmty_ident path
|
2008-08-07 01:25:09 -07:00
|
|
|
| Pmty_signature ssg ->
|
|
|
|
Tmty_signature(approx_sig env ssg)
|
|
|
|
| Pmty_functor(param, sarg, sres) ->
|
|
|
|
let arg = approx_modtype env sarg in
|
|
|
|
let (id, newenv) = Env.enter_module param arg env in
|
|
|
|
let res = approx_modtype newenv sres in
|
|
|
|
Tmty_functor(id, arg, res)
|
|
|
|
| Pmty_with(sbody, constraints) ->
|
|
|
|
approx_modtype env sbody
|
2010-04-02 05:53:33 -07:00
|
|
|
| Pmty_typeof smod ->
|
|
|
|
!type_module_type_of_fwd env smod
|
2008-08-07 01:25:09 -07:00
|
|
|
|
|
|
|
and approx_sig env ssg =
|
|
|
|
match ssg with
|
|
|
|
[] -> []
|
|
|
|
| item :: srem ->
|
|
|
|
match item.psig_desc with
|
|
|
|
| Psig_type sdecls ->
|
|
|
|
let decls = Typedecl.approx_type_decl env sdecls in
|
|
|
|
let rem = approx_sig env srem in
|
|
|
|
map_rec' (fun rs (id, info) -> Tsig_type(id, info, rs)) decls rem
|
|
|
|
| Psig_module(name, smty) ->
|
|
|
|
let mty = approx_modtype env smty in
|
|
|
|
let (id, newenv) = Env.enter_module name mty env in
|
|
|
|
Tsig_module(id, mty, Trec_not) :: approx_sig newenv srem
|
|
|
|
| Psig_recmodule sdecls ->
|
|
|
|
let decls =
|
|
|
|
List.map
|
|
|
|
(fun (name, smty) ->
|
|
|
|
(Ident.create name, approx_modtype env smty))
|
|
|
|
sdecls in
|
|
|
|
let newenv =
|
|
|
|
List.fold_left (fun env (id, mty) -> Env.add_module id mty env)
|
|
|
|
env decls in
|
|
|
|
map_rec (fun rs (id, mty) -> Tsig_module(id, mty, rs)) decls
|
|
|
|
(approx_sig newenv srem)
|
|
|
|
| Psig_modtype(name, sinfo) ->
|
|
|
|
let info = approx_modtype_info env sinfo in
|
|
|
|
let (id, newenv) = Env.enter_modtype name info env in
|
|
|
|
Tsig_modtype(id, info) :: approx_sig newenv srem
|
|
|
|
| Psig_open lid ->
|
2009-11-01 13:52:29 -08:00
|
|
|
approx_sig (type_open env item.psig_loc lid) srem
|
2008-08-07 01:25:09 -07:00
|
|
|
| Psig_include smty ->
|
|
|
|
let mty = approx_modtype env smty in
|
|
|
|
let sg = Subst.signature Subst.identity
|
|
|
|
(extract_sig env smty.pmty_loc mty) in
|
|
|
|
let newenv = Env.add_signature sg env in
|
|
|
|
sg @ approx_sig newenv srem
|
|
|
|
| Psig_class sdecls | Psig_class_type sdecls ->
|
|
|
|
let decls = Typeclass.approx_class_declarations env sdecls in
|
|
|
|
let rem = approx_sig env srem in
|
|
|
|
List.flatten
|
|
|
|
(map_rec
|
|
|
|
(fun rs (i1, d1, i2, d2, i3, d3) ->
|
|
|
|
[Tsig_cltype(i1, d1, rs);
|
|
|
|
Tsig_type(i2, d2, rs);
|
|
|
|
Tsig_type(i3, d3, rs)])
|
|
|
|
decls [rem])
|
|
|
|
| _ ->
|
|
|
|
approx_sig env srem
|
|
|
|
|
|
|
|
and approx_modtype_info env sinfo =
|
|
|
|
match sinfo with
|
|
|
|
Pmodtype_abstract ->
|
|
|
|
Tmodtype_abstract
|
|
|
|
| Pmodtype_manifest smty ->
|
|
|
|
Tmodtype_manifest(approx_modtype env smty)
|
2003-06-19 08:53:53 -07:00
|
|
|
|
2003-07-01 06:05:43 -07:00
|
|
|
(* Additional validity checks on type definitions arising from
|
|
|
|
recursive modules *)
|
|
|
|
|
|
|
|
let check_recmod_typedecls env sdecls decls =
|
|
|
|
let recmod_ids = List.map fst decls in
|
|
|
|
List.iter2
|
|
|
|
(fun (_, smty) (id, mty) ->
|
|
|
|
List.iter
|
|
|
|
(fun path ->
|
|
|
|
Typedecl.check_recmod_typedecl env smty.pmty_loc recmod_ids
|
|
|
|
path (Env.find_type path env))
|
|
|
|
(Mtype.type_paths env (Pident id) mty))
|
|
|
|
sdecls decls
|
|
|
|
|
1999-03-02 06:49:38 -08:00
|
|
|
(* Auxiliaries for checking uniqueness of names in signatures and structures *)
|
|
|
|
|
|
|
|
module StringSet = Set.Make(struct type t = string let compare = compare end)
|
|
|
|
|
|
|
|
let check cl loc set_ref name =
|
|
|
|
if StringSet.mem name !set_ref
|
|
|
|
then raise(Error(loc, Repeated_name(cl, name)))
|
|
|
|
else set_ref := StringSet.add name !set_ref
|
|
|
|
|
|
|
|
let check_sig_item type_names module_names modtype_names loc = function
|
2004-06-12 01:55:49 -07:00
|
|
|
Tsig_type(id, _, _) ->
|
1999-03-02 06:49:38 -08:00
|
|
|
check "type" loc type_names (Ident.name id)
|
2004-06-12 01:55:49 -07:00
|
|
|
| Tsig_module(id, _, _) ->
|
1999-03-02 06:49:38 -08:00
|
|
|
check "module" loc module_names (Ident.name id)
|
|
|
|
| Tsig_modtype(id, _) ->
|
|
|
|
check "module type" loc modtype_names (Ident.name id)
|
|
|
|
| _ -> ()
|
|
|
|
|
2010-04-17 07:45:12 -07:00
|
|
|
let rec remove_values ids = function
|
|
|
|
[] -> []
|
2011-07-20 02:17:07 -07:00
|
|
|
| Tsig_value (id, _) :: rem
|
|
|
|
when List.exists (Ident.equal id) ids -> remove_values ids rem
|
2010-04-17 07:45:12 -07:00
|
|
|
| f :: rem -> f :: remove_values ids rem
|
|
|
|
|
|
|
|
let rec get_values = function
|
|
|
|
[] -> []
|
|
|
|
| Tsig_value (id, _) :: rem -> id :: get_values rem
|
|
|
|
| f :: rem -> get_values rem
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Check and translate a module type expression *)
|
|
|
|
|
2009-10-26 03:53:16 -07:00
|
|
|
let transl_modtype_longident loc env lid =
|
2010-05-18 10:18:24 -07:00
|
|
|
let (path, info) = Typetexp.find_modtype env loc lid in
|
|
|
|
path
|
2009-10-26 03:53:16 -07:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let rec transl_modtype env smty =
|
|
|
|
match smty.pmty_desc with
|
|
|
|
Pmty_ident lid ->
|
2009-10-26 03:53:16 -07:00
|
|
|
Tmty_ident (transl_modtype_longident smty.pmty_loc env lid)
|
1995-08-28 04:23:33 -07:00
|
|
|
| Pmty_signature ssg ->
|
|
|
|
Tmty_signature(transl_signature env ssg)
|
1995-05-04 03:15:53 -07:00
|
|
|
| Pmty_functor(param, sarg, sres) ->
|
|
|
|
let arg = transl_modtype env sarg in
|
|
|
|
let (id, newenv) = Env.enter_module param arg env in
|
|
|
|
let res = transl_modtype newenv sres in
|
|
|
|
Tmty_functor(id, arg, res)
|
1995-09-28 03:42:38 -07:00
|
|
|
| Pmty_with(sbody, constraints) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
let body = transl_modtype env sbody in
|
1995-09-28 03:42:38 -07:00
|
|
|
let init_sg = extract_sig env sbody.pmty_loc body in
|
|
|
|
let final_sg =
|
|
|
|
List.fold_left
|
|
|
|
(fun sg (lid, sdecl) ->
|
|
|
|
merge_constraint env smty.pmty_loc sg lid sdecl)
|
|
|
|
init_sg constraints in
|
2004-02-14 09:38:02 -08:00
|
|
|
Mtype.freshen (Tmty_signature final_sg)
|
2010-04-02 05:53:33 -07:00
|
|
|
| Pmty_typeof smod ->
|
|
|
|
!type_module_type_of_fwd env smod
|
2006-09-20 04:14:37 -07:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
and transl_signature env sg =
|
1999-03-02 06:49:38 -08:00
|
|
|
let type_names = ref StringSet.empty
|
|
|
|
and module_names = ref StringSet.empty
|
|
|
|
and modtype_names = ref StringSet.empty in
|
|
|
|
let rec transl_sig env sg =
|
|
|
|
Ctype.init_def(Ident.current_time());
|
|
|
|
match sg with
|
|
|
|
[] -> []
|
|
|
|
| item :: srem ->
|
|
|
|
match item.psig_desc with
|
|
|
|
| Psig_value(name, sdesc) ->
|
2011-10-20 20:26:35 -07:00
|
|
|
let desc = Typedecl.transl_value_decl env item.psig_loc sdesc in
|
2011-12-29 09:49:58 -08:00
|
|
|
let (id, newenv) = Env.enter_value ~check:(fun s -> Warnings.Unused_value_declaration s) name desc env in
|
1999-03-02 06:49:38 -08:00
|
|
|
let rem = transl_sig newenv srem in
|
2010-04-17 07:45:12 -07:00
|
|
|
if List.exists (Ident.equal id) (get_values rem) then rem
|
|
|
|
else Tsig_value(id, desc) :: rem
|
1999-03-02 06:49:38 -08:00
|
|
|
| Psig_type sdecls ->
|
|
|
|
List.iter
|
|
|
|
(fun (name, decl) -> check "type" item.psig_loc type_names name)
|
|
|
|
sdecls;
|
|
|
|
let (decls, newenv) = Typedecl.transl_type_decl env sdecls in
|
|
|
|
let rem = transl_sig newenv srem in
|
2005-03-22 19:08:37 -08:00
|
|
|
map_rec' (fun rs (id, info) -> Tsig_type(id, info, rs)) decls rem
|
1999-03-02 06:49:38 -08:00
|
|
|
| Psig_exception(name, sarg) ->
|
2012-03-06 11:03:17 -08:00
|
|
|
let arg = Typedecl.transl_exception env item.psig_loc sarg in
|
1999-03-02 06:49:38 -08:00
|
|
|
let (id, newenv) = Env.enter_exception name arg env in
|
|
|
|
let rem = transl_sig newenv srem in
|
|
|
|
Tsig_exception(id, arg) :: rem
|
|
|
|
| Psig_module(name, smty) ->
|
2001-03-05 04:59:23 -08:00
|
|
|
check "module" item.psig_loc module_names name;
|
1999-03-02 06:49:38 -08:00
|
|
|
let mty = transl_modtype env smty in
|
|
|
|
let (id, newenv) = Env.enter_module name mty env in
|
|
|
|
let rem = transl_sig newenv srem in
|
2004-06-12 01:55:49 -07:00
|
|
|
Tsig_module(id, mty, Trec_not) :: rem
|
2003-06-19 08:53:53 -07:00
|
|
|
| Psig_recmodule sdecls ->
|
|
|
|
List.iter
|
|
|
|
(fun (name, smty) ->
|
|
|
|
check "module" item.psig_loc module_names name)
|
|
|
|
sdecls;
|
|
|
|
let (decls, newenv) =
|
|
|
|
transl_recmodule_modtypes item.psig_loc env sdecls in
|
|
|
|
let rem = transl_sig newenv srem in
|
2004-06-12 01:55:49 -07:00
|
|
|
map_rec (fun rs (id, mty) -> Tsig_module(id, mty, rs)) decls rem
|
1999-03-02 06:49:38 -08:00
|
|
|
| Psig_modtype(name, sinfo) ->
|
2001-03-05 04:59:23 -08:00
|
|
|
check "module type" item.psig_loc modtype_names name;
|
1999-03-02 06:49:38 -08:00
|
|
|
let info = transl_modtype_info env sinfo in
|
|
|
|
let (id, newenv) = Env.enter_modtype name info env in
|
|
|
|
let rem = transl_sig newenv srem in
|
|
|
|
Tsig_modtype(id, info) :: rem
|
|
|
|
| Psig_open lid ->
|
2009-11-01 13:52:29 -08:00
|
|
|
transl_sig (type_open env item.psig_loc lid) srem
|
1999-03-02 06:49:38 -08:00
|
|
|
| Psig_include smty ->
|
|
|
|
let mty = transl_modtype env smty in
|
2000-12-01 01:35:00 -08:00
|
|
|
let sg = Subst.signature Subst.identity
|
|
|
|
(extract_sig env smty.pmty_loc mty) in
|
1999-03-02 06:49:38 -08:00
|
|
|
List.iter
|
|
|
|
(check_sig_item type_names module_names modtype_names
|
|
|
|
item.psig_loc)
|
|
|
|
sg;
|
|
|
|
let newenv = Env.add_signature sg env in
|
|
|
|
let rem = transl_sig newenv srem in
|
2010-04-17 07:45:12 -07:00
|
|
|
remove_values (get_values rem) sg @ rem
|
1999-03-02 06:49:38 -08:00
|
|
|
| Psig_class cl ->
|
|
|
|
List.iter
|
|
|
|
(fun {pci_name = name} ->
|
|
|
|
check "type" item.psig_loc type_names name)
|
|
|
|
cl;
|
|
|
|
let (classes, newenv) = Typeclass.class_descriptions env cl in
|
|
|
|
let rem = transl_sig newenv srem in
|
|
|
|
List.flatten
|
2004-06-12 01:55:49 -07:00
|
|
|
(map_rec
|
|
|
|
(fun rs (i, d, i', d', i'', d'', i''', d''', _, _, _) ->
|
|
|
|
[Tsig_class(i, d, rs);
|
|
|
|
Tsig_cltype(i', d', rs);
|
|
|
|
Tsig_type(i'', d'', rs);
|
|
|
|
Tsig_type(i''', d''', rs)])
|
1999-03-02 06:49:38 -08:00
|
|
|
classes [rem])
|
|
|
|
| Psig_class_type cl ->
|
|
|
|
List.iter
|
|
|
|
(fun {pci_name = name} ->
|
|
|
|
check "type" item.psig_loc type_names name)
|
|
|
|
cl;
|
|
|
|
let (classes, newenv) = Typeclass.class_type_declarations env cl in
|
|
|
|
let rem = transl_sig newenv srem in
|
|
|
|
List.flatten
|
2004-06-12 01:55:49 -07:00
|
|
|
(map_rec
|
|
|
|
(fun rs (i, d, i', d', i'', d'') ->
|
|
|
|
[Tsig_cltype(i, d, rs);
|
|
|
|
Tsig_type(i', d', rs);
|
|
|
|
Tsig_type(i'', d'', rs)])
|
1999-03-02 06:49:38 -08:00
|
|
|
classes [rem])
|
|
|
|
in transl_sig env sg
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
and transl_modtype_info env sinfo =
|
|
|
|
match sinfo with
|
|
|
|
Pmodtype_abstract ->
|
|
|
|
Tmodtype_abstract
|
|
|
|
| Pmodtype_manifest smty ->
|
|
|
|
Tmodtype_manifest(transl_modtype env smty)
|
|
|
|
|
2003-06-19 08:53:53 -07:00
|
|
|
and transl_recmodule_modtypes loc env sdecls =
|
|
|
|
let make_env curr =
|
|
|
|
List.fold_left
|
|
|
|
(fun env (id, mty) -> Env.add_module id mty env)
|
|
|
|
env curr in
|
|
|
|
let transition env_c curr =
|
|
|
|
List.map2
|
|
|
|
(fun (_, smty) (id, mty) -> (id, transl_modtype env_c smty))
|
|
|
|
sdecls curr in
|
|
|
|
let init =
|
|
|
|
List.map
|
|
|
|
(fun (name, smty) ->
|
2008-08-07 01:25:09 -07:00
|
|
|
(Ident.create name, approx_modtype env smty))
|
2003-06-19 08:53:53 -07:00
|
|
|
sdecls in
|
2008-01-11 08:13:18 -08:00
|
|
|
let env0 = make_env init in
|
|
|
|
let dcl1 = transition env0 init in
|
|
|
|
let env1 = make_env dcl1 in
|
2008-08-07 01:39:14 -07:00
|
|
|
check_recmod_typedecls env1 sdecls dcl1;
|
2008-01-11 08:13:18 -08:00
|
|
|
let dcl2 = transition env1 dcl1 in
|
|
|
|
(*
|
|
|
|
List.iter
|
|
|
|
(fun (id, mty) ->
|
|
|
|
Format.printf "%a: %a@." Printtyp.ident id Printtyp.modtype mty)
|
|
|
|
dcl2;
|
|
|
|
*)
|
2008-08-07 01:25:09 -07:00
|
|
|
let env2 = make_env dcl2 in
|
|
|
|
check_recmod_typedecls env2 sdecls dcl2;
|
2008-01-11 08:13:18 -08:00
|
|
|
(dcl2, env2)
|
2003-06-19 08:53:53 -07:00
|
|
|
|
1995-08-23 04:55:54 -07:00
|
|
|
(* Try to convert a module expression to a module path. *)
|
|
|
|
|
|
|
|
exception Not_a_path
|
|
|
|
|
|
|
|
let rec path_of_module mexp =
|
|
|
|
match mexp.mod_desc with
|
|
|
|
Tmod_ident p -> p
|
2009-07-15 07:06:37 -07:00
|
|
|
| Tmod_apply(funct, arg, coercion) when !Clflags.applicative_functors ->
|
1995-08-23 04:55:54 -07:00
|
|
|
Papply(path_of_module funct, path_of_module arg)
|
|
|
|
| _ -> raise Not_a_path
|
|
|
|
|
1995-09-02 11:55:37 -07:00
|
|
|
(* Check that all core type schemes in a structure are closed *)
|
|
|
|
|
1996-05-22 09:22:33 -07:00
|
|
|
let rec closed_modtype = function
|
|
|
|
Tmty_ident p -> true
|
|
|
|
| Tmty_signature sg -> List.for_all closed_signature_item sg
|
|
|
|
| Tmty_functor(id, param, body) -> closed_modtype body
|
|
|
|
|
|
|
|
and closed_signature_item = function
|
1997-03-18 13:06:28 -08:00
|
|
|
Tsig_value(id, desc) -> Ctype.closed_schema desc.val_type
|
2004-06-12 01:55:49 -07:00
|
|
|
| Tsig_module(id, mty, _) -> closed_modtype mty
|
1996-05-22 09:22:33 -07:00
|
|
|
| _ -> true
|
|
|
|
|
|
|
|
let check_nongen_scheme env = function
|
|
|
|
Tstr_value(rec_flag, pat_exp_list) ->
|
|
|
|
List.iter
|
|
|
|
(fun (pat, exp) ->
|
1997-03-18 13:06:28 -08:00
|
|
|
if not (Ctype.closed_schema exp.exp_type) then
|
1996-05-22 09:22:33 -07:00
|
|
|
raise(Error(exp.exp_loc, Non_generalizable exp.exp_type)))
|
|
|
|
pat_exp_list
|
|
|
|
| Tstr_module(id, md) ->
|
|
|
|
if not (closed_modtype md.mod_type) then
|
|
|
|
raise(Error(md.mod_loc, Non_generalizable_module md.mod_type))
|
|
|
|
| _ -> ()
|
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
let check_nongen_schemes env str =
|
1996-05-22 09:22:33 -07:00
|
|
|
List.iter (check_nongen_scheme env) str
|
1995-09-02 11:55:37 -07:00
|
|
|
|
2000-12-01 01:35:00 -08:00
|
|
|
(* Extract the list of "value" identifiers bound by a signature.
|
|
|
|
"Value" identifiers are identifiers for signature components that
|
2001-09-10 08:11:14 -07:00
|
|
|
correspond to a run-time value: values, exceptions, modules, classes.
|
|
|
|
Note: manifest primitives do not correspond to a run-time value! *)
|
2000-12-01 01:35:00 -08:00
|
|
|
|
|
|
|
let rec bound_value_identifiers = function
|
|
|
|
[] -> []
|
2001-09-10 08:11:14 -07:00
|
|
|
| Tsig_value(id, {val_kind = Val_reg}) :: rem ->
|
|
|
|
id :: bound_value_identifiers rem
|
2000-12-01 01:35:00 -08:00
|
|
|
| Tsig_exception(id, decl) :: rem -> id :: bound_value_identifiers rem
|
2004-06-12 01:55:49 -07:00
|
|
|
| Tsig_module(id, mty, _) :: rem -> id :: bound_value_identifiers rem
|
|
|
|
| Tsig_class(id, decl, _) :: rem -> id :: bound_value_identifiers rem
|
2000-12-01 01:35:00 -08:00
|
|
|
| _ :: rem -> bound_value_identifiers rem
|
|
|
|
|
2003-06-19 08:53:53 -07:00
|
|
|
(* Helpers for typing recursive modules *)
|
|
|
|
|
|
|
|
let anchor_submodule name anchor =
|
|
|
|
match anchor with None -> None | Some p -> Some(Pdot(p, name, nopos))
|
|
|
|
let anchor_recmodule id anchor =
|
|
|
|
Some (Pident id)
|
|
|
|
|
|
|
|
let enrich_type_decls anchor decls oldenv newenv =
|
|
|
|
match anchor with
|
|
|
|
None -> newenv
|
|
|
|
| Some p ->
|
|
|
|
List.fold_left
|
|
|
|
(fun e (id, info) ->
|
|
|
|
let info' =
|
|
|
|
Mtype.enrich_typedecl oldenv (Pdot(p, Ident.name id, nopos)) info
|
|
|
|
in
|
|
|
|
Env.add_type id info' e)
|
|
|
|
oldenv decls
|
|
|
|
|
|
|
|
let enrich_module_type anchor name mty env =
|
|
|
|
match anchor with
|
|
|
|
None -> mty
|
|
|
|
| Some p -> Mtype.enrich_modtype env (Pdot(p, name, nopos)) mty
|
|
|
|
|
2008-01-11 08:13:18 -08:00
|
|
|
let check_recmodule_inclusion env bindings =
|
|
|
|
(* PR#4450, PR#4470: consider
|
|
|
|
module rec X : DECL = MOD where MOD has inferred type ACTUAL
|
|
|
|
The "natural" typing condition
|
|
|
|
E, X: ACTUAL |- ACTUAL <: DECL
|
2008-12-03 10:09:09 -08:00
|
|
|
leads to circularities through manifest types.
|
2008-01-11 08:13:18 -08:00
|
|
|
Instead, we "unroll away" the potential circularities a finite number
|
|
|
|
of times. The (weaker) condition we implement is:
|
|
|
|
E, X: DECL,
|
|
|
|
X1: ACTUAL,
|
|
|
|
X2: ACTUAL{X <- X1}/X1
|
|
|
|
...
|
|
|
|
Xn: ACTUAL{X <- X(n-1)}/X(n-1)
|
|
|
|
|- ACTUAL{X <- Xn}/Xn <: DECL{X <- Xn}
|
|
|
|
so that manifest types rooted at X(n+1) are expanded in terms of X(n),
|
|
|
|
avoiding circularities. The strengthenings ensure that
|
|
|
|
Xn.t = X(n-1).t = ... = X2.t = X1.t.
|
|
|
|
N can be chosen arbitrarily; larger values of N result in more
|
|
|
|
recursive definitions being accepted. A good choice appears to be
|
|
|
|
the number of mutually recursive declarations. *)
|
|
|
|
|
|
|
|
let subst_and_strengthen env s id mty =
|
|
|
|
Mtype.strengthen env (Subst.modtype s mty)
|
|
|
|
(Subst.module_path s (Pident id)) in
|
|
|
|
|
|
|
|
let rec check_incl first_time n env s =
|
|
|
|
if n > 0 then begin
|
|
|
|
(* Generate fresh names Y_i for the rec. bound module idents X_i *)
|
|
|
|
let bindings1 =
|
|
|
|
List.map
|
|
|
|
(fun (id, mty_decl, modl, mty_actual) ->
|
|
|
|
(id, Ident.rename id, mty_actual))
|
|
|
|
bindings in
|
|
|
|
(* Enter the Y_i in the environment with their actual types substituted
|
|
|
|
by the input substitution s *)
|
|
|
|
let env' =
|
|
|
|
List.fold_left
|
|
|
|
(fun env (id, id', mty_actual) ->
|
|
|
|
let mty_actual' =
|
|
|
|
if first_time
|
|
|
|
then mty_actual
|
|
|
|
else subst_and_strengthen env s id mty_actual in
|
|
|
|
Env.add_module id' mty_actual' env)
|
|
|
|
env bindings1 in
|
|
|
|
(* Build the output substitution Y_i <- X_i *)
|
|
|
|
let s' =
|
|
|
|
List.fold_left
|
|
|
|
(fun s (id, id', mty_actual) ->
|
|
|
|
Subst.add_module id (Pident id') s)
|
|
|
|
Subst.identity bindings1 in
|
|
|
|
(* Recurse with env' and s' *)
|
|
|
|
check_incl false (n-1) env' s'
|
|
|
|
end else begin
|
|
|
|
(* Base case: check inclusion of s(mty_actual) in s(mty_decl)
|
|
|
|
and insert coercion if needed *)
|
|
|
|
let check_inclusion (id, mty_decl, modl, mty_actual) =
|
|
|
|
let mty_decl' = Subst.modtype s mty_decl
|
|
|
|
and mty_actual' = subst_and_strengthen env s id mty_actual in
|
|
|
|
let coercion =
|
|
|
|
try
|
|
|
|
Includemod.modtypes env mty_actual' mty_decl'
|
|
|
|
with Includemod.Error msg ->
|
|
|
|
raise(Error(modl.mod_loc, Not_included msg)) in
|
|
|
|
let modl' =
|
|
|
|
{ mod_desc = Tmod_constraint(modl, mty_decl, coercion);
|
|
|
|
mod_type = mty_decl;
|
|
|
|
mod_env = env;
|
|
|
|
mod_loc = modl.mod_loc } in
|
|
|
|
(id, modl') in
|
|
|
|
List.map check_inclusion bindings
|
|
|
|
end
|
|
|
|
in check_incl true (List.length bindings) env Subst.identity
|
|
|
|
|
2010-10-21 16:59:33 -07:00
|
|
|
(* Helper for unpack *)
|
|
|
|
|
2011-12-14 02:26:15 -08:00
|
|
|
let rec package_constraints env loc mty constrs =
|
|
|
|
if constrs = [] then mty
|
|
|
|
else let sg = extract_sig env loc mty in
|
|
|
|
let sg' =
|
|
|
|
List.map
|
|
|
|
(function
|
|
|
|
| Tsig_type (id, ({type_params=[]} as td), rs) when List.mem_assoc [Ident.name id] constrs ->
|
|
|
|
let ty = List.assoc [Ident.name id] constrs in
|
|
|
|
Tsig_type (id, {td with type_manifest = Some ty}, rs)
|
|
|
|
| Tsig_module (id, mty, rs) ->
|
|
|
|
let rec aux = function
|
|
|
|
| (m :: ((_ :: _) as l), t) :: rest when m = Ident.name id -> (l, t) :: aux rest
|
|
|
|
| _ :: rest -> aux rest
|
|
|
|
| [] -> []
|
|
|
|
in
|
|
|
|
Tsig_module (id, package_constraints env loc mty (aux constrs), rs)
|
|
|
|
| item -> item
|
|
|
|
)
|
|
|
|
sg
|
|
|
|
in
|
|
|
|
Tmty_signature sg'
|
|
|
|
|
2010-10-21 16:59:33 -07:00
|
|
|
let modtype_of_package env loc p nl tl =
|
|
|
|
try match Env.find_modtype p env with
|
|
|
|
| Tmodtype_manifest mty when nl <> [] ->
|
2011-12-14 02:26:15 -08:00
|
|
|
package_constraints env loc mty (List.combine (List.map Longident.flatten nl) tl)
|
2010-10-21 16:59:33 -07:00
|
|
|
| _ ->
|
|
|
|
if nl = [] then Tmty_ident p
|
|
|
|
else raise(Error(loc, Signature_expected))
|
|
|
|
with Not_found ->
|
|
|
|
raise(Typetexp.Error(loc, Typetexp.Unbound_modtype (Ctype.lid_of_path p)))
|
|
|
|
|
|
|
|
let wrap_constraint env arg mty =
|
|
|
|
let coercion =
|
|
|
|
try
|
|
|
|
Includemod.modtypes env arg.mod_type mty
|
|
|
|
with Includemod.Error msg ->
|
|
|
|
raise(Error(arg.mod_loc, Not_included msg)) in
|
|
|
|
{ mod_desc = Tmod_constraint(arg, mty, coercion);
|
|
|
|
mod_type = mty;
|
|
|
|
mod_env = env;
|
|
|
|
mod_loc = arg.mod_loc }
|
|
|
|
|
1995-05-05 03:05:18 -07:00
|
|
|
(* Type a module value expression *)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2010-08-02 07:37:22 -07:00
|
|
|
let rec type_module sttn funct_body anchor env smod =
|
1995-05-04 03:15:53 -07:00
|
|
|
match smod.pmod_desc with
|
|
|
|
Pmod_ident lid ->
|
2010-05-18 10:14:31 -07:00
|
|
|
let (path, mty) = Typetexp.find_module env smod.pmod_loc lid in
|
2003-04-01 22:57:15 -08:00
|
|
|
rm { mod_desc = Tmod_ident path;
|
2010-08-02 07:37:22 -07:00
|
|
|
mod_type = if sttn then Mtype.strengthen env mty path else mty;
|
2003-04-01 22:57:15 -08:00
|
|
|
mod_env = env;
|
|
|
|
mod_loc = smod.pmod_loc }
|
1995-05-04 03:15:53 -07:00
|
|
|
| Pmod_structure sstr ->
|
2010-08-02 07:37:22 -07:00
|
|
|
let (str, sg, finalenv) =
|
|
|
|
type_structure funct_body anchor env sstr smod.pmod_loc in
|
2003-04-01 22:57:15 -08:00
|
|
|
rm { mod_desc = Tmod_structure str;
|
|
|
|
mod_type = Tmty_signature sg;
|
|
|
|
mod_env = env;
|
|
|
|
mod_loc = smod.pmod_loc }
|
1995-05-04 03:15:53 -07:00
|
|
|
| Pmod_functor(name, smty, sbody) ->
|
|
|
|
let mty = transl_modtype env smty in
|
|
|
|
let (id, newenv) = Env.enter_module name mty env in
|
2010-08-02 07:37:22 -07:00
|
|
|
let body = type_module sttn true None newenv sbody in
|
2003-04-01 22:57:15 -08:00
|
|
|
rm { mod_desc = Tmod_functor(id, mty, body);
|
|
|
|
mod_type = Tmty_functor(id, mty, body.mod_type);
|
|
|
|
mod_env = env;
|
|
|
|
mod_loc = smod.pmod_loc }
|
1995-05-04 03:15:53 -07:00
|
|
|
| Pmod_apply(sfunct, sarg) ->
|
2010-08-02 07:37:22 -07:00
|
|
|
let arg = type_module true funct_body None env sarg in
|
|
|
|
let path = try Some (path_of_module arg) with Not_a_path -> None in
|
|
|
|
let funct =
|
|
|
|
type_module (sttn && path <> None) funct_body None env sfunct in
|
1995-05-04 03:15:53 -07:00
|
|
|
begin match Mtype.scrape env funct.mod_type with
|
|
|
|
Tmty_functor(param, mty_param, mty_res) as mty_functor ->
|
|
|
|
let coercion =
|
|
|
|
try
|
|
|
|
Includemod.modtypes env arg.mod_type mty_param
|
|
|
|
with Includemod.Error msg ->
|
|
|
|
raise(Error(sarg.pmod_loc, Not_included msg)) in
|
|
|
|
let mty_appl =
|
2010-08-02 07:37:22 -07:00
|
|
|
match path with
|
|
|
|
Some path ->
|
|
|
|
Subst.modtype (Subst.add_module param path Subst.identity)
|
|
|
|
mty_res
|
|
|
|
| None ->
|
|
|
|
try
|
|
|
|
Mtype.nondep_supertype
|
|
|
|
(Env.add_module param arg.mod_type env) param mty_res
|
|
|
|
with Not_found ->
|
|
|
|
raise(Error(smod.pmod_loc,
|
|
|
|
Cannot_eliminate_dependency mty_functor))
|
|
|
|
in
|
2003-04-01 22:57:15 -08:00
|
|
|
rm { mod_desc = Tmod_apply(funct, arg, coercion);
|
|
|
|
mod_type = mty_appl;
|
|
|
|
mod_env = env;
|
|
|
|
mod_loc = smod.pmod_loc }
|
1995-05-04 03:15:53 -07:00
|
|
|
| _ ->
|
|
|
|
raise(Error(sfunct.pmod_loc, Cannot_apply funct.mod_type))
|
2006-09-20 04:14:37 -07:00
|
|
|
end
|
1995-05-04 03:15:53 -07:00
|
|
|
| Pmod_constraint(sarg, smty) ->
|
2010-08-02 07:37:22 -07:00
|
|
|
let arg = type_module true funct_body anchor env sarg in
|
1995-05-04 03:15:53 -07:00
|
|
|
let mty = transl_modtype env smty in
|
2010-10-21 16:59:33 -07:00
|
|
|
rm {(wrap_constraint env arg mty) with mod_loc = smod.pmod_loc}
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2010-10-21 16:59:33 -07:00
|
|
|
| Pmod_unpack sexp ->
|
2010-08-02 07:37:22 -07:00
|
|
|
if funct_body then
|
|
|
|
raise (Error (smod.pmod_loc, Not_allowed_in_functor_body));
|
2010-10-21 16:59:33 -07:00
|
|
|
if !Clflags.principal then Ctype.begin_def ();
|
|
|
|
let exp = Typecore.type_exp env sexp in
|
|
|
|
if !Clflags.principal then begin
|
|
|
|
Ctype.end_def ();
|
|
|
|
Ctype.generalize_structure exp.exp_type
|
|
|
|
end;
|
|
|
|
let mty =
|
|
|
|
match Ctype.expand_head env exp.exp_type with
|
|
|
|
{desc = Tpackage (p, nl, tl)} ->
|
|
|
|
if List.exists (fun t -> Ctype.free_variables t <> []) tl then
|
|
|
|
raise (Error (smod.pmod_loc,
|
|
|
|
Incomplete_packed_module exp.exp_type));
|
|
|
|
if !Clflags.principal &&
|
|
|
|
not (Typecore.generalizable (Btype.generic_level-1) exp.exp_type)
|
|
|
|
then
|
|
|
|
Location.prerr_warning smod.pmod_loc
|
|
|
|
(Warnings.Not_principal "this module unpacking");
|
|
|
|
modtype_of_package env smod.pmod_loc p nl tl
|
2011-09-22 02:05:42 -07:00
|
|
|
| {desc = Tvar _} ->
|
2010-10-21 16:59:33 -07:00
|
|
|
raise (Typecore.Error
|
|
|
|
(smod.pmod_loc, Typecore.Cannot_infer_signature))
|
|
|
|
| _ ->
|
|
|
|
raise (Error (smod.pmod_loc, Not_a_packed_module exp.exp_type))
|
|
|
|
in
|
2009-10-26 03:53:16 -07:00
|
|
|
rm { mod_desc = Tmod_unpack(exp, mty);
|
|
|
|
mod_type = mty;
|
|
|
|
mod_env = env;
|
|
|
|
mod_loc = smod.pmod_loc }
|
|
|
|
|
|
|
|
and type_structure funct_body anchor env sstr scope =
|
2000-12-01 01:35:00 -08:00
|
|
|
let type_names = ref StringSet.empty
|
|
|
|
and module_names = ref StringSet.empty
|
|
|
|
and modtype_names = ref StringSet.empty in
|
|
|
|
let rec type_struct env sstr =
|
|
|
|
Ctype.init_def(Ident.current_time());
|
|
|
|
match sstr with
|
|
|
|
[] ->
|
|
|
|
([], [], env)
|
|
|
|
| {pstr_desc = Pstr_eval sexpr} :: srem ->
|
|
|
|
let expr = Typecore.type_expression env sexpr in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct env srem in
|
|
|
|
(Tstr_eval expr :: str_rem, sig_rem, final_env)
|
2007-05-16 01:21:41 -07:00
|
|
|
| {pstr_desc = Pstr_value(rec_flag, sdefs); pstr_loc = loc} :: srem ->
|
|
|
|
let scope =
|
|
|
|
match rec_flag with
|
|
|
|
| Recursive -> Some (Annot.Idef {scope with
|
|
|
|
Location.loc_start = loc.Location.loc_start})
|
|
|
|
| Nonrecursive ->
|
|
|
|
let start = match srem with
|
2008-07-29 08:42:44 -07:00
|
|
|
| [] -> loc.Location.loc_end
|
2007-05-16 01:21:41 -07:00
|
|
|
| {pstr_loc = loc2} :: _ -> loc2.Location.loc_start
|
|
|
|
in Some (Annot.Idef {scope with Location.loc_start = start})
|
|
|
|
| Default -> None
|
|
|
|
in
|
2000-12-01 01:35:00 -08:00
|
|
|
let (defs, newenv) =
|
2007-05-16 01:21:41 -07:00
|
|
|
Typecore.type_binding env rec_flag sdefs scope in
|
2000-12-01 01:35:00 -08:00
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
|
|
|
|
let bound_idents = let_bound_idents defs in
|
2011-12-21 07:40:54 -08:00
|
|
|
(* Note: Env.find_value does not trigger the value_used event. Values
|
|
|
|
will be marked as being used during the signature inclusion test. *)
|
2000-12-01 01:35:00 -08:00
|
|
|
let make_sig_value id =
|
|
|
|
Tsig_value(id, Env.find_value (Pident id) newenv) in
|
|
|
|
(Tstr_value(rec_flag, defs) :: str_rem,
|
|
|
|
map_end make_sig_value bound_idents sig_rem,
|
|
|
|
final_env)
|
2011-10-20 20:26:35 -07:00
|
|
|
| {pstr_desc = Pstr_primitive(name, sdesc); pstr_loc = loc} :: srem ->
|
|
|
|
let desc = Typedecl.transl_value_decl env loc sdesc in
|
2011-12-29 09:49:58 -08:00
|
|
|
let (id, newenv) = Env.enter_value ~check:(fun s -> Warnings.Unused_value_declaration s) name desc env in
|
2000-12-01 01:35:00 -08:00
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
|
|
|
|
(Tstr_primitive(id, desc) :: str_rem,
|
|
|
|
Tsig_value(id, desc) :: sig_rem,
|
|
|
|
final_env)
|
|
|
|
| {pstr_desc = Pstr_type sdecls; pstr_loc = loc} :: srem ->
|
|
|
|
List.iter
|
|
|
|
(fun (name, decl) -> check "type" loc type_names name)
|
|
|
|
sdecls;
|
|
|
|
let (decls, newenv) = Typedecl.transl_type_decl env sdecls in
|
2006-09-20 04:14:37 -07:00
|
|
|
let newenv' =
|
2003-06-19 08:53:53 -07:00
|
|
|
enrich_type_decls anchor decls env newenv in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv' srem in
|
2000-12-01 01:35:00 -08:00
|
|
|
(Tstr_type decls :: str_rem,
|
2005-03-22 19:08:37 -08:00
|
|
|
map_rec' (fun rs (id, info) -> Tsig_type(id, info, rs)) decls sig_rem,
|
2000-12-01 01:35:00 -08:00
|
|
|
final_env)
|
2012-03-06 11:03:17 -08:00
|
|
|
| {pstr_desc = Pstr_exception(name, sarg); pstr_loc = loc} :: srem ->
|
|
|
|
let arg = Typedecl.transl_exception env loc sarg in
|
2000-12-01 01:35:00 -08:00
|
|
|
let (id, newenv) = Env.enter_exception name arg env in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
|
|
|
|
(Tstr_exception(id, arg) :: str_rem,
|
|
|
|
Tsig_exception(id, arg) :: sig_rem,
|
|
|
|
final_env)
|
|
|
|
| {pstr_desc = Pstr_exn_rebind(name, longid); pstr_loc = loc} :: srem ->
|
|
|
|
let (path, arg) = Typedecl.transl_exn_rebind env loc longid in
|
|
|
|
let (id, newenv) = Env.enter_exception name arg env in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
|
|
|
|
(Tstr_exn_rebind(id, path) :: str_rem,
|
|
|
|
Tsig_exception(id, arg) :: sig_rem,
|
|
|
|
final_env)
|
|
|
|
| {pstr_desc = Pstr_module(name, smodl); pstr_loc = loc} :: srem ->
|
|
|
|
check "module" loc module_names name;
|
2010-08-02 07:37:22 -07:00
|
|
|
let modl =
|
|
|
|
type_module true funct_body (anchor_submodule name anchor) env
|
|
|
|
smodl in
|
2003-06-19 08:53:53 -07:00
|
|
|
let mty = enrich_module_type anchor name modl.mod_type env in
|
|
|
|
let (id, newenv) = Env.enter_module name mty env in
|
2000-12-01 01:35:00 -08:00
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
|
|
|
|
(Tstr_module(id, modl) :: str_rem,
|
2004-06-12 01:55:49 -07:00
|
|
|
Tsig_module(id, modl.mod_type, Trec_not) :: sig_rem,
|
2000-12-01 01:35:00 -08:00
|
|
|
final_env)
|
2003-06-19 08:53:53 -07:00
|
|
|
| {pstr_desc = Pstr_recmodule sbind; pstr_loc = loc} :: srem ->
|
|
|
|
List.iter
|
|
|
|
(fun (name, _, _) -> check "module" loc module_names name)
|
|
|
|
sbind;
|
|
|
|
let (decls, newenv) =
|
|
|
|
transl_recmodule_modtypes loc env
|
|
|
|
(List.map (fun (name, smty, smodl) -> (name, smty)) sbind) in
|
2008-01-11 08:13:18 -08:00
|
|
|
let bindings1 =
|
|
|
|
List.map2
|
|
|
|
(fun (id, mty) (name, smty, smodl) ->
|
|
|
|
let modl =
|
2010-08-02 07:37:22 -07:00
|
|
|
type_module true funct_body (anchor_recmodule id anchor) newenv
|
|
|
|
smodl in
|
2008-01-11 08:13:18 -08:00
|
|
|
let mty' =
|
2010-08-02 07:37:22 -07:00
|
|
|
enrich_module_type anchor (Ident.name id) modl.mod_type newenv
|
|
|
|
in
|
2008-01-11 08:13:18 -08:00
|
|
|
(id, mty, modl, mty'))
|
|
|
|
decls sbind in
|
|
|
|
let bindings2 =
|
|
|
|
check_recmodule_inclusion newenv bindings1 in
|
2003-06-19 08:53:53 -07:00
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
|
2008-01-11 08:13:18 -08:00
|
|
|
(Tstr_recmodule bindings2 :: str_rem,
|
2004-06-12 01:55:49 -07:00
|
|
|
map_rec (fun rs (id, modl) -> Tsig_module(id, modl.mod_type, rs))
|
2008-01-11 08:13:18 -08:00
|
|
|
bindings2 sig_rem,
|
2003-06-19 08:53:53 -07:00
|
|
|
final_env)
|
2000-12-01 01:35:00 -08:00
|
|
|
| {pstr_desc = Pstr_modtype(name, smty); pstr_loc = loc} :: srem ->
|
|
|
|
check "module type" loc modtype_names name;
|
|
|
|
let mty = transl_modtype env smty in
|
|
|
|
let (id, newenv) = Env.enter_modtype name (Tmodtype_manifest mty) env in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
|
|
|
|
(Tstr_modtype(id, mty) :: str_rem,
|
|
|
|
Tsig_modtype(id, Tmodtype_manifest mty) :: sig_rem,
|
|
|
|
final_env)
|
|
|
|
| {pstr_desc = Pstr_open lid; pstr_loc = loc} :: srem ->
|
2009-11-01 13:52:29 -08:00
|
|
|
type_struct (type_open env loc lid) srem
|
2001-08-13 02:35:49 -07:00
|
|
|
| {pstr_desc = Pstr_class cl; pstr_loc = loc} :: srem ->
|
|
|
|
List.iter
|
|
|
|
(fun {pci_name = name} -> check "type" loc type_names name)
|
|
|
|
cl;
|
2000-12-01 01:35:00 -08:00
|
|
|
let (classes, new_env) = Typeclass.class_declarations env cl in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct new_env srem in
|
|
|
|
(Tstr_class
|
2006-04-04 19:28:13 -07:00
|
|
|
(List.map (fun (i, d, _,_,_,_,_,_, s, m, c) ->
|
|
|
|
let vf = if d.cty_new = None then Virtual else Concrete in
|
|
|
|
(i, s, m, c, vf)) classes) ::
|
2000-12-01 01:35:00 -08:00
|
|
|
Tstr_cltype
|
|
|
|
(List.map (fun (_,_, i, d, _,_,_,_,_,_,_) -> (i, d)) classes) ::
|
|
|
|
Tstr_type
|
|
|
|
(List.map (fun (_,_,_,_, i, d, _,_,_,_,_) -> (i, d)) classes) ::
|
|
|
|
Tstr_type
|
|
|
|
(List.map (fun (_,_,_,_,_,_, i, d, _,_,_) -> (i, d)) classes) ::
|
|
|
|
str_rem,
|
|
|
|
List.flatten
|
2004-06-12 01:55:49 -07:00
|
|
|
(map_rec
|
|
|
|
(fun rs (i, d, i', d', i'', d'', i''', d''', _, _, _) ->
|
|
|
|
[Tsig_class(i, d, rs);
|
|
|
|
Tsig_cltype(i', d', rs);
|
|
|
|
Tsig_type(i'', d'', rs);
|
|
|
|
Tsig_type(i''', d''', rs)])
|
2000-12-01 01:35:00 -08:00
|
|
|
classes [sig_rem]),
|
|
|
|
final_env)
|
2001-08-13 02:35:49 -07:00
|
|
|
| {pstr_desc = Pstr_class_type cl; pstr_loc = loc} :: srem ->
|
|
|
|
List.iter
|
|
|
|
(fun {pci_name = name} -> check "type" loc type_names name)
|
|
|
|
cl;
|
2000-12-01 01:35:00 -08:00
|
|
|
let (classes, new_env) = Typeclass.class_type_declarations env cl in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct new_env srem in
|
|
|
|
(Tstr_cltype
|
|
|
|
(List.map (fun (i, d, _, _, _, _) -> (i, d)) classes) ::
|
|
|
|
Tstr_type
|
|
|
|
(List.map (fun (_, _, i, d, _, _) -> (i, d)) classes) ::
|
|
|
|
Tstr_type
|
|
|
|
(List.map (fun (_, _, _, _, i, d) -> (i, d)) classes) ::
|
|
|
|
str_rem,
|
|
|
|
List.flatten
|
2004-06-12 01:55:49 -07:00
|
|
|
(map_rec
|
|
|
|
(fun rs (i, d, i', d', i'', d'') ->
|
|
|
|
[Tsig_cltype(i, d, rs);
|
|
|
|
Tsig_type(i', d', rs);
|
|
|
|
Tsig_type(i'', d'', rs)])
|
2000-12-01 01:35:00 -08:00
|
|
|
classes [sig_rem]),
|
|
|
|
final_env)
|
|
|
|
| {pstr_desc = Pstr_include smodl; pstr_loc = loc} :: srem ->
|
2010-08-02 07:37:22 -07:00
|
|
|
let modl = type_module true funct_body None env smodl in
|
2000-12-01 01:35:00 -08:00
|
|
|
(* Rename all identifiers bound by this signature to avoid clashes *)
|
|
|
|
let sg = Subst.signature Subst.identity
|
|
|
|
(extract_sig_open env smodl.pmod_loc modl.mod_type) in
|
|
|
|
List.iter
|
|
|
|
(check_sig_item type_names module_names modtype_names loc) sg;
|
|
|
|
let new_env = Env.add_signature sg env in
|
|
|
|
let (str_rem, sig_rem, final_env) = type_struct new_env srem in
|
|
|
|
(Tstr_include (modl, bound_value_identifiers sg) :: str_rem,
|
|
|
|
sg @ sig_rem,
|
|
|
|
final_env)
|
2003-07-23 09:52:41 -07:00
|
|
|
in
|
2007-05-16 01:21:41 -07:00
|
|
|
if !Clflags.annotations
|
2003-07-23 09:52:41 -07:00
|
|
|
then List.iter (function {pstr_loc = l} -> Stypes.record_phrase l) sstr;
|
2005-08-08 02:41:52 -07:00
|
|
|
type_struct env sstr
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2010-08-02 07:37:22 -07:00
|
|
|
let type_module = type_module true false None
|
2009-10-26 03:53:16 -07:00
|
|
|
let type_structure = type_structure false None
|
2003-06-19 08:53:53 -07:00
|
|
|
|
2000-02-24 02:18:25 -08:00
|
|
|
(* Normalize types in a signature *)
|
|
|
|
|
|
|
|
let rec normalize_modtype env = function
|
|
|
|
Tmty_ident p -> ()
|
|
|
|
| Tmty_signature sg -> normalize_signature env sg
|
|
|
|
| Tmty_functor(id, param, body) -> normalize_modtype env body
|
|
|
|
|
|
|
|
and normalize_signature env = List.iter (normalize_signature_item env)
|
|
|
|
|
|
|
|
and normalize_signature_item env = function
|
|
|
|
Tsig_value(id, desc) -> Ctype.normalize_type env desc.val_type
|
2004-06-12 01:55:49 -07:00
|
|
|
| Tsig_module(id, mty, _) -> normalize_modtype env mty
|
2000-02-24 02:18:25 -08:00
|
|
|
| _ -> ()
|
|
|
|
|
2005-08-08 02:41:52 -07:00
|
|
|
(* Simplify multiple specifications of a value or an exception in a signature.
|
|
|
|
(Other signature components, e.g. types, modules, etc, are checked for
|
|
|
|
name uniqueness.) If multiple specifications with the same name,
|
|
|
|
keep only the last (rightmost) one. *)
|
|
|
|
|
|
|
|
let rec simplify_modtype mty =
|
|
|
|
match mty with
|
|
|
|
Tmty_ident path -> mty
|
|
|
|
| Tmty_functor(id, arg, res) -> Tmty_functor(id, arg, simplify_modtype res)
|
|
|
|
| Tmty_signature sg -> Tmty_signature(simplify_signature sg)
|
|
|
|
|
|
|
|
and simplify_signature sg =
|
|
|
|
let rec simplif val_names exn_names res = function
|
|
|
|
[] -> res
|
|
|
|
| (Tsig_value(id, descr) as component) :: sg ->
|
|
|
|
let name = Ident.name id in
|
|
|
|
simplif (StringSet.add name val_names) exn_names
|
|
|
|
(if StringSet.mem name val_names then res else component :: res)
|
|
|
|
sg
|
|
|
|
| (Tsig_exception(id, decl) as component) :: sg ->
|
|
|
|
let name = Ident.name id in
|
|
|
|
simplif val_names (StringSet.add name exn_names)
|
|
|
|
(if StringSet.mem name exn_names then res else component :: res)
|
|
|
|
sg
|
|
|
|
| Tsig_module(id, mty, rs) :: sg ->
|
|
|
|
simplif val_names exn_names
|
|
|
|
(Tsig_module(id, simplify_modtype mty, rs) :: res) sg
|
|
|
|
| component :: sg ->
|
|
|
|
simplif val_names exn_names (component :: res) sg
|
|
|
|
in
|
|
|
|
simplif StringSet.empty StringSet.empty [] (List.rev sg)
|
|
|
|
|
2010-04-27 21:54:57 -07:00
|
|
|
(* Extract the module type of a module expression *)
|
|
|
|
|
|
|
|
let type_module_type_of env smod =
|
2010-04-28 00:53:19 -07:00
|
|
|
let mty =
|
|
|
|
match smod.pmod_desc with
|
|
|
|
| Pmod_ident lid -> (* turn off strengthening in this case *)
|
2010-05-18 10:14:31 -07:00
|
|
|
let (path, mty) = Typetexp.find_module env smod.pmod_loc lid in mty
|
2010-04-28 00:53:19 -07:00
|
|
|
| _ -> (type_module env smod).mod_type in
|
2010-04-29 22:12:44 -07:00
|
|
|
(* PR#5037: clean up inferred signature to remove duplicate specs *)
|
|
|
|
let mty = simplify_modtype mty in
|
2010-04-28 00:53:19 -07:00
|
|
|
(* PR#5036: must not contain non-generalized type variables *)
|
|
|
|
if not (closed_modtype mty) then
|
|
|
|
raise(Error(smod.pmod_loc, Non_generalizable_module mty));
|
2010-04-29 22:12:44 -07:00
|
|
|
mty
|
2010-04-27 21:54:57 -07:00
|
|
|
|
2010-10-21 16:59:33 -07:00
|
|
|
(* For Typecore *)
|
|
|
|
|
|
|
|
let rec get_manifest_types = function
|
|
|
|
[] -> []
|
|
|
|
| Tsig_type (id, {type_params=[]; type_manifest=Some ty}, _) :: rem ->
|
|
|
|
(Ident.name id, ty) :: get_manifest_types rem
|
|
|
|
| _ :: rem -> get_manifest_types rem
|
|
|
|
|
|
|
|
let type_package env m p nl tl =
|
2011-08-19 19:51:34 -07:00
|
|
|
(* Same as Pexp_letmodule *)
|
|
|
|
(* remember original level *)
|
|
|
|
let lv = Ctype.get_current_level () in
|
|
|
|
Ctype.begin_def ();
|
|
|
|
Ident.set_current_time lv;
|
|
|
|
let context = Typetexp.narrow () in
|
2010-10-21 16:59:33 -07:00
|
|
|
let modl = type_module env m in
|
2011-08-19 19:51:34 -07:00
|
|
|
Ctype.init_def(Ident.current_time());
|
|
|
|
Typetexp.widen context;
|
|
|
|
let (mp, env) =
|
|
|
|
match modl.mod_desc with
|
|
|
|
Tmod_ident mp -> (mp, env)
|
|
|
|
| _ ->
|
|
|
|
let (id, new_env) = Env.enter_module "%M" modl.mod_type env in
|
|
|
|
(Pident id, new_env)
|
2010-10-21 16:59:33 -07:00
|
|
|
in
|
2011-12-14 02:26:15 -08:00
|
|
|
let rec mkpath mp = function
|
|
|
|
| Lident name -> Pdot(mp, name, nopos)
|
|
|
|
| Ldot (m, name) -> Pdot(mkpath mp m, name, nopos)
|
|
|
|
| _ -> assert false
|
|
|
|
in
|
2011-08-19 19:51:34 -07:00
|
|
|
let tl' =
|
2011-12-14 02:26:15 -08:00
|
|
|
List.map (fun name -> Ctype.newconstr (mkpath mp name) []) nl in
|
2011-08-19 19:51:34 -07:00
|
|
|
(* go back to original level *)
|
|
|
|
Ctype.end_def ();
|
|
|
|
if nl = [] then (wrap_constraint env modl (Tmty_ident p), []) else
|
2010-10-21 16:59:33 -07:00
|
|
|
let mty = modtype_of_package env modl.mod_loc p nl tl' in
|
2011-08-19 19:51:34 -07:00
|
|
|
List.iter2
|
|
|
|
(fun n ty ->
|
|
|
|
try Ctype.unify env ty (Ctype.newvar ())
|
|
|
|
with Ctype.Unify _ -> raise (Error(m.pmod_loc, Scoping_pack (n,ty))))
|
|
|
|
nl tl';
|
2010-10-21 16:59:33 -07:00
|
|
|
(wrap_constraint env modl mty, tl')
|
|
|
|
|
2010-04-27 21:54:57 -07:00
|
|
|
(* Fill in the forward declarations *)
|
|
|
|
let () =
|
|
|
|
Typecore.type_module := type_module;
|
|
|
|
Typetexp.transl_modtype_longident := transl_modtype_longident;
|
|
|
|
Typetexp.transl_modtype := transl_modtype;
|
|
|
|
Typecore.type_open := type_open;
|
2010-10-21 16:59:33 -07:00
|
|
|
Typecore.type_package := type_package;
|
2010-04-27 21:54:57 -07:00
|
|
|
type_module_type_of_fwd := type_module_type_of
|
|
|
|
|
2003-03-10 08:57:04 -08:00
|
|
|
(* Typecheck an implementation file *)
|
|
|
|
|
2004-06-13 05:48:01 -07:00
|
|
|
let type_implementation sourcefile outputprefix modulename initial_env ast =
|
2003-03-10 08:57:04 -08:00
|
|
|
Typecore.reset_delayed_checks ();
|
2008-01-21 00:42:14 -08:00
|
|
|
let (str, sg, finalenv) = type_structure initial_env ast Location.none in
|
2007-10-08 07:19:34 -07:00
|
|
|
let simple_sg = simplify_signature sg in
|
2003-06-23 07:00:49 -07:00
|
|
|
if !Clflags.print_types then begin
|
2007-10-08 07:19:34 -07:00
|
|
|
fprintf std_formatter "%a@." Printtyp.signature simple_sg;
|
|
|
|
(str, Tcoerce_none) (* result is ignored by Compile.implementation *)
|
2003-06-23 07:00:49 -07:00
|
|
|
end else begin
|
2007-10-08 07:19:34 -07:00
|
|
|
let sourceintf =
|
|
|
|
Misc.chop_extension_if_any sourcefile ^ !Config.interface_suffix in
|
|
|
|
if Sys.file_exists sourceintf then begin
|
|
|
|
let intf_file =
|
|
|
|
try
|
|
|
|
find_in_path_uncap !Config.load_path (modulename ^ ".cmi")
|
|
|
|
with Not_found ->
|
|
|
|
raise(Error(Location.none, Interface_not_compiled sourceintf)) in
|
|
|
|
let dclsig = Env.read_signature modulename intf_file in
|
|
|
|
let coercion = Includemod.compunit sourcefile sg intf_file dclsig in
|
2011-12-21 07:40:54 -08:00
|
|
|
Typecore.force_delayed_checks ();
|
|
|
|
(* It is important to run these checks after the inclusion test above,
|
|
|
|
so that value declarations which are not used internally but exported
|
|
|
|
are not reported as being unused. *)
|
2007-10-08 07:19:34 -07:00
|
|
|
(str, coercion)
|
|
|
|
end else begin
|
|
|
|
check_nongen_schemes finalenv str;
|
2008-10-08 06:09:39 -07:00
|
|
|
normalize_signature finalenv simple_sg;
|
2007-10-08 07:19:34 -07:00
|
|
|
let coercion =
|
|
|
|
Includemod.compunit sourcefile sg
|
|
|
|
"(inferred signature)" simple_sg in
|
2011-12-21 07:40:54 -08:00
|
|
|
Typecore.force_delayed_checks ();
|
|
|
|
(* See comment above. Here the target signature contains all
|
|
|
|
the value being exported. We can still capture unused
|
|
|
|
declarations like "let x = true;; let x = 1;;", because in this
|
|
|
|
case, the inferred signature contains only the last declaration. *)
|
2007-10-08 07:19:34 -07:00
|
|
|
if not !Clflags.dont_write_files then
|
|
|
|
Env.save_signature simple_sg modulename (outputprefix ^ ".cmi");
|
|
|
|
(str, coercion)
|
|
|
|
end
|
2003-06-23 07:00:49 -07:00
|
|
|
end
|
2003-03-10 08:57:04 -08:00
|
|
|
|
2002-02-08 08:55:44 -08:00
|
|
|
(* "Packaging" of several compilation units into one unit
|
|
|
|
having them as sub-modules. *)
|
|
|
|
|
|
|
|
let rec package_signatures subst = function
|
|
|
|
[] -> []
|
|
|
|
| (name, sg) :: rem ->
|
|
|
|
let sg' = Subst.signature subst sg in
|
|
|
|
let oldid = Ident.create_persistent name
|
|
|
|
and newid = Ident.create name in
|
2004-06-12 01:55:49 -07:00
|
|
|
Tsig_module(newid, Tmty_signature sg', Trec_not) ::
|
2002-02-08 08:55:44 -08:00
|
|
|
package_signatures (Subst.add_module oldid (Pident newid) subst) rem
|
|
|
|
|
|
|
|
let package_units objfiles cmifile modulename =
|
|
|
|
(* Read the signatures of the units *)
|
|
|
|
let units =
|
|
|
|
List.map
|
|
|
|
(fun f ->
|
2007-02-23 05:44:51 -08:00
|
|
|
let pref = chop_extensions f in
|
2002-02-08 08:55:44 -08:00
|
|
|
let modname = String.capitalize(Filename.basename pref) in
|
2004-04-09 06:32:28 -07:00
|
|
|
let sg = Env.read_signature modname (pref ^ ".cmi") in
|
|
|
|
if Filename.check_suffix f ".cmi" &&
|
|
|
|
not(Mtype.no_code_needed_sig Env.initial sg)
|
|
|
|
then raise(Error(Location.none, Implementation_is_required f));
|
2002-02-08 08:55:44 -08:00
|
|
|
(modname, Env.read_signature modname (pref ^ ".cmi")))
|
|
|
|
objfiles in
|
|
|
|
(* Compute signature of packaged unit *)
|
2003-08-20 07:35:14 -07:00
|
|
|
Ident.reinit();
|
2002-02-08 08:55:44 -08:00
|
|
|
let sg = package_signatures Subst.identity units in
|
2003-03-06 07:59:55 -08:00
|
|
|
(* See if explicit interface is provided *)
|
|
|
|
let mlifile =
|
|
|
|
chop_extension_if_any cmifile ^ !Config.interface_suffix in
|
|
|
|
if Sys.file_exists mlifile then begin
|
2005-03-24 09:20:54 -08:00
|
|
|
if not (Sys.file_exists cmifile) then begin
|
|
|
|
raise(Error(Location.in_file mlifile, Interface_not_compiled mlifile))
|
|
|
|
end;
|
2003-03-06 07:59:55 -08:00
|
|
|
let dclsig = Env.read_signature modulename cmifile in
|
2006-09-20 04:14:37 -07:00
|
|
|
Includemod.compunit "(obtained by packing)" sg mlifile dclsig
|
2003-03-06 07:59:55 -08:00
|
|
|
end else begin
|
|
|
|
(* Determine imports *)
|
|
|
|
let unit_names = List.map fst units in
|
|
|
|
let imports =
|
|
|
|
List.filter
|
|
|
|
(fun (name, crc) -> not (List.mem name unit_names))
|
|
|
|
(Env.imported_units()) in
|
|
|
|
(* Write packaged signature *)
|
|
|
|
Env.save_signature_with_imports sg modulename cmifile imports;
|
|
|
|
Tcoerce_none
|
|
|
|
end
|
2002-02-08 08:55:44 -08:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Error report *)
|
|
|
|
|
|
|
|
open Printtyp
|
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
let report_error ppf = function
|
2010-05-18 10:18:24 -07:00
|
|
|
Cannot_apply mty ->
|
2000-03-21 07:16:48 -08:00
|
|
|
fprintf ppf
|
|
|
|
"@[This module is not a functor; it has type@ %a@]" modtype mty
|
|
|
|
| Not_included errs ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[<v>Signature mismatch:@ %a@]" Includemod.report_error errs
|
|
|
|
| Cannot_eliminate_dependency mty ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[This functor has type@ %a@ \
|
|
|
|
The parameter cannot be eliminated in the result type.@ \
|
|
|
|
Please bind the argument to a module identifier.@]" modtype mty
|
2000-03-06 14:12:09 -08:00
|
|
|
| Signature_expected -> fprintf ppf "This module type is not a signature"
|
2000-03-21 07:16:48 -08:00
|
|
|
| Structure_expected mty ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[This module is not a structure; it has type@ %a" modtype mty
|
|
|
|
| With_no_component lid ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[The signature constrained by `with' has no component named %a@]"
|
|
|
|
longident lid
|
|
|
|
| With_mismatch(lid, explanation) ->
|
|
|
|
fprintf ppf
|
2001-07-23 08:35:49 -07:00
|
|
|
"@[<v>\
|
2000-03-21 07:16:48 -08:00
|
|
|
@[In this `with' constraint, the new definition of %a@ \
|
|
|
|
does not match its original definition@ \
|
|
|
|
in the constrained signature:@]@ \
|
|
|
|
%a@]"
|
|
|
|
longident lid Includemod.report_error explanation
|
|
|
|
| Repeated_name(kind, name) ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[Multiple definition of the %s name %s.@ \
|
|
|
|
Names must be unique in a given structure or signature.@]" kind name
|
|
|
|
| Non_generalizable typ ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[The type of this expression,@ %a,@ \
|
|
|
|
contains type variables that cannot be generalized@]" type_scheme typ
|
|
|
|
| Non_generalizable_class (id, desc) ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[The type of this class,@ %a,@ \
|
|
|
|
contains type variables that cannot be generalized@]"
|
|
|
|
(class_declaration id) desc
|
|
|
|
| Non_generalizable_module mty ->
|
|
|
|
fprintf ppf
|
|
|
|
"@[The type of this module,@ %a,@ \
|
|
|
|
contains type variables that cannot be generalized@]" modtype mty
|
2004-04-09 06:32:28 -07:00
|
|
|
| Implementation_is_required intf_name ->
|
|
|
|
fprintf ppf
|
2012-03-07 09:37:05 -08:00
|
|
|
"@[The interface %a@ declares values, not just types.@ \
|
|
|
|
An implementation must be provided.@]"
|
|
|
|
Location.print_filename intf_name
|
2004-06-13 05:48:01 -07:00
|
|
|
| Interface_not_compiled intf_name ->
|
|
|
|
fprintf ppf
|
2012-03-07 09:37:05 -08:00
|
|
|
"@[Could not find the .cmi file for interface@ %a.@]"
|
|
|
|
Location.print_filename intf_name
|
2009-10-26 03:53:16 -07:00
|
|
|
| Not_allowed_in_functor_body ->
|
|
|
|
fprintf ppf
|
|
|
|
"This kind of expression is not allowed within the body of a functor."
|
2010-04-17 07:45:12 -07:00
|
|
|
| With_need_typeconstr ->
|
|
|
|
fprintf ppf
|
|
|
|
"Only type constructors with identical parameters can be substituted."
|
2010-10-21 16:59:33 -07:00
|
|
|
| Not_a_packed_module ty ->
|
|
|
|
fprintf ppf
|
|
|
|
"This expression is not a packed module. It has type@ %a"
|
|
|
|
type_expr ty
|
|
|
|
| Incomplete_packed_module ty ->
|
|
|
|
fprintf ppf
|
|
|
|
"The type of this packed module contains variables:@ %a"
|
|
|
|
type_expr ty
|
2011-12-14 02:26:15 -08:00
|
|
|
| Scoping_pack (lid, ty) ->
|
2011-08-19 19:51:34 -07:00
|
|
|
fprintf ppf
|
2011-12-14 02:26:15 -08:00
|
|
|
"The type %a in this module cannot be exported.@ " longident lid;
|
2011-08-19 19:51:34 -07:00
|
|
|
fprintf ppf
|
|
|
|
"Its type contains local dependencies:@ %a" type_expr ty
|