mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-27 07:14:20 +00:00
compiler/file_names.m:
Change the order of arguments of module_name_to_file_name and related
predicates to make it easier to construct closures from them. Delete
the previous higher-order-friendly versions, which the previous step
has made unnecessary.
compiler/compile_target_code.m:
compiler/elds_to_erlang.m:
compiler/export.m:
compiler/find_module.m:
compiler/generate_dep_d_files.m:
compiler/intermod.m:
compiler/llds_out_file.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/mercury_compile_front_end.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mercury_compile_main.m:
compiler/mercury_compile_middle_passes.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/mmc_analysis.m:
compiler/mode_constraints.m:
compiler/module_cmds.m:
compiler/modules.m:
compiler/read_modules.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
compiler/xml_documentation.m:
Conform to the change above. In several places, this means replacing
explicit lambda expressions with simple partial application of the
relevant predicates.
285 lines
11 KiB
Mathematica
285 lines
11 KiB
Mathematica
%-----------------------------------------------------------------------------e
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------e
|
|
% Copyright (C) 2014 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.file_util.
|
|
:- import_module libs.globals.
|
|
:- import_module mdbcomp.sym_name.
|
|
|
|
:- import_module io.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% search_for_module_source(Globals, Dirs, InterfaceDirs,
|
|
% 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.
|
|
%
|
|
% This will also search for files matching partially qualified versions
|
|
% of ModuleName, dropping qualifiers outermost to innermost, but only if
|
|
% a more qualified `.m' or `.int' file doesn't exist in InterfaceDirs.
|
|
% For example, module foo.bar.baz can be found in foo.bar.m, bar.baz.m
|
|
% or bar.m.
|
|
%
|
|
:- pred search_for_module_source(globals::in, list(dir_name)::in,
|
|
list(dir_name)::in, module_name::in,
|
|
maybe_error(file_name)::out, io::di, io::uo) is det.
|
|
|
|
% search_for_module_source_and_stream(Globals, Dirs, InterfaceDirs,
|
|
% 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(globals::in, list(dir_name)::in,
|
|
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(Globals, Dirs, InterfaceDirs, ModuleName,
|
|
MaybeFileName, !IO) :-
|
|
search_for_module_source_and_stream(Globals, Dirs, InterfaceDirs,
|
|
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(Globals, Dirs, InterfaceDirs, ModuleName,
|
|
MaybeFileNameAndStream, !IO) :-
|
|
search_for_module_source_dropping_qualifiers(Globals,
|
|
Dirs, ModuleName, MaybeFileNameAndStream0, !IO),
|
|
(
|
|
MaybeFileNameAndStream0 =
|
|
ok(path_name_and_stream(SourceFileName, SourceStream)),
|
|
( if
|
|
string.remove_suffix(dir.basename(SourceFileName),
|
|
".m", SourceFileBaseName),
|
|
file_name_to_module_name(SourceFileBaseName, SourceFileModuleName),
|
|
ModuleName \= SourceFileModuleName
|
|
then
|
|
% The module name doesn't match the file name. Return an error
|
|
% if there is a more qualified matching `.m' or `.int' file in
|
|
% the interface search path. This avoids having a file `read.m'
|
|
% in the current directory prevent the compiler from finding
|
|
% `bit_buffer.read.int' in the standard library.
|
|
% Note that we never need to read from this more qualified file.
|
|
|
|
search_for_module_source_dropping_qualifiers(Globals,
|
|
InterfaceDirs, ModuleName, MaybeIFaceFileNameAndStream, !IO),
|
|
(
|
|
MaybeIFaceFileNameAndStream =
|
|
ok(path_name_and_stream(_IFaceFileName, IFaceStream)),
|
|
io.close_input(IFaceStream, !IO)
|
|
;
|
|
MaybeIFaceFileNameAndStream = error(_)
|
|
),
|
|
( if
|
|
MaybeIFaceFileNameAndStream =
|
|
ok(path_name_and_stream(IFaceFileName, _IFaceStream)),
|
|
IFaceFileName \= SourceFileName,
|
|
string.remove_suffix(dir.basename(IFaceFileName), ".m",
|
|
IFaceFileBaseName),
|
|
file_name_to_module_name(IFaceFileBaseName,
|
|
IFaceFileModuleName),
|
|
partial_sym_name_matches_full(SourceFileModuleName,
|
|
IFaceFileModuleName)
|
|
then
|
|
io.close_input(SourceStream, !IO),
|
|
Error =
|
|
find_source_error(ModuleName, Dirs, yes(IFaceFileName)),
|
|
MaybeFileNameAndStream = error(Error)
|
|
else
|
|
module_name_to_file_name(Globals, do_not_create_dirs, ".int",
|
|
ModuleName, IntFile, !IO),
|
|
search_for_file_returning_dir(InterfaceDirs, IntFile,
|
|
MaybeIntDir, !IO),
|
|
( if
|
|
MaybeIntDir = ok(IntDir),
|
|
IntDir \= dir.this_directory
|
|
then
|
|
io.close_input(SourceStream, !IO),
|
|
Error = find_source_error(ModuleName, Dirs,
|
|
yes(IntDir/IntFile)),
|
|
MaybeFileNameAndStream = error(Error)
|
|
else
|
|
MaybeFileNameAndStream = MaybeFileNameAndStream0
|
|
)
|
|
)
|
|
else
|
|
MaybeFileNameAndStream = MaybeFileNameAndStream0
|
|
)
|
|
;
|
|
MaybeFileNameAndStream0 = error(_),
|
|
MaybeFileNameAndStream = MaybeFileNameAndStream0
|
|
).
|
|
|
|
%------------%
|
|
|
|
:- pred search_for_module_source_dropping_qualifiers(globals::in,
|
|
list(dir_name)::in, module_name::in,
|
|
maybe_error(path_name_and_stream)::out, io::di, io::uo) is det.
|
|
|
|
search_for_module_source_dropping_qualifiers(Globals, Dirs, ModuleName,
|
|
MaybeErrorFileNameAndStream, !IO) :-
|
|
search_for_module_source_dropping_qualifiers_loop(Globals, Dirs,
|
|
ModuleName, MaybeFileNameAndStream, !IO),
|
|
(
|
|
MaybeFileNameAndStream = yes(FileNameAndStream),
|
|
MaybeErrorFileNameAndStream = ok(FileNameAndStream)
|
|
;
|
|
MaybeFileNameAndStream = no,
|
|
Error = find_source_error(ModuleName, Dirs, no),
|
|
MaybeErrorFileNameAndStream = error(Error)
|
|
).
|
|
|
|
:- pred search_for_module_source_dropping_qualifiers_loop(globals::in,
|
|
list(dir_name)::in, module_name::in, maybe(path_name_and_stream)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
search_for_module_source_dropping_qualifiers_loop(Globals, Dirs,
|
|
PartialModuleName0, MaybeFileNameAndStream, !IO) :-
|
|
module_name_to_file_name(Globals, do_not_create_dirs, ".m",
|
|
PartialModuleName0, FileName0, !IO),
|
|
search_for_file_and_stream(Dirs, FileName0, MaybeFileNameAndStream0, !IO),
|
|
(
|
|
MaybeFileNameAndStream0 = ok(FileNameAndStream0),
|
|
MaybeFileNameAndStream = yes(FileNameAndStream0)
|
|
;
|
|
MaybeFileNameAndStream0 = error(_),
|
|
( if
|
|
drop_outermost_qualifier(PartialModuleName0, PartialModuleName1)
|
|
then
|
|
search_for_module_source_dropping_qualifiers_loop(Globals, Dirs,
|
|
PartialModuleName1, MaybeFileNameAndStream, !IO)
|
|
else
|
|
MaybeFileNameAndStream = no
|
|
)
|
|
).
|
|
|
|
%------------%
|
|
|
|
:- pred drop_outermost_qualifier(module_name::in, module_name::out) is semidet.
|
|
|
|
drop_outermost_qualifier(SymName, DroppedQualifierSymName) :-
|
|
SymName = qualified(ParentModuleName, ChildName),
|
|
drop_outermost_qualifier_loop(ParentModuleName, ChildName,
|
|
DroppedQualifierSymName).
|
|
|
|
:- pred drop_outermost_qualifier_loop(module_name::in, string::in,
|
|
module_name::out) is det.
|
|
|
|
drop_outermost_qualifier_loop(ParentModuleName, ChildName,
|
|
DroppedQualifierSymName) :-
|
|
(
|
|
ParentModuleName = unqualified(_ParentName),
|
|
DroppedQualifierSymName = unqualified(ChildName)
|
|
;
|
|
ParentModuleName = qualified(GrandParentModuleName, ParentName),
|
|
drop_outermost_qualifier_loop(GrandParentModuleName, ParentName,
|
|
DroppedQualifierGrandParentModuleName),
|
|
DroppedQualifierSymName =
|
|
qualified(DroppedQualifierGrandParentModuleName, ChildName)
|
|
).
|
|
|
|
%------------%
|
|
|
|
:- 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.
|
|
% XXX _NumErrors
|
|
write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !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(severity_error, phase_read_files,
|
|
[error_msg(no, treat_as_first, 0, [always(Pieces)])]),
|
|
% XXX _NumErrors
|
|
write_error_spec(Spec, Globals, 0, _NumWarnings, 0, _NumErrors, !IO),
|
|
MaybeModuleName = no
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module parse_tree.find_module.
|
|
%---------------------------------------------------------------------------%
|