[m-rev.] for review: fix module search bug

Simon Taylor staylr at gmail.com
Mon May 14 16:19:27 AEST 2007



Estimated hours taken: 2
Branches: main

compiler/modules.m:
compiler/prog_io.m:
	Fix a bug which caused the presence of a file named write.m
	in the current directory to stop the compiler finding a module
	bit_buffer.write in a library.  The test case for this is
	tests/hard_coded/bit_buffer_test.m.

	`mmc --make' already handled this correctly.


Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.422
diff -u -u -r1.422 modules.m
--- compiler/modules.m	7 May 2007 05:21:34 -0000	1.422
+++ compiler/modules.m	13 May 2007 11:05:12 -0000
@@ -3919,7 +3919,8 @@
         !:OptDeps, !:TransOptDeps, !IO),
     (
         BuildOptFiles = yes,
-        search_for_module_source(IntermodDirs, Dep, Result1, !IO),
+        search_for_module_source(IntermodDirs, IntermodDirs,
+            Dep, Result1, !IO),
         (
             Result1 = ok(_),
             !:OptDeps = [Dep | !.OptDeps],
@@ -3973,7 +3974,8 @@
     get_opt_deps(BuildOptFiles, Deps, IntermodDirs, Suffix, !:OptDeps, !IO),
     (
         BuildOptFiles = yes,
-        search_for_module_source(IntermodDirs, Dep, Result1, !IO),
+        search_for_module_source(IntermodDirs, IntermodDirs,
+            Dep, Result1, !IO),
         (
             Result1 = ok(_),
             !:OptDeps = [Dep | !.OptDeps],
@@ -6395,18 +6397,23 @@
     maybe_write_string(VeryVerbose, "'... ", !IO),
     maybe_flush_output(VeryVerbose, !IO),
 
+    globals.io_lookup_accumulating_option(search_directories,
+        InterfaceSearchDirs, !IO),
     (
         Search = yes,
-        globals.io_lookup_accumulating_option(search_directories, SearchDirs,
-            !IO)
+        SearchDirs = InterfaceSearchDirs
     ;
         Search = no,
         SearchDirs = [dir.this_directory]
     ),
     ( Extension = ".m" ->
         % For `.m' files we need to deal with the case where
-        % the module name does not match the file name.
-        OpenFile = search_for_module_source(SearchDirs, ModuleName)
+        % the module name does not match the file name, or where
+        % a partial match occurs in the current directory but the
+        % full match occurs in a search directory.
+        %
+        OpenFile = search_for_module_source(SearchDirs,
+                        InterfaceSearchDirs, ModuleName)
     ;
         OpenFile = search_for_file(SearchDirs, FileName0)
     ),
Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.281
diff -u -u -r1.281 prog_io.m
--- compiler/prog_io.m	19 Jan 2007 07:04:27 -0000	1.281
+++ compiler/prog_io.m	14 May 2007 00:07:16 -0000
@@ -145,14 +145,17 @@
 :- pred search_for_file_returning_dir(list(dir_name)::in, file_name::in,
     maybe_error(dir_name)::out, io::di, io::uo) is det.
 
-    % search_for_module_source(Dirs, ModuleName, FoundSourceFileName, !IO):
+    % search_for_module_source(Dirs, InterfaceDirs, ModuleName,
+    %   FoundSourceFileName, !IO):
     %
     % Look for the source for ModuleName in Dirs. This will also search for
-    % files matching partially qualified versions of ModuleName. For example,
-    % module foo.bar.baz can be found in foo.bar.m, bar.baz.m or bar.m.
+    % files matching partially qualified versions of ModuleName, but only if
+    % a more qualified `.m' or `.int' file doesn't exist in InterfaceDirs.
+    % 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(list(dir_name)::in, module_name::in,
-    maybe_error(file_name)::out, io::di, io::uo) is det.
+:- pred search_for_module_source(list(dir_name)::in, list(dir_name)::in,
+    module_name::in, maybe_error(file_name)::out, io::di, io::uo) is det.
 
     % Read the first item from the given file to find the module name.
     %
@@ -432,14 +435,92 @@
         search_for_file_returning_dir(Dirs, AllDirs, FileName, R, !IO)
     ).
 
-search_for_module_source(Dirs, ModuleName, MaybeFileName, !IO) :-
-    search_for_module_source(Dirs, ModuleName, ModuleName, MaybeFileName, !IO).
+search_for_module_source(Dirs, InterfaceDirs,
+        ModuleName, MaybeFileName, !IO) :-
+    search_for_module_source_2(Dirs, ModuleName, ModuleName,
+        MaybeFileName0, !IO),
+    (
+        MaybeFileName0 = ok(SourceFileName),
+        ( 
+            string.remove_suffix(dir.basename(SourceFileName),
+                ".m", SourceFileBaseName),
+            file_name_to_module_name(SourceFileBaseName, SourceFileModuleName),
+            ModuleName \= SourceFileModuleName
+        ->
+            % 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.
+            %
+            io.input_stream(SourceStream, !IO),
+            search_for_module_source_2(InterfaceDirs, ModuleName,
+                ModuleName, MaybeFileName2, !IO),
+            ( MaybeFileName2 = ok(_) ->
+                io.seen(!IO)
+            ;
+                true
+            ),
+            (
+                MaybeFileName2 = ok(SourceFileName2),
+                SourceFileName2 \= SourceFileName,
+                string.remove_suffix(dir.basename(SourceFileName2), ".m",
+                    SourceFileBaseName2),
+                file_name_to_module_name(SourceFileBaseName2,
+                    SourceFileModuleName2),
+                match_sym_name(SourceFileModuleName, SourceFileModuleName2)
+            ->
+                io.close_input(SourceStream, !IO),
+                MaybeFileName = error(find_source_error(ModuleName,
+                                    Dirs, yes(SourceFileName2)))
+            ;
+                module_name_to_file_name(ModuleName, ".int", no, IntFile, !IO),
+                search_for_file_returning_dir(InterfaceDirs, IntFile,
+                    MaybeIntDir, !IO),
+                ( MaybeIntDir = ok(_) ->
+                    io.seen(!IO)
+                ;
+                    true
+                ),
+                (
+                    MaybeIntDir = ok(IntDir),
+                    IntDir \= dir.this_directory
+                ->
+                    io.close_input(SourceStream, !IO),
+                    MaybeFileName = error(find_source_error(ModuleName,
+                                        Dirs, yes(IntDir/IntFile)))
+                ;
+                    io.set_input_stream(SourceStream, _, !IO),
+                    MaybeFileName = MaybeFileName0
+                )
+            )
+        ;
+            MaybeFileName = MaybeFileName0
+        )
+    ;
+        MaybeFileName0 = error(_),
+        MaybeFileName = MaybeFileName0
+    ).
 
-:- pred search_for_module_source(list(dir_name)::in,
-    module_name::in, module_name::in, maybe_error(file_name)::out,
-    io::di, io::uo) is det.
+:- 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(", ", Dirs),
+    (
+        MaybeBetterMatch = no, Msg = Msg0
+    ;
+        MaybeBetterMatch = yes(BetterMatchFile),
+        Msg = Msg0 ++ ", but found " ++ BetterMatchFile
+                    ++ " in interface search path"
+    ).
+
+:- pred search_for_module_source_2(list(dir_name)::in, module_name::in,
+    module_name::in, maybe_error(file_name)::out, io::di, io::uo) is det.
 
-search_for_module_source(Dirs, ModuleName, PartialModuleName, Result, !IO) :-
+search_for_module_source_2(Dirs, ModuleName, PartialModuleName, Result, !IO) :-
     module_name_to_file_name(PartialModuleName, ".m", no, FileName, !IO),
     search_for_file(Dirs, FileName, Result0, !IO),
     (
@@ -450,12 +531,10 @@
         (
             PartialModuleName1 = drop_one_qualifier(PartialModuleName)
         ->
-            search_for_module_source(Dirs, ModuleName, PartialModuleName1,
+            search_for_module_source_2(Dirs, ModuleName, PartialModuleName1,
                 Result, !IO)
         ;
-            ModuleNameStr = sym_name_to_string(ModuleName),
-            Result = error("can't find source for module `" ++
-                ModuleNameStr ++ "'")
+            Result = error(find_source_error(ModuleName, Dirs, no))
         )
     ).
 
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list