Normally, whenever a piece of MOO code raises an error, the entire task is
aborted and a message printed to the user. Often, such errors can be
anticipated in advance by the programmer and code written to deal with them in
a more graceful manner. The try
-except
statement allows you to
do this; the syntax is as follows:
try statements-0 except variable-1 (codes-1) statements-1 except variable-2 (codes-2) statements-2 ... endtry
where the variables may be omitted and each codes part is either
the keyword ANY
or else a comma-separated list of expressions, just like
an argument list. As in an argument list, the splicing operator (`@')
can be used here. There can be anywhere from 1 to 255 except
clauses.
First, each codes part is evaluated, yielding a list of error codes that
should be caught if they're raised; if a codes is ANY
, then it is
equivalent to the list of all possible MOO values.
Next, statements-0 is executed; if it doesn't raise an error, then that's
all that happens for the entire try
-except
statement. Otherwise,
let E be the error it raises. From top to bottom, E is searched
for in the lists resulting from the various codes parts; if it isn't
found in any of them, then it continues to be raised, possibly to be caught by
some piece of code either surrounding this try
-except
statement
or higher up on the verb-call stack.
If E is found first in codes-i, then variable-i (if provided) is assigned a value containing information about the error being raised and statements-i is executed. The value assigned to variable-i is a list of four elements:
{code, message, value, traceback}
where code is E, the error being raised, message and
value are as provided by the code that raised the error, and
traceback is a list like that returned by the `callers()' function,
including line numbers. The traceback list contains entries for every
verb from the one that raised the error through the one containing this
try
-except
statement.
Unless otherwise mentioned, all of the built-in errors raised by expressions,
statements, and functions provide tostr(code)
as message and
zero as value.
Here's an example of the use of this kind of statement:
try result = object:(command)(@arguments); player:tell("=> ", toliteral(result)); except v (ANY) tb = v[4]; if (length(tb) == 1) player:tell("** Illegal command: ", v[2]); else top = tb[1]; tb[1..1] = {}; player:tell(top[1], ":", top[2], ", line ", top[6], ":", v[2]); for fr in (tb) player:tell("... called from ", fr[1], ":", fr[2], ", line ", fr[6]); endfor player:tell("(End of traceback)"); endif endtry