diff --git a/compiler/assertion.m b/compiler/assertion.m index 9d17cadd8..888185ddb 100644 --- a/compiler/assertion.m +++ b/compiler/assertion.m @@ -869,6 +869,7 @@ is_defined_in_implementation_section(imported(implementation), yes). is_defined_in_implementation_section(external(implementation), yes). is_defined_in_implementation_section(imported(interface), no). +is_defined_in_implementation_section(imported(ancestor), no). is_defined_in_implementation_section(external(interface), no). is_defined_in_implementation_section(opt_imported, no). is_defined_in_implementation_section(abstract_imported, no). diff --git a/compiler/hlds_module.m b/compiler/hlds_module.m index f42a7b849..b71492c81 100644 --- a/compiler/hlds_module.m +++ b/compiler/hlds_module.m @@ -244,9 +244,8 @@ :- mode module_info_get_indirectly_imported_module_specifiers(in, out) is det. % The visible modules are the current module, any - % imported modules, and any ancestor modules. - % XXX BUG: it should also include modules imported - % from ancestor modules! + % imported modules, any ancestor modules and any + % modules imported by ancestor modules. % It excludes transitively imported modules (those % for which we read `.int2' files). :- pred visible_module(module_name, module_info). diff --git a/compiler/hlds_out.m b/compiler/hlds_out.m index 77f7f36ac..ec9d8a83c 100644 --- a/compiler/hlds_out.m +++ b/compiler/hlds_out.m @@ -2637,6 +2637,8 @@ hlds_out__write_import_status(imported(interface)) --> io__write_string("imported in the interface"). hlds_out__write_import_status(imported(implementation)) --> io__write_string("imported in the implementation"). +hlds_out__write_import_status(imported(ancestor)) --> + io__write_string("imported by an ancestor"). hlds_out__write_import_status(external(interface)) --> io__write_string("external (and exported)"). hlds_out__write_import_status(external(implementation)) --> diff --git a/compiler/hlds_pred.m b/compiler/hlds_pred.m index 9b9b8aae8..cef060ad2 100644 --- a/compiler/hlds_pred.m +++ b/compiler/hlds_pred.m @@ -282,7 +282,7 @@ % It can be through the use of another % language, or it could be through some % other method we haven't thought of yet. - ; imported(section) + ; imported(import_locn) % defined in the interface of some other module ; opt_imported % defined in the optimization % interface of another module diff --git a/compiler/make_hlds.m b/compiler/make_hlds.m index c4bb04690..1ce0a32c6 100644 --- a/compiler/make_hlds.m +++ b/compiler/make_hlds.m @@ -288,7 +288,11 @@ add_item_decl_pass_1(module_defn(_VarSet, ModuleDefn), Context, ; { ModuleDefn = import(module(Specifiers)) } -> { Status = Status0 }, { Status = item_status(IStat, _) }, - ( { status_defined_in_this_module(IStat, yes) } -> + ( + { status_defined_in_this_module(IStat, yes) + ; IStat = imported(ancestor) + } + -> { module_add_imported_module_specifiers(Specifiers, Module0, Module) } ; @@ -298,7 +302,11 @@ add_item_decl_pass_1(module_defn(_VarSet, ModuleDefn), Context, ; { ModuleDefn = use(module(Specifiers)) } -> { Status = Status0 }, { Status = item_status(IStat, _) }, - ( { status_defined_in_this_module(IStat, yes) } -> + ( + { status_defined_in_this_module(IStat, yes) + ; IStat = imported(ancestor) + } + -> { module_add_imported_module_specifiers(Specifiers, Module0, Module) } ; diff --git a/compiler/modules.m b/compiler/modules.m index 9ca2c8501..37d1bca9e 100644 --- a/compiler/modules.m +++ b/compiler/modules.m @@ -435,11 +435,11 @@ :- pred make_pseudo_decl(module_defn, item_and_context). :- mode make_pseudo_decl(in, out) is det. - % append_pseudo_decl(Module0, PseudoDecl, Module): + % append_pseudo_decl(PseudoDecl, Module0, Module): % append the specified module declaration to the list % of items in Module0 to give Module. % -:- pred append_pseudo_decl(module_imports, module_defn, module_imports). +:- pred append_pseudo_decl(module_defn, module_imports, module_imports). :- mode append_pseudo_decl(in, in, out) is det. % Strip off the `:- interface' declaration at the start of @@ -1612,7 +1612,7 @@ touch_datestamp(OutputFileName) --> grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, NestedChildren, ReadModules, MaybeTimestamp, - Items0, Module, Error) --> + Items0, !:Module, Error) --> % % Find out which modules this one depends on % @@ -1646,7 +1646,7 @@ grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, }, { init_module_imports(SourceFileName, SourceFileModuleName, ModuleName, Items0, PublicChildren, NestedChildren, FactDeps, - MaybeTimestamps, Module0) }, + MaybeTimestamps, !:Module) }, % If this module has any seperately-compiled sub-modules, % then we need to make everything in the implementation @@ -1655,8 +1655,7 @@ grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, % them in a special `:- private_interface' section. { get_children(Items0, Children) }, { Children = [] -> - Items1 = Items0, - Module1 = Module0 + Items1 = Items0 ; split_clauses_and_decls(ImplItems, Clauses, ImplDecls), make_pseudo_decl(interface, InterfaceDecl), @@ -1666,14 +1665,9 @@ grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, [[InterfaceDecl | InterfaceItems], [PrivateInterfaceDecl | ImplDecls], [ImplementationDecl | Clauses]], Items1), - module_imports_set_items(Module0, Items1, Module1) + module_imports_set_items(!.Module, Items1, !:Module) }, - % We add a pseudo-declarations `:- imported' at the end - % of the item list. Uses of the items with declarations - % following this do not need module qualifiers. - { append_pseudo_decl(Module1, imported(interface), Module2) }, - % Add `builtin' and `private_builtin' to the % list of imported modules globals__io_get_globals(Globals), @@ -1681,59 +1675,70 @@ grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, IntImportedModules1, IntUsedModules1, IntImportedModules2, IntUsedModules2) }, + % We add a pseudo-declaration `:- imported(ancestor)' at the + % end of the item list. Uses of the items with declarations + % following this do not need module qualifiers. Modules + % imported by ancestors are considered to be visible + % in the current module. + { append_pseudo_decl(imported(ancestor), !Module) }, + % Process the ancestor modules process_module_private_interfaces(ReadModules, AncestorModules, IntImportedModules2, IntImportedModules, - IntUsedModules2, IntUsedModules, - Module2, Module3), + IntUsedModules2, IntUsedModules, !Module), + + % We add a pseudo-declaration `:- imported(interface)' at + % the end of the item list. Uses of the items with declarations + % following this do not need module qualifiers. + { append_pseudo_decl(imported(interface), !Module) }, % Process the modules imported using `import_module'. { IntIndirectImports0 = [] }, process_module_long_interfaces(ReadModules, may_be_unqualified, IntImportedModules, ".int", IntIndirectImports0, - IntIndirectImports1, Module3, Module4), + IntIndirectImports1, !Module), - { append_pseudo_decl(Module4, imported(implementation), Module5) }, + { append_pseudo_decl(imported(implementation), !Module) }, { ImpIndirectImports0 = [] }, process_module_long_interfaces(ReadModules, may_be_unqualified, ImpImportedModules, ".int", ImpIndirectImports0, - ImpIndirectImports1, Module5, Module6), + ImpIndirectImports1, !Module), % Process the modules imported using `use_module' . - { append_pseudo_decl(Module6, used(interface), Module7) }, + { append_pseudo_decl(used(interface), !Module) }, process_module_long_interfaces(ReadModules, must_be_qualified, IntUsedModules, ".int", IntIndirectImports1, - IntIndirectImports, Module7, Module8), - { append_pseudo_decl(Module8, used(implementation), Module9) }, + IntIndirectImports, !Module), + { append_pseudo_decl(used(implementation), !Module) }, process_module_long_interfaces(ReadModules, must_be_qualified, ImpUsedModules, ".int", ImpIndirectImports1, - ImpIndirectImports, Module9, Module10), + ImpIndirectImports, !Module), % Process the short interfaces for indirectly imported modules. % The short interfaces are treated as if % they are imported using `use_module'. - { append_pseudo_decl(Module10, transitively_imported, Module11) }, - { append_pseudo_decl(Module11, used(interface), Module12) }, + { append_pseudo_decl(transitively_imported, !Module) }, + { append_pseudo_decl(used(interface), !Module) }, process_module_short_interfaces_transitively(ReadModules, - IntIndirectImports, ".int2", Module12, Module13), - { append_pseudo_decl(Module13, used(implementation), Module14) }, + IntIndirectImports, ".int2", !Module), + { append_pseudo_decl(used(implementation), !Module) }, process_module_short_interfaces_transitively(ReadModules, - ImpIndirectImports, ".int2", Module14, Module), + ImpIndirectImports, ".int2", !Module), - { module_imports_get_items(Module, Items) }, + { module_imports_get_items(!.Module, Items) }, check_imports_accessibility(ModuleName, IntImportedModules ++ IntUsedModules ++ ImpImportedModules ++ ImpUsedModules, Items), - { module_imports_get_error(Module, Error) }. + { module_imports_get_error(!.Module, Error) }. % grab_unqual_imported_modules: % like grab_imported_modules, but gets the `.int3' files % instead of the `.int' and `.int2' files. grab_unqual_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, - Items0, Module, Error) --> + Items0, !:Module, Error) --> % % Find out which modules this one depends on % @@ -1746,8 +1751,8 @@ grab_unqual_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, % and append a `:- imported' decl to the items. % { init_module_imports(SourceFileName, SourceFileModuleName, ModuleName, - Items0, [], [], [], no, Module0) }, - { append_pseudo_decl(Module0, imported(interface), Module1) }, + Items0, [], [], [], no, !:Module) }, + { append_pseudo_decl(imported(interface), !Module) }, % Add `builtin' and `private_builtin' to the imported modules. globals__io_get_globals(Globals), @@ -1762,50 +1767,52 @@ grab_unqual_imported_modules(SourceFileName, SourceFileModuleName, ModuleName, % first the .int0s for parent modules process_module_private_interfaces(ReadModules, ParentDeps, IntImportDeps1, IntImportDeps, IntUseDeps1, IntUseDeps, - Module1, Module2), + !Module), % then the .int3s for `:- import'-ed modules process_module_long_interfaces(ReadModules, may_be_unqualified, IntImportDeps, ".int3", [], - IntIndirectImportDeps0, Module2, Module3), + IntIndirectImportDeps0, !Module), - { append_pseudo_decl(Module3, imported(implementation), Module4) }, + { append_pseudo_decl(imported(ancestor), !Module) }, process_module_private_interfaces(ReadModules, ParentDeps, ImpImportDeps0, ImpImportDeps, ImpUseDeps0, ImpUseDeps, - Module4, Module5), + !Module), + + { append_pseudo_decl(imported(implementation), !Module) }, process_module_long_interfaces(ReadModules, may_be_unqualified, ImpImportDeps, ".int3", [], ImpIndirectImportDeps0, - Module5, Module6), + !Module), % then (after appropriate `:- used' decls) % the .int3s for `:- use'-ed modules - { append_pseudo_decl(Module6, used(interface), Module7) }, + { append_pseudo_decl(used(interface), !Module) }, process_module_long_interfaces(ReadModules, must_be_qualified, IntUseDeps, ".int3", IntIndirectImportDeps0, - IntIndirectImportDeps, Module7, Module8), - { append_pseudo_decl(Module8, used(implementation), Module9) }, + IntIndirectImportDeps, !Module), + { append_pseudo_decl(used(implementation), !Module) }, process_module_long_interfaces(ReadModules, must_be_qualified, ImpUseDeps, ".int3", ImpIndirectImportDeps0, - ImpIndirectImportDeps, Module9, Module10), + ImpIndirectImportDeps, !Module), % then (after appropriate `:- used' decl) % the .int3s for indirectly imported modules - { append_pseudo_decl(Module10, used(interface), Module11) }, + { append_pseudo_decl(used(interface), !Module) }, process_module_short_interfaces_transitively(ReadModules, - IntIndirectImportDeps, ".int3", Module11, Module12), + IntIndirectImportDeps, ".int3", !Module), - { append_pseudo_decl(Module12, used(implementation), Module13) }, + { append_pseudo_decl(used(implementation), !Module) }, process_module_short_interfaces_transitively(ReadModules, - ImpIndirectImportDeps, ".int3", Module13, Module), + ImpIndirectImportDeps, ".int3", !Module), - { module_imports_get_items(Module, Items) }, + { module_imports_get_items(!.Module, Items) }, check_imports_accessibility(ModuleName, IntImportDeps ++ IntUseDeps ++ ImpImportDeps ++ ImpUseDeps, Items), - { module_imports_get_error(Module, Error) }. + { module_imports_get_error(!.Module, Error) }. %-----------------------------------------------------------------------------% @@ -1847,7 +1854,7 @@ module_imports_set_impl_deps(Module, ImplDeps, module_imports_set_indirect_deps(Module, IndirectDeps, Module ^ indirect_deps := IndirectDeps). -append_pseudo_decl(Module0, PseudoDecl, Module) :- +append_pseudo_decl(PseudoDecl, Module0, Module) :- Items0 = Module0 ^ items, make_pseudo_decl(PseudoDecl, Item), list__append(Items0, [Item], Items), diff --git a/compiler/prog_data.m b/compiler/prog_data.m index e7673140f..1169c059f 100644 --- a/compiler/prog_data.m +++ b/compiler/prog_data.m @@ -966,13 +966,13 @@ % such items need to be exported to the % sub-modules. - ; imported(section) + ; imported(import_locn) % This is used internally by the compiler, % to identify declarations which originally % came from some other module imported with % a `:- import_module' declaration, and which % section the module was imported. - ; used(section) + ; used(import_locn) % This is used internally by the compiler, % to identify declarations which originally % came from some other module and for which @@ -1014,6 +1014,11 @@ ---> implementation ; interface. +:- type import_locn + ---> implementation + ; interface + ; ancestor. + :- type sym_list ---> sym(list(sym_specifier)) ; pred(list(pred_specifier)) diff --git a/compiler/trans_opt.m b/compiler/trans_opt.m index 02682af26..6666b36ff 100644 --- a/compiler/trans_opt.m +++ b/compiler/trans_opt.m @@ -136,7 +136,7 @@ trans_opt__grab_optfiles(Module0, TransOptDeps, Module, FoundError) --> read_trans_opt_files(TransOptDeps, [], OptItems, no, FoundError), - { append_pseudo_decl(Module0, opt_imported, Module1) }, + { append_pseudo_decl(opt_imported, Module0, Module1) }, { module_imports_get_items(Module1, Items0) }, { list__append(Items0, OptItems, Items) }, { module_imports_set_items(Module1, Items, Module2) }, diff --git a/configure.in b/configure.in index 3f018f819..92fa2242f 100644 --- a/configure.in +++ b/configure.in @@ -104,12 +104,12 @@ if test "$BOOTSTRAP_MC" != ""; then :- import_module int. - main --> - { return_rtti_version(Version) }, - ( { Version >= 6 } -> - print("Hello, world\n") + main(!IO) :- + return_rtti_version(Version), + ( Version >= 6 -> + print("Hello, world\n", !IO) ; - print("Nope.\n") + print("Nope.\n", !IO) ). :- pred return_rtti_version(int::out) is det. diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile index c26c543bc..9b392358e 100644 --- a/tests/invalid/Mmakefile +++ b/tests/invalid/Mmakefile @@ -17,6 +17,7 @@ MULTIMODULE_PROGS= \ aditi_update_mode_errors \ duplicate_instance_2 \ ho_default_func_2.sub \ + import_in_parent \ imported_mode \ missing_parent_import \ partial_implied_mode \ diff --git a/tests/invalid/import_in_parent.err_exp b/tests/invalid/import_in_parent.err_exp new file mode 100644 index 000000000..dfa04930d --- /dev/null +++ b/tests/invalid/import_in_parent.err_exp @@ -0,0 +1,3 @@ +import_in_parent.m:019: In clause for predicate `import_in_parent:sub:foo/1': +import_in_parent.m:019: error: undefined predicate `bool:foo/1'. +For more information, try recompiling with `-E'. diff --git a/tests/invalid/import_in_parent.m b/tests/invalid/import_in_parent.m new file mode 100644 index 000000000..95011e820 --- /dev/null +++ b/tests/invalid/import_in_parent.m @@ -0,0 +1,23 @@ +:- module import_in_parent. + +:- interface. + +:- import_module bool. + +:- type foo. + +:- implementation. + + :- module import_in_parent__sub. + + :- interface. + + :- pred foo(bool::in) is semidet. + + :- implementation. + + foo(X) :- bool__foo(X). + + :- end_module import_in_parent__sub. + +:- end_module import_in_parent.