[m-rev.] for review: automatic_include declaration
Peter Ross
peter.ross at miscrit.be
Sat Nov 17 01:05:06 AEDT 2001
Hi,
===================================================================
Estimated hours taken: 4
Branches: main
Add the `:- automatic_include' declaration.
This declaration allows one to automatically import a sub-module when
the parent module is imported.
This is useful for cases where you have extremely large sub-module
hierachies where each sub-module only contains a small amount of
functionality. These sort of hierachies are generated by the .NET
interface generation tool.
compiler/modules.m:
When reading in short and long interfaces recursively read in any
modules specified by an `:- automatic_include' declaration.
Check that any `:- automatic_include' declaration in the interface
refers to an existing visible sub-module.
compiler/make_hlds.m:
compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/prog_data.m:
compiler/prog_io.m:
library/ops.m:
Small changes to handle the new declaration.
doc/reference_manual.texi:
Document the `:- automatic_include' declaration.
tests/hard_coded/sub-modules/Mmakefile:
tests/hard_coded/sub-modules/auto_parent.m:
tests/hard_coded/sub-modules/auto_parent.separate.m:
tests/hard_coded/sub-modules/automatic_include.exp:
tests/hard_coded/sub-modules/automatic_include.m:
tests/invalid/Mmakefile:
tests/invalid/automatic_include.err_exp:
tests/invalid/automatic_include.m:
Test cases.
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.391
diff -u -r1.391 make_hlds.m
--- compiler/make_hlds.m 12 Nov 2001 11:08:07 -0000 1.391
+++ compiler/make_hlds.m 16 Nov 2001 13:47:45 -0000
@@ -280,6 +280,9 @@
{ module_add_indirectly_imported_module_specifiers(
Specifiers, Module0, Module) }
)
+ ; { ModuleDefn = automatic_include(_) } ->
+ { Status = Status0 },
+ { Module = Module0 }
; { ModuleDefn = include_module(_) } ->
{ Status = Status0 },
{ Module = Module0 }
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.198
diff -u -r1.198 mercury_to_mercury.m
--- compiler/mercury_to_mercury.m 8 Nov 2001 15:30:31 -0000 1.198
+++ compiler/mercury_to_mercury.m 16 Nov 2001 13:47:46 -0000
@@ -762,6 +762,10 @@
io__write_string(":- interface.\n")
; { ModuleDefn = implementation } ->
io__write_string(":- implementation.\n")
+ ; { ModuleDefn = automatic_include(IncludedModules) } ->
+ io__write_string(":- automatic_include "),
+ mercury_write_module_spec_list(IncludedModules),
+ io__write_string(".\n")
; { ModuleDefn = include_module(IncludedModules) } ->
io__write_string(":- include_module "),
mercury_write_module_spec_list(IncludedModules),
Index: compiler/module_qual.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/module_qual.m,v
retrieving revision 1.70
diff -u -r1.70 module_qual.m
--- compiler/module_qual.m 6 Nov 2001 15:21:05 -0000 1.70
+++ compiler/module_qual.m 16 Nov 2001 13:47:46 -0000
@@ -311,6 +311,8 @@
process_module_defn(module(ModuleName), Info0, Info) :-
add_module_defn(ModuleName, Info0, Info).
+process_module_defn(automatic_include(ModuleNameList), Info0, Info) :-
+ list__foldl(add_module_defn, ModuleNameList, Info0, Info).
process_module_defn(include_module(ModuleNameList), Info0, Info) :-
list__foldl(add_module_defn, ModuleNameList, Info0, Info).
process_module_defn(interface, Info0, Info) :-
@@ -627,6 +629,7 @@
update_import_status(import(_), Info, Info, yes).
update_import_status(use(_), Info, Info, yes).
update_import_status(version_numbers(_, _), Info, Info, yes).
+update_import_status(automatic_include(_), Info, Info, yes).
update_import_status(include_module(_), Info0, Info, yes) :-
% The sub-module might make use of *any* of the imported modules.
% There's no way for us to tell which ones.
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.205
diff -u -r1.205 modules.m
--- compiler/modules.m 15 Nov 2001 16:02:14 -0000 1.205
+++ compiler/modules.m 16 Nov 2001 13:47:48 -0000
@@ -620,7 +620,7 @@
:- implementation.
:- import_module llds_out, passes_aux, prog_out, prog_util, mercury_to_mercury.
:- import_module prog_io_util, options, module_qual, foreign.
-:- import_module recompilation_version.
+:- import_module error_util, recompilation_version.
:- import_module string, map, term, varset, dir, library.
:- import_module assoc_list, relation, char, require.
@@ -2043,19 +2043,35 @@
"endif"
]),
+ % The .date and .date0 files depend on the .int0 files
+ % for the parent modules, and the .int3 files for the
+ % directly and indirectly imported modules.
+ %
+ % For nested sub-modules, the `.date' files for the
+ % parent modules also depend on the same things as the
+ % `.date' files for this module, since all the `.date'
+ % files will get produced by a single mmc command.
+ % XXX The same is true for the `.date0' files, but
+ % including those dependencies here might result in
+ % cyclic dependencies(?).
+
module_name_to_file_name(ModuleName, ".date", no,
DateFileName),
module_name_to_file_name(ModuleName, ".date0", no,
Date0FileName),
io__write_strings(DepStream, [
"\n\n", DateFileName, " ",
- Date0FileName, " : ",
+ Date0FileName
+ ]),
+ write_dependencies_list(ParentDeps, ".date", DepStream),
+ io__write_strings(DepStream, [
+ " : ",
SourceFileName
]),
write_dependencies_list(ParentDeps, ".int0", DepStream),
write_dependencies_list(LongDeps, ".int3", DepStream),
write_dependencies_list(ShortDeps, ".int3", DepStream),
-
+
module_name_to_file_name(ModuleName, ".dir", no, DirFileName),
module_name_to_split_c_file_name(ModuleName, 0, ".$O",
SplitCObj0FileName),
@@ -4687,6 +4703,7 @@
ModItems0)
),
{ get_dependencies(Items, IndirectImports1, IndirectUses1) },
+ { get_automatic_includes(Items, Includes) },
{ list__append(IndirectImports0, IndirectImports1,
IndirectImports2) },
{ list__append(IndirectImports2, IndirectUses1,
@@ -4697,8 +4714,11 @@
^ error := ModError },
process_module_long_interfaces(ReadModules, NeedQualifier,
- Imports, Ext, IndirectImports3, IndirectImports,
- Module2, Module)
+ Includes, Ext, IndirectImports3, IndirectImports4,
+ Module2, Module3),
+ process_module_long_interfaces(ReadModules, NeedQualifier,
+ Imports, Ext, IndirectImports4, IndirectImports,
+ Module3, Module)
).
:- pred check_module_accessibility(module_name, module_name, item_list,
@@ -4870,14 +4890,17 @@
{ ModIndirectImports = [Import | ModIndirectImports0] },
{ get_dependencies(Items, Imports1, Uses1) },
+ { get_automatic_includes(Items, Includes) },
{ list__append(IndirectImports0, Imports1, IndirectImports1) },
{ list__append(IndirectImports1, Uses1, IndirectImports2) },
{ list__append(ModItems0, Items, ModItems) },
{ Module2 = ((Module1 ^ indirect_deps := ModIndirectImports)
^ items := ModItems)
^ error := ModError },
+ process_module_short_interfaces(ReadModules, Includes, Ext,
+ IndirectImports2, IndirectImports3, Module2, Module3),
process_module_short_interfaces(ReadModules, Imports, Ext,
- IndirectImports2, IndirectImports, Module2, Module)
+ IndirectImports3, IndirectImports, Module3, Module)
).
strip_off_interface_decl(Items0, Items) :-
@@ -4957,6 +4980,31 @@
%-----------------------------------------------------------------------------%
+ % get_automatic_includes(Items, IncludeDeps):
+ % IncludeDeps is the list of modules referenced by a
+ % `:- automatic_include' in Items.
+ %
+:- pred get_automatic_includes(item_list::in, list(module_name)::out) is det.
+
+get_automatic_includes(Items, IncludeDeps) :-
+ get_automatic_includes_2(Items, [], IncludeDeps).
+
+:- pred get_automatic_includes_2(item_list::in,
+ list(module_name)::in, list(module_name)::out) is det.
+
+get_automatic_includes_2([], IncludeDeps, IncludeDeps).
+get_automatic_includes_2([Item - _Ctxt | Items], IncludeDeps0, IncludeDeps) :-
+ (
+ Item = module_defn(_VarSet, automatic_include(Modules))
+ ->
+ list__append(IncludeDeps0, Modules, IncludeDeps1)
+ ;
+ IncludeDeps1 = IncludeDeps0
+ ),
+ get_automatic_includes_2(Items, IncludeDeps1, IncludeDeps).
+
+%-----------------------------------------------------------------------------%
+
get_dependencies(Items, ImportDeps, UseDeps) :-
get_dependencies_implementation(Items, [], [] , [], [],
IntImportDeps, IntUseDeps, ImpImportDeps, ImpUseDeps),
@@ -5122,12 +5170,37 @@
%
{ get_children(Items0, NestedSubmodules) },
{ assoc_list__keys(ModuleList, SeparateSubModules) },
- { Duplicates = set__intersect(set__list_to_set(NestedSubmodules),
- set__list_to_set(SeparateSubModules)) },
+ { NestedSubmodulesSet = set__list_to_set(NestedSubmodules) },
+ { SeparateSubModulesSet = set__list_to_set(SeparateSubModules) },
+ { Duplicates = NestedSubmodulesSet `intersect` SeparateSubModulesSet },
( { set__empty(Duplicates) } ->
[]
;
report_duplicate_modules(Duplicates, Items0)
+ ),
+
+ %
+ % Ensure that the automatic_include only refers to public
+ % sub-modules of the current module.
+ % seen by the current module.
+ %
+ ( { ModuleList = [ _ - CurrentModuleItems | _ ] } ->
+ { get_interface(CurrentModuleItems, InterfaceItems) },
+ { get_automatic_includes(InterfaceItems, AutomaticIncludes) },
+ { get_children(InterfaceItems, PublicSubModules) },
+ { AutomaticIncludesSet = set__list_to_set(AutomaticIncludes) },
+ { PublicSubModulesSet = set__list_to_set(PublicSubModules) },
+ ( { AutomaticIncludesSet `subset` PublicSubModulesSet } ->
+ []
+ ;
+ { ErrorIncludes = to_sorted_list(
+ AutomaticIncludesSet `difference`
+ PublicSubModulesSet) },
+ list__foldl(report_improper_automatic_include(
+ CurrentModuleItems), ErrorIncludes)
+ )
+ ;
+ { unexpected(this_file, "empty module list") }
).
:- pred split_into_submodules_2(module_name, item_list, bool, item_list,
@@ -5334,6 +5407,30 @@
io__write_string(" a separate sub-module and a nested sub-module.\n"),
io__set_exit_status(1).
+:- pred report_improper_automatic_include(item_list::in, module_name::in,
+ io__state::di, io__state::uo) is det.
+
+report_improper_automatic_include(Items, ModuleName) -->
+ { FindContexts = (pred(Context::out) is nondet :-
+ list__member(Item, Items),
+ Item = module_defn(_VarSet, ModuleDefn) - Context,
+ ModuleDefn = automatic_include(AutomaticIncludes),
+ list__member(ModuleName, AutomaticIncludes)
+ ) },
+ { WriteError = (pred(Context::in, di, uo) is det -->
+ { ModuleNameStr = describe_sym_name(ModuleName) },
+ error_util__write_error_pieces(Context, 0,
+ [words("error:"),
+ words("The automatic_include declaration"),
+ words("refers to the sub-module "),
+ words(ModuleNameStr),
+ words("which doesn't exist or is not"),
+ words("visible externally.")])
+ ) },
+ { solutions(FindContexts, Contexts) },
+ list__foldl(WriteError, Contexts),
+ io__set_exit_status(1).
+
% Given a module (well, a list of items), extract the interface
% part of that module, i.e. all the items between `:- interface'
% and `:- implementation'.
@@ -5556,5 +5653,11 @@
;
[]
).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "modules.m".
%-----------------------------------------------------------------------------%
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.71
diff -u -r1.71 prog_data.m
--- compiler/prog_data.m 6 Nov 2001 15:21:09 -0000 1.71
+++ compiler/prog_data.m 16 Nov 2001 13:47:49 -0000
@@ -912,6 +912,7 @@
; use(sym_list)
; include_module(list(module_name))
+ ; automatic_include(list(module_name))
% This is used to represent the version numbers
% of items in an interface file for use in
Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.197
diff -u -r1.197 prog_io.m
--- compiler/prog_io.m 16 Jul 2001 08:21:04 -0000 1.197
+++ compiler/prog_io.m 16 Nov 2001 13:47:50 -0000
@@ -1092,6 +1092,20 @@
),
check_no_attributes(Result1, Attributes, Result).
+process_decl(DefaultModuleName, VarSet0, "automatic_include", [ModuleNames],
+ Attributes, Result) :-
+ parse_list(parse_module_name(DefaultModuleName), ModuleNames, Result0),
+ (
+ Result0 = ok(ModuleNameSyms),
+ varset__coerce(VarSet0, VarSet),
+ Result1 = ok(module_defn(VarSet,
+ automatic_include(ModuleNameSyms)))
+ ;
+ Result0 = error(A, B),
+ Result1 = error(A, B)
+ ),
+ check_no_attributes(Result1, Attributes, Result).
+
process_decl(DefaultModuleName, VarSet0, "end_module", [ModuleName],
Attributes, Result) :-
%
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.224
diff -u -r1.224 reference_manual.texi
--- doc/reference_manual.texi 12 Nov 2001 11:08:13 -0000 1.224
+++ doc/reference_manual.texi 16 Nov 2001 13:47:57 -0000
@@ -489,6 +489,7 @@
end_module fx 1199
import_module fx 1199
include_module fx 1199
+automatic_include fx 1199
instance fx 1199
inst fx 1199
mode fx 1199
@@ -541,6 +542,7 @@
:- implementation
:- import_module
:- use_module
+:- automatic_include
:- include_module
:- end_module
@end example
@@ -3657,6 +3659,7 @@
* Nested sub-modules::
* Separate sub-modules::
* Visibility rules::
+* Automatic importation of sub-modules::
* Implementation bugs and limitations::
@end menu
@@ -3747,6 +3750,25 @@
Note that as mentioned previously, all @samp{:- import_module} and
@samp{:- use_module} declarations must use fully-qualified module
names.
+
+ at node Automatic importation of sub-modules
+ at subsection Automatic importation of sub-modules
+
+The @samp{:- automatic_include} declaration allows one to automatically
+import a sub-module when the parent module is imported.
+
+Each module mentioned by an @samp{:- automatic_include} declaration in
+the interface section of a parent module will also be imported when the
+parent module is imported.
+The modules the @samp{:- automatic_include} specifies will be treated as if
+they were imported by the same declaration which imported the parent
+module,
+namely a @samp{:- import_module} or a @samp{:- use_module}.
+It is an error to specify
+a module which is not a direct sub-module of the parent module
+or a sub-module which is not visible externally (an implementation sub-module).
+An @samp{:- automatic_include} declaration which occurs in the
+implementation section of a module is ignored.
@node Implementation bugs and limitations
@subsection Implementation bugs and limitations
Index: library/ops.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/ops.m,v
retrieving revision 1.37
diff -u -r1.37 ops.m
--- library/ops.m 12 Nov 2001 11:08:16 -0000 1.37
+++ library/ops.m 16 Nov 2001 13:47:57 -0000
@@ -310,6 +310,7 @@
ops__op_table("aditi_top_down", before, fx, 500). % Mercury extension
ops__op_table("all", before, fxy, 950). % Mercury/NU-Prolog extension
ops__op_table("and", after, xfy, 720). % NU-Prolog extension
+ops__op_table("automatic_include", before, fx, 1199). % Mercury extension
ops__op_table("div", after, yfx, 400). % standard ISO Prolog
ops__op_table("else", after, xfy, 1170). % Mercury/NU-Prolog extension
ops__op_table("end_module", before, fx, 1199). % Mercury extension
Index: tests/hard_coded/sub-modules/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/sub-modules/Mmakefile,v
retrieving revision 1.4
diff -u -r1.4 Mmakefile
--- tests/hard_coded/sub-modules/Mmakefile 15 Nov 2001 15:01:30 -0000 1.4
+++ tests/hard_coded/sub-modules/Mmakefile 16 Nov 2001 13:47:58 -0000
@@ -25,7 +25,8 @@
nested2 \
nested3 \
class \
- nested_intermod_main
+ nested_intermod_main \
+ automatic_include
MCFLAGS-nested_intermod = --intermodule-optimization
MCFLAGS-nested_intermod_main = --intermodule-optimization
Index: tests/hard_coded/sub-modules/auto_parent.m
===================================================================
RCS file: tests/hard_coded/sub-modules/auto_parent.m
diff -N tests/hard_coded/sub-modules/auto_parent.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sub-modules/auto_parent.m 16 Nov 2001 13:47:58 -0000
@@ -0,0 +1,32 @@
+% Test the automatic_include statement.
+% Used by automatic_include.m
+
+:- module auto_parent.
+
+:- interface.
+
+:- import_module io.
+
+:- include_module separate.
+
+:- automatic_include auto_parent__nested, auto_parent__separate.
+
+:- pred hello(io__state::di, io__state::uo) is det.
+
+ :- module auto_parent__nested.
+ :- interface.
+ :- pred hello(io__state::di, io__state::uo) is det.
+ :- end_module auto_parent__nested.
+
+:- implementation.
+
+hello -->
+ io__write_string("auto_parent: hello\n").
+
+:- module auto_parent__nested.
+:- implementation.
+
+hello -->
+ io__write_string("auto_parent__nested: hello\n").
+
+:- end_module auto_parent__nested.
Index: tests/hard_coded/sub-modules/auto_parent.separate.m
===================================================================
RCS file: tests/hard_coded/sub-modules/auto_parent.separate.m
diff -N tests/hard_coded/sub-modules/auto_parent.separate.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sub-modules/auto_parent.separate.m 16 Nov 2001 13:47:58 -0000
@@ -0,0 +1,14 @@
+% Used by automatic_include.m
+
+:- module auto_parent__separate.
+
+:- interface.
+
+% The parent module autos io.
+
+:- pred hello(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+hello -->
+ io__write_string("auto_parent__separate: hello\n").
Index: tests/hard_coded/sub-modules/automatic_include.exp
===================================================================
RCS file: tests/hard_coded/sub-modules/automatic_include.exp
diff -N tests/hard_coded/sub-modules/automatic_include.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sub-modules/automatic_include.exp 16 Nov 2001 13:47:58 -0000
@@ -0,0 +1,2 @@
+auto_parent__nested: hello
+auto_parent__separate: hello
Index: tests/hard_coded/sub-modules/automatic_include.m
===================================================================
RCS file: tests/hard_coded/sub-modules/automatic_include.m
diff -N tests/hard_coded/sub-modules/automatic_include.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sub-modules/automatic_include.m 16 Nov 2001 13:47:58 -0000
@@ -0,0 +1,18 @@
+% Test the when importing the module auto_parent that we also get the
+% sub-modules nested and separate automatically imported.
+
+:- module (automatic_include).
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- use_module auto_parent.
+
+main -->
+ auto_parent__nested__hello,
+ auto_parent__separate__hello.
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.101
diff -u -r1.101 Mmakefile
--- tests/invalid/Mmakefile 15 Nov 2001 13:32:48 -0000 1.101
+++ tests/invalid/Mmakefile 16 Nov 2001 13:47:58 -0000
@@ -32,6 +32,7 @@
SINGLEMODULE_SOURCES= \
any_mode.m \
assert_in_interface.m \
+ automatic_include.m \
bigtest.m \
bind_var_errors.m \
builtin_int.m \
@@ -185,6 +186,7 @@
# For these test cases, the bug is caught when generating dependencies,
# so it is easiest just to do that step.
+MCFLAGS-automatic_include = --generate-dependencies -E
MCFLAGS-nested_impl_in_int = --generate-dependencies
MCFLAGS-duplicate_module_test = --generate-dependencies
Index: tests/invalid/automatic_include.err_exp
===================================================================
RCS file: tests/invalid/automatic_include.err_exp
diff -N tests/invalid/automatic_include.err_exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/invalid/automatic_include.err_exp 16 Nov 2001 13:47:58 -0000
@@ -0,0 +1,6 @@
+automatic_include.m:007: error: The automatic_include declaration refers to the
+automatic_include.m:007: sub-module `automatic_include:child' which doesn't
+automatic_include.m:007: exist or is not visible externally.
+automatic_include.m:008: error: The automatic_include declaration refers to the
+automatic_include.m:008: sub-module `automatic_include:list' which doesn't
+automatic_include.m:008: exist or is not visible externally.
Index: tests/invalid/automatic_include.m
===================================================================
RCS file: tests/invalid/automatic_include.m
diff -N tests/invalid/automatic_include.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/invalid/automatic_include.m 16 Nov 2001 13:47:58 -0000
@@ -0,0 +1,15 @@
+:- module (automatic_include).
+
+:- interface.
+
+:- type t.
+
+:- automatic_include automatic_include__child. % not visible
+:- automatic_include list. % doesn't exist
+
+:- implementation.
+
+:- module automatic_include__child.
+:- interface.
+:- type t.
+:- end_module automatic_include__child.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list