Exception handling
Try and finally
The try block in Toit is used to execute code following the try statement as a “normal” part of the program.
The finally keyword defines a block of code to run when the try block is final.
The finally block will be executed no matter if the try block raises an error or not.
This can be useful to close objects and clean up resources.
main:
connection ::= device.ConsoleConnection.open
try:
accelerometer := Accelerometer.start
try:
print "started"
while true:
force := movement accelerometer
print
"got movement: $force - moving: $(is-moving force)"
sleep --ms=1000
finally:
accelerometer.close
finally:
connection.closeThrow
The throw keyword in Toit is used to explicitly throw an exception from a
method or any block of code. Any object can be thrown. Currently the core
libraries often throw strings containing error messages. Although it looks like
a keyword, throw is implemented as a function that takes a value to be
thrown.
Catch
Code that may throw an exception can be wrapped in a catch. This is
implemented as a function that takes the possibly throwing code as a block.
Catch will return the thrown object, or null if no object was thrown.
Catch takes two optional arguments
The
--traceargument is a boolean or a block that evaluates to a boolean. It controls whether the caught exception is reported in the console. By default the exception is not reported. Thetraceblock is passed an argument that is the thrown object.The
--unwindargument takes a boolean or a block that evaluates to a boolean. It determines whether the execution stack continues to unwind after the catch. By defaultunwindisfalse. If the block evaluates totruethen the exception will continue to unwind the call stack as if the catch were not present. Theunwindblock is passed the thrown object as an argument, which it can use to determine whether to unwind.
my-function:
my-exception := catch --trace:
code-that-might-throw 42 103
if my-exception:
code-to-run-when-an-exception-was-thrown "foo" "bar"
// Identifies exceptions that we want to catch. Every other
// exception will result in a stack trace on the console and
// an uncaught exception (which may nevertheless be caught
// further up the call stack).
is-bad thrown-object:
return thrown-object != "HARMLESS_ERROR"
my-other-function:
exception := catch
--trace=: | thrown | is-bad thrown
--unwind=: | thrown | is-bad thrown:
code-that-might-throw 42 103
if exception:
// A harmless error was thrown.
code-to-run-when-an-exception-was-thrown "foo" "bar"