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:
parent
9c126282b2
commit
dba25d2622
3 changed files with 31 additions and 7 deletions
|
|
@ -1866,6 +1866,14 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
addSonSkipIntLit(typ, n.sons[i].typ)
|
addSonSkipIntLit(typ, n.sons[i].typ)
|
||||||
result.typ = 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) =
|
proc checkInitialized(n: PNode, ids: IntSet, info: TLineInfo) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
|
|
@ -2129,7 +2137,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of nkPar:
|
of nkPar:
|
||||||
case checkPar(n)
|
case checkPar(n)
|
||||||
of paNone: result = errorNode(c, 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 paTupleFields: result = semTupleFieldsConstr(c, n, flags)
|
||||||
of paSingle: result = semExpr(c, n.sons[0], flags)
|
of paSingle: result = semExpr(c, n.sons[0], flags)
|
||||||
of nkCurly: result = semSetConstr(c, n)
|
of nkCurly: result = semSetConstr(c, n)
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,13 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
localError(n.info, errIdentifierExpected)
|
localError(n.info, errIdentifierExpected)
|
||||||
result = errorSym(c, n)
|
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 =
|
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var typ: PType
|
var typ: PType
|
||||||
result = newOrPrevType(tyTuple, prev, c)
|
result = newOrPrevType(tyTuple, prev, c)
|
||||||
|
|
@ -1116,9 +1123,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
of nkPar:
|
of nkPar:
|
||||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||||
else:
|
else:
|
||||||
# XXX support anon tuple here
|
result = semAnonTuple(c, n, prev)
|
||||||
localError(n.info, errTypeExpected)
|
|
||||||
result = newOrPrevType(tyError, prev, c)
|
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
if isRange(n):
|
if isRange(n):
|
||||||
result = semRangeAux(c, n, prev)
|
result = semRangeAux(c, n, prev)
|
||||||
|
|
|
||||||
|
|
@ -507,18 +507,22 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
if prefer == preferModuleInfo: preferModuleInfo else: preferName)
|
if prefer == preferModuleInfo: preferModuleInfo else: preferName)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
# we iterate over t.sons here, because t.n may be nil
|
# we iterate over t.sons here, because t.n may be nil
|
||||||
result = "tuple["
|
|
||||||
if t.n != nil:
|
if t.n != nil:
|
||||||
|
result = "tuple["
|
||||||
assert(sonsLen(t.n) == sonsLen(t))
|
assert(sonsLen(t.n) == sonsLen(t))
|
||||||
for i in countup(0, sonsLen(t.n) - 1):
|
for i in countup(0, sonsLen(t.n) - 1):
|
||||||
assert(t.n.sons[i].kind == nkSym)
|
assert(t.n.sons[i].kind == nkSym)
|
||||||
add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
|
add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
|
||||||
if i < sonsLen(t.n) - 1: add(result, ", ")
|
if i < sonsLen(t.n) - 1: add(result, ", ")
|
||||||
|
add(result, ']')
|
||||||
|
elif sonsLen(t) == 0:
|
||||||
|
result = "tuple[]"
|
||||||
else:
|
else:
|
||||||
|
result = "("
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
add(result, typeToString(t.sons[i]))
|
add(result, typeToString(t.sons[i]))
|
||||||
if i < sonsLen(t) - 1: add(result, ", ")
|
if i < sonsLen(t) - 1: add(result, ", ")
|
||||||
add(result, ']')
|
add(result, ')')
|
||||||
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
|
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
|
||||||
result = typeToStr[t.kind]
|
result = typeToStr[t.kind]
|
||||||
if t.len >= 2:
|
if t.len >= 2:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue