Files
mercury/compiler/modules.m
David Overton 89ffc9a93a Changes to automatic dependency generation to allow parallel make to
Estimated hours taken: 0.5

Changes to automatic dependency generation to allow parallel make to
work with modules containing `pragma fact_table's and to add fact
table C files to the list of files deleted by `mmake clean' and
`mmake realclean'.

compiler/modules.m:
        In `.dep' files: add the C file produced by
                `:- pragma fact_table' to the list of <main_module>.cs so it
                is deleted by `mmake clean' and `mmake realclean'.
        in `.d' files: add a dependency to stop the fact table C file
                from being compiled before it is created by
                `mercury_compile'.  This allows parallel make (i.e.  `-j<n>')
                to work properly.
1997-02-16 23:48:59 +00:00

1463 lines
50 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1995 University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
% file: modules.m
% main author: fjh
% This module contains all the code for handling module imports and exports,
% for computing module dependencies, and for generate makefile fragments to
% record those dependencies.
%
%
% The interface system works as follows:
%
% 1. a .int3 file is written, which contains all the types, insts
% and modes defined in the interface. Equivalence types, insts and
% modes are written in full, others are written in abstract form.
% These are module qualified as far as possible given the information
% present in the current module. The datestamp on the .date3 file
% gives the last time the .int3 file was checked for consistency.
%
% 2. The .int and .int2 files are created, using the .int3 files
% of imported modules to fully module qualify all items. Therefore
% the .int2 file is just a fully qualified version of the .int3 file.
% The .int3 file must be kept for datestamping purposes. The datestamp
% on the .date file gives the last time the .int and .int2 files
% were checked.
%
%-----------------------------------------------------------------------------%
:- module modules.
:- interface.
:- import_module prog_data, prog_io.
:- import_module list, io.
% read_mod(ModuleName, Extension, Descr, Search, Items, Error):
% Given a module name and a file extension (e.g. `.m',
% `.int', or `int2'), read in the list of items in that file.
% If Search is yes, search all directories given by the option
% search_directories for the module.
%
:- pred read_mod(string, string, string, bool, item_list, module_error,
io__state, io__state).
:- mode read_mod(in, in, in, in, out, out, di, uo) is det.
% Same as above, but doesn't return error messages.
:- pred read_mod_ignore_errors(string, string, string, bool, item_list,
module_error, io__state, io__state).
:- mode read_mod_ignore_errors(in, in, in, in, out, out, di, uo) is det.
% make_interface(ModuleName, Items):
% Given a module name and the list of items in that module,
% output the long (`.int') and short (`.int2') interface files
% for the module.
%
:- pred make_interface(string, item_list, io__state, io__state).
:- mode make_interface(in, in, di, uo) is det.
% Output the unqualified short interface file to <module>.int3.
%
:- pred make_short_interface(string, item_list, io__state, io__state).
:- mode make_short_interface(in, in, di, uo) is det.
% grab_imported_modules(ModuleName, Items, Module, FactDeps, Error)
% Given a module name and the list of items in that module,
% read in the full interface files for all the imported modules,
% and the short interface files for all the indirectly imported
% modules, and return a `module_imports' structure containing the
% relevant information.
% Also returns FactDeps list of filenames for fact tables in this
% module.
%
:- type module_imports --->
module_imports(
string, % The primary module name
list(string), % The list of modules it directly imports
list(string), % The list of modules it indirectly imports
item_list, % The contents of the module and its imports
module_error % Whether an error has been encountered
).
:- pred grab_imported_modules(string, item_list, module_imports, list(string),
module_error, io__state, io__state).
:- mode grab_imported_modules(in, in, out, out, out, di, uo) is det.
% write_dependency_file(ModuleName, LongDeps, ShortDeps, FactDeps):
% Write out the per-module makefile dependencies (`.d') file
% for a module `ModuleName' which depends directly on the
% modules `LongDeps' and indirectly on the modules `ShortDeps'.
% FactDeps is the list of filenames of fact tables in the module.
%
:- pred write_dependency_file(string, list(string), list(string), list(string),
io__state, io__state).
:- mode write_dependency_file(in, in, in, in, di, uo) is det.
% generate_dependencies(ModuleName):
% Generate the per-program makefile dependencies (`.dep') file
% for a program whose top-level module is `ModuleName'.
% This involes first transitively reading in all imported
% modules. While we're at it, we also save the per-module
% makefile dependency (`.d') files for all those modules.
%
:- pred generate_dependencies(string, io__state, io__state).
:- mode generate_dependencies(in, di, uo) is det.
% Given a module (well, a list of items),
% determine all the modules that it depends upon
% (both interface dependencies and also implementation dependencies).
:- pred get_dependencies(item_list, list(string)).
:- mode get_dependencies(in, out) is det.
% Do the importing of the interface files of imported modules.
:- pred process_module_interfaces(list(string), list(string),
module_imports, module_imports,
io__state, io__state).
:- mode process_module_interfaces(in, in, in, out, di, uo) is det.
% touch_interface_datestamp(ModuleName, Ext).
%
% Touch the datestamp file `ModuleName.Ext'. Datestamp files
% are used to record when each of the interface files was last
% updated.
:- pred touch_interface_datestamp(string, string, io__state, io__state).
:- mode touch_interface_datestamp(in, in, di, uo) is det.
% update_interface(FileName)
%
% Call the shell script mercury_update_interface to update the
% interface file FileName if it has changed.
:- pred update_interface(string, io__state, io__state).
:- mode update_interface(in, di, uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module passes_aux, prog_out, mercury_to_mercury.
:- import_module prog_io_util, globals, options, intermod, module_qual.
:- import_module bool, string, set, map, term, varset, dir, std_util, library.
% Read in the .int3 files that the current module depends on,
% and use these to qualify all items in the interface as much as
% possible. Then write out the .int and .int2 files.
make_interface(ModuleName, Items0) -->
% Get interface, including imports.
{ get_interface(Items0, yes, InterfaceItems0) },
{ term__context_init(Context) },
{ varset__init(Varset) },
{ get_dependencies(InterfaceItems0, InterfaceDeps) },
{ list__append(InterfaceItems0,
[module_defn(Varset, imported) - Context],
InterfaceItems0a) },
{ Module0 = module_imports(ModuleName, [], [], InterfaceItems0a, no) },
% Get the .int3s that the current .int depends on.
process_module_short_interfaces(["mercury_builtin" | InterfaceDeps],
".int3", Module0, Module),
{ Module = module_imports(_, _, _, InterfaceItems1, Error) },
( { Error = yes } ->
io__write_strings(["Error reading short interface files.\n",
ModuleName, ".int and ",
ModuleName, ".int2 not written.\n"])
;
% Qualify all items.
module_qual__module_qualify_items(InterfaceItems1,
InterfaceItems2, ModuleName, yes, _, _, _),
io__get_exit_status(Status),
( { Status \= 0 } ->
io__write_strings([ModuleName, ".int not written.\n"])
;
{ strip_imported_items(InterfaceItems2, [],
InterfaceItems3) },
check_for_clauses_in_interface(InterfaceItems3,
InterfaceItems),
check_for_no_exports(InterfaceItems, ModuleName),
write_interface_file(ModuleName, ".int",
InterfaceItems),
{ get_short_interface(InterfaceItems,
ShortInterfaceItems) },
write_interface_file(ModuleName, ".int2",
ShortInterfaceItems),
touch_interface_datestamp(ModuleName, ".date")
)
).
% This qualifies everything as much as it can given the
% information in the current module and writes out the .int3 file.
make_short_interface(ModuleName, Items0) -->
{ get_interface(Items0, no, InterfaceItems0) },
check_for_clauses_in_interface(InterfaceItems0, InterfaceItems),
{ get_short_interface(InterfaceItems, ShortInterfaceItems0) },
module_qual__module_qualify_items(ShortInterfaceItems0,
ShortInterfaceItems, ModuleName, no, _, _, _),
write_interface_file(ModuleName, ".int3", ShortInterfaceItems),
touch_interface_datestamp(ModuleName, ".date3").
:- pred strip_imported_items(item_list::in, item_list::in,
item_list::out) is det.
strip_imported_items([], Items0, Items) :-
list__reverse(Items0, Items).
strip_imported_items([Item - Context | Rest], Items0, Items) :-
(
Item = module_defn(_, imported)
->
list__reverse(Items0, Items)
;
strip_imported_items(Rest, [Item - Context | Items0], Items)
).
%-----------------------------------------------------------------------------%
:- pred check_for_clauses_in_interface(item_list, item_list,
io__state, io__state).
:- mode check_for_clauses_in_interface(in, out, di, uo) is det.
check_for_clauses_in_interface([], []) --> [].
check_for_clauses_in_interface([ItemAndContext0 | Items0], Items) -->
{ ItemAndContext0 = Item0 - Context },
(
( { Item0 = pred_clause(_,_,_,_) }
; { Item0 = func_clause(_,_,_,_,_) }
)
->
prog_out__write_context(Context),
report_warning("Warning: clause in module interface.\n"),
check_for_clauses_in_interface(Items0, Items)
;
% `pragma obsolete' declarations are supposed to go
% in the interface, but all other pragma declarations
% should go in the implementation.
{ Item0 = pragma(Pragma) },
{ Pragma \= obsolete(_, _) }
->
prog_out__write_context(Context),
report_warning("Warning: pragma in module interface.\n"),
check_for_clauses_in_interface(Items0, Items)
;
{ Items = [ItemAndContext0 | Items1] },
check_for_clauses_in_interface(Items0, Items1)
).
:- pred check_for_no_exports(item_list, string, io__state, io__state).
:- mode check_for_no_exports(in, in, di, uo) is det.
check_for_no_exports([], ModuleName) -->
warn_no_exports(ModuleName).
check_for_no_exports([Item - _Context | Items], ModuleName) -->
(
{ Item = nothing
; Item = module_defn(_,_)
}
->
% nothing useful - keep searching
check_for_no_exports(Items, ModuleName)
;
% we found something useful - don't issue the warning
[]
).
:- pred warn_no_exports(string, io__state, io__state).
:- mode warn_no_exports(in, di, uo) is det.
warn_no_exports(ModuleName) -->
globals__io_lookup_bool_option(warn_nothing_exported, ExportWarning),
(
{ ExportWarning = yes }
->
report_warning(ModuleName, 1,
"interface does not export anything."),
globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
(
{ VerboseErrors = yes }
->
io__stderr_stream(StdErr),
io__write_strings(StdErr, [ "\t\t",
"To be useful, a module should export something.\n\t\t",
"A file should contain at least one declaration other than\n\t\t",
"`:- import_module' in its interface section(s).\n\t\t",
"This would normally be a `:- pred', `:- func', `:- type',\n\t\t",
"`:- inst' or `:- mode' declaration.\n"
])
;
[]
)
;
[]
).
%-----------------------------------------------------------------------------%
:- pred write_interface_file(string, string, item_list, io__state, io__state).
:- mode write_interface_file(in, in, in, di, uo) is det.
write_interface_file(ModuleName, Suffix, InterfaceItems) -->
% create <Module>.int.tmp
{ string__append(ModuleName, Suffix, OutputFileName) },
{ string__append(OutputFileName, ".tmp", TmpOutputFileName) },
{ dir__basename(ModuleName, BaseModuleName) },
% we need to add a `:- interface' declaration at the start
% of the item list
{ varset__init(VarSet) },
{ term__context_init(ModuleName, 0, Context) },
{ InterfaceDeclaration = module_defn(VarSet, interface) - Context },
{ InterfaceItems1 = [InterfaceDeclaration | InterfaceItems] },
convert_to_mercury(BaseModuleName, TmpOutputFileName, InterfaceItems1),
update_interface(OutputFileName).
% invoke the shell script `mercury_update_interface'
% to update <Module>.int from <Module>.int.tmp if
% necessary
update_interface(OutputFileName) -->
globals__io_lookup_bool_option(verbose, Verbose),
maybe_write_string(Verbose, "% Updating interface:\n"),
( { Verbose = yes } ->
{ Command = "mercury_update_interface -v " }
;
{ Command = "mercury_update_interface " }
),
{ string__append(Command, OutputFileName, ShellCommand) },
invoke_system_command(ShellCommand, Succeeded),
( { Succeeded = no } ->
report_error("problem updating interface files.")
;
[]
).
%-----------------------------------------------------------------------------%
touch_interface_datestamp(ModuleName, Ext) -->
{ string__append(ModuleName, Ext, OutputFileName) },
globals__io_lookup_bool_option(verbose, Verbose),
maybe_write_string(Verbose, "% Touching `"),
maybe_write_string(Verbose, OutputFileName),
maybe_write_string(Verbose, "'... "),
maybe_flush_output(Verbose),
io__open_output(OutputFileName, Result),
( { Result = ok(OutputStream) } ->
io__write_string(OutputStream, "\n"),
io__close_output(OutputStream),
maybe_write_string(Verbose, " done.\n")
;
io__write_string("\nError opening `"),
io__write_string(OutputFileName),
io__write_string("' for output\n")
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
grab_imported_modules(ModuleName, Items0, Module, FactDeps, Error) -->
{ get_dependencies(Items0, ImportedModules) },
{ get_fact_table_dependencies(Items0, FactDeps) },
% we add a pseudo-declaration `:- imported' at the end
% of the item list, so that make_hlds knows which items
% are imported and which are defined in the main module
{ varset__init(VarSet) },
{ term__context_init(ModuleName, 0, Context) },
{ list__append(Items0,
[module_defn(VarSet, imported) - Context], Items1) },
{ dir__basename(ModuleName, BaseModuleName) },
{ Module0 = module_imports(BaseModuleName, [], [], Items1, no) },
process_module_interfaces(["mercury_builtin" | ImportedModules],
[], Module0, Module),
{ Module = module_imports(_, _, _, _, Error) }.
%-----------------------------------------------------------------------------%
write_dependency_file(ModuleName, LongDeps0, ShortDeps0, FactDeps0) -->
globals__io_lookup_bool_option(verbose, Verbose),
{ string__append(ModuleName, ".d", DependencyFileName) },
maybe_write_string(Verbose, "% Writing auto-dependency file `"),
maybe_write_string(Verbose, DependencyFileName),
maybe_write_string(Verbose, "'..."),
maybe_flush_output(Verbose),
io__open_output(DependencyFileName, Result),
( { Result = ok(DepStream) } ->
{ list__sort_and_remove_dups(LongDeps0, LongDeps1) },
{ list__delete_all(LongDeps1, ModuleName, LongDeps) },
{ list__sort_and_remove_dups(ShortDeps0, ShortDeps1) },
{ list__delete_elems(ShortDeps1, LongDeps, ShortDeps2) },
{ list__delete_all(ShortDeps2, ModuleName, ShortDeps) },
{ list__sort_and_remove_dups(FactDeps0, FactDeps) },
io__write_strings(DepStream, [
ModuleName, ".optdate ",
ModuleName, ".c ",
ModuleName, ".err ",
ModuleName, ".o : ",
ModuleName, ".m"
] ),
write_dependencies_list(LongDeps, ".int", DepStream),
write_dependencies_list(ShortDeps, ".int2", DepStream),
write_dependencies_list(FactDeps, "", DepStream),
globals__io_lookup_bool_option(intermodule_optimization,
Intermod),
( { Intermod = yes } ->
io__write_strings(DepStream, [
"\n\n", ModuleName, ".c ",
ModuleName, ".err ", ModuleName, ".o :"
]),
% The .c file only depends on the .opt files from
% the current directory, so that inter-module
% optimization works when the .opt files for the
% library are unavailable. This is only necessary
% because make doesn't allow conditional dependencies.
% The dependency on the current module's .opt file
% is to make sure the module gets type-checked without
% having the definitions of abstract types from other
% modules.
globals__io_lookup_accumulating_option(
intermod_directories, IntermodDirs),
get_opt_deps(LongDeps, IntermodDirs, [], OptDeps),
write_dependencies_list([ModuleName | OptDeps],
".opt", DepStream)
;
[]
),
io__write_strings(DepStream, [
"\n\n", ModuleName, ".date : ",
ModuleName, ".m"
]),
write_dependencies_list(LongDeps, ".int3", DepStream),
write_dependencies_list(ShortDeps, ".int3", DepStream),
io__write_strings(DepStream, [
"\n\n",
ModuleName, ".dir/", ModuleName, "_000.o: ",
ModuleName, ".m\n",
"\trm -rf ", ModuleName, ".dir\n",
"\t$(MCS) -s$(GRADE) $(MCSFLAGS) ", ModuleName, ".m\n"
]),
( { FactDeps = [_|_] } ->
{ Lambda = lambda([S0::in, S::out] is det,
string__append(S0, ".c ", S)) },
{ list__map(Lambda, FactDeps, Fact_C_Files) },
io__nl,
io__write_strings(DepStream, Fact_C_Files),
io__write_strings(DepStream, [": ",ModuleName,".o\n"])
;
[]
),
io__close_output(DepStream),
maybe_write_string(Verbose, " done.\n")
;
{ string__append_list(["can't open file `", DependencyFileName,
"' for output."], Message) },
report_error(Message)
).
% For each dependency, search intermod_directories for a .opt
% file or a .m file, filtering out those for which the search fails.
:- pred get_opt_deps(list(string)::in, list(string)::in, list(string)::in,
list(string)::out, io__state::di, io__state::uo) is det.
get_opt_deps([], _, OptDeps, OptDeps) --> [].
get_opt_deps([Dep | Deps], IntermodDirs, OptDeps0, OptDeps) -->
{ string__append(Dep, ".m", DepName) },
search_for_file(IntermodDirs, DepName, Result1),
( { Result1 = yes } ->
{ OptDeps1 = [Dep | OptDeps0] },
io__seen
;
{ string__append(Dep, ".opt", OptName) },
search_for_file(IntermodDirs, OptName, Result2),
( { Result2 = yes } ->
{ OptDeps1 = [Dep | OptDeps0] },
io__seen
;
{ OptDeps1 = OptDeps0 }
)
),
get_opt_deps(Deps, IntermodDirs, OptDeps1, OptDeps).
%-----------------------------------------------------------------------------%
generate_dependencies(Module) -->
%
% first, build up a map of the dependencies (writing `.d' files as
% we go)
%
{ map__init(DepsMap0) },
generate_deps_map([Module], DepsMap0, DepsMap),
%
% check whether we couldn't read the main `.m' file
%
{ map__lookup(DepsMap, Module, deps(_, Error, _, _, _)) },
( { Error = fatal } ->
{ string__append_list(["fatal error reading module `",
Module, "'."], Message) },
report_error(Message)
;
%
% now, write the `.dep' file
%
{ string__append(Module, ".dep", DepFileName) },
globals__io_lookup_bool_option(verbose, Verbose),
maybe_write_string(Verbose, "% Creating auto-dependency file `"),
maybe_write_string(Verbose, DepFileName),
maybe_write_string(Verbose, "'...\n"),
io__open_output(DepFileName, Result),
( { Result = ok(DepStream) } ->
generate_dep_file(Module, DepsMap, DepStream),
io__close_output(DepStream),
maybe_write_string(Verbose, "% done\n")
;
{ string__append_list(["can't open file `", DepFileName,
"' for output."], Message) },
report_error(Message)
)
).
% This is the data structure we use to record the dependencies.
% We keep a map from module name to information about the module.
:- type deps_map == map(string, deps).
:- type deps
---> deps(
bool, % have we processed this module yet?
module_error, % if we did, where there any errors?
list(string), % interface dependencies
list(string), % implementation dependencies
list(string) % fact table dependencies
).
% This is the predicate which creates the above data structure.
:- pred generate_deps_map(list(string), deps_map, deps_map,
io__state, io__state).
:- mode generate_deps_map(in, in, out, di, uo) is det.
generate_deps_map([], DepsMap, DepsMap) --> [].
generate_deps_map([Module | Modules], DepsMap0, DepsMap) -->
% Look up the module's dependencies, and determine whether
% it has been processed yet.
lookup_dependencies(Module, DepsMap0, no, Done, Error, IntDeps,
ImplDeps, FactDeps, DepsMap1),
% If the module hadn't been processed yet, compute its
% transitive dependencies (we already know its primary ones),
% (1) output this module's dependencies to its `.d' file
% (if the `.m' file exists), (2) add its imports to the list of
% dependencies we need to generate, and (3) mark it as having
% been processed.
( { Done = no } ->
{ map__set(DepsMap1, Module,
deps(yes, Error, IntDeps, ImplDeps, FactDeps),
DepsMap2) },
transitive_dependencies(ImplDeps, DepsMap2, no, SecondaryDeps,
DepsMap3),
( { Error \= fatal } ->
write_dependency_file(Module, ImplDeps, SecondaryDeps,
FactDeps)
;
[]
),
{ list__append(ImplDeps, Modules, Modules2) }
;
{ DepsMap3 = DepsMap1 },
{ Modules2 = Modules }
),
% Recursively process the remaining modules
generate_deps_map(Modules2, DepsMap3, DepsMap).
% Write out the `.dep' file, using the information collected in the
% deps_map data structure.
:- pred generate_dep_file(string, deps_map, io__output_stream,
io__state, io__state).
:- mode generate_dep_file(in, in, in, di, uo) is det.
generate_dep_file(ModuleName, DepsMap, DepStream) -->
io__write_string(DepStream,
"# Automatically generated dependencies for module `"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, "'.\n"),
{ library__version(Version) },
io__write_string(DepStream,
"# Generated by the Mercury compiler, version "),
io__write_string(DepStream, Version),
io__write_string(DepStream, ".\n\n"),
{ map__keys(DepsMap, Modules0) },
{ select_ok_modules(Modules0, DepsMap, Modules) },
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".ms ="),
write_dependencies_list(Modules, ".m", DepStream),
io__write_string(DepStream, "\n\n"),
globals__io_lookup_bool_option(assume_gmake, Gmake),
(
{ Gmake = yes },
{ string__append(ModuleName, ".ms", VarName) },
{ Basis = yes(VarName - ".m") }
;
{ Gmake = no },
{ Basis = no }
),
{ get_extra_link_objects(Modules, DepsMap, ExtraLinkObjs) },
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".nos = "),
write_compact_dependencies_list(Modules, ".no", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".qls = "),
write_compact_dependencies_list(Modules, ".ql", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".cs = "),
write_compact_dependencies_list(Modules, ".c", Basis, DepStream),
write_dependencies_list(ExtraLinkObjs, ".c", DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".os = "),
write_compact_dependencies_list(Modules, ".o", Basis, DepStream),
write_dependencies_list(ExtraLinkObjs, ".o", DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".pic_os = "),
write_compact_dependencies_list(Modules, ".$(EXT_FOR_PIC_OBJECTS)",
Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".dirs = "),
write_compact_dependencies_list(Modules, ".dir", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".dir_os = "),
write_compact_dependencies_list(Modules, ".dir/*.o", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".ss = "),
write_compact_dependencies_list(Modules, ".s", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".errs = "),
write_compact_dependencies_list(Modules, ".err", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".dates = "),
write_compact_dependencies_list(Modules, ".date", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".date3s = "),
write_compact_dependencies_list(Modules, ".date3", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".optdates = "),
write_compact_dependencies_list(Modules, ".optdate", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".ds = "),
write_compact_dependencies_list(Modules, ".d", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".hs = "),
write_compact_dependencies_list(Modules, ".h", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".ints = "),
write_compact_dependencies_list(Modules, ".int", Basis, DepStream),
write_compact_dependencies_separator(Basis, DepStream),
write_compact_dependencies_list(Modules, ".int2", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".int3s = "),
write_compact_dependencies_list(Modules, ".int3", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".opts = "),
write_compact_dependencies_list(Modules, ".opt", Basis, DepStream),
io__write_string(DepStream, "\n\n"),
globals__io_lookup_string_option(gc, GC_Opt),
( { GC_Opt = "accurate" } ->
{ map__init(AllMap) },
trans_impl_dependencies([ModuleName], AllMap, yes,
AllDeps, _),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".garbs = "),
write_compact_dependencies_list(AllDeps, ".garb",
Basis, DepStream),
io__write_string(DepStream, "\n\n")
;
[]
),
( { GC_Opt = "accurate" } ->
io__write_strings(DepStream, [
ModuleName, "_garb.c : $(",
ModuleName, ".garbs)\n",
"\t$(MLINK) $(MLINKFLAGS) -o ", ModuleName,
"_garb.c $(", ModuleName, ".garbs)\n\n"
])
;
[]
),
( { GC_Opt = "accurate" } ->
io__write_strings(DepStream, [
ModuleName, " : $(", ModuleName, ".os) ",
ModuleName, "_init.o ",
ModuleName, "_garb.o\n",
"\t$(ML) -s $(GRADE) $(MLFLAGS) -o ", ModuleName, " ",
ModuleName, "_garb.o ",
ModuleName, "_init.o \\\n",
"\t$(", ModuleName, ".os) $(MLLIBS)\n\n"
])
;
io__write_strings(DepStream, [
ModuleName, " : $(", ModuleName, ".os) ",
ModuleName, "_init.o\n",
"\t$(ML) -s $(GRADE) $(MLFLAGS) -o ", ModuleName, " ",
ModuleName, "_init.o \\\n",
"\t$(", ModuleName, ".os) $(MLLIBS)\n\n"
])
),
io__write_strings(DepStream, [
ModuleName, ".split : ", ModuleName, ".split.a ",
ModuleName, "_init.o\n",
"\t$(ML) -s $(GRADE) $(MLFLAGS) -o ", ModuleName, ".split ",
ModuleName, "_init.o \\\n",
"\t", ModuleName, ".split.a $(MLLIBS)\n\n"
]),
io__write_strings(DepStream, [
ModuleName, ".split.a : $(", ModuleName, ".dir_os)\n",
"\trm -f ", ModuleName, ".split.a\n",
"\tar cr ", ModuleName, ".split.a\n",
"\tfor dir in $(", ModuleName, ".dirs); do \\\n",
"\t ar q ", ModuleName, ".split.a $$dir/*.o; \\\n",
"\tdone\n",
"\tranlib ", ModuleName, ".split.a\n\n"
]),
/************
% I decided to leave the rules for `foo.so' and `foo.a' out,
% mainly because the rule for `foo.so' is hard to make portable.
% The rules here would conflict with the one in library/Mmake.
io__write_strings(DepStream, [
ModuleName, ".so : $(", ModuleName, ".pic_os)\n",
"\t$(LINK_SHARED_LIB) -o ", ModuleName, ".so ",
"$(", ModuleName, ".pic_os)\n\n"
]),
io__write_strings(DepStream, [
ModuleName, ".a : $(", ModuleName, ".os)\n",
"\trm -f ", ModuleName, ".a\n",
"\tar cr ", ModuleName, ".a ",
"$(", ModuleName, ".os)\n",
"\tranlib ", ModuleName, ".a\n\n"
]),
************/
io__write_strings(DepStream, [
ModuleName, "_init.c :\n",
"\t$(C2INIT) $(C2INITFLAGS) $(", ModuleName, ".ms) > ",
ModuleName, "_init.c\n\n"
]),
io__write_strings(DepStream, [
ModuleName, ".nu : $(", ModuleName, ".nos)\n",
"\t$(MNL) $(MNLFLAGS) -o ", ModuleName, ".nu ",
"$(", ModuleName, ".nos)\n\n",
ModuleName, ".nu.debug : $(", ModuleName, ".nos)\n",
"\t$(MNL) --debug $(MNLFLAGS) -o ", ModuleName, ".nu.debug ",
"$(", ModuleName, ".nos)\n\n"
]),
io__write_strings(DepStream, [
ModuleName, ".sicstus : $(", ModuleName, ".qls)\n",
"\t$(MSL) $(MSLFLAGS) -o ", ModuleName, ".sicstus ",
"$(", ModuleName, ".qls)\n\n",
ModuleName, ".sicstus.debug : $(", ModuleName, ".qls)\n",
"\t$(MSL) --debug $(MSLFLAGS) -o ", ModuleName,
".sicstus.debug $(", ModuleName, ".qls)\n\n"
]),
io__write_strings(DepStream, [
ModuleName, ".check : $(", ModuleName, ".errs)\n\n",
ModuleName, ".ints : $(", ModuleName, ".dates)\n\n",
ModuleName, ".int3s : $(", ModuleName, ".date3s)\n\n",
ModuleName, ".opts : $(", ModuleName, ".optdates)\n\n"
]),
io__write_strings(DepStream, [
"clean: ", ModuleName, ".clean\n"
]),
io__write_strings(DepStream, [
ModuleName, ".clean :\n",
"\t-rm -rf ", ModuleName, ".dir\n",
"\t-rm -f $(", ModuleName, ".cs) ", ModuleName, "_init.c\n",
"\t-rm -f $(", ModuleName, ".ss) ", ModuleName, "_init.s\n",
"\t-rm -f $(", ModuleName, ".os) ", ModuleName, "_init.o\n",
"\t-rm -f $(", ModuleName, ".nos)\n",
"\t-rm -f $(", ModuleName, ".qls)\n",
"\t-rm -f $(", ModuleName, ".errs)\n"
]),
( { GC_Opt = "accurate" } ->
io__write_strings(DepStream, [
"\t-rm -f $(", ModuleName, ".garbs)\n",
"\t-rm -f ", ModuleName, "_garb.o ", ModuleName,
"_garb.c ", ModuleName, "_garb.s\n\n"
])
;
io__write_string(DepStream, "\n")
),
io__write_strings(DepStream, [
ModuleName, ".change_clean :\n",
"\t-rm -f $(", ModuleName, ".cs) ", ModuleName, "_init.c\n",
"\t-rm -f $(", ModuleName, ".ss) ", ModuleName, "_init.s\n",
"\t-rm -f $(", ModuleName, ".os) ", ModuleName, "_init.o\n",
"\t-rm -f $(", ModuleName, ".hs)\n",
"\t-rm -f $(", ModuleName, ".ds)\n",
"\t-rm -f ", ModuleName, ".dep ", ModuleName, "\n",
"\t-rm -f ", ModuleName, ".split ", ModuleName,".split.a\n\n"
]),
io__write_strings(DepStream, [
"realclean: ", ModuleName, ".realclean\n"
]),
io__write_strings(DepStream, [
ModuleName, ".realclean : ", ModuleName, ".clean\n",
"\t-rm -f $(", ModuleName, ".dates)\n",
"\t-rm -f $(", ModuleName, ".date3s)\n",
"\t-rm -f $(", ModuleName, ".optdates)\n",
"\t-rm -f $(", ModuleName, ".ints)\n",
"\t-rm -f $(", ModuleName, ".int3s)\n",
"\t-rm -f $(", ModuleName, ".opts)\n",
"\t-rm -f $(", ModuleName, ".ds)\n",
"\t-rm -f $(", ModuleName, ".hs)\n"
]),
io__write_strings(DepStream, [
"\t-rm -f ",
ModuleName, " ",
ModuleName, ".split ",
ModuleName, ".split.a ",
ModuleName, ".nu ",
ModuleName, ".nu.save ",
ModuleName, ".nu.debug.save ",
ModuleName, ".nu.debug ",
ModuleName, ".sicstus ",
ModuleName, ".sicstus.debug ",
ModuleName, ".dep\n\n"
]),
io__write_strings(DepStream, [
"clean_nu: ", ModuleName, ".clean_nu\n",
ModuleName, ".clean_nu :\n",
"\t-rm -f $(", ModuleName, ".nos)\n\n",
"clean_sicstus: ", ModuleName, ".clean_sicstus\n",
ModuleName, ".clean_sicstus :\n",
"\t-rm -f $(", ModuleName, ".qls)\n\n"
]).
%-----------------------------------------------------------------------------%
% get_extra_link_objects(Modules, DepsMap, ExtraLinkObjs) },
% Find any extra .o files that should be linked into the executable.
% Currently only looks for fact table object files.
:- pred get_extra_link_objects(list(string), deps_map, list(string)).
:- mode get_extra_link_objects(in, in, out) is det.
get_extra_link_objects(Modules, DepsMap, ExtraLinkObjs) :-
get_extra_link_objects_2(Modules, DepsMap, [], ExtraLinkObjs).
:- pred get_extra_link_objects_2(list(string), deps_map,
list(string), list(string)).
:- mode get_extra_link_objects_2(in, in, in, out) is det.
get_extra_link_objects_2([], _DepsMap, ExtraLinkObjs, ExtraLinkObjs).
get_extra_link_objects_2([Module | Modules], DepsMap,
ExtraLinkObjs0, ExtraLinkObjs) :-
map__lookup(DepsMap, Module, deps(_, _, _, _, ObjList)),
list__append(ObjList, ExtraLinkObjs0, ExtraLinkObjs1),
get_extra_link_objects_2(Modules, DepsMap, ExtraLinkObjs1,
ExtraLinkObjs).
%-----------------------------------------------------------------------------%
:- pred select_ok_modules(list(string), deps_map, list(string)).
:- mode select_ok_modules(in, in, out) is det.
select_ok_modules([], _, []).
select_ok_modules([Module | Modules0], DepsMap, Modules) :-
map__lookup(DepsMap, Module, deps(_, Error, _, _, _)),
( Error = fatal ->
Modules = Modules1
;
Modules = [Module | Modules1]
),
select_ok_modules(Modules0, DepsMap, Modules1).
%-----------------------------------------------------------------------------%
:- pred write_dependencies_list(list(string), string, io__output_stream,
io__state, io__state).
:- mode write_dependencies_list(in, in, in, di, uo) is det.
write_dependencies_list([], _, _) --> [].
write_dependencies_list([Module | Modules], Suffix, DepStream) -->
io__write_string(DepStream, " \\\n\t"),
io__write_string(DepStream, Module),
io__write_string(DepStream, Suffix),
write_dependencies_list(Modules, Suffix, DepStream).
%-----------------------------------------------------------------------------%
:- pred write_compact_dependencies_list(list(string), string,
maybe(pair(string)), io__output_stream, io__state, io__state).
:- mode write_compact_dependencies_list(in, in, in, in, di, uo) is det.
write_compact_dependencies_list(Modules, Suffix, no, DepStream) -->
write_dependencies_list(Modules, Suffix, DepStream).
write_compact_dependencies_list(_Modules, Suffix, yes(VarName - OldSuffix),
DepStream) -->
io__write_string(DepStream, "$("),
io__write_string(DepStream, VarName),
io__write_string(DepStream, ":"),
io__write_string(DepStream, OldSuffix),
io__write_string(DepStream, "="),
io__write_string(DepStream, Suffix),
io__write_string(DepStream, ")").
:- pred write_compact_dependencies_separator(maybe(pair(string)),
io__output_stream, io__state, io__state).
:- mode write_compact_dependencies_separator(in, in, di, uo) is det.
write_compact_dependencies_separator(no, _DepStream) --> [].
write_compact_dependencies_separator(yes(_), DepStream) -->
io__write_string(DepStream, " ").
%-----------------------------------------------------------------------------%
% Given a list of modules, return a list of those modules
% and all their transitive interface dependencies.
:- pred transitive_dependencies(list(string), deps_map, bool, list(string),
deps_map, io__state, io__state).
:- mode transitive_dependencies(in, in, in, out, out, di, uo) is det.
transitive_dependencies(Modules, DepsMap0, Search, Dependencies, DepsMap) -->
{ set__init(Dependencies0) },
transitive_dependencies_2(Modules, Dependencies0, DepsMap0, Search,
Dependencies1, DepsMap),
{ set__to_sorted_list(Dependencies1, Dependencies) }.
:- pred transitive_dependencies_2(list(string), set(string), deps_map, bool,
set(string), deps_map,
io__state, io__state).
:- mode transitive_dependencies_2(in, in, in, in, out, out, di, uo) is det.
transitive_dependencies_2([], Deps, DepsMap, _Search, Deps, DepsMap) --> [].
transitive_dependencies_2([Module | Modules0], Deps0, DepsMap0, Search, Deps,
DepsMap)
-->
( { set__member(Module, Deps0) } ->
{ Deps1 = Deps0 },
{ DepsMap1 = DepsMap0 },
{ Modules1 = Modules0 }
;
{ set__insert(Deps0, Module, Deps1) },
lookup_dependencies(Module, DepsMap0, Search, _, _,
IntDeps, _ImplDeps, _FactDeps, DepsMap1),
{ list__append(IntDeps, Modules0, Modules1) }
),
transitive_dependencies_2(Modules1, Deps1, DepsMap1, Search, Deps,
DepsMap).
%-----------------------------------------------------------------------------%
% Given a list of modules, return a list of those modules
% and all their transitive implementation dependencies.
:- pred trans_impl_dependencies(list(string), deps_map, bool,
list(string), deps_map, io__state, io__state).
:- mode trans_impl_dependencies(in, in, in, out, out, di, uo) is det.
trans_impl_dependencies(Modules, DepsMap0, Search, Dependencies, DepsMap) -->
{ set__init(Dependencies0) },
trans_impl_dependencies_2(Modules, Dependencies0, DepsMap0, Search,
Dependencies1, DepsMap),
{ set__to_sorted_list(Dependencies1, Dependencies) }.
:- pred trans_impl_dependencies_2(list(string), set(string), deps_map, bool,
set(string), deps_map,
io__state, io__state).
:- mode trans_impl_dependencies_2(in, in, in, in, out, out, di, uo) is det.
trans_impl_dependencies_2([], Deps, DepsMap, _Search, Deps, DepsMap) --> [].
trans_impl_dependencies_2([Module | Modules0], Deps0, DepsMap0, Search, Deps,
DepsMap)
-->
( { set__member(Module, Deps0) } ->
{ Deps1 = Deps0 },
{ DepsMap1 = DepsMap0 },
{ Modules2 = Modules0 }
;
{ set__insert(Deps0, Module, Deps1) },
lookup_dependencies(Module, DepsMap0, Search, _, _, IntDeps,
ImplDeps, _FactDeps, DepsMap1),
{ list__append(IntDeps, Modules0, Modules1) },
{ list__append(ImplDeps, Modules1, Modules2) }
),
trans_impl_dependencies_2(Modules2, Deps1, DepsMap1, Search, Deps,
DepsMap).
%-----------------------------------------------------------------------------%
% Look up a module in the dependency map
% If we don't know its dependencies, read the
% module and save the dependencies in the dependency map.
:- pred lookup_dependencies(string, deps_map, bool,
bool, module_error, list(string), list(string), list(string),
deps_map, io__state, io__state).
:- mode lookup_dependencies(in, in, in, out, out, out, out, out, out,
di, uo) is det.
lookup_dependencies(Module, DepsMap0, Search, Done, Error, IntDeps,
ImplDeps, FactDeps, DepsMap)
-->
(
{ map__search(DepsMap0, Module,
deps(Done0, Error0, IntDeps0, ImplDeps0, FactDeps0)) }
->
{ Done = Done0 },
{ Error = Error0 },
{ IntDeps = IntDeps0 },
{ ImplDeps = ImplDeps0 },
{ FactDeps = FactDeps0 },
{ DepsMap = DepsMap0 }
;
read_dependencies(Module, Search, IntDeps, ImplDeps, FactDeps,
Error),
{ map__set(DepsMap0, Module,
deps(no, Error, IntDeps, ImplDeps, FactDeps), DepsMap) },
{ Done = no }
).
% Read a module to determine its dependencies.
:- pred read_dependencies(string, bool, list(string), list(string),
list(string), module_error, io__state, io__state).
:- mode read_dependencies(in, in, out, out, out, out, di, uo) is det.
read_dependencies(Module, Search, InterfaceDeps, ImplementationDeps,
FactTableDeps, Error) -->
io__gc_call(read_mod_ignore_errors(Module, ".m",
"Getting dependencies for module", Search, Items0, Error)),
( { Items0 = [], Error = fatal } ->
io__gc_call(read_mod_ignore_errors(Module, ".int",
"Getting dependencies for module interface", Search,
Items, _Error))
;
{ Items = Items0 }
),
{ get_dependencies(Items, ImplementationDeps0) },
{ get_interface(Items, no, InterfaceItems) },
{ get_dependencies(InterfaceItems, InterfaceDeps0) },
{ InterfaceDeps = ["mercury_builtin" | InterfaceDeps0] },
{ ImplementationDeps = ["mercury_builtin" | ImplementationDeps0] },
{ get_fact_table_dependencies(Items, FactTableDeps) }.
%-----------------------------------------------------------------------------%
read_mod(ModuleName, Extension, Descr, Search, Items, Error) -->
{ dir__basename(ModuleName, Module) },
{ string__append(ModuleName, Extension, FileName) },
globals__io_lookup_bool_option(very_verbose, VeryVerbose),
maybe_write_string(VeryVerbose, "% "),
maybe_write_string(VeryVerbose, Descr),
maybe_write_string(VeryVerbose, " `"),
maybe_write_string(VeryVerbose, FileName),
maybe_write_string(VeryVerbose, "'... "),
maybe_flush_output(VeryVerbose),
prog_io__read_module(FileName, Module, Search, Error, Messages, Items),
( { Error = fatal } ->
maybe_write_string(VeryVerbose, "fatal error(s).\n"),
io__set_exit_status(1)
; { Error = yes } ->
maybe_write_string(VeryVerbose, "parse error(s).\n"),
io__set_exit_status(1)
;
maybe_write_string(VeryVerbose, "successful parse.\n")
),
prog_out__write_messages(Messages).
/*
:- pred combine_module_errors(module_error, module_error, module_error).
:- mode combine_module_errors(in, in, out) is det.
combine_module_errors(fatal, _, fatal).
combine_module_errors(yes, fatal, fatal).
combine_module_errors(yes, yes, yes).
combine_module_errors(yes, no, yes).
combine_module_errors(no, Error, Error).
*/
read_mod_ignore_errors(ModuleName, Extension, Descr, Search, Items, Error) -->
{ dir__basename(ModuleName, Module) },
globals__io_lookup_bool_option(very_verbose, VeryVerbose),
maybe_write_string(VeryVerbose, "% "),
maybe_write_string(VeryVerbose, Descr),
maybe_write_string(VeryVerbose, " `"),
maybe_write_string(VeryVerbose, Module),
maybe_write_string(VeryVerbose, "'... "),
maybe_flush_output(VeryVerbose),
{ string__append(ModuleName, Extension, FileName) },
prog_io__read_module(FileName, Module, Search, Error, _Messages, Items),
maybe_write_string(VeryVerbose, "done.\n").
:- pred read_mod_short_interface(string, string, string, bool, item_list,
module_error, io__state, io__state).
:- mode read_mod_short_interface(in, in, in, in, out, out, di, uo) is det.
read_mod_short_interface(Module, Ext, Descr, Search, Items, Error) -->
read_mod(Module, Ext, Descr, Search, Items, Error).
:- pred read_mod_interface(string, string, bool, item_list, module_error,
io__state, io__state).
:- mode read_mod_interface(in, in, in, out, out, di, uo) is det.
read_mod_interface(Module, Descr, Search, Items, Error) -->
read_mod(Module, ".int", Descr, Search, Items, Error).
%-----------------------------------------------------------------------------%
process_module_interfaces([], IndirectImports, Module0, Module) -->
process_module_short_interfaces(IndirectImports, Module0, Module).
process_module_interfaces([Import | Imports], IndirectImports0, Module0, Module)
-->
{ Module0 = module_imports(ModuleName, DirectImports0,
OldIndirectImports, Items0, Error0) },
(
{ Import = ModuleName }
->
( { ModuleName = "mercury_builtin" } ->
[]
;
globals__io_lookup_bool_option(warn_simple_code,
Warn),
( { Warn = yes } ->
{ term__context_init(ModuleName, 1, Context) },
prog_out__write_context(Context),
io__write_string(
"Warning: module imports itself!\n")
;
[]
)
),
process_module_interfaces(Imports, IndirectImports0,
Module0, Module)
;
{ list__member(Import, DirectImports0) }
->
process_module_interfaces(Imports, IndirectImports0,
Module0, Module)
;
io__gc_call(
read_mod_interface(Import,
"Reading interface for module", yes,
LongIntItems1, Error1)
),
% strip off the `:- interface' declaration at the start, if any
{
LongIntItems1 = [ FirstItem | LongIntItems2 ],
FirstItem = module_defn(_, interface) - _
->
Items1 = LongIntItems2
;
Items1 = LongIntItems1
},
{ ( Error1 \= no ->
Error2 = yes
;
Error2 = Error0
) },
globals__io_lookup_bool_option(statistics, Statistics),
maybe_report_stats(Statistics),
{ get_dependencies(Items1, IndirectImports1) },
( { Error1 = fatal } ->
{ DirectImports1 = DirectImports0 }
;
{ DirectImports1 = [Import | DirectImports0] }
),
{ list__append(IndirectImports0, IndirectImports1,
IndirectImports2) },
{ list__append(Items0, Items1, Items2) },
{ Module1 = module_imports(ModuleName, DirectImports1,
OldIndirectImports, Items2, Error2) },
process_module_interfaces(Imports, IndirectImports2,
Module1, Module)
).
%-----------------------------------------------------------------------------%
:- pred process_module_short_interfaces(list(string),
module_imports, module_imports, io__state, io__state).
:- mode process_module_short_interfaces(in, in, out, di, uo) is det.
process_module_short_interfaces(Imports, Module0, Module) -->
process_module_short_interfaces(Imports, ".int2", Module0, Module).
:- pred process_module_short_interfaces(list(string), string,
module_imports, module_imports, io__state, io__state).
:- mode process_module_short_interfaces(in, in, in, out, di, uo) is det.
process_module_short_interfaces([], _, Module, Module) --> [].
process_module_short_interfaces([Import | Imports], Ext, Module0, Module) -->
{ Module0 = module_imports(ModuleName, DirectImports, IndirectImports0,
Items0, Error0) },
(
% check if the imported module has already been imported
{ Import = ModuleName
; list__member(Import, DirectImports)
; list__member(Import, IndirectImports0)
}
->
process_module_short_interfaces(Imports, Ext, Module0, Module)
;
io__gc_call(
read_mod_short_interface(Import, Ext,
"Reading short interface for module", yes,
ShortIntItems1, Error1)
),
% strip off the `:- interface' declaration at the start, if any
{
ShortIntItems1 = [ FirstItem | ShortIntItems2 ],
FirstItem = module_defn(_, interface) - _
->
Items1 = ShortIntItems2
;
Items1 = ShortIntItems1
},
{ Error1 \= no ->
Error2 = yes
;
Error2 = Error0
},
globals__io_lookup_bool_option(statistics, Statistics),
maybe_report_stats(Statistics),
{ get_dependencies(Items1, Imports1) },
{ list__append(Imports, Imports1, Imports2) },
{ list__append(Items0, Items1, Items2) },
{ IndirectImports1 = [Import | IndirectImports0] },
{ Module1 = module_imports(ModuleName, DirectImports,
IndirectImports1, Items2, Error2) },
process_module_short_interfaces(Imports2, Ext, Module1, Module)
).
%-----------------------------------------------------------------------------%
get_dependencies(Items, Deps) :-
get_dependencies_2(Items, [], Deps).
:- pred get_dependencies_2(item_list, list(string), list(string)).
:- mode get_dependencies_2(in, in, out) is det.
get_dependencies_2([], Deps, Deps).
get_dependencies_2([Item - _Context | Items], Deps0, Deps) :-
(
Item = module_defn(_VarSet, import(module(Modules)))
->
list__append(Deps0, Modules, Deps1)
;
Deps1 = Deps0
),
get_dependencies_2(Items, Deps1, Deps).
%-----------------------------------------------------------------------------%
% get the fact table dependencies for a module
:- pred get_fact_table_dependencies(item_list, list(string)).
:- mode get_fact_table_dependencies(in, out) is det.
get_fact_table_dependencies(Items, Deps) :-
get_fact_table_dependencies_2(Items, [], Deps).
:- pred get_fact_table_dependencies_2(item_list, list(string), list(string)).
:- mode get_fact_table_dependencies_2(in, in, out) is det.
get_fact_table_dependencies_2([], Deps, Deps).
get_fact_table_dependencies_2([Item - _Context | Items], Deps0, Deps) :-
(
Item = pragma(fact_table(_SymName, _Arity, FileName))
->
Deps1 = [FileName | Deps0]
;
Deps1 = Deps0
),
get_fact_table_dependencies_2(Items, Deps1, Deps).
%-----------------------------------------------------------------------------%
% 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.
:- pred get_interface(item_list, bool, item_list).
:- mode get_interface(in, in, out) is det.
get_interface(Items0, IncludeImported, Items) :-
get_interface_2(Items0, no, IncludeImported, [], RevItems),
list__reverse(RevItems, Items).
:- pred get_interface_2(item_list, bool, bool, item_list, item_list).
:- mode get_interface_2(in, in, in, in, out) is det.
get_interface_2([], _, _, Items, Items).
get_interface_2([Item - Context | Rest], InInterface0,
IncludeImported, Items0, Items) :-
( Item = module_defn(_, interface) ->
Items1 = Items0,
InInterface1 = yes
; Item = module_defn(_, imported) ->
% module_qual.m needs the :- imported declaration.
( IncludeImported = yes ->
InInterface1 = yes,
Items1 = [Item - Context | Items0]
;
InInterface1 = no,
Items1 = Items0
)
; Item = module_defn(_, implementation) ->
Items1 = Items0,
InInterface1 = no
;
( InInterface0 = yes ->
Items1 = [Item - Context | Items0]
;
Items1 = Items0
),
InInterface1 = InInterface0
),
get_interface_2(Rest, InInterface1, IncludeImported, Items1, Items).
% Given a module interface (well, a list of items), extract the
% short interface part of that module, i.e. the exported
% type/inst/mode declarations, but not the exported pred or
% constructor declarations. If the module interface imports
% other modules, then the short interface only needs to include
% those import_module declarations only if the short interface
% contains some equivalence types or some mode or inst definitions
% that might use declarations in the imported modules.
% If the short interface is empty, or only contains abstract
% type declarations, then it doesn't need any import_module
% declarations.
:- pred get_short_interface(item_list, item_list).
:- mode get_short_interface(in, out) is det.
get_short_interface(Items0, Items) :-
get_short_interface_2(Items0, [], [], no,
RevItems, RevImports, NeedsImports),
list__reverse(RevItems, Items1),
( NeedsImports = yes ->
list__reverse(RevImports, Imports1),
list__append(Imports1, Items1, Items)
;
Items = Items1
).
:- pred get_short_interface_2(item_list, item_list, item_list, bool,
item_list, item_list, bool).
:- mode get_short_interface_2(in, in, in, in, out, out, out) is det.
get_short_interface_2([], Items, Imports, NeedsImports,
Items, Imports, NeedsImports).
get_short_interface_2([ItemAndContext | Rest], Items0, Imports0, NeedsImports0,
Items, Imports, NeedsImports) :-
ItemAndContext = Item0 - Context,
( Item0 = module_defn(_, import(_)) ->
Items1 = Items0,
Imports1 = [ItemAndContext | Imports0],
NeedsImports1 = NeedsImports0
; make_abstract_type_defn(Item0, Item1) ->
Imports1 = Imports0,
Items1 = [Item1 - Context | Items0],
NeedsImports1 = NeedsImports0
; include_in_short_interface(Item0) ->
Imports1 = Imports0,
Items1 = [ItemAndContext | Items0],
NeedsImports1 = yes
;
Items1 = Items0,
Imports1 = Imports0,
NeedsImports1 = NeedsImports0
),
get_short_interface_2(Rest, Items1, Imports1, NeedsImports1,
Items, Imports, NeedsImports).
:- pred include_in_short_interface(item).
:- mode include_in_short_interface(in) is semidet.
include_in_short_interface(type_defn(_, _, _)).
include_in_short_interface(inst_defn(_, _, _)).
include_in_short_interface(mode_defn(_, _, _)).
include_in_short_interface(module_defn(_, _)).
:- pred make_abstract_type_defn(item, item).
:- mode make_abstract_type_defn(in, out) is semidet.
make_abstract_type_defn(type_defn(VarSet, du_type(Name, Args, _Ctors), Cond),
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)).
%-----------------------------------------------------------------------------%