bugfix: typeinfo generation for tuples
This commit is contained in:
parent
849208d779
commit
18bec94e22
7 changed files with 82 additions and 41 deletions
|
|
@ -642,19 +642,15 @@ proc genObjectInfo(m: BModule, typ: PType, name: PRope) =
|
||||||
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
|
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
|
||||||
|
|
||||||
proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
|
proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
|
||||||
var
|
|
||||||
tmp, expr, tmp2: PRope
|
|
||||||
length: int
|
|
||||||
a: PType
|
|
||||||
genTypeInfoAuxBase(m, typ, name, toRope("0"))
|
genTypeInfoAuxBase(m, typ, name, toRope("0"))
|
||||||
expr = getNimNode(m)
|
var expr = getNimNode(m)
|
||||||
length = sonsLen(typ)
|
var length = sonsLen(typ)
|
||||||
if length > 0:
|
if length > 0:
|
||||||
tmp = getTempName()
|
var tmp = getTempName()
|
||||||
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, toRope(length)])
|
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, toRope(length)])
|
||||||
for i in countup(0, length - 1):
|
for i in countup(0, length - 1):
|
||||||
a = typ.sons[i]
|
var a = typ.sons[i]
|
||||||
tmp2 = getNimNode(m)
|
var tmp2 = getNimNode(m)
|
||||||
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
|
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
|
||||||
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
|
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
|
||||||
"$1.offset = offsetof($2, Field$3);$n" & "$1.typ = $4;$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:
|
else:
|
||||||
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n",
|
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n",
|
||||||
[expr, toRope(length)])
|
[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) =
|
proc genEnumInfo(m: BModule, typ: PType, name: PRope) =
|
||||||
# Type information for enumerations is quite heavy, so we do some
|
# Type information for enumerations is quite heavy, so we do some
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,7 @@ proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym =
|
||||||
if genericSym.id == a.id:
|
if genericSym.id == a.id:
|
||||||
var b = c.generics.sons[i].sons[1].sym
|
var b = c.generics.sons[i].sons[1].sym
|
||||||
if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
|
if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
|
||||||
#if gVerbosity > 0 then
|
#echo "found in cache: ", getProcHeader(instSym)
|
||||||
# MessageOut('found in cache: ' + getProcHeader(instSym));
|
|
||||||
return b
|
return b
|
||||||
|
|
||||||
proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) =
|
proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) =
|
||||||
|
|
@ -66,20 +65,17 @@ proc removeDefaultParamValues(n: PNode) =
|
||||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
# generates an instantiated proc
|
# generates an instantiated proc
|
||||||
var
|
|
||||||
oldPrc, oldMod: PSym
|
|
||||||
n: PNode
|
|
||||||
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
||||||
inc(c.InstCounter)
|
inc(c.InstCounter)
|
||||||
# NOTE: for access of private fields within generics from a different module
|
# NOTE: for access of private fields within generics from a different module
|
||||||
# and other identifiers we fake the current module temporarily!
|
# and other identifiers we fake the current module temporarily!
|
||||||
# XXX bad hack!
|
# XXX bad hack!
|
||||||
oldMod = c.module
|
var oldMod = c.module
|
||||||
c.module = getModule(fn)
|
c.module = getModule(fn)
|
||||||
result = copySym(fn, false)
|
result = copySym(fn, false)
|
||||||
incl(result.flags, sfFromGeneric)
|
incl(result.flags, sfFromGeneric)
|
||||||
result.owner = getCurrOwner().owner
|
result.owner = getCurrOwner().owner
|
||||||
n = copyTree(fn.ast)
|
var n = copyTree(fn.ast)
|
||||||
result.ast = n
|
result.ast = n
|
||||||
pushOwner(result)
|
pushOwner(result)
|
||||||
openScope(c.tab)
|
openScope(c.tab)
|
||||||
|
|
@ -98,7 +94,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
result.typ = newTypeS(tyProc, c)
|
result.typ = newTypeS(tyProc, c)
|
||||||
addSon(result.typ, nil)
|
addSon(result.typ, nil)
|
||||||
result.typ.callConv = fn.typ.callConv
|
result.typ.callConv = fn.typ.callConv
|
||||||
oldPrc = GenericCacheGet(c, fn, result)
|
var oldPrc = GenericCacheGet(c, fn, result)
|
||||||
if oldPrc == nil:
|
if oldPrc == nil:
|
||||||
# add it here, so that recursive generic procs are possible:
|
# add it here, so that recursive generic procs are possible:
|
||||||
GenericCacheAdd(c, fn, result)
|
GenericCacheAdd(c, fn, result)
|
||||||
|
|
@ -110,6 +106,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
addResultNode(c, n)
|
addResultNode(c, n)
|
||||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||||
popProcCon(c)
|
popProcCon(c)
|
||||||
|
#echo "code instantiated ", result.name.s
|
||||||
else:
|
else:
|
||||||
result = oldPrc
|
result = oldPrc
|
||||||
popInfoContext()
|
popInfoContext()
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ proc containsGenericType*(t: PType): bool =
|
||||||
proc searchInstTypes(tab: TIdTable, key: PType): PType =
|
proc searchInstTypes(tab: TIdTable, key: PType): PType =
|
||||||
# returns nil if we need to declare this type
|
# returns nil if we need to declare this type
|
||||||
result = PType(IdTableGet(tab, key))
|
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
|
# we have to do a slow linear search because types may need
|
||||||
# to be compared by their structure:
|
# to be compared by their structure:
|
||||||
for h in countup(0, high(tab.data)):
|
for h in countup(0, high(tab.data)):
|
||||||
|
|
|
||||||
|
|
@ -514,8 +514,8 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
|
||||||
popTransCon(c)
|
popTransCon(c)
|
||||||
|
|
||||||
proc getMagicOp(call: PNode): TMagic =
|
proc getMagicOp(call: PNode): TMagic =
|
||||||
if (call.sons[0].kind == nkSym) and
|
if call.sons[0].kind == nkSym and
|
||||||
(call.sons[0].sym.kind in {skProc, skMethod, skConverter}):
|
call.sons[0].sym.kind in {skProc, skMethod, skConverter}:
|
||||||
result = call.sons[0].sym.magic
|
result = call.sons[0].sym.magic
|
||||||
else:
|
else:
|
||||||
result = mNone
|
result = mNone
|
||||||
|
|
@ -528,10 +528,10 @@ proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
|
||||||
var s = n.sym
|
var s = n.sym
|
||||||
var found = false
|
var found = false
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar: found = not (sfGlobal in s.flags)
|
of skVar: found = sfGlobal notin s.flags
|
||||||
of skTemp, skForVar, skParam: found = true
|
of skTemp, skForVar, skParam: found = true
|
||||||
else: nil
|
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)
|
incl(s.flags, sfInClosure)
|
||||||
addSon(container, copyNode(n)) # DON'T make a copy of the symbol!
|
addSon(container, copyNode(n)) # DON'T make a copy of the symbol!
|
||||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||||
|
|
@ -559,7 +559,7 @@ proc indirectAccess(a, b: PSym): PNode =
|
||||||
proc transformLambda(c: PTransf, n: PNode): PNode =
|
proc transformLambda(c: PTransf, n: PNode): PNode =
|
||||||
var marked = initIntSet()
|
var marked = initIntSet()
|
||||||
result = n
|
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 s = n.sons[namePos].sym
|
||||||
var closure = newNodeI(nkRecList, n.sons[codePos].info)
|
var closure = newNodeI(nkRecList, n.sons[codePos].info)
|
||||||
gatherVars(c, n.sons[codePos], marked, s, closure)
|
gatherVars(c, n.sons[codePos], marked, s, closure)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,43 @@
|
||||||
# distribution, for details about the copyright.
|
# 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, mt: PNimType, shallow: bool)
|
||||||
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
||||||
var
|
var
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,24 @@ type
|
||||||
data: TKeyValuePairSeq[A, B]
|
data: TKeyValuePairSeq[A, B]
|
||||||
counter: int
|
counter: int
|
||||||
|
|
||||||
proc len*[A, B](t: TTable[A, B]): int =
|
iterator mycountup(a, b: int): int =
|
||||||
result = t.counter
|
var res = a
|
||||||
|
while res <= b:
|
||||||
|
yield res
|
||||||
|
inc(res)
|
||||||
|
|
||||||
iterator pairs*[A, B](t: TTable[A, B]): tuple[key: A, val: B] =
|
iterator pairs*[A, B](t: TTable[A, B]): tuple[key: A, val: B] =
|
||||||
## iterates over any (key, value) pair in the table `t`.
|
## iterates over any (key, value) pair in the table `t`.
|
||||||
for h in 0..high(t.data):
|
var h = 0
|
||||||
if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
|
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] =
|
proc initTable*[A, B](initialSize=64): TTable[A, B] =
|
||||||
## creates a new hash table that is empty. `initialSize` needs to be
|
## creates a new hash table that is empty. `initialSize` needs to be
|
||||||
|
|
|
||||||
12
todo.txt
12
todo.txt
|
|
@ -1,14 +1,14 @@
|
||||||
High priority (version 0.8.12)
|
High priority (version 0.8.12)
|
||||||
==============================
|
==============================
|
||||||
* implement message passing built-ins
|
- sorting with leads to a strange memory corruption: tsimplesort
|
||||||
|
|
||||||
* 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!
|
|
||||||
--> system.swap or genericAssign is broken! And indeed, if reference counts
|
--> 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
|
are not modified and the GC is triggered in between a swap, bad things
|
||||||
may happen!
|
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
|
version 0.9.0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue