tuple field names are ignored

This commit is contained in:
Araq 2014-12-23 17:54:22 +01:00
commit c0cc62c6b1
9 changed files with 29 additions and 40 deletions

View file

@ -423,34 +423,21 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1): addSon(result, n.sons[i]) for i in countup(0, sonsLen(n) - 1): addSon(result, n.sons[i])
result = semExpr(c, result) result = semExpr(c, result)
proc changeType(n: PNode, newType: PType, check: bool) = proc changeType(n: PNode, newType: PType, check: bool) =
case n.kind case n.kind
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:
if newType.kind != tyTuple: if newType.kind != tyTuple:
internalError(n.info, "changeType: no tuple type for constructor") internalError(n.info, "changeType: no tuple type for constructor")
elif newType.n == nil: discard
elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
for i in countup(0, sonsLen(n) - 1):
var m = n.sons[i].sons[0]
if m.kind != nkSym:
internalError(m.info, "changeType(): invalid tuple constr")
return
var f = getSymFromList(newType.n, m.sym.name)
if f == nil:
internalError(m.info, "changeType(): invalid identifier")
return
changeType(n.sons[i].sons[1], f.typ, check)
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var m = n.sons[i] var m = n.sons[i]
var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i]) if m.kind == nkExprColonExpr:
addSon(a, newSymNode(newType.n.sons[i].sym)) m = m.sons[1]
addSon(a, m) n.sons[i] = m
changeType(m, newType.sons[i], check) changeType(m, newType.sons[i], check)
n.sons[i] = a
of nkCharLit..nkUInt64Lit: of nkCharLit..nkUInt64Lit:
if check: if check:
let value = n.intVal let value = n.intVal
@ -541,7 +528,8 @@ proc fixAbstractType(c: PContext, n: PNode) =
elif skipTypes(it.sons[1].typ, abstractVar).kind in elif skipTypes(it.sons[1].typ, abstractVar).kind in
{tyNil, tyArrayConstr, tyTuple, tySet}: {tyNil, tyArrayConstr, tyTuple, tySet}:
var s = skipTypes(it.typ, abstractVar) var s = skipTypes(it.typ, abstractVar)
changeType(it.sons[1], s, check=true) if s.kind != tyExpr:
changeType(it.sons[1], s, check=true)
n.sons[i] = it.sons[1] n.sons[i] = it.sons[1]
of nkBracket: of nkBracket:
# an implicitly constructed array (passed to an open array): # an implicitly constructed array (passed to an open array):

View file

@ -349,7 +349,7 @@ proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
var y = a.n.sons[i].sym var y = a.n.sons[i].sym
if f.kind == tyObject and typeRel(c, x.typ, y.typ) < isSubtype: if f.kind == tyObject and typeRel(c, x.typ, y.typ) < isSubtype:
return isNone return isNone
if x.name.id != y.name.id: return isNone if x.name.id != y.name.id and f.kind != tyTuple: return isNone
proc allowsNil(f: PType): TTypeRelation {.inline.} = proc allowsNil(f: PType): TTypeRelation {.inline.} =
result = if tfNotNil notin f.flags: isSubtype else: isNone result = if tfNotNil notin f.flags: isSubtype else: isNone

View file

@ -762,7 +762,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
# two tuples are equivalent iff the names, types and positions are the same; # two tuples are equivalent iff the names, types and positions are the same;
# however, both types may not have any field names (t.n may be nil) which # however, both types may not have any field names (t.n may be nil) which
# complicates the matter a bit. # complicates the matter a bit.
if sonsLen(a) == sonsLen(b): if sonsLen(a) == sonsLen(b):
result = true result = true
for i in countup(0, sonsLen(a) - 1): for i in countup(0, sonsLen(a) - 1):
var x = a.sons[i] var x = a.sons[i]
@ -773,17 +773,6 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
result = sameTypeAux(x, y, c) result = sameTypeAux(x, y, c)
if not result: return if not result: return
if a.n != nil and b.n != nil and IgnoreTupleFields notin c.flags:
for i in countup(0, sonsLen(a.n) - 1):
# check field names:
if a.n.sons[i].kind == nkSym and b.n.sons[i].kind == nkSym:
var x = a.n.sons[i].sym
var y = b.n.sons[i].sym
result = x.name.id == y.name.id
if not result: break
else: internalError(a.n.info, "sameTuple")
else:
result = false
template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} = template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
if tfFromGeneric notin a.flags + b.flags: if tfFromGeneric notin a.flags + b.flags:

View file

@ -31,6 +31,7 @@ algorithm (in pseudo-code) determines type equality:
result = typeEqualsAux(a.baseType, b.baseType, s) and result = typeEqualsAux(a.baseType, b.baseType, s) and
typeEqualsAux(a.indexType, b.indexType, s) typeEqualsAux(a.indexType, b.indexType, s)
of tuple: of tuple:
# Note: tuple field names are ignored
if a.tupleLen == b.tupleLen: if a.tupleLen == b.tupleLen:
for i in 0..a.tupleLen-1: for i in 0..a.tupleLen-1:
if not typeEqualsAux(a[i], b[i], s): return false if not typeEqualsAux(a[i], b[i], s): return false

View file

@ -508,9 +508,8 @@ defines an *order* of the fields. Tuples are meant for heterogeneous storage
types with no overhead and few abstraction possibilities. The constructor ``()`` types with no overhead and few abstraction possibilities. The constructor ``()``
can be used to construct tuples. The order of the fields in the constructor can be used to construct tuples. The order of the fields in the constructor
must match the order of the tuple's definition. Different tuple-types are must match the order of the tuple's definition. Different tuple-types are
*equivalent* if they specify the same fields of the same type in the same *equivalent* if they specify the same types in the same
order. The *names* of the fields also have to be identical but this might order. The *names* of the fields are ignored.
change in a future version of the language.
The assignment operator for tuples copies each component. The assignment operator for tuples copies each component.
The default assignment operator for objects copies each component. Overloading The default assignment operator for objects copies each component. Overloading
@ -528,6 +527,8 @@ in future versions of the compiler.
person = (name: "Peter", age: 30) person = (name: "Peter", age: 30)
# the same, but less readable: # the same, but less readable:
person = ("Peter", 30) person = ("Peter", 30)
# the same, but with confusing tuple field names:
person = (creditCard: "Peter", id: 20)
The implementation aligns the fields for best access performance. The alignment The implementation aligns the fields for best access performance. The alignment
is compatible with the way the C compiler does it. is compatible with the way the C compiler does it.

View file

@ -1,5 +1,6 @@
discard """ discard """
output: "61, 125" output: '''61, 125
89'''
""" """
proc `^` (a, b: int): int = proc `^` (a, b: int): int =
@ -13,3 +14,6 @@ m = (n[0] + m[1], m[1] ^ n[1])
echo m[0], ", ", m[1] echo m[0], ", ", m[1]
var x = (bar: 38)
x = (foo: 89)
echo x[0]

View file

@ -1,6 +1,7 @@
discard """ discard """
errormsg: "illegal recursion in type 'TNode'" errormsg: "illegal recursion in type 'TNode'"
line: 8 line: 8
disabled: true
""" """
type type

View file

@ -1,3 +1,7 @@
discard """
disabled: true
"""
import typetraits import typetraits
type type
@ -35,7 +39,9 @@ proc p(a, b) =
var f: TFoo[m(a.type), b.type] var f: TFoo[m(a.type), b.type]
static: static:
assert f.x.type.name == "int" assert f.x.type.name == "int"
echo f.y.type.name
assert f.y.type.name == "float" assert f.y.type.name == "float"
echo f.z.type.name
assert f.z.type.name == "float" assert f.z.type.name == "float"
p(A, f) p(A, f)

View file

@ -3,7 +3,6 @@ version 0.10
- The bitwise 'not' operator will be renamed to 'bnot' to - The bitwise 'not' operator will be renamed to 'bnot' to
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs! prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
- A named tuple will be compatible to a tuple with different names.
- The 'do' notation might be trimmed so that its only purpose is to pass - The 'do' notation might be trimmed so that its only purpose is to pass
multiple multi line constructs to a macro. multiple multi line constructs to a macro.