summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/ccgexprs.nim4
-rw-r--r--compiler/dfa.nim2
-rw-r--r--compiler/evalffi.nim6
-rw-r--r--compiler/jsgen.nim8
-rw-r--r--compiler/parser.nim6
-rw-r--r--compiler/pragmas.nim4
-rw-r--r--compiler/renderer.nim8
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semexprs.nim20
-rw-r--r--compiler/semfold.nim6
-rw-r--r--compiler/semmacrosanity.nim2
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/semstmts.nim4
-rw-r--r--compiler/semtypes.nim5
-rw-r--r--compiler/transf.nim6
-rw-r--r--compiler/trees.nim2
-rw-r--r--compiler/vm.nim18
-rw-r--r--compiler/vmdeps.nim2
-rw-r--r--compiler/vmgen.nim6
-rw-r--r--compiler/vmmarshal.nim2
-rw-r--r--compiler/vmops.nim4
-rw-r--r--compiler/writetracking.nim4
23 files changed, 72 insertions, 54 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index aa7250513..da7e828f2 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -221,7 +221,8 @@ type
     nkGotoState,          # used for the state machine (for iterators)
     nkState,              # give a label to a code section (for iterators)
     nkBreakState,         # special break statement for easier code generation
-    nkFuncDef             # a func
+    nkFuncDef,            # a func
+    nkTupleConstr         # a tuple constructor
 
   TNodeKinds* = set[TNodeKind]
 
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 5888f6430..7e3c2632a 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -2226,7 +2226,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
       genSeqConstr(p, n, d)
     else:
       genArrayConstr(p, n, d)
-  of nkPar:
+  of nkPar, nkTupleConstr:
     if isDeepConstExpr(n) and n.len != 0:
       exprComplexConst(p, n, d)
     else:
@@ -2458,7 +2458,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
     var cs: TBitSet
     toBitSet(n, cs)
     result = genRawSetData(cs, int(getSize(n.typ)))
-  of nkBracket, nkPar, nkClosure:
+  of nkBracket, nkPar, nkTupleConstr, nkClosure:
     var t = skipTypes(n.typ, abstractInst)
     if t.kind == tySequence:
       result = genConstSeq(p, n, n.typ)
diff --git a/compiler/dfa.nim b/compiler/dfa.nim
index b648995f4..bc9d13870 100644
--- a/compiler/dfa.nim
+++ b/compiler/dfa.nim
@@ -323,7 +323,7 @@ proc gen(c: var Con; n: PNode) =
   of nkBreakStmt: genBreak(c, n)
   of nkTryStmt: genTry(c, n)
   of nkStmtList, nkStmtListExpr, nkChckRangeF, nkChckRange64, nkChckRange,
-     nkBracket, nkCurly, nkPar, nkClosure, nkObjConstr:
+     nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr:
     for x in n: gen(c, x)
   of nkPragmaBlock: gen(c, n.lastSon)
   of nkDiscardStmt: gen(c, n.sons[0])
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index 5bf8f358a..0e3d0609d 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -151,7 +151,7 @@ proc getField(n: PNode; position: int): PSym =
   else: discard
 
 proc packObject(x: PNode, typ: PType, res: pointer) =
-  internalAssert x.kind in {nkObjConstr, nkPar}
+  internalAssert x.kind in {nkObjConstr, nkPar, nkTupleConstr}
   # compute the field's offsets:
   discard typ.getSize
   for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
@@ -260,14 +260,14 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
   # iterate over any actual field of 'n' ... if n is nil we need to create
   # the nkPar node:
   if n.isNil:
-    result = newNode(nkPar)
+    result = newNode(nkTupleConstr)
     result.typ = typ
     if typ.n.isNil:
       internalError("cannot unpack unnamed tuple")
     unpackObjectAdd(x, typ.n, result)
   else:
     result = n
-    if result.kind notin {nkObjConstr, nkPar}:
+    if result.kind notin {nkObjConstr, nkPar, nkTupleConstr}:
       globalError(n.info, "cannot map value from FFI")
     if typ.n.isNil:
       globalError(n.info, "cannot unpack unnamed tuple")
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index dc74fa933..357708bb9 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -307,7 +307,7 @@ proc useMagic(p: PProc, name: string) =
 
 proc isSimpleExpr(p: PProc; n: PNode): bool =
   # calls all the way down --> can stay expression based
-  if n.kind in nkCallKinds+{nkBracketExpr, nkDotExpr, nkPar} or
+  if n.kind in nkCallKinds+{nkBracketExpr, nkDotExpr, nkPar, nkTupleConstr} or
       (p.target == targetJS and n.kind in {nkObjConstr, nkBracket, nkCurly}):
     for c in n:
       if not p.isSimpleExpr(c): return false
@@ -894,7 +894,7 @@ proc countJsParams(typ: PType): int =
 
 const
   nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
-    nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString,
+    nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkTupleConstr, nkObjConstr, nkStringToCString,
     nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix,
     nkCommand, nkHiddenCallConv, nkCallStrLit}
 
@@ -1714,7 +1714,7 @@ proc genToArray(p: PProc; n: PNode; r: var TCompRes) =
   if x.kind == nkBracket:
     for i in countup(0, x.len - 1):
       let it = x[i]
-      if it.kind == nkPar and it.len == 2:
+      if it.kind in {nkPar, nkTupleConstr} and it.len == 2:
         if i > 0: r.res.add(", ")
         gen(p, it[0], a)
         gen(p, it[1], b)
@@ -2309,7 +2309,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
   of nkClosure: gen(p, n[0], r)
   of nkCurly: genSetConstr(p, n, r)
   of nkBracket: genArrayConstr(p, n, r)
-  of nkPar: genTupleConstr(p, n, r)
+  of nkPar, nkTupleConstr: genTupleConstr(p, n, r)
   of nkObjConstr: genObjConstr(p, n, r)
   of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
   of nkAddr, nkHiddenAddr:
diff --git a/compiler/parser.nim b/compiler/parser.nim
index c14330ec2..c8edd5136 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -399,6 +399,9 @@ proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
     addSon(result, a)
     if p.tok.tokType != tkComma: break
     getTok(p)
+    # (1,) produces a tuple expression
+    if endTok == tkParRi and p.tok.tokType == tkParRi:
+      result.kind = nkTupleConstr
     skipComment(p, a)
   optPar(p)
   eat(p, endTok)
@@ -566,6 +569,9 @@ proc parsePar(p: var TParser): PNode =
       if p.tok.tokType == tkComma:
         getTok(p)
         skipComment(p, a)
+        # (1,) produces a tuple expression:
+        if p.tok.tokType == tkParRi:
+          result.kind = nkTupleConstr
         # progress guaranteed
         while p.tok.tokType != tkParRi and p.tok.tokType != tkEof:
           var a = exprColonEqExpr(p)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index d5fed7640..bb7801f6f 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -423,7 +423,7 @@ proc processCompile(c: PContext, n: PNode) =
       result = ""
 
   let it = if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] else: n
-  if it.kind == nkPar and it.len == 2:
+  if it.kind in {nkPar, nkTupleConstr} and it.len == 2:
     let s = getStrLit(c, it, 0)
     let dest = getStrLit(c, it, 1)
     var found = parentDir(n.info.toFullPath) / s
@@ -530,7 +530,7 @@ proc pragmaLine(c: PContext, n: PNode) =
   if n.kind in nkPragmaCallKinds and n.len == 2:
     n.sons[1] = c.semConstExpr(c, n.sons[1])
     let a = n.sons[1]
-    if a.kind == nkPar:
+    if a.kind in {nkPar, nkTupleConstr}:
       # unpack the tuple
       var x = a.sons[0]
       var y = a.sons[1]
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 0b1b0479f..7d513afb1 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -437,6 +437,9 @@ proc lsub(g: TSrcGen; n: PNode): int =
   of nkCommand: result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + 1
   of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(g, n) + 3
   of nkPar, nkCurly, nkBracket, nkClosure: result = lcomma(g, n) + 2
+  of nkTupleConstr:
+    # assume the trailing comma:
+    result = lcomma(g, n) + 3
   of nkArgList: result = lcomma(g, n)
   of nkTableConstr:
     result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}")
@@ -1007,6 +1010,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     put(g, tkParLe, "(")
     gcomma(g, n, c)
     put(g, tkParRi, ")")
+  of nkTupleConstr:
+    put(g, tkParLe, "(")
+    gcomma(g, n, c)
+    if n.len == 1: put(g, tkComma, ",")
+    put(g, tkParRi, ")")
   of nkCurly:
     put(g, tkCurlyLe, "{")
     gcomma(g, n, c)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 937f1637a..4fef1bc60 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -85,7 +85,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
       result.typ = formal
     else:
       let x = result.skipConv
-      if x.kind == nkPar and formal.kind != tyExpr:
+      if x.kind in {nkPar, nkTupleConstr} and formal.kind != tyExpr:
         changeType(x, formal, check=true)
       else:
         result = skipHiddenSubConv(result)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index a523bfc9e..4256e0aa6 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -215,7 +215,7 @@ proc semConv(c: PContext, n: PNode): PNode =
       # handle SomeProcType(SomeGenericProc)
       if op.kind == nkSym and op.sym.isGenericRoutine:
         result.sons[1] = fitNode(c, result.typ, result.sons[1], result.info)
-      elif op.kind == nkPar and targetType.kind == tyTuple:
+      elif op.kind in {nkPar, nkTupleConstr} and targetType.kind == tyTuple:
         op = fitNode(c, targetType, op, result.info)
     of convNotNeedeed:
       message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString)
@@ -364,7 +364,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
   of nkCurly, nkBracket:
     for i in countup(0, sonsLen(n) - 1):
       changeType(n.sons[i], elemType(newType), check)
-  of nkPar:
+  of nkPar, nkTupleConstr:
     let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink})
     if tup.kind != tyTuple:
       if tup.kind == tyObject: return
@@ -1402,7 +1402,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
     result = buildOverloadedSubscripts(n.sons[0], getIdent"{}=")
     add(result, n[1])
     return semExprNoType(c, result)
-  of nkPar:
+  of nkPar, nkTupleConstr:
     if a.len >= 2:
       # unfortunately we need to rewrite ``(x, y) = foo()`` already here so
       # that overloading of the assignment operator still works. Usually we
@@ -1521,10 +1521,10 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
       var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
       if e.kind in {tyVar, tyLent}:
         if e.kind == tyVar: e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
-        if n.sons[0].kind == nkPar:
+        if n.sons[0].kind in {nkPar, nkTupleConstr}:
           n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i], e.kind == tyLent)
         elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
-             n.sons[0].sons[1].kind == nkPar:
+             n.sons[0].sons[1].kind in {nkPar, nkTupleConstr}:
           var a = n.sons[0].sons[1]
           a.sons[i] = takeImplicitAddr(c, a.sons[i], false)
         else:
@@ -2047,12 +2047,12 @@ proc semTableConstr(c: PContext, n: PNode): PNode =
     var x = n.sons[i]
     if x.kind == nkExprColonExpr and sonsLen(x) == 2:
       for j in countup(lastKey, i-1):
-        var pair = newNodeI(nkPar, x.info)
+        var pair = newNodeI(nkTupleConstr, x.info)
         pair.add(n.sons[j])
         pair.add(x[1])
         result.add(pair)
 
-      var pair = newNodeI(nkPar, x.info)
+      var pair = newNodeI(nkTupleConstr, x.info)
       pair.add(x[0])
       pair.add(x[1])
       result.add(pair)
@@ -2072,6 +2072,7 @@ proc checkPar(n: PNode): TParKind =
     result = paTuplePositions # ()
   elif length == 1:
     if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
+    elif n.kind == nkTupleConstr: result = paTuplePositions
     else: result = paSingle         # (expr)
   else:
     if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
@@ -2088,7 +2089,7 @@ proc checkPar(n: PNode): TParKind =
           return paNone
 
 proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
-  result = newNodeI(nkPar, n.info)
+  result = newNodeI(nkTupleConstr, n.info)
   var typ = newTypeS(tyTuple, c)
   typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
   var ids = initIntSet()
@@ -2113,6 +2114,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
 
 proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = n                  # we don't modify n, but compute the type:
+  result.kind = nkTupleConstr
   var typ = newTypeS(tyTuple, c)  # leave typ.n nil!
   for i in countup(0, sonsLen(n) - 1):
     n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor})
@@ -2344,7 +2346,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       invalidPragma(n)
 
     result = semExpr(c, n[0], flags)
-  of nkPar:
+  of nkPar, nkTupleConstr:
     case checkPar(n)
     of paNone: result = errorNode(c, n)
     of paTuplePositions:
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 62bab4edb..096fc19e0 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -427,7 +427,7 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
 
   var idx = getOrdValue(y)
   case x.kind
-  of nkPar:
+  of nkPar, nkTupleConstr:
     if idx >= 0 and idx < sonsLen(x):
       result = x.sons[int(idx)]
       if result.kind == nkExprColonExpr: result = result.sons[1]
@@ -450,7 +450,7 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
 proc foldFieldAccess(m: PSym, n: PNode): PNode =
   # a real field access; proc calls have already been transformed
   var x = getConstExpr(m, n.sons[0])
-  if x == nil or x.kind notin {nkObjConstr, nkPar}: return
+  if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
 
   var field = n.sons[1].sym
   for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
@@ -624,7 +624,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
   #    if a == nil: return nil
   #    result.sons[i].sons[1] = a
   #  incl(result.flags, nfAllConst)
-  of nkPar:
+  of nkPar, nkTupleConstr:
     # tuple constructor
     result = copyTree(n)
     if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim
index fe9bb6c8d..f6df67441 100644
--- a/compiler/semmacrosanity.nim
+++ b/compiler/semmacrosanity.nim
@@ -50,7 +50,7 @@ proc annotateType*(n: PNode, t: PType) =
       else:
         internalAssert(n.sons[i].kind == nkExprColonExpr)
         annotateType(n.sons[i].sons[1], field.typ)
-  of nkPar:
+  of nkPar, nkTupleConstr:
     if x.kind == tyTuple:
       n.typ = t
       for i in 0 ..< n.len:
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 9031e4640..3f0df0065 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -73,7 +73,7 @@ proc expectIntLit(c: PContext, n: PNode): int =
   else: localError(n.info, errIntLiteralExpected)
 
 proc semInstantiationInfo(c: PContext, n: PNode): PNode =
-  result = newNodeIT(nkPar, n.info, n.typ)
+  result = newNodeIT(nkTupleConstr, n.info, n.typ)
   let idx = expectIntLit(c, n.sons[1])
   let useFullPaths = expectIntLit(c, n.sons[2])
   let info = getInfoContext(idx)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index c53ff9803..3de26344c 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -552,7 +552,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
         b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
         b.sons[length-1] = def
         addToVarSection(c, result, n, b)
-    elif tup.kind == tyTuple and def.kind == nkPar and
+    elif tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
         a.kind == nkIdentDefs and a.len > 3:
       message(a.info, warnEachIdentIsTuple)
 
@@ -592,7 +592,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
         addSon(b, copyTree(def))
         addToVarSection(c, result, n, b)
       else:
-        if def.kind == nkPar: v.ast = def[j]
+        if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j]
         setVarType(v, tup.sons[j])
         b.sons[j] = newSymNode(v)
       checkNilable(v)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index a23ee01e1..1fc263617 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -392,8 +392,8 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
   if sonsLen(n) == 0:
     localError(n.info, errTypeExpected)
   result = newOrPrevType(tyTuple, prev, c)
-  for i in countup(0, sonsLen(n) - 1):
-    addSonSkipIntLit(result, semTypeNode(c, n.sons[i], nil))
+  for it in n:
+    addSonSkipIntLit(result, semTypeNode(c, it, nil))
 
 proc semTuple(c: PContext, n: PNode, prev: PType): PType =
   var typ: PType
@@ -1341,6 +1341,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
     else:
       result = semAnonTuple(c, n, prev)
+  of nkTupleConstr: result = semAnonTuple(c, n, prev)
   of nkCallKinds:
     let x = n[0]
     let ident = case x.kind
diff --git a/compiler/transf.nim b/compiler/transf.nim
index e6dc69b38..f30f8583a 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -334,7 +334,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
   if skipTypes(e.typ, {tyGenericInst, tyAlias, tySink}).kind == tyTuple and
       c.transCon.forStmt.len != 3:
     e = skipConv(e)
-    if e.kind == nkPar:
+    if e.kind in {nkPar, nkTupleConstr}:
       for i in countup(0, sonsLen(e) - 1):
         var v = e.sons[i]
         if v.kind == nkExprColonExpr: v = v.sons[1]
@@ -500,7 +500,7 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto =
   case arg.kind
   of nkEmpty..nkNilLit:
     result = paDirectMapping
-  of nkPar, nkCurly, nkBracket:
+  of nkPar, nkTupleConstr, nkCurly, nkBracket:
     result = paFastAsgn
     for i in countup(0, sonsLen(arg) - 1):
       if putArgInto(arg.sons[i], formal) != paDirectMapping: return
@@ -745,7 +745,7 @@ proc transformExceptBranch(c: PTransf, n: PNode): PTransNode =
 proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
   # symbols that expand to a complex constant (array, etc.) should not be
   # inlined, unless it's the empty array:
-  result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and
+  result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket} and
       cnst.len != 0
 
 proc commonOptimizations*(c: PSym, n: PNode): PNode =
diff --git a/compiler/trees.nim b/compiler/trees.nim
index f69108942..fb523de9d 100644
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -97,7 +97,7 @@ proc isDeepConstExpr*(n: PNode): bool =
     result = true
   of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
     result = isDeepConstExpr(n.sons[1])
-  of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure, nkRange:
+  of nkCurly, nkBracket, nkPar, nkTupleConstr, nkObjConstr, nkClosure, nkRange:
     for i in ord(n.kind == nkObjConstr) ..< n.len:
       if not isDeepConstExpr(n.sons[i]): return false
     if n.typ.isNil: result = true
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 33c17eff4..7e2a171a2 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -418,14 +418,14 @@ proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
   let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
   let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
   let typeKind = case typeEntry.kind
-  of tyUInt..tyUInt64: nkUIntLit
-  of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
-  of tyFloat..tyFloat128: nkFloatLit
-  of tyString: nkStrLit
-  of tyObject: nkObjConstr
-  of tySequence: nkNilLit
-  of tyProc, tyTuple: nkPar
-  else: nkEmpty
+                 of tyUInt..tyUInt64: nkUIntLit
+                 of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
+                 of tyFloat..tyFloat128: nkFloatLit
+                 of tyString: nkStrLit
+                 of tyObject: nkObjConstr
+                 of tySequence: nkNilLit
+                 of tyProc, tyTuple: nkTupleConstr
+                 else: nkEmpty
 
   let oldLen = node.len
   setLen(node.sons, newLen)
@@ -939,7 +939,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       let rb = instr.regB
       let rc = instr.regC
       let bb = regs[rb].node
-      let isClosure = bb.kind == nkPar
+      let isClosure = bb.kind == nkTupleConstr
       let prc = if not isClosure: bb.sym else: bb.sons[0].sym
       if prc.offset < -1:
         # it's a callback:
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index bb6c47324..071cc7706 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -186,7 +186,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
     if inst:
       # only named tuples have a node, unnamed tuples don't
       if t.n.isNil:
-        result = newNodeX(nkPar)
+        result = newNodeX(nkTupleConstr)
         for subType in t.sons:
           result.add mapTypeToAst(subType, info)
       else:
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index a8ecfd4ae..c3eaf8946 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1560,7 +1560,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
     if t.callConv != ccClosure:
       result = newNodeIT(nkNilLit, info, t)
     else:
-      result = newNodeIT(nkPar, info, t)
+      result = newNodeIT(nkTupleConstr, info, t)
       result.add(newNodeIT(nkNilLit, info, t))
       result.add(newNodeIT(nkNilLit, info, t))
   of tyObject:
@@ -1577,7 +1577,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
     for i in countup(0, int(lengthOrd(t)) - 1):
       addSon(result, getNullValue(elemType(t), info))
   of tyTuple:
-    result = newNodeIT(nkPar, info, t)
+    result = newNodeIT(nkTupleConstr, info, t)
     for i in countup(0, sonsLen(t) - 1):
       addSon(result, getNullValue(t.sons[i], info))
   of tySet:
@@ -1884,7 +1884,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   of nkBracket: genArrayConstr(c, n, dest)
   of nkCurly: genSetConstr(c, n, dest)
   of nkObjConstr: genObjConstr(c, n, dest)
-  of nkPar, nkClosure: genTupleConstr(c, n, dest)
+  of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest)
   of nkCast:
     if allowCast in c.features:
       genConv(c, n, n.sons[1], dest, opcCast)
diff --git a/compiler/vmmarshal.nim b/compiler/vmmarshal.nim
index 5f725994e..d76909443 100644
--- a/compiler/vmmarshal.nim
+++ b/compiler/vmmarshal.nim
@@ -190,7 +190,7 @@ proc loadAny(p: var JsonParser, t: PType,
   of tyTuple:
     if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object")
     next(p)
-    result = newNode(nkPar)
+    result = newNode(nkTupleConstr)
     var i = 0
     while p.kind != jsonObjectEnd and p.kind != jsonEof:
       if p.kind != jsonString:
diff --git a/compiler/vmops.nim b/compiler/vmops.nim
index f7debe2df..7f8bf06c1 100644
--- a/compiler/vmops.nim
+++ b/compiler/vmops.nim
@@ -74,13 +74,13 @@ proc getCurrentExceptionMsgWrapper(a: VmArgs) {.nimcall.} =
 proc staticWalkDirImpl(path: string, relative: bool): PNode =
   result = newNode(nkBracket)
   for k, f in walkDir(path, relative):
-    result.add newTree(nkPar, newIntNode(nkIntLit, k.ord),
+    result.add newTree(nkTupleConstr, newIntNode(nkIntLit, k.ord),
                               newStrNode(nkStrLit, f))
 
 proc gorgeExWrapper(a: VmArgs) {.nimcall.} =
   let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
                        a.currentLineInfo)
-  setResult a, newTree(nkPar, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e))
+  setResult a, newTree(nkTupleConstr, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e))
 
 proc getProjectPathWrapper(a: VmArgs) {.nimcall.} =
   setResult a, gProjectPath
diff --git a/compiler/writetracking.nim b/compiler/writetracking.nim
index 577db613d..e03d6fb59 100644
--- a/compiler/writetracking.nim
+++ b/compiler/writetracking.nim
@@ -120,7 +120,7 @@ proc returnsNewExpr*(n: PNode): NewLocation =
       nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkOfBranch,
       nkElifBranch, nkElse, nkExceptBranch, nkFinally, nkCast:
     result = returnsNewExpr(n.lastSon)
-  of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure,
+  of nkCurly, nkBracket, nkPar, nkTupleConstr, nkObjConstr, nkClosure,
       nkIfExpr, nkIfStmt, nkWhenStmt, nkCaseStmt, nkTryStmt:
     result = newLit
     for i in ord(n.kind == nkObjConstr) ..< n.len:
@@ -179,7 +179,7 @@ proc deps(w: var W; n: PNode) =
     for child in n:
       let last = lastSon(child)
       if last.kind == nkEmpty: continue
-      if child.kind == nkVarTuple and last.kind == nkPar:
+      if child.kind == nkVarTuple and last.kind in {nkPar, nkTupleConstr}:
         internalAssert child.len-2 == last.len
         for i in 0 .. child.len-3:
           deps(w, child.sons[i], last.sons[i], {})