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
parent ab426faa22
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``.
- ``macros.callsite`` is now deprecated. Since the introduction of ``varargs``
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

View File

@@ -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]

View File

@@ -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)

View File

@@ -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])

View File

@@ -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")

View File

@@ -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:

View File

@@ -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)

View File

@@ -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]

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 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)

View File

@@ -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)

View File

@@ -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:

View File

@@ -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):

View File

@@ -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:

View File

@@ -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)

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-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)

View File

@@ -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

View File

@@ -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 =

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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)

View File

@@ -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:

View File

@@ -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

View File

@@ -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], {})

View File

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

View File

@@ -1,7 +1,10 @@
discard """
output: '''61, 125'''
output: '''61, 125
(Field0: 0) (Field0: 13)'''
"""
import macros
proc `^` (a, b: int): int =
result = 1
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])
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()