@@ -174,12 +174,14 @@ type
174174 tempVarId: int # unique name counter
175175 hasExceptions: bool # Does closure have yield in try?
176176 curExcLandingState: PNode
177- curExceptLevel: int
178177 curFinallyLevel: int
179178 idgen: IdGenerator
180179 varStates: Table [ItemId , int ] # Used to detect if local variable belongs to multiple states
181180 finallyPathLen: PNode # int literal
182181
182+ nullifyCurExc: PNode # Empty node, if no yields in tries
183+ restoreExternExc: PNode # Empty node, id no yields in tries
184+
183185const
184186 nkSkip = {nkEmpty.. nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
185187 nkCommentStmt, nkMixinStmt, nkBindStmt, nkTypeOfExpr} + procDefs
@@ -311,7 +313,7 @@ proc hasYields(n: PNode): bool =
311313 break
312314
313315proc newNullifyCurExc (ctx: var Ctx , info: TLineInfo ): PNode =
314- # :curEcx = nil
316+ # :curExc = nil
315317 let curExc = ctx.newCurExcAccess ()
316318 curExc.info = info
317319 let nilnode = newNodeIT (nkNilLit, info, getSysType (ctx.g, info, tyNil))
@@ -862,7 +864,7 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
862864 retStmt.flags.incl (nfNoRewrite)
863865
864866 let ifBody = newTree (nkIfStmt,
865- newTree (nkElifBranch, excNilCmp, retStmt),
867+ newTree (nkElifBranch, excNilCmp, newTree (nkStmtList, ctx. newRestoreExternException (), retStmt) ),
866868 newTree (nkElse,
867869 newTree (nkStmtList,
868870 newTreeI (nkRaiseStmt, info, ctx.g.emptyNode))))
@@ -917,16 +919,15 @@ proc transformBreakStmt(ctx: var Ctx, n: PNode): PNode =
917919 result = n
918920
919921proc transformReturnStmt (ctx: var Ctx , n: PNode ): PNode =
920- # "Returning" involves jumping along all the cureent finally path.
922+ # "Returning" involves jumping along all the current finally path.
921923 # The last finally should exit to state 0 which is a special case for last exit
922924 # (either return or propagating exception to the caller).
923925 # It is eccounted for in newEndFinallyNode.
924926 result = newNodeI (nkStmtList, n.info)
925927
926928 # Returns prevent exception propagation
927- result .add (ctx.newNullifyCurExc (n.info) )
929+ result .add (ctx.nullifyCurExc )
928930
929- result .add (ctx.newRestoreExternException ())
930931
931932 var finallyChain = newSeq [PNode ]()
932933
@@ -950,6 +951,7 @@ proc transformReturnStmt(ctx: var Ctx, n: PNode): PNode =
950951 result .add (ctx.newJumpAlongFinallyChain (finallyChain, n.info))
951952 else :
952953 # There are no (split) finallies on the path, so we can return right away
954+ result .add (ctx.restoreExternExc)
953955 result .add (n)
954956
955957proc transformBreaksAndReturns (ctx: var Ctx , n: PNode ): PNode =
@@ -960,7 +962,7 @@ proc transformBreaksAndReturns(ctx: var Ctx, n: PNode): PNode =
960962 # of nkContinueStmt: # By this point all relevant continues should be
961963 # lowered to breaks in transf.nim.
962964 of nkReturnStmt:
963- if ctx.curFinallyLevel > 0 and nfNoRewrite notin n.flags:
965+ if nfNoRewrite notin n.flags:
964966 result = ctx.transformReturnStmt (n)
965967 else :
966968 for i in 0 ..< n.len:
@@ -994,8 +996,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
994996
995997 of nkYieldStmt:
996998 result = addGotoOut (result , gotoOut)
997- if ctx.curExceptLevel > 0 or ctx.curFinallyLevel > 0 :
998- result = newTree (nkStmtList, ctx.newRestoreExternException (), result )
999+ result = newTree (nkStmtList, ctx.restoreExternExc, result )
9991000
10001001 of nkElse, nkElseExpr:
10011002 result [0 ] = addGotoOut (result [0 ], gotoOut)
@@ -1107,7 +1108,6 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
11071108 tryBody = ctx.transformClosureIteratorBody (tryBody, tryOut)
11081109
11091110 if exceptBody.kind != nkEmpty:
1110- inc ctx.curExceptLevel
11111111 ctx.curExcLandingState = if finallyBody.kind != nkEmpty: finallyLabel
11121112 else : oldExcLandingState
11131113 discard ctx.newState (exceptBody, false , exceptLabel)
@@ -1116,7 +1116,6 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
11161116 exceptBody = ctx.addElseToExcept (exceptBody, normalOut)
11171117 # echo "EXCEPT: ", renderTree(exceptBody)
11181118 exceptBody = ctx.transformClosureIteratorBody (exceptBody, tryOut)
1119- inc ctx.curExceptLevel
11201119
11211120 ctx.curExcLandingState = oldExcLandingState
11221121
@@ -1469,13 +1468,17 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
14691468
14701469 ctx.curExcLandingState = ctx.newStateLabel ()
14711470 ctx.stateLoopLabel = newSym (skLabel, getIdent (ctx.g.cache, " :stateLoop" ), idgen, fn, fn.info)
1471+
1472+
1473+ ctx.nullifyCurExc = newTree (nkStmtList)
1474+ ctx.restoreExternExc = newTree (nkStmtList)
1475+
14721476 var n = n.toStmtList
14731477 # echo "transformed into ", n
14741478
14751479 discard ctx.newState (n, false , nil )
14761480
1477- let finalState = ctx.newStateLabel ()
1478- let gotoOut = newTree (nkGotoState, finalState)
1481+ let gotoOut = newTree (nkGotoState, g.newIntLit (n.info, - 1 ))
14791482
14801483 var ns = false
14811484 n = ctx.lowerStmtListExprs (n, ns)
@@ -1487,11 +1490,9 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
14871490 # Splitting transformation
14881491 discard ctx.transformClosureIteratorBody (n, gotoOut)
14891492
1490- let finalStateBody = newTree (nkStmtList)
14911493 if ctx.hasExceptions:
1492- finalStateBody.add (ctx.newRestoreExternException ())
1493- finalStateBody.add (newTree (nkGotoState, g.newIntLit (n.info, - 1 )))
1494- discard ctx.newState (finalStateBody, true , finalState)
1494+ ctx.nullifyCurExc.add (ctx.newNullifyCurExc (fn.info))
1495+ ctx.restoreExternExc.add (ctx.newRestoreExternException ())
14951496
14961497 # Assign state label indexes
14971498 for i in 0 .. ctx.states.high:
@@ -1510,7 +1511,9 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
15101511 let body = ctx.transformStateAssignments (s.body)
15111512 caseDispatcher.add newTreeI (nkOfBranch, body.info, s.label, body)
15121513
1513- caseDispatcher.add newTreeI (nkElse, n.info, newTreeI (nkReturnStmt, n.info, g.emptyNode))
1514+ caseDispatcher.add newTreeI (nkElse, n.info,
1515+ newTree (nkStmtList, ctx.restoreExternExc,
1516+ newTreeI (nkReturnStmt, n.info, g.emptyNode)))
15141517
15151518 result = wrapIntoStateLoop (ctx, caseDispatcher)
15161519 result = liftLocals (ctx, result )
0 commit comments