180180 varStates: Table [ItemId , int ] # Used to detect if local variable belongs to multiple states
181181 finallyPathLen: PNode # int literal
182182
183+ nullifyCurExc: PNode # Empty node, if no yields in tries
184+ restoreExternExc: PNode # Empty node, id no yields in tries
185+
183186const
184187 nkSkip = {nkEmpty.. nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
185188 nkCommentStmt, nkMixinStmt, nkBindStmt, nkTypeOfExpr} + procDefs
@@ -862,7 +865,7 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
862865 retStmt.flags.incl (nfNoRewrite)
863866
864867 let ifBody = newTree (nkIfStmt,
865- newTree (nkElifBranch, excNilCmp, retStmt),
868+ newTree (nkElifBranch, excNilCmp, newTree (nkStmtList, ctx. newRestoreExternException (), retStmt) ),
866869 newTree (nkElse,
867870 newTree (nkStmtList,
868871 newTreeI (nkRaiseStmt, info, ctx.g.emptyNode))))
@@ -917,16 +920,15 @@ proc transformBreakStmt(ctx: var Ctx, n: PNode): PNode =
917920 result = n
918921
919922proc transformReturnStmt (ctx: var Ctx , n: PNode ): PNode =
920- # "Returning" involves jumping along all the cureent finally path.
923+ # "Returning" involves jumping along all the current finally path.
921924 # The last finally should exit to state 0 which is a special case for last exit
922925 # (either return or propagating exception to the caller).
923926 # It is eccounted for in newEndFinallyNode.
924927 result = newNodeI (nkStmtList, n.info)
925928
926929 # Returns prevent exception propagation
927- result .add (ctx.newNullifyCurExc (n.info) )
930+ result .add (ctx.nullifyCurExc )
928931
929- result .add (ctx.newRestoreExternException ())
930932
931933 var finallyChain = newSeq [PNode ]()
932934
@@ -950,6 +952,7 @@ proc transformReturnStmt(ctx: var Ctx, n: PNode): PNode =
950952 result .add (ctx.newJumpAlongFinallyChain (finallyChain, n.info))
951953 else :
952954 # There are no (split) finallies on the path, so we can return right away
955+ result .add (ctx.restoreExternExc)
953956 result .add (n)
954957
955958proc transformBreaksAndReturns (ctx: var Ctx , n: PNode ): PNode =
@@ -960,7 +963,7 @@ proc transformBreaksAndReturns(ctx: var Ctx, n: PNode): PNode =
960963 # of nkContinueStmt: # By this point all relevant continues should be
961964 # lowered to breaks in transf.nim.
962965 of nkReturnStmt:
963- if ctx.curFinallyLevel > 0 and nfNoRewrite notin n.flags:
966+ if nfNoRewrite notin n.flags:
964967 result = ctx.transformReturnStmt (n)
965968 else :
966969 for i in 0 ..< n.len:
@@ -995,7 +998,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
995998 of nkYieldStmt:
996999 result = addGotoOut (result , gotoOut)
9971000 if ctx.curExceptLevel > 0 or ctx.curFinallyLevel > 0 :
998- result = newTree (nkStmtList, ctx.newRestoreExternException () , result )
1001+ result = newTree (nkStmtList, ctx.restoreExternExc , result )
9991002
10001003 of nkElse, nkElseExpr:
10011004 result [0 ] = addGotoOut (result [0 ], gotoOut)
@@ -1469,6 +1472,11 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
14691472
14701473 ctx.curExcLandingState = ctx.newStateLabel ()
14711474 ctx.stateLoopLabel = newSym (skLabel, getIdent (ctx.g.cache, " :stateLoop" ), idgen, fn, fn.info)
1475+
1476+
1477+ ctx.nullifyCurExc = newTree (nkStmtList)
1478+ ctx.restoreExternExc = newTree (nkStmtList)
1479+
14721480 var n = n.toStmtList
14731481 # echo "transformed into ", n
14741482
@@ -1490,6 +1498,9 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
14901498 let finalStateBody = newTree (nkStmtList)
14911499 if ctx.hasExceptions:
14921500 finalStateBody.add (ctx.newRestoreExternException ())
1501+ ctx.nullifyCurExc.add (ctx.newNullifyCurExc (fn.info))
1502+ ctx.restoreExternExc.add (ctx.newRestoreExternException ())
1503+
14931504 finalStateBody.add (newTree (nkGotoState, g.newIntLit (n.info, - 1 )))
14941505 discard ctx.newState (finalStateBody, true , finalState)
14951506
0 commit comments