mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 01:43:35 +00:00
compiler/*.m:
Standardize on the do_not spelling over the dont contraction
in the compiler directory. (We used to have a lot of both spellings.)
1064 lines
45 KiB
Mathematica
1064 lines
45 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2015, 2024 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% This module formats insts for use in error messages, with the objective
|
|
% of making the generated output easily readable by humans. This sometimes
|
|
% requires departing from strict Mercury syntax, so the output is NOT
|
|
% expected to parseable by machine.
|
|
%
|
|
% The module also formats modes, since this is needed for printing the insts
|
|
% of higher order types. This capability is not yet exported.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module hlds.error_msg_inst.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.error_spec.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module list.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type maybe_expand_named_insts
|
|
---> do_not_expand_named_insts
|
|
; expand_named_insts.
|
|
|
|
:- type user_or_developer
|
|
---> uod_user
|
|
; uod_developer(tvarset).
|
|
|
|
:- type short_inst
|
|
---> quote_short_inst
|
|
; fixed_short_inst.
|
|
|
|
% error_msg_inst(ModuleInfo, InstVarSet, ExpandNamedInsts, UserOrDeveloper,
|
|
% QuoteShortInst, ShortInstPrefix, ShortInstSuffix,
|
|
% LongInstPrefix, LongInstSuffix, Inst0) = Pieces:
|
|
%
|
|
% Format Inst0 for use in an error message, in a short form that fits at
|
|
% the end of the current line if possible, and in a long form that starts
|
|
% on a separate line, if it is not.
|
|
%
|
|
% When using the short form, put the inst's text representation into quotes
|
|
% if QuoteShortInst = quote_short_inst. Put ShortInstPrefix before it
|
|
% and add ShortInstSuffix after it. Normally, ShortInstSuffix will end
|
|
% with either nl or nl_indent_delta.
|
|
%
|
|
% When using the long form, leave the inst's text representation as is,
|
|
% without quotations, put LongInstPrefix before it, and LongInstSuffix
|
|
% after it. Normally, LongInstPrefix will start with nl or nl_indent_delta
|
|
% to start the inst on a new line, and LongInstSuffix will end with nl
|
|
% or nl_indent_delta as well. (The second nl_indent_delta will usually
|
|
% undo the effect of the first.)
|
|
%
|
|
:- func error_msg_inst(module_info, inst_varset, maybe_expand_named_insts,
|
|
user_or_developer, short_inst, list(format_piece), list(format_piece),
|
|
list(format_piece), list(format_piece), mer_inst) = list(format_piece).
|
|
|
|
% Do the same job as error_msg_inst, but for inst names.
|
|
%
|
|
:- func error_msg_inst_name(module_info, inst_varset, maybe_expand_named_insts,
|
|
user_or_developer, short_inst, list(format_piece), list(format_piece),
|
|
list(format_piece), list(format_piece), inst_name) = list(format_piece).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds.
|
|
:- import_module check_hlds.inst_lookup.
|
|
:- import_module hlds.hlds_inst_mode.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.builtin_modules.
|
|
:- import_module mdbcomp.prim_data.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.error_type_util.
|
|
:- import_module parse_tree.parse_tree_out_cons_id.
|
|
:- import_module parse_tree.parse_tree_out_info.
|
|
:- import_module parse_tree.parse_tree_out_inst.
|
|
:- import_module parse_tree.parse_tree_out_misc.
|
|
:- import_module parse_tree.parse_tree_out_term.
|
|
:- import_module parse_tree.parse_tree_to_term.
|
|
:- import_module parse_tree.prog_mode.
|
|
:- import_module parse_tree.prog_util.
|
|
:- import_module parse_tree.write_error_spec.
|
|
|
|
:- import_module counter.
|
|
:- import_module int.
|
|
:- import_module map.
|
|
:- import_module require.
|
|
:- import_module set.
|
|
:- import_module string.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type inst_msg_info
|
|
---> inst_msg_info(
|
|
imi_module_info :: module_info,
|
|
imi_inst_varset :: inst_varset,
|
|
imi_named_insts :: maybe_expand_named_insts,
|
|
imi_audience :: user_or_developer
|
|
).
|
|
|
|
:- type maybe_inline_pieces
|
|
---> multi_line_pieces
|
|
; inline_pieces.
|
|
|
|
:- inst multi_line_pieces for maybe_inline_pieces/0
|
|
---> multi_line_pieces.
|
|
:- inst inline_pieces for maybe_inline_pieces/0
|
|
---> inline_pieces.
|
|
|
|
% We record which inst names we have seen before. The main reason why
|
|
% we do this is to prevent infinite loops when expanding inst names
|
|
% whose definitions are recursive, but even in the absence of recursion,
|
|
% printing just the name of a named inst on its second and later
|
|
% occurrences can make the output smaller and easier to read.
|
|
%
|
|
:- type expansions_info
|
|
---> expansions_info(
|
|
% We put every inst name into this map if it can be recursive.
|
|
% The value associated with an inst name is what we should
|
|
% print on any later references to the inst name.
|
|
%
|
|
% XXX Internally generated inst names can be quite big.
|
|
% If comparisons on these inside map lookups ever become
|
|
% a problem, we could make the key not the inst_name,
|
|
% but its address.
|
|
ei_seen_inst_names :: map(inst_name,
|
|
list(format_piece)),
|
|
|
|
% Inst names generated internally by the compiler don't have
|
|
% intuitively understandable names we can print, so
|
|
% we give these inst names a number. We allocate these
|
|
% using this counter.
|
|
ei_inst_num_counter :: counter
|
|
).
|
|
|
|
error_msg_inst(ModuleInfo, InstVarSet, ExpandNamedInsts, UserOrDeveloper,
|
|
QuoteShortInst, ShortInstPrefix, ShortInstSuffix,
|
|
LongInstPrefix, LongInstSuffix, Inst) = Pieces :-
|
|
Info = inst_msg_info(ModuleInfo, InstVarSet, ExpandNamedInsts,
|
|
UserOrDeveloper),
|
|
% We used to call strip_module_names_from_inst to strip builtin
|
|
% module names from all parts of the inst we are asked to convert
|
|
% to Pieces. This worked well when we used the code in this module
|
|
% only for generating descriptions of insts for error messages.
|
|
% However, it became a problem when we
|
|
%
|
|
% - started using this code to describe insts in HLDS dumps, *and*
|
|
% - we modified inst_lookup.m to report inst names that were effectively
|
|
% *dangling references*, i.e. references to an entries in the inst tables
|
|
% that weren't actually there.
|
|
%
|
|
% The sequence of events that led to the problem was as follows.
|
|
%
|
|
% - Mode analysis creates an entry in the ground inst table. Both the key
|
|
% and the value of this entry contains the same higher order inst, and
|
|
% the modes of the arguments of the pred_inst_info have the form
|
|
%
|
|
% user_defined_mode(qualified(unqualified("builtin"), "in"), [])
|
|
%
|
|
% - When printing the value in the ground table entry in a HLDS dump,
|
|
% the call to strip_module_names_from_inst replaces all the argument
|
|
% modes in that pred_inst_info with modes of the form
|
|
%
|
|
% user_defined_mode(unqualified("in"), [])
|
|
%
|
|
% - Execution continues to the call to inst_to_pieces below, which calls
|
|
% inst_name_to_pieces, which calls inst_lookup_debug. The difference
|
|
% in module qualification then causes the search of the ground inst
|
|
% table there to fail, which in turn causes inst_lookup_debug to return
|
|
% an inst constructed by make_missing_inst_name, which will then contain
|
|
% "MISSING_INST" in its name.
|
|
%
|
|
% - The occurence of this string in the HLDS dump is *supposed* to mean
|
|
% that the process of *constructing* the inst has a bug, but in this case
|
|
% it is the process of *printing* the inst that has a bug. This can be
|
|
% quite misleading.
|
|
%
|
|
% It was misleading enough to cause me, zs, to add a significant amount
|
|
% of code to help me track down what I thought was a problem in inst
|
|
% construction, only to find that the problem was in code I previously
|
|
% added to help find another bug :-) I don't want this to happen again
|
|
% in the future, so from now on.
|
|
%
|
|
% The general approach of the fix is two-fold.
|
|
%
|
|
% - First, when we generate Pieces for users, we want to strip any
|
|
% module qualifiers for builtin modules from insts only *after*
|
|
% we have called inst_lookup_debug on those insts. This should prevent
|
|
% the problem above.
|
|
%
|
|
% - Second, for insts and inst names that contain other insts or inst
|
|
% names, we want to strip away module qualifiers for builtin modules
|
|
% only from the parts of the inst or inst name that are *outside*
|
|
% the contained insts or inst names. We want to leave the contained
|
|
% insts and inst names intact, because if we didn't, the original
|
|
% problem could still occur, just for the contained insts/inst names.
|
|
% Any builtin module qualifiers in those contained insts/inst names
|
|
% would still get stripped away later, when we get to process *them*.
|
|
Expansions0 = expansions_info(map.init, counter.init(1)),
|
|
InlineSuffixPieces = [],
|
|
inst_to_pieces(Info, inline_pieces, Inst, InlineSuffixPieces,
|
|
InlinePieces, Expansions0, _InlineExpansions),
|
|
InlineStr = error_pieces_to_one_line_string(InlinePieces),
|
|
% We could base the decision on whether to put the inst inline
|
|
% on criteria other than its length, such as
|
|
%
|
|
% - on a count of the parentheses in it (which would effectively be
|
|
% a test of the inst's depth);
|
|
% - on a count of the commas in it (which would effectively be a test
|
|
% of the number of arguments in the inst); or
|
|
% - on a composite test, such as "the number of left parentheses
|
|
% plus the number of commas cannot exceed six".
|
|
%
|
|
% The current test is just a guess; experience will give us feedback.
|
|
( if
|
|
string.length(InlineStr, Len),
|
|
Len < 40
|
|
then
|
|
(
|
|
QuoteShortInst = quote_short_inst,
|
|
% An inst that is shown on the same line as English text needs
|
|
% something to visually separate it from the English text.
|
|
% The quotes provide that separation.
|
|
%
|
|
% Without a small length limit, we would use words_quote
|
|
% instead of quote to wrap InlineStr.
|
|
InlinePiece = quote(InlineStr)
|
|
;
|
|
QuoteShortInst = fixed_short_inst,
|
|
% Our caller has told us that it ensured this separation already.
|
|
InlinePiece = fixed(InlineStr)
|
|
),
|
|
Pieces = ShortInstPrefix ++ [InlinePiece | ShortInstSuffix]
|
|
else
|
|
% Showing the inst on a separate line from the English text
|
|
% provides enough separation by itself.
|
|
inst_to_pieces(Info, multi_line_pieces, Inst, LongInstSuffix,
|
|
MultiLinePieces, Expansions0, _MultiLineExpansions),
|
|
Pieces = LongInstPrefix ++ MultiLinePieces
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
error_msg_inst_name(ModuleInfo, InstVarSet, ExpandNamedInsts, UserOrDeveloper,
|
|
QuoteShortInst, ShortInstPrefix, ShortInstSuffix,
|
|
LongInstPrefix, LongInstSuffix, InstName) = Pieces :-
|
|
Info = inst_msg_info(ModuleInfo, InstVarSet, ExpandNamedInsts,
|
|
UserOrDeveloper),
|
|
Expansions0 = expansions_info(map.init, counter.init(1)),
|
|
InlineSuffixPieces = [],
|
|
inst_name_to_pieces(Info, inline_pieces, InstName, InlineSuffixPieces,
|
|
InlinePieces, Expansions0, _InlineExpansions),
|
|
InlineStr = error_pieces_to_one_line_string(InlinePieces),
|
|
% We could base the decision on whether to put the inst inline
|
|
% on criteria other than its length, such as
|
|
%
|
|
% - on a count of the parentheses in it (which would effectively be
|
|
% a test of the inst's depth);
|
|
% - on a count of the commas in it (which would effectively be a test
|
|
% of the number of arguments in the inst); or
|
|
% - on a composite test, such as "the number of left parentheses
|
|
% plus the number of commas cannot exceed six".
|
|
%
|
|
% The current test is just a guess; experience will give us feedback.
|
|
( if
|
|
string.length(InlineStr, Len),
|
|
Len < 40
|
|
then
|
|
(
|
|
QuoteShortInst = quote_short_inst,
|
|
% An inst that is shown on the same line as English text needs
|
|
% something to visually separate it from the English text.
|
|
% The quotes provide that separation.
|
|
%
|
|
% Without a small length limit, we would use words_quote
|
|
% instead of quote to wrap InlineStr.
|
|
InlinePiece = quote(InlineStr)
|
|
;
|
|
% Our caller has told us that it ensured this separation already.
|
|
QuoteShortInst = fixed_short_inst,
|
|
InlinePiece = fixed(InlineStr)
|
|
),
|
|
Pieces = ShortInstPrefix ++ [InlinePiece | ShortInstSuffix]
|
|
else
|
|
% Showing the inst on a separate line from the English text
|
|
% provides enough separation by itself.
|
|
inst_name_to_pieces(Info, multi_line_pieces, InstName, LongInstSuffix,
|
|
MultiLinePieces, Expansions0, _MultiLineExpansions),
|
|
Pieces = LongInstPrefix ++ MultiLinePieces
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% The following predicates are sort-of duplicated. The predicates whose names
|
|
% end in "to_pieces" generate output that put different parts of the inst
|
|
% on (mostly) separate lines, showing the structure of the inst through
|
|
% indentation. The predicates whose names end in "to_inline_pieces" generate
|
|
% output that contains the same components, but all on one line.
|
|
%
|
|
|
|
:- pred inst_to_pieces(inst_msg_info, maybe_inline_pieces, mer_inst,
|
|
list(format_piece), list(format_piece), expansions_info, expansions_info).
|
|
:- mode inst_to_pieces(in, in(multi_line_pieces),
|
|
in, in, out, in, out) is det.
|
|
:- mode inst_to_pieces(in, in(inline_pieces),
|
|
in, in, out, in, out) is det.
|
|
|
|
inst_to_pieces(Info, MaybeInline, Inst, Suffix, Pieces, !Expansions) :-
|
|
(
|
|
Inst = free,
|
|
Pieces = [fixed("free") | Suffix]
|
|
;
|
|
Inst = bound(Uniq, _, BoundFunctors),
|
|
BoundName = mercury_uniqueness_to_string(Uniq, "bound"),
|
|
(
|
|
BoundFunctors = [],
|
|
Pieces = [fixed(BoundName) | Suffix]
|
|
;
|
|
BoundFunctors = [HeadBoundFunctor | TailBoundFunctors],
|
|
bound_functors_to_pieces(Info, MaybeInline,
|
|
HeadBoundFunctor, TailBoundFunctors, [], BoundPieces,
|
|
!Expansions),
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
Pieces = [fixed(BoundName ++ "("), nl_indent_delta(1) |
|
|
BoundPieces] ++ [nl_indent_delta(-1), fixed(")") | Suffix]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
Pieces = [prefix(BoundName ++ "(") | BoundPieces] ++
|
|
[suffix(")") | Suffix]
|
|
)
|
|
)
|
|
;
|
|
Inst = ground(Uniq, HOInstInfo),
|
|
(
|
|
HOInstInfo = higher_order(PredInstInfo),
|
|
pred_inst_info_to_pieces(Info, MaybeInline, "", Uniq,
|
|
PredInstInfo, HOPieces, !Expansions),
|
|
Pieces = HOPieces ++ Suffix
|
|
;
|
|
HOInstInfo = none_or_default_func,
|
|
Str = mercury_uniqueness_to_string(Uniq, "ground"),
|
|
Pieces = [fixed(Str) | Suffix]
|
|
)
|
|
;
|
|
Inst = any(Uniq, HOInstInfo),
|
|
(
|
|
HOInstInfo = higher_order(PredInstInfo),
|
|
pred_inst_info_to_pieces(Info, MaybeInline, "any_", Uniq,
|
|
PredInstInfo, HOPieces, !Expansions),
|
|
Pieces = HOPieces ++ Suffix
|
|
;
|
|
HOInstInfo = none_or_default_func,
|
|
Str = mercury_any_uniqueness_to_string(Uniq),
|
|
Pieces = [fixed(Str) | Suffix]
|
|
)
|
|
;
|
|
Inst = inst_var(Var),
|
|
InstVarSet = Info ^ imi_inst_varset,
|
|
Name = mercury_var_to_string_vs(InstVarSet, print_name_only, Var),
|
|
Pieces = [fixed(Name) | Suffix]
|
|
;
|
|
Inst = constrained_inst_vars(Vars, SubInst),
|
|
InstVarSet = Info ^ imi_inst_varset,
|
|
Names = mercury_vars_to_string_vs(InstVarSet, print_name_only,
|
|
set.to_sorted_list(Vars)),
|
|
inst_to_pieces(Info, MaybeInline, SubInst, [], SubInstPieces,
|
|
!Expansions),
|
|
Pieces = [fixed("("), words(Names), fixed("=<") | SubInstPieces] ++
|
|
[fixed(")") | Suffix]
|
|
;
|
|
Inst = defined_inst(InstName),
|
|
inst_name_to_pieces(Info, MaybeInline, InstName, Suffix, Pieces,
|
|
!Expansions)
|
|
;
|
|
Inst = not_reached,
|
|
Pieces = [fixed("not_reached") | Suffix]
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred insts_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
mer_inst, list(mer_inst), list(format_piece), list(format_piece),
|
|
expansions_info, expansions_info).
|
|
:- mode insts_to_pieces(in, in(multi_line_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
:- mode insts_to_pieces(in, in(inline_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
|
|
insts_to_pieces(Info, MaybeInline, HeadInst, TailInsts, Suffix, Pieces,
|
|
!Expansions) :-
|
|
(
|
|
TailInsts = [],
|
|
HeadSuffix = Suffix,
|
|
inst_to_pieces(Info, MaybeInline, HeadInst, HeadSuffix,
|
|
Pieces, !Expansions)
|
|
;
|
|
TailInsts = [HeadTailInst | TailTailInsts],
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
HeadSuffix = [suffix(","), nl]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
HeadSuffix = [suffix(",")]
|
|
),
|
|
inst_to_pieces(Info, MaybeInline, HeadInst, HeadSuffix,
|
|
HeadPieces, !Expansions),
|
|
insts_to_pieces(Info, MaybeInline, HeadTailInst, TailTailInsts, Suffix,
|
|
TailPieces, !Expansions),
|
|
Pieces = HeadPieces ++ TailPieces
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred bound_functors_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
bound_functor, list(bound_functor), list(format_piece), list(format_piece),
|
|
expansions_info, expansions_info).
|
|
:- mode bound_functors_to_pieces(in, in(multi_line_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
:- mode bound_functors_to_pieces(in, in(inline_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
|
|
bound_functors_to_pieces(Info, MaybeInline,
|
|
HeadBoundFunctor, TailBoundFunctors, Suffix, Pieces, !Expansions) :-
|
|
(
|
|
TailBoundFunctors = [],
|
|
HeadSuffix = Suffix
|
|
;
|
|
TailBoundFunctors = [HeadTailBoundFunctor | TailTailBoundFunctors],
|
|
bound_functors_to_pieces(Info, MaybeInline,
|
|
HeadTailBoundFunctor, TailTailBoundFunctors, Suffix, TailPieces,
|
|
!Expansions),
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
HeadSuffix = [nl_indent_delta(-1), fixed(";"), nl_indent_delta(1) |
|
|
TailPieces]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
HeadSuffix = [fixed(";") | TailPieces]
|
|
)
|
|
),
|
|
HeadBoundFunctor = bound_functor(ConsId0, ArgInsts),
|
|
( if
|
|
ConsId0 = du_data_ctor(du_ctor(SymName, Arity, TypeCtor)),
|
|
% The module names of the cons_ids are uniquely specified
|
|
% by the types of the variables whose we are printing. Printing them
|
|
% would therefore generate more clutter than enlightenment.
|
|
% XXX This is true *most* of the time, but it is not true *all*
|
|
% of the time. For tests/invalid/qualified_cons_id2.m, it yields
|
|
% a confusing error message, at least as of 2024 apr 30.
|
|
SymName = qualified(_ModuleName, BaseName)
|
|
then
|
|
ConsId = du_data_ctor(du_ctor(unqualified(BaseName), Arity, TypeCtor))
|
|
else
|
|
ConsId = ConsId0
|
|
),
|
|
ConsIdStr = mercury_cons_id_to_string(output_mercury,
|
|
does_not_need_brackets, ConsId),
|
|
name_and_arg_insts_to_pieces(Info, MaybeInline, ConsIdStr, ArgInsts,
|
|
HeadSuffix, Pieces, !Expansions).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred inst_name_to_pieces(inst_msg_info, maybe_inline_pieces, inst_name,
|
|
list(format_piece), list(format_piece), expansions_info, expansions_info).
|
|
:- mode inst_name_to_pieces(in, in(multi_line_pieces),
|
|
in, in, out, in, out) is det.
|
|
:- mode inst_name_to_pieces(in, in(inline_pieces),
|
|
in, in, out, in, out) is det.
|
|
|
|
inst_name_to_pieces(Info, MaybeInline, InstName, Suffix, Pieces,
|
|
!Expansions) :-
|
|
( if have_we_expanded_inst_name(!.Expansions, InstName, PastPieces) then
|
|
Pieces = PastPieces ++ Suffix
|
|
else
|
|
(
|
|
InstName = user_inst(SymName, ArgInsts),
|
|
sym_name_to_min_qual_string(Info, SymName, SymNameStr),
|
|
% XXX If ArgInsts contains named user insts, expanding them
|
|
% inside the name of another inst is far from ideal. However,
|
|
% leaving them to be expanded in the call to inst_to_pieces
|
|
% on EqvInst below also has a problem. This is that we construct
|
|
% lists of insts, such as the (expansion of ArgInsts in EqvInst)
|
|
% in a back-to-front order, which means that if a named inst
|
|
% occurs in EqvInst more than once, it will be the *last*
|
|
% occurrence, not the first, which will be expanded.
|
|
NameInfo = Info ^ imi_named_insts := do_not_expand_named_insts,
|
|
ModuleInfo = Info ^ imi_module_info,
|
|
module_info_get_inst_table(ModuleInfo, InstTable),
|
|
inst_table_get_user_insts(InstTable, UserInstTable),
|
|
list.length(ArgInsts, Arity),
|
|
InstCtor = inst_ctor(SymName, Arity),
|
|
( if
|
|
is_unknown_or_missing_user_inst_name(InstName)
|
|
then
|
|
name_and_arg_insts_to_pieces(NameInfo, MaybeInline,
|
|
SymNameStr, ArgInsts, Suffix, Pieces, !.Expansions, _)
|
|
else if
|
|
map.search(UserInstTable, InstCtor, InstDefn)
|
|
then
|
|
name_and_arg_insts_to_pieces(NameInfo, MaybeInline,
|
|
SymNameStr, ArgInsts, [], NamePieces, !.Expansions, _),
|
|
NamedNamePieces = [words("named inst") | NamePieces],
|
|
ExpandInsts = Info ^ imi_named_insts,
|
|
(
|
|
ExpandInsts = do_not_expand_named_insts,
|
|
Pieces = NamePieces ++ Suffix
|
|
;
|
|
ExpandInsts = expand_named_insts,
|
|
record_user_inst_name(InstName, NamedNamePieces,
|
|
!Expansions),
|
|
InstDefn = hlds_inst_defn(_VarSet, Params, InstBody, _MMTC,
|
|
_Context, _Status),
|
|
InstBody = eqv_inst(EqvInst0),
|
|
inst_substitute_arg_list(Params, ArgInsts,
|
|
EqvInst0, EqvInst),
|
|
( if EqvInst = defined_inst(InstName) then
|
|
% XXX Would NamePieces look better in the output?
|
|
Pieces = NamedNamePieces ++ Suffix
|
|
else
|
|
inst_to_pieces(Info, MaybeInline, EqvInst,
|
|
Suffix, EqvPieces, !Expansions),
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
Pieces = NamedNamePieces ++
|
|
[nl, words("which expands to"),
|
|
nl_indent_delta(1) | EqvPieces] ++
|
|
[nl_indent_delta(-1)]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
Pieces = NamedNamePieces ++
|
|
[words("which expands to"),
|
|
prefix("<") | EqvPieces] ++ [suffix(">")]
|
|
)
|
|
)
|
|
)
|
|
else if
|
|
SymName = unqualified(BaseName),
|
|
Builtin = mercury_public_builtin_module,
|
|
BuiltinInstCtor =
|
|
inst_ctor(qualified(Builtin, BaseName), Arity),
|
|
map.search(UserInstTable, BuiltinInstCtor, _InstDefn)
|
|
then
|
|
% check_mutable_insts in add_mutable_aux_pred.m removes
|
|
% any module qualifications by mercury_public_builtin_module
|
|
% from the inst name, to signal us that the qualification
|
|
% should not be printed in the error message.
|
|
name_and_arg_insts_to_pieces(NameInfo, MaybeInline,
|
|
SymNameStr, ArgInsts, [], NamePieces, !.Expansions, _),
|
|
Pieces = NamePieces ++ Suffix
|
|
else
|
|
( if
|
|
SymName = qualified(unqualified("FAKE_CONS_ID"),
|
|
ConsIdName)
|
|
then
|
|
% mode_error_unify_var_functor_to_spec created InstName,
|
|
% asking us to treat it just as a wrapper around ArgInsts.
|
|
name_and_arg_insts_to_pieces(NameInfo, MaybeInline,
|
|
ConsIdName, ArgInsts, [], NamePieces, !.Expansions, _),
|
|
Pieces = NamePieces ++ Suffix
|
|
else
|
|
InstCtorName = sym_name_to_string(SymName),
|
|
string.format("undefined inst %s/%d",
|
|
[s(InstCtorName), i(Arity)], Msg),
|
|
unexpected($pred, Msg)
|
|
)
|
|
)
|
|
;
|
|
InstName = typed_inst(Type, SubInstName),
|
|
Audience = Info ^ imi_audience,
|
|
(
|
|
Audience = uod_user,
|
|
% The user doesn't care about the typed_inst wrapper,
|
|
% and the wrapper cannot make an inst recursive.
|
|
inst_name_to_pieces(Info, MaybeInline, SubInstName, Suffix,
|
|
Pieces, !Expansions)
|
|
;
|
|
Audience = uod_developer(TVarSet),
|
|
InstVarSet = Info ^ imi_inst_varset,
|
|
TypePieces = type_to_pieces(TVarSet, InstVarSet,
|
|
print_name_and_num, do_not_add_quotes, [], Type),
|
|
inst_name_to_pieces(Info, MaybeInline, SubInstName, [],
|
|
SubInstNamePieces, !Expansions),
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
Pieces = [fixed("typed_inst("), nl_indent_delta(1)] ++
|
|
TypePieces ++ [suffix(","), nl] ++
|
|
SubInstNamePieces ++
|
|
[nl_indent_delta(-1), fixed(")") | Suffix]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
Pieces = [fixed("typed_inst(")] ++
|
|
TypePieces ++ [suffix(",")] ++
|
|
SubInstNamePieces ++ [suffix(")") | Suffix]
|
|
)
|
|
)
|
|
;
|
|
InstName = typed_ground(Uniq, Type),
|
|
Audience = Info ^ imi_audience,
|
|
(
|
|
Audience = uod_user,
|
|
% The user doesn't care about the typed_inst wrapper,
|
|
% and the wrapper cannot make an inst recursive.
|
|
EqvInst = ground(Uniq, none_or_default_func),
|
|
inst_to_pieces(Info, MaybeInline, EqvInst, Suffix,
|
|
Pieces, !Expansions)
|
|
;
|
|
Audience = uod_developer(TVarSet),
|
|
InstVarSet = Info ^ imi_inst_varset,
|
|
TypePieces = type_to_pieces(TVarSet, InstVarSet,
|
|
print_name_and_num, do_not_add_quotes, [], Type),
|
|
UniqStr = inst_uniqueness(Uniq, "shared"),
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
Pieces = [fixed("typed_ground(" ++ UniqStr ++ ",")] ++
|
|
[nl_indent_delta(1)] ++ TypePieces ++
|
|
[nl_indent_delta(-1), fixed(")") | Suffix]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
Pieces = [fixed("typed_ground(" ++ UniqStr ++ ",")] ++
|
|
TypePieces ++ [suffix(")") | Suffix]
|
|
)
|
|
)
|
|
;
|
|
( InstName = unify_inst(_, _, _, _)
|
|
; InstName = merge_inst(_, _)
|
|
; InstName = ground_inst(_, _, _, _)
|
|
; InstName = any_inst(_, _, _, _)
|
|
; InstName = shared_inst(_)
|
|
; InstName = mostly_uniq_inst(_)
|
|
),
|
|
ModuleInfo = Info ^ imi_module_info,
|
|
% We need to lookup InstName0, NOT InstName. The reason
|
|
% is explained in the big comment in error_msg_inst.
|
|
inst_lookup_debug(ModuleInfo, InstName, EqvInst),
|
|
( if
|
|
EqvInst = defined_inst(EqvInstName),
|
|
EqvInstName = user_inst(EqvSymName, EqvArgInsts),
|
|
is_unknown_or_missing_user_inst_name(EqvInstName)
|
|
then
|
|
NameInfo = Info ^ imi_named_insts := do_not_expand_named_insts,
|
|
sym_name_to_min_qual_string(Info, EqvSymName, EqvSymNameStr),
|
|
name_and_arg_insts_to_pieces(NameInfo, MaybeInline,
|
|
EqvSymNameStr, EqvArgInsts, Suffix, Pieces,
|
|
!.Expansions, _)
|
|
else
|
|
Audience = Info ^ imi_audience,
|
|
compiler_key_inst_name_to_dollar_string(InstName, InstNameStr),
|
|
(
|
|
Audience = uod_user,
|
|
( if EqvInst = defined_inst(InstName) then
|
|
Pieces = [fixed(InstNameStr) | Suffix]
|
|
else
|
|
record_internal_inst_name(InstName, InstNameStr,
|
|
InstNumPieces, !Expansions),
|
|
inst_to_pieces(Info, MaybeInline, EqvInst, Suffix,
|
|
EqvPieces, !Expansions),
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
Pieces = InstNumPieces ++
|
|
[nl, words("which expands to"),
|
|
nl_indent_delta(1) | EqvPieces] ++
|
|
[nl_indent_delta(-1) | Suffix]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
Pieces = InstNumPieces ++
|
|
[words("which expands to"),
|
|
prefix("<") | EqvPieces] ++ [suffix(">") | Suffix]
|
|
)
|
|
)
|
|
;
|
|
Audience = uod_developer(_TVarSet),
|
|
(
|
|
(
|
|
InstName = unify_inst(Live, Real,
|
|
SubInstA, SubInstB),
|
|
UnifyOrMerge = "unify",
|
|
InitialArgs =
|
|
[suffix(is_live_to_str(Live) ++ ","),
|
|
fixed(unify_is_real_to_str(Real) ++ ",")]
|
|
;
|
|
InstName = merge_inst(SubInstA, SubInstB),
|
|
UnifyOrMerge = "merge",
|
|
InitialArgs = []
|
|
),
|
|
SubSuffixA = [],
|
|
SubSuffixB = [],
|
|
inst_to_pieces(Info, MaybeInline, SubInstA, SubSuffixA,
|
|
SubInstPiecesA, !Expansions),
|
|
inst_to_pieces(Info, MaybeInline, SubInstB, SubSuffixB,
|
|
SubInstPiecesB, !Expansions),
|
|
InstNamePieces = [fixed(UnifyOrMerge ++ "(")] ++
|
|
InitialArgs ++ [nl_indent_delta(1)] ++
|
|
SubInstPiecesA ++ [suffix(","), nl] ++
|
|
SubInstPiecesB ++ [nl_indent_delta(-1), fixed(")")]
|
|
;
|
|
(
|
|
InstName = ground_inst(SubInstName, Uniq,
|
|
Live, Real),
|
|
GroundOrAny = "ground",
|
|
UniqStr = inst_uniqueness(Uniq, "shared")
|
|
;
|
|
InstName = any_inst(SubInstName, Uniq, Live, Real),
|
|
GroundOrAny = "any",
|
|
UniqStr = any_inst_uniqueness(Uniq)
|
|
),
|
|
SubSuffix = [],
|
|
inst_name_to_pieces(Info, MaybeInline, SubInstName,
|
|
SubSuffix, SubInstNamePieces, !Expansions),
|
|
InstNamePieces =
|
|
[fixed(GroundOrAny ++ "(" ++ UniqStr ++ ","),
|
|
fixed(is_live_to_str(Live) ++ ","),
|
|
fixed(unify_is_real_to_str(Real) ++ ","),
|
|
nl_indent_delta(1)] ++ SubInstNamePieces ++
|
|
[nl_indent_delta(-1), fixed(")")]
|
|
;
|
|
(
|
|
InstName = shared_inst(SubInstName),
|
|
SorMU = "shared"
|
|
;
|
|
InstName = mostly_uniq_inst(SubInstName),
|
|
SorMU = "mostly_uniq"
|
|
),
|
|
SubSuffix = [],
|
|
inst_name_to_pieces(Info, MaybeInline, SubInstName,
|
|
SubSuffix, SubInstNamePieces, !Expansions),
|
|
InstNamePieces = [fixed(SorMU ++ "("),
|
|
nl_indent_delta(1)] ++ SubInstNamePieces ++
|
|
[nl_indent_delta(-1), fixed(")")]
|
|
),
|
|
Pieces = InstNamePieces
|
|
)
|
|
)
|
|
)
|
|
).
|
|
|
|
:- inst compiler_key_inst_name for inst_name/0
|
|
---> unify_inst(ground, ground, ground, ground)
|
|
; merge_inst(ground, ground)
|
|
; ground_inst(ground, ground, ground, ground)
|
|
; any_inst(ground, ground, ground, ground)
|
|
; shared_inst(ground)
|
|
; mostly_uniq_inst(ground).
|
|
|
|
:- pred compiler_key_inst_name_to_dollar_string(
|
|
inst_name::in(compiler_key_inst_name), string::out) is det.
|
|
|
|
compiler_key_inst_name_to_dollar_string(InstName, InstNameStr) :-
|
|
(
|
|
InstName = unify_inst(_, _, _, _),
|
|
InstNameStr = "$unify_inst"
|
|
;
|
|
InstName = merge_inst(_, _),
|
|
InstNameStr = "$merge_inst"
|
|
;
|
|
InstName = ground_inst(_, _, _, _),
|
|
InstNameStr = "$ground_inst"
|
|
;
|
|
InstName = any_inst(_, _, _, _),
|
|
InstNameStr = "$any_inst"
|
|
;
|
|
InstName = shared_inst(_),
|
|
InstNameStr = "$shared_inst"
|
|
;
|
|
InstName = mostly_uniq_inst(_),
|
|
InstNameStr = "$mostly_uniq_inst"
|
|
).
|
|
|
|
:- pred sym_name_to_min_qual_string(inst_msg_info::in,
|
|
sym_name::in, string::out) is det.
|
|
|
|
sym_name_to_min_qual_string(Info, SymName, SymNameStr) :-
|
|
(
|
|
SymName = qualified(ModuleName, BaseName),
|
|
ModuleInfo = Info ^ imi_module_info,
|
|
module_info_get_name(ModuleInfo, CurModuleName),
|
|
( if
|
|
( ModuleName = CurModuleName
|
|
; ModuleName = mercury_public_builtin_module
|
|
)
|
|
then
|
|
SymNameStr = BaseName
|
|
else
|
|
SymNameStr = sym_name_to_string(SymName)
|
|
)
|
|
;
|
|
SymName = unqualified(BaseName),
|
|
SymNameStr = BaseName
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred have_we_expanded_inst_name(expansions_info::in, inst_name::in,
|
|
list(format_piece)::out) is semidet.
|
|
|
|
have_we_expanded_inst_name(Expansions, InstName, PastPieces) :-
|
|
Expansions = expansions_info(ExpansionsMap, _),
|
|
map.search(ExpansionsMap, InstName, PastPieces).
|
|
|
|
:- pred record_user_inst_name(inst_name::in, list(format_piece)::in,
|
|
expansions_info::in, expansions_info::out) is det.
|
|
|
|
record_user_inst_name(InstName, Pieces, !Expansions) :-
|
|
!.Expansions = expansions_info(ExpansionsMap0, ExpansionsCounter0),
|
|
( if map.insert(InstName, Pieces, ExpansionsMap0, ExpansionsMap) then
|
|
!:Expansions = expansions_info(ExpansionsMap, ExpansionsCounter0)
|
|
else
|
|
% An inst_name IN may occur as its own argument, like this:
|
|
%
|
|
% IN(..., IN(...), ...)
|
|
%
|
|
% By the time our caller calls us for the outer occurrence of IN,
|
|
% the code handling an inner occurrence may have already added IN
|
|
% to !Expansions.
|
|
true
|
|
).
|
|
|
|
:- pred record_internal_inst_name(inst_name::in, string::in,
|
|
list(format_piece)::out,
|
|
expansions_info::in, expansions_info::out) is det.
|
|
|
|
record_internal_inst_name(InstName, InstNameStr, InstNumPieces, !Expansions) :-
|
|
!.Expansions = expansions_info(ExpansionsMap0, ExpansionsCounter0),
|
|
counter.allocate(InstNum, ExpansionsCounter0, ExpansionsCounter),
|
|
string.format("internal %s #%d", [s(InstNameStr), i(InstNum)],
|
|
InstNameNumStr),
|
|
InstNumPieces = [fixed(InstNameNumStr)],
|
|
map.det_insert(InstName, InstNumPieces, ExpansionsMap0, ExpansionsMap),
|
|
!:Expansions = expansions_info(ExpansionsMap, ExpansionsCounter).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred pred_inst_info_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
string, uniqueness, pred_inst_info, list(format_piece),
|
|
expansions_info, expansions_info).
|
|
:- mode pred_inst_info_to_pieces(in, in(multi_line_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
:- mode pred_inst_info_to_pieces(in, in(inline_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
|
|
pred_inst_info_to_pieces(Info, MaybeInline, AnyPrefix, Uniq, PredInstInfo,
|
|
Pieces, !Expansions) :-
|
|
PredInstInfo = pred_inst_info(PredOrFunc, ArgModes, _MaybeArgRegs, Det),
|
|
(
|
|
Uniq = shared,
|
|
UniqPieces = []
|
|
;
|
|
( Uniq = unique
|
|
; Uniq = mostly_unique
|
|
; Uniq = clobbered
|
|
; Uniq = mostly_clobbered
|
|
),
|
|
BoundName = mercury_uniqueness_to_string(Uniq, "ground"),
|
|
UniqPieces = [fixed("/*"), fixed(BoundName), fixed("*/")]
|
|
),
|
|
modes_to_pieces(Info, MaybeInline, ArgModes, ArgModesPieces, !Expansions),
|
|
IsDetStr = "is " ++ mercury_det_to_string(Det),
|
|
% XXX Should we print each argument mode on a separate line
|
|
% with multi_line_pieces?
|
|
(
|
|
PredOrFunc = pf_predicate,
|
|
(
|
|
ArgModes = [],
|
|
ModesDetPieces = [fixed("(" ++ AnyPrefix ++ "pred"),
|
|
fixed(IsDetStr), suffix(")")]
|
|
;
|
|
ArgModes = [_ | _],
|
|
JoinedArgModePieces = pieces_strict_list_to_pieces(ArgModesPieces),
|
|
ModesDetPieces = [prefix("(" ++ AnyPrefix ++ "pred(") |
|
|
JoinedArgModePieces] ++
|
|
[suffix(")"), fixed(IsDetStr), suffix(")")]
|
|
)
|
|
;
|
|
PredOrFunc = pf_function,
|
|
pred_args_to_func_args(ArgModesPieces,
|
|
RealArgModePieces, RetModePieces),
|
|
% XXX Should we put parentheses around RetModePieces?
|
|
% If it prints as "InitInst >> FinalInst", then the parentheses
|
|
% could make the output easier to read, but if it prints as a
|
|
% simple name, they would probably be just in the way.
|
|
(
|
|
RealArgModePieces = [],
|
|
ModesDetPieces =
|
|
[fixed("(" ++ AnyPrefix ++ "func =") | RetModePieces] ++
|
|
[fixed(IsDetStr), suffix(")")]
|
|
;
|
|
RealArgModePieces = [_ | _],
|
|
JoinedRealArgModePieces =
|
|
pieces_strict_list_to_pieces(RealArgModePieces),
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
ModesDetPieces =
|
|
[fixed("(" ++ AnyPrefix ++ "func("), nl_indent_delta(1) |
|
|
JoinedRealArgModePieces] ++
|
|
[nl_indent_delta(-1), fixed(") =") | RetModePieces] ++
|
|
[fixed(IsDetStr ++ ")")]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
ModesDetPieces =
|
|
[prefix("(" ++ AnyPrefix ++ "func(") |
|
|
JoinedRealArgModePieces] ++
|
|
[suffix(") =") | RetModePieces] ++
|
|
[fixed(IsDetStr ++ ")")]
|
|
)
|
|
)
|
|
),
|
|
Pieces = UniqPieces ++ ModesDetPieces.
|
|
|
|
%---------------------%
|
|
|
|
:- pred modes_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
list(mer_mode), list(list(format_piece)),
|
|
expansions_info, expansions_info).
|
|
:- mode modes_to_pieces(in, in(multi_line_pieces),
|
|
in, out, in, out) is det.
|
|
:- mode modes_to_pieces(in, in(inline_pieces),
|
|
in, out, in, out) is det.
|
|
|
|
modes_to_pieces(_Info, _, [], [], !Expansions).
|
|
modes_to_pieces(Info, MaybeInline, [HeadMode | TailModes],
|
|
[HeadPieces | TailPieces], !Expansions) :-
|
|
mode_to_pieces(Info, MaybeInline, HeadMode, HeadPieces, !Expansions),
|
|
modes_to_pieces(Info, MaybeInline, TailModes, TailPieces, !Expansions).
|
|
|
|
%---------------------%
|
|
|
|
:- pred mode_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
mer_mode, list(format_piece), expansions_info, expansions_info).
|
|
:- mode mode_to_pieces(in, in(multi_line_pieces), in, out, in, out) is det.
|
|
:- mode mode_to_pieces(in, in(inline_pieces), in, out, in, out) is det.
|
|
|
|
mode_to_pieces(Info, MaybeInline, Mode0, Pieces, !Expansions) :-
|
|
strip_typed_insts_from_mode(Mode0, Mode1),
|
|
(
|
|
Mode1 = from_to_mode(FromInst1, ToInst1),
|
|
insts_to_mode(FromInst1, ToInst1, Mode),
|
|
(
|
|
Mode = from_to_mode(FromInst, ToInst),
|
|
inst_to_pieces(Info, MaybeInline, FromInst, [], FromPieces,
|
|
!Expansions),
|
|
inst_to_pieces(Info, MaybeInline, ToInst, [], ToPieces,
|
|
!Expansions),
|
|
Pieces = FromPieces ++ [fixed(">>") | ToPieces]
|
|
;
|
|
Mode = user_defined_mode(ModeName, ArgInsts),
|
|
user_defined_mode_to_pieces(Info, MaybeInline, ModeName, ArgInsts,
|
|
Pieces, !Expansions)
|
|
)
|
|
;
|
|
Mode1 = user_defined_mode(ModeName, ArgInsts),
|
|
user_defined_mode_to_pieces(Info, MaybeInline, ModeName, ArgInsts,
|
|
Pieces, !Expansions)
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
:- pred user_defined_mode_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
sym_name, list(mer_inst), list(format_piece),
|
|
expansions_info, expansions_info).
|
|
:- mode user_defined_mode_to_pieces(in, in(multi_line_pieces),
|
|
in, in, out, in, out) is det.
|
|
:- mode user_defined_mode_to_pieces(in, in(inline_pieces),
|
|
in, in, out, in, out) is det.
|
|
|
|
user_defined_mode_to_pieces(Info, MaybeInline, ModeName, ArgInsts, Pieces,
|
|
!Expansions) :-
|
|
BaseModeName = unqualify_name(ModeName),
|
|
(
|
|
ArgInsts = [],
|
|
Pieces = [fixed(BaseModeName)]
|
|
;
|
|
ArgInsts = [_ | _],
|
|
arg_insts_to_pieces(Info, MaybeInline, ArgInsts, ArgInstPieces,
|
|
!Expansions),
|
|
Pieces =
|
|
[prefix(BaseModeName ++ "(") |
|
|
pieces_strict_list_to_pieces(ArgInstPieces)] ++
|
|
[suffix(")")]
|
|
).
|
|
|
|
%---------------------%
|
|
|
|
:- pred arg_insts_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
list(mer_inst), list(list(format_piece)),
|
|
expansions_info, expansions_info).
|
|
:- mode arg_insts_to_pieces(in, in(multi_line_pieces),
|
|
in, out, in, out) is det.
|
|
:- mode arg_insts_to_pieces(in, in(inline_pieces),
|
|
in, out, in, out) is det.
|
|
|
|
arg_insts_to_pieces(_Info, _, [], [], !Expansions).
|
|
arg_insts_to_pieces(Info, MaybeInline, [HeadArgInst | TailArgInsts],
|
|
[HeadPieces | TailPieces], !Expansions) :-
|
|
inst_to_pieces(Info, MaybeInline, HeadArgInst, [], HeadPieces,
|
|
!Expansions),
|
|
arg_insts_to_pieces(Info, MaybeInline, TailArgInsts, TailPieces,
|
|
!Expansions).
|
|
|
|
%---------------------%
|
|
|
|
:- pred name_and_arg_insts_to_pieces(inst_msg_info, maybe_inline_pieces,
|
|
string, list(mer_inst), list(format_piece), list(format_piece),
|
|
expansions_info, expansions_info).
|
|
:- mode name_and_arg_insts_to_pieces(in, in(multi_line_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
:- mode name_and_arg_insts_to_pieces(in, in(inline_pieces),
|
|
in, in, in, out, in, out) is det.
|
|
|
|
name_and_arg_insts_to_pieces(Info, MaybeInline, Name, ArgInsts, Suffix, Pieces,
|
|
!Expansions) :-
|
|
(
|
|
ArgInsts = [],
|
|
Pieces = [fixed(Name) | Suffix]
|
|
;
|
|
ArgInsts = [HeadArgInst | TailArgInsts],
|
|
insts_to_pieces(Info, MaybeInline, HeadArgInst, TailArgInsts,
|
|
[], ArgPieces, !Expansions),
|
|
( if summarize_a_few_arg_insts(ArgPieces, 4, ArgSummary) then
|
|
Pieces = [fixed(Name ++ "(" ++ ArgSummary ++ ")") | Suffix]
|
|
else
|
|
(
|
|
MaybeInline = multi_line_pieces,
|
|
Pieces = [fixed(Name), suffix("("), nl_indent_delta(1)] ++
|
|
ArgPieces ++ [nl_indent_delta(-1), fixed(")") | Suffix]
|
|
;
|
|
MaybeInline = inline_pieces,
|
|
Pieces = [prefix(Name ++ "(") | ArgPieces] ++
|
|
[suffix(")") | Suffix]
|
|
)
|
|
)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred summarize_a_few_arg_insts(list(format_piece)::in,
|
|
int::in, string::out) is semidet.
|
|
|
|
summarize_a_few_arg_insts(Pieces, Left, Summary) :-
|
|
Left > 0,
|
|
Pieces = [fixed(FirstFixed) | AfterFirstFixed],
|
|
(
|
|
AfterFirstFixed = [],
|
|
Summary = FirstFixed
|
|
;
|
|
AfterFirstFixed = [suffix(","), nl | TailPieces],
|
|
summarize_a_few_arg_insts(TailPieces, Left - 1, TailSummary),
|
|
Summary = FirstFixed ++ ", " ++ TailSummary
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module hlds.error_msg_inst.
|
|
%---------------------------------------------------------------------------%
|