diff options
-rw-r--r-- | contrib/extraction/extract_env.ml | 2 | ||||
-rw-r--r-- | library/declaremods.ml | 142 | ||||
-rw-r--r-- | library/declaremods.mli | 33 | ||||
-rw-r--r-- | library/library.ml | 6 | ||||
-rwxr-xr-x | library/nametab.ml | 5 | ||||
-rwxr-xr-x | library/nametab.mli | 5 | ||||
-rw-r--r-- | parsing/g_vernac.ml4 | 3 | ||||
-rw-r--r-- | test-suite/output/TranspModtype.out | 7 | ||||
-rw-r--r-- | test-suite/output/TranspModtype.v | 22 | ||||
-rw-r--r-- | toplevel/vernacentries.ml | 10 | ||||
-rw-r--r-- | toplevel/vernacexpr.ml | 2 |
11 files changed, 189 insertions, 48 deletions
diff --git a/contrib/extraction/extract_env.ml b/contrib/extraction/extract_env.ml index 9e68ec8e4..0e5325a2e 100644 --- a/contrib/extraction/extract_env.ml +++ b/contrib/extraction/extract_env.ml @@ -259,7 +259,7 @@ let mono_environment kn_set = let dir_module_of_id m = try - Nametab.locate_loaded_library (make_short_qualid m) + Nametab.full_name_module (make_short_qualid m) with Not_found -> errorlabstrm "module_message" (str "Module" ++ spc () ++ pr_id m ++ spc () ++ str "not found.") diff --git a/library/declaremods.ml b/library/declaremods.ml index 2be5e8a73..5dba4c208 100644 --- a/library/declaremods.ml +++ b/library/declaremods.ml @@ -77,7 +77,8 @@ let modtab_objects = (* currently started interactive module (if any) - its arguments (if it is a functor) and declared output type *) let openmod_info = - ref (([],None) : mod_bound_id list * module_type_entry option) + ref (([],None,None) : mod_bound_id list * module_type_entry option + * module_type_body option) let _ = Summary.declare_summary "MODULE-INFO" { Summary.freeze_function = (fun () -> @@ -91,7 +92,7 @@ let _ = Summary.declare_summary "MODULE-INFO" Summary.init_function = (fun () -> modtab_substobjs := MPmap.empty; modtab_objects := MPmap.empty; - openmod_info := ([],None)); + openmod_info := ([],None,None)); Summary.survive_section = false } (* auxiliary functions to transform section_path and kernel_name given @@ -119,6 +120,18 @@ let msid_of_prefix (_,(mp,sec)) = anomaly ("Non-empty section in module name!" ^ string_of_mp mp ^ "." ^ string_of_dirpath sec) + +(* This function checks if the type calculated for the module [mp] is + a subtype of [sub_mtb]. Uses only the global environment. *) +let check_subtypes mp sub_mtb = + let env = Global.env () in + let mtb = (Environ.lookup_module mp env).mod_type in + let _ = Environ.add_constraints + (Subtyping.check_subtypes env mtb sub_mtb) + in + () (* The constraints are checked and forgot immediately! *) + + (* This function registers the visibility of the module and iterates through its components. It is called by plenty module functions *) @@ -164,10 +177,20 @@ let cache_module ((sp,kn as oname),(entry,substobjs,substituted)) = let _ = match entry with | None -> anomaly "You must not recache interactive modules!" - | Some me -> + | Some (me,sub_mte_o) -> + let sub_mtb_o = match sub_mte_o with + None -> None + | Some mte -> Some (Mod_typing.translate_modtype (Global.env()) mte) + in + let mp = Global.add_module (basename sp) me in if mp <> mp_of_kn kn then - anomaly "Kernel and Library names do not match" + anomaly "Kernel and Library names do not match"; + + match sub_mtb_o with + None -> () + | Some sub_mtb -> check_subtypes mp sub_mtb + in conv_names_do_module false "cache" load_objects 1 oname substobjs substituted @@ -431,12 +454,31 @@ let start_module interp_modtype id args res_o = List.fold_left (intern_args interp_modtype) (env,[]) args in let arg_entries = List.concat (List.rev arg_entries_revlist) in - let res_entry_o = option_app (interp_modtype env) res_o in + + let res_entry_o, sub_body_o = match res_o with + None -> None, None + | Some (res, true) -> + Some (interp_modtype env res), None + | Some (res, false) -> + (* If the module type is non-restricting, we must translate it + here to catch errors as early as possible. If it is + estricting, the kernel takes care of it. *) + let sub_mte = + List.fold_right + (fun (arg_id,arg_t) mte -> MTEfunsig(arg_id,arg_t,mte)) + arg_entries + (interp_modtype env res) + in + let sub_mtb = + Mod_typing.translate_modtype (Global.env()) sub_mte + in + None, Some sub_mtb + in let mp = Global.start_module id arg_entries res_entry_o in let mbids = List.map fst arg_entries in - openmod_info:=(mbids,res_entry_o); + openmod_info:=(mbids,res_entry_o,sub_body_o); let prefix = Lib.start_module id mp fs in Nametab.push_dir (Nametab.Until 1) (fst prefix) (DirOpenModule prefix); Lib.add_frozen_state () @@ -446,11 +488,17 @@ let end_module id = let oldoname,oldprefix,fs,lib_stack = Lib.end_module id in let mp = Global.end_module id in + let mbids, res_o, sub_o = !openmod_info in + + begin match sub_o with + None -> () + | Some sub_mtb -> check_subtypes mp sub_mtb + end; + let substitute, keep, special = Lib.classify_segment lib_stack in let dir = fst oldprefix in let msid = msid_of_prefix oldprefix in - let mbids, res_o = !openmod_info in Summary.unfreeze_other_summaries fs; @@ -528,7 +576,7 @@ let register_library dir cenv objs digest = let start_library dir = let mp = Global.start_library dir in - openmod_info:=[],None; + openmod_info:=[],None,None; Lib.start_compilation dir mp; Lib.add_frozen_state () @@ -542,6 +590,33 @@ let export_library dir = +let do_open_export (_,(_,mp)) = +(* for non-substitutive exports: + let mp = Nametab.locate_module (qualid_of_dirpath dir) in *) + let prefix,objects = MPmap.find mp !modtab_objects in + open_objects 1 prefix objects + +let classify_export (_,(export,_ as obj)) = + if export then Substitute obj else Dispose + +let subst_export (_,subst,(export,mp as obj)) = + let mp' = subst_mp subst mp in + if mp'==mp then obj else + (export,mp') + +let (in_export,out_export) = + declare_object {(default_object "EXPORT MODULE") with + cache_function = do_open_export; + open_function = (fun i o -> if i=1 then do_open_export o); + subst_function = subst_export; + classify_function = classify_export } + +let export_module mp = +(* for non-substitutive exports: + let dir = Nametab.dir_of_mp mp in *) + Lib.add_anonymous_leaf (in_export (true,mp)) + + let import_module mp = let prefix,objects = MPmap.find mp !modtab_objects in open_objects 1 prefix objects @@ -638,21 +713,32 @@ let declare_module interp_modtype interp_modexpr id args mty_o mexpr_o = List.fold_left (intern_args interp_modtype) (env,[]) args in let arg_entries = List.concat (List.rev arg_entries_revlist) in - let mty_entry_o = option_app (interp_modtype env) mty_o in - let mexpr_entry_o = option_app (interp_modexpr env) mexpr_o in + let mty_entry_o, mty_sub_o = match mty_o with + None -> None, None + | (Some (mty, true)) -> + Some (List.fold_right + (fun (arg_id,arg_t) mte -> MTEfunsig(arg_id,arg_t,mte)) + arg_entries + (interp_modtype env mty)), + None + | (Some (mty, false)) -> + None, + Some (List.fold_right + (fun (arg_id,arg_t) mte -> MTEfunsig(arg_id,arg_t,mte)) + arg_entries + (interp_modtype env mty)) + in + let mexpr_entry_o = match mexpr_o with + None -> None + | Some mexpr -> + Some (List.fold_right + (fun (mbid,mte) me -> MEfunctor(mbid,mte,me)) + arg_entries + (interp_modexpr env mexpr)) + in let entry = - {mod_entry_type = - option_app - (List.fold_right - (fun (arg_id,arg_t) mte -> MTEfunsig(arg_id,arg_t,mte)) - arg_entries) - mty_entry_o; - mod_entry_expr = - option_app - (List.fold_right - (fun (mbid,mte) me -> MEfunctor(mbid,mte,me)) - arg_entries) - mexpr_entry_o } + {mod_entry_type = mty_entry_o; + mod_entry_expr = mexpr_entry_o } in let substobjs = match entry with @@ -660,14 +746,14 @@ let declare_module interp_modtype interp_modexpr id args mty_o mexpr_o = | {mod_entry_expr = Some mexpr} -> get_module_substobjs mexpr | _ -> anomaly "declare_module: No type, no body ..." in - Summary.unfreeze_summaries fs; + Summary.unfreeze_summaries fs; - let dir,mp = dir_of_sp (Lib.make_path id), mp_of_kn (Lib.make_kn id) in - let substituted = subst_substobjs dir mp substobjs in + let dir,mp = dir_of_sp (Lib.make_path id), mp_of_kn (Lib.make_kn id) in + let substituted = subst_substobjs dir mp substobjs in - ignore (add_leaf - id - (in_module (Some entry, substobjs, substituted))) + ignore (add_leaf + id + (in_module (Some (entry, mty_sub_o), substobjs, substituted))) (*s Iterators. *) diff --git a/library/declaremods.mli b/library/declaremods.mli index 9edd051ca..114ea3cf9 100644 --- a/library/declaremods.mli +++ b/library/declaremods.mli @@ -15,21 +15,36 @@ open Environ open Libnames open Libobject open Lib -(*i*) + (*i*) -(*s This modules provides official fucntions to declare modules and - module types *) +(*s This modules provides official functions to declare modules and + module types *) (*s Modules *) +(* [declare_module interp_modtype interp_modexpr id fargs typ expr] + declares module [id], with type constructed by [interp_modtype] + from functor arguments [fargs] and [typ] and with module body + constructed by [interp_modtype] from functor arguments [fargs] and + by [interp_modexpr] from [expr]. At least one of [typ], [expr] must + be non-empty. + + The [bool] in [typ] tells if the module must be abstracted [true] + with respect to the module type or merely matched without any + restriction [false]. +*) + val declare_module : (env -> 'modtype -> module_type_entry) -> (env -> 'modexpr -> module_expr) -> identifier -> - (identifier list * 'modtype) list -> 'modtype option -> 'modexpr option -> unit - -val start_module : (env -> 'modtype -> module_type_entry) -> - identifier -> (identifier list * 'modtype) list -> 'modtype option -> unit + (identifier list * 'modtype) list -> ('modtype * bool) option -> + 'modexpr option -> unit + +val start_module : (env -> 'modtype -> module_type_entry) -> + identifier -> + (identifier list * 'modtype) list -> ('modtype * bool) option -> + unit val end_module : identifier -> unit @@ -74,6 +89,10 @@ val export_library : val import_module : module_path -> unit +(* [export_module mp] is similar, but is run when the module + containing it is imported *) + +val export_module : module_path -> unit (*s [fold_all_segments] and [iter_all_segments] iterate over all segments, the modules' segments first and then the current diff --git a/library/library.ml b/library/library.ml index e7087438b..1f75b4ca0 100644 --- a/library/library.ml +++ b/library/library.ml @@ -389,7 +389,7 @@ let rec_intern_by_filename_only id f = let locate_qualified_library qid = (* Look if loaded in current environment *) try - let dir = Nametab.locate_loaded_library qid in + let dir = Nametab.full_name_module qid in (LibLoaded, dir, library_full_filename dir) with Not_found -> (* Look if in loadpath *) @@ -511,8 +511,8 @@ let export_library (loc,qid) = match Nametab.locate_module qid with MPfile dir -> add_anonymous_leaf (in_require ([dir],Some true)) - | _ -> - raise Not_found + | mp -> + export_module mp with Not_found -> user_err_loc diff --git a/library/nametab.ml b/library/nametab.ml index f6418de3e..cbb3b23e9 100755 --- a/library/nametab.ml +++ b/library/nametab.ml @@ -355,7 +355,7 @@ let locate_module qid = | DirModule (_,(mp,_)) -> mp | _ -> raise Not_found -let locate_loaded_library qid = +let full_name_module qid = match locate_dir qid with | DirModule (dir,_) -> dir | _ -> raise Not_found @@ -428,6 +428,9 @@ let id_of_global ctx_opt ref = let sp_of_syntactic_definition kn = Globrevtab.find (SyntacticDef kn) !the_globrevtab +let dir_of_mp mp = + MPmap.find mp !the_modrevtab + (* Shortest qualid functions **********************************************) diff --git a/library/nametab.mli b/library/nametab.mli index 1f29a9313..bd1a8b1bd 100755 --- a/library/nametab.mli +++ b/library/nametab.mli @@ -127,7 +127,7 @@ val full_name_modtype : qualid -> section_path val full_name_cci : qualid -> section_path (* As above but checks that the path found is indeed a module *) -val locate_loaded_library : qualid -> dir_path +val full_name_module : qualid -> dir_path (*s Reverse lookup -- finding user names corresponding to the given @@ -145,6 +145,9 @@ val shortest_qualid_of_syndef : val id_of_global : Sign.named_context option -> global_reference -> identifier +val dir_of_mp : + module_path -> dir_path + (* Printing of global references using names as short as possible *) val pr_global_env : Sign.named_context option -> global_reference -> std_ppcmds diff --git a/parsing/g_vernac.ml4 b/parsing/g_vernac.ml4 index b4f7abbb0..fdf73d047 100644 --- a/parsing/g_vernac.ml4 +++ b/parsing/g_vernac.ml4 @@ -343,7 +343,8 @@ GEXTEND Gram [ [ bls = LIST0 module_binders -> List.flatten bls ] ] ; of_module_type: - [ [ ":"; mty = Module.module_type -> mty ] ] + [ [ ":"; mty = Module.module_type -> (mty, true) + | "<:"; mty = Module.module_type -> (mty, false) ] ] ; is_module_type: [ [ ":="; mty = Module.module_type -> mty ] ] diff --git a/test-suite/output/TranspModtype.out b/test-suite/output/TranspModtype.out new file mode 100644 index 000000000..f94ed6423 --- /dev/null +++ b/test-suite/output/TranspModtype.out @@ -0,0 +1,7 @@ +TrM.A = M.A + : Set +OpM.A = M.A + : Set +TrM.B = M.B + : Set +*** [ OpM.B : Set ] diff --git a/test-suite/output/TranspModtype.v b/test-suite/output/TranspModtype.v new file mode 100644 index 000000000..27b1fb9f9 --- /dev/null +++ b/test-suite/output/TranspModtype.v @@ -0,0 +1,22 @@ +Module Type SIG. + Axiom A:Set. + Axiom B:Set. +End SIG. + +Module M:SIG. + Definition A:=nat. + Definition B:=nat. +End M. + +Module N<:SIG:=M. + +Module TranspId[X:SIG] <: SIG with Definition A:=X.A := X. +Module OpaqueId[X:SIG] : SIG with Definition A:=X.A := X. + +Module TrM := TranspId M. +Module OpM := OpaqueId M. + +Print TrM.A. +Print OpM.A. +Print TrM.B. +Print OpM.B. diff --git a/toplevel/vernacentries.ml b/toplevel/vernacentries.ml index 5efbcc5d3..5bba0c630 100644 --- a/toplevel/vernacentries.ml +++ b/toplevel/vernacentries.ml @@ -819,16 +819,16 @@ let vernac_print = function | PrintHintDb -> Auto.print_searchtable () | PrintScope s -> pp (Symbols.pr_scope (Constrextern.without_symbols pr_rawterm) s) -let global_loaded_library r = +let global_module r = let (loc,qid) = qualid_of_reference r in - try Nametab.locate_loaded_library qid + try Nametab.full_name_module qid with Not_found -> - user_err_loc (loc, "global_loaded_library", + user_err_loc (loc, "global_module", str "Module/section " ++ pr_qualid qid ++ str " not found") let interp_search_restriction = function - | SearchOutside l -> (List.map global_loaded_library l, true) - | SearchInside l -> (List.map global_loaded_library l, false) + | SearchOutside l -> (List.map global_module l, true) + | SearchInside l -> (List.map global_module l, false) let vernac_search s r = let r = interp_search_restriction r in diff --git a/toplevel/vernacexpr.ml b/toplevel/vernacexpr.ml index 4756755b4..51d080faf 100644 --- a/toplevel/vernacexpr.ml +++ b/toplevel/vernacexpr.ml @@ -196,7 +196,7 @@ type vernac_expr = (* Modules and Module Types *) | VernacDeclareModule of identifier * - module_binder list * module_type_ast option * module_ast option + module_binder list * (module_type_ast * bool) option * module_ast option | VernacDeclareModuleType of identifier * module_binder list * module_type_ast option |