fixes #1742
This commit is contained in:
parent
a505918e0c
commit
2be3f501a1
6 changed files with 39 additions and 14 deletions
|
|
@ -798,7 +798,9 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
startBlock(p)
|
startBlock(p)
|
||||||
var finallyBlock = t.lastSon
|
var finallyBlock = t.lastSon
|
||||||
if finallyBlock.kind == nkFinally:
|
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")
|
line(p, cpsStmts, ~"throw;$n")
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
||||||
|
|
@ -807,7 +809,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
|
|
||||||
discard pop(p.nestedTryStmts)
|
discard pop(p.nestedTryStmts)
|
||||||
if (i < length) and (t.sons[i].kind == nkFinally):
|
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) =
|
proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
# code to generate:
|
# code to generate:
|
||||||
|
|
@ -899,7 +901,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
endBlock(p) # end of else block
|
endBlock(p) # end of else block
|
||||||
if i < length and t.sons[i].kind == nkFinally:
|
if i < length and t.sons[i].kind == nkFinally:
|
||||||
p.finallySafePoints.add(safePoint)
|
p.finallySafePoints.add(safePoint)
|
||||||
exprBlock(p, t.sons[i].sons[0], d)
|
genSimpleBlock(p, t.sons[i].sons[0])
|
||||||
discard pop(p.finallySafePoints)
|
discard pop(p.finallySafePoints)
|
||||||
linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint)
|
linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -601,15 +601,13 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
if p.target == targetJS:
|
if p.target == targetJS:
|
||||||
app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
|
app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
|
||||||
if i < length and n.sons[i].kind == nkFinally:
|
if i < length and n.sons[i].kind == nkFinally:
|
||||||
gen(p, n.sons[i].sons[0], a)
|
genStmt(p, n.sons[i].sons[0])
|
||||||
moveInto(p, a, r)
|
|
||||||
if p.target == targetJS:
|
if p.target == targetJS:
|
||||||
app(p.body, "}" & tnl)
|
app(p.body, "}" & tnl)
|
||||||
if p.target == targetLua:
|
if p.target == targetLua:
|
||||||
# we need to repeat the finally block for Lua ...
|
# we need to repeat the finally block for Lua ...
|
||||||
if i < length and n.sons[i].kind == nkFinally:
|
if i < length and n.sons[i].kind == nkFinally:
|
||||||
gen(p, n.sons[i].sons[0], a)
|
genStmt(p, n.sons[i].sons[0])
|
||||||
moveInto(p, a, r)
|
|
||||||
|
|
||||||
proc genRaiseStmt(p: PProc, n: PNode) =
|
proc genRaiseStmt(p: PProc, n: PNode) =
|
||||||
genLineDir(p, n)
|
genLineDir(p, n)
|
||||||
|
|
|
||||||
|
|
@ -505,7 +505,7 @@ proc parsePar(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase,
|
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,
|
tkConst, tkLet, tkWhen, tkVar,
|
||||||
tkMixin}:
|
tkMixin}:
|
||||||
# XXX 'bind' used to be an expression, so we exclude it here;
|
# XXX 'bind' used to be an expression, so we exclude it here;
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,8 @@ proc semTry(c: PContext, n: PNode): PNode =
|
||||||
n.sons[0] = semExprBranchScope(c, n.sons[0])
|
n.sons[0] = semExprBranchScope(c, n.sons[0])
|
||||||
typ = commonType(typ, n.sons[0].typ)
|
typ = commonType(typ, n.sons[0].typ)
|
||||||
var check = initIntSet()
|
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]
|
var a = n.sons[i]
|
||||||
checkMinSonsLen(a, 1)
|
checkMinSonsLen(a, 1)
|
||||||
var length = sonsLen(a)
|
var length = sonsLen(a)
|
||||||
|
|
@ -286,7 +287,8 @@ proc semTry(c: PContext, n: PNode): PNode =
|
||||||
illFormedAst(n)
|
illFormedAst(n)
|
||||||
# last child of an nkExcept/nkFinally branch is a statement:
|
# last child of an nkExcept/nkFinally branch is a statement:
|
||||||
a.sons[length-1] = semExprBranchScope(c, a.sons[length-1])
|
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
|
dec c.p.inTryStmt
|
||||||
if isEmptyType(typ) or typ.kind == tyNil:
|
if isEmptyType(typ) or typ.kind == tyNil:
|
||||||
discardCheck(c, n.sons[0])
|
discardCheck(c, n.sons[0])
|
||||||
|
|
@ -294,8 +296,9 @@ proc semTry(c: PContext, n: PNode): PNode =
|
||||||
if typ == enforceVoidContext:
|
if typ == enforceVoidContext:
|
||||||
result.typ = enforceVoidContext
|
result.typ = enforceVoidContext
|
||||||
else:
|
else:
|
||||||
|
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon)
|
||||||
n.sons[0] = fitNode(c, typ, n.sons[0])
|
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]
|
var it = n.sons[i]
|
||||||
let j = it.len-1
|
let j = it.len-1
|
||||||
it.sons[j] = fitNode(c, typ, it.sons[j])
|
it.sons[j] = fitNode(c, typ, it.sons[j])
|
||||||
|
|
@ -1251,6 +1254,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
tryStmt.addSon(deferPart)
|
tryStmt.addSon(deferPart)
|
||||||
n.sons[i] = semTry(c, tryStmt)
|
n.sons[i] = semTry(c, tryStmt)
|
||||||
n.sons.setLen(i+1)
|
n.sons.setLen(i+1)
|
||||||
|
n.typ = n.sons[i].typ
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
n.sons[i] = semExpr(c, n.sons[i])
|
n.sons[i] = semExpr(c, n.sons[i])
|
||||||
|
|
|
||||||
|
|
@ -463,7 +463,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
# from the stack
|
# from the stack
|
||||||
c.gABx(fin, opcFinally, 0, 0)
|
c.gABx(fin, opcFinally, 0, 0)
|
||||||
if fin.kind == nkFinally:
|
if fin.kind == nkFinally:
|
||||||
c.gen(fin.sons[0], dest)
|
c.gen(fin.sons[0])
|
||||||
c.clearDest(n, dest)
|
c.clearDest(n, dest)
|
||||||
c.gABx(fin, opcFinallyEnd, 0, 0)
|
c.gABx(fin, opcFinallyEnd, 0, 0)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,27 @@ the rest of the procedure - that is not within a ``finally`` clause -
|
||||||
is not executed (if an exception occurs).
|
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
|
Defer statement
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue