bugfix: typeinfo generation for tuples

This commit is contained in:
Araq
2011-06-19 15:47:10 +02:00
parent 849208d779
commit 18bec94e22
7 changed files with 82 additions and 41 deletions

View File

@@ -641,20 +641,16 @@ proc genObjectInfo(m: BModule, typ: PType, name: PRope) =
genObjectFields(m, typ, typ.n, tmp)
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
var
tmp, expr, tmp2: PRope
length: int
a: PType
proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
genTypeInfoAuxBase(m, typ, name, toRope("0"))
expr = getNimNode(m)
length = sonsLen(typ)
var expr = getNimNode(m)
var length = sonsLen(typ)
if length > 0:
tmp = getTempName()
var tmp = getTempName()
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, toRope(length)])
for i in countup(0, length - 1):
a = typ.sons[i]
tmp2 = getNimNode(m)
var a = typ.sons[i]
var tmp2 = getNimNode(m)
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
"$1.offset = offsetof($2, Field$3);$n" & "$1.typ = $4;$n" &
@@ -665,7 +661,7 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
else:
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n",
[expr, toRope(length)])
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, expr])
proc genEnumInfo(m: BModule, typ: PType, name: PRope) =
# Type information for enumerations is quite heavy, so we do some

View File

@@ -36,9 +36,8 @@ proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym =
var a = c.generics.sons[i].sons[0].sym
if genericSym.id == a.id:
var b = c.generics.sons[i].sons[1].sym
if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
#if gVerbosity > 0 then
# MessageOut('found in cache: ' + getProcHeader(instSym));
if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
#echo "found in cache: ", getProcHeader(instSym)
return b
proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) =
@@ -66,20 +65,17 @@ proc removeDefaultParamValues(n: PNode) =
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym =
# generates an instantiated proc
var
oldPrc, oldMod: PSym
n: PNode
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
inc(c.InstCounter)
# NOTE: for access of private fields within generics from a different module
# and other identifiers we fake the current module temporarily!
# XXX bad hack!
oldMod = c.module
var oldMod = c.module
c.module = getModule(fn)
result = copySym(fn, false)
incl(result.flags, sfFromGeneric)
result.owner = getCurrOwner().owner
n = copyTree(fn.ast)
var n = copyTree(fn.ast)
result.ast = n
pushOwner(result)
openScope(c.tab)
@@ -98,7 +94,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
result.typ = newTypeS(tyProc, c)
addSon(result.typ, nil)
result.typ.callConv = fn.typ.callConv
oldPrc = GenericCacheGet(c, fn, result)
var oldPrc = GenericCacheGet(c, fn, result)
if oldPrc == nil:
# add it here, so that recursive generic procs are possible:
GenericCacheAdd(c, fn, result)
@@ -110,6 +106,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
addResultNode(c, n)
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
popProcCon(c)
#echo "code instantiated ", result.name.s
else:
result = oldPrc
popInfoContext()

View File

@@ -32,7 +32,7 @@ proc containsGenericType*(t: PType): bool =
proc searchInstTypes(tab: TIdTable, key: PType): PType =
# returns nil if we need to declare this type
result = PType(IdTableGet(tab, key))
if (result == nil) and (tab.counter > 0):
if result == nil and tab.counter > 0:
# we have to do a slow linear search because types may need
# to be compared by their structure:
for h in countup(0, high(tab.data)):
@@ -127,13 +127,13 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
of tyGenericBody:
InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody")
result = ReplaceTypeVarsT(cl, lastSon(t))
else:
if containsGenericType(t):
else:
if containsGenericType(t):
result = copyType(t, t.owner, false)
for i in countup(0, sonsLen(result) - 1):
for i in countup(0, sonsLen(result) - 1):
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
result.n = ReplaceTypeVarsN(cl, result.n)
if result.Kind in GenericTypes:
if result.Kind in GenericTypes:
LocalError(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
#writeln(output, ropeToStr(Typetoyaml(result)))
#checkConstructedType(cl.info, result)

View File

@@ -514,10 +514,10 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
popTransCon(c)
proc getMagicOp(call: PNode): TMagic =
if (call.sons[0].kind == nkSym) and
(call.sons[0].sym.kind in {skProc, skMethod, skConverter}):
if call.sons[0].kind == nkSym and
call.sons[0].sym.kind in {skProc, skMethod, skConverter}:
result = call.sons[0].sym.magic
else:
else:
result = mNone
proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
@@ -528,10 +528,10 @@ proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
var s = n.sym
var found = false
case s.kind
of skVar: found = not (sfGlobal in s.flags)
of skVar: found = sfGlobal notin s.flags
of skTemp, skForVar, skParam: found = true
else: nil
if found and (owner.id != s.owner.id) and not ContainsOrIncl(marked, s.id):
if found and owner.id != s.owner.id and not ContainsOrIncl(marked, s.id):
incl(s.flags, sfInClosure)
addSon(container, copyNode(n)) # DON'T make a copy of the symbol!
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
@@ -559,7 +559,7 @@ proc indirectAccess(a, b: PSym): PNode =
proc transformLambda(c: PTransf, n: PNode): PNode =
var marked = initIntSet()
result = n
if (n.sons[namePos].kind != nkSym): InternalError(n.info, "transformLambda")
if n.sons[namePos].kind != nkSym: InternalError(n.info, "transformLambda")
var s = n.sons[namePos].sym
var closure = newNodeI(nkRecList, n.sons[codePos].info)
gatherVars(c, n.sons[codePos], marked, s, closure)

View File

@@ -7,6 +7,43 @@
# distribution, for details about the copyright.
#
proc checkTypeInfo*(dest: Pointer, src: int, mt: pointer)
proc checkTypeInfo(dest: Pointer, src: int, n: ptr TNimNode) =
var
d = cast[TAddress](dest)
s = cast[TAddress](src)
case n.kind
of nkSlot: checkTypeInfo(cast[pointer](d +% n.offset), src, n.typ)
of nkList:
for i in 0..n.len-1: checkTypeInfo(dest, src, n.sons[i])
of nkCase:
var m = selectBranch(dest, n)
if m != nil: checkTypeInfo(dest, src, m)
else:
c_fprintf(cstdout, "ugh memory corruption! in check type info %ld\n", src)
quit 1
#of nkNone: assert(false)
proc checkTypeInfo(dest: Pointer, src: int, mt: pointer) =
var mt = cast[PNimType](mt)
var
d = cast[TAddress](dest)
s = cast[TAddress](src)
assert(mt != nil)
case mt.Kind
of tyString: nil
of tySequence: nil
of tyObject, tyTuple, tyPureObject:
checkTypeInfo(dest, src, mt.node)
of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1:
checkTypeInfo(cast[pointer](d +% i*% mt.base.size),
src, mt.base)
of tyRef: nil
else:
nil # copy raw bits
proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool)
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
var

View File

@@ -13,13 +13,24 @@ type
data: TKeyValuePairSeq[A, B]
counter: int
proc len*[A, B](t: TTable[A, B]): int =
result = t.counter
iterator mycountup(a, b: int): int =
var res = a
while res <= b:
yield res
inc(res)
iterator pairs*[A, B](t: TTable[A, B]): tuple[key: A, val: B] =
## iterates over any (key, value) pair in the table `t`.
for h in 0..high(t.data):
if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
var h = 0
while h <= high(t.data):
var k = t.data[h].key
if t.data[h].slot == seFilled: yield (k, t.data[h].val)
inc(h)
when false:
for h in mycountup(0, high(t.data)):
var k = t.data[h].key
if t.data[h].slot == seFilled: yield (k, t.data[h].val)
proc initTable*[A, B](initialSize=64): TTable[A, B] =
## creates a new hash table that is empty. `initialSize` needs to be

View File

@@ -1,14 +1,14 @@
High priority (version 0.8.12)
==============================
* implement message passing built-ins
* add --deadlock_prevention:on|off switch? timeout for locks?
* built-in serialization
- bug: invoking a generic iterator twice triggers a code gen bug (titer2)
- sorting with leads to a strange memory corruption!
- sorting with leads to a strange memory corruption: tsimplesort
--> system.swap or genericAssign is broken! And indeed, if reference counts
are not modified and the GC is triggered in between a swap, bad things
may happen!
- bug: invoking a generic iterator twice triggers a code gen bug (titer2)
* implement message passing built-ins
* add --deadlock_prevention:on|off switch? timeout for locks?
* built-in serialization
version 0.9.0