introduce nkTupleConstr AST node for unary tuple construction; breaking change

This commit is contained in:
Andreas Rumpf 2018-04-13 17:06:46 +02:00
commit 47335aab41
26 changed files with 91 additions and 56 deletions

View file

@ -5,6 +5,10 @@
- The stdlib module ``future`` has been renamed to ``sugar``. - The stdlib module ``future`` has been renamed to ``sugar``.
- ``macros.callsite`` is now deprecated. Since the introduction of ``varargs`` - ``macros.callsite`` is now deprecated. Since the introduction of ``varargs``
parameters this became unnecessary. parameters this became unnecessary.
- Anonymous tuples with a single element can now be written as ``(1,)`` with a
trailing comma. The underlying AST is ``nnkTupleConst(newLit 1)`` for this
example. ``nnkTupleConstr`` is a new node kind your macros need to be able
to deal with!
#### Breaking changes in the standard library #### Breaking changes in the standard library

View file

@ -221,7 +221,8 @@ type
nkGotoState, # used for the state machine (for iterators) nkGotoState, # used for the state machine (for iterators)
nkState, # give a label to a code section (for iterators) nkState, # give a label to a code section (for iterators)
nkBreakState, # special break statement for easier code generation nkBreakState, # special break statement for easier code generation
nkFuncDef # a func nkFuncDef, # a func
nkTupleConstr # a tuple constructor
TNodeKinds* = set[TNodeKind] TNodeKinds* = set[TNodeKind]

View file

@ -2226,7 +2226,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
genSeqConstr(p, n, d) genSeqConstr(p, n, d)
else: else:
genArrayConstr(p, n, d) genArrayConstr(p, n, d)
of nkPar: of nkPar, nkTupleConstr:
if isDeepConstExpr(n) and n.len != 0: if isDeepConstExpr(n) and n.len != 0:
exprComplexConst(p, n, d) exprComplexConst(p, n, d)
else: else:
@ -2458,7 +2458,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
var cs: TBitSet var cs: TBitSet
toBitSet(n, cs) toBitSet(n, cs)
result = genRawSetData(cs, int(getSize(n.typ))) result = genRawSetData(cs, int(getSize(n.typ)))
of nkBracket, nkPar, nkClosure: of nkBracket, nkPar, nkTupleConstr, nkClosure:
var t = skipTypes(n.typ, abstractInst) var t = skipTypes(n.typ, abstractInst)
if t.kind == tySequence: if t.kind == tySequence:
result = genConstSeq(p, n, n.typ) result = genConstSeq(p, n, n.typ)

View file

@ -323,7 +323,7 @@ proc gen(c: var Con; n: PNode) =
of nkBreakStmt: genBreak(c, n) of nkBreakStmt: genBreak(c, n)
of nkTryStmt: genTry(c, n) of nkTryStmt: genTry(c, n)
of nkStmtList, nkStmtListExpr, nkChckRangeF, nkChckRange64, nkChckRange, of nkStmtList, nkStmtListExpr, nkChckRangeF, nkChckRange64, nkChckRange,
nkBracket, nkCurly, nkPar, nkClosure, nkObjConstr: nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr:
for x in n: gen(c, x) for x in n: gen(c, x)
of nkPragmaBlock: gen(c, n.lastSon) of nkPragmaBlock: gen(c, n.lastSon)
of nkDiscardStmt: gen(c, n.sons[0]) of nkDiscardStmt: gen(c, n.sons[0])

View file

@ -151,7 +151,7 @@ proc getField(n: PNode; position: int): PSym =
else: discard else: discard
proc packObject(x: PNode, typ: PType, res: pointer) = 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: # compute the field's offsets:
discard typ.getSize discard typ.getSize
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1): 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 # iterate over any actual field of 'n' ... if n is nil we need to create
# the nkPar node: # the nkPar node:
if n.isNil: if n.isNil:
result = newNode(nkPar) result = newNode(nkTupleConstr)
result.typ = typ result.typ = typ
if typ.n.isNil: if typ.n.isNil:
internalError("cannot unpack unnamed tuple") internalError("cannot unpack unnamed tuple")
unpackObjectAdd(x, typ.n, result) unpackObjectAdd(x, typ.n, result)
else: else:
result = n result = n
if result.kind notin {nkObjConstr, nkPar}: if result.kind notin {nkObjConstr, nkPar, nkTupleConstr}:
globalError(n.info, "cannot map value from FFI") globalError(n.info, "cannot map value from FFI")
if typ.n.isNil: if typ.n.isNil:
globalError(n.info, "cannot unpack unnamed tuple") globalError(n.info, "cannot unpack unnamed tuple")

View file

@ -307,7 +307,7 @@ proc useMagic(p: PProc, name: string) =
proc isSimpleExpr(p: PProc; n: PNode): bool = proc isSimpleExpr(p: PProc; n: PNode): bool =
# calls all the way down --> can stay expression based # 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}): (p.target == targetJS and n.kind in {nkObjConstr, nkBracket, nkCurly}):
for c in n: for c in n:
if not p.isSimpleExpr(c): return false if not p.isSimpleExpr(c): return false
@ -894,7 +894,7 @@ proc countJsParams(typ: PType): int =
const const
nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString, nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkTupleConstr, nkObjConstr, nkStringToCString,
nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix, nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix,
nkCommand, nkHiddenCallConv, nkCallStrLit} nkCommand, nkHiddenCallConv, nkCallStrLit}
@ -1714,7 +1714,7 @@ proc genToArray(p: PProc; n: PNode; r: var TCompRes) =
if x.kind == nkBracket: if x.kind == nkBracket:
for i in countup(0, x.len - 1): for i in countup(0, x.len - 1):
let it = x[i] 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(", ") if i > 0: r.res.add(", ")
gen(p, it[0], a) gen(p, it[0], a)
gen(p, it[1], b) 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 nkClosure: gen(p, n[0], r)
of nkCurly: genSetConstr(p, n, r) of nkCurly: genSetConstr(p, n, r)
of nkBracket: genArrayConstr(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 nkObjConstr: genObjConstr(p, n, r)
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
of nkAddr, nkHiddenAddr: of nkAddr, nkHiddenAddr:

View file

@ -399,6 +399,9 @@ proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
addSon(result, a) addSon(result, a)
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
getTok(p) getTok(p)
# (1,) produces a tuple expression
if endTok == tkParRi and p.tok.tokType == tkParRi:
result.kind = nkTupleConstr
skipComment(p, a) skipComment(p, a)
optPar(p) optPar(p)
eat(p, endTok) eat(p, endTok)
@ -566,6 +569,9 @@ proc parsePar(p: var TParser): PNode =
if p.tok.tokType == tkComma: if p.tok.tokType == tkComma:
getTok(p) getTok(p)
skipComment(p, a) skipComment(p, a)
# (1,) produces a tuple expression:
if p.tok.tokType == tkParRi:
result.kind = nkTupleConstr
# progress guaranteed # progress guaranteed
while p.tok.tokType != tkParRi and p.tok.tokType != tkEof: while p.tok.tokType != tkParRi and p.tok.tokType != tkEof:
var a = exprColonEqExpr(p) var a = exprColonEqExpr(p)

View file

@ -423,7 +423,7 @@ proc processCompile(c: PContext, n: PNode) =
result = "" result = ""
let it = if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] else: n 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 s = getStrLit(c, it, 0)
let dest = getStrLit(c, it, 1) let dest = getStrLit(c, it, 1)
var found = parentDir(n.info.toFullPath) / s 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: if n.kind in nkPragmaCallKinds and n.len == 2:
n.sons[1] = c.semConstExpr(c, n.sons[1]) n.sons[1] = c.semConstExpr(c, n.sons[1])
let a = n.sons[1] let a = n.sons[1]
if a.kind == nkPar: if a.kind in {nkPar, nkTupleConstr}:
# unpack the tuple # unpack the tuple
var x = a.sons[0] var x = a.sons[0]
var y = a.sons[1] var y = a.sons[1]

View file

@ -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 nkCommand: result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + 1
of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(g, n) + 3 of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(g, n) + 3
of nkPar, nkCurly, nkBracket, nkClosure: result = lcomma(g, n) + 2 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 nkArgList: result = lcomma(g, n)
of nkTableConstr: of nkTableConstr:
result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}") 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, "(") put(g, tkParLe, "(")
gcomma(g, n, c) gcomma(g, n, c)
put(g, tkParRi, ")") put(g, tkParRi, ")")
of nkTupleConstr:
put(g, tkParLe, "(")
gcomma(g, n, c)
if n.len == 1: put(g, tkComma, ",")
put(g, tkParRi, ")")
of nkCurly: of nkCurly:
put(g, tkCurlyLe, "{") put(g, tkCurlyLe, "{")
gcomma(g, n, c) gcomma(g, n, c)

View file

@ -85,7 +85,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
result.typ = formal result.typ = formal
else: else:
let x = result.skipConv 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) changeType(x, formal, check=true)
else: else:
result = skipHiddenSubConv(result) result = skipHiddenSubConv(result)

View file

@ -215,7 +215,7 @@ proc semConv(c: PContext, n: PNode): PNode =
# handle SomeProcType(SomeGenericProc) # handle SomeProcType(SomeGenericProc)
if op.kind == nkSym and op.sym.isGenericRoutine: if op.kind == nkSym and op.sym.isGenericRoutine:
result.sons[1] = fitNode(c, result.typ, result.sons[1], result.info) 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) op = fitNode(c, targetType, op, result.info)
of convNotNeedeed: of convNotNeedeed:
message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString) message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString)
@ -364,7 +364,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
of nkCurly, nkBracket: of nkCurly, nkBracket:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
changeType(n.sons[i], elemType(newType), check) changeType(n.sons[i], elemType(newType), check)
of nkPar: of nkPar, nkTupleConstr:
let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink}) let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink})
if tup.kind != tyTuple: if tup.kind != tyTuple:
if tup.kind == tyObject: return if tup.kind == tyObject: return
@ -1402,7 +1402,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
result = buildOverloadedSubscripts(n.sons[0], getIdent"{}=") result = buildOverloadedSubscripts(n.sons[0], getIdent"{}=")
add(result, n[1]) add(result, n[1])
return semExprNoType(c, result) return semExprNoType(c, result)
of nkPar: of nkPar, nkTupleConstr:
if a.len >= 2: if a.len >= 2:
# unfortunately we need to rewrite ``(x, y) = foo()`` already here so # unfortunately we need to rewrite ``(x, y) = foo()`` already here so
# that overloading of the assignment operator still works. Usually we # 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}) var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
if e.kind in {tyVar, tyLent}: if e.kind in {tyVar, tyLent}:
if e.kind == tyVar: e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892 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) n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i], e.kind == tyLent)
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and 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] var a = n.sons[0].sons[1]
a.sons[i] = takeImplicitAddr(c, a.sons[i], false) a.sons[i] = takeImplicitAddr(c, a.sons[i], false)
else: else:
@ -2047,12 +2047,12 @@ proc semTableConstr(c: PContext, n: PNode): PNode =
var x = n.sons[i] var x = n.sons[i]
if x.kind == nkExprColonExpr and sonsLen(x) == 2: if x.kind == nkExprColonExpr and sonsLen(x) == 2:
for j in countup(lastKey, i-1): 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(n.sons[j])
pair.add(x[1]) pair.add(x[1])
result.add(pair) result.add(pair)
var pair = newNodeI(nkPar, x.info) var pair = newNodeI(nkTupleConstr, x.info)
pair.add(x[0]) pair.add(x[0])
pair.add(x[1]) pair.add(x[1])
result.add(pair) result.add(pair)
@ -2072,6 +2072,7 @@ proc checkPar(n: PNode): TParKind =
result = paTuplePositions # () result = paTuplePositions # ()
elif length == 1: elif length == 1:
if n.sons[0].kind == nkExprColonExpr: result = paTupleFields if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
elif n.kind == nkTupleConstr: result = paTuplePositions
else: result = paSingle # (expr) else: result = paSingle # (expr)
else: else:
if n.sons[0].kind == nkExprColonExpr: result = paTupleFields if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
@ -2088,7 +2089,7 @@ proc checkPar(n: PNode): TParKind =
return paNone return paNone
proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = newNodeI(nkPar, n.info) result = newNodeI(nkTupleConstr, n.info)
var typ = newTypeS(tyTuple, c) var typ = newTypeS(tyTuple, c)
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
var ids = initIntSet() 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 = proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = n # we don't modify n, but compute the type: result = n # we don't modify n, but compute the type:
result.kind = nkTupleConstr
var typ = newTypeS(tyTuple, c) # leave typ.n nil! var typ = newTypeS(tyTuple, c) # leave typ.n nil!
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor}) 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) invalidPragma(n)
result = semExpr(c, n[0], flags) result = semExpr(c, n[0], flags)
of nkPar: of nkPar, nkTupleConstr:
case checkPar(n) case checkPar(n)
of paNone: result = errorNode(c, n) of paNone: result = errorNode(c, n)
of paTuplePositions: of paTuplePositions:

View file

@ -427,7 +427,7 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
var idx = getOrdValue(y) var idx = getOrdValue(y)
case x.kind case x.kind
of nkPar: of nkPar, nkTupleConstr:
if idx >= 0 and idx < sonsLen(x): if idx >= 0 and idx < sonsLen(x):
result = x.sons[int(idx)] result = x.sons[int(idx)]
if result.kind == nkExprColonExpr: result = result.sons[1] 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 = proc foldFieldAccess(m: PSym, n: PNode): PNode =
# a real field access; proc calls have already been transformed # a real field access; proc calls have already been transformed
var x = getConstExpr(m, n.sons[0]) 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 var field = n.sons[1].sym
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1): 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 # if a == nil: return nil
# result.sons[i].sons[1] = a # result.sons[i].sons[1] = a
# incl(result.flags, nfAllConst) # incl(result.flags, nfAllConst)
of nkPar: of nkPar, nkTupleConstr:
# tuple constructor # tuple constructor
result = copyTree(n) result = copyTree(n)
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr): if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):

View file

@ -50,7 +50,7 @@ proc annotateType*(n: PNode, t: PType) =
else: else:
internalAssert(n.sons[i].kind == nkExprColonExpr) internalAssert(n.sons[i].kind == nkExprColonExpr)
annotateType(n.sons[i].sons[1], field.typ) annotateType(n.sons[i].sons[1], field.typ)
of nkPar: of nkPar, nkTupleConstr:
if x.kind == tyTuple: if x.kind == tyTuple:
n.typ = t n.typ = t
for i in 0 ..< n.len: for i in 0 ..< n.len:

View file

@ -73,7 +73,7 @@ proc expectIntLit(c: PContext, n: PNode): int =
else: localError(n.info, errIntLiteralExpected) else: localError(n.info, errIntLiteralExpected)
proc semInstantiationInfo(c: PContext, n: PNode): PNode = 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 idx = expectIntLit(c, n.sons[1])
let useFullPaths = expectIntLit(c, n.sons[2]) let useFullPaths = expectIntLit(c, n.sons[2])
let info = getInfoContext(idx) let info = getInfoContext(idx)

View file

@ -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-2] = a.sons[length-2] # keep type desc for doc generator
b.sons[length-1] = def b.sons[length-1] = def
addToVarSection(c, result, n, b) 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: a.kind == nkIdentDefs and a.len > 3:
message(a.info, warnEachIdentIsTuple) message(a.info, warnEachIdentIsTuple)
@ -592,7 +592,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
addSon(b, copyTree(def)) addSon(b, copyTree(def))
addToVarSection(c, result, n, b) addToVarSection(c, result, n, b)
else: else:
if def.kind == nkPar: v.ast = def[j] if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j]
setVarType(v, tup.sons[j]) setVarType(v, tup.sons[j])
b.sons[j] = newSymNode(v) b.sons[j] = newSymNode(v)
checkNilable(v) checkNilable(v)

View file

@ -392,8 +392,8 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
if sonsLen(n) == 0: if sonsLen(n) == 0:
localError(n.info, errTypeExpected) localError(n.info, errTypeExpected)
result = newOrPrevType(tyTuple, prev, c) result = newOrPrevType(tyTuple, prev, c)
for i in countup(0, sonsLen(n) - 1): for it in n:
addSonSkipIntLit(result, semTypeNode(c, n.sons[i], nil)) addSonSkipIntLit(result, semTypeNode(c, it, nil))
proc semTuple(c: PContext, n: PNode, prev: PType): PType = proc semTuple(c: PContext, n: PNode, prev: PType): PType =
var typ: 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) if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
else: else:
result = semAnonTuple(c, n, prev) result = semAnonTuple(c, n, prev)
of nkTupleConstr: result = semAnonTuple(c, n, prev)
of nkCallKinds: of nkCallKinds:
let x = n[0] let x = n[0]
let ident = case x.kind let ident = case x.kind

View file

@ -334,7 +334,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
if skipTypes(e.typ, {tyGenericInst, tyAlias, tySink}).kind == tyTuple and if skipTypes(e.typ, {tyGenericInst, tyAlias, tySink}).kind == tyTuple and
c.transCon.forStmt.len != 3: c.transCon.forStmt.len != 3:
e = skipConv(e) e = skipConv(e)
if e.kind == nkPar: if e.kind in {nkPar, nkTupleConstr}:
for i in countup(0, sonsLen(e) - 1): for i in countup(0, sonsLen(e) - 1):
var v = e.sons[i] var v = e.sons[i]
if v.kind == nkExprColonExpr: v = v.sons[1] if v.kind == nkExprColonExpr: v = v.sons[1]
@ -500,7 +500,7 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto =
case arg.kind case arg.kind
of nkEmpty..nkNilLit: of nkEmpty..nkNilLit:
result = paDirectMapping result = paDirectMapping
of nkPar, nkCurly, nkBracket: of nkPar, nkTupleConstr, nkCurly, nkBracket:
result = paFastAsgn result = paFastAsgn
for i in countup(0, sonsLen(arg) - 1): for i in countup(0, sonsLen(arg) - 1):
if putArgInto(arg.sons[i], formal) != paDirectMapping: return 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.} = proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
# symbols that expand to a complex constant (array, etc.) should not be # symbols that expand to a complex constant (array, etc.) should not be
# inlined, unless it's the empty array: # 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 cnst.len != 0
proc commonOptimizations*(c: PSym, n: PNode): PNode = proc commonOptimizations*(c: PSym, n: PNode): PNode =

View file

@ -97,7 +97,7 @@ proc isDeepConstExpr*(n: PNode): bool =
result = true result = true
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv: of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
result = isDeepConstExpr(n.sons[1]) 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: for i in ord(n.kind == nkObjConstr) ..< n.len:
if not isDeepConstExpr(n.sons[i]): return false if not isDeepConstExpr(n.sons[i]): return false
if n.typ.isNil: result = true if n.typ.isNil: result = true

View file

@ -424,7 +424,7 @@ proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
of tyString: nkStrLit of tyString: nkStrLit
of tyObject: nkObjConstr of tyObject: nkObjConstr
of tySequence: nkNilLit of tySequence: nkNilLit
of tyProc, tyTuple: nkPar of tyProc, tyTuple: nkTupleConstr
else: nkEmpty else: nkEmpty
let oldLen = node.len let oldLen = node.len
@ -939,7 +939,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let rb = instr.regB let rb = instr.regB
let rc = instr.regC let rc = instr.regC
let bb = regs[rb].node 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 let prc = if not isClosure: bb.sym else: bb.sons[0].sym
if prc.offset < -1: if prc.offset < -1:
# it's a callback: # it's a callback:

View file

@ -186,7 +186,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
if inst: if inst:
# only named tuples have a node, unnamed tuples don't # only named tuples have a node, unnamed tuples don't
if t.n.isNil: if t.n.isNil:
result = newNodeX(nkPar) result = newNodeX(nkTupleConstr)
for subType in t.sons: for subType in t.sons:
result.add mapTypeToAst(subType, info) result.add mapTypeToAst(subType, info)
else: else:

View file

@ -1560,7 +1560,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
if t.callConv != ccClosure: if t.callConv != ccClosure:
result = newNodeIT(nkNilLit, info, t) result = newNodeIT(nkNilLit, info, t)
else: else:
result = newNodeIT(nkPar, info, t) result = newNodeIT(nkTupleConstr, info, t)
result.add(newNodeIT(nkNilLit, info, t)) result.add(newNodeIT(nkNilLit, info, t))
result.add(newNodeIT(nkNilLit, info, t)) result.add(newNodeIT(nkNilLit, info, t))
of tyObject: of tyObject:
@ -1577,7 +1577,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
for i in countup(0, int(lengthOrd(t)) - 1): for i in countup(0, int(lengthOrd(t)) - 1):
addSon(result, getNullValue(elemType(t), info)) addSon(result, getNullValue(elemType(t), info))
of tyTuple: of tyTuple:
result = newNodeIT(nkPar, info, t) result = newNodeIT(nkTupleConstr, info, t)
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):
addSon(result, getNullValue(t.sons[i], info)) addSon(result, getNullValue(t.sons[i], info))
of tySet: of tySet:
@ -1884,7 +1884,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
of nkBracket: genArrayConstr(c, n, dest) of nkBracket: genArrayConstr(c, n, dest)
of nkCurly: genSetConstr(c, n, dest) of nkCurly: genSetConstr(c, n, dest)
of nkObjConstr: genObjConstr(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: of nkCast:
if allowCast in c.features: if allowCast in c.features:
genConv(c, n, n.sons[1], dest, opcCast) genConv(c, n, n.sons[1], dest, opcCast)

View file

@ -190,7 +190,7 @@ proc loadAny(p: var JsonParser, t: PType,
of tyTuple: of tyTuple:
if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object") if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object")
next(p) next(p)
result = newNode(nkPar) result = newNode(nkTupleConstr)
var i = 0 var i = 0
while p.kind != jsonObjectEnd and p.kind != jsonEof: while p.kind != jsonObjectEnd and p.kind != jsonEof:
if p.kind != jsonString: if p.kind != jsonString:

View file

@ -74,13 +74,13 @@ proc getCurrentExceptionMsgWrapper(a: VmArgs) {.nimcall.} =
proc staticWalkDirImpl(path: string, relative: bool): PNode = proc staticWalkDirImpl(path: string, relative: bool): PNode =
result = newNode(nkBracket) result = newNode(nkBracket)
for k, f in walkDir(path, relative): 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)) newStrNode(nkStrLit, f))
proc gorgeExWrapper(a: VmArgs) {.nimcall.} = proc gorgeExWrapper(a: VmArgs) {.nimcall.} =
let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2), let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
a.currentLineInfo) 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.} = proc getProjectPathWrapper(a: VmArgs) {.nimcall.} =
setResult a, gProjectPath setResult a, gProjectPath

View file

@ -120,7 +120,7 @@ proc returnsNewExpr*(n: PNode): NewLocation =
nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkOfBranch, nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkOfBranch,
nkElifBranch, nkElse, nkExceptBranch, nkFinally, nkCast: nkElifBranch, nkElse, nkExceptBranch, nkFinally, nkCast:
result = returnsNewExpr(n.lastSon) result = returnsNewExpr(n.lastSon)
of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure, of nkCurly, nkBracket, nkPar, nkTupleConstr, nkObjConstr, nkClosure,
nkIfExpr, nkIfStmt, nkWhenStmt, nkCaseStmt, nkTryStmt: nkIfExpr, nkIfStmt, nkWhenStmt, nkCaseStmt, nkTryStmt:
result = newLit result = newLit
for i in ord(n.kind == nkObjConstr) ..< n.len: for i in ord(n.kind == nkObjConstr) ..< n.len:
@ -179,7 +179,7 @@ proc deps(w: var W; n: PNode) =
for child in n: for child in n:
let last = lastSon(child) let last = lastSon(child)
if last.kind == nkEmpty: continue 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 internalAssert child.len-2 == last.len
for i in 0 .. child.len-3: for i in 0 .. child.len-3:
deps(w, child.sons[i], last.sons[i], {}) deps(w, child.sons[i], last.sons[i], {})

View file

@ -82,7 +82,8 @@ type
nnkGotoState, nnkGotoState,
nnkState, nnkState,
nnkBreakState, nnkBreakState,
nnkFuncDef nnkFuncDef,
nnkTupleConstr
NimNodeKinds* = set[NimNodeKind] NimNodeKinds* = set[NimNodeKind]
NimTypeKind* = enum # some types are no longer used, see ast.nim NimTypeKind* = enum # some types are no longer used, see ast.nim

View file

@ -1,7 +1,10 @@
discard """ discard """
output: '''61, 125''' output: '''61, 125
(Field0: 0) (Field0: 13)'''
""" """
import macros
proc `^` (a, b: int): int = proc `^` (a, b: int): int =
result = 1 result = 1
for i in 1..b: result = result * a for i in 1..b: result = result * a
@ -12,3 +15,12 @@ var n = (56, 3)
m = (n[0] + m[1], m[1] ^ n[1]) m = (n[0] + m[1], m[1] ^ n[1])
echo m[0], ", ", m[1] echo m[0], ", ", m[1]
# also test we can produce unary anon tuples in a macro:
macro mm(): untyped =
result = newTree(nnkTupleConstr, newLit(13))
proc nowTuple(): (int,) =
result = (0,)
echo nowTuple(), " ", mm()