summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--changelog.md30
-rw-r--r--compiler/ccgexprs.nim31
-rw-r--r--compiler/cgen.nim7
-rw-r--r--compiler/commands.nim4
-rw-r--r--compiler/docgen.nim61
-rw-r--r--compiler/guards.nim8
-rw-r--r--compiler/jsgen.nim8
-rw-r--r--compiler/main.nim11
-rw-r--r--compiler/options.nim1
-rw-r--r--compiler/pluginsupport.nim5
-rw-r--r--compiler/semfold.nim14
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/semtypes.nim10
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--compiler/transf.nim6
-rw-r--r--compiler/types.nim12
-rw-r--r--compiler/vmgen.nim6
-rw-r--r--doc/advopt.txt3
-rw-r--r--doc/basicopt.txt1
-rw-r--r--doc/lib.rst7
-rw-r--r--doc/manual/generics.txt54
-rw-r--r--doc/manual/pragmas.txt8
-rw-r--r--doc/manual/type_sections.txt3
-rw-r--r--doc/tut1.rst3
-rw-r--r--doc/tut2.rst17
-rw-r--r--examples/cross_calculator/ios/resources/ui/NRViewController.xib2
-rw-r--r--examples/cross_calculator/lazarus/unit1.pas2
-rw-r--r--examples/cross_calculator/nim_commandline/nim.cfg2
-rw-r--r--examples/cross_calculator/readme.txt2
-rw-r--r--examples/cross_todo/nim_backend/backend.nim66
-rw-r--r--examples/cross_todo/nim_backend/testbackend.nim13
-rw-r--r--examples/cross_todo/nim_commandline/nim.cfg2
-rw-r--r--examples/cross_todo/nim_commandline/nimtodo.nim56
-rw-r--r--examples/cross_todo/nim_commandline/readme.txt2
-rw-r--r--examples/cross_todo/readme.txt2
-rw-r--r--examples/keyval.nim3
-rw-r--r--examples/readme.txt2
-rw-r--r--examples/talk/dsl.nim10
-rw-r--r--examples/talk/formatoptimizer.nim6
-rw-r--r--examples/talk/quasiquote.nim2
-rw-r--r--examples/talk/tags.nim3
-rw-r--r--koch.nim4
-rw-r--r--lib/core/macros.nim75
-rw-r--r--lib/deprecated/pure/rawsockets.nim4
-rw-r--r--lib/pure/asynchttpserver.nim271
-rw-r--r--lib/pure/asyncmacro.nim30
-rw-r--r--lib/pure/browsers.nim20
-rw-r--r--lib/pure/collections/sequtils.nim54
-rw-r--r--lib/pure/collections/sharedstrings.nim4
-rw-r--r--lib/pure/cookies.nim9
-rw-r--r--lib/pure/future.nim2
-rw-r--r--lib/pure/gentabs.nim211
-rw-r--r--lib/pure/ioselectors.nim1
-rw-r--r--lib/pure/json.nim4
-rw-r--r--lib/pure/numeric.nim87
-rw-r--r--lib/pure/os.nim20
-rw-r--r--lib/pure/osproc.nim2
-rw-r--r--lib/pure/parseutils.nim60
-rw-r--r--lib/pure/poly.nim371
-rw-r--r--lib/pure/romans.nim59
-rw-r--r--lib/pure/strutils.nim24
-rw-r--r--lib/pure/typetraits.nim2
-rw-r--r--lib/pure/uri.nim37
-rw-r--r--lib/system.nim50
-rw-r--r--lib/system/atomics.nim20
-rw-r--r--lib/system/endb.nim2
-rw-r--r--lib/system/excpt.nim85
-rw-r--r--lib/system/gc2.nim2
-rw-r--r--lib/system/sysspawn.nim4
-rw-r--r--lib/system/sysstr.nim61
-rw-r--r--tests/async/tasyncall.nim9
-rw-r--r--tests/async/tasyncsend4757.nim15
-rw-r--r--tests/async/tnewasyncudp.nim2
-rw-r--r--tests/ccgbugs/trefseqsort.nim33
-rw-r--r--tests/cpp/tasync_cpp.nim2
-rw-r--r--tests/cpp/tcasts.nim10
-rw-r--r--tests/cpp/tcovariancerules.nim2
-rw-r--r--tests/cpp/tcppraise.nim2
-rw-r--r--tests/cpp/tdont_init_instantiation.nim2
-rw-r--r--tests/cpp/tembarrassing_generic_failure.nim1
-rw-r--r--tests/cpp/temitlist.nim2
-rw-r--r--tests/cpp/tempty_generic_obj.nim2
-rw-r--r--tests/cpp/tgen_prototype_for_importc.nim2
-rw-r--r--tests/cpp/tget_subsystem.nim2
-rw-r--r--tests/cpp/tnativesockets.nim2
-rw-r--r--tests/cpp/treturn_array.nim3
-rw-r--r--tests/cpp/tsigbreak.nim2
-rw-r--r--tests/cpp/tstaticvar_via_typedesc.nim2
-rw-r--r--tests/cpp/ttemplatetype.nim4
-rw-r--r--tests/cpp/tthread_createthread.nim1
-rw-r--r--tests/cpp/ttypeinfo.nim2
-rw-r--r--tests/cpp/ttypeinfo2.nim2
-rw-r--r--tests/cpp/tvector_iterator.nim2
-rw-r--r--tests/cpp/tvectorseq.nim2
-rw-r--r--tests/errmsgs/tmake_tuple_visible.nim23
-rw-r--r--tests/exprs/tstmtexprs.nim21
-rw-r--r--tests/generics/toverloading_typedesc.nim1
-rw-r--r--tests/misc/tromans.nim71
-rw-r--r--tests/overload/tstatic_with_converter.nim47
-rw-r--r--tests/parser/tpostexprblocks.nim178
-rw-r--r--tests/rational/trat_init.nim10
-rw-r--r--tests/stdlib/thttpclient.nim1
-rw-r--r--tests/test_nimscript.nims1
-rw-r--r--tests/testament/categories.nim20
-rw-r--r--tests/testament/specs.nim4
-rw-r--r--tests/testament/tester.nim207
-rw-r--r--tests/types/tinheritref.nim25
-rw-r--r--tests/types/tyet_another_generic_regression.nim13
-rw-r--r--tests/vm/tnimnode.nim12
-rw-r--r--todo.txt5
-rw-r--r--tools/niminst/buildsh.tmpl2
-rw-r--r--tools/niminst/makefile.tmpl22
-rw-r--r--tools/nimweb.nim2
-rw-r--r--web/website.ini2
115 files changed, 1291 insertions, 1554 deletions
diff --git a/.gitignore b/.gitignore
index 5476e173f..fc090130b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,3 +57,7 @@ dist/
 # Private directories and files (IDEs)
 .*/
 ~*
+
+# testament cruft
+testresults/
+test.txt
diff --git a/changelog.md b/changelog.md
index 77e5a29b5..14191e85f 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,9 +2,7 @@
 
 ### Changes affecting backwards compatibility
 
-- Removed basic2d/basic3d out of the stdlib and into Nimble packages.
-  These packages deprecated however, use the ``glm``, ``arraymancer``, ``neo``
-  or another package.
+
 - Arrays of char cannot be converted to ``cstring`` anymore, pointers to
   arrays of char can! This means ``$`` for arrays can finally exist
   in ``system.nim`` and do the right thing.
@@ -16,7 +14,6 @@
   module.
 - The overloading rules changed slightly so that constrained generics are
   preferred over unconstrained generics. (Bug #6526)
-- Removed libuv out of the stdlib and into Nimble packages.
 - It is now possible to forward declare object types so that mutually
   recursive types can be created across module boundaries. See
   [package level objects](https://nim-lang.org/docs/manual.html#package-level-objects)
@@ -40,8 +37,6 @@
 - Added ``typetraits.$`` as an alias for ``typetraits.name``.
 - ``os.getEnv`` now takes an optional ``default`` parameter that tells ``getEnv``
   what to return if the environment variable does not exist.
-- Removed PDCurses wrapper from the stdlib and published it as a separate
-  Nimble package.
 - Bodies of ``for`` loops now get their own scope:
 
 .. code-block:: nim
@@ -74,3 +69,26 @@ This now needs to be written as:
   var a = -5
   for i in a..b:
     echo i
+
+- ``formatFloat``/``formatBiggestFloat`` now support formatting floats with zero
+  precision digits. The previous ``precision = 0`` behavior (default formatting)
+  is now available via ``precision = -1``.
+- The ``nim doc`` command is now an alias for ``nim doc2``, the second version of
+  the documentation generator. The old version 1 can still be accessed
+  via the new ``nim doc0`` command.
+- Added ``system.getStackTraceEntries`` that allows you to access the stack
+  trace in a structured manner without string parsing.
+- Added ``sequtils.mapLiterals`` for easier construction of array and tuple
+  literals.
+- Added ``parseutils.parseSaturatedNatural``.
+- Moved from stdlib into Nimble packages:
+  - [``basic2d``](https://github.com/nim-lang/basic2d)
+    _deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
+  - [``basic3d``](https://github.com/nim-lang/basic3d)
+    _deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
+  - [``gentabs``](https://github.com/lcrees/gentabs)
+  - [``libuv``](https://github.com/lcrees/libuv)
+  - [``numeric``](https://github.com/lcrees/polynumeric)
+  - [``poly``](https://github.com/lcrees/polynumeric)
+  - [``pdcurses``](https://github.com/lcrees/pdcurses)
+  - [``romans``](https://github.com/lcrees/romans)
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 5ea719839..d7b8ec667 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -798,8 +798,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
 
 proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
 
-proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym;
-                   origTy: PType) =
+proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
   var test, u, v: TLoc
   for i in countup(1, sonsLen(e) - 1):
     var it = e.sons[i]
@@ -811,12 +810,10 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym;
     assert(disc.kind == nkSym)
     initLoc(test, locNone, it, OnStack)
     initLocExpr(p, it.sons[1], u)
-    var o = obj
-    let d = lookupFieldAgain(p, origTy, disc.sym, o)
     initLoc(v, locExpr, disc, OnUnknown)
-    v.r = o
+    v.r = obj
     v.r.add(".")
-    v.r.add(d.loc.r)
+    v.r.add(disc.sym.loc.r)
     genInExprAux(p, it, u, v, test)
     let id = nodeTableTestOrSet(p.module.dataCache,
                                newStrNode(nkStrLit, field.name.s), p.module.labels)
@@ -842,7 +839,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
     if field.loc.r == nil: fillObjectFields(p.module, ty)
     if field.loc.r == nil:
       internalError(e.info, "genCheckedRecordField") # generate the checks:
-    genFieldCheck(p, e, r, field, ty)
+    genFieldCheck(p, e, r, field)
     add(r, rfmt(nil, ".$1", field.loc.r))
     putIntoDest(p, d, e.sons[0], r, a.storage)
   else:
@@ -1226,7 +1223,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     if field.loc.r == nil: fillObjectFields(p.module, ty)
     if field.loc.r == nil: internalError(e.info, "genObjConstr")
     if it.len == 3 and optFieldCheck in p.options:
-      genFieldCheck(p, it.sons[2], r, field, ty)
+      genFieldCheck(p, it.sons[2], r, field)
     add(tmp2.r, ".")
     add(tmp2.r, field.loc.r)
     tmp2.k = locTemp
@@ -1645,8 +1642,14 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
     putIntoDest(p, d, e, "(($1) ($2))" %
         [getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)], a.storage)
   else:
-    putIntoDest(p, d, e, "(($1) ($2))" %
-        [getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
+    let srcTyp = skipTypes(e.sons[1].typ, abstractRange)
+    # C++ does not like direct casts from pointer to shorter integral types
+    if srcTyp.kind in {tyPtr, tyPointer} and etyp.kind in IntegralTypes:
+      putIntoDest(p, d, e, "(($1) (ptrdiff_t) ($2))" %
+          [getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
+    else:
+      putIntoDest(p, d, e, "(($1) ($2))" %
+          [getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
 
 proc genCast(p: BProc, e: PNode, d: var TLoc) =
   const ValueTypes = {tyFloat..tyFloat128, tyTuple, tyObject, tyArray}
@@ -2275,7 +2278,13 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
       result = "{{$1}}" % [genTypeInfo(p.module, t, info)]
     else:
       result = rope"{}"
-  of tyArray, tyTuple: result = rope"{}"
+  of tyTuple:
+    result = rope"{"
+    for i in 0 ..< typ.len:
+      if i > 0: result.add ", "
+      result.add getDefaultValue(p, typ.sons[i], info)
+    result.add "}"
+  of tyArray: result = rope"{}"
   of tySet:
     if mapType(t) == ctArray: result = rope"{}"
     else: result = rope"0"
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 2a979e8c5..07c2824d0 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -896,14 +896,15 @@ proc addIntTypes(result: var Rope) {.inline.} =
     platform.CPU[targetCPU].intSize.rope])
 
 proc getCopyright(cfile: Cfile): Rope =
+  const copyrightYear = "2017"
   if optCompileOnly in gGlobalOptions:
     result = ("/* Generated by Nim Compiler v$1 */$N" &
-        "/*   (c) " & CompileDate.substr(0, 3) & " Andreas Rumpf */$N" &
+        "/*   (c) " & copyrightYear & " Andreas Rumpf */$N" &
         "/* The generated code is subject to the original license. */$N") %
         [rope(VersionAsString)]
   else:
     result = ("/* Generated by Nim Compiler v$1 */$N" &
-        "/*   (c) " & CompileDate.substr(0, 3) & " Andreas Rumpf */$N" &
+        "/*   (c) " & copyrightYear & " Andreas Rumpf */$N" &
         "/* The generated code is subject to the original license. */$N" &
         "/* Compiled for: $2, $3, $4 */$N" &
         "/* Command for C compiler:$n   $5 */$N") %
@@ -1292,7 +1293,7 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
 
 proc writeHeader(m: BModule) =
   var result = ("/* Generated by Nim Compiler v$1 */$N" &
-        "/*   (c) " & CompileDate.substr(0, 3) & " Andreas Rumpf */$N" &
+        "/*   (c) 2017 Andreas Rumpf */$N" &
         "/* The generated code is subject to the original license. */$N") %
         [rope(VersionAsString)]
 
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 71de28e09..11a66cf55 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -53,8 +53,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
 # implementation
 
 const
-  HelpMessage = "Nim Compiler Version $1 (" & CompileDate & ") [$2: $3]\n" &
-      "Copyright (c) 2006-" & CompileDate.substr(0, 3) & " by Andreas Rumpf\n"
+  HelpMessage = "Nim Compiler Version $1 [$2: $3]\n" &
+      "Copyright (c) 2006-2017 by Andreas Rumpf\n"
 
 const
   Usage = slurp"../doc/basicopt.txt".replace("//", "")
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index b31e9ce75..8978052e2 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -608,6 +608,52 @@ proc generateJson*(d: PDoc, n: PNode) =
       generateJson(d, lastSon(n.sons[0]))
   else: discard
 
+proc genTagsItem(d: PDoc, n, nameNode: PNode, k: TSymKind): string =
+  var
+    name = getName(d, nameNode)
+
+  result = name & "\n"
+
+proc generateTags*(d: PDoc, n: PNode, r: var Rope) =
+  case n.kind
+  of nkCommentStmt:
+    if n.comment != nil and startsWith(n.comment, "##"):
+      let stripped = n.comment.substr(2).strip
+      r.add stripped
+  of nkProcDef:
+    when useEffectSystem: documentRaises(n)
+    r.add genTagsItem(d, n, n.sons[namePos], skProc)
+  of nkFuncDef:
+    when useEffectSystem: documentRaises(n)
+    r.add genTagsItem(d, n, n.sons[namePos], skFunc)
+  of nkMethodDef:
+    when useEffectSystem: documentRaises(n)
+    r.add genTagsItem(d, n, n.sons[namePos], skMethod)
+  of nkIteratorDef:
+    when useEffectSystem: documentRaises(n)
+    r.add genTagsItem(d, n, n.sons[namePos], skIterator)
+  of nkMacroDef:
+    r.add genTagsItem(d, n, n.sons[namePos], skMacro)
+  of nkTemplateDef:
+    r.add genTagsItem(d, n, n.sons[namePos], skTemplate)
+  of nkConverterDef:
+    when useEffectSystem: documentRaises(n)
+    r.add genTagsItem(d, n, n.sons[namePos], skConverter)
+  of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
+    for i in countup(0, sonsLen(n) - 1):
+      if n.sons[i].kind != nkCommentStmt:
+        # order is always 'type var let const':
+        r.add genTagsItem(d, n.sons[i], n.sons[i].sons[0],
+                succ(skType, ord(n.kind)-ord(nkTypeSection)))
+  of nkStmtList:
+    for i in countup(0, sonsLen(n) - 1):
+      generateTags(d, n.sons[i], r)
+  of nkWhenStmt:
+    # generate documentation for the first branch only:
+    if not checkForFalse(n.sons[0].sons[0]):
+      generateTags(d, lastSon(n.sons[0]), r)
+  else: discard
+
 proc genSection(d: PDoc, kind: TSymKind) =
   const sectionNames: array[skModule..skTemplate, string] = [
     "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Funcs",
@@ -745,6 +791,21 @@ proc commandJson*() =
     #echo getOutFile(gProjectFull, JsonExt)
     writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false)
 
+proc commandTags*() =
+  var ast = parseFile(gProjectMainIdx, newIdentCache())
+  if ast == nil: return
+  var d = newDocumentor(gProjectFull, options.gConfigVars)
+  d.hasToc = true
+  var
+    content: Rope
+  generateTags(d, ast, content)
+
+  if optStdout in gGlobalOptions:
+    writeRope(stdout, content)
+  else:
+    #echo getOutFile(gProjectFull, TagsExt)
+    writeRope(content, getOutFile(gProjectFull, TagsExt), useWarning = false)
+
 proc commandBuildIndex*() =
   var content = mergeIndexes(gProjectFull).rope
 
diff --git a/compiler/guards.nim b/compiler/guards.nim
index 3805320ae..a5e6058c9 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -52,7 +52,7 @@ proc isLet(n: PNode): bool =
 
 proc isVar(n: PNode): bool =
   n.kind == nkSym and n.sym.kind in {skResult, skVar} and
-      {sfGlobal, sfAddrTaken} * n.sym.flags == {}
+      {sfAddrTaken} * n.sym.flags == {}
 
 proc isLetLocation(m: PNode, isApprox: bool): bool =
   # consider: 'n[].kind' --> we really need to support 1 deref op even if this
@@ -768,8 +768,10 @@ macro `=~`(x: PNode, pat: untyped): bool =
 
   var conds = newTree(nnkBracket)
   m(x, pat, conds)
-  result = nestList(!"and", conds)
-
+  when declared(macros.toNimIdent):
+    result = nestList(toNimIdent"and", conds)
+  else:
+    result = nestList(!"and", conds)
 
 proc isMinusOne(n: PNode): bool =
   n.kind in {nkCharLit..nkUInt64Lit} and n.intVal == -1
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 8be53f11d..4e0d4e28b 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -376,8 +376,8 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
     ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
     ["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
-    ["divInt", "", "divInt($1, $2)", "Math.floor($1 / $2)"], # DivI
-    ["modInt", "", "modInt($1, $2)", "Math.floor($1 % $2)"], # ModI
+    ["divInt", "", "divInt($1, $2)", "Math.trunc($1 / $2)"], # DivI
+    ["modInt", "", "modInt($1, $2)", "Math.trunc($1 % $2)"], # ModI
     ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # Succ
     ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # Pred
     ["", "", "($1 + $2)", "($1 + $2)"], # AddF64
@@ -444,8 +444,8 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["toU32", "toU32", "toU32($1)", "toU32($1)"], # toU32
     ["", "", "$1", "$1"],     # ToFloat
     ["", "", "$1", "$1"],     # ToBiggestFloat
-    ["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt
-    ["", "", "Math.floor($1)", "Math.floor($1)"], # ToBiggestInt
+    ["", "", "Math.trunc($1)", "Math.trunc($1)"], # ToInt
+    ["", "", "Math.trunc($1)", "Math.trunc($1)"], # ToBiggestInt
     ["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"],
     ["nimBoolToStr", "nimBoolToStr", "nimBoolToStr($1)", "nimBoolToStr($1)"],
     ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"],
diff --git a/compiler/main.nim b/compiler/main.nim
index 450542c4c..1e94a6ca0 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -186,12 +186,12 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
   of "php":
     gCmd = cmdCompileToPHP
     commandCompileToJS(graph, cache)
-  of "doc":
+  of "doc0":
     wantMainModule()
     gCmd = cmdDoc
     loadConfigs(DocConfig, cache)
     commandDoc()
-  of "doc2":
+  of "doc2", "doc":
     gCmd = cmdDoc
     loadConfigs(DocConfig, cache)
     defineSymbol("nimdoc")
@@ -217,6 +217,13 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
     wantMainModule()
     defineSymbol("nimdoc")
     commandDoc2(graph, cache, true)
+  of "ctags":
+    wantMainModule()
+    gCmd = cmdDoc
+    loadConfigs(DocConfig, cache)
+    wantMainModule()
+    defineSymbol("nimdoc")
+    commandTags()
   of "buildindex":
     gCmd = cmdDoc
     loadConfigs(DocConfig, cache)
diff --git a/compiler/options.nim b/compiler/options.nim
index 312e4539a..eec9ce448 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -162,6 +162,7 @@ const
   RodExt* = "rod"
   HtmlExt* = "html"
   JsonExt* = "json"
+  TagsExt* = "tags"
   TexExt* = "tex"
   IniExt* = "ini"
   DefaultConfig* = "nim.cfg"
diff --git a/compiler/pluginsupport.nim b/compiler/pluginsupport.nim
index 19a0bc84d..f67942c97 100644
--- a/compiler/pluginsupport.nim
+++ b/compiler/pluginsupport.nim
@@ -7,8 +7,9 @@
 #    distribution, for details about the copyright.
 #
 
-## Plugin support for the Nim compiler. Right now they
-## need to be build with the compiler, no DLL support.
+## Plugin support for the Nim compiler. Right now plugins
+## need to be built with the compiler only: plugins using 
+## DLLs or the FFI will not work.
 
 import ast, semdata, idents
 
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 089e66abd..1e7c0aa9e 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -606,13 +606,13 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
       if a == nil: return nil
       result.sons[i] = a
     incl(result.flags, nfAllConst)
-  of nkObjConstr:
-    result = copyTree(n)
-    for i in countup(1, sonsLen(n) - 1):
-      var a = getConstExpr(m, n.sons[i].sons[1])
-      if a == nil: return nil
-      result.sons[i].sons[1] = a
-    incl(result.flags, nfAllConst)
+  #of nkObjConstr:
+  #  result = copyTree(n)
+  #  for i in countup(1, sonsLen(n) - 1):
+  #    var a = getConstExpr(m, n.sons[i].sons[1])
+  #    if a == nil: return nil
+  #    result.sons[i].sons[1] = a
+  #  incl(result.flags, nfAllConst)
   of nkPar:
     # tuple constructor
     result = copyTree(n)
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 0803b99ec..0d0f2ee82 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -127,7 +127,7 @@ proc evalTypeTrait(traitCall: PNode, operand: PType, context: PSym): PNode =
   of "not":
     return typeWithSonsResult(tyNot, @[operand])
   of "name":
-    result = newStrNode(nkStrLit, operand.typeToString(preferName))
+    result = newStrNode(nkStrLit, operand.typeToString(preferTypeName))
     result.typ = newType(tyString, context)
     result.info = traitCall.info
   of "arity":
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 92a36857a..b032557b7 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1420,9 +1420,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     else: result = semGeneric(c, n, s, prev)
   of nkDotExpr:
     let typeExpr = semExpr(c, n)
-    if typeExpr.typ.kind == tyFromExpr:
-      return typeExpr.typ
-    if typeExpr.typ.kind != tyTypeDesc:
+    if typeExpr.typ.isNil:
+      localError(n.info, "object constructor needs an object type;" &
+          " for named arguments use '=' instead of ':'")
+      result = errorType(c)
+    elif typeExpr.typ.kind == tyFromExpr:
+      result = typeExpr.typ
+    elif typeExpr.typ.kind != tyTypeDesc:
       localError(n.info, errTypeExpected)
       result = errorType(c)
     else:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 97b18306b..3d0b0ed3d 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1385,7 +1385,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
     # XXX: This is very hacky. It should be moved back into liftTypeParam
     if x.kind in {tyGenericInst, tyArray} and
        c.calleeSym != nil and
-       c.calleeSym.kind in {skProc, skFunc}:
+       c.calleeSym.kind in {skProc, skFunc} and c.call != nil:
       let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f)
       return typeRel(c, inst, a)
 
@@ -1613,7 +1613,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
           if not exprStructuralEquivalent(f.n, aOrig.n):
             result = isNone
         if result != isNone: put(c, f, aOrig)
-      elif aOrig.n != nil:
+      elif aOrig.n != nil and aOrig.n.typ != nil:
         result = typeRel(c, f.lastSon, aOrig.n.typ)
         if result != isNone:
           var boundType = newTypeWithSons(c.c, tyStatic, @[aOrig.n.typ])
diff --git a/compiler/transf.nim b/compiler/transf.nim
index baf801cbf..69c526951 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -365,7 +365,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
       # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
       n.sons[0].sons[0] = m.sons[0]
       result = PTransNode(n.sons[0])
-      if n.typ.kind != tyOpenArray:
+      if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
         PNode(result).typ = n.typ
   of nkHiddenStdConv, nkHiddenSubConv, nkConv:
     var m = n.sons[0].sons[1]
@@ -373,13 +373,13 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
       # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
       n.sons[0].sons[1] = m.sons[0]
       result = PTransNode(n.sons[0])
-      if n.typ.kind != tyOpenArray:
+      if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
         PNode(result).typ = n.typ
   else:
     if n.sons[0].kind == a or n.sons[0].kind == b:
       # addr ( deref ( x )) --> x
       result = PTransNode(n.sons[0].sons[0])
-      if n.typ.kind != tyOpenArray:
+      if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
         PNode(result).typ = n.typ
 
 proc generateThunk(prc: PNode, dest: PType): PNode =
diff --git a/compiler/types.nim b/compiler/types.nim
index b49640b1f..369d918fd 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -14,7 +14,8 @@ import
 
 type
   TPreferedDesc* = enum
-    preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
+    preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg,
+    preferTypeName
 
 proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
 template `$`*(typ: PType): string = typeToString(typ)
@@ -394,7 +395,7 @@ const
     "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
     "void"]
 
-const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
+const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo, preferGenericArg}
 
 template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
   tc.sons.safeAdd concrete
@@ -420,7 +421,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
        sfAnon notin t.sym.flags:
     if t.kind == tyInt and isIntLit(t):
       result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
-    elif prefer == preferName or t.sym.owner.isNil:
+    elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
       result = t.sym.name.s
       if t.kind == tyGenericParam and t.sons != nil and t.sonsLen > 0:
         result.add ": "
@@ -518,7 +519,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     result = "openarray[" & typeToString(t.sons[0]) & ']'
   of tyDistinct:
     result = "distinct " & typeToString(t.sons[0],
-      if prefer == preferModuleInfo: preferModuleInfo else: preferName)
+      if prefer == preferModuleInfo: preferModuleInfo else: preferTypeName)
   of tyTuple:
     # we iterate over t.sons here, because t.n may be nil
     if t.n != nil:
@@ -532,7 +533,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     elif sonsLen(t) == 0:
       result = "tuple[]"
     else:
-      result = "("
+      if prefer == preferTypeName: result = "("
+      else: result = "tuple of ("
       for i in countup(0, sonsLen(t) - 1):
         add(result, typeToString(t.sons[i]))
         if i < sonsLen(t) - 1: add(result, ", ")
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index b869be113..8f0c72e45 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1773,8 +1773,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddrNode, flags)
   of nkIfStmt, nkIfExpr: genIf(c, n, dest)
   of nkWhenStmt:
-      # This is "when nimvm" node. Chose the first branch.
-      gen(c, n.sons[0].sons[1], dest)
+    # This is "when nimvm" node. Chose the first branch.
+    gen(c, n.sons[0].sons[1], dest)
   of nkCaseStmt: genCase(c, n, dest)
   of nkWhileStmt:
     unused(n, dest)
@@ -1810,7 +1810,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   of nkVarSection, nkLetSection:
     unused(n, dest)
     genVarSection(c, n)
-  of declarativeDefs:
+  of declarativeDefs, nkMacroDef:
     unused(n, dest)
   of nkLambdaKinds:
     #let s = n.sons[namePos].sym
diff --git a/doc/advopt.txt b/doc/advopt.txt
index fb6fd719b..60fd081b8 100644
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -7,7 +7,8 @@ Advanced commands:
   //rst2html                convert a reStructuredText file to HTML
   //rst2tex                 convert a reStructuredText file to TeX
   //jsondoc                 extract the documentation to a json file
-  //jsondoc2                extract documentation to a json file (uses doc2)
+  //jsondoc2                extract the documentation to a json file (uses doc2)
+  //ctags                   create a tags file
   //buildIndex              build an index for the whole documentation
   //run                     run the project (with Tiny C backend; buggy!)
   //genDepend               generate a DOT file containing the
diff --git a/doc/basicopt.txt b/doc/basicopt.txt
index 3b0271077..4db2d5af7 100644
--- a/doc/basicopt.txt
+++ b/doc/basicopt.txt
@@ -5,7 +5,6 @@
 Command:
   //compile, c                compile project with default code generator (C)
   //doc                       generate the documentation for inputfile
-  //doc2                      generate the documentation for inputfile
 
 Arguments:
   arguments are passed to the program being run (if --run option is selected)
diff --git a/doc/lib.rst b/doc/lib.rst
index 069fcc87c..6dd3f5bea 100644
--- a/doc/lib.rst
+++ b/doc/lib.rst
@@ -64,7 +64,6 @@ Core
 * `cpuinfo <cpuinfo.html>`_
   This module implements procs to determine the number of CPUs / cores.
 
-
 Collections and algorithms
 --------------------------
 
@@ -182,6 +181,12 @@ Generic Operating System Services
   This module implements asynchronous file reading and writing using
   ``asyncdispatch``.
 
+* `distros <distros.html>`_
+  This module implements the basics for OS distribution ("distro") detection and the OS's native package manager.
+  Its primary purpose is to produce output for Nimble packages, but it also contains the widely used **Distribution** enum
+  that is useful for writing platform specific code.
+
+
 Math libraries
 --------------
 
diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt
index cceea33c0..1ba62bb5c 100644
--- a/doc/manual/generics.txt
+++ b/doc/manual/generics.txt
@@ -9,26 +9,26 @@ The following example shows a generic binary tree can be modelled:
 
 .. code-block:: nim
   type
-    BinaryTreeObj[T] = object    # BinaryTreeObj is a generic type with
-                                 # with generic param ``T``
-      le, ri: BinaryTree[T]      # left and right subtrees; may be nil
-      data: T                    # the data stored in a node
-    BinaryTree[T] = ref BinaryTreeObj[T] # a shorthand for notational convenience
+    BinaryTree*[T] = ref object # BinaryTree is a generic type with
+                                # generic param ``T``
+      le, ri: BinaryTree[T]     # left and right subtrees; may be nil
+      data: T                   # the data stored in a node
 
-  proc newNode[T](data: T): BinaryTree[T] = # constructor for a node
+  proc newNode*[T](data: T): BinaryTree[T] =
+    # constructor for a node
     new(result)
     result.data = data
 
-  proc add[T](root: var BinaryTree[T], n: BinaryTree[T]) =
+  proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) =
+    # insert a node into the tree
     if root == nil:
       root = n
     else:
       var it = root
       while it != nil:
-        var c = cmp(it.data, n.data) # compare the data items; uses
-                                     # the generic ``cmp`` proc that works for
-                                     # any type that has a ``==`` and ``<``
-                                     # operator
+        # compare the data items; uses the generic ``cmp`` proc
+        # that works for any type that has a ``==`` and ``<`` operator
+        var c = cmp(it.data, n.data)
         if c < 0:
           if it.le == nil:
             it.le = n
@@ -40,20 +40,28 @@ The following example shows a generic binary tree can be modelled:
             return
           it = it.ri
 
-  iterator inorder[T](root: BinaryTree[T]): T =
-    # inorder traversal of a binary tree
-    # recursive iterators are not yet implemented, so this does not work in
-    # the current compiler!
-    if root.le != nil: yield inorder(root.le)
-    yield root.data
-    if root.ri != nil: yield inorder(root.ri)
+  proc add*[T](root: var BinaryTree[T], data: T) =
+    # convenience proc:
+    add(root, newNode(data))
+
+  iterator preorder*[T](root: BinaryTree[T]): T =
+    # Preorder traversal of a binary tree.
+    # Since recursive iterators are not yet implemented,
+    # this uses an explicit stack (which is more efficient anyway):
+    var stack: seq[BinaryTree[T]] = @[root]
+    while stack.len > 0:
+      var n = stack.pop()
+      while n != nil:
+        yield n.data
+        add(stack, n.ri)  # push right subtree onto the stack
+        n = n.le          # and follow the left pointer
 
   var
-    root: BinaryTree[string]  # instantiate a BinaryTree with the type string
-  add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and
-  add(root, newNode("world")) # ``add``
-  for str in inorder(root):
-    writeLine(stdout, str)
+    root: BinaryTree[string] # instantiate a BinaryTree with ``string``
+  add(root, newNode("hello")) # instantiates ``newNode`` and ``add``
+  add(root, "world")          # instantiates the second ``add`` proc
+  for str in preorder(root):
+    stdout.writeLine(str)
 
 
 Is operator
diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt
index db7ce7e63..835b6909d 100644
--- a/doc/manual/pragmas.txt
+++ b/doc/manual/pragmas.txt
@@ -102,6 +102,14 @@ collector to not consider objects of this type as part of a cycle:
       left, right: Node
       data: string
 
+Or if we directly use a ref object:
+
+.. code-block:: nim
+  type
+    Node = ref object {.acyclic, final.}
+      left, right: Node
+      data: string
+
 In the example a tree structure is declared with the ``Node`` type. Note that
 the type definition is recursive and the GC has to assume that objects of
 this type may form a cyclic graph. The ``acyclic`` pragma passes the
diff --git a/doc/manual/type_sections.txt b/doc/manual/type_sections.txt
index af761c77e..12b2a11ac 100644
--- a/doc/manual/type_sections.txt
+++ b/doc/manual/type_sections.txt
@@ -5,8 +5,7 @@ Example:
 
 .. code-block:: nim
   type # example demonstrating mutually recursive types
-    Node = ref NodeObj # a traced pointer to a NodeObj
-    NodeObj = object
+    Node = ref object  # an object managed by the garbage collector (ref)
       le, ri: Node     # left and right subtrees
       sym: ref Sym     # leaves contain a reference to a Sym
 
diff --git a/doc/tut1.rst b/doc/tut1.rst
index be5cd8c11..6731efde9 100644
--- a/doc/tut1.rst
+++ b/doc/tut1.rst
@@ -1511,8 +1511,7 @@ operators perform implicit dereferencing operations for reference types:
 .. code-block:: nim
 
   type
-    Node = ref NodeObj
-    NodeObj = object
+    Node = ref object
       le, ri: Node
       data: int
   var
diff --git a/doc/tut2.rst b/doc/tut2.rst
index 0bb4c94e1..0636c4ed6 100644
--- a/doc/tut2.rst
+++ b/doc/tut2.rst
@@ -104,15 +104,14 @@ Example:
 
 .. code-block:: nim
   type
-    Node = ref NodeObj # a traced reference to a NodeObj
-    NodeObj = object
+    Node = ref object  # a reference to an object with the following field:
       le, ri: Node     # left and right subtrees
       sym: ref Sym     # leaves contain a reference to a Sym
 
     Sym = object       # a symbol
       name: string     # the symbol's name
       line: int        # the line the symbol was declared in
-      code: Node      # the symbol's abstract syntax tree
+      code: Node       # the symbol's abstract syntax tree
 
 
 Type conversions
@@ -155,8 +154,7 @@ An example:
       nkAdd,          # an addition
       nkSub,          # a subtraction
       nkIf            # an if statement
-    Node = ref NodeObj
-    NodeObj = object
+    Node = ref object
       case kind: NodeKind  # the ``kind`` field is the discriminator
       of nkInt: intVal: int
       of nkFloat: floatVal: float
@@ -482,11 +480,10 @@ containers:
 
 .. code-block:: nim
   type
-    BinaryTreeObj[T] = object # BinaryTree is a generic type with
-                              # with generic param ``T``
-      le, ri: BinaryTree[T]   # left and right subtrees; may be nil
-      data: T                 # the data stored in a node
-    BinaryTree*[T] = ref BinaryTreeObj[T] # type that is exported
+    BinaryTree*[T] = ref object # BinaryTree is a generic type with
+                                # generic param ``T``
+      le, ri: BinaryTree[T]     # left and right subtrees; may be nil
+      data: T                   # the data stored in a node
 
   proc newNode*[T](data: T): BinaryTree[T] =
     # constructor for a node
diff --git a/examples/cross_calculator/ios/resources/ui/NRViewController.xib b/examples/cross_calculator/ios/resources/ui/NRViewController.xib
index b260db2af..2118b5044 100644
--- a/examples/cross_calculator/ios/resources/ui/NRViewController.xib
+++ b/examples/cross_calculator/ios/resources/ui/NRViewController.xib
@@ -85,7 +85,7 @@
 						<int key="IBUITag">2</int>
 						<bool key="IBUIUserInteractionEnabled">NO</bool>
 						<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
-						<string key="IBUIText">Nimrod Crossplatform Calculator</string>
+						<string key="IBUIText">Nim Crossplatform Calculator</string>
 						<object class="NSColor" key="IBUITextColor" id="128895179">
 							<int key="NSColorSpace">1</int>
 							<bytes key="NSRGB">MCAwIDAAA</bytes>
diff --git a/examples/cross_calculator/lazarus/unit1.pas b/examples/cross_calculator/lazarus/unit1.pas
index aa0ef6cf7..6091a61d3 100644
--- a/examples/cross_calculator/lazarus/unit1.pas
+++ b/examples/cross_calculator/lazarus/unit1.pas
@@ -42,7 +42,7 @@ function myAdd(x, y: longint): longint; cdecl; external;
 
 procedure TForm1.FormCreate(Sender: TObject);
 begin
-  // we initialize the Nimrod data structures here:
+  // we initialize the Nim data structures here:
   NimMain();
 end;
 
diff --git a/examples/cross_calculator/nim_commandline/nim.cfg b/examples/cross_calculator/nim_commandline/nim.cfg
index 41c034430..6f0cb4a01 100644
--- a/examples/cross_calculator/nim_commandline/nim.cfg
+++ b/examples/cross_calculator/nim_commandline/nim.cfg
@@ -1,4 +1,4 @@
-# Nimrod configuration file.
+# Nim configuration file.
 # The file is used only to add the path of the backend to the compiler options.
 
 path="../nim_backend"
diff --git a/examples/cross_calculator/readme.txt b/examples/cross_calculator/readme.txt
index 5011792b9..72e4130eb 100644
--- a/examples/cross_calculator/readme.txt
+++ b/examples/cross_calculator/readme.txt
@@ -2,7 +2,7 @@ The cross platform calculator illustrates how to use Nim to create a backend
 called by different native user interfaces.
 
 Since the purpose of the example is to show how the cross platform code
-interacts with Nimrod the actual backend code is just a simple addition proc.
+interacts with Nim the actual backend code is just a simple addition proc.
 By keeping your program logic in Nim you can easily reuse it in different
 platforms.
 
diff --git a/examples/cross_todo/nim_backend/backend.nim b/examples/cross_todo/nim_backend/backend.nim
index 6869665f8..513fe304f 100644
--- a/examples/cross_todo/nim_backend/backend.nim
+++ b/examples/cross_todo/nim_backend/backend.nim
@@ -4,9 +4,8 @@
 
 import db_sqlite, parseutils, strutils, times
 
-
 type
-  TTodo* = object
+  Todo* = object
     ## A todo object holding the information serialized to the database.
     id: int64                 ## Unique identifier of the object in the
                               ## database, use the getId() accessor to read it.
@@ -17,7 +16,7 @@ type
                               ## outside of this module, use the
                               ## getModificationDate accessor.
 
-  TPagedParams* = object
+  PagedParams* = object
     ## Contains parameters for a query, initialize default values with
     ## initDefaults().
     pageSize*: int64          ## Lines per returned query page, -1 for
@@ -27,11 +26,10 @@ type
     showUnchecked*: bool      ## Get unchecked objects.
     showChecked*: bool        ## Get checked objects.
 
-
 # - General procs
-#
-proc initDefaults*(params: var TPagedParams) =
-  ## Sets sane defaults for a TPagedParams object.
+
+proc initDefaults*(params: var PagedParams) =
+  ## Sets sane defaults for a PagedParams object.
   ##
   ## Note that you should always provide a non zero pageSize, either a specific
   ## positive value or negative for unbounded query results.
@@ -41,7 +39,6 @@ proc initDefaults*(params: var TPagedParams) =
   params.showUnchecked = true
   params.showChecked = false
 
-
 proc openDatabase*(path: string): DbConn =
   ## Creates or opens the sqlite3 database.
   ##
@@ -56,16 +53,14 @@ proc openDatabase*(path: string): DbConn =
       desc TEXT NOT NULL,
       modification_date INTEGER NOT NULL,
       CONSTRAINT Todos UNIQUE (id))"""
-
   db_sqlite.exec(conn, query)
   result = conn
 
+# - Procs related to Todo objects
 
-# - Procs related to TTodo objects
-#
 proc initFromDB(id: int64; text: string; priority: int, isDone: bool;
-               modificationDate: Time): TTodo =
-  ## Returns an initialized TTodo object created from database parameters.
+               modificationDate: Time): Todo =
+  ## Returns an initialized Todo object created from database parameters.
   ##
   ## The proc assumes all values are right. Note this proc is NOT exported.
   assert(id >= 0, "Identity identifiers should not be negative")
@@ -75,29 +70,25 @@ proc initFromDB(id: int64; text: string; priority: int, isDone: bool;
   result.isDone = isDone
   result.modificationDate = modificationDate
 
-
-proc getId*(todo: TTodo): int64 =
+proc getId*(todo: Todo): int64 =
   ## Accessor returning the value of the private id property.
   return todo.id
 
-
-proc getModificationDate*(todo: TTodo): Time =
-  ## Returns the last modification date of a TTodo entry.
+proc getModificationDate*(todo: Todo): Time =
+  ## Returns the last modification date of a Todo entry.
   return todo.modificationDate
 
-
-proc update*(todo: var TTodo; conn: DbConn): bool =
+proc update*(todo: var Todo; conn: DbConn): bool =
   ## Checks the database for the object and refreshes its variables.
   ##
   ## Use this method if you (or another entity) have modified the database and
   ## want to update the object you have with whatever the database has stored.
   ## Returns true if the update succeeded, or false if the object was not found
   ## in the database any more, in which case you should probably get rid of the
-  ## TTodo object.
+  ## Todo object.
   assert(todo.id >= 0, "The identifier of the todo entry can't be negative")
   let query = sql"""SELECT desc, priority, is_done, modification_date
     FROM Todos WHERE id = ?"""
-
   try:
     let rows = conn.getAllRows(query, $todo.id)
     if len(rows) < 1:
@@ -111,8 +102,7 @@ proc update*(todo: var TTodo; conn: DbConn): bool =
   except:
     echo("Something went wrong selecting for id " & $todo.id)
 
-
-proc save*(todo: var TTodo; conn: DbConn): bool =
+proc save*(todo: var Todo; conn: DbConn): bool =
   ## Saves the current state of text, priority and isDone to the database.
   ##
   ## Returns true if the database object was updated (in which case the
@@ -127,15 +117,13 @@ proc save*(todo: var TTodo; conn: DbConn): bool =
       WHERE id = ?"""
     rowsUpdated = conn.execAffectedRows(query, $todo.text,
       $todo.priority, $todo.isDone, $int(currentDate), $todo.id)
-
   if 1 == rowsUpdated:
     todo.modificationDate = currentDate
     result = true
 
-
 # - Procs dealing directly with the database
-#
-proc addTodo*(conn: DbConn; priority: int; text: string): TTodo =
+
+proc addTodo*(conn: DbConn; priority: int; text: string): Todo =
   ## Inserts a new todo into the database.
   ##
   ## Returns the generated todo object. If there is an error EDb will be raised.
@@ -145,10 +133,8 @@ proc addTodo*(conn: DbConn; priority: int; text: string): TTodo =
       (priority, is_done, desc, modification_date)
       VALUES (?, 'false', ?, ?)"""
     todoId = conn.insertId(query, priority, text, $int(currentDate))
-
   result = initFromDB(todoId, text, priority, false, currentDate)
 
-
 proc deleteTodo*(conn: DbConn; todoId: int64): int64 {.discardable.} =
   ## Deletes the specified todo identifier.
   ##
@@ -156,7 +142,6 @@ proc deleteTodo*(conn: DbConn; todoId: int64): int64 {.discardable.} =
   let query = sql"""DELETE FROM Todos WHERE id = ?"""
   result = conn.execAffectedRows(query, $todoId)
 
-
 proc getNumEntries*(conn: DbConn): int =
   ## Returns the number of entries in the Todos table.
   ##
@@ -170,38 +155,30 @@ proc getNumEntries*(conn: DbConn): int =
     echo("Something went wrong retrieving number of Todos entries")
     result = -1
 
-
-proc getPagedTodos*(conn: DbConn; params: TPagedParams;
-                    page = 0'i64): seq[TTodo] =
+proc getPagedTodos*(conn: DbConn; params: PagedParams; page = 0'i64): seq[Todo] =
   ## Returns the todo entries for a specific page.
   ##
   ## Pages are calculated based on the params.pageSize parameter, which can be
   ## set to a negative value to specify no limit at all.  The query will be
-  ## affected by the TPagedParams, which should have sane values (call
+  ## affected by the PagedParams, which should have sane values (call
   ## initDefaults).
   assert(page >= 0, "You should request a page zero or bigger than zero")
   result = @[]
-
   # Well, if you don't want to see anything, there's no point in asking the db.
   if not params.showUnchecked and not params.showChecked: return
-
   let
     order_by = [
       if params.priorityAscending: "ASC" else: "DESC",
       if params.dateAscending: "ASC" else: "DESC"]
-
     query = sql("""SELECT id, desc, priority, is_done, modification_date
       FROM Todos
       WHERE is_done = ? OR is_done = ?
       ORDER BY priority $1, modification_date $2, id DESC
       LIMIT ? * ?,?""" % order_by)
-
     args = @[$params.showChecked, $(not params.showUnchecked),
       $params.pageSize, $page, $params.pageSize]
-
   #echo("Query " & string(query))
   #echo("args: " & args.join(", "))
-
   var newId: BiggestInt
   for row in conn.fastRows(query, args):
     let numChars = row[0].parseBiggestInt(newId)
@@ -209,10 +186,9 @@ proc getPagedTodos*(conn: DbConn; params: TPagedParams;
     result.add(initFromDB(int64(newId), row[1], row[2].parseInt,
         row[3].parseBool, Time(row[4].parseInt)))
 
-
-proc getTodo*(conn: DbConn; todoId: int64): ref TTodo =
-  ## Returns a reference to a TTodo or nil if the todo could not be found.
-  var tempTodo: TTodo
+proc getTodo*(conn: DbConn; todoId: int64): ref Todo =
+  ## Returns a reference to a Todo or nil if the todo could not be found.
+  var tempTodo: Todo
   tempTodo.id = todoId
   if tempTodo.update(conn):
     new(result)
diff --git a/examples/cross_todo/nim_backend/testbackend.nim b/examples/cross_todo/nim_backend/testbackend.nim
index 6754f013a..4a71d5f2c 100644
--- a/examples/cross_todo/nim_backend/testbackend.nim
+++ b/examples/cross_todo/nim_backend/testbackend.nim
@@ -2,8 +2,7 @@
 
 import backend, db_sqlite, strutils, times
 
-
-proc showPagedResults(conn: DbConn; params: TPagedParams) =
+proc showPagedResults(conn: DbConn; params: PagedParams) =
   ## Shows the contents of the database in pages of specified size.
   ##
   ## Hmm... I guess this is more of a debug proc which should be moved outside,
@@ -11,7 +10,6 @@ proc showPagedResults(conn: DbConn; params: TPagedParams) =
   var
     page = 0'i64
     rows = conn.getPagedTodos(params)
-
   while rows.len > 0:
     echo("page " & $page)
     for row in rows:
@@ -25,7 +23,6 @@ proc showPagedResults(conn: DbConn; params: TPagedParams) =
     else:
       break
 
-
 proc dumTest() =
   let conn = openDatabase("todo.sqlite3")
   try:
@@ -35,10 +32,8 @@ proc dumTest() =
       # Fill some dummy rows if there are not many entries yet.
       discard conn.addTodo(3, "Filler1")
       discard conn.addTodo(4, "Filler2")
-
     var todo = conn.addTodo(2, "Testing")
     echo("New todo added with id " & $todo.getId)
-
     # Try changing it and updating the database.
     var clonedTodo = conn.getTodo(todo.getId)[]
     assert(clonedTodo.text == todo.text, "Should be equal")
@@ -49,13 +44,11 @@ proc dumTest() =
       echo("Updated priority $1, done $2" % [$todo.priority, $todo.isDone])
     else:
       assert(false, "Uh oh, I wasn't expecting that!")
-
     # Verify our cloned copy is different but can be updated.
     assert(clonedTodo.text != todo.text, "Should be different")
     discard clonedTodo.update(conn)
     assert(clonedTodo.text == todo.text, "Should be equal")
-
-    var params: TPagedParams
+    var params: PagedParams
     params.initDefaults
     conn.showPagedResults(params)
     conn.deleteTodo(todo.getId)
@@ -66,7 +59,6 @@ proc dumTest() =
       echo("Later priority $1, done $2" % [$todo.priority, $todo.isDone])
     else:
       echo("Can't update object $1 from db!" % $todo.getId)
-
     # Try to list content in a different way.
     params.pageSize = 5
     params.priorityAscending = true
@@ -77,7 +69,6 @@ proc dumTest() =
     conn.close
     echo("Database closed")
 
-
 # Code that will be run only on the commandline.
 when isMainModule:
   dumTest()
diff --git a/examples/cross_todo/nim_commandline/nim.cfg b/examples/cross_todo/nim_commandline/nim.cfg
index 41c034430..6f0cb4a01 100644
--- a/examples/cross_todo/nim_commandline/nim.cfg
+++ b/examples/cross_todo/nim_commandline/nim.cfg
@@ -1,4 +1,4 @@
-# Nimrod configuration file.
+# Nim configuration file.
 # The file is used only to add the path of the backend to the compiler options.
 
 path="../nim_backend"
diff --git a/examples/cross_todo/nim_commandline/nimtodo.nim b/examples/cross_todo/nim_commandline/nimtodo.nim
index c8993b2c8..be5b3407b 100644
--- a/examples/cross_todo/nim_commandline/nimtodo.nim
+++ b/examples/cross_todo/nim_commandline/nimtodo.nim
@@ -18,8 +18,8 @@ Commands:
   -h, --help  shows this help
 
 List options (optional):
-  -p=+|-      Sorts list by ascending|desdencing priority. Default:desdencing.
-  -m=+|-      Sorts list by ascending|desdencing date. Default:desdencing.
+  -p=+|-      Sorts list by ascending|descending priority. Default:descending.
+  -m=+|-      Sorts list by ascending|descending date. Default:descending.
   -t          Show checked entries. By default they are not shown.
   -z          Hide unchecked entries. By default they are shown.
 
@@ -33,7 +33,7 @@ Examples:
 """
 
 type
-  TCommand = enum     # The possible types of commands
+  Command = enum     # The possible types of commands
     cmdAdd            # The user wants to add a new todo entry.
     cmdCheck          # User wants to check a todo entry.
     cmdUncheck        # User wants to uncheck a todo entry.
@@ -42,30 +42,27 @@ type
     cmdGenerate       # Add random rows to the database, for testing.
     cmdList           # User wants to list contents.
 
-  TParamConfig = object
+  ParamConfig = object
     # Structure containing the parsed options from the commandline.
-    command: TCommand         # Store the type of operation
+    command: Command         # Store the type of operation
     addPriority: int          # Only valid with cmdAdd, stores priority.
     addText: seq[string]      # Only valid with cmdAdd, stores todo text.
     todoId: int64             # The todo id for operations like check or delete.
-    listParams: TPagedParams  # Uses the backend structure directly for params.
+    listParams: PagedParams  # Uses the backend structure directly for params.
 
-
-proc initDefaults(params: var TParamConfig) =
+proc initDefaults(params: var ParamConfig) =
   ## Initialises defaults value in the structure.
   ##
   ## Most importantly we want to have an empty list for addText.
   params.listParams.initDefaults
   params.addText = @[]
 
-
 proc abort(message: string, value: int) =
   # Simple wrapper to abort also displaying the help to the user.
   stdout.write(USAGE)
   quit(message, value)
 
-
-template parseTodoIdAndSetCommand(newCommand: TCommand): stmt =
+template parseTodoIdAndSetCommand(newCommand: Command): untyped =
   ## Helper to parse a big todo identifier into todoId and set command.
   try:
     let numChars = val.parseBiggestInt(newId)
@@ -75,8 +72,7 @@ template parseTodoIdAndSetCommand(newCommand: TCommand): stmt =
   except OverflowError:
     raise newException(ValueError, "Value $1 too big" % val)
 
-
-template verifySingleCommand(actions: stmt): stmt =
+template verifySingleCommand(actions: typed): typed =
   ## Helper to make sure only one command has been specified so far.
   if specifiedCommand:
     abort("Only one command can be specified at a time! (extra:$1)" % [key], 2)
@@ -84,7 +80,6 @@ template verifySingleCommand(actions: stmt): stmt =
     actions
     specifiedCommand = true
 
-
 proc parsePlusMinus(val: string, debugText: string): bool =
   ## Helper to process a plus or minus character from the commandline.
   ##
@@ -100,11 +95,10 @@ proc parsePlusMinus(val: string, debugText: string): bool =
   else:
     abort("$1 parameter should be + or - but was '$2'." % [debugText, val], 4)
 
-
-proc parseCmdLine(): TParamConfig =
+proc parseCmdLine(): ParamConfig =
   ## Parses the commandline.
   ##
-  ## Returns a TParamConfig structure filled with the proper values or directly
+  ## Returns a ParamConfig structure filled with the proper values or directly
   ## calls quit() with the appropriate error message.
   var
     specifiedCommand = false
@@ -112,15 +106,12 @@ proc parseCmdLine(): TParamConfig =
     p = initOptParser()
     key, val: TaintedString
     newId: BiggestInt
-
   result.initDefaults
-
   try:
     while true:
       next(p)
       key = p.key
       val = p.val
-
       case p.kind
       of cmdArgument:
         if specifiedCommand and cmdAdd == result.command:
@@ -180,17 +171,13 @@ proc parseCmdLine(): TParamConfig =
         break
   except ValueError:
     abort("Invalid integer value '$1' for parameter '$2'." % [val, key], 7)
-
   if not specifiedCommand:
     abort("Didn't specify any command.", 8)
-
   if cmdAdd == result.command and result.addText.len < 1:
     abort("Used the add command, but provided no text/description.", 9)
-
   if usesListParams and cmdList != result.command:
     abort("Used list options, but didn't specify the list command.", 10)
 
-
 proc generateDatabaseRows(conn: DbConn) =
   ## Adds some rows to the database ignoring errors.
   discard conn.addTodo(1, "Watch another random youtube video")
@@ -208,19 +195,16 @@ proc generateDatabaseRows(conn: DbConn) =
   discard conn.addTodo(6, "Learn a functional programming language")
   echo("Generated some entries, they were added to your database.")
 
-
-proc listDatabaseContents(conn: DbConn; listParams: TPagedParams) =
+proc listDatabaseContents(conn: DbConn; listParams: PagedParams) =
   ## Dumps the database contents formatted to the standard output.
   ##
   ## Pass the list/filter parameters parsed from the commandline.
   var params = listParams
   params.pageSize = -1
-
   let todos = conn.getPagedTodos(params)
   if todos.len < 1:
     echo("Database empty")
     return
-
   echo("Todo id, is done, priority, last modification date, text:")
   # First detect how long should be our columns for formatting.
   var cols: array[0..2, int]
@@ -228,7 +212,6 @@ proc listDatabaseContents(conn: DbConn; listParams: TPagedParams) =
     cols[0] = max(cols[0], ($todo.getId).len)
     cols[1] = max(cols[1], ($todo.priority).len)
     cols[2] = max(cols[2], ($todo.getModificationDate).len)
-
   # Now dump all the rows using the calculated alignment sizes.
   for todo in todos:
     echo("$1 $2 $3, $4, $5" % [
@@ -238,7 +221,6 @@ proc listDatabaseContents(conn: DbConn; listParams: TPagedParams) =
       ($todo.getModificationDate).align(cols[2]),
       todo.text])
 
-
 proc deleteOneTodo(conn: DbConn; todoId: int64) =
   ## Deletes a single todo entry from the database.
   let numDeleted = conn.deleteTodo(todoId)
@@ -247,7 +229,6 @@ proc deleteOneTodo(conn: DbConn; todoId: int64) =
   else:
     quit("Couldn't delete todo id " & $todoId, 11)
 
-
 proc deleteAllTodos(conn: DbConn) =
   ## Deletes all the contents from the database.
   ##
@@ -256,43 +237,35 @@ proc deleteAllTodos(conn: DbConn) =
   ## ourselfves to the API exported by backend.
   var
     counter: int64
-    params: TPagedParams
-
+    params: PagedParams
   params.initDefaults
   params.pageSize = -1
   params.showUnchecked = true
   params.showChecked = true
-
   let todos = conn.getPagedTodos(params)
   for todo in todos:
     if conn.deleteTodo(todo.getId) > 0:
       counter += 1
     else:
       quit("Couldn't delete todo id " & $todo.getId, 12)
-
   echo("Deleted $1 todo entries from database." % $counter)
 
-
 proc setTodoCheck(conn: DbConn; todoId: int64; value: bool) =
   ## Changes the check state of a todo entry to the specified value.
   let
     newState = if value: "checked" else: "unchecked"
     todo = conn.getTodo(todoId)
-
   if todo == nil:
     quit("Can't modify todo id $1, its not in the database." % $todoId, 13)
-
   if todo[].isDone == value:
     echo("Todo id $1 was already set to $2." % [$todoId, newState])
     return
-
   todo[].isDone = value
   if todo[].save(conn):
     echo("Todo id $1 set to $2." % [$todoId, newState])
   else:
     quit("Error updating todo id $1 to $2." % [$todoId, newState])
 
-
 proc addTodo(conn: DbConn; priority: int; tokens: seq[string]) =
   ## Adds to the database a todo with the specified priority.
   ##
@@ -302,17 +275,14 @@ proc addTodo(conn: DbConn; priority: int; tokens: seq[string]) =
   echo("Created todo entry with id:$1 for priority $2 and text '$3'." % [
     $todo.getId, $todo.priority, todo.text])
 
-
 when isMainModule:
   ## Main entry point.
   let
     opt = parseCmdLine()
     dbPath = getConfigDir() / "nimtodo.sqlite3"
-
   if not dbPath.existsFile:
     createDir(getConfigDir())
     echo("No database found at $1, it will be created for you." % dbPath)
-
   let conn = openDatabase(dbPath)
   try:
     case opt.command
diff --git a/examples/cross_todo/nim_commandline/readme.txt b/examples/cross_todo/nim_commandline/readme.txt
index ca4b67521..7d68bbc8b 100644
--- a/examples/cross_todo/nim_commandline/readme.txt
+++ b/examples/cross_todo/nim_commandline/readme.txt
@@ -14,6 +14,6 @@ generation switch can be used to fill the database with some basic todo entries
 you can play with.
 
 Compilation is fairly easy despite having the source split in different
-directories. Thanks to the Nim.cfg file, which adds the ../Nim_backend
+directories. Thanks to the nim.cfg file, which adds the ../Nim_backend
 directory as a search path, you can compile and run the example just fine from
 the command line with 'nim c -r nimtodo.nim'.
diff --git a/examples/cross_todo/readme.txt b/examples/cross_todo/readme.txt
index 5be01e197..44e8c47aa 100644
--- a/examples/cross_todo/readme.txt
+++ b/examples/cross_todo/readme.txt
@@ -1,4 +1,4 @@
-The cross platform todo illustrates how to use Nim to create a backend
+This cross platform todo illustrates how to use Nim to create a backend
 called by different native user interfaces.
 
 This example builds on the knowledge learned from the cross_calculator example.
diff --git a/examples/keyval.nim b/examples/keyval.nim
index ae8cb8f08..a594c0fa8 100644
--- a/examples/keyval.nim
+++ b/examples/keyval.nim
@@ -3,7 +3,6 @@ import re
 
 for x in lines("myfile.txt"):
   if x =~ re"(\w+)=(.*)":
-    echo "Key: ", matches[0],
-         " Value: ", matches[1]
+    echo "Key: ", matches[0], " Value: ", matches[1]
 
 
diff --git a/examples/readme.txt b/examples/readme.txt
index dc3d3fb9b..176bc8239 100644
--- a/examples/readme.txt
+++ b/examples/readme.txt
@@ -1,4 +1,4 @@
-In this directory you will find several examples for how to use the Nimrod
+In this directory you will find several examples for how to use the Nim
 library.
 
 Copyright (c) 2004-2012 Andreas Rumpf.
diff --git a/examples/talk/dsl.nim b/examples/talk/dsl.nim
index 1034c99d4..2dde51790 100644
--- a/examples/talk/dsl.nim
+++ b/examples/talk/dsl.nim
@@ -1,20 +1,20 @@
 
 import strutils
 
-template html(name: expr, matter: stmt) {.immediate.} =
+template html(name, matter: untyped) =
   proc name(): string =
     result = "<html>"
     matter
     result.add("</html>")
 
-template nestedTag(tag: expr) {.immediate.} =
-  template tag(matter: stmt) {.immediate.} =
+template nestedTag(tag: untyped) =
+  template tag(matter: typed) =
     result.add("<" & astToStr(tag) & ">")
     matter
     result.add("</" & astToStr(tag) & ">")
 
-template simpleTag(tag: expr) {.immediate.} =
-  template tag(matter: expr) {.immediate.} =
+template simpleTag(tag: untyped) =
+  template tag(matter: untyped) =
     result.add("<$1>$2</$1>" % [astToStr(tag), matter])
 
 nestedTag body
diff --git a/examples/talk/formatoptimizer.nim b/examples/talk/formatoptimizer.nim
index db11d112d..104214e19 100644
--- a/examples/talk/formatoptimizer.nim
+++ b/examples/talk/formatoptimizer.nim
@@ -5,7 +5,7 @@ import macros
 proc invalidFormatString() =
   echo "invalidFormatString"
 
-template formatImpl(handleChar: expr) =
+template formatImpl(handleChar: untyped) =
   var i = 0
   while i < f.len:
     if f[i] == '$':
@@ -24,11 +24,11 @@ template formatImpl(handleChar: expr) =
       i += 1
 
 proc `%`*(f: string, a: openArray[string]): string =
-  template identity(x: expr): expr = x
+  template identity(x: untyped): untyped = x
   result = ""
   formatImpl(identity)
 
-macro optFormat{`%`(f, a)}(f: string{lit}, a: openArray[string]): expr =
+macro optFormat{`%`(f, a)}(f: string{lit}, a: openArray[string]): untyped =
   result = newNimNode(nnkBracket)
   #newCall("&")
   let f = f.strVal
diff --git a/examples/talk/quasiquote.nim b/examples/talk/quasiquote.nim
index df4003e6e..b3c7bb971 100644
--- a/examples/talk/quasiquote.nim
+++ b/examples/talk/quasiquote.nim
@@ -1,7 +1,7 @@
 
 import macros
 
-macro check(ex: expr): stmt =
+macro check(ex: untyped): typed =
   var info = ex.lineinfo
   var expString = ex.toStrLit
   result = quote do:
diff --git a/examples/talk/tags.nim b/examples/talk/tags.nim
index 12b9a08c3..8bf3450c9 100644
--- a/examples/talk/tags.nim
+++ b/examples/talk/tags.nim
@@ -1,8 +1,9 @@
 
-template htmlTag(tag: expr) {.immediate.} =
+template htmlTag(tag: untyped) =
   proc tag(): string = "<" & astToStr(tag) & ">"
 
 htmlTag(br)
 htmlTag(html)
 
 echo br()
+echo html()
\ No newline at end of file
diff --git a/koch.nim b/koch.nim
index dd4213437..cde74966b 100644
--- a/koch.nim
+++ b/koch.nim
@@ -473,7 +473,7 @@ proc temp(args: string) =
   # commit.
   let (bootArgs, programArgs) = splitArgs(args)
   let nimexec = findNim()
-  exec(nimexec & " c " & bootArgs & " compiler" / "nim", 125)
+  exec(nimexec & " c -d:debug " & bootArgs & " compiler" / "nim", 125)
   copyExe(output, finalDest)
   if programArgs.len > 0: exec(finalDest & " " & programArgs)
 
@@ -482,7 +482,7 @@ proc xtemp(cmd: string) =
   copyExe(d / "bin" / "nim".exe, d / "bin" / "nim_backup".exe)
   try:
     withDir(d):
-      temp"-d:debug"
+      temp""
     copyExe(d / "bin" / "nim_temp".exe, d / "bin" / "nim".exe)
     exec(cmd)
   finally:
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index dc56bb671..ebc9f7714 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -113,7 +113,9 @@ type
 
 type
   NimIdent* = object of RootObj
-    ## represents a Nim identifier in the AST
+    ## represents a Nim identifier in the AST. **Note**: This is only
+    ## rarely useful, for identifier construction from a string
+    ## use ``ident"abc"``.
 
   NimSymObj = object # hidden
   NimSym* = ref NimSymObj
@@ -129,7 +131,11 @@ const
   nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
                    nnkCallStrLit}
 
-proc `!`*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect.}
+proc `!`*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect, deprecated.}
+  ## constructs an identifier from the string `s`
+  ## **Deprecated since version 0.18.0**: Use ``toNimIdent`` instead.
+
+proc toNimIdent*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect.}
   ## constructs an identifier from the string `s`
 
 proc `$`*(i: NimIdent): string {.magic: "IdentToStr", noSideEffect.}
@@ -237,7 +243,7 @@ proc `ident=`*(n: NimNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect.}
 proc `strVal=`*(n: NimNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
 
 proc newNimNode*(kind: NimNodeKind,
-                 lineInfoFrom: NimNode=nil): NimNode
+                 lineInfoFrom: NimNode = nil): NimNode
   {.magic: "NNewNimNode", noSideEffect.}
   ## Creates a new AST node of the specified kind.
   ##
@@ -290,7 +296,7 @@ proc newIdentNode*(i: NimIdent): NimNode {.compileTime.} =
 proc newIdentNode*(i: string): NimNode {.compileTime.} =
   ## creates an identifier node from `i`
   result = newNimNode(nnkIdent)
-  result.ident = !i
+  result.ident = toNimIdent i
 
 
 type
@@ -400,7 +406,7 @@ proc quote*(bl: typed, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.}
   ##
   ## .. code-block:: nim
   ##
-  ##   macro check(ex: expr): stmt =
+  ##   macro check(ex: untyped): typed =
   ##     # this is a simplified version of the check macro from the
   ##     # unittest module.
   ##
@@ -477,7 +483,6 @@ proc newLit*(c: char): NimNode {.compileTime.} =
   result = newNimNode(nnkCharLit)
   result.intVal = ord(c)
 
-
 proc newLit*(i: int): NimNode {.compileTime.} =
   ## produces a new integer literal node.
   result = newNimNode(nnkIntLit)
@@ -581,7 +586,7 @@ proc newLit*[T](arg: seq[T]): NimNode {.compileTime.} =
 proc newLit*(arg: tuple): NimNode {.compileTime.} =
   result = nnkPar.newTree
   for a,b in arg.fieldPairs:
-    result.add nnkExprColonExpr.newTree( newIdentNode(a), newLit(b) )
+    result.add nnkExprColonExpr.newTree(newIdentNode(a), newLit(b))
 
 proc newLit*(s: string): NimNode {.compileTime.} =
   ## produces a new string literal node.
@@ -615,7 +620,7 @@ proc treeRepr*(n: NimNode): string {.compileTime, benign.} =
     of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal)
     of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)
     of nnkStrLit..nnkTripleStrLit: res.add(" " & $n.strVal)
-    of nnkIdent: res.add(" !\"" & $n.ident & '"')
+    of nnkIdent: res.add(" ident\"" & $n.ident & '"')
     of nnkSym: res.add(" \"" & $n.symbol & '"')
     of nnkNone: assert false
     else:
@@ -640,7 +645,7 @@ proc lispRepr*(n: NimNode): string {.compileTime, benign.} =
   of nnkCharLit..nnkInt64Lit: add(result, $n.intVal)
   of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
   of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)
-  of nnkIdent: add(result, "!\"" & $n.ident & '"')
+  of nnkIdent: add(result, "ident\"" & $n.ident & '"')
   of nnkSym: add(result, $n.symbol)
   of nnkNone: assert false
   else:
@@ -664,7 +669,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
   ## .. code-block:: nim
   ##   nnkStmtList.newTree(
   ##     nnkCommand.newTree(
-  ##       newIdentNode(!"echo"),
+  ##       newIdentNode("echo"),
   ##       newLit("Hello world")
   ##     )
   ##   )
@@ -718,7 +723,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
     of nnkIntLit..nnkInt64Lit: res.add($n.intVal)
     of nnkFloatLit..nnkFloat64Lit: res.add($n.floatVal)
     of nnkStrLit..nnkTripleStrLit: res.add($n.strVal.escape())
-    of nnkIdent: res.add("!" & ($n.ident).escape())
+    of nnkIdent: res.add(($n.ident).escape())
     of nnkSym: res.add(($n.symbol).escape())
     of nnkNone: assert false
     else:
@@ -898,6 +903,48 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]):
   for i in branches:
     result.add(newNimNode(nnkElifBranch).add(i.cond, i.body))
 
+proc newEnum*(name: NimNode, fields: openArray[NimNode],
+              public, pure: bool): NimNode {.compileTime.} =
+
+  ## Creates a new enum. `name` must be an ident. Fields are allowed to be
+  ## either idents or EnumFieldDef
+  ##
+  ## .. code-block:: nim
+  ##
+  ##    newEnum(
+  ##      name    = ident("Colors"),
+  ##      fields  = [ident("Blue"), ident("Red")],
+  ##      public  = true, pure = false)
+  ##
+  ##    # type Colors* = Blue Red
+  ##
+
+  expectKind name, nnkIdent
+  doAssert len(fields) > 0, "Enum must contain at least one field"
+  for field in fields:
+    expectKind field, {nnkIdent, nnkEnumFieldDef}
+
+  let enumBody = newNimNode(nnkEnumTy).add(newEmptyNode()).add(fields)
+  var typeDefArgs = [name, newEmptyNode(), enumBody]
+
+  if public:
+    let postNode = newNimNode(nnkPostfix).add(
+      newIdentNode("*"), typeDefArgs[0])
+
+    typeDefArgs[0] = postNode
+
+  if pure:
+    let pragmaNode = newNimNode(nnkPragmaExpr).add(
+      typeDefArgs[0],
+      add(newNimNode(nnkPragma), newIdentNode("pure")))
+
+    typeDefArgs[0] = pragmaNode
+
+  let
+    typeDef   = add(newNimNode(nnkTypeDef), typeDefArgs)
+    typeSect  = add(newNimNode(nnkTypeSection), typeDef)
+
+  return typeSect
 
 proc copyChildrenTo*(src, dest: NimNode) {.compileTime.}=
   ## Copy all children from `src` to `dest`
@@ -1015,7 +1062,7 @@ template findChild*(n: NimNode; cond: untyped): NimNode {.dirty.} =
   ##
   ## .. code-block:: nim
   ##   var res = findChild(n, it.kind == nnkPostfix and
-  ##                          it.basename.ident == !"foo")
+  ##                          it.basename.ident == toNimIdent"foo")
   block:
     var res: NimNode
     for it in n.children:
@@ -1049,7 +1096,7 @@ proc basename*(a: NimNode): NimNode =
 
 proc `basename=`*(a: NimNode; val: string) {.compileTime.}=
   case a.kind
-  of nnkIdent: macros.`ident=`(a,  !val)
+  of nnkIdent: macros.`ident=`(a, toNimIdent val)
   of nnkPostfix, nnkPrefix: a[1] = ident(val)
   else:
     quit "Do not know how to get basename of (" & treeRepr(a) & ")\n" & repr(a)
@@ -1110,7 +1157,7 @@ proc eqIdent*(node: NimNode; s: string): bool {.compileTime.} =
   ## other ways like ``node.ident`` are much more error-prone, unfortunately.
   case node.kind
   of nnkIdent:
-    result = node.ident == !s
+    result = node.ident == toNimIdent s
   of nnkSym:
     result = eqIdent($node.symbol, s)
   of nnkOpenSymChoice, nnkClosedSymChoice:
diff --git a/lib/deprecated/pure/rawsockets.nim b/lib/deprecated/pure/rawsockets.nim
index ee77b232e..876334f9e 100644
--- a/lib/deprecated/pure/rawsockets.nim
+++ b/lib/deprecated/pure/rawsockets.nim
@@ -3,12 +3,12 @@ export nativesockets
 
 {.warning: "rawsockets module is deprecated, use nativesockets instead".}
 
-template newRawSocket*(domain, sockType, protocol: cint): expr =
+template newRawSocket*(domain, sockType, protocol: cint): untyped =
   {.warning: "newRawSocket is deprecated, use newNativeSocket instead".}
   newNativeSocket(domain, sockType, protocol)
 
 template newRawSocket*(domain: Domain = AF_INET,
                        sockType: SockType = SOCK_STREAM,
-                       protocol: Protocol = IPPROTO_TCP): expr =
+                       protocol: Protocol = IPPROTO_TCP): untyped =
   {.warning: "newRawSocket is deprecated, use newNativeSocket instead".}
   newNativeSocket(domain, sockType, protocol)
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 6d4b85145..433931c9d 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -58,15 +58,18 @@ type
     socket: AsyncSocket
     reuseAddr: bool
     reusePort: bool
+    maxBody: int ## The maximum content-length that will be read for the body.
 
 {.deprecated: [TRequest: Request, PAsyncHttpServer: AsyncHttpServer,
   THttpCode: HttpCode, THttpVersion: HttpVersion].}
 
-proc newAsyncHttpServer*(reuseAddr = true, reusePort = false): AsyncHttpServer =
+proc newAsyncHttpServer*(reuseAddr = true, reusePort = false,
+                         maxBody = 8388608): AsyncHttpServer =
   ## Creates a new ``AsyncHttpServer`` instance.
   new result
   result.reuseAddr = reuseAddr
   result.reusePort = reusePort
+  result.maxBody = maxBody
 
 proc addHeaders(msg: var string, headers: HttpHeaders) =
   for k, v in headers:
@@ -122,144 +125,160 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
     raise newException(ValueError, "Invalid request protocol. Got: " &
         protocol)
   result.orig = protocol
-  i.inc protocol.parseInt(result.major, i)
+  i.inc protocol.parseSaturatedNatural(result.major, i)
   i.inc # Skip .
-  i.inc protocol.parseInt(result.minor, i)
+  i.inc protocol.parseSaturatedNatural(result.minor, i)
 
 proc sendStatus(client: AsyncSocket, status: string): Future[void] =
   client.send("HTTP/1.1 " & status & "\c\L\c\L")
 
-proc processClient(client: AsyncSocket, address: string,
-                   callback: proc (request: Request):
+proc processRequest(server: AsyncHttpServer, req: FutureVar[Request],
+                    client: AsyncSocket,
+                    address: string, lineFut: FutureVar[string],
+                    callback: proc (request: Request):
                       Future[void] {.closure, gcsafe.}) {.async.} =
-  var request: Request
-  request.url = initUri()
-  request.headers = newHttpHeaders()
-  var lineFut = newFutureVar[string]("asynchttpserver.processClient")
-  lineFut.mget() = newStringOfCap(80)
-  var key, value = ""
 
-  while not client.isClosed:
-    # GET /path HTTP/1.1
-    # Header: val
-    # \n
-    request.headers.clear()
-    request.body = ""
-    request.hostname.shallowCopy(address)
-    assert client != nil
-    request.client = client
-
-    # We should skip at least one empty line before the request
-    # https://tools.ietf.org/html/rfc7230#section-3.5
-    for i in 0..1:
-      lineFut.mget().setLen(0)
-      lineFut.clean()
-      await client.recvLineInto(lineFut, maxLength=maxLine) # TODO: Timeouts.
-
-      if lineFut.mget == "":
-        client.close()
-        return
+  # Alias `request` to `req.mget()` so we don't have to write `mget` everywhere.
+  template request(): Request =
+    req.mget()
+
+  # GET /path HTTP/1.1
+  # Header: val
+  # \n
+  request.headers.clear()
+  request.body = ""
+  request.hostname.shallowCopy(address)
+  assert client != nil
+  request.client = client
+
+  # We should skip at least one empty line before the request
+  # https://tools.ietf.org/html/rfc7230#section-3.5
+  for i in 0..1:
+    lineFut.mget().setLen(0)
+    lineFut.clean()
+    await client.recvLineInto(lineFut, maxLength=maxLine) # TODO: Timeouts.
+
+    if lineFut.mget == "":
+      client.close()
+      return
 
-      if lineFut.mget.len > maxLine:
-        await request.respondError(Http413)
-        client.close()
+    if lineFut.mget.len > maxLine:
+      await request.respondError(Http413)
+      client.close()
+      return
+    if lineFut.mget != "\c\L":
+      break
+
+  # First line - GET /path HTTP/1.1
+  var i = 0
+  for linePart in lineFut.mget.split(' '):
+    case i
+    of 0:
+      try:
+        # TODO: this is likely slow.
+        request.reqMethod = parseEnum[HttpMethod]("http" & linePart)
+      except ValueError:
+        asyncCheck request.respondError(Http400)
         return
-      if lineFut.mget != "\c\L":
-        break
-
-    # First line - GET /path HTTP/1.1
-    var i = 0
-    for linePart in lineFut.mget.split(' '):
-      case i
-      of 0:
-        try:
-          # TODO: this is likely slow.
-          request.reqMethod = parseEnum[HttpMethod]("http" & linePart)
-        except ValueError:
-          asyncCheck request.respondError(Http400)
-          continue
-      of 1: 
-        try:
-          parseUri(linePart, request.url)
-        except ValueError:
-          asyncCheck request.respondError(Http400) 
-          continue
-      of 2:
-        try:
-          request.protocol = parseProtocol(linePart)
-        except ValueError:
-          asyncCheck request.respondError(Http400)
-          continue
-      else:
-        await request.respondError(Http400)
-        continue
-      inc i
-
-    # Headers
-    while true:
-      i = 0
-      lineFut.mget.setLen(0)
-      lineFut.clean()
-      await client.recvLineInto(lineFut, maxLength=maxLine)
-
-      if lineFut.mget == "":
-        client.close(); return
-      if lineFut.mget.len > maxLine:
-        await request.respondError(Http413)
-        client.close(); return
-      if lineFut.mget == "\c\L": break
-      let (key, value) = parseHeader(lineFut.mget)
-      request.headers[key] = value
-      # Ensure the client isn't trying to DoS us.
-      if request.headers.len > headerLimit:
-        await client.sendStatus("400 Bad Request")
-        request.client.close()
+    of 1:
+      try:
+        parseUri(linePart, request.url)
+      except ValueError:
+        asyncCheck request.respondError(Http400)
         return
+    of 2:
+      try:
+        request.protocol = parseProtocol(linePart)
+      except ValueError:
+        asyncCheck request.respondError(Http400)
+        return
+    else:
+      await request.respondError(Http400)
+      return
+    inc i
 
-    if request.reqMethod == HttpPost:
-      # Check for Expect header
-      if request.headers.hasKey("Expect"):
-        if "100-continue" in request.headers["Expect"]:
-          await client.sendStatus("100 Continue")
-        else:
-          await client.sendStatus("417 Expectation Failed")
-
-    # Read the body
-    # - Check for Content-length header
-    if request.headers.hasKey("Content-Length"):
-      var contentLength = 0
-      if parseInt(request.headers["Content-Length"],
-                  contentLength) == 0:
-        await request.respond(Http400, "Bad Request. Invalid Content-Length.")
-        continue
-      else:
-        request.body = await client.recv(contentLength)
-        if request.body.len != contentLength:
-          await request.respond(Http400, "Bad Request. Content-Length does not match actual.")
-          continue
-    elif request.reqMethod == HttpPost:
-      await request.respond(Http411, "Content-Length required.")
-      continue
-
-    # Call the user's callback.
-    await callback(request)
-
-    if "upgrade" in request.headers.getOrDefault("connection"):
+  # Headers
+  while true:
+    i = 0
+    lineFut.mget.setLen(0)
+    lineFut.clean()
+    await client.recvLineInto(lineFut, maxLength=maxLine)
+
+    if lineFut.mget == "":
+      client.close(); return
+    if lineFut.mget.len > maxLine:
+      await request.respondError(Http413)
+      client.close(); return
+    if lineFut.mget == "\c\L": break
+    let (key, value) = parseHeader(lineFut.mget)
+    request.headers[key] = value
+    # Ensure the client isn't trying to DoS us.
+    if request.headers.len > headerLimit:
+      await client.sendStatus("400 Bad Request")
+      request.client.close()
       return
 
-    # Persistent connections
-    if (request.protocol == HttpVer11 and
-        request.headers.getOrDefault("connection").normalize != "close") or
-       (request.protocol == HttpVer10 and
-        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.
-      # Unless the connection header states otherwise.
-      discard
+  if request.reqMethod == HttpPost:
+    # Check for Expect header
+    if request.headers.hasKey("Expect"):
+      if "100-continue" in request.headers["Expect"]:
+        await client.sendStatus("100 Continue")
+      else:
+        await client.sendStatus("417 Expectation Failed")
+
+  # Read the body
+  # - Check for Content-length header
+  if request.headers.hasKey("Content-Length"):
+    var contentLength = 0
+    if parseSaturatedNatural(request.headers["Content-Length"], contentLength) == 0:
+      await request.respond(Http400, "Bad Request. Invalid Content-Length.")
+      return
     else:
-      request.client.close()
-      break
+      if contentLength > server.maxBody:
+        await request.respondError(Http413)
+        return
+      request.body = await client.recv(contentLength)
+      if request.body.len != contentLength:
+        await request.respond(Http400, "Bad Request. Content-Length does not match actual.")
+        return
+  elif request.reqMethod == HttpPost:
+    await request.respond(Http411, "Content-Length required.")
+    return
+
+  # Call the user's callback.
+  await callback(request)
+
+  if "upgrade" in request.headers.getOrDefault("connection"):
+    return
+
+  # Persistent connections
+  if (request.protocol == HttpVer11 and
+      cmpIgnoreCase(request.headers.getOrDefault("connection"), "close") != 0) or
+     (request.protocol == HttpVer10 and
+      cmpIgnoreCase(request.headers.getOrDefault("connection"), "keep-alive") == 0):
+    # 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.
+    # Unless the connection header states otherwise.
+    discard
+  else:
+    request.client.close()
+    return
+
+proc processClient(server: AsyncHttpServer, client: AsyncSocket, address: string,
+                   callback: proc (request: Request):
+                      Future[void] {.closure, gcsafe.}) {.async.} =
+  var request = newFutureVar[Request]("asynchttpserver.processClient")
+  request.mget().url = initUri()
+  request.mget().headers = newHttpHeaders()
+  var lineFut = newFutureVar[string]("asynchttpserver.processClient")
+  lineFut.mget() = newStringOfCap(80)
+
+  while not client.isClosed:
+    try:
+      await processRequest(server, request, client, address, lineFut, callback)
+    except:
+      asyncCheck request.mget().respondError(Http500)
 
 proc serve*(server: AsyncHttpServer, port: Port,
             callback: proc (request: Request): Future[void] {.closure,gcsafe.},
@@ -280,7 +299,7 @@ proc serve*(server: AsyncHttpServer, port: Port,
     # TODO: Causes compiler crash.
     #var (address, client) = await server.socket.acceptAddr()
     var fut = await server.socket.acceptAddr()
-    asyncCheck processClient(fut.client, fut.address, callback)
+    asyncCheck processClient(server, fut.client, fut.address, callback)
     #echo(f.isNil)
     #echo(f.repr)
 
diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim
index 981190211..a8e378d5c 100644
--- a/lib/pure/asyncmacro.nim
+++ b/lib/pure/asyncmacro.nim
@@ -472,27 +472,13 @@ proc stripAwait(node: NimNode): NimNode =
 proc splitParamType(paramType: NimNode, async: bool): NimNode =
   result = paramType
   if paramType.kind == nnkInfix and $paramType[0].ident in ["|", "or"]:
-    let firstType = paramType[1]
-    let firstTypeName = $firstType.ident
-    let secondType = paramType[2]
-    let secondTypeName = $secondType.ident
-
-    # Make sure that at least one has the name `async`, otherwise we shouldn't
-    # touch it.
-    if not ("async" in firstTypeName.normalize or
-            "async" in secondTypeName.normalize):
-      return
-
-    if async:
-      if firstTypeName.normalize.startsWith("async"):
-        result = paramType[1]
-      elif secondTypeName.normalize.startsWith("async"):
-        result = paramType[2]
-    else:
-      if not firstTypeName.normalize.startsWith("async"):
-        result = paramType[1]
-      elif not secondTypeName.normalize.startsWith("async"):
-        result = paramType[2]
+    let firstAsync = "async" in ($paramType[1].ident).normalize
+    let secondAsync = "async" in ($paramType[2].ident).normalize
+
+    if firstAsync:
+      result = paramType[if async: 1 else: 2]
+    elif secondAsync:
+      result = paramType[if async: 2 else: 1]
 
 proc stripReturnType(returnType: NimNode): NimNode =
   # Strip out the 'Future' from 'Future[T]'.
@@ -535,4 +521,4 @@ macro multisync*(prc: untyped): untyped =
   let (sync, asyncPrc) = splitProc(prc)
   result = newStmtList()
   result.add(asyncSingleProc(asyncPrc))
-  result.add(sync)
\ No newline at end of file
+  result.add(sync)
diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim
index c6a603318..6912b893c 100644
--- a/lib/pure/browsers.nim
+++ b/lib/pure/browsers.nim
@@ -21,24 +21,18 @@ proc openDefaultBrowser*(url: string) =
   ## opens `url` with the user's default browser. This does not block.
   ##
   ## Under Windows, ``ShellExecute`` is used. Under Mac OS X the ``open``
-  ## command is used. Under Unix, it is checked if ``gnome-open`` exists and
-  ## used if it does. Next attempt is ``kde-open``, then ``xdg-open``.
-  ## Otherwise the environment variable ``BROWSER`` is used to determine the
-  ## default browser to use.
+  ## command is used. Under Unix, it is checked if ``xdg-open`` exists and
+  ## used if it does. Otherwise the environment variable ``BROWSER`` is 
+  ## used to determine the default browser to use.
   when defined(windows):
-    when useWinUnicode:
-      var o = newWideCString("open")
-      var u = newWideCString(url)
-      discard shellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL)
-    else:
-      discard shellExecuteA(0'i32, "open", url, nil, nil, SW_SHOWNORMAL)
+    var o = newWideCString("open")
+    var u = newWideCString(url)
+    discard shellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL)
   elif defined(macosx):
     discard execShellCmd("open " & quoteShell(url))
   else:
-    const attempts = ["gnome-open ", "kde-open ", "xdg-open "]
     var u = quoteShell(url)
-    for a in items(attempts):
-      if execShellCmd(a & u) == 0: return
+    if execShellCmd("xdg-open " & u) == 0: return
     for b in getEnv("BROWSER").string.split(PathSep):
       try:
         # we use ``startProcess`` here because we don't want to block!
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 0eb8e6704..3f8a9574d 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -20,6 +20,8 @@
 
 include "system/inclrtl"
 
+import macros
+
 when not defined(nimhygiene):
   {.pragma: dirty.}
 
@@ -704,6 +706,52 @@ template newSeqWith*(len: int, init: untyped): untyped =
     result[i] = init
   result
 
+proc mapLitsImpl(constructor: NimNode; op: NimNode; nested: bool;
+                 filter = nnkLiterals): NimNode =
+  if constructor.kind in filter:
+    result = newNimNode(nnkCall, lineInfoFrom=constructor)
+    result.add op
+    result.add constructor
+  else:
+    result = newNimNode(constructor.kind, lineInfoFrom=constructor)
+    for v in constructor:
+      if nested or v.kind in filter:
+        result.add mapLitsImpl(v, op, nested, filter)
+      else:
+        result.add v
+
+macro mapLiterals*(constructor, op: untyped;
+                   nested = true): untyped =
+  ## applies ``op`` to each of the **atomic** literals like ``3``
+  ## or ``"abc"`` in the specified ``constructor`` AST. This can
+  ## be used to map every array element to some target type:
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##   let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
+  ##   doAssert x is array[4, int]
+  ##
+  ## Short notation for:
+  ##
+  ## .. code-block::
+  ##   let x = [int(0.1), int(1.2), int(2.3), int(3.4)]
+  ##
+  ## If ``nested`` is true, the literals are replaced everywhere
+  ## in the ``constructor`` AST, otherwise only the first level
+  ## is considered:
+  ##
+  ## .. code-block::
+  ##   mapLiterals((1, ("abc"), 2), float, nested=false)
+  ##
+  ## Produces::
+  ##
+  ##   (float(1), ("abc"), float(2))
+  ##
+  ## There are no constraints for the ``constructor`` AST, it
+  ## works for nested tuples of arrays of sets etc.
+  result = mapLitsImpl(constructor, op, nested.boolVal)
+
 when isMainModule:
   import strutils
   block: # concat test
@@ -992,5 +1040,11 @@ when isMainModule:
     seq2D[0][1] = true
     doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
 
+  block: # mapLiterals tests
+    let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
+    doAssert x is array[4, int]
+    doAssert mapLiterals((1, ("abc"), 2), float, nested=false) == (float(1), "abc", float(2))
+    doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2")
+
   when not defined(testing):
     echo "Finished doc tests"
diff --git a/lib/pure/collections/sharedstrings.nim b/lib/pure/collections/sharedstrings.nim
index 83edf8d94..7e9de4b73 100644
--- a/lib/pure/collections/sharedstrings.nim
+++ b/lib/pure/collections/sharedstrings.nim
@@ -87,10 +87,10 @@ proc newSharedString*(s: string): SharedString =
   result.len = len
 
 when declared(atomicLoadN):
-  template load(x): expr = atomicLoadN(addr x, ATOMIC_SEQ_CST)
+  template load(x): untyped = atomicLoadN(addr x, ATOMIC_SEQ_CST)
 else:
   # XXX Fixme
-  template load(x): expr = x
+  template load(x): untyped = x
 
 proc add*(s: var SharedString; t: cstring; len: Natural) =
   if len == 0: return
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index 7d850798c..07b37c7d4 100644
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
@@ -13,6 +13,15 @@ import strtabs, times
 
 proc parseCookies*(s: string): StringTableRef =
   ## parses cookies into a string table.
+  ##
+  ## The proc is meant to parse the Cookie header set by a client, not the
+  ## "Set-Cookie" header set by servers.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::Nim
+  ##     doAssert parseCookies("a=1; foo=bar") == {"a": 1, "foo": "bar"}.newStringTable
+
   result = newStringTable(modeCaseInsensitive)
   var i = 0
   while true:
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
index f6592df71..1a3ab688d 100644
--- a/lib/pure/future.nim
+++ b/lib/pure/future.nim
@@ -197,4 +197,4 @@ macro dump*(x: typed): untyped =
   let s = x.toStrLit
   let r = quote do:
     debugEcho `s`, " = ", `x`
-  return r
\ No newline at end of file
+  return r
diff --git a/lib/pure/gentabs.nim b/lib/pure/gentabs.nim
deleted file mode 100644
index 928ff8fe0..000000000
--- a/lib/pure/gentabs.nim
+++ /dev/null
@@ -1,211 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## The ``gentabs`` module implements an efficient hash table that is a
-## key-value mapping. The keys are required to be strings, but the values
-## may be any Nim or user defined type. This module supports matching
-## of keys in case-sensitive, case-insensitive and style-insensitive modes.
-##
-## **Warning:** This module is deprecated, new code shouldn't use it!
-
-{.deprecated.}
-
-import
-  os, hashes, strutils
-
-type
-  GenTableMode* = enum     ## describes the table's key matching mode
-    modeCaseSensitive,     ## case sensitive matching of keys
-    modeCaseInsensitive,   ## case insensitive matching of keys
-    modeStyleInsensitive   ## style sensitive matching of keys
-
-  GenKeyValuePair[T] = tuple[key: string, val: T]
-  GenKeyValuePairSeq[T] = seq[GenKeyValuePair[T]]
-  GenTable*[T] = object of RootObj
-    counter: int
-    data: GenKeyValuePairSeq[T]
-    mode: GenTableMode
-
-  PGenTable*[T] = ref GenTable[T]     ## use this type to declare hash tables
-
-{.deprecated: [TGenTableMode: GenTableMode, TGenKeyValuePair: GenKeyValuePair,
-              TGenKeyValuePairSeq: GenKeyValuePairSeq, TGenTable: GenTable].}
-
-const
-  growthFactor = 2
-  startSize = 64
-
-
-proc len*[T](tbl: PGenTable[T]): int {.inline.} =
-  ## returns the number of keys in `tbl`.
-  result = tbl.counter
-
-iterator pairs*[T](tbl: PGenTable[T]): tuple[key: string, value: T] =
-  ## iterates over any (key, value) pair in the table `tbl`.
-  for h in 0..high(tbl.data):
-    if not isNil(tbl.data[h].key):
-      yield (tbl.data[h].key, tbl.data[h].val)
-
-proc myhash[T](tbl: PGenTable[T], key: string): Hash =
-  case tbl.mode
-  of modeCaseSensitive: result = hashes.hash(key)
-  of modeCaseInsensitive: result = hashes.hashIgnoreCase(key)
-  of modeStyleInsensitive: result = hashes.hashIgnoreStyle(key)
-
-proc myCmp[T](tbl: PGenTable[T], a, b: string): bool =
-  case tbl.mode
-  of modeCaseSensitive: result = cmp(a, b) == 0
-  of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0
-  of modeStyleInsensitive: result = cmpIgnoreStyle(a, b) == 0
-
-proc mustRehash(length, counter: int): bool =
-  assert(length > counter)
-  result = (length * 2 < counter * 3) or (length - counter < 4)
-
-proc newGenTable*[T](mode: GenTableMode): PGenTable[T] =
-  ## creates a new generic hash table that is empty.
-  new(result)
-  result.mode = mode
-  result.counter = 0
-  newSeq(result.data, startSize)
-
-proc nextTry(h, maxHash: Hash): Hash {.inline.} =
-  result = ((5 * h) + 1) and maxHash
-
-proc rawGet[T](tbl: PGenTable[T], key: string): int =
-  var h: Hash
-  h = myhash(tbl, key) and high(tbl.data) # start with real hash value
-  while not isNil(tbl.data[h].key):
-    if myCmp(tbl, tbl.data[h].key, key):
-      return h
-    h = nextTry(h, high(tbl.data))
-  result = - 1
-
-proc rawInsert[T](tbl: PGenTable[T], data: var GenKeyValuePairSeq[T],
-                  key: string, val: T) =
-  var h: Hash
-  h = myhash(tbl, key) and high(data)
-  while not isNil(data[h].key):
-    h = nextTry(h, high(data))
-  data[h].key = key
-  data[h].val = val
-
-proc enlarge[T](tbl: PGenTable[T]) =
-  var n: GenKeyValuePairSeq[T]
-  newSeq(n, len(tbl.data) * growthFactor)
-  for i in countup(0, high(tbl.data)):
-    if not isNil(tbl.data[i].key):
-      rawInsert[T](tbl, n, tbl.data[i].key, tbl.data[i].val)
-  swap(tbl.data, n)
-
-proc hasKey*[T](tbl: PGenTable[T], key: string): bool =
-  ## returns true iff `key` is in the table `tbl`.
-  result = rawGet(tbl, key) >= 0
-
-proc `[]`*[T](tbl: PGenTable[T], key: string): T =
-  ## retrieves the value at ``tbl[key]``. If `key` is not in `tbl`,
-  ## default(T) is returned and no exception is raised. One can check
-  ## with ``hasKey`` whether the key exists.
-  var index = rawGet(tbl, key)
-  if index >= 0: result = tbl.data[index].val
-
-proc `[]=`*[T](tbl: PGenTable[T], key: string, val: T) =
-  ## puts a (key, value)-pair into `tbl`.
-  var index = rawGet(tbl, key)
-  if index >= 0:
-    tbl.data[index].val = val
-  else:
-    if mustRehash(len(tbl.data), tbl.counter): enlarge(tbl)
-    rawInsert(tbl, tbl.data, key, val)
-    inc(tbl.counter)
-
-
-when isMainModule:
-  #
-  # Verify tables of integer values (string keys)
-  #
-  var x = newGenTable[int](modeCaseInsensitive)
-  x["one"]   = 1
-  x["two"]   = 2
-  x["three"] = 3
-  x["four"]  = 4
-  x["five"]  = 5
-  assert(len(x) == 5)             # length procedure works
-  assert(x["one"] == 1)           # case-sensitive lookup works
-  assert(x["ONE"] == 1)           # case-insensitive should work for this table
-  assert(x["one"]+x["two"] == 3)  # make sure we're getting back ints
-  assert(x.hasKey("one"))         # hasKey should return 'true' for a key
-                                  # of "one"...
-  assert(not x.hasKey("NOPE"))    # ...but key "NOPE" is not in the table.
-  for k,v in pairs(x):            # make sure the 'pairs' iterator works
-    assert(x[k]==v)
-
-  #
-  # Verify a table of user-defined types
-  #
-  type
-    MyType = tuple[first, second: string] # a pair of strings
-  {.deprecated: [TMyType: MyType].}
-
-  var y = newGenTable[MyType](modeCaseInsensitive) # hash table where each
-                                                    # value is MyType tuple
-
-  #var junk: MyType = ("OK", "Here")
-
-  #echo junk.first, " ", junk.second
-
-  y["Hello"] = ("Hello", "World")
-  y["Goodbye"] = ("Goodbye", "Everyone")
-  #y["Hello"] = MyType( ("Hello", "World") )
-  #y["Goodbye"] = MyType( ("Goodbye", "Everyone") )
-
-  assert( not isNil(y["Hello"].first) )
-  assert( y["Hello"].first == "Hello" )
-  assert( y["Hello"].second == "World" )
-
-  #
-  # Verify table of tables
-  #
-  var z: PGenTable[ PGenTable[int] ] # hash table where each value is
-                                     # a hash table of ints
-
-  z = newGenTable[PGenTable[int]](modeCaseInsensitive)
-  z["first"] = newGenTable[int](modeCaseInsensitive)
-  z["first"]["one"] = 1
-  z["first"]["two"] = 2
-  z["first"]["three"] = 3
-
-  z["second"] = newGenTable[int](modeCaseInsensitive)
-  z["second"]["red"] = 10
-  z["second"]["blue"] = 20
-
-  assert(len(z) == 2)               # length of outer table
-  assert(len(z["first"]) == 3)      # length of "first" table
-  assert(len(z["second"]) == 2)     # length of "second" table
-  assert( z["first"]["one"] == 1)   # retrieve from first inner table
-  assert( z["second"]["red"] == 10) # retrieve from second inner table
-
-  when false:
-    # disabled: depends on hash order:
-    var output = ""
-    for k, v in pairs(z):
-      output.add( "$# ($#) ->\L" % [k,$len(v)] )
-      for k2,v2 in pairs(v):
-        output.add( "  $# <-> $#\L" % [k2,$v2] )
-
-    let expected = unindent """
-      first (3) ->
-        two <-> 2
-        three <-> 3
-        one <-> 1
-      second (2) ->
-        red <-> 10
-        blue <-> 20
-    """
-    assert output == expected
diff --git a/lib/pure/ioselectors.nim b/lib/pure/ioselectors.nim
index ef8072221..1722da1c6 100644
--- a/lib/pure/ioselectors.nim
+++ b/lib/pure/ioselectors.nim
@@ -43,6 +43,7 @@ const bsdPlatform = defined(macosx) or defined(freebsd) or
                     defined(dragonfly)
 
 when defined(nimdoc):
+  type SocketHandle = int
   type
     Selector*[T] = ref object
       ## An object which holds descriptors to be checked for read/write status
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 3d86cc9d7..cea485c43 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -1849,8 +1849,8 @@ when isMainModule:
       discard parseJson"""{ invalid"""
     except:
       discard
-  # memory diff should less than 2M
-  doAssert(abs(getOccupiedMem() - startMemory) < 2 * 1024 * 1024)
+  # memory diff should less than 4M
+  doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024)
 
 
   # test `$`
diff --git a/lib/pure/numeric.nim b/lib/pure/numeric.nim
deleted file mode 100644
index ccda3a146..000000000
--- a/lib/pure/numeric.nim
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2013 Robert Persson
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## **Warning:** This module will be moved out of the stdlib and into a
-## Nimble package, don't use it.
-
-type OneVarFunction* = proc (x: float): float
-
-{.deprecated: [TOneVarFunction: OneVarFunction].}
-
-proc brent*(xmin,xmax:float, function:OneVarFunction, tol:float,maxiter=1000):
-  tuple[rootx, rooty: float, success: bool]=
-  ## Searches `function` for a root between `xmin` and `xmax`
-  ## using brents method. If the function value at `xmin`and `xmax` has the
-  ## same sign, `rootx`/`rooty` is set too the extrema value closest to x-axis
-  ## and succes is set to false.
-  ## Otherwise there exists at least one root and success is set to true.
-  ## This root is searched for at most `maxiter` iterations.
-  ## If `tol` tolerance is reached within `maxiter` iterations
-  ## the root refinement stops and success=true.
-
-  # see http://en.wikipedia.org/wiki/Brent%27s_method
-  var
-    a=xmin
-    b=xmax
-    c=a
-    d=1.0e308
-    fa=function(a)
-    fb=function(b)
-    fc=fa
-    s=0.0
-    fs=0.0
-    mflag:bool
-    i=0
-    tmp2:float
-
-  if fa*fb>=0:
-    if abs(fa)<abs(fb):
-      return (a,fa,false)
-    else:
-      return (b,fb,false)
-
-  if abs(fa)<abs(fb):
-    swap(fa,fb)
-    swap(a,b)
-
-  while fb!=0.0 and abs(a-b)>tol:
-    if fa!=fc and fb!=fc: # inverse quadratic interpolation
-      s = a * fb * fc / (fa - fb) / (fa - fc) + b * fa * fc / (fb - fa) / (fb - fc) + c * fa * fb / (fc - fa) / (fc - fb)
-    else: #secant rule
-      s = b - fb * (b - a) / (fb - fa)
-    tmp2 = (3.0 * a + b) / 4.0
-    if not((s > tmp2 and s < b) or (s < tmp2 and s > b)) or
-      (mflag and abs(s - b) >= (abs(b - c) / 2.0)) or
-      (not mflag and abs(s - b) >= abs(c - d) / 2.0):
-      s=(a+b)/2.0
-      mflag=true
-    else:
-      if (mflag and (abs(b - c) < tol)) or (not mflag and (abs(c - d) < tol)):
-        s=(a+b)/2.0
-        mflag=true
-      else:
-        mflag=false
-    fs = function(s)
-    d = c
-    c = b
-    fc = fb
-    if fa * fs<0.0:
-      b=s
-      fb=fs
-    else:
-      a=s
-      fa=fs
-    if abs(fa)<abs(fb):
-      swap(a,b)
-      swap(fa,fb)
-    inc i
-    if i>maxiter:
-      break
-
-  return (b,fb,true)
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index a1ae4e250..8b26552de 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1195,14 +1195,15 @@ when defined(nimdoc):
     ## Returns the number of `command line arguments`:idx: given to the
     ## application.
     ##
-    ## If your binary was called without parameters this will return zero.  You
-    ## can later query each individual paramater with `paramStr() <#paramStr>`_
+    ## Unlike `argc`:idx: in C, if your binary was called without parameters this
+    ## will return zero.
+    ## You can query each individual paramater with `paramStr() <#paramStr>`_
     ## or retrieve all of them in one go with `commandLineParams()
     ## <#commandLineParams>`_.
     ##
-    ## **Availability**: On Posix there is no portable way to get the command
-    ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `declared() <system.html#declared>`_.
+    ## **Availability**: When generating a dynamic library (see --app:lib) on
+    ## Posix this proc is not defined.
+    ## Test for availability using `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nim
@@ -1219,13 +1220,14 @@ when defined(nimdoc):
     ## `paramCount() <#paramCount>`_ with this proc you can call the
     ## convenience `commandLineParams() <#commandLineParams>`_.
     ##
-    ## It is possible to call ``paramStr(0)`` but this will return OS specific
+    ## Similarly to `argv`:idx: in C,
+    ## it is possible to call ``paramStr(0)`` but this will return OS specific
     ## contents (usually the name of the invoked executable). You should avoid
     ## this and call `getAppFilename() <#getAppFilename>`_ instead.
     ##
-    ## **Availability**: On Posix there is no portable way to get the command
-    ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `declared() <system.html#declared>`_.
+    ## **Availability**: When generating a dynamic library (see --app:lib) on
+    ## Posix this proc is not defined.
+    ## Test for availability using `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nim
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index d768a7de9..dc25ea4c3 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -841,7 +841,7 @@ elif not defined(useNimRtl):
       var attr: Tposix_spawnattr
       var fops: Tposix_spawn_file_actions
 
-      template chck(e: expr) =
+      template chck(e: untyped) =
         if e != 0'i32: raiseOSError(osLastError())
 
       chck posix_spawn_file_actions_init(fops)
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index 3c790512f..a602b0e1b 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -252,6 +252,31 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
   elif result != 0:
     number = int(res)
 
+proc parseSaturatedNatural*(s: string, b: var int, start = 0): int =
+  ## parses a natural number into ``b``. This cannot raise an overflow
+  ## error. Instead of an ``Overflow`` exception ``high(int)`` is returned.
+  ## The number of processed character is returned.
+  ## This is usually what you really want to use instead of `parseInt`:idx:.
+  ## Example:
+  ##
+  ## .. code-block:: nim
+  ##   var res = 0
+  ##   discard parseSaturatedNatural("848", res)
+  ##   doAssert res == 848
+  var i = start
+  if s[i] == '+': inc(i)
+  if s[i] in {'0'..'9'}:
+    b = 0
+    while s[i] in {'0'..'9'}:
+      let c = ord(s[i]) - ord('0')
+      if b <= (high(int) - c) div 10:
+        b = b * 10 + c
+      else:
+        b = high(int)
+      inc(i)
+      while s[i] == '_': inc(i) # underscores are allowed and ignored
+    result = i - start
+
 # overflowChecks doesn't work with BiggestUInt
 proc rawParseUInt(s: string, b: var BiggestUInt, start = 0): int =
   var
@@ -393,16 +418,43 @@ when isMainModule:
   let input = "$test{}  $this is ${an{  example}}  "
   let expected = @[(ikVar, "test"), (ikStr, "{}  "), (ikVar, "this"),
                    (ikStr, " is "), (ikExpr, "an{  example}"), (ikStr, "  ")]
-  assert toSeq(interpolatedFragments(input)) == expected
+  doAssert toSeq(interpolatedFragments(input)) == expected
 
   var value = 0
   discard parseHex("0x38", value)
-  assert value == 56
+  doAssert value == 56
   discard parseHex("0x34", value)
-  assert value == 56 * 256 + 52
+  doAssert value == 56 * 256 + 52
   value = -1
   discard parseHex("0x38", value)
-  assert value == -200
+  doAssert value == -200
 
+  value = -1
+  doAssert(parseSaturatedNatural("848", value) == 3)
+  doAssert value == 848
+
+  value = -1
+  discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value)
+  doAssert value == high(int)
+
+  value = -1
+  discard parseSaturatedNatural("9223372036854775808", value)
+  doAssert value == high(int)
+
+  value = -1
+  discard parseSaturatedNatural("9223372036854775807", value)
+  doAssert value == high(int)
+
+  value = -1
+  discard parseSaturatedNatural("18446744073709551616", value)
+  doAssert value == high(int)
+
+  value = -1
+  discard parseSaturatedNatural("18446744073709551615", value)
+  doAssert value == high(int)
+
+  value = -1
+  doAssert(parseSaturatedNatural("1_000_000", value) == 9)
+  doAssert value == 1_000_000
 
 {.pop.}
diff --git a/lib/pure/poly.nim b/lib/pure/poly.nim
deleted file mode 100644
index e286c5d17..000000000
--- a/lib/pure/poly.nim
+++ /dev/null
@@ -1,371 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2013 Robert Persson
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## **Warning:** This module will be moved out of the stdlib and into a
-## Nimble package, don't use it.
-
-import math
-import strutils
-import numeric
-
-type
-  Poly* = object
-      cofs:seq[float]
-
-{.deprecated: [TPoly: Poly].}
-
-proc degree*(p:Poly):int=
-  ## Returns the degree of the polynomial,
-  ## that is the number of coefficients-1
-  return p.cofs.len-1
-
-
-proc eval*(p:Poly,x:float):float=
-  ## Evaluates a polynomial function value for `x`
-  ## quickly using Horners method
-  var n=p.degree
-  result=p.cofs[n]
-  dec n
-  while n>=0:
-    result = result*x+p.cofs[n]
-    dec n
-
-proc `[]` *(p:Poly;idx:int):float=
-  ## Gets a coefficient of the polynomial.
-  ## p[2] will returns the quadric term, p[3] the cubic etc.
-  ## Out of bounds index will return 0.0.
-  if idx<0 or idx>p.degree:
-      return 0.0
-  return p.cofs[idx]
-
-proc `[]=` *(p:var Poly;idx:int,v:float)=
-  ## Sets an coefficient of the polynomial by index.
-  ## p[2] set the quadric term, p[3] the cubic etc.
-  ## If index is out of range for the coefficients,
-  ## the polynomial grows to the smallest needed degree.
-  assert(idx>=0)
-
-  if idx>p.degree:  #polynomial must grow
-    var oldlen=p.cofs.len
-    p.cofs.setLen(idx+1)
-    for q in oldlen.. <high(p.cofs):
-      p.cofs[q]=0.0 #new-grown coefficients set to zero
-
-  p.cofs[idx]=v
-
-
-iterator items*(p:Poly):float=
-  ## Iterates through the coefficients of the polynomial.
-  var i=p.degree
-  while i>=0:
-    yield p[i]
-    dec i
-
-proc clean*(p:var Poly;zerotol=0.0)=
-  ## Removes leading zero coefficients of the polynomial.
-  ## An optional tolerance can be given for what's considered zero.
-  var n=p.degree
-  var relen=false
-
-  while n>0 and abs(p[n])<=zerotol:    # >0 => keep at least one coefficient
-    dec n
-    relen=true
-
-  if relen: p.cofs.setLen(n+1)
-
-
-proc `$` *(p:Poly):string =
-  ## Gets a somewhat reasonable string representation of the polynomial
-  ## The format should be compatible with most online function plotters,
-  ## for example directly in google search
-  result=""
-  var first=true #might skip + sign if first coefficient
-
-  for idx in countdown(p.degree,0):
-    let a=p[idx]
-
-    if a==0.0:
-      continue
-
-    if a>= 0.0 and not first:
-      result.add('+')
-    first=false
-
-    if a!=1.0 or idx==0:
-      result.add(formatFloat(a,ffDefault,0))
-    if idx>=2:
-      result.add("x^" & $idx)
-    elif idx==1:
-      result.add("x")
-
-  if result=="":
-      result="0"
-
-
-proc derivative*(p: Poly): Poly=
-  ## Returns a new polynomial, which is the derivative of `p`
-  newSeq[float](result.cofs,p.degree)
-  for idx in 0..high(result.cofs):
-    result.cofs[idx]=p.cofs[idx+1]*float(idx+1)
-
-proc diff*(p:Poly,x:float):float=
-  ## Evaluates the differentiation of a polynomial with
-  ## respect to `x` quickly using a modifed Horners method
-  var n=p.degree
-  result=p[n]*float(n)
-  dec n
-  while n>=1:
-    result = result*x+p[n]*float(n)
-    dec n
-
-proc integral*(p:Poly):Poly=
-  ## Returns a new polynomial which is the indefinite
-  ## integral of `p`. The constant term is set to 0.0
-  newSeq(result.cofs,p.cofs.len+1)
-  result.cofs[0]=0.0  #constant arbitrary term, use 0.0
-  for i in 1..high(result.cofs):
-    result.cofs[i]=p.cofs[i-1]/float(i)
-
-
-proc integrate*(p:Poly;xmin,xmax:float):float=
-  ## Computes the definite integral of `p` between `xmin` and `xmax`
-  ## quickly using a modified version of Horners method
-  var
-    n=p.degree
-    s1=p[n]/float(n+1)
-    s2=s1
-    fac:float
-
-  dec n
-  while n>=0:
-    fac=p[n]/float(n+1)
-    s1 = s1*xmin+fac
-    s2 = s2*xmax+fac
-    dec n
-
-  result=s2*xmax-s1*xmin
-
-proc initPoly*(cofs:varargs[float]):Poly=
-  ## Initializes a polynomial with given coefficients.
-  ## The most significant coefficient is first, so to create x^2-2x+3:
-  ## intiPoly(1.0,-2.0,3.0)
-  if len(cofs)<=0:
-      result.cofs= @[0.0]  #need at least one coefficient
-  else:
-    # reverse order of coefficients so indexing matches degree of
-    # coefficient...
-    result.cofs= @[]
-    for idx in countdown(cofs.len-1,0):
-      result.cofs.add(cofs[idx])
-
-  result.clean #remove leading zero terms
-
-
-proc divMod*(p,d:Poly;q,r:var Poly)=
-  ## Divides `p` with `d`, and stores the quotinent in `q` and
-  ## the remainder in `d`
-  var
-    pdeg=p.degree
-    ddeg=d.degree
-    power=p.degree-d.degree
-    ratio:float
-
-  r.cofs = p.cofs #initial remainder=numerator
-  if power<0: #denominator is larger than numerator
-    q.cofs= @ [0.0] #quotinent is 0.0
-    return # keep remainder as numerator
-
-  q.cofs=newSeq[float](power+1)
-
-  for i in countdown(pdeg,ddeg):
-    ratio=r.cofs[i]/d.cofs[ddeg]
-
-    q.cofs[i-ddeg]=ratio
-    r.cofs[i]=0.0
-
-    for j in countup(0,<ddeg):
-        var idx=i-ddeg+j
-        r.cofs[idx] = r.cofs[idx] - d.cofs[j]*ratio
-
-  r.clean # drop zero coefficients in remainder
-
-proc `+` *(p1:Poly,p2:Poly):Poly=
-  ## Adds two polynomials
-  var n=max(p1.cofs.len,p2.cofs.len)
-  newSeq(result.cofs,n)
-
-  for idx in countup(0,n-1):
-      result[idx]=p1[idx]+p2[idx]
-
-  result.clean # drop zero coefficients in remainder
-
-proc `*` *(p1:Poly,p2:Poly):Poly=
-  ## Multiplies the polynomial `p1` with `p2`
-  var
-    d1=p1.degree
-    d2=p2.degree
-    n=d1+d2
-    idx:int
-
-  newSeq(result.cofs,n)
-
-  for i1 in countup(0,d1):
-    for i2 in countup(0,d2):
-      idx=i1+i2
-      result[idx]=result[idx]+p1[i1]*p2[i2]
-
-  result.clean
-
-proc `*` *(p:Poly,f:float):Poly=
-  ## Multiplies the polynomial `p` with a real number
-  newSeq(result.cofs,p.cofs.len)
-  for i in 0..high(p.cofs):
-    result[i]=p.cofs[i]*f
-  result.clean
-
-proc `*` *(f:float,p:Poly):Poly=
-  ## Multiplies a real number with a polynomial
-  return p*f
-
-proc `-`*(p:Poly):Poly=
-  ## Negates a polynomial
-  result=p
-  for i in countup(0,<result.cofs.len):
-    result.cofs[i]= -result.cofs[i]
-
-proc `-` *(p1:Poly,p2:Poly):Poly=
-  ## Subtract `p1` with `p2`
-  var n=max(p1.cofs.len,p2.cofs.len)
-  newSeq(result.cofs,n)
-
-  for idx in countup(0,n-1):
-      result[idx]=p1[idx]-p2[idx]
-
-  result.clean # drop zero coefficients in remainder
-
-proc `/`*(p:Poly,f:float):Poly=
-  ## Divides polynomial `p` with a real number `f`
-  newSeq(result.cofs,p.cofs.len)
-  for i in 0..high(p.cofs):
-    result[i]=p.cofs[i]/f
-  result.clean
-
-proc `/` *(p,q:Poly):Poly=
-  ## Divides polynomial `p` with polynomial `q`
-  var dummy:Poly
-  p.divMod(q,result,dummy)
-
-proc `mod` *(p,q:Poly):Poly=
-  ## Computes the polynomial modulo operation,
-  ## that is the remainder of `p`/`q`
-  var dummy:Poly
-  p.divMod(q,dummy,result)
-
-
-proc normalize*(p:var Poly)=
-  ## Multiplies the polynomial inplace by a term so that
-  ## the leading term is 1.0.
-  ## This might lead to an unstable polynomial
-  ## if the leading term is zero.
-  p=p/p[p.degree]
-
-
-proc solveQuadric*(a,b,c:float;zerotol=0.0):seq[float]=
-  ## Solves the quadric equation `ax^2+bx+c`, with a possible
-  ## tolerance `zerotol` to find roots of curves just 'touching'
-  ## the x axis. Returns sequence with 0,1 or 2 solutions.
-
-  var p,q,d:float
-
-  p=b/(2.0*a)
-
-  if p==Inf or p==NegInf: #linear equation..
-    var linrt= -c/b
-    if linrt==Inf or linrt==NegInf: #constant only
-      return @[]
-    return @[linrt]
-
-  q=c/a
-  d=p*p-q
-
-  if d<0.0:
-    #check for inside zerotol range for neg. roots
-    var err=a*p*p-b*p+c #evaluate error at parabola center axis
-    if(err<=zerotol): return @[-p]
-    return @[]
-  else:
-    var sr=sqrt(d)
-    result= @[-sr-p,sr-p]
-
-proc getRangeForRoots(p:Poly):tuple[xmin,xmax:float]=
-  ## helper function for `roots` function
-  ## quickly computes a range, guaranteed to contain
-  ## all the real roots of the polynomial
-  # see http://www.mathsisfun.com/algebra/polynomials-bounds-zeros.html
-
-  var deg=p.degree
-  var d=p[deg]
-  var bound1,bound2:float
-
-  for i in countup(0,deg):
-    var c=abs(p.cofs[i]/d)
-    bound1=max(bound1,c+1.0)
-    bound2=bound2+c
-
-  bound2=max(1.0,bound2)
-  result.xmax=min(bound1,bound2)
-  result.xmin= -result.xmax
-
-
-proc addRoot(p:Poly,res:var seq[float],xp0,xp1,tol,zerotol,mergetol:float,maxiter:int)=
-  ## helper function for `roots` function
-  ## try to do a numeric search for a single root in range xp0-xp1,
-  ## adding it to `res` (allocating `res` if nil)
-  var br=brent(xp0,xp1, proc(x:float):float=p.eval(x),tol)
-  if br.success:
-    if res.len==0 or br.rootx>=res[high(res)]+mergetol: #dont add equal roots.
-      res.add(br.rootx)
-  else:
-    #this might be a 'touching' case, check function value against
-    #zero tolerance
-    if abs(br.rooty)<=zerotol:
-      if res.len==0 or br.rootx>=res[high(res)]+mergetol: #dont add equal roots.
-        res.add(br.rootx)
-
-
-proc roots*(p:Poly,tol=1.0e-9,zerotol=1.0e-6,mergetol=1.0e-12,maxiter=1000):seq[float]=
-  ## Computes the real roots of the polynomial `p`
-  ## `tol` is the tolerance used to break searching for each root when reached.
-  ## `zerotol` is the tolerance, which is 'close enough' to zero to be considered a root
-  ## and is used to find roots for curves that only 'touch' the x-axis.
-  ## `mergetol` is the tolerance, of which two x-values are considered being the same root.
-  ## `maxiter` can be used to limit the number of iterations for each root.
-  ## Returns a (possibly empty) sorted sequence with the solutions.
-  var deg=p.degree
-  if deg<=0: #constant only => no roots
-    return @[]
-  elif p.degree==1: #linear
-    var linrt= -p.cofs[0]/p.cofs[1]
-    if linrt==Inf or linrt==NegInf:
-      return @[] #constant only => no roots
-    return @[linrt]
-  elif p.degree==2:
-    return solveQuadric(p.cofs[2],p.cofs[1],p.cofs[0],zerotol)
-  else:
-    # degree >=3 , find min/max points of polynomial with recursive
-    # derivative and do a numerical search for root between each min/max
-    var range=p.getRangeForRoots()
-    var minmax=p.derivative.roots(tol,zerotol,mergetol)
-    result= @[]
-    if minmax!=nil: #ie. we have minimas/maximas in this function
-      for x in minmax.items:
-        addRoot(p,result,range.xmin,x,tol,zerotol,mergetol,maxiter)
-        range.xmin=x
-    addRoot(p,result,range.xmin,range.xmax,tol,zerotol,mergetol,maxiter)
-
diff --git a/lib/pure/romans.nim b/lib/pure/romans.nim
deleted file mode 100644
index aa047d1cc..000000000
--- a/lib/pure/romans.nim
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2011 Philippe Lhoste
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## Module for converting an integer to a Roman numeral.
-## See http://en.wikipedia.org/wiki/Roman_numerals for reference.
-##
-## **Warning:** This module will be moved out of the stdlib and into a
-## Nimble package, don't use it.
-
-const
-  RomanNumeralDigits* = {'I', 'i', 'V', 'v', 'X', 'x', 'L', 'l', 'C', 'c',
-    'D', 'd', 'M', 'm'} ## set of all characters a Roman numeral may consist of
-
-proc romanToDecimal*(romanVal: string): int =
-  ## Converts a Roman numeral to its int representation.
-  result = 0
-  var prevVal = 0
-  for i in countdown(romanVal.len - 1, 0):
-    var val = 0
-    case romanVal[i]
-    of 'I', 'i': val = 1
-    of 'V', 'v': val = 5
-    of 'X', 'x': val = 10
-    of 'L', 'l': val = 50
-    of 'C', 'c': val = 100
-    of 'D', 'd': val = 500
-    of 'M', 'm': val = 1000
-    else:
-      raise newException(EInvalidValue, "invalid roman numeral: " & $romanVal)
-    if val >= prevVal:
-      inc(result, val)
-    else:
-      dec(result, val)
-    prevVal = val
-
-proc decimalToRoman*(number: range[1..3_999]): string =
-  ## Converts a number to a Roman numeral.
-  const romanComposites = [
-    ("M", 1000), ("CM", 900),
-    ("D", 500), ("CD", 400), ("C", 100),
-    ("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9),
-    ("V", 5), ("IV", 4), ("I", 1)]
-  result = ""
-  var decVal: int = number
-  for key, val in items(romanComposites):
-    while decVal >= val:
-      dec(decVal, val)
-      result.add(key)
-
-when isMainModule:
-  for i in 1 .. 3_999:
-    assert i == i.decimalToRoman.romanToDecimal
-
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 5c07757cb..d773cc7d8 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -1927,7 +1927,7 @@ type
 {.deprecated: [TFloatFormat: FloatFormatMode].}
 
 proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
-                         precision: range[0..32] = 16;
+                         precision: range[-1..32] = 16;
                          decimalSep = '.'): string {.
                          noSideEffect, rtl, extern: "nsu$1".} =
   ## Converts a floating point value `f` to a string.
@@ -1939,7 +1939,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
   ## `precision`'s default value is the maximum number of meaningful digits
   ## after the decimal point for Nim's ``biggestFloat`` type.
   ##
-  ## If ``precision == 0``, it tries to format it nicely.
+  ## If ``precision == -1``, it tries to format it nicely.
   when defined(js):
     var res: cstring
     case format
@@ -1961,7 +1961,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
       buf {.noinit.}: array[0..2500, char]
       L: cint
     frmtstr[0] = '%'
-    if precision > 0:
+    if precision >= 0:
       frmtstr[1] = '#'
       frmtstr[2] = '.'
       frmtstr[3] = '*'
@@ -1984,7 +1984,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
       # but nothing else is possible:
       if buf[i] in {'.', ','}: result[i] = decimalsep
       else: result[i] = buf[i]
-    when defined(vcc):
+    when defined(windows):
       # VS pre 2015 violates the C standard: "The exponent always contains at
       # least two digits, and only as many more digits as necessary to
       # represent the exponent." [C11 §7.21.6.1]
@@ -1995,7 +1995,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
         result.setLen(result.len - 1)
 
 proc formatFloat*(f: float, format: FloatFormatMode = ffDefault,
-                  precision: range[0..32] = 16; decimalSep = '.'): string {.
+                  precision: range[-1..32] = 16; decimalSep = '.'): string {.
                   noSideEffect, rtl, extern: "nsu$1".} =
   ## Converts a floating point value `f` to a string.
   ##
@@ -2006,16 +2006,16 @@ proc formatFloat*(f: float, format: FloatFormatMode = ffDefault,
   ## `precision`'s default value is the maximum number of meaningful digits
   ## after the decimal point for Nim's ``float`` type.
   ##
-  ## If ``precision == 0``, it tries to format it nicely.
+  ## If ``precision == -1``, it tries to format it nicely.
   ##
   ## Examples:
   ##
   ## .. code-block:: nim
   ##
   ##    let x = 123.456
-  ##    echo x.formatFloat()                # 123.4560000000000
-  ##    echo x.formatFloat(ffDecimal, 4)    # 123.4560
-  ##    echo x.formatFloat(ffScientific, 2) # 1.23e+02
+  ##    doAssert x.formatFloat() == "123.4560000000000"
+  ##    doAssert x.formatFloat(ffDecimal, 4) == "123.4560"
+  ##    doAssert x.formatFloat(ffScientific, 2) == "1.23e+02"
   ##
   result = formatBiggestFloat(f, format, precision, decimalSep)
 
@@ -2471,12 +2471,14 @@ when isMainModule:
     outp = " this is a\nlong text\n--\nmuchlongerthan10chars\nand here\nit goes"
   doAssert wordWrap(inp, 10, false) == outp
 
+  doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
+  doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235."
+  doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
   doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
   doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
                                                    ["1,0e-11", "1,0e-011"]
   # bug #6589
-  doAssert formatFloat(123.456, ffScientific, precision=0) in
-      ["1.234560e+02", "1.234560e+002"]
+  doAssert formatFloat(123.456, ffScientific, precision = -1) == "1.234560e+02"
 
   doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
   doAssert "${1}12 ${-1}$2" % ["a", "b"] == "a12 bb"
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index 3b6f7de1a..2047abda4 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -21,7 +21,7 @@ proc name*(t: typedesc): string {.magic: "TypeTrait".}
   ##
   ##   proc `$`*(T: typedesc): string = name(T)
   ##
-  ##   template test(x): stmt =
+  ##   template test(x): typed =
   ##     echo "type: ", type(x), ", value: ", x
   ##
   ##   test 42
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index c702b054c..164a57ecf 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -308,11 +308,16 @@ proc `$`*(u: Uri): string =
       result.add(":")
       result.add(u.password)
     result.add("@")
-  result.add(u.hostname)
+  if u.hostname.endswith('/'):
+    result.add(u.hostname[0..^2])
+  else:
+    result.add(u.hostname)
   if u.port.len > 0:
     result.add(":")
     result.add(u.port)
   if u.path.len > 0:
+    if u.hostname.len > 0 and u.path[0] != '/':
+      result.add('/')
     result.add(u.path)
   if u.query.len > 0:
     result.add("?")
@@ -483,6 +488,34 @@ when isMainModule:
     let foo = parseUri("http://localhost:9515") / "status"
     doAssert $foo == "http://localhost:9515/status"
 
+  # bug #6649 #6652
+  block:
+    var foo = parseUri("http://example.com")
+    foo.hostname = "example.com"
+    foo.path = "baz"
+    doAssert $foo == "http://example.com/baz"
+
+    foo.hostname = "example.com/"
+    foo.path = "baz"
+    doAssert $foo == "http://example.com/baz"
+
+    foo.hostname = "example.com"
+    foo.path = "/baz"
+    doAssert $foo == "http://example.com/baz"
+
+    foo.hostname = "example.com/"
+    foo.path = "/baz"
+    doAssert $foo == "http://example.com/baz"
+
+    foo.hostname = "example.com/"
+    foo.port = "8000"
+    foo.path = "baz"
+    doAssert $foo == "http://example.com:8000/baz"
+
+    foo = parseUri("file:/dir/file")
+    foo.path = "relative"
+    doAssert $foo == "file:relative"
+
   # isAbsolute tests
   block:
     doAssert "www.google.com".parseUri().isAbsolute() == false
@@ -524,4 +557,4 @@ when isMainModule:
     doAssert "https://example.com/about/staff.html?".parseUri().isAbsolute == true
     doAssert "https://example.com/about/staff.html?parameters".parseUri().isAbsolute == true
 
-  echo("All good!")
\ No newline at end of file
+  echo("All good!")
diff --git a/lib/system.nim b/lib/system.nim
index 687a68119..c1bf1a919 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -456,6 +456,13 @@ type
   WriteIOEffect* = object of IOEffect  ## Effect describing a write IO operation.
   ExecIOEffect* = object of IOEffect   ## Effect describing an executing IO operation.
 
+  StackTraceEntry* = object ## In debug mode exceptions store the stack trace that led
+                            ## to them. A StackTraceEntry is a single entry of the
+                            ## stack trace.
+    procname*: cstring  ## name of the proc that is currently executing
+    line*: int          ## line number of the proc that is currently executing
+    filename*: cstring  ## filename of the proc that is currently executing
+
   Exception* {.compilerproc.} = object of RootObj ## \
     ## Base exception class.
     ##
@@ -468,7 +475,10 @@ type
     msg* {.exportc: "message".}: string ## the exception's message. Not
                                         ## providing an exception message
                                         ## is bad style.
-    trace: string
+    when defined(js):
+      trace: string
+    else:
+      trace: seq[StackTraceEntry]
     up: ref Exception # used for stacking exceptions. Not exported!
 
   SystemError* = object of Exception ## \
@@ -895,7 +905,7 @@ proc `div` *(x, y: int8): int8 {.magic: "DivI", noSideEffect.}
 proc `div` *(x, y: int16): int16 {.magic: "DivI", noSideEffect.}
 proc `div` *(x, y: int32): int32 {.magic: "DivI", noSideEffect.}
   ## computes the integer division. This is roughly the same as
-  ## ``floor(x/y)``.
+  ## ``trunc(x/y)``.
   ##
   ## .. code-block:: Nim
   ##   1 div 2 == 0
@@ -1097,7 +1107,7 @@ proc `*`*[T: SomeUnsignedInt](x, y: T): T {.magic: "MulU", noSideEffect.}
 
 proc `div`*[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
   ## computes the integer division. This is roughly the same as
-  ## ``floor(x/y)``.
+  ## ``trunc(x/y)``.
   ##
   ## .. code-block:: Nim
   ##  (7 div 5) == 1
@@ -2015,19 +2025,19 @@ when defined(nimNewRoof):
         yield res
         inc(res)
 
-  iterator `..`*(a, b: int64): int64 {.inline.} =
-    ## A special version of ``..`` for ``int64`` only.
-    var res = a
-    while res <= b:
-      yield res
-      inc(res)
+  template dotdotImpl(t) {.dirty.} =
+    iterator `..`*(a, b: t): t {.inline.} =
+      ## A type specialized version of ``..`` for convenience so that
+      ## mixing integer types work better.
+      var res = a
+      while res <= b:
+        yield res
+        inc(res)
 
-  iterator `..`*(a, b: int32): int32 {.inline.} =
-    ## A special version of ``..`` for ``int32`` only.
-    var res = a
-    while res <= b:
-      yield res
-      inc(res)
+  dotdotImpl(int64)
+  dotdotImpl(int32)
+  dotdotImpl(uint64)
+  dotdotImpl(uint32)
 
 else:
   iterator countup*[S, T](a: S, b: T, step = 1): T {.inline.} =
@@ -2763,9 +2773,9 @@ when defined(nimvarargstyped):
     ## pretends to be free of side effects, so that it can be used for debugging
     ## routines marked as `noSideEffect <manual.html#pragmas-nosideeffect-pragma>`_.
 else:
-  proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
+  proc echo*(x: varargs[untyped, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
     benign, sideEffect.}
-  proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect,
+  proc debugEcho*(x: varargs[untyped, `$`]) {.magic: "Echo", noSideEffect,
                                              tags: [], raises: [].}
 
 template newException*(exceptn: typedesc, message: string;
@@ -3706,7 +3716,7 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[
   ## .. code-block:: nim
   ##   import strutils
   ##
-  ##   template testException(exception, code: expr): stmt =
+  ##   template testException(exception, code: untyped): typed =
   ##     try:
   ##       let pos = instantiationInfo()
   ##       discard(code)
@@ -3844,11 +3854,11 @@ type
 {.deprecated: [PNimrodNode: NimNode].}
 
 when false:
-  template eval*(blk: stmt): stmt =
+  template eval*(blk: typed): typed =
     ## executes a block of code at compile time just as if it was a macro
     ## optionally, the block can return an AST tree that will replace the
     ## eval expression
-    macro payload: stmt {.gensym.} = blk
+    macro payload: typed {.gensym.} = blk
     payload()
 
 when hasAlloc:
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 8c3801687..afc435638 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -213,12 +213,20 @@ proc atomicDec*(memLoc: var int, x: int = 1): int =
     result = memLoc
 
 when defined(vcc):
-  proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64
-    {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
-  proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32
-    {.importc: "_InterlockedCompareExchange", header: "<intrin.h>".}
-  proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte
-    {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
+  when defined(cpp):
+    proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64
+      {.importcpp: "_InterlockedCompareExchange64(static_cast<NI64 volatile *>(#), #, #)", header: "<intrin.h>".}
+    proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32
+      {.importcpp: "_InterlockedCompareExchange(static_cast<NI volatile *>(#), #, #)", header: "<intrin.h>".}
+    proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte
+      {.importcpp: "_InterlockedCompareExchange8(static_cast<char volatile *>(#), #, #)", header: "<intrin.h>".}
+  else:
+    proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64
+      {.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
+    proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32
+      {.importc: "_InterlockedCompareExchange", header: "<intrin.h>".}
+    proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte
+      {.importc: "_InterlockedCompareExchange8", header: "<intrin.h>".}
 
   proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
     when sizeof(T) == 8:
diff --git a/lib/system/endb.nim b/lib/system/endb.nim
index 35d8f25c4..d51ae29df 100644
--- a/lib/system/endb.nim
+++ b/lib/system/endb.nim
@@ -370,7 +370,7 @@ proc commandPrompt() =
     if dbgUser.len == 0: dbgUser.len = oldLen
     # now look what we have to do:
     var i = scanWord(addr dbgUser.data, dbgTemp, 0)
-    template `?`(x: expr): expr = dbgTemp == cstring(x)
+    template `?`(x: untyped): untyped = dbgTemp == cstring(x)
     if ?"s" or ?"step":
       dbgState = dbStepInto
       again = false
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 9e02d6824..70c18ae21 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -155,6 +155,52 @@ when not hasThreadSupport:
   var
     tempFrames: array[0..127, PFrame] # should not be alloc'd on stack
 
+const
+  reraisedFromBegin = -10
+  reraisedFromEnd = -100
+
+template reraisedFrom(z): untyped =
+  StackTraceEntry(procname: nil, line: z, filename: nil)
+
+proc auxWriteStackTrace(f: PFrame; s: var seq[StackTraceEntry]) =
+  var
+    it = f
+    i = 0
+  while it != nil:
+    inc(i)
+    it = it.prev
+  var last = i-1
+  if s.isNil:
+    s = newSeq[StackTraceEntry](i)
+  else:
+    last = s.len + i - 1
+    s.setLen(last+1)
+  it = f
+  while it != nil:
+    s[last] = StackTraceEntry(procname: it.procname,
+                              line: it.line,
+                              filename: it.filename)
+    it = it.prev
+    dec last
+
+template addFrameEntry(s, f: untyped) =
+  var oldLen = s.len
+  add(s, f.filename)
+  if f.line > 0:
+    add(s, '(')
+    add(s, $f.line)
+    add(s, ')')
+  for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
+  add(s, f.procname)
+  add(s, "\n")
+
+proc `$`(s: seq[StackTraceEntry]): string =
+  result = newStringOfCap(2000)
+  for i in 0 .. s.len-1:
+    if s[i].line == reraisedFromBegin: result.add "[[reraised from:\n"
+    elif s[i].line == reraisedFromEnd: result.add "]]\n"
+    else: addFrameEntry(result, s[i])
+
 proc auxWriteStackTrace(f: PFrame, s: var string) =
   when hasThreadSupport:
     var
@@ -194,17 +240,9 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
     if tempFrames[j] == nil:
       add(s, "(")
       add(s, $skipped)
-      add(s, " calls omitted) ...")
+      add(s, " calls omitted) ...\n")
     else:
-      var oldLen = s.len
-      add(s, tempFrames[j].filename)
-      if tempFrames[j].line > 0:
-        add(s, '(')
-        add(s, $tempFrames[j].line)
-        add(s, ')')
-      for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
-      add(s, tempFrames[j].procname)
-    add(s, "\n")
+      addFrameEntry(s, tempFrames[j])
 
 proc stackTraceAvailable*(): bool
 
@@ -221,6 +259,13 @@ when hasSomeStackTrace:
       auxWriteStackTraceWithBacktrace(s)
     else:
       add(s, "No stack traceback available\n")
+
+  proc rawWriteStackTrace(s: var seq[StackTraceEntry]) =
+    when NimStackTrace:
+      auxWriteStackTrace(framePtr, s)
+    else:
+      s = nil
+
   proc stackTraceAvailable(): bool =
     when NimStackTrace:
       if framePtr == nil:
@@ -240,12 +285,6 @@ proc quitOrDebug() {.inline.} =
   else:
     endbStep() # call the debugger
 
-when false:
-  proc rawRaise*(e: ref Exception) =
-    ## undocumented. Do not use.
-    pushCurrentException(e)
-    c_longjmp(excHandler.context, 1)
-
 var onUnhandledException*: (proc (errorMsg: string) {.
   nimcall.}) ## set this error \
   ## handler to override the existing behaviour on an unhandled exception.
@@ -282,7 +321,7 @@ proc raiseExceptionAux(e: ref Exception) =
       when hasSomeStackTrace:
         var buf = newStringOfCap(2000)
         if isNil(e.trace): rawWriteStackTrace(buf)
-        else: add(buf, e.trace)
+        else: add(buf, $e.trace)
         add(buf, "Error: unhandled exception: ")
         if not isNil(e.msg): add(buf, e.msg)
         add(buf, " [")
@@ -318,12 +357,11 @@ proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
   if e.name.isNil: e.name = ename
   when hasSomeStackTrace:
     if e.trace.isNil:
-      e.trace = ""
       rawWriteStackTrace(e.trace)
     elif framePtr != nil:
-      e.trace.add "[[reraised from:\n"
+      e.trace.add reraisedFrom(reraisedFromBegin)
       auxWriteStackTrace(framePtr, e.trace)
-      e.trace.add "]]\n"
+      e.trace.add reraisedFrom(reraisedFromEnd)
   raiseExceptionAux(e)
 
 proc reraiseException() {.compilerRtl.} =
@@ -349,10 +387,15 @@ proc getStackTrace(): string =
 
 proc getStackTrace(e: ref Exception): string =
   if not isNil(e) and not isNil(e.trace):
-    result = e.trace
+    result = $e.trace
   else:
     result = ""
 
+proc getStackTraceEntries*(e: ref Exception): seq[StackTraceEntry] =
+  ## Returns the attached stack trace to the exception ``e`` as
+  ## a ``seq``. This is not yet available for the JS backend.
+  shallowCopy(result, e.trace)
+
 when defined(nimRequiresNimFrame):
   proc stackOverflow() {.noinline.} =
     writeStackTrace()
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index 70bed8740..4ecf3b226 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -173,7 +173,7 @@ proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
 when BitsPerPage mod (sizeof(int)*8) != 0:
   {.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
 
-template color(c): expr = c.refCount and colorMask
+template color(c): untyped = c.refCount and colorMask
 template setColor(c, col) =
   c.refcount = c.refcount and not colorMask or col
 
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index a0d10c446..dc2d13578 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -153,12 +153,12 @@ proc preferSpawn*(): bool =
   ## it is not necessary to call this directly; use 'spawnX' instead.
   result = gSomeReady.event
 
-proc spawn*(call: stmt) {.magic: "Spawn".}
+proc spawn*(call: typed) {.magic: "Spawn".}
   ## always spawns a new task, so that the 'call' is never executed on
   ## the calling thread. 'call' has to be proc call 'p(...)' where 'p'
   ## is gcsafe and has 'void' as the return type.
 
-template spawnX*(call: stmt) =
+template spawnX*(call: typed) =
   ## spawns a new task if a CPU core is ready, otherwise executes the
   ## call in the calling thread. Usually it is advised to
   ## use 'spawn' in order to not block the producer for an unknown
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index d9586b00d..3f8e0eff0 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -322,37 +322,40 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
   result.add x
 
 proc add*(result: var string; x: float) =
-  var buf: array[0..64, char]
-  when defined(nimNoArrayToCstringConversion):
-    var n: int = c_sprintf(addr buf, "%.16g", x)
+  when nimvm:
+    result.add $x
   else:
-    var n: int = c_sprintf(buf, "%.16g", x)
-  var hasDot = false
-  for i in 0..n-1:
-    if buf[i] == ',':
-      buf[i] = '.'
-      hasDot = true
-    elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
-      hasDot = true
-  if not hasDot:
-    buf[n] = '.'
-    buf[n+1] = '0'
-    buf[n+2] = '\0'
-  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN'
-  # of '-1.#IND' are produced.
-  # We want to get rid of these here:
-  if buf[n-1] in {'n', 'N', 'D', 'd'}:
-    result.add "nan"
-  elif buf[n-1] == 'F':
-    if buf[0] == '-':
-      result.add "-inf"
+    var buf: array[0..64, char]
+    when defined(nimNoArrayToCstringConversion):
+      var n: int = c_sprintf(addr buf, "%.16g", x)
     else:
-      result.add "inf"
-  else:
-    var i = 0
-    while buf[i] != '\0':
-      result.add buf[i]
-      inc i
+      var n: int = c_sprintf(buf, "%.16g", x)
+    var hasDot = false
+    for i in 0..n-1:
+      if buf[i] == ',':
+        buf[i] = '.'
+        hasDot = true
+      elif buf[i] in {'a'..'z', 'A'..'Z', '.'}:
+        hasDot = true
+    if not hasDot:
+      buf[n] = '.'
+      buf[n+1] = '0'
+      buf[n+2] = '\0'
+    # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN'
+    # of '-1.#IND' are produced.
+    # We want to get rid of these here:
+    if buf[n-1] in {'n', 'N', 'D', 'd'}:
+      result.add "nan"
+    elif buf[n-1] == 'F':
+      if buf[0] == '-':
+        result.add "-inf"
+      else:
+        result.add "inf"
+    else:
+      var i = 0
+      while buf[i] != '\0':
+        result.add buf[i]
+        inc i
 
 proc nimFloatToStr(f: float): string {.compilerproc.} =
   result = newStringOfCap(8)
diff --git a/tests/async/tasyncall.nim b/tests/async/tasyncall.nim
index 7daecd9ef..a3926eabd 100644
--- a/tests/async/tasyncall.nim
+++ b/tests/async/tasyncall.nim
@@ -40,8 +40,7 @@ proc testVarargs(x, y, z: int): seq[int] =
 
   result = waitFor all(a, b, c)
 
-suite "tasyncall":
-  test "testFuturesWithValue":
+block:
     let
       startTime = cpuTime()
       results = testFuturesWithValue(42)
@@ -51,14 +50,14 @@ suite "tasyncall":
     doAssert execTime * 1000 < taskCount * sleepDuration
     doAssert results == expected
 
-  test "testFuturesWithoutValues":
+block:
     let startTime = cpuTime()
     testFuturesWithoutValues()
     let execTime = cpuTime() - startTime
 
     doAssert execTime * 1000 < taskCount * sleepDuration
 
-  test "testVarargs":
+block:
     let
       startTime = cpuTime()
       results = testVarargs(1, 2, 3)
@@ -68,7 +67,7 @@ suite "tasyncall":
     doAssert execTime * 100 < taskCount * sleepDuration
     doAssert results == expected
 
-  test "all on seq[Future]":
+block:
     let
       noIntFuturesFut = all(newSeq[Future[int]]())
       noVoidFuturesFut = all(newSeq[Future[void]]())
diff --git a/tests/async/tasyncsend4757.nim b/tests/async/tasyncsend4757.nim
index 1066f38e5..752bb3e75 100644
--- a/tests/async/tasyncsend4757.nim
+++ b/tests/async/tasyncsend4757.nim
@@ -3,11 +3,22 @@ discard """
   output: "Finished"
 """
 
-import asyncdispatch
+import asyncdispatch, asyncnet
+
+proc createServer(port: Port) {.async.} =
+  var server = newAsyncSocket()
+  server.setSockOpt(OptReuseAddr, true)
+  bindAddr(server, port)
+  server.listen()
+  while true:
+    let client = await server.accept()
+    discard await client.recvLine()
+
+asyncCheck createServer(10335.Port)
 
 proc f(): Future[void] {.async.} =
   let s = newAsyncNativeSocket()
-  await s.connect("example.com", 80.Port)
+  await s.connect("localhost", 10335.Port)
   await s.send("123")
   echo "Finished"
 
diff --git a/tests/async/tnewasyncudp.nim b/tests/async/tnewasyncudp.nim
index b56cdc71b..e61f630e4 100644
--- a/tests/async/tnewasyncudp.nim
+++ b/tests/async/tnewasyncudp.nim
@@ -86,7 +86,7 @@ proc readMessages(server: AsyncFD) {.async.} =
     size = 0
     var grammString = $cstring(addr buffer)
     if grammString.startswith("Message ") and
-       saddr.sin_addr.s_addr == 0x100007F:
+       saddr.sin_addr.s_addr == nativesockets.ntohl(INADDR_LOOPBACK.uint32):
       await sendTo(server, addr grammString[0], len(grammString),
                    cast[ptr SockAddr](addr saddr), slen)
       inc(msgCount)
diff --git a/tests/ccgbugs/trefseqsort.nim b/tests/ccgbugs/trefseqsort.nim
new file mode 100644
index 000000000..2410770cf
--- /dev/null
+++ b/tests/ccgbugs/trefseqsort.nim
@@ -0,0 +1,33 @@
+discard """
+  output: '''@[0, 4, 9, 1, 3, 2]
+@[0, 1, 2, 3, 9]'''
+"""
+# bug #6724
+import algorithm
+
+type
+  Bar = object
+    bar: ref seq[int]
+  Foo = ref Bar
+
+proc test(x: ref Foo) =
+  x.bar[].del(1)
+  x.bar[].sort(cmp)
+
+proc main() =
+  var foo: ref Foo
+  new(foo)
+
+  var s = @[0, 4, 9, 1, 3, 2]
+
+  var sr: ref seq[int]
+  new(sr)
+  sr[] = s
+
+  foo[] = Foo(bar: sr)
+  echo($foo.bar[])
+
+  test(foo)
+  echo($foo.bar[])
+
+main()
diff --git a/tests/cpp/tasync_cpp.nim b/tests/cpp/tasync_cpp.nim
index ec78ae26c..a5e3374b6 100644
--- a/tests/cpp/tasync_cpp.nim
+++ b/tests/cpp/tasync_cpp.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
   output: "hello"
 """
 
diff --git a/tests/cpp/tcasts.nim b/tests/cpp/tcasts.nim
new file mode 100644
index 000000000..35f06234d
--- /dev/null
+++ b/tests/cpp/tcasts.nim
@@ -0,0 +1,10 @@
+discard """
+  cmd: "nim cpp $file"
+  output: ""
+"""
+
+block: #5979
+  var a = 'a'
+  var p: pointer = cast[pointer](a)
+  var c = cast[char](p)
+  doAssert(c == 'a')
diff --git a/tests/cpp/tcovariancerules.nim b/tests/cpp/tcovariancerules.nim
index dfe4cb941..9365a3a18 100644
--- a/tests/cpp/tcovariancerules.nim
+++ b/tests/cpp/tcovariancerules.nim
@@ -1,5 +1,5 @@
 discard """
-cmd: "nim cpp $file"
+targets: "cpp"
 output: '''
 cat
 cat
diff --git a/tests/cpp/tcppraise.nim b/tests/cpp/tcppraise.nim
index a9ea8e6ce..7db9c0cfa 100644
--- a/tests/cpp/tcppraise.nim
+++ b/tests/cpp/tcppraise.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
   output: '''foo
 bar
 Need odd and >= 3 digits##
diff --git a/tests/cpp/tdont_init_instantiation.nim b/tests/cpp/tdont_init_instantiation.nim
index 652cb1414..fe487fba0 100644
--- a/tests/cpp/tdont_init_instantiation.nim
+++ b/tests/cpp/tdont_init_instantiation.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
   output: ''''''
   disabled: true
 """
diff --git a/tests/cpp/tembarrassing_generic_failure.nim b/tests/cpp/tembarrassing_generic_failure.nim
index 3c31dcdb8..4b5050948 100644
--- a/tests/cpp/tembarrassing_generic_failure.nim
+++ b/tests/cpp/tembarrassing_generic_failure.nim
@@ -1,4 +1,5 @@
 discard """
+  targets: "cpp"
   cmd: "nim cpp --threads:on $file"
 """
 
diff --git a/tests/cpp/temitlist.nim b/tests/cpp/temitlist.nim
index cef0fc52d..a7a8ebde4 100644
--- a/tests/cpp/temitlist.nim
+++ b/tests/cpp/temitlist.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
   output: '''6.0'''
 """
 
diff --git a/tests/cpp/tempty_generic_obj.nim b/tests/cpp/tempty_generic_obj.nim
index e2957a5cd..b4c746a30 100644
--- a/tests/cpp/tempty_generic_obj.nim
+++ b/tests/cpp/tempty_generic_obj.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
   output: '''int
 float'''
 """
diff --git a/tests/cpp/tgen_prototype_for_importc.nim b/tests/cpp/tgen_prototype_for_importc.nim
index 91f34755b..4e5a197a8 100644
--- a/tests/cpp/tgen_prototype_for_importc.nim
+++ b/tests/cpp/tgen_prototype_for_importc.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
   output: '''Hello world'''
 """
 
diff --git a/tests/cpp/tget_subsystem.nim b/tests/cpp/tget_subsystem.nim
index 81009dd39..e9a3fabdd 100644
--- a/tests/cpp/tget_subsystem.nim
+++ b/tests/cpp/tget_subsystem.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
 """
 
 {.emit: """
diff --git a/tests/cpp/tnativesockets.nim b/tests/cpp/tnativesockets.nim
index 6108380a8..c62008050 100644
--- a/tests/cpp/tnativesockets.nim
+++ b/tests/cpp/tnativesockets.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
 """
 
 import nativesockets
diff --git a/tests/cpp/treturn_array.nim b/tests/cpp/treturn_array.nim
index ba4fbd6cc..432b9ce3b 100644
--- a/tests/cpp/treturn_array.nim
+++ b/tests/cpp/treturn_array.nim
@@ -1,3 +1,6 @@
+discard """
+  targets: "cpp"
+"""
 
 # bug #2259
 type Mat4f* = array[0..15, float]
diff --git a/tests/cpp/tsigbreak.nim b/tests/cpp/tsigbreak.nim
index c8044f2bf..9a381d84f 100644
--- a/tests/cpp/tsigbreak.nim
+++ b/tests/cpp/tsigbreak.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
 """
 
 import tables, lists
diff --git a/tests/cpp/tstaticvar_via_typedesc.nim b/tests/cpp/tstaticvar_via_typedesc.nim
index 7a9fa2afc..0d8f424d0 100644
--- a/tests/cpp/tstaticvar_via_typedesc.nim
+++ b/tests/cpp/tstaticvar_via_typedesc.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
   output: "42"
 """
 
diff --git a/tests/cpp/ttemplatetype.nim b/tests/cpp/ttemplatetype.nim
index 7f56a225d..ef24e4cdc 100644
--- a/tests/cpp/ttemplatetype.nim
+++ b/tests/cpp/ttemplatetype.nim
@@ -1,3 +1,7 @@
+discard """
+  targets: "cpp"
+"""
+
 type
   Map {.importcpp: "std::map", header: "<map>".} [T,U] = object
 
diff --git a/tests/cpp/tthread_createthread.nim b/tests/cpp/tthread_createthread.nim
index 363136e9d..b46b876b7 100644
--- a/tests/cpp/tthread_createthread.nim
+++ b/tests/cpp/tthread_createthread.nim
@@ -1,4 +1,5 @@
 discard """
+  targets: "cpp"
   cmd: "nim cpp --hints:on --threads:on $options $file"
 """
 
diff --git a/tests/cpp/ttypeinfo.nim b/tests/cpp/ttypeinfo.nim
index 282c682b2..97825f452 100644
--- a/tests/cpp/ttypeinfo.nim
+++ b/tests/cpp/ttypeinfo.nim
@@ -1,6 +1,6 @@
 discard """
+  targets: "cpp"
   output: '''100'''
-  cmd: "nim cpp $file"
 """
 
 import typeinfo
diff --git a/tests/cpp/ttypeinfo2.nim b/tests/cpp/ttypeinfo2.nim
index 64bd43e96..e3661c848 100644
--- a/tests/cpp/ttypeinfo2.nim
+++ b/tests/cpp/ttypeinfo2.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
 """
 # bug #2841
 import typeinfo
diff --git a/tests/cpp/tvector_iterator.nim b/tests/cpp/tvector_iterator.nim
index cb5ab33af..9df3754ba 100644
--- a/tests/cpp/tvector_iterator.nim
+++ b/tests/cpp/tvector_iterator.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $file"
+  targets: "cpp"
 """
 
 {.emit: """
diff --git a/tests/cpp/tvectorseq.nim b/tests/cpp/tvectorseq.nim
index 6eb5dc9e4..4d9ffc3d6 100644
--- a/tests/cpp/tvectorseq.nim
+++ b/tests/cpp/tvectorseq.nim
@@ -1,7 +1,7 @@
 discard """
+  targets: "cpp"
   output: '''(x: 1.0)
 (x: 0.0)'''
-  cmd: "nim cpp $file"
   disabled: "true"
 """
 
diff --git a/tests/errmsgs/tmake_tuple_visible.nim b/tests/errmsgs/tmake_tuple_visible.nim
new file mode 100644
index 000000000..43337c2a9
--- /dev/null
+++ b/tests/errmsgs/tmake_tuple_visible.nim
@@ -0,0 +1,23 @@
+discard """
+  errormsg: '''got (tuple of (type NimEdAppWindow, int))'''
+  line: 22
+  nimout: '''got (tuple of (type NimEdAppWindow, int))
+but expected one of:
+template xxx(tn: typedesc; i: int)'''
+"""
+
+type
+  NimEdAppWindow = ptr NimEdAppWindowObj
+  NimEdAppWindowObj = object
+    i: int
+
+template gDefineTypeExtended*(tn: typeDesc) =
+  discard
+
+gDefineTypeExtended (NimEdAppWindow)
+
+template xxx*(tn: typeDesc, i: int) =
+  discard
+
+xxx (NimEdAppWindow, 0)
+# bug #6776
diff --git a/tests/exprs/tstmtexprs.nim b/tests/exprs/tstmtexprs.nim
index b2d5db408..01f429b07 100644
--- a/tests/exprs/tstmtexprs.nim
+++ b/tests/exprs/tstmtexprs.nim
@@ -5,7 +5,8 @@ discard """
 6
 abcdefghijklmnopqrstuvwxyz
 145 23
-3'''
+3
+2'''
 """
 
 import strutils
@@ -122,3 +123,21 @@ var testTry =
     PFooBase(field: 5)
 
 echo(testTry.field)
+
+# bug #6166
+
+proc quo(op: proc (x: int): bool): int =
+  result =
+     if op(3):
+        2
+     else:
+        0
+
+echo(
+  if true:
+     quo do (a: int) -> bool:
+        a mod 2 != 0
+  else:
+     quo do (a: int) -> bool:
+        a mod 3 != 0
+)
\ No newline at end of file
diff --git a/tests/generics/toverloading_typedesc.nim b/tests/generics/toverloading_typedesc.nim
index 5882640f2..94f4d860d 100644
--- a/tests/generics/toverloading_typedesc.nim
+++ b/tests/generics/toverloading_typedesc.nim
@@ -1,5 +1,6 @@
 discard """
   exitcode: 0
+  disabled: '''true'''
 """
 import moverloading_typedesc
 import tables
diff --git a/tests/misc/tromans.nim b/tests/misc/tromans.nim
deleted file mode 100644
index 132c73ddd..000000000
--- a/tests/misc/tromans.nim
+++ /dev/null
@@ -1,71 +0,0 @@
-discard """
-  file: "tromans.nim"
-  output: "success"
-"""
-import
-  strutils
-
-## Convert an integer to a Roman numeral
-# See http://en.wikipedia.org/wiki/Roman_numerals for reference
-
-proc raiseInvalidValue(msg: string) {.noreturn.} =
-  # Yes, we really need a shorthand for this code...
-  var e: ref EInvalidValue
-  new(e)
-  e.msg = msg
-  raise e
-
-# I should use a class, perhaps.
-# --> No. Why introduce additional state into such a simple and nice
-# interface? State is evil. :D
-
-proc RomanToDecimal(romanVal: string): int =
-  result = 0
-  var prevVal = 0
-  for i in countdown(romanVal.len - 1, 0):
-    var val = 0
-    case romanVal[i]
-    of 'I', 'i': val = 1
-    of 'V', 'v': val = 5
-    of 'X', 'x': val = 10
-    of 'L', 'l': val = 50
-    of 'C', 'c': val = 100
-    of 'D', 'd': val = 500
-    of 'M', 'm': val = 1000
-    else: raiseInvalidValue("Incorrect character in roman numeral! (" &
-                            $romanVal[i] & ")")
-    if val >= prevVal:
-      inc(result, val)
-    else:
-      dec(result, val)
-    prevVal = val
-
-proc DecimalToRoman(decValParam: int): string =
-  # Apparently numbers cannot be above 4000
-  # Well, they can be (using overbar or parenthesis notation)
-  # but I see little interest (beside coding challenge) in coding them as
-  # we rarely use huge Roman numeral.
-  const romanComposites = [
-    ("M", 1000), ("CM", 900),
-    ("D", 500), ("CD", 400), ("C", 100),
-    ("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9),
-    ("V", 5), ("IV", 4), ("I", 1)]
-  if decValParam < 1 or decValParam > 3999:
-    raiseInvalidValue("number not representable")
-  result = ""
-  var decVal = decValParam
-  for key, val in items(romanComposites):
-    while decVal >= val:
-      dec(decVal, val)
-      result.add(key)
-
-for i in 1..100:
-  if RomanToDecimal(DecimalToRoman(i)) != i: quit "BUG"
-
-for i in items([1238, 1777, 3830, 2401, 379, 33, 940, 3973]):
-  if RomanToDecimal(DecimalToRoman(i)) != i: quit "BUG"
-
-echo "success" #OUT success
-
-
-
diff --git a/tests/overload/tstatic_with_converter.nim b/tests/overload/tstatic_with_converter.nim
new file mode 100644
index 000000000..2871744eb
--- /dev/null
+++ b/tests/overload/tstatic_with_converter.nim
@@ -0,0 +1,47 @@
+discard """
+output: '''
+9.0'''
+"""
+
+### bug #6773
+
+{.emit: """ /*INCLUDESECTION*/
+typedef double cimported;
+ 
+cimported set1_imported(double x) {
+  return x;
+}
+ 
+"""}
+ 
+type vfloat{.importc: "cimported".} = object
+ 
+proc set1(a: float): vfloat {.importc: "set1_imported".}
+ 
+converter scalar_to_vector(x: float): vfloat =
+  set1(x)
+ 
+proc sqrt(x: vfloat): vfloat =
+  x
+ 
+proc pow(x, y: vfloat): vfloat =
+  y
+ 
+proc `^`(x: vfloat, exp: static[int]): vfloat =
+  when exp == 0:
+    1.0
+  else:
+    x
+ 
+proc `^`(x: vfloat, exp: static[float]): vfloat =
+  when exp == 0.5:
+    sqrt(x)
+  else:
+   pow(x, exp)
+ 
+proc `$`(x: vfloat): string =
+  let y = cast[ptr float](unsafeAddr x)
+  echo y[]
+ 
+let x = set1(9.0)
+echo x^0.5
diff --git a/tests/parser/tpostexprblocks.nim b/tests/parser/tpostexprblocks.nim
index 341ca737a..3b9c956c2 100644
--- a/tests/parser/tpostexprblocks.nim
+++ b/tests/parser/tpostexprblocks.nim
@@ -1,82 +1,82 @@
 discard """
 nimout: '''
 StmtList
-  Ident !"foo010"
+  Ident ident"foo010"
   Call
-    Ident !"foo020"
+    Ident ident"foo020"
   Call
-    Ident !"foo030"
-    Ident !"x"
+    Ident ident"foo030"
+    Ident ident"x"
   Command
-    Ident !"foo040"
-    Ident !"x"
+    Ident ident"foo040"
+    Ident ident"x"
   Call
-    Ident !"foo050"
+    Ident ident"foo050"
     StmtList
       DiscardStmt
         Empty
   Call
-    Ident !"foo060"
+    Ident ident"foo060"
     StmtList
       DiscardStmt
         Empty
   Call
-    Ident !"foo070"
+    Ident ident"foo070"
     StrLit test
     StmtList
       DiscardStmt
         Empty
   Call
-    Ident !"foo080"
+    Ident ident"foo080"
     StrLit test
     StmtList
       DiscardStmt
         Empty
   Command
-    Ident !"foo090"
+    Ident ident"foo090"
     StrLit test
     StmtList
       DiscardStmt
         Empty
   Command
-    Ident !"foo100"
+    Ident ident"foo100"
     Call
       StrLit test
       StmtList
         DiscardStmt
           Empty
   Command
-    Ident !"foo101"
+    Ident ident"foo101"
     Call
       IntLit 10
       StmtList
         DiscardStmt
           Empty
   Command
-    Ident !"foo110"
+    Ident ident"foo110"
     IntLit 1
     Par
       Infix
-        Ident !"+"
+        Ident ident"+"
         IntLit 2
         IntLit 3
     StmtList
       DiscardStmt
         Empty
   Command
-    Ident !"foo120"
+    Ident ident"foo120"
     IntLit 1
     Call
       Par
         Infix
-          Ident !"+"
+          Ident ident"+"
           IntLit 2
           IntLit 3
       StmtList
         DiscardStmt
           Empty
   Call
-    Ident !"foo130"
+    Ident ident"foo130"
     Do
       Empty
       Empty
@@ -84,7 +84,7 @@ StmtList
       FormalParams
         Empty
         IdentDefs
-          Ident !"x"
+          Ident ident"x"
           Empty
           Empty
       Empty
@@ -93,7 +93,7 @@ StmtList
         DiscardStmt
           Empty
   Call
-    Ident !"foo140"
+    Ident ident"foo140"
     Do
       Empty
       Empty
@@ -101,8 +101,8 @@ StmtList
       FormalParams
         Empty
         IdentDefs
-          Ident !"x"
-          Ident !"int"
+          Ident ident"x"
+          Ident ident"int"
           Empty
       Empty
       Empty
@@ -110,16 +110,16 @@ StmtList
         DiscardStmt
           Empty
   Call
-    Ident !"foo150"
+    Ident ident"foo150"
     Do
       Empty
       Empty
       Empty
       FormalParams
-        Ident !"int"
+        Ident ident"int"
         IdentDefs
-          Ident !"x"
-          Ident !"int"
+          Ident ident"x"
+          Ident ident"int"
           Empty
       Empty
       Empty
@@ -127,9 +127,9 @@ StmtList
         DiscardStmt
           Empty
   Command
-    Ident !"foo160"
+    Ident ident"foo160"
     Call
-      Ident !"x"
+      Ident ident"x"
       Do
         Empty
         Empty
@@ -137,7 +137,7 @@ StmtList
         FormalParams
           Empty
           IdentDefs
-            Ident !"y"
+            Ident ident"y"
             Empty
             Empty
         Empty
@@ -146,7 +146,7 @@ StmtList
           DiscardStmt
             Empty
   Call
-    Ident !"foo170"
+    Ident ident"foo170"
     StmtList
       DiscardStmt
         Empty
@@ -155,7 +155,7 @@ StmtList
         DiscardStmt
           Empty
   Call
-    Ident !"foo180"
+    Ident ident"foo180"
     StmtList
       DiscardStmt
         Empty
@@ -167,9 +167,9 @@ StmtList
         DiscardStmt
           Empty
   Command
-    Ident !"foo190"
+    Ident ident"foo190"
     Call
-      Ident !"x"
+      Ident ident"x"
       Do
         Empty
         Empty
@@ -177,7 +177,7 @@ StmtList
         FormalParams
           Empty
           IdentDefs
-            Ident !"y"
+            Ident ident"y"
             Empty
             Empty
         Empty
@@ -190,9 +190,9 @@ StmtList
         Empty
         Empty
         FormalParams
-          Ident !"int"
+          Ident ident"int"
           IdentDefs
-            Ident !"z"
+            Ident ident"z"
             Empty
             Empty
         Empty
@@ -205,10 +205,10 @@ StmtList
         Empty
         Empty
         FormalParams
-          Ident !"int"
+          Ident ident"int"
           IdentDefs
-            Ident !"w"
-            Ident !"int"
+            Ident ident"w"
+            Ident ident"int"
             Empty
         Empty
         Empty
@@ -223,10 +223,10 @@ StmtList
           DiscardStmt
             Empty
   Call
-    Ident !"foo200"
-    Ident !"x"
+    Ident ident"foo200"
+    Ident ident"x"
     Call
-      Ident !"bar"
+      Ident ident"bar"
       StmtList
         DiscardStmt
           Empty
@@ -236,53 +236,53 @@ StmtList
             Empty
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
-      Ident !"foo210"
+      Ident ident"foo210"
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
       Call
-        Ident !"foo220"
+        Ident ident"foo220"
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
       Call
-        Ident !"foo230"
-        Ident !"x"
+        Ident ident"foo230"
+        Ident ident"x"
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
       Command
-        Ident !"foo240"
-        Ident !"x"
+        Ident ident"foo240"
+        Ident ident"x"
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
       Call
-        Ident !"foo250"
+        Ident ident"foo250"
         StmtList
           DiscardStmt
             Empty
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
       Call
-        Ident !"foo260"
+        Ident ident"foo260"
         StmtList
           DiscardStmt
             Empty
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
       Call
-        Ident !"foo270"
+        Ident ident"foo270"
         StmtList
           DiscardStmt
             Empty
@@ -292,12 +292,12 @@ StmtList
               Empty
   VarSection
     IdentDefs
-      Ident !"a"
+      Ident ident"a"
       Empty
       Command
-        Ident !"foo280"
+        Ident ident"foo280"
         Call
-          Ident !"x"
+          Ident ident"x"
           Do
             Empty
             Empty
@@ -305,7 +305,7 @@ StmtList
             FormalParams
               Empty
               IdentDefs
-                Ident !"y"
+                Ident ident"y"
                 Empty
                 Empty
             Empty
@@ -318,40 +318,40 @@ StmtList
               DiscardStmt
                 Empty
   Asgn
-    Ident !"a"
-    Ident !"foo290"
+    Ident ident"a"
+    Ident ident"foo290"
   Asgn
-    Ident !"a"
+    Ident ident"a"
     Call
-      Ident !"foo300"
+      Ident ident"foo300"
   Asgn
-    Ident !"a"
+    Ident ident"a"
     Call
-      Ident !"foo310"
-      Ident !"x"
+      Ident ident"foo310"
+      Ident ident"x"
   Asgn
-    Ident !"a"
+    Ident ident"a"
     Command
-      Ident !"foo320"
-      Ident !"x"
+      Ident ident"foo320"
+      Ident ident"x"
   Asgn
-    Ident !"a"
+    Ident ident"a"
     Call
-      Ident !"foo330"
+      Ident ident"foo330"
       StmtList
         DiscardStmt
           Empty
   Asgn
-    Ident !"a"
+    Ident ident"a"
     Call
-      Ident !"foo340"
+      Ident ident"foo340"
       StmtList
         DiscardStmt
           Empty
   Asgn
-    Ident !"a"
+    Ident ident"a"
     Call
-      Ident !"foo350"
+      Ident ident"foo350"
       StmtList
         DiscardStmt
           Empty
@@ -360,13 +360,13 @@ StmtList
           DiscardStmt
             Empty
   Asgn
-    Ident !"a"
+    Ident ident"a"
     Command
-      Ident !"foo360"
+      Ident ident"foo360"
       Call
         DotExpr
-          Ident !"x"
-          Ident !"bar"
+          Ident ident"x"
+          Ident ident"bar"
         Do
           Empty
           Empty
@@ -374,7 +374,7 @@ StmtList
           FormalParams
             Empty
             IdentDefs
-              Ident !"y"
+              Ident ident"y"
               Empty
               Empty
           Empty
@@ -388,20 +388,20 @@ StmtList
               Empty
   Command
     DotExpr
-      Ident !"foo370"
-      Ident !"add"
+      Ident ident"foo370"
+      Ident ident"add"
     Call
-      Ident !"quote"
+      Ident ident"quote"
       StmtList
         DiscardStmt
           Empty
   Call
     DotExpr
-      Ident !"foo380"
-      Ident !"add"
+      Ident ident"foo380"
+      Ident ident"add"
     BracketExpr
       Call
-        Ident !"quote"
+        Ident ident"quote"
         StmtList
           DiscardStmt
             Empty
diff --git a/tests/rational/trat_init.nim b/tests/rational/trat_init.nim
index df29ff6e3..360a48537 100644
--- a/tests/rational/trat_init.nim
+++ b/tests/rational/trat_init.nim
@@ -1,10 +1,14 @@
 discard """
-  file: "trat_init.nim"
-  exitcode: "1"
+  output: '''true'''
 """
 import rationals
 var
   z = Rational[int](num: 0, den: 1)
   o = initRational(num=1, den=1)
   a = initRational(1, 2)
-  r = initRational(1, 0)  # this fails - no zero denominator
+
+try:
+  var
+    r = initRational(1, 0)  # this fails - no zero denominator
+except AssertionError:
+  echo "true"
diff --git a/tests/stdlib/thttpclient.nim b/tests/stdlib/thttpclient.nim
index 54588d3f0..fff02722a 100644
--- a/tests/stdlib/thttpclient.nim
+++ b/tests/stdlib/thttpclient.nim
@@ -3,6 +3,7 @@ discard """
   exitcode: 0
   output: "OK"
   disabled: "travis"
+  disabled: "appveyor"
 """
 
 import strutils
diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims
index 2500bac73..d3eb9808e 100644
--- a/tests/test_nimscript.nims
+++ b/tests/test_nimscript.nims
@@ -21,5 +21,6 @@ import subexes
 import tables
 import unicode
 import uri
+import macros
 
 echo "Nimscript imports are successful."
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 68e988975..ca621969f 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -219,9 +219,9 @@ proc debuggerTests(r: var TResults, cat: Category, options: string) =
 proc jsTests(r: var TResults, cat: Category, options: string) =
   template test(filename: untyped) =
     testSpec r, makeTest(filename, options & " -d:nodejs", cat,
-                         actionRun, targetJS)
+                         actionRun), targetJS
     testSpec r, makeTest(filename, options & " -d:nodejs -d:release", cat,
-                         actionRun, targetJS)
+                         actionRun), targetJS
 
   for t in os.walkFiles("tests/js/t*.nim"):
     test(t)
@@ -245,10 +245,10 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) =
     testSpec r, makeTest(filename, options, cat, action)
 
   template testJS(filename: untyped) =
-    testSpec r, makeTest(filename, options, cat, actionCompile, targetJS)
+    testSpec r, makeTest(filename, options, cat, actionCompile), targetJS
 
   template testCPP(filename: untyped) =
-    testSpec r, makeTest(filename, options, cat, actionCompile, targetCPP)
+    testSpec r, makeTest(filename, options, cat, actionCompile), targetCPP
 
   let tests = [
     "niminaction/Chapter3/ChatApp/src/server",
@@ -387,7 +387,7 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) =
         installStatus = waitForExitEx(installProcess)
       installProcess.close
       if installStatus != QuitSuccess:
-        r.addResult(test, "", "", reInstallFailed)
+        r.addResult(test, targetC, "", "", reInstallFailed)
         continue
 
       let
@@ -396,12 +396,12 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) =
         buildStatus = waitForExitEx(buildProcess)
       buildProcess.close
       if buildStatus != QuitSuccess:
-        r.addResult(test, "", "", reBuildFailed)
-      r.addResult(test, "", "", reSuccess)
-    r.addResult(packageFileTest, "", "", reSuccess)
+        r.addResult(test, targetC, "", "", reBuildFailed)
+      r.addResult(test, targetC, "", "", reSuccess)
+    r.addResult(packageFileTest, targetC, "", "", reSuccess)
   except JsonParsingError:
     echo("[Warning] - Cannot run nimble tests: Invalid package file.")
-    r.addResult(packageFileTest, "", "", reBuildFailed)
+    r.addResult(packageFileTest, targetC, "", "", reBuildFailed)
 
 
 # ----------------------------------------------------------------------------
@@ -420,7 +420,7 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
   let test = "tests" & DirSep &.? cat.string / test
   let target = if cat.string.normalize == "js": targetJS else: targetC
 
-  if existsFile(test): testSpec r, makeTest(test, options, cat, target = target)
+  if existsFile(test): testSpec r, makeTest(test, options, cat), target
   else: echo "[Warning] - ", test, " test does not exist"
 
 proc processCategory(r: var TResults, cat: Category, options: string) =
diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim
index e5506e796..e8513ab24 100644
--- a/tests/testament/specs.nim
+++ b/tests/testament/specs.nim
@@ -13,6 +13,7 @@ import parseutils, strutils, os, osproc, streams, parsecfg
 var compilerPrefix* = "compiler" / "nim "
 
 let isTravis = existsEnv("TRAVIS")
+let isAppVeyor = existsEnv("APPVEYOR")
 
 proc cmdTemplate*(): string =
   compilerPrefix & "$target --lib:lib --hints:on -d:testing $options $file"
@@ -151,6 +152,7 @@ proc parseSpec*(filename: string): TSpec =
       result.sortoutput = parseCfgBool(e.value)
     of "exitcode":
       discard parseInt(e.value, result.exitCode)
+      result.action = actionRun
     of "msg":
       result.msg = e.value
       if result.action != actionRun:
@@ -178,6 +180,8 @@ proc parseSpec*(filename: string): TSpec =
         when defined(posix): result.err = reIgnored
       of "travis":
         if isTravis: result.err = reIgnored
+      of "appveyor":
+        if isAppVeyor: result.err = reIgnored
       else:
         raise newException(ValueError, "cannot interpret as a bool: " & e.value)
     of "cmd":
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index d75c9d770..2f0485135 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -44,7 +44,6 @@ type
     name: string
     cat: Category
     options: string
-    target: TTarget
     action: TTestAction
     startTime: float
 
@@ -155,13 +154,13 @@ proc `$`(x: TResults): string =
             "Tests skipped: $2 / $3 <br />\n") %
             [$x.passed, $x.skipped, $x.total]
 
-proc addResult(r: var TResults, test: TTest,
+proc addResult(r: var TResults, test: TTest, target: TTarget,
                expected, given: string, success: TResultEnum) =
-  let name = test.name.extractFilename & test.options
+  let name = test.name.extractFilename & " " & $target & test.options
   let duration = epochTime() - test.startTime
   backend.writeTestResult(name = name,
                           category = test.cat.string,
-                          target = $test.target,
+                          target = $target,
                           action = $test.action,
                           result = $success,
                           expected = expected,
@@ -197,29 +196,29 @@ proc addResult(r: var TResults, test: TTest,
     discard waitForExit(p)
     close(p)
 
-proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
+proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest, target: TTarget) =
   if strip(expected.msg) notin strip(given.msg):
-    r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
+    r.addResult(test, target, expected.msg, given.msg, reMsgsDiffer)
   elif expected.nimout.len > 0 and expected.nimout.normalizeMsg notin given.nimout.normalizeMsg:
-    r.addResult(test, expected.nimout, given.nimout, reMsgsDiffer)
+    r.addResult(test, target, expected.nimout, given.nimout, reMsgsDiffer)
   elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and
       "internal error:" notin expected.msg:
-    r.addResult(test, expected.file, given.file, reFilesDiffer)
+    r.addResult(test, target, expected.file, given.file, reFilesDiffer)
   elif expected.line   != given.line   and expected.line   != 0 or
        expected.column != given.column and expected.column != 0:
-    r.addResult(test, $expected.line & ':' & $expected.column,
+    r.addResult(test, target, $expected.line & ':' & $expected.column,
                       $given.line    & ':' & $given.column,
                       reLinesDiffer)
   elif expected.tfile != "" and extractFilename(expected.tfile) != extractFilename(given.tfile) and
       "internal error:" notin expected.msg:
-    r.addResult(test, expected.tfile, given.tfile, reFilesDiffer)
+    r.addResult(test, target, expected.tfile, given.tfile, reFilesDiffer)
   elif expected.tline   != given.tline   and expected.tline   != 0 or
        expected.tcolumn != given.tcolumn and expected.tcolumn != 0:
-    r.addResult(test, $expected.tline & ':' & $expected.tcolumn,
+    r.addResult(test, target, $expected.tline & ':' & $expected.tcolumn,
                       $given.tline    & ':' & $given.tcolumn,
                       reLinesDiffer)
   else:
-    r.addResult(test, expected.msg, given.msg, reSuccess)
+    r.addResult(test, target, expected.msg, given.msg, reSuccess)
     inc(r.passed)
 
 proc generatedFile(path, name: string, target: TTarget): string =
@@ -231,11 +230,11 @@ proc generatedFile(path, name: string, target: TTarget): string =
 proc needsCodegenCheck(spec: TSpec): bool =
   result = spec.maxCodeSize > 0 or spec.ccodeCheck.len > 0
 
-proc codegenCheck(test: TTest, spec: TSpec, expectedMsg: var string,
+proc codegenCheck(test: TTest, target: TTarget, spec: TSpec, expectedMsg: var string,
                   given: var TSpec) =
   try:
     let (path, name, _) = test.name.splitFile
-    let genFile = generatedFile(path, name, test.target)
+    let genFile = generatedFile(path, name, target)
     let contents = readFile(genFile).string
     let check = spec.ccodeCheck
     if check.len > 0:
@@ -267,13 +266,13 @@ proc makeDeterministic(s: string): string =
   sort(x, system.cmp)
   result = join(x, "\n")
 
-proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec;
-                         r: var TResults) =
+proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec,
+                         expected: TSpec; r: var TResults) =
   var expectedmsg: string = ""
   var givenmsg: string = ""
   if given.err == reSuccess:
     if expected.needsCodegenCheck:
-      codegenCheck(test, expected, expectedmsg, given)
+      codegenCheck(test, target, expected, expectedmsg, given)
       givenmsg = given.msg
     if expected.nimout.len > 0:
       expectedmsg = expected.nimout
@@ -282,7 +281,7 @@ proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec;
   else:
     givenmsg = given.nimout.strip
   if given.err == reSuccess: inc(r.passed)
-  r.addResult(test, expectedmsg, givenmsg, given.err)
+  r.addResult(test, target, expectedmsg, givenmsg, given.err)
 
 proc analyzeAndConsolidateOutput(s: string): string =
   result = ""
@@ -298,13 +297,7 @@ proc analyzeAndConsolidateOutput(s: string): string =
       result = substr(rows[i], pos)
       return
 
-proc testSpec(r: var TResults, test: TTest) =
-  # major entry point for a single test
-  if test.target notin targets:
-    r.addResult(test, "", "", reIgnored)
-    inc(r.skipped)
-    return
-
+proc testSpec(r: var TResults, test: TTest, target = targetC) =
   let tname = test.name.addFileExt(".nim")
   #echo "TESTING ", tname
   inc(r.total)
@@ -316,83 +309,92 @@ proc testSpec(r: var TResults, test: TTest) =
     expected.action = actionRunNoSpec
 
   if expected.err == reIgnored:
-    r.addResult(test, "", "", reIgnored)
+    r.addResult(test, target, "", "", reIgnored)
     inc(r.skipped)
     return
 
-  case expected.action
-  of actionCompile:
-    var given = callCompiler(expected.cmd, test.name,
-      test.options & " --stdout --hint[Path]:off --hint[Processing]:off",
-      test.target)
-    compilerOutputTests(test, given, expected, r)
-  of actionRun, actionRunNoSpec:
-    # In this branch of code "early return" pattern is clearer than deep
-    # nested conditionals - the empty rows in between to clarify the "danger"
-    var given = callCompiler(expected.cmd, test.name, test.options,
-                             test.target)
-
-    if given.err != reSuccess:
-      r.addResult(test, "", given.msg, given.err)
-      return
-
-    let isJsTarget = test.target == targetJS
-    var exeFile: string
-    if isJsTarget:
-      let (dir, file, _) = splitFile(tname)
-      exeFile = dir / "nimcache" / file & ".js" # *TODO* hardcoded "nimcache"
-    else:
-      exeFile = changeFileExt(tname, ExeExt)
-
-    if not existsFile(exeFile):
-      r.addResult(test, expected.outp, "executable not found", reExeNotFound)
-      return
-
-    let nodejs = if isJsTarget: findNodeJs() else: ""
-    if isJsTarget and nodejs == "":
-      r.addResult(test, expected.outp, "nodejs binary not in PATH",
-                  reExeNotFound)
-      return
-
-    let exeCmd = (if isJsTarget: nodejs & " " else: "") & exeFile
-    var (buf, exitCode) = execCmdEx(exeCmd, options = {poStdErrToStdOut})
-
-    # Treat all failure codes from nodejs as 1. Older versions of nodejs used
-    # to return other codes, but for us it is sufficient to know that it's not 0.
-    if exitCode != 0: exitCode = 1
-
-    let bufB = if expected.sortoutput: makeDeterministic(strip(buf.string))
-               else: strip(buf.string)
-    let expectedOut = strip(expected.outp)
-
-    if exitCode != expected.exitCode:
-      r.addResult(test, "exitcode: " & $expected.exitCode,
-                        "exitcode: " & $exitCode & "\n\nOutput:\n" &
-                        analyzeAndConsolidateOutput(bufB),
-                        reExitCodesDiffer)
-      return
-
-    if bufB != expectedOut and expected.action != actionRunNoSpec:
-      if not (expected.substr and expectedOut in bufB):
-        given.err = reOutputsDiffer
-        r.addResult(test, expected.outp, bufB, reOutputsDiffer)
-        return
-
-    compilerOutputTests(test, given, expected, r)
-    return
-
-  of actionReject:
-    var given = callCompiler(expected.cmd, test.name, test.options,
-                             test.target)
-    cmpMsgs(r, expected, given, test)
-    return
-
-proc testNoSpec(r: var TResults, test: TTest) =
+  if expected.targets == {}:
+    expected.targets.incl(target)
+
+  for target in expected.targets:
+    if target notin targets:
+      r.addResult(test, target, "", "", reIgnored)
+      inc(r.skipped)
+      continue
+
+    case expected.action
+    of actionCompile:
+      var given = callCompiler(expected.cmd, test.name,
+        test.options & " --stdout --hint[Path]:off --hint[Processing]:off",
+        target)
+      compilerOutputTests(test, target, given, expected, r)
+    of actionRun, actionRunNoSpec:
+      # In this branch of code "early return" pattern is clearer than deep
+      # nested conditionals - the empty rows in between to clarify the "danger"
+      var given = callCompiler(expected.cmd, test.name, test.options,
+                               target)
+
+      if given.err != reSuccess:
+        r.addResult(test, target, "", given.msg, given.err)
+        continue
+
+      let isJsTarget = target == targetJS
+      var exeFile: string
+      if isJsTarget:
+        let (dir, file, _) = splitFile(tname)
+        exeFile = dir / "nimcache" / file & ".js" # *TODO* hardcoded "nimcache"
+      else:
+        exeFile = changeFileExt(tname, ExeExt)
+
+      if not existsFile(exeFile):
+        r.addResult(test, target, expected.outp, "executable not found", reExeNotFound)
+        continue
+
+      let nodejs = if isJsTarget: findNodeJs() else: ""
+      if isJsTarget and nodejs == "":
+        r.addResult(test, target, expected.outp, "nodejs binary not in PATH",
+                    reExeNotFound)
+        continue
+
+      let exeCmd = (if isJsTarget: nodejs & " " else: "") & exeFile
+      var (buf, exitCode) = execCmdEx(exeCmd, options = {poStdErrToStdOut})
+
+      # Treat all failure codes from nodejs as 1. Older versions of nodejs used
+      # to return other codes, but for us it is sufficient to know that it's not 0.
+      if exitCode != 0: exitCode = 1
+
+      let bufB = if expected.sortoutput: makeDeterministic(strip(buf.string))
+                 else: strip(buf.string)
+      let expectedOut = strip(expected.outp)
+
+      if exitCode != expected.exitCode:
+        r.addResult(test, target, "exitcode: " & $expected.exitCode,
+                          "exitcode: " & $exitCode & "\n\nOutput:\n" &
+                          analyzeAndConsolidateOutput(bufB),
+                          reExitCodesDiffer)
+        continue
+
+      if bufB != expectedOut and expected.action != actionRunNoSpec:
+        if not (expected.substr and expectedOut in bufB):
+          given.err = reOutputsDiffer
+          r.addResult(test, target, expected.outp, bufB, reOutputsDiffer)
+          continue
+
+      compilerOutputTests(test, target, given, expected, r)
+      continue
+
+    of actionReject:
+      var given = callCompiler(expected.cmd, test.name, test.options,
+                               target)
+      cmpMsgs(r, expected, given, test, target)
+      continue
+
+proc testNoSpec(r: var TResults, test: TTest, target = targetC) =
   # does not extract the spec because the file is not supposed to have any
   #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)
+  let given = callCompiler(cmdTemplate(), test.name, test.options, target)
+  r.addResult(test, target, "", given.msg, given.err)
   if given.err == reSuccess: inc(r.passed)
 
 proc testC(r: var TResults, test: TTest) =
@@ -400,9 +402,9 @@ proc testC(r: var TResults, test: TTest) =
   let tname = test.name.addFileExt(".c")
   inc(r.total)
   styledEcho "Processing ", fgCyan, extractFilename(tname)
-  var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, test.target)
+  var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, targetC)
   if given.err != reSuccess:
-    r.addResult(test, "", given.msg, given.err)
+    r.addResult(test, targetC, "", given.msg, given.err)
   elif test.action == actionRun:
     let exeFile = changeFileExt(test.name, ExeExt)
     var (_, exitCode) = execCmdEx(exeFile, options = {poStdErrToStdOut, poUsePath})
@@ -410,10 +412,10 @@ proc testC(r: var TResults, test: TTest) =
   if given.err == reSuccess: inc(r.passed)
 
 proc makeTest(test, options: string, cat: Category, action = actionCompile,
-              target = targetC, env: string = ""): TTest =
+              env: string = ""): TTest =
   # start with 'actionCompile', will be overwritten in the spec:
   result = TTest(cat: cat, name: test, options: options,
-                 target: target, action: action, startTime: epochTime())
+                 action: action, startTime: epochTime())
 
 when defined(windows):
   const
@@ -463,7 +465,10 @@ proc main() =
     let testsDir = "tests" & DirSep
     var myself = quoteShell(findExe("tests" / "testament" / "tester"))
     if targetsStr.len > 0:
-      myself &= " '--targets:" & targetsStr & "'"
+      myself &= " " & quoteShell("--targets:" & targetsStr)
+
+    myself &= " " & quoteShell("--nim:" & compilerPrefix)
+
     var cmds: seq[string] = @[]
     let rest = if p.cmdLineRest.string.len > 0: " " & p.cmdLineRest.string else: ""
     for kind, dir in walkDir(testsDir):
diff --git a/tests/types/tinheritref.nim b/tests/types/tinheritref.nim
index ecd62a06f..00af0538d 100644
--- a/tests/types/tinheritref.nim
+++ b/tests/types/tinheritref.nim
@@ -1,5 +1,7 @@
 discard """
-  output: "23"
+  output: '''23
+1.5
+'''
 """
 
 # bug #554, #179
@@ -25,3 +27,24 @@ type
 var
   it: TKeysIterator[int, string] = nil
 
+#bug #5521
+type
+  Texture = enum
+    Smooth
+    Coarse
+
+  FruitBase = object of RootObj
+    color: int
+    case kind: Texture
+    of Smooth:
+      skin: float64
+    of Coarse:
+      grain: int
+
+  Apple = object of FruitBase
+    width: int
+    taste: float64
+
+var x = Apple(kind: Smooth, skin: 1.5)
+var u = x.skin
+echo u
diff --git a/tests/types/tyet_another_generic_regression.nim b/tests/types/tyet_another_generic_regression.nim
new file mode 100644
index 000000000..914166e06
--- /dev/null
+++ b/tests/types/tyet_another_generic_regression.nim
@@ -0,0 +1,13 @@
+import system
+
+type Bar[T] = ref object
+ value: T
+
+type types = int32|int64 # if I change this to just int32 or int64 it works (compiles)
+
+# if I replace Bar everywhere with seq it also compiles fine
+proc Foo[T: Bar[types]](): T =
+ when T is Bar: nil
+
+discard Foo[Bar[int32]]()
+#bug #6073
diff --git a/tests/vm/tnimnode.nim b/tests/vm/tnimnode.nim
index 60e3189b0..0614b9807 100644
--- a/tests/vm/tnimnode.nim
+++ b/tests/vm/tnimnode.nim
@@ -26,12 +26,12 @@ proc checkNode(arg: NimNode; name: string): void {. compileTime .} =
   seqAppend.add(arg)   # bit this creates a copy
   arg.add newCall(ident"echo", newLit("Hello World"))
 
-  assertEq arg.lispRepr          , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
-  assertEq node.lispRepr         , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
-  assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
-  assertEq nodeSeq[0].lispRepr   , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
-  assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
-  assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
+  assertEq arg.lispRepr          , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
+  assertEq node.lispRepr         , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
+  assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
+  assertEq nodeSeq[0].lispRepr   , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
+  assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
+  assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
 
   echo "OK"
 
diff --git a/todo.txt b/todo.txt
index ba137039e..a30c23ce3 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,9 +1,6 @@
 version 1.0 battle plan
 =======================
 
-- make 'doc2' an alias for 'doc' and introduce 'doc0'
-- make 'break' not leave named blocks
-- make FlowVar compatible to Futures
 - fix "high priority" bugs
 - try to fix as many compiler crashes as reasonable
 
@@ -11,6 +8,8 @@ version 1.0 battle plan
 Not critical for 1.0
 ====================
 
+- make 'break' not leave named blocks
+- make FlowVar compatible to Futures
 - make 'not nil' the default (produce warnings instead of errors for
   a smooth migration path)
 - case objects needs to be safe and need to support pattern matching
diff --git a/tools/niminst/buildsh.tmpl b/tools/niminst/buildsh.tmpl
index ec20566ac..3e7d8ae6e 100644
--- a/tools/niminst/buildsh.tmpl
+++ b/tools/niminst/buildsh.tmpl
@@ -144,6 +144,8 @@ case $ucpu in
       mycpu="sparc64"
     fi
     ;;
+  *ppc64le* )
+    mycpu="powerpc64el" ;;
   *ppc64* )
     if [ "$myos" = "linux" ] ; then
       COMP_FLAGS="$COMP_FLAGS -m64"
diff --git a/tools/niminst/makefile.tmpl b/tools/niminst/makefile.tmpl
index 4a20680e0..fa96117b8 100644
--- a/tools/niminst/makefile.tmpl
+++ b/tools/niminst/makefile.tmpl
@@ -17,7 +17,6 @@ endif
 
 ucpu := $(shell sh -c 'uname -m | tr "[:upper:]" "[:lower:]"')
 uos := $(shell sh -c 'uname | tr "[:upper:]" "[:lower:]"')
-uosname := $(shell sh -c 'uname -o | tr "[:upper:]" "[:lower:]"')
 
 ifeq ($(uos),linux)
   myos = linux
@@ -65,15 +64,10 @@ endif
 ifeq ($(uos),haiku)
   myos = haiku
 endif
-ifndef uos
+ifndef myos
   $(error unknown operating system: $(uos))
 endif
 
-ifeq ($(uosname),android)
-  myos = android
-  LINK_FLAGS += -landroid-glob
-endif
-
 ifeq ($(ucpu),i386)
   mycpu = i386
 endif
@@ -107,6 +101,9 @@ endif
 ifeq ($(ucpu),sun)
   mycpu = sparc
 endif
+ifeq ($(ucpu),ppc64le)
+  mycpu = powerpc64el
+endif
 ifeq ($(ucpu),ppc64)
   mycpu = powerpc64
   ifeq ($(myos),linux)
@@ -138,7 +135,16 @@ endif
 ifeq ($(ucpu),armv6l)
   mycpu = arm
 endif
-ifndef ucpu
+ifeq ($(ucpu),armv7l)
+  mycpu = arm
+endif
+ifeq ($(ucpu),armv7hl)
+  mycpu = arm
+endif
+ifeq ($(ucpu),aarch64)
+  mycpu = arm64
+endif
+ifndef mycpu
   $(error unknown processor: $(ucpu))
 endif
 
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index a082520e0..ffb1ac4e3 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -307,7 +307,7 @@ proc buildDoc(c: var TConfigData, destPath: string) =
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
   for d in items(c.srcdoc):
-    commands[i] = findNim() & " doc $# --git.url:$# -o:$# --index:on $#" %
+    commands[i] = findNim() & " doc0 $# --git.url:$# -o:$# --index:on $#" %
       [c.nimArgs, gitRepo,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
diff --git a/web/website.ini b/web/website.ini
index 6142bcddb..be9ec85f0 100644
--- a/web/website.ini
+++ b/web/website.ini
@@ -60,7 +60,7 @@ srcdoc2: "packages/docutils/rst;packages/docutils/rstast"
 srcdoc2: "packages/docutils/rstgen;pure/logging;pure/options;pure/asyncdispatch;pure/asyncnet"
 srcdoc2: "pure/nativesockets;pure/asynchttpserver;pure/net;pure/selectors;pure/future"
 srcdoc2: "deprecated/pure/ftpclient;pure/collections/chains"
-srcdoc2: "pure/asyncfile;pure/asyncftpclient"
+srcdoc2: "pure/asyncfile;pure/asyncftpclient;pure/ioselectors"
 srcdoc2: "pure/md5;pure/rationals"
 srcdoc2: "posix/posix;pure/distros;pure/oswalkdir"
 srcdoc2: "pure/collections/heapqueue"