intsets are now a proper module and part of the stdlib

This commit is contained in:
Araq
2011-06-14 01:36:49 +02:00
parent ca637c019c
commit ade67f1abc
25 changed files with 297 additions and 286 deletions

View File

@@ -10,7 +10,7 @@
# abstract syntax tree + symbol table
import
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, intsets
const
ImportTablePos* = 0
@@ -620,39 +620,6 @@ proc leValue*(a, b: PNode): bool
# a <= b? a, b are literals
proc ValueToString*(a: PNode): string
# ------------- efficient integer sets -------------------------------------
type
TBitScalar* = int
const
InitIntSetSize* = 8 # must be a power of two!
TrunkShift* = 9
BitsPerTrunk* = 1 shl TrunkShift # needs to be a power of 2 and
# divisible by 64
TrunkMask* = BitsPerTrunk - 1
IntsPerTrunk* = BitsPerTrunk div (sizeof(TBitScalar) * 8)
IntShift* = 5 + ord(sizeof(TBitScalar) == 8) # 5 or 6, depending on int width
IntMask* = 1 shl IntShift - 1
type
PTrunk* = ref TTrunk
TTrunk*{.final.} = object
next*: PTrunk # all nodes are connected with this pointer
key*: int # start address at bit 0
bits*: array[0..IntsPerTrunk - 1, TBitScalar] # a bit vector
TTrunkSeq* = seq[PTrunk]
TIntSet*{.final.} = object
counter*, max*: int
head*: PTrunk
data*: TTrunkSeq
proc IntSetContains*(s: TIntSet, key: int): bool
proc IntSetIncl*(s: var TIntSet, key: int)
proc IntSetExcl*(s: var TIntSet, key: int)
proc IntSetInit*(s: var TIntSet)
proc IntSetContainsOrIncl*(s: var TIntSet, key: int): bool
const
debugIds* = false
@@ -663,7 +630,7 @@ var usedIds: TIntSet
proc registerID(id: PIdObj) =
if debugIDs:
if (id.id == - 1) or IntSetContainsOrIncl(usedIds, id.id):
if (id.id == - 1) or ContainsOrIncl(usedIds, id.id):
InternalError("ID already used: " & $(id.id))
proc getID(): int =
@@ -1036,109 +1003,4 @@ proc getStrOrChar*(a: PNode): string =
internalError(a.info, "getStrOrChar")
result = ""
proc mustRehash(length, counter: int): bool {.inline.} =
assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4)
proc nextTry(h, maxHash: THash): THash {.inline.} =
result = ((5 * h) + 1) and maxHash
# For any initial h in range(maxHash), repeating that maxHash times
# generates each int in range(maxHash) exactly once (see any text on
# random-number generation for proof).
proc IntSetInit(s: var TIntSet) =
newSeq(s.data, InitIntSetSize)
s.max = InitIntSetSize - 1
s.counter = 0
s.head = nil
proc IntSetGet(t: TIntSet, key: int): PTrunk =
var h = key and t.max
while t.data[h] != nil:
if t.data[h].key == key:
return t.data[h]
h = nextTry(h, t.max)
result = nil
proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) =
var h = desc.key and t.max
while data[h] != nil:
assert(data[h] != desc)
h = nextTry(h, t.max)
assert(data[h] == nil)
data[h] = desc
proc IntSetEnlarge(t: var TIntSet) =
var
n: TTrunkSeq
oldMax: int
oldMax = t.max
t.max = ((t.max + 1) * 2) - 1
newSeq(n, t.max + 1)
for i in countup(0, oldmax):
if t.data[i] != nil: IntSetRawInsert(t, n, t.data[i])
swap(t.data, n)
proc IntSetPut(t: var TIntSet, key: int): PTrunk =
var h = key and t.max
while t.data[h] != nil:
if t.data[h].key == key:
return t.data[h]
h = nextTry(h, t.max)
if mustRehash(t.max + 1, t.counter): IntSetEnlarge(t)
inc(t.counter)
h = key and t.max
while t.data[h] != nil: h = nextTry(h, t.max)
assert(t.data[h] == nil)
new(result)
result.next = t.head
result.key = key
t.head = result
t.data[h] = result
proc IntSetContains(s: TIntSet, key: int): bool =
var
u: TBitScalar
t: PTrunk
t = IntSetGet(s, `shr`(key, TrunkShift))
if t != nil:
u = key and TrunkMask
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
else:
result = false
proc IntSetIncl(s: var TIntSet, key: int) =
var
u: TBitScalar
t: PTrunk
t = IntSetPut(s, `shr`(key, TrunkShift))
u = key and TrunkMask
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
`shl`(1, u and IntMask)
proc IntSetExcl(s: var TIntSet, key: int) =
var
u: TBitScalar
t: PTrunk
t = IntSetGet(s, `shr`(key, TrunkShift))
if t != nil:
u = key and TrunkMask
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
not `shl`(1, u and IntMask)
proc IntSetContainsOrIncl(s: var TIntSet, key: int): bool =
var
u: TBitScalar
t: PTrunk
t = IntSetGet(s, `shr`(key, TrunkShift))
if t != nil:
u = key and TrunkMask
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
if not result:
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
`shl`(1, u and IntMask)
else:
IntSetIncl(s, key)
result = false
if debugIDs: IntSetInit(usedIds)
if debugIDs: usedIds = InitIntSet()

View File

@@ -12,7 +12,7 @@
# the data structures here are used in various places of the compiler.
import
ast, hashes, strutils, options, msgs, ropes, idents, rodutils
ast, hashes, intsets, strutils, options, msgs, ropes, idents, rodutils
proc hashNode*(p: PObject): THash
proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope
@@ -263,7 +263,7 @@ proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int,
maxRecDepth: int): PRope =
if n == nil:
result = toRope("null")
elif IntSetContainsOrIncl(marker, n.id):
elif ContainsOrIncl(marker, n.id):
result = ropef("\"$1 @$2\"", [toRope(n.name.s), toRope(
strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
else:
@@ -284,7 +284,7 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
maxRecDepth: int): PRope =
if n == nil:
result = toRope("null")
elif intSetContainsOrIncl(marker, n.id):
elif ContainsOrIncl(marker, n.id):
result = ropef("\"$1 @$2\"", [toRope($n.kind), toRope(
strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
else:
@@ -346,18 +346,15 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
appf(result, "$n$1}", [spaces(indent)])
proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = treeToYamlAux(n, marker, indent, maxRecDepth)
proc typeToYaml(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = typeToYamlAux(n, marker, indent, maxRecDepth)
proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = symToYamlAux(n, marker, indent, maxRecDepth)
proc debugType(n: PType): PRope =
@@ -612,15 +609,15 @@ proc NextIdentExcluding*(ti: var TIdentIter, tab: TStrTable,
var start = h
result = tab.data[h]
while result != nil:
if result.Name.id == ti.name.id and
not IntSetContains(excluding, result.id): break
if result.Name.id == ti.name.id and not Contains(excluding, result.id):
break
h = nextTry(h, high(tab.data))
if h == start:
result = nil
break
result = tab.data[h]
ti.h = nextTry(h, high(tab.data))
if result != nil and IntSetContains(excluding, result.id): result = nil
if result != nil and Contains(excluding, result.id): result = nil
proc FirstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
excluding: TIntSet): PSym =

View File

@@ -709,7 +709,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
assert t.kind == tyObject
discard genTypeInfo(p.module, t)
var L = lengthOrd(field.typ)
if not IntSetContainsOrIncl(p.module.declaredThings, field.id):
if not ContainsOrIncl(p.module.declaredThings, field.id):
appcg(p.module, cfsVars, "extern $1",
discriminatorTableDecl(p.module, t, field))
appcg(p, cpsStmts,

View File

@@ -387,7 +387,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
if t.sym != nil: useHeader(m, t.sym)
result = getTypePre(m, t)
if result != nil: return
if IntSetContainsOrIncl(check, t.id):
if ContainsOrIncl(check, t.id):
InternalError("cannot generate C type for: " & typeToString(typ))
# XXX: this BUG is hard to fix -> we need to introduce helper structs,
# but determining when this needs to be done is hard. We should split
@@ -490,8 +490,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
result = nil
proc getTypeDesc(m: BModule, typ: PType): PRope =
var check: TIntSet
IntSetInit(check)
var check = initIntSet()
result = getTypeDescAux(m, typ, check)
proc getTypeDesc(m: BModule, magic: string): PRope =
@@ -511,10 +510,9 @@ proc finishTypeDescriptions(m: BModule) =
proc genProcHeader(m: BModule, prc: PSym): PRope =
var
rettype, params: PRope
check: TIntSet
# using static is needed for inline procs
if (prc.typ.callConv == ccInline): result = toRope"static "
IntSetInit(check)
var check = initIntSet()
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown)
genProcParams(m, prc.typ, rettype, params, check)
appf(result, "$1($2, $3)$4",
@@ -736,7 +734,7 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
else:
dataGenerated = true
result = ropef("NTI$1", [toRope(id)])
if not IntSetContainsOrIncl(m.typeInfoMarker, id):
if not ContainsOrIncl(m.typeInfoMarker, id):
# declare type information structures:
discard cgsym(m, "TNimType")
discard cgsym(m, "TNimNode")

View File

@@ -12,7 +12,7 @@
import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
options,
options, intsets,
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
rodutils
@@ -690,12 +690,12 @@ proc genProcPrototype(m: BModule, sym: PSym) =
if lfNoDecl in sym.loc.Flags: return
if lfDynamicLib in sym.loc.Flags:
if sym.owner.id != m.module.id and
not intSetContainsOrIncl(m.declaredThings, sym.id):
not ContainsOrIncl(m.declaredThings, sym.id):
appff(m.s[cfsVars], "extern $1 $2;$n",
"@$2 = linkonce global $1 zeroinitializer$n",
[getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
elif not IntSetContainsOrIncl(m.declaredProtos, sym.id):
elif not ContainsOrIncl(m.declaredProtos, sym.id):
appf(m.s[cfsProcHeaders], "$1;$n", [genProcHeader(m, sym)])
proc genProcNoForward(m: BModule, prc: PSym) =
@@ -707,12 +707,12 @@ proc genProcNoForward(m: BModule, prc: PSym) =
# We add inline procs to the calling module to enable C based inlining.
# This also means that a check with ``gGeneratedSyms`` is wrong, we need
# a check for ``m.declaredThings``.
if not intSetContainsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
if not ContainsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
elif lfDynamicLib in prc.loc.flags:
if not IntSetContainsOrIncl(gGeneratedSyms, prc.id):
if not ContainsOrIncl(gGeneratedSyms, prc.id):
SymInDynamicLib(findPendingModule(m, prc), prc)
elif not (sfImportc in prc.flags):
if not IntSetContainsOrIncl(gGeneratedSyms, prc.id):
if not ContainsOrIncl(gGeneratedSyms, prc.id):
genProcAux(findPendingModule(m, prc), prc)
proc genProc(m: BModule, prc: PSym) =
@@ -726,7 +726,7 @@ proc genVarPrototype(m: BModule, sym: PSym) =
useHeader(m, sym)
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap)
if (lfNoDecl in sym.loc.Flags) or
intSetContainsOrIncl(m.declaredThings, sym.id):
ContainsOrIncl(m.declaredThings, sym.id):
return
if sym.owner.id != m.module.id:
# else we already have the symbol generated!
@@ -748,7 +748,7 @@ proc genConstPrototype(m: BModule, sym: PSym) =
if sym.loc.k == locNone:
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown)
if (lfNoDecl in sym.loc.Flags) or
intSetContainsOrIncl(m.declaredThings, sym.id):
ContainsOrIncl(m.declaredThings, sym.id):
return
if sym.owner.id != m.module.id:
# else we already have the symbol generated!
@@ -903,14 +903,14 @@ proc genModule(m: BModule, cfilenoext: string): PRope =
proc rawNewModule(module: PSym, filename: string): BModule =
new(result)
InitLinkedList(result.headerFiles)
intSetInit(result.declaredThings)
intSetInit(result.declaredProtos)
result.declaredThings = initIntSet()
result.declaredProtos = initIntSet()
result.cfilename = filename
result.filename = filename
initIdTable(result.typeCache)
initIdTable(result.forwTypeCache)
result.module = module
intSetInit(result.typeInfoMarker)
result.typeInfoMarker = initIntSet()
result.initProc = newProc(nil, result)
result.initProc.options = gOptions
initNodeTable(result.dataCache)
@@ -1037,4 +1037,4 @@ proc cgenPass(): TPass =
result.close = myClose
InitIiTable(gToTypeInfoId)
IntSetInit(gGeneratedSyms)
gGeneratedSyms = initIntSet()

View File

@@ -10,7 +10,7 @@
## This module implements code generation for multi methods.
import
options, ast, astalgo, msgs, idents, renderer, types, magicsys
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
var dest = skipTypes(d, abstractPtrs)
@@ -95,7 +95,7 @@ proc relevantCol(methods: TSymSeq, col: int): bool =
proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int =
result = 0
for col in countup(1, sonsLen(a.typ) - 1):
if intSetContains(relevantCols, col):
if Contains(relevantCols, col):
var aa = skipTypes(a.typ.sons[col], skipPtrs)
var bb = skipTypes(b.typ.sons[col], skipPtrs)
var d = inheritanceDiff(aa, bb)
@@ -132,7 +132,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
var curr = methods[meth] # generate condition:
var cond: PNode = nil
for col in countup(1, paramLen - 1):
if IntSetContains(relevantCols, col):
if Contains(relevantCols, col):
var isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
addSon(isn, newSymNode(iss))
addSon(isn, newSymNode(base.typ.n.sons[col].sym))
@@ -169,12 +169,11 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
result.ast.sons[codePos] = disp
proc generateMethodDispatchers*(): PNode =
var relevantCols: TIntSet
result = newNode(nkStmtList)
for bucket in countup(0, len(gMethods) - 1):
IntSetInit(relevantCols)
var relevantCols = initIntSet()
for col in countup(1, sonsLen(gMethods[bucket][0].typ) - 1):
if relevantCol(gMethods[bucket], col): IntSetIncl(relevantCols, col)
if relevantCol(gMethods[bucket], col): Incl(relevantCols, col)
sortBucket(gMethods[bucket], relevantCols)
addSon(result, newSymNode(genDispatcher(gMethods[bucket], relevantCols)))

View File

@@ -14,7 +14,8 @@
import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils,
intsets
proc ecmasgenPass*(): TPass
# implementation
@@ -67,7 +68,7 @@ type
proc newGlobals(): PGlobals =
new(result)
IntSetInit(result.typeInfoGenerated)
result.typeInfoGenerated = initIntSet()
proc initCompRes(r: var TCompRes) =
r.com = nil
@@ -228,7 +229,7 @@ proc genTypeInfo(p: var TProc, typ: PType): PRope =
var t = typ
if t.kind == tyGenericInst: t = lastSon(t)
result = ropef("NTI$1", [toRope(t.id)])
if IntSetContainsOrIncl(p.globals.TypeInfoGenerated, t.id): return
if ContainsOrIncl(p.globals.TypeInfoGenerated, t.id): return
case t.kind
of tyDistinct:
result = genTypeInfo(p, typ.sons[0])

View File

@@ -10,8 +10,8 @@
# This module implements the symbol importing mechanism.
import
strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups, semdata,
passes
intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups,
semdata, passes
proc evalImport*(c: PContext, n: PNode): PNode
proc evalFrom*(c: PContext, n: PNode): PNode
@@ -45,8 +45,8 @@ proc rawImportSymbol(c: PContext, s: PSym) =
if (check != nil) and (check.id != copy.id):
if not (s.kind in OverloadableSyms):
# s and check need to be qualified:
IntSetIncl(c.AmbiguousSymbols, copy.id)
IntSetIncl(c.AmbiguousSymbols, check.id)
Incl(c.AmbiguousSymbols, copy.id)
Incl(c.AmbiguousSymbols, check.id)
StrTableAdd(c.tab.stack[importTablePos], copy)
if s.kind == skType:
var etyp = s.typ

View File

@@ -10,7 +10,8 @@
# This module implements lookup helpers.
import
ast, astalgo, idents, semdata, types, msgs, options, rodread, renderer
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
renderer
proc considerAcc*(n: PNode): PIdent =
case n.kind
@@ -115,7 +116,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
result = SymtabGet(c.Tab, ident)
if result == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s)
else: InternalError(n.info, "lookUp")
if IntSetContains(c.AmbiguousSymbols, result.id):
if Contains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, result.name.s)
if result.kind == skStub: loadStub(result)
@@ -131,12 +132,11 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
if result == nil and checkUndeclared in flags:
GlobalError(n.info, errUndeclaredIdentifier, ident.s)
elif checkAmbiguity in flags and result != nil and
IntSetContains(c.AmbiguousSymbols, result.id):
Contains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, ident.s)
of nkSym:
result = n.sym
if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols,
result.id):
if checkAmbiguity in flags and Contains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, n.sym.name.s)
of nkDotExpr:
result = nil
@@ -197,8 +197,8 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoice
result = n.sons[0].sym
o.stackPtr = 1
IntSetInit(o.inSymChoice)
IntSetIncl(o.inSymChoice, result.id)
o.inSymChoice = initIntSet()
Incl(o.inSymChoice, result.id)
else: nil
if result != nil and result.kind == skStub: loadStub(result)
@@ -223,7 +223,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimSymChoice:
if o.stackPtr < sonsLen(n):
result = n.sons[o.stackPtr].sym
IntSetIncl(o.inSymChoice, result.id)
Incl(o.inSymChoice, result.id)
inc(o.stackPtr)
else:
# try 'local' symbols too for Koenig's lookup:

View File

@@ -12,8 +12,8 @@
# writing of rod files is split into two different modules.
import
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
ropes, idents, crc, rodread, passes, importer
intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
condsyms, ropes, idents, crc, rodread, passes, importer
proc rodwritePass*(): TPass
# implementation
@@ -446,4 +446,4 @@ proc rodwritePass(): TPass =
result.close = myClose
result.process = process
IntSetInit(debugWritten)
debugWritten= initIntSet()

View File

@@ -14,7 +14,7 @@ import
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer,
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest,
semthreads
semthreads, intsets
proc semPass*(): TPass
# implementation

View File

@@ -10,7 +10,8 @@
# This module contains the data structures for the semantic checking phase.
import
strutils, lists, options, lexer, ast, astalgo, trees, treetab, wordrecg,
strutils, lists, intsets, options, lexer, ast, astalgo, trees, treetab,
wordrecg,
ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
magicsys, nversion, nimsets, parser, times, passes, rodread
@@ -118,7 +119,7 @@ proc newOptionEntry(): POptionEntry =
proc newContext(module: PSym, nimfile: string): PContext =
new(result)
InitSymTab(result.tab)
IntSetInit(result.AmbiguousSymbols)
result.AmbiguousSymbols = initIntset()
initLinkedList(result.optionStack)
initLinkedList(result.libs)
append(result.optionStack, newOptionEntry())
@@ -127,7 +128,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
result.threadEntries = newNode(nkStmtList)
result.converters = @[]
result.filename = nimfile
IntSetInit(result.includedFiles)
result.includedFiles = initIntSet()
initStrTable(result.userPragmas)
proc addConverter(c: PContext, conv: PSym) =

View File

@@ -888,11 +888,10 @@ proc checkPar(n: PNode): TParKind =
return paNone
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
var ids: TIntSet
result = newNodeI(nkPar, n.info)
var typ = newTypeS(tyTuple, c)
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
IntSetInit(ids)
var ids = initIntSet()
for i in countup(0, sonsLen(n) - 1):
if (n.sons[i].kind != nkExprColonExpr) or
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
@@ -900,7 +899,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
var id: PIdent
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
else: id = n.sons[i].sons[0].sym.name
if IntSetContainsOrIncl(ids, id.id):
if ContainsOrIncl(ids, id.id):
localError(n.sons[i].info, errFieldInitTwice, id.s)
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
var f = newSymS(skField, n.sons[i].sons[0], c)

View File

@@ -476,11 +476,10 @@ proc semRaise(c: PContext, n: PNode): PNode =
localError(n.info, errExprCannotBeRaised)
proc semTry(c: PContext, n: PNode): PNode =
var check: TIntSet
result = n
checkMinSonsLen(n, 2)
n.sons[0] = semStmtScope(c, n.sons[0])
IntSetInit(check)
var check = initIntSet()
for i in countup(1, sonsLen(n) - 1):
var a = n.sons[i]
checkMinSonsLen(a, 1)
@@ -493,7 +492,7 @@ proc semTry(c: PContext, n: PNode): PNode =
GlobalError(a.sons[j].info, errExprCannotBeRaised)
a.sons[j] = newNodeI(nkType, a.sons[j].info)
a.sons[j].typ = typ
if IntSetContainsOrIncl(check, typ.id):
if ContainsOrIncl(check, typ.id):
localError(a.sons[j].info, errExceptionAlreadyHandled)
elif a.kind != nkFinally:
illFormedAst(n)
@@ -820,10 +819,10 @@ proc evalInclude(c: PContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1):
var f = getModuleFile(n.sons[i])
var fileIndex = includeFilename(f)
if IntSetContainsOrIncl(c.includedFiles, fileIndex):
if ContainsOrIncl(c.includedFiles, fileIndex):
GlobalError(n.info, errRecursiveDependencyX, f)
addSon(result, semStmt(c, gIncludeFile(f)))
IntSetExcl(c.includedFiles, fileIndex)
Excl(c.includedFiles, fileIndex)
proc SemStmt(c: PContext, n: PNode): PNode =
const # must be last statements in a block:

View File

@@ -117,7 +117,7 @@ proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
var s: PSym
case n.kind
of nkIdent:
if not withinBind and not IntSetContains(toBind, n.ident.id):
if not withinBind and not Contains(toBind, n.ident.id):
s = SymTabLocalGet(c.Tab, n.ident)
if (s != nil):
result = newSymNode(s)
@@ -125,7 +125,7 @@ proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
else:
result = n
else:
IntSetIncl(toBind, n.ident.id)
Incl(toBind, n.ident.id)
result = symChoice(c, n, lookup(c, n))
of nkEmpty, nkSym..nkNilLit: # atom
result = n
@@ -160,7 +160,6 @@ proc transformToExpr(n: PNode): PNode =
proc semTemplateDef(c: PContext, n: PNode): PNode =
var
s: PSym
toBind: TIntSet
if c.p.owner.kind == skModule:
s = semIdentVis(c, skTemplate, n.sons[0], {sfStar})
incl(s.flags, sfGlobal)
@@ -189,7 +188,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
s.typ.sons[0] = newTypeS(tyStmt, c)
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
addParams(c, s.typ.n) # resolve parameters:
IntSetInit(toBind)
var toBind = initIntSet()
n.sons[codePos] = resolveTemplateParams(c, n.sons[codePos], false, toBind)
if not (s.typ.sons[0].kind in {tyStmt, tyTypeDesc}):
n.sons[codePos] = transformToExpr(n.sons[codePos])

View File

@@ -192,10 +192,9 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
var
typ: PType
check: TIntSet
result = newOrPrevType(tyTuple, prev, c)
result.n = newNodeI(nkRecList, n.info)
IntSetInit(check)
var check = initIntSet()
var counter = 0
for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i]
@@ -212,7 +211,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
field.typ = typ
field.position = counter
inc(counter)
if IntSetContainsOrIncl(check, field.name.id):
if ContainsOrIncl(check, field.name.id):
GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
addSon(result.n, newSymNode(field))
addSon(result, typ)
@@ -396,7 +395,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
f.loc.r = toRope(f.name.s)
f.flags = f.flags + ({sfImportc, sfExportc} * rectype.flags)
inc(pos)
if IntSetContainsOrIncl(check, f.name.id):
if ContainsOrIncl(check, f.name.id):
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
if a.kind == nkEmpty: addSon(father, newSymNode(f))
else: addSon(a, newSymNode(f))
@@ -419,7 +418,7 @@ proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int,
for i in countup(0, sonsLen(n) - 1):
addInheritedFieldsAux(c, check, pos, n.sons[i])
of nkSym:
IntSetIncl(check, n.sym.name.id)
Incl(check, n.sym.name.id)
inc(pos)
else: InternalError(n.info, "addInheritedFieldsAux()")
@@ -437,8 +436,7 @@ proc skipGenericInvokation(t: PType): PType {.inline.} =
result = lastSon(result)
proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
var check: TIntSet
IntSetInit(check)
var check = initIntSet()
var pos = 0
var base: PType = nil
# n.sons[0] contains the pragmas (if any). We process these later...
@@ -460,7 +458,7 @@ proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
cl: var TIntSet): PType =
result = t
if t == nil: return
if IntSetContainsOrIncl(cl, t.id): return
if ContainsOrIncl(cl, t.id): return
case t.kind
of tyGenericBody:
#debug(t)
@@ -470,7 +468,7 @@ proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
if t.sons[i].kind != tyGenericParam:
InternalError("addTypeVarsOfGenericBody")
# do not declare ``TKey`` twice:
#if not IntSetContainsOrIncl(cl, t.sons[i].sym.ident.id):
#if not ContainsOrIncl(cl, t.sons[i].sym.ident.id):
var s = copySym(t.sons[i].sym)
s.position = sonsLen(genericParams)
if s.typ == nil or s.typ.kind != tyGenericParam:
@@ -501,16 +499,17 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
var
def, res: PNode
typ: PType
check, cl: TIntSet
cl: TIntSet
checkMinSonsLen(n, 1)
result = newOrPrevType(tyProc, prev, c)
result.callConv = lastOptionEntry(c).defaultCC
result.n = newNodeI(nkFormalParams, n.info)
if (genericParams != nil) and (sonsLen(genericParams) == 0): IntSetInit(cl)
if (genericParams != nil) and (sonsLen(genericParams) == 0):
cl = initIntSet()
addSon(result, nil) # return type
res = newNodeI(nkType, n.info)
addSon(result.n, res)
IntSetInit(check)
var check = initIntSet()
var counter = 0
for i in countup(1, sonsLen(n) - 1):
var a = n.sons[i]
@@ -539,7 +538,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
arg.position = counter
inc(counter)
if def.kind != nkEmpty: arg.ast = copyTree(def)
if IntSetContainsOrIncl(check, arg.name.id):
if ContainsOrIncl(check, arg.name.id):
LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
addSon(result.n, newSymNode(arg))
addSon(result, typ)

View File

@@ -11,7 +11,7 @@
# the call to overloaded procs, generic procs and operators.
import
ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
magicsys
type
@@ -608,7 +608,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
# no error message!
m.state = csNoMatch
return
if IntSetContainsOrIncl(marker, formal.position):
if ContainsOrIncl(marker, formal.position):
# already in namedParams:
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch
@@ -653,7 +653,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
if m.callee.n.sons[f].kind != nkSym:
InternalError(n.sons[a].info, "matches")
formal = m.callee.n.sons[f].sym
if IntSetContainsOrIncl(marker, formal.position):
if ContainsOrIncl(marker, formal.position):
# already in namedParams:
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch
@@ -677,20 +677,18 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) =
# for 'suggest' support:
var marker: TIntSet
IntSetInit(marker)
var marker = initIntSet()
matchesAux(c, n, m, marker)
proc matches*(c: PContext, n: PNode, m: var TCandidate) =
var marker: TIntSet
IntSetInit(marker)
var marker = initIntSet()
matchesAux(c, n, m, marker)
if m.state == csNoMatch: return
# check that every formal parameter got a value:
var f = 1
while f < sonsLen(m.callee.n):
var formal = m.callee.n.sons[f].sym
if not IntSetContainsOrIncl(marker, formal.position):
if not ContainsOrIncl(marker, formal.position):
if formal.ast == nil:
if formal.typ.kind == tyOpenArray:
var container = newNodeI(nkBracket, n.info)

View File

@@ -17,7 +17,7 @@
# * introduces method dispatchers
import
strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
idents, renderer, types, passes, semfold, magicsys, cgmeth
const
@@ -528,8 +528,7 @@ proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
of skVar: found = not (sfGlobal in s.flags)
of skTemp, skForVar, skParam: found = true
else: nil
if found and (owner.id != s.owner.id) and
not IntSetContainsOrIncl(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:
@@ -555,9 +554,8 @@ proc indirectAccess(a, b: PSym): PNode =
result.typ = y.typ
proc transformLambda(c: PTransf, n: PNode): PNode =
var marked: TIntSet
var marked = initIntSet()
result = n
IntSetInit(marked)
if (n.sons[namePos].kind != nkSym): InternalError(n.info, "transformLambda")
var s = n.sons[namePos].sym
var closure = newNodeI(nkRecList, n.sons[codePos].info)

View File

@@ -10,7 +10,7 @@
# this module contains routines for accessing and iterating over types
import
ast, astalgo, trees, msgs, strutils, platform
intsets, ast, astalgo, trees, msgs, strutils, platform
proc firstOrd*(t: PType): biggestInt
proc lastOrd*(t: PType): biggestInt
@@ -219,7 +219,7 @@ proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter,
if t == nil: return
result = iter(t, closure)
if result: return
if not IntSetContainsOrIncl(marker, t.id):
if not ContainsOrIncl(marker, t.id):
case t.kind
of tyGenericInst, tyGenericBody:
result = iterOverTypeAux(marker, lastSon(t), iter, closure)
@@ -230,8 +230,7 @@ proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter,
if t.n != nil: result = iterOverNode(marker, t.n, iter, closure)
proc IterOverType(t: PType, iter: TTypeIter, closure: PObject): bool =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = iterOverTypeAux(marker, t, iter, closure)
proc searchTypeForAux(t: PType, predicate: TTypePredicate,
@@ -263,7 +262,7 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate, marker: var TIntSet):
# iterates over VALUE types!
result = false
if t == nil: return
if IntSetContainsOrIncl(marker, t.id): return
if ContainsOrIncl(marker, t.id): return
result = Predicate(t)
if result: return
case t.kind
@@ -280,8 +279,7 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate, marker: var TIntSet):
nil
proc searchTypeFor(t: PType, predicate: TTypePredicate): bool =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = searchTypeForAux(t, predicate, marker)
proc isObjectPredicate(t: PType): bool =
@@ -322,8 +320,7 @@ proc analyseObjectWithTypeFieldAux(t: PType, marker: var TIntSet): TTypeFieldRes
nil
proc analyseObjectWithTypeField(t: PType): TTypeFieldResult =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = analyseObjectWithTypeFieldAux(t, marker)
proc isGBCRef(t: PType): bool =
@@ -365,7 +362,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
if tfAcyclic in t.flags: return
case t.kind
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray:
if not IntSetContainsOrIncl(marker, t.id):
if not ContainsOrIncl(marker, t.id):
for i in countup(0, sonsLen(t) - 1):
result = canFormAcycleAux(marker, t.sons[i], startId)
if result: return
@@ -376,8 +373,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
nil
proc canFormAcycle(typ: PType): bool =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = canFormAcycleAux(marker, typ, typ.id)
proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
@@ -400,7 +396,7 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
result = nil
if t == nil: return
result = iter(t, closure)
if not IntSetContainsOrIncl(marker, t.id):
if not ContainsOrIncl(marker, t.id):
for i in countup(0, sonsLen(t) - 1):
result.sons[i] = mutateTypeAux(marker, result.sons[i], iter, closure)
if (result.sons[i] == nil) and (result.kind == tyGenericInst):
@@ -409,8 +405,7 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
assert(result != nil)
proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = mutateTypeAux(marker, t, iter, closure)
proc rangeToStr(n: PNode): string =
@@ -591,17 +586,14 @@ proc equalParam(a, b: PSym): TParamsEquality =
result = paramsNotEqual
proc equalParams(a, b: PNode): TParamsEquality =
var
length: int
m, n: PSym
result = paramsEqual
length = sonsLen(a)
var length = sonsLen(a)
if length != sonsLen(b):
result = paramsNotEqual
else:
for i in countup(1, length - 1):
m = a.sons[i].sym
n = b.sons[i].sym
var m = a.sons[i].sym
var n = b.sons[i].sym
assert((m.kind == skParam) and (n.kind == skParam))
case equalParam(m, n)
of paramsNotEqual:
@@ -646,7 +638,6 @@ proc sameTuple(a, b: PType, DistinctOf: bool): bool =
# two tuples are equivalent iff the names, types and positions are the same;
# however, both types may not have any field names (t.n may be nil) which
# complicates the matter a bit.
var x, y: PSym
if sonsLen(a) == sonsLen(b):
result = true
for i in countup(0, sonsLen(a) - 1):
@@ -658,8 +649,8 @@ proc sameTuple(a, b: PType, DistinctOf: bool): bool =
# check field names:
if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
if b.n.sons[i].kind != nkSym: InternalError(b.n.info, "sameTuple")
x = a.n.sons[i].sym
y = b.n.sons[i].sym
var x = a.n.sons[i].sym
var y = b.n.sons[i].sym
result = x.name.id == y.name.id
if not result: break
else:
@@ -758,17 +749,16 @@ proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind): bool =
if not result: return
proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
var t, t2: PType
assert(kind in {skVar, skConst, skParam})
# if we have already checked the type, return true, because we stop the
# evaluation if something is wrong:
result = true
if typ == nil:
return # if we have already checked the type, return true, because we stop the
# evaluation if something is wrong:
if IntSetContainsOrIncl(marker, typ.id): return
t = skipTypes(typ, abstractInst)
if typ == nil: return
if ContainsOrIncl(marker, typ.id): return
var t = skipTypes(typ, abstractInst)
case t.kind
of tyVar:
t2 = skipTypes(t.sons[0], abstractInst)
var t2 = skipTypes(t.sons[0], abstractInst)
case t2.kind
of tyVar:
result = false # ``var var`` is always an invalid type:
@@ -815,8 +805,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
if t.n != nil: result = typeAllowedNode(marker, t.n, skVar)
proc typeAllowed(t: PType, kind: TSymKind): bool =
var marker: TIntSet
IntSetInit(marker)
var marker = InitIntSet()
result = typeAllowedAux(marker, t, kind)
proc align(address, alignment: biggestInt): biggestInt =

View File

@@ -42,6 +42,9 @@ Core
Contains procs for serialization and deseralization of arbitrary Nimrod
data structures.
* `typeinfo <typeinfo.html>`_
Provides (unsafe) access to Nimrod's run time type information.
Collections and algorithms
--------------------------
@@ -53,7 +56,9 @@ Collections and algorithms
* `lists <lists.html>`_
Nimrod linked list support. Contains singly and doubly linked lists and
circular lists ("rings").
* `intsets <intsets.html>`_
Efficient implementation of a set of ints as a sparse bit set.
String handling
---------------

View File

@@ -0,0 +1,177 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## The ``intsets`` module implements an efficient int set implemented as a
## sparse bit set.
## **Note**: Since Nimrod does not allow the assignment operator to be
## overloaded, ``=`` for int sets performs some rather meaningless shallow
## copy.
import
os, hashes, math
type
TBitScalar = int
const
InitIntSetSize = 8 # must be a power of two!
TrunkShift = 9
BitsPerTrunk = 1 shl TrunkShift # needs to be a power of 2 and
# divisible by 64
TrunkMask = BitsPerTrunk - 1
IntsPerTrunk = BitsPerTrunk div (sizeof(TBitScalar) * 8)
IntShift = 5 + ord(sizeof(TBitScalar) == 8) # 5 or 6, depending on int width
IntMask = 1 shl IntShift - 1
type
PTrunk = ref TTrunk
TTrunk {.final.} = object
next: PTrunk # all nodes are connected with this pointer
key: int # start address at bit 0
bits: array[0..IntsPerTrunk - 1, TBitScalar] # a bit vector
TTrunkSeq = seq[PTrunk]
TIntSet* {.final.} = object ## an efficient set of 'int' implemented as a
## sparse bit set
counter, max: int
head: PTrunk
data: TTrunkSeq
proc mustRehash(length, counter: int): bool {.inline.} =
assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4)
proc nextTry(h, maxHash: THash): THash {.inline.} =
result = ((5 * h) + 1) and maxHash
proc IntSetGet(t: TIntSet, key: int): PTrunk =
var h = key and t.max
while t.data[h] != nil:
if t.data[h].key == key:
return t.data[h]
h = nextTry(h, t.max)
result = nil
proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) =
var h = desc.key and t.max
while data[h] != nil:
assert(data[h] != desc)
h = nextTry(h, t.max)
assert(data[h] == nil)
data[h] = desc
proc IntSetEnlarge(t: var TIntSet) =
var n: TTrunkSeq
var oldMax = t.max
t.max = ((t.max + 1) * 2) - 1
newSeq(n, t.max + 1)
for i in countup(0, oldmax):
if t.data[i] != nil: IntSetRawInsert(t, n, t.data[i])
swap(t.data, n)
proc IntSetPut(t: var TIntSet, key: int): PTrunk =
var h = key and t.max
while t.data[h] != nil:
if t.data[h].key == key:
return t.data[h]
h = nextTry(h, t.max)
if mustRehash(t.max + 1, t.counter): IntSetEnlarge(t)
inc(t.counter)
h = key and t.max
while t.data[h] != nil: h = nextTry(h, t.max)
assert(t.data[h] == nil)
new(result)
result.next = t.head
result.key = key
t.head = result
t.data[h] = result
proc contains*(s: TIntSet, key: int): bool =
## returns true iff `key` is in `s`.
var t = IntSetGet(s, `shr`(key, TrunkShift))
if t != nil:
var u = key and TrunkMask
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
else:
result = false
proc incl*(s: var TIntSet, key: int) =
## includes an element `key` in `s`.
var t = IntSetPut(s, `shr`(key, TrunkShift))
var u = key and TrunkMask
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
`shl`(1, u and IntMask)
proc excl*(s: var TIntSet, key: int) =
## excludes `key` from the set `s`.
var t = IntSetGet(s, `shr`(key, TrunkShift))
if t != nil:
var u = key and TrunkMask
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
not `shl`(1, u and IntMask)
proc containsOrIncl*(s: var TIntSet, key: int): bool =
## returns true if `s` contains `key`, otherwise `key` is included in `s`
## and false is returned.
var t = IntSetGet(s, `shr`(key, TrunkShift))
if t != nil:
var u = key and TrunkMask
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
if not result:
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
`shl`(1, u and IntMask)
else:
incl(s, key)
result = false
proc initIntSet*: TIntSet =
## creates a new int set that is empty.
newSeq(result.data, InitIntSetSize)
result.max = InitIntSetSize-1
result.counter = 0
result.head = nil
template dollarImpl(): stmt =
result = "{"
for key in items(s):
if result.len > 1: result.add(", ")
result.add($key)
result.add("}")
proc `$`*(s: TIntSet): string =
## The `$` operator for int sets.
dollarImpl()
iterator items*(s: TIntSet): int {.inline.} =
## iterates over any included element of `s`.
var r = s.head
while r != nil:
var i = 0
while i <= high(r.bits):
var w = r.bits[i]
# taking a copy of r.bits[i] here is correct, because
# modifying operations are not allowed during traversation
var j = 0
while w != 0: # test all remaining bits for zero
if (w and 1) != 0: # the bit is set!
yield (r.key shl TrunkShift) or (i shl IntShift +% j)
inc(j)
w = w shr 1
inc(i)
r = r.next
when isMainModule:
var x = initIntSet()
x.incl(1)
x.incl(2)
x.incl(7)
x.incl(1056)
for e in items(x): echo e

View File

@@ -1,12 +0,0 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#

View File

@@ -78,7 +78,7 @@ Low priority
Library
-------
- specialized bit sets; specialized string sets
- radix tree for strings; maybe suffix tree
- locale support
- conversion between character sets
- bignums

View File

@@ -51,6 +51,7 @@ Additions
- Added ``lists`` module which contains generic linked lists.
- Added ``sets`` module which contains generic hash sets.
- Added ``tables`` module which contains generic hash tables.
- Added ``intsets`` module which contains a specialized int set data type.
- Added ``scgi`` module.
- Added ``smtp`` module.
- Added ``re.findAll``, ``pegs.findAll``.

View File

@@ -24,7 +24,7 @@ file: ticker
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview"
doc: "tools;c2nim;niminst"
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst"
srcdoc: "core/macros;core/marshal"
srcdoc: "core/macros;core/marshal;core/typeinfo"
srcdoc: "impure/graphics;pure/sockets"
srcdoc: "system.nim;system/threads.nim;pure/os;pure/strutils;pure/math"
srcdoc: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib"
@@ -39,6 +39,7 @@ srcdoc: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors"
srcdoc: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
srcdoc: "impure/rdstdin;wrappers/zmq"
srcdoc: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
srcdoc: "pure/collections/intsets"
webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"