summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/docgen.nim2
-rw-r--r--compiler/importer.nim4
-rw-r--r--compiler/main.nim2
-rw-r--r--compiler/nimblecmd.nim2
-rw-r--r--compiler/options.nim6
-rw-r--r--compiler/rodread.nim6
-rw-r--r--compiler/suggest.nim6
-rw-r--r--compiler/transf.nim4
-rw-r--r--compiler/vmhooks.nim8
-rw-r--r--compiler/vmmarshal.nim2
-rw-r--r--examples/maximum.nim2
-rw-r--r--lib/impure/re.nim4
-rw-r--r--lib/packages/docutils/rstgen.nim23
-rw-r--r--lib/pure/asynchttpserver.nim15
-rw-r--r--lib/pure/cgi.nim2
-rw-r--r--lib/pure/collections/critbits.nim32
-rw-r--r--lib/pure/collections/intsets.nim2
-rw-r--r--lib/pure/collections/sequtils.nim296
-rw-r--r--lib/pure/collections/sets.nim11
-rw-r--r--lib/pure/collections/tables.nim155
-rw-r--r--lib/pure/hashes.nim74
-rw-r--r--lib/pure/logging.nim27
-rw-r--r--lib/pure/marshal.nim2
-rw-r--r--lib/pure/md5.nim2
-rw-r--r--lib/pure/mimetypes.nim2
-rw-r--r--lib/pure/ospaths.nim46
-rw-r--r--lib/pure/parseopt.nim (renamed from lib/deprecated/pure/parseopt.nim)0
-rw-r--r--lib/pure/scgi.nim11
-rw-r--r--lib/pure/strtabs.nim32
-rw-r--r--lib/pure/strutils.nim178
-rwxr-xr-xlib/pure/unittest.nim3
-rw-r--r--lib/pure/xmltree.nim11
-rw-r--r--lib/system.nim56
-rw-r--r--lib/system/inclrtl.nim5
-rw-r--r--lib/system/mmdisp.nim46
-rw-r--r--lib/system/threads.nim61
-rw-r--r--readme.md19
-rw-r--r--tests/actiontable/tactiontable.nim1
-rw-r--r--tests/closure/tclosure4.nim2
-rw-r--r--tests/collections/tapply.nim11
-rw-r--r--tests/collections/tmapit.nim33
-rw-r--r--tests/collections/ttables.nim6
-rw-r--r--tests/collections/ttablesref.nim6
-rw-r--r--tests/generics/tinferredgenericprocs.nim1
-rw-r--r--tests/generics/tmap_auto.nim2
-rw-r--r--tests/misc/teventemitter.nim3
-rw-r--r--tests/newconfig/tfoo.nims3
-rw-r--r--tests/overload/toverprc.nim2
-rw-r--r--tests/parser/tcommand_as_expr.nim1
-rw-r--r--tests/stdlib/tmget.nim141
-rw-r--r--tests/stdlib/tmitems.nim2
-rw-r--r--tests/stdlib/tunittest.nim2
-rw-r--r--tests/template/twrongmapit.nim2
-rw-r--r--tests/testament/backend.nim6
-rw-r--r--tests/testament/categories.nim15
-rw-r--r--tests/testament/htmlgen.nim2
-rw-r--r--tests/testament/tester.nim10
-rw-r--r--web/news.txt24
-rw-r--r--web/website.ini11
59 files changed, 1124 insertions, 321 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 4b52b1c92..8ae32492a 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -75,7 +75,7 @@ proc newDocumentor*(filename: string, config: StringTableRef): PDoc =
   ga('send', 'pageview');
 
 </script>
-    """ % [config["doc.googleAnalytics"]]
+    """ % [config.getOrDefault"doc.googleAnalytics"]
   else:
     result.analytics = ""
 
diff --git a/compiler/importer.nim b/compiler/importer.nim
index d619725db..c121059fd 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -121,7 +121,7 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
       if s.kind != skEnumField:
         if s.kind notin ExportableSymKinds:
           internalError(s.info, "importAllSymbols: " & $s.kind)
-        if exceptSet.empty or s.name.id notin exceptSet:
+        if exceptSet.isNil or s.name.id notin exceptSet:
           rawImportSymbol(c, s)
     s = nextIter(i, fromMod.tab)
 
@@ -138,7 +138,7 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
       let s = a.sym
       if s.kind == skModule:
         importAllSymbolsExcept(c, s, exceptSet)
-      elif exceptSet.empty or s.name.id notin exceptSet:
+      elif exceptSet.isNil or s.name.id notin exceptSet:
         rawImportSymbol(c, s)
   of nkExportExceptStmt:
     localError(n.info, errGenerated, "'export except' not implemented")
diff --git a/compiler/main.nim b/compiler/main.nim
index 3bb6fc343..2ee07a443 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -15,7 +15,7 @@ import
   wordrecg, sem, semdata, idents, passes, docgen, extccomp,
   cgen, jsgen, json, nversion,
   platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
-  tables, docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists
+  docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists
 
 from magicsys import systemModule, resetSysTypes
 
diff --git a/compiler/nimblecmd.nim b/compiler/nimblecmd.nim
index 9b647e67d..c6c2ab058 100644
--- a/compiler/nimblecmd.nim
+++ b/compiler/nimblecmd.nim
@@ -48,7 +48,7 @@ proc addPackage(packages: StringTableRef, p: string) =
   let name = p.substr(0, x-1)
   if x < p.len:
     let version = p.substr(x+1)
-    if packages[name] <. version:
+    if packages.getOrDefault(name) <. version:
       packages[name] = version
   else:
     packages[name] = latest
diff --git a/compiler/options.nim b/compiler/options.nim
index adb340fea..98224a11d 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -86,7 +86,7 @@ type                          # please make sure we have under 32 options
     gcNone, gcBoehm, gcGo, gcMarkAndSweep, gcRefc, gcV2, gcGenerational
 
   IdeCmd* = enum
-    ideNone, ideSug, ideCon, ideDef, ideUse
+    ideNone, ideSug, ideCon, ideDef, ideUse, ideDus
 
 var
   gIdeCmd*: IdeCmd
@@ -173,7 +173,7 @@ proc existsConfigVar*(key: string): bool =
   result = hasKey(gConfigVars, key)
 
 proc getConfigVar*(key: string): string =
-  result = gConfigVars[key]
+  result = gConfigVars.getOrDefault key
 
 proc setConfigVar*(key, val: string) =
   gConfigVars[key] = val
@@ -421,6 +421,7 @@ proc parseIdeCmd*(s: string): IdeCmd =
   of "con": ideCon
   of "def": ideDef
   of "use": ideUse
+  of "dus": ideDus
   else: ideNone
 
 proc `$`*(c: IdeCmd): string =
@@ -429,4 +430,5 @@ proc `$`*(c: IdeCmd): string =
   of ideCon: "con"
   of ideDef: "def"
   of ideUse: "use"
+  of ideDus: "dus"
   of ideNone: "none"
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index e4530c2cc..2a85c8975 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -372,7 +372,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
   else:
     internalError(info, "decodeSym: no ident")
   #echo "decoding: {", ident.s
-  result = r.syms[id]
+  result = r.syms.getOrDefault(id)
   if result == nil:
     new(result)
     result.id = id
@@ -491,7 +491,7 @@ proc processCompilerProcs(r: PRodReader, module: PSym) =
     inc(r.pos)
     var key = decodeVInt(r.s, r.pos)
     inc(r.pos)                # #10
-    var s = r.syms[key]
+    var s = r.syms.getOrDefault(key)
     if s == nil:
       s = newStub(r, w, key)
       s.owner = module
@@ -737,7 +737,7 @@ proc getReader(moduleId: int): PRodReader =
   return nil
 
 proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
-  result = r.syms[id]
+  result = r.syms.getOrDefault(id)
   if result == nil:
     # load the symbol:
     var d = iiTableGet(r.index.tab, id)
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index ed21aa4ea..18d723315 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -309,6 +309,10 @@ proc suggestSym*(info: TLineInfo; s: PSym) {.inline.} =
     findUsages(info, s)
   elif gIdeCmd == ideDef:
     findDefinition(info, s)
+  elif gIdeCmd == ideDus and s != nil:
+    if isTracked(info, s.name.s.len):
+      suggestResult(symToSuggest(s, isLocal=false, $ideDef))
+    findUsages(info, s)
 
 proc markUsed(info: TLineInfo; s: PSym) =
   incl(s.flags, sfUsed)
@@ -366,7 +370,7 @@ proc suggestExpr*(c: PContext, node: PNode) =
       suggestCall(c, a, n, outputs)
 
   dec(c.compilesContextId)
-  if outputs > 0 and gIdeCmd != ideUse: suggestQuit()
+  if outputs > 0 and gIdeCmd notin {ideUse, ideDus}: suggestQuit()
 
 proc suggestStmt*(c: PContext, n: PNode) =
   suggestExpr(c, n)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 0ea9f7d80..92319ac19 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -825,11 +825,13 @@ proc flattenStmts(n: PNode) =
   var goOn = true
   while goOn:
     goOn = false
-    for i in 0..<n.len:
+    var i = 0
+    while i < n.len:
       let it = n[i]
       if it.kind in {nkStmtList, nkStmtListExpr}:
         n.sons[i..i] = it.sons[0..<it.len]
         goOn = true
+      inc i
 
 proc liftDeferAux(n: PNode) =
   if n.kind in {nkStmtList, nkStmtListExpr}:
diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim
index 5dd27feda..576b0565f 100644
--- a/compiler/vmhooks.nim
+++ b/compiler/vmhooks.nim
@@ -30,6 +30,14 @@ proc setResult*(a: VmArgs; v: string) =
   s[a.ra].node = newNode(nkStrLit)
   s[a.ra].node.strVal = v
 
+proc setResult*(a: VmArgs; n: PNode) =
+  var s: seq[TFullReg]
+  move(s, cast[seq[TFullReg]](a.slots))
+  if s[a.ra].kind != rkNode:
+    myreset(s[a.ra])
+    s[a.ra].kind = rkNode
+  s[a.ra].node = n
+
 proc setResult*(a: VmArgs; v: seq[string]) =
   var s: seq[TFullReg]
   move(s, cast[seq[TFullReg]](a.slots))
diff --git a/compiler/vmmarshal.nim b/compiler/vmmarshal.nim
index 1670dd4c4..c08c5d249 100644
--- a/compiler/vmmarshal.nim
+++ b/compiler/vmmarshal.nim
@@ -239,7 +239,7 @@ proc loadAny(p: var JsonParser, t: PType,
       result = newNode(nkNilLit)
       next(p)
     of jsonInt:
-      result = tab[p.getInt]
+      result = tab.getOrDefault(p.getInt)
       if result.isNil:
         raiseParseErr(p, "cannot load object with address " & $p.getInt)
       next(p)
diff --git a/examples/maximum.nim b/examples/maximum.nim
index aa3fe375a..6552a8144 100644
--- a/examples/maximum.nim
+++ b/examples/maximum.nim
@@ -1,6 +1,6 @@
 # Test high level features
 
-import strutils
+import strutils, sequtils
 
 echo "Give a list of numbers (separated by spaces): "
 stdin.readLine.split.map(parseInt).max.`$`.echo(" is the maximum!")
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index 30081bb19..60bb6c77f 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -28,6 +28,8 @@
 import
   pcre, strutils, rtarrays
 
+{.deprecated.}
+
 const
   MaxSubpatterns* = 20
     ## defines the maximum number of subpatterns that can be captured.
@@ -46,7 +48,7 @@ type
     h: ptr Pcre
     e: ptr ExtraData
 
-  Regex* {.deprecated.} = ref RegexDesc ## a compiled regular expression
+  Regex* = ref RegexDesc ## a compiled regular expression
 
   RegexError* = object of ValueError
     ## is raised if the pattern is no valid regular expression.
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index 83e1b8b9f..4a0304a7c 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -139,7 +139,7 @@ proc initRstGenerator*(g: var RstGenerator, target: OutputTarget,
   g.seenIndexTerms = initTable[string, int]()
   g.msgHandler = msgHandler
 
-  let s = config["split.item.toc"]
+  let s = config.getOrDefault"split.item.toc"
   if s != "": g.splitAfter = parseInt(s)
   for i in low(g.meta)..high(g.meta): g.meta[i] = ""
 
@@ -341,10 +341,10 @@ proc renderIndexTerm*(d: PDoc, n: PRstNode, result: var string) =
   ## previously appeared to give a different identifier value for each.
   let refname = n.rstnodeToRefname
   if d.seenIndexTerms.hasKey(refname):
-    d.seenIndexTerms[refname] = d.seenIndexTerms[refname] + 1
+    d.seenIndexTerms[refname] = d.seenIndexTerms.getOrDefault(refname) + 1
   else:
     d.seenIndexTerms[refname] = 1
-  let id = refname & '_' & $d.seenIndexTerms[refname]
+  let id = refname & '_' & $d.seenIndexTerms.getOrDefault(refname)
 
   var term = ""
   renderAux(d, n, term)
@@ -518,7 +518,7 @@ proc generateDocumentationIndex(docs: IndexedDocs): string =
   sort(titles, cmp)
 
   for title in titles:
-    let tocList = generateDocumentationTOC(docs[title])
+    let tocList = generateDocumentationTOC(docs.getOrDefault(title))
     result.add("<ul><li><a href=\"" &
       title.link & "\">" & title.keyword & "</a>\n" & tocList & "</ul>\n")
 
@@ -786,7 +786,8 @@ proc renderSmiley(d: PDoc, n: PRstNode, result: var string) =
   dispA(d.target, result,
     """<img src="$1" width="15"
         height="17" hspace="2" vspace="2" class="smiley" />""",
-    "\\includegraphics{$1}", [d.config["doc.smiley_format"] % n.text])
+    "\\includegraphics{$1}",
+    [d.config.getOrDefault"doc.smiley_format" % n.text])
 
 proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) =
   ## Parses useful fields which can appear before a code block.
@@ -844,8 +845,8 @@ proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string):
   inc d.listingCounter
   let id = $d.listingCounter
   if not params.numberLines:
-    result = (d.config["doc.listing_start"] % id,
-              d.config["doc.listing_end"] % id)
+    result = (d.config.getOrDefault"doc.listing_start" % id,
+              d.config.getOrDefault"doc.listing_end" % id)
     return
 
   var codeLines = 1 + code.strip.countLines
@@ -856,9 +857,11 @@ proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string):
     result.beginTable.add($line & "\n")
     line.inc
     codeLines.dec
-  result.beginTable.add("</pre></td><td>" & (d.config["doc.listing_start"] % id))
-  result.endTable = (d.config["doc.listing_end"] % id) &
-      "</td></tr></tbody></table>" & (d.config["doc.listing_button"] % id)
+  result.beginTable.add("</pre></td><td>" & (
+      d.config.getOrDefault"doc.listing_start" % id))
+  result.endTable = (d.config.getOrDefault"doc.listing_end" % id) &
+      "</td></tr></tbody></table>" & (
+      d.config.getOrDefault"doc.listing_button" % id)
 
 proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
   ## Renders a code block, appending it to `result`.
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 5d74896bf..590b52c1a 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -212,7 +212,7 @@ proc processClient(client: AsyncSocket, address: string,
     if request.reqMethod == "post":
       # Check for Expect header
       if request.headers.hasKey("Expect"):
-        if request.headers["Expect"].toLower == "100-continue":
+        if request.headers.getOrDefault("Expect").toLower == "100-continue":
           await client.sendStatus("100 Continue")
         else:
           await client.sendStatus("417 Expectation Failed")
@@ -221,7 +221,8 @@ proc processClient(client: AsyncSocket, address: string,
       # - Check for Content-length header
       if request.headers.hasKey("Content-Length"):
         var contentLength = 0
-        if parseInt(request.headers["Content-Length"], contentLength) == 0:
+        if parseInt(request.headers.getOrDefault("Content-Length"),
+                    contentLength) == 0:
           await request.respond(Http400, "Bad Request. Invalid Content-Length.")
           continue
         else:
@@ -232,16 +233,18 @@ proc processClient(client: AsyncSocket, address: string,
         continue
 
     case request.reqMethod
-    of "get", "post", "head", "put", "delete", "trace", "options", "connect", "patch":
+    of "get", "post", "head", "put", "delete", "trace", "options",
+       "connect", "patch":
       await callback(request)
     else:
-      await request.respond(Http400, "Invalid request method. Got: " & request.reqMethod)
+      await request.respond(Http400, "Invalid request method. Got: " &
+        request.reqMethod)
 
     # Persistent connections
     if (request.protocol == HttpVer11 and
-        request.headers["connection"].normalize != "close") or
+        request.headers.getOrDefault("connection").normalize != "close") or
        (request.protocol == HttpVer10 and
-        request.headers["connection"].normalize == "keep-alive"):
+        request.headers.getOrDefault("connection").normalize == "keep-alive"):
       # In HTTP 1.1 we assume that connection is persistent. Unless connection
       # header states otherwise.
       # In HTTP 1.0 we assume that the connection should not be persistent.
diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim
index cfd768f91..200a4adf1 100644
--- a/lib/pure/cgi.nim
+++ b/lib/pure/cgi.nim
@@ -387,7 +387,7 @@ var
 proc getCookie*(name: string): TaintedString =
   ## Gets a cookie. If no cookie of `name` exists, "" is returned.
   if gcookies == nil: gcookies = parseCookies(getHttpCookie())
-  result = TaintedString(gcookies[name])
+  result = TaintedString(gcookies.getOrDefault(name))
 
 proc existsCookie*(name: string): bool =
   ## Checks if a cookie of `name` exists.
diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim
index 09b20fd45..8c507d4fb 100644
--- a/lib/pure/collections/critbits.nim
+++ b/lib/pure/collections/critbits.nim
@@ -11,6 +11,8 @@
 ## container for a set or a mapping of strings. Based on the excellent paper
 ## by Adam Langley.
 
+include "system/inclrtl"
+
 type
   NodeObj[T] = object {.acyclic.}
     byte: int ## byte index of the difference
@@ -140,20 +142,32 @@ proc `[]=`*[T](c: var CritBitTree[T], key: string, val: T) =
   var n = rawInsert(c, key)
   n.val = val
 
-proc `[]`*[T](c: CritBitTree[T], key: string): T {.inline.} =
-  ## retrieves the value at ``c[key]``. If `key` is not in `t`,
-  ## default empty value for the type `B` is returned
-  ## and no exception is raised. One can check with ``hasKey`` whether the key
-  ## exists.
+template get[T](c: CritBitTree[T], key: string): T {.immediate.} =
   let n = rawGet(c, key)
   if n != nil: result = n.val
+  else:
+    when compiles($key):
+      raise newException(KeyError, "key not found: " & $key)
+    else:
+      raise newException(KeyError, "key not found")
 
-proc mget*[T](c: var CritBitTree[T], key: string): var T {.inline.} =
+proc `[]`*[T](c: CritBitTree[T], key: string): T {.inline, deprecatedGet.} =
+  ## retrieves the value at ``c[key]``. If `key` is not in `t`, the
+  ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
+  ## the key exists.
+  get(c, key)
+
+proc `[]`*[T](c: var CritBitTree[T], key: string): var T {.inline,
+  deprecatedGet.} =
   ## retrieves the value at ``c[key]``. The value can be modified.
   ## If `key` is not in `t`, the ``KeyError`` exception is raised.
-  let n = rawGet(c, key)
-  if n != nil: result = n.val
-  else: raise newException(KeyError, "key not found: " & $key)
+  get(c, key)
+
+proc mget*[T](c: var CritBitTree[T], key: string): var T {.inline, deprecated.} =
+  ## retrieves the value at ``c[key]``. The value can be modified.
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  ## Use ```[]``` instead.
+  get(c, key)
 
 proc excl*[T](c: var CritBitTree[T], key: string) =
   ## removes `key` (and its associated value) from the set `c`.
diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim
index 38bc9d462..603a4b595 100644
--- a/lib/pure/collections/intsets.nim
+++ b/lib/pure/collections/intsets.nim
@@ -138,6 +138,8 @@ proc initIntSet*: IntSet =
   result.counter = 0
   result.head = nil
 
+proc isNil*(x: IntSet): bool {.inline.} = x.head.isNil
+
 proc assign*(dest: var IntSet, src: IntSet) =
   ## copies `src` to `dest`. `dest` does not need to be initialized by
   ## `initIntSet`.
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index e6ea19a6b..71babe93b 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -47,7 +47,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
       result[i] = itm
       inc(i)
 
-proc repeat*[T](s: seq[T], n: Natural): seq[T] =
+proc cycle*[T](s: seq[T], n: Natural): seq[T] =
   ## Returns a new sequence with the items of `s` repeated `n` times.
   ##
   ## Example:
@@ -56,15 +56,29 @@ proc repeat*[T](s: seq[T], n: Natural): seq[T] =
   ##
   ##   let
   ##     s = @[1, 2, 3]
-  ##     total = s.repeat(3)
+  ##     total = s.cycle(3)
   ##   assert total == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
   result = newSeq[T](n * s.len)
   var o = 0
-  for x in 1..n:
+  for x in 0..<n:
     for e in s:
       result[o] = e
       inc o
 
+proc repeat*[T](x: T, n: Natural): seq[T] =
+  ## Returns a new sequence with the item `x` repeated `n` times.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:
+  ##
+  ##   let
+  ##     total = repeat(5, 3)
+  ##   assert total == @[5, 5, 5]
+  result = newSeq[T](n)
+  for i in 0..<n:
+    result[i] = x
+
 proc deduplicate*[T](seq1: seq[T]): seq[T] =
   ## Returns a new sequence without duplicates.
   ##
@@ -169,6 +183,77 @@ proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
       first = last
 
 
+proc map*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}):
+                                                            seq[S]{.inline.} =
+  ## Returns a new sequence with the results of `op` applied to every item in
+  ## `data`.
+  ##
+  ## Since the input is not modified you can use this version of ``map`` to
+  ## transform the type of the elements in the input sequence. Example:
+  ##
+  ## .. code-block:: nim
+  ##   let
+  ##     a = @[1, 2, 3, 4]
+  ##     b = map(a, proc(x: int): string = $x)
+  ##   assert b == @["1", "2", "3", "4"]
+  newSeq(result, data.len)
+  for i in 0..data.len-1: result[i] = op(data[i])
+
+proc map*[T](data: var openArray[T], op: proc (x: var T) {.closure.})
+                                                              {.deprecated.} =
+  ## Applies `op` to every item in `data` modifying it directly.
+  ##
+  ## Note that this version of ``map`` requires your input and output types to
+  ## be the same, since they are modified in-place. Example:
+  ##
+  ## .. code-block:: nim
+  ##   var a = @["1", "2", "3", "4"]
+  ##   echo repr(a)
+  ##   # --> ["1", "2", "3", "4"]
+  ##   map(a, proc(x: var string) = x &= "42")
+  ##   echo repr(a)
+  ##   # --> ["142", "242", "342", "442"]
+  ## **Deprecated since version 0.12.0:** Use the ``apply`` proc instead.
+  for i in 0..data.len-1: op(data[i])
+
+proc apply*[T](data: var seq[T], op: proc (x: var T) {.closure.})
+                                                              {.inline.} =
+  ## Applies `op` to every item in `data` modifying it directly.
+  ##
+  ## Note that this requires your input and output types to
+  ## be the same, since they are modified in-place.
+  ## The parameter function takes a ``var T`` type parameter.
+  ## Example:
+  ##
+  ## .. code-block:: nim
+  ##   var a = @["1", "2", "3", "4"]
+  ##   echo repr(a)
+  ##   # --> ["1", "2", "3", "4"]
+  ##   map(a, proc(x: var string) = x &= "42")
+  ##   echo repr(a)
+  ##   # --> ["142", "242", "342", "442"]
+  ##
+  for i in 0..data.len-1: op(data[i])
+
+proc apply*[T](data: var seq[T], op: proc (x: T): T {.closure.})
+                                                              {.inline.} =
+  ## Applies `op` to every item in `data` modifying it directly.
+  ##
+  ## Note that this requires your input and output types to
+  ## be the same, since they are modified in-place.
+  ## The parameter function takes and returns a ``T`` type variable.
+  ## Example:
+  ##
+  ## .. code-block:: nim
+  ##   var a = @["1", "2", "3", "4"]
+  ##   echo repr(a)
+  ##   # --> ["1", "2", "3", "4"]
+  ##   map(a, proc(x: string): string = x & "42")
+  ##   echo repr(a)
+  ##   # --> ["142", "242", "342", "442"]
+  ##
+  for i in 0..data.len-1: data[i] = op(data[i])
+
 
 iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T =
   ## Iterates through a sequence and yields every item that fulfills the
@@ -181,11 +266,12 @@ iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T =
   ##   for n in filter(numbers, proc (x: int): bool = x mod 2 == 0):
   ##     echo($n)
   ##   # echoes 4, 8, 4 in separate lines
-  for i in countup(0, len(seq1)-1):
-    var item = seq1[i]
-    if pred(item): yield seq1[i]
+  for i in 0..<seq1.len:
+    if pred(seq1[i]):
+      yield seq1[i]
 
-proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] =
+proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T]
+                                                                  {.inline.} =
   ## Returns a new sequence with all the items that fulfilled the predicate.
   ##
   ## Example:
@@ -197,9 +283,13 @@ proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] =
   ##     f2 = filter(colors) do (x: string) -> bool : x.len > 5
   ##   assert f1 == @["red", "black"]
   ##   assert f2 == @["yellow"]
-  accumulateResult(filter(seq1, pred))
+  result = newSeq[T]()
+  for i in 0..<seq1.len:
+    if pred(seq1[i]):
+      result.add(seq1[i])
 
-proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.}) =
+proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.})
+                                                                {.inline.} =
   ## Keeps the items in the passed sequence if they fulfilled the predicate.
   ## Same as the ``filter`` proc, but modifies the sequence directly.
   ##
@@ -213,7 +303,7 @@ proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.}) =
   for i in 0 .. <len(seq1):
     if pred(seq1[i]):
       if pos != i:
-        seq1[pos] = seq1[i]
+        shallowCopy(seq1[pos], seq1[i])
       inc(pos)
   setLen(seq1, pos)
 
@@ -268,7 +358,7 @@ proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) =
     inc(j)
 
 
-template filterIt*(seq1, pred: expr): expr {.immediate.} =
+template filterIt*(seq1, pred: expr): expr =
   ## Returns a new sequence with all the items that fulfilled the predicate.
   ##
   ## Unlike the `proc` version, the predicate needs to be an expression using
@@ -282,12 +372,12 @@ template filterIt*(seq1, pred: expr): expr {.immediate.} =
   ##      notAcceptable = filterIt(temperatures, it > 50 or it < -10)
   ##    assert acceptable == @[-2.0, 24.5, 44.31]
   ##    assert notAcceptable == @[-272.15, 99.9, -113.44]
-  var result {.gensym.}: type(seq1) = @[]
+  var result {.gensym.} = newSeq[type(seq1[0])]()
   for it {.inject.} in items(seq1):
     if pred: result.add(it)
   result
 
-template keepItIf*(varSeq, pred: expr) =
+template keepItIf*(varSeq: seq, pred: expr) =
   ## Convenience template around the ``keepIf`` proc to reduce typing.
   ##
   ## Unlike the `proc` version, the predicate needs to be an expression using
@@ -303,10 +393,71 @@ template keepItIf*(varSeq, pred: expr) =
     let it {.inject.} = varSeq[i]
     if pred:
       if pos != i:
-        varSeq[pos] = varSeq[i]
+        shallowCopy(varSeq[pos], varSeq[i])
       inc(pos)
   setLen(varSeq, pos)
 
+proc all*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): bool =
+  ## Iterates through a sequence and checks if every item fulfills the
+  ## predicate.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   let numbers = @[1, 4, 5, 8, 9, 7, 4]
+  ##   assert all(numbers, proc (x: int): bool = return x < 10) == true
+  ##   assert all(numbers, proc (x: int): bool = return x < 9) == false
+  for i in seq1:
+    if not pred(i):
+      return false
+  return true
+
+template allIt*(seq1, pred: expr): bool {.immediate.} =
+  ## Checks if every item fulfills the predicate.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   let numbers = @[1, 4, 5, 8, 9, 7, 4]
+  ##   assert allIt(numbers, it < 10) == true
+  ##   assert allIt(numbers, it < 9) == false
+  var result {.gensym.} = true
+  for it {.inject.} in items(seq1):
+    if not pred:
+      result = false
+      break
+  result
+
+proc any*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): bool =
+  ## Iterates through a sequence and checks if some item fulfills the
+  ## predicate.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   let numbers = @[1, 4, 5, 8, 9, 7, 4]
+  ##   assert any(numbers, proc (x: int): bool = return x > 8) == true
+  ##   assert any(numbers, proc (x: int): bool = return x > 9) == false
+  for i in seq1:
+    if pred(i):
+      return true
+  return false
+
+template anyIt*(seq1, pred: expr): bool {.immediate.} =
+  ## Checks if some item fulfills the predicate.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   let numbers = @[1, 4, 5, 8, 9, 7, 4]
+  ##   assert anyIt(numbers, it > 8) == true
+  ##   assert anyIt(numbers, it > 9) == false
+  var result {.gensym.} = false
+  for it {.inject.} in items(seq1):
+    if pred:
+      result = true
+      break
+  result
 
 template toSeq*(iter: expr): expr {.immediate.} =
   ## Transforms any iterator into a sequence.
@@ -320,14 +471,19 @@ template toSeq*(iter: expr): expr {.immediate.} =
   ##       if x mod 2 == 1:
   ##         result = true)
   ##   assert odd_numbers == @[1, 3, 5, 7, 9]
-  ##
-  ## **Note**: Since this is an immediate macro, you cannot always invoke this
-  ## as ``x.toSeq``, depending on the ``x``.
-  ## See `this <manual.html#limitations-of-the-method-call-syntax>`_
-  ## for an explanation.
-  var result {.gensym.}: seq[type(iter)] = @[]
-  for x in iter: add(result, x)
-  result
+  
+  when compiles(iter.len):
+    var i = 0
+    var result = newSeq[type(iter)](iter.len)
+    for x in iter:
+      result[i] = x
+      inc i
+    result
+  else:
+    var result: seq[type(iter)] = @[]
+    for x in iter:
+      result.add(x)
+    result
 
 template foldl*(sequence, operation: expr): expr =
   ## Template to fold a sequence from left to right, returning the accumulation.
@@ -358,7 +514,7 @@ template foldl*(sequence, operation: expr): expr =
   assert sequence.len > 0, "Can't fold empty sequences"
   var result {.gensym.}: type(sequence[0])
   result = sequence[0]
-  for i in countup(1, sequence.len - 1):
+  for i in 1..<sequence.len:
     let
       a {.inject.} = result
       b {.inject.} = sequence[i]
@@ -401,7 +557,7 @@ template foldr*(sequence, operation: expr): expr =
     result = operation
   result
 
-template mapIt*(seq1, typ, op: expr): expr =
+template mapIt*(seq1, typ, op: expr): expr {.deprecated.}=
   ## Convenience template around the ``map`` proc to reduce typing.
   ##
   ## The template injects the ``it`` variable which you can use directly in an
@@ -414,13 +570,45 @@ template mapIt*(seq1, typ, op: expr): expr =
   ##     nums = @[1, 2, 3, 4]
   ##     strings = nums.mapIt(string, $(4 * it))
   ##   assert strings == @["4", "8", "12", "16"]
+  ## **Deprecated since version 0.12.0:** Use the ``mapIt(seq1, op)``
+  ##   template instead.
   var result {.gensym.}: seq[typ] = @[]
   for it {.inject.} in items(seq1):
     result.add(op)
   result
 
-template mapIt*(varSeq, op: expr) =
-  ## Convenience template around the mutable ``map`` proc to reduce typing.
+
+template mapIt*(seq1, op: expr): expr =
+  ## Convenience template around the ``map`` proc to reduce typing.
+  ##
+  ## The template injects the ``it`` variable which you can use directly in an
+  ## expression. Example:
+  ##
+  ## .. code-block::
+  ##   let
+  ##     nums = @[1, 2, 3, 4]
+  ##     strings = nums.mapIt($(4 * it))
+  ##   assert strings == @["4", "8", "12", "16"]
+  type outType = type((
+    block:
+      var it{.inject.}: type(items(seq1));
+      op))
+  var result: seq[outType]
+  when compiles(seq1.len):
+    let s = seq1
+    var i = 0
+    result = newSeq[outType](s.len)
+    for it {.inject.} in s:
+      result[i] = op
+      i += 1
+  else:
+    result = @[]
+    for it {.inject.} in seq1:
+      result.add(op)
+  result
+
+template applyIt*(varSeq, op: expr) =
+  ## Convenience template around the mutable ``apply`` proc to reduce typing.
   ##
   ## The template injects the ``it`` variable which you can use directly in an
   ## expression. The expression has to return the same type as the sequence you
@@ -428,12 +616,14 @@ template mapIt*(varSeq, op: expr) =
   ##
   ## .. code-block::
   ##   var nums = @[1, 2, 3, 4]
-  ##   nums.mapIt(it * 3)
+  ##   nums.applyIt(it * 3)
   ##   assert nums[0] + nums[3] == 15
-  for i in 0 .. <len(varSeq):
+  for i in 0 .. <varSeq.len:
     let it {.inject.} = varSeq[i]
     varSeq[i] = op
 
+
+
 template newSeqWith*(len: int, init: expr): expr =
   ## creates a new sequence, calling `init` to initialize each value. Example:
   ##
@@ -513,6 +703,38 @@ when isMainModule:
     keepItIf(candidates, it.len == 3 and it[0] == 'b')
     assert candidates == @["bar", "baz"]
 
+  block: # any
+    let
+      numbers = @[1, 4, 5, 8, 9, 7, 4]
+      len0seq : seq[int] = @[]
+    assert any(numbers, proc (x: int): bool = return x > 8) == true
+    assert any(numbers, proc (x: int): bool = return x > 9) == false
+    assert any(len0seq, proc (x: int): bool = return true) == false
+
+  block: # anyIt
+    let
+      numbers = @[1, 4, 5, 8, 9, 7, 4]
+      len0seq : seq[int] = @[]
+    assert anyIt(numbers, it > 8) == true
+    assert anyIt(numbers, it > 9) == false
+    assert anyIt(len0seq, true) == false
+
+  block: # all
+    let
+      numbers = @[1, 4, 5, 8, 9, 7, 4]
+      len0seq : seq[int] = @[]
+    assert all(numbers, proc (x: int): bool = return x < 10) == true
+    assert all(numbers, proc (x: int): bool = return x < 9) == false
+    assert all(len0seq, proc (x: int): bool = return false) == true
+
+  block: # allIt
+    let
+      numbers = @[1, 4, 5, 8, 9, 7, 4]
+      len0seq : seq[int] = @[]
+    assert allIt(numbers, it < 10) == true
+    assert allIt(numbers, it < 9) == false
+    assert allIt(len0seq, false) == true
+
   block: # toSeq test
     let
       numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
@@ -568,8 +790,8 @@ when isMainModule:
   block: # mapIt tests
     var
       nums = @[1, 2, 3, 4]
-      strings = nums.mapIt(string, $(4 * it))
-    nums.mapIt(it * 3)
+      strings = nums.mapIt($(4 * it))
+    nums.applyIt(it * 3)
     assert nums[0] + nums[3] == 15
 
   block: # distribute tests
@@ -605,15 +827,19 @@ when isMainModule:
     seq2D[0][1] = true
     doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
 
-  block: # repeat tests
+  block: # cycle tests
     let
       a = @[1, 2, 3]
       b: seq[int] = @[]
 
-    doAssert a.repeat(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
-    doAssert a.repeat(0) == @[]
-    #doAssert a.repeat(-1) == @[] # will not compile!
-    doAssert b.repeat(3) == @[]
+    doAssert a.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
+    doAssert a.cycle(0) == @[]
+    #doAssert a.cycle(-1) == @[] # will not compile!
+    doAssert b.cycle(3) == @[]
+
+  block: # repeat tests
+    assert repeat(10, 5) == @[10, 10, 10, 10, 10]
+    assert repeat(@[1,2,3], 2) == @[@[1,2,3], @[1,2,3]]
 
   when not defined(testing):
     echo "Finished doc tests"
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 3d4de8fdc..abe9cf85e 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -154,9 +154,9 @@ proc rawGetKnownHC[A](s: HashSet[A], key: A, hc: Hash): int {.inline.} =
 proc rawGet[A](s: HashSet[A], key: A, hc: var Hash): int {.inline.} =
   rawGetImpl()
 
-proc mget*[A](s: var HashSet[A], key: A): var A =
+proc `[]`*[A](s: var HashSet[A], key: A): var A =
   ## returns the element that is actually stored in 's' which has the same
-  ## value as 'key' or raises the ``EInvalidKey`` exception. This is useful
+  ## value as 'key' or raises the ``KeyError`` exception. This is useful
   ## when one overloaded 'hash' and '==' but still needs reference semantics
   ## for sharing.
   assert s.isValid, "The set needs to be initialized."
@@ -165,6 +165,13 @@ proc mget*[A](s: var HashSet[A], key: A): var A =
   if index >= 0: result = s.data[index].key
   else: raise newException(KeyError, "key not found: " & $key)
 
+proc mget*[A](s: var HashSet[A], key: A): var A {.deprecated.} =
+  ## returns the element that is actually stored in 's' which has the same
+  ## value as 'key' or raises the ``KeyError`` exception. This is useful
+  ## when one overloaded 'hash' and '==' but still needs reference semantics
+  ## for sharing. Use ```[]``` instead.
+  s[key]
+
 proc contains*[A](s: HashSet[A], key: A): bool =
   ## Returns true iff `key` is in `s`.
   ##
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index be6b755ed..329b2a1cb 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -68,6 +68,8 @@
 import
   hashes, math
 
+include "system/inclrtl"
+
 type
   KeyValuePair[A, B] = tuple[hcode: Hash, key: A, val: B]
   KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]]
@@ -96,18 +98,10 @@ proc len*[A, B](t: Table[A, B]): int =
   ## returns the number of keys in `t`.
   result = t.counter
 
-proc `[]`*[A, B](t: Table[A, B], key: A): B =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
-  ## default empty value for the type `B` is returned
-  ## and no exception is raised. One can check with ``hasKey`` whether the key
-  ## exists.
-  var hc: Hash
-  var index = rawGet(t, key, hc)
-  if index >= 0: result = t.data[index].val
-
-proc mget*[A, B](t: var Table[A, B], key: A): var B =
+template get(t, key): untyped {.immediate.} =
   ## retrieves the value at ``t[key]``. The value can be modified.
   ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  mixin rawGet
   var hc: Hash
   var index = rawGet(t, key, hc)
   if index >= 0: result = t.data[index].val
@@ -117,6 +111,31 @@ proc mget*[A, B](t: var Table[A, B], key: A): var B =
     else:
       raise newException(KeyError, "key not found")
 
+template getOrDefaultImpl(t, key): untyped {.immediate.} =
+  mixin rawGet
+  var hc: Hash
+  var index = rawGet(t, key, hc)
+  if index >= 0: result = t.data[index].val
+
+proc `[]`*[A, B](t: Table[A, B], key: A): B {.deprecatedGet.} =
+  ## retrieves the value at ``t[key]``. If `key` is not in `t`, the
+  ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
+  ## the key exists.
+  get(t, key)
+
+proc `[]`*[A, B](t: var Table[A, B], key: A): var B {.deprecatedGet.} =
+  ## retrieves the value at ``t[key]``. The value can be modified.
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  get(t, key)
+
+proc mget*[A, B](t: var Table[A, B], key: A): var B {.deprecated.} =
+  ## retrieves the value at ``t[key]``. The value can be modified.
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised. Use ```[]```
+  ## instead.
+  get(t, key)
+
+proc getOrDefault*[A, B](t: Table[A, B], key: A): B = getOrDefaultImpl(t, key)
+
 iterator allValues*[A, B](t: Table[A, B]; key: A): B =
   ## iterates over any value in the table `t` that belongs to the given `key`.
   var h: Hash = hash(key) and high(t.data)
@@ -276,17 +295,19 @@ iterator mvalues*[A, B](t: TableRef[A, B]): var B =
   for h in 0..high(t.data):
     if isFilled(t.data[h].hcode): yield t.data[h].val
 
-proc `[]`*[A, B](t: TableRef[A, B], key: A): B =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
-  ## default empty value for the type `B` is returned
-  ## and no exception is raised. One can check with ``hasKey`` whether the key
-  ## exists.
+proc `[]`*[A, B](t: TableRef[A, B], key: A): var B {.deprecatedGet.} =
+  ## retrieves the value at ``t[key]``.  If `key` is not in `t`, the
+  ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
+  ## the key exists.
   result = t[][key]
 
-proc mget*[A, B](t: TableRef[A, B], key: A): var B =
+proc mget*[A, B](t: TableRef[A, B], key: A): var B {.deprecated.} =
   ## retrieves the value at ``t[key]``. The value can be modified.
-  ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
-  t[].mget(key)
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  ## Use ```[]``` instead.
+  t[][key]
+
+proc getOrDefault*[A, B](t: TableRef[A, B], key: A): B = getOrDefault(t[], key)
 
 proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
   ## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
@@ -399,22 +420,26 @@ proc rawGetDeep[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int {.inline
 proc rawGet[A, B](t: OrderedTable[A, B], key: A, hc: var Hash): int =
   rawGetImpl()
 
-proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
-  ## default empty value for the type `B` is returned
-  ## and no exception is raised. One can check with ``hasKey`` whether the key
-  ## exists.
-  var hc: Hash
-  var index = rawGet(t, key, hc)
-  if index >= 0: result = t.data[index].val
+proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B {.deprecatedGet.} =
+  ## retrieves the value at ``t[key]``. If `key` is not in `t`, the
+  ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
+  ## the key exists.
+  get(t, key)
 
-proc mget*[A, B](t: var OrderedTable[A, B], key: A): var B =
+proc `[]`*[A, B](t: var OrderedTable[A, B], key: A): var B{.deprecatedGet.} =
   ## retrieves the value at ``t[key]``. The value can be modified.
-  ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
-  var hc: Hash
-  var index = rawGet(t, key, hc)
-  if index >= 0: result = t.data[index].val
-  else: raise newException(KeyError, "key not found: " & $key)
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  get(t, key)
+
+proc mget*[A, B](t: var OrderedTable[A, B], key: A): var B {.deprecated.} =
+  ## retrieves the value at ``t[key]``. The value can be modified.
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  ## Use ```[]``` instead.
+  get(t, key)
+
+proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A): B =
+  getOrDefaultImpl(t, key)
+
 
 proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
   ## returns true iff `key` is in the table `t`.
@@ -572,17 +597,20 @@ iterator mvalues*[A, B](t: OrderedTableRef[A, B]): var B =
   forAllOrderedPairs:
     yield t.data[h].val
 
-proc `[]`*[A, B](t: OrderedTableRef[A, B], key: A): B =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
-  ## default empty value for the type `B` is returned
-  ## and no exception is raised. One can check with ``hasKey`` whether the key
-  ## exists.
+proc `[]`*[A, B](t: OrderedTableRef[A, B], key: A): var B =
+  ## retrieves the value at ``t[key]``. If `key` is not in `t`, the
+  ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
+  ## the key exists.
   result = t[][key]
 
-proc mget*[A, B](t: OrderedTableRef[A, B], key: A): var B =
+proc mget*[A, B](t: OrderedTableRef[A, B], key: A): var B {.deprecated.} =
   ## retrieves the value at ``t[key]``. The value can be modified.
-  ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
-  result = t[].mget(key)
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  ## Use ```[]``` instead.
+  result = t[][key]
+
+proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A): B =
+  getOrDefault(t[], key)
 
 proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
   ## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
@@ -683,19 +711,35 @@ proc rawGet[A](t: CountTable[A], key: A): int =
     h = nextTry(h, high(t.data))
   result = -1 - h                   # < 0 => MISSING; insert idx = -1 - result
 
-proc `[]`*[A](t: CountTable[A], key: A): int =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
-  ## 0 is returned. One can check with ``hasKey`` whether the key
-  ## exists.
+template ctget(t, key: untyped): untyped {.immediate.} =
   var index = rawGet(t, key)
   if index >= 0: result = t.data[index].val
+  else:
+    when compiles($key):
+      raise newException(KeyError, "key not found: " & $key)
+    else:
+      raise newException(KeyError, "key not found")
+
+proc `[]`*[A](t: CountTable[A], key: A): int {.deprecatedGet.} =
+  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
+  ## the ``KeyError`` exception is raised. One can check with ``hasKey``
+  ## whether the key exists.
+  ctget(t, key)
 
-proc mget*[A](t: var CountTable[A], key: A): var int =
+proc `[]`*[A](t: var CountTable[A], key: A): var int {.deprecatedGet.} =
   ## retrieves the value at ``t[key]``. The value can be modified.
-  ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  ctget(t, key)
+
+proc mget*[A](t: var CountTable[A], key: A): var int {.deprecated.} =
+  ## retrieves the value at ``t[key]``. The value can be modified.
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  ## Use ```[]``` instead.
+  ctget(t, key)
+
+proc getOrDefault*[A](t: CountTable[A], key: A): int =
   var index = rawGet(t, key)
   if index >= 0: result = t.data[index].val
-  else: raise newException(KeyError, "key not found: " & $key)
 
 proc hasKey*[A](t: CountTable[A], key: A): bool =
   ## returns true iff `key` is in the table `t`.
@@ -831,16 +875,19 @@ iterator mvalues*[A](t: CountTableRef[A]): var int =
   for h in 0..high(t.data):
     if t.data[h].val != 0: yield t.data[h].val
 
-proc `[]`*[A](t: CountTableRef[A], key: A): int =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
-  ## 0 is returned. One can check with ``hasKey`` whether the key
-  ## exists.
+proc `[]`*[A](t: CountTableRef[A], key: A): var int {.deprecatedGet.} =
+  ## retrieves the value at ``t[key]``. The value can be modified.
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
   result = t[][key]
 
-proc mget*[A](t: CountTableRef[A], key: A): var int =
+proc mget*[A](t: CountTableRef[A], key: A): var int {.deprecated.} =
   ## retrieves the value at ``t[key]``. The value can be modified.
-  ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
-  result = t[].mget(key)
+  ## If `key` is not in `t`, the ``KeyError`` exception is raised.
+  ## Use ```[]``` instead.
+  result = t[][key]
+
+proc getOrDefault*[A](t: CountTableRef[A], key: A): int =
+  getOrDefaultImpl(t, key)
 
 proc hasKey*[A](t: CountTableRef[A], key: A): bool =
   ## returns true iff `key` is in the table `t`.
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 61c16129b..11af81149 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -8,9 +8,10 @@
 #
 
 ## This module implements efficient computations of hash values for diverse
-## Nim types. All the procs are based on these two building blocks: the `!&
-## proc <#!&>`_ used to start or mix a hash value, and the `!$ proc <#!$>`_
-## used to *finish* the hash value.  If you want to implement hash procs for
+## Nim types. All the procs are based on these two building blocks:
+## - `!& proc <#!&>`_ used to start or mix a hash value, and
+## - `!$ proc <#!$>`_ used to *finish* the hash value.
+## If you want to implement hash procs for
 ## your custom types you will end up writing the following kind of skeleton of
 ## code:
 ##
@@ -108,7 +109,7 @@ proc hash*(x: int): Hash {.inline.} =
   result = x
 
 proc hash*(x: int64): Hash {.inline.} =
-  ## efficient hashing of integers
+  ## efficient hashing of int64 integers
   result = toU32(x)
 
 proc hash*(x: char): Hash {.inline.} =
@@ -126,6 +127,16 @@ proc hash*(x: string): Hash =
     h = h !& ord(x[i])
   result = !$h
 
+proc hash*(sBuf: string, sPos, ePos: int): Hash =
+  ## efficient hashing of a string buffer, from starting
+  ## position `sPos` to ending position `ePos`
+  ##
+  ## ``hash(myStr, 0, myStr.high)`` is equivalent to ``hash(myStr)``
+  var h: Hash = 0
+  for i in sPos..ePos:
+    h = h !& ord(sBuf[i])
+  result = !$h
+
 proc hashIgnoreStyle*(x: string): Hash =
   ## efficient hashing of strings; style is ignored
   var h: Hash = 0
@@ -145,6 +156,27 @@ proc hashIgnoreStyle*(x: string): Hash =
 
   result = !$h
 
+proc hashIgnoreStyle*(sBuf: string, sPos, ePos: int): Hash =
+  ## efficient hashing of a string buffer, from starting
+  ## position `sPos` to ending position `ePos`; style is ignored
+  ##
+  ## ``hashIgnoreStyle(myBuf, 0, myBuf.high)`` is equivalent
+  ## to ``hashIgnoreStyle(myBuf)``
+  var h: Hash = 0
+  var i = sPos
+  while i <= ePos:
+    var c = sBuf[i]
+    if c == '_':
+      inc(i)
+    elif isMagicIdentSeparatorRune(cstring(sBuf), i):
+      inc(i, magicIdentSeparatorRuneByteWidth)
+    else:
+      if c in {'A'..'Z'}:
+        c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
+      h = h !& ord(c)
+      inc(i)
+  result = !$h
+
 proc hashIgnoreCase*(x: string): Hash =
   ## efficient hashing of strings; case is ignored
   var h: Hash = 0
@@ -155,7 +187,22 @@ proc hashIgnoreCase*(x: string): Hash =
     h = h !& ord(c)
   result = !$h
 
+proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
+  ## efficient hashing of a string buffer, from starting
+  ## position `sPos` to ending position `ePos`; case is ignored
+  ##
+  ## ``hashIgnoreCase(myBuf, 0, myBuf.high)`` is equivalent
+  ## to ``hashIgnoreCase(myBuf)``
+  var h: Hash = 0
+  for i in sPos..ePos:
+    var c = sBuf[i]
+    if c in {'A'..'Z'}:
+      c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
+    h = h !& ord(c)
+  result = !$h
+
 proc hash*(x: float): Hash {.inline.} =
+  ## efficient hashing of floats.
   var y = x + 1.0
   result = cast[ptr Hash](addr(y))[]
 
@@ -173,10 +220,29 @@ proc hash*[T: tuple](x: T): Hash =
   result = !$result
 
 proc hash*[A](x: openArray[A]): Hash =
+  ## efficient hashing of arrays and sequences.
   for it in items(x): result = result !& hash(it)
   result = !$result
 
+proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash =
+  ## efficient hashing of portions of arrays and sequences.
+  ##
+  ## ``hash(myBuf, 0, myBuf.high)`` is equivalent to ``hash(myBuf)``
+  for i in sPos..ePos:
+    result = result !& hash(aBuf[i])
+  result = !$result
+
 proc hash*[A](x: set[A]): Hash =
+  ## efficient hashing of sets.
   for it in items(x): result = result !& hash(it)
   result = !$result
 
+when isMainModule:
+  doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) )
+  doAssert( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") )
+  doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
+  let xx = @['H','e','l','l','o']
+  let ss = "Hello"
+  doAssert( hash(xx) == hash(ss) )
+  doAssert( hash(xx) == hash(xx, 0, xx.high) )
+  doAssert( hash(ss) == hash(ss, 0, ss.high) )
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index 7a900daae..aa55b5ade 100644
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -77,7 +77,7 @@ type
                                         ## console
 
   FileLogger* = ref object of Logger ## logger that writes the messages to a file
-    f: File
+    file*: File  ## the wrapped file.
 
   RollingFileLogger* = ref object of FileLogger ## logger that writes the
                                                 ## messages to a file and
@@ -92,7 +92,9 @@ type
 {.deprecated: [TLevel: Level, PLogger: Logger, PConsoleLogger: ConsoleLogger,
     PFileLogger: FileLogger, PRollingFileLogger: RollingFileLogger].}
 
-proc substituteLog(frmt: string, level: Level, args: varargs[string, `$`]): string =
+proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): string =
+  ## Format a log message using the ``frmt`` format string, ``level`` and varargs.
+  ## See the module documentation for the format string syntax.
   var msgLen = 0
   for arg in args:
     msgLen += arg.len
@@ -124,7 +126,7 @@ proc substituteLog(frmt: string, level: Level, args: varargs[string, `$`]): stri
 
 method log*(logger: Logger, level: Level, args: varargs[string, `$`]) {.
             raises: [Exception],
-            tags: [TimeEffect, WriteIOEffect, ReadIOEffect].} =
+            tags: [TimeEffect, WriteIOEffect, ReadIOEffect], base.} =
   ## Override this method in custom loggers. Default implementation does
   ## nothing.
   discard
@@ -133,15 +135,17 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
   ## Logs to the console using ``logger`` only.
   if level >= logger.levelThreshold:
     writeLine(stdout, substituteLog(logger.fmtStr, level, args))
+    if level in {lvlError, lvlFatal}: flushFile(stdout)
 
 method log*(logger: FileLogger, level: Level, args: varargs[string, `$`]) =
   ## Logs to a file using ``logger`` only.
   if level >= logger.levelThreshold:
-    writeLine(logger.f, substituteLog(logger.fmtStr, level, args))
+    writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
+    if level in {lvlError, lvlFatal}: flushFile(logger.file)
 
 proc defaultFilename*(): string =
   ## Returns the default filename for a logger.
-  var (path, name, ext) = splitFile(getAppFilename())
+  var (path, name, _) = splitFile(getAppFilename())
   result = changeFileExt(path / name, "log")
 
 proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr): ConsoleLogger =
@@ -160,14 +164,14 @@ proc newFileLogger*(filename = defaultFilename(),
   ## (-1: use system defaults, 0: unbuffered, >0: fixed buffer size).
   new(result)
   result.levelThreshold = levelThreshold
-  result.f = open(filename, mode, bufSize = bufSize)
+  result.file = open(filename, mode, bufSize = bufSize)
   result.fmtStr = fmtStr
 
 # ------
 
 proc countLogLines(logger: RollingFileLogger): int =
   result = 0
-  for line in logger.f.lines():
+  for line in logger.file.lines():
     result.inc()
 
 proc countFiles(filename: string): int =
@@ -200,7 +204,7 @@ proc newRollingFileLogger*(filename = defaultFilename(),
   result.fmtStr = fmtStr
   result.maxLines = maxLines
   result.bufSize = bufSize
-  result.f = open(filename, mode, bufSize=result.bufSize)
+  result.file = open(filename, mode, bufSize=result.bufSize)
   result.curLine = 0
   result.baseName = filename
   result.baseMode = mode
@@ -222,13 +226,14 @@ method log*(logger: RollingFileLogger, level: Level, args: varargs[string, `$`])
   ## Logs to a file using rolling ``logger`` only.
   if level >= logger.levelThreshold:
     if logger.curLine >= logger.maxLines:
-      logger.f.close()
+      logger.file.close()
       rotate(logger)
       logger.logFiles.inc
       logger.curLine = 0
-      logger.f = open(logger.baseName, logger.baseMode, bufSize = logger.bufSize)
+      logger.file = open(logger.baseName, logger.baseMode, bufSize = logger.bufSize)
 
-    writeLine(logger.f, substituteLog(logger.fmtStr, level, args))
+    writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
+    if level in {lvlError, lvlFatal}: flushFile(logger.file)
     logger.curLine.inc
 
 # --------
diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim
index 173cd1e81..134581a06 100644
--- a/lib/pure/marshal.nim
+++ b/lib/pure/marshal.nim
@@ -176,7 +176,7 @@ proc loadAny(p: var JsonParser, a: Any, t: var Table[BiggestInt, pointer]) =
       setPointer(a, nil)
       next(p)
     of jsonInt:
-      setPointer(a, t[p.getInt])
+      setPointer(a, t.getOrDefault(p.getInt))
       next(p)
     of jsonArrayStart:
       next(p)
diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim
index 5ee301b15..44b9ed0d4 100644
--- a/lib/pure/md5.nim
+++ b/lib/pure/md5.nim
@@ -9,8 +9,6 @@
 
 ## Module for computing MD5 checksums.
 
-import unsigned
-
 type
   MD5State = array[0..3, uint32]
   MD5Block = array[0..15, uint32]
diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim
index 642419e64..1e315afb4 100644
--- a/lib/pure/mimetypes.nim
+++ b/lib/pure/mimetypes.nim
@@ -499,7 +499,7 @@ proc newMimetypes*(): MimeDB =
 proc getMimetype*(mimedb: MimeDB, ext: string, default = "text/plain"): string =
   ## Gets mimetype which corresponds to ``ext``. Returns ``default`` if ``ext``
   ## could not be found.
-  result = mimedb.mimes[ext]
+  result = mimedb.mimes.getOrDefault(ext)
   if result == "":
     return default
 
diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim
index 667ca82d7..e9f5bee0a 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -26,8 +26,10 @@ when not declared(getEnv) or defined(nimscript):
                                               ## to an environment variable
 
     ReadDirEffect* = object of ReadIOEffect   ## effect that denotes a write
-                                              ## operation to the directory structure
-    WriteDirEffect* = object of WriteIOEffect ## effect that denotes a write operation to
+                                              ## operation to the directory
+                                              ## structure
+    WriteDirEffect* = object of WriteIOEffect ## effect that denotes a write
+                                              ## operation to
                                               ## the directory structure
 
     OSErrorCode* = distinct int32 ## Specifies an OS Error Code.
@@ -63,13 +65,13 @@ when not declared(getEnv) or defined(nimscript):
       AltSep* = '/'
         ## An alternative character used by the operating system to separate
         ## pathname components, or the same as `DirSep` if only one separator
-        ## character exists. This is set to '/' on Windows systems where `DirSep`
-        ## is a backslash.
+        ## character exists. This is set to '/' on Windows systems
+        ## where `DirSep` is a backslash.
 
       PathSep* = ':'
         ## The character conventionally used by the operating system to separate
-        ## search patch components (as in PATH), such as ':' for POSIX or ';' for
-        ## Windows.
+        ## search patch components (as in PATH), such as ':' for POSIX
+        ## or ';' for Windows.
 
       FileSystemCaseSensitive* = true
         ## true if the file system is case sensitive, false otherwise. Used by
@@ -104,7 +106,8 @@ when not declared(getEnv) or defined(nimscript):
     #  MacOS directory separator is a colon ":" which is the only character not
     #  allowed in filenames.
     #
-    #  A path containing no colon or which begins with a colon is a partial path.
+    #  A path containing no colon or which begins with a colon is a partial
+    #  path.
     #  E.g. ":kalle:petter" ":kalle" "kalle"
     #
     #  All other paths are full (absolute) paths. E.g. "HD:kalle:" "HD:"
@@ -206,9 +209,9 @@ when not declared(getEnv) or defined(nimscript):
 
   proc joinPath*(parts: varargs[string]): string {.noSideEffect,
     rtl, extern: "nos$1OpenArray".} =
-    ## The same as `joinPath(head, tail)`, but works with any number of directory
-    ## parts. You need to pass at least one element or the proc will assert in
-    ## debug builds and crash on release builds.
+    ## The same as `joinPath(head, tail)`, but works with any number of
+    ## directory parts. You need to pass at least one element or the proc
+    ## will assert in debug builds and crash on release builds.
     result = parts[0]
     for i in 1..high(parts):
       result = joinPath(result, parts[i])
@@ -316,8 +319,8 @@ when not declared(getEnv) or defined(nimscript):
       if inclusive: yield path
 
   proc `/../` * (head, tail: string): string {.noSideEffect.} =
-    ## The same as ``parentDir(head) / tail`` unless there is no parent directory.
-    ## Then ``head / tail`` is performed instead.
+    ## The same as ``parentDir(head) / tail`` unless there is no parent
+    ## directory. Then ``head / tail`` is performed instead.
     let sepPos = parentDirPos(head)
     if sepPos >= 0:
       result = substr(head, 0, sepPos-1) / tail
@@ -500,7 +503,8 @@ when defined(nimdoc) and not declared(os):
   proc existsFile(x: string): bool = discard
 
 when declared(getEnv) or defined(nimscript):
-  proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect, ReadIOEffect].} =
+  proc getHomeDir*(): string {.rtl, extern: "nos$1",
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Returns the home directory of the current user.
     ##
     ## This proc is wrapped by the expandTilde proc for the convenience of
@@ -508,18 +512,21 @@ when declared(getEnv) or defined(nimscript):
     when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
     else: return string(getEnv("HOME")) & "/"
 
-  proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect, ReadIOEffect].} =
+  proc getConfigDir*(): string {.rtl, extern: "nos$1",
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Returns the config directory of the current user for applications.
     when defined(windows): return string(getEnv("APPDATA")) & "\\"
     else: return string(getEnv("HOME")) & "/.config/"
 
-  proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
+  proc getTempDir*(): string {.rtl, extern: "nos$1",
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Returns the temporary directory of the current user for applications to
     ## save temporary files in.
     when defined(windows): return string(getEnv("TEMP")) & "\\"
     else: return "/tmp/"
 
-  proc expandTilde*(path: string): string {.tags: [ReadEnvEffect, ReadIOEffect].} =
+  proc expandTilde*(path: string): string {.
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Expands a path starting with ``~/`` to a full path.
     ##
     ## If `path` starts with the tilde character and is followed by `/` or `\\`
@@ -527,8 +534,8 @@ when declared(getEnv) or defined(nimscript):
     ## the getHomeDir() proc, otherwise the input path will be returned without
     ## modification.
     ##
-    ## The behaviour of this proc is the same on the Windows platform despite not
-    ## having this convention. Example:
+    ## The behaviour of this proc is the same on the Windows platform despite
+    ## not having this convention. Example:
     ##
     ## .. code-block:: nim
     ##   let configFile = expandTilde("~" / "appname.cfg")
@@ -549,7 +556,8 @@ when declared(getEnv) or defined(nimscript):
           yield substr(s, first, last-1)
           inc(last)
 
-  proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect].} =
+  proc findExe*(exe: string): string {.
+    tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect].} =
     ## Searches for `exe` in the current working directory and then
     ## in directories listed in the ``PATH`` environment variable.
     ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`
diff --git a/lib/deprecated/pure/parseopt.nim b/lib/pure/parseopt.nim
index 218f5ab81..218f5ab81 100644
--- a/lib/deprecated/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
diff --git a/lib/pure/scgi.nim b/lib/pure/scgi.nim
index 1d54b4591..711e4a897 100644
--- a/lib/pure/scgi.nim
+++ b/lib/pure/scgi.nim
@@ -145,8 +145,8 @@ proc next*(s: var ScgiState, timeout: int = -1): bool =
       L = L * 10 + ord(d) - ord('0')
     recvBuffer(s, L+1)
     s.headers = parseHeaders(s.input, L)
-    if s.headers["SCGI"] != "1": raiseScgiError("SCGI Version 1 expected")
-    L = parseInt(s.headers["CONTENT_LENGTH"])
+    if s.headers.getOrDefault("SCGI") != "1": raiseScgiError("SCGI Version 1 expected")
+    L = parseInt(s.headers.getOrDefault("CONTENT_LENGTH"))
     recvBuffer(s, L)
     return true
 
@@ -221,10 +221,10 @@ proc handleClientRead(client: AsyncClient, s: AsyncScgiState) =
     case ret
     of ReadFullLine:
       client.headers = parseHeaders(client.input, client.input.len-1)
-      if client.headers["SCGI"] != "1": raiseScgiError("SCGI Version 1 expected")
+      if client.headers.getOrDefault("SCGI") != "1": raiseScgiError("SCGI Version 1 expected")
       client.input = "" # For next part
 
-      let contentLen = parseInt(client.headers["CONTENT_LENGTH"])
+      let contentLen = parseInt(client.headers.getOrDefault("CONTENT_LENGTH"))
       if contentLen > 0:
         client.mode = ClientReadContent
       else:
@@ -232,7 +232,8 @@ proc handleClientRead(client: AsyncClient, s: AsyncScgiState) =
         checkCloseSocket(client)
     of ReadPartialLine, ReadDisconnected, ReadNone: return
   of ClientReadContent:
-    let L = parseInt(client.headers["CONTENT_LENGTH"])-client.input.len
+    let L = parseInt(client.headers.getOrDefault("CONTENT_LENGTH")) -
+               client.input.len
     if L > 0:
       let ret = recvBufferAsync(client, L)
       case ret
diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim
index 1ce9067a7..1c761cd92 100644
--- a/lib/pure/strtabs.nim
+++ b/lib/pure/strtabs.nim
@@ -101,21 +101,31 @@ proc rawGet(t: StringTableRef, key: string): int =
     h = nextTry(h, high(t.data))
   result = - 1
 
-proc `[]`*(t: StringTableRef, key: string): string {.rtl, extern: "nstGet".} =
-  ## retrieves the value at ``t[key]``. If `key` is not in `t`, "" is returned
-  ## and no exception is raised. One can check with ``hasKey`` whether the key
-  ## exists.
+template get(t: StringTableRef, key: string): stmt {.immediate.} =
   var index = rawGet(t, key)
   if index >= 0: result = t.data[index].val
-  else: result = ""
+  else:
+    when compiles($key):
+      raise newException(KeyError, "key not found: " & $key)
+    else:
+      raise newException(KeyError, "key not found")
 
-proc mget*(t: StringTableRef, key: string): var string {.
-             rtl, extern: "nstTake".} =
+proc `[]`*(t: StringTableRef, key: string): var string {.
+           rtl, extern: "nstTake", deprecatedGet.} =
   ## retrieves the location at ``t[key]``. If `key` is not in `t`, the
-  ## ``KeyError`` exception is raised.
+  ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
+  ## the key exists.
+  get(t, key)
+
+proc mget*(t: StringTableRef, key: string): var string {.deprecated.} =
+  ## retrieves the location at ``t[key]``. If `key` is not in `t`, the
+  ## ``KeyError`` exception is raised. Use ```[]``` instead.
+  get(t, key)
+
+proc getOrDefault*(t: StringTableRef; key: string): string =
   var index = rawGet(t, key)
   if index >= 0: result = t.data[index].val
-  else: raise newException(KeyError, "key does not exist: " & key)
+  else: result = ""
 
 proc hasKey*(t: StringTableRef, key: string): bool {.rtl, extern: "nst$1".} =
   ## returns true iff `key` is in the table `t`.
@@ -152,7 +162,7 @@ proc raiseFormatException(s: string) =
   raise e
 
 proc getValue(t: StringTableRef, flags: set[FormatFlag], key: string): string =
-  if hasKey(t, key): return t[key]
+  if hasKey(t, key): return t.getOrDefault(key)
   # hm difficult: assume safety in taint mode here. XXX This is dangerous!
   if useEnvironment in flags: result = os.getEnv(key).string
   else: result = ""
@@ -248,7 +258,7 @@ when isMainModule:
   assert x["k"] == "v"
   assert x["11"] == "22"
   assert x["565"] == "67"
-  x.mget("11") = "23"
+  x["11"] = "23"
   assert x["11"] == "23"
 
   x.clear(modeCaseInsensitive)
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index eacea72e4..a78fed4b9 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -60,6 +60,132 @@ const
     ##   doAssert "01234".find(invalid) == -1
     ##   doAssert "01A34".find(invalid) == 2
 
+proc isAlpha*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaChar".}=
+  ## Checks whether or not `c` is alphabetical.
+  ##
+  ## This checks a-z, A-Z ASCII characters only.
+  return c in Letters
+
+proc isAlphaNumeric*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaNumericChar".}=
+  ## Checks whether or not `c` is alphanumeric.
+  ##
+  ## This checks a-z, A-Z, 0-9 ASCII characters only.
+  return c in Letters or c in Digits
+
+proc isDigit*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsDigitChar".}=
+  ## Checks whether or not `c` is a number.
+  ##
+  ## This checks 0-9 ASCII characters only.
+  return c in Digits
+
+proc isSpace*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsSpaceChar".}=
+  ## Checks whether or not `c` is a whitespace character.
+  return c in Whitespace
+
+proc isLower*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsLowerChar".}=
+  ## Checks whether or not `c` is a lower case character.
+  ##
+  ## This checks ASCII characters only.
+  return c in {'a'..'z'}
+
+proc isUpper*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsUpperChar".}=
+  ## Checks whether or not `c` is an upper case character.
+  ##
+  ## This checks ASCII characters only.
+  return c in {'A'..'Z'}
+
+proc isAlpha*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaStr".}=
+  ## Checks whether or not `s` is alphabetical.
+  ##
+  ## This checks a-z, A-Z ASCII characters only.
+  ## Returns true if all characters in `s` are
+  ## alphabetic and there is at least one character
+  ## in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isAlpha() and result
+
+proc isAlphaNumeric*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaNumericStr".}=
+  ## Checks whether or not `s` is alphanumeric.
+  ##
+  ## This checks a-z, A-Z, 0-9 ASCII characters only.
+  ## Returns true if all characters in `s` are
+  ## alpanumeric and there is at least one character
+  ## in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isAlphaNumeric() and result
+
+proc isDigit*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsDigitStr".}=
+  ## Checks whether or not `s` is a numeric value.
+  ##
+  ## This checks 0-9 ASCII characters only.
+  ## Returns true if all characters in `s` are
+  ## numeric and there is at least one character
+  ## in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isDigit() and result
+
+proc isSpace*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsSpaceStr".}=
+  ## Checks whether or not `s` is completely whitespace.
+  ##
+  ## Returns true if all characters in `s` are whitespace
+  ## characters and there is at least one character in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isSpace() and result
+
+proc isLower*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsLowerStr".}=
+  ## Checks whether or not `s` contains all lower case characters.
+  ##
+  ## This checks ASCII characters only.
+  ## Returns true if all characters in `s` are lower case
+  ## and there is at least one character  in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isLower() and result
+
+proc isUpper*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsUpperStr".}=
+  ## Checks whether or not `s` contains all upper case characters.
+  ##
+  ## This checks ASCII characters only.
+  ## Returns true if all characters in `s` are upper case
+  ## and there is at least one character in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isUpper() and result
+
 proc toLower*(c: char): char {.noSideEffect, procvar,
   rtl, extern: "nsuToLowerChar".} =
   ## Converts `c` into lower case.
@@ -1526,3 +1652,55 @@ when isMainModule:
   doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos"
 
   doAssert "  foo\n  bar".indent(4, "Q") == "QQQQ  foo\nQQQQ  bar"
+
+  doAssert isAlpha('r')
+  doAssert isAlpha('A')
+  doAssert(not isAlpha('$'))
+
+  doAssert isAlpha("Rasp")
+  doAssert isAlpha("Args")
+  doAssert(not isAlpha("$Tomato"))
+  
+  doAssert isAlphaNumeric('3')
+  doAssert isAlphaNumeric('R')
+  doAssert(not isAlphaNumeric('!'))
+
+  doAssert isAlphaNumeric("34ABc")
+  doAssert isAlphaNumeric("Rad")
+  doAssert isAlphaNumeric("1234")
+  doAssert(not isAlphaNumeric("@nose"))
+
+  doAssert isDigit('3')
+  doAssert(not isDigit('a'))
+  doAssert(not isDigit('%'))
+
+  doAssert isDigit("12533")
+  doAssert(not isDigit("12.33"))
+  doAssert(not isDigit("A45b"))
+
+  doAssert isSpace('\t')
+  doAssert isSpace('\l')
+  doAssert(not isSpace('A'))
+
+  doAssert isSpace("\t\l \v\r\f")
+  doAssert isSpace("       ")
+  doAssert(not isSpace("ABc   \td"))
+
+  doAssert isLower('a')
+  doAssert isLower('z')
+  doAssert(not isLower('A'))
+  doAssert(not isLower('5'))
+  doAssert(not isLower('&'))
+
+  doAssert isLower("abcd")
+  doAssert(not isLower("abCD"))
+  doAssert(not isLower("33aa"))
+
+  doAssert isUpper('A')
+  doAssert(not isUpper('b'))
+  doAssert(not isUpper('5'))
+  doAssert(not isUpper('%'))
+
+  doAssert isUpper("ABC")
+  doAssert(not isUpper("AAcc"))
+  doAssert(not isUpper("A#$"))
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index a0f7b955e..aca9d51e2 100755
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -150,6 +150,8 @@ template test*(name: expr, body: stmt): stmt {.immediate, dirty.} =
     try:
       when declared(testSetupIMPLFlag): testSetupIMPL()
       body
+      when declared(testTeardownIMPLFlag):
+        defer: testTeardownIMPL()
 
     except:
       when not defined(js):
@@ -158,7 +160,6 @@ template test*(name: expr, body: stmt): stmt {.immediate, dirty.} =
       fail()
 
     finally:
-      when declared(testTeardownIMPLFlag): testTeardownIMPL()
       testDone name, testStatusIMPL
 
 proc checkpoint*(msg: string) =
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 7c97a0a56..a9fc8998a 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -139,11 +139,16 @@ proc delete*(n: XmlNode, i: Natural) {.noSideEffect.} =
   assert n.k == xnElement
   n.s.delete(i)
 
-proc mget* (n: var XmlNode, i: int): var XmlNode {.inline.} =
+proc `[]`* (n: var XmlNode, i: int): var XmlNode {.inline.} =
   ## returns the `i`'th child of `n` so that it can be modified
   assert n.k == xnElement
   result = n.s[i]
 
+proc mget*(n: var XmlNode, i: int): var XmlNode {.inline, deprecated.} =
+  ## returns the `i`'th child of `n` so that it can be modified. Use ```[]```
+  ## instead.
+  n[i]
+
 iterator items*(n: XmlNode): XmlNode {.inline.} =
   ## iterates over any child of `n`.
   assert n.k == xnElement
@@ -152,7 +157,7 @@ iterator items*(n: XmlNode): XmlNode {.inline.} =
 iterator mitems*(n: var XmlNode): var XmlNode {.inline.} =
   ## iterates over any child of `n`.
   assert n.k == xnElement
-  for i in 0 .. n.len-1: yield mget(n, i)
+  for i in 0 .. n.len-1: yield n[i]
 
 proc attrs*(n: XmlNode): XmlAttributes {.inline.} =
   ## gets the attributes belonging to `n`.
@@ -337,7 +342,7 @@ proc attr*(n: XmlNode, name: string): string =
   ## Returns "" on failure.
   assert n.kind == xnElement
   if n.attrs == nil: return ""
-  return n.attrs[name]
+  return n.attrs.getOrDefault(name)
 
 proc findAll*(n: XmlNode, tag: string, result: var seq[XmlNode]) =
   ## Iterates over all the children of `n` returning those matching `tag`.
diff --git a/lib/system.nim b/lib/system.nim
index 1d2ca6a9a..89de08c6f 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1260,6 +1260,15 @@ const
   hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
   taintMode = compileOption("taintmode")
 
+when defined(boehmgc):
+  when defined(windows):
+    const boehmLib = "boehmgc.dll"
+  elif defined(macosx):
+    const boehmLib = "libgc.dylib"
+  else:
+    const boehmLib = "libgc.so.1"
+  {.pragma: boehmGC, noconv, dynlib: boehmLib.}
+
 when taintMode:
   type TaintedString* = distinct string ## a distinct string type that
                                         ## is `tainted`:idx:. It is an alias for
@@ -2160,53 +2169,6 @@ proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
   result = s[L]
   setLen(s, L)
 
-proc each*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}): seq[S] {.
-  deprecated.} =
-  ## The well-known ``map`` operation from functional programming. Applies
-  ## `op` to every item in `data` and returns the result as a sequence.
-  ##
-  ## **Deprecated since version 0.9:** Use the ``map`` proc instead.
-  newSeq(result, data.len)
-  for i in 0..data.len-1: result[i] = op(data[i])
-
-proc each*[T](data: var openArray[T], op: proc (x: var T) {.closure.}) {.
-  deprecated.} =
-  ## The well-known ``map`` operation from functional programming. Applies
-  ## `op` to every item in `data` modifying it directly.
-  ##
-  ## **Deprecated since version 0.9:** Use the ``map`` proc instead.
-  for i in 0..data.len-1: op(data[i])
-
-proc map*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}): seq[S] =
-  ## Returns a new sequence with the results of `op` applied to every item in
-  ## `data`.
-  ##
-  ## Since the input is not modified you can use this version of ``map`` to
-  ## transform the type of the elements in the input sequence. Example:
-  ##
-  ## .. code-block:: nim
-  ##   let
-  ##     a = @[1, 2, 3, 4]
-  ##     b = map(a, proc(x: int): string = $x)
-  ##   assert b == @["1", "2", "3", "4"]
-  newSeq(result, data.len)
-  for i in 0..data.len-1: result[i] = op(data[i])
-
-proc map*[T](data: var openArray[T], op: proc (x: var T) {.closure.}) =
-  ## Applies `op` to every item in `data` modifying it directly.
-  ##
-  ## Note that this version of ``map`` requires your input and output types to
-  ## be the same, since they are modified in-place. Example:
-  ##
-  ## .. code-block:: nim
-  ##   var a = @["1", "2", "3", "4"]
-  ##   echo repr(a)
-  ##   # --> ["1", "2", "3", "4"]
-  ##   map(a, proc(x: var string) = x &= "42")
-  ##   echo repr(a)
-  ##   # --> ["142", "242", "342", "442"]
-  for i in 0..data.len-1: op(data[i])
-
 iterator fields*[T: tuple|object](x: T): RootObj {.
   magic: "Fields", noSideEffect.}
   ## iterates over every field of `x`. Warning: This really transforms
diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim
index 201a99ca7..3caeefcbc 100644
--- a/lib/system/inclrtl.nim
+++ b/lib/system/inclrtl.nim
@@ -51,3 +51,8 @@ when defined(nimlocks):
   {.pragma: benign, gcsafe, locks: 0.}
 else:
   {.pragma: benign, gcsafe.}
+
+when defined(nimTableGet):
+  {.pragma: deprecatedGet, deprecated.}
+else:
+  {.pragma: deprecatedGet.}
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 8a946716d..1c13f3ff8 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -66,41 +66,34 @@ proc raiseOutOfMem() {.noinline.} =
   quit(1)
 
 when defined(boehmgc):
-  when defined(windows):
-    const boehmLib = "boehmgc.dll"
-  elif defined(macosx):
-    const boehmLib = "libgc.dylib"
-  else:
-    const boehmLib = "libgc.so.1"
-
-  proc boehmGCinit {.importc: "GC_init", dynlib: boehmLib.}
-  proc boehmGC_disable {.importc: "GC_disable", dynlib: boehmLib.}
-  proc boehmGC_enable {.importc: "GC_enable", dynlib: boehmLib.}
+  proc boehmGCinit {.importc: "GC_init", boehmGC.}
+  proc boehmGC_disable {.importc: "GC_disable", boehmGC.}
+  proc boehmGC_enable {.importc: "GC_enable", boehmGC.}
   proc boehmGCincremental {.
-    importc: "GC_enable_incremental", dynlib: boehmLib.}
-  proc boehmGCfullCollect {.importc: "GC_gcollect", dynlib: boehmLib.}
-  proc boehmAlloc(size: int): pointer {.
-    importc: "GC_malloc", dynlib: boehmLib.}
+    importc: "GC_enable_incremental", boehmGC.}
+  proc boehmGCfullCollect {.importc: "GC_gcollect", boehmGC.}
+  proc boehmAlloc(size: int): pointer {.importc: "GC_malloc", boehmGC.}
   proc boehmAllocAtomic(size: int): pointer {.
-    importc: "GC_malloc_atomic", dynlib: boehmLib.}
+    importc: "GC_malloc_atomic", boehmGC.}
   proc boehmRealloc(p: pointer, size: int): pointer {.
-    importc: "GC_realloc", dynlib: boehmLib.}
-  proc boehmDealloc(p: pointer) {.importc: "GC_free", dynlib: boehmLib.}
+    importc: "GC_realloc", boehmGC.}
+  proc boehmDealloc(p: pointer) {.importc: "GC_free", boehmGC.}
+  when hasThreadSupport:
+    proc boehmGC_allow_register_threads {.
+      importc: "GC_allow_register_threads", boehmGC.}
 
-  proc boehmGetHeapSize: int {.importc: "GC_get_heap_size", dynlib: boehmLib.}
+  proc boehmGetHeapSize: int {.importc: "GC_get_heap_size", boehmGC.}
     ## Return the number of bytes in the heap.  Excludes collector private
     ## data structures. Includes empty blocks and fragmentation loss.
     ## Includes some pages that were allocated but never written.
 
-  proc boehmGetFreeBytes: int {.importc: "GC_get_free_bytes", dynlib: boehmLib.}
+  proc boehmGetFreeBytes: int {.importc: "GC_get_free_bytes", boehmGC.}
     ## Return a lower bound on the number of free bytes in the heap.
 
-  proc boehmGetBytesSinceGC: int {.importc: "GC_get_bytes_since_gc",
-    dynlib: boehmLib.}
+  proc boehmGetBytesSinceGC: int {.importc: "GC_get_bytes_since_gc", boehmGC.}
     ## Return the number of bytes allocated since the last collection.
 
-  proc boehmGetTotalBytes: int {.importc: "GC_get_total_bytes",
-    dynlib: boehmLib.}
+  proc boehmGetTotalBytes: int {.importc: "GC_get_total_bytes", boehmGC.}
     ## Return the total number of bytes allocated in this process.
     ## Never decreases.
 
@@ -157,7 +150,9 @@ when defined(boehmgc):
     proc setStackBottom(theStackBottom: pointer) = discard
 
   proc initGC() =
-    when defined(macosx): boehmGCinit()
+    boehmGCinit()
+    when hasThreadSupport:
+      boehmGC_allow_register_threads()
 
   proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
     if ntfNoRefs in typ.flags: result = allocAtomic(size)
@@ -204,9 +199,6 @@ elif defined(gogc):
   else:
     const goLib = "libgo.so"
 
-  proc `div`[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
-  proc `-`[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.}
-
   proc roundup(x, v: int): int {.inline.} =
     result = (x + (v-1)) and not (v-1)
 
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index c7cb8d9df..c5de841f8 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -304,22 +304,53 @@ type
 when not defined(boehmgc) and not hasSharedHeap and not defined(gogc):
   proc deallocOsPages()
 
+when defined(boehmgc):
+  type GCStackBaseProc = proc(sb: pointer, t: pointer) {.noconv.}
+  proc boehmGC_call_with_stack_base(sbp: GCStackBaseProc, p: pointer)
+    {.importc: "GC_call_with_stack_base", boehmGC.}
+  proc boehmGC_register_my_thread(sb: pointer)
+    {.importc: "GC_register_my_thread", boehmGC.}
+  proc boehmGC_unregister_my_thread()
+    {.importc: "GC_unregister_my_thread", boehmGC.}
+
+  proc threadProcWrapDispatch[TArg](sb: pointer, thrd: pointer) {.noconv.} =
+    boehmGC_register_my_thread(sb)
+    let thrd = cast[ptr Thread[TArg]](thrd)
+    when TArg is void:
+      thrd.dataFn()
+    else:
+      thrd.dataFn(thrd.data)
+    boehmGC_unregister_my_thread()
+else:
+  proc threadProcWrapDispatch[TArg](thrd: ptr Thread[TArg]) =
+    when TArg is void:
+      thrd.dataFn()
+    else:
+      thrd.dataFn(thrd.data)
+
+proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
+  when defined(boehmgc):
+    boehmGC_call_with_stack_base(threadProcWrapDispatch[TArg], thrd)
+  elif not defined(nogc) and not defined(gogc):
+    var p {.volatile.}: proc(a: ptr Thread[TArg]) {.nimcall.} =
+      threadProcWrapDispatch[TArg]
+    when not hasSharedHeap:
+      # init the GC for refc/markandsweep
+      setStackBottom(addr(p))
+      initGC()
+    when declared(registerThread):
+      thrd.stackBottom = addr(thrd)
+      registerThread(thrd)
+    p(thrd)
+    when declared(registerThread): unregisterThread(thrd)
+    when declared(deallocOsPages): deallocOsPages()
+  else:
+    threadProcWrapDispatch(thrd)
+
 template threadProcWrapperBody(closure: expr) {.immediate.} =
   when declared(globalsSlot): threadVarSetValue(globalsSlot, closure)
-  var t = cast[ptr Thread[TArg]](closure)
-  when useStackMaskHack:
-    var tls: ThreadLocalStorage
-  when not defined(boehmgc) and not defined(gogc) and not defined(nogc) and not hasSharedHeap:
-    # init the GC for this thread:
-    setStackBottom(addr(t))
-    initGC()
-  when declared(registerThread):
-    t.stackBottom = addr(t)
-    registerThread(t)
-  when TArg is void: t.dataFn()
-  else: t.dataFn(t.data)
-  when declared(registerThread): unregisterThread(t)
-  when declared(deallocOsPages): deallocOsPages()
+  var thrd = cast[ptr Thread[TArg]](closure)
+  threadProcWrapStackFrame(thrd)
   # Since an unhandled exception terminates the whole process (!), there is
   # no need for a ``try finally`` here, nor would it be correct: The current
   # exception is tried to be re-raised by the code-gen after the ``finally``!
@@ -327,7 +358,7 @@ template threadProcWrapperBody(closure: expr) {.immediate.} =
   # page!
 
   # mark as not running anymore:
-  t.dataFn = nil
+  thrd.dataFn = nil
 
 {.push stack_trace:off.}
 when defined(windows):
diff --git a/readme.md b/readme.md
index 80723cabc..4c996ebae 100644
--- a/readme.md
+++ b/readme.md
@@ -79,22 +79,29 @@ All rights reserved.
 # Build Status
 [**Build Waterfall**][waterfall]
 
-|        | Linux                                                                                                  | Windows                               | Mac                           |
-| ------ | -----                                                                                                  | -------                               | ---                           |
-| x86    | ![linux-x86][linux-x86-img]                                                                            | ![windows-x86][windows-x86-img]       | ![mac-x86][mac-x86-img]       |
-| x86_64 | ![linux-x86_64][linux-x86_64-img]                                                                      | ![windows-x86_64][windows-x86_64-img] | ![mac-x86_64][mac-x86_64-img] |
-| arm    | ![linux-armv5][linux-arm5-img]<br/> ![linux-armv6][linux-arm6-img]<br/> ![linux-armv7][linux-arm7-img] |                                       |                               |
+|        | Linux | Windows | Mac |
+| ------ | ----- | ------- | --- |
+| x86    | [![linux-x86][linux-x86-img]][linux-x86] | [![windows-x86][windows-x86-img]][windows-x86] |
+| x86_64 | [![linux-x86_64][linux-x86_64-img]][linux-x86_64] | [![windows-x86_64][windows-x86_64-img]][windows-x86_64] | [![mac-x86_64][mac-x86_64-img]][mac-x86_64] |
+| arm    | [![linux-armv5][linux-arm5-img]][linux-arm5]<br/> [![linux-armv6][linux-arm6-img]][linux-arm6]<br/> [![linux-armv7][linux-arm7-img]][linux-arm7]
 
+[linux-x86]:          http://buildbot.nim-lang.org/builders/linux-x32-builder
 [linux-x86-img]:      http://buildbot.nim-lang.org/buildstatusimage?builder=linux-x32-builder
+[linux-x86_64]:       http://buildbot.nim-lang.org/builders/linux-x64-builder
 [linux-x86_64-img]:   http://buildbot.nim-lang.org/buildstatusimage?builder=linux-x64-builder
+[linux-arm5]:         http://buildbot.nim-lang.org/builders/linux-arm5-builder
 [linux-arm5-img]:     http://buildbot.nim-lang.org/buildstatusimage?builder=linux-arm5-builder
+[linux-arm6]:         http://buildbot.nim-lang.org/builders/linux-arm6-builder
 [linux-arm6-img]:     http://buildbot.nim-lang.org/buildstatusimage?builder=linux-arm6-builder
+[linux-arm7]:         http://buildbot.nim-lang.org/builders/linux-arm7-builder
 [linux-arm7-img]:     http://buildbot.nim-lang.org/buildstatusimage?builder=linux-arm7-builder
 
+[windows-x86]:        http://buildbot.nim-lang.org/builders/windows-x32-builder
 [windows-x86-img]:    http://buildbot.nim-lang.org/buildstatusimage?builder=windows-x32-builder
+[windows-x86_64]:     http://buildbot.nim-lang.org/builders/windows-x64-builder
 [windows-x86_64-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=windows-x64-builder
 
-[mac-x86-img]:        http://buildbot.nim-lang.org/buildstatusimage?builder=mac-x32-builder
+[mac-x86_64]:         http://buildbot.nim-lang.org/builders/mac-x64-builder
 [mac-x86_64-img]:     http://buildbot.nim-lang.org/buildstatusimage?builder=mac-x64-builder
 
 [waterfall]: http://buildbot.nim-lang.org/waterfall
diff --git a/tests/actiontable/tactiontable.nim b/tests/actiontable/tactiontable.nim
index 18b0fd388..4560d0f7f 100644
--- a/tests/actiontable/tactiontable.nim
+++ b/tests/actiontable/tactiontable.nim
@@ -24,4 +24,3 @@ var
     "D": action4}.toTable
 
 actionTable["C"]("arg")
-
diff --git a/tests/closure/tclosure4.nim b/tests/closure/tclosure4.nim
index 8e08376b6..10c7cac54 100644
--- a/tests/closure/tclosure4.nim
+++ b/tests/closure/tclosure4.nim
@@ -1,5 +1,5 @@
 
-import json, tables
+import json, tables, sequtils
 
 proc run(json_params: TTable) =
   let json_elems = json_params["files"].elems
diff --git a/tests/collections/tapply.nim b/tests/collections/tapply.nim
new file mode 100644
index 000000000..2b7464216
--- /dev/null
+++ b/tests/collections/tapply.nim
@@ -0,0 +1,11 @@
+discard """
+  output: '''true'''
+"""
+
+import sequtils
+
+var x = @[1, 2, 3]
+x.apply(proc(x: var int) = x = x+10)
+x.apply(proc(x: int): int = x+100)
+x.applyIt(it+5000)
+echo x == @[5111, 5112, 5113]
diff --git a/tests/collections/tmapit.nim b/tests/collections/tmapit.nim
new file mode 100644
index 000000000..b2afa9429
--- /dev/null
+++ b/tests/collections/tmapit.nim
@@ -0,0 +1,33 @@
+discard """
+  output: '''true
+true'''
+"""
+
+import sequtils
+
+var x = @[1, 2, 3]
+# This mapIt call will run with preallocation because ``len`` is available.
+var y = x.mapIt($(it+10))
+echo y == @["11", "12", "13"]
+
+type structureWithoutLen = object
+  a: array[5, int]
+
+iterator items(s: structureWithoutLen): int {.inline.} =
+  yield s.a[0]
+  yield s.a[1]
+  yield s.a[2]
+  yield s.a[3]
+  yield s.a[4]
+
+var st: structureWithoutLen
+st.a[0] = 0
+st.a[1] = 1
+st.a[2] = 2
+st.a[3] = 3
+st.a[4] = 4
+
+# this will run without preallocating the result
+# since ``len`` is not available
+var r = st.mapIt($(it+10))
+echo r == @["10", "11", "12", "13", "14"]
diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim
index a10606843..a8a182a78 100644
--- a/tests/collections/ttables.nim
+++ b/tests/collections/ttables.nim
@@ -60,8 +60,12 @@ block tableTest2:
   t["123"] = 1.5 # test overwriting
 
   assert t["123"] == 1.5
-  assert t["111"] == 0.0 # deleted
+  try:
+    echo t["111"] # deleted
+  except KeyError:
+    discard
   assert(not hasKey(t, "111"))
+
   assert "123" in t
   assert("111" notin t)
 
diff --git a/tests/collections/ttablesref.nim b/tests/collections/ttablesref.nim
index 0b641ebc7..32494f1f2 100644
--- a/tests/collections/ttablesref.nim
+++ b/tests/collections/ttablesref.nim
@@ -60,8 +60,10 @@ block tableTest2:
   t["123"] = 1.5 # test overwriting
 
   assert t["123"] == 1.5
-  assert t["111"] == 0.0 # deleted
-  assert "123" in t
+  try:
+    echo t["111"] # deleted
+  except KeyError:
+    discard
   assert(not hasKey(t, "111"))
   assert "111" notin t
 
diff --git a/tests/generics/tinferredgenericprocs.nim b/tests/generics/tinferredgenericprocs.nim
index 5cbeabb94..359c71ba8 100644
--- a/tests/generics/tinferredgenericprocs.nim
+++ b/tests/generics/tinferredgenericprocs.nim
@@ -5,6 +5,7 @@ discard """
 3'''
 """
 
+import sequtils
 # https://github.com/Araq/Nim/issues/797
 proc foo[T](s:T):string = $s
 
diff --git a/tests/generics/tmap_auto.nim b/tests/generics/tmap_auto.nim
index dea9b571f..572556722 100644
--- a/tests/generics/tmap_auto.nim
+++ b/tests/generics/tmap_auto.nim
@@ -1,4 +1,4 @@
-import future
+import future, sequtils
 
 let x = map(@[1, 2, 3], x => x+10)
 assert x == @[11, 12, 13]
diff --git a/tests/misc/teventemitter.nim b/tests/misc/teventemitter.nim
index 32cc81be4..7da1a2522 100644
--- a/tests/misc/teventemitter.nim
+++ b/tests/misc/teventemitter.nim
@@ -18,7 +18,7 @@ proc on*(emitter: var EventEmitter, event: string,
   if not hasKey(emitter.events, event):
     var list: DoublyLinkedList[proc(e: EventArgs) {.nimcall.}]
     add(emitter.events, event, list) #if not, add it.
-  append(emitter.events.mget(event), fn)
+  append(emitter.events[event], fn)
 
 proc initEmitter(emitter: var EventEmitter) =
   emitter.events = initTable[string,
@@ -30,4 +30,3 @@ var
 initEmitter(ee)
 ee.on("print", proc(e: EventArgs) = echo("pie"))
 ee.emit("print", args)
-
diff --git a/tests/newconfig/tfoo.nims b/tests/newconfig/tfoo.nims
index a2166576d..519a868d5 100644
--- a/tests/newconfig/tfoo.nims
+++ b/tests/newconfig/tfoo.nims
@@ -3,6 +3,9 @@ mode = ScriptMode.Whatif
 
 exec "gcc -v"
 
+# test that ospaths actually compiles:
+import ospaths
+
 --forceBuild
 
 task listDirs, "lists every subdirectory":
diff --git a/tests/overload/toverprc.nim b/tests/overload/toverprc.nim
index 78831f744..112eae096 100644
--- a/tests/overload/toverprc.nim
+++ b/tests/overload/toverprc.nim
@@ -5,7 +5,7 @@ yay'''
 
 # Test overloading of procs when used as function pointers
 
-import strutils
+import strutils, sequtils
 
 proc parseInt(x: float): int {.noSideEffect.} = discard
 proc parseInt(x: bool): int {.noSideEffect.} = discard
diff --git a/tests/parser/tcommand_as_expr.nim b/tests/parser/tcommand_as_expr.nim
index 730e9cbb7..a244c8767 100644
--- a/tests/parser/tcommand_as_expr.nim
+++ b/tests/parser/tcommand_as_expr.nim
@@ -5,6 +5,7 @@ discard """
 77'''
 """
 #import math
+import sequtils
 
 proc optarg(x:int, y:int = 0):int = x + 3 * y
 proc singlearg(x:int):int = 20*x
diff --git a/tests/stdlib/tmget.nim b/tests/stdlib/tmget.nim
new file mode 100644
index 000000000..5792b6282
--- /dev/null
+++ b/tests/stdlib/tmget.nim
@@ -0,0 +1,141 @@
+discard """
+  output: '''Can't access 6
+10
+11
+Can't access 6
+10
+11
+Can't access 6
+10
+11
+Can't access 6
+10
+11
+Can't access 6
+10
+11
+Can't access 6
+10
+11
+Can't access 6
+5
+Can't access 6
+10
+11
+Can't access 6
+10
+11'''
+"""
+
+import tables
+
+block:
+  var x = initTable[int, int]()
+  x[5] = 10
+  try:
+    echo x[6]
+  except KeyError:
+    echo "Can't access 6"
+  echo x[5]
+  x[5] += 1
+  var c = x[5]
+  echo c
+
+block:
+  var x = newTable[int, int]()
+  x[5] = 10
+  try:
+    echo x[6]
+  except KeyError:
+    echo "Can't access 6"
+  echo x[5]
+  x[5] += 1
+  var c = x[5]
+  echo c
+
+block:
+  var x = initOrderedTable[int, int]()
+  x[5] = 10
+  try:
+    echo x[6]
+  except KeyError:
+    echo "Can't access 6"
+  echo x[5]
+  x[5] += 1
+  var c = x[5]
+  echo c
+
+block:
+  var x = newOrderedTable[int, int]()
+  x[5] = 10
+  try:
+    echo x[6]
+  except KeyError:
+    echo "Can't access 6"
+  echo x[5]
+  x[5] += 1
+  var c = x[5]
+  echo c
+
+block:
+  var x = initCountTable[int]()
+  x[5] = 10
+  try:
+    echo x[6]
+  except KeyError:
+    echo "Can't access 6"
+  echo x[5]
+  x[5] += 1
+  var c = x[5]
+  echo c
+
+block:
+  var x = newCountTable[int]()
+  x[5] = 10
+  try:
+    echo x[6]
+  except KeyError:
+    echo "Can't access 6"
+  echo x[5]
+  x[5] += 1
+  var c = x[5]
+  echo c
+
+import sets
+
+block:
+  var x = initSet[int]()
+  x.incl 5
+  try:
+    echo x[6]
+  except KeyError:
+    echo "Can't access 6"
+  echo x[5]
+
+import critbits
+
+block:
+  var x: CritBitTree[int]
+  x["5"] = 10
+  try:
+    echo x["6"]
+  except KeyError:
+    echo "Can't access 6"
+  echo x["5"]
+  x["5"] += 1
+  var c = x["5"]
+  echo c
+
+import strtabs
+
+block:
+  var x = newStringTable()
+  x["5"] = "10"
+  try:
+    echo x["6"]
+  except KeyError:
+    echo "Can't access 6"
+  echo x["5"]
+  x["5"][1] = '1'
+  var c = x["5"]
+  echo c
diff --git a/tests/stdlib/tmitems.nim b/tests/stdlib/tmitems.nim
index 544ad0334..27ff344e5 100644
--- a/tests/stdlib/tmitems.nim
+++ b/tests/stdlib/tmitems.nim
@@ -132,5 +132,5 @@ block:
   </Students>""")
   for x in d.mitems:
     x = <>Student(Name=x.attrs["Name"] & "foo")
-  d.mget(1).attrs["Name"] = "bar"
+  d[1].attrs["Name"] = "bar"
   echo d
diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim
index 4d2a2a340..4b210c23b 100644
--- a/tests/stdlib/tunittest.nim
+++ b/tests/stdlib/tunittest.nim
@@ -1,4 +1,4 @@
-import unittest
+import unittest, sequtils
 
 
 proc doThings(spuds: var int): int =
diff --git a/tests/template/twrongmapit.nim b/tests/template/twrongmapit.nim
index 0a6d694f6..df695fcd6 100644
--- a/tests/template/twrongmapit.nim
+++ b/tests/template/twrongmapit.nim
@@ -27,6 +27,6 @@ when ATTEMPT == 0:
 # bug #1543
 import sequtils
 
-(var i = @[""];i).mapIt(it)
+(var i = @[""];i).applyIt(it)
 # now works:
 echo "##", i[0], "##"
diff --git a/tests/testament/backend.nim b/tests/testament/backend.nim
index 269835607..671b5c8b7 100644
--- a/tests/testament/backend.nim
+++ b/tests/testament/backend.nim
@@ -8,7 +8,7 @@
 
 import strutils, db_sqlite, os, osproc
 
-var db: TDbConn
+var db: DbConn
 
 proc createDb() =
   db.exec(sql"""
@@ -61,7 +61,7 @@ var
 
 proc `()`(cmd: string{lit}): string = cmd.execProcess.string.strip
 
-proc getMachine*(db: TDbConn): MachineId =
+proc getMachine*(db: DbConn): MachineId =
   var name = "hostname"()
   if name.len == 0:
     name = when defined(posix): getenv"HOSTNAME".string
@@ -76,7 +76,7 @@ proc getMachine*(db: TDbConn): MachineId =
     result = db.insertId(sql"insert into Machine(name, os, cpu) values (?,?,?)",
                          name, system.hostOS, system.hostCPU).MachineId
 
-proc getCommit(db: TDbConn): CommitId =
+proc getCommit(db: DbConn): CommitId =
   const commLen = "commit ".len
   let hash = "git log -n 1"()[commLen..commLen+10]
   let branch = "git symbolic-ref --short HEAD"()
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index d9fafaf7f..3bb18d8a2 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -119,12 +119,21 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
     testSpec r, makeTest("tests/gc" / filename, options &
                   " -d:release -d:useRealtimeGC", cat, actionRun)
 
-  template test(filename: expr): stmt =
+  template testWithoutBoehm(filename: expr): stmt =
     testWithoutMs filename
     testSpec r, makeTest("tests/gc" / filename, options &
                   " --gc:markAndSweep", cat, actionRun)
     testSpec r, makeTest("tests/gc" / filename, options &
                   " -d:release --gc:markAndSweep", cat, actionRun)
+  template test(filename: expr): stmt =
+    testWithoutBoehm filename
+    when not defined(windows):
+      # AR: cannot find any boehm.dll on the net, right now, so disabled
+      # for windows:
+      testSpec r, makeTest("tests/gc" / filename, options &
+                    " --gc:boehm", cat, actionRun)
+      testSpec r, makeTest("tests/gc" / filename, options &
+                    " -d:release --gc:boehm", cat, actionRun)
 
   test "gcemscripten"
   test "growobjcrash"
@@ -136,9 +145,9 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
   test "gcleak4"
   # Disabled because it works and takes too long to run:
   #test "gcleak5"
-  test "weakrefs"
+  testWithoutBoehm "weakrefs"
   test "cycleleak"
-  test "closureleak"
+  testWithoutBoehm "closureleak"
   testWithoutMs "refarrayleak"
 
   test "stackrefleak"
diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim
index 98ccf1170..15960f09a 100644
--- a/tests/testament/htmlgen.nim
+++ b/tests/testament/htmlgen.nim
@@ -109,7 +109,7 @@ div.tabContent.hide { display: none; }
 proc td(s: string): string =
   result = "<td>" & s.substr(0, 200).xmlEncode & "</td>"
 
-proc getCommit(db: TDbConn, c: int): string =
+proc getCommit(db: DbConn, c: int): string =
   var commit = c
   for thisCommit in db.rows(sql"select id from [Commit] order by id desc"):
     if commit == 0: result = thisCommit[0]
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index a5e622010..451bee1d1 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -65,7 +65,7 @@ proc callCompiler(cmdTemplate, filename, options: string,
   let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target],
                        "options", options, "file", filename.quoteShell])
   var p = startProcess(command=c[0], args=c[1.. ^1],
-                       options={poStdErrToStdOut, poUseShell})
+                       options={poStdErrToStdOut, poUsePath})
   let outp = p.outputStream
   var suc = ""
   var err = ""
@@ -215,7 +215,7 @@ proc generatedFile(path, name: string, target: TTarget): string =
 
 proc codegenCheck(test: TTest, check: string, given: var TSpec) =
   try:
-    let (path, name, ext2) = test.name.splitFile
+    let (path, name, _) = test.name.splitFile
     let genFile = generatedFile(path, name, test.target)
     let contents = readFile(genFile).string
     if check[0] == '\\':
@@ -307,7 +307,7 @@ proc testSpec(r: var TResults, test: TTest) =
     let isJsTarget = test.target == targetJS
     var exeFile: string
     if isJsTarget:
-      let (dir, file, ext) = splitFile(tname)
+      let (dir, file, _) = splitFile(tname)
       exeFile = dir / "nimcache" / file & ".js" # *TODO* hardcoded "nimcache"
     else:
       exeFile = changeFileExt(tname, ExeExt)
@@ -352,7 +352,7 @@ proc testSpec(r: var TResults, test: TTest) =
 
 proc testNoSpec(r: var TResults, test: TTest) =
   # does not extract the spec because the file is not supposed to have any
-  let tname = test.name.addFileExt(".nim")
+  #let tname = test.name.addFileExt(".nim")
   inc(r.total)
   let given = callCompiler(cmdTemplate, test.name, test.options, test.target)
   r.addResult(test, "", given.msg, given.err)
@@ -368,7 +368,7 @@ proc testC(r: var TResults, test: TTest) =
     r.addResult(test, "", given.msg, given.err)
   elif test.action == actionRun:
     let exeFile = changeFileExt(test.name, ExeExt)
-    var (buf, exitCode) = execCmdEx(exeFile, options = {poStdErrToStdOut, poUseShell})
+    var (_, exitCode) = execCmdEx(exeFile, options = {poStdErrToStdOut, poUsePath})
     if exitCode != 0: given.err = reExitCodesDiffer
   if given.err == reSuccess: inc(r.passed)
 
diff --git a/web/news.txt b/web/news.txt
index 2b6079620..89e075b6c 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -8,7 +8,11 @@ News
 
   Changes affecting backwards compatibility
   -----------------------------------------
-
+  - ``tables.[]``, ``strtabs.[]``, ``critbits.[]`` **now raise**
+    the ``KeyError`` **exception when the key does not exist**! Use the
+    new ``getOrDefault`` instead to get the old behaviour. Compile all your
+    code with ``-d:nimTableGet`` to get a listing of where your code
+    uses ``[]``!
   - The ``rawsockets`` module has been renamed to ``nativesockets`` to avoid
     confusion with TCP/IP raw sockets, so ``newNativeSocket`` should be used
     instead of ``newRawSocket``.
@@ -68,10 +72,10 @@ News
     * ``libeay32.dll``: Split into ``libeay32.dll`` and ``libeay64.dll``.
 
     Compile with ``-d:nimOldDLLs`` to make the stdlib use the old DLL names.
-  - Nim VM now treats objects as nkObjConstr nodes, and not nkPar nodes as it
-    was previously. Macros that generate nkPar nodes when object is expected are
-    likely to break. Macros that expect nkPar nodes to which objects are passed
-    are likely to break as well.
+  - Nim VM now treats objects as ``nkObjConstr`` nodes, and not ``nkPar`` nodes
+    as it was previously. Macros that generate ``nkPar`` nodes when object is
+    expected are likely to break. Macros that expect ``nkPar`` nodes to which
+    objects are passed are likely to break as well.
   - Base methods now need to be annotated with the ``base`` pragma. This makes
     multi methods less error-prone to use with the effect system.
   - Nim's parser directive ``#!`` is now ``#?`` in order to produce no conflicts
@@ -86,8 +90,14 @@ News
 
       echo f(0, "abc")
   - The ``ftpclient`` module is now deprecated in favour of the
-    ``asyncdispatch`` module.
-
+    ``asyncftpclient`` module.
+  - In sequtils.nim renamed ``repeat`` function to ``cycle`` (concatenating
+    a sequence by itself the given times), and also introduced ``repeat``,
+    which repeats an element the given times.
+  - The function ``map`` is moved to sequtils.nim. The inplace ``map`` version
+    is renamed to ``apply``.
+  - The template ``mapIt`` now doesn't require the result's type parameter.
+    Also the inplace ``mapIt`` is renamed to ``apply``.
 
   Library Additions
   -----------------
diff --git a/web/website.ini b/web/website.ini
index dcfea8bf4..0a2117564 100644
--- a/web/website.ini
+++ b/web/website.ini
@@ -34,8 +34,8 @@ doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt"
 doc: "nimfix.txt;nimsuggest.txt;nep1.txt;nims.txt"
 pdf: "manual.txt;lib;tut1;tut2;nimc;niminst;gc"
 srcdoc2: "system.nim;system/nimscript;pure/ospaths"
-srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned"
-srcdoc2: "impure/re;pure/sockets;pure/typetraits"
+srcdoc2: "core/macros;pure/marshal;core/typeinfo"
+srcdoc2: "impure/re;pure/typetraits"
 srcdoc2: "pure/concurrency/threadpool.nim;pure/concurrency/cpuinfo.nim"
 srcdoc: "system/threads.nim;system/channels.nim;js/dom"
 srcdoc2: "pure/os;pure/strutils;pure/math;pure/matchers;pure/algorithm"
@@ -52,12 +52,13 @@ srcdoc2: "pure/json;pure/base64;pure/scgi"
 srcdoc2: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
 srcdoc2: "pure/collections/intsets;pure/collections/queues;pure/encodings"
 srcdoc2: "pure/events;pure/collections/sequtils;pure/cookies"
-srcdoc2: "pure/ftpclient;pure/memfiles;pure/subexes;pure/collections/critbits"
-srcdoc2: "pure/asyncio;pure/actors;core/locks;pure/oids;pure/endians;pure/uri"
+srcdoc2: "pure/memfiles;pure/subexes;pure/collections/critbits"
+srcdoc2: "deprecated/pure/asyncio;deprecated/pure/actors;core/locks;pure/oids;pure/endians;pure/uri"
 srcdoc2: "pure/nimprof;pure/unittest;packages/docutils/highlite"
 srcdoc2: "packages/docutils/rst;packages/docutils/rstast"
 srcdoc2: "packages/docutils/rstgen;pure/logging;pure/asyncdispatch;pure/asyncnet"
-srcdoc2: "pure/rawsockets;pure/asynchttpserver;pure/net;pure/selectors;pure/future"
+srcdoc2: "deprecated/pure/rawsockets;pure/asynchttpserver;pure/net;pure/selectors;pure/future"
+srcdoc2: "deprecated/pure/ftpclient"
 srcdoc2: "pure/asyncfile"
 srcdoc2: "pure/md5;pure/rationals"
 srcdoc2: "posix/posix"