summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--appveyor.yml5
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/astalgo.nim1
-rw-r--r--compiler/ccgexprs.nim9
-rw-r--r--compiler/ccgstmts.nim7
-rw-r--r--compiler/ccgthreadvars.nim4
-rw-r--r--compiler/cgen.nim11
-rw-r--r--compiler/extccomp.nim14
-rw-r--r--compiler/sem.nim5
-rw-r--r--compiler/semdata.nim30
-rw-r--r--compiler/semexprs.nim13
-rw-r--r--compiler/semfold.nim7
-rw-r--r--compiler/seminst.nim9
-rw-r--r--compiler/semstmts.nim1
-rw-r--r--compiler/semtempl.nim2
-rw-r--r--compiler/semtypes.nim9
-rw-r--r--compiler/sigmatch.nim2
-rw-r--r--compiler/transf.nim7
-rw-r--r--compiler/trees.nim2
-rw-r--r--doc/backends.txt8
-rw-r--r--doc/tut1.rst22
-rw-r--r--koch.nim5
-rw-r--r--lib/impure/db_postgres.nim182
-rw-r--r--lib/impure/re.nim2
-rw-r--r--lib/pure/algorithm.nim2
-rw-r--r--lib/pure/collections/heapqueue.nim41
-rw-r--r--lib/pure/distros.nim2
-rw-r--r--lib/pure/hashes.nim10
-rw-r--r--lib/pure/httpcore.nim6
-rw-r--r--lib/pure/os.nim4
-rw-r--r--lib/pure/parseutils.nim24
-rw-r--r--lib/pure/strutils.nim2
-rw-r--r--lib/system.nim11
-rw-r--r--lib/system/gc_common.nim29
-rw-r--r--lib/system/sysio.nim28
-rw-r--r--lib/system/threads.nim16
-rw-r--r--readme.md253
-rw-r--r--tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim26
-rw-r--r--tests/errmsgs/tproper_stacktrace3.nim23
-rw-r--r--tests/gc/foreign_thr.nim88
-rw-r--r--tests/metatype/tfieldaccessor.nim17
-rw-r--r--tests/overload/tprefer_tygenericinst.nim2
-rw-r--r--tests/stdlib/tbug5382.nim11
-rw-r--r--tests/template/tgensymregression.nim28
-rw-r--r--tests/template/tparams_gensymed.nim9
-rw-r--r--tests/testament/categories.nim1
-rw-r--r--tests/untestable/tpostgres.nim229
-rw-r--r--tools/finish.nim3
-rw-r--r--web/bountysource.nim.cfg1
-rw-r--r--web/inactive_sponsors.csv33
-rw-r--r--web/news/e031_version_0_16_2.rst6
-rw-r--r--web/sponsors.csv72
52 files changed, 1052 insertions, 285 deletions
diff --git a/appveyor.yml b/appveyor.yml
index 87640b192..ea98b8507 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -7,10 +7,7 @@ cache:
 # - i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
 
 matrix:
-  fast_finish: true     # set this flag to immediately finish build once one of the jobs fails.
-  allow_failures:
-    - platform: x64
-#   - platform: x86
+  fast_finish: true
 
 environment:
   matrix:
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 8fbec64cf..4ea68dc99 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1541,8 +1541,7 @@ proc skipGenericOwner*(s: PSym): PSym =
   ## Generic instantiations are owned by their originating generic
   ## symbol. This proc skips such owners and goes straight to the owner
   ## of the generic itself (the module or the enclosing proc).
-  result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags ==
-                                                  {sfFromGeneric}:
+  result = if s.kind in skProcKinds and sfFromGeneric in s.flags:
              s.owner.owner
            else:
              s.owner
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index affbdffd9..226d5ee42 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -388,6 +388,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
              [istr, makeYamlString($n.kind)]
     addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
     if maxRecDepth != 0:
+      addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)])
       case n.kind
       of nkCharLit..nkUInt64Lit:
         addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 95a7beada..6f7e83c18 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -220,7 +220,7 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
                      optAsgnLoc(src, t, field), newflags)
 
 proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
-                      t: PNode) =
+                      t: PNode, typ: PType) =
   if t == nil: return
   let newflags =
     if src.s == OnStatic:
@@ -232,10 +232,11 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
   case t.kind
   of nkSym:
     let field = t.sym
+    if field.loc.r == nil: fillObjectFields(p.module, typ)
     genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r),
                      optAsgnLoc(src, field.typ, field.loc.r), newflags)
   of nkRecList:
-    for child in items(t): genOptAsgnObject(p, dest, src, newflags, child)
+    for child in items(t): genOptAsgnObject(p, dest, src, newflags, child, typ)
   else: discard
 
 proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
@@ -315,9 +316,9 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
       genGenericAsgn(p, dest, src, flags)
     elif needsComplexAssignment(ty):
       if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4:
-        discard getTypeDesc(p.module, dest.t)
+        discard getTypeDesc(p.module, ty)
         internalAssert ty.n != nil
-        genOptAsgnObject(p, dest, src, flags, ty.n)
+        genOptAsgnObject(p, dest, src, flags, ty.n, ty)
       else:
         genGenericAsgn(p, dest, src, flags)
     else:
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 45d675f64..02119d63e 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -1103,8 +1103,8 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
   genAssignment(p, a, tmp, {})
 
 proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
-  genLineDir(p, e)
   if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags:
+    genLineDir(p, e)
     genGotoVar(p, e.sons[1])
   elif not fieldDiscriminantCheckNeeded(p, e):
     var a: TLoc
@@ -1114,8 +1114,11 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
       initLocExpr(p, e.sons[0], a)
     if fastAsgn: incl(a.flags, lfNoDeepCopy)
     assert(a.t != nil)
-    loadInto(p, e.sons[0], e.sons[1], a)
+    let ri = e.sons[1]
+    genLineDir(p, ri)
+    loadInto(p, e.sons[0], ri, a)
   else:
+    genLineDir(p, e)
     asgnFieldDiscriminant(p, e)
 
 proc genStmts(p: BProc, t: PNode) =
diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim
index 3efddbf30..505b69eab 100644
--- a/compiler/ccgthreadvars.nim
+++ b/compiler/ccgthreadvars.nim
@@ -57,8 +57,8 @@ proc generateThreadLocalStorage(m: BModule) =
 
 proc generateThreadVarsSize(m: BModule) =
   if nimtv != nil:
-    let externc = if gCmd != cmdCompileToCpp and
-                       sfCompileToCpp in m.module.flags: "extern \"C\""
+    let externc = if gCmd == cmdCompileToCpp or
+                       sfCompileToCpp in m.module.flags: "extern \"C\" "
                   else: ""
     addf(m.s[cfsProcs],
       "$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n",
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 62ed9ad6e..63a7cda0e 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -715,10 +715,13 @@ proc genProcAux(m: BModule, prc: PSym) =
     add(generatedProc, ~"}$N")
   add(m.s[cfsProcs], generatedProc)
 
-proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} =
-  result = sfCompileToCpp in m.module.flags and
+proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
+  result = (sfCompileToCpp in m.module.flags and
            sfCompileToCpp notin sym.getModule().flags and
-           gCmd != cmdCompileToCpp
+           gCmd != cmdCompileToCpp) or (
+           sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and
+           sym.magic == mNone and
+           gCmd == cmdCompileToCpp)
 
 proc genProcPrototype(m: BModule, sym: PSym) =
   useHeader(m, sym)
@@ -732,7 +735,7 @@ proc genProcPrototype(m: BModule, sym: PSym) =
     var header = genProcHeader(m, sym)
     if sfNoReturn in sym.flags and hasDeclspec in extccomp.CC[cCompiler].props:
       header = "__declspec(noreturn) " & header
-    if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym):
+    if sym.typ.callConv != ccInline and requiresExternC(m, sym):
       header = "extern \"C\" " & header
     if sfPure in sym.flags and hasAttribute in CC[cCompiler].props:
       header.add(" __attribute__((naked))")
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 0f283b208..1b068385a 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -566,16 +566,18 @@ proc needsExeExt(): bool {.inline.} =
   result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
            (platform.hostOS == osWindows)
 
-proc getCompilerExe(compiler: TSystemCC): string =
-  result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler
-           else: CC[compiler].compilerExe
+proc getCompilerExe(compiler: TSystemCC; cfile: string): string =
+  result = if gCmd == cmdCompileToCpp and not cfile.endsWith(".c"):
+             CC[compiler].cppCompiler
+           else:
+             CC[compiler].compilerExe
   if result.len == 0:
     rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name)
 
 proc getLinkerExe(compiler: TSystemCC): string =
   result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
            elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
-           else: compiler.getCompilerExe
+           else: compiler.getCompilerExe("")
 
 proc getCompileCFileCmd*(cfile: Cfile): string =
   var c = cCompiler
@@ -596,7 +598,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string =
 
   var options = cFileSpecificOptions(cfile.cname)
   var exe = getConfigVar(c, ".exe")
-  if exe.len == 0: exe = c.getCompilerExe
+  if exe.len == 0: exe = c.getCompilerExe(cfile.cname)
 
   if needsExeExt(): exe = addFileExt(exe, "exe")
   if optGenDynLib in gGlobalOptions and
@@ -614,7 +616,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string =
     compilePattern = joinPath(ccompilerpath, exe)
   else:
     includeCmd = ""
-    compilePattern = c.getCompilerExe
+    compilePattern = c.getCompilerExe(cfile.cname)
 
   var cf = if noAbsolutePaths(): extractFilename(cfile.cname)
            else: cfile.cname
diff --git a/compiler/sem.nim b/compiler/sem.nim
index dbf237635..fc7736b07 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -178,6 +178,11 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
     if result.kind != kind:
       localError(n.info, "cannot use symbol of kind '" &
                  $result.kind & "' as a '" & $kind & "'")
+    if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
+      # declarative context, so produce a fresh gensym:
+      result = copySym(result)
+      result.ast = n.sym.ast
+      put(c.p, n.sym, result)
     # when there is a nested proc inside a template, semtmpl
     # will assign a wrong owner during the first pass over the
     # template; we must fix it here: see #909
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 20fd1d9be..77a530a15 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -39,6 +39,7 @@ type
     next*: PProcCon           # used for stacking procedure contexts
     wasForwarded*: bool       # whether the current proc has a separate header
     bracketExpr*: PNode       # current bracket expression (for ^ support)
+    mapping*: TIdTable
 
   TInstantiationPair* = object
     genericSym*: PSym
@@ -147,6 +148,35 @@ proc lastOptionEntry*(c: PContext): POptionEntry =
 
 proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
 
+proc put*(p: PProcCon; key, val: PSym) =
+  if p.mapping.data == nil: initIdTable(p.mapping)
+  #echo "put into table ", key.info
+  p.mapping.idTablePut(key, val)
+
+proc get*(p: PProcCon; key: PSym): PSym =
+  if p.mapping.data == nil: return nil
+  result = PSym(p.mapping.idTableGet(key))
+
+proc getGenSym*(c: PContext; s: PSym): PSym =
+  if sfGenSym notin s.flags: return s
+  var it = c.p
+  while it != nil:
+    result = get(it, s)
+    if result != nil:
+      #echo "got from table ", result.name.s, " ", result.info
+      return result
+    it = it.next
+  result = s
+
+proc considerGenSyms*(c: PContext; n: PNode) =
+  if n.kind == nkSym:
+    let s = getGenSym(c, n.sym)
+    if n.sym != s:
+      n.sym = s
+  else:
+    for i in 0..<n.safeLen:
+      considerGenSyms(c, n.sons[i])
+
 proc newOptionEntry*(): POptionEntry =
   new(result)
   result.options = gOptions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 57674735a..542d7b4e3 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -922,7 +922,8 @@ proc readTypeParameter(c: PContext, typ: PType,
         return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
   #echo "came here: returned nil"
 
-proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
+proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
+  let s = getGenSym(c, sym)
   case s.kind
   of skConst:
     markUsed(n.info, s)
@@ -1093,11 +1094,11 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
       return readTypeParameter(c, ty, i, n.info)
     of tyObject, tyTuple:
       if ty.n != nil and ty.n.kind == nkRecList:
-        for field in ty.n:
-          if field.sym.name == i:
-            n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])
-            n.typ.n = copyTree(n)
-            return n
+        let field = lookupInRecord(ty.n, i)
+        if field != nil:
+          n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ])
+          n.typ.n = copyTree(n)
+          return n
     else:
       # echo "TYPE FIELD ACCESS"
       # debug ty
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 05e398c9a..749deded1 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -628,7 +628,10 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
     of {skProc, skMethod}:
       result = n
     of skType:
-      result = newSymNodeTypeDesc(s, n.info)
+      # XXX gensym'ed symbols can come here and cannot be resolved. This is
+      # dirty, but correct.
+      if s.typ != nil:
+        result = newSymNodeTypeDesc(s, n.info)
     of skGenericParam:
       if s.typ.kind == tyStatic:
         if s.typ.n != nil:
@@ -656,7 +659,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
           localError(a.info, errCannotEvalXBecauseIncompletelyDefined,
                      "sizeof")
           result = nil
-        elif skipTypes(a.typ, typedescInst).kind in
+        elif skipTypes(a.typ, typedescInst+{tyRange}).kind in
              IntegralTypes+NilableTypes+{tySet}:
           #{tyArray,tyObject,tyTuple}:
           result = newIntNodeT(getSize(a.typ), n)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 9c57be023..acaade494 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -106,15 +106,18 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) =
   #if n.kind == nkSym and sfGenSym in n.sym.flags:
   #  if n.sym.owner != orig:
   #    echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner
-  if n.kind == nkSym and {sfGenSym, sfFromGeneric} * n.sym.flags == {sfGenSym}: # and
+  if n.kind == nkSym and sfGenSym in n.sym.flags: # and
     #  (n.sym.owner == orig or n.sym.owner.kind in {skPackage}):
     let s = n.sym
     var x = PSym(idTableGet(symMap, s))
-    if x == nil:
+    if x != nil:
+      n.sym = x
+    elif s.owner.kind == skPackage:
+      #echo "copied this ", s.name.s
       x = copySym(s, false)
       x.owner = owner
       idTablePut(symMap, s, x)
-    n.sym = x
+      n.sym = x
   else:
     for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, orig, symMap)
 
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 5a15f9f5a..6a3793d73 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1360,6 +1360,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
 proc determineType(c: PContext, s: PSym) =
   if s.typ != nil: return
   #if s.magic != mNone: return
+  #if s.ast.isNil: return
   discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
 
 proc semIterator(c: PContext, n: PNode): PNode =
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index a69fe477b..8819f17cc 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -172,7 +172,7 @@ proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
   result = newSym(kind, considerQuotedIdent(n), c.owner, n.info)
   incl(result.flags, sfGenSym)
   incl(result.flags, sfShadowed)
-  if c.scopeN == 0: incl(result.flags, sfFromGeneric)
+  #if c.scopeN == 0: incl(result.flags, sfFromGeneric)
 
 proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
   # locals default to 'gensym':
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 17c065b49..440edd226 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -297,7 +297,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
 
 proc semTypeIdent(c: PContext, n: PNode): PSym =
   if n.kind == nkSym:
-    result = n.sym
+    result = getGenSym(c, n.sym)
   else:
     when defined(nimfix):
       result = pickSym(c, n, skType)
@@ -1319,8 +1319,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
           prev.id = s.typ.id
         result = prev
   of nkSym:
-    if n.sym.kind == skType and n.sym.typ != nil:
-      var t = n.sym.typ
+    let s = getGenSym(c, n.sym)
+    if s.kind == skType and s.typ != nil:
+      var t = s.typ
       let alias = maybeAliasType(c, t, prev)
       if alias != nil:
         result = alias
@@ -1332,7 +1333,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       markUsed(n.info, n.sym)
       styleCheckUse(n.info, n.sym)
     else:
-      if n.sym.kind != skError: localError(n.info, errTypeExpected)
+      if s.kind != skError: localError(n.info, errTypeExpected)
       result = newOrPrevType(tyError, prev, c)
   of nkObjectTy: result = semObjectNode(c, n, prev)
   of nkTupleTy: result = semTuple(c, n, prev)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 6d5e6f742..117b66cd8 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1583,12 +1583,14 @@ proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
     result = c.semOperand(c, a, flags)
   else:
     result = a
+    considerGenSyms(c, result)
 
 proc prepareOperand(c: PContext; a: PNode): PNode =
   if a.typ.isNil:
     result = c.semOperand(c, a, {efDetermineType})
   else:
     result = a
+    considerGenSyms(c, result)
 
 proc prepareNamedParam(a: PNode) =
   if a.sons[0].kind != nkIdent:
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 13c6dd8fe..2103d48bf 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -869,7 +869,12 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     else:
       result = transformSons(c, n)
   of nkIdentDefs, nkConstDef:
-    result = transformSons(c, n)
+    when true:
+      result = transformSons(c, n)
+    else:
+      result = n.PTransNode
+      let L = n.len-1
+      result[L] = transform(c, n.sons[L])
     # XXX comment handling really sucks:
     if importantComments():
       PNode(result).comment = n.comment
diff --git a/compiler/trees.nim b/compiler/trees.nim
index 7208f7d7b..79a460aa0 100644
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -38,7 +38,7 @@ proc exprStructuralEquivalent*(a, b: PNode; strictSymEquality=false): bool =
         # don't go nuts here: same symbol as string is enough:
         result = a.sym.name.id == b.sym.name.id
     of nkIdent: result = a.ident.id == b.ident.id
-    of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
+    of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
     of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
     of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
     of nkEmpty, nkNilLit, nkType: result = true
diff --git a/doc/backends.txt b/doc/backends.txt
index 5846cce9b..6446103ed 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -461,3 +461,11 @@ can then attach a GC to this thread via
 It is **not** safe to disable the garbage collector and enable it after the
 call from your background thread even if the code you are calling is short
 lived.
+
+Before the thread exits, you should tear down the thread's GC to prevent memory
+leaks by calling
+
+.. code-block:: nim
+
+  system.tearDownForeignThreadGc()
+
diff --git a/doc/tut1.rst b/doc/tut1.rst
index 47cafc7fa..e79214dee 100644
--- a/doc/tut1.rst
+++ b/doc/tut1.rst
@@ -361,7 +361,7 @@ iterator:
 .. code-block:: nim
   echo "Counting to ten: "
   for i in countup(1, 10):
-    echo $i
+    echo i
   # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
 
 The built-in `$ <system.html#$>`_ operator turns an integer (``int``) and many
@@ -374,7 +374,7 @@ Each value is ``echo``-ed. This code does the same:
   echo "Counting to 10: "
   var i = 1
   while i <= 10:
-    echo $i
+    echo i
     inc(i) # increment i by 1
   # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
 
@@ -383,7 +383,7 @@ Counting down can be achieved as easily (but is less often needed):
 .. code-block:: nim
   echo "Counting down from 10 to 1: "
   for i in countdown(10, 1):
-    echo $i
+    echo i
   # --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
 
 Since counting up occurs so often in programs, Nim also has a `..
@@ -827,7 +827,7 @@ Let's return to the boring counting example:
 .. code-block:: nim
   echo "Counting to ten: "
   for i in countup(1, 10):
-    echo $i
+    echo i
 
 Can a `countup <system.html#countup>`_ proc be written that supports this
 loop? Lets try:
@@ -1035,15 +1035,15 @@ there is a difference between the ``$`` and ``repr`` outputs:
     myString = "nim"
     myInteger = 42
     myFloat = 3.14
-  echo $myBool, ":", repr(myBool)
+  echo myBool, ":", repr(myBool)
   # --> true:true
-  echo $myCharacter, ":", repr(myCharacter)
+  echo myCharacter, ":", repr(myCharacter)
   # --> n:'n'
-  echo $myString, ":", repr(myString)
+  echo myString, ":", repr(myString)
   # --> nim:0x10fa8c050"nim"
-  echo $myInteger, ":", repr(myInteger)
+  echo myInteger, ":", repr(myInteger)
   # --> 42:42
-  echo $myFloat, ":", repr(myFloat)
+  echo myFloat, ":", repr(myFloat)
   # --> 3.1400000000000001e+00:3.1400000000000001e+00
 
 
@@ -1075,7 +1075,7 @@ at runtime by 0, the second by 1 and so on. Example:
       north, east, south, west
 
   var x = south      # `x` is of type `Direction`; its value is `south`
-  echo $x           # writes "south" to `stdout`
+  echo x           # writes "south" to `stdout`
 
 All comparison operators can be used with enumeration types.
 
@@ -1289,7 +1289,7 @@ value. Here the ``for`` statement is looping over the results from the
 
 .. code-block:: nim
   for i in @[3, 4, 5]:
-    echo $i
+    echo i
   # --> 3
   # --> 4
   # --> 5
diff --git a/koch.nim b/koch.nim
index 825b360a0..109dcc3f1 100644
--- a/koch.nim
+++ b/koch.nim
@@ -223,8 +223,9 @@ proc bundleWinTools() =
   copyExe("tools/finish".exe, "finish".exe)
   removeFile("tools/finish".exe)
   nimexec("c -o:bin/vccexe.exe tools/vccenv/vccexe")
-  nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " &
-          r"--path:..\ui tools\downloader.nim")
+  when false:
+    nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " &
+            r"--path:..\ui tools\downloader.nim")
 
 proc zip(args: string) =
   bundleNimbleSrc()
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
index 60bd1f081..fc587b5df 100644
--- a/lib/impure/db_postgres.nim
+++ b/lib/impure/db_postgres.nim
@@ -69,16 +69,14 @@ import db_common
 export db_common
 
 type
-  DbConn* = PPGconn   ## encapsulates a database connection
-  Row* = seq[string]  ## a row of a dataset. NULL database values will be
-                      ## converted to nil.
-  InstantRow* = tuple[res: PPGresult, line: int32]  ## a handle that can be
-                                                    ## used to get a row's
-                                                    ## column text on demand
+  DbConn* = PPGconn    ## encapsulates a database connection
+  Row* = seq[string]   ## a row of a dataset. NULL database values will be
+                       ## converted to nil.
+  InstantRow* = object ## a handle that can be
+    res: PPGresult     ## used to get a row's
+    line: int          ## column text on demand             
   SqlPrepared* = distinct string ## a identifier for the prepared queries
-
-{.deprecated: [TRow: Row, TDbConn: DbConn,
-              TSqlPrepared: SqlPrepared].}
+{.deprecated: [TRow: Row, TDbConn: DbConn, TSqlPrepared: SqlPrepared].}
 
 proc dbError*(db: DbConn) {.noreturn.} =
   ## raises a DbError exception.
@@ -213,7 +211,7 @@ iterator instantRows*(db: DbConn, query: SqlQuery,
   ## on demand using []. Returned handle is valid only within iterator body.
   var res = setupQuery(db, query, args)
   for i in 0..pqNtuples(res)-1:
-    yield (res: res, line: i)
+    yield InstantRow(res: res, line: i)
   pqClear(res)
 
 iterator instantRows*(db: DbConn, stmtName: SqlPrepared,
@@ -223,16 +221,170 @@ iterator instantRows*(db: DbConn, stmtName: SqlPrepared,
   ## on demand using []. Returned handle is valid only within iterator body.
   var res = setupQuery(db, stmtName, args)
   for i in 0..pqNtuples(res)-1:
-    yield (res: res, line: i)
+    yield InstantRow(res: res, line: i)
+  pqClear(res)
+
+proc getColumnType(res: PPGresult, col: int) : DbType =
+  ## returns DbType for given column in the row
+  ## defined in pg_type.h file in the postgres source code
+  ## Wire representation for types: http://www.npgsql.org/dev/types.html
+  var oid = pqftype(res, int32(col))
+  ## The integer returned is the internal OID number of the type
+  case oid
+  of 16: return DbType(kind: DbTypeKind.dbBool, name: "bool")
+  of 17: return DbType(kind: DbTypeKind.dbBlob, name: "bytea")
+
+  of 21:   return DbType(kind: DbTypeKind.dbInt, name: "int2", size: 2)
+  of 23:   return DbType(kind: DbTypeKind.dbInt, name: "int4", size: 4)
+  of 20:   return DbType(kind: DbTypeKind.dbInt, name: "int8", size: 8)
+  of 1560: return DbType(kind: DbTypeKind.dbBit, name: "bit")  
+  of 1562: return DbType(kind: DbTypeKind.dbInt, name: "varbit")
+
+  of 18:   return DbType(kind: DbTypeKind.dbFixedChar, name: "char")
+  of 19:   return DbType(kind: DbTypeKind.dbFixedChar, name: "name")
+  of 1042: return DbType(kind: DbTypeKind.dbFixedChar, name: "bpchar")
+
+  of 25:   return DbType(kind: DbTypeKind.dbVarchar, name: "text")
+  of 1043: return DbType(kind: DbTypeKind.dbVarChar, name: "varchar")
+  of 2275: return DbType(kind: DbTypeKind.dbVarchar, name: "cstring")
+
+  of 700: return DbType(kind: DbTypeKind.dbFloat, name: "float4")
+  of 701: return DbType(kind: DbTypeKind.dbFloat, name: "float8")
+
+  of 790:  return DbType(kind: DbTypeKind.dbDecimal, name: "money")  
+  of 1700: return DbType(kind: DbTypeKind.dbDecimal, name: "numeric")
+
+  of 704:  return DbType(kind: DbTypeKind.dbTimeInterval, name: "tinterval")
+  of 702:  return DbType(kind: DbTypeKind.dbTimestamp, name: "abstime")
+  of 703:  return DbType(kind: DbTypeKind.dbTimeInterval, name: "reltime")
+  of 1082: return DbType(kind: DbTypeKind.dbDate, name: "date")
+  of 1083: return DbType(kind: DbTypeKind.dbTime, name: "time")
+  of 1114: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamp")
+  of 1184: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamptz")
+  of 1186: return DbType(kind: DbTypeKind.dbTimeInterval, name: "interval")
+  of 1266: return DbType(kind: DbTypeKind.dbTime, name: "timetz")
+
+  of 114:  return DbType(kind: DbTypeKind.dbJson, name: "json")
+  of 142:  return DbType(kind: DbTypeKind.dbXml, name: "xml")
+  of 3802: return DbType(kind: DbTypeKind.dbJson, name: "jsonb")
+
+  of 600: return DbType(kind: DbTypeKind.dbPoint, name: "point")
+  of 601: return DbType(kind: DbTypeKind.dbLseg, name: "lseg")
+  of 602: return DbType(kind: DbTypeKind.dbPath, name: "path")
+  of 603: return DbType(kind: DbTypeKind.dbBox, name: "box")
+  of 604: return DbType(kind: DbTypeKind.dbPolygon, name: "polygon")
+  of 628: return DbType(kind: DbTypeKind.dbLine, name: "line")
+  of 718: return DbType(kind: DbTypeKind.dbCircle, name: "circle")  
+
+  of 650: return DbType(kind: DbTypeKind.dbInet, name: "cidr")
+  of 829: return DbType(kind: DbTypeKind.dbMacAddress, name: "macaddr")
+  of 869: return DbType(kind: DbTypeKind.dbInet, name: "inet")
+  
+  of 2950: return DbType(kind: DbTypeKind.dbVarchar, name: "uuid")
+  of 3614: return DbType(kind: DbTypeKind.dbVarchar, name: "tsvector")
+  of 3615: return DbType(kind: DbTypeKind.dbVarchar, name: "tsquery")
+  of 2970: return DbType(kind: DbTypeKind.dbVarchar, name: "txid_snapshot")
+
+  of 27:   return DbType(kind: DbTypeKind.dbComposite, name: "tid")
+  of 1790: return DbType(kind: DbTypeKind.dbComposite, name: "refcursor")
+  of 2249: return DbType(kind: DbTypeKind.dbComposite, name: "record")
+  of 3904: return DbType(kind: DbTypeKind.dbComposite, name: "int4range")
+  of 3906: return DbType(kind: DbTypeKind.dbComposite, name: "numrange")
+  of 3908: return DbType(kind: DbTypeKind.dbComposite, name: "tsrange")
+  of 3910: return DbType(kind: DbTypeKind.dbComposite, name: "tstzrange")
+  of 3912: return DbType(kind: DbTypeKind.dbComposite, name: "daterange")
+  of 3926: return DbType(kind: DbTypeKind.dbComposite, name: "int8range")
+
+  of 22:   return DbType(kind: DbTypeKind.dbArray, name: "int2vector")
+  of 30:   return DbType(kind: DbTypeKind.dbArray, name: "oidvector")
+  of 143:  return DbType(kind: DbTypeKind.dbArray, name: "xml[]")
+  of 199:  return DbType(kind: DbTypeKind.dbArray, name: "json[]")
+  of 629:  return DbType(kind: DbTypeKind.dbArray, name: "line[]")
+  of 651:  return DbType(kind: DbTypeKind.dbArray, name: "cidr[]")
+  of 719:  return DbType(kind: DbTypeKind.dbArray, name: "circle[]")
+  of 791:  return DbType(kind: DbTypeKind.dbArray, name: "money[]")
+  of 1000: return DbType(kind: DbTypeKind.dbArray, name: "bool[]")
+  of 1001: return DbType(kind: DbTypeKind.dbArray, name: "bytea[]")
+  of 1002: return DbType(kind: DbTypeKind.dbArray, name: "char[]")
+  of 1003: return DbType(kind: DbTypeKind.dbArray, name: "name[]")
+  of 1005: return DbType(kind: DbTypeKind.dbArray, name: "int2[]")
+  of 1006: return DbType(kind: DbTypeKind.dbArray, name: "int2vector[]")
+  of 1007: return DbType(kind: DbTypeKind.dbArray, name: "int4[]")
+  of 1008: return DbType(kind: DbTypeKind.dbArray, name: "regproc[]")
+  of 1009: return DbType(kind: DbTypeKind.dbArray, name: "text[]")
+  of 1028: return DbType(kind: DbTypeKind.dbArray, name: "oid[]")
+  of 1010: return DbType(kind: DbTypeKind.dbArray, name: "tid[]")
+  of 1011: return DbType(kind: DbTypeKind.dbArray, name: "xid[]")
+  of 1012: return DbType(kind: DbTypeKind.dbArray, name: "cid[]")
+  of 1013: return DbType(kind: DbTypeKind.dbArray, name: "oidvector[]")
+  of 1014: return DbType(kind: DbTypeKind.dbArray, name: "bpchar[]")
+  of 1015: return DbType(kind: DbTypeKind.dbArray, name: "varchar[]")
+  of 1016: return DbType(kind: DbTypeKind.dbArray, name: "int8[]")
+  of 1017: return DbType(kind: DbTypeKind.dbArray, name: "point[]")
+  of 1018: return DbType(kind: DbTypeKind.dbArray, name: "lseg[]")
+  of 1019: return DbType(kind: DbTypeKind.dbArray, name: "path[]")
+  of 1020: return DbType(kind: DbTypeKind.dbArray, name: "box[]")
+  of 1021: return DbType(kind: DbTypeKind.dbArray, name: "float4[]")
+  of 1022: return DbType(kind: DbTypeKind.dbArray, name: "float8[]")
+  of 1023: return DbType(kind: DbTypeKind.dbArray, name: "abstime[]")
+  of 1024: return DbType(kind: DbTypeKind.dbArray, name: "reltime[]")
+  of 1025: return DbType(kind: DbTypeKind.dbArray, name: "tinterval[]")
+  of 1027: return DbType(kind: DbTypeKind.dbArray, name: "polygon[]")
+  of 1040: return DbType(kind: DbTypeKind.dbArray, name: "macaddr[]")
+  of 1041: return DbType(kind: DbTypeKind.dbArray, name: "inet[]")
+  of 1263: return DbType(kind: DbTypeKind.dbArray, name: "cstring[]")
+  of 1115: return DbType(kind: DbTypeKind.dbArray, name: "timestamp[]")
+  of 1182: return DbType(kind: DbTypeKind.dbArray, name: "date[]")
+  of 1183: return DbType(kind: DbTypeKind.dbArray, name: "time[]")
+  of 1185: return DbType(kind: DbTypeKind.dbArray, name: "timestamptz[]")
+  of 1187: return DbType(kind: DbTypeKind.dbArray, name: "interval[]")
+  of 1231: return DbType(kind: DbTypeKind.dbArray, name: "numeric[]")
+  of 1270: return DbType(kind: DbTypeKind.dbArray, name: "timetz[]")
+  of 1561: return DbType(kind: DbTypeKind.dbArray, name: "bit[]")
+  of 1563: return DbType(kind: DbTypeKind.dbArray, name: "varbit[]")
+  of 2201: return DbType(kind: DbTypeKind.dbArray, name: "refcursor[]")
+  of 2951: return DbType(kind: DbTypeKind.dbArray, name: "uuid[]")
+  of 3643: return DbType(kind: DbTypeKind.dbArray, name: "tsvector[]")
+  of 3645: return DbType(kind: DbTypeKind.dbArray, name: "tsquery[]")
+  of 3807: return DbType(kind: DbTypeKind.dbArray, name: "jsonb[]")
+  of 2949: return DbType(kind: DbTypeKind.dbArray, name: "txid_snapshot[]")
+  of 3905: return DbType(kind: DbTypeKind.dbArray, name: "int4range[]")
+  of 3907: return DbType(kind: DbTypeKind.dbArray, name: "numrange[]")
+  of 3909: return DbType(kind: DbTypeKind.dbArray, name: "tsrange[]")
+  of 3911: return DbType(kind: DbTypeKind.dbArray, name: "tstzrange[]")
+  of 3913: return DbType(kind: DbTypeKind.dbArray, name: "daterange[]")
+  of 3927: return DbType(kind: DbTypeKind.dbArray, name: "int8range[]")
+  of 2287: return DbType(kind: DbTypeKind.dbArray, name: "record[]")
+
+  of 705:  return DbType(kind: DbTypeKind.dbUnknown, name: "unknown")
+  else: return DbType(kind: DbTypeKind.dbUnknown, name: $oid) ## Query the system table pg_type to determine exactly which type is referenced.
+
+proc setColumnInfo(columns: var DbColumns; res: PPGresult; L: int32) =
+  setLen(columns, L)
+  for i in 0..<L:
+    columns[i].name = $pqfname(res, i)
+    columns[i].typ = getColumnType(res, i)
+    columns[i].tableName = $(pqftable(res, i)) ## Returns the OID of the table from which the given column was fetched.
+                                               ## Query the system table pg_class to determine exactly which table is referenced.  
+    #columns[i].primaryKey = libpq does not have a function for that
+    #columns[i].foreignKey = libpq does not have a function for that
+
+iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery;
+                      args: varargs[string, `$`]): InstantRow
+                      {.tags: [ReadDbEffect].} =
+  var res = setupQuery(db, query, args)
+  setColumnInfo(columns, res, pqnfields(res))
+  for i in 0..<pqntuples(res):
+    yield InstantRow(res: res, line: i)
   pqClear(res)
 
-proc `[]`*(row: InstantRow, col: int32): string {.inline.} =
+proc `[]`*(row: InstantRow; col: int): string {.inline.} =
   ## returns text for given column of the row
-  $pqgetvalue(row.res, row.line, col)
+  $pqgetvalue(row.res, int32(row.line), int32(col))
 
-proc len*(row: InstantRow): int32 {.inline.} =
+proc len*(row: InstantRow): int {.inline.} =
   ## returns number of columns in the row
-  pqNfields(row.res)
+  int(pqNfields(row.res))
 
 proc getRow*(db: DbConn, query: SqlQuery,
              args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index 9d5d2bdd0..e00f91de1 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -290,7 +290,7 @@ proc find*(buf: cstring, pattern: Regex, matches: var openArray[string],
   for i in 1..int(res)-1:
     var a = rawMatches[i * 2]
     var b = rawMatches[i * 2 + 1]
-    if a >= 0'i32: matches[i-1] = bufSubstr(buf, int(a), int(b)-1)
+    if a >= 0'i32: matches[i-1] = bufSubstr(buf, int(a), int(b))
     else: matches[i-1] = nil
   return rawMatches[0]
 
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 739cdc16b..bc39f153b 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -46,7 +46,7 @@ proc reverse*[T](a: var openArray[T], first, last: Natural) =
 
 proc reverse*[T](a: var openArray[T]) =
   ## reverses the array `a`.
-  reverse(a, 0, a.high)
+  reverse(a, 0, max(0, a.high))
 
 proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] =
   ## returns the reverse of the array `a[first..last]`.
diff --git a/lib/pure/collections/heapqueue.nim b/lib/pure/collections/heapqueue.nim
index abe20e556..f86ba1d3f 100644
--- a/lib/pure/collections/heapqueue.nim
+++ b/lib/pure/collections/heapqueue.nim
@@ -77,8 +77,10 @@ proc pop*[T](heap: var HeapQueue[T]): T =
 proc del*[T](heap: var HeapQueue[T], index: int) =
   ## Removes element at `index`, maintaining the heap invariant.
   swap(seq[T](heap)[^1], seq[T](heap)[index])
-  seq[T](heap).setLen(heap.len - 1)
-  heap.siftup(index)
+  let newLen = heap.len - 1
+  seq[T](heap).setLen(newLen)
+  if index < newLen:
+    heap.siftup(index)
 
 proc replace*[T](heap: var HeapQueue[T], item: T): T =
   ## Pop and return the current smallest value, and add the new item.
@@ -101,16 +103,19 @@ proc pushpop*[T](heap: var HeapQueue[T], item: T): T =
   return item
 
 when isMainModule:
+  proc toSortedSeq[T](h: HeapQueue[T]): seq[T] =
+    var tmp = h
+    result = @[]
+    while tmp.len > 0:
+      result.add(pop(tmp))
+
   block: # Simple sanity test
     var heap = newHeapQueue[int]()
     let data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
     for item in data:
       push(heap, item)
     doAssert(heap[0] == 0)
-    var sort = newSeq[int]()
-    while heap.len > 0:
-      sort.add(pop(heap))
-    doAssert(sort == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+    doAssert(heap.toSortedSeq == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
 
   block: # Test del
     var heap = newHeapQueue[int]()
@@ -121,11 +126,27 @@ when isMainModule:
     doAssert(heap[0] == 1)
 
     heap.del(seq[int](heap).find(7))
+    doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 5, 6, 8, 9])
+
     heap.del(seq[int](heap).find(5))
+    doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 6, 8, 9])
+
     heap.del(seq[int](heap).find(6))
+    doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 8, 9])
+
     heap.del(seq[int](heap).find(2))
+    doAssert(heap.toSortedSeq == @[1, 3, 4, 8, 9])
+
+  block: # Test del last
+    var heap = newHeapQueue[int]()
+    let data = [1, 2, 3]
+    for item in data: push(heap, item)
+
+    heap.del(2)
+    doAssert(heap.toSortedSeq == @[1, 2])
 
-    var sort = newSeq[int]()
-    while heap.len > 0:
-      sort.add(pop(heap))
-    doAssert(sort == @[1, 3, 4, 8, 9])
+    heap.del(1)
+    doAssert(heap.toSortedSeq == @[1])
+
+    heap.del(0)
+    doAssert(heap.toSortedSeq == @[])
diff --git a/lib/pure/distros.nim b/lib/pure/distros.nim
index ff30f6134..896497630 100644
--- a/lib/pure/distros.nim
+++ b/lib/pure/distros.nim
@@ -225,7 +225,7 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
     else:
       result = ("<your package manager here> install " & p, true)
   else:
-    result = ("brew install " & p, true)
+    result = ("brew install " & p, false)
 
 proc foreignDep*(foreignPackageName: string) =
   ## Registers 'foreignPackageName' to the internal list of foreign deps.
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 11af81149..17d1c6442 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -127,6 +127,15 @@ proc hash*(x: string): Hash =
     h = h !& ord(x[i])
   result = !$h
 
+proc hash*(x: cstring): Hash =
+  ## efficient hashing of null-terminated strings
+  var h: Hash = 0
+  var i = 0
+  while x[i] != 0.char:
+    h = h !& ord(x[i])
+    inc i
+  result = !$h
+
 proc hash*(sBuf: string, sPos, ePos: int): Hash =
   ## efficient hashing of a string buffer, from starting
   ## position `sPos` to ending position `ePos`
@@ -239,6 +248,7 @@ proc hash*[A](x: set[A]): Hash =
 
 when isMainModule:
   doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) )
+  doAssert( hash("aa bb aaaa1234") == hash(cstring("aa bb aaaa1234")) )
   doAssert( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") )
   doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
   let xx = @['H','e','l','l','o']
diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim
index d7f720f66..aa8f1958d 100644
--- a/lib/pure/httpcore.nim
+++ b/lib/pure/httpcore.nim
@@ -206,6 +206,8 @@ proc parseHeader*(line: string): tuple[key: string, value: seq[string]] =
   inc(i) # skip :
   if i < len(line):
     i += parseList(line, result.value, i)
+  elif result.key.len > 0:
+    result.value = @[""]
   else:
     result.value = @[]
 
@@ -318,4 +320,6 @@ when isMainModule:
   let (key, value) = parseHeader("foobar: ")
   test = newHttpHeaders()
   test[key] = value
-  doAssert test["foobar"] == ""
\ No newline at end of file
+  doAssert test["foobar"] == ""
+
+  doAssert parseHeader("foobar:") == ("foobar", @[""])
\ No newline at end of file
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 4cd3870c7..92e295820 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1002,8 +1002,8 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
 
 iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
   tags: [ReadDirEffect].} =
-  ## walks over the directory `dir` and yields for each file in `dir`. The
-  ## full path for each file is returned.
+  ## Recursively walks over the directory `dir` and yields for each file in `dir`.
+  ## The full path for each file is returned. Directories are not returned.
   ## **Warning**:
   ## Modifying the directory structure while the iterator
   ## is traversing may result in undefined behavior!
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index fb7d72182..8d53a0360 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -250,18 +250,18 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
   elif result != 0:
     number = int(res)
 
-# overflowChecks doesn't work with uint64
-proc rawParseUInt(s: string, b: var uint64, start = 0): int =
+# overflowChecks doesn't work with BiggestUInt
+proc rawParseUInt(s: string, b: var BiggestUInt, start = 0): int =
   var
-    res = 0'u64
-    prev = 0'u64
+    res = 0.BiggestUInt
+    prev = 0.BiggestUInt
     i = start
   if s[i] == '+': inc(i) # Allow
   if s[i] in {'0'..'9'}:
     b = 0
     while s[i] in {'0'..'9'}:
       prev = res
-      res = res * 10 + (ord(s[i]) - ord('0')).uint64
+      res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt
       if prev > res:
         return 0 # overflowChecks emulation
       inc(i)
@@ -269,13 +269,13 @@ proc rawParseUInt(s: string, b: var uint64, start = 0): int =
     b = res
     result = i - start
 
-proc parseBiggestUInt*(s: string, number: var uint64, start = 0): int {.
+proc parseBiggestUInt*(s: string, number: var BiggestUInt, start = 0): int {.
   rtl, extern: "npuParseBiggestUInt", noSideEffect.} =
   ## parses an unsigned integer starting at `start` and stores the value
   ## into `number`.
   ## Result is the number of processed chars or 0 if there is no integer
   ## or overflow detected.
-  var res: uint64
+  var res: BiggestUInt
   # use 'res' for exception safety (don't write to 'number' in case of an
   # overflow exception):
   result = rawParseUInt(s, res, start)
@@ -287,12 +287,12 @@ proc parseUInt*(s: string, number: var uint, start = 0): int {.
   ## into `number`.
   ## Result is the number of processed chars or 0 if there is no integer or
   ## overflow detected.
-  var res: uint64
+  var res: BiggestUInt
   result = parseBiggestUInt(s, res, start)
-  if (sizeof(uint) <= 4) and
-      (res > 0xFFFF_FFFF'u64):
-    raise newException(OverflowError, "overflow")
-  elif result != 0:
+  when sizeof(BiggestUInt) > sizeof(uint) and sizeof(uint) <= 4:
+    if res > 0xFFFF_FFFF'u64:
+      raise newException(OverflowError, "overflow")
+  if result != 0:
     number = uint(res)
 
 proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 235e66f6a..9c205a54f 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -939,7 +939,7 @@ proc parseUInt*(s: string): uint {.noSideEffect, procvar,
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid unsigned integer: " & s)
 
-proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar,
+proc parseBiggestUInt*(s: string): BiggestUInt {.noSideEffect, procvar,
   rtl, extern: "nsuParseBiggestUInt".} =
   ## Parses a decimal unsigned integer value contained in `s`.
   ##
diff --git a/lib/system.nim b/lib/system.nim
index 13ca6eaf7..bab5369f1 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1512,6 +1512,17 @@ type
     ## compiler supports. Currently this is ``float64``, but it is
     ## platform-dependant in general.
 
+when defined(JS):
+  type BiggestUInt* = uint32
+    ## is an alias for the biggest unsigned integer type the Nim compiler
+    ## supports. Currently this is ``uint32`` for JS and ``uint64`` for other
+    ## targets.
+else:
+  type BiggestUInt* = uint64
+    ## is an alias for the biggest unsigned integer type the Nim compiler
+    ## supports. Currently this is ``uint32`` for JS and ``uint64`` for other
+    ## targets.
+
 {.deprecated: [TAddress: ByteAddress].}
 
 when defined(windows):
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index 269514ceb..6ab6bd920 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -128,13 +128,7 @@ iterator items(stack: ptr GcStack): ptr GcStack =
     yield s
     s = s.next
 
-# There will be problems with GC in foreign threads if `threads` option is off or TLS emulation is enabled
-const allowForeignThreadGc = compileOption("threads") and not compileOption("tlsEmulation")
-
-when allowForeignThreadGc:
-  var
-    localGcInitialized {.rtlThreadVar.}: bool
-
+when declared(threadType):
   proc setupForeignThreadGc*() {.gcsafe.} =
     ## Call this if you registered a callback that will be run from a thread not
     ## under your control. This has a cheap thread-local guard, so the GC for
@@ -143,16 +137,33 @@ when allowForeignThreadGc:
     ##
     ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
     ## switches are used
-    if not localGcInitialized:
-      localGcInitialized = true
+    if threadType == ThreadType.None:
       initAllocator()
       var stackTop {.volatile.}: pointer
       setStackBottom(addr(stackTop))
       initGC()
+      threadType = ThreadType.ForeignThread
+
+  proc tearDownForeignThreadGc*() {.gcsafe.} =
+    ## Call this to tear down the GC, previously initialized by ``setupForeignThreadGc``.
+    ## If GC has not been previously initialized, or has already been torn down, the
+    ## call does nothing.
+    ##
+    ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
+    ## switches are used
+    if threadType != ThreadType.ForeignThread:
+      return
+    when declared(deallocOsPages): deallocOsPages()
+    threadType = ThreadType.None
+    when declared(gch): zeroMem(addr gch, sizeof(gch))
+
 else:
   template setupForeignThreadGc*() =
     {.error: "setupForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
 
+  template tearDownForeignThreadGc*() =
+    {.error: "tearDownForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
+
 # ----------------- stack management --------------------------------------
 #  inspired from Smart Eiffel
 
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 9f4944eb0..7444661e3 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -67,7 +67,7 @@ proc checkErr(f: File) =
 {.push stackTrace:off, profiler:off.}
 proc readBuffer(f: File, buffer: pointer, len: Natural): int =
   result = c_fread(buffer, 1, len, f)
-  checkErr(f)
+  if result != len: checkErr(f)
 
 proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int =
   result = readBuffer(f, addr(a[start]), len)
@@ -118,8 +118,9 @@ const
 proc close*(f: File) = discard c_fclose(f)
 proc readChar(f: File): char =
   let x = c_fgetc(f)
-  if x == -1: raiseEOF()
-  checkErr(f)
+  if x < 0:
+    checkErr(f)
+    raiseEOF()
   result = char(x)
 
 proc flushFile*(f: File) = discard c_fflush(f)
@@ -140,7 +141,7 @@ proc readLine(f: File, line: var TaintedString): bool =
     # fgets doesn't append an \L
     c_memset(addr line.string[pos], '\L'.ord, sp)
     var fgetsSuccess = c_fgets(addr line.string[pos], sp, f) != nil
-    checkErr(f)
+    if not fgetsSuccess: checkErr(f)
     let m = c_memchr(addr line.string[pos], '\L'.ord, sp)
     if m != nil:
       # \l found: Could be our own or the one by fgets, in any case, we're done
@@ -170,21 +171,23 @@ proc readLine(f: File): TaintedString =
 
 proc write(f: File, i: int) =
   when sizeof(int) == 8:
-    c_fprintf(f, "%lld", i)
+    if c_fprintf(f, "%lld", i) < 0: checkErr(f)
   else:
-    c_fprintf(f, "%ld", i)
+    if c_fprintf(f, "%ld", i) < 0: checkErr(f)
 
 proc write(f: File, i: BiggestInt) =
   when sizeof(BiggestInt) == 8:
-    c_fprintf(f, "%lld", i)
+    if c_fprintf(f, "%lld", i) < 0: checkErr(f)
   else:
-    c_fprintf(f, "%ld", i)
+    if c_fprintf(f, "%ld", i) < 0: checkErr(f)
 
 proc write(f: File, b: bool) =
   if b: write(f, "true")
   else: write(f, "false")
-proc write(f: File, r: float32) = c_fprintf(f, "%g", r)
-proc write(f: File, r: BiggestFloat) = c_fprintf(f, "%g", r)
+proc write(f: File, r: float32) =
+  if c_fprintf(f, "%g", r) < 0: checkErr(f)
+proc write(f: File, r: BiggestFloat) =
+  if c_fprintf(f, "%g", r) < 0: checkErr(f)
 
 proc write(f: File, c: char) = discard c_putc(ord(c), f)
 proc write(f: File, a: varargs[string, `$`]) =
@@ -212,7 +215,10 @@ proc rawFileSize(file: File): int =
   discard c_fseek(file, clong(oldPos), 0)
 
 proc endOfFile(f: File): bool =
-  result = c_feof(f) != 0
+  var c = c_fgetc(f)
+  discard c_ungetc(c, f)
+  return c < 0'i32
+  #result = c_feof(f) != 0
 
 proc readAllFile(file: File, len: int): string =
   # We acquire the filesize beforehand and hope it doesn't change.
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index e8b34bf2e..6e58638e9 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -285,7 +285,19 @@ when useStackMaskHack:
 when not defined(useNimRtl):
   when not useStackMaskHack:
     #when not defined(createNimRtl): initStackBottom()
-    when declared(initGC): initGC()
+    when declared(initGC):
+      initGC()
+      when not emulatedThreadVars:
+        type ThreadType {.pure.} = enum
+          None = 0,
+          NimThread = 1,
+          ForeignThread = 2
+        var
+          threadType {.rtlThreadVar.}: ThreadType
+
+        threadType = ThreadType.NimThread
+
+
 
   when emulatedThreadVars:
     if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
@@ -442,6 +454,8 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
       # init the GC for refc/markandsweep
       setStackBottom(addr(p))
       initGC()
+      when declared(threadType):
+        threadType = ThreadType.NimThread
     when declared(registerThread):
       thrd.stackBottom = addr(thrd)
       registerThread(thrd)
diff --git a/readme.md b/readme.md
index 6eb85b0a3..865724b71 100644
--- a/readme.md
+++ b/readme.md
@@ -1,146 +1,175 @@
-# <img src="https://raw.githubusercontent.com/nim-lang/assets/master/Art/logo-crown.png" width="36"> Nim [![Build Status](https://travis-ci.org/nim-lang/Nim.svg?branch=devel)](https://travis-ci.org/nim-lang/Nim)
+# ![Logo][image-nim-logo] Nim [![Build Status][badge-nim-travisci]][nim-travisci]
 
-This repo contains the Nim compiler, Nim's stdlib, tools and
-documentation. For more information about Nim, including downloads
-and documentation for the latest release, check out
-[Nim's website](http://nim-lang.org).
+This repository contains the Nim compiler, Nim's stdlib, tools and documentation.
+For more information about Nim, including downloads and documentation for
+the latest release, check out [Nim's website][nim-site].
 
-## Compiling
-Compiling the Nim compiler is quite straightforward. Because
-the Nim compiler itself is written in the Nim programming language
-the C source of an older version of the compiler are needed to bootstrap the
-latest version. The C sources are available in a separate
-repo [here](http://github.com/nim-lang/csources).
+## Community
+[![Join the IRC chat][badge-nim-irc]][nim-irc]
+[![Join the Gitter chat][badge-nim-gitter]][nim-gitter]
+[![Get help][badge-nim-forum-gethelp]][nim-forum]
+[![View Nim posts on Stack Overflow][badge-nim-stackoverflow]][nim-stackoverflow-newest]
+[![Follow @nim_lang on Twitter][badge-nim-twitter]][nim-twitter]
+
+* The [forum][nim-forum] - the best place to ask questions and to discuss Nim.
+* [#nim IRC Channel (Freenode)][nim-irc] - a place to discuss Nim in real-time.
+  Also where most development decisions get made.
+* [Gitter][nim-gitter] - an additional place to discuss Nim in real-time. There
+  is a bridge between Gitter and the IRC channel.
+* [Stack Overflow][nim-stackoverflow] - a popular Q/A site for programming related
+  topics that includes posts about Nim.
 
-The compiler currently supports the following platform and architecture
-combinations:
+## Compiling
+The compiler currently officially supports the following platform and
+architecture combinations:
 
   * Windows (Windows XP or greater) - x86 and x86_64
   * Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l
-  * Mac OS X 10.04 or higher - x86, x86_64 and ppc64
+  * Mac OS X (10.04 or greater) - x86, x86_64 and ppc64
 
-In reality a lot more are supported, however they are not tested regularly.
+More platforms are supported, however they are not tested regularly and they
+may not be as stable as the above-listed platforms.
 
-To build from source you will need:
+Compiling the Nim compiler is quite straightforward if you follow these steps:
 
-  * gcc 3.x or later recommended. Other alternatives which may work
-    are: clang, Visual C++, Intel's C++ compiler
-  * git or wget
+First, the C source of an older version of the Nim compiler is needed to
+bootstrap the latest version because the Nim compiler itself is written in the
+Nim programming language. Those C sources are available within the 
+[``nim-lang/csources``][csources-repo] repository.
 
-**Note:** When installing ``gcc`` on Ubuntu (and likely other distros) ensure
-that the ``build-essentials`` package is installed also.
+Next, to build from source you will need:
 
-If you are on a fairly modern *nix system, the following steps should work:
+  * A C compiler such as ``gcc`` 3.x/later or an alternative such as ``clang``,
+    ``Visual C++`` or ``Intel C++``. It is recommended to use ``gcc`` 3.x or
+    later.
+  * Either ``git`` or ``wget`` to download the needed source repositories.
+  * The ``build-essentials`` package when using ``gcc`` on Ubuntu (and likely
+    other distros as well). 
+
+Then, if you are on a \*nix system or Windows, the following steps should compile
+Nim from source using ``gcc``, ``git`` and the ``koch`` build tool (in the place
+of ``sh build.sh`` you should substitute ``build.bat`` on x86 Windows or
+``build64.bat`` on x86_64 Windows):
 
 ```
 $ git clone https://github.com/nim-lang/Nim.git
 $ cd Nim
-$ git clone --depth 1 https://github.com/nim-lang/csources
-$ cd csources && sh build.sh
-$ cd ..
+$ git clone --depth 1 https://github.com/nim-lang/csources.git
+$ cd csources
+$ sh build.sh
+$ cd ../
 $ bin/nim c koch
 $ ./koch boot -d:release
 ```
 
-You should then add the ``bin`` directory to your PATH, to make it easily
-executable on your system.
+Finally, once you have finished the build steps (on Windows, Mac or Linux) you
+should add the ``bin`` directory to your PATH.
 
-The above steps can be performed on Windows in a similar fashion, the
-``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
-instead of ``build.sh``.
+## Koch
+``koch`` is the build tool used to build various parts of Nim and to generate
+documentation and the website, among other things. The ``koch`` tool can also
+be used to run the Nim test suite. 
 
-The ``koch`` tool is the Nim build tool, more ``koch`` related options are
-documented in [doc/koch.rst](doc/koch.rst).
+Assuming that you added Nim's ``bin`` directory to your PATH, you may execute
+the tests using ``./koch tests``. The tests take a while to run, but you
+can run a subset of tests by specifying a category (for example 
+``./koch tests cat async``).
 
+For more information on the ``koch`` build tool please see the documentation
+within the [doc/koch.rst](doc/koch.rst) file.
 
 ## Nimble
-[Nimble](https://github.com/nim-lang/nimble) is Nim's package manager. For the
-source based installations, where you added Nim's ``bin`` directory to your PATH,
-the easiest way of installing Nimble is via:
-
-```
-$ koch nimble
-```
-
-## Community
-[![Join the Chat at irc.freenode.net#nim](https://img.shields.io/badge/IRC-join_chat_in_%23nim-blue.svg)](https://webchat.freenode.net/?channels=nim)
-[![Join the Gitter channel](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nim-lang/Nim)
-[![Get help](https://img.shields.io/badge/Forum-get%20help-4eb899.svg)](http://forum.nim-lang.org)
-[![Stackoverflow](https://img.shields.io/badge/stackoverflow-use_%23nim_tag-yellow.svg)](http://stackoverflow.com/questions/tagged/nim?sort=newest&pageSize=15)
-[![Follow @nim_lang!](https://img.shields.io/twitter/follow/nim_lang.svg?style=social)](https://twitter.com/nim_lang)
-
-* The [forum](http://forum.nim-lang.org/) - the best place to ask questions and to discuss Nim.
-* [IRC (Freenode#nim)](https://webchat.freenode.net/?channels=nim) - a place to discuss
-  Nim in real-time, this is also where most development decision get made!
-* [Gitter](https://gitter.im/nim-lang/Nim) allows to discuss Nim from your browser, one click to join.
-  There is a bridge between Gitter and IRC channels.
-* [Stackoverflow](http://stackoverflow.com/questions/tagged/nim)
+``nimble`` is Nim's package manager and it can be acquired from the
+[``nim-lang/nimble``][nimble-repo] repository. Assuming that you added Nim's
+``bin`` directory to your PATH, you may install Nimble from source by running
+``koch nimble`` within the root of the cloned repository.
 
 ## Contributing
+[![Contribute to Nim via Gratipay][badge-nim-gratipay]][nim-gratipay]
+[![Setup a bounty via Bountysource][badge-nim-bountysource]][nim-bountysource]
+[![Donate Bitcoins][badge-nim-bitcoin]][nim-bitcoin]
 
-[![Contribute to Nim via Gratipay!](https://img.shields.io/gratipay/team/nim.svg)](https://gratipay.com/nim/)
-[![Bountysource](https://img.shields.io/bountysource/team/nim/activity.svg)](https://www.bountysource.com/teams/nim)
-
-We welcome everyone's contributions to Nim. No matter how small or large
-the contribution is, anything from small spelling fixes to large modules
-intended to be included in the standard library are accepted. Before
-you get started, you should know the following about this repositories
-structure:
+We welcome everyone's contributions to Nim independent of how small or how large
+they are. Anything from small spelling fixes to large modules intended to
+be included in the standard library are welcome and appreciated. Before you get
+started contributing, you should familiarize yourself with the repository structure:
 
 * ``bin/``, ``build/`` - these directories are empty, but are used when Nim is built.
-* ``compiler/`` - the compiler source code, all the Nim source code files in this
-  directory implement the compiler. This also includes nimfix, and plugins
-  which live in ``compiler/nimfix`` and ``compiler/plugins``
-  respectively. Nimsuggest used to live in the ``compiler`` directory also,
-  but was moved to https://github.com/nim-lang/nimsuggest.
+* ``compiler/`` - the compiler source code. Also includes nimfix, and plugins within
+  ``compiler/nimfix`` and ``compiler/plugins`` respectively. Nimsuggest was moved to
+  the [``nim-lang/nimsuggest``][nimsuggest-repo] repository, though it previously also 
+  lived within the ``compiler/`` directory.
 * ``config/`` - the configuration for the compiler and documentation generator.
 * ``doc/`` - the documentation files in reStructuredText format.
-* ``lib/`` - where the standard library lives.
+* ``lib/`` - the standard library, including:
     * ``pure/`` - modules in the standard library written in pure Nim.
-    * ``impure/`` - modules in the standard library written in pure Nim which
-      depend on libraries written in other languages.
-    * ``wrappers/`` - modules which wrap libraries written in other languages.
-* ``tests/`` - contains tests for the compiler and standard library, organised by
-    category.
-* ``tools/`` - the tools including ``niminst`` and ``nimweb``, most of these are invoked
-    via ``koch``.
-* ``web/`` - the Nim website (http://nim-lang.org).
-* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website, documentation
-  and more.
-
-Most importantly, the ``koch`` tool can be used to run the test suite. To do so compile it first
-by executing ``nim c koch``, then execute ``./koch tests``. The test suite takes a while to run,
-but you can run specific tests by specifying a category to run, for example ``./koch tests cat async``.
-
-Make sure that the tests all pass before
-[submitting your pull request](https://help.github.com/articles/using-pull-requests/).
-If you're short on time, you can
-just run the tests specific to your change. Just run the category which corresponds to the change
-you've made. When you create your pull request, Travis CI will verify that all the tests pass
-anyway.
-
-If you're looking for things to do, take a look at our
-[issue tracker](https://github.com/nim-lang/Nim/issues). There is always plenty of issues
-labelled [``Easy``](https://github.com/nim-lang/Nim/labels/Easy), these should be a good
-starting point if this is your first contribution to Nim.
-
-You can also help with the development of Nim by making donations. You can do so
-in many ways:
-
-* [Gratipay](https://gratipay.com/nim/)
-* [Bountysource](https://www.bountysource.com/teams/nim)
-* Bitcoin - 1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ
-
-Finally, if you have any questions feel free to submit a question on the issue tracker,
-on the [Nim forum](http://forum.nim-lang.org), or on IRC.
+    * ``impure/`` - modules in the standard library written in pure Nim with
+    dependencies written in other languages.
+    * ``wrappers/`` - modules which wrap dependencies written in other languages.
+* ``tests/`` - contains categorized tests for the compiler and standard library.
+* ``tools/`` - the tools including ``niminst`` and ``nimweb`` (mostly invoked via
+  ``koch``).
+* ``web/`` - [the Nim website][nim-site].
+* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website,
+  and generate the documentation.
+
+If you are not familiar with making a pull request using GitHub and/or git, please
+read [this guide][pull-request-instructions].
+
+Ideally you should make sure that all tests pass before submitting a pull request.
+However, if you are short on time, you can just run the tests specific to your
+changes by only running the corresponding categories of tests. Travis CI verifies
+that all tests pass before allowing the pull request to be accepted, so only
+running specific tests should be harmless.
+
+If you're looking for ways to contribute, please look at our [issue tracker][nim-issues].
+There are always plenty of issues labelled [``Easy``][nim-issues-easy]; these should
+be a good starting point for an initial contribution to Nim.
+
+You can also help with the development of Nim by making donations. Donations can be
+made using:
+
+* [Gratipay][nim-gratipay]
+* [Bountysource][nim-bountysource]
+* [Bitcoin][nim-bitcoin]
+
+If you have any questions feel free to submit a question on the
+[Nim forum][nim-forum], or via IRC on [the \#nim channel][nim-irc].
 
 ## License
-The compiler and the standard library are licensed under the MIT license,
-except for some modules where the documentation suggests otherwise. This means
-that you can use any license for your own programs developed with Nim,
-allowing you to create commercial applications.
-
-Read copying.txt for more details.
-
-Copyright (c) 2006-2017 Andreas Rumpf.
-All rights reserved.
+The compiler and the standard library are licensed under the MIT license, except
+for some modules which explicitly state otherwise. As a result you may use any
+compatible license (essentially any license) for your own programs developed with
+Nim. You are explicitly permitted to develop commercial applications using Nim.
+
+Please read the [copying.txt](copying.txt) file for more details.
+
+Copyright © 2006-2017 Andreas Rumpf, all rights reserved.
+
+[nim-site]: https://nim-lang.org
+[nim-forum]: https://forum.nim-lang.org
+[nim-issues]: https://github.com/nim-lang/Nim/issues
+[nim-issues-easy]: https://github.com/nim-lang/Nim/labels/Easy
+[nim-irc]: https://webchat.freenode.net/?channels=nim
+[nim-travisci]: https://travis-ci.org/nim-lang/Nim
+[nim-twitter]: https://twitter.com/nim_lang
+[nim-stackoverflow]: https://stackoverflow.com/questions/tagged/nim
+[nim-stackoverflow-newest]: https://stackoverflow.com/questions/tagged/nim?sort=newest&pageSize=15
+[nim-gitter]: https://gitter.im/nim-lang/Nim
+[nim-gratipay]: https://gratipay.com/nim/
+[nim-bountysource]: https://www.bountysource.com/teams/nim
+[nim-bitcoin]: https://blockchain.info/address/1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ
+[nimble-repo]: https://github.com/nim-lang/nimble
+[nimsuggest-repo]: https://github.com/nim-lang/nimsuggest
+[csources-repo]: https://github.com/nim-lang/csources
+[badge-nim-travisci]: https://img.shields.io/travis/nim-lang/Nim/devel.svg?style=flat-square
+[badge-nim-irc]: https://img.shields.io/badge/chat-on_irc-blue.svg?style=flat-square
+[badge-nim-gitter]: https://img.shields.io/badge/chat-on_gitter-blue.svg?style=flat-square
+[badge-nim-forum-gethelp]: https://img.shields.io/badge/Forum-get%20help-4eb899.svg?style=flat-square
+[badge-nim-twitter]: https://img.shields.io/twitter/follow/nim_lang.svg?style=social
+[badge-nim-stackoverflow]: https://img.shields.io/badge/stackoverflow-nim_tag-yellow.svg?style=flat-square
+[badge-nim-gratipay]: https://img.shields.io/gratipay/team/nim.svg?style=flat-square
+[badge-nim-bountysource]: https://img.shields.io/bountysource/team/nim/activity.svg?style=flat-square
+[badge-nim-bitcoin]: https://img.shields.io/badge/bitcoin-1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ-D69134.svg?style=flat-square
+[image-nim-logo]: https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?url=https://raw.githubusercontent.com/nim-lang/assets/master/Art/logo-crown.png&container=focus&resize_w=36&refresh=21600
+[pull-request-instructions]: https://help.github.com/articles/using-pull-requests/
diff --git a/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim
new file mode 100644
index 000000000..919dc3fc1
--- /dev/null
+++ b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim
@@ -0,0 +1,26 @@
+discard """
+  output: '''false'''
+"""
+
+# bug #5402
+
+import lists
+
+type
+  Container[T] = ref object
+    obj: T
+
+  ListOfContainers[T] = ref object
+    list: DoublyLinkedList[Container[T]]
+
+proc contains[T](this: ListOfContainers[T], obj: T): bool =
+  for item in this.list.items():
+    if item.obj == obj: return true
+  return false
+
+proc newListOfContainers[T](): ListOfContainers[T] =
+  new(result)
+  result.list = initDoublyLinkedList[Container[T]]()
+
+let q = newListOfContainers[int64]()
+echo q.contains(123)
diff --git a/tests/errmsgs/tproper_stacktrace3.nim b/tests/errmsgs/tproper_stacktrace3.nim
new file mode 100644
index 000000000..c292fa092
--- /dev/null
+++ b/tests/errmsgs/tproper_stacktrace3.nim
@@ -0,0 +1,23 @@
+discard """
+  outputsub: '''tproper_stacktrace3.nim(21) main'''
+  exitcode: 1
+"""
+
+# bug #5400
+
+type Container = object
+  val: int
+
+proc actualResolver(x: ptr Container): ptr Container = x
+
+template resolve(): untyped = actualResolver(db)
+
+proc myfail(): int =
+  doAssert false
+
+proc main() =
+  var db: ptr Container = nil
+  # actualResolver(db).val = myfail() # actualResolver is not included in stack trace.
+  resolve().val = myfail() # resolve template is included in stack trace.
+
+main()
diff --git a/tests/gc/foreign_thr.nim b/tests/gc/foreign_thr.nim
new file mode 100644
index 000000000..88ab95113
--- /dev/null
+++ b/tests/gc/foreign_thr.nim
@@ -0,0 +1,88 @@
+discard """
+  output: '''
+Hello from thread
+Hello from thread
+Hello from thread
+Hello from thread
+'''
+  cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
+"""
+# Copied from stdlib
+import strutils
+
+const
+  StackGuardSize = 4096
+  ThreadStackMask = 1024*256*sizeof(int)-1
+  ThreadStackSize = ThreadStackMask+1 - StackGuardSize
+
+type ThreadFunc = proc() {.thread.}
+
+when defined(posix):
+  import posix
+
+  proc runInForeignThread(f: ThreadFunc) =
+    proc wrapper(p: pointer): pointer {.noconv.} =
+      let thr = cast[ThreadFunc](p)
+      setupForeignThreadGc()
+      thr()
+      tearDownForeignThreadGc()
+      setupForeignThreadGc()
+      thr()
+      tearDownForeignThreadGc()
+      result = nil
+
+    var attrs {.noinit.}: PthreadAttr
+    doAssert pthread_attr_init(addr attrs) == 0
+    doAssert pthread_attr_setstacksize(addr attrs, ThreadStackSize) == 0
+    var tid: Pthread
+    doAssert pthread_create(addr tid, addr attrs, wrapper, f) == 0
+    doAssert pthread_join(tid, nil) == 0
+
+elif defined(windows):
+  import winlean
+  type
+    WinThreadProc = proc (x: pointer): int32 {.stdcall.}
+
+  proc createThread(lpThreadAttributes: pointer, dwStackSize: DWORD,
+                     lpStartAddress: WinThreadProc,
+                     lpParameter: pointer,
+                     dwCreationFlags: DWORD,
+                     lpThreadId: var DWORD): Handle {.
+    stdcall, dynlib: "kernel32", importc: "CreateThread".}
+
+  proc wrapper(p: pointer): int32 {.stdcall.} =
+    let thr = cast[ThreadFunc](p)
+    setupForeignThreadGc()
+    thr()
+    tearDownForeignThreadGc()
+    setupForeignThreadGc()
+    thr()
+    tearDownForeignThreadGc()
+    result = 0'i32
+
+  proc runInForeignThread(f: ThreadFunc) =
+    var dummyThreadId: DWORD
+    var h = createThread(nil, ThreadStackSize.int32, wrapper.WinThreadProc, cast[pointer](f), 0, dummyThreadId)
+    doAssert h != 0.Handle
+    doAssert waitForSingleObject(h, -1'i32) == 0.DWORD
+
+else:
+  {.fatal: "Unknown system".}
+
+proc runInNativeThread(f: ThreadFunc) =
+  proc wrapper(f: ThreadFunc) {.thread.} =
+    # These operations must be NOP
+    setupForeignThreadGc()
+    tearDownForeignThreadGc()
+    f()
+    f()
+  var thr: Thread[ThreadFunc]
+  createThread(thr, wrapper, f)
+  joinThread(thr)
+
+proc f {.thread.} =
+  var msg = "Hello " & "from thread"
+  echo msg
+
+runInForeignThread(f)
+runInNativeThread(f)
diff --git a/tests/metatype/tfieldaccessor.nim b/tests/metatype/tfieldaccessor.nim
new file mode 100644
index 000000000..7054dd22b
--- /dev/null
+++ b/tests/metatype/tfieldaccessor.nim
@@ -0,0 +1,17 @@
+type
+  Test = object
+    x: int
+    case p: bool
+    of true:
+      a: int
+    else:
+      case q: bool
+      of true:
+        b: int
+      else:
+        discard
+
+proc f[T](t: typedesc[T]): int =
+  1
+
+assert Test.f == 1
diff --git a/tests/overload/tprefer_tygenericinst.nim b/tests/overload/tprefer_tygenericinst.nim
index 9787af06b..56541c7e8 100644
--- a/tests/overload/tprefer_tygenericinst.nim
+++ b/tests/overload/tprefer_tygenericinst.nim
@@ -19,7 +19,7 @@ when true:
   q(B()) # This call reported as ambiguous.
 
 # bug #2219
-template testPred(a: expr) =
+template testPred(a: untyped) =
   block:
     type A = object of RootObj
     type B = object of A
diff --git a/tests/stdlib/tbug5382.nim b/tests/stdlib/tbug5382.nim
new file mode 100644
index 000000000..c86656d32
--- /dev/null
+++ b/tests/stdlib/tbug5382.nim
@@ -0,0 +1,11 @@
+discard """
+  output: '''
+02
+'''
+"""
+import re
+
+let regexp = re"^\/([0-9]{2})\.html$"
+var matches: array[1, string]
+discard "/02.html".find(regexp, matches)
+echo matches[0]
diff --git a/tests/template/tgensymregression.nim b/tests/template/tgensymregression.nim
index e73ff258d..e758e0d9a 100644
--- a/tests/template/tgensymregression.nim
+++ b/tests/template/tgensymregression.nim
@@ -1,3 +1,10 @@
+discard """
+  output: '''[0.0, 0.0, 0.0]
+
+[0.0, 0.0, 0.0, 0.0]
+
+5050'''
+"""
 
 template mathPerComponent(op: untyped): untyped =
   proc op*[N,T](v,u: array[N,T]): array[N,T] {.inline.} =
@@ -19,3 +26,24 @@ proc foo(): void =
   echo repr(v1 *** v2)
 
 foo()
+
+# bug #5383
+import sequtils
+
+proc zipWithIndex[A](ts: seq[A]): seq[(int, A)] =
+  toSeq(pairs(ts))
+
+proc main =
+  discard zipWithIndex(@["foo", "bar"])
+  discard zipWithIndex(@[1, 2])
+  discard zipWithIndex(@[true, false])
+
+main()
+
+# bug #5405
+
+proc main2() =
+  let s = toSeq(1..100).foldL(a + b)
+  echo s
+
+main2()
diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim
index 6c4413866..568725fd4 100644
--- a/tests/template/tparams_gensymed.nim
+++ b/tests/template/tparams_gensymed.nim
@@ -5,8 +5,8 @@ import macros
 
 # Test that parameters are properly gensym'ed finally:
 
-template genNodeKind(kind, name: expr): stmt =
-  proc name*(children: varargs[PNimrodNode]): PNimrodNode {.compiletime.}=
+template genNodeKind(kind, name: untyped) =
+  proc name*(children: varargs[NimNode]): NimNode {.compiletime.}=
     result = newNimNode(kind)
     for c in children:
       result.add(c)
@@ -22,7 +22,7 @@ type Something = object
 
 proc testA(x: Something) = discard
 
-template def(name: expr) {.immediate.} =
+template def(name: untyped) =
   proc testB[T](reallyUniqueName: T) =
     `test name`(reallyUniqueName)
 def A
@@ -35,8 +35,7 @@ testB(x)
 # Test that templates in generics still work (regression to fix the
 # regression...)
 
-template forStatic(index: expr, slice: Slice[int], predicate: stmt):
-                   stmt {.immediate.} =
+template forStatic(index, slice, predicate: untyped) =
   const a = slice.a
   const b = slice.b
   when a <= b:
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 2dc8e3318..0685dd73a 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -147,6 +147,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
       testSpec r, makeTest("tests/gc" / filename, options &
                     " -d:release --gc:boehm", cat, actionRun)
 
+  testWithoutBoehm "foreign_thr"
   test "gcemscripten"
   test "growobjcrash"
   test "gcbench"
diff --git a/tests/untestable/tpostgres.nim b/tests/untestable/tpostgres.nim
index dcbdaad39..486d0d703 100644
--- a/tests/untestable/tpostgres.nim
+++ b/tests/untestable/tpostgres.nim
@@ -76,7 +76,236 @@ for i in 1..10:
   echo(name)
   discard db.getRow(
     SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name]))
+    
+# get column details
+db.exec(SqlQuery("DROP TABLE IF EXISTS dbtypes;"))
+db.exec(SqlQuery("DROP TYPE IF EXISTS custom_enum;"))
+db.exec(SqlQuery("CREATE TYPE custom_enum AS ENUM ('1', '2', '3');"))
+db.exec(SqlQuery("DROP TYPE IF EXISTS custom_composite;"))
+db.exec(SqlQuery("CREATE TYPE custom_composite AS (r double precision, i double precision);"))
+db.exec(SqlQuery("""CREATE TABLE dbtypes(
+                    id serial UNIQUE,
+                    bytea_col bytea,
+                    smallint_col smallint,
+                    integer_col integer,
+                    bigint_col bigint,
+                    decimal_col decimal,
+                    numeric_col numeric,
+                    real_col real,
+                    double_precision_col double precision,
+                    smallserial_col smallserial,
+                    serial_col serial,
+                    bigserial_col bigserial,
+                    money_col money,
+                    varchar_col varchar(10),
+                    character_col character(1),
+                    text_col text,
+                    timestamp_col timestamp,
+                    date_col date,
+                    time_col time,
+                    interval_col interval,
+                    bool_col boolean,
+                    custom_enum_col custom_enum,
+                    point_col point,
+                    line_col line,
+                    lseg_col lseg,
+                    box_col box,
+                    path_col path,
+                    polygon_col polygon,
+                    circle_col circle,
+                    cidr_col cidr,
+                    inet_col inet,
+                    macaddr_col macaddr,
+                    bit_col bit,
+                    varbit_col bit(3),
+                    tsvector_col tsvector,
+                    tsquery_col tsquery,
+                    uuid_col uuid,
+                    xml_col xml,
+                    json_col json,
+                    array_col integer[],
+                    custom_composite_col custom_composite,
+                    range_col int4range
+                    );"""))
+db.exec(SqlQuery("INSERT INTO dbtypes (id) VALUES(0);"))
 
+var dbCols : DbColumns = @[]
+for row in db.instantRows(dbCols, sql"SELECT * FROM dbtypes"):
+  doAssert len(dbCols) == 42
+
+doAssert dbCols[0].name == "id"
+doAssert dbCols[0].typ.kind == DbTypeKind.dbInt
+doAssert dbCols[0].typ.name == "int4"
+doAssert dbCols[0].typ.size == 4
+
+doAssert dbCols[1].name == "bytea_col"
+doAssert dbCols[1].typ.kind == DbTypeKind.dbBlob
+doAssert dbCols[1].typ.name == "bytea"
+
+doAssert dbCols[2].name == "smallint_col"
+doAssert dbCols[2].typ.kind == DbTypeKind.dbInt
+doAssert dbCols[2].typ.name == "int2"
+doAssert dbCols[2].typ.size == 2
+
+doAssert dbCols[3].name == "integer_col"
+doAssert dbCols[3].typ.kind == DbTypeKind.dbInt
+doAssert dbCols[3].typ.name == "int4"
+doAssert dbCols[3].typ.size == 4
+
+doAssert dbCols[4].name == "bigint_col"
+doAssert dbCols[4].typ.kind == DbTypeKind.dbInt
+doAssert dbCols[4].typ.name == "int8"
+doAssert dbCols[4].typ.size == 8
+
+doAssert dbCols[5].name == "decimal_col"
+doAssert dbCols[5].typ.kind == DbTypeKind.dbDecimal
+doAssert dbCols[5].typ.name == "numeric"
+
+doAssert dbCols[6].name == "numeric_col"
+doAssert dbCols[6].typ.kind == DbTypeKind.dbDecimal
+doAssert dbCols[6].typ.name == "numeric"
+
+doAssert dbCols[7].name == "real_col"
+doAssert dbCols[7].typ.kind == DbTypeKind.dbFloat
+doAssert dbCols[7].typ.name == "float4"
+
+doAssert dbCols[8].name == "double_precision_col"
+doAssert dbCols[8].typ.kind == DbTypeKind.dbFloat
+doAssert dbCols[8].typ.name == "float8"
+
+doAssert dbCols[9].name == "smallserial_col"
+doAssert dbCols[9].typ.kind == DbTypeKind.dbInt
+doAssert dbCols[9].typ.name == "int2"
+
+doAssert dbCols[10].name == "serial_col"
+doAssert dbCols[10].typ.kind == DbTypeKind.dbInt
+doAssert dbCols[10].typ.name == "int4"
+
+doAssert dbCols[11].name == "bigserial_col"
+doAssert dbCols[11].typ.kind == DbTypeKind.dbInt
+doAssert dbCols[11].typ.name == "int8"
+
+doAssert dbCols[12].name == "money_col"
+doAssert dbCols[12].typ.kind == DbTypeKind.dbDecimal
+doAssert dbCols[12].typ.name == "money"    
+    
+doAssert dbCols[13].name == "varchar_col"
+doAssert dbCols[13].typ.kind == DbTypeKind.dbVarchar
+doAssert dbCols[13].typ.name == "varchar"
+
+doAssert dbCols[14].name == "character_col"
+doAssert dbCols[14].typ.kind == DbTypeKind.dbFixedChar
+doAssert dbCols[14].typ.name == "bpchar"
+
+doAssert dbCols[15].name == "text_col"
+doAssert dbCols[15].typ.kind == DbTypeKind.dbVarchar
+doAssert dbCols[15].typ.name == "text"
+
+doAssert dbCols[16].name == "timestamp_col"
+doAssert dbCols[16].typ.kind == DbTypeKind.dbTimestamp
+doAssert dbCols[16].typ.name == "timestamp"
+
+doAssert dbCols[17].name == "date_col"
+doAssert dbCols[17].typ.kind == DbTypeKind.dbDate
+doAssert dbCols[17].typ.name == "date"
+
+doAssert dbCols[18].name == "time_col"
+doAssert dbCols[18].typ.kind == DbTypeKind.dbTime
+doAssert dbCols[18].typ.name == "time"
+
+doAssert dbCols[19].name == "interval_col"
+doAssert dbCols[19].typ.kind == DbTypeKind.dbTimeInterval
+doAssert dbCols[19].typ.name == "interval"
+
+doAssert dbCols[20].name == "bool_col"
+doAssert dbCols[20].typ.kind == DbTypeKind.dbBool
+doAssert dbCols[20].typ.name == "bool"
+
+doAssert dbCols[21].name == "custom_enum_col"
+doAssert dbCols[21].typ.kind == DbTypeKind.dbUnknown
+doAssert parseInt(dbCols[21].typ.name) > 0
+    
+doAssert dbCols[22].name == "point_col"
+doAssert dbCols[22].typ.kind == DbTypeKind.dbPoint
+doAssert dbCols[22].typ.name == "point"    
+
+doAssert dbCols[23].name == "line_col"
+doAssert dbCols[23].typ.kind == DbTypeKind.dbLine
+doAssert dbCols[23].typ.name == "line"    
+
+doAssert dbCols[24].name == "lseg_col"
+doAssert dbCols[24].typ.kind == DbTypeKind.dbLseg
+doAssert dbCols[24].typ.name == "lseg"    
+
+doAssert dbCols[25].name == "box_col"
+doAssert dbCols[25].typ.kind == DbTypeKind.dbBox
+doAssert dbCols[25].typ.name == "box"    
+
+doAssert dbCols[26].name == "path_col"
+doAssert dbCols[26].typ.kind == DbTypeKind.dbPath
+doAssert dbCols[26].typ.name == "path"    
+
+doAssert dbCols[27].name == "polygon_col"
+doAssert dbCols[27].typ.kind == DbTypeKind.dbPolygon
+doAssert dbCols[27].typ.name == "polygon"
+
+doAssert dbCols[28].name == "circle_col"
+doAssert dbCols[28].typ.kind == DbTypeKind.dbCircle
+doAssert dbCols[28].typ.name == "circle"
+
+doAssert dbCols[29].name == "cidr_col"
+doAssert dbCols[29].typ.kind == DbTypeKind.dbInet
+doAssert dbCols[29].typ.name == "cidr"
+
+doAssert dbCols[30].name == "inet_col"
+doAssert dbCols[30].typ.kind == DbTypeKind.dbInet
+doAssert dbCols[30].typ.name == "inet"
+
+doAssert dbCols[31].name == "macaddr_col"
+doAssert dbCols[31].typ.kind == DbTypeKind.dbMacAddress
+doAssert dbCols[31].typ.name == "macaddr"
+
+doAssert dbCols[32].name == "bit_col"
+doAssert dbCols[32].typ.kind == DbTypeKind.dbBit
+doAssert dbCols[32].typ.name == "bit"
+
+doAssert dbCols[33].name == "varbit_col"
+doAssert dbCols[33].typ.kind == DbTypeKind.dbBit
+doAssert dbCols[33].typ.name == "bit"
+
+doAssert dbCols[34].name == "tsvector_col"
+doAssert dbCols[34].typ.kind == DbTypeKind.dbVarchar
+doAssert dbCols[34].typ.name == "tsvector"
+
+doAssert dbCols[35].name == "tsquery_col"
+doAssert dbCols[35].typ.kind == DbTypeKind.dbVarchar
+doAssert dbCols[35].typ.name == "tsquery"
+
+doAssert dbCols[36].name == "uuid_col"
+doAssert dbCols[36].typ.kind == DbTypeKind.dbVarchar
+doAssert dbCols[36].typ.name == "uuid"
+
+doAssert dbCols[37].name == "xml_col"
+doAssert dbCols[37].typ.kind == DbTypeKind.dbXml
+doAssert dbCols[37].typ.name == "xml"
+
+doAssert dbCols[38].name == "json_col"
+doAssert dbCols[38].typ.kind == DbTypeKind.dbJson
+doAssert dbCols[38].typ.name == "json"
+
+doAssert dbCols[39].name == "array_col"
+doAssert dbCols[39].typ.kind == DbTypeKind.dbArray
+doAssert dbCols[39].typ.name == "int4[]"
+
+doAssert dbCols[40].name == "custom_composite_col"
+doAssert dbCols[40].typ.kind == DbTypeKind.dbUnknown
+doAssert parseInt(dbCols[40].typ.name) > 0
+
+doAssert dbCols[41].name == "range_col"
+doAssert dbCols[41].typ.kind == DbTypeKind.dbComposite
+doAssert dbCols[41].typ.name == "int4range"
+    
 echo("All tests succeeded!")
 
 db.close()
+
diff --git a/tools/finish.nim b/tools/finish.nim
index a9fb444a0..e39062b02 100644
--- a/tools/finish.nim
+++ b/tools/finish.nim
@@ -209,6 +209,9 @@ proc main() =
           of Manual:
             echo "After download, move it to: ", dest
             if askBool("Download successful? (y/n) "):
+              while not fileExists("dist" / mingw):
+                echo "could not find: ", "dist" / mingw
+                if not askBool("Try again? (y/n) "): break
               if unzip(): retry = true
           of Failure: discard
           of Success:
diff --git a/web/bountysource.nim.cfg b/web/bountysource.nim.cfg
new file mode 100644
index 000000000..521e21de4
--- /dev/null
+++ b/web/bountysource.nim.cfg
@@ -0,0 +1 @@
+-d:ssl
diff --git a/web/inactive_sponsors.csv b/web/inactive_sponsors.csv
index d466f3f31..6352bc194 100644
--- a/web/inactive_sponsors.csv
+++ b/web/inactive_sponsors.csv
@@ -1,26 +1,40 @@
 logo, name, url, this_month, all_time, since, level
 ,bogen,,0,1010,"Jul 23, 2016",1
 ,mikra,,0,400,"Apr 28, 2016",1
-,linkmonitor,,0,180,"Jan 28, 2016",1
+,shkolnick-kun,,0,375,"Jul 6, 2016",1
+,"Chris Heller",,0,350,"May 19, 2016",1
+,linkmonitor,,0,280,"Jan 28, 2016",1
 ,avsej,,0,110,"Jun 10, 2016",1
 ,WilRubin,,0,100,"Aug 11, 2015",1
 ,"Benny Luypaert",,0,100,"Apr 10, 2016",1
-,"Chris Heller",,0,100,"May 19, 2016",1
 ,PhilipWitte,,0,100,"Aug 5, 2016",1
+,skunkiferous,,0,100,"Oct 2, 2016",1
+,"Jonathan Arnett",,0,90,"May 20, 2016",1
 ,Boxifier,,0,75,"Apr 12, 2016",1
 ,iolloyd,,0,75,"Apr 29, 2016",1
+,btbytes,,0,70,"Apr 6, 2016",1
 ,rb01,,0,50,"May 4, 2016",1
+,barcharcraz,,0,50,"Jun 2, 2016",1
+,zachaysan,,0,50,"Jun 7, 2016",1
+,kunev,,0,50,"Dec 26, 2016",1
+,iboB,,0,50,"Jan 28, 2017",1
 ,TedSinger,,0,45,"Apr 9, 2016",1
+,johnnovak,,0,45,"Apr 30, 2016",1
+,"Matthew Baulch",,0,40,"Jun 7, 2016",1
+,"Matthew Newton",,0,35,"Apr 20, 2016",1
 ,martinbbjerregaard,,0,35,"Jun 9, 2016",1
 ,RationalG,,0,30,"Jun 17, 2016",1
 ,benbve,,0,30,"Jul 12, 2016",1
-,barcharcraz,,0,25,"Jun 2, 2016",1
+,multikatt,,0,30,"Nov 2, 2016",1
 ,"Landon Bass",,0,25,"Jun 7, 2016",1
 ,jimrichards,,0,25,"Jun 8, 2016",1
 ,jjzazuet,,0,25,"Jul 10, 2016",1
-,moigagoo,,0,20,"May 13, 2016",1
 ,kteza1,,0,20,"Jun 10, 2016",1
 ,tomkeus,,0,20,"Sep 4, 2016",1
+,csoriano89,,0,20,"Sep 7, 2016",1
+,juanjux,,0,20,"Oct 29, 2016",1
+,zagfai,,0,20,"Nov 3, 2016",1
+,hellcoderz,,0,20,"Jan 24, 2017",1
 ,mirek,,0,15,"Apr 9, 2016",1
 ,DateinAsia,,0,15,"Jul 30, 2016",1
 ,rickc,,0,15,"Jul 31, 2016",1
@@ -38,13 +52,6 @@ logo, name, url, this_month, all_time, since, level
 ,Blumenversand,,0,10,"Jul 21, 2016",1
 ,cinnabardk,,0,10,"Aug 6, 2016",1
 ,reddec,,0,10,"Aug 31, 2016",1
+,cupen,,0,10,"Nov 21, 2016",1
+,yay,,0,10,"Jan 25, 2017",1
 ,niv,,0,5,"Apr 6, 2016",1
-,goniz,,0,5,"Apr 7, 2016",1
-,genunix,,0,5,"Apr 12, 2016",1
-,CynepHy6,,0,5,"Apr 14, 2016",1
-,ivanflorentin,,0,5,"May 3, 2016",1
-,stevenyhw,,0,5,"May 20, 2016",1
-,"Sanjay Singh",,0,5,"Jun 6, 2016",1
-,yuttie,,0,5,"Jun 7, 2016",1
-,hron,,0,5,"Jun 11, 2016",1
-,laszlowaty,,0,5,"Jun 17, 2016",1
diff --git a/web/news/e031_version_0_16_2.rst b/web/news/e031_version_0_16_2.rst
index 5ee40b772..171e4cef1 100644
--- a/web/news/e031_version_0_16_2.rst
+++ b/web/news/e031_version_0_16_2.rst
@@ -18,7 +18,11 @@ Changes affecting backwards compatibility
 - The IO routines now raise ``EOFError`` for the "end of file" condition.
   ``EOFError`` is a subtype of ``IOError`` and so it's easier to distinguish
   between "error during read" and "error due to EOF".
-
+- A hash procedure has been added for ``cstring`` type in ``hashes`` module.
+  Previously, hash of a ``cstring`` would be calculated as a hash of the
+  pointer. Now the hash is calculated from the contents of the string, assuming
+  ``cstring`` is a null-terminated string. Equal ``string`` and ``cstring``
+  values produce an equal hash value.
 
 Library Additions
 -----------------
diff --git a/web/sponsors.csv b/web/sponsors.csv
index 0701575d5..7136808c6 100644
--- a/web/sponsors.csv
+++ b/web/sponsors.csv
@@ -1,34 +1,40 @@
 logo, name, url, this_month, all_time, since, level
-assets/bountysource/secondspectrum.png,Second Spectrum,http://www.secondspectrum.com/,250,1250,"May 5, 2016",250
-assets/bountysource/xored.svg,"Xored Software, Inc.",http://xored.com/,250,1000,"Jun 20, 2016",250
-,shkolnick-kun,https://github.com/shkolnick-kun,75,225,"Jul 6, 2016",75
-,flyx,http://flyx.org,35,210,"Apr 7, 2016",75
-,"Yuriy Glukhov",,25,150,"Apr 6, 2016",25
-,endragor,https://github.com/endragor,25,150,"Apr 7, 2016",25
-,FedericoCeratto,http://firelet.net,25,150,"Apr 7, 2016",25
-,"Adrian Veith",,25,150,"Apr 20, 2016",25
-,skunkiferous,https://github.com/skunkiferous,100,100,"Oct 2, 2016",150
-,euantorano,http://euantorano.co.uk,25,100,"Jun 7, 2016",25
-,xxlabaza,https://github.com/xxlabaza,25,95,"Jun 17, 2016",25
-,btbytes,https://www.btbytes.com/,10,60,"Apr 6, 2016",10
-,niebaopeng,https://github.com/niebaopeng,10,50,"Apr 15, 2016",10
-,"Jonathan Arnett",,10,50,"May 20, 2016",10
-,swalf,https://github.com/swalf,5,45,"May 9, 2016",5
-,zolern,https://github.com/zolern,10,40,"Apr 15, 2016",10
-,"pyloor ",https://schwarz-weiss.cc/,10,40,"May 16, 2016",10
-,zachaysan,http://venn.lc,10,40,"Jun 7, 2016",10
-,"Matthew Baulch",,10,40,"Jun 7, 2016",10
-,"Oskari Timperi",,10,40,"Jun 8, 2016",10
-,"Handojo Goenadi",,5,35,"Apr 19, 2016",5
-,"Matthew Newton",,5,30,"Apr 20, 2016",5
-,johnnovak,http://www.johnnovak.net/,5,30,"Apr 29, 2016",5
-,RyanMarcus,http://rmarcus.info,5,15,"Jul 19, 2016",5
-,lenzenmi,https://github.com/lenzenmi,5,15,"Jul 28, 2016",5
-,cpunion,https://github.com/cpunion,10,10,"Sep 9, 2016",10
-,pandada8,https://github.com/pandada8,5,10,"Aug 12, 2016",5
-,abeaumont,http://alfredobeaumont.org/blog,5,10,"Aug 12, 2016",5
-,"Svend Knudsen",,1,6,"Apr 11, 2016",1
-,"Michael D. Sklaroff",,1,6,"Apr 27, 2016",1
-,csoriano89,https://github.com/csoriano89,5,5,"Sep 7, 2016",5
-,nicck,,1,2,"Aug 9, 2016",1
-,campbellr,,1,1,"Sep 4, 2016",1
+assets/bountysource/secondspectrum.png,Second Spectrum,http://www.secondspectrum.com/,250,2250,"May 5, 2016",250
+assets/bountysource/xored.svg,"Xored Software, Inc.",http://xored.com/,250,1000,250,2000,"Jun 20, 2016",250
+,Varriount,https://github.com/Varriount,250,750,"Nov 18, 2016",250
+,flyx,http://flyx.org,35,350,"Apr 7, 2016",75
+,"Yuriy Glukhov",,25,250,"Apr 6, 2016",25
+,endragor,https://github.com/endragor,25,250,"Apr 7, 2016",25
+,FedericoCeratto,http://firelet.net,25,250,"Apr 7, 2016",25
+,"Adrian Veith",,25,250,"Apr 20, 2016",25
+,euantorano,http://euantorano.co.uk,25,200,"Jun 7, 2016",25
+,xxlabaza,https://github.com/xxlabaza,25,170,"Jun 17, 2016",25
+,devted,https://github.com/devted,25,100,"Oct 19, 2016",25
+,"pyloor ",https://schwarz-weiss.cc/,10,95,"May 16, 2016",10
+,niebaopeng,https://github.com/niebaopeng,10,90,"Apr 15, 2016",10
+,zolern,https://github.com/zolern,10,80,"Apr 15, 2016",10
+,"Oskari Timperi",,10,80,"Jun 8, 2016",10
+,jcosborn,https://github.com/jcosborn,25,75,"Nov 21, 2016",25
+,swalf,https://github.com/swalf,5,65,"May 9, 2016",5
+,"Handojo Goenadi",,5,55,"Apr 19, 2016",5
+,cpunion,https://github.com/cpunion,10,50,"Sep 9, 2016",10
+,D-L,https://github.com/D-L,5,50,"Apr 7, 2016",5
+,moigagoo,http://sloth-ci.com,10,40,"May 13, 2016",10
+,enthus1ast,http://code0.xyz/,10,40,"Oct 28, 2016",10
+,RyanMarcus,http://rmarcus.info,5,35,"Jul 19, 2016",5
+,lenzenmi,https://github.com/lenzenmi,5,35,"Jul 28, 2016",5
+,"Christian Bagley",,10,30,"Oct 11, 2016",10
+,pandada8,https://github.com/pandada8,5,30,"Aug 12, 2016",5
+,abeaumont,http://alfredobeaumont.org/blog,5,30,"Aug 12, 2016",5
+,opendragon,http://www.opendragon.com,25,25,"Jan 18, 2017",25
+,"Eric Raible",,10,20,"Dec 23, 2016",10
+,zefciu,http://pythonista.net,10,20,"Dec 29, 2016",10
+,"Andrey ",https://github.com/Andrey,5,20,"Oct 10, 2016",5
+,syrol,https://github.com/syrol,5,10,"Dec 12, 2016",5
+,"Svend Knudsen",,1,10,"Apr 11, 2016",1
+,"Michael D. Sklaroff",,1,10,"Apr 27, 2016",1
+,nicck,,1,6,"Aug 9, 2016",1
+,cnygaard,,5,5,"Jan 17, 2017",5
+,Aldrog,,5,5,"Feb 11, 2017",5
+,mpachecofaulk55,,5,5,"Feb 11, 2017",5
+,campbellr,,1,5,"Sep 4, 2016",1