diff: nested modules: allow split int/impl
Fergus Henderson
fjh at cs.mu.OZ.AU
Sun Jul 26 05:46:34 AEST 1998
Estimated hours taken: 4
Implement some parts of the support for nested modules that I had
forgotten about.
compiler/modules.m:
Allow the `:- interface' and `:- implementation' parts of
nested modules to be separated.
Check that `:- implementation' declarations for nested
modules don't occur in the interface section of the parent module.
tests/hard_coded/nested3.m:
tests/hard_coded/nested3.exp:
tests/invalid/nested_impl_in_int.m:
tests/invalid/nested_impl_in_int.err_exp:
Test cases for the above-mentioned feature.
tests/hard_coded/Mmakefile:
Add `RM_C=:', so that the nested modules tests work with
parallel makes, and then enable those tests.
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.82
diff -u -r1.82 modules.m
--- modules.m 1998/07/09 22:03:09 1.82
+++ modules.m 1998/07/25 19:38:52
@@ -280,10 +280,14 @@
% Given a module (well, a list of items), split it into
% its constituent sub-modules, in top-down order.
+ % Report an error if the `implementation' section of a sub-module
+ % is contained inside the `interface' section of its parent module.
-:- pred split_into_submodules(module_name, item_list,
- list(pair(module_name, item_list))).
-:- mode split_into_submodules(in, in, out) is det.
+:- type module_list == list(pair(module_name, item_list)).
+
+:- pred split_into_submodules(module_name, item_list, module_list,
+ io__state, io__state).
+:- mode split_into_submodules(in, in, out, di, uo) is det.
%-----------------------------------------------------------------------------%
@@ -1775,7 +1779,7 @@
read_mod_from_file(FileName, ".m", "Reading file", no,
Items, Error, ModuleName),
{ string__append(FileName, ".m", SourceFileName) },
- { split_into_submodules(ModuleName, Items, SubModuleList) },
+ split_into_submodules(ModuleName, Items, SubModuleList),
{ list__map(init_dependencies(SourceFileName, Error), SubModuleList,
ModuleImportsList) },
{ map__init(DepsMap0) },
@@ -2749,7 +2753,7 @@
;
{ FileName = FileName0 },
{ Items = Items0 },
- { split_into_submodules(ModuleName, Items, SubModuleList) }
+ split_into_submodules(ModuleName, Items, SubModuleList)
),
{ list__map(init_dependencies(FileName, Error), SubModuleList,
ModuleImportsList) }.
@@ -3322,79 +3326,172 @@
%-----------------------------------------------------------------------------%
+:- type submodule_map == map(module_name, item_list).
+
% Given a module (well, a list of items), split it into
% its constituent sub-modules, in top-down order.
+split_into_submodules(ModuleName, Items0, ModuleList) -->
+ { InParentInterface = no },
+ split_into_submodules_2(ModuleName, Items0, InParentInterface,
+ Items, ModuleList),
+ { require(unify(Items, []), "modules.m: items after end_module") }.
+
+:- pred split_into_submodules_2(module_name, item_list, bool, item_list,
+ module_list, io__state, io__state).
+:- mode split_into_submodules_2(in, in, in, out, out, di, uo) is det.
+
+split_into_submodules_2(ModuleName, Items0, InParentInterface,
+ Items, ModuleList) -->
+ { InInterface0 = no },
+ split_into_submodules_3(ModuleName, Items0,
+ InParentInterface, InInterface0,
+ ThisModuleItems, Items, SubModules),
+ { map__to_assoc_list(SubModules, SubModuleList) },
+ { ModuleList = [ModuleName - ThisModuleItems | SubModuleList] }.
-split_into_submodules(ModuleName, Items0, ModuleList) :-
- split_into_submodules_2(ModuleName, Items0, Items, ModuleList),
- require(unify(Items, []), "modules.m: items after end_module").
-
-:- pred split_into_submodules_2(module_name, item_list, item_list,
- list(pair(module_name, item_list))).
-:- mode split_into_submodules_2(in, in, out, out) is det.
-
-split_into_submodules_2(ModuleName, Items0, Items, ModuleList) :-
- split_into_submodules_3(ModuleName, Items0, ThisModuleItems,
- Items, SubModuleList),
- ModuleList = [ModuleName - ThisModuleItems | SubModuleList].
-
-:- pred split_into_submodules_3(module_name, item_list, item_list, item_list,
- list(pair(module_name, item_list))).
-:- mode split_into_submodules_3(in, in, out, out, out) is det.
+:- pred split_into_submodules_3(module_name, item_list, bool, bool,
+ item_list, item_list, map(module_name, item_list),
+ io__state, io__state).
+:- mode split_into_submodules_3(in, in, in, in, out, out, out, di, uo) is det.
-split_into_submodules_3(_ModuleName, [], [], [], []).
+split_into_submodules_3(_ModuleName, [], _, _, [], [], SubModules) -->
+ { map__init(SubModules) }.
split_into_submodules_3(ModuleName, [Item | Items1],
- ThisModuleItems, OtherItems, SubModules) :-
+ InParentInterface, InInterface0,
+ ThisModuleItems, OtherItems, SubModules) -->
(
%
% check for a `module' declaration, which signals
% the start of a nested module
%
- Item = module_defn(VarSet, module(SubModuleName)) - Context
+ { Item = module_defn(VarSet, module(SubModuleName)) - Context }
->
%
% parse in the items for the nested submodule
%
- split_into_submodules_2(SubModuleName, Items1,
+ split_into_submodules_2(SubModuleName, Items1, InInterface0,
Items2, SubModules0),
%
% parse in the remaining items for this module
%
- split_into_submodules_3(ModuleName, Items2,
- ThisModuleItems0, Items3, SubModules1),
+ split_into_submodules_3(ModuleName, Items2, InParentInterface,
+ InInterface0, ThisModuleItems0, Items3, SubModules1),
+
+ %
+ % combine the sub-module declarations from the prevous two
+ % steps
+ %
+ { list__foldl(add_submodule, SubModules0, SubModules1,
+ SubModules) },
%
% replace the nested submodule with an `include_module'
% declaration
%
- IncludeSubMod = module_defn(VarSet,
- include_module([SubModuleName])) - Context,
- ThisModuleItems = [IncludeSubMod | ThisModuleItems0],
- OtherItems = Items3,
- list__append(SubModules0, SubModules1, SubModules)
+ { IncludeSubMod = module_defn(VarSet,
+ include_module([SubModuleName])) - Context },
+ { ThisModuleItems = [IncludeSubMod | ThisModuleItems0] },
+ { OtherItems = Items3 }
;
%
% check for a matching `end_module' declaration
%
- Item = module_defn(_VarSet, end_module(ModuleName)) - _Context
+ { Item = module_defn(_VarSet, end_module(ModuleName)) - _ }
->
%
% if so, thats the end of this module
%
- ThisModuleItems = [],
- OtherItems = Items1,
- SubModules = []
+ { ThisModuleItems = [] },
+ { OtherItems = Items1 },
+ { map__init(SubModules) }
;
%
- % otherwise just parse the remaining items for this
- % module and then put the current item back onto the
- % front of the item list for this module
+ % otherwise, process the next item in this module
+ %
+
+ %
+ % update the flag which records whether
+ % we're currently in the interface section,
+ % and report an error if there is an `implementation'
+ % section inside an `interface' section.
+ %
+ (
+ { Item = module_defn(_, interface) - _Context }
+ ->
+ { InInterface1 = yes }
+ ;
+ { Item = module_defn(_, implementation) - Context }
+ ->
+ ( { InParentInterface = yes } ->
+ report_error_implementation_in_interface(
+ ModuleName, Context)
+ ;
+ []
+ ),
+ { InInterface1 = no }
+ ;
+ { InInterface1 = InInterface0 }
+ ),
+ %
+ % parse the remaining items for this module,
%
split_into_submodules_3(ModuleName, Items1,
+ InParentInterface, InInterface1,
ThisModuleItems0, Items2, SubModules),
- ThisModuleItems = [Item | ThisModuleItems0],
- OtherItems = Items2
+ %
+ % put the current item back onto the
+ % front of the item list for this module
+ %
+ { ThisModuleItems = [Item | ThisModuleItems0] },
+ { OtherItems = Items2 }
).
-
+
+:- pred add_submodule(pair(module_name, item_list),
+ submodule_map, submodule_map).
+:- mode add_submodule(in, in, out) is det.
+
+add_submodule(ModuleName - ModuleItemList, SubModules0, SubModules) :-
+ %
+ % If the same module name occurs twice, then just append
+ % the lists of items together.
+ % Perhaps we should be a bit more strict about this, for
+ % example by only allowing one `:- implementation' section
+ % and one `:- interface' section for each module?
+ %
+ ( map__search(SubModules0, ModuleName, ItemList0) ->
+ list__append(ModuleItemList, ItemList0, ItemList),
+ map__det_update(SubModules0, ModuleName, ItemList, SubModules)
+ ;
+ map__det_insert(SubModules0, ModuleName, ModuleItemList,
+ SubModules)
+ ).
+
+:- pred report_error_implementation_in_interface(module_name, term__context,
+ io__state, io__state).
+:- mode report_error_implementation_in_interface(in, in, di, uo) is det.
+
+report_error_implementation_in_interface(ModuleName, Context) -->
+ { ModuleName = qualified(ParentModule0, ChildModule0) ->
+ ParentModule = ParentModule0,
+ ChildModule = ChildModule0
+ ;
+ error("report_error_implementation_in_interface")
+ },
+ prog_out__write_context(Context),
+ io__write_string("In interface for module `"),
+ prog_out__write_sym_name(ParentModule),
+ io__write_string("':\n"),
+ prog_out__write_context(Context),
+ io__write_string(" in definition of sub-module `"),
+ io__write_string(ChildModule),
+ io__write_string("':\n"),
+ prog_out__write_context(Context),
+ io__write_string(
+ " error: `:- implementation.' declaration for sub-module\n"),
+ prog_out__write_context(Context),
+ io__write_string(
+ " occurs in interface section of parent module.\n"),
+ 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'. If IncludeImported is yes, also
@@ -3519,5 +3616,11 @@
type_defn(VarSet, abstract_type(Name, Args), Cond)).
make_abstract_type_defn(type_defn(VarSet, abstract_type(Name, Args), Cond),
type_defn(VarSet, abstract_type(Name, Args), Cond)).
+
+ % Given a module (well, a list of items), extract the interface
+ % part of that module, i.e. all the items between `:- interface'
+ % and `:- implementation'. If IncludeImported is yes, also
+ % include all items after a `:- imported'. This is useful for
+ % making the .int file.
%-----------------------------------------------------------------------------%
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.35
diff -u -r1.35 Mmakefile
--- Mmakefile 1998/07/20 10:03:58 1.35
+++ Mmakefile 1998/07/25 19:08:28
@@ -51,6 +51,9 @@
minint_bug \
mode_choice \
name_mangling \
+ nested \
+ nested2 \
+ nested3 \
no_fully_strict \
no_inline \
nullary_ho_func \
@@ -83,7 +86,11 @@
# Not working:
# cycles - loops when compiled in a non-GC grade with --deforestation.
# cycles2 - loops when compiled in a non-GC grade.
-# nested, nested2 - sometimes fail if using parallel makes
+
+# The following is required to make the test cases
+# nested, nested2, and nested3
+# work reliabily with parallel makes -- without this they occaisionally fail.
+RM_C = :
#-----------------------------------------------------------------------------#
Index: tests/hard_coded/nested3.exp
===================================================================
RCS file: nested3.exp
diff -N nested3.exp
--- /dev/null Sun Jul 26 05:45:11 1998
+++ nested3.exp Sun Jul 26 05:10:13 1998
@@ -0,0 +1,14 @@
+nested3:child:hello
+nested3:child:hello
+nested3:child:hello
+nested3:child2:hello
+t1 = nested3:child:foo
+t2 = nested3:child:foo
+t3 = nested3:child:foo
+t4 = nested3:child2:foo
+t5 = nested3:child2:foo
+has_type_t1 = bar
+has_type_t2 = bar
+has_type_t3 = bar
+has_type_t4 = bar
+has_type_t5 = bar
Index: tests/hard_coded/nested3.m
===================================================================
RCS file: nested3.m
diff -N nested3.m
--- /dev/null Sun Jul 26 05:45:11 1998
+++ nested3.m Sun Jul 26 05:06:15 1998
@@ -0,0 +1,100 @@
+% "Hello World" in Mercury, using nested modules.
+
+:- module nested3.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+ :- module nested3:child.
+ :- interface.
+ :- import_module io.
+
+ :- type foo ---> bar ; baz(int).
+
+ :- pred hello(io__state::di, io__state::uo) is det.
+
+ :- end_module nested3:child.
+
+:- implementation.
+
+%-----------------------------------------------------------------------------%
+
+ :- module nested3:child2.
+ :- interface.
+ :- import_module io.
+
+ :- type foo ---> bar ; baz(int).
+
+ :- pred hello(io__state::di, io__state::uo) is det.
+ :- end_module nested3:child2.
+
+%-----------------------------------------------------------------------------%
+
+ :- module nested3:child.
+ :- implementation.
+
+ hello --> io__write_string("nested3:child:hello\n").
+
+ :- end_module nested3:child.
+
+ :- module nested3:child2.
+ :- implementation.
+
+ hello --> io__write_string("nested3:child2:hello\n").
+
+ :- end_module nested3:child2.
+
+%-----------------------------------------------------------------------------%
+
+% now we're back in the parent module.
+
+:- import_module nested3:child.
+:- use_module nested3:child2.
+:- import_module std_util, require.
+
+:- type t1 == nested3:child:foo.
+:- type t2 == child:foo.
+:- type t3 == foo.
+:- type t4 == nested3:child2:foo.
+% :- type t5 == child2:foo. % XXX mixing of use_module and import_module
+ % is not yet supported.
+:- type t5 == nested3:child2:foo.
+
+main -->
+ nested3:child:hello,
+ child:hello,
+ hello,
+ nested3:child2:hello,
+ % child2:hello, % XXX mixing of use_module and import_module
+ % is not yet supported.
+
+ print("t1 = "), print(type_of(has_type_t1)), nl,
+ print("t2 = "), print(type_of(has_type_t2)), nl,
+ print("t3 = "), print(type_of(has_type_t3)), nl,
+ print("t4 = "), print(type_of(has_type_t4)), nl,
+ print("t5 = "), print(type_of(has_type_t5)), nl,
+
+ print("has_type_t1 = "), print(has_type_t1), nl,
+ print("has_type_t2 = "), print(has_type_t2), nl,
+ print("has_type_t3 = "), print(has_type_t3), nl,
+ print("has_type_t4 = "), print(has_type_t4), nl,
+ print("has_type_t5 = "), print(has_type_t5), nl,
+
+ { true }.
+
+:- func has_type_t1 = t1.
+:- func has_type_t2 = t2.
+:- func has_type_t3 = t3.
+:- func has_type_t4 = t4.
+:- func has_type_t5 = t5.
+
+has_type_t1 = nested3:child:bar.
+has_type_t2 = child:bar.
+has_type_t3 = bar.
+has_type_t4 = nested3:child2:bar.
+% has_type_t5 = child2:bar. % XXX mixing of use_module and import_module
+ % is not yet supported.
+has_type_t5 = nested3:child2:bar.
+
+:- end_module nested3.
Index: tests/invalid/nested_impl_in_int.err_exp
===================================================================
RCS file: nested_impl_in_int.err_exp
diff -N nested_impl_in_int.err_exp
--- /dev/null Sun Jul 26 05:45:11 1998
+++ nested_impl_in_int.err_exp Sun Jul 26 05:43:22 1998
@@ -0,0 +1,9 @@
+nested_impl_in_int.m:020: In interface for module `nested_impl_in_int':
+nested_impl_in_int.m:020: in definition of sub-module `child':
+nested_impl_in_int.m:020: error: `:- implementation.' declaration for sub-module
+nested_impl_in_int.m:020: occurs in interface section of parent module.
+nested_impl_in_int.m:037: In interface for module `nested_impl_in_int':
+nested_impl_in_int.m:037: in definition of sub-module `child2':
+nested_impl_in_int.m:037: error: `:- implementation.' declaration for sub-module
+nested_impl_in_int.m:037: occurs in interface section of parent module.
+For more information, try recompiling with `-E'.
Index: tests/invalid/nested_impl_in_int.m
===================================================================
RCS file: nested_impl_in_int.m
diff -N nested_impl_in_int.m
--- /dev/null Sun Jul 26 05:45:11 1998
+++ nested_impl_in_int.m Sun Jul 26 05:25:09 1998
@@ -0,0 +1,97 @@
+% "Hello World" in Mercury, using nested modules.
+
+:- module nested_impl_in_int.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+ :- module nested_impl_in_int:child.
+ :- interface.
+ :- import_module io.
+
+ :- type foo ---> bar ; baz(int).
+
+ :- pred hello(io__state::di, io__state::uo) is det.
+
+ :- end_module nested_impl_in_int:child.
+
+ :- module nested_impl_in_int:child.
+ :- implementation.
+
+ hello --> io__write_string("nested_impl_in_int:child:hello\n").
+
+ :- end_module nested_impl_in_int:child.
+
+
+%-----------------------------------------------------------------------------%
+
+ :- module nested_impl_in_int:child2.
+ :- interface.
+ :- import_module io.
+
+ :- type foo ---> bar ; baz(int).
+
+ :- pred hello(io__state::di, io__state::uo) is det.
+
+ :- implementation.
+
+ hello --> io__write_string("nested_impl_in_int:child2:hello\n").
+
+ :- end_module nested_impl_in_int:child2.
+
+:- implementation.
+
+%-----------------------------------------------------------------------------%
+
+% now we're back in the parent module.
+
+:- import_module nested_impl_in_int:child.
+:- use_module nested_impl_in_int:child2.
+:- import_module std_util, require.
+
+:- type t1 == nested_impl_in_int:child:foo.
+:- type t2 == child:foo.
+:- type t3 == foo.
+:- type t4 == nested_impl_in_int:child2:foo.
+% :- type t5 == child2:foo. % XXX mixing of use_module and import_module
+ % is not yet supported.
+:- type t5 == nested_impl_in_int:child2:foo.
+
+main -->
+ nested_impl_in_int:child:hello,
+ child:hello,
+ hello,
+ nested_impl_in_int:child2:hello,
+ % child2:hello, % XXX mixing of use_module and import_module
+ % is not yet supported.
+
+ print("t1 = "), print(type_of(has_type_t1)), nl,
+ print("t2 = "), print(type_of(has_type_t2)), nl,
+ print("t3 = "), print(type_of(has_type_t3)), nl,
+ print("t4 = "), print(type_of(has_type_t4)), nl,
+ print("t5 = "), print(type_of(has_type_t5)), nl,
+
+ print("has_type_t1 = "), print(has_type_t1), nl,
+ print("has_type_t2 = "), print(has_type_t2), nl,
+ print("has_type_t3 = "), print(has_type_t3), nl,
+ print("has_type_t4 = "), print(has_type_t4), nl,
+ print("has_type_t5 = "), print(has_type_t5), nl,
+
+ { true }.
+
+:- func has_type_t1 = t1.
+:- func has_type_t2 = t2.
+:- func has_type_t3 = t3.
+:- func has_type_t4 = t4.
+:- func has_type_t5 = t5.
+
+has_type_t1 = nested_impl_in_int:child:bar.
+has_type_t2 = child:bar.
+has_type_t3 = bar.
+has_type_t4 = nested_impl_in_int:child2:bar.
+% has_type_t5 = child2:bar. % XXX mixing of use_module and import_module
+ % is not yet supported.
+has_type_t5 = nested_impl_in_int:child2:bar.
+
+:- end_module nested_impl_in_int.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list