Files
mercury/compiler/modules.m
Fergus Henderson 3a2a10c193 Simplify the process for creating and using Mercury libraries,
and document it.

compiler/modules.m:
	Add rules for creating the `.a', `.so', and `.init' files.
	The `.so' file is creating using ml's new `--make-shared-lib' option.

scripts/Mmake.vars.in:
	Add definitions for AR, ARFLAGS, RANLIB, and RANLIBFLAGS,
	for use by the new rules generated in `.dep' files by modules.m.

Mmake.common.in:
	Remove RANLIB, since it's now defined in scripts/Mmake.vars.in.

doc/user_guide.texi:
	Add a chapter on libraries.
1997-07-15 09:12:01 +00:00

1573 lines
54 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.
% get_dependencies(Items, ImportDeps, UseDeps).
% Get the list of modules that a list of items depends on.
% ImportDeps is the list of modules imported using
% `:- import_module', UseDeps is the list of modules imported
% using `:- use_module'.
%
:- pred get_dependencies(item_list, list(string), list(string)).
:- mode get_dependencies(in, out, 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,
InterfaceImportDeps, InterfaceUseDeps) },
{ list__append(InterfaceItems0,
[module_defn(Varset, imported) - Context],
InterfaceItems1) },
{ Module1 = module_imports(ModuleName, [], [], InterfaceItems1, no) },
% Get the .int3s that the current .int depends on.
process_module_short_interfaces(
["mercury_builtin" | InterfaceImportDeps],
".int3", Module1, Module2),
{ Module2 = module_imports(_, Direct2, Indirect2,
InterfaceItems2, Error2) },
{ list__append(InterfaceItems2,
[module_defn(Varset, used) - Context],
InterfaceItems3) },
{ Module3 = module_imports(ModuleName, Direct2, Indirect2,
InterfaceItems3, Error2) },
process_module_short_interfaces(InterfaceUseDeps,
".int3", Module3, Module4),
{ Module4 = module_imports(_, _, _, InterfaceItems4, 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(InterfaceItems4,
InterfaceItems5, ModuleName, yes, _, _, _, _),
io__get_exit_status(Status),
( { Status \= 0 } ->
io__write_strings([ModuleName, ".int not written.\n"])
;
{ strip_imported_items(InterfaceItems5, [],
InterfaceItems6) },
check_for_clauses_in_interface(InterfaceItems6,
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)
; Item = module_defn(_, used) ->
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, UsedModules0) },
{ set__list_to_set(ImportedModules, ImportedSet) },
{ set__list_to_set(UsedModules0, UsedSet) },
{ set__intersect(ImportedSet, UsedSet, BothSet) },
% Report errors for modules imported using both :- use_module
% and :- import_module. Remove the import_module declaration.
{ string__append(ModuleName, ".m", FileName) },
{ term__context_init(FileName, 0, Context) },
( { set__empty(BothSet) } ->
{ UsedModules = UsedModules0 }
;
prog_out__write_context(Context),
io__write_string("Warning:"),
{ set__to_sorted_list(BothSet, BothList) },
( { BothList = [_] } ->
io__write_string(" module "),
prog_out__write_module_list(BothList),
io__write_string(" is ")
;
io__write_string(" modules "),
prog_out__write_module_list(BothList),
io__write_string(" are ")
),
io__write_string("imported using both\n"),
prog_out__write_context(Context),
io__write_string(" `:- import_module' and `:- use_module' declarations.\n"),
% Treat the modules with both types of import as if they
% were imported using :- import_module.
{ list__delete_elems(UsedModules0, BothList,
UsedModules) },
globals__io_lookup_bool_option(halt_at_warn, Halt),
( { Halt = yes } ->
io__set_exit_status(1)
;
[]
)
),
{ get_fact_table_dependencies(Items0, FactDeps) },
% 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.
{ varset__init(VarSet) },
{ list__append(Items0,
[module_defn(VarSet, imported) - Context], Items1) },
{ dir__basename(ModuleName, BaseModuleName) },
{ Module1 = module_imports(BaseModuleName, [], [], Items1, no) },
process_module_interfaces(["mercury_builtin" | ImportedModules],
[], Module1, Module2),
{ Module2 = module_imports(_, Direct2, Indirect2, Items2, Error2) },
% we add a pseudo-declarations `:- used' at the end
% of the item list. Uses of the items with declarations
% following this must be module qualified.
{ list__append(Items2,
[module_defn(VarSet, used) - Context], Items3) },
{ Module3 = module_imports(BaseModuleName, Direct2, Indirect2,
Items3, Error2) },
process_module_interfaces(UsedModules, [], Module3, 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) },
( { FactDeps \= [] } ->
io__write_strings(DepStream,
[ModuleName, ".fact_tables = "]),
write_dependencies_list(FactDeps, "", DepStream),
io__nl(DepStream),
globals__io_lookup_bool_option(assume_gmake,
AssumeGmake),
( { AssumeGmake = no} ->
io__write_strings(DepStream,
[ModuleName, ".fact_tables.os = "]),
write_dependencies_list(FactDeps, ".o",
DepStream),
io__write_strings(DepStream, [
"\n\n",
ModuleName, ".fact_tables.cs = "]),
write_dependencies_list(FactDeps, ".c",
DepStream),
io__nl(DepStream)
;
io__write_strings(DepStream, [
"\n\n", ModuleName,
".fact_tables.os = $(", ModuleName,
".fact_tables:%=%.o)\n\n",
ModuleName,
".fact_tables.cs = $(", ModuleName,
".fact_tables:%=%.c)\n\n"
])
)
;
[]
),
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),
( { FactDeps \= [] } ->
io__write_strings(DepStream, [
" \\\n\t$(", ModuleName, ".fact_tables)\n\n",
"$(", ModuleName, ".fact_tables.os) : $(",
ModuleName, ".fact_tables) ",
ModuleName, ".m\n\n",
"$(", ModuleName, ".fact_tables.cs) : ",
ModuleName, ".o\n"
] )
;
[]
),
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"
]),
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"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".qls = "),
write_compact_dependencies_list(Modules, ".ql", Basis, DepStream),
io__write_string(DepStream, "\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"),
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"),
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"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".dirs = "),
write_compact_dependencies_list(Modules, ".dir", Basis, DepStream),
io__write_string(DepStream, "\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"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".ss = "),
write_compact_dependencies_list(Modules, ".s", Basis, DepStream),
io__write_string(DepStream, "\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".errs = "),
write_compact_dependencies_list(Modules, ".err", Basis, DepStream),
io__write_string(DepStream, "\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".dates = "),
write_compact_dependencies_list(Modules, ".date", Basis, DepStream),
io__write_string(DepStream, "\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".date3s = "),
write_compact_dependencies_list(Modules, ".date3", Basis, DepStream),
io__write_string(DepStream, "\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".optdates = "),
write_compact_dependencies_list(Modules, ".optdate", Basis, DepStream),
io__write_string(DepStream, "\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".ds = "),
write_compact_dependencies_list(Modules, ".d", Basis, DepStream),
io__write_string(DepStream, "\n"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".hs = "),
write_compact_dependencies_list(Modules, ".h", Basis, DepStream),
io__write_string(DepStream, "\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"),
io__write_string(DepStream, ModuleName),
io__write_string(DepStream, ".int3s = "),
write_compact_dependencies_list(Modules, ".int3", Basis, DepStream),
io__write_string(DepStream, "\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"),
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",
"\t$(AR) $(ARFLAGS) ", ModuleName, ".split.a\n",
"\tfor dir in $(", ModuleName, ".dirs); do \\\n",
"\t $(AR) q ", ModuleName, ".split.a $$dir/*.o; \\\n",
"\tdone\n",
"\t$(RANLIB) $(RANLIBFLAGS) ", ModuleName, ".split.a\n\n"
]),
io__write_strings(DepStream, [
"lib", ModuleName, " : ",
"lib", ModuleName, ".a ",
"lib", ModuleName, ".$(EXT_FOR_SHARED_LIB) \\\n",
"\t\t$(", ModuleName, ".ints) ",
"$(", ModuleName, ".opts) ",
ModuleName, ".init\n\n"
]),
io__write_strings(DepStream, [
"lib", ModuleName, ".so : $(", ModuleName, ".pic_os)\n",
"\t$(ML) --make-shared-lib $(MLFLAGS) -o ",
"lib", ModuleName, ".so \\\n",
"\t\t$(", ModuleName, ".pic_os) $(MLLIBS)\n\n"
]),
io__write_strings(DepStream, [
"lib", ModuleName, ".a : $(", ModuleName, ".os)\n",
"\trm -f ", ModuleName, ".a\n",
"\t$(AR) $(ARFLAGS) lib", ModuleName, ".a ",
"$(", ModuleName, ".os)\n",
"\t$(RANLIB) $(RANLIBFLAGS) lib", ModuleName, ".a\n\n"
]),
io__write_strings(DepStream, [
ModuleName, ".init : ", ModuleName, ".dep\n",
"\tfor file in $(", ModuleName, ".ms); do \\\n",
"\t\techo ""INIT mercury__`basename $$file .m`__init""; \\\n",
"\tdone > ", ModuleName, ".init\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"
]),
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, " ",
ModuleName, ".split ",
ModuleName, ".split.a ",
ModuleName, ".init ",
"lib", ModuleName, ".a ",
"lib", ModuleName, ".so ",
ModuleName, ".dep\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, ".init ",
"lib", ModuleName, ".a ",
"lib", ModuleName, ".so ",
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__det_insert(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) -->
read_mod_ignore_errors(Module, ".m",
"Getting dependencies for module", Search, Items0, Error),
( { Items0 = [], Error = fatal } ->
read_mod_ignore_errors(Module, ".int",
"Getting dependencies for module interface", Search,
Items, _Error)
;
{ Items = Items0 }
),
{ get_dependencies(Items, ImplImportDeps, ImplUseDeps) },
{ list__append(ImplImportDeps, ImplUseDeps, ImplementationDeps0) },
{ get_interface(Items, no, InterfaceItems) },
{ get_dependencies(InterfaceItems, InterfaceImportDeps,
InterfaceUseDeps) },
{ list__append(InterfaceImportDeps, InterfaceUseDeps,
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)
;
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, IndirectUses1) },
( { Error1 = fatal } ->
{ DirectImports1 = DirectImports0 }
;
{ DirectImports1 = [Import | DirectImports0] }
),
{ list__append(IndirectImports0, IndirectImports1,
IndirectImports2) },
{ list__append(IndirectImports2, IndirectUses1,
IndirectImports3) },
{ list__append(Items0, Items1, Items2) },
{ Module1 = module_imports(ModuleName, DirectImports1,
OldIndirectImports, Items2, Error2) },
process_module_interfaces(Imports, IndirectImports3,
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) -->
{ Module0 = module_imports(ModuleName, DirectImports0,
IndirectImports0, Items0, Error0) },
% Treat indirectly imported items as if they were imported
% using `:- use_module', since all uses of them in the `.int'
% files must be module qualified.
{ varset__init(Varset) },
{ term__context_init(Context) },
{ list__append(Items0, [module_defn(Varset, used) - Context],
Items1) },
{ Module1 = module_imports(ModuleName, DirectImports0,
IndirectImports0, Items1, Error0) },
process_module_short_interfaces(Imports, ".int2", Module1, 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)
;
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, _Uses1) },
{ 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, ImportDeps, UseDeps) :-
get_dependencies_2(Items, [], ImportDeps, [], UseDeps).
:- pred get_dependencies_2(item_list, list(string), list(string),
list(string), list(string)).
:- mode get_dependencies_2(in, in, out, in, out) is det.
get_dependencies_2([], ImportDeps, ImportDeps, UseDeps, UseDeps).
get_dependencies_2([Item - _Context | Items], ImportDeps0, ImportDeps,
UseDeps0, UseDeps) :-
(
Item = module_defn(_VarSet, import(module(Modules)))
->
list__append(ImportDeps0, Modules, ImportDeps1),
UseDeps1 = UseDeps0
;
Item = module_defn(_VarSet, use(module(Modules)))
->
list__append(UseDeps0, Modules, UseDeps1),
ImportDeps1 = ImportDeps0
;
ImportDeps1 = ImportDeps0,
UseDeps1 = UseDeps0
),
get_dependencies_2(Items, ImportDeps1, ImportDeps, UseDeps1, UseDeps).
%-----------------------------------------------------------------------------%
% 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(_, Defn),
( Defn = imported
; Defn = used
)
->
% module_qual.m needs the :- imported declaration.
( IncludeImported = yes, InInterface0 = yes ->
Items1 = [Item - Context | Items0]
;
Items1 = Items0
),
InInterface1 = InInterface0
;
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
; Item0 = module_defn(_, use(_)) ->
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)).
%-----------------------------------------------------------------------------%