stand-alone except and finally blocks

This is equivalent to the on-error and at-scope-exit operators in other languages
This commit is contained in:
Zahary Karadjov 2012-05-23 02:25:16 +03:00
commit b1574bb0e0
4 changed files with 69 additions and 30 deletions

View file

@ -999,6 +999,13 @@ proc parseTry(p: var TParser): PNode =
if b.kind == nkFinally: break if b.kind == nkFinally: break
if b == nil: parMessage(p, errTokenExpected, "except") if b == nil: parMessage(p, errTokenExpected, "except")
proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode =
result = newNodeP(kind, p)
getTok(p)
eat(p, tkColon)
skipComment(p, result)
addSon(result, parseStmt(p))
proc parseFor(p: var TParser): PNode = proc parseFor(p: var TParser): PNode =
result = newNodeP(nkForStmt, p) result = newNodeP(nkForStmt, p)
getTok(p) getTok(p)
@ -1393,6 +1400,8 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkWhile: result = parseWhile(p) of tkWhile: result = parseWhile(p)
of tkCase: result = parseCase(p) of tkCase: result = parseCase(p)
of tkTry: result = parseTry(p) of tkTry: result = parseTry(p)
of tkFinally: result = parseExceptBlock(p, nkFinally)
of tkExcept: result = parseExceptBlock(p, nkExceptBranch)
of tkFor: result = parseFor(p) of tkFor: result = parseFor(p)
of tkBlock: result = parseBlock(p) of tkBlock: result = parseBlock(p)
of tkStatic: result = parseStatic(p) of tkStatic: result = parseStatic(p)

View file

@ -872,6 +872,26 @@ proc SemStmt(c: PContext, n: PNode): PNode =
of nkStmtList: of nkStmtList:
var length = sonsLen(n) var length = sonsLen(n)
for i in countup(0, length - 1): for i in countup(0, length - 1):
case n.sons[i].kind
of nkFinally, nkExceptBranch:
# stand-alone finally and except blocks are
# transformed into regular try blocks:
#
# var f = fopen("somefile") | var f = fopen("somefile")
# finally: fcsole(f) | try:
# ... | ...
# | finally:
# | fclose(f)
var tryStmt = newNodeI(nkTryStmt, n.sons[i].info)
var body = newNodeI(nkStmtList, n.sons[i].info)
if i < n.sonsLen - 1:
body.sons = n.sons[(i+1)..(-1)]
tryStmt.addSon(body)
tryStmt.addSon(n.sons[i])
n.sons[i] = semTry(c, tryStmt)
n.sons.setLen(i+1)
return
else:
n.sons[i] = semStmt(c, n.sons[i]) n.sons[i] = semStmt(c, n.sons[i])
if n.sons[i].kind in LastBlockStmts: if n.sons[i].kind in LastBlockStmts:
for j in countup(i + 1, length - 1): for j in countup(i + 1, length - 1):

View file

@ -1879,6 +1879,15 @@ handled, it is propagated through the call stack. This means that often
the rest of the procedure - that is not within a ``finally`` clause - the rest of the procedure - that is not within a ``finally`` clause -
is not executed (if an exception occurs). is not executed (if an exception occurs).
`except`:idx: and `finally`:idx: can also be used as a stand-alone statements.
Any statements following them in the current block will be considered to be
in an implicit try block:
.. code-block:: nimrod
var f = fopen("numbers.txt", "r")
finally: fcsole(f)
...
Return statement Return statement
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~

View file

@ -97,6 +97,7 @@ Language Additions
- ``when`` expressions are now allowed just like ``if`` expressions. - ``when`` expressions are now allowed just like ``if`` expressions.
- The precedence for operators starting with ``@`` is different now - The precedence for operators starting with ``@`` is different now
allowing for *sigil-like* operators. allowing for *sigil-like* operators.
- Stand-alone ``finally`` and ``except`` blocks are now supported.
2012-02-09 Version 0.8.14 released 2012-02-09 Version 0.8.14 released