mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 10:24:44 +00:00
enable syntax for anonymous tuples.
Turns out to be slightly problematic as `(int, int)` could be logically thought of as an expression evaluating to a tuple value containing two typedesc[int]s. To disambiguate, the zero-tuple's type must still be written as `tuple[]`, and what would be tuple value expressions containing only typedescs are interpreted as types. () # value of type `tuple[]` (int, int) # tuple type (int, int, ()) # value of type `(typedesc[int], typedesc[int], tuple[])`
This commit is contained in:
@@ -1866,6 +1866,14 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
addSonSkipIntLit(typ, n.sons[i].typ)
|
||||
result.typ = typ
|
||||
|
||||
proc isTupleType(n: PNode): bool =
|
||||
if n.len == 0:
|
||||
return false # don't interpret () as type
|
||||
for i in countup(0, n.len - 1):
|
||||
if n[i].typ == nil or n[i].typ.kind != tyTypeDesc:
|
||||
return false
|
||||
return true
|
||||
|
||||
proc checkInitialized(n: PNode, ids: IntSet, info: TLineInfo) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
@@ -2129,7 +2137,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkPar:
|
||||
case checkPar(n)
|
||||
of paNone: result = errorNode(c, n)
|
||||
of paTuplePositions: result = semTuplePositionsConstr(c, n, flags)
|
||||
of paTuplePositions:
|
||||
var tupexp = semTuplePositionsConstr(c, n, flags)
|
||||
if isTupleType(tupexp):
|
||||
# reinterpret as type
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter})
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
else:
|
||||
result = tupexp
|
||||
of paTupleFields: result = semTupleFieldsConstr(c, n, flags)
|
||||
of paSingle: result = semExpr(c, n.sons[0], flags)
|
||||
of nkCurly: result = semSetConstr(c, n)
|
||||
|
||||
@@ -344,7 +344,14 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
else:
|
||||
localError(n.info, errIdentifierExpected)
|
||||
result = errorSym(c, n)
|
||||
|
||||
|
||||
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))
|
||||
|
||||
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
var typ: PType
|
||||
result = newOrPrevType(tyTuple, prev, c)
|
||||
@@ -1116,9 +1123,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkPar:
|
||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||
else:
|
||||
# XXX support anon tuple here
|
||||
localError(n.info, errTypeExpected)
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
result = semAnonTuple(c, n, prev)
|
||||
of nkCallKinds:
|
||||
if isRange(n):
|
||||
result = semRangeAux(c, n, prev)
|
||||
|
||||
@@ -507,18 +507,22 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
if prefer == preferModuleInfo: preferModuleInfo else: preferName)
|
||||
of tyTuple:
|
||||
# we iterate over t.sons here, because t.n may be nil
|
||||
result = "tuple["
|
||||
if t.n != nil:
|
||||
result = "tuple["
|
||||
assert(sonsLen(t.n) == sonsLen(t))
|
||||
for i in countup(0, sonsLen(t.n) - 1):
|
||||
assert(t.n.sons[i].kind == nkSym)
|
||||
add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
|
||||
if i < sonsLen(t.n) - 1: add(result, ", ")
|
||||
add(result, ']')
|
||||
elif sonsLen(t) == 0:
|
||||
result = "tuple[]"
|
||||
else:
|
||||
result = "("
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
add(result, typeToString(t.sons[i]))
|
||||
if i < sonsLen(t) - 1: add(result, ", ")
|
||||
add(result, ']')
|
||||
add(result, ')')
|
||||
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
|
||||
result = typeToStr[t.kind]
|
||||
if t.len >= 2:
|
||||
|
||||
Reference in New Issue
Block a user