mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-15 05:44:58 +00:00
Estimated hours taken: 2 Branches: main compiler/mercury_compile.m: Bring this module up to date with our current coding standards. Use predmode declarations and state variable syntax where appropriate. Reorder predicate arguments where this is needed for the use of state variable syntax. Replace lambda expressions with explicitly named predicates where appropriate. Break up predicates that are excessively long and/or excessively deeply indented. Fix inconsistent indentation and wrap 80+ column lines. The only algorithmic change is the replacement of some calls to io__write with calls to predicates in error_util. compiler/error_util.m: Add a predicate for printing messages without context, for use by mercury_compile.m to report problems that are not specific to a single predicate, e.g. inconsistent options. Bring this module up to date with our coding standards. Use predmode declarations and state variable syntax where appropriate. compiler/check_typeclass.m: compiler/dnf.m: compiler/optimize.m: Reorder arguments of predicates exported to mercury_compile.m to allow the use of state variable syntax. compiler/globals.m: Wrap an 80+ column line.
584 lines
18 KiB
Mathematica
584 lines
18 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1997-2004 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.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% error_util.m
|
|
% Main author: zs.
|
|
%
|
|
% This module contains code that can be helpful in the formatting of
|
|
% error messages.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module hlds__error_util.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds__hlds_module.
|
|
:- import_module hlds__hlds_pred.
|
|
:- import_module parse_tree__prog_data.
|
|
|
|
:- import_module assoc_list, char, io, list, std_util.
|
|
|
|
% Given a context, a starting indentation level and a list of words,
|
|
% print an error message that looks like this:
|
|
%
|
|
% module.m:10: first line of error message blah blah blah
|
|
% module.m:10: second line of error message blah blah blah
|
|
% module.m:10: third line of error message blah blah blah
|
|
%
|
|
% The words will be packed into lines as tightly as possible,
|
|
% with spaces between each pair of words, subject to the constraints
|
|
% that every line starts with a context, followed by Indent+1 spaces
|
|
% on the first line and Indent+3 spaces on later lines, and that every
|
|
% line contains at most 79 characters (unless a long single word
|
|
% forces the line over this limit).
|
|
%
|
|
% The caller supplies the list of words to be printed in the form
|
|
% of a list of error message components. Each component may specify
|
|
% a string to printed exactly as it is, or it may specify a string
|
|
% containing a list of words, which may be broken at white space.
|
|
|
|
:- type format_component
|
|
---> fixed(string) % This string should appear in the output
|
|
% in one piece, as it is.
|
|
|
|
; words(string) % This string contains words separated by
|
|
% white space. The words should appear in
|
|
% the output in the given order, but the
|
|
% white space may be rearranged and line
|
|
% breaks may be inserted.
|
|
|
|
; nl. % Insert a line break if there has been text
|
|
% output since the last line break.
|
|
|
|
% Convert a list of strings into a list of format_components,
|
|
% suitable for displaying as an error message.
|
|
:- pred error_util__list_to_pieces(list(string)::in,
|
|
list(format_component)::out) is det.
|
|
|
|
% Convert a list of lists of format_components into a list of
|
|
% format_components separated by commas, with the last two
|
|
% elements separated by `and'.
|
|
:- func error_util__component_lists_to_pieces(list(list(format_component))) =
|
|
list(format_component).
|
|
|
|
% Display the given error message, without a context and with standard
|
|
% indentation.
|
|
:- pred write_error_pieces_plain(list(format_component)::in,
|
|
io::di, io::uo) is det.
|
|
|
|
% Display the given error message.
|
|
:- pred write_error_pieces(prog_context::in, int::in,
|
|
list(format_component)::in, io::di, io::uo) is det.
|
|
|
|
% Display the given error message, but indent the first line.
|
|
% This is useful when adding extra lines to an already
|
|
% displayed message.
|
|
:- pred write_error_pieces_not_first_line(prog_context::in, int::in,
|
|
list(format_component)::in, io::di, io::uo) is det.
|
|
|
|
:- pred write_error_pieces_maybe_with_context(maybe(prog_context)::in, int::in,
|
|
list(format_component)::in, io::di, io::uo) is det.
|
|
|
|
% Report a warning, and set the exit status to error if the
|
|
% --halt-at-warn option is set. This predicate does the same thing as
|
|
% prog_io_util__report_warning, except that it does a nicer job of
|
|
% displaying the warning message.
|
|
:- pred report_warning(prog_context::in, int::in, list(format_component)::in,
|
|
io::di, io::uo) is det.
|
|
|
|
% Predicates to convert a predicate names to strings.
|
|
|
|
:- pred error_util__describe_one_pred_name(module_info::in, pred_id::in,
|
|
string::out) is det.
|
|
|
|
:- pred error_util__describe_several_pred_names(module_info::in,
|
|
list(pred_id)::in, list(format_component)::out) is det.
|
|
|
|
:- pred error_util__describe_one_proc_name(module_info::in, pred_proc_id::in,
|
|
string::out) is det.
|
|
|
|
:- pred error_util__describe_several_proc_names(module_info::in,
|
|
list(pred_proc_id)::in, list(format_component)::out) is det.
|
|
|
|
:- pred error_util__describe_one_call_site(module_info::in,
|
|
pair(pred_proc_id, prog_context)::in, string::out) is det.
|
|
|
|
:- pred error_util__describe_several_call_sites(module_info::in,
|
|
assoc_list(pred_proc_id, prog_context)::in,
|
|
list(format_component)::out) is det.
|
|
|
|
:- func error_util__describe_sym_name(sym_name) = string.
|
|
|
|
:- func error_util__describe_sym_name_and_arity(sym_name_and_arity) = string.
|
|
|
|
:- func error_util__pred_or_func_to_string(pred_or_func) = string.
|
|
|
|
% Append a punctuation character to a message, avoiding unwanted
|
|
% line splitting between the message and the punctuation.
|
|
:- func error_util__append_punctuation(list(format_component), char) =
|
|
list(format_component).
|
|
|
|
% report_error_num_args(MaybePredOrFunc, Arity, CorrectArities).
|
|
%
|
|
% Write
|
|
% "wrong number of arguments (<Arity>; should be <CorrectArities>)",
|
|
% adjusting `Arity' and `CorrectArities' if `MaybePredOrFunc' is
|
|
% `yes(function)'.
|
|
:- pred report_error_num_args(maybe(pred_or_func)::in, int::in, list(int)::in,
|
|
io::di, io::uo) is det.
|
|
|
|
% sorry(ModuleName, Message)
|
|
% Call error/1 with a "Sorry, not implemented" message.
|
|
%
|
|
% Use this for features that should be implemented (or at
|
|
% least could be implemented).
|
|
%
|
|
:- pred sorry(string::in, string::in) is erroneous.
|
|
|
|
% unexpected(ModuleName, Message)
|
|
% Call error/1 with an "Unexpected" message.
|
|
%
|
|
% Use this to handle cases which are not expected to arise (i.e.
|
|
% bugs).
|
|
%
|
|
:- pred unexpected(string::in, string::in) is erroneous.
|
|
|
|
:- implementation.
|
|
|
|
:- import_module parse_tree__prog_out.
|
|
:- import_module parse_tree__prog_util.
|
|
:- import_module libs__globals.
|
|
:- import_module libs__options.
|
|
|
|
:- import_module bool, io, list, term, char, string, int, require.
|
|
|
|
error_util__list_to_pieces([], []).
|
|
error_util__list_to_pieces([Elem], [words(Elem)]).
|
|
error_util__list_to_pieces([Elem1, Elem2],
|
|
[fixed(Elem1), words("and"), fixed(Elem2)]).
|
|
error_util__list_to_pieces([Elem1, Elem2, Elem3 | Elems], Pieces) :-
|
|
string__append(Elem1, ",", Piece1),
|
|
error_util__list_to_pieces([Elem2, Elem3 | Elems], Pieces1),
|
|
Pieces = [fixed(Piece1) | Pieces1].
|
|
|
|
error_util__component_lists_to_pieces([]) = [].
|
|
error_util__component_lists_to_pieces([Components]) = Components.
|
|
error_util__component_lists_to_pieces([Components1, Components2]) =
|
|
list__condense([Components1, [words("and")], Components2]).
|
|
error_util__component_lists_to_pieces(
|
|
[Components1, Components2, Components3 | Components]) =
|
|
list__append(append_punctuation(Components1, ','),
|
|
error_util__component_lists_to_pieces(
|
|
[Components2, Components3 | Components])).
|
|
|
|
report_warning(Context, Indent, Components, !IO) :-
|
|
globals__io_lookup_bool_option(halt_at_warn, HaltAtWarn, !IO),
|
|
( HaltAtWarn = yes ->
|
|
io__set_exit_status(1, !IO)
|
|
;
|
|
true
|
|
),
|
|
write_error_pieces(Context, Indent, Components, !IO).
|
|
|
|
write_error_pieces_plain(Components, !IO) :-
|
|
write_error_pieces_maybe_with_context(yes, no, 0, Components, !IO).
|
|
|
|
write_error_pieces(Context, Indent, Components, !IO) :-
|
|
write_error_pieces_maybe_with_context(yes, yes(Context),
|
|
Indent, Components, !IO).
|
|
|
|
write_error_pieces_not_first_line(Context, Indent, Components, !IO) :-
|
|
write_error_pieces_maybe_with_context(no, yes(Context),
|
|
Indent, Components, !IO).
|
|
|
|
write_error_pieces_maybe_with_context(MaybeContext, Indent, Components, !IO) :-
|
|
write_error_pieces_maybe_with_context(yes, MaybeContext,
|
|
Indent, Components, !IO).
|
|
|
|
:- pred write_error_pieces_maybe_with_context(bool::in,
|
|
maybe(prog_context)::in, int::in, list(format_component)::in,
|
|
io::di, io::uo) is det.
|
|
|
|
write_error_pieces_maybe_with_context(IsFirst, MaybeContext,
|
|
Indent, Components, !IO) :-
|
|
(
|
|
% The fixed characters at the start of the line are:
|
|
% filename
|
|
% :
|
|
% line number (min 3 chars)
|
|
% :
|
|
% space
|
|
% indent
|
|
(
|
|
MaybeContext = yes(Context),
|
|
term__context_file(Context, FileName),
|
|
term__context_line(Context, LineNumber),
|
|
string__length(FileName, FileNameLength),
|
|
string__int_to_string(LineNumber, LineNumberStr),
|
|
string__length(LineNumberStr, LineNumberStrLength0),
|
|
( LineNumberStrLength0 < 3 ->
|
|
LineNumberStrLength = 3
|
|
;
|
|
LineNumberStrLength = LineNumberStrLength0
|
|
),
|
|
ContextLength = FileNameLength + 1 +
|
|
LineNumberStrLength + 2
|
|
;
|
|
MaybeContext = no,
|
|
ContextLength = 0
|
|
),
|
|
NotFirstIndent = (IsFirst = yes -> 0 ; 2),
|
|
Remain = 79 - (ContextLength + Indent + NotFirstIndent),
|
|
convert_components_to_word_list(Components, [], [], Words),
|
|
group_words(IsFirst, Words, Remain, Lines)
|
|
),
|
|
( IsFirst = yes ->
|
|
write_lines(Lines, MaybeContext, Indent, !IO)
|
|
;
|
|
write_nonfirst_lines(Lines, MaybeContext, Indent + 2, !IO)
|
|
).
|
|
|
|
:- pred write_lines(list(list(string))::in, maybe(prog_context)::in, int::in,
|
|
io::di, io::uo) is det.
|
|
|
|
write_lines([], _, _, !IO).
|
|
write_lines([Line | Lines], MaybeContext, Indent, !IO) :-
|
|
(
|
|
MaybeContext = yes(Context),
|
|
prog_out__write_context(Context, !IO)
|
|
;
|
|
MaybeContext = no
|
|
),
|
|
string__pad_left("", ' ', Indent, IndentStr),
|
|
io__write_string(IndentStr, !IO),
|
|
write_line(Line, !IO),
|
|
Indent2 = Indent + 2,
|
|
write_nonfirst_lines(Lines, MaybeContext, Indent2, !IO).
|
|
|
|
:- pred write_nonfirst_lines(list(list(string))::in, maybe(prog_context)::in,
|
|
int::in, io::di, io::uo) is det.
|
|
|
|
write_nonfirst_lines([], _, _, !IO).
|
|
write_nonfirst_lines([Line | Lines], MaybeContext, Indent, !IO) :-
|
|
(
|
|
MaybeContext = yes(Context),
|
|
prog_out__write_context(Context, !IO)
|
|
;
|
|
MaybeContext = no
|
|
),
|
|
string__pad_left("", ' ', Indent, IndentStr),
|
|
io__write_string(IndentStr, !IO),
|
|
write_line(Line, !IO),
|
|
write_nonfirst_lines(Lines, MaybeContext, Indent, !IO).
|
|
|
|
:- pred write_line(list(string)::in, io::di, io::uo) is det.
|
|
|
|
write_line([], !IO).
|
|
write_line([Word | Words], !IO) :-
|
|
io__write_string(Word, !IO),
|
|
write_line_rest(Words, !IO),
|
|
io__write_char('\n', !IO).
|
|
|
|
:- pred write_line_rest(list(string)::in, io::di, io::uo) is det.
|
|
|
|
write_line_rest([], !IO).
|
|
write_line_rest([Word | Words], !IO) :-
|
|
io__write_char(' ', !IO),
|
|
io__write_string(Word, !IO),
|
|
write_line_rest(Words, !IO).
|
|
|
|
%----------------------------------------------------------------------------%
|
|
|
|
:- pred convert_components_to_word_list(list(format_component)::in,
|
|
list(string)::in, list(list(string))::in, list(list(string))::out)
|
|
is det.
|
|
|
|
convert_components_to_word_list([], Words0, Paras0, Paras) :-
|
|
list__reverse(Words0, Words),
|
|
list__reverse([Words | Paras0], Paras).
|
|
convert_components_to_word_list([Component | Components], Words0,
|
|
Paras0, Paras) :-
|
|
(
|
|
Component = fixed(Word),
|
|
Words1 = [Word | Words0],
|
|
Paras1 = Paras0
|
|
;
|
|
Component = words(WordsStr),
|
|
break_into_words(WordsStr, Words0, Words1),
|
|
Paras1 = Paras0
|
|
;
|
|
Component = nl,
|
|
list__reverse(Words0, Words),
|
|
Paras1 = [Words | Paras0],
|
|
Words1 = []
|
|
),
|
|
convert_components_to_word_list(Components, Words1, Paras1, Paras).
|
|
|
|
:- pred break_into_words(string::in, list(string)::in, list(string)::out)
|
|
is det.
|
|
|
|
break_into_words(String, Words0, Words) :-
|
|
break_into_words_from(String, 0, Words0, Words).
|
|
|
|
:- pred break_into_words_from(string::in, int::in, list(string)::in,
|
|
list(string)::out) is det.
|
|
|
|
break_into_words_from(String, Cur, Words0, Words) :-
|
|
( find_word_start(String, Cur, Start) ->
|
|
find_word_end(String, Start, End),
|
|
Length = End - Start + 1,
|
|
string__substring(String, Start, Length, Word),
|
|
Next = End + 1,
|
|
break_into_words_from(String, Next, [Word | Words0], Words)
|
|
;
|
|
Words = Words0
|
|
).
|
|
|
|
:- pred find_word_start(string::in, int::in, int::out) is semidet.
|
|
|
|
find_word_start(String, Cur, WordStart) :-
|
|
string__index(String, Cur, Char),
|
|
( char__is_whitespace(Char) ->
|
|
Next = Cur + 1,
|
|
find_word_start(String, Next, WordStart)
|
|
;
|
|
WordStart = Cur
|
|
).
|
|
|
|
:- pred find_word_end(string::in, int::in, int::out) is det.
|
|
|
|
find_word_end(String, Cur, WordEnd) :-
|
|
Next = Cur + 1,
|
|
( string__index(String, Next, Char) ->
|
|
( char__is_whitespace(Char) ->
|
|
WordEnd = Cur
|
|
;
|
|
find_word_end(String, Next, WordEnd)
|
|
)
|
|
;
|
|
WordEnd = Cur
|
|
).
|
|
|
|
%----------------------------------------------------------------------------%
|
|
|
|
% Groups the given words into lines. The first line can have up to Max
|
|
% characters on it; the later lines (if any) up to Max-2 characters.
|
|
% The given list of words must be nonempty, since we always return
|
|
% at least one line.
|
|
|
|
:- pred group_words(bool::in, list(list(string))::in, int::in,
|
|
list(list(string))::out) is det.
|
|
|
|
group_words(IsFirst, Paras, Max, Lines) :-
|
|
(
|
|
Paras = [],
|
|
Lines = []
|
|
;
|
|
Paras = [FirstPara | LaterParas],
|
|
(
|
|
FirstPara = [],
|
|
group_words(IsFirst, LaterParas, Max, Lines)
|
|
;
|
|
FirstPara = [FirstWord | LaterWords],
|
|
get_line_of_words(FirstWord, LaterWords,
|
|
Max, Line, RestWords),
|
|
( IsFirst = yes ->
|
|
Max2 = Max - 2
|
|
;
|
|
Max2 = Max
|
|
),
|
|
group_nonfirst_line_words(RestWords, Max2, RestLines1),
|
|
Lines1 = [Line | RestLines1],
|
|
group_words(no, LaterParas, Max2, RestLines),
|
|
list__append(Lines1, RestLines, Lines)
|
|
)
|
|
).
|
|
|
|
:- pred group_nonfirst_line_words(list(string)::in, int::in,
|
|
list(list(string))::out) is det.
|
|
|
|
group_nonfirst_line_words(Words, Max, Lines) :-
|
|
(
|
|
Words = [],
|
|
Lines = []
|
|
;
|
|
Words = [FirstWord | LaterWords],
|
|
get_line_of_words(FirstWord, LaterWords, Max, Line, RestWords),
|
|
group_nonfirst_line_words(RestWords, Max, RestLines),
|
|
Lines = [Line | RestLines]
|
|
).
|
|
|
|
:- pred get_line_of_words(string::in, list(string)::in, int::in,
|
|
list(string)::out, list(string)::out) is det.
|
|
|
|
get_line_of_words(FirstWord, LaterWords, MaxLen, Line, RestWords) :-
|
|
string__length(FirstWord, FirstWordLen),
|
|
get_later_words(LaterWords, FirstWordLen, MaxLen, [FirstWord],
|
|
Line, RestWords).
|
|
|
|
:- pred get_later_words(list(string)::in, int::in, int::in,
|
|
list(string)::in, list(string)::out, list(string)::out) is det.
|
|
|
|
get_later_words([], _, _, Line, Line, []).
|
|
get_later_words([Word | Words], OldLen, MaxLen, Line0, Line, RestWords) :-
|
|
string__length(Word, WordLen),
|
|
NewLen = OldLen + 1 + WordLen,
|
|
( NewLen =< MaxLen ->
|
|
list__append(Line0, [Word], Line1),
|
|
get_later_words(Words, NewLen, MaxLen,
|
|
Line1, Line, RestWords)
|
|
;
|
|
Line = Line0,
|
|
RestWords = [Word | Words]
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% The code of this predicate duplicates the functionality of
|
|
% hlds_out__write_pred_id. Changes here should be made there as well.
|
|
|
|
error_util__describe_one_pred_name(Module, PredId, Piece) :-
|
|
module_info_pred_info(Module, PredId, PredInfo),
|
|
ModuleName = pred_info_module(PredInfo),
|
|
prog_out__sym_name_to_string(ModuleName, ModuleNameString),
|
|
PredName = pred_info_name(PredInfo),
|
|
Arity = pred_info_arity(PredInfo),
|
|
PredOrFunc = pred_info_is_pred_or_func(PredInfo),
|
|
PredOrFuncPart = pred_or_func_to_string(PredOrFunc),
|
|
adjust_func_arity(PredOrFunc, OrigArity, Arity),
|
|
(
|
|
pred_info_get_goal_type(PredInfo, promise(PromiseType))
|
|
->
|
|
Piece = "`" ++ promise_to_string(PromiseType) ++ "' declaration"
|
|
;
|
|
string__int_to_string(OrigArity, ArityPart),
|
|
string__append_list([
|
|
PredOrFuncPart,
|
|
" `",
|
|
ModuleNameString,
|
|
".",
|
|
PredName,
|
|
"/",
|
|
ArityPart,
|
|
"'"], Piece)
|
|
).
|
|
|
|
error_util__describe_several_pred_names(Module, PredId, Pieces) :-
|
|
list__map(error_util__describe_one_pred_name(Module), PredId, Pieces0),
|
|
error_util__list_to_pieces(Pieces0, Pieces).
|
|
|
|
error_util__describe_one_proc_name(Module, proc(PredId, ProcId), Piece) :-
|
|
error_util__describe_one_pred_name(Module, PredId, PredPiece),
|
|
proc_id_to_int(ProcId, ProcIdInt),
|
|
string__int_to_string(ProcIdInt, ProcIdPart),
|
|
string__append_list([
|
|
PredPiece,
|
|
" mode ",
|
|
ProcIdPart
|
|
], Piece).
|
|
|
|
error_util__describe_several_proc_names(Module, PPIds, Pieces) :-
|
|
list__map(error_util__describe_one_proc_name(Module), PPIds, Pieces0),
|
|
error_util__list_to_pieces(Pieces0, Pieces).
|
|
|
|
error_util__describe_one_call_site(Module, PPId - Context, Piece) :-
|
|
error_util__describe_one_proc_name(Module, PPId, ProcName),
|
|
term__context_file(Context, FileName),
|
|
term__context_line(Context, LineNumber),
|
|
string__int_to_string(LineNumber, LineNumberPart),
|
|
string__append_list([
|
|
ProcName,
|
|
" at ",
|
|
FileName,
|
|
":",
|
|
LineNumberPart
|
|
], Piece).
|
|
|
|
error_util__describe_several_call_sites(Module, Sites, Pieces) :-
|
|
list__map(error_util__describe_one_call_site(Module), Sites, Pieces0),
|
|
error_util__list_to_pieces(Pieces0, Pieces).
|
|
|
|
error_util__describe_sym_name_and_arity(SymName / Arity) =
|
|
string__append_list(["`", SymNameString,
|
|
"/", string__int_to_string(Arity), "'"]) :-
|
|
sym_name_to_string(SymName, SymNameString).
|
|
|
|
error_util__describe_sym_name(SymName) =
|
|
string__append_list(["`", SymNameString, "'"]) :-
|
|
sym_name_to_string(SymName, SymNameString).
|
|
|
|
error_util__pred_or_func_to_string(predicate) = "predicate".
|
|
error_util__pred_or_func_to_string(function) = "function".
|
|
|
|
error_util__append_punctuation([], _) = _ :-
|
|
error("error_util__append_punctuation: " ++
|
|
"appending punctuation after nothing").
|
|
error_util__append_punctuation([Piece0], Punc) = [Piece] :-
|
|
% Avoid unwanted line splitting between the message
|
|
% and the punctuation.
|
|
(
|
|
Piece0 = words(String),
|
|
Piece = words(string__append(String, char_to_string(Punc)))
|
|
;
|
|
Piece0 = fixed(String),
|
|
Piece = fixed(string__append(String, char_to_string(Punc)))
|
|
;
|
|
Piece0 = nl,
|
|
error("error_util__append_punctutation: " ++
|
|
"appending punctuation after newline")
|
|
).
|
|
error_util__append_punctuation([Piece1, Piece2 | Pieces], Punc) =
|
|
[Piece1 | error_util__append_punctuation([Piece2 | Pieces], Punc)].
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
report_error_num_args(MaybePredOrFunc, Arity0, Arities0, !IO) :-
|
|
% Adjust arities for functions.
|
|
( MaybePredOrFunc = yes(function) ->
|
|
adjust_func_arity(function, Arity, Arity0),
|
|
list__map(
|
|
(pred(OtherArity0::in, OtherArity::out) is det :-
|
|
adjust_func_arity(function,
|
|
OtherArity, OtherArity0)
|
|
),
|
|
Arities0, Arities)
|
|
;
|
|
Arity = Arity0,
|
|
Arities = Arities0
|
|
),
|
|
io__write_string("wrong number of arguments (", !IO),
|
|
io__write_int(Arity, !IO),
|
|
io__write_string("; should be ", !IO),
|
|
report_error_right_num_args(Arities, !IO),
|
|
io__write_string(")", !IO).
|
|
|
|
:- pred report_error_right_num_args(list(int)::in, io::di, io::uo) is det.
|
|
|
|
report_error_right_num_args([], !IO).
|
|
report_error_right_num_args([Arity | Arities], !IO) :-
|
|
io__write_int(Arity, !IO),
|
|
( Arities = [] ->
|
|
true
|
|
; Arities = [_] ->
|
|
io__write_string(" or ", !IO)
|
|
;
|
|
io__write_string(", ", !IO)
|
|
),
|
|
report_error_right_num_args(Arities, !IO).
|
|
|
|
% Call error/1 with a "Sorry, not implemented" message.
|
|
%
|
|
sorry(Module, What) :-
|
|
string__format("%s: Sorry, not implemented: %s",
|
|
[s(Module), s(What)], ErrorMessage),
|
|
error(ErrorMessage).
|
|
|
|
unexpected(Module, What) :-
|
|
string__format("%s: Unexpected: %s",
|
|
[s(Module), s(What)], ErrorMessage),
|
|
error(ErrorMessage).
|