123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- Exception handling
- ==================
- Try statement
- -------------
- Example:
- .. code-block:: nim
- # read the first two lines of a text file that should contain numbers
- # and tries to add them
- var
- f: File
- if open(f, "numbers.txt"):
- try:
- var a = readLine(f)
- var b = readLine(f)
- echo "sum: " & $(parseInt(a) + parseInt(b))
- except OverflowError:
- echo "overflow!"
- except ValueError:
- echo "could not convert string to integer"
- except IOError:
- echo "IO error!"
- except:
- echo "Unknown exception!"
- finally:
- close(f)
- The statements after the ``try`` are executed in sequential order unless
- an exception ``e`` is raised. If the exception type of ``e`` matches any
- listed in an ``except`` clause the corresponding statements are executed.
- The statements following the ``except`` clauses are called
- `exception handlers`:idx:.
- The empty `except`:idx: clause is executed if there is an exception that is
- not listed otherwise. It is similar to an ``else`` clause in ``if`` statements.
- If there is a `finally`:idx: clause, it is always executed after the
- exception handlers.
- The exception is *consumed* in an exception handler. However, an
- exception handler may raise another exception. If the exception is not
- handled, it is propagated through the call stack. This means that often
- the rest of the procedure - that is not within a ``finally`` clause -
- is not executed (if an exception occurs).
- Try expression
- --------------
- Try can also be used as an expression; the type of the ``try`` branch then
- needs to fit the types of ``except`` branches, but the type of the ``finally``
- branch always has to be ``void``:
- .. code-block:: nim
- let x = try: parseInt("133a")
- except: -1
- finally: echo "hi"
- To prevent confusing code there is a parsing limitation; if the ``try``
- follows a ``(`` it has to be written as a one liner:
- .. code-block:: nim
- let x = (try: parseInt("133a") except: -1)
- Except clauses
- --------------
- Within an ``except`` clause, it is possible to use
- ``getCurrentException`` to retrieve the exception that has been
- raised:
- .. code-block:: nim
- try:
- # ...
- except IOError:
- let e = getCurrentException()
- # Now use "e"
- Note that ``getCurrentException`` always returns a ``ref Exception``
- type. If a variable of the proper type is needed (in the example
- above, ``IOError``), one must convert it explicitly:
- .. code-block:: nim
- try:
- # ...
- except IOError:
- let e = (ref IOError)(getCurrentException())
- # "e" is now of the proper type
- However, this is seldom needed. The most common case is to extract an
- error message from ``e``, and for such situations it is enough to use
- ``getCurrentExceptionMsg``:
- .. code-block:: nim
- try:
- # ...
- except IOError:
- echo "I/O error: " & getCurrentExceptionMsg()
- Defer statement
- ---------------
- Instead of a ``try finally`` statement a ``defer`` statement can be used.
- Any statements following the ``defer`` in the current block will be considered
- to be in an implicit try block:
- .. code-block:: nim
- var f = open("numbers.txt")
- defer: close(f)
- f.write "abc"
- f.write "def"
- Is rewritten to:
- .. code-block:: nim
- var f = open("numbers.txt")
- try:
- f.write "abc"
- f.write "def"
- finally:
- close(f)
- Top level ``defer`` statements are not supported
- since it's unclear what such a statement should refer to.
- Raise statement
- ---------------
- Example:
- .. code-block:: nim
- raise newEOS("operating system failed")
- Apart from built-in operations like array indexing, memory allocation, etc.
- the ``raise`` statement is the only way to raise an exception.
- .. XXX document this better!
- If no exception name is given, the current exception is `re-raised`:idx:. The
- `ReraiseError`:idx: exception is raised if there is no exception to
- re-raise. It follows that the ``raise`` statement *always* raises an
- exception.
- Exception hierarchy
- -------------------
- The exception tree is defined in the `system <system.html>`_ module:
- .. include:: ../exception_hierarchy_fragment.txt
|