summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-05-23 02:25:16 +0300
committerZahary Karadjov <zahary@gmail.com>2012-05-23 02:25:16 +0300
commitb1574bb0e00f0d2eeea610a79fb26e60f49f8aef (patch)
treee023d11c920e37b0f2808b0dcbf5bc0b941e646a
parente2221ab3105852b53aa9c1090a4cc9be462f9a06 (diff)
downloadNim-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-xcompiler/parser.nim11
-rwxr-xr-xcompiler/semstmts.nim34
-rwxr-xr-xdoc/manual.txt53
-rwxr-xr-xweb/news.txt1
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