19 Exceptions
Exceptions are sophisticated form of jump instruction. They are used
to inform about unusual situation in a program, in order to transfer
control to block, that can handle it. They can be thought of as member
of a huge union:
union exn {
// system defined
void Std::Null_access;
void Std::Match_failure;
void Std::Not_found;
void Std::End_of_file;
string Std::Invalid_argument;
string Std::Failure;
void Std::Exit;
// user defined, Compiler is name of user module
string Compiler::Syntax_error;
void Compiler::ICE;
}
New members are added with exception keyword, for example one can say
in compiler.g or compiler.gi:
exception string Syntax_error;
exception void ICE;
In order to signal unusual situation, you use raise keyword:
raise Syntax_error["parse error"];
raise ICE;
raise Compiler::ICE[];
At the place, where you know how to handle it, you use try:
try {
open_file();
...
parse();
...
} with {
case Syntax_error[s]:
print_msg(s);
case ICE:
print_msg("Internal Compiler Error");
} finally {
close_file();
}
Statements in try { ... }
are executed. If exception
occurs during this process control is transfered to
with { ... }
part. Exception is then pattern matched
against case clauses there. If it didn't match anything,
it is raised again (to be possibly caught by another enclosing
try block).
No matter how control leaves try block, statements in
finally { ... }
are executed upon exit. This can
be used to release some allocated resources (for example to close a
file, like in our example).
One can omit with { ... }
part and use only
try { ... }
finally { ... }
, or
omit finally { ... }
and use only
try { ... }
with { ... }
.