summary refs log tree commit diff stats
path: root/compiler/semstmts.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semstmts.nim')
-rw-r--r--compiler/semstmts.nim70
1 files changed, 54 insertions, 16 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 363049672..aa0230f2f 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -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)