mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 02:18:00 +00:00
Const tuple unpacking (#9964)
* tuple unpacking is now supported for consts * Move nkConstTuple to the end of TNodeKind * Add nnkConstTuple in macros.nim * Fix Formatting
This commit is contained in:
committed by
Andreas Rumpf
parent
3f917c8d91
commit
8e90ed0618
@@ -222,7 +222,8 @@ type
|
||||
nkState, # give a label to a code section (for iterators)
|
||||
nkBreakState, # special break statement for easier code generation
|
||||
nkFuncDef, # a func
|
||||
nkTupleConstr # a tuple constructor
|
||||
nkTupleConstr, # a tuple constructor
|
||||
nkConstTuple # a ``const (a, b) = expr`` construct
|
||||
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
|
||||
@@ -1764,21 +1764,43 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, p.tok)
|
||||
|
||||
proc parseConstant(p: var TParser): PNode =
|
||||
#| constant = identWithPragma (colon typeDesc)? '=' optInd expr indAndComment
|
||||
result = newNodeP(nkConstDef, p)
|
||||
addSon(result, identWithPragma(p))
|
||||
if p.tok.tokType == tkColon:
|
||||
proc parseConstTuple(p: var TParser): PNode =
|
||||
result = newNodeP(nkConstTuple, p)
|
||||
getTok(p) # skip '('
|
||||
optInd(p, result)
|
||||
while p.tok.tokType in {tkSymbol, tkAccent}:
|
||||
addSon(result, identWithPragma(p))
|
||||
if p.tok.tokType == tkColon:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
addSon(result, parseTypeDesc(p))
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
addSon(result, parseTypeDesc(p))
|
||||
else:
|
||||
addSon(result, p.emptyNode)
|
||||
|
||||
addSon(result, p.emptyNode)
|
||||
eat(p, tkParRi)
|
||||
eat(p, tkEquals)
|
||||
optInd(p, result)
|
||||
addSon(result, parseExpr(p))
|
||||
indAndComment(p, result)
|
||||
|
||||
proc parseConstant(p: var TParser): PNode =
|
||||
#| constant = identWithPragma (colon typeDesc)? '=' optInd expr indAndComment
|
||||
if p.tok.tokType == tkParLe: result = parseConstTuple(p)
|
||||
else:
|
||||
result = newNodeP(nkConstDef, p)
|
||||
addSon(result, identWithPragma(p))
|
||||
if p.tok.tokType == tkColon:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
addSon(result, parseTypeDesc(p))
|
||||
else:
|
||||
addSon(result, p.emptyNode)
|
||||
eat(p, tkEquals)
|
||||
optInd(p, result)
|
||||
addSon(result, parseExpr(p))
|
||||
indAndComment(p, result)
|
||||
|
||||
proc parseEnum(p: var TParser): PNode =
|
||||
#| enum = 'enum' optInd (symbol optInd ('=' optInd expr COMMENT?)? comma?)+
|
||||
result = newNodeP(nkEnumTy, p)
|
||||
|
||||
@@ -542,17 +542,17 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
var a = n.sons[i]
|
||||
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind != nkConstDef: illFormedAst(a, c.config)
|
||||
checkSonsLen(a, 3, c.config)
|
||||
var v = semIdentDef(c, a.sons[0], skConst)
|
||||
styleCheckDef(c.config, v)
|
||||
onDef(a[0].info, v)
|
||||
var typ: PType = nil
|
||||
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
|
||||
if a.kind notin {nkConstDef, nkConstTuple}: illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var length = sonsLen(a)
|
||||
|
||||
var def = semConstExpr(c, a.sons[2])
|
||||
var typ: PType = nil
|
||||
if a.sons[length-2].kind != nkEmpty:
|
||||
typ = semTypeNode(c, a.sons[length-2], nil)
|
||||
|
||||
var def = semConstExpr(c, a.sons[length-1])
|
||||
if def == nil:
|
||||
localError(c.config, a.sons[2].info, errConstExprExpected)
|
||||
localError(c.config, a.sons[length-1].info, errConstExprExpected)
|
||||
continue
|
||||
# check type compatibility between def.typ and typ:
|
||||
if typ != nil:
|
||||
@@ -560,21 +560,43 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
typ = def.typ
|
||||
if typ == nil:
|
||||
localError(c.config, a.sons[2].info, errConstExprExpected)
|
||||
localError(c.config, a.sons[length-1].info, errConstExprExpected)
|
||||
continue
|
||||
if typeAllowed(typ, skConst) != nil and def.kind != nkNilLit:
|
||||
localError(c.config, a.info, "invalid type for const: " & typeToString(typ))
|
||||
continue
|
||||
setVarType(c, v, typ)
|
||||
v.ast = def # no need to copy
|
||||
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
var b = newNodeI(nkConstDef, a.info)
|
||||
if importantComments(c.config): b.comment = a.comment
|
||||
addSon(b, newSymNode(v))
|
||||
addSon(b, a.sons[1])
|
||||
addSon(b, copyTree(def))
|
||||
addSon(result, b)
|
||||
|
||||
var b: PNode
|
||||
if a.kind == nkConstTuple:
|
||||
if typ.kind != tyTuple:
|
||||
localError(c.config, a.info, errXExpected, "tuple")
|
||||
elif int(length/2) != sonsLen(typ):
|
||||
localError(c.config, a.info, errWrongNumberOfVariables)
|
||||
b = newNodeI(nkConstTuple, a.info)
|
||||
newSons(b, length)
|
||||
b.sons[length-2] = a.sons[length-2]
|
||||
b.sons[length-1] = def
|
||||
|
||||
for j in countup(0, length-3):
|
||||
var v = semIdentDef(c, a.sons[j], skConst)
|
||||
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
styleCheckDef(c.config, v)
|
||||
onDef(a[j].info, v)
|
||||
|
||||
if a.kind != nkConstTuple:
|
||||
setVarType(c, v, typ)
|
||||
v.ast = def # no need to copy
|
||||
b = newNodeI(nkConstDef, a.info)
|
||||
if importantComments(c.config): b.comment = a.comment
|
||||
addSon(b, newSymNode(v))
|
||||
addSon(b, a.sons[1])
|
||||
addSon(b, copyTree(def))
|
||||
else:
|
||||
setVarType(c, v, typ.sons[j])
|
||||
v.ast = def[j]
|
||||
b.sons[j] = newSymNode(v)
|
||||
addSon(result,b)
|
||||
|
||||
include semfields
|
||||
|
||||
|
||||
@@ -81,7 +81,8 @@ type
|
||||
nnkState,
|
||||
nnkBreakState,
|
||||
nnkFuncDef,
|
||||
nnkTupleConstr
|
||||
nnkTupleConstr,
|
||||
nnkConstTuple
|
||||
|
||||
NimNodeKinds* = set[NimNodeKind]
|
||||
NimTypeKind* = enum # some types are no longer used, see ast.nim
|
||||
|
||||
Reference in New Issue
Block a user