diff --git a/compiler/error_spec.m b/compiler/error_spec.m index 5b3e32b5e..b64e9e2f7 100644 --- a/compiler/error_spec.m +++ b/compiler/error_spec.m @@ -63,11 +63,6 @@ % (and equivalent in every respect to) error_spec(Id, Severity, Phase, % error_msg(maybe.no, treat_based_on_posn, 0, [always(Pieces)])). % -% conditional_spec(Id, Option, MatchValue, Severity, Phase, Msgs) is intended -% to represent the error specification given by its last three fields -% *iff* Option has the value MatchValue. If Option is *not* MatchValue, -% it asks for nothing to be printed, and for the exit status to be left alone. -% % The Id field, which is present in all these alternatives, is totally % ignored when printing error_specs. Its job is something completely different: % helping developers track down where in the source code each error_spec @@ -107,17 +102,6 @@ es_phase :: spec_phase, es_msgs :: list(error_msg) ). -% If we ever want to both -% - print an error_spec just after it is generated, and -% - also return it to inform decisions about the presence of errors, -% we can print the actual message and return it wrapped up in this -% new function symbol, which preserves its severity (for decisions) -% and its text (which may be helpful when debugging the code that -% makes those decision). -% -% ; already_printed_spec( -% ap_spec :: std_error_spec -% ). % An error_spec that is *intended* to contain a warning, % XXX We can now enforce that intention using subtypes. @@ -136,9 +120,11 @@ % When they succeed, they return some result(s); when they don't, % they return one or more errors. % -:- type maybe_error_specs(T) - ---> ok_no_spec(T) - ; error_specs(error_spec, list(error_spec)). + % This type is not (yet) used. + % +% :- type maybe_error_specs(T) +% ---> ok_no_spec(T) +% ; error_specs(error_spec, list(error_spec)). %---------------------------------------------------------------------------% @@ -147,10 +133,6 @@ % Always print the spec, and % always set the exit status to indicate an error. - ; severity_error(option) - % Print the spec and set the exit status to indicate an error - % only if this option is enabled. - ; severity_warning(option) % Print the spec only if this option is enabled. % Set the exit status to indicate an error only if diff --git a/compiler/error_util.m b/compiler/error_util.m index a92103969..4eb4177ee 100644 --- a/compiler/error_util.m +++ b/compiler/error_util.m @@ -56,6 +56,8 @@ % :- pred actual_spec_severity_is_error(globals::in, error_spec::in) is semidet. +%---------------------------------------------------------------------------% + % Compute the worst actual severity (if any) occurring in a list of % error_specs. % @@ -89,6 +91,39 @@ :- func contains_errors_or_warnings_treated_as_errors_opt_table(option_table, list(error_spec)) = bool. +%---------------------------------------------------------------------------% + +:- type maybe_written_spec + ---> to_be_written_spec(error_spec) + ; already_written_spec(std_error_spec). + % Sometimes we want to both + % + % - print an error_spec just after it is generated, and + % - also return it to inform decisions about the presence + % of errors. + % + % To prevent the caller from writing out a duplicate copy + % of the error_spec, we can return it wrapped up + % in this function symbol, which + % + % - preserves its severity (for decisions), + % - preserves its text (which may be helpful when debugging + % the code that makes those decision), + % - but which write_error_spec.m knows to ignore. + % + % An alternative design would create a new type, called maybe + % gen_error_spec, which contains error_spec's three function + % symbols *and* already_printed_spec, and make error_spec + % a subtype of this new type. This design works (I, zs, have + % tested it), but it makes references to error_spec's three + % function symbols ambiguous, since their type can be either + % error_spec or gen_error_spec. In most cases, the surrounding + % context resolves the ambiguity, but in some cases, it does not. + +:- func maybe_written_spec_to_spec(maybe_written_spec) = error_spec. +:- func maybe_written_specs_to_specs(list(maybe_written_spec)) + = list(error_spec). + %---------------------------------------------------------------------------% % Given a function that constructs lists of format pieces when given @@ -232,16 +267,6 @@ severity_to_maybe_actual_severity(OptionTable, Severity, ( Severity = severity_error, MaybeActualSeverity = yes(actual_severity_error) - ; - Severity = severity_error(Option), - getopt.lookup_bool_option(OptionTable, Option, OptionValue), - ( - OptionValue = yes, - MaybeActualSeverity = yes(actual_severity_error) - ; - OptionValue = no, - MaybeActualSeverity = no - ) ; Severity = severity_warning(Option), getopt.lookup_bool_option(OptionTable, Option, OptionValue), @@ -411,6 +436,19 @@ contains_errors_or_warnings_treated_as_errors_opt_table(OptionTable, Specs) %---------------------------------------------------------------------------% +maybe_written_spec_to_spec(MaybeWrittenSpec) = Spec :- + ( + MaybeWrittenSpec = to_be_written_spec(Spec) + ; + MaybeWrittenSpec = already_written_spec(StdSpec), + Spec = coerce(StdSpec) + ). + +maybe_written_specs_to_specs(MaybeWrittenSpecs) = Specs :- + Specs = list.map(maybe_written_spec_to_spec, MaybeWrittenSpecs). + +%---------------------------------------------------------------------------% + construct_sorted_line_pieces(MakeItemPiecesFunc, Items, Pieces) :- ( Items = [], diff --git a/compiler/parse_item.m b/compiler/parse_item.m index 360d104b2..cd92fba24 100644 --- a/compiler/parse_item.m +++ b/compiler/parse_item.m @@ -109,8 +109,6 @@ :- implementation. -:- import_module libs. -:- import_module libs.options. :- import_module mdbcomp.prim_data. :- import_module parse_tree.parse_class. :- import_module parse_tree.parse_dcg_goal. @@ -861,8 +859,8 @@ parse_version_numbers_marker(ModuleName, Functor, ArgTerms, words("was created by an obsolete compiler,")] ++ color_as_incorrect([words("so it must be rebuilt.")]) ++ [nl], - Severity = severity_error(warn_smart_recompilation), - Spec = spec($pred, Severity, phase_t2pt, Context, Pieces), + Spec = spec($pred, severity_error, phase_t2pt, + Context, Pieces), MaybeIOM = ok1(iom_handled_error([Spec])) ) else diff --git a/compiler/write_error_spec.m b/compiler/write_error_spec.m index 63311d370..1a4bf9534 100644 --- a/compiler/write_error_spec.m +++ b/compiler/write_error_spec.m @@ -36,6 +36,7 @@ :- import_module libs.indent. :- import_module libs.options. :- import_module parse_tree.error_spec. +:- import_module parse_tree.error_util. :- import_module parse_tree.prog_data. :- import_module bool. @@ -43,6 +44,17 @@ :- import_module list. :- import_module maybe. +%---------------------------------------------------------------------------% + + % write_not_yet_written_specs(Stream, Globals, !MaybeWrittenSpecs, !IO): + % + % Write out any to_be_written specs in !.MaybeWrittenSpecs, and + % add them back to !:MaybeWrittenSpecs as already_written specs. + % +:- pred write_not_yet_written_specs(io.text_output_stream::in, globals::in, + list(maybe_written_spec)::in, list(maybe_written_spec)::out, + io::di, io::uo) is det. + %---------------------------------------------------------------------------% % write_error_spec(Stream, Globals, Spec, !IO): @@ -224,7 +236,6 @@ :- import_module mdbcomp.prim_data. :- import_module mdbcomp.sym_name. :- import_module parse_tree.error_sort. -:- import_module parse_tree.error_util. :- import_module parse_tree.maybe_error. :- import_module parse_tree.parse_tree_out_cons_id. :- import_module parse_tree.parse_tree_out_misc. @@ -245,6 +256,33 @@ :- import_module term_context. :- import_module uint. +%---------------------------------------------------------------------------% + +write_not_yet_written_specs(Stream, Globals, !MaybeWrittenSpecs, !IO) :- + categorize_maybe_written_specs(!.MaybeWrittenSpecs, + [], AlreadyWritten0, [], ToBeWritten0), + write_error_specs_return_std(Stream, Globals, + ToBeWritten0, NowWrittenStd, !IO), + NowWritten = list.map((func(S) = already_written_spec(S)), NowWrittenStd), + !:MaybeWrittenSpecs = AlreadyWritten0 ++ NowWritten. + +:- pred categorize_maybe_written_specs(list(maybe_written_spec)::in, + list(maybe_written_spec)::in, list(maybe_written_spec)::out, + list(error_spec)::in, list(error_spec)::out) is det. + +categorize_maybe_written_specs([], !AlreadyWritten, !ToBeWritten). +categorize_maybe_written_specs([MaybeWritten | MaybeWrittens], + !AlreadyWritten, !ToBeWritten) :- + ( + MaybeWritten = already_written_spec(_StdSpec), + !:AlreadyWritten = [MaybeWritten | !.AlreadyWritten] + ; + MaybeWritten = to_be_written_spec(Spec), + !:ToBeWritten = [Spec | !.ToBeWritten] + ), + categorize_maybe_written_specs(MaybeWrittens, + !AlreadyWritten, !ToBeWritten). + %---------------------------------------------------------------------------% % % We keep a record of the set of already-printed verbose_once components @@ -256,24 +294,21 @@ % all its occrrences are generated in one pass. For pretty much all our passes, % all the error messages generated by the pass are printed by a single % call to write_error_specs. This means that while in theory, it is possible -% for verbose_once message to be printed by each of several invocations +% for a verbose_once message to be printed by each of several invocations % of write_error_specs, in practice it won't happen. write_error_spec(Stream, Globals, Spec, !IO) :- - standardize_error_specs([Spec], StdSpecs), - ( - StdSpecs = [] - ; - StdSpecs = [_ | _], - globals.get_options(Globals, OptionTable), - globals.get_limit_error_contexts_map(Globals, LimitErrorContextsMap), - sort_and_write_error_specs(Stream, OptionTable, LimitErrorContextsMap, - StdSpecs, !IO) - ). + write_error_specs_return_std(Stream, Globals, [Spec], _StdSpecs, !IO). + +write_error_specs(Stream, Globals, Specs0, !IO) :- + write_error_specs_return_std(Stream, Globals, Specs0, _StdSpecs, !IO). %---------------------% -write_error_specs(Stream, Globals, Specs0, !IO) :- +:- pred write_error_specs_return_std(io.text_output_stream::in, globals::in, + list(error_spec)::in, list(std_error_spec)::out, io::di, io::uo) is det. + +write_error_specs_return_std(Stream, Globals, Specs0, StdSpecs, !IO) :- standardize_error_specs(Specs0, StdSpecs), globals.get_options(Globals, OptionTable), globals.get_limit_error_contexts_map(Globals, LimitErrorContextsMap),