mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-21 03:50:43 +00:00
bugfix: typeinfo generation for tuples
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
12
todo.txt
12
todo.txt
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user