summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-06-14 01:36:49 +0200
committerAraq <rumpf_a@web.de>2011-06-14 01:36:49 +0200
commitade67f1abcc29402b489e9f5940036276878fb18 (patch)
treec21aeca55a0b9137bf4479dcf67726b367ea1859
parentca637c019c13f552d0f44a18d3f3afe4b8a88832 (diff)
downloadNim-ade67f1abcc29402b489e9f5940036276878fb18.tar.gz
intsets are now a proper module and part of the stdlib
-rwxr-xr-xcompiler/ast.nim144
-rwxr-xr-xcompiler/astalgo.nim21
-rwxr-xr-xcompiler/ccgstmts.nim2
-rwxr-xr-xcompiler/ccgtypes.nim10
-rwxr-xr-xcompiler/cgen.nim24
-rwxr-xr-xcompiler/cgmeth.nim11
-rwxr-xr-xcompiler/ecmasgen.nim7
-rwxr-xr-xcompiler/importer.nim8
-rwxr-xr-xcompiler/lookups.nim16
-rwxr-xr-xcompiler/rodwrite.nim6
-rwxr-xr-xcompiler/sem.nim2
-rwxr-xr-xcompiler/semdata.nim7
-rwxr-xr-xcompiler/semexprs.nim5
-rwxr-xr-xcompiler/semstmts.nim9
-rwxr-xr-xcompiler/semtempl.nim7
-rwxr-xr-xcompiler/semtypes.nim25
-rwxr-xr-xcompiler/sigmatch.nim14
-rwxr-xr-xcompiler/transf.nim8
-rwxr-xr-xcompiler/types.nim55
-rwxr-xr-xdoc/lib.txt7
-rw-r--r--lib/pure/collections/intsets.nim177
-rwxr-xr-xlib/system/cntbits.nim12
-rwxr-xr-xtodo.txt2
-rwxr-xr-xweb/news.txt1
-rwxr-xr-xweb/nimrod.ini3
25 files changed, 297 insertions, 286 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 808fb683d..ae8680c6b 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -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()
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index fa01dabbf..08b502af7 100755
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -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 = 
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index d45035989..8a05c68a4 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -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,
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 84e1850ad..26c0242f5 100755
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -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")
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index e549f1101..449814d01 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -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()
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index dff844489..dd1ab944e 100755
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -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)))
 
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index dc87d1924..592a24043 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -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])
diff --git a/compiler/importer.nim b/compiler/importer.nim
index 06eebcb4e..6267cb68d 100755
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -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
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 0aaff6bc5..d72ec1555 100755
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -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:
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index ea427dce9..66cf7bd2c 100755
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -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()
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 533f93601..a22452b39 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -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
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index a1a641ba4..7e40cd0a6 100755
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -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) = 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 342d07cbf..dac72c2f0 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -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)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 0c4ccef40..f074a00cd 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -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:
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 7782c7b42..dee703d30 100755
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -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]) 
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 91a00de11..ca46ea0e0 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -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)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 5b397167a..c9ab27123 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -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)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 9e38822c7..15deb266d 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -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)
diff --git a/compiler/types.nim b/compiler/types.nim
index 953366deb..8769993f2 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -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 = 
diff --git a/doc/lib.txt b/doc/lib.txt
index 23dd93aea..6effabe0b 100755
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -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
 ---------------
diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim
new file mode 100644
index 000000000..bbe6a674b
--- /dev/null
+++ b/lib/pure/collections/intsets.nim
@@ -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
+
+
diff --git a/lib/system/cntbits.nim b/lib/system/cntbits.nim
deleted file mode 100755
index 281b96dd0..000000000
--- a/lib/system/cntbits.nim
+++ /dev/null
@@ -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.
-#
-
-
-
-
diff --git a/todo.txt b/todo.txt
index 5ab4d3be6..873cf8bf9 100755
--- a/todo.txt
+++ b/todo.txt
@@ -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
diff --git a/web/news.txt b/web/news.txt
index f048ae541..d9b0ef6b2 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -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``.
diff --git a/web/nimrod.ini b/web/nimrod.ini
index a7bee7492..e9562eb3a 100755
--- a/web/nimrod.ini
+++ b/web/nimrod.ini
@@ -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"