From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from majordomo@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id LAA09066; Tue, 27 Mar 2001 11:19:18 +0200 (MET DST) X-Authentication-Warning: pauillac.inria.fr: majordomo set sender to owner-caml-list@pauillac.inria.fr using -f Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id LAA09053 for ; Tue, 27 Mar 2001 11:19:18 +0200 (MET DST) Received: from ext.lri.fr (ext.lri.fr [129.175.15.4]) by nez-perce.inria.fr (8.11.1/8.10.0) with ESMTP id f2R9JHT26978; Tue, 27 Mar 2001 11:19:17 +0200 (MET DST) Received: from pc802.lri.fr (root@pc8-118 [129.175.8.118]) by ext.lri.fr (8.11.1/jtpda-5.3.2) with ESMTP id f2R9JFu15433 ; Tue, 27 Mar 2001 11:19:15 +0200 (MET DST) Received: by pc802.lri.fr (8.9.3/feuille) id LAA01427 ; Tue, 27 Mar 2001 11:19:14 +0200 From: Judicael Courant MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="poEMdttgo4" Content-Transfer-Encoding: 8bit Message-ID: <15040.23314.342226.514937@pc8-118.lri.fr> Date: Tue, 27 Mar 2001 11:19:14 +0200 (MEST) To: "Dave Berry" Cc: , "Xavier Leroy" , "Andreas Rossberg" , "Christophe Raffalli" Subject: RE: [Caml-list] Caml 3.01 : pb with include In-Reply-To: References: X-Mailer: VM 6.62 under Emacs 20.7.2 Sender: owner-caml-list@pauillac.inria.fr Precedence: bulk --poEMdttgo4 Content-Type: text/plain; charset=iso-8859-1 Content-Description: message body text Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=iso-8859-1 Content-Description: message body text Content-Transfer-Encoding: 8bit Dave Berry a écrit : > > Do you have a real-life example where you need module equality of the > sort you suggest? I recognize the choice of an intentional notion of module equality was not driven by immediate practical considerations. However, if you have a look at Xavier's modular module system, it is used several times. Of course, you can do without it (and in the background, Caml does without). When I tried to define a module calculus for Pure Type Systems with good metatheroetical properties, it happens that I needed module equality: if you are familiar with O'Caml typing system for modules, you probably know that it has a rule telling E |- m : M ------------ E |- m : M/m where "M/m" is M strengthened by m. Roughly this rule says if X is a module defining an abstract type t then we at least know that this type t is equal to X.T (the result of strengthening sig type t end by X is sig type t = X.t end). Now, a metatheoretical result you want is that if m has type M and M is a correct module type then M/m is a correct module type. It turns out that if you want this property in presence of dependent types, you need a notion of equality over modules that ensures that if X=Y then F(X).t = F(Y).t (although this seems to be a truism, it is false in O'Caml with the current definition of module equality). The extentionnal definition is IMHO the wrong one since this lead to accept that F(X).t = F(Y).t when F is Map.Make with X = struct type t = int let compare x y = x-y end and Y = struct type t = int let compare x y = y-x end as I said in my previous post. So I was left with the intentionnal one. module equality is therefore part of the semantic of modules in MC, so you have it for free. I did not try to add it to the modular module system of Xavier until friday, when I began to write this reply. In a few hours, I could patch Xavier's code so that it accepts module equality constraints (about 6h of total work time, including writing this message and a very basic web page). I enclose the patch below, you can download the fully modified code at http://www.lri.fr/~jcourant/01/03/modular_modules Here is an example that can be checked by miniML (look at the signature of W) ---------------------------------------------------------------------- struct module IntOrder = struct type t = int val equal x y = x == y val less x y = x < y end module IntOrder' = struct type t = int val equal x y = x == y val less x y = x > y end module Z = struct module X = IntOrder module Y = IntOrder end module F = functor(W:sig module X : sig type t = int end module Y : sig type t = int end = X end ) struct end module G = F(Z) end ---------------------------------------------------------------------- The previous example typechecks but if you replace "module Y = IntOrder" by "module Y = IntOrder'", it does not typechecks as X and Y are now different. If you have a look at the code, you will notice that any module defined as "module X = m" is transparent as long as "m" is a path. It is difficult to make more module transparent unless you extend the definition of a path. However, you might wish some definition "module X = p" (where p is a path) be opaque. It would be quite easy to change the code so that the standard module definition is opaque and introduce a "transparent module" definition. Sincerly yours, Judicaël. --poEMdttgo4 Content-Type: text/plain Content-Description: Patch to Leroy's modular module system, adds module sharing Content-Disposition: inline; filename="patch" Content-Transfer-Encoding: 7bit diff -c modular_modules.orig/miniC.ml modular_modules/miniC.ml *** modular_modules.orig/miniC.ml Fri Dec 3 14:35:22 1999 --- modular_modules/miniC.ml Tue Mar 27 09:31:14 2001 *************** *** 78,84 **** List.for_all2 (valtype_match env) args1 args2 && valtype_match env res1 res2 | (Typename path1, Typename path2) -> ! path_equal path1 path2 || begin match (CEnv.find_type path1 env, CEnv.find_type path2 env) with ({manifest = Some def}, _) -> valtype_match env def ty2 --- 78,84 ---- List.for_all2 (valtype_match env) args1 args2 && valtype_match env res1 res2 | (Typename path1, Typename path2) -> ! Env.path_equal env path1 path2 || begin match (CEnv.find_type path1 env, CEnv.find_type path2 env) with ({manifest = Some def}, _) -> valtype_match env def ty2 *************** *** 351,360 **** print_string "typedef "; print_name_type id ty | Type_sig(id, {manifest = None}) -> print_string "typedef "; print_string(Ident.name id) ! | Module_sig(id, mty) -> open_hvbox 2; print_string "module "; print_string(Ident.name id); ! print_string ":"; print_space(); print_modtype mty; close_box() end --- 351,368 ---- print_string "typedef "; print_name_type id ty | Type_sig(id, {manifest = None}) -> print_string "typedef "; print_string(Ident.name id) ! | Module_sig(id, mdecl) -> open_hvbox 2; print_string "module "; print_string(Ident.name id); ! print_string ":"; print_space(); print_moddecl mdecl; close_box() + and print_moddecl mdecl = + open_hvbox 2; + print_modtype mdecl.CMod.ty; + (match mdecl.CMod.eq with + | None -> () + | Some p -> print_space (); print_string "="; print_space(); + print_path p); + close_box() end diff -c modular_modules.orig/miniCparser.mly modular_modules/miniCparser.mly *** modular_modules.orig/miniCparser.mly Fri Dec 3 16:34:11 1999 --- modular_modules/miniCparser.mly Tue Mar 27 09:32:49 2001 *************** *** 240,247 **** CMod.Type_sig(id, {CMod.kind = (); CMod.manifest = Some ty}) } | TYPEDEF UIDENT SEMI { CMod.Type_sig(Ident.create $2, {CMod.kind = (); CMod.manifest = None}) } ! | MODULE UIDENT COLON moduletype SEMI { CMod.Module_sig(Ident.create $2, $4) } ; /* Toplevel entry point */ --- 240,253 ---- CMod.Type_sig(id, {CMod.kind = (); CMod.manifest = Some ty}) } | TYPEDEF UIDENT SEMI { CMod.Type_sig(Ident.create $2, {CMod.kind = (); CMod.manifest = None}) } ! | MODULE UIDENT COLON moduledecl SEMI { CMod.Module_sig(Ident.create $2, $4) } + ; + + + moduledecl: + moduletype EQUAL upath { { CMod.ty = $1 ; CMod.eq = Some $3 } } + | moduletype { { CMod.ty = $1 ; CMod.eq = None } } ; /* Toplevel entry point */ diff -c modular_modules.orig/miniML.ml modular_modules/miniML.ml *** modular_modules.orig/miniML.ml Fri Dec 3 14:34:45 1999 --- modular_modules/miniML.ml Tue Mar 27 09:23:51 2001 *************** *** 86,92 **** let repr1 = typerepr ty1 and repr2 = typerepr ty2 in match (repr1, repr2) with (Typeconstr(path1, args1), Typeconstr(path2, args2)) -> ! if path_equal path1 path2 then (repr1, repr2) else begin try --- 86,92 ---- let repr1 = typerepr ty1 and repr2 = typerepr ty2 in match (repr1, repr2) with (Typeconstr(path1, args1), Typeconstr(path2, args2)) -> ! if Env.path_equal env path1 path2 then (repr1, repr2) else begin try *************** *** 394,402 **** open_hvbox 2; print_string "type "; print_typedecl id decl; close_box() ! | Module_sig(id, mty) -> open_hvbox 2; print_string "module "; print_string(Ident.name id); ! print_string ":"; print_space(); print_modtype mty; close_box() end --- 394,410 ---- open_hvbox 2; print_string "type "; print_typedecl id decl; close_box() ! | Module_sig(id, mdecl) -> open_hvbox 2; print_string "module "; print_string(Ident.name id); ! print_string ":"; print_space(); print_moddecl mdecl; close_box() + and print_moddecl mdecl = + open_hvbox 2; + print_modtype mdecl.MLMod.ty; + (match mdecl.MLMod.eq with + | None -> () + | Some p -> print_space (); print_string "="; print_space(); + print_path p); + close_box() end diff -c modular_modules.orig/miniMLparser.mly modular_modules/miniMLparser.mly *** modular_modules.orig/miniMLparser.mly Fri Dec 3 12:03:55 1999 --- modular_modules/miniMLparser.mly Tue Mar 27 09:33:03 2001 *************** *** 217,223 **** signature_item: VALUE IDENT valuedecl { MLMod.Value_sig(Ident.create $2, $3) } | TYPE typeinfo { let (id, def) = $2 in MLMod.Type_sig(Ident.create id, def) } ! | MODULE IDENT COLON moduletype { MLMod.Module_sig(Ident.create $2, $4) } ; /* Toplevel entry point */ --- 217,228 ---- signature_item: VALUE IDENT valuedecl { MLMod.Value_sig(Ident.create $2, $3) } | TYPE typeinfo { let (id, def) = $2 in MLMod.Type_sig(Ident.create id, def) } ! | MODULE IDENT COLON moduledecl { MLMod.Module_sig(Ident.create $2, $4) } ! ; ! ! moduledecl: ! moduletype EQUAL path { { MLMod.ty = $1 ; MLMod.eq = Some $3 } } ! | moduletype { { MLMod.ty = $1 ; MLMod.eq = None } } ; /* Toplevel entry point */ Only in modular_modules: modeq.miniML diff -c modular_modules.orig/modules.ml modular_modules/modules.ml *** modular_modules.orig/modules.ml Fri Dec 3 12:00:09 1999 --- modular_modules/modules.ml Tue Mar 27 09:20:15 2001 *************** *** 44,56 **** Pident of Ident.t (* identifier *) | Pdot of path * string (* access to a module component *) - let rec path_equal p1 p2 = - match (p1, p2) with - (Pident id1, Pident id2) -> Ident.equal id1 id2 - | (Pdot(r1, field1), Pdot(r2, field2)) -> - path_equal r1 r2 && field1 = field2 - | (_, _) -> false - (* Section 2.3: Substitutions *) module type SUBST = --- 44,49 ---- *************** *** 101,107 **** and specification = Value_sig of Ident.t * Core.val_type (* val x: ty *) | Type_sig of Ident.t * type_decl (* type t :: k [= ty] *) ! | Module_sig of Ident.t * mod_type (* module X: mty *) type mod_term = Longident of path (* X or X.Y.Z *) | Structure of structure (* struct ... end *) --- 94,101 ---- and specification = Value_sig of Ident.t * Core.val_type (* val x: ty *) | Type_sig of Ident.t * type_decl (* type t :: k [= ty] *) ! | Module_sig of Ident.t * mod_decl (* module X: mty [=p]*) ! and mod_decl = { ty : mod_type; eq : path option } type mod_term = Longident of path (* X or X.Y.Z *) | Structure of structure (* struct ... end *) *************** *** 116,121 **** --- 110,116 ---- (* type t :: k = ty *) | Module_str of Ident.t * mod_term (* module X = mod *) val subst_typedecl: type_decl -> Subst.t -> type_decl + val subst_moddecl: mod_decl -> Subst.t -> mod_decl val subst_modtype: mod_type -> Subst.t -> mod_type end *************** *** 134,140 **** and specification = Value_sig of Ident.t * Core.val_type (* val x: ty *) | Type_sig of Ident.t * type_decl (* type t :: k [= ty] *) ! | Module_sig of Ident.t * mod_type (* module X: mty *) type mod_term = Longident of path (* X or X.Y.Z *) | Structure of structure (* struct ... end *) --- 129,136 ---- and specification = Value_sig of Ident.t * Core.val_type (* val x: ty *) | Type_sig of Ident.t * type_decl (* type t :: k [= ty] *) ! | Module_sig of Ident.t * mod_decl (* module X: mty [ = p]*) ! and mod_decl = { ty : mod_type; eq : path option } type mod_term = Longident of path (* X or X.Y.Z *) | Structure of structure (* struct ... end *) *************** *** 162,168 **** and subst_sig_item sub = function Value_sig(id, vty) -> Value_sig(id, Core.subst_valtype vty sub) | Type_sig(id, decl) -> Type_sig(id, subst_typedecl decl sub) ! | Module_sig(id, mty) -> Module_sig(id, subst_modtype mty sub) end (* Section 2.6: The environment structure *) --- 158,169 ---- and subst_sig_item sub = function Value_sig(id, vty) -> Value_sig(id, Core.subst_valtype vty sub) | Type_sig(id, decl) -> Type_sig(id, subst_typedecl decl sub) ! | Module_sig(id, mdecl) -> Module_sig(id, subst_moddecl mdecl sub) ! and subst_moddecl mdecl sub = ! { ty = subst_modtype mdecl.ty sub; ! eq = match mdecl.eq with ! | None -> None ! | Some p -> Some(Subst.path p sub) } end (* Section 2.6: The environment structure *) *************** *** 172,185 **** module Mod: MOD_SYNTAX type t val empty: t val add_value: Ident.t -> Mod.Core.val_type -> t -> t val add_type: Ident.t -> Mod.type_decl -> t -> t ! val add_module: Ident.t -> Mod.mod_type -> t -> t val add_spec: Mod.specification -> t -> t val add_signature: Mod.signature -> t -> t val find_value: path -> t -> Mod.Core.val_type val find_type: path -> t -> Mod.type_decl val find_module: path -> t -> Mod.mod_type end module Env(Mod_syntax: MOD_SYNTAX) = --- 173,189 ---- module Mod: MOD_SYNTAX type t val empty: t + val path_equal : t -> path -> path -> bool val add_value: Ident.t -> Mod.Core.val_type -> t -> t val add_type: Ident.t -> Mod.type_decl -> t -> t ! val add_module: Ident.t -> Mod.mod_decl -> t -> t ! val add_absmodule: Ident.t -> Mod.mod_type -> t -> t val add_spec: Mod.specification -> t -> t val add_signature: Mod.signature -> t -> t val find_value: path -> t -> Mod.Core.val_type val find_type: path -> t -> Mod.type_decl val find_module: path -> t -> Mod.mod_type + (* val find_module_type: path -> t -> Mod.mod_type *) end module Env(Mod_syntax: MOD_SYNTAX) = *************** *** 188,204 **** type binding = Value of Mod.Core.val_type | Type of Mod.type_decl ! | Module of Mod.mod_type type t = binding Ident.tbl let empty = Ident.emptytbl let add_value id vty env = Ident.add id (Value vty) env let add_type id decl env = Ident.add id (Type decl) env ! let add_module id mty env = Ident.add id (Module mty) env let add_spec item env = match item with Mod.Value_sig(id, vty) -> add_value id vty env | Mod.Type_sig(id, decl) -> add_type id decl env ! | Mod.Module_sig(id, mty) -> add_module id mty env let add_signature = List.fold_right add_spec let rec find path env = match path with --- 192,210 ---- type binding = Value of Mod.Core.val_type | Type of Mod.type_decl ! | Module of Mod.mod_decl type t = binding Ident.tbl let empty = Ident.emptytbl let add_value id vty env = Ident.add id (Value vty) env let add_type id decl env = Ident.add id (Type decl) env ! let add_module id mdecl env = Ident.add id (Module mdecl) env ! let add_absmodule id mty env = ! Ident.add id (Module { Mod.ty = mty; Mod.eq = None }) env let add_spec item env = match item with Mod.Value_sig(id, vty) -> add_value id vty env | Mod.Type_sig(id, decl) -> add_type id decl env ! | Mod.Module_sig(id, mdecl) -> add_module id mdecl env let add_signature = List.fold_right add_spec let rec find path env = match path with *************** *** 219,227 **** then Type(Mod.subst_typedecl decl subst) else find_field p field (Subst.add id (Pdot(p, Ident.name id)) subst) rem ! | Mod.Module_sig(id, mty) :: rem -> if Ident.name id = field ! then Module(Mod.subst_modtype mty subst) else find_field p field (Subst.add id (Pdot(p, Ident.name id)) subst) rem and find_value path env = --- 225,233 ---- then Type(Mod.subst_typedecl decl subst) else find_field p field (Subst.add id (Pdot(p, Ident.name id)) subst) rem ! | Mod.Module_sig(id, mdecl) :: rem -> if Ident.name id = field ! then Module(Mod.subst_moddecl mdecl subst) else find_field p field (Subst.add id (Pdot(p, Ident.name id)) subst) rem and find_value path env = *************** *** 232,238 **** Type decl -> decl | _ -> error "type field expected" and find_module path env = match find path env with ! Module mty -> mty | _ -> error "module field expected" end (* Section 2.7: Type-checking the base language *) --- 238,277 ---- Type decl -> decl | _ -> error "type field expected" and find_module path env = match find path env with ! Module mdecl -> mdecl.Mod.ty | _ -> error "module field expected" ! ! (* norm_path : -> path * signature option *) ! let rec norm_path env path = ! let norm_binding path b = ! match b with ! | Module { Mod.eq = Some p } -> norm_path env p ! | Module { Mod.ty = Mod.Signature sg } -> path, Some sg ! | _ -> path, None ! in ! match path with ! | Pident id -> norm_binding path (Ident.find id env) ! | Pdot(root, field) -> ! let p', sgopt = norm_path env root in ! (match sgopt with ! | None -> error "structure expected in dot access" ! | Some sg -> ! let b = find_field p' field Subst.identity sg in ! norm_binding (Pdot(p', field)) b ! ) ! ! (* syntactic equality *) ! let rec path_syn_equal p1 p2 = ! match (p1, p2) with ! (Pident id1, Pident id2) -> Ident.equal id1 id2 ! | (Pdot(r1, field1), Pdot(r2, field2)) -> ! path_syn_equal r1 r2 && field1 = field2 ! | (_, _) -> false ! ! (* semantic equality *) ! let path_equal env p1 p2 = ! let p1', _ = norm_path env p1 ! and p2', _ = norm_path env p2 in ! path_syn_equal p1' p2' end (* Section 2.7: Type-checking the base language *) *************** *** 286,292 **** let subst = Subst.add param1 (Pident param2) Subst.identity in let res1' = Mod.subst_modtype res1 subst in modtype_match env arg2 arg1; ! modtype_match (Env.add_module param2 arg2 env) res1' res2 | (_, _) -> error "module type mismatch" and pair_signature_components sig1 sig2 = --- 325,331 ---- let subst = Subst.add param1 (Pident param2) Subst.identity in let res1' = Mod.subst_modtype res1 subst in modtype_match env arg2 arg1; ! modtype_match (Env.add_absmodule param2 arg2 env) res1' res2 | (_, _) -> error "module type mismatch" and pair_signature_components sig1 sig2 = *************** *** 318,325 **** if not (typedecl_match env id decl1 (Mod.subst_typedecl decl2 subst)) then error "type components do not match" ! | (Module_sig(_, mty1), Module_sig(_, mty2)) -> ! modtype_match env mty1 (Mod.subst_modtype mty2 subst) and typedecl_match env id decl1 decl2 = CT.kind_match env decl1.kind decl2.kind && (match (decl1.manifest, decl2.manifest) with --- 357,375 ---- if not (typedecl_match env id decl1 (Mod.subst_typedecl decl2 subst)) then error "type components do not match" ! | (Module_sig(id, mdecl1), Module_sig(_, mdecl2)) -> ! moddecl_match env id mdecl1 (Mod.subst_moddecl mdecl2 subst) ! and moddecl_match env id mdecl1 mdecl2 = ! let mty1, mty2 = mdecl1.Mod.ty, mdecl2.Mod.ty in ! modtype_match env mty1 mty2; ! match (mdecl1.Mod.eq, mdecl2.Mod.eq) with ! | (_, None) -> () ! | Some p1, Some p2 -> ! if not (Env.path_equal env p1 p2) ! then error "module components do not match" ! | None, Some p -> ! if not (Env.path_equal env (Pident id) p) ! then error "module components do not match" and typedecl_match env id decl1 decl2 = CT.kind_match env decl1.kind decl2.kind && (match (decl1.manifest, decl2.manifest) with *************** *** 345,352 **** (Pdot(path, Ident.name id)) decl.kind) | Some ty -> Some ty in Type_sig(id, {kind = decl.kind; manifest = m}) ! | Module_sig(id, mty) -> ! Module_sig(id, strengthen_modtype (Pdot(path, Ident.name id)) mty) (* Continuation of section 2.8: Type-checking the module language *) --- 395,406 ---- (Pdot(path, Ident.name id)) decl.kind) | Some ty -> Some ty in Type_sig(id, {kind = decl.kind; manifest = m}) ! | Module_sig(id, mdecl) -> ! Module_sig(id, strengthen_moddecl (Pdot(path, Ident.name id)) mdecl) ! and strengthen_moddecl path mdecl = ! let mty = strengthen_modtype path mdecl.Mod.ty ! and path' = match mdecl.Mod.eq with None -> path | Some p -> p ! in { Mod.ty = mty ; Mod.eq = Some path' } (* Continuation of section 2.8: Type-checking the module language *) *************** *** 354,360 **** Signature sg -> check_signature env [] sg | Functor_type(param, arg, res) -> check_modtype env arg; ! check_modtype (Env.add_module param arg env) res and check_signature env seen = function [] -> () | Value_sig(id, vty) :: rem -> --- 408,414 ---- Signature sg -> check_signature env [] sg | Functor_type(param, arg, res) -> check_modtype env arg; ! check_modtype (Env.add_absmodule param arg env) res and check_signature env seen = function [] -> () | Value_sig(id, vty) :: rem -> *************** *** 375,386 **** end; check_signature (Env.add_type id decl env) (Ident.name id :: seen) rem ! | Module_sig(id, mty) :: rem -> if List.mem (Ident.name id) seen then error "repeated module name"; ! check_modtype env mty; ! check_signature (Env.add_module id mty env) (Ident.name id :: seen) rem let rec type_module env = function Longident path -> --- 429,448 ---- end; check_signature (Env.add_type id decl env) (Ident.name id :: seen) rem ! | Module_sig(id, mdecl) :: rem -> if List.mem (Ident.name id) seen then error "repeated module name"; ! check_moddecl env mdecl; ! check_signature (Env.add_module id mdecl env) (Ident.name id :: seen) rem + and check_moddecl env mdecl = + let mty = mdecl.ty in + check_modtype env mdecl.Mod.ty; + match mdecl.Mod.eq with + | None -> () + | Some path -> + let mty' = strengthen_modtype path (Env.find_module path env) in + modtype_match env mty' mty let rec type_module env = function Longident path -> *************** *** 390,396 **** | Functor(param, mty, body) -> check_modtype env mty; Functor_type(param, mty, ! type_module (Env.add_module param mty env) body) | Apply(funct, (Longident path as arg)) -> (match type_module env funct with Functor_type(param, mty_param, mty_res) -> --- 452,458 ---- | Functor(param, mty, body) -> check_modtype env mty; Functor_type(param, mty, ! type_module (Env.add_absmodule param mty env) body) | Apply(funct, (Longident path as arg)) -> (match type_module env funct with Functor_type(param, mty_param, mty_res) -> *************** *** 417,423 **** | Module_str(id, modl) -> if List.mem (Ident.name id) seen then error "repeated module name"; ! (Module_sig(id, type_module env modl), Ident.name id :: seen) | Type_str(id, kind, typ) -> if List.mem (Ident.name id) seen then error "repeated type name"; --- 479,487 ---- | Module_str(id, modl) -> if List.mem (Ident.name id) seen then error "repeated module name"; ! let eq = match modl with Longident p -> Some p | _ -> None in ! let mdecl = { Mod.ty = type_module env modl ; Mod.eq = eq } in ! (Module_sig(id, mdecl), Ident.name id :: seen) | Type_str(id, kind, typ) -> if List.mem (Ident.name id) seen then error "repeated type name"; *************** *** 525,533 **** | Type_sig(id, decl) :: rem -> Type_sig(id, scope_typedecl sc decl) :: scope_signature (Scope.enter_type id sc) rem ! | Module_sig(id, mty) :: rem -> ! Module_sig(id, scope_modtype sc mty) :: scope_signature (Scope.enter_module id sc) rem let rec scope_module sc = function Longident path -> Longident(Scope.module_path path sc) | Structure str -> Structure(scope_structure sc str) --- 589,604 ---- | Type_sig(id, decl) :: rem -> Type_sig(id, scope_typedecl sc decl) :: scope_signature (Scope.enter_type id sc) rem ! | Module_sig(id, mdecl) :: rem -> ! Module_sig(id, scope_moddecl sc mdecl) :: scope_signature (Scope.enter_module id sc) rem + and scope_moddecl sc mdecl = + let mty = scope_modtype sc mdecl.Mod.ty in + let meq = match mdecl.eq with + | None -> None + | Some path -> Some (Scope.module_path path sc) + in + { Mod.ty = mty; Mod.eq = meq } let rec scope_module sc = function Longident path -> Longident(Scope.module_path path sc) | Structure str -> Structure(scope_structure sc str) --poEMdttgo4 Content-Type: text/plain; charset=iso-8859-1 Content-Description: .signature Content-Transfer-Encoding: 8bit -- Judicael.Courant@lri.fr, http://www.lri.fr/~jcourant/ (+33) (0)1 69 15 64 85 "Montre moi des morceaux de ton monde, et je te montrerai le mien" Tim, matricule #929, condamné à mort. http://rozenn.picard.free.fr/tim.html --poEMdttgo4-- ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr