Files
mercury/compiler/find_module.m
Zoltan Somogyi c2f92d5454 Partition extensions into ".m" and "all others".
This is a first step towards a much finer grained partition.

compiler/file_names.m:
    Split the ext type into ext_src and ext_other, as mentioned above.

    Add the first predicate for checking whether a string falls into
    a given category of extensions.

    Add an XXX proposing a better solution for an old problem that does not
    actually arise in practice.

compiler/compile_target_code.m:
    Split the two-moded predicate maybe_pic_object_file_extension into
    two separate one-mode predicates, one for each old mode. The
    implementations of the two modes were already separate, because
    the two modes already did different jobs: while one went from PIC
    to an "extension", the other went from an "extension string" to PIC.
    Until now, "extension" and "extension string" were equivalent;
    after this diff, they aren't anymore.

    Delete an unused argument.

compiler/make.util.m:
    Split the two-moded predicate target_extension into
    two separate one-mode predicates, one for each old mode,
    for the same reason as maybe_pic_object_file_extension above:
    the fact that "extension" and "extension string" are now distinct.

compiler/options_file.m:
    Move debug infrastructure here from mercury_compile_main.m, to help
    debug possible problems with options files. (I had such a problem
    while writing this diff.)

    Improve how progress messages are printed.

compiler/options.m:
    Make an error message more useful.

compiler/mercury_compile_main.m:
    Add infrastructure for debugging possible problems with command lines.
    (I had such a problem while writing this diff.)

compiler/analysis.m:
    Conform to the changes above. Put the arguments of some methods
    into the same order as similar predicates in file_names.m.

compiler/find_module.m:
    Conform to the changes above. Delete an unused argument,

compiler/analysis.file.m:
compiler/du_type_layout.m:
compiler/elds_to_erlang.m:
compiler/export.m:
compiler/fact_table.m:
compiler/file_kind.m:
compiler/generate_dep_d_files.m:
compiler/grab_modules.m:
compiler/llds_out_file.m:
compiler/make.build.m:
compiler/make.deps_set.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_java_file.m:
compiler/mmc_analysis.m:
compiler/mode_constraints.m:
compiler/module_cmds.m:
compiler/prog_foreign.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/source_file_map.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
2020-08-17 23:43:15 +10:00

151 lines
5.6 KiB
Mathematica

%-----------------------------------------------------------------------------e
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------e
% Copyright (C) 2014, 2016-2017, 2019-2020 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% This module defines predicates that find Mercury modules.
%
%---------------------------------------------------------------------------%
:- module parse_tree.find_module.
:- interface.
:- import_module libs.
:- import_module libs.file_util.
:- import_module libs.globals.
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module io.
:- import_module list.
:- import_module maybe.
%---------------------------------------------------------------------------%
% search_for_module_source(Dirs, ModuleName, FoundSourceFile, !IO):
%
% Look for the source for ModuleName in Dirs. If found, return the
% (relative or absolute) path name of the source file that contains
% the module.
%
:- pred search_for_module_source(list(dir_name)::in, module_name::in,
maybe_error(file_name)::out, io::di, io::uo) is det.
% search_for_module_source_and_stream(Dirs, ModuleName,
% FoundSourceFileNameAndStream, !IO):
%
% As search_for_module_source, but if we find the file, then return
% not just its path name, but also an open stream reading from it.
% Closing that stream is the caller's responsibility.
%
:- pred search_for_module_source_and_stream(list(dir_name)::in, module_name::in,
maybe_error(path_name_and_stream)::out, io::di, io::uo) is det.
% Read the first item from the given file to find the module name.
%
:- pred find_module_name(globals::in, file_name::in, maybe(module_name)::out,
io::di, io::uo) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module parse_tree.error_util.
:- import_module parse_tree.file_names.
:- import_module parse_tree.parse_module. % for peek_at_file
:- import_module dir.
:- import_module string.
%---------------------------------------------------------------------------%
search_for_module_source(Dirs, ModuleName, MaybeFileName, !IO) :-
search_for_module_source_and_stream(Dirs, ModuleName,
MaybeFileNameAndStream, !IO),
(
MaybeFileNameAndStream =
ok(path_name_and_stream(SourceFileName, SourceStream)),
io.close_input(SourceStream, !IO),
MaybeFileName = ok(SourceFileName)
;
MaybeFileNameAndStream = error(Msg),
MaybeFileName = error(Msg)
).
search_for_module_source_and_stream(Dirs, ModuleName,
MaybeFileNameAndStream, !IO) :-
module_name_to_source_file_name(ModuleName, FileName0, !IO),
search_for_file_and_stream(Dirs, FileName0, MaybeFileNameAndStream0, !IO),
(
MaybeFileNameAndStream0 = ok(_),
MaybeFileNameAndStream = MaybeFileNameAndStream0
;
MaybeFileNameAndStream0 = error(_),
Error = find_source_error(ModuleName, Dirs, no),
MaybeFileNameAndStream = error(Error)
).
%------------%
:- func find_source_error(module_name, list(dir_name), maybe(file_name))
= string.
find_source_error(ModuleName, Dirs, MaybeBetterMatch) = Msg :-
ModuleNameStr = sym_name_to_string(ModuleName),
Msg0 = "cannot find source for module `" ++ ModuleNameStr ++
"' in directories " ++
string.join_list(", ",
map((func(Dir) = "`" ++ Dir ++ "'"), Dirs)),
(
MaybeBetterMatch = no,
Msg = Msg0
;
MaybeBetterMatch = yes(BetterMatchFile),
Msg = Msg0 ++ ", but found " ++ BetterMatchFile ++
" in interface search path"
).
%---------------------------------------------------------------------------%
find_module_name(Globals, FileName, MaybeModuleName, !IO) :-
io.open_input(FileName, OpenRes, !IO),
(
OpenRes = ok(FileStream),
( if string.remove_suffix(FileName, ".m", PartialFileName0) then
PartialFileName = PartialFileName0
else
PartialFileName = FileName
),
( if dir.basename(PartialFileName, BaseName0) then
BaseName = BaseName0
else
BaseName = ""
),
file_name_to_module_name(BaseName, DefaultModuleName),
peek_at_file(FileStream, DefaultModuleName, [], FileName, ModuleName,
Specs, !IO),
io.close_input(FileStream, !IO),
MaybeModuleName = yes(ModuleName),
% XXX We don't check whether ModuleName was actually read
% from the named file; it could just be DefaultModuleName.
write_error_specs_ignore(Globals, Specs, !IO)
;
OpenRes = error(Error),
ErrorMsg = io.error_message(Error),
io.progname_base("mercury_compile", Progname, !IO),
Pieces = [fixed(Progname), suffix(":"), words("error opening"),
quote(FileName), suffix(":"), words(ErrorMsg), suffix("."), nl],
Spec = error_spec($pred, severity_error, phase_read_files,
[error_msg(no, treat_as_first, 0, [always(Pieces)])]),
write_error_spec_ignore(Globals, Spec, !IO),
MaybeModuleName = no
).
%---------------------------------------------------------------------------%
:- end_module parse_tree.find_module.
%---------------------------------------------------------------------------%