Files
mercury/compiler/error_util.m
Zoltan Somogyi 307b1dc148 Split up error_util.m into five modules.
compiler/error_spec.m:
    This new module contains the part of the old error_util.m that defines
    the error_spec type, and some functions that can help construct pieces
    of error_specs. Most modules of the compiler that deal with errors
    will need to import only this part of the old error_util.m.

    This change also renames the format_component type to format_piece,
    which matches our long-standing naming convention for variables containing
    (lists of) values of this type.

compiler/write_error_spec.m:
    This new module contains the part of the old error_util.m that
    writes out error specs, and converts them to strings.

    This diff marks as obsolete the versions of predicates that
    write out error specs to the current output stream, without
    *explicitly* specifying the intended stream.

compiler/error_sort.m:
    This new module contains the part of the old error_util.m that
    sorts lists of error specs and error msgs.

compiler/error_type_util.m:
    This new module contains the part of the old error_util.m that
    convert types to format_pieces that generate readable output.

compiler/parse_tree.m:
compiler/notes/compiler_design.html:
    Include and document the new modules.

compiler/error_util.m:
    The code remaining in the original error_util.m consists of
    general utility predicates and functions that don't fit into
    any of the modules above.

    Delete an unneeded pair of I/O states from the argument list
    of a predicate.

compiler/file_util.m:
    Move the unable_to_open_file predicate here from error_util.m,
    since it belongs here. Mark another predicate that writes
    to the current output stream as obsolete.

compiler/hlds_error_util.m:
    Mark two predicates that wrote out error_spec to the current output
    stream as obsolete, and add versions that take an explicit output stream.

compiler/Mercury.options:
    Compile the modules that call the newly obsoleted predicates
    with --no-warn-obsolete, for the time being.

compiler/*.m:
    Conform to the changes above, mostly by updating import_module
    declarations, and renaming format_component to format_piece.
2022-10-12 20:50:16 +11:00

429 lines
15 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 1997-2012 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% File: error_util.m.
% Main author: zs.
%
% This module contains utility predicates and functions operating on
% error_specs.
%
%---------------------------------------------------------------------------%
:- module parse_tree.error_util.
:- interface.
:- import_module libs.
:- import_module libs.globals.
:- import_module parse_tree.error_spec.
:- import_module bool.
:- import_module list.
:- import_module maybe.
%---------------------------------------------------------------------------%
% Would trying to print the given spec result in any output?
% The answer can be "no" if all parts of the error_spec are
% under a condition that happens to be false.
%
:- pred does_spec_print_anything(globals::in, error_spec::in) is semidet.
%---------------------------------------------------------------------------%
% Return the worst of two actual severities.
%
:- func worst_severity(actual_severity, actual_severity)
= actual_severity.
% Compute the actual severity of a message with the given severity
% (if it actually prints anything).
%
:- func actual_error_severity(globals, error_severity)
= maybe(actual_severity).
% Compute the actual severity of an error_spec
% (if it actually prints anything).
%
:- func actual_spec_severity(globals, error_spec) = maybe(actual_severity).
% Compute the worst actual severity (if any) occurring in a list of
% error_specs.
%
:- func worst_severity_in_specs(globals, list(error_spec))
= maybe(actual_severity).
% Return `yes' if the given list contains error_specs whose actual severity
% is actual_severity_error.
%
:- func contains_errors(globals, list(error_spec)) = bool.
% Return `yes' if the given list contains error_specs whose actual severity
% is actual_severity_error or actual_severity_warning.
%
:- func contains_errors_and_or_warnings(globals, list(error_spec)) = bool.
% If --halt-at-warn is not set, then return `yes' if the given list
% contains error_specs whose actual severity is actual_severity_error.
%
% If --halt-at-warn is set, then return `yes' if the given list
% contains error_specs whose actual severity is either
% actual_severity_error or actual_severity_warning.
%
:- func contains_errors_or_warnings_treated_as_errors(globals,
list(error_spec)) = bool.
%---------------------------------------------------------------------------%
% Delete all the given error_specs, which are supposed to have been
% gathered during the process that generates the contents of an interface
% file, if halt_at_invalid_interface is not set.
%
% Even if it is set, delete any conditional error specs whose conditions
% are false.
%
:- pred filter_interface_generation_specs(globals::in,
list(error_spec)::in, list(error_spec)::out) is det.
%---------------------------------------------------------------------------%
%
% The error_spec_accumulator type can be used to accumulate errors for
% multiple modes of a predicate. accumulate_error_specs_for_proc will
% eliminate warnings that should only be reported if they occur in every mode,
% but don't occur in every mode.
:- type error_spec_accumulator.
:- func init_error_spec_accumulator = error_spec_accumulator.
:- pred accumulate_error_specs_for_proc(list(error_spec)::in,
error_spec_accumulator::in, error_spec_accumulator::out) is det.
:- func error_spec_accumulator_to_list(error_spec_accumulator) =
list(error_spec).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module libs.options.
:- import_module pair.
:- import_module set.
:- import_module term_context.
%---------------------------------------------------------------------------%
does_spec_print_anything(Globals, Spec) :-
does_spec_print_anything_2(Globals, Spec) = yes.
:- func does_spec_print_anything_2(globals, error_spec) = bool.
does_spec_print_anything_2(Globals, Spec) = Prints :-
(
( Spec = simplest_spec(_, _, _, _, _)
; Spec = simplest_no_context_spec(_, _, _, _)
),
Prints = yes
;
Spec = error_spec(_, _, _, Msgs),
PrintsList = list.map(does_msg_print_anything(Globals), Msgs),
bool.or_list(PrintsList, Prints)
;
Spec = conditional_spec(_, Option, MatchValue, _, _, Msgs),
globals.lookup_bool_option(Globals, Option, OptionValue),
( if OptionValue = MatchValue then
PrintsList = list.map(does_msg_print_anything(Globals), Msgs),
bool.or_list(PrintsList, Prints)
else
Prints = no
)
).
:- func does_msg_print_anything(globals, error_msg) = bool.
does_msg_print_anything(Globals, Msg) = Prints :-
(
( Msg = simplest_msg(_, _)
; Msg = simplest_no_context_msg(_)
),
Prints = yes
;
( Msg = simple_msg(_, MsgComponents)
; Msg = error_msg(_, _, _, MsgComponents)
),
PrintsList = list.map(does_msg_component_print_anything(Globals),
MsgComponents),
bool.or_list(PrintsList, Prints)
).
:- func does_msg_component_print_anything(globals, error_msg_component) = bool.
does_msg_component_print_anything(Globals, MsgComponent) = Prints :-
(
( MsgComponent = always(_)
; MsgComponent = verbose_only(_, _)
; MsgComponent = verbose_and_nonverbose(_, _)
; MsgComponent = print_anything(_)
),
Prints = yes
;
MsgComponent = option_is_set(Option, MatchValue, MsgComponents),
globals.lookup_bool_option(Globals, Option, OptionValue),
( if OptionValue = MatchValue then
PrintsList = list.map(does_msg_component_print_anything(Globals),
MsgComponents),
bool.or_list(PrintsList, Prints)
else
Prints = no
)
).
%---------------------------------------------------------------------------%
worst_severity(actual_severity_error, actual_severity_error) =
actual_severity_error.
worst_severity(actual_severity_error, actual_severity_warning) =
actual_severity_error.
worst_severity(actual_severity_error, actual_severity_informational) =
actual_severity_error.
worst_severity(actual_severity_warning, actual_severity_error) =
actual_severity_error.
worst_severity(actual_severity_warning, actual_severity_warning) =
actual_severity_warning.
worst_severity(actual_severity_warning, actual_severity_informational) =
actual_severity_warning.
worst_severity(actual_severity_informational, actual_severity_error) =
actual_severity_error.
worst_severity(actual_severity_informational, actual_severity_warning) =
actual_severity_warning.
worst_severity(actual_severity_informational, actual_severity_informational) =
actual_severity_informational.
actual_error_severity(Globals, Severity) = MaybeActual :-
(
Severity = severity_error,
MaybeActual = yes(actual_severity_error)
;
Severity = severity_warning,
MaybeActual = yes(actual_severity_warning)
;
Severity = severity_informational,
MaybeActual = yes(actual_severity_informational)
;
Severity = severity_conditional(Option, MatchValue,
Match, MaybeNoMatch),
globals.lookup_bool_option(Globals, Option, Value),
( if Value = MatchValue then
MaybeActual = actual_error_severity(Globals, Match)
else
(
MaybeNoMatch = no,
MaybeActual = no
;
MaybeNoMatch = yes(NoMatch),
MaybeActual = actual_error_severity(Globals, NoMatch)
)
)
).
actual_spec_severity(Globals, Spec) = MaybeSeverity :-
(
( Spec = error_spec(_, Severity, _, _)
; Spec = simplest_spec(_, Severity, _, _, _)
; Spec = simplest_no_context_spec(_, Severity, _, _)
),
MaybeSeverity = actual_error_severity(Globals, Severity)
;
Spec = conditional_spec(_, Option, MatchValue, Severity, _, _),
globals.lookup_bool_option(Globals, Option, OptionValue),
( if OptionValue = MatchValue then
MaybeSeverity = actual_error_severity(Globals, Severity)
else
MaybeSeverity = no
)
).
worst_severity_in_specs(Globals, Specs) = MaybeWorst :-
worst_severity_in_specs_2(Globals, Specs, no, MaybeWorst).
:- pred worst_severity_in_specs_2(globals::in, list(error_spec)::in,
maybe(actual_severity)::in, maybe(actual_severity)::out) is det.
worst_severity_in_specs_2(_Globals, [], !MaybeWorst).
worst_severity_in_specs_2(Globals, [Spec | Specs], !MaybeWorst) :-
MaybeThis = actual_spec_severity(Globals, Spec),
(
!.MaybeWorst = no,
!:MaybeWorst = MaybeThis
;
!.MaybeWorst = yes(Worst),
(
MaybeThis = no
;
MaybeThis = yes(This),
!:MaybeWorst = yes(worst_severity(Worst, This))
)
),
worst_severity_in_specs_2(Globals, Specs, !MaybeWorst).
contains_errors(Globals, Specs) = Errors :-
MaybeWorstActual = worst_severity_in_specs(Globals, Specs),
(
MaybeWorstActual = no,
Errors = no
;
MaybeWorstActual = yes(WorstActual),
(
WorstActual = actual_severity_error,
Errors = yes
;
( WorstActual = actual_severity_warning
; WorstActual = actual_severity_informational
),
Errors = no
)
).
contains_errors_and_or_warnings(Globals, Specs) = ErrorsOrWarnings :-
MaybeWorstActual = worst_severity_in_specs(Globals, Specs),
(
MaybeWorstActual = no,
ErrorsOrWarnings = no
;
MaybeWorstActual = yes(WorstActual),
(
( WorstActual = actual_severity_error
; WorstActual = actual_severity_warning
),
ErrorsOrWarnings = yes
;
WorstActual = actual_severity_informational,
ErrorsOrWarnings = no
)
).
contains_errors_or_warnings_treated_as_errors(Globals, Specs) = Halt :-
MaybeWorstActual = worst_severity_in_specs(Globals, Specs),
(
MaybeWorstActual = no,
Halt = no
;
MaybeWorstActual = yes(WorstActual),
(
WorstActual = actual_severity_error,
Halt = yes
;
WorstActual = actual_severity_warning,
globals.lookup_bool_option(Globals, halt_at_warn, HaltAtWarn),
(
HaltAtWarn = yes,
Halt = yes
;
HaltAtWarn = no,
Halt = no
)
;
WorstActual = actual_severity_informational,
Halt = no
)
).
%---------------------------------------------------------------------------%
filter_interface_generation_specs(Globals, Specs, SpecsToPrint) :-
globals.lookup_bool_option(Globals,
halt_at_invalid_interface, HaltInvalidInterface),
(
HaltInvalidInterface = yes,
list.filter(does_spec_print_anything(Globals), Specs, SpecsToPrint)
;
HaltInvalidInterface = no,
SpecsToPrint = []
).
%---------------------------------------------------------------------------%
:- type error_spec_accumulator == maybe(pair(set(error_spec))).
init_error_spec_accumulator = no.
accumulate_error_specs_for_proc(ProcSpecs, !MaybeSpecs) :-
list.filter(
( pred(Spec::in) is semidet :-
Phase = project_spec_phase(Spec),
ModeReportControl = get_maybe_mode_report_control(Phase),
ModeReportControl = yes(report_only_if_in_all_modes)
), ProcSpecs, ProcAllModeSpecs, ProcAnyModeSpecs),
ProcAnyModeSpecSet = set.list_to_set(ProcAnyModeSpecs),
ProcAllModeSpecSet = set.list_to_set(ProcAllModeSpecs),
(
!.MaybeSpecs = yes(AnyModeSpecSet0 - AllModeSpecSet0),
set.union(AnyModeSpecSet0, ProcAnyModeSpecSet, AnyModeSpecSet),
set.intersect(AllModeSpecSet0, ProcAllModeSpecSet, AllModeSpecSet),
!:MaybeSpecs = yes(AnyModeSpecSet - AllModeSpecSet)
;
!.MaybeSpecs = no,
!:MaybeSpecs = yes(ProcAnyModeSpecSet - ProcAllModeSpecSet)
).
:- func project_spec_phase(error_spec) = error_phase.
project_spec_phase(Spec) = Phase :-
(
Spec = error_spec(_, _, Phase, _)
;
Spec = simplest_spec(_, _, Phase, _, _)
;
Spec = simplest_no_context_spec(_, _, Phase, _)
;
Spec = conditional_spec(_, _, _, _, Phase, _)
).
error_spec_accumulator_to_list(no) = [].
error_spec_accumulator_to_list(yes(AnyModeSpecSet - AllModeSpecSet)) =
set.to_sorted_list(set.union(AnyModeSpecSet, AllModeSpecSet)).
:- func get_maybe_mode_report_control(error_phase) =
maybe(mode_report_control).
get_maybe_mode_report_control(phase_options) = no.
get_maybe_mode_report_control(phase_check_libs) = no.
get_maybe_mode_report_control(phase_make_target) = no.
get_maybe_mode_report_control(phase_read_files) = no.
get_maybe_mode_report_control(phase_module_name) = no.
get_maybe_mode_report_control(phase_term_to_parse_tree) = no.
get_maybe_mode_report_control(phase_type_inst_mode_check) = no.
get_maybe_mode_report_control(phase_type_inst_mode_check_invalid_type) = no.
get_maybe_mode_report_control(phase_type_inst_mode_check_invalid_inst_mode)
= no.
get_maybe_mode_report_control(phase_type_repn) = no.
get_maybe_mode_report_control(phase_parse_tree_to_hlds) = no.
get_maybe_mode_report_control(phase_expand_types) = no.
get_maybe_mode_report_control(phase_type_check) = no.
get_maybe_mode_report_control(phase_inst_check) = no.
get_maybe_mode_report_control(phase_polymorphism) = no.
get_maybe_mode_report_control(phase_mode_check(Control)) = yes(Control).
get_maybe_mode_report_control(phase_purity_check) = no.
get_maybe_mode_report_control(phase_detism_check) = no.
get_maybe_mode_report_control(phase_fact_table_check) = no.
get_maybe_mode_report_control(phase_oisu_check) = no.
get_maybe_mode_report_control(phase_simplify(Control)) = yes(Control).
get_maybe_mode_report_control(phase_direct_arg_in_out) = no.
get_maybe_mode_report_control(phase_style) = no.
get_maybe_mode_report_control(phase_dead_code) = no.
get_maybe_mode_report_control(phase_termination_analysis) = no.
get_maybe_mode_report_control(phase_accumulator_intro) = no.
get_maybe_mode_report_control(phase_auto_parallelism) = no.
get_maybe_mode_report_control(phase_interface_gen) = no.
get_maybe_mode_report_control(phase_code_gen) = no.
%---------------------------------------------------------------------------%
:- end_module parse_tree.error_util.
%---------------------------------------------------------------------------%