Fix bugs in the handling of nested sub-modules with --smart-recompilation.

Estimated hours taken: 1
Branches: main

Fix bugs in the handling of nested sub-modules with --smart-recompilation.

compiler/recompilation_check.m:
	If an error occurs before the nested sub-modules of the top-level
	module are known, recompile all of the nested sub-modules.

	If there is a syntax error in a `.used' file, recompile all
	sub-modules. This makes the above change simpler, and is probably
	a good idea anyway -- all outputs from a compilation which produces
	output files containing syntax errors are suspect.

compiler/mercury_compile.m:
	When working out the list of sub-modules of the main module
	in a source file, use all the sub-modules, not just the ones
	that are being recompiled.

tests/recompilation/Mmakefile:
tests/recompilation/TESTS:
tests/recompilation/nested_module_2_r*:
	Test case.
This commit is contained in:
Simon Taylor
2001-10-24 05:56:41 +00:00
parent 7a0205f617
commit d26863ea86
11 changed files with 156 additions and 60 deletions

View File

@@ -721,11 +721,11 @@ process_module_2(FileOrModule, MaybeModulesToRecompile, ReadModules0,
list__member(SubModule,
ModulesToRecompile)
),
SubModuleList0, SubModuleList)
SubModuleList0, SubModuleListToCompile)
;
SubModuleList = SubModuleList0
SubModuleListToCompile = SubModuleList0
},
{ assoc_list__keys(SubModuleList, NestedSubModules0) },
{ assoc_list__keys(SubModuleList0, NestedSubModules0) },
{ list__delete_all(NestedSubModules0,
ModuleName, NestedSubModules) },
@@ -751,7 +751,7 @@ process_module_2(FileOrModule, MaybeModulesToRecompile, ReadModules0,
compile_all_submodules(FileName,
ModuleName - NestedSubModules,
MaybeTimestamp, ReadModules,
FindTimestampFiles, SubModuleList,
FindTimestampFiles, SubModuleListToCompile,
ModulesToLink),
globals__io_set_option(trace_stack_layout, bool(TSL)),
@@ -760,7 +760,7 @@ process_module_2(FileOrModule, MaybeModulesToRecompile, ReadModules0,
compile_all_submodules(FileName,
ModuleName - NestedSubModules,
MaybeTimestamp, ReadModules,
FindTimestampFiles, SubModuleList,
FindTimestampFiles, SubModuleListToCompile,
ModulesToLink)
)
).

View File

@@ -131,7 +131,7 @@ recompilation_check__should_recompile_2(IsSubModule, FindTargetFiles,
io__set_input_stream(OldInputStream, VersionStream),
io__close_input(VersionStream),
( { (all) = Info1 ^ modules_to_recompile } ->
( { (all) = Info4 ^ modules_to_recompile } ->
{ Info = Info4 }
;
{ Info5 = Info4 ^ is_inline_sub_module := yes },
@@ -158,6 +158,15 @@ recompilation_check__should_recompile_2(IsSubModule, FindTargetFiles,
recompilation_check__should_recompile_3(IsSubModule, FindTargetFiles,
Info0, Info) -->
%
% WARNING: any exceptions thrown before the sub_modules
% field is set in the recompilation_check_info must set
% the modules_to_recompile field to `all', or else
% the nested sub-modules will not be checked and necessary
% recompilations may be missed.
%
%
% Check that the format of the usage file is the current format.
%
@@ -179,11 +188,11 @@ recompilation_check__should_recompile_3(IsSubModule, FindTargetFiles,
[]
;
io__input_stream_name(UsageFileName),
{ throw(recompile_exception(
{ throw_syntax_error(
file_error(UsageFileName,
"invalid usage file version number in file `"
++ UsageFileName ++ "'."),
Info0)) }
Info0) }
),
%
@@ -213,45 +222,26 @@ recompilation_check__should_recompile_3(IsSubModule, FindTargetFiles,
->
record_read_file(ModuleName,
ModuleTimestamp ^ timestamp := NewTimestamp,
Items, Error, FileName, Info0, ErrorInfo),
Items, Error, FileName, Info0, RecompileInfo0),
RecompileInfo =
RecompileInfo0 ^ modules_to_recompile := (all),
throw(recompile_exception(module_changed(FileName),
ErrorInfo))
RecompileInfo))
;
( Error \= no_module_errors
; MaybeNewTimestamp = no
)
->
throw(recompile_exception(
throw_syntax_error(
file_error(FileName,
"error reading file `"
++ FileName ++ "'."),
Info0))
Info0)
;
true
}
),
%
% Check whether the output files are present and up-to-date.
%
FindTargetFiles(Info0 ^ module_name, TargetFiles),
list__foldl(
(pred(TargetFile::in, di, uo) is det -->
io__file_modification_time(TargetFile, TargetModTimeResult),
(
{ TargetModTimeResult = ok(TargetModTime) },
{ compare(TargetModTimeCompare,
time_t_to_timestamp(TargetModTime),
RecordedTimestamp) },
{ TargetModTimeCompare = (>) }
->
[]
;
{ Reason1 = output_file_not_up_to_date(TargetFile) },
{ throw(recompile_exception(Reason1, Info0)) }
)
), TargetFiles),
%
% Find out whether this module has any inline sub-modules.
%
@@ -268,11 +258,32 @@ recompilation_check__should_recompile_3(IsSubModule, FindTargetFiles,
->
Info1 = Info0 ^ sub_modules := SubModules
;
Reason2 = syntax_error(get_term_context(SubModulesTerm),
Reason1 = syntax_error(get_term_context(SubModulesTerm),
"error in sub_modules term"),
throw(recompile_exception(Reason2, Info0))
throw_syntax_error(Reason1, Info0)
},
%
% Check whether the output files are present and up-to-date.
%
FindTargetFiles(Info1 ^ module_name, TargetFiles),
list__foldl(
(pred(TargetFile::in, di, uo) is det -->
io__file_modification_time(TargetFile, TargetModTimeResult),
(
{ TargetModTimeResult = ok(TargetModTime) },
{ compare(TargetModTimeCompare,
time_t_to_timestamp(TargetModTime),
RecordedTimestamp) },
{ TargetModTimeCompare = (>) }
->
[]
;
{ Reason2 = output_file_not_up_to_date(TargetFile) },
{ throw(recompile_exception(Reason2, Info1)) }
)
), TargetFiles),
%
% Read in the used items, used for checking for
% ambiguities with new items.
@@ -299,7 +310,7 @@ recompilation_check__should_recompile_3(IsSubModule, FindTargetFiles,
;
Reason3 = syntax_error(get_term_context(UsedClassesTerm),
"error in used_typeclasses term"),
throw(recompile_exception(Reason3, Info2))
throw_syntax_error(Reason3, Info2)
},
check_imported_modules(Info3, Info).
@@ -332,7 +343,7 @@ parse_module_timestamp(Info, Term, ModuleName, ModuleTimestamp) :-
;
Reason = syntax_error(get_term_context(Term),
"error in module timestamp"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
%-----------------------------------------------------------------------------%
@@ -348,7 +359,7 @@ parse_used_items(Info, Term, UsedItems) :-
;
Reason = syntax_error(get_term_context(Term),
"error in used items"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_used_item_set(recompilation_check_info::in, term::in,
@@ -378,12 +389,12 @@ parse_used_item_set(Info, Term, UsedItems0, UsedItems) :-
string__append(
"error in used items: unknown item type :",
ItemTypeStr)),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
)
;
Reason = syntax_error(get_term_context(Term),
"error in used items"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_simple_item(recompilation_check_info::in, term::in,
@@ -403,7 +414,7 @@ parse_simple_item(Info, Term, Set0, Set) :-
;
Reason = syntax_error(get_term_context(Term),
"error in simple items"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_simple_item_match(recompilation_check_info::in, term::in,
@@ -427,7 +438,7 @@ parse_simple_item_match(Info, Term, Items0, Items) :-
;
Reason = syntax_error(get_term_context(Term),
"error in simple item match"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_pred_or_func_item(recompilation_check_info::in,
@@ -448,7 +459,7 @@ parse_pred_or_func_item(Info, Term, Set0, Set) :-
;
Reason = syntax_error(get_term_context(Term),
"error in pred or func match"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_pred_or_func_item_match(recompilation_check_info::in, term::in,
@@ -479,7 +490,7 @@ parse_pred_or_func_item_match(Info, Term, Items0, Items) :-
;
Reason = syntax_error(get_term_context(Term),
"error in pred or func match"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_functor_item(recompilation_check_info::in, term::in,
@@ -498,7 +509,7 @@ parse_functor_item(Info, Term, Set0, Set) :-
;
Reason = syntax_error(get_term_context(Term),
"error in functor matches"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_functor_arity_matches(recompilation_check_info::in, term::in,
@@ -517,7 +528,7 @@ parse_functor_arity_matches(Info, Term, Arity - MatchMap) :-
;
Reason = syntax_error(get_term_context(Term),
"error in functor match"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_functor_matches(recompilation_check_info::in, term::in,
@@ -537,7 +548,7 @@ parse_functor_matches(Info, Term, Map0, Map) :-
;
Reason = syntax_error(get_term_context(Term),
"error in functor match"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
:- pred parse_resolved_functor(recompilation_check_info::in, term::in,
@@ -571,7 +582,7 @@ parse_resolved_functor(Info, Term, Ctor) :-
;
Reason = syntax_error(get_term_context(Term),
"error in functor match"),
throw(recompile_exception(Reason, Info))
throw_syntax_error(Reason, Info)
).
%-----------------------------------------------------------------------------%
@@ -600,7 +611,7 @@ check_imported_modules(Info0, Info) -->
io__input_stream_name(FileName),
{ Reason = syntax_error(term__context(FileName, Line),
Message) },
{ throw(recompile_exception(Reason, Info0)) }
{ throw_syntax_error(Reason, Info0) }
;
{ TermResult = eof },
%
@@ -613,7 +624,7 @@ check_imported_modules(Info0, Info) -->
io__get_line_number(Line),
{ Reason = syntax_error(term__context(FileName, Line),
"unexpected end of file") },
{ throw(recompile_exception(Reason, Info0)) }
{ throw_syntax_error(Reason, Info0) }
).
:- pred check_imported_module(term::in, recompilation_check_info::in,
@@ -661,7 +672,8 @@ check_imported_module(Term, Info0, Info) -->
),
{
MaybeNewTimestamp = yes(NewTimestamp),
NewTimestamp \= RecordedTimestamp
NewTimestamp \= RecordedTimestamp,
Error = no_module_errors
->
( Recorded = no ->
record_read_file(ImportedModuleName,
@@ -687,10 +699,10 @@ check_imported_module(Term, Info0, Info) -->
;
Error \= no_module_errors
->
throw(recompile_exception(
throw_syntax_error(
file_error(FileName,
"error reading file `" ++ FileName ++ "'."),
Info0))
Info0)
;
Info = Info0
}.
@@ -710,9 +722,8 @@ check_module_used_items(ModuleName, NeedQualifier, OldTimestamp,
UsedItemsResult = ok(UsedVersionNumbers)
;
UsedItemsResult = error(Msg, ErrorTerm),
Reason = syntax_error(get_term_context(ErrorTerm),
Msg),
throw(recompile_exception(Reason, Info0))
Reason = syntax_error(get_term_context(ErrorTerm), Msg),
throw_syntax_error(Reason, Info0)
},
{ UsedVersionNumbers = version_numbers(UsedItemVersionNumbers,
@@ -1473,7 +1484,7 @@ read_term_check_for_error_or_eof(Info, Item, Term) -->
io__input_stream_name(FileName),
{ Reason = syntax_error(term__context(FileName, Line),
Message) },
{ throw(recompile_exception(Reason, Info)) }
{ throw_syntax_error(Reason, Info) }
;
{ TermResult = eof },
io__input_stream_name(FileName),
@@ -1482,7 +1493,7 @@ read_term_check_for_error_or_eof(Info, Item, Term) -->
string__append_list(
["unexpected end of file, expected ",
Item, "."])) },
{ throw(recompile_exception(Reason, Info)) }
{ throw_syntax_error(Reason, Info) }
).
:- func get_term_context(term) = term__context.
@@ -1494,4 +1505,14 @@ get_term_context(Term) =
term__context_init
).
:- pred throw_syntax_error(recompile_reason::in,
recompilation_check_info::in) is erroneous.
throw_syntax_error(Reason, Info) :-
% If there were syntax errors in a `.used' file written during
% a compilation, all outputs of that compilation are slightly
% suspect, so it's worth entirely redoing the compilation.
RecompileInfo = Info ^ modules_to_recompile := (all),
throw(recompile_exception(Reason, RecompileInfo)).
%-----------------------------------------------------------------------------%

View File

@@ -33,4 +33,7 @@ override EXTRA_MCFLAGS += --no-intermodule-optimization --smart-recompilation \
# for which no version numbers have been computed.
MCFLAGS-no_version_numbers_r_2 = --no-smart-recompilation
$(ints_subdir)nested_module_2_r_2.date: \
$(int0s_subdir)nested_module_2_r_2.int0
#-----------------------------------------------------------------------------#

View File

@@ -28,8 +28,8 @@ TESTS_SHOULD_SUCCEED="\
# nested sub-module are run twice, resulting in incorrect output in
# the `.err' file.
NO_PARALLEL_MAKE_TESTS="\
nested_module_r
"
nested_module_r \
nested_module_2_r"
TESTS_SHOULD_FAIL="\
add_type_re \

View File

@@ -0,0 +1,2 @@
Recompiling module `nested_module_2_r':
file `nested_module_2_r.used' not found.

View File

@@ -0,0 +1 @@
answer 1

View File

@@ -0,0 +1 @@
answer 2

View File

@@ -0,0 +1,14 @@
:- module nested_module_2_r.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is det.
:- implementation.
:- import_module nested_module_2_r_2.
main -->
main_2.

View File

@@ -0,0 +1,2 @@
Recompiling module `nested_module_2_r_2':
file `nested_module_2_r_2.m' has changed.

View File

@@ -0,0 +1,26 @@
:- module nested_module_2_r_2.
:- interface.
:- import_module io.
:- pred main_2(io__state::di, io__state::uo) is det.
:- implementation.
:- import_module nested_module_2_r_2__sub_module.
main_2 --> main_3.
:- module nested_module_2_r_2__sub_module.
:- interface.
:- import_module io.
:- pred main_3(io__state::di, io__state::uo) is det.
:- implementation.
main_3 --> io__write_string("answer 1\n").

View File

@@ -0,0 +1,26 @@
:- module nested_module_2_r_2.
:- interface.
:- import_module io.
:- pred main_2(io__state::di, io__state::uo) is det.
:- implementation.
:- import_module nested_module_2_r_2__sub_module.
main_2 --> main_3.
:- module nested_module_2_r_2__sub_module.
:- interface.
:- import_module io.
:- pred main_3(io__state::di, io__state::uo) is det.
:- implementation.
main_3 --> io__write_string("answer 2\n").