This commit is contained in:
Araq
2014-12-24 13:02:58 +01:00
parent a505918e0c
commit 2be3f501a1
6 changed files with 39 additions and 14 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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])

View File

@@ -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)

View File

@@ -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
---------------