summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-12-24 13:02:58 +0100
committerAraq <rumpf_a@web.de>2014-12-24 13:02:58 +0100
commit2be3f501a1f94d00cb9a74de5ec13cfcb4443b07 (patch)
tree76690451f6689c56d832618a7be17beb9506e836
parenta505918e0ce860e8289844a1a5da8f913998110e (diff)
downloadNim-2be3f501a1f94d00cb9a74de5ec13cfcb4443b07.tar.gz
fixes #1742
-rw-r--r--compiler/ccgstmts.nim8
-rw-r--r--compiler/jsgen.nim6
-rw-r--r--compiler/parser.nim2
-rw-r--r--compiler/semstmts.nim14
-rw-r--r--compiler/vmgen.nim2
-rw-r--r--doc/manual/exceptions.txt21
6 files changed, 39 insertions, 14 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index e5848f558..6c7d40d1c 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -798,7 +798,9 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
     startBlock(p)
     var finallyBlock = t.lastSon
     if finallyBlock.kind == nkFinally:
-      expr(p, finallyBlock.sons[0], d)
+      #expr(p, finallyBlock.sons[0], d)
+      genStmts(p, finallyBlock.sons[0])
+
     line(p, cpsStmts, ~"throw;$n")
     endBlock(p)
   
@@ -807,7 +809,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
   
   discard pop(p.nestedTryStmts)
   if (i < length) and (t.sons[i].kind == nkFinally):
-    exprBlock(p, t.sons[i].sons[0], d)
+    genSimpleBlock(p, t.sons[i].sons[0])
   
 proc genTry(p: BProc, t: PNode, d: var TLoc) = 
   # code to generate:
@@ -899,7 +901,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   endBlock(p) # end of else block
   if i < length and t.sons[i].kind == nkFinally:
     p.finallySafePoints.add(safePoint)
-    exprBlock(p, t.sons[i].sons[0], d)
+    genSimpleBlock(p, t.sons[i].sons[0])
     discard pop(p.finallySafePoints)
   linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint)
 
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index c838aa90b..a3423b1d5 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -601,15 +601,13 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
   if p.target == targetJS:
     app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
   if i < length and n.sons[i].kind == nkFinally:
-    gen(p, n.sons[i].sons[0], a)
-    moveInto(p, a, r)
+    genStmt(p, n.sons[i].sons[0])
   if p.target == targetJS:
     app(p.body, "}" & tnl)
   if p.target == targetLua:
     # we need to repeat the finally block for Lua ...
     if i < length and n.sons[i].kind == nkFinally:
-      gen(p, n.sons[i].sons[0], a)
-      moveInto(p, a, r)
+      genStmt(p, n.sons[i].sons[0])
 
 proc genRaiseStmt(p: PProc, n: PNode) =
   genLineDir(p, n)
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 87565ae3a..ff620b5fb 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -505,7 +505,7 @@ proc parsePar(p: var TParser): PNode =
   getTok(p)
   optInd(p, result)
   if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase, 
-                       tkTry, tkFinally, tkExcept, tkFor, tkBlock, 
+                       tkTry, tkDefer, tkFinally, tkExcept, tkFor, tkBlock, 
                        tkConst, tkLet, tkWhen, tkVar,
                        tkMixin}:
     # XXX 'bind' used to be an expression, so we exclude it here;
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 646775aae..152d540c9 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -263,7 +263,8 @@ proc semTry(c: PContext, n: PNode): PNode =
   n.sons[0] = semExprBranchScope(c, n.sons[0])
   typ = commonType(typ, n.sons[0].typ)
   var check = initIntSet()
-  for i in countup(1, sonsLen(n) - 1): 
+  var last = sonsLen(n) - 1
+  for i in countup(1, last):
     var a = n.sons[i]
     checkMinSonsLen(a, 1)
     var length = sonsLen(a)
@@ -282,11 +283,12 @@ proc semTry(c: PContext, n: PNode): PNode =
         a.sons[j].typ = typ
         if containsOrIncl(check, typ.id):
           localError(a.sons[j].info, errExceptionAlreadyHandled)
-    elif a.kind != nkFinally: 
+    elif a.kind != nkFinally:
       illFormedAst(n)
     # last child of an nkExcept/nkFinally branch is a statement:
     a.sons[length-1] = semExprBranchScope(c, a.sons[length-1])
-    typ = commonType(typ, a.sons[length-1].typ)
+    if a.kind != nkFinally: typ = commonType(typ, a.sons[length-1].typ)
+    else: dec last
   dec c.p.inTryStmt
   if isEmptyType(typ) or typ.kind == tyNil:
     discardCheck(c, n.sons[0])
@@ -294,13 +296,14 @@ proc semTry(c: PContext, n: PNode): PNode =
     if typ == enforceVoidContext:
       result.typ = enforceVoidContext
   else:
+    if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon)
     n.sons[0] = fitNode(c, typ, n.sons[0])
-    for i in 1..n.len-1:
+    for i in 1..last:
       var it = n.sons[i]
       let j = it.len-1
       it.sons[j] = fitNode(c, typ, it.sons[j])
     result.typ = typ
-  
+
 proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode = 
   result = fitNode(c, typ, n)
   if result.kind in {nkHiddenStdConv, nkHiddenSubConv}: 
@@ -1251,6 +1254,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
       tryStmt.addSon(deferPart)
       n.sons[i] = semTry(c, tryStmt)
       n.sons.setLen(i+1)
+      n.typ = n.sons[i].typ
       return
     else:
       n.sons[i] = semExpr(c, n.sons[i])
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 7397a562c..c4101874c 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -463,7 +463,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
   # from the stack
   c.gABx(fin, opcFinally, 0, 0)
   if fin.kind == nkFinally:
-    c.gen(fin.sons[0], dest)
+    c.gen(fin.sons[0])
     c.clearDest(n, dest)
   c.gABx(fin, opcFinallyEnd, 0, 0)
 
diff --git a/doc/manual/exceptions.txt b/doc/manual/exceptions.txt
index 311a810ff..e40742e0a 100644
--- a/doc/manual/exceptions.txt
+++ b/doc/manual/exceptions.txt
@@ -47,6 +47,27 @@ 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)
+
+
+
 Defer statement
 ---------------