Messages are processed in two major phases. The user can influence the behavior of each phase using appropriate hooks, described later.
The first phase is called the message generation phase: it determines the text of the message from the input (the abstract message term). No printing is done here. In this phase the user can change the phrasing or the language of the messages.
The result of the first phase is created in the form of a
format-command list. This is a list whose elements are
format-commands, or the atom nl
denoting the end of a
line. A format-command describes a piece of text not extending
over a line boundary and it can be one of the following:
-
Argsformat(
FormatString,
Args)
format(FormatString, Args).
write_term(
Term,
Options)
write_term(Term, Options).
write_term(
Term)
write_term(
Term,
Options)
where
Options is the actual value of the Prolog flag
toplevel_print_options
.
As an example, let us see what happens in case of the toplevel call
_ =:= 3
. An instantiation error is raised by the Prolog
system, which is caught, and the abstract message term
error(instantiation_error,instantiation_error(_=:=3,1))
is
generated—the first argument is the goal, and the second argument is
the position of the uninstantiated variable within the goal. In the
first phase of message processing this is converted to the following
format-command list:
['Instantiation error'-[],' in argument ~d of ~q'-[1,=:= /2],nl, 'goal: '-[],write_term(_=:=3),nl]
A minor transformation, so-called line splitting is performed on
the message text before it is handed over to the second phase. The
format-command list is broken up along the nl
atoms
into a list of lines, where each line is a list of
format-commands. We will use the term format-command lines
to refer to the result of this transformation.
In the example above, the result of this conversion is the following:
[['Instantiation error'-[],' in argument ~d of ~q'-[1,=:= /2]], ['goal: '-[],write_term(_=:=3)]]
The above format-command lines term is the input of the second phase of message processing.
The second phase is called the message printing phase, this is where the message is actually displayed. The severity of the message is used here to prefix each line of the message with some characters indicating the type of the message, as listed above.
The user can change the exact method of printing (e.g. redirection of messages to a stream, a window, or using different prefixes, etc.) through appropriate hooks.
In our example the following lines are printed by the second phase of processing:
! Instantiation error in argument 1 of =:= /2 ! goal: _=:=3
The user can override the default message processing mechanism in the following two ways:
portray_message/2
, which is the first thing called by message
processing. If this hook exists and succeeds, it overrides
all other processing—nothing further is done by
print_message/2
.