diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-05-23 02:25:16 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-05-23 02:25:16 +0300 |
commit | b1574bb0e00f0d2eeea610a79fb26e60f49f8aef (patch) | |
tree | e023d11c920e37b0f2808b0dcbf5bc0b941e646a | |
parent | e2221ab3105852b53aa9c1090a4cc9be462f9a06 (diff) | |
download | Nim-b1574bb0e00f0d2eeea610a79fb26e60f49f8aef.tar.gz |
stand-alone except and finally blocks
This is equivalent to the on-error and at-scope-exit operators in other languages
-rwxr-xr-x | compiler/parser.nim | 11 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 34 | ||||
-rwxr-xr-x | doc/manual.txt | 53 | ||||
-rwxr-xr-x | web/news.txt | 1 |
4 files changed, 69 insertions, 30 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 78e39bcd2..13aaec41b 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -998,7 +998,14 @@ proc parseTry(p: var TParser): PNode = addSon(result, b) if b.kind == nkFinally: break 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 = result = newNodeP(nkForStmt, p) getTok(p) @@ -1393,6 +1400,8 @@ proc complexOrSimpleStmt(p: var TParser): PNode = of tkWhile: result = parseWhile(p) of tkCase: result = parseCase(p) of tkTry: result = parseTry(p) + of tkFinally: result = parseExceptBlock(p, nkFinally) + of tkExcept: result = parseExceptBlock(p, nkExceptBranch) of tkFor: result = parseFor(p) of tkBlock: result = parseBlock(p) of tkStatic: result = parseStatic(p) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 6b79326fe..9c5efaf2d 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -871,13 +871,33 @@ proc SemStmt(c: PContext, n: PNode): PNode = of nkBlockStmt: result = semBlock(c, n) of nkStmtList: var length = sonsLen(n) - for i in countup(0, length - 1): - n.sons[i] = semStmt(c, n.sons[i]) - if n.sons[i].kind in LastBlockStmts: - for j in countup(i + 1, length - 1): - case n.sons[j].kind - of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil - else: localError(n.sons[j].info, errStmtInvalidAfterReturn) + 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]) + if n.sons[i].kind in LastBlockStmts: + for j in countup(i + 1, length - 1): + case n.sons[j].kind + of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil + else: localError(n.sons[j].info, errStmtInvalidAfterReturn) of nkRaiseStmt: result = semRaise(c, n) of nkVarSection: result = semVarOrLet(c, n, skVar) of nkLetSection: result = semVarOrLet(c, n, skLet) diff --git a/doc/manual.txt b/doc/manual.txt index 98a8d7122..5359dfc57 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -388,37 +388,37 @@ indentation tokens is already described in the `Lexical Analysis`_ section. Nimrod allows user-definable operators. Binary operators have 10 different levels of precedence. - -Relevant character ------------------- - + +Relevant character +------------------ + An operator symbol's *relevant character* is its first character unless the first character is ``\`` and its length is greater than 1 -then it is the second character. - -This rule allows to escape operator symbols with ``\`` and keeps the operator's -precedence and associativity; this is useful for meta programming. - - -Associativity -------------- - -All binary operators are left-associative, except binary operators whose +then it is the second character. + +This rule allows to escape operator symbols with ``\`` and keeps the operator's +precedence and associativity; this is useful for meta programming. + + +Associativity +------------- + +All binary operators are left-associative, except binary operators whose relevant char is ``^``. - -Precedence ----------- + +Precedence +---------- For operators that are not keywords the precedence is determined by the following rules: If the operator ends with ``=`` and its relevant character is none of ``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which -has the lowest precedence. - -If the operator's relevant character is ``@`` it is a `sigil-like`:idx: -operator which binds stronger than a ``primarySuffix``: ``@x.abc`` is parsed -as ``(@x).abc`` whereas ``$x.abc`` is parsed as ``$(x.abc)``. +has the lowest precedence. + +If the operator's relevant character is ``@`` it is a `sigil-like`:idx: +operator which binds stronger than a ``primarySuffix``: ``@x.abc`` is parsed +as ``(@x).abc`` whereas ``$x.abc`` is parsed as ``$(x.abc)``. Otherwise precedence is determined by the relevant character. @@ -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 - 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 ~~~~~~~~~~~~~~~~ diff --git a/web/news.txt b/web/news.txt index e047cf1fc..d6f2acef2 100755 --- a/web/news.txt +++ b/web/news.txt @@ -97,6 +97,7 @@ Language Additions - ``when`` expressions are now allowed just like ``if`` expressions. - The precedence for operators starting with ``@`` is different now allowing for *sigil-like* operators. +- Stand-alone ``finally`` and ``except`` blocks are now supported. 2012-02-09 Version 0.8.14 released |