<< Prev | - Up - | Next >> |
Error
The Error
module is concerned with various tasks related to error reporting. This encompasses the following:
Reporting errors as represented by data-structures called error messages.
Constructing error messages from run-time error conditions in the form of exceptions.
At boot time, the system installs a default exception handler processing all uncaught exceptions. This involves printing out the exception with the mechanisms mentioned above and executing a handler as given by the properties 'errors.toplevel'
and 'errors.subordinate'
, which see.
The central data structure used in this module is the error message. The general format is as follows:
<message> ::= <message label> (
[
kind:
<extended virtual string>]% origin subsystem or component [
msg:
<extended virtual string>]% main message [
items: [
<line>]
]% additional information ...
)
% internal fields
All fields of the record are optional and specify information as indicated by the comments (wherever applicable). It is recommended that both kind
and msg
start with a lower-case letter and do not end in a period.
The label of the record is currently ignored by the procedures from the Error
module, but other system modules expect it to be either error
or warn
, depending on the severity of the condition.
<message label> ::= error
|warn
The items
describe a sequence of lines meant to give additional hints about the error, but one should make sure that the error message is comprehensible without this information. All keys should start with a capital letter.
<line> ::= hint(
[l:
<extended virtual string>][
m:
<extended virtual string>])% key/value pair | <coordinates> % source code error relates to | line(
<extended virtual string>)
% full line of text | unit
% empty line (separator)
<coordinates> ::= pos(
<atom>% file name; ''
if not known<int>
% line number; required <int>
)
% column number; ~1
if not known
An <extended virtual string> is a virtual string that may contain, for convenience, embedded records with special interpretation.
<extended virtual string> ::= <atom> | <int> | <float> | <string> | '#'(
<extended virtual string> ... <extended virtual string>)
| oz(
<value>)
| pn(
<atom>)
| <coordinates> | apply(
<procedure or print name>[
<value>])
| list([
<value>]
<extended virtual string>)
<procedure or print name> ::= <procedure> | <atom>
The embedded records are translated to virtual strings as follows:
oz(
X
)
transforms X
using Value.toVirtualString
, using the print depth and width given by the system properties 'errors.depth'
and 'errors.width'
, respectively.
pn(
+A
)
considers A
to be a variable print name, i. e., escapes non-printable characters according to variable concrete syntax if A
is enclosed in backquotes.
pos(
+A
+I
+I
)
prints out source coordinates, e. g., in file
A
, line
I
, column
I
with the unspecified parts omitted.
apply(
+X
+Ys
)
represents an Oz application of X
to Ys
. Output uses the usual brace notation.
list(
+Xs
+ExtendedVirtualString
)
outputs the values in Xs
as if each was wrapped inside oz(
...)
, inserting ExtendedVirtualString
between every pair of elements.
The error registry has the purpose of storing so-called error formatters under specific keys of type ``literal''. An error formatter P is a procedure with the signature
{
P
+ExceptionR
?MessageR
}
P must be capable of processing any exception having as label any of the keys under which P has been entered into the error registry and must return a <message> as defined above describing the condition. In the case of error or system exceptions, only the record found in the dispatch field of the exception is handed to the formatter.
Error formatters may be invoked by the default exception handler installed at boot time. Possibly dealing with serious conditions, formatters are required to be robust. In particular, the handler flags the thread executing the formatter to be non-blocking, i. e., if it ever blocks on a logic variable, an exception is raised in this thread. This increases chances of any message being output at all. Note that it is allowed to block on futures though and that this flag is not inherited by any created child thread.
The following piece of code illustrates how an error formatter might be registered and how it could behave. Assume a system component called compiler
, which is given ``queries'' to process. If any query is ill-typed, an exception is raised, containing the query, the number of the ill-typed argument, and the expected argument type. Furthermore, an internal
exception is raised when an internal programming assertion is violated. For robustness, an else
case is included to handle any other exceptions. The formatter simply prints out the exception record, since this might help more than no output at all.
{Error.registerFormatter compiler
...
fun {$ E}
T = 'compiler engine error'
BugReport = 'please send a bug report to mozart-bugs@ps.uni-sb.de'
in
case E of compiler(internal X) then
error(kind: T
msg: 'Internal compiler error'
items: [hint(l: 'Additional information' m: oz(X))
line(BugReport)])
elseof compiler(invalidQuery M I A) then
error(kind: T
msg: 'Ill-typed query argument'
items: [hint(l: 'Query' m: oz(M))
hint(l: 'At argument' m: I)
hint(l: 'Expected type' m: A)])
else
error(kind: T
items: [line(oz(E))])
end
end}
exceptionToMessage
{Error.exceptionToMessage
+Exception
?Message
}
constructs a <message> from an exception, using the formatters defined in the error registry or a generic formatter if none is defined for the exception. The message returned by the formatter is enriched with additional fields copied from the exception.
messageToVirtualString
{Error.messageToVirtualString
+Message
?V
}
converts a <message> to a virtual string using the standard layout. This can span several lines and includes the final newline.
extendedVSToVS
{Error.extendedVSToVS
+ExtendedVirtualString
?V
}
converts an <extended virtual string> to a <virtual string>.
printException
{Error.printException
+Exception
}
converts an exception to a message and this to a virtual string, printing the result on standard error (using System.printError
).
registerFormatter
{Error.registerFormatter
+L
+P
}
enters a formatter for exceptions with label L
into the error registry, quietly replacing a possibly existing formatter for L
.
<< Prev | - Up - | Next >> |