bugfix: field names of tuples are treated consistently in the C backend

This commit is contained in:
Araq
2012-05-27 14:57:12 +02:00
parent 558d0db89f
commit 7a249eb8c1
5 changed files with 39 additions and 25 deletions

View File

@@ -283,7 +283,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
proc expr(p: BProc, e: PNode, d: var TLoc)
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
initLoc(result, locNone, getUniqueType(e.typ), OnUnknown)
initLoc(result, locNone, e.typ, OnUnknown)
expr(p, e, result)
proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
@@ -543,17 +543,17 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
initLocExpr(p, e.sons[0], a)
if (e.sons[1].kind != nkSym): InternalError(e.info, "genRecordFieldAux")
if e.sons[1].kind != nkSym: InternalError(e.info, "genRecordFieldAux")
if d.k == locNone: d.s = a.s
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
result = getUniqueType(a.t)
result = a.t
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
var a: TLoc
var ty = genRecordFieldAux(p, e, d, a)
var r = rdLoc(a)
var f = e.sons[1].sym
if ty.n == nil:
if ty.kind == tyTuple:
# we found a unique tuple type which lacks field information
# so we use Field$i
appf(r, ".Field$1", [toRope(f.position)])
@@ -561,14 +561,14 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
else:
var field: PSym = nil
while ty != nil:
if not (ty.kind in {tyTuple, tyObject}):
if ty.kind notin {tyTuple, tyObject}:
InternalError(e.info, "genRecordField")
field = lookupInRecord(ty.n, f.name)
if field != nil: break
if gCmd != cmdCompileToCpp: app(r, ".Sup")
ty = GetUniqueType(ty.sons[0])
if field == nil: InternalError(e.info, "genRecordField")
if field.loc.r == nil: InternalError(e.info, "genRecordField")
if field == nil: InternalError(e.info, "genRecordField 2 ")
if field.loc.r == nil: InternalError(e.info, "genRecordField 3")
appf(r, ".$1", [field.loc.r])
putIntoDest(p, d, field.typ, r)
@@ -579,16 +579,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[0], a)
if d.k == locNone: d.s = a.s
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
var ty = getUniqueType(a.t)
var ty = a.t
var r = rdLoc(a)
case e.sons[1].kind
of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal)
else: internalError(e.info, "genTupleElem")
if ty.n != nil:
var field = ty.n.sons[i].sym
if field == nil: InternalError(e.info, "genTupleElem")
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
appf(r, ".$1", [field.loc.r])
when false:
if ty.n != nil:
var field = ty.n.sons[i].sym
if field == nil: InternalError(e.info, "genTupleElem")
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
appf(r, ".$1", [field.loc.r])
else:
appf(r, ".Field$1", [toRope(i)])
putIntoDest(p, d, ty.sons[i], r)
@@ -1508,11 +1509,10 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i]
if it.kind == nkExprColonExpr: it = it.sons[1]
if t.n == nil:
initLoc(rec, locExpr, it.typ, d.s)
rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
expr(p, it, rec)
else:
initLoc(rec, locExpr, it.typ, d.s)
rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
expr(p, it, rec)
when false:
initLoc(rec, locExpr, it.typ, d.s)
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr")
rec.r = ropef("$1.$2",

View File

@@ -32,7 +32,7 @@ proc genVarTuple(p: BProc, n: PNode) =
assignLocalVar(p, v)
initLocalVar(p, v, immediateAsgn=true)
initLoc(field, locExpr, t.sons[i], tup.s)
if t.n == nil:
if t.kind == tyTuple:
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
else:
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple")

View File

@@ -561,7 +561,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
IdTablePut(m.forwTypeCache, t, result)
IdTablePut(m.typeCache, t, result) # always call for sideeffects:
if t.n != nil: recdesc = getRecordDesc(m, t, result, check)
if t.kind != tyTuple: recdesc = getRecordDesc(m, t, result, check)
else: recdesc = getTupleDesc(m, t, result, check)
if not isImportedType(t): app(m.s[cfsTypes], recdesc)
of tySet:
@@ -889,8 +889,11 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
of tyEnum: genEnumInfo(gNimDat, t, result)
of tyObject: genObjectInfo(gNimDat, t, result)
of tyTuple:
if t.n != nil: genObjectInfo(gNimDat, t, result)
else: genTupleInfo(gNimDat, t, result)
# if t.n != nil: genObjectInfo(gNimDat, t, result)
# else:
# BUGFIX: use consistently RTTI without proper field names; otherwise
# results are not deterministic!
genTupleInfo(gNimDat, t, result)
else: InternalError("genTypeInfo(" & $t.kind & ')')
proc genTypeSection(m: BModule, n: PNode) =

View File

@@ -87,14 +87,19 @@ proc GetUniqueType*(key: PType): PType =
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
result = GetUniqueType(lastSon(key))
of tyArrayConstr, tyGenericInvokation, tyGenericBody,
tyOpenArray, tyArray, tyTuple, tySet, tyRange,
tyOpenArray, tyArray, tySet, tyRange, tyTuple,
tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
# tuples are quite horrible as C does not support them directly and
# tuple[string, string] is a (strange) subtype of
# tuple[nameA, nameB: string]. This bites us here, so we
# use 'sameBackendType' instead of 'sameType'.
# we have to do a slow linear search because types may need
# to be compared by their structure:
if IdTableHasObjectAsKey(gTypeTable[k], key): return key
for h in countup(0, high(gTypeTable[k].data)):
var t = PType(gTypeTable[k].data[h].key)
if t != nil and sameType(t, key):
if t != nil and sameBackendType(t, key):
return t
IdTablePut(gTypeTable[k], key, key)
result = key

View File

@@ -550,6 +550,7 @@ type
TSameTypeClosure = object {.pure.}
cmp: TDistinctCompare
ignoreTupleFields: bool
recCheck: int
s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
# (few elements expected)
@@ -645,7 +646,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
for i in countup(0, sonsLen(a) - 1):
result = SameTypeAux(a.sons[i], b.sons[i], c)
if not result: return
if a.n != nil and b.n != nil:
if a.n != nil and b.n != nil and not c.ignoreTupleFields:
for i in countup(0, sonsLen(a.n) - 1):
# check field names:
if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
@@ -787,6 +788,11 @@ proc SameType*(x, y: PType): bool =
var c = initSameTypeClosure()
result = sameTypeAux(x, y, c)
proc sameBackendType*(x, y: PType): bool =
var c = initSameTypeClosure()
c.ignoreTupleFields = true
result = sameTypeAux(x, y, c)
proc compareTypes*(x, y: PType, cmp: TDistinctCompare): bool =
## compares two type for equality (modulo type distinction)
var c = initSameTypeClosure()