summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/passes.nim98
-rw-r--r--compiler/transf.nim264
-rw-r--r--lib/system.nim204
-rw-r--r--lib/system/gc.nim82
-rw-r--r--todo.txt1
5 files changed, 326 insertions, 323 deletions
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 96088bd88..129d8ad47 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -10,15 +10,15 @@
 # This module implements the passes functionality. A pass must implement the
 # `TPass` interface.
 
-import 
-  strutils, lists, options, ast, astalgo, llstream, msgs, platform, os, 
-  condsyms, idents, renderer, types, extccomp, math, magicsys, nversion, 
+import
+  strutils, lists, options, ast, astalgo, llstream, msgs, platform, os,
+  condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
   nimsets, syntaxes, times, rodread, idgen
 
-type  
+type
   TPassContext* = object of RootObj # the pass's context
     fromCache*: bool  # true if created by "openCached"
-   
+
   PPassContext* = ref TPassContext
 
   TPassOpen* = proc (module: PSym): PPassContext {.nimcall.}
@@ -33,8 +33,8 @@ type
   TPassData* = tuple[input: PNode, closeOutput: PNode]
   TPasses* = openArray[TPass]
 
-# a pass is a tuple of procedure vars ``TPass.close`` may produce additional 
-# nodes. These are passed to the other close procedures. 
+# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
+# nodes. These are passed to the other close procedures.
 # This mechanism used to be used for the instantiation of generics.
 
 proc makePass*(open: TPassOpen = nil,
@@ -53,46 +53,46 @@ proc makePass*(open: TPassOpen = nil,
 proc processModule*(module: PSym, stream: PLLStream, rd: PRodReader)
 
 # the semantic checker needs these:
-var 
+var
   gImportModule*: proc (m: PSym, fileIdx: int32): PSym {.nimcall.}
   gIncludeFile*: proc (m: PSym, fileIdx: int32): PNode {.nimcall.}
 
 # implementation
 
-proc skipCodegen*(n: PNode): bool {.inline.} = 
-  # can be used by codegen passes to determine whether they should do 
+proc skipCodegen*(n: PNode): bool {.inline.} =
+  # can be used by codegen passes to determine whether they should do
   # something with `n`. Currently, this ignores `n` and uses the global
   # error count instead.
   result = msgs.gErrorCounter > 0
 
-proc astNeeded*(s: PSym): bool = 
+proc astNeeded*(s: PSym): bool =
   # The ``rodwrite`` module uses this to determine if the body of a proc
   # needs to be stored. The passes manager frees s.sons[codePos] when
   # appropriate to free the procedure body's memory. This is important
   # to keep memory usage down.
   if (s.kind in {skMethod, skProc}) and
       ({sfCompilerProc, sfCompileTime} * s.flags == {}) and
-      (s.typ.callConv != ccInline) and 
-      (s.ast.sons[genericParamsPos].kind == nkEmpty): 
+      (s.typ.callConv != ccInline) and
+      (s.ast.sons[genericParamsPos].kind == nkEmpty):
     result = false
     # XXX this doesn't really make sense with excessive CTFE
   else:
     result = true
-  
-const 
+
+const
   maxPasses = 10
 
-type 
+type
   TPassContextArray = array[0..maxPasses - 1, PPassContext]
 
-var 
+var
   gPasses: array[0..maxPasses - 1, TPass]
   gPassesLen*: int
 
 proc clearPasses* =
   gPassesLen = 0
 
-proc registerPass*(p: TPass) = 
+proc registerPass*(p: TPass) =
   gPasses[gPassesLen] = p
   inc(gPassesLen)
 
@@ -109,48 +109,48 @@ proc carryPasses*(nodes: PNode, module: PSym, passes: TPasses) =
     passdata = carryPass(pass, module, passdata)
 
 proc openPasses(a: var TPassContextArray, module: PSym) =
-  for i in countup(0, gPassesLen - 1): 
-    if not isNil(gPasses[i].open): 
+  for i in countup(0, gPassesLen - 1):
+    if not isNil(gPasses[i].open):
       a[i] = gPasses[i].open(module)
     else: a[i] = nil
-  
+
 proc openPassesCached(a: var TPassContextArray, module: PSym, rd: PRodReader) =
-  for i in countup(0, gPassesLen - 1): 
-    if not isNil(gPasses[i].openCached): 
+  for i in countup(0, gPassesLen - 1):
+    if not isNil(gPasses[i].openCached):
       a[i] = gPasses[i].openCached(module, rd)
-      if a[i] != nil: 
+      if a[i] != nil:
         a[i].fromCache = true
     else:
       a[i] = nil
-  
-proc closePasses(a: var TPassContextArray) = 
+
+proc closePasses(a: var TPassContextArray) =
   var m: PNode = nil
-  for i in countup(0, gPassesLen - 1): 
+  for i in countup(0, gPassesLen - 1):
     if not isNil(gPasses[i].close): m = gPasses[i].close(a[i], m)
     a[i] = nil                # free the memory here
-  
-proc processTopLevelStmt(n: PNode, a: var TPassContextArray): bool = 
+
+proc processTopLevelStmt(n: PNode, a: var TPassContextArray): bool =
   # this implements the code transformation pipeline
   var m = n
-  for i in countup(0, gPassesLen - 1): 
-    if not isNil(gPasses[i].process): 
+  for i in countup(0, gPassesLen - 1):
+    if not isNil(gPasses[i].process):
       m = gPasses[i].process(a[i], m)
       if isNil(m): return false
   result = true
-  
-proc processTopLevelStmtCached(n: PNode, a: var TPassContextArray) = 
+
+proc processTopLevelStmtCached(n: PNode, a: var TPassContextArray) =
   # this implements the code transformation pipeline
   var m = n
-  for i in countup(0, gPassesLen - 1): 
+  for i in countup(0, gPassesLen - 1):
     if not isNil(gPasses[i].openCached): m = gPasses[i].process(a[i], m)
-  
-proc closePassesCached(a: var TPassContextArray) = 
+
+proc closePassesCached(a: var TPassContextArray) =
   var m: PNode = nil
-  for i in countup(0, gPassesLen - 1): 
-    if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close): 
+  for i in countup(0, gPassesLen - 1):
+    if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close):
       m = gPasses[i].close(a[i], m)
     a[i] = nil                # free the memory here
-  
+
 proc processImplicits(implicits: seq[string], nodeKind: TNodeKind,
                       a: var TPassContextArray) =
   for module in items(implicits):
@@ -159,45 +159,45 @@ proc processImplicits(implicits: seq[string], nodeKind: TNodeKind,
     str.info = gCmdLineInfo
     importStmt.addSon str
     if not processTopLevelStmt(importStmt, a): break
-  
+
 proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
-  var 
+  var
     p: TParsers
     a: TPassContextArray
     s: PLLStream
     fileIdx = module.fileIdx
-  if rd == nil: 
+  if rd == nil:
     openPasses(a, module)
-    if stream == nil: 
+    if stream == nil:
       let filename = fileIdx.toFullPathConsiderDirty
       if module.name.s == "-":
         module.name.s = "stdinfile"
         s = llStreamOpen(stdin)
       else:
         s = llStreamOpen(filename, fmRead)
-      if s == nil: 
+      if s == nil:
         rawMessage(errCannotOpenFile, filename)
         return
     else:
       s = stream
-    while true: 
+    while true:
       openParsers(p, fileIdx, s)
 
       if sfSystemModule notin module.flags:
-        # XXX what about caching? no processing then? what if I change the 
+        # XXX what about caching? no processing then? what if I change the
         # modules to include between compilation runs? we'd need to track that
         # in ROD files. I think we should enable this feature only
         # for the interactive mode.
         processImplicits implicitImports, nkImportStmt, a
         processImplicits implicitIncludes, nkIncludeStmt, a
 
-      while true: 
+      while true:
         var n = parseTopLevelStmt(p)
-        if n.kind == nkEmpty: break 
+        if n.kind == nkEmpty: break
         if not processTopLevelStmt(n, a): break
 
       closeParsers(p)
-      if s.kind != llsStdIn: break 
+      if s.kind != llsStdIn: break
     closePasses(a)
     # id synchronization point for more consistent code generation:
     idSynchronizationPoint(1000)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 2f520aa20..e5e3bbe63 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -17,27 +17,27 @@
 # * introduces method dispatchers
 # * performs lambda lifting for closure support
 
-import 
-  intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, 
+import
+  intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
   idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
   lambdalifting, sempass2, lowerings
 
 # implementation
 
-type 
+type
   PTransNode* = distinct PNode
-  
+
   PTransCon = ref TTransCon
   TTransCon{.final.} = object # part of TContext; stackable
     mapping: TIdNodeTable     # mapping from symbols to nodes
     owner: PSym               # current owner
     forStmt: PNode            # current for stmt
-    forLoopBody: PTransNode   # transformed for loop body 
-    yieldStmts: int           # we count the number of yield statements, 
+    forLoopBody: PTransNode   # transformed for loop body
+    yieldStmts: int           # we count the number of yield statements,
                               # because we need to introduce new variables
                               # if we encounter the 2nd yield statement
     next: PTransCon           # for stacking
-  
+
   TTransfContext = object of passes.TPassContext
     module: PSym
     transCon: PTransCon      # top of a TransCon stack
@@ -46,52 +46,52 @@ type
     contSyms, breakSyms: seq[PSym]  # to transform 'continue' and 'break'
   PTransf = ref TTransfContext
 
-proc newTransNode(a: PNode): PTransNode {.inline.} = 
+proc newTransNode(a: PNode): PTransNode {.inline.} =
   result = PTransNode(shallowCopy(a))
 
-proc newTransNode(kind: TNodeKind, info: TLineInfo, 
-                  sons: int): PTransNode {.inline.} = 
+proc newTransNode(kind: TNodeKind, info: TLineInfo,
+                  sons: int): PTransNode {.inline.} =
   var x = newNodeI(kind, info)
   newSeq(x.sons, sons)
   result = x.PTransNode
 
-proc newTransNode(kind: TNodeKind, n: PNode, 
-                  sons: int): PTransNode {.inline.} = 
+proc newTransNode(kind: TNodeKind, n: PNode,
+                  sons: int): PTransNode {.inline.} =
   var x = newNodeIT(kind, n.info, n.typ)
   newSeq(x.sons, sons)
   x.typ = n.typ
   result = x.PTransNode
 
-proc `[]=`(a: PTransNode, i: int, x: PTransNode) {.inline.} = 
+proc `[]=`(a: PTransNode, i: int, x: PTransNode) {.inline.} =
   var n = PNode(a)
   n.sons[i] = PNode(x)
 
-proc `[]`(a: PTransNode, i: int): PTransNode {.inline.} = 
+proc `[]`(a: PTransNode, i: int): PTransNode {.inline.} =
   var n = PNode(a)
   result = n.sons[i].PTransNode
-  
+
 proc add(a, b: PTransNode) {.inline.} = addSon(PNode(a), PNode(b))
 proc len(a: PTransNode): int {.inline.} = result = sonsLen(a.PNode)
 
-proc newTransCon(owner: PSym): PTransCon = 
+proc newTransCon(owner: PSym): PTransCon =
   assert owner != nil
   new(result)
   initIdNodeTable(result.mapping)
   result.owner = owner
 
-proc pushTransCon(c: PTransf, t: PTransCon) = 
+proc pushTransCon(c: PTransf, t: PTransCon) =
   t.next = c.transCon
   c.transCon = t
 
-proc popTransCon(c: PTransf) = 
+proc popTransCon(c: PTransf) =
   if (c.transCon == nil): internalError("popTransCon")
   c.transCon = c.transCon.next
 
-proc getCurrOwner(c: PTransf): PSym = 
+proc getCurrOwner(c: PTransf): PSym =
   if c.transCon != nil: result = c.transCon.owner
   else: result = c.module
-  
-proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PSym = 
+
+proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PSym =
   result = newSym(skTemp, getIdent(genPrefix), getCurrOwner(c), info)
   result.typ = skipTypes(typ, {tyGenericInst})
   incl(result.flags, sfFromGeneric)
@@ -100,10 +100,10 @@ proc transform(c: PTransf, n: PNode): PTransNode
 
 proc transformSons(c: PTransf, n: PNode): PTransNode =
   result = newTransNode(n)
-  for i in countup(0, sonsLen(n)-1): 
+  for i in countup(0, sonsLen(n)-1):
     result[i] = transform(c, n.sons[i])
 
-proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode = 
+proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode =
   result = newTransNode(nkFastAsgn, PNode(ri).info, 2)
   result[0] = PTransNode(le)
   result[1] = ri
@@ -113,30 +113,30 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
   #  return liftIterSym(n)
   var b: PNode
   var tc = c.transCon
-  if sfBorrow in n.sym.flags: 
+  if sfBorrow in n.sym.flags:
     # simply exchange the symbol:
     b = n.sym.getBody
     if b.kind != nkSym: internalError(n.info, "wrong AST for borrowed symbol")
     b = newSymNode(b.sym)
     b.info = n.info
-  else: 
+  else:
     b = n
-  while tc != nil: 
+  while tc != nil:
     result = idNodeTableGet(tc.mapping, b.sym)
     if result != nil: return
     tc = tc.next
   result = b
 
-proc transformSym(c: PTransf, n: PNode): PTransNode = 
+proc transformSym(c: PTransf, n: PNode): PTransNode =
   result = PTransNode(transformSymAux(c, n))
 
 proc transformVarSection(c: PTransf, v: PNode): PTransNode =
   result = newTransNode(v)
   for i in countup(0, sonsLen(v)-1):
     var it = v.sons[i]
-    if it.kind == nkCommentStmt: 
+    if it.kind == nkCommentStmt:
       result[i] = PTransNode(it)
-    elif it.kind == nkIdentDefs: 
+    elif it.kind == nkIdentDefs:
       if it.sons[0].kind != nkSym: internalError(it.info, "transformVarSection")
       internalAssert(it.len == 3)
       var newVar = copySym(it.sons[0].sym)
@@ -153,12 +153,12 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
       defs[1] = it.sons[1].PTransNode
       defs[2] = transform(c, it.sons[2])
       result[i] = defs
-    else: 
-      if it.kind != nkVarTuple: 
+    else:
+      if it.kind != nkVarTuple:
         internalError(it.info, "transformVarSection: not nkVarTuple")
       var L = sonsLen(it)
       var defs = newTransNode(it.kind, it.info, L)
-      for j in countup(0, L-3): 
+      for j in countup(0, L-3):
         var newVar = copySym(it.sons[j].sym)
         incl(newVar.flags, sfFromGeneric)
         newVar.owner = getCurrOwner(c)
@@ -188,12 +188,12 @@ proc transformConstSection(c: PTransf, v: PNode): PTransNode =
       else:
         result[i] = PTransNode(it)
 
-proc hasContinue(n: PNode): bool = 
+proc hasContinue(n: PNode): bool =
   case n.kind
   of nkEmpty..nkNilLit, nkForStmt, nkParForStmt, nkWhileStmt: discard
   of nkContinueStmt: result = true
-  else: 
-    for i in countup(0, sonsLen(n) - 1): 
+  else:
+    for i in countup(0, sonsLen(n) - 1):
       if hasContinue(n.sons[i]): return true
 
 proc newLabel(c: PTransf, n: PNode): PSym =
@@ -224,10 +224,10 @@ proc transformBlock(c: PTransf, n: PNode): PTransNode =
   discard c.breakSyms.pop
   result[0] = newSymNode(labl).PTransNode
 
-proc transformLoopBody(c: PTransf, n: PNode): PTransNode =  
-  # What if it contains "continue" and "break"? "break" needs 
+proc transformLoopBody(c: PTransf, n: PNode): PTransNode =
+  # What if it contains "continue" and "break"? "break" needs
   # an explicit label too, but not the same!
-  
+
   # We fix this here by making every 'break' belong to its enclosing loop
   # and changing all breaks that belong to a 'block' by annotating it with
   # a label (if it hasn't one already).
@@ -239,7 +239,7 @@ proc transformLoopBody(c: PTransf, n: PNode): PTransNode =
     result[0] = newSymNode(labl).PTransNode
     result[1] = transform(c, n)
     discard c.contSyms.pop()
-  else: 
+  else:
     result = transform(c, n)
 
 proc transformWhile(c: PTransf; n: PNode): PTransNode =
@@ -273,27 +273,27 @@ proc transformBreak(c: PTransf, n: PNode): PTransNode =
     result = transformSons(c, n)
     result[0] = newSymNode(labl).PTransNode
 
-proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) = 
+proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) =
   # XXX: BUG: what if `n` is an expression with side-effects?
-  for i in countup(0, sonsLen(c.transCon.forStmt) - 3): 
-    add(father, newAsgnStmt(c, c.transCon.forStmt.sons[i], 
+  for i in countup(0, sonsLen(c.transCon.forStmt) - 3):
+    add(father, newAsgnStmt(c, c.transCon.forStmt.sons[i],
         transform(c, newTupleAccess(n, i))))
 
-proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode = 
+proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode =
   case n.kind
-  of nkSym: 
+  of nkSym:
     result = transformSym(c, n)
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: 
+  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
     # nothing to be done for leaves:
     result = PTransNode(n)
   of nkVarSection, nkLetSection:
     result = transformVarSection(c, n)
   else:
     result = newTransNode(n)
-    for i in countup(0, sonsLen(n)-1): 
+    for i in countup(0, sonsLen(n)-1):
       result[i] =  introduceNewLocalVars(c, n.sons[i])
 
-proc transformYield(c: PTransf, n: PNode): PTransNode = 
+proc transformYield(c: PTransf, n: PNode): PTransNode =
   result = newTransNode(nkStmtList, n.info, 0)
   var e = n.sons[0]
   # c.transCon.forStmt.len == 3 means that there is one for loop variable
@@ -301,21 +301,21 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
   if skipTypes(e.typ, {tyGenericInst}).kind == tyTuple and
       c.transCon.forStmt.len != 3:
     e = skipConv(e)
-    if e.kind == nkPar: 
-      for i in countup(0, sonsLen(e) - 1): 
-        add(result, newAsgnStmt(c, c.transCon.forStmt.sons[i], 
+    if e.kind == nkPar:
+      for i in countup(0, sonsLen(e) - 1):
+        add(result, newAsgnStmt(c, c.transCon.forStmt.sons[i],
                                 transform(c, e.sons[i])))
-    else: 
+    else:
       unpackTuple(c, e, result)
-  else: 
+  else:
     var x = transform(c, e)
     add(result, newAsgnStmt(c, c.transCon.forStmt.sons[0], x))
-  
+
   inc(c.transCon.yieldStmts)
   if c.transCon.yieldStmts <= 1:
     # common case
     add(result, c.transCon.forLoopBody)
-  else: 
+  else:
     # we need to introduce new local variables:
     add(result, introduceNewLocalVars(c, c.transCon.forLoopBody.PNode))
 
@@ -340,25 +340,25 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
     if n.sons[0].kind == a or n.sons[0].kind == b:
       # addr ( deref ( x )) --> x
       result = PTransNode(n.sons[0].sons[0])
-  
-proc transformConv(c: PTransf, n: PNode): PTransNode = 
+
+proc transformConv(c: PTransf, n: PNode): PTransNode =
   # numeric types need range checks:
   var dest = skipTypes(n.typ, abstractVarRange)
   var source = skipTypes(n.sons[1].typ, abstractVarRange)
   case dest.kind
-  of tyInt..tyInt64, tyEnum, tyChar, tyBool, tyUInt8..tyUInt32: 
+  of tyInt..tyInt64, tyEnum, tyChar, tyBool, tyUInt8..tyUInt32:
     # we don't include uint and uint64 here as these are no ordinal types ;-)
     if not isOrdinalType(source):
       # float -> int conversions. ugh.
       result = transformSons(c, n)
     elif firstOrd(n.typ) <= firstOrd(n.sons[1].typ) and
-        lastOrd(n.sons[1].typ) <= lastOrd(n.typ): 
+        lastOrd(n.sons[1].typ) <= lastOrd(n.typ):
       # BUGFIX: simply leave n as it is; we need a nkConv node,
       # but no range check:
       result = transformSons(c, n)
-    else: 
+    else:
       # generate a range check:
-      if dest.kind == tyInt64 or source.kind == tyInt64: 
+      if dest.kind == tyInt64 or source.kind == tyInt64:
         result = newTransNode(nkChckRange64, n, 3)
       else:
         result = newTransNode(nkChckRange, n, 3)
@@ -368,7 +368,7 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
       result[2] = newIntTypeNode(nkIntLit, lastOrd(dest), source).PTransNode
   of tyFloat..tyFloat128:
     # XXX int64 -> float conversion?
-    if skipTypes(n.typ, abstractVar).kind == tyRange: 
+    if skipTypes(n.typ, abstractVar).kind == tyRange:
       result = newTransNode(nkChckRangeF, n, 3)
       dest = skipTypes(n.typ, abstractVar)
       result[0] = transform(c, n.sons[1])
@@ -378,81 +378,81 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
       result = transformSons(c, n)
   of tyOpenArray, tyVarargs:
     result = transform(c, n.sons[1])
-  of tyCString: 
-    if source.kind == tyString: 
+  of tyCString:
+    if source.kind == tyString:
       result = newTransNode(nkStringToCString, n, 1)
       result[0] = transform(c, n.sons[1])
     else:
       result = transformSons(c, n)
-  of tyString: 
-    if source.kind == tyCString: 
+  of tyString:
+    if source.kind == tyCString:
       result = newTransNode(nkCStringToString, n, 1)
       result[0] = transform(c, n.sons[1])
     else:
       result = transformSons(c, n)
-  of tyRef, tyPtr: 
+  of tyRef, tyPtr:
     dest = skipTypes(dest, abstractPtrs)
     source = skipTypes(source, abstractPtrs)
-    if source.kind == tyObject: 
+    if source.kind == tyObject:
       var diff = inheritanceDiff(dest, source)
-      if diff < 0: 
+      if diff < 0:
         result = newTransNode(nkObjUpConv, n, 1)
         result[0] = transform(c, n.sons[1])
-      elif diff > 0: 
+      elif diff > 0:
         result = newTransNode(nkObjDownConv, n, 1)
         result[0] = transform(c, n.sons[1])
-      else: 
+      else:
         result = transform(c, n.sons[1])
     else:
       result = transformSons(c, n)
-  of tyObject: 
+  of tyObject:
     var diff = inheritanceDiff(dest, source)
-    if diff < 0: 
+    if diff < 0:
       result = newTransNode(nkObjUpConv, n, 1)
       result[0] = transform(c, n.sons[1])
-    elif diff > 0: 
+    elif diff > 0:
       result = newTransNode(nkObjDownConv, n, 1)
       result[0] = transform(c, n.sons[1])
-    else: 
+    else:
       result = transform(c, n.sons[1])
   of tyGenericParam, tyOrdinal:
     result = transform(c, n.sons[1])
     # happens sometimes for generated assignments, etc.
-  else: 
+  else:
     result = transformSons(c, n)
-  
-type 
-  TPutArgInto = enum 
+
+type
+  TPutArgInto = enum
     paDirectMapping, paFastAsgn, paVarAsgn
 
-proc putArgInto(arg: PNode, formal: PType): TPutArgInto = 
+proc putArgInto(arg: PNode, formal: PType): TPutArgInto =
   # This analyses how to treat the mapping "formal <-> arg" in an
   # inline context.
   if skipTypes(formal, abstractInst).kind in {tyOpenArray, tyVarargs}:
     return paDirectMapping    # XXX really correct?
                               # what if ``arg`` has side-effects?
   case arg.kind
-  of nkEmpty..nkNilLit: 
+  of nkEmpty..nkNilLit:
     result = paDirectMapping
-  of nkPar, nkCurly, nkBracket: 
+  of nkPar, nkCurly, nkBracket:
     result = paFastAsgn
-    for i in countup(0, sonsLen(arg) - 1): 
-      if putArgInto(arg.sons[i], formal) != paDirectMapping: return 
+    for i in countup(0, sonsLen(arg) - 1):
+      if putArgInto(arg.sons[i], formal) != paDirectMapping: return
     result = paDirectMapping
-  else: 
+  else:
     if skipTypes(formal, abstractInst).kind == tyVar: result = paVarAsgn
     else: result = paFastAsgn
-  
+
 proc findWrongOwners(c: PTransf, n: PNode) =
   if n.kind == nkVarSection:
     let x = n.sons[0].sons[0]
     if x.kind == nkSym and x.sym.owner != getCurrOwner(c):
-      internalError(x.info, "bah " & x.sym.name.s & " " & 
+      internalError(x.info, "bah " & x.sym.name.s & " " &
         x.sym.owner.name.s & " " & getCurrOwner(c).name.s)
   else:
     for i in 0 .. <safeLen(n): findWrongOwners(c, n.sons[i])
 
-proc transformFor(c: PTransf, n: PNode): PTransNode = 
+proc transformFor(c: PTransf, n: PNode): PTransNode =
   # generate access statements for the parameters (unless they are constant)
   # put mapping from formal parameters to actual parameters
   if n.kind != nkForStmt: internalError(n.info, "transformFor")
@@ -466,26 +466,26 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
   result[0] = newSymNode(labl).PTransNode
 
   if call.typ.kind != tyIter and
-    (call.kind notin nkCallKinds or call.sons[0].kind != nkSym or 
+    (call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
       call.sons[0].sym.kind != skIterator):
     n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
     result[1] = lambdalifting.liftForLoop(n).PTransNode
     discard c.breakSyms.pop
     return result
-  
+
   #echo "transforming: ", renderTree(n)
   var stmtList = newTransNode(nkStmtList, n.info, 0)
-  
+
   var loopBody = transformLoopBody(c, n.sons[length-1])
 
   result[1] = stmtList
   discard c.breakSyms.pop
 
   var v = newNodeI(nkVarSection, n.info)
-  for i in countup(0, length - 3): 
+  for i in countup(0, length - 3):
     addVar(v, copyTree(n.sons[i])) # declare new vars
   add(stmtList, v.PTransNode)
-  
+
   # Bugfix: inlined locals belong to the invoking routine, not to the invoked
   # iterator!
   let iter = call.sons[0].sym
@@ -496,9 +496,9 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
   if iter.kind != skIterator: return result
   # generate access statements for the parameters (unless they are constant)
   pushTransCon(c, newC)
-  for i in countup(1, sonsLen(call) - 1): 
+  for i in countup(1, sonsLen(call) - 1):
     var arg = transform(c, call.sons[i]).PNode
-    var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym 
+    var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym
     if arg.typ.kind == tyIter: continue
     case putArgInto(arg, formal.typ)
     of paDirectMapping:
@@ -527,20 +527,20 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
   popInfoContext()
   popTransCon(c)
   # echo "transformed: ", stmtList.PNode.renderTree
-  
-proc getMagicOp(call: PNode): TMagic = 
+
+proc getMagicOp(call: PNode): TMagic =
   if call.sons[0].kind == nkSym and
-      call.sons[0].sym.kind in {skProc, skMethod, skConverter}: 
+      call.sons[0].sym.kind in {skProc, skMethod, skConverter}:
     result = call.sons[0].sym.magic
   else:
     result = mNone
 
-proc transformCase(c: PTransf, n: PNode): PTransNode = 
+proc transformCase(c: PTransf, n: PNode): PTransNode =
   # removes `elif` branches of a case stmt
   # adds ``else: nil`` if needed for the code generator
   result = newTransNode(nkCaseStmt, n, 0)
   var ifs = PTransNode(nil)
-  for i in 0 .. sonsLen(n)-1: 
+  for i in 0 .. sonsLen(n)-1:
     var it = n.sons[i]
     var e = transform(c, it)
     case it.kind
@@ -564,8 +564,8 @@ proc transformCase(c: PTransf, n: PNode): PTransNode =
     var elseBranch = newTransNode(nkElse, n.info, 1)
     elseBranch[0] = newTransNode(nkNilLit, n.info, 0)
     add(result, elseBranch)
-  
-proc transformArrayAccess(c: PTransf, n: PNode): PTransNode = 
+
+proc transformArrayAccess(c: PTransf, n: PNode): PTransNode =
   # XXX this is really bad; transf should use a proper AST visitor
   if n.sons[0].kind == nkSym and n.sons[0].sym.kind == skType:
     result = n.PTransNode
@@ -573,45 +573,45 @@ proc transformArrayAccess(c: PTransf, n: PNode): PTransNode =
     result = newTransNode(n)
     for i in 0 .. < n.len:
       result[i] = transform(c, skipConv(n.sons[i]))
-  
-proc getMergeOp(n: PNode): PSym = 
+
+proc getMergeOp(n: PNode): PSym =
   case n.kind
-  of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, 
-     nkCallStrLit: 
+  of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix,
+     nkCallStrLit:
     if (n.sons[0].kind == nkSym) and (n.sons[0].sym.kind == skProc) and
-        (sfMerge in n.sons[0].sym.flags): 
+        (sfMerge in n.sons[0].sym.flags):
       result = n.sons[0].sym
   else: discard
 
-proc flattenTreeAux(d, a: PNode, op: PSym) = 
+proc flattenTreeAux(d, a: PNode, op: PSym) =
   let op2 = getMergeOp(a)
   if op2 != nil and
-      (op2.id == op.id or op.magic != mNone and op2.magic == op.magic): 
+      (op2.id == op.id or op.magic != mNone and op2.magic == op.magic):
     for i in countup(1, sonsLen(a)-1): flattenTreeAux(d, a.sons[i], op)
-  else: 
+  else:
     addSon(d, copyTree(a))
-  
-proc flattenTree(root: PNode): PNode = 
+
+proc flattenTree(root: PNode): PNode =
   let op = getMergeOp(root)
-  if op != nil: 
+  if op != nil:
     result = copyNode(root)
     addSon(result, copyTree(root.sons[0]))
     flattenTreeAux(result, root, op)
-  else: 
+  else:
     result = root
 
-proc transformCall(c: PTransf, n: PNode): PTransNode = 
+proc transformCall(c: PTransf, n: PNode): PTransNode =
   var n = flattenTree(n)
   let op = getMergeOp(n)
   let magic = getMagic(n)
-  if op != nil and op.magic != mNone and n.len >= 3: 
+  if op != nil and op.magic != mNone and n.len >= 3:
     result = newTransNode(nkCall, n, 0)
     add(result, transform(c, n.sons[0]))
     var j = 1
-    while j < sonsLen(n): 
+    while j < sonsLen(n):
       var a = transform(c, n.sons[j]).PNode
       inc(j)
-      if isConstExpr(a): 
+      if isConstExpr(a):
         while (j < sonsLen(n)):
           let b = transform(c, n.sons[j]).PNode
           if not isConstExpr(b): break
@@ -640,7 +640,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
 proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
   # symbols that expand to a complex constant (array, etc.) should not be
   # inlined, unless it's the empty array:
-  result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and 
+  result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and
       cnst.len != 0
 
 proc commonOptimizations*(c: PSym, n: PNode): PNode =
@@ -673,11 +673,11 @@ proc commonOptimizations*(c: PSym, n: PNode): PNode =
     else:
       result = n
 
-proc transform(c: PTransf, n: PNode): PTransNode = 
+proc transform(c: PTransf, n: PNode): PTransNode =
   case n.kind
-  of nkSym: 
+  of nkSym:
     result = transformSym(c, n)
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: 
+  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
     # nothing to be done for leaves:
     result = PTransNode(n)
   of nkBracketExpr: result = transformArrayAccess(c, n)
@@ -702,7 +702,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
         n.sons[bodyPos] = PNode(transform(c, s.getBody))
         if n.kind == nkMethodDef: methodDef(s, false)
     result = PTransNode(n)
-  of nkForStmt: 
+  of nkForStmt:
     result = transformFor(c, n)
   of nkParForStmt:
     result = transformSons(c, n)
@@ -713,14 +713,14 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     add(result, PTransNode(newSymNode(labl)))
   of nkBreakStmt: result = transformBreak(c, n)
   of nkWhileStmt: result = transformWhile(c, n)
-  of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, 
-     nkCallStrLit: 
+  of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix,
+     nkCallStrLit:
     result = transformCall(c, n)
-  of nkAddr, nkHiddenAddr: 
+  of nkAddr, nkHiddenAddr:
     result = transformAddrDeref(c, n, nkDerefExpr, nkHiddenDeref)
-  of nkDerefExpr, nkHiddenDeref: 
+  of nkDerefExpr, nkHiddenDeref:
     result = transformAddrDeref(c, n, nkAddr, nkHiddenAddr)
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv: 
+  of nkHiddenStdConv, nkHiddenSubConv, nkConv:
     result = transformConv(c, n)
   of nkDiscardStmt:
     result = PTransNode(n)
@@ -730,7 +730,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
         # ensure that e.g. discard "some comment" gets optimized away
         # completely:
         result = PTransNode(newNode(nkCommentStmt))
-  of nkCommentStmt, nkTemplateDef: 
+  of nkCommentStmt, nkTemplateDef:
     return n.PTransNode
   of nkConstSection:
     # do not replace ``const c = 3`` with ``const 3 = 3``
@@ -744,10 +744,10 @@ proc transform(c: PTransf, n: PNode): PTransNode =
       result = transformVarSection(c, n)
     else:
       result = transformSons(c, n)
-  of nkYieldStmt: 
+  of nkYieldStmt:
     if c.inlining > 0:
       result = transformYield(c, n)
-    else: 
+    else:
       result = transformSons(c, n)
   of nkBlockStmt, nkBlockExpr:
     result = transformBlock(c, n)
@@ -764,7 +764,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
   if cnst != nil and not dontInlineConstant(n, cnst):
     result = PTransNode(cnst) # do not miss an optimization
 
-proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode = 
+proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode =
   # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip
   # this step! We have to rely that the semantic pass transforms too errornous
   # nodes into an empty node.
@@ -774,7 +774,7 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode =
   popTransCon(c)
   incl(result.flags, nfTransf)
 
-proc openTransf(module: PSym, filename: string): PTransf = 
+proc openTransf(module: PSym, filename: string): PTransf =
   new(result)
   result.contSyms = @[]
   result.breakSyms = @[]
diff --git a/lib/system.nim b/lib/system.nim
index abf31c821..4180f24f9 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -89,7 +89,7 @@ type
   SomeOrdinal* = int|int8|int16|int32|int64|bool|enum|uint8|uint16|uint32
     ## type class matching all ordinal types; however this includes enums with
     ## holes.
-  
+
   SomeReal* = float|float32|float64
     ## type class matching all floating point number types
 
@@ -181,7 +181,7 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
   ## freeing the object. Note: The `finalizer` refers to the type `T`, not to
   ## the object! This means that for each object of type `T` the finalizer
   ## will be called!
-  
+
 proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.}
   ## resets an object `obj` to its initial (binary zero) value. This needs to
   ## be called before any possible `object branch transition`:idx:.
@@ -348,7 +348,7 @@ type
                   ## This field is filled automatically in the
                   ## ``raise`` statement.
     msg* {.exportc: "message".}: string ## the exception's message. Not
-                                        ## providing an exception message 
+                                        ## providing an exception message
                                         ## is bad style.
     trace: string
 
@@ -483,7 +483,7 @@ type
 
   E_Base: Exception, ESystem: SystemError, EIO: IOError,
   EOS: OSError, EInvalidLibrary: LibraryError,
-  EResourceExhausted: ResourceExhaustedError, 
+  EResourceExhausted: ResourceExhaustedError,
   EArithmetic: ArithmeticError, EDivByZero: DivByZeroError,
   EOverflow: OverflowError, EAccessViolation: AccessViolationError,
   EAssertionFailed: AssertionError, EInvalidValue: ValueError,
@@ -494,7 +494,7 @@ type
   EInvalidObjectAssignment: ObjectAssignmentError,
   EInvalidObjectConversion: ObjectConversionError,
   EDeadThread: DeadThreadError,
-  EFloatInexact: FloatInexactError, 
+  EFloatInexact: FloatInexactError,
   EFloatUnderflow: FloatUnderflowError,
   EFloatingPoint: FloatingPointError,
   EFloatInvalidOp: FloatInvalidOpError,
@@ -511,11 +511,11 @@ proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
 
 proc `<`*[T](x: Ordinal[T]): T {.magic: "UnaryLt", noSideEffect.}
   ## unary ``<`` that can be used for nice looking excluding ranges:
-  ## 
+  ##
   ## .. code-block:: nim
   ##   for i in 0 .. <10: echo i
   ##
-  ## Semantically this is the same as ``pred``. 
+  ## Semantically this is the same as ``pred``.
 
 proc succ*[T](x: Ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.}
   ## returns the ``y``-th successor of the value ``x``. ``T`` has to be
@@ -536,7 +536,7 @@ proc dec*[T: Ordinal|uint|uint64](x: var T, y = 1) {.magic: "Dec", noSideEffect.
   ## decrements the ordinal ``x`` by ``y``. If such a value does not
   ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
   ## short notation for: ``x = pred(x, y)``.
-  
+
 proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.}
   ## creates a new sequence of type ``seq[T]`` with length ``len``.
   ## This is equivalent to ``s = @[]; setlen(s, len)``, but more
@@ -636,7 +636,7 @@ when not defined(JS):
 
   proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
     ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
-    ## from `x`.    
+    ## from `x`.
   proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.}
     ## treats `x` as unsigned and converts it to an ``int16`` by taking the last
     ## 16 bits from `x`.
@@ -800,7 +800,7 @@ proc `%%` *(x, y: int64): int64 {.magic: "ModU", noSideEffect.}
   ## The result is truncated to fit into the result.
   ## This implements modulo arithmetic.
   ## No overflow errors are possible.
-  
+
 proc `<=%` *(x, y: IntMax32): bool {.magic: "LeU", noSideEffect.}
 proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
   ## treats `x` and `y` as unsigned and compares them.
@@ -889,7 +889,7 @@ template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x)
 
 proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
   ## Checks if T is of the same type as S
-  ## 
+  ##
   ## .. code-block:: Nim
   ##   proc test[T](a: T): int =
   ##     when (T is int):
@@ -924,7 +924,7 @@ proc cmp*(x, y: string): int {.noSideEffect, procvar.}
 proc `@` * [IDX, T](a: array[IDX, T]): seq[T] {.
   magic: "ArrToSeq", nosideeffect.}
   ## turns an array into a sequence. This most often useful for constructing
-  ## sequences with the array constructor: ``@[1, 2, 3]`` has the type 
+  ## sequences with the array constructor: ``@[1, 2, 3]`` has the type
   ## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``.
 
 proc setLen*[T](s: var seq[T], newlen: int) {.
@@ -933,14 +933,14 @@ proc setLen*[T](s: var seq[T], newlen: int) {.
   ## ``T`` may be any sequence type.
   ## If the current length is greater than the new length,
   ## ``s`` will be truncated. `s` cannot be nil! To initialize a sequence with
-  ## a size, use ``newSeq`` instead. 
+  ## a size, use ``newSeq`` instead.
 
 proc setLen*(s: var string, newlen: int) {.
   magic: "SetLengthStr", noSideEffect.}
   ## sets the length of `s` to `newlen`.
   ## If the current length is greater than the new length,
   ## ``s`` will be truncated. `s` cannot be nil! To initialize a string with
-  ## a size, use ``newString`` instead. 
+  ## a size, use ``newString`` instead.
 
 proc newString*(len: int): string {.
   magic: "NewString", importc: "mnewString", noSideEffect.}
@@ -953,7 +953,7 @@ proc newString*(len: int): string {.
 proc newStringOfCap*(cap: int): string {.
   magic: "NewStringOfCap", importc: "rawNewString", noSideEffect.}
   ## returns a new string of length ``0`` but with capacity `cap`.This
-  ## procedure exists only for optimization purposes; the same effect can 
+  ## procedure exists only for optimization purposes; the same effect can
   ## be achieved with the ``&`` operator or with ``add``.
 
 proc `&` * (x: string, y: char): string {.
@@ -982,7 +982,7 @@ proc `&` * (x: char, y: string): string {.
   ##   assert('a' & "bc" == "abc")
 
 # implementation note: These must all have the same magic value "ConStrStr" so
-# that the merge optimization works properly. 
+# that the merge optimization works properly.
 
 proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
   ## Appends `y` to `x` in place
@@ -1039,15 +1039,15 @@ proc compileOption*(option: string): bool {.
   ## can be used to determine an on|off compile-time option. Example:
   ##
   ## .. code-block:: nim
-  ##   when compileOption("floatchecks"): 
+  ##   when compileOption("floatchecks"):
   ##     echo "compiled with floating point NaN and Inf checks"
-  
+
 proc compileOption*(option, arg: string): bool {.
   magic: "CompileOptionArg", noSideEffect.}
   ## can be used to determine an enum compile-time option. Example:
   ##
   ## .. code-block:: nim
-  ##   when compileOption("opt", "size") and compileOption("gc", "boehm"): 
+  ##   when compileOption("opt", "size") and compileOption("gc", "boehm"):
   ##     echo "compiled with optimization for size and uses Boehm's GC"
 
 const
@@ -1056,16 +1056,16 @@ const
   taintMode = compileOption("taintmode")
 
 when taintMode:
-  type TaintedString* = distinct string ## a distinct string type that 
+  type TaintedString* = distinct string ## a distinct string type that
                                         ## is `tainted`:idx:. It is an alias for
                                         ## ``string`` if the taint mode is not
                                         ## turned on. Use the ``-d:taintMode``
                                         ## command line switch to turn the taint
                                         ## mode on.
-  
+
   proc len*(s: TaintedString): int {.borrow.}
 else:
-  type TaintedString* = string          ## a distinct string type that 
+  type TaintedString* = string          ## a distinct string type that
                                         ## is `tainted`:idx:. It is an alias for
                                         ## ``string`` if the taint mode is not
                                         ## turned on. Use the ``-d:taintMode``
@@ -1136,25 +1136,25 @@ proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
 proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
   ## use this instead of `=` for a `shallow copy`:idx:. The shallow copy
   ## only changes the semantics for sequences and strings (and types which
-  ## contain those). Be careful with the changed semantics though! There 
+  ## contain those). Be careful with the changed semantics though! There
   ## is a reason why the default assignment does a deep copy of sequences
   ## and strings.
 
-proc del*[T](x: var seq[T], i: int) {.noSideEffect.} = 
+proc del*[T](x: var seq[T], i: int) {.noSideEffect.} =
   ## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
   ## This is an O(1) operation.
   let xl = x.len
   shallowCopy(x[i], x[xl-1])
   setLen(x, xl-1)
-  
-proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} = 
+
+proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} =
   ## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
   ## This is an O(n) operation.
   let xl = x.len
-  for j in i..xl-2: shallowCopy(x[j], x[j+1]) 
+  for j in i..xl-2: shallowCopy(x[j], x[j+1])
   setLen(x, xl-1)
-  
-proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} = 
+
+proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} =
   ## inserts `item` into `x` at position `i`.
   let xl = x.len
   setLen(x, xl+1)
@@ -1233,7 +1233,7 @@ type # these work for most platforms:
     ## This is binary compatible to the type ``char**`` in *C*. The array's
     ## high value is large enough to disable bounds checking in practice.
     ## Use `cstringArrayToSeq` to convert it into a ``seq[string]``.
-  
+
   PFloat32* = ptr float32 ## an alias for ``ptr float32``
   PFloat64* = ptr float64 ## an alias for ``ptr float64``
   PInt64* = ptr int64 ## an alias for ``ptr int64``
@@ -1280,7 +1280,7 @@ proc addQuitProc*(QuitProc: proc() {.noconv.}) {.
 proc copy*(s: string, first = 0): string {.
   magic: "CopyStr", importc: "copyStr", noSideEffect, deprecated.}
 proc copy*(s: string, first, last: int): string {.
-  magic: "CopyStrLast", importc: "copyStrLast", noSideEffect, 
+  magic: "CopyStrLast", importc: "copyStrLast", noSideEffect,
   deprecated.}
   ## copies a slice of `s` into a new string and returns this new
   ## string. The bounds `first` and `last` denote the indices of
@@ -1358,7 +1358,7 @@ when not defined(nimrodVM):
       ## The allocated memory belongs to its allocating thread!
       ## Use `createShared` to allocate from a shared heap.
       cast[ptr T](alloc0(T.sizeof * size))
-    proc realloc*(p: pointer, newSize: int): pointer {.noconv, rtl, tags: [], 
+    proc realloc*(p: pointer, newSize: int): pointer {.noconv, rtl, tags: [],
                                                        benign.}
       ## grows or shrinks a given memory block. If p is **nil** then a new
       ## memory block is returned. In either way the block has at least
@@ -1381,7 +1381,7 @@ when not defined(nimrodVM):
       ## ``realloc``. This procedure is dangerous! If one forgets to
       ## free the memory a leak occurs; if one tries to access freed
       ## memory (or just freeing it twice!) a core dump may happen
-      ## or other memory may be corrupted. 
+      ## or other memory may be corrupted.
       ## The freed memory must belong to its allocating thread!
       ## Use `deallocShared` to deallocate from a shared heap.
     proc free*[T](p: ptr T) {.inline, benign.} =
@@ -1390,30 +1390,30 @@ when not defined(nimrodVM):
       ## allocates a new memory block on the shared heap with at
       ## least ``size`` bytes. The block has to be freed with
       ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
-      ## is not initialized, so reading from it before writing to it is 
+      ## is not initialized, so reading from it before writing to it is
       ## undefined behaviour!
-    proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline, 
+    proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline,
                                                                  benign.} =
       ## allocates a new memory block on the shared heap with at
       ## least ``T.sizeof * size`` bytes. The block has to be freed with
       ## ``resizeShared(block, 0)`` or ``freeShared(block)``. The block
-      ## is not initialized, so reading from it before writing to it is 
+      ## is not initialized, so reading from it before writing to it is
       ## undefined behaviour!
       cast[ptr T](allocShared(T.sizeof * size))
     proc allocShared0*(size: int): pointer {.noconv, rtl, benign.}
-      ## allocates a new memory block on the shared heap with at 
+      ## allocates a new memory block on the shared heap with at
       ## least ``size`` bytes. The block has to be freed with
       ## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
       ## The block is initialized with all bytes
       ## containing zero, so it is somewhat safer than ``allocShared``.
     proc createShared*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
-      ## allocates a new memory block on the shared heap with at 
+      ## allocates a new memory block on the shared heap with at
       ## least ``T.sizeof * size`` bytes. The block has to be freed with
       ## ``resizeShared(block, 0)`` or ``freeShared(block)``.
       ## The block is initialized with all bytes
       ## containing zero, so it is somewhat safer than ``createSharedU``.
       cast[ptr T](allocShared0(T.sizeof * size))
-    proc reallocShared*(p: pointer, newSize: int): pointer {.noconv, rtl, 
+    proc reallocShared*(p: pointer, newSize: int): pointer {.noconv, rtl,
                                                              benign.}
       ## grows or shrinks a given memory block on the heap. If p is **nil**
       ## then a new memory block is returned. In either way the block has at
@@ -1525,7 +1525,7 @@ const
   NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
     ## is the version of Nim as a string.
 
-{.deprecated: [TEndian: Endianness, NimrodVersion: NimVersion, 
+{.deprecated: [TEndian: Endianness, NimrodVersion: NimVersion,
     NimrodMajor: NimMajor, NimrodMinor: NimMinor, NimrodPatch: NimPatch].}
 
 # GC interface:
@@ -1805,7 +1805,7 @@ proc `==` *[I, T](x, y: array[I, T]): bool =
       return
   result = true
 
-proc `@`*[T](a: openArray[T]): seq[T] = 
+proc `@`*[T](a: openArray[T]): seq[T] =
   ## turns an openarray into a sequence. This is not as efficient as turning
   ## a fixed length array into a sequence as it always copies every element
   ## of `a`.
@@ -1853,7 +1853,7 @@ when not defined(NimrodVM):
   else:
     proc seqToPtr[T](x: seq[T]): pointer {.asmNoStackFrame, nosideeffect.} =
       asm """return `x`"""
-  
+
   proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
     ## Generic equals operator for sequences: relies on a equals operator for
     ## the element type `T`.
@@ -1879,7 +1879,7 @@ proc contains*[T](a: openArray[T], item: T): bool {.inline.}=
   ## for ``find(a, item) >= 0``.
   return find(a, item) >= 0
 
-proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} = 
+proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
   ## returns the last item of `s` and decreases ``s.len`` by one. This treats
   ## `s` as a stack and implements the common *pop* operation.
   var L = s.len-1
@@ -1941,7 +1941,7 @@ iterator fields*[T: tuple|object](x: T): RootObj {.
 iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a,b: expr] {.
   magic: "Fields", noSideEffect.}
   ## iterates over every field of `x` and `y`.
-  ## Warning: This is really transforms the 'for' and unrolls the loop. 
+  ## Warning: This is really transforms the 'for' and unrolls the loop.
   ## The current implementation also has a bug that affects symbol binding
   ## in the loop body.
 iterator fieldPairs*[T: tuple|object](x: T): RootObj {.
@@ -1982,18 +1982,18 @@ iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[
   a, b: expr] {.
   magic: "FieldPairs", noSideEffect.}
   ## iterates over every field of `x` and `y`.
-  ## Warning: This really transforms the 'for' and unrolls the loop. 
+  ## Warning: This really transforms the 'for' and unrolls the loop.
   ## The current implementation also has a bug that affects symbol binding
   ## in the loop body.
 
-proc `==`*[T: tuple|object](x, y: T): bool = 
+proc `==`*[T: tuple|object](x, y: T): bool =
   ## generic ``==`` operator for tuples that is lifted from the components
   ## of `x` and `y`.
   for a, b in fields(x, y):
     if a != b: return false
   return true
 
-proc `<=`*[T: tuple](x, y: T): bool = 
+proc `<=`*[T: tuple](x, y: T): bool =
   ## generic ``<=`` operator for tuples that is lifted from the components
   ## of `x` and `y`. This implementation uses `cmp`.
   for a, b in fields(x, y):
@@ -2002,7 +2002,7 @@ proc `<=`*[T: tuple](x, y: T): bool =
     if c > 0: return false
   return true
 
-proc `<`*[T: tuple](x, y: T): bool = 
+proc `<`*[T: tuple](x, y: T): bool =
   ## generic ``<`` operator for tuples that is lifted from the components
   ## of `x` and `y`. This implementation uses `cmp`.
   for a, b in fields(x, y):
@@ -2011,7 +2011,7 @@ proc `<`*[T: tuple](x, y: T): bool =
     if c > 0: return false
   return false
 
-proc `$`*[T: tuple|object](x: T): string = 
+proc `$`*[T: tuple|object](x: T): string =
   ## generic ``$`` operator for tuples that is lifted from the components
   ## of `x`. Example:
   ##
@@ -2021,13 +2021,13 @@ proc `$`*[T: tuple|object](x: T): string =
   result = "("
   var firstElement = true
   for name, value in fieldPairs(x):
-    if not(firstElement): result.add(", ")
+    if not firstElement: result.add(", ")
     result.add(name)
     result.add(": ")
     result.add($value)
     firstElement = false
   result.add(")")
-  
+
 proc collectionToString[T](x: T, b, e: string): string =
   result = b
   var firstElement = true
@@ -2037,7 +2037,7 @@ proc collectionToString[T](x: T, b, e: string): string =
     firstElement = false
   result.add(e)
 
-proc `$`*[T](x: set[T]): string = 
+proc `$`*[T](x: set[T]): string =
   ## generic ``$`` operator for sets that is lifted from the components
   ## of `x`. Example:
   ##
@@ -2045,7 +2045,7 @@ proc `$`*[T](x: set[T]): string =
   ##   ${23, 45} == "{23, 45}"
   collectionToString(x, "{", "}")
 
-proc `$`*[T](x: seq[T]): string = 
+proc `$`*[T](x: seq[T]): string =
   ## generic ``$`` operator for seqs that is lifted from the components
   ## of `x`. Example:
   ##
@@ -2056,7 +2056,7 @@ proc `$`*[T](x: seq[T]): string =
 when false:
   # causes bootstrapping to fail as we use array of chars and cstring should
   # match better ...
-  proc `$`*[T, IDX](x: array[IDX, T]): string = 
+  proc `$`*[T, IDX](x: array[IDX, T]): string =
     collectionToString(x, "[", "]")
 
 # ----------------- GC interface ---------------------------------------------
@@ -2098,14 +2098,14 @@ when not defined(nimrodVM) and hostOS != "standalone":
   proc GC_getStatistics*(): string {.rtl, benign.}
     ## returns an informative string about the GC's activity. This may be useful
     ## for tweaking.
-    
+
   proc GC_ref*[T](x: ref T) {.magic: "GCref", benign.}
   proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign.}
   proc GC_ref*(x: string) {.magic: "GCref", benign.}
     ## marks the object `x` as referenced, so that it will not be freed until
     ## it is unmarked via `GC_unref`. If called n-times for the same object `x`,
-    ## n calls to `GC_unref` are needed to unmark `x`. 
-    
+    ## n calls to `GC_unref` are needed to unmark `x`.
+
   proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign.}
   proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign.}
   proc GC_unref*(x: string) {.magic: "GCunref", benign.}
@@ -2141,19 +2141,19 @@ var
     ## application code should never set this hook! You better know what you
     ## do when setting this. If ``localRaiseHook`` returns false, the exception
     ## is caught and does not propagate further through the call stack.
-    
+
   outOfMemHook*: proc () {.nimcall, tags: [], benign.}
-    ## set this variable to provide a procedure that should be called 
+    ## set this variable to provide a procedure that should be called
     ## in case of an `out of memory`:idx: event. The standard handler
     ## writes an error message and terminates the program. `outOfMemHook` can
     ## be used to raise an exception in case of OOM like so:
-    ## 
+    ##
     ## .. code-block:: nim
     ##
     ##   var gOutOfMem: ref EOutOfMemory
     ##   new(gOutOfMem) # need to be allocated *before* OOM really happened!
     ##   gOutOfMem.msg = "out of memory"
-    ## 
+    ##
     ##   proc handleOOM() =
     ##     raise gOutOfMem
     ##
@@ -2210,7 +2210,7 @@ proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
   ## <manual.html#nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
   ## instead.
 
-proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect, 
+proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect,
                                            tags: [], raises: [].}
   ## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho``
   ## pretends to be free of side effects, so that it can be used for debugging
@@ -2262,7 +2262,7 @@ proc abs*(x: int16): int16 {.magic: "AbsI", noSideEffect.} =
 proc abs*(x: int32): int32 {.magic: "AbsI", noSideEffect.} =
   if x < 0: -x else: x
 proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.} =
-  ## returns the absolute value of `x`. If `x` is ``low(x)`` (that 
+  ## returns the absolute value of `x`. If `x` is ``low(x)`` (that
   ## is -MININT for its type), an overflow exception is thrown (if overflow
   ## checking is turned on).
   if x < 0: -x else: x
@@ -2318,14 +2318,14 @@ when not defined(JS): #and not defined(NimrodVM):
       # we use binary mode in Windows:
       setmode(fileno(c_stdin), O_BINARY)
       setmode(fileno(c_stdout), O_BINARY)
-    
+
     when defined(endb):
       proc endbStep()
 
   # ----------------- IO Part ------------------------------------------------
   when hostOS != "standalone":
     type
-      CFile {.importc: "FILE", header: "<stdio.h>", 
+      CFile {.importc: "FILE", header: "<stdio.h>",
               final, incompletestruct.} = object
       File* = ptr CFile ## The type representing a file handle.
 
@@ -2375,9 +2375,9 @@ when not defined(JS): #and not defined(NimrodVM):
       ## Creates a ``TFile`` from a `filehandle` with given `mode`.
       ##
       ## Default mode is readonly. Returns true iff the file could be opened.
-      
+
     proc open*(filename: string,
-               mode: FileMode = fmRead, bufSize: int = -1): File = 
+               mode: FileMode = fmRead, bufSize: int = -1): File =
       ## Opens a file named `filename` with given `mode`.
       ##
       ## Default mode is readonly. Raises an ``IO`` exception if the file
@@ -2387,7 +2387,7 @@ when not defined(JS): #and not defined(NimrodVM):
 
     proc reopen*(f: File, filename: string, mode: FileMode = fmRead): bool {.
       tags: [], benign.}
-      ## reopens the file `f` with given `filename` and `mode`. This 
+      ## reopens the file `f` with given `filename` and `mode`. This
       ## is often used to redirect the `stdin`, `stdout` or `stderr`
       ## file variables.
       ##
@@ -2398,7 +2398,7 @@ when not defined(JS): #and not defined(NimrodVM):
 
     proc endOfFile*(f: File): bool {.tags: [], benign.}
       ## Returns true iff `f` is at the end.
-      
+
     proc readChar*(f: File): char {.
       importc: "fgetc", header: "<stdio.h>", tags: [ReadIOEffect].}
       ## Reads a single character from the stream `f`.
@@ -2411,7 +2411,7 @@ when not defined(JS): #and not defined(NimrodVM):
       ##
       ## Raises an IO exception in case of an error. It is an error if the
       ## current file position is not at the beginning of the file.
-    
+
     proc readFile*(filename: string): TaintedString {.tags: [ReadIOEffect], benign.}
       ## Opens a file named `filename` for reading.
       ##
@@ -2440,8 +2440,8 @@ when not defined(JS): #and not defined(NimrodVM):
       ## reads a line of text from the file `f`. May throw an IO exception.
       ## A line of text may be delimited by ``CR``, ``LF`` or
       ## ``CRLF``. The newline character(s) are not part of the returned string.
-    
-    proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect], 
+
+    proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect],
                   benign.}
       ## reads a line of text from the file `f` into `line`. `line` must not be
       ## ``nil``! May throw an IO exception.
@@ -2450,7 +2450,7 @@ when not defined(JS): #and not defined(NimrodVM):
       ## Returns ``false`` if the end of the file has been reached, ``true``
       ## otherwise. If ``false`` is returned `line` contains no new data.
 
-    proc writeln*[Ty](f: File, x: varargs[Ty, `$`]) {.inline, 
+    proc writeln*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
                              tags: [WriteIOEffect], benign.}
       ## writes the values `x` to `f` and then writes "\n".
       ## May throw an IO exception.
@@ -2544,11 +2544,11 @@ when not defined(JS): #and not defined(NimrodVM):
       dealloc(a)
 
   when not defined(NimrodVM):
-    proc atomicInc*(memLoc: var int, x: int = 1): int {.inline, 
+    proc atomicInc*(memLoc: var int, x: int = 1): int {.inline,
       discardable, benign.}
       ## atomic increment of `memLoc`. Returns the value after the operation.
-    
-    proc atomicDec*(memLoc: var int, x: int = 1): int {.inline, 
+
+    proc atomicDec*(memLoc: var int, x: int = 1): int {.inline,
       discardable, benign.}
       ## atomic decrement of `memLoc`. Returns the value after the operation.
 
@@ -2562,7 +2562,7 @@ when not defined(JS): #and not defined(NimrodVM):
       context: C_JmpBuf
       hasRaiseAction: bool
       raiseAction: proc (e: ref Exception): bool {.closure.}
-  
+
   when declared(initAllocator):
     initAllocator()
   when hasThreadSupport:
@@ -2576,7 +2576,7 @@ when not defined(JS): #and not defined(NimrodVM):
     proc setControlCHook*(hook: proc () {.noconv.} not nil)
       ## allows you to override the behaviour of your application when CTRL+C
       ## is pressed. Only one such hook is supported.
-      
+
     proc writeStackTrace*() {.tags: [WriteIOEffect].}
       ## writes the current stack trace to ``stderr``. This is only works
       ## for debug builds.
@@ -2587,20 +2587,20 @@ when not defined(JS): #and not defined(NimrodVM):
       proc getStackTrace*(e: ref Exception): string
         ## gets the stack trace associated with `e`, which is the stack that
         ## lead to the ``raise`` statement. This only works for debug builds.
-        
+
     {.push stack_trace: off, profiler:off.}
     when hostOS == "standalone":
       include "system/embedded"
     else:
       include "system/excpt"
     include "system/chcks"
-      
+
     # we cannot compile this with stack tracing on
     # as it would recurse endlessly!
     include "system/arithm"
     {.pop.} # stack trace
   {.pop.} # stack trace
-      
+
   when hostOS != "standalone" and not defined(NimrodVM):
     include "system/dyncalls"
   when not defined(NimrodVM):
@@ -2608,7 +2608,7 @@ when not defined(JS): #and not defined(NimrodVM):
 
     const
       GenericSeqSize = (2 * sizeof(int))
-      
+
     proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
       sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
       var d: int
@@ -2728,7 +2728,7 @@ when not defined(JS): #and not defined(NimrodVM):
       ##       process(value)
       ##     else:
       ##       echo "Value too big!"
-    
+
     proc unlikely*(val: bool): bool {.importc: "unlikely", nodecl, nosideeffect.}
       ## Hints the optimizer that `val` is likely going to be false.
       ##
@@ -2742,7 +2742,7 @@ when not defined(JS): #and not defined(NimrodVM):
       ##       echo "Value too big!"
       ##     else:
       ##       process(value)
-      
+
     proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} =
       ## retrieves the raw proc pointer of the closure `x`. This is
       ## useful for interfacing closures with C.
@@ -2774,7 +2774,7 @@ elif defined(JS):
   proc GC_enableMarkAndSweep() = discard
   proc GC_disableMarkAndSweep() = discard
   proc GC_getStatistics(): string = return ""
-  
+
   proc getOccupiedMem(): int = return -1
   proc getFreeMem(): int = return -1
   proc getTotalMem(): int = return -1
@@ -2797,7 +2797,7 @@ elif defined(JS):
       if x == y: return 0
       if x < y: return -1
       return 1
-  
+
   when defined(nimffi):
     include "system/sysio"
 
@@ -2831,14 +2831,14 @@ template spliceImpl(s, a, L, b: expr): stmt {.immediate.} =
     # cut down:
     setLen(s, newLen)
   # fill the hole:
-  for i in 0 .. <b.len: s[i+a] = b[i]  
+  for i in 0 .. <b.len: s[i+a] = b[i]
 
 when hostOS != "standalone":
   proc `[]`*(s: string, x: Slice[int]): string {.inline.} =
     ## slice operation for strings. Negative indexes are supported.
     result = s.substr(x.a-|s, x.b-|s)
 
-  proc `[]=`*(s: var string, x: Slice[int], b: string) = 
+  proc `[]=`*(s: var string, x: Slice[int], b: string) =
     ## slice assignment for strings. Negative indexes are supported. If
     ## ``b.len`` is not exactly the number of elements that are referred to
     ## by `x`, a `splice`:idx: is performed:
@@ -2880,7 +2880,7 @@ proc `[]`*[Idx, T](a: array[Idx, T], x: Slice[Idx]): seq[T] =
   var L = ord(x.b) - ord(x.a) + 1
   newSeq(result, L)
   var j = x.a
-  for i in 0.. <L: 
+  for i in 0.. <L:
     result[i] = a[j]
     inc(j)
 
@@ -2890,23 +2890,23 @@ proc `[]=`*[Idx, T](a: var array[Idx, T], x: Slice[Idx], b: openArray[T]) =
   var L = ord(x.b) - ord(x.a) + 1
   if L == b.len:
     var j = x.a
-    for i in 0 .. <L: 
+    for i in 0 .. <L:
       a[j] = b[i]
       inc(j)
   else:
     sysFatal(RangeError, "different lengths for slice assignment")
 
-proc `[]`*[T](s: seq[T], x: Slice[int]): seq[T] = 
+proc `[]`*[T](s: seq[T], x: Slice[int]): seq[T] =
   ## slice operation for sequences. Negative indexes are supported.
   var a = x.a-|s
   var L = x.b-|s - a + 1
   newSeq(result, L)
   for i in 0.. <L: result[i] = s[i + a]
 
-proc `[]=`*[T](s: var seq[T], x: Slice[int], b: openArray[T]) = 
+proc `[]=`*[T](s: var seq[T], x: Slice[int], b: openArray[T]) =
   ## slice assignment for sequences. Negative indexes are supported. If
   ## ``b.len`` is not exactly the number of elements that are referred to
-  ## by `x`, a `splice`:idx: is performed. 
+  ## by `x`, a `splice`:idx: is performed.
   var a = x.a-|s
   var L = x.b-|s - a + 1
   if L == b.len:
@@ -2937,7 +2937,7 @@ proc staticExec*(command: string, input = ""): string {.
   ## to the executed program.
   ##
   ## .. code-block:: nim
-  ##     const buildInfo = "Revision " & staticExec("git rev-parse HEAD") & 
+  ##     const buildInfo = "Revision " & staticExec("git rev-parse HEAD") &
   ##                       "\nCompiled on " & staticExec("uname -v")
   ##
   ## `gorge <#gorge>`_ is an alias for ``staticExec``. Note that you can use
@@ -2979,7 +2979,7 @@ proc `&=`* (x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
 proc astToStr*[T](x: T): string {.magic: "AstToStr", noSideEffect.}
   ## converts the AST of `x` into a string representation. This is very useful
   ## for debugging.
-  
+
 proc instantiationInfo*(index = -1, fullPaths = false): tuple[
   filename: string, line: int] {. magic: "InstantiationInfo", noSideEffect.}
   ## provides access to the compiler's instantiation stack line information.
@@ -3090,16 +3090,16 @@ template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
   ## Sets an assertion failure handler that will intercept any assert
   ## statements following `onFailedAssert` in the current lexical scope.
   ## Can be defined multiple times in a single function.
-  ##  
+  ##
   ## .. code-block:: nim
   ##
   ##   proc example(x: int): TErrorCode =
   ##     onFailedAssert(msg):
   ##       log msg
   ##       return E_FAIL
-  ## 
+  ##
   ##     assert(...)
-  ##     
+  ##
   ##     onFailedAssert(msg):
   ##       raise newException(EMyException, msg)
   ##
@@ -3111,7 +3111,7 @@ template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
 
 proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
   ## marks a sequence `s` as `shallow`:idx:. Subsequent assignments will not
-  ## perform deep copies of `s`. This is only useful for optimization 
+  ## perform deep copies of `s`. This is only useful for optimization
   ## purposes.
   when not defined(JS) and not defined(NimrodVM):
     var s = cast[PGenericSeq](s)
@@ -3119,7 +3119,7 @@ proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
 
 proc shallow*(s: var string) {.noSideEffect, inline.} =
   ## marks a string `s` as `shallow`:idx:. Subsequent assignments will not
-  ## perform deep copies of `s`. This is only useful for optimization 
+  ## perform deep copies of `s`. This is only useful for optimization
   ## purposes.
   when not defined(JS) and not defined(NimrodVM):
     var s = cast[PGenericSeq](s)
@@ -3141,13 +3141,13 @@ else:
 when false:
   template eval*(blk: stmt): stmt =
     ## executes a block of code at compile time just as if it was a macro
-    ## optionally, the block can return an AST tree that will replace the 
+    ## optionally, the block can return an AST tree that will replace the
     ## eval expression
     macro payload: stmt {.gensym.} = blk
     payload()
 
 when hostOS != "standalone":
-  proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} = 
+  proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} =
     ## inserts `item` into `x` at position `i`.
     var xl = x.len
     setLen(x, xl+item.len)
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 9de0c6503..bbf8cbf66 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -48,7 +48,7 @@ type
   TWalkOp = enum
     waMarkGlobal,    # part of the backup/debug mark&sweep
     waMarkPrecise,   # part of the backup/debug mark&sweep
-    waZctDecRef, waPush, waCycleDecRef, waMarkGray, waScan, waScanBlack, 
+    waZctDecRef, waPush, waCycleDecRef, waMarkGray, waScan, waScanBlack,
     waCollectWhite #, waDebug
 
   TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
@@ -61,9 +61,9 @@ type
     maxThreshold: int        # max threshold that has been set
     maxStackSize: int        # max stack size
     maxStackCells: int       # max stack cells in ``decStack``
-    cycleTableSize: int      # max entries in cycle table  
+    cycleTableSize: int      # max entries in cycle table
     maxPause: int64          # max measured GC pause in nanoseconds
-  
+
   TGcHeap {.final, pure.} = object # this contains the zero count and
                                    # non-zero count table
     stackBottom: pointer
@@ -88,11 +88,11 @@ var
 when not defined(useNimRtl):
   instantiateForRegion(gch.region)
 
-template acquire(gch: TGcHeap) = 
+template acquire(gch: TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     acquireSys(HeapLock)
 
-template release(gch: TGcHeap) = 
+template release(gch: TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     releaseSys(HeapLock)
 
@@ -163,7 +163,7 @@ when hasThreadSupport and hasSharedHeap:
   template `--`(x: expr): expr = atomicDec(x, rcIncrement) <% rcIncrement
   template `++`(x: expr): stmt = discard atomicInc(x, rcIncrement)
 else:
-  template `--`(x: expr): expr = 
+  template `--`(x: expr): expr =
     dec(x, rcIncrement)
     x <% rcIncrement
   template `++`(x: expr): stmt = inc(x, rcIncrement)
@@ -181,7 +181,7 @@ proc prepareDealloc(cell: PCell) =
     (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
 
-proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = 
+proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} =
   # we MUST access gch as a global here, because this crosses DLL boundaries!
   when hasThreadSupport and hasSharedHeap:
     acquireSys(HeapLock)
@@ -211,7 +211,7 @@ proc decRef(c: PCell) {.inline.} =
     rtlAddCycleRoot(c)
     #writeCell("decRef", c)
 
-proc incRef(c: PCell) {.inline.} = 
+proc incRef(c: PCell) {.inline.} =
   gcAssert(isAllocatedPtr(gch.region, c), "incRef: interiorPtr")
   c.refcount = c.refcount +% rcIncrement
   # and not colorMask
@@ -246,12 +246,12 @@ proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} =
   dest[] = src
 
 proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} =
-  # the code generator calls this proc if it is known at compile time that no 
+  # the code generator calls this proc if it is known at compile time that no
   # cycle is possible.
   if src != nil:
     var c = usrToCell(src)
     ++c.refcount
-  if dest[] != nil: 
+  if dest[] != nil:
     var c = usrToCell(dest[])
     if --c.refcount:
       rtlAddZCT(c)
@@ -269,7 +269,7 @@ proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} =
     if cast[int](dest[]) >=% PageSize: decRef(usrToCell(dest[]))
   else:
     # can't be an interior pointer if it's a stack location!
-    gcAssert(interiorAllocatedPtr(gch.region, dest) == nil, 
+    gcAssert(interiorAllocatedPtr(gch.region, dest) == nil,
              "stack loc AND interior pointer")
   dest[] = src
 
@@ -321,7 +321,7 @@ when useMarkForDebug or useBackupGc:
       echo "[GC] cannot register global variable; too many global variables"
       quit 1
 
-proc cellsetReset(s: var TCellSet) = 
+proc cellsetReset(s: var TCellSet) =
   deinit(s)
   init(s)
 
@@ -336,7 +336,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} =
         if n.sons[i].typ.kind in {tyRef, tyString, tySequence}:
           doOperation(cast[PPointer](d +% n.sons[i].offset)[], op)
         else:
-          forAllChildrenAux(cast[pointer](d +% n.sons[i].offset), 
+          forAllChildrenAux(cast[pointer](d +% n.sons[i].offset),
                             n.sons[i].typ, op)
       else:
         forAllSlotsAux(dest, n.sons[i], op)
@@ -384,7 +384,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
   # we check the last 8 entries (cache line) for a slot that could be reused.
   # In 63% of all cases we succeed here! But we have to optimize the heck
   # out of this small linear search so that ``newObj`` is not slowed down.
-  # 
+  #
   # Slots to try          cache hit
   # 1                     32%
   # 4                     59%
@@ -481,7 +481,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
   gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
   collectCT(gch)
   sysAssert(allocInv(gch.region), "newObjRC1 after collectCT")
-  
+
   var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
   sysAssert(allocInv(gch.region), "newObjRC1 after rawAlloc")
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
@@ -510,7 +510,7 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   cast[PGenericSeq](result).len = len
   cast[PGenericSeq](result).reserved = len
   when defined(memProfiler): nimProfile(size)
-  
+
 proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   acquire(gch)
   collectCT(gch)
@@ -522,7 +522,7 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(TCell)))
   var elemSize = 1
   if ol.typ.kind != tyString: elemSize = ol.typ.base.size
-  
+
   var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
   copyMem(res, ol, oldsize + sizeof(TCell))
   zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
@@ -536,7 +536,7 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
     writeCell("growObj new cell", res)
   gcTrace(ol, csZctFreed)
   gcTrace(res, csAllocated)
-  when reallyDealloc: 
+  when reallyDealloc:
     sysAssert(allocInv(gch.region), "growObj before dealloc")
     if ol.refcount shr rcShift <=% 1:
       # free immediately to save space:
@@ -580,7 +580,7 @@ proc freeCyclicCell(gch: var TGcHeap, c: PCell) =
   prepareDealloc(c)
   gcTrace(c, csCycFreed)
   when logGC: writeCell("cycle collector dealloc cell", c)
-  when reallyDealloc: 
+  when reallyDealloc:
     sysAssert(allocInv(gch.region), "free cyclic cell")
     rawDealloc(gch.region, c)
   else:
@@ -767,7 +767,7 @@ proc collectCycles(gch: var TGcHeap) =
       gcAssert isAllocatedPtr(gch.region, c), "addBackStackRoots"
       gcAssert c.refcount >=% rcIncrement, "addBackStackRoots: dead cell"
       if canBeCycleRoot(c):
-        #if c notin gch.cycleRoots: 
+        #if c notin gch.cycleRoots:
         inc cycleRootsLen
         incl(gch.cycleRoots, c)
       gcAssert c.typ != nil, "addBackStackRoots 2"
@@ -794,12 +794,12 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
         add(gch.decStack, cell)
   sysAssert(allocInv(gch.region), "gcMark end")
 
-proc markThreadStacks(gch: var TGcHeap) = 
+proc markThreadStacks(gch: var TGcHeap) =
   when hasThreadSupport and hasSharedHeap:
     {.error: "not fully implemented".}
     var it = threadList
     while it != nil:
-      # mark registers: 
+      # mark registers:
       for i in 0 .. high(it.registers): gcMark(gch, it.registers[i])
       var sp = cast[TAddress](it.stackBottom)
       var max = cast[TAddress](it.stackTop)
@@ -933,7 +933,7 @@ else:
       while sp <=% max:
         gcMark(gch, cast[PPointer](sp)[])
         sp = sp +% sizeof(pointer)
-    
+
 proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
   forEachStackSlot(gch, gcMark)
 
@@ -946,13 +946,13 @@ when useMarkForDebug or useBackupGc:
 # ----------------------------------------------------------------------------
 
 proc collectZCT(gch: var TGcHeap): bool =
-  # Note: Freeing may add child objects to the ZCT! So essentially we do 
-  # deep freeing, which is bad for incremental operation. In order to 
+  # Note: Freeing may add child objects to the ZCT! So essentially we do
+  # deep freeing, which is bad for incremental operation. In order to
   # avoid a deep stack, we move objects to keep the ZCT small.
   # This is performance critical!
   const workPackage = 100
   var L = addr(gch.zct.len)
-  
+
   when withRealTime:
     var steps = workPackage
     var t0: TTicks
@@ -962,15 +962,15 @@ proc collectZCT(gch: var TGcHeap): bool =
     sysAssert(isAllocatedPtr(gch.region, c), "CollectZCT: isAllocatedPtr")
     # remove from ZCT:
     gcAssert((c.refcount and ZctFlag) == ZctFlag, "collectZCT")
-    
+
     c.refcount = c.refcount and not ZctFlag
     gch.zct.d[0] = gch.zct.d[L[] - 1]
     dec(L[])
     when withRealTime: dec steps
-    if c.refcount <% rcIncrement: 
+    if c.refcount <% rcIncrement:
       # It may have a RC > 0, if it is in the hardware stack or
       # it has not been removed yet from the ZCT. This is because
-      # ``incref`` does not bother to remove the cell from the ZCT 
+      # ``incref`` does not bother to remove the cell from the ZCT
       # as this might be too slow.
       # In any case, it should be removed from the ZCT. But not
       # freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!**
@@ -983,7 +983,7 @@ proc collectZCT(gch: var TGcHeap): bool =
       # access invalid memory. This is done by prepareDealloc():
       prepareDealloc(c)
       forAllChildren(c, waZctDecRef)
-      when reallyDealloc: 
+      when reallyDealloc:
         sysAssert(allocInv(gch.region), "collectZCT: rawDealloc")
         rawDealloc(gch.region, c)
       else:
@@ -994,7 +994,7 @@ proc collectZCT(gch: var TGcHeap): bool =
         steps = workPackage
         if gch.maxPause > 0:
           let duration = getticks() - t0
-          # the GC's measuring is not accurate and needs some cleanup actions 
+          # the GC's measuring is not accurate and needs some cleanup actions
           # (stack unmarking), so subtract some short amount of time in
           # order to miss deadlines less often:
           if duration >= gch.maxPause - 50_000:
@@ -1017,7 +1017,7 @@ proc collectCTBody(gch: var TGcHeap) =
   when withRealTime:
     let t0 = getticks()
   sysAssert(allocInv(gch.region), "collectCT: begin")
-  
+
   gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
   sysAssert(gch.decStack.len == 0, "collectCT")
   prepareForInteriorPointerChecking(gch.region)
@@ -1036,7 +1036,7 @@ proc collectCTBody(gch: var TGcHeap) =
         gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
   unmarkStackAndRegisters(gch)
   sysAssert(allocInv(gch.region), "collectCT: end")
-  
+
   when withRealTime:
     let duration = getticks() - t0
     gch.stat.maxPause = max(gch.stat.maxPause, duration)
@@ -1050,8 +1050,12 @@ when useMarkForDebug or useBackupGc:
     markGlobals(gch)
 
 proc collectCT(gch: var TGcHeap) =
-  if (gch.zct.len >= ZctThreshold or (cycleGC and
-      getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and 
+  # stackMarkCosts prevents some pathological behaviour: Stack marking
+  # becomes more expensive with large stacks and large stacks mean that
+  # cells with RC=0 are more likely to be kept alive by the stack.
+  let stackMarkCosts = max(stackSize() div (16*sizeof(int)), ZctThreshold)
+  if (gch.zct.len >= stackMarkCosts or (cycleGC and
+      getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and
       gch.recGcLock == 0:
     when useMarkForDebug:
       prepareForInteriorPointerChecking(gch.region)
@@ -1070,7 +1074,7 @@ when withRealTime:
     acquire(gch)
     gch.maxPause = us.toNano
     if (gch.zct.len >= ZctThreshold or (cycleGC and
-        getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or 
+        getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or
         strongAdvice:
       collectCTBody(gch)
     release(gch)
@@ -1078,13 +1082,13 @@ when withRealTime:
   proc GC_step*(us: int, strongAdvice = false) = GC_step(gch, us, strongAdvice)
 
 when not defined(useNimRtl):
-  proc GC_disable() = 
+  proc GC_disable() =
     when hasThreadSupport and hasSharedHeap:
       discard atomicInc(gch.recGcLock, 1)
     else:
       inc(gch.recGcLock)
   proc GC_enable() =
-    if gch.recGcLock > 0: 
+    if gch.recGcLock > 0:
       when hasThreadSupport and hasSharedHeap:
         discard atomicDec(gch.recGcLock, 1)
       else:
diff --git a/todo.txt b/todo.txt
index 1d180f737..69674f019 100644
--- a/todo.txt
+++ b/todo.txt
@@ -53,7 +53,6 @@ Bugs
 - VM: Pegs do not work at compile-time
 - VM: ptr/ref T cannot work in general
 - scopes are still broken for generic instantiation!
-- compilation of niminst takes way too long. looks like a regression
 - blocks can "export" an identifier but the CCG generates {} for them ...