Fixes 9716 [backport] (#9790)

* reuse temporary variable
* fixes #9716 [backport]
* Declare local vars in safer place
This commit is contained in:
Yuriy Glukhov 2018-11-24 11:50:48 +02:00 • committed by Andreas Rumpf
commit 410fd1deae
4 changed files with 30 additions and 14 deletions

View file

@ -307,11 +307,13 @@ proc genSingleVar(p: BProc, a: PNode) =
proc genClosureVar(p: BProc, a: PNode) = proc genClosureVar(p: BProc, a: PNode) =
var immediateAsgn = a.sons[2].kind != nkEmpty var immediateAsgn = a.sons[2].kind != nkEmpty
if immediateAsgn:
var v: TLoc var v: TLoc
initLocExpr(p, a.sons[0], v) initLocExpr(p, a.sons[0], v)
genLineDir(p, a) genLineDir(p, a)
if immediateAsgn:
loadInto(p, a.sons[0], a.sons[2], v) loadInto(p, a.sons[0], a.sons[2], v)
else:
constructLoc(p, v)
proc genVarStmt(p: BProc, n: PNode) = proc genVarStmt(p: BProc, n: PNode) =
for it in n.sons: for it in n.sons:

View file

@ -1009,7 +1009,7 @@ proc stateFromGotoState(n: PNode): int =
assert(n.kind == nkGotoState) assert(n.kind == nkGotoState)
result = n[0].intVal.int result = n[0].intVal.int
proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode = proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
# This transforms 3 patterns: # This transforms 3 patterns:
########################## 1 ########################## 1
# yield e # yield e
@ -1051,7 +1051,7 @@ proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
result.add(retStmt) result.add(retStmt)
else: else:
for i in 0 ..< n.len: for i in 0 ..< n.len:
n[i] = ctx.tranformStateAssignments(n[i]) n[i] = ctx.transformStateAssignments(n[i])
of nkSkip: of nkSkip:
discard discard
@ -1071,7 +1071,7 @@ proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
else: else:
for i in 0 ..< n.len: for i in 0 ..< n.len:
n[i] = ctx.tranformStateAssignments(n[i]) n[i] = ctx.transformStateAssignments(n[i])
proc skipStmtList(ctx: Ctx; n: PNode): PNode = proc skipStmtList(ctx: Ctx; n: PNode): PNode =
result = n result = n
@ -1220,18 +1220,20 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
# while true: # while true:
# block :stateLoop: # block :stateLoop:
# gotoState :state # gotoState :state
# local vars decl (if needed)
# body # Might get wrapped in try-except # body # Might get wrapped in try-except
let loopBody = newNodeI(nkStmtList, n.info) let loopBody = newNodeI(nkStmtList, n.info)
result = newTree(nkWhileStmt, newSymNode(ctx.g.getSysSym(n.info, "true")), loopBody) result = newTree(nkWhileStmt, newSymNode(ctx.g.getSysSym(n.info, "true")), loopBody)
result.info = n.info result.info = n.info
let localVars = newNodeI(nkStmtList, n.info)
if not ctx.stateVarSym.isNil: if not ctx.stateVarSym.isNil:
let varSect = newNodeI(nkVarSection, n.info) let varSect = newNodeI(nkVarSection, n.info)
addVar(varSect, newSymNode(ctx.stateVarSym)) addVar(varSect, newSymNode(ctx.stateVarSym))
loopBody.add(varSect) localVars.add(varSect)
if not ctx.tempVars.isNil: if not ctx.tempVars.isNil:
loopBody.add(ctx.tempVars) localVars.add(ctx.tempVars)
let blockStmt = newNodeI(nkBlockStmt, n.info) let blockStmt = newNodeI(nkBlockStmt, n.info)
blockStmt.add(newSymNode(ctx.stateLoopLabel)) blockStmt.add(newSymNode(ctx.stateLoopLabel))
@ -1240,7 +1242,7 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
gs.add(ctx.newStateAccess()) gs.add(ctx.newStateAccess())
gs.add(ctx.g.newIntLit(n.info, ctx.states.len - 1)) gs.add(ctx.g.newIntLit(n.info, ctx.states.len - 1))
var blockBody = newTree(nkStmtList, gs, n) var blockBody = newTree(nkStmtList, gs, localVars, n)
if ctx.hasExceptions: if ctx.hasExceptions:
blockBody = ctx.wrapIntoTryExcept(blockBody) blockBody = ctx.wrapIntoTryExcept(blockBody)
@ -1292,7 +1294,6 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
# should folllow the same logic. # should folllow the same logic.
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info) ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn) ctx.stateVarSym.typ = g.createClosureIterStateType(fn)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info) ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info)
var n = n.toStmtList var n = n.toStmtList
@ -1320,7 +1321,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
result.add(s) result.add(s)
result.add(body) result.add(body)
result = ctx.tranformStateAssignments(result) result = ctx.transformStateAssignments(result)
result = ctx.wrapIntoStateLoop(result) result = ctx.wrapIntoStateLoop(result)
# echo "TRANSFORM TO STATES: " # echo "TRANSFORM TO STATES: "

View file

@ -218,7 +218,7 @@ when defineSsl:
var data = await recv(socket.fd.AsyncFD, BufferSize, flags) var data = await recv(socket.fd.AsyncFD, BufferSize, flags)
let length = len(data) let length = len(data)
if length > 0: if length > 0:
let ret = bioWrite(socket.bioIn, addr data[0], data.len.cint) let ret = bioWrite(socket.bioIn, addr data[0], length.cint)
if ret < 0: if ret < 0:
raiseSSLError() raiseSSLError()
elif length == 0: elif length == 0:

View file

@ -454,5 +454,18 @@ block: #9694 - yield in ObjConstr
test(it, 1, 2) test(it, 1, 2)
block: #9716
iterator it(): int {.closure.} =
var a = 0
for i in 1 .. 3:
var a: int # Make sure the "local" var is reset
var b: string # ditto
yield 1
a += 5
b &= "hello"
doAssert(a == 5)
doAssert(b == "hello")
test(it, 1, 1, 1)
echo "ok" echo "ok"