added system.onRaise to support a condition system
This commit is contained in:
parent
42c8fd1fe2
commit
865d9cc6e6
7 changed files with 100 additions and 36 deletions
|
|
@ -157,10 +157,8 @@ proc trackPragmaStmt(tracked: PEffects, n: PNode) =
|
|||
var it = n.sons[i]
|
||||
if whichPragma(it) == wEffects:
|
||||
# list the computed effects up to here:
|
||||
pushInfoContext(n.info)
|
||||
listEffects(tracked)
|
||||
popInfoContext()
|
||||
|
||||
|
||||
proc raisesSpec*(n: PNode): PNode =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
|
|
|
|||
|
|
@ -1969,29 +1969,6 @@ a special syntactic extension, the ``when`` construct is also available
|
|||
within ``object`` definitions.
|
||||
|
||||
|
||||
Raise statement
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Syntax::
|
||||
|
||||
raiseStmt ::= 'raise' [expr]
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
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
|
||||
`ENoExceptionToReraise`:idx: exception is raised if there is no exception to
|
||||
re-raise. It follows that the ``raise`` statement *always* raises an
|
||||
exception.
|
||||
|
||||
|
||||
Try statement
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -2060,6 +2037,48 @@ in an implicit try block:
|
|||
...
|
||||
|
||||
|
||||
Raise statement
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Syntax::
|
||||
|
||||
raiseStmt ::= 'raise' [expr]
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
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
|
||||
`ENoExceptionToReraise`:idx: exception is raised if there is no exception to
|
||||
re-raise. It follows that the ``raise`` statement *always* raises an
|
||||
exception (unless a raise hook has been provided).
|
||||
|
||||
|
||||
OnRaise builtin
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
``system.onRaise`` can be used to override the behaviour of ``raise`` for a
|
||||
single ``try`` statement. `onRaise`:idx: has to be called within the ``try``
|
||||
statement that should be affected.
|
||||
|
||||
This allows for a Lisp-like `condition system`:idx:\:
|
||||
|
||||
.. code-block:: nimrod
|
||||
var myFile = open("broken.txt", fmWrite)
|
||||
try:
|
||||
onRaise(proc (e: ref E_Base): bool =
|
||||
stdout.writeln "ok, writing to stdout instead")
|
||||
myFile.writeln "writing to broken file"
|
||||
finally:
|
||||
myFile.close()
|
||||
|
||||
|
||||
Return statement
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -1941,6 +1941,7 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
|||
prev: PSafePoint # points to next safe point ON THE STACK
|
||||
status: int
|
||||
context: C_JmpBuf
|
||||
raiseAction: proc (e: ref E_Base): bool {.closure.}
|
||||
|
||||
when defined(initAllocator):
|
||||
initAllocator()
|
||||
|
|
@ -2040,6 +2041,14 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
|||
var e = getCurrentException()
|
||||
return if e == nil: "" else: e.msg
|
||||
|
||||
proc onRaise*(action: proc(e: ref E_Base): bool{.closure.}) =
|
||||
## can be used in a ``try`` statement to setup a Lisp-like
|
||||
## `condition system`:idx:\: This prevents the 'raise' statement to
|
||||
## raise an exception but instead calls ``action``.
|
||||
## If ``action`` returns false, the exception has been handled and
|
||||
## does not propagate further through the call stack.
|
||||
if not isNil(excHandler): excHandler.raiseAction = action
|
||||
|
||||
{.push stack_trace: off, profiler:off.}
|
||||
when defined(endb):
|
||||
include "system/debugger"
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ proc setFrame(s: PFrame) {.compilerRtl, inl.} =
|
|||
framePtr = s
|
||||
|
||||
proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
||||
s.raiseAction = nil
|
||||
s.prev = excHandler
|
||||
excHandler = s
|
||||
|
||||
|
|
@ -198,8 +199,9 @@ proc raiseExceptionAux(e: ref E_Base) =
|
|||
if globalRaiseHook != nil:
|
||||
if not globalRaiseHook(e): return
|
||||
if excHandler != nil:
|
||||
pushCurrentException(e)
|
||||
c_longjmp(excHandler.context, 1)
|
||||
if isNil(excHandler.raiseAction) or excHandler.raiseAction(e):
|
||||
pushCurrentException(e)
|
||||
c_longjmp(excHandler.context, 1)
|
||||
elif e[] of EOutOfMemory:
|
||||
writeToStdErr(e.name)
|
||||
quitOrDebug()
|
||||
|
|
|
|||
34
tests/run/tonraise.nim
Normal file
34
tests/run/tonraise.nim
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
discard """
|
||||
output: '''i: 1
|
||||
success'''
|
||||
"""
|
||||
|
||||
type
|
||||
ESomething = object of E_Base
|
||||
ESomeOtherErr = object of E_Base
|
||||
|
||||
proc genErrors(s: string) =
|
||||
if s == "error!":
|
||||
raise newException(ESomething, "Test")
|
||||
else:
|
||||
raise newException(EsomeotherErr, "bla")
|
||||
|
||||
proc foo() =
|
||||
var i = 0
|
||||
try:
|
||||
inc i
|
||||
onRaise(proc (e: ref E_Base): bool =
|
||||
echo "i: ", i)
|
||||
genErrors("errssor!")
|
||||
except ESomething:
|
||||
echo("ESomething happened")
|
||||
except:
|
||||
echo("Some other error happened")
|
||||
|
||||
# test that raise handler is gone:
|
||||
try:
|
||||
genErrors("error!")
|
||||
except ESomething:
|
||||
echo "success"
|
||||
|
||||
foo()
|
||||
4
todo.txt
4
todo.txt
|
|
@ -1,7 +1,7 @@
|
|||
version 0.9.2
|
||||
=============
|
||||
|
||||
- implement/generalize the effect system; checked exceptions
|
||||
- implement/generalize the effect system; document checked exceptions
|
||||
- overloading based on ASTs: 'constraint' should not be in PType but for the
|
||||
parameter *symbol*
|
||||
|
||||
|
|
@ -96,8 +96,6 @@ Library
|
|||
Low priority
|
||||
------------
|
||||
|
||||
- make 'raiseHook' take a closure and provide push and pop for this
|
||||
--> Lisp-style condition system
|
||||
- change how comments are part of the AST
|
||||
- ``with proc `+`(x, y: T): T`` for generic code
|
||||
- new feature: ``distinct T with operations``
|
||||
|
|
|
|||
14
web/news.txt
14
web/news.txt
|
|
@ -2,10 +2,10 @@
|
|||
News
|
||||
====
|
||||
|
||||
2012-XX-XX Version 0.9.XX released
|
||||
==================================
|
||||
2012-XX-XX Version 0.9.2 released
|
||||
=================================
|
||||
|
||||
Version 0.8.XX has been released! Get it `here <download.html>`_.
|
||||
Version 0.9.2 has been released! Get it `here <download.html>`_.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
|
@ -15,6 +15,7 @@ Bugfixes
|
|||
Library Additions
|
||||
-----------------
|
||||
|
||||
- Added ``system.onRaise`` to support a condition system.
|
||||
|
||||
|
||||
Changes affecting backwards compatibility
|
||||
|
|
@ -31,8 +32,11 @@ Language Additions
|
|||
------------------
|
||||
|
||||
- ``case expressions`` are now supported.
|
||||
- table constructors now mimic more closely the syntax of case... of...
|
||||
- Nimrod can now infer the return type of a proc from its body
|
||||
- Table constructors now mimic more closely the syntax of the ``case``
|
||||
statement.
|
||||
- Nimrod can now infer the return type of a proc from its body.
|
||||
- Exception tracking has been added and the ``doc2`` command annotates possible
|
||||
exceptions for you.
|
||||
|
||||
|
||||
2012-09-23 Version 0.9.0 released
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue