diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 26c0242f5c..6d9533dd1d 100755 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -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 diff --git a/compiler/seminst.nim b/compiler/seminst.nim index e37c6e0fc8..6d2eaa6d12 100755 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -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() diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index b6126e2852..e5f573248b 100755 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -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) diff --git a/compiler/transf.nim b/compiler/transf.nim index f301a3717e..4031e6eb45 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -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) diff --git a/lib/system/assign.nim b/lib/system/assign.nim index 798409ba50..943d1f9bd3 100755 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -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 diff --git a/tests/accept/compile/titer2.nim b/tests/accept/compile/titer2.nim index 878ddf5e34..19c7298b0a 100644 --- a/tests/accept/compile/titer2.nim +++ b/tests/accept/compile/titer2.nim @@ -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 diff --git a/todo.txt b/todo.txt index 068068bebb..424a32b103 100755 --- a/todo.txt +++ b/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