Tuple unpacking now works for for vars (#10152)

* Tuple unpacking now works for `for` vars
* Give error if length of tuple vars != length of tuple
* Fix error message showing wrong tuple length
* unpacking now works now for mutable items
* Update changelog
This commit is contained in:
Neelesh Chandola 2019-02-23 18:31:34 +05:30 • committed by Andreas Rumpf
commit 9884129058
7 changed files with 156 additions and 45 deletions

View file

@ -672,28 +672,66 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
# and thus no tuple unpacking:
if iter.kind != tyTuple or length == 3:
if length == 3:
var v = symForVar(c, n.sons[0])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
# BUGFIX: don't use `iter` here as that would strip away
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
# for an example:
v.typ = iterBase
n.sons[0] = newSymNode(v)
if sfGenSym notin v.flags: addForVarDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
if n.sons[0].kind == nkVarTuple:
var mutable = false
if iter.kind == tyVar:
iter = iter.skipTypes({tyVar})
mutable = true
if sonsLen(n[0])-1 != sonsLen(iter):
localError(c.config, n[0].info, errWrongNumberOfVariables)
for i in 0 ..< sonsLen(n[0])-1:
var v = symForVar(c, n[0][i])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
if mutable:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iter[i]
else:
v.typ = iter.sons[i]
n.sons[0][i] = newSymNode(v)
if sfGenSym notin v.flags: addForVarDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
else:
var v = symForVar(c, n.sons[0])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
# BUGFIX: don't use `iter` here as that would strip away
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
# for an example:
v.typ = iterBase
n.sons[0] = newSymNode(v)
if sfGenSym notin v.flags: addForVarDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
else:
localError(c.config, n.info, errWrongNumberOfVariables)
elif length-2 != sonsLen(iter):
localError(c.config, n.info, errWrongNumberOfVariables)
else:
for i in countup(0, length - 3):
var v = symForVar(c, n.sons[i])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
v.typ = iter.sons[i]
n.sons[i] = newSymNode(v)
if sfGenSym notin v.flags:
if not isDiscardUnderscore(v): addForVarDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
if n.sons[i].kind == nkVarTuple:
var mutable = false
if iter[i].kind == tyVar:
iter[i] = iter[i].skipTypes({tyVar})
mutable = true
if sonsLen(n[i])-1 != sonsLen(iter[i]):
localError(c.config, n[i].info, errWrongNumberOfVariables)
for j in 0 ..< sonsLen(n[i])-1:
var v = symForVar(c, n[i][j])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
if mutable:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iter[i][j]
else:
v.typ = iter[i][j]
n.sons[i][j] = newSymNode(v)
if not isDiscardUnderscore(v): addForVarDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
else:
var v = symForVar(c, n.sons[i])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
v.typ = iter.sons[i]
n.sons[i] = newSymNode(v)
if sfGenSym notin v.flags:
if not isDiscardUnderscore(v): addForVarDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
inc(c.p.nestedLoopCounter)
openScope(c)
n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)