diff options
author | Araq <rumpf_a@web.de> | 2014-12-24 13:02:58 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-12-24 13:02:58 +0100 |
commit | 2be3f501a1f94d00cb9a74de5ec13cfcb4443b07 (patch) | |
tree | 76690451f6689c56d832618a7be17beb9506e836 | |
parent | a505918e0ce860e8289844a1a5da8f913998110e (diff) | |
download | Nim-2be3f501a1f94d00cb9a74de5ec13cfcb4443b07.tar.gz |
fixes #1742
-rw-r--r-- | compiler/ccgstmts.nim | 8 | ||||
-rw-r--r-- | compiler/jsgen.nim | 6 | ||||
-rw-r--r-- | compiler/parser.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 14 | ||||
-rw-r--r-- | compiler/vmgen.nim | 2 | ||||
-rw-r--r-- | doc/manual/exceptions.txt | 21 |
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 --------------- |