summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim15
-rw-r--r--compiler/ccgstmts.nim8
-rw-r--r--compiler/evaltempl.nim50
-rw-r--r--compiler/jsgen.nim6
-rw-r--r--compiler/nim.ini2
-rw-r--r--compiler/nim.nimrod.cfg2
-rw-r--r--compiler/nimfix/nimfix.nim6
-rw-r--r--compiler/parser.nim16
-rw-r--r--compiler/sem.nim21
-rw-r--r--compiler/semcall.nim27
-rw-r--r--compiler/semdata.nim2
-rw-r--r--compiler/semexprs.nim47
-rw-r--r--compiler/semgnrc.nim13
-rw-r--r--compiler/seminst.nim29
-rw-r--r--compiler/semstmts.nim34
-rw-r--r--compiler/semtypes.nim81
-rw-r--r--compiler/sigmatch.nim144
-rw-r--r--compiler/suggest.nim3
-rw-r--r--compiler/types.nim20
-rw-r--r--compiler/vm.nim32
-rw-r--r--compiler/vmdef.nim3
-rw-r--r--compiler/vmgen.nim38
-rw-r--r--copying.txt2
-rw-r--r--doc/backends.txt6
-rw-r--r--doc/basicopt.txt2
-rw-r--r--doc/idetools.txt2
-rw-r--r--doc/lib.txt22
-rw-r--r--doc/manual/exceptions.txt62
-rw-r--r--doc/manual/procs.txt7
-rw-r--r--doc/manual/types.txt130
-rw-r--r--doc/nimc.txt52
-rw-r--r--doc/tut1.txt6
-rw-r--r--doc/tut2.txt54
-rw-r--r--koch.nim16
-rw-r--r--lib/core/macros.nim2
-rw-r--r--lib/impure/osinfo_posix.nim10
-rw-r--r--lib/impure/osinfo_win.nim8
-rw-r--r--lib/posix/posix.nim4
-rw-r--r--lib/pure/asyncdispatch.nim34
-rw-r--r--lib/pure/asynchttpserver.nim77
-rw-r--r--lib/pure/asyncio.nim7
-rw-r--r--lib/pure/asyncnet.nim45
-rw-r--r--lib/pure/complex.nim5
-rw-r--r--lib/pure/htmlgen.nim2
-rw-r--r--lib/pure/httpclient.nim185
-rw-r--r--lib/pure/md5.nim270
-rw-r--r--lib/pure/net.nim33
-rw-r--r--lib/pure/os.nim2
-rw-r--r--lib/pure/parseurl.nim8
-rw-r--r--lib/pure/pegs.nim2
-rw-r--r--lib/pure/rawsockets.nim4
-rw-r--r--lib/pure/rawsockets.pretty.nim426
-rw-r--r--lib/pure/scgi.nim4
-rw-r--r--lib/pure/selectors.nim11
-rw-r--r--lib/pure/sockets.nim7
-rw-r--r--lib/pure/unittest.nim4
-rw-r--r--lib/pure/uri.nim85
-rw-r--r--lib/system.nim2
-rw-r--r--lib/system/channels.nim7
-rw-r--r--lib/system/excpt.nim6
-rw-r--r--lib/system/gc.nim36
-rw-r--r--lib/windows/winlean.nim44
-rw-r--r--lib/wrappers/openssl.nim13
-rw-r--r--tests/async/tasyncawait.nim4
-rw-r--r--tests/async/tasynciossl.nim4
-rw-r--r--tests/async/tasyncudp.nim6
-rw-r--r--tests/gc/closureleak.nim4
-rw-r--r--tests/gc/cyclecollector.nim21
-rw-r--r--tests/gc/gctest.nim3
-rw-r--r--tests/generics/t1050.nim16
-rw-r--r--tests/generics/t1056.nim26
-rw-r--r--tests/generics/t1789.nim44
-rw-r--r--tests/macros/tvtable.nim4
-rw-r--r--tests/metatype/tsemistatic.nim8
-rw-r--r--tests/metatype/tstaticparams.nim86
-rw-r--r--tests/metatype/tusertypeclasses.nim29
-rw-r--r--tests/misc/tcolonisproc.nim9
-rw-r--r--tests/misc/tnoinst.nim1
-rw-r--r--tests/misc/tvarious.nim112
-rw-r--r--tests/parser/tprecedence.nim8
-rw-r--r--tests/static/tstaticparammacro.nim22
-rw-r--r--tests/stdlib/tmath2.nim4
-rw-r--r--tests/stdlib/tparsefloat.nim3
-rw-r--r--tests/stdlib/tpegs.nim64
-rw-r--r--tests/stdlib/tsockets.nim12
-rw-r--r--tests/testament/categories.nim13
-rw-r--r--tests/threads/ttryrecv.nim35
-rw-r--r--tests/typerel/typedescs.nim7
-rw-r--r--tests/types/temptyseqs.nim26
-rw-r--r--tests/types/tisopr.nim17
-rw-r--r--tests/vm/triangle_array.nim17
-rw-r--r--tests/vm/tstringnil.nim2
-rw-r--r--todo.txt5
-rw-r--r--tools/niminst/niminst.nim4
-rw-r--r--tools/niminst/nsis.tmpl2
-rw-r--r--tools/nimweb.nim24
-rw-r--r--tools/website.tmpl2
-rw-r--r--web/assets/style.css5
-rw-r--r--web/community.txt6
-rw-r--r--web/download.txt17
-rw-r--r--web/index.txt38
-rw-r--r--web/learn.txt2
-rw-r--r--web/news.txt287
-rw-r--r--web/nimblepkglist.nim (renamed from web/babelpkglist.nim)5
-rw-r--r--web/question.txt1
-rw-r--r--web/ticker.txt10
106 files changed, 2290 insertions, 1028 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 64b59a283..a071060d4 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -399,6 +399,7 @@ const
   tyPureObject* = tyTuple
   GcTypeKinds* = {tyRef, tySequence, tyString}
   tyError* = tyProxy # as an errornous node should match everything
+  tyUnknown* = tyFromExpr
 
   tyUnknownTypes* = {tyError, tyFromExpr}
 
@@ -1340,6 +1341,10 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
   result = t
   while result.kind in kinds: result = lastSon(result)
 
+proc safeSkipTypes*(t: PType, kinds: TTypeKinds): PType =
+  result = if t != nil: t.skipTypes(kinds)
+           else: nil
+
 proc isGCedMem*(t: PType): bool {.inline.} =
   result = t.kind in {tyString, tyRef, tySequence} or
            t.kind == tyProc and t.callConv == ccClosure
@@ -1517,8 +1522,8 @@ proc getStr*(a: PNode): string =
 proc getStrOrChar*(a: PNode): string = 
   case a.kind
   of nkStrLit..nkTripleStrLit: result = a.strVal
-  of nkCharLit: result = $chr(int(a.intVal))
-  else: 
+  of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
+  else:
     internalError(a.info, "getStrOrChar")
     result = ""
 
@@ -1560,3 +1565,9 @@ proc isEmptyType*(t: PType): bool {.inline.} =
   ## 'void' and 'stmt' types are often equivalent to 'nil' these days:
   result = t == nil or t.kind in {tyEmpty, tyStmt}
 
+proc makeStmtList*(n: PNode): PNode =
+  if n.kind == nkStmtList:
+    result = n
+  else:
+    result = newNodeI(nkStmtList, n.info)
+    result.add n
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index e5848f558..6c7d40d1c 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -798,7 +798,9 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
     startBlock(p)
     var finallyBlock = t.lastSon
     if finallyBlock.kind == nkFinally:
-      expr(p, finallyBlock.sons[0], d)
+      #expr(p, finallyBlock.sons[0], d)
+      genStmts(p, finallyBlock.sons[0])
+
     line(p, cpsStmts, ~"throw;$n")
     endBlock(p)
   
@@ -807,7 +809,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
   
   discard pop(p.nestedTryStmts)
   if (i < length) and (t.sons[i].kind == nkFinally):
-    exprBlock(p, t.sons[i].sons[0], d)
+    genSimpleBlock(p, t.sons[i].sons[0])
   
 proc genTry(p: BProc, t: PNode, d: var TLoc) = 
   # code to generate:
@@ -899,7 +901,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   endBlock(p) # end of else block
   if i < length and t.sons[i].kind == nkFinally:
     p.finallySafePoints.add(safePoint)
-    exprBlock(p, t.sons[i].sons[0], d)
+    genSimpleBlock(p, t.sons[i].sons[0])
     discard pop(p.finallySafePoints)
   linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint)
 
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 78cc691c0..ecb898d8a 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -25,16 +25,22 @@ proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
   if ctx.instLines: result.info = b.info
 
 proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
+  template handleParam(param) =
+    let x = param
+    if x.kind == nkArgList:
+      for y in items(x): result.add(y)
+    else:
+      result.add copyTree(x)
+
   case templ.kind
   of nkSym:
     var s = templ.sym
     if s.owner.id == c.owner.id:
-      if s.kind == skParam:
-        let x = actual.sons[s.position]
-        if x.kind == nkArgList:
-          for y in items(x): result.add(y)
-        else:
-          result.add copyTree(x)
+      case s.kind
+      of skParam:
+        handleParam actual.sons[s.position]
+      of skGenericParam:
+        handleParam actual.sons[s.owner.typ.len + s.position - 1]
       else:
         internalAssert sfGenSym in s.flags
         var x = PSym(idTableGet(c.mapping, s))
@@ -56,21 +62,31 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
 proc evalTemplateArgs(n: PNode, s: PSym): PNode =
   # if the template has zero arguments, it can be called without ``()``
   # `n` is then a nkSym or something similar
-  var a: int
-  case n.kind
-  of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
-    a = sonsLen(n)
-  else: a = 0
-  var f = s.typ.sonsLen
-  if a > f: globalError(n.info, errWrongNumberOfArguments)
+  var totalParams = case n.kind
+    of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: <n.len
+    else: 0
+
+  var
+    genericParams = s.ast[genericParamsPos].len
+    expectedRegularParams = <s.typ.len
+    givenRegularParams = totalParams - genericParams
+
+  if totalParams > expectedRegularParams + genericParams:
+    globalError(n.info, errWrongNumberOfArguments)
 
   result = newNodeI(nkArgList, n.info)
-  for i in countup(1, f - 1):
-    var arg = if i < a: n.sons[i] else: copyTree(s.typ.n.sons[i].sym.ast)
-    if arg == nil or arg.kind == nkEmpty:
+  for i in 1 .. givenRegularParams:
+    result.addSon n.sons[i]
+
+  for i in givenRegularParams+1 .. expectedRegularParams:
+    let default = s.typ.n.sons[i].sym.ast
+    if default.kind == nkEmpty:
       localError(n.info, errWrongNumberOfArguments)
-    addSon(result, arg)
+    result.addSon default.copyTree
 
+  for i in 1 .. genericParams:
+    result.addSon n.sons[givenRegularParams + i]
+  
 var evalTemplateCounter* = 0
   # to prevent endless recursion in templates instantiation
 
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index c838aa90b..a3423b1d5 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -601,15 +601,13 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
   if p.target == targetJS:
     app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
   if i < length and n.sons[i].kind == nkFinally:
-    gen(p, n.sons[i].sons[0], a)
-    moveInto(p, a, r)
+    genStmt(p, n.sons[i].sons[0])
   if p.target == targetJS:
     app(p.body, "}" & tnl)
   if p.target == targetLua:
     # we need to repeat the finally block for Lua ...
     if i < length and n.sons[i].kind == nkFinally:
-      gen(p, n.sons[i].sons[0], a)
-      moveInto(p, a, r)
+      genStmt(p, n.sons[i].sons[0])
 
 proc genRaiseStmt(p: PProc, n: PNode) =
   genLineDir(p, n)
diff --git a/compiler/nim.ini b/compiler/nim.ini
index 576b6d2bb..1f14eb21b 100644
--- a/compiler/nim.ini
+++ b/compiler/nim.ini
@@ -125,7 +125,7 @@ Files: "start.bat"
 BinPath: r"bin;dist\mingw\bin;dist"
 
 ;           Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
-Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|doc\overview.html"
+Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|overview.html"
 Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
 Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe"
 ; for now only NSIS supports optional downloads
diff --git a/compiler/nim.nimrod.cfg b/compiler/nim.nimrod.cfg
index ba7697c4c..f4d8b9dcb 100644
--- a/compiler/nim.nimrod.cfg
+++ b/compiler/nim.nimrod.cfg
@@ -1,7 +1,5 @@
 # Special configuration file for the Nim project
 
-# gc:markAndSweep
-
 hint[XDeclaredButNotUsed]:off
 path:"llvm"
 path:"$projectPath/.."
diff --git a/compiler/nimfix/nimfix.nim b/compiler/nimfix/nimfix.nim
index 7b42537c4..918f58e3d 100644
--- a/compiler/nimfix/nimfix.nim
+++ b/compiler/nimfix/nimfix.nim
@@ -26,12 +26,13 @@ Options:
   --styleCheck:on|off|auto         performs style checking for identifiers
                                    and suggests an alternative spelling; 
                                    'auto' corrects the spelling.
+  --bestEffort                     try to fix the code even when there
+                                   are errors.
 
 In addition, all command line options of Nim are supported.
 """
 
 proc mainCommand =
-  #msgs.gErrorMax = high(int)  # do not stop after first error
   registerPass verbosePass
   registerPass semPass
   gCmd = cmdPretty
@@ -63,13 +64,14 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
         of "on": gCheckExtern = true
         of "off": gCheckExtern = false
         else: localError(gCmdLineInfo, errOnOrOffExpected)
-      of "stylecheck": 
+      of "stylecheck":
         case p.val.normalize
         of "off": gStyleCheck = StyleCheck.None
         of "on": gStyleCheck = StyleCheck.Warn
         of "auto": gStyleCheck = StyleCheck.Auto
         else: localError(gCmdLineInfo, errOnOrOffExpected)
       of "wholeproject": gOnlyMainfile = false
+      of "besteffort": msgs.gErrorMax = high(int) # dont stop after first error
       else:
         processSwitch(pass, p)
     of cmdArgument:
diff --git a/compiler/parser.nim b/compiler/parser.nim
index a91760e15..fab3c453b 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -505,7 +505,7 @@ proc parsePar(p: var TParser): PNode =
   getTok(p)
   optInd(p, result)
   if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase, 
-                       tkTry, tkFinally, tkExcept, tkFor, tkBlock, 
+                       tkTry, tkDefer, tkFinally, tkExcept, tkFor, tkBlock, 
                        tkConst, tkLet, tkWhen, tkVar,
                        tkMixin}:
     # XXX 'bind' used to be an expression, so we exclude it here;
@@ -894,7 +894,8 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
   var a: PNode
   result = newNodeP(nkFormalParams, p)
   addSon(result, ast.emptyNode) # return type
-  if p.tok.tokType == tkParLe and p.tok.indent < 0:
+  let hasParLe = p.tok.tokType == tkParLe and p.tok.indent < 0
+  if hasParLe:
     getTok(p)
     optInd(p, result)
     while true:
@@ -918,6 +919,9 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
     getTok(p)
     optInd(p, result)
     result.sons[0] = parseTypeDesc(p)
+  elif not retColon and not hasParle:
+    # Mark as "not there" in order to mark for deprecation in the semantic pass:
+    result = ast.emptyNode
 
 proc optPragmas(p: var TParser): PNode =
   if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)):
@@ -1130,7 +1134,7 @@ proc parseMacroColon(p: var TParser, x: PNode): PNode =
     skipComment(p, result)
     if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept}:
       let body = parseStmt(p)
-      addSon(result, newProcNode(nkDo, body.info, body))
+      addSon(result, makeStmtList(body))
     while sameInd(p):
       var b: PNode
       case p.tok.tokType
@@ -1980,15 +1984,17 @@ proc parseTopLevelStmt(p: var TParser): PNode =
   ## top-level statement or emptyNode if end of stream.
   result = ast.emptyNode
   while true:
-    if p.tok.indent != 0: 
+    if p.tok.indent != 0:
       if p.firstTok and p.tok.indent < 0: discard
-      else: parMessage(p, errInvalidIndentation)
+      elif p.tok.tokType != tkSemiColon:
+        parMessage(p, errInvalidIndentation)
     p.firstTok = false
     case p.tok.tokType
     of tkSemiColon:
       getTok(p)
       if p.tok.indent <= 0: discard
       else: parMessage(p, errInvalidIndentation)
+      p.firstTok = true
     of tkEof: break
     else:
       result = complexOrSimpleStmt(p)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 5160af20a..9ac7ad139 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -41,7 +41,6 @@ proc addParams(c: PContext, n: PNode, kind: TSymKind)
 proc maybeAddResult(c: PContext, s: PSym, n: PNode)
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
 proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
-proc fixImmediateParams(n: PNode): PNode
 proc activate(c: PContext, n: PNode)
 proc semQuoteAst(c: PContext, n: PNode): PNode
 proc finishMethod(c: PContext, s: PSym)
@@ -68,12 +67,25 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
       # error correction:
       result = copyTree(arg)
       result.typ = formal
+    else:
+      let x = result.skipConv
+      if x.kind == nkPar and formal.kind != tyExpr:
+        changeType(x, formal, check=true)
 
 proc inferWithMetatype(c: PContext, formal: PType,
                        arg: PNode, coerceDistincts = false): PNode
 
 var commonTypeBegin = PType(kind: tyExpr)
 
+proc isEmptyContainer(t: PType): bool =
+  case t.kind
+  of tyExpr, tyNil: result = true
+  of tyArray, tyArrayConstr: result = t.sons[1].kind == tyEmpty
+  of tySet, tySequence, tyOpenArray, tyVarargs:
+    result = t.sons[0].kind == tyEmpty
+  of tyGenericInst: result = isEmptyContainer(t.lastSon)
+  else: result = false
+
 proc commonType*(x, y: PType): PType =
   # new type relation that is used for array constructors,
   # if expressions, etc.:
@@ -97,6 +109,13 @@ proc commonType*(x, y: PType): PType =
     # check for seq[empty] vs. seq[int]
     let idx = ord(b.kind in {tyArray, tyArrayConstr})
     if a.sons[idx].kind == tyEmpty: return y
+  elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len:
+    var nt: PType
+    for i in 0.. <a.len:
+      if isEmptyContainer(a.sons[i]) and not isEmptyContainer(b.sons[i]):
+        if nt.isNil: nt = copyType(a, a.owner, false)
+        nt.sons[i] = b.sons[i]
+    if not nt.isNil: result = nt
     #elif b.sons[idx].kind == tyEmpty: return x
   elif a.kind == tyRange and b.kind == tyRange:
     # consider:  (range[0..3], range[0..4]) here. We should make that
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 3971b8ff5..961c61c57 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -277,16 +277,27 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
   styleCheckUse(n.sons[0].info, finalCallee)
   if finalCallee.ast == nil:
     internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
-  if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
-    # a generic proc!
-    if not x.proxyMatch:
+  if x.hasFauxMatch:
+    result = x.call
+    result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
+    if containsGenericType(result.typ) or x.fauxMatch == tyUnknown:
+      result.typ = newTypeS(x.fauxMatch, c)
+    return
+  let gp = finalCallee.ast.sons[genericParamsPos]
+  if gp.kind != nkEmpty:
+    if x.calleeSym.kind notin {skMacro, skTemplate}:
       finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
     else:
-      result = x.call
-      result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
-      result.typ = finalCallee.typ.sons[0]
-      if containsGenericType(result.typ): result.typ = errorType(c)
-      return
+      # For macros and templates, the resolved generic params
+      # are added as normal params.
+      for s in instantiateGenericParamList(c, gp, x.bindings):
+        case s.kind
+          of skConst:
+            x.call.add s.ast
+          of skType:
+            x.call.add newSymNode(s, n.info)
+          else:
+            internalAssert false
   result = x.call
   instGenericConvertersSons(c, result, x)
   result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index f876770c0..623f9b633 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -268,7 +268,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
 
 template rangeHasStaticIf*(t: PType): bool =
   # this accepts the ranges's node
-  t.n[1].kind == nkStaticExpr
+  t.n != nil and t.n.len > 1 and t.n[1].kind == nkStaticExpr
 
 template getStaticTypeFromRange*(t: PType): PType =
   t.n[1][0][1].typ
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index fc217262e..68921a15a 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -219,7 +219,7 @@ proc maybeLiftType(t: var PType, c: PContext, info: TLineInfo) =
   # gnrc. params, then it won't be necessary to open a new scope here
   openScope(c)
   var lifted = liftParamType(c, skType, newNodeI(nkArgList, info),
-                         t, ":anon", info)
+                             t, ":anon", info)
   closeScope(c)
   if lifted != nil: t = lifted
 
@@ -229,7 +229,7 @@ proc semConv(c: PContext, n: PNode): PNode =
     return n
 
   result = newNodeI(nkConv, n.info)
-  var targetType = semTypeNode(c, n.sons[0], nil)
+  var targetType = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
   maybeLiftType(targetType, c, n[0].info)
   result.addSon copyTree(n.sons[0])
   var op = semExprWithType(c, n.sons[1])
@@ -429,7 +429,8 @@ proc changeType(n: PNode, newType: PType, check: bool) =
     for i in countup(0, sonsLen(n) - 1):
       changeType(n.sons[i], elemType(newType), check)
   of nkPar:
-    if newType.kind != tyTuple:
+    let tup = newType.skipTypes({tyGenericInst})
+    if tup.kind != tyTuple:
       internalError(n.info, "changeType: no tuple type for constructor")
     else:
       for i in countup(0, sonsLen(n) - 1):
@@ -437,7 +438,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
         if m.kind == nkExprColonExpr:
           m = m.sons[1]
           n.sons[i] = m
-        changeType(m, newType.sons[i], check)
+        changeType(m, tup.sons[i], check)
   of nkCharLit..nkUInt64Lit:
     if check:
       let value = n.intVal
@@ -779,7 +780,6 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
   elif t != nil and t.kind == tyTypeDesc:
     if n.len == 1: return semObjConstr(c, n, flags)
-    let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
     return semConv(c, n)
   else:
     result = overloadedCallOpr(c, n)
@@ -925,18 +925,19 @@ const
 proc readTypeParameter(c: PContext, typ: PType,
                        paramName: PIdent, info: TLineInfo): PNode =
   let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
-           else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1])
-  
+           else: (internalAssert(typ.kind == tyCompositeTypeClass);
+                  typ.sons[1].skipGenericAlias)
   let tbody = ty.sons[0]
   for s in countup(0, tbody.len-2):
     let tParam = tbody.sons[s]
-    if tParam.sym.name == paramName:
+    if tParam.sym.name.id == paramName.id:
       let rawTyp = ty.sons[s + 1]
       if rawTyp.kind == tyStatic:
         return rawTyp.n
       else:
         let foundTyp = makeTypeDesc(c, rawTyp)
         return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
+  #echo "came here: returned nil"
 
 proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if it's not a built-in field access
@@ -963,6 +964,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   var ty = n.sons[0].typ
   var f: PSym = nil
   result = nil
+
   if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
     if ty.kind == tyTypeDesc: ty = ty.base
     ty = ty.skipTypes(tyDotOpTransparent)
@@ -971,7 +973,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
       # look up if the identifier belongs to the enum:
       while ty != nil:
         f = getSymFromList(ty.n, i)
-        if f != nil: break 
+        if f != nil: break
         ty = ty.sons[0]         # enum inheritance
       if f != nil:
         result = newSymNode(f)
@@ -983,7 +985,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
     of tyTypeParamsHolders:
       return readTypeParameter(c, ty, i, n.info)
     of tyObject, tyTuple:
-      if ty.n.kind == nkRecList:
+      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])
@@ -1505,11 +1507,11 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
   
   doBlk.sons[namePos] = newAnonSym(skTemplate, n.info).newSymNode
   if ids.len > 0:
-    doBlk[paramsPos].sons.setLen(2)
-    doBlk[paramsPos].sons[0] = getSysSym("stmt").newSymNode # return type
+    doBlk.sons[paramsPos] = newNodeI(nkFormalParams, n.info)
+    doBlk[paramsPos].add getSysSym("stmt").newSymNode # return type
     ids.add getSysSym("expr").newSymNode # params type
     ids.add emptyNode # no default value
-    doBlk[paramsPos].sons[1] = newNode(nkIdentDefs, n.info, ids)
+    doBlk[paramsPos].add newNode(nkIdentDefs, n.info, ids)
   
   var tmpl = semTemplateDef(c, doBlk)
   quotes[0] = tmpl[namePos]
@@ -1892,19 +1894,6 @@ proc semBlock(c: PContext, n: PNode): PNode =
   closeScope(c)
   dec(c.p.nestedBlockCounter)
 
-proc doBlockIsStmtList(n: PNode): bool =
-  result = n.kind == nkDo and
-           n[paramsPos].sonsLen == 1 and
-           n[paramsPos][0].kind == nkEmpty
-
-proc fixImmediateParams(n: PNode): PNode =
-  # XXX: Temporary work-around until we carry out
-  # the planned overload resolution reforms
-  for i in 1 .. <safeLen(n):
-    if doBlockIsStmtList(n[i]):
-      n.sons[i] = n[i][bodyPos]
-  result = n
-
 proc semExport(c: PContext, n: PNode): PNode =
   var x = newNodeI(n.kind, n.info)
   #let L = if n.kind == nkExportExceptStmt: L = 1 else: n.len
@@ -2022,14 +2011,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
         if sfImmediate notin s.flags:
           result = semDirectOp(c, n, flags)
         else:
-          var p = fixImmediateParams(n)
-          result = semMacroExpr(c, p, p, s, flags)
+          result = semMacroExpr(c, n, n, s, flags)
       of skTemplate:
         if sfImmediate notin s.flags:
           result = semDirectOp(c, n, flags)
         else:
-          var p = fixImmediateParams(n)
-          result = semTemplateExpr(c, p, s, flags)
+          result = semTemplateExpr(c, n, s, flags)
       of skType:
         # XXX think about this more (``set`` procs)
         if n.len == 2:
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 723789a31..1ab4f5989 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -48,7 +48,6 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
   of skTemplate:
     if macroToExpand(s):
       styleCheckUse(n.info, s)
-      let n = fixImmediateParams(n)
       result = semTemplateExpr(c, n, s, {efNoSemCheck})
       result = semGenericStmt(c, result, {}, ctx)
     else:
@@ -61,13 +60,20 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
     else:
       result = symChoice(c, n, s, scOpen)
   of skGenericParam: 
-    result = newSymNodeTypeDesc(s, n.info)
+    if s.typ != nil and s.typ.kind == tyStatic:
+      if s.typ.n != nil:
+        result = s.typ.n
+      else:
+        result = n
+    else:
+      result = newSymNodeTypeDesc(s, n.info)
     styleCheckUse(n.info, s)
   of skParam:
     result = n
     styleCheckUse(n.info, s)
   of skType: 
-    if (s.typ != nil) and (s.typ.kind != tyGenericParam): 
+    if (s.typ != nil) and
+       (s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
       result = newSymNodeTypeDesc(s, n.info)
     else: 
       result = n
@@ -185,7 +191,6 @@ proc semGenericStmt(c: PContext, n: PNode,
       of skTemplate:
         if macroToExpand(s):
           styleCheckUse(fn.info, s)
-          let n = fixImmediateParams(n)
           result = semTemplateExpr(c, n, s, {efNoSemCheck})
           result = semGenericStmt(c, result, {}, ctx)
         else:
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 2decb5d0b..dd60e0881 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -10,18 +10,15 @@
 # This module implements the instantiation of generic procs.
 # included from sem.nim
 
-proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
-                                 entry: var TInstantiation) = 
-  if n.kind != nkGenericParams: 
-    internalError(n.info, "instantiateGenericParamList; no generic params")
-  newSeq(entry.concreteTypes, n.len)
+iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym =
+  internalAssert n.kind == nkGenericParams
   for i, a in n.pairs:
-    if a.kind != nkSym: 
-      internalError(a.info, "instantiateGenericParamList; no symbol")
+    internalAssert a.kind == nkSym
     var q = a.sym
     if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
       continue
-    var s = newSym(skType, q.name, getCurrOwner(), q.info)
+    let symKind = if q.typ.kind == tyStatic: skConst else: skType
+    var s = newSym(symKind, q.name, getCurrOwner(), q.info)
     s.flags = s.flags + {sfUsed, sfFromGeneric}
     var t = PType(idTableGet(pt, q.typ))
     if t == nil:
@@ -40,8 +37,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
       t = generateTypeInstance(c, pt, a, t)
       #t = ReplaceTypeVarsT(cl, t)
     s.typ = t
-    addDecl(c, s)
-    entry.concreteTypes[i] = t
+    if t.kind == tyStatic: s.ast = t.n
+    yield s
 
 proc sameInstantiation(a, b: TInstantiation): bool =
   if a.concreteTypes.len == b.concreteTypes.len:
@@ -194,7 +191,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   ## The `pt` parameter is a type-unsafe mapping table used to link generic
   ## parameters to their concrete types within the generic instance.
   # no need to instantiate generic templates/macros:
-  if fn.kind in {skTemplate, skMacro}: return fn
+  internalAssert fn.kind notin {skMacro, skTemplate}
   # generates an instantiated proc
   if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
   inc(c.instCounter)
@@ -211,12 +208,18 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   result.ast = n
   pushOwner(result)
   openScope(c)
-  internalAssert n.sons[genericParamsPos].kind != nkEmpty
+  let gp = n.sons[genericParamsPos]
+  internalAssert gp.kind != nkEmpty
   n.sons[namePos] = newSymNode(result)
   pushInfoContext(info)
   var entry = TInstantiation.new
   entry.sym = result
-  instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
+  newSeq(entry.concreteTypes, gp.len)
+  var i = 0
+  for s in instantiateGenericParamList(c, gp, pt):
+    addDecl(c, s)
+    entry.concreteTypes[i] = s.typ
+    inc i
   pushProcCon(c, result)
   instantiateProcType(c, pt, result, info)
   n.sons[genericParamsPos] = ast.emptyNode
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 646775aae..1396ef374 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -263,7 +263,8 @@ proc semTry(c: PContext, n: PNode): PNode =
   n.sons[0] = semExprBranchScope(c, n.sons[0])
   typ = commonType(typ, n.sons[0].typ)
   var check = initIntSet()
-  for i in countup(1, sonsLen(n) - 1): 
+  var last = sonsLen(n) - 1
+  for i in countup(1, last):
     var a = n.sons[i]
     checkMinSonsLen(a, 1)
     var length = sonsLen(a)
@@ -282,11 +283,12 @@ proc semTry(c: PContext, n: PNode): PNode =
         a.sons[j].typ = typ
         if containsOrIncl(check, typ.id):
           localError(a.sons[j].info, errExceptionAlreadyHandled)
-    elif a.kind != nkFinally: 
+    elif a.kind != nkFinally:
       illFormedAst(n)
     # last child of an nkExcept/nkFinally branch is a statement:
     a.sons[length-1] = semExprBranchScope(c, a.sons[length-1])
-    typ = commonType(typ, a.sons[length-1].typ)
+    if a.kind != nkFinally: typ = commonType(typ, a.sons[length-1].typ)
+    else: dec last
   dec c.p.inTryStmt
   if isEmptyType(typ) or typ.kind == tyNil:
     discardCheck(c, n.sons[0])
@@ -294,13 +296,14 @@ proc semTry(c: PContext, n: PNode): PNode =
     if typ == enforceVoidContext:
       result.typ = enforceVoidContext
   else:
+    if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon)
     n.sons[0] = fitNode(c, typ, n.sons[0])
-    for i in 1..n.len-1:
+    for i in 1..last:
       var it = n.sons[i]
       let j = it.len-1
       it.sons[j] = fitNode(c, typ, it.sons[j])
     result.typ = typ
-  
+
 proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode = 
   result = fitNode(c, typ, n)
   if result.kind in {nkHiddenStdConv, nkHiddenSubConv}: 
@@ -650,7 +653,8 @@ proc checkForMetaFields(n: PNode) =
   template checkMeta(t) =
     if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
       localError(n.info, errTIsNotAConcreteType, t.typeToString)
-  
+
+  if n.isNil: return
   case n.kind
   of nkRecList, nkRecCase:
     for s in n: checkForMetaFields(s)
@@ -773,7 +777,7 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
     if it.kind == nkExprColonExpr:
       # pass pragma argument to the macro too:
       x.add(it.sons[1])
-    x.add(newProcNode(nkDo, prc.info, prc))
+    x.add(prc)
     # recursion assures that this works for multiple macro annotations too:
     return semStmt(c, x)
 
@@ -801,6 +805,9 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
     gp = newNodeI(nkGenericParams, n.info)
 
   if n.sons[paramsPos].kind != nkEmpty:
+    #if n.kind == nkDo and not experimentalMode(c):
+    #  localError(n.sons[paramsPos].info,
+    #      "use the {.experimental.} pragma to enable 'do' with parameters")
     semParamList(c, n.sons[paramsPos], gp, s)
     # paramsTypeCheck(c, s.typ)
     if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
@@ -1251,13 +1258,18 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
       tryStmt.addSon(deferPart)
       n.sons[i] = semTry(c, tryStmt)
       n.sons.setLen(i+1)
+      n.typ = n.sons[i].typ
       return
     else:
       n.sons[i] = semExpr(c, n.sons[i])
-      if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool:
-        let verdict = semConstExpr(c, n[i])
-        if verdict.intVal == 0:
-          localError(result.info, "type class predicate failed")
+      if c.inTypeClass > 0 and n[i].typ != nil:
+        case n[i].typ.kind
+        of tyBool:
+          let verdict = semConstExpr(c, n[i])
+          if verdict.intVal == 0:
+            localError(result.info, "type class predicate failed")
+        of tyUnknown: continue
+        else: discard
       if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
         voidContext = true
         n.typ = enforceVoidContext
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 4305a48e1..deb4b1288 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -214,44 +214,47 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
     localError(n.info, errXExpectsOneTypeParam, "range")
     result = newOrPrevType(tyError, prev, c)
 
+proc semArrayIndex(c: PContext, n: PNode): PType =
+  if isRange(n): result = semRangeAux(c, n, nil)
+  else:
+    let e = semExprWithType(c, n, {efDetermineType})
+    if e.typ.kind == tyFromExpr:
+      result = makeRangeWithStaticExpr(c, e.typ.n)
+    elif e.kind in {nkIntLit..nkUInt64Lit}:
+      result = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
+    elif e.kind == nkSym and e.typ.kind == tyStatic:
+      if e.sym.ast != nil:
+        return semArrayIndex(c, e.sym.ast)
+      if not isOrdinalType(e.typ.lastSon):
+        localError(n[1].info, errOrdinalTypeExpected)
+      result = makeRangeWithStaticExpr(c, e)
+      if c.inGenericContext >0: result.flags.incl tfUnresolved
+    elif e.kind in nkCallKinds and hasGenericArguments(e):
+      if not isOrdinalType(e.typ):
+        localError(n[1].info, errOrdinalTypeExpected)
+      # This is an int returning call, depending on an
+      # yet unknown generic param (see tgenericshardcases).
+      # We are going to construct a range type that will be
+      # properly filled-out in semtypinst (see how tyStaticExpr
+      # is handled there).
+      result = makeRangeWithStaticExpr(c, e)
+    elif e.kind == nkIdent:
+      result = e.typ.skipTypes({tyTypeDesc})
+    else:
+      let x = semConstExpr(c, e)
+      if x.kind in {nkIntLit..nkUInt64Lit}:
+        result = makeRangeType(c, 0, x.intVal-1, n.info, 
+                             x.typ.skipTypes({tyTypeDesc}))
+      else:
+        result = x.typ.skipTypes({tyTypeDesc})
+        #localError(n[1].info, errConstExprExpected)
+
 proc semArray(c: PContext, n: PNode, prev: PType): PType = 
-  var indx, base: PType
+  var base: PType
   result = newOrPrevType(tyArray, prev, c)
-  if sonsLen(n) == 3: 
+  if sonsLen(n) == 3:
     # 3 = length(array indx base)
-    if isRange(n[1]): indx = semRangeAux(c, n[1], nil)
-    else:
-      let e = semExprWithType(c, n.sons[1], {efDetermineType})
-      if e.typ.kind == tyFromExpr:
-        indx = makeRangeWithStaticExpr(c, e.typ.n)
-      elif e.kind in {nkIntLit..nkUInt64Lit}:
-        indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
-      elif e.kind == nkSym and e.typ.kind == tyStatic:
-        if e.sym.ast != nil: return semArray(c, e.sym.ast, nil)
-        internalAssert c.inGenericContext > 0
-        if not isOrdinalType(e.typ.lastSon):
-          localError(n[1].info, errOrdinalTypeExpected)
-        indx = makeRangeWithStaticExpr(c, e)
-        indx.flags.incl tfUnresolved
-      elif e.kind in nkCallKinds and hasGenericArguments(e):
-        if not isOrdinalType(e.typ):
-          localError(n[1].info, errOrdinalTypeExpected)
-        # This is an int returning call, depending on an
-        # yet unknown generic param (see tgenericshardcases).
-        # We are going to construct a range type that will be
-        # properly filled-out in semtypinst (see how tyStaticExpr
-        # is handled there).
-        indx = makeRangeWithStaticExpr(c, e)
-      elif e.kind == nkIdent:
-        indx = e.typ.skipTypes({tyTypeDesc})
-      else:
-        let x = semConstExpr(c, e)
-        if x.kind in {nkIntLit..nkUInt64Lit}:
-          indx = makeRangeType(c, 0, x.intVal-1, n.info, 
-                               x.typ.skipTypes({tyTypeDesc}))
-        else:
-          indx = x.typ.skipTypes({tyTypeDesc})
-          #localError(n[1].info, errConstExprExpected)
+    var indx = semArrayIndex(c, n[1])
     addSonSkipIntLit(result, indx)
     if indx.kind == tyGenericInst: indx = lastSon(indx)
     if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}:
@@ -778,10 +781,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   of tyGenericBody:
     result = newTypeS(tyGenericInvokation, c)
     result.rawAddSon(paramType)
+      
     for i in 0 .. paramType.sonsLen - 2:
-      result.rawAddSon newTypeS(tyAnything, c)
-      # result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
-
+      let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown
+                      else: tyAnything
+      result.rawAddSon newTypeS(dummyType, c)
+      
     if paramType.lastSon.kind == tyUserTypeClass:
       result.kind = tyUserTypeClassInst
       result.rawAddSon paramType.lastSon
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index ba493bdfa..721f7e318 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -39,7 +39,9 @@ type
     bindings*: TIdTable      # maps types to types
     baseTypeMatch: bool      # needed for conversions from T to openarray[T]
                              # for example
-    proxyMatch*: bool        # to prevent instantiations
+    fauxMatch*: TTypeKind    # the match was successful only due to the use
+                             # of error or wildcard (unknown) types.
+                             # this is used to prevent instantiations.
     genericConverter*: bool  # true if a generic converter needs to
                              # be instantiated
     coerceDistincts*: bool   # this is an explicit coercion that can strip away
@@ -66,6 +68,8 @@ const
     
 proc markUsed*(info: TLineInfo, s: PSym)
 
+template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
+
 proc initCandidateAux(ctx: PContext,
                       c: var TCandidate, callee: PType) {.inline.} =
   c.c = ctx
@@ -109,9 +113,12 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
     for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
       var formalTypeParam = typeParams.sons[i-1].typ
       var bound = binding[i].typ
-      if bound != nil and formalTypeParam.kind != tyTypeDesc:
+      internalAssert bound != nil
+      if formalTypeParam.kind == tyTypeDesc:
+        if bound.kind != tyTypeDesc:
+          bound = makeTypeDesc(ctx, bound)
+      else:
         bound = bound.skipTypes({tyTypeDesc})
-      assert bound != nil
       put(c.bindings, formalTypeParam, bound)
 
 proc newCandidate*(ctx: PContext, callee: PSym,
@@ -462,9 +469,23 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
       var
         typeParamName = ff.base.sons[i-1].sym.name
         typ = ff.sons[i]
-        param = newSym(skType, typeParamName, body.sym, body.sym.info)
-        
-      param.typ = makeTypeDesc(c, typ)
+        param: PSym
+
+      template paramSym(kind): expr =
+        newSym(kind, typeParamName, body.sym, body.sym.info)
+
+      case typ.kind
+      of tyStatic:
+        param = paramSym skConst
+        param.typ = typ.base
+        param.ast = typ.n
+      of tyUnknown:
+        param = paramSym skVar
+        param.typ = typ
+      else:
+        param = paramSym skType
+        param.typ = makeTypeDesc(c, typ)
+      
       addDecl(c, param)
 
   for param in body.n[0]:
@@ -517,6 +538,16 @@ proc maybeSkipDistinct(t: PType, callee: PSym): PType =
   else:
     result = t
 
+proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode =
+  # Consider this example:
+  #   type Value[N: static[int]] = object
+  #   proc foo[N](a: Value[N], r: range[0..(N-1)])
+  # Here, N-1 will be initially nkStaticExpr that can be evaluated only after
+  # N is bound to a concrete value during the matching of the first param.
+  # This proc is used to evaluate such static expressions.
+  let instantiated = replaceTypesInBody(c.c, c.bindings, n)
+  result = c.c.semExpr(c.c, instantiated)
+
 proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # typeRel can be used to establish various relationships between types:
   #
@@ -616,10 +647,16 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
   of tyRange:
     if a.kind == f.kind:
+      if f.base.kind == tyNone: return isGeneric
       result = typeRel(c, base(f), base(a))
       # bugfix: accept integer conversions here
       #if result < isGeneric: result = isNone
       if result notin {isNone, isGeneric}:
+        # resolve any late-bound static expressions
+        # that may appear in the range:
+        for i in 0..1:
+          if f.n[i].kind == nkStaticExpr:
+            f.n.sons[i] = tryResolvingStaticExpr(c, f.n[i])
         result = typeRangeRel(f, a)
     else:
       if skipTypes(f, {tyRange}).kind == a.kind:
@@ -657,22 +694,27 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         else:
           fRange = prev
       result = typeRel(c, f.sons[1], a.sons[1])
-      if result < isGeneric:
-        result = isNone
-      elif tfUnresolved in fRange.flags and
-           rangeHasStaticIf(fRange):
-        # This is a range from an array instantiated with a generic
-        # static param. We must extract the static param here and bind
-        # it to the size of the currently supplied array.
-        var
-          rangeStaticT = fRange.getStaticTypeFromRange
-          replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType])
-          inputUpperBound = a.sons[0].n[1].intVal
-        # we must correct for the off-by-one discrepancy between
-        # ranges and static params:
-        replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
-        put(c.bindings, rangeStaticT, replacementT)
-        result = isGeneric
+      if result < isGeneric: return isNone
+      if rangeHasStaticIf(fRange):
+        if tfUnresolved in fRange.flags:
+          # This is a range from an array instantiated with a generic
+          # static param. We must extract the static param here and bind
+          # it to the size of the currently supplied array.
+          var
+            rangeStaticT = fRange.getStaticTypeFromRange
+            replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType])
+            inputUpperBound = a.sons[0].n[1].intVal
+          # we must correct for the off-by-one discrepancy between
+          # ranges and static params:
+          replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
+          put(c.bindings, rangeStaticT, replacementT)
+          return isGeneric
+
+        let len = tryResolvingStaticExpr(c, fRange.n[1])
+        if len.kind == nkIntLit and len.intVal+1 == lengthOrd(a):
+          return # if we get this far, the result is already good
+        else:
+          return isNone
       elif lengthOrd(fRange) != lengthOrd(a):
         result = isNone
     else: discard
@@ -930,7 +972,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
           else:
             internalAssert a.sons != nil and a.sons.len > 0
             c.typedescMatched = true
-            result = typeRel(c, f.base, a.base)
+            result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc}))
         else:
           result = isNone
       else:
@@ -962,12 +1004,19 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       result = typeRel(c, x, a) # check if it fits
   
   of tyStatic:
-    if aOrig.kind == tyStatic:
-      result = typeRel(c, f.lastSon, a)
-      if result != isNone: put(c.bindings, f, aOrig)
+    let prev = PType(idTableGet(c.bindings, f))
+    if prev == nil:
+      if aOrig.kind == tyStatic:
+        result = typeRel(c, f.lastSon, a)
+        if result != isNone and f.n != nil:
+          if not exprStructuralEquivalent(f.n, aOrig.n):
+            result = isNone
+        if result != isNone: put(c.bindings, f, aOrig)
+      else:
+        result = isNone
     else:
-      result = isNone
-
+      result = typeRel(c, prev, aOrig)
+      
   of tyTypeDesc:
     var prev = PType(idTableGet(c.bindings, f))
     if prev == nil:
@@ -1006,15 +1055,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   of tyFromExpr:
     # fix the expression, so it contains the already instantiated types
-    let instantiated = replaceTypesInBody(c.c, c.bindings, f.n)
-    let reevaluted = c.c.semExpr(c.c, instantiated)
-    case reevaluted.typ.kind
+    if f.n == nil: return isGeneric
+    let reevaluated = tryResolvingStaticExpr(c, f.n)
+    case reevaluated.typ.kind
     of tyTypeDesc:
-      result = typeRel(c, a, reevaluted.typ.base)
+      result = typeRel(c, a, reevaluated.typ.base)
     of tyStatic:
-      result = typeRel(c, a, reevaluted.typ.base)
-      if result != isNone and reevaluted.typ.n != nil:
-        if not exprStructuralEquivalent(aOrig.n, reevaluted.typ.n):
+      result = typeRel(c, a, reevaluated.typ.base)
+      if result != isNone and reevaluated.typ.n != nil:
+        if not exprStructuralEquivalent(aOrig.n, reevaluated.typ.n):
           result = isNone
     else:
       localError(f.n.info, errTypeExpected)
@@ -1028,10 +1077,10 @@ proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
   initCandidate(c, m, f)
   result = typeRel(m, f, a)
 
-proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, 
-                         f: PType): PType = 
+proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
+                         f: PType): PType =
   result = PType(idTableGet(m.bindings, f))
-  if result == nil: 
+  if result == nil:
     result = generateTypeInstance(c, m.bindings, arg, f)
   if result == nil:
     internalError(arg.info, "getInstantiatedType")
@@ -1041,7 +1090,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
                   c: PContext): PNode = 
   result = newNodeI(kind, arg.info)
   if containsGenericType(f):
-    if not m.proxyMatch:
+    if not m.hasFauxMatch:
       result.typ = getInstantiatedType(c, arg, m, f)
     else:
       result.typ = errorType(c)
@@ -1083,6 +1132,11 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
                     arg: PNode): PNode = 
   # arg.typ can be nil in 'suggest':
   if isNil(arg.typ): return nil
+
+  # sem'checking for 'echo' needs to be re-entrant:
+  # XXX we will revisit this issue after 0.10.2 is released
+  if f == arg.typ and arg.kind == nkHiddenStdConv: return arg
+
   var call = newNodeI(nkCall, arg.info)
   call.add(f.n.copyTree)
   call.add(arg.copyTree)
@@ -1108,7 +1162,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     arg = argSemantized
     argType = argType
     c = m.c
- 
+  
   if tfHasStatic in fMaybeStatic.flags:
     # XXX: When implicit statics are the default
     # this will be done earlier - we just have to
@@ -1122,7 +1176,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
       return argSemantized
 
     if argType.kind == tyStatic:
-      if m.callee.kind == tyGenericBody:
+      if m.callee.kind == tyGenericBody and tfGenericTypeParam notin argType.flags:
         result = newNodeI(nkType, argOrig.info)
         result.typ = makeTypeFromExpr(c, arg)
         return
@@ -1153,8 +1207,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     of isEqual: inc(m.exactMatches)
     of isNone: discard
 
-    if f.kind == tyStmt and argOrig.kind == nkDo:
-      return argOrig[bodyPos]
+    if f.kind == tyStmt:
+      return arg
     elif f.kind == tyTypeDesc:
       return arg
     elif f.kind == tyStatic:
@@ -1215,9 +1269,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
       result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
   of isNone:
     # do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
-    if a.kind == tyProxy:
+    if a.kind in {tyProxy, tyUnknown}:
       inc(m.genericMatches)
-      m.proxyMatch = true
+      m.fauxMatch = a.kind
       return copyTree(arg)
     result = userConvMatch(c, m, f, a, arg) 
     # check for a base type match, which supports varargs[T] without []
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index c700db323..f7b00c8f8 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -74,9 +74,6 @@ proc suggestField(c: PContext, s: PSym, outputs: var int) =
     suggestWriteln(symToStr(s, isLocal=true, sectionSuggest))
     inc outputs
 
-when not defined(nimhygiene):
-  {.pragma: inject.}
-
 template wholeSymTab(cond, section: expr) {.immediate.} =
   var isLocal = true
   for scope in walkScopes(c.currentScope):
diff --git a/compiler/types.nim b/compiler/types.nim
index f67cd239e..4a77773e6 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -17,7 +17,7 @@ proc lastOrd*(t: PType): BiggestInt
 proc lengthOrd*(t: PType): BiggestInt
 type 
   TPreferedDesc* = enum
-    preferName, preferDesc, preferExported, preferModuleInfo
+    preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
 
 proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
 proc base*(t: PType): PType
@@ -411,11 +411,13 @@ const
     "UserTypeClassInst", "CompositeTypeClass",
     "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"]
 
+const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
+
 proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
   var t = typ
   result = ""
   if t == nil: return 
-  if prefer in {preferName, preferModuleInfo} and t.sym != nil and
+  if prefer in preferToResolveSymbols and t.sym != nil and
        sfAnon notin t.sym.flags:
     if t.kind == tyInt and isIntLit(t):
       return t.sym.name.s & " literal(" & $t.n.intVal & ")"
@@ -428,20 +430,26 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     if not isIntLit(t) or prefer == preferExported:
       result = typeToStr[t.kind]
     else:
-      result = "int literal(" & $t.n.intVal & ")"
+      if prefer == preferGenericArg:
+        result = $t.n.intVal
+      else:
+        result = "int literal(" & $t.n.intVal & ")"
   of tyGenericBody, tyGenericInst, tyGenericInvokation:
     result = typeToString(t.sons[0]) & '['
     for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)):
       if i > 1: add(result, ", ")
-      add(result, typeToString(t.sons[i]))
+      add(result, typeToString(t.sons[i], preferGenericArg))
     add(result, ']')
   of tyTypeDesc:
     if t.base.kind == tyNone: result = "typedesc"
     else: result = "typedesc[" & typeToString(t.base) & "]"
   of tyStatic:
     internalAssert t.len > 0
-    result = "static[" & typeToString(t.sons[0]) & "]"
-    if t.n != nil: result.add "(" & renderTree(t.n) & ")"
+    if prefer == preferGenericArg and t.n != nil:
+      result = t.n.renderTree
+    else:
+      result = "static[" & typeToString(t.sons[0]) & "]"
+      if t.n != nil: result.add "(" & renderTree(t.n) & ")"
   of tyUserTypeClass:
     internalAssert t.sym != nil and t.sym.owner != nil
     return t.sym.owner.name.s
diff --git a/compiler/vm.nim b/compiler/vm.nim
index ad0d3b0a1..4072ed765 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1417,12 +1417,20 @@ proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) =
 proc setupCompileTimeVar*(module: PSym, n: PNode) =
   discard evalConstExprAux(module, nil, n, emStaticStmt)
 
-proc setupMacroParam(x: PNode): PNode =
-  result = x
-  if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
-  result = canonValue(result)
-  result.flags.incl nfIsRef
-  result.typ = x.typ
+proc setupMacroParam(x: PNode, typ: PType): TFullReg =
+  case typ.kind
+  of tyStatic:
+    putIntoReg(result, x)
+  of tyTypeDesc:
+    putIntoReg(result, x)
+  else:
+    result.kind = rkNode
+    var n = x
+    if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n.sons[1]
+    n = n.canonValue
+    n.flags.incl nfIsRef
+    n.typ = x.typ
+    result.node = n
 
 var evalMacroCounter: int
 
@@ -1442,6 +1450,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
 
   c.callsite = nOrig
   let start = genProc(c, sym)
+  # c.echoCode start
 
   var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
   let maxSlots = sym.offset
@@ -1457,9 +1466,14 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   tos.slots[0].kind = rkNode
   tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
   # setup parameters:
-  for i in 1 .. < min(tos.slots.len, L):
-    tos.slots[i].kind = rkNode
-    tos.slots[i].node = setupMacroParam(n.sons[i])
+  for i in 1.. <sym.typ.len:
+    tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i])
+
+  let gp = sym.ast[genericParamsPos]
+  for i in 0 .. <gp.len:
+    let idx = sym.typ.len + i
+    tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ)
+
   # temporary storage:
   #for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos).regToNode
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index c06606318..3d49cb130 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -164,7 +164,8 @@ type
     slotTempInt,      # some temporary int
     slotTempFloat,    # some temporary float
     slotTempStr,      # some temporary string
-    slotTempComplex   # some complex temporary (s.node field is used)
+    slotTempComplex,  # some complex temporary (s.node field is used)
+    slotTempPerm      # slot is temporary but permanent (hack)
 
   PProc* = ref object
     blocks*: seq[TBlock]    # blocks; temp data structure
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 7397a562c..8444af7ba 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -16,7 +16,7 @@
 #   types that use the 'node' field; the reason is that slots are
 #   re-used in a register based VM. Example:
 # 
-# .. code-block:: nimrod
+# .. code-block:: nim
 #   let s = a & b  # no matter what, create fresh node
 #   s = a & b  # no matter what, keep the node
 #
@@ -28,7 +28,7 @@
 # this copy depends on the involved types.
 
 import
-  unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef, 
+  unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef,
   trees, intsets, rodread, magicsys, options, lowerings
 
 from os import splitFile
@@ -58,6 +58,7 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
     if i in jumpTargets: result.addf("L$1:\n", i)
     let x = c.code[i]
 
+    result.add($i)
     let opc = opcode(x)
     if opc in {opcConv, opcCast}:
       let y = c.code[i+1]
@@ -163,7 +164,8 @@ proc getSlotKind(t: PType): TSlotKind =
 const
   HighRegisterPressure = 40
 
-proc getTemp(c: PCtx; typ: PType): TRegister =
+proc getTemp(c: PCtx; tt: PType): TRegister =
+  let typ = tt.safeSkipTypes({tyStatic})
   let c = c.prc
   # we prefer the same slot kind here for efficiency. Unfortunately for
   # discardable return types we may not know the desired type. This can happen
@@ -188,7 +190,7 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
 
 proc freeTemp(c: PCtx; r: TRegister) =
   let c = c.prc
-  if c.slots[r].kind >= slotSomeTemp: c.slots[r].inUse = false
+  if c.slots[r].kind in {slotSomeTemp..slotTempComplex}: c.slots[r].inUse = false
 
 proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister =
   # if register pressure is high, we re-use more aggressively:
@@ -463,7 +465,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
   # from the stack
   c.gABx(fin, opcFinally, 0, 0)
   if fin.kind == nkFinally:
-    c.gen(fin.sons[0], dest)
+    c.gen(fin.sons[0])
     c.clearDest(n, dest)
   c.gABx(fin, opcFinallyEnd, 0, 0)
 
@@ -684,7 +686,7 @@ proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABC(n, opc, dest, tmp)
   c.gABx(n, opc, 0, genType(c, n.typ))
-  c.gABx(n, opc, 0, genType(c, arg.typ))
+  c.gABx(n, opc, 0, genType(c, arg.typ.skipTypes({tyStatic})))
   c.freeTemp(tmp)
 
 proc genCard(c: PCtx; n: PNode; dest: var TDest) =
@@ -1074,15 +1076,18 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
         c.gABC(n, opcNodeToReg, dest, dest)
     elif c.prc.slots[tmp].kind >= slotTempUnknown:
       gABC(c, n, opcAddrNode, dest, tmp)
-      # XXX this can still be wrong sometimes; hopefully it's only generated
-      # in call contexts, where it is safe
+      # hack ahead; in order to fix bug #1781 we mark the temporary as
+      # permanent, so that it's not used for anything else:
+      c.prc.slots[tmp].kind = slotTempPerm
+      # XXX this is still a hack
       #message(n.info, warnUser, "suspicious opcode used")
     else:
       gABC(c, n, opcAddrReg, dest, tmp)
     c.freeTemp(tmp)
 
 proc whichAsgnOpc(n: PNode): TOpcode =
-  case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
+  let toSkip = abstractRange-{tyTypeDesc}
+  case n.typ.skipTypes(toSkip).kind
   of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
     opcAsgnInt
   of tyString, tyCString:
@@ -1556,6 +1561,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
         c.gABx(n, opcLdConst, dest, lit)
     of skType:
       genTypeLit(c, s.typ, dest)
+    of skGenericParam:
+      if c.prc.sym.kind == skMacro:
+        genRdVar(c, n, dest, flags)
+      else:
+        internalError(n.info, "cannot generate code for: " & s.name.s)
     else:
       internalError(n.info, "cannot generate code for: " & s.name.s)
   of nkCallKinds:
@@ -1687,6 +1697,14 @@ proc genParams(c: PCtx; params: PNode) =
     c.prc.slots[i] = (inUse: true, kind: slotFixedLet)
   c.prc.maxSlots = max(params.len, 1)
 
+proc genGenericParams(c: PCtx; gp: PNode) =
+  var base = c.prc.maxSlots
+  for i in 0.. <gp.len:
+    var param = gp.sons[i].sym
+    param.position = base + i # XXX: fix this earlier; make it consistent with templates
+    c.prc.slots[base + i] = (inUse: true, kind: slotFixedLet)
+  c.prc.maxSlots = base + gp.len
+
 proc finalJumpTarget(c: PCtx; pc, diff: int) =
   internalAssert(-0x7fff < diff and diff < 0x7fff)
   let oldInstr = c.code[pc]
@@ -1758,6 +1776,8 @@ proc genProc(c: PCtx; s: PSym): int =
     c.prc = p
     # iterate over the parameters and allocate space for them:
     genParams(c, s.typ.n)
+    if s.kind == skMacro and s.ast[genericParamsPos].kind != nkEmpty:
+      genGenericParams(c, s.ast[genericParamsPos])
     if tfCapturesEnv in s.typ.flags:
       #let env = s.ast.sons[paramsPos].lastSon.sym
       #assert env.position == 2
diff --git a/copying.txt b/copying.txt
index 254b91c77..908625e18 100644
--- a/copying.txt
+++ b/copying.txt
@@ -1,5 +1,5 @@
 =====================================================
-Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/
+Nim -- a Compiler for Nim. http://nim-lang.org/
 
 Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved.
  
diff --git a/doc/backends.txt b/doc/backends.txt
index eb16217cd..ffe2d5e88 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -456,11 +456,7 @@ can then attach a GC to this thread via
 
 .. code-block:: nim
 
-  setStackBottom(addr(someLocal))
-  initGC()
-
-At the moment this support is still experimental so you need to expose these
-functions yourself or submit patches to request a public API. 
+  system.setupForeignThreadGc()
 
 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
diff --git a/doc/basicopt.txt b/doc/basicopt.txt
index ffb374f18..e366b2718 100644
--- a/doc/basicopt.txt
+++ b/doc/basicopt.txt
@@ -37,4 +37,4 @@ Options:
   --advanced                show advanced command line switches
   -h, --help                show this help
 
-Note: Even single letter options require the colon: -p:PATH.
+Note, single letter options that take an argument require a colon. E.g. -p:PATH.
diff --git a/doc/idetools.txt b/doc/idetools.txt
index 5429d0c07..e04f530f4 100644
--- a/doc/idetools.txt
+++ b/doc/idetools.txt
@@ -145,7 +145,7 @@ The ``--usages`` idetools switch lists all usages of the symbol at
 a position. IDEs can use this to find all the places in the file
 where the symbol is used and offer the user to rename it in all
 places at the same time. Again, a pure string based search and
-replace may catch symbols out of the scope of a funcion/loop.
+replace may catch symbols out of the scope of a function/loop.
 
 For this kind of query the IDE will most likely ignore all the
 type/signature info provided by idetools and concentrate on the
diff --git a/doc/lib.txt b/doc/lib.txt
index aba05c2ba..45d9dfd2a 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -18,7 +18,7 @@ low-level interface to a C library.
 
 Read this `document <apis.html>`_ for a quick overview of the API design.
 
-The `bottom <#babel>`_ of this page includes a list of 3rd party packages
+The `bottom <#nimble>`_ of this page includes a list of 3rd party packages
 created by the Nim community. These packages are a useful addition to the
 modules in the standard library.
 
@@ -154,8 +154,8 @@ Generic Operating System Services
 
 * `streams <streams.html>`_
   This module provides a stream interface and two implementations thereof:
-  the `PFileStream` and the `PStringStream` which implement the stream
-  interface for Nim file objects (`TFile`) and strings. Other modules
+  the `FileStream` and the `StringStream` which implement the stream
+  interface for Nim file objects (`File`) and strings. Other modules
   may provide other implementations for this standard stream interface.
 
 * `marshal <marshal.html>`_
@@ -581,12 +581,12 @@ Scientific computing
 * `libsvm <libsvm.html>`_ 
   Low level wrapper for `lib svm <http://www.csie.ntu.edu.tw/~cjlin/libsvm/>`_.
 
-Babel
+Nimble
 ====================
 
-Babel is a package manager for the Nim programming language.
-For instructions on how to install Babel packages see
-`its README <https://github.com/nim-code/babel#readme>`_.
+Nimble is a package manager for the Nim programming language.
+For instructions on how to install Nimble packages see
+`its README <https://github.com/nim-lang/babel#readme>`_.
 
 Official packages
 -----------------
@@ -598,7 +598,7 @@ compiler.
 .. raw:: html
 
   <div id="officialPkgList"><b>If you are reading this you are missing
-  babelpkglist.js or have javascript disabled in your browser.</b></div>
+  nimblepkglist.js or have javascript disabled in your browser.</b></div>
 
 Unofficial packages
 -------------------
@@ -610,7 +610,7 @@ Nim programming language.
 .. raw:: html
 
   <div id="unofficialPkgList"><b>If you are reading this you are missing
-  babelpkglist.js or have javascript disabled in your browser.</b></div>
+  nimblepkglist.js or have javascript disabled in your browser.</b></div>
 
-  <script type="text/javascript" src="babelpkglist.js"></script>
-  <script type="text/javascript" src="http://build.nim-lang.org/packages?callback=gotPackageList"></script>
+  <script type="text/javascript" src="nimblepkglist.js"></script>
+  <script type="text/javascript" src="http://irclogs.nim-lang.org/packages?callback=gotPackageList"></script>
diff --git a/doc/manual/exceptions.txt b/doc/manual/exceptions.txt
index 7cad1c2b4..e40742e0a 100644
--- a/doc/manual/exceptions.txt
+++ b/doc/manual/exceptions.txt
@@ -47,36 +47,52 @@ the rest of the procedure - that is not within a ``finally`` clause -
 is not executed (if an exception occurs).
 
 
-Standalone except and finally statements
-----------------------------------------
+Try expression
+--------------
 
-``except`` and ``finally`` can also be used as a stand-alone statements.
-Any statements following them in the current block will be considered to be 
-in an implicit try block:
+Try can also be used as an expression; the type of the ``try`` branch then
+needs to fit the types of ``except`` branches, but the type of the ``finally``
+branch always has to be ``void``:
+
+.. code-block:: nim
+  let x = try: parseInt("133a")
+          except: -1
+          finally: echo "hi"
+
+
+To prevent confusing code there is a parsing limitation; if the ``try``
+follows a ``(`` it has to be written as a one liner:
+
+.. code-block:: nim
+  let x = (try: parseInt("133a") except: -1)
+
+
+
+Defer statement
+---------------
+
+Instead of a ``try finally`` statement a ``defer`` statement can be used.
+
+Any statements following the ``defer`` in the current block will be considered
+to be in an implicit try block:
 
 .. code-block:: nim
   var f = open("numbers.txt")
-  finally: close(f)
-  ...
+  defer: close(f)
+  f.write "abc"
+  f.write "def"
 
-The ``except`` statement has a limitation in this form: one can't specify the
-type of the exception, one has to catch everything. Also, if one wants to use
-both ``finally`` and ``except`` one needs to reverse the usual sequence of the
-statements. Example:
+Is rewritten to:
 
 .. code-block:: nim
-  proc test() =
-    raise newException(Exception, "Hey ho")
-  
-  proc tester() =
-    finally: echo "3. Finally block"
-    except: echo "2. Except block"
-    echo "1. Pre exception"
-    test()
-    echo "4. Post exception"
-  # --> 1, 2, 3 is printed, 4 is never reached
-
-Top level standalone ``finally`` or ``except`` statements are not supported
+  var f = open("numbers.txt")
+  try:
+    f.write "abc"
+    f.write "def"
+  finally:
+    close(f)
+
+Top level ``defer`` statements are not supported
 since it's unclear what such a statement should refer to.
 
 
diff --git a/doc/manual/procs.txt b/doc/manual/procs.txt
index 156e96f1b..2ebbe494d 100644
--- a/doc/manual/procs.txt
+++ b/doc/manual/procs.txt
@@ -200,6 +200,8 @@ executable code.
 Do notation
 -----------
 
+**Note:** The future of the ``do`` notation is uncertain.
+
 As a special more convenient notation, proc expressions involved in procedure
 calls can use the ``do`` keyword:
 
@@ -224,11 +226,6 @@ More than one ``do`` block can appear in a single call:
   do:
     # code to undo it
 
-For compatibility with ``stmt`` templates and macros, the ``do`` keyword can be
-omitted if the supplied proc doesn't have any parameters and return value. 
-The compatibility works in the other direction too as the ``do`` syntax can be
-used with macros and templates expecting ``stmt`` blocks.
-
 
 Nonoverloadable builtins
 ------------------------
diff --git a/doc/manual/types.txt b/doc/manual/types.txt
index b028752e8..94611bbbb 100644
--- a/doc/manual/types.txt
+++ b/doc/manual/types.txt
@@ -40,7 +40,7 @@ These integer types are pre-defined:
 
 ``int``
   the generic signed integer type; its size is platform dependent and has the
-  same size as a pointer. This type should be used in general. An integer 
+  same size as a pointer. This type should be used in general. An integer
   literal that has no type suffix is of this type.
 
 intXX
@@ -51,7 +51,7 @@ intXX
 
 ``uint``
   the generic `unsigned integer`:idx: type; its size is platform dependent and
-  has the same size as a pointer. An integer literal with the type 
+  has the same size as a pointer. An integer literal with the type
   suffix ``'u`` is of this type.
 
 uintXX
@@ -59,15 +59,15 @@ uintXX
   (example: uint16 is a 16 bit wide unsigned integer).
   The current implementation supports ``uint8``, ``uint16``, ``uint32``,
   ``uint64``. Literals of these types have the suffix 'uXX.
-  Unsigned operations all wrap around; they cannot lead to over- or 
+  Unsigned operations all wrap around; they cannot lead to over- or
   underflow errors.
 
 
 In addition to the usual arithmetic operators for signed and unsigned integers
-(``+ - *`` etc.) there are also operators that formally work on *signed* 
-integers but treat their arguments as *unsigned*: They are mostly provided 
-for backwards compatibility with older versions of the language that lacked 
-unsigned integer types. These unsigned operations for signed integers use 
+(``+ - *`` etc.) there are also operators that formally work on *signed*
+integers but treat their arguments as *unsigned*: They are mostly provided
+for backwards compatibility with older versions of the language that lacked
+unsigned integer types. These unsigned operations for signed integers use
 the ``%`` suffix as convention:
 
 
@@ -98,7 +98,7 @@ operation                meaning
 kinds of integer types are used: the smaller type is converted to the larger.
 
 A `narrowing type conversion`:idx: converts a larger to a smaller type (for
-example ``int32 -> int16``. A `widening type conversion`:idx: converts a 
+example ``int32 -> int16``. A `widening type conversion`:idx: converts a
 smaller type to a larger type (for example ``int16 -> int32``). In Nim only
 widening type conversions are *implicit*:
 
@@ -111,7 +111,7 @@ widening type conversions are *implicit*:
 
 However, ``int`` literals are implicitly convertible to a smaller integer type
 if the literal's value fits this smaller type and such a conversion is less
-expensive than other implicit conversions, so ``myInt16 + 34`` produces 
+expensive than other implicit conversions, so ``myInt16 + 34`` produces
 an ``int16`` result.
 
 For further details, see `Convertible relation`_.
@@ -137,12 +137,12 @@ determined). Assignments from the base type to one of its subrange types
 A subrange type has the same size as its base type (``int`` in the example).
 
 Nim requires `interval arithmetic`:idx: for subrange types over a set
-of built-in operators that involve constants: ``x %% 3`` is of 
-type ``range[0..2]``. The following built-in operators for integers are 
+of built-in operators that involve constants: ``x %% 3`` is of
+type ``range[0..2]``. The following built-in operators for integers are
 affected by this rule: ``-``, ``+``, ``*``, ``min``, ``max``, ``succ``,
 ``pred``, ``mod``, ``div``, ``%%``, ``and`` (bitwise ``and``).
 
-Bitwise ``and`` only produces a ``range`` if one of its operands is a 
+Bitwise ``and`` only produces a ``range`` if one of its operands is a
 constant *x* so that (x+1) is a number of two.
 (Bitwise ``and`` is then a ``%%`` operation.)
 
@@ -155,7 +155,7 @@ This means that the following code is accepted:
   of 9: echo "C"
   of 10: echo "D"
   # note: no ``else`` required as (x and 3) + 7 has the type: range[7..10]
-  
+
 
 Pre-defined floating point types
 --------------------------------
@@ -186,17 +186,17 @@ The IEEE standard defines five types of floating-point exceptions:
   for example 0.0/0.0, sqrt(-1.0), and log(-37.8).
 * Division by zero: divisor is zero and dividend is a finite nonzero number,
   for example 1.0/0.0.
-* Overflow: operation produces a result that exceeds the range of the exponent, 
+* Overflow: operation produces a result that exceeds the range of the exponent,
   for example MAXDOUBLE+0.0000000000001e308.
-* Underflow: operation produces a result that is too small to be represented 
+* Underflow: operation produces a result that is too small to be represented
   as a normal number, for example, MINDOUBLE * MINDOUBLE.
-* Inexact: operation produces a result that cannot be represented with infinite 
+* Inexact: operation produces a result that cannot be represented with infinite
   precision, for example, 2.0 / 3.0, log(1.1) and 0.1 in input.
 
-The IEEE exceptions are either ignored at runtime or mapped to the 
+The IEEE exceptions are either ignored at runtime or mapped to the
 Nim exceptions: `FloatInvalidOpError`:idx:, `FloatDivByZeroError`:idx:,
 `FloatOverflowError`:idx:, `FloatUnderflowError`:idx:,
-and `FloatInexactError`:idx:. 
+and `FloatInexactError`:idx:.
 These exceptions inherit from the `FloatingPointError`:idx: base class.
 
 Nim provides the pragmas `NaNChecks`:idx: and `InfChecks`:idx: to control
@@ -212,7 +212,7 @@ whether the IEEE exceptions are ignored or trap a Nim exception:
 In the current implementation ``FloatDivByZeroError`` and ``FloatInexactError``
 are never raised. ``FloatOverflowError`` is raised instead of
 ``FloatDivByZeroError``.
-There is also a `floatChecks`:idx: pragma that is a short-cut for the 
+There is also a `floatChecks`:idx: pragma that is a short-cut for the
 combination of ``NaNChecks`` and ``InfChecks`` pragmas. ``floatChecks`` are
 turned off as default.
 
@@ -303,7 +303,7 @@ and ``pred`` are not available for them either.
 
 
 The compiler supports the built-in stringify operator ``$`` for enumerations.
-The stringify's result can be controlled by explicitly giving the string 
+The stringify's result can be controlled by explicitly giving the string
 values to use:
 
 .. code-block:: nim
@@ -315,12 +315,12 @@ values to use:
       valueC = 2,
       valueD = (3, "abc")
 
-As can be seen from the example, it is possible to both specify a field's 
+As can be seen from the example, it is possible to both specify a field's
 ordinal value and its string value by using a tuple. It is also
 possible to only specify one of them.
 
 An enum can be marked with the ``pure`` pragma so that it's fields are not
-added to the current scope, so they always need to be accessed 
+added to the current scope, so they always need to be accessed
 via ``MyEnum.value``:
 
 .. code-block:: nim
@@ -328,7 +328,7 @@ via ``MyEnum.value``:
   type
     MyEnum {.pure.} = enum
       valueA, valueB, valueC, valueD
-  
+
   echo valueA # error: Unknown identifier
   echo MyEnum.valueA # works
 
@@ -364,22 +364,22 @@ cstring type
 ------------
 The ``cstring`` type represents a pointer to a zero-terminated char array
 compatible to the type ``char*`` in Ansi C. Its primary purpose lies in easy
-interfacing with C. The index operation ``s[i]`` means the i-th *char* of 
+interfacing with C. The index operation ``s[i]`` means the i-th *char* of
 ``s``; however no bounds checking for ``cstring`` is performed making the
 index operation unsafe.
 
-A Nim ``string`` is implicitly convertible 
+A Nim ``string`` is implicitly convertible
 to ``cstring`` for convenience. If a Nim string is passed to a C-style
 variadic proc, it is implicitly converted to ``cstring`` too:
 
 .. code-block:: nim
-  proc printf(formatstr: cstring) {.importc: "printf", varargs, 
+  proc printf(formatstr: cstring) {.importc: "printf", varargs,
                                     header: "<stdio.h>".}
-  
+
   printf("This works %s", "as expected")
 
 Even though the conversion is implicit, it is not *safe*: The garbage collector
-does not consider a ``cstring`` to be a root and may collect the underlying 
+does not consider a ``cstring`` to be a root and may collect the underlying
 memory. However in practice this almost never happens as the GC considers
 stack roots conservatively. One can use the builtin procs ``GC_ref`` and
 ``GC_unref`` to keep the string data alive for the rare cases where it does
@@ -390,7 +390,7 @@ string from a cstring:
 
 .. code-block:: nim
   var str: string = "Hello!"
-  var cstr: cstring = s
+  var cstr: cstring = str
   var newstr: string = $cstr
 
 
@@ -410,9 +410,9 @@ integers from 0 to ``len(A)-1``. An array expression may be constructed by the
 array constructor ``[]``.
 
 Sequences are similar to arrays but of dynamic length which may change
-during runtime (like strings). Sequences are implemented as growable arrays, 
+during runtime (like strings). Sequences are implemented as growable arrays,
 allocating pieces of memory as items are added. A sequence ``S`` is always
-indexed by integers from 0 to ``len(S)-1`` and its bounds are checked. 
+indexed by integers from 0 to ``len(S)-1`` and its bounds are checked.
 Sequences can be constructed by the array constructor ``[]`` in conjunction
 with the array to sequence operator ``@``. Another way to allocate space for a
 sequence is to call the built-in ``newSeq`` procedure.
@@ -452,11 +452,11 @@ Open arrays
 
 Often fixed size arrays turn out to be too inflexible; procedures should
 be able to deal with arrays of different sizes. The `openarray`:idx: type
-allows this; it can only be used for parameters. Openarrays are always 
-indexed with an ``int`` starting at position 0. The ``len``, ``low`` 
-and ``high`` operations are available for open arrays too. Any array with 
-a compatible base type can be passed to an openarray parameter, the index 
-type does not matter. In addition to arrays sequences can also be passed 
+allows this; it can only be used for parameters. Openarrays are always
+indexed with an ``int`` starting at position 0. The ``len``, ``low``
+and ``high`` operations are available for open arrays too. Any array with
+a compatible base type can be passed to an openarray parameter, the index
+type does not matter. In addition to arrays sequences can also be passed
 to an open array parameter.
 
 The openarray type cannot be nested: multidimensional openarrays are not
@@ -467,7 +467,7 @@ Varargs
 -------
 
 A ``varargs`` parameter is an openarray parameter that additionally
-allows to pass a variable number of arguments to a procedure. The compiler 
+allows to pass a variable number of arguments to a procedure. The compiler
 converts the list of arguments to an array implicitly:
 
 .. code-block:: nim
@@ -494,7 +494,7 @@ type conversions in this context:
   # is transformed to:
   myWriteln(stdout, [$123, $"def", $4.0])
 
-In this example ``$`` is applied to any argument that is passed to the 
+In this example ``$`` is applied to any argument that is passed to the
 parameter ``a``. (Note that ``$`` applied to strings is a nop.)
 
 
@@ -531,7 +531,7 @@ in future versions of the compiler.
   person = (creditCard: "Peter", id: 20)
 
 The implementation aligns the fields for best access performance. The alignment
-is compatible with the way the C compiler does it. 
+is compatible with the way the C compiler does it.
 
 For consistency  with ``object`` declarations, tuples in a ``type`` section
 can also be defined with indentation instead of ``[]``:
@@ -571,7 +571,7 @@ Object construction
 -------------------
 
 Objects can also be created with an `object construction expression`:idx: that
-has the syntax ``T(fieldA: valueA, fieldB: valueB, ...)`` where ``T`` is 
+has the syntax ``T(fieldA: valueA, fieldB: valueB, ...)`` where ``T`` is
 an ``object`` type or a ``ref object`` type:
 
 .. code-block:: nim
@@ -617,10 +617,10 @@ An example:
   # the following statement raises an `EInvalidField` exception, because
   # n.kind's value does not fit and the ``nkString`` branch is not active:
   n.strVal = ""
-  
+
   # invalid: would change the active object branch:
   n.kind = nkInt
-  
+
   var x = PNode(kind: nkAdd, leftOp: PNode(kind: nkInt, intVal: 4),
                              rightOp: PNode(kind: nkInt, intVal: 2))
   # valid: does not change the active object branch:
@@ -660,8 +660,8 @@ untraced references are *unsafe*. However for certain low-level operations
 Traced references are declared with the **ref** keyword, untraced references
 are declared with the **ptr** keyword.
 
-An empty subscript ``[]`` notation can be used to derefer a reference, 
-the ``addr`` procedure returns the address of an item. An address is always 
+An empty subscript ``[]`` notation can be used to derefer a reference,
+the ``addr`` procedure returns the address of an item. An address is always
 an untraced reference.
 Thus the usage of ``addr`` is an *unsafe* feature.
 
@@ -680,7 +680,7 @@ dereferencing operations for reference types:
   var
     n: PNode
   new(n)
-  n.data = 9 
+  n.data = 9
   # no need to write n[].data; in fact n[].data is highly discouraged!
 
 In order to simplify structural type checking, recursive tuples are not valid:
@@ -751,20 +751,20 @@ details like this when mixing garbage collected data with unmanaged memory.
 Not nil annotation
 ------------------
 
-All types for that ``nil`` is a valid value can be annotated to 
+All types for that ``nil`` is a valid value can be annotated to
 exclude ``nil`` as a valid value with the ``not nil`` annotation:
 
 .. code-block:: nim
   type
     PObject = ref TObj not nil
     TProc = (proc (x, y: int)) not nil
-    
+
   proc p(x: PObject) =
     echo "not nil"
-  
+
   # compiler catches this:
   p(nil)
-  
+
   # and also this:
   var x: PObject
   p(x)
@@ -851,22 +851,22 @@ Examples:
 
   forEach(printItem)  # this will NOT compile because calling conventions differ
 
-  
+
 .. code-block:: nim
 
   type
     TOnMouseMove = proc (x, y: int) {.closure.}
-  
+
   proc onMouseMove(mouseX, mouseY: int) =
     # has default calling convention
     echo "x: ", mouseX, " y: ", mouseY
-  
+
   proc setOnMouseMove(mouseMoveEvent: TOnMouseMove) = discard
-  
+
   # ok, 'onMouseMove' has the default calling convention, which is compatible
   # to 'closure':
   setOnMouseMove(onMouseMove)
-  
+
 
 A subtle issue with procedural types is that the calling convention of the
 procedure influences the type compatibility: procedural types are only
@@ -932,7 +932,7 @@ of the following conditions hold:
 3) The procedure has a calling convention that differs from ``nimcall``.
 4) The procedure is anonymous.
 
-The rules' purpose is to prevent the case that extending a non-``procvar`` 
+The rules' purpose is to prevent the case that extending a non-``procvar``
 procedure with default parameters breaks client code.
 
 The default calling convention is ``nimcall``, unless it is an inner proc (a
@@ -964,7 +964,7 @@ types are a perfect tool to model different currencies:
   type
     TDollar = distinct int
     TEuro = distinct int
-  
+
   var
     d: TDollar
     e: TEuro
@@ -989,7 +989,7 @@ number without unit; and the same holds for division:
 
   proc `*` (x: int, y: TDollar): TDollar =
     result = TDollar(x * int(y))
-    
+
   proc `div` ...
 
 This quickly gets tedious. The implementations are trivial and the compiler
@@ -1014,7 +1014,7 @@ currency. This can be solved with templates_.
   template additive(typ: typedesc): stmt =
     proc `+` *(x, y: typ): typ {.borrow.}
     proc `-` *(x, y: typ): typ {.borrow.}
-    
+
     # unary operators:
     proc `+` *(x: typ): typ {.borrow.}
     proc `-` *(x: typ): typ {.borrow.}
@@ -1036,7 +1036,7 @@ currency. This can be solved with templates_.
     additive(typ)
     multiplicative(typ, base)
     comparable(typ)
-    
+
   defineCurrency(TDollar, int)
   defineCurrency(TEuro, int)
 
@@ -1127,21 +1127,21 @@ modules like `db_sqlite <db_sqlite.html>`_.
 Void type
 ---------
 
-The ``void`` type denotes the absense of any type. Parameters of 
+The ``void`` type denotes the absense of any type. Parameters of
 type ``void`` are treated as non-existent, ``void`` as a return type means that
 the procedure does not return a value:
 
 .. code-block:: nim
   proc nothing(x, y: void): void =
     echo "ha"
-  
+
   nothing() # writes "ha" to stdout
 
 The ``void`` type is particularly useful for generic code:
 
 .. code-block:: nim
   proc callProc[T](p: proc (x: T), x: T) =
-    when T is void: 
+    when T is void:
       p()
     else:
       p(x)
@@ -1151,13 +1151,13 @@ The ``void`` type is particularly useful for generic code:
 
   callProc[int](intProc, 12)
   callProc[void](emptyProc)
-  
+
 However, a ``void`` type cannot be inferred in generic code:
 
 .. code-block:: nim
-  callProc(emptyProc) 
+  callProc(emptyProc)
   # Error: type mismatch: got (proc ())
-  # but expected one of: 
+  # but expected one of:
   # callProc(p: proc (T), x: T)
 
 The ``void`` type is only valid for parameters and return types; other symbols
diff --git a/doc/nimc.txt b/doc/nimc.txt
index 92acd3979..a2274febd 100644
--- a/doc/nimc.txt
+++ b/doc/nimc.txt
@@ -550,58 +550,6 @@ in C/C++).
 **Note**: This pragma will not exist for the LLVM backend.

 
 
-Source code style
-=================
-
-Nim allows you to `mix freely case and underscores as identifier separators
-<manual.html#identifiers-keywords>`_, so variables named ``MyPrecioussInt`` and
-``my_preciouss_int`` are equivalent:
-
-.. code-block:: Nim
-  var MyPrecioussInt = 3
-  # Following line compiles fine!
-  echo my_preciouss_int
-
-Since this can lead to many variants of the same source code (you can use
-`nimgrep <nimgrep.html>`_ instead of your typical ``grep`` to ignore style
-problems) the compiler provides the command ``pretty`` to help unifying the
-style of source code.  Running ``nim pretty ugly_test.nim`` with this
-example will generate a secondary file named ``ugly_test.pretty.nim`` with the
-following content:
-
-.. code-block:: Nim
-  var MyPrecioussInt = 3
-  # Following line compiles fine!
-  echo MyPrecioussInt
-
-During execution the ``pretty`` command will also run on Nim's standard
-library, since it doesn't differentiate the standard library as something
-special, and hence will warn of many *errors* which are out of your hand to
-fix, creating respective ``.pretty.nim`` files all the way. You can ignore
-these errors if they don't belong to your source and simply compare your
-original version to the new pretty one. In fact, running ``pretty`` on our test
-file will show the following::
-
-  Hint: ugly_test [Processing]
-  ugly_test.nim(1, 4) Error: name should be: myPrecioussInt
-  ugly_test.nim(1, 4) Error: name should be: myPrecioussInt
-
-At the moment ``pretty`` will homogenize the style of symbols but will leave
-important changes for you to review. In this case the command is warning that a
-variable name should not start with a capital letter, which is usually reserved
-to `object types <tut2.html#objects>`_. To learn about the accepted `camel case
-style <https://en.wikipedia.org/wiki/Camelcase>`_ read `Coding Guidelines in
-the Internals of Nim Compiler <intern.html#coding-guidelines>`_ or `Coding
-Guidelines <https://github.com/Araq/Nim/wiki/Coding-Guidelines>`_ and `NEP 1
-: Style Guide for Nim Code
-<https://github.com/Araq/Nim/wiki/NEP-1-:-Style-Guide-for-Nim-Code>`_
-from the Nim `GitHub wiki<https://github.com/Araq/Nim/wiki>`_.
-
-This command is safe to run because it will never attempt to overwrite your
-existing sources, but the respective ``.pretty.nim`` files **will** be
-overwritten without notice.
-
-
 DynlibOverride
 ==============
 
diff --git a/doc/tut1.txt b/doc/tut1.txt
index 9d75b1ea2..5901dd02a 100644
--- a/doc/tut1.txt
+++ b/doc/tut1.txt
@@ -139,7 +139,7 @@ Numbers
 Numerical literals are written as in most other languages. As a special twist,
 underscores are allowed for better readability: ``1_000_000`` (one million).
 A number that contains a dot (or 'e' or 'E') is a floating point literal:
-``1.0e9`` (one million). Hexadecimal literals are prefixed with ``0x``,
+``1.0e9`` (one billion). Hexadecimal literals are prefixed with ``0x``,
 binary literals with ``0b`` and octal literals with ``0o``. A leading zero
 alone does not produce an octal.
 
@@ -1070,7 +1070,7 @@ Operation             Comment
 ``dec(x, n)``         decrements `x` by `n`; `n` is an integer
 ``succ(x)``           returns the successor of `x`
 ``succ(x, n)``        returns the `n`'th successor of `x`
-``prec(x)``           returns the predecessor of `x`
+``pred(x)``           returns the predecessor of `x`
 ``pred(x, n)``        returns the `n`'th predecessor of `x`
 -----------------     --------------------------------------------------------
 
@@ -1323,7 +1323,7 @@ define operators which accept TSlice objects to define ranges.
     a = "Nim is a progamming language"
     b = "Slices are useless."
 
-  echo a[10..15] # --> 'a prog'
+  echo a[7..12] # --> 'a prog'
   b[11.. -2] = "useful"
   echo b # --> 'Slices are useful.'
 
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 6e239d681..2ae0f18f6 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -35,7 +35,7 @@ Object Oriented Programming
 ===========================
 
 While Nim's support for object oriented programming (OOP) is minimalistic,
-powerful OOP technics can be used. OOP is seen as *one* way to design a
+powerful OOP techniques can be used. OOP is seen as *one* way to design a
 program, not *the only* way. Often a procedural approach leads to simpler
 and more efficient code. In particular, prefering composition over inheritance
 is often the better design.
@@ -56,7 +56,7 @@ Objects have access to their type at runtime. There is an
 
 .. code-block:: nim
   type
-    TPerson = object of TObject
+    TPerson = object of RootObj
       name*: string  # the * means that `name` is accessible from other modules
       age: int       # no * means that the field is hidden from other modules
 
@@ -76,10 +76,10 @@ never *equivalent*. New object types can only be defined within a type
 section.
 
 Inheritance is done with the ``object of`` syntax. Multiple inheritance is
-currently not supported. If an object type has no suitable ancestor, ``TObject``
-can be used as its ancestor, but this is only a convention. Objects that have 
-no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma 
-to introduce new object roots apart from ``system.TObject``. (This is used
+currently not supported. If an object type has no suitable ancestor, ``RootObj``
+can be used as its ancestor, but this is only a convention. Objects that have
+no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma
+to introduce new object roots apart from ``system.RootObj``. (This is used
 in the GTK wrapper for instance.)
 
 
@@ -199,7 +199,7 @@ This method call syntax is not restricted to objects, it can be used
 for any type:
 
 .. code-block:: nim
-  
+
   echo("abc".len) # is the same as echo(len("abc"))
   echo("abc".toUpper())
   echo({'a', 'b', 'c'}.card)
@@ -212,7 +212,7 @@ So "pure object oriented" code is easy to write:
 
 .. code-block:: nim
   import strutils
-  
+
   stdout.writeln("Give a list of numbers (separated by spaces): ")
   stdout.write(stdin.readLine.split.map(parseInt).max.`$`)
   stdout.writeln(" is the maximum!")
@@ -226,9 +226,9 @@ the same. But setting a value is different; for this a special setter syntax
 is needed:
 
 .. code-block:: nim
-  
+
   type
-    TSocket* = object of TObject
+    TSocket* = object of RootObj
       FHost: int # cannot be accessed from the outside of the module
                  # the `F` prefix is a convention to avoid clashes since
                  # the accessors are named `host`
@@ -236,7 +236,7 @@ is needed:
   proc `host=`*(s: var TSocket, value: int) {.inline.} =
     ## setter of hostAddr
     s.FHost = value
-  
+
   proc host*(s: TSocket): int {.inline.} =
     ## getter of hostAddr
     s.FHost
@@ -284,7 +284,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the
 
 .. code-block:: nim
   type
-    PExpr = ref object of TObject ## abstract base class for an expression
+    PExpr = ref object of RootObj ## abstract base class for an expression
     PLiteral = ref object of PExpr
       x: int
     PPlusExpr = ref object of PExpr
@@ -294,15 +294,15 @@ Procedures always use static dispatch. For dynamic dispatch replace the
   method eval(e: PExpr): int =
     # override this base method
     quit "to override!"
-  
+
   method eval(e: PLiteral): int = e.x
   method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
-  
+
   proc newLit(x: int): PLiteral = PLiteral(x: x)
   proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)
-  
+
   echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
-  
+
 Note that in the example the constructors ``newLit`` and ``newPlus`` are procs
 because they should use static binding, but ``eval`` is a method because it
 requires dynamic binding.
@@ -313,19 +313,19 @@ dispatching:
 .. code-block:: nim
 
   type
-    TThing = object of TObject
+    TThing = object of RootObj
     TUnit = object of TThing
       x: int
-      
+
   method collide(a, b: TThing) {.inline.} =
     quit "to override!"
-    
+
   method collide(a: TThing, b: TUnit) {.inline.} =
     echo "1"
-  
+
   method collide(a: TUnit, b: TThing) {.inline.} =
     echo "2"
-  
+
   var
     a, b: TUnit
   collide(a, b) # output: 2
@@ -526,7 +526,7 @@ containers:
         yield n.data
         add(stack, n.ri)  # push right subtree onto the stack
         n = n.le          # and follow the left pointer
-      
+
   var
     root: PBinaryTree[string] # instantiate a PBinaryTree with ``string``
   add(root, newNode("hello")) # instantiates ``newNode`` and ``add``
@@ -578,7 +578,7 @@ simple proc for logging:
 
   proc log(msg: string) {.inline.} =
     if debug: stdout.writeln(msg)
-  
+
   var
     x = 4
   log("x has the value: " & $x)
@@ -595,7 +595,7 @@ Turning the ``log`` proc into a template solves this problem:
 
   template log(msg: string) =
     if debug: stdout.writeln(msg)
-  
+
   var
     x = 4
   log("x has the value: " & $x)
@@ -622,11 +622,11 @@ via a special ``:`` syntax:
         close(f)
     else:
       quit("cannot open: " & fn)
-      
+
   withFile(txt, "ttempl3.txt", fmWrite):
     txt.writeln("line 1")
     txt.writeln("line 2")
-  
+
 In the example the two ``writeln`` statements are bound to the ``body``
 parameter. The ``withFile`` template contains boilerplate code and helps to
 avoid a common bug: to forget to close the file. Note how the
@@ -739,7 +739,7 @@ Term rewriting macros
 ---------------------
 
 Term rewriting macros can be used to enhance the compilation process
-with user defined optimizations; see this `document <trmacros.html>`_ for 
+with user defined optimizations; see this `document <trmacros.html>`_ for
 further information.
 
 
diff --git a/koch.nim b/koch.nim
index 79228c1a4..e3831617c 100644
--- a/koch.nim
+++ b/koch.nim
@@ -94,16 +94,16 @@ const
   compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
 
 proc csource(args: string) = 
-  exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=mingw32 csource compiler/nim.ini $1" %
+  exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=none csource compiler/nim.ini $1" %
        [args, VersionAsString, compileNimInst, findNim()])
 
 proc zip(args: string) =
-  exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nim.ini" %
+  exec("$3 cc -r $2 --var:version=$1 --var:mingw=none scripts compiler/nim.ini" %
        [VersionAsString, compileNimInst, findNim()])
-  exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nim.ini" %
+  exec("$# --var:version=$# --var:mingw=none zip compiler/nim.ini" %
        ["tools/niminst/niminst".exe, VersionAsString])
-  
-proc buildTool(toolname, args: string) = 
+
+proc buildTool(toolname, args: string) =
   exec("$# cc $# $#" % [findNim(), args, toolname])
   copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
 
@@ -114,11 +114,11 @@ proc nsis(args: string) =
   # produce 'nimrod_debug.exe':
   exec "nim c compiler" / "nim.nim"
   copyExe("compiler/nim".exe, "bin/nim_debug".exe)
-  exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" &
-        " nsis compiler/nim") % VersionAsString)
+  exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" &
+        " nsis compiler/nim") % [VersionAsString, $(sizeof(pointer)*8)])
 
 proc install(args: string) = 
-  exec("$# cc -r $# --var:version=$# --var:mingw=mingw32 scripts compiler/nim.ini" %
+  exec("$# cc -r $# --var:version=$# --var:mingw=none scripts compiler/nim.ini" %
        [findNim(), compileNimInst, VersionAsString])
   exec("sh ./install.sh $#" % args)
 
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index ed5d3c50c..353254d49 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -649,6 +649,8 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
     result = $node.basename.ident & "*"
   of nnkStrLit..nnkTripleStrLit:
     result = node.strVal
+  of nnkSym:
+    result = $node.symbol
   else: 
     badNodeKind node.kind, "$"
 
diff --git a/lib/impure/osinfo_posix.nim b/lib/impure/osinfo_posix.nim
index 1baff8c55..0ed4289c4 100644
--- a/lib/impure/osinfo_posix.nim
+++ b/lib/impure/osinfo_posix.nim
@@ -35,7 +35,15 @@ proc getSystemVersion*(): string =
   elif $unix_info.sysname == "Darwin":
     # Darwin
     result.add("Mac OS X ")
-    if "10" in $unix_info.release:
+    if "14" in $unix_info.release:
+      result.add("v10.10 Yosemite")
+    elif "13" in $unix_info.release:
+      result.add("v10.9 Mavericks")
+    elif "12" in $unix_info.release:
+      result.add("v10.8 Mountian Lion")
+    elif "11" in $unix_info.release:
+      result.add("v10.7 Lion")
+    elif "10" in $unix_info.release:
       result.add("v10.6 Snow Leopard")
     elif "9" in $unix_info.release:
       result.add("v10.5 Leopard")
diff --git a/lib/impure/osinfo_win.nim b/lib/impure/osinfo_win.nim
index f423a34a3..becec928e 100644
--- a/lib/impure/osinfo_win.nim
+++ b/lib/impure/osinfo_win.nim
@@ -245,6 +245,14 @@ proc `$`*(osvi: TVersionInfo): string =
         if osvi.ProductType == VER_NT_WORKSTATION:
           result.add("Windows 7 ")
         else: result.add("Windows Server 2008 R2 ")
+      elif osvi.minorVersion == 2:
+        if osvi.ProductType == VER_NT_WORKSTATION:
+          result.add("Windows 8 ")
+        else: result.add("Windows Server 2012 ")
+      elif osvi.minorVersion == 3:
+        if osvi.ProductType == VER_NT_WORKSTATION:
+          result.add("Windows 8.1 ")
+        else: result.add("Windows Server 2012 R2 ")
     
       var dwType = getProductInfo(osvi.majorVersion, osvi.minorVersion, 0, 0)
       case dwType
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index deb120372..0498a0e70 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -1570,9 +1570,9 @@ else:
 
 
 when defined(macosx):
+  # We can't use the NOSIGNAL flag in the ``send`` function, it has no effect
   var
-    MSG_HAVEMORE* {.importc, header: "<sys/socket.h>".}: cint
-    MSG_NOSIGNAL* = MSG_HAVEMORE
+    MSG_NOSIGNAL* = 0'i32
 else:
   var
     MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index a9a0b0fbe..c4abdf9f3 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -436,12 +436,12 @@ when defined(windows) or defined(nimdoc):
     if not initPointer(dummySock, getAcceptExSockAddrsPtr, WSAID_GETACCEPTEXSOCKADDRS):
       raiseOSError(osLastError())
 
-  proc connectEx(s: SocketHandle, name: ptr TSockAddr, namelen: cint, 
+  proc connectEx(s: SocketHandle, name: ptr SockAddr, namelen: cint, 
                   lpSendBuffer: pointer, dwSendDataLength: Dword,
                   lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool =
     if connectExPtr.isNil: raise newException(ValueError, "Need to initialise ConnectEx().")
     let fun =
-      cast[proc (s: SocketHandle, name: ptr TSockAddr, namelen: cint, 
+      cast[proc (s: SocketHandle, name: ptr SockAddr, namelen: cint, 
          lpSendBuffer: pointer, dwSendDataLength: Dword,
          lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](connectExPtr)
 
@@ -464,16 +464,16 @@ when defined(windows) or defined(nimdoc):
 
   proc getAcceptExSockaddrs(lpOutputBuffer: pointer,
       dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength: Dword,
-      LocalSockaddr: ptr ptr TSockAddr, LocalSockaddrLength: LPInt,
-      RemoteSockaddr: ptr ptr TSockAddr, RemoteSockaddrLength: LPInt) =
+      LocalSockaddr: ptr ptr SockAddr, LocalSockaddrLength: LPInt,
+      RemoteSockaddr: ptr ptr SockAddr, RemoteSockaddrLength: LPInt) =
     if getAcceptExSockAddrsPtr.isNil:
       raise newException(ValueError, "Need to initialise getAcceptExSockAddrs().")
 
     let fun =
       cast[proc (lpOutputBuffer: pointer,
                  dwReceiveDataLength, dwLocalAddressLength,
-                 dwRemoteAddressLength: Dword, LocalSockaddr: ptr ptr TSockAddr,
-                 LocalSockaddrLength: LPInt, RemoteSockaddr: ptr ptr TSockAddr,
+                 dwRemoteAddressLength: Dword, LocalSockaddr: ptr ptr SockAddr,
+                 LocalSockaddrLength: LPInt, RemoteSockaddr: ptr ptr SockAddr,
                 RemoteSockaddrLength: LPInt) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
     
     fun(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
@@ -489,12 +489,12 @@ when defined(windows) or defined(nimdoc):
     verifyPresence(socket)
     var retFuture = newFuture[void]("connect")
     # Apparently ``ConnectEx`` expects the socket to be initially bound:
-    var saddr: Tsockaddr_in
+    var saddr: Sockaddr_in
     saddr.sin_family = int16(toInt(af))
     saddr.sin_port = 0
     saddr.sin_addr.s_addr = INADDR_ANY
-    if bindAddr(socket.SocketHandle, cast[ptr TSockAddr](addr(saddr)),
-                  sizeof(saddr).TSockLen) < 0'i32:
+    if bindAddr(socket.SocketHandle, cast[ptr SockAddr](addr(saddr)),
+                  sizeof(saddr).SockLen) < 0'i32:
       raiseOSError(osLastError())
 
     var aiList = getAddrInfo(address, port, af)
@@ -516,7 +516,7 @@ when defined(windows) or defined(nimdoc):
       )
       
       var ret = connectEx(socket.SocketHandle, it.ai_addr,
-                          sizeof(Tsockaddr_in).cint, nil, 0, nil,
+                          sizeof(Sockaddr_in).cint, nil, 0, nil,
                           cast[POVERLAPPED](ol))
       if ret:
         # Request to connect completed immediately.
@@ -700,17 +700,17 @@ when defined(windows) or defined(nimdoc):
     var lpOutputBuf = newString(lpOutputLen)
     var dwBytesReceived: Dword
     let dwReceiveDataLength = 0.Dword # We don't want any data to be read.
-    let dwLocalAddressLength = Dword(sizeof (Tsockaddr_in) + 16)
-    let dwRemoteAddressLength = Dword(sizeof(Tsockaddr_in) + 16)
+    let dwLocalAddressLength = Dword(sizeof (Sockaddr_in) + 16)
+    let dwRemoteAddressLength = Dword(sizeof(Sockaddr_in) + 16)
 
     template completeAccept(): stmt {.immediate, dirty.} =
       var listenSock = socket
       let setoptRet = setsockopt(clientSock, SOL_SOCKET,
           SO_UPDATE_ACCEPT_CONTEXT, addr listenSock,
-          sizeof(listenSock).TSockLen)
+          sizeof(listenSock).SockLen)
       if setoptRet != 0: raiseOSError(osLastError())
 
-      var localSockaddr, remoteSockaddr: ptr TSockAddr
+      var localSockaddr, remoteSockaddr: ptr SockAddr
       var localLen, remoteLen: int32
       getAcceptExSockaddrs(addr lpOutputBuf[0], dwReceiveDataLength,
                            dwLocalAddressLength, dwRemoteAddressLength,
@@ -719,7 +719,7 @@ when defined(windows) or defined(nimdoc):
       register(clientSock.TAsyncFD)
       # TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186
       retFuture.complete(
-        (address: $inet_ntoa(cast[ptr Tsockaddr_in](remoteSockAddr).sin_addr),
+        (address: $inet_ntoa(cast[ptr Sockaddr_in](remoteSockAddr).sin_addr),
          client: clientSock.TAsyncFD)
       )
 
@@ -878,6 +878,10 @@ else:
       let data = PData(info.key.data)
       assert data.fd == info.key.fd.TAsyncFD
       #echo("In poll ", data.fd.cint)
+      if EvError in info.events:
+        closeSocket(data.fd)
+        continue
+
       if EvRead in info.events:
         # Callback may add items to ``data.readCBs`` which causes issues if
         # we are iterating over ``data.readCBs`` at the same time. We therefore
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index e0f3b6fc2..4c48350aa 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -17,8 +17,10 @@
 ## as the response body.
 ##
 ## .. code-block::nim
+##    import asynchttpserver, asyncdispatch
+##
 ##    var server = newAsyncHttpServer()
-##    proc cb(req: TRequest) {.async.} =
+##    proc cb(req: Request) {.async.} =
 ##      await req.respond(Http200, "Hello World")
 ##
 ##    asyncCheck server.serve(Port(8080), cb)
@@ -27,25 +29,52 @@
 import strtabs, asyncnet, asyncdispatch, parseutils, uri, strutils
 type
   Request* = object
-    client*: PAsyncSocket # TODO: Separate this into a Response object?
+    client*: AsyncSocket # TODO: Separate this into a Response object?
     reqMethod*: string
-    headers*: PStringTable
+    headers*: StringTableRef
     protocol*: tuple[orig: string, major, minor: int]
-    url*: TUri
+    url*: Uri
     hostname*: string ## The hostname of the client that made the request.
     body*: string
 
   AsyncHttpServer* = ref object
-    socket: PAsyncSocket
+    socket: AsyncSocket
     reuseAddr: bool
 
   HttpCode* = enum
+    Http100 = "100 Continue",
+    Http101 = "101 Switching Protocols",
     Http200 = "200 OK",
-    Http303 = "303 Moved",
+    Http201 = "201 Created",
+    Http202 = "202 Accepted",
+    Http204 = "204 No Content",
+    Http205 = "205 Reset Content",
+    Http206 = "206 Partial Content",
+    Http300 = "300 Multiple Choices",
+    Http301 = "301 Moved Permanently",
+    Http302 = "302 Found",
+    Http303 = "303 See Other",
+    Http304 = "304 Not Modified",
+    Http305 = "305 Use Proxy",
+    Http307 = "307 Temporary Redirect",
     Http400 = "400 Bad Request",
+    Http401 = "401 Unauthorized",
+    Http403 = "403 Forbidden",
     Http404 = "404 Not Found",
+    Http405 = "405 Method Not Allowed",
+    Http406 = "406 Not Acceptable",
+    Http407 = "407 Proxy Authentication Required",
+    Http408 = "408 Request Timeout",
+    Http409 = "409 Conflict",
+    Http410 = "410 Gone",
+    Http411 = "411 Length Required",
+    Http418 = "418 I'm a teapot",
     Http500 = "500 Internal Server Error",
-    Http502 = "502 Bad Gateway"
+    Http501 = "501 Not Implemented",
+    Http502 = "502 Bad Gateway",
+    Http503 = "503 Service Unavailable",
+    Http504 = "504 Gateway Timeout",
+    Http505 = "505 HTTP Version Not Supported"
 
   HttpVersion* = enum
     HttpVer11,
@@ -55,7 +84,7 @@ type
   THttpCode: HttpCode, THttpVersion: HttpVersion].}
 
 proc `==`*(protocol: tuple[orig: string, major, minor: int],
-           ver: THttpVersion): bool =
+           ver: HttpVersion): bool =
   let major =
     case ver
     of HttpVer11, HttpVer10: 1
@@ -65,23 +94,23 @@ proc `==`*(protocol: tuple[orig: string, major, minor: int],
     of HttpVer10: 0
   result = protocol.major == major and protocol.minor == minor
 
-proc newAsyncHttpServer*(reuseAddr = true): PAsyncHttpServer =
+proc newAsyncHttpServer*(reuseAddr = true): AsyncHttpServer =
   ## Creates a new ``AsyncHttpServer`` instance.
   new result
   result.reuseAddr = reuseAddr
 
-proc addHeaders(msg: var string, headers: PStringTable) =
+proc addHeaders(msg: var string, headers: StringTableRef) =
   for k, v in headers:
     msg.add(k & ": " & v & "\c\L")
 
-proc sendHeaders*(req: TRequest, headers: PStringTable): Future[void] =
+proc sendHeaders*(req: Request, headers: StringTableRef): Future[void] =
   ## Sends the specified headers to the requesting client.
   var msg = ""
   addHeaders(msg, headers)
   return req.client.send(msg)
 
-proc respond*(req: TRequest, code: THttpCode,
-        content: string, headers: PStringTable = newStringTable()) {.async.} =
+proc respond*(req: Request, code: HttpCode,
+        content: string, headers = newStringTable()) {.async.} =
   ## Responds to the request with the specified ``HttpCode``, headers and
   ## content.
   ##
@@ -92,7 +121,7 @@ proc respond*(req: TRequest, code: THttpCode,
   msg.addHeaders(customHeaders)
   await req.client.send(msg & "\c\L" & content)
 
-proc newRequest(): TRequest =
+proc newRequest(): Request =
   result.headers = newStringTable(modeCaseInsensitive)
   result.hostname = ""
   result.body = ""
@@ -107,20 +136,20 @@ proc parseHeader(line: string): tuple[key, value: string] =
 proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
   var i = protocol.skipIgnoreCase("HTTP/")
   if i != 5:
-    raise newException(EInvalidValue, "Invalid request protocol. Got: " &
+    raise newException(ValueError, "Invalid request protocol. Got: " &
         protocol)
   result.orig = protocol
   i.inc protocol.parseInt(result.major, i)
   i.inc # Skip .
   i.inc protocol.parseInt(result.minor, i)
 
-proc sendStatus(client: PAsyncSocket, status: string): Future[void] =
+proc sendStatus(client: AsyncSocket, status: string): Future[void] =
   client.send("HTTP/1.1 " & status & "\c\L")
 
-proc processClient(client: PAsyncSocket, address: string,
-                   callback: proc (request: TRequest):
+proc processClient(client: AsyncSocket, address: string,
+                   callback: proc (request: Request):
                       Future[void] {.closure, gcsafe.}) {.async.} =
-  while not client.closed:
+  while not client.isClosed:
     # GET /path HTTP/1.1
     # Header: val
     # \n
@@ -160,7 +189,7 @@ proc processClient(client: PAsyncSocket, address: string,
     request.url = parseUri(path)
     try:
       request.protocol = protocol.parseProtocol()
-    except EInvalidValue:
+    except ValueError:
       asyncCheck request.respond(Http400, "Invalid request protocol. Got: " &
           protocol)
       continue
@@ -206,8 +235,8 @@ proc processClient(client: PAsyncSocket, address: string,
       request.client.close()
       break
 
-proc serve*(server: PAsyncHttpServer, port: Port,
-            callback: proc (request: TRequest): Future[void] {.closure,gcsafe.},
+proc serve*(server: AsyncHttpServer, port: Port,
+            callback: proc (request: Request): Future[void] {.closure,gcsafe.},
             address = "") {.async.} =
   ## Starts the process of listening for incoming HTTP connections on the
   ## specified address and port.
@@ -227,14 +256,14 @@ proc serve*(server: PAsyncHttpServer, port: Port,
     #echo(f.isNil)
     #echo(f.repr)
 
-proc close*(server: PAsyncHttpServer) =
+proc close*(server: AsyncHttpServer) =
   ## Terminates the async http server instance.
   server.socket.close()
 
 when isMainModule:
   proc main =
     var server = newAsyncHttpServer()
-    proc cb(req: TRequest) {.async.} =
+    proc cb(req: Request) {.async.} =
       #echo(req.reqMethod, " ", req.url)
       #echo(req.headers)
       let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT",
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index 4c25952a8..d40c3849e 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -10,6 +10,11 @@ include "system/inclrtl"
 
 import sockets, os
 
+##
+## **Warning:** This module is deprecated since version 0.10.2.
+## Use the brand new `asyncdispatch <asyncdispatch.html>`_ module together
+## with the `asyncnet <asyncnet.html>`_ module.
+
 ## This module implements an asynchronous event loop together with asynchronous
 ## sockets which use this event loop.
 ## It is akin to Python's asyncore module. Many modules that use sockets
@@ -90,6 +95,8 @@ import sockets, os
 ##      var client: Socket
 ##      getSocket(s).accept(client)
 
+{.deprecated.}
+
 when defined(windows):
   from winlean import TimeVal, SocketHandle, FD_SET, FD_ZERO, TFdSet,
     FD_ISSET, select
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index fd29e0a22..76b2bc46c 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -69,13 +69,13 @@ type
   # TODO: I would prefer to just do:
   # AsyncSocket* {.borrow: `.`.} = distinct Socket. But that doesn't work.
   AsyncSocketDesc  = object
-    fd*: SocketHandle
-    closed*: bool ## determines whether this socket has been closed
-    case isBuffered*: bool ## determines whether this socket is buffered.
+    fd: SocketHandle
+    closed: bool ## determines whether this socket has been closed
+    case isBuffered: bool ## determines whether this socket is buffered.
     of true:
-      buffer*: array[0..BufferSize, char]
-      currPos*: int # current index in buffer
-      bufLen*: int # current length of buffer
+      buffer: array[0..BufferSize, char]
+      currPos: int # current index in buffer
+      bufLen: int # current length of buffer
     of false: nil
     case isSsl: bool
     of true:
@@ -91,7 +91,8 @@ type
 
 # TODO: Save AF, domain etc info and reuse it in procs which need it like connect.
 
-proc newSocket(fd: TAsyncFD, isBuff: bool): AsyncSocket =
+proc newAsyncSocket*(fd: TAsyncFD, isBuff: bool): AsyncSocket =
+  ## Creates a new ``AsyncSocket`` based on the supplied params.
   assert fd != osInvalidSocket.TAsyncFD
   new(result)
   result.fd = fd.SocketHandle
@@ -102,11 +103,17 @@ proc newSocket(fd: TAsyncFD, isBuff: bool): AsyncSocket =
 proc newAsyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
     protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket =
   ## Creates a new asynchronous socket.
-  result = newSocket(newAsyncRawSocket(domain, typ, protocol), buffered)
+  ##
+  ## This procedure will also create a brand new file descriptor for
+  ## this socket.
+  result = newAsyncSocket(newAsyncRawSocket(domain, typ, protocol), buffered)
 
 proc newAsyncSocket*(domain, typ, protocol: cint, buffered = true): AsyncSocket =
   ## Creates a new asynchronous socket.
-  result = newSocket(newAsyncRawSocket(domain, typ, protocol), buffered)
+  ##
+  ## This procedure will also create a brand new file descriptor for
+  ## this socket.
+  result = newAsyncSocket(newAsyncRawSocket(domain, typ, protocol), buffered)
 
 when defined(ssl):
   proc getSslError(handle: SslPtr, err: cint): cint =
@@ -275,7 +282,7 @@ proc acceptAddr*(socket: AsyncSocket, flags = {SocketFlag.SafeDisconn}):
         retFuture.fail(future.readError)
       else:
         let resultTup = (future.read.address,
-                         newSocket(future.read.client, socket.isBuffered))
+                         newAsyncSocket(future.read.client, socket.isBuffered))
         retFuture.complete(resultTup)
   return retFuture
 
@@ -399,13 +406,13 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.
 
 proc close*(socket: AsyncSocket) =
   ## Closes the socket.
-  socket.fd.TAsyncFD.closeSocket()
+  defer:
+    socket.fd.TAsyncFD.closeSocket()
   when defined(ssl):
     if socket.isSSL:
       let res = SslShutdown(socket.sslHandle)
       if res == 0:
-        if SslShutdown(socket.sslHandle) != 1:
-          raiseSslError()
+        discard
       elif res != 1:
         raiseSslError()
   socket.closed = true # TODO: Add extra debugging checks for this.
@@ -439,6 +446,18 @@ proc setSockOpt*(socket: AsyncSocket, opt: SOBool, value: bool,
   var valuei = cint(if value: 1 else: 0)
   setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
 
+proc isSsl*(socket: AsyncSocket): bool =
+  ## Determines whether ``socket`` is a SSL socket.
+  socket.isSsl
+
+proc getFd*(socket: AsyncSocket): SocketHandle =
+  ## Returns the socket's file descriptor.
+  return socket.fd
+
+proc isClosed*(socket: AsyncSocket): bool =
+  ## Determines whether the socket has been closed.
+  return socket.closed
+
 when isMainModule:
   type
     TestCases = enum
diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim
index a8709e098..0c5704f69 100644
--- a/lib/pure/complex.nim
+++ b/lib/pure/complex.nim
@@ -19,10 +19,7 @@ import
   math
  
 const
-  EPS = 5.0e-6 ## Epsilon used for float comparisons (should be smaller
-               ## if float is really float64, but w/ the current version
-               ## it seems to be float32?)
-
+  EPS = 1.0e-7 ## Epsilon used for float comparisons.
 
 type
   Complex* = tuple[re, im: float]
diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim
index a1440b6f4..4852ed50d 100644
--- a/lib/pure/htmlgen.nim
+++ b/lib/pure/htmlgen.nim
@@ -264,7 +264,7 @@ macro html*(e: expr): expr {.immediate.} =
   let e = callsite()
   result = xmlCheckedTag(e, "html", "xmlns", "")
 
-macro hr*(e: expr): expr {.immediate.} = 
+macro hr*(): expr {.immediate.} = 
   ## generates the HTML ``hr`` element.
   let e = callsite()
   result = xmlCheckedTag(e, "hr", commonAttr, "", true)
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 3afb625ee..bfdfed72c 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -32,21 +32,12 @@
 ## the server.
 ##
 ## .. code-block:: Nim
-##   var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
-##   var body: string = "--xyz\c\L"
-##   # soap 1.2 output
-##   body.add("Content-Disposition: form-data; name=\"output\"\c\L")
-##   body.add("\c\Lsoap12\c\L")
+##   var data = newMultipartData()
+##   data["output"] = "soap12"
+##   data["uploaded_file"] = ("test.html", "text/html",
+##     "<html><head></head><body><p>test</p></body></html>")
 ##
-##   # html
-##   body.add("--xyz\c\L")
-##   body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
-##            " filename=\"test.html\"\c\L")
-##   body.add("Content-Type: text/html\c\L")
-##   body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
-##   body.add("--xyz--")
-##
-##   echo(postContent("http://validator.w3.org/check", headers, body))
+##   echo postContent("http://validator.w3.org/check", multipart=data)
 ##
 ## Asynchronous HTTP requests
 ## ==========================
@@ -88,7 +79,7 @@
 ## constructor should be used for this purpose. However,
 ## currently only basic authentication is supported.
 
-import net, strutils, uri, parseutils, strtabs, base64, os
+import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math
 import asyncnet, asyncdispatch
 import rawsockets
 
@@ -103,6 +94,10 @@ type
     url*: Uri
     auth*: string
 
+  MultipartEntries* = openarray[tuple[name, content: string]]
+  MultipartData* = ref object
+    content: seq[string]
+
   ProtocolError* = object of IOError   ## exception that is raised when server
                                        ## does not conform to the implemented
                                        ## protocol
@@ -282,6 +277,109 @@ proc newProxy*(url: string, auth = ""): Proxy =
   ## Constructs a new ``TProxy`` object.
   result = Proxy(url: parseUri(url), auth: auth)
 
+proc newMultipartData*: MultipartData =
+  ## Constructs a new ``MultipartData`` object.
+  MultipartData(content: @[])
+
+proc add*(p: var MultipartData, name, content: string, filename: string = nil,
+          contentType: string = nil) =
+  ## Add a value to the multipart data. Raises a `ValueError` exception if
+  ## `name`, `filename` or `contentType` contain newline characters.
+
+  if {'\c','\L'} in name:
+    raise newException(ValueError, "name contains a newline character")
+  if filename != nil and {'\c','\L'} in filename:
+    raise newException(ValueError, "filename contains a newline character")
+  if contentType != nil and {'\c','\L'} in contentType:
+    raise newException(ValueError, "contentType contains a newline character")
+
+  var str = "Content-Disposition: form-data; name=\"" & name & "\""
+  if filename != nil:
+    str.add("; filename=\"" & filename & "\"")
+  str.add("\c\L")
+  if contentType != nil:
+    str.add("Content-Type: " & contentType & "\c\L")
+  str.add("\c\L" & content & "\c\L")
+
+  p.content.add(str)
+
+proc add*(p: var MultipartData, xs: MultipartEntries): MultipartData
+         {.discardable.} =
+  ## Add a list of multipart entries to the multipart data `p`. All values are
+  ## added without a filename and without a content type.
+  ##
+  ## .. code-block:: Nim
+  ##   data.add({"action": "login", "format": "json"})
+  for name, content in xs.items:
+    p.add(name, content)
+  result = p
+
+proc newMultipartData*(xs: MultipartEntries): MultipartData =
+  ## Create a new multipart data object and fill it with the entries `xs`
+  ## directly.
+  ##
+  ## .. code-block:: Nim
+  ##   var data = newMultipartData({"action": "login", "format": "json"})
+  result = MultipartData(content: @[])
+  result.add(xs)
+
+proc addFiles*(p: var MultipartData, xs: openarray[tuple[name, file: string]]):
+              MultipartData {.discardable.} =
+  ## Add files to a multipart data object. The file will be opened from your
+  ## disk, read and sent with the automatically determined MIME type. Raises an
+  ## `IOError` if the file cannot be opened or reading fails. To manually
+  ## specify file content, filename and MIME type, use `[]=` instead.
+  ##
+  ## .. code-block:: Nim
+  ##   data.addFiles({"uploaded_file": "public/test.html"})
+  var m = newMimetypes()
+  for name, file in xs.items:
+    var contentType: string
+    let (dir, fName, ext) = splitFile(file)
+    if ext.len > 0:
+      contentType = m.getMimetype(ext[1..ext.high], nil)
+    p.add(name, readFile(file), fName & ext, contentType)
+  result = p
+
+proc `[]=`*(p: var MultipartData, name, content: string) =
+  ## Add a multipart entry to the multipart data `p`. The value is added
+  ## without a filename and without a content type.
+  ##
+  ## .. code-block:: Nim
+  ##   data["username"] = "NimUser"
+  p.add(name, content)
+
+proc `[]=`*(p: var MultipartData, name: string,
+            file: tuple[name, contentType, content: string]) =
+  ## Add a file to the multipart data `p`, specifying filename, contentType and
+  ## content manually.
+  ##
+  ## .. code-block:: Nim
+  ##   data["uploaded_file"] = ("test.html", "text/html",
+  ##     "<html><head></head><body><p>test</p></body></html>")
+  p.add(name, file.content, file.name, file.contentType)
+
+proc format(p: MultipartData): tuple[header, body: string] =
+  if p == nil or p.content == nil or p.content.len == 0:
+    return ("", "")
+
+  # Create boundary that is not in the data to be formatted
+  var bound: string
+  while true:
+    bound = $random(int.high)
+    var found = false
+    for s in p.content:
+      if bound in s:
+        found = true
+    if not found:
+      break
+
+  result.header = "Content-Type: multipart/form-data; boundary=" & bound & "\c\L"
+  result.body = ""
+  for s in p.content:
+    result.body.add("--" & bound & "\c\L" & s)
+  result.body.add("--" & bound & "--\c\L")
+
 proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
               body = "",
               sslContext: SSLContext = defaultSSLContext,
@@ -294,7 +392,9 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
   var r = if proxy == nil: parseUri(url) else: proxy.url
   var headers = substr($httpMethod, len("http"))
   if proxy == nil:
-    headers.add(" /" & r.path & r.query)
+    headers.add(" " & r.path)
+    if r.query.len > 0:
+      headers.add("?" & r.query)
   else:
     headers.add(" " & url)
 
@@ -387,15 +487,30 @@ proc post*(url: string, extraHeaders = "", body = "",
            maxRedirects = 5,
            sslContext: SSLContext = defaultSSLContext,
            timeout = -1, userAgent = defUserAgent,
-           proxy: Proxy = nil): Response =
+           proxy: Proxy = nil,
+           multipart: MultipartData = nil): Response =
   ## | POSTs ``body`` to the ``url`` and returns a ``Response`` object.
   ## | This proc adds the necessary Content-Length header.
   ## | This proc also handles redirection.
   ## | Extra headers can be specified and must be separated by ``\c\L``.
   ## | An optional timeout can be specified in miliseconds, if reading from the
   ## server takes longer than specified an ETimeout exception will be raised.
-  var xh = extraHeaders & "Content-Length: " & $len(body) & "\c\L"
-  result = request(url, httpPOST, xh, body, sslContext, timeout, userAgent,
+  ## | The optional ``multipart`` parameter can be used to create
+  ## ``multipart/form-data`` POSTs comfortably.
+  let (mpHeaders, mpBody) = format(multipart)
+
+  template withNewLine(x): expr =
+    if x.len > 0 and not x.endsWith("\c\L"):
+      x & "\c\L"
+    else:
+      x
+
+  var xb = mpBody.withNewLine() & body.withNewLine()
+
+  var xh = extraHeaders.withNewLine() & mpHeaders.withNewLine() &
+    withNewLine("Content-Length: " & $len(xb))
+
+  result = request(url, httpPOST, xh, xb, sslContext, timeout, userAgent,
                    proxy)
   var lastUrl = ""
   for i in 1..maxRedirects:
@@ -410,14 +525,17 @@ proc postContent*(url: string, extraHeaders = "", body = "",
                   maxRedirects = 5,
                   sslContext: SSLContext = defaultSSLContext,
                   timeout = -1, userAgent = defUserAgent,
-                  proxy: Proxy = nil): string =
+                  proxy: Proxy = nil,
+                  multipart: MultipartData = nil): string =
   ## | POSTs ``body`` to ``url`` and returns the response's body as a string
   ## | Raises exceptions for the status codes ``4xx`` and ``5xx``
   ## | Extra headers can be specified and must be separated by ``\c\L``.
   ## | An optional timeout can be specified in miliseconds, if reading from the
   ## server takes longer than specified an ETimeout exception will be raised.
+  ## | The optional ``multipart`` parameter can be used to create
+  ## ``multipart/form-data`` POSTs comfortably.
   var r = post(url, extraHeaders, body, maxRedirects, sslContext, timeout,
-               userAgent, proxy)
+               userAgent, proxy, multipart)
   if r.status[0] in {'4','5'}:
     raise newException(HttpRequestError, r.status)
   else:
@@ -442,7 +560,9 @@ proc generateHeaders(r: Uri, httpMethod: HttpMethod,
                      headers: StringTableRef): string =
   result = substr($httpMethod, len("http"))
   # TODO: Proxies
-  result.add(" /" & r.path & r.query)
+  result.add(" " & r.path)
+  if r.query.len > 0:
+    result.add("?" & r.query)
   result.add(" HTTP/1.1\c\L")
 
   add(result, "Host: " & r.hostname & "\c\L")
@@ -706,18 +826,9 @@ when isMainModule:
     #var r = get("http://validator.w3.org/check?uri=http%3A%2F%2Fgoogle.com&
     #  charset=%28detect+automatically%29&doctype=Inline&group=0")
 
-    var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
-    var body: string = "--xyz\c\L"
-    # soap 1.2 output
-    body.add("Content-Disposition: form-data; name=\"output\"\c\L")
-    body.add("\c\Lsoap12\c\L")
-
-    # html
-    body.add("--xyz\c\L")
-    body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
-             " filename=\"test.html\"\c\L")
-    body.add("Content-Type: text/html\c\L")
-    body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
-    body.add("--xyz--")
-
-    echo(postContent("http://validator.w3.org/check", headers, body))
+    var data = newMultipartData()
+    data["output"] = "soap12"
+    data["uploaded_file"] = ("test.html", "text/html",
+      "<html><head></head><body><p>test</p></body></html>")
+
+    echo postContent("http://validator.w3.org/check", multipart=data)
diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim
index 3b5453957..c6228af50 100644
--- a/lib/pure/md5.nim
+++ b/lib/pure/md5.nim
@@ -9,18 +9,20 @@
 
 ## Module for computing MD5 checksums.
 
-type 
-  MD5State = array[0..3, int32]
-  MD5Block = array[0..15, int32]
-  MD5CBits = array[0..7, int8]
-  MD5Digest* = array[0..15, int8]
-  MD5Buffer = array[0..63, int8]
-  MD5Context* {.final.} = object 
+import unsigned
+
+type
+  MD5State = array[0..3, uint32]
+  MD5Block = array[0..15, uint32]
+  MD5CBits = array[0..7, uint8]
+  MD5Digest* = array[0..15, uint8]
+  MD5Buffer = array[0..63, uint8]
+  MD5Context* {.final.} = object
     state: MD5State
-    count: array[0..1, int32]
+    count: array[0..1, uint32]
     buffer: MD5Buffer
 
-const 
+const
   padding: cstring = "\x80\0\0\0" &
                      "\0\0\0\0\0\0\0\0" &
                      "\0\0\0\0\0\0\0\0" &
@@ -31,60 +33,60 @@ const
                      "\0\0\0\0\0\0\0\0" &
                      "\0\0\0\0"
 
-proc F(x, y, z: int32): int32 {.inline.} = 
+proc F(x, y, z: uint32): uint32 {.inline.} =
   result = (x and y) or ((not x) and z)
 
-proc G(x, y, z: int32): int32 {.inline.} = 
+proc G(x, y, z: uint32): uint32 {.inline.} =
   result = (x and z) or (y and (not z))
 
-proc H(x, y, z: int32): int32 {.inline.} = 
+proc H(x, y, z: uint32): uint32 {.inline.} =
   result = x xor y xor z
 
-proc I(x, y, z: int32): int32 {.inline.} = 
+proc I(x, y, z: uint32): uint32 {.inline.} =
   result = y xor (x or (not z))
 
-proc rot(x: var int32, n: int8) {.inline.} = 
-  x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n)))
+proc rot(x: var uint32, n: uint8) {.inline.} =
+  x = (x shl n) or (x shr (32'u32 - n))
 
-proc FF(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% F(b, c, d) +% x +% ac
+proc FF(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + F(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc GG(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% G(b, c, d) +% x +% ac
+proc GG(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + G(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc HH(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% H(b, c, d) +% x +% ac
+proc HH(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + H(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc II(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = 
-  a = a +% I(b, c, d) +% x +% ac
+proc II(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
+  a = a + I(b, c, d) + x + ac
   rot(a, s)
-  a = a +% b
+  a = a + b
 
-proc encode(dest: var MD5Block, src: cstring) = 
+proc encode(dest: var MD5Block, src: cstring) =
   var j = 0
   for i in 0..high(dest):
-    dest[i] = toU32(ord(src[j]) or 
-                ord(src[j+1]) shl 8 or
-                ord(src[j+2]) shl 16 or
-                ord(src[j+3]) shl 24)
+    dest[i] = uint32(ord(src[j])) or
+              uint32(ord(src[j+1])) shl 8 or
+              uint32(ord(src[j+2])) shl 16 or
+              uint32(ord(src[j+3])) shl 24
     inc(j, 4)
 
-proc decode(dest: var openArray[int8], src: openArray[int32]) = 
+proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
   var i = 0
   for j in 0..high(src):
-    dest[i] = toU8(src[j] and 0xff'i32)
-    dest[i+1] = toU8(src[j] shr 8'i32 and 0xff'i32)
-    dest[i+2] = toU8(src[j] shr 16'i32 and 0xff'i32)
-    dest[i+3] = toU8(src[j] shr 24'i32 and 0xff'i32)
+    dest[i] = src[j] and 0xff'u32
+    dest[i+1] = src[j] shr 8 and 0xff'u32
+    dest[i+2] = src[j] shr 16 and 0xff'u32
+    dest[i+3] = src[j] shr 24 and 0xff'u32
     inc(i, 4)
 
-proc transform(buffer: pointer, state: var MD5State) = 
+proc transform(buffer: pointer, state: var MD5State) =
   var
     myBlock: MD5Block
   encode(myBlock, cast[cstring](buffer))
@@ -92,111 +94,111 @@ proc transform(buffer: pointer, state: var MD5State) =
   var b = state[1]
   var c = state[2]
   var d = state[3]
-  FF(a, b, c, d, myBlock[0], 7'i8, 0xD76AA478'i32)
-  FF(d, a, b, c, myBlock[1], 12'i8, 0xE8C7B756'i32)
-  FF(c, d, a, b, myBlock[2], 17'i8, 0x242070DB'i32)
-  FF(b, c, d, a, myBlock[3], 22'i8, 0xC1BDCEEE'i32)
-  FF(a, b, c, d, myBlock[4], 7'i8, 0xF57C0FAF'i32)
-  FF(d, a, b, c, myBlock[5], 12'i8, 0x4787C62A'i32)
-  FF(c, d, a, b, myBlock[6], 17'i8, 0xA8304613'i32)
-  FF(b, c, d, a, myBlock[7], 22'i8, 0xFD469501'i32)
-  FF(a, b, c, d, myBlock[8], 7'i8, 0x698098D8'i32)
-  FF(d, a, b, c, myBlock[9], 12'i8, 0x8B44F7AF'i32)
-  FF(c, d, a, b, myBlock[10], 17'i8, 0xFFFF5BB1'i32)
-  FF(b, c, d, a, myBlock[11], 22'i8, 0x895CD7BE'i32)
-  FF(a, b, c, d, myBlock[12], 7'i8, 0x6B901122'i32)
-  FF(d, a, b, c, myBlock[13], 12'i8, 0xFD987193'i32)
-  FF(c, d, a, b, myBlock[14], 17'i8, 0xA679438E'i32)
-  FF(b, c, d, a, myBlock[15], 22'i8, 0x49B40821'i32)
-  GG(a, b, c, d, myBlock[1], 5'i8, 0xF61E2562'i32)
-  GG(d, a, b, c, myBlock[6], 9'i8, 0xC040B340'i32)
-  GG(c, d, a, b, myBlock[11], 14'i8, 0x265E5A51'i32)
-  GG(b, c, d, a, myBlock[0], 20'i8, 0xE9B6C7AA'i32)
-  GG(a, b, c, d, myBlock[5], 5'i8, 0xD62F105D'i32)
-  GG(d, a, b, c, myBlock[10], 9'i8, 0x02441453'i32)
-  GG(c, d, a, b, myBlock[15], 14'i8, 0xD8A1E681'i32)
-  GG(b, c, d, a, myBlock[4], 20'i8, 0xE7D3FBC8'i32)
-  GG(a, b, c, d, myBlock[9], 5'i8, 0x21E1CDE6'i32)
-  GG(d, a, b, c, myBlock[14], 9'i8, 0xC33707D6'i32)
-  GG(c, d, a, b, myBlock[3], 14'i8, 0xF4D50D87'i32)
-  GG(b, c, d, a, myBlock[8], 20'i8, 0x455A14ED'i32)
-  GG(a, b, c, d, myBlock[13], 5'i8, 0xA9E3E905'i32)
-  GG(d, a, b, c, myBlock[2], 9'i8, 0xFCEFA3F8'i32)
-  GG(c, d, a, b, myBlock[7], 14'i8, 0x676F02D9'i32)
-  GG(b, c, d, a, myBlock[12], 20'i8, 0x8D2A4C8A'i32)
-  HH(a, b, c, d, myBlock[5], 4'i8, 0xFFFA3942'i32)
-  HH(d, a, b, c, myBlock[8], 11'i8, 0x8771F681'i32)
-  HH(c, d, a, b, myBlock[11], 16'i8, 0x6D9D6122'i32)
-  HH(b, c, d, a, myBlock[14], 23'i8, 0xFDE5380C'i32)
-  HH(a, b, c, d, myBlock[1], 4'i8, 0xA4BEEA44'i32)
-  HH(d, a, b, c, myBlock[4], 11'i8, 0x4BDECFA9'i32)
-  HH(c, d, a, b, myBlock[7], 16'i8, 0xF6BB4B60'i32)
-  HH(b, c, d, a, myBlock[10], 23'i8, 0xBEBFBC70'i32)
-  HH(a, b, c, d, myBlock[13], 4'i8, 0x289B7EC6'i32)
-  HH(d, a, b, c, myBlock[0], 11'i8, 0xEAA127FA'i32)
-  HH(c, d, a, b, myBlock[3], 16'i8, 0xD4EF3085'i32)
-  HH(b, c, d, a, myBlock[6], 23'i8, 0x04881D05'i32)
-  HH(a, b, c, d, myBlock[9], 4'i8, 0xD9D4D039'i32)
-  HH(d, a, b, c, myBlock[12], 11'i8, 0xE6DB99E5'i32)
-  HH(c, d, a, b, myBlock[15], 16'i8, 0x1FA27CF8'i32)
-  HH(b, c, d, a, myBlock[2], 23'i8, 0xC4AC5665'i32)
-  II(a, b, c, d, myBlock[0], 6'i8, 0xF4292244'i32)
-  II(d, a, b, c, myBlock[7], 10'i8, 0x432AFF97'i32)
-  II(c, d, a, b, myBlock[14], 15'i8, 0xAB9423A7'i32)
-  II(b, c, d, a, myBlock[5], 21'i8, 0xFC93A039'i32)
-  II(a, b, c, d, myBlock[12], 6'i8, 0x655B59C3'i32)
-  II(d, a, b, c, myBlock[3], 10'i8, 0x8F0CCC92'i32)
-  II(c, d, a, b, myBlock[10], 15'i8, 0xFFEFF47D'i32)
-  II(b, c, d, a, myBlock[1], 21'i8, 0x85845DD1'i32)
-  II(a, b, c, d, myBlock[8], 6'i8, 0x6FA87E4F'i32)
-  II(d, a, b, c, myBlock[15], 10'i8, 0xFE2CE6E0'i32)
-  II(c, d, a, b, myBlock[6], 15'i8, 0xA3014314'i32)
-  II(b, c, d, a, myBlock[13], 21'i8, 0x4E0811A1'i32)
-  II(a, b, c, d, myBlock[4], 6'i8, 0xF7537E82'i32)
-  II(d, a, b, c, myBlock[11], 10'i8, 0xBD3AF235'i32)
-  II(c, d, a, b, myBlock[2], 15'i8, 0x2AD7D2BB'i32)
-  II(b, c, d, a, myBlock[9], 21'i8, 0xEB86D391'i32)
-  state[0] = state[0] +% a
-  state[1] = state[1] +% b
-  state[2] = state[2] +% c
-  state[3] = state[3] +% d
-  
-proc md5Init*(c: var MD5Context) = 
-  ## initializes a MD5Context  
-  c.state[0] = 0x67452301'i32
-  c.state[1] = 0xEFCDAB89'i32
-  c.state[2] = 0x98BADCFE'i32
-  c.state[3] = 0x10325476'i32
-  c.count[0] = 0'i32
-  c.count[1] = 0'i32
+  FF(a, b, c, d, myBlock[0], 7'u8, 0xD76AA478'u32)
+  FF(d, a, b, c, myBlock[1], 12'u8, 0xE8C7B756'u32)
+  FF(c, d, a, b, myBlock[2], 17'u8, 0x242070DB'u32)
+  FF(b, c, d, a, myBlock[3], 22'u8, 0xC1BDCEEE'u32)
+  FF(a, b, c, d, myBlock[4], 7'u8, 0xF57C0FAF'u32)
+  FF(d, a, b, c, myBlock[5], 12'u8, 0x4787C62A'u32)
+  FF(c, d, a, b, myBlock[6], 17'u8, 0xA8304613'u32)
+  FF(b, c, d, a, myBlock[7], 22'u8, 0xFD469501'u32)
+  FF(a, b, c, d, myBlock[8], 7'u8, 0x698098D8'u32)
+  FF(d, a, b, c, myBlock[9], 12'u8, 0x8B44F7AF'u32)
+  FF(c, d, a, b, myBlock[10], 17'u8, 0xFFFF5BB1'u32)
+  FF(b, c, d, a, myBlock[11], 22'u8, 0x895CD7BE'u32)
+  FF(a, b, c, d, myBlock[12], 7'u8, 0x6B901122'u32)
+  FF(d, a, b, c, myBlock[13], 12'u8, 0xFD987193'u32)
+  FF(c, d, a, b, myBlock[14], 17'u8, 0xA679438E'u32)
+  FF(b, c, d, a, myBlock[15], 22'u8, 0x49B40821'u32)
+  GG(a, b, c, d, myBlock[1], 5'u8, 0xF61E2562'u32)
+  GG(d, a, b, c, myBlock[6], 9'u8, 0xC040B340'u32)
+  GG(c, d, a, b, myBlock[11], 14'u8, 0x265E5A51'u32)
+  GG(b, c, d, a, myBlock[0], 20'u8, 0xE9B6C7AA'u32)
+  GG(a, b, c, d, myBlock[5], 5'u8, 0xD62F105D'u32)
+  GG(d, a, b, c, myBlock[10], 9'u8, 0x02441453'u32)
+  GG(c, d, a, b, myBlock[15], 14'u8, 0xD8A1E681'u32)
+  GG(b, c, d, a, myBlock[4], 20'u8, 0xE7D3FBC8'u32)
+  GG(a, b, c, d, myBlock[9], 5'u8, 0x21E1CDE6'u32)
+  GG(d, a, b, c, myBlock[14], 9'u8, 0xC33707D6'u32)
+  GG(c, d, a, b, myBlock[3], 14'u8, 0xF4D50D87'u32)
+  GG(b, c, d, a, myBlock[8], 20'u8, 0x455A14ED'u32)
+  GG(a, b, c, d, myBlock[13], 5'u8, 0xA9E3E905'u32)
+  GG(d, a, b, c, myBlock[2], 9'u8, 0xFCEFA3F8'u32)
+  GG(c, d, a, b, myBlock[7], 14'u8, 0x676F02D9'u32)
+  GG(b, c, d, a, myBlock[12], 20'u8, 0x8D2A4C8A'u32)
+  HH(a, b, c, d, myBlock[5], 4'u8, 0xFFFA3942'u32)
+  HH(d, a, b, c, myBlock[8], 11'u8, 0x8771F681'u32)
+  HH(c, d, a, b, myBlock[11], 16'u8, 0x6D9D6122'u32)
+  HH(b, c, d, a, myBlock[14], 23'u8, 0xFDE5380C'u32)
+  HH(a, b, c, d, myBlock[1], 4'u8, 0xA4BEEA44'u32)
+  HH(d, a, b, c, myBlock[4], 11'u8, 0x4BDECFA9'u32)
+  HH(c, d, a, b, myBlock[7], 16'u8, 0xF6BB4B60'u32)
+  HH(b, c, d, a, myBlock[10], 23'u8, 0xBEBFBC70'u32)
+  HH(a, b, c, d, myBlock[13], 4'u8, 0x289B7EC6'u32)
+  HH(d, a, b, c, myBlock[0], 11'u8, 0xEAA127FA'u32)
+  HH(c, d, a, b, myBlock[3], 16'u8, 0xD4EF3085'u32)
+  HH(b, c, d, a, myBlock[6], 23'u8, 0x04881D05'u32)
+  HH(a, b, c, d, myBlock[9], 4'u8, 0xD9D4D039'u32)
+  HH(d, a, b, c, myBlock[12], 11'u8, 0xE6DB99E5'u32)
+  HH(c, d, a, b, myBlock[15], 16'u8, 0x1FA27CF8'u32)
+  HH(b, c, d, a, myBlock[2], 23'u8, 0xC4AC5665'u32)
+  II(a, b, c, d, myBlock[0], 6'u8, 0xF4292244'u32)
+  II(d, a, b, c, myBlock[7], 10'u8, 0x432AFF97'u32)
+  II(c, d, a, b, myBlock[14], 15'u8, 0xAB9423A7'u32)
+  II(b, c, d, a, myBlock[5], 21'u8, 0xFC93A039'u32)
+  II(a, b, c, d, myBlock[12], 6'u8, 0x655B59C3'u32)
+  II(d, a, b, c, myBlock[3], 10'u8, 0x8F0CCC92'u32)
+  II(c, d, a, b, myBlock[10], 15'u8, 0xFFEFF47D'u32)
+  II(b, c, d, a, myBlock[1], 21'u8, 0x85845DD1'u32)
+  II(a, b, c, d, myBlock[8], 6'u8, 0x6FA87E4F'u32)
+  II(d, a, b, c, myBlock[15], 10'u8, 0xFE2CE6E0'u32)
+  II(c, d, a, b, myBlock[6], 15'u8, 0xA3014314'u32)
+  II(b, c, d, a, myBlock[13], 21'u8, 0x4E0811A1'u32)
+  II(a, b, c, d, myBlock[4], 6'u8, 0xF7537E82'u32)
+  II(d, a, b, c, myBlock[11], 10'u8, 0xBD3AF235'u32)
+  II(c, d, a, b, myBlock[2], 15'u8, 0x2AD7D2BB'u32)
+  II(b, c, d, a, myBlock[9], 21'u8, 0xEB86D391'u32)
+  state[0] = state[0] + a
+  state[1] = state[1] + b
+  state[2] = state[2] + c
+  state[3] = state[3] + d
+
+proc md5Init*(c: var MD5Context) =
+  ## initializes a MD5Context
+  c.state[0] = 0x67452301'u32
+  c.state[1] = 0xEFCDAB89'u32
+  c.state[2] = 0x98BADCFE'u32
+  c.state[3] = 0x10325476'u32
+  c.count[0] = 0'u32
+  c.count[1] = 0'u32
   zeroMem(addr(c.buffer), sizeof(MD5buffer))
 
-proc md5Update*(c: var MD5Context, input: cstring, len: int) = 
+proc md5Update*(c: var MD5Context, input: cstring, len: int) =
   ## updates the MD5Context with the `input` data of length `len`
   var input = input
-  var Index = (c.count[0] shr 3) and 0x3F
-  c.count[0] = c.count[0] +% toU32(len shl 3)
-  if c.count[0] < (len shl 3): c.count[1] = c.count[1] +% 1'i32
-  c.count[1] = c.count[1] +% toU32(len shr 29)
+  var Index = int((c.count[0] shr 3) and 0x3F)
+  c.count[0] = c.count[0] + (uint32(len) shl 3)
+  if c.count[0] < (uint32(len) shl 3): c.count[1] = c.count[1] + 1'u32
+  c.count[1] = c.count[1] + (uint32(len) shr 29)
   var PartLen = 64 - Index
-  if len >= PartLen: 
+  if len >= PartLen:
     copyMem(addr(c.buffer[Index]), input, PartLen)
     transform(addr(c.buffer), c.state)
     var i = PartLen
-    while i + 63 < len: 
+    while i + 63 < len:
       transform(addr(input[i]), c.state)
       inc(i, 64)
     copyMem(addr(c.buffer[0]), addr(input[i]), len-i)
   else:
     copyMem(addr(c.buffer[Index]), addr(input[0]), len)
 
-proc md5Final*(c: var MD5Context, digest: var MD5Digest) = 
+proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
   ## finishes the MD5Context and stores the result in `digest`
   var
     Bits: MD5CBits
     PadLen: int
   decode(Bits, c.count)
-  var Index = (c.count[0] shr 3) and 0x3F
+  var Index = int((c.count[0] shr 3) and 0x3F)
   if Index < 56: PadLen = 56 - Index
   else: PadLen = 120 - Index
   md5Update(c, padding, PadLen)
@@ -204,34 +206,34 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
   decode(digest, c.state)
   zeroMem(addr(c), sizeof(MD5Context))
 
-proc toMD5*(s: string): MD5Digest = 
+proc toMD5*(s: string): MD5Digest =
   ## computes the MD5Digest value for a string `s`
   var c: MD5Context
   md5Init(c)
   md5Update(c, cstring(s), len(s))
   md5Final(c, result)
-  
-proc `$`*(D: MD5Digest): string = 
+
+proc `$`*(D: MD5Digest): string =
   ## converts a MD5Digest value into its string representation
   const digits = "0123456789abcdef"
   result = ""
-  for i in 0..15: 
+  for i in 0..15:
     add(result, digits[(D[i] shr 4) and 0xF])
     add(result, digits[D[i] and 0xF])
 
-proc getMD5*(s: string): string =  
+proc getMD5*(s: string): string =
   ## computes an MD5 value of `s` and returns its string representation
-  var 
+  var
     c: MD5Context
     d: MD5Digest
   md5Init(c)
   md5Update(c, cstring(s), len(s))
   md5Final(c, d)
   result = $d
-  
-proc `==`*(D1, D2: MD5Digest): bool =  
+
+proc `==`*(D1, D2: MD5Digest): bool =
   ## checks if two MD5Digest values are identical
-  for i in 0..15: 
+  for i in 0..15:
     if D1[i] != D2[i]: return false
   return true
 
@@ -241,5 +243,3 @@ when isMainModule:
   assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
     "7e716d0e702df0505fc72e2b89467910")
   assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")
-
-
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 28b84eb39..e6fe79740 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -44,21 +44,21 @@ const
 
 type
   SocketImpl* = object ## socket type
-    fd*: SocketHandle
-    case isBuffered*: bool # determines whether this socket is buffered.
+    fd: SocketHandle
+    case isBuffered: bool # determines whether this socket is buffered.
     of true:
-      buffer*: array[0..BufferSize, char]
-      currPos*: int # current index in buffer
-      bufLen*: int # current length of buffer
+      buffer: array[0..BufferSize, char]
+      currPos: int # current index in buffer
+      bufLen: int # current length of buffer
     of false: nil
     when defined(ssl):
-      case isSsl*: bool
+      case isSsl: bool
       of true:
-        sslHandle*: SSLPtr
-        sslContext*: SSLContext
-        sslNoHandshake*: bool # True if needs handshake.
-        sslHasPeekChar*: bool
-        sslPeekChar*: char
+        sslHandle: SSLPtr
+        sslContext: SSLContext
+        sslNoHandshake: bool # True if needs handshake.
+        sslHasPeekChar: bool
+        sslPeekChar: char
       of false: nil
   
   Socket* = ref SocketImpl
@@ -100,7 +100,8 @@ proc toOSFlags*(socketFlags: set[SocketFlag]): cint =
       result = result or MSG_PEEK
     of SocketFlag.SafeDisconn: continue
 
-proc createSocket(fd: SocketHandle, isBuff: bool): Socket =
+proc newSocket(fd: SocketHandle, isBuff: bool): Socket =
+  ## Creates a new socket as specified by the params.
   assert fd != osInvalidSocket
   new(result)
   result.fd = fd
@@ -115,7 +116,7 @@ proc newSocket*(domain, typ, protocol: cint, buffered = true): Socket =
   let fd = newRawSocket(domain, typ, protocol)
   if fd == osInvalidSocket:
     raiseOSError(osLastError())
-  result = createSocket(fd, buffered)
+  result = newSocket(fd, buffered)
 
 proc newSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
              protocol: Protocol = IPPROTO_TCP, buffered = true): Socket =
@@ -125,7 +126,7 @@ proc newSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
   let fd = newRawSocket(domain, typ, protocol)
   if fd == osInvalidSocket:
     raiseOSError(osLastError())
-  result = createSocket(fd, buffered)
+  result = newSocket(fd, buffered)
 
 when defined(ssl):
   CRYPTO_malloc_init()
@@ -937,10 +938,10 @@ proc connect*(socket: Socket, address: string, port = Port(0), timeout: int,
         doAssert socket.handshake()
   socket.fd.setBlocking(true)
 
-proc isSSL*(socket: Socket): bool = return socket.isSSL
+proc isSsl*(socket: Socket): bool = return socket.isSSL
   ## Determines whether ``socket`` is a SSL socket.
 
-proc getFD*(socket: Socket): SocketHandle = return socket.fd
+proc getFd*(socket: Socket): SocketHandle = return socket.fd
   ## Returns the socket's file descriptor
 
 type
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 004287d39..ad82dc682 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -575,7 +575,7 @@ proc `/` * (head, tail: string): string {.noSideEffect.} =
 proc splitPath*(path: string): tuple[head, tail: string] {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Splits a directory into (head, tail), so that
-  ## ``joinPath(head, tail) == path``.
+  ## ``head / tail == path`` (except for edge cases like "/usr").
   ##
   ## Examples:
   ##
diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim
index 32e69b89a..f27cd8c12 100644
--- a/lib/pure/parseurl.nim
+++ b/lib/pure/parseurl.nim
@@ -7,10 +7,12 @@
 #    distribution, for details about the copyright.
 #
 
-## Parses & constructs URLs.
+## **Warnings:** This module is deprecated since version 0.10.2.
+## Use the `uri <uri.html>`_ module instead.
 ##
-## **Note**: This module will be deprecated in the future and merged into a
-## new ``url`` module.
+## Parses & constructs URLs.
+
+{.deprecated.}
 
 import strutils
 
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 8b7554661..7cef0a00d 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -1433,7 +1433,7 @@ proc eat(p: var PegParser, kind: TTokKind) =
   if p.tok.kind == kind: getTok(p)
   else: pegError(p, tokKindToStr[kind] & " expected")
 
-proc parseExpr(p: var PegParser): Peg
+proc parseExpr(p: var PegParser): Peg {.gcsafe.}
 
 proc getNonTerminal(p: var PegParser, name: string): NonTerminal =
   for i in 0..high(p.nonterms):
diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim
index 62a011999..e23deea5b 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/rawsockets.nim
@@ -428,6 +428,10 @@ proc selectWrite*(writefds: var seq[SocketHandle],
   
   pruneSocketSet(writefds, (wr))
 
+# We ignore signal SIGPIPE on Darwin
+when defined(macosx):
+  signal(SIGPIPE, SIG_IGN)
+
 when defined(Windows):
   var wsa: WSAData
   if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError())
diff --git a/lib/pure/rawsockets.pretty.nim b/lib/pure/rawsockets.pretty.nim
new file mode 100644
index 000000000..46bfba9e7
--- /dev/null
+++ b/lib/pure/rawsockets.pretty.nim
@@ -0,0 +1,426 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements a low-level cross-platform sockets interface. Look
+## at the ``net`` module for the higher-level version.
+
+# TODO: Clean up the exports a bit and everything else in general.
+
+import unsigned, os
+
+when hostOS == "solaris":
+  {.passl: "-lsocket -lnsl".}
+
+const useWinVersion = defined(Windows) or defined(nimdoc)
+
+when useWinVersion:
+  import winlean
+  export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
+         WSAEDISCON, ERROR_NETNAME_DELETED
+else:
+  import posix
+  export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,
+    EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET
+
+export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
+  inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto
+
+export
+  SO_ERROR,
+  SOL_SOCKET,
+  SOMAXCONN,
+  SO_ACCEPTCONN, SO_BROADCAST, SO_DEBUG, SO_DONTROUTE,
+  SO_KEEPALIVE, SO_OOBINLINE, SO_REUSEADDR,
+  MSG_PEEK
+
+type
+  Port* = distinct uint16  ## port type
+  
+  Domain* = enum    ## domain, which specifies the protocol family of the
+                    ## created socket. Other domains than those that are listed
+                    ## here are unsupported.
+    AF_UNIX,        ## for local socket (using a file). Unsupported on Windows.
+    AF_INET = 2,    ## for network protocol IPv4 or
+    AF_INET6 = 23   ## for network protocol IPv6.
+
+  SockType* = enum     ## second argument to `socket` proc
+    SOCK_STREAM = 1,   ## reliable stream-oriented service or Stream Sockets
+    SOCK_DGRAM = 2,    ## datagram service or Datagram Sockets
+    SOCK_RAW = 3,      ## raw protocols atop the network layer.
+    SOCK_SEQPACKET = 5 ## reliable sequenced packet service
+
+  Protocol* = enum      ## third argument to `socket` proc
+    IPPROTO_TCP = 6,    ## Transmission control protocol. 
+    IPPROTO_UDP = 17,   ## User datagram protocol.
+    IPPROTO_IP,         ## Internet protocol. Unsupported on Windows.
+    IPPROTO_IPV6,       ## Internet Protocol Version 6. Unsupported on Windows.
+    IPPROTO_RAW,        ## Raw IP Packets Protocol. Unsupported on Windows.
+    IPPROTO_ICMP        ## Control message protocol. Unsupported on Windows.
+
+  Servent* = object ## information about a service
+    name*: string
+    aliases*: seq[string]
+    port*: Port
+    proto*: string
+
+  Hostent* = object ## information about a given host
+    name*: string
+    aliases*: seq[string]
+    addrtype*: Domain
+    length*: int
+    addrList*: seq[string]
+
+{.deprecated: [TPort: Port, TDomain: Domain, TType: SockType,
+    TProtocol: Protocol, TServent: Servent, THostent: Hostent].}
+
+when useWinVersion:
+  let
+    osInvalidSocket* = winlean.INVALID_SOCKET
+
+  const
+    IOCPARM_MASK* = 127
+    IOC_IN* = int(-2147483648)
+    FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or 
+                             (102 shl 8) or 126
+
+  proc ioctlsocket*(s: SocketHandle, cmd: clong, 
+                   argptr: ptr clong): cint {.
+                   stdcall, importc: "ioctlsocket", dynlib: "ws2_32.dll".}
+else:
+  let
+    osInvalidSocket* = posix.INVALID_SOCKET
+
+proc `==`*(a, b: Port): bool {.borrow.}
+  ## ``==`` for ports.
+
+proc `$`*(p: Port): string {.borrow.}
+  ## returns the port number as a string
+
+proc toInt*(domain: Domain): cint
+  ## Converts the TDomain enum to a platform-dependent ``cint``.
+
+proc toInt*(typ: SockType): cint
+  ## Converts the TType enum to a platform-dependent ``cint``.
+
+proc toInt*(p: Protocol): cint
+  ## Converts the TProtocol enum to a platform-dependent ``cint``.
+
+when not useWinVersion:
+  proc toInt(domain: Domain): cint =
+    case domain
+    of AF_UNIX:        result = posix.AF_UNIX
+    of AF_INET:        result = posix.AF_INET
+    of AF_INET6:       result = posix.AF_INET6
+    else: discard
+
+  proc toInt(typ: SockType): cint =
+    case typ
+    of SOCK_STREAM:    result = posix.SOCK_STREAM
+    of SOCK_DGRAM:     result = posix.SOCK_DGRAM
+    of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
+    of SOCK_RAW:       result = posix.SOCK_RAW
+    else: discard
+
+  proc toInt(p: Protocol): cint =
+    case p
+    of IPPROTO_TCP:    result = posix.IPPROTO_TCP
+    of IPPROTO_UDP:    result = posix.IPPROTO_UDP
+    of IPPROTO_IP:     result = posix.IPPROTO_IP
+    of IPPROTO_IPV6:   result = posix.IPPROTO_IPV6
+    of IPPROTO_RAW:    result = posix.IPPROTO_RAW
+    of IPPROTO_ICMP:   result = posix.IPPROTO_ICMP
+    else: discard
+
+else:
+  proc toInt(domain: Domain): cint = 
+    result = toU16(ord(domain))
+
+  proc toInt(typ: SockType): cint =
+    result = cint(ord(typ))
+  
+  proc toInt(p: Protocol): cint =
+    result = cint(ord(p))
+
+
+proc newRawSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
+             protocol: Protocol = IPPROTO_TCP): SocketHandle =
+  ## Creates a new socket; returns `InvalidSocket` if an error occurs.
+  socket(toInt(domain), toInt(typ), toInt(protocol))
+
+proc close*(socket: SocketHandle) =
+  ## closes a socket.
+  when useWinVersion:
+    discard winlean.closesocket(socket)
+  else:
+    discard posix.close(socket)
+  # TODO: These values should not be discarded. An EOS should be raised.
+  # http://stackoverflow.com/questions/12463473/what-happens-if-you-call-close-on-a-bsd-socket-multiple-times
+
+proc bindAddr*(socket: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint =
+  result = bindSocket(socket, name, namelen)
+
+proc listen*(socket: SocketHandle, backlog = SOMAXCONN): cint {.tags: [ReadIOEffect].} =
+  ## Marks ``socket`` as accepting connections. 
+  ## ``Backlog`` specifies the maximum length of the 
+  ## queue of pending connections.
+  when useWinVersion:
+    result = winlean.listen(socket, cint(backlog))
+  else:
+    result = posix.listen(socket, cint(backlog))
+
+proc getAddrInfo*(address: string, port: Port, af: Domain = AF_INET, typ: SockType = SOCK_STREAM,
+                 prot: Protocol = IPPROTO_TCP): ptr AddrInfo =
+  ##
+  ##
+  ## **Warning**: The resulting ``ptr TAddrInfo`` must be freed using ``dealloc``!
+  var hints: AddrInfo
+  result = nil
+  hints.ai_family = toInt(af)
+  hints.ai_socktype = toInt(typ)
+  hints.ai_protocol = toInt(prot)
+  var gaiResult = getaddrinfo(address, $port, addr(hints), result)
+  if gaiResult != 0'i32:
+    when useWinVersion:
+      raiseOSError(osLastError())
+    else:
+      raise newException(OSError, $gai_strerror(gaiResult))
+
+proc dealloc*(ai: ptr AddrInfo) =
+  freeaddrinfo(ai)
+
+proc ntohl*(x: int32): int32 = 
+  ## Converts 32-bit integers from network to host byte order.
+  ## On machines where the host byte order is the same as network byte order,
+  ## this is a no-op; otherwise, it performs a 4-byte swap operation.
+  when cpuEndian == bigEndian: result = x
+  else: result = (x shr 24'i32) or
+                 (x shr 8'i32 and 0xff00'i32) or
+                 (x shl 8'i32 and 0xff0000'i32) or
+                 (x shl 24'i32)
+
+proc ntohs*(x: int16): int16 =
+  ## Converts 16-bit integers from network to host byte order. On machines
+  ## where the host byte order is the same as network byte order, this is
+  ## a no-op; otherwise, it performs a 2-byte swap operation.
+  when cpuEndian == bigEndian: result = x
+  else: result = (x shr 8'i16) or (x shl 8'i16)
+
+proc htonl*(x: int32): int32 =
+  ## Converts 32-bit integers from host to network byte order. On machines
+  ## where the host byte order is the same as network byte order, this is
+  ## a no-op; otherwise, it performs a 4-byte swap operation.
+  result = rawsockets.ntohl(x)
+
+proc htons*(x: int16): int16 =
+  ## Converts 16-bit positive integers from host to network byte order.
+  ## On machines where the host byte order is the same as network byte
+  ## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
+  result = rawsockets.ntohs(x)
+
+proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
+  ## Searches the database from the beginning and finds the first entry for 
+  ## which the service name specified by ``name`` matches the s_name member
+  ## and the protocol name specified by ``proto`` matches the s_proto member.
+  ##
+  ## On posix this will search through the ``/etc/services`` file.
+  when useWinVersion:
+    var s = winlean.getservbyname(name, proto)
+  else:
+    var s = posix.getservbyname(name, proto)
+  if s == nil: raise newException(OSError, "Service not found.")
+  result.name = $s.s_name
+  result.aliases = cstringArrayToSeq(s.s_aliases)
+  result.port = Port(s.s_port)
+  result.proto = $s.s_proto
+  
+proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].} = 
+  ## Searches the database from the beginning and finds the first entry for 
+  ## which the port specified by ``port`` matches the s_port member and the 
+  ## protocol name specified by ``proto`` matches the s_proto member.
+  ##
+  ## On posix this will search through the ``/etc/services`` file.
+  when useWinVersion:
+    var s = winlean.getservbyport(ze(int16(port)).cint, proto)
+  else:
+    var s = posix.getservbyport(ze(int16(port)).cint, proto)
+  if s == nil: raise newException(OSError, "Service not found.")
+  result.name = $s.s_name
+  result.aliases = cstringArrayToSeq(s.s_aliases)
+  result.port = Port(s.s_port)
+  result.proto = $s.s_proto
+
+proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
+  ## This function will lookup the hostname of an IP Address.
+  var myaddr: InAddr
+  myaddr.s_addr = inet_addr(ip)
+  
+  when useWinVersion:
+    var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
+                                  cint(rawsockets.AF_INET))
+    if s == nil: raiseOSError(osLastError())
+  else:
+    var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, 
+                                cint(posix.AF_INET))
+    if s == nil:
+      raise newException(OSError, $hstrerror(h_errno))
+  
+  result.name = $s.h_name
+  result.aliases = cstringArrayToSeq(s.h_aliases)
+  when useWinVersion:
+    result.addrtype = Domain(s.h_addrtype)
+  else:
+    if s.h_addrtype == posix.AF_INET:
+      result.addrtype = AF_INET
+    elif s.h_addrtype == posix.AF_INET6:
+      result.addrtype = AF_INET6
+    else:
+      raise newException(OSError, "unknown h_addrtype")
+  result.addrList = cstringArrayToSeq(s.h_addr_list)
+  result.length = int(s.h_length)
+
+proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = 
+  ## This function will lookup the IP address of a hostname.
+  when useWinVersion:
+    var s = winlean.gethostbyname(name)
+  else:
+    var s = posix.gethostbyname(name)
+  if s == nil: raiseOSError(osLastError())
+  result.name = $s.h_name
+  result.aliases = cstringArrayToSeq(s.h_aliases)
+  when useWinVersion:
+    result.addrtype = Domain(s.h_addrtype)
+  else:
+    if s.h_addrtype == posix.AF_INET:
+      result.addrtype = AF_INET
+    elif s.h_addrtype == posix.AF_INET6:
+      result.addrtype = AF_INET6
+    else:
+      raise newException(OSError, "unknown h_addrtype")
+  result.addrList = cstringArrayToSeq(s.h_addr_list)
+  result.length = int(s.h_length)
+
+proc getSockName*(socket: SocketHandle): Port = 
+  ## returns the socket's associated port number.
+  var name: Sockaddr_in
+  when useWinVersion:
+    name.sin_family = int16(ord(AF_INET))
+  else:
+    name.sin_family = posix.AF_INET
+  #name.sin_port = htons(cint16(port))
+  #name.sin_addr.s_addr = htonl(INADDR_ANY)
+  var namelen = sizeof(name).SockLen
+  if getsockname(socket, cast[ptr SockAddr](addr(name)),
+                 addr(namelen)) == -1'i32:
+    raiseOSError(osLastError())
+  result = Port(rawsockets.ntohs(name.sin_port))
+
+proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
+  tags: [ReadIOEffect].} = 
+  ## getsockopt for integer options.
+  var res: cint
+  var size = sizeof(res).SockLen
+  if getsockopt(socket, cint(level), cint(optname), 
+                addr(res), addr(size)) < 0'i32:
+    raiseOSError(osLastError())
+  result = int(res)
+
+proc setSockOptInt*(socket: SocketHandle, level, optname, optval: int) {.
+  tags: [WriteIOEffect].} =
+  ## setsockopt for integer options.
+  var value = cint(optval)
+  if setsockopt(socket, cint(level), cint(optname), addr(value),  
+                sizeof(value).SockLen) < 0'i32:
+    raiseOSError(osLastError())
+
+proc setBlocking*(s: SocketHandle, blocking: bool) =
+  ## Sets blocking mode on socket.
+  ##
+  ## Raises EOS on error.
+  when useWinVersion:
+    var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking
+    if ioctlsocket(s, FIONBIO, addr(mode)) == -1:
+      raiseOSError(osLastError())
+  else: # BSD sockets
+    var x: int = fcntl(s, F_GETFL, 0)
+    if x == -1:
+      raiseOSError(osLastError())
+    else:
+      var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK
+      if fcntl(s, F_SETFL, mode) == -1:
+        raiseOSError(osLastError())
+
+proc timeValFromMilliseconds(timeout = 500): Timeval =
+  if timeout != -1:
+    var seconds = timeout div 1000
+    result.tv_sec = seconds.int32
+    result.tv_usec = ((timeout - seconds * 1000) * 1000).int32
+
+proc createFdSet(fd: var FdSet, s: seq[SocketHandle], m: var int) = 
+  FD_ZERO(fd)
+  for i in items(s): 
+    m = max(m, int(i))
+    fdSet(i, fd)
+   
+proc pruneSocketSet(s: var seq[SocketHandle], fd: var FdSet) = 
+  var i = 0
+  var L = s.len
+  while i < L:
+    if FD_ISSET(s[i], fd) == 0'i32:
+      s[i] = s[L-1]
+      dec(L)
+    else:
+      inc(i)
+  setLen(s, L)
+
+proc select*(readfds: var seq[SocketHandle], timeout = 500): int =
+  ## Traditional select function. This function will return the number of
+  ## sockets that are ready to be read from, written to, or which have errors.
+  ## If there are none; 0 is returned. 
+  ## ``Timeout`` is in miliseconds and -1 can be specified for no timeout.
+  ## 
+  ## A socket is removed from the specific ``seq`` when it has data waiting to
+  ## be read/written to or has errors (``exceptfds``).
+  var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout)
+  
+  var rd: FdSet
+  var m = 0
+  createFdSet((rd), readfds, m)
+  
+  if timeout != -1:
+    result = int(select(cint(m+1), addr(rd), nil, nil, addr(tv)))
+  else:
+    result = int(select(cint(m+1), addr(rd), nil, nil, nil))
+  
+  pruneSocketSet(readfds, (rd))
+
+proc selectWrite*(writefds: var seq[SocketHandle],
+                  timeout = 500): int {.tags: [ReadIOEffect].} =
+  ## When a socket in ``writefds`` is ready to be written to then a non-zero
+  ## value will be returned specifying the count of the sockets which can be
+  ## written to. The sockets which can be written to will also be removed
+  ## from ``writefds``.
+  ##
+  ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for
+  ## an unlimited time.
+  var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout)
+  
+  var wr: FdSet
+  var m = 0
+  createFdSet((wr), writefds, m)
+  
+  if timeout != -1:
+    result = int(select(cint(m+1), nil, addr(wr), nil, addr(tv)))
+  else:
+    result = int(select(cint(m+1), nil, addr(wr), nil, nil))
+  
+  pruneSocketSet(writefds, (wr))
+
+when defined(Windows):
+  var wsa: WSAData
+  if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError())
diff --git a/lib/pure/scgi.nim b/lib/pure/scgi.nim
index 58b37833a..f3e2b583c 100644
--- a/lib/pure/scgi.nim
+++ b/lib/pure/scgi.nim
@@ -25,6 +25,10 @@
 ##
 ## **Warning:** The API of this module is unstable, and therefore is subject
 ## to change.
+##
+## **Warning:** This module only supports the old asynchronous interface.
+## You may wish to use the `asynchttpserver <asynchttpserver.html>`_
+## instead for web applications.
 
 include "system/inclrtl"
 
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
index 1c988c609..f17c6d317 100644
--- a/lib/pure/selectors.nim
+++ b/lib/pure/selectors.nim
@@ -23,7 +23,7 @@ proc `$`*(x: SocketHandle): string {.borrow.}
 
 type
   Event* = enum
-    EvRead, EvWrite
+    EvRead, EvWrite, EvError
 
   SelectorKey* = ref object
     fd*: SocketHandle
@@ -146,12 +146,19 @@ elif defined(linux):
     ## on the ``fd``.
     result = @[]
     let evNum = epoll_wait(s.epollFD, addr s.events[0], 64.cint, timeout.cint)
-    if evNum < 0: raiseOSError(osLastError())
+    if evNum < 0:
+      let err = osLastError()
+      if err.cint == EINTR:
+        return @[]
+      raiseOSError(osLastError())
     if evNum == 0: return @[]
     for i in 0 .. <evNum:
       let fd = s.events[i].data.fd.SocketHandle
     
       var evSet: set[Event] = {}
+      if (s.events[i].events and EPOLLERR) != 0: evSet = evSet + {EvError}
+      if (s.events[i].events and EPOLLHUP) != 0: evSet = evSet + {EvError}
+      if (s.events[i].events and EPOLLRDHUP) != 0: evSet = evSet + {EvError}
       if (s.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead}
       if (s.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite}
       let selectorKey = s.fds[fd]
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index 79f409179..11eeefcb9 100644
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -7,6 +7,10 @@
 #    distribution, for details about the copyright.
 #
 
+## **Warning:** Since version 0.10.2 this module is deprecated.
+## Use the `net <net.html>`_ or the
+## `rawsockets <rawsockets.html>`_ module instead.
+##
 ## This module implements portable sockets, it supports a mix of different types
 ## of sockets. Sockets are buffered by default meaning that data will be
 ## received in ``BufferSize`` (4000) sized chunks, buffering
@@ -23,9 +27,6 @@
 ##
 ## Asynchronous sockets are supported, however a better alternative is to use
 ## the `asyncio <asyncio.html>`_ module.
-##
-## Since version 0.10.2 this module is deprecated. Use the `net <net.html>`_
-## or the `rawsockets <rawsockets.html>`_ module instead.
 
 {.deprecated.}
 
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index 6c0246f8b..21efea3bc 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -97,7 +97,9 @@ proc checkpoint*(msg: string) =
 template fail* =
   bind checkpoints
   for msg in items(checkpoints):
-    echo msg
+    # this used to be 'echo' which now breaks due to a bug. XXX will revisit
+    # this issue later.
+    stdout.writeln msg
 
   when not defined(ECMAScript):
     if abortOnError: quit(1)
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index 2c65d071e..edc690aec 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -16,17 +16,18 @@ type
   Uri* = object
     scheme*, username*, password*: string 
     hostname*, port*, path*, query*, anchor*: string
+    opaque*: bool
 
 {.deprecated: [TUrl: Url, TUri: Uri].}
 
-proc `$`*(url: TUrl): string {.deprecated.} =
-  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
+proc `$`*(url: Url): string {.deprecated.} =
+  ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   return string(url)
 
-proc `/`*(a, b: TUrl): TUrl {.deprecated.} =
+proc `/`*(a, b: Url): Url {.deprecated.} =
   ## Joins two URLs together, separating them with / if needed.
   ##
-  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
+  ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   var urlS = $a
   var bS = $b
   if urlS == "": return b
@@ -36,15 +37,15 @@ proc `/`*(a, b: TUrl): TUrl {.deprecated.} =
     urlS.add(bS.substr(1))
   else:
     urlS.add(bs)
-  result = TUrl(urlS)
+  result = Url(urlS)
 
-proc add*(url: var TUrl, a: TUrl) {.deprecated.} =
+proc add*(url: var Url, a: Url) {.deprecated.} =
   ## Appends url to url.
   ##
-  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
+  ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   url = url / a
 
-proc parseAuthority(authority: string, result: var TUri) =
+proc parseAuthority(authority: string, result: var Uri) =
   var i = 0
   var inPort = false
   while true:
@@ -65,7 +66,7 @@ proc parseAuthority(authority: string, result: var TUri) =
         result.hostname.add(authority[i])
     i.inc
 
-proc parsePath(uri: string, i: var int, result: var TUri) =
+proc parsePath(uri: string, i: var int, result: var Uri) =
   
   i.inc parseUntil(uri, result.path, {'?', '#'}, i)
 
@@ -82,11 +83,11 @@ proc parsePath(uri: string, i: var int, result: var TUri) =
     i.inc # Skip '#'
     i.inc parseUntil(uri, result.anchor, {}, i)
 
-proc initUri(): TUri =
-  result = TUri(scheme: "", username: "", password: "", hostname: "", port: "",
+proc initUri(): Uri =
+  result = Uri(scheme: "", username: "", password: "", hostname: "", port: "",
                 path: "", query: "", anchor: "")
 
-proc parseUri*(uri: string): TUri =
+proc parseUri*(uri: string): Uri =
   ## Parses a URI.
   result = initUri()
 
@@ -113,8 +114,10 @@ proc parseUri*(uri: string): TUri =
     var authority = ""
     i.inc parseUntil(uri, authority, {'/', '?', '#'}, i)
     if authority == "":
-      raise newException(EInvalidValue, "Expected authority got nothing.")
+      raise newException(ValueError, "Expected authority got nothing.")
     parseAuthority(authority, result)
+  else:
+    result.opaque = true
 
   # Path
   parsePath(uri, i, result)
@@ -150,7 +153,7 @@ proc removeDotSegments(path: string): string =
   result = collection.join("/")
   if endsWithSlash: result.add '/'
 
-proc merge(base, reference: TUri): string =
+proc merge(base, reference: Uri): string =
   # http://tools.ietf.org/html/rfc3986#section-5.2.3
   if base.hostname != "" and base.path == "":
     '/' & reference.path
@@ -161,7 +164,7 @@ proc merge(base, reference: TUri): string =
     else:
       base.path[0 .. lastSegment] & reference.path
 
-proc combine*(base: TUri, reference: TUri): TUri =
+proc combine*(base: Uri, reference: Uri): Uri =
   ## Combines a base URI with a reference URI.
   ##
   ## This uses the algorithm specified in
@@ -216,13 +219,13 @@ proc combine*(base: TUri, reference: TUri): TUri =
     result.scheme = base.scheme
   result.anchor = reference.anchor
 
-proc combine*(uris: varargs[TUri]): TUri =
+proc combine*(uris: varargs[Uri]): Uri =
   ## Combines multiple URIs together.
   result = uris[0]
   for i in 1 .. <uris.len:
     result = combine(result, uris[i])
 
-proc `/`*(x: TUri, path: string): TUri =
+proc `/`*(x: Uri, path: string): Uri =
   ## Concatenates the path specified to the specified URI's path.
   ##
   ## Contrary to the ``combine`` procedure you do not have to worry about
@@ -251,12 +254,15 @@ proc `/`*(x: TUri, path: string): TUri =
       result.path.add '/'
     result.path.add(path)
 
-proc `$`*(u: TUri): string =
+proc `$`*(u: Uri): string =
   ## Returns the string representation of the specified URI object.
   result = ""
   if u.scheme.len > 0:
     result.add(u.scheme)
-    result.add("://")
+    if u.opaque:
+      result.add(":")
+    else:
+      result.add("://")
   if u.username.len > 0:
     result.add(u.username)
     if u.password.len > 0:
@@ -268,22 +274,28 @@ proc `$`*(u: TUri): string =
     result.add(":")
     result.add(u.port)
   if u.path.len > 0:
-    if u.path[0] != '/': result.add("/")
     result.add(u.path)
-  result.add(u.query)
-  result.add(u.anchor)
+  if u.query.len > 0:
+    result.add("?")
+    result.add(u.query)
+  if u.anchor.len > 0:
+    result.add("#")
+    result.add(u.anchor)
 
 when isMainModule:
   block:
-    let test = parseUri("http://localhost:8080/test")
+    let str = "http://localhost:8080/test"
+    let test = parseUri(str)
     doAssert test.scheme == "http"
     doAssert test.port == "8080"
     doAssert test.path == "/test"
     doAssert test.hostname == "localhost"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("foo://username:password@example.com:8042/over/there" &
-                        "/index.dtb?type=animal&name=narwhal#nose")
+    let str = "foo://username:password@example.com:8042/over/there" &
+              "/index.dtb?type=animal&name=narwhal#nose"
+    let test = parseUri(str)
     doAssert test.scheme == "foo"
     doAssert test.username == "username"
     doAssert test.password == "password"
@@ -292,34 +304,45 @@ when isMainModule:
     doAssert test.path == "/over/there/index.dtb"
     doAssert test.query == "type=animal&name=narwhal"
     doAssert test.anchor == "nose"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("urn:example:animal:ferret:nose")
+    let str = "urn:example:animal:ferret:nose"
+    let test = parseUri(str)
     doAssert test.scheme == "urn"
     doAssert test.path == "example:animal:ferret:nose"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("mailto:username@example.com?subject=Topic")
+    let str = "mailto:username@example.com?subject=Topic"
+    let test = parseUri(str)
     doAssert test.scheme == "mailto"
     doAssert test.username == "username"
     doAssert test.hostname == "example.com"
     doAssert test.query == "subject=Topic"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar")
+    let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
+    let test = parseUri(str)
     doAssert test.scheme == "magnet"
     doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("/test/foo/bar?q=2#asdf")
+    let str = "/test/foo/bar?q=2#asdf"
+    let test = parseUri(str)
     doAssert test.scheme == ""
     doAssert test.path == "/test/foo/bar"
     doAssert test.query == "q=2"
     doAssert test.anchor == "asdf"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("test/no/slash")
+    let str = "test/no/slash"
+    let test = parseUri(str)
     doAssert test.path == "test/no/slash"
+    doAssert($test == str)
 
   # Remove dot segments tests
   block:
@@ -371,5 +394,3 @@ when isMainModule:
   block:
     let test = parseUri("http://example.com/foo/") / "/bar/asd"
     doAssert test.path == "/foo/bar/asd"
-
-  
diff --git a/lib/system.nim b/lib/system.nim
index 0cd4b84e2..b7c77e276 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1516,7 +1516,7 @@ const
   NimMinor*: int = 10
     ## is the minor number of Nim's version.
 
-  NimPatch*: int = 1
+  NimPatch*: int = 3
     ## is the patch number of Nim's version.
 
   NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index 3e5ca0795..d07d6eae1 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -232,9 +232,10 @@ proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
   ## it returns ``(false, default(msg))``.

   var q = cast[PRawChannel](addr(c))

   if q.mask != ChannelDeadMask:

-    if tryAcquireSys(q.lock):

-      llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))

-      result.dataAvailable = true

+    if tryAcquireSys(q.lock):
+      if q.count > 0:

+        llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))

+        result.dataAvailable = true

       releaseSys(q.lock)

 

 proc peek*[TMsg](c: var TChannel[TMsg]): int =

diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index e21eeca6a..237b42482 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -296,15 +296,15 @@ when not defined(noSignalHandler):
     template processSignal(s, action: expr) {.immediate,  dirty.} =
       if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
       elif s == SIGSEGV: 
-        action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
+        action("SIGSEGV: Illegal storage access. (Try to compile with -d:useSysAssert -d:useGcAssert for details.)\n")
       elif s == SIGABRT:
         when defined(endb):
           if dbgAborting: return # the debugger wants to abort
         action("SIGABRT: Abnormal termination.\n")
       elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n")
       elif s == SIGILL: action("SIGILL: Illegal operation.\n")
-      elif s == SIGBUS: 
-        action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
+      elif s == SIGBUS:
+        action("SIGBUS: Illegal storage access.  (Try to compile with -d:useSysAssert -d:useGcAssert for details.)\n")
       else:
         block platformSpecificSignal:
           when declared(SIGPIPE):
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index e0db3fba4..58587cf7f 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -49,7 +49,7 @@ type
     waMarkGlobal,    # part of the backup/debug mark&sweep
     waMarkPrecise,   # part of the backup/debug mark&sweep
     waZctDecRef, waPush, waCycleDecRef, waMarkGray, waScan, waScanBlack, 
-    waCollectWhite,
+    waCollectWhite #, waDebug
 
   TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
     # A ref type can have a finalizer that is called before the object's
@@ -595,9 +595,15 @@ proc scan(s: PCell) =
     else:
       s.setColor(rcWhite)
       forAllChildren(s, waScan)
-  
+
 proc collectWhite(s: PCell) =
-  if s.color == rcWhite and s notin gch.cycleRoots:
+  # This is a hacky way to deal with the following problem (bug #1796)
+  # Consider this content in cycleRoots:
+  #   x -> a; y -> a  where 'a' is an acyclic object so not included in
+  # cycleRoots itself. Then 'collectWhite' used to free 'a' twice. The
+  # 'isAllocatedPtr' check prevents this. This also means we do not need
+  # to query 's notin gch.cycleRoots' at all.
+  if isAllocatedPtr(gch.region, s) and s.color == rcWhite:
     s.setColor(rcBlack)
     forAllChildren(s, waCollectWhite)
     freeCyclicCell(gch, s)
@@ -648,6 +654,28 @@ when useMarkForDebug or useBackupGc:
       if objStart != nil:
         markS(gch, objStart)
 
+when logGC:
+  var
+    cycleCheckA: array[100, PCell]
+    cycleCheckALen = 0
+
+  proc alreadySeen(c: PCell): bool =
+    for i in 0 .. <cycleCheckALen:
+      if cycleCheckA[i] == c: return true
+    if cycleCheckALen == len(cycleCheckA):
+      gcAssert(false, "cycle detection overflow")
+      quit 1
+    cycleCheckA[cycleCheckALen] = c
+    inc cycleCheckALen
+
+  proc debugGraph(s: PCell) =
+    if alreadySeen(s):
+      writeCell("child cell (already seen) ", s)
+    else:
+      writeCell("cell {", s)
+      forAllChildren(s, waDebug)
+      c_fprintf(c_stdout, "}\n")
+
 proc doOperation(p: pointer, op: TWalkOp) =
   if p == nil: return
   var c: PCell = usrToCell(p)
@@ -690,6 +718,7 @@ proc doOperation(p: pointer, op: TWalkOp) =
   of waMarkPrecise:
     when useMarkForDebug or useBackupGc:
       add(gch.tempStack, c)
+  #of waDebug: debugGraph(c)
 
 proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
   doOperation(d, TWalkOp(op))
@@ -702,7 +731,6 @@ when useMarkForDebug or useBackupGc:
 
 proc collectRoots(gch: var TGcHeap) =
   for s in elements(gch.cycleRoots):
-    excl(gch.cycleRoots, s)
     collectWhite(s)
 
 proc collectCycles(gch: var TGcHeap) =
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 76d17bc4a..51a12141b 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -368,32 +368,32 @@ type
 {.deprecated: [TSocketHandle: SocketHandle].}
 
 type
-  WSAData* {.importc: "WSADATA", header: "Winsock2.h".} = object 
+  WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object 
     wVersion, wHighVersion: int16
     szDescription: array[0..WSADESCRIPTION_LEN, char]
     szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
     iMaxSockets, iMaxUdpDg: int16
     lpVendorInfo: cstring
     
-  SockAddr* {.importc: "SOCKADDR", header: "Winsock2.h".} = object 
+  SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object 
     sa_family*: int16 # unsigned
     sa_data: array[0..13, char]
 
-  InAddr* {.importc: "IN_ADDR", header: "Winsock2.h".} = object
+  InAddr* {.importc: "IN_ADDR", header: "winsock2.h".} = object
     s_addr*: int32  # IP address
   
   Sockaddr_in* {.importc: "SOCKADDR_IN", 
-                  header: "Winsock2.h".} = object
+                  header: "winsock2.h".} = object
     sin_family*: int16
     sin_port*: int16 # unsigned
     sin_addr*: InAddr
     sin_zero*: array[0..7, char]
 
-  In6_addr* {.importc: "IN6_ADDR", header: "Winsock2.h".} = object 
+  In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object 
     bytes*: array[0..15, char]
 
   Sockaddr_in6* {.importc: "SOCKADDR_IN6", 
-                   header: "Winsock2.h".} = object
+                   header: "winsock2.h".} = object
     sin6_family*: int16
     sin6_port*: int16 # unsigned
     sin6_flowinfo*: int32 # unsigned
@@ -450,22 +450,22 @@ type
 
 
 var
-  SOMAXCONN* {.importc, header: "Winsock2.h".}: cint
-  INVALID_SOCKET* {.importc, header: "Winsock2.h".}: SocketHandle
-  SOL_SOCKET* {.importc, header: "Winsock2.h".}: cint
-  SO_DEBUG* {.importc, header: "Winsock2.h".}: cint ## turn on debugging info recording
-  SO_ACCEPTCONN* {.importc, header: "Winsock2.h".}: cint # socket has had listen()
-  SO_REUSEADDR* {.importc, header: "Winsock2.h".}: cint # allow local address reuse
-  SO_KEEPALIVE* {.importc, header: "Winsock2.h".}: cint # keep connections alive
-  SO_DONTROUTE* {.importc, header: "Winsock2.h".}: cint # just use interface addresses
-  SO_BROADCAST* {.importc, header: "Winsock2.h".}: cint # permit sending of broadcast msgs
-  SO_USELOOPBACK* {.importc, header: "Winsock2.h".}: cint # bypass hardware when possible
-  SO_LINGER* {.importc, header: "Winsock2.h".}: cint # linger on close if data present
-  SO_OOBINLINE* {.importc, header: "Winsock2.h".}: cint # leave received OOB data in line
-
-  SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint
-  SO_EXCLUSIVEADDRUSE* {.importc, header: "Winsock2.h".}: cint # disallow local address reuse
-  SO_ERROR* {.importc, header: "Winsock2.h".}: cint
+  SOMAXCONN* {.importc, header: "winsock2.h".}: cint
+  INVALID_SOCKET* {.importc, header: "winsock2.h".}: SocketHandle
+  SOL_SOCKET* {.importc, header: "winsock2.h".}: cint
+  SO_DEBUG* {.importc, header: "winsock2.h".}: cint ## turn on debugging info recording
+  SO_ACCEPTCONN* {.importc, header: "winsock2.h".}: cint # socket has had listen()
+  SO_REUSEADDR* {.importc, header: "winsock2.h".}: cint # allow local address reuse
+  SO_KEEPALIVE* {.importc, header: "winsock2.h".}: cint # keep connections alive
+  SO_DONTROUTE* {.importc, header: "winsock2.h".}: cint # just use interface addresses
+  SO_BROADCAST* {.importc, header: "winsock2.h".}: cint # permit sending of broadcast msgs
+  SO_USELOOPBACK* {.importc, header: "winsock2.h".}: cint # bypass hardware when possible
+  SO_LINGER* {.importc, header: "winsock2.h".}: cint # linger on close if data present
+  SO_OOBINLINE* {.importc, header: "winsock2.h".}: cint # leave received OOB data in line
+
+  SO_DONTLINGER* {.importc, header: "winsock2.h".}: cint
+  SO_EXCLUSIVEADDRUSE* {.importc, header: "winsock2.h".}: cint # disallow local address reuse
+  SO_ERROR* {.importc, header: "winsock2.h".}: cint
 
 proc `==`*(x, y: SocketHandle): bool {.borrow.}
 
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index ba25fbf1a..29fe3a921 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -50,7 +50,7 @@ when useWinVersion:
   from winlean import SocketHandle
 else:
   const
-    versions = "(|.1.0.0|.0.9.9|.0.9.8|.0.9.7|.0.9.6|.0.9.5|.0.9.4)"
+    versions = "(.10|.1.0.1|.1.0.0|.0.9.9|.0.9.8|.0.9.7|.0.9.6|.0.9.5|.0.9.4)"
   when defined(macosx):
     const
       DLLSSLName = "libssl" & versions & ".dylib"
@@ -280,9 +280,18 @@ when not useWinVersion:
   proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, 
     dynlib: DLLUtilName, importc.}
 
+  proc allocWrapper(size: int): pointer {.cdecl.} = alloc(size)
+  proc reallocWrapper(p: pointer; newsize: int): pointer {.cdecl.} =
+    if p == nil:
+      if newSize > 0: result = alloc(newsize)
+    elif newsize == 0: dealloc(p)
+    else: result = realloc(p, newsize)
+  proc deallocWrapper(p: pointer) {.cdecl.} =
+    if p != nil: dealloc(p)
+
 proc CRYPTO_malloc_init*() =
   when not useWinVersion:
-    CRYPTO_set_mem_functions(alloc, realloc, dealloc)
+    CRYPTO_set_mem_functions(allocWrapper, reallocWrapper, deallocWrapper)
 
 proc SSL_CTX_ctrl*(ctx: SslCtx, cmd: cInt, larg: int, parg: pointer): int{.
   cdecl, dynlib: DLLSSLName, importc.}
diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim
index 5165b0f06..13d531387 100644
--- a/tests/async/tasyncawait.nim
+++ b/tests/async/tasyncawait.nim
@@ -53,9 +53,7 @@ proc createServer(port: TPort) {.async.} =
   
   discard server.SocketHandle.listen()
   while true:
-    var client = await accept(server)
-    asyncCheck readMessages(client)
-    # TODO: Test: readMessages(disp, await disp.accept(server))
+    asyncCheck readMessages(await accept(server))
 
 asyncCheck createServer(TPort(10335))
 asyncCheck launchSwarm(TPort(10335))
diff --git a/tests/async/tasynciossl.nim b/tests/async/tasynciossl.nim
index b0222e4ff..118b9e74d 100644
--- a/tests/async/tasynciossl.nim
+++ b/tests/async/tasynciossl.nim
@@ -47,7 +47,7 @@ proc serverAccept(s: PAsyncSocket) =
 proc launchSwarm(disp: var PDispatcher, port: TPort, count: int,
                  buffered = true, useSSL = false) =
   for i in 1..count:
-    var client = AsyncSocket()
+    var client = asyncSocket()
     when defined(ssl):
       if useSSL:
         ctx1.wrapSocket(client)
@@ -56,7 +56,7 @@ proc launchSwarm(disp: var PDispatcher, port: TPort, count: int,
     client.connect("localhost", port)
 
 proc createSwarm(port: TPort, buffered = true, useSSL = false) =
-  var server = AsyncSocket()
+  var server = asyncSocket()
   when defined(ssl):
     if useSSL:
       ctx.wrapSocket(server)
diff --git a/tests/async/tasyncudp.nim b/tests/async/tasyncudp.nim
index fd7f3d568..2a7ed40bf 100644
--- a/tests/async/tasyncudp.nim
+++ b/tests/async/tasyncudp.nim
@@ -42,14 +42,14 @@ proc swarmConnect(s: PAsyncSocket) =
 proc createClient(disp: var PDispatcher, port: TPort,
                   buffered = true) =
   currentClient.inc()
-  var client = AsyncSocket(typ = SOCK_DGRAM, protocol = IPPROTO_UDP,
+  var client = asyncSocket(typ = SOCK_DGRAM, protocol = IPPROTO_UDP,
                            buffered = buffered)
   client.handleConnect = swarmConnect
   disp.register(client)
   client.connect("localhost", port)
 
 proc createServer(port: TPort, buffered = true) =
-  var server = AsyncSocket(typ = SOCK_DGRAM, protocol = IPPROTO_UDP,
+  var server = asyncSocket(typ = SOCK_DGRAM, protocol = IPPROTO_UDP,
                            buffered = buffered)
   server.handleRead = serverRead
   disp.register(server)
@@ -75,4 +75,4 @@ while true:
     break
 
 assert msgCount == messagesToSend * serverCount * swarmSize
-echo(msgCount)
\ No newline at end of file
+echo(msgCount)
diff --git a/tests/gc/closureleak.nim b/tests/gc/closureleak.nim
index 38ee1250a..1c39f43d5 100644
--- a/tests/gc/closureleak.nim
+++ b/tests/gc/closureleak.nim
@@ -7,7 +7,7 @@ from strutils import join
 type
   TFoo * = object
     id: int
-    func: proc(){.closure.}
+    fn: proc(){.closure.}
 var foo_counter = 0
 var alive_foos = newseq[int](0)
 
@@ -26,7 +26,7 @@ for i in 0 .. <10:
 
 for i in 0 .. <10:
   let f = newFoo()
-  f.func = proc = 
+  f.fn = proc = 
     echo f.id
 
 GC_fullcollect()
diff --git a/tests/gc/cyclecollector.nim b/tests/gc/cyclecollector.nim
new file mode 100644
index 000000000..46fed6c45
--- /dev/null
+++ b/tests/gc/cyclecollector.nim
@@ -0,0 +1,21 @@
+
+# Program to detect bug #1796 reliably
+
+type
+  Node = ref object
+    a, b: Node
+    leaf: string
+
+proc createCycle(leaf: string): Node =
+  new result
+  result.a = result
+  shallowCopy result.leaf, leaf
+
+proc main =
+  for i in 0 .. 100_000:
+    var leaf = "this is the leaf. it allocates"
+    let x = createCycle(leaf)
+    let y = createCycle(leaf)
+  echo "done ", getOccupiedMem()
+
+main()
diff --git a/tests/gc/gctest.nim b/tests/gc/gctest.nim
index 27134d7dd..2213a83ac 100644
--- a/tests/gc/gctest.nim
+++ b/tests/gc/gctest.nim
@@ -196,7 +196,8 @@ write(stdout, "starting main...\n")
 main()
 
 GC_fullCollect()
+# the M&S GC fails with this call and it's unclear why. Definitely something
+# we need to fix!
 GC_fullCollect()
 writeln(stdout, GC_getStatistics())
 write(stdout, "finished\n")
-
diff --git a/tests/generics/t1050.nim b/tests/generics/t1050.nim
new file mode 100644
index 000000000..a6f9a2482
--- /dev/null
+++ b/tests/generics/t1050.nim
@@ -0,0 +1,16 @@
+discard """
+  msg: "int"
+  output: "4"
+"""
+
+import typetraits
+
+type ArrayType[T] = distinct T
+
+proc arrayItem(a: ArrayType): auto =
+  static: echo(name(type(a).T))
+  result = (type(a).T)(4)
+
+var arr: ArrayType[int]
+echo arrayItem(arr)
+
diff --git a/tests/generics/t1056.nim b/tests/generics/t1056.nim
new file mode 100644
index 000000000..73a24a76a
--- /dev/null
+++ b/tests/generics/t1056.nim
@@ -0,0 +1,26 @@
+discard """
+  output: '''TMatrix[3, 3, system.int]
+3
+3'''
+"""
+
+import typetraits
+
+type
+  TMatrix*[N,M: static[int], T] = object
+    data*: array[0..N*M-1, T]
+
+  TMat2[T] = TMatrix[2,2,T]
+
+proc echoMatrix(a: TMatrix) =
+  echo a.type.name
+  echo TMatrix.N
+
+proc echoMat2(a: TMat2) =
+  echo TMat2.M
+  
+var m = TMatrix[3,3,int](data: [1,2,3,4,5,6,7,8,9])
+
+echoMatrix m
+echoMat2 m
+
diff --git a/tests/generics/t1789.nim b/tests/generics/t1789.nim
new file mode 100644
index 000000000..188db88f6
--- /dev/null
+++ b/tests/generics/t1789.nim
@@ -0,0 +1,44 @@
+discard """
+  output: "3\n0"
+"""
+
+# https://github.com/Araq/Nim/issues/1789
+
+type
+  Foo[N: static[int]] = object
+
+proc bindStaticN[N](foo: Foo[N]) =
+  var ar0: array[3, int]
+  var ar1: array[N, int]
+  var ar2: array[1..N, int]
+  var ar3: array[0..(N+10), float]
+  echo N
+
+var f: Foo[3]
+f.bindStaticN
+
+# case 2
+
+type
+  ObjectWithStatic[X, Y: static[int], T] = object
+    bar: array[X * Y, T]   # this one works
+
+  AliasWithStatic[X, Y: static[int], T] = array[X * Y, T]
+
+var
+  x: ObjectWithStatic[1, 2, int]
+  y: AliasWithStatic[2, 3, int]
+
+# case 3
+
+type
+  Bar[N: static[int], T] = object
+    bar: array[N, T]
+
+proc `[]`*[N, T](f: Bar[N, T], n: range[0..(N - 1)]): T =
+  assert high(n) == N-1
+  result = f.bar[n]
+  
+var b: Bar[3, int]
+echo b[2]
+
diff --git a/tests/macros/tvtable.nim b/tests/macros/tvtable.nim
index 51894618c..3e3b9c0e6 100644
--- a/tests/macros/tvtable.nim
+++ b/tests/macros/tvtable.nim
@@ -11,8 +11,8 @@ OBJ 2 bar
 
 type
   # these are the signatures of the virtual procs for each type
-  fooProc[T] = proc (o: var T): int
-  barProc[T] = proc (o: var T)
+  fooProc[T] = proc (o: var T): int {.nimcall.}
+  barProc[T] = proc (o: var T) {.nimcall.}
 
   # an untyped table to store the proc pointers
   # it's also possible to use a strongly typed tuple here
diff --git a/tests/metatype/tsemistatic.nim b/tests/metatype/tsemistatic.nim
index 0a003be03..a13175ba8 100644
--- a/tests/metatype/tsemistatic.nim
+++ b/tests/metatype/tsemistatic.nim
@@ -1,9 +1,15 @@
 discard """
   msg: "static 10\ndynamic\nstatic 20\n"
   output: "s\nd\nd\ns"
-  disabled: "true"
 """
 
+type
+  semistatic[T] =
+    static[T] or T
+
+template isStatic*(x): expr =
+  compiles(static(x))
+
 proc foo(x: semistatic[int]) =
   when isStatic(x):
     static: echo "static ", x
diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim
index 6d7c569e0..7fc5f479b 100644
--- a/tests/metatype/tstaticparams.nim
+++ b/tests/metatype/tstaticparams.nim
@@ -1,6 +1,6 @@
 discard """
   file: "tstaticparams.nim"
-  output: "abracadabra\ntest\n3\n15\n4\n2"
+  output: "abracadabra\ntest\n3\n15\n4\n2\nfloat\n3\nfloat\nyin\nyang"
 """
 
 type 
@@ -56,3 +56,87 @@ type TTestSub[N: static[int]] = TTest[1, N]
 
 var z: TTestSub[2]
 echo z.high
+
+# issue 1049
+proc matrix_1*[M, N, T](mat: Matrix[M,N,T], a: array[N, int]) = discard
+proc matrix_2*[M, N, T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard
+
+proc matrix_3*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N, int]) = discard
+proc matrix_4*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard
+
+var
+  tmat: Matrix[4,4,int]
+  ar1: array[4, int]
+  ar2: array[5, int]
+
+matrix_1(tmat, ar1)
+matrix_2(tmat, ar2)
+matrix_3(tmat, ar1)
+matrix_4(tmat, ar2)
+
+template reject(x): stmt =
+  static: assert(not compiles(x))
+
+# test with arrays of wrong size
+reject matrix_1(tmat, ar2)
+reject matrix_2(tmat, ar1)
+reject matrix_3(tmat, ar2)
+reject matrix_4(tmat, ar1)
+
+# bug 1820
+
+type
+  T1820_1[T; Y: static[int]] = object
+    bar: T
+
+proc intOrFloat*[Y](f: T1820_1[int, Y]) = echo "int"
+proc intOrFloat*[Y](f: T1820_1[float, Y]) = echo "float"
+proc threeOrFour*[T](f: T1820_1[T, 3]) =  echo "3"
+proc threeOrFour*[T](f: T1820_1[T, 4]) = echo "4"
+
+var foo_1: T1820_1[float, 3]
+
+foo_1.intOrFloat
+foo_1.threeOrFour
+
+type
+  YinAndYang = enum
+    Yin,
+    Yang
+
+  T1820_2[T; Y: static[YinAndYang]] = object
+    bar: T
+
+proc intOrFloat*[Y](f: T1820_2[int, Y]) = echo "int"
+proc intOrFloat*[Y](f: T1820_2[float, Y]) = echo "float"
+proc yinOrYang*[T](f: T1820_2[T, YinAndYang.Yin]) = echo "yin"
+proc yinOrYang*[T](f: T1820_2[T, Yang]) = echo "yang"
+
+var foo_2: T1820_2[float, Yin]
+var foo_3: T1820_2[float, YinAndYang.Yang]
+
+foo_2.intOrFloat
+foo_2.yinOrYang
+foo_3.yinOrYang
+
+# bug 1859
+
+type 
+  TypeWith2Params[N, M: static[int]] = object
+
+proc bindBothParams[N](x: TypeWith2Params[N, N]) = discard
+proc dontBind1[N,M](x: TypeWith2Params[N, M]) = discard
+proc dontBind2(x: TypeWith2Params) = discard
+
+var bb_1: TypeWith2Params[2, 2]
+var bb_2: TypeWith2Params[2, 3]
+
+bindBothParams(bb_1)
+reject bindBothParams(bb_2)
+
+dontBind1 bb_1
+dontBind1 bb_2
+
+dontBind2 bb_1
+dontBind2 bb_2
+
diff --git a/tests/metatype/tusertypeclasses.nim b/tests/metatype/tusertypeclasses.nim
index a5d575dbf..4e5e6221c 100644
--- a/tests/metatype/tusertypeclasses.nim
+++ b/tests/metatype/tusertypeclasses.nim
@@ -1,5 +1,13 @@
 discard """
-  output: "Sortable\nSortable\nContainer"
+  output: '''Sortable
+Sortable
+Container
+true
+true
+false
+false
+false
+'''
 """
 
 import typetraits
@@ -12,7 +20,7 @@ type
     (x < y) is bool
 
   ObjectContainer = generic C
-    C.len is ordinal
+    C.len is Ordinal
     for v in items(C):
       v.type is tuple|object
 
@@ -41,3 +49,20 @@ proc y(x: TObj): int = 10
 proc testFoo(x: TFoo) = discard
 testFoo(TObj(x: 10))
 
+type
+  Matrix[Rows, Cols: static[int]; T] = generic M
+    M.M == Rows
+    M.N == Cols
+    M.T is T
+
+  MyMatrix[M, N: static[int]; T] = object
+    data: array[M*N, T]
+
+var x: MyMatrix[3, 3, int]
+
+echo x is Matrix
+echo x is Matrix[3, 3, int]
+echo x is Matrix[3, 3, float]
+echo x is Matrix[4, 3, int]
+echo x is Matrix[3, 4, int]
+
diff --git a/tests/misc/tcolonisproc.nim b/tests/misc/tcolonisproc.nim
index e55587dfc..af4077284 100644
--- a/tests/misc/tcolonisproc.nim
+++ b/tests/misc/tcolonisproc.nim
@@ -2,10 +2,11 @@
 proc p(a, b: int, c: proc ()) =
   c()
 
- 
-p(1, 3): 
-  echo 1
-  echo 3
+when false:
+  # language spec changed:
+  p(1, 3):
+    echo 1
+    echo 3
     
 p(1, 1, proc() =
   echo 1
diff --git a/tests/misc/tnoinst.nim b/tests/misc/tnoinst.nim
index db1058d09..4c8d9d1aa 100644
--- a/tests/misc/tnoinst.nim
+++ b/tests/misc/tnoinst.nim
@@ -1,6 +1,7 @@
 discard """
   line: 12
   errormsg: "instantiate 'notConcrete' explicitly"
+  disabled: "true"
 """
 
 proc wrap[T]() =
diff --git a/tests/misc/tvarious.nim b/tests/misc/tvarious.nim
index ed2964cf9..8124b3fc7 100644
--- a/tests/misc/tvarious.nim
+++ b/tests/misc/tvarious.nim
@@ -1,64 +1,68 @@
-# Test various aspects

+# Test various aspects
 
 # bug #572
 var a=12345678901'u64
-

+
 var x = (x: 42, y: (a: 8, z: 10))
 echo x.y
-

-import

-  mvarious

-

-type

-  PA = ref TA

-  PB = ref TB

-

-  TB = object

-    a: PA

-

-  TA = object

-    b: TB

-    x: int

-

-proc getPA(): PA =

-  var

-    b: bool

-  b = not false

-  return nil

+
+import
+  mvarious
+
+type
+  PA = ref TA
+  PB = ref TB
+
+  TB = object
+    a: PA
+
+  TA = object
+    b: TB
+    x: int
+
+proc getPA(): PA =
+  var
+    b: bool
+  b = not false
+  return nil
 
 # bug #501
 proc f(): int = 54
-

-var

-  global: int

-

-var

-  s: string

-  i: int

-  r: TA

-

-r.b.a.x = 0

-global = global + 1

-exportme()

-write(stdout, "Hallo wie heißt du? ")

-write(stdout, getPA().x)

-s = readLine(stdin)

-i = 0

-while i < s.len:

-  if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n")

-  i = i + 1

-

-write(stdout, "Du heißt " & s)

+
+var
+  global: int
+
+var
+  s: string
+  i: int
+  r: TA
+
+r.b.a.x = 0
+global = global + 1
+exportme()
+write(stdout, "Hallo wie heißt du? ")
+write(stdout, getPA().x)
+s = readLine(stdin)
+i = 0
+while i < s.len:
+  if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n")
+  i = i + 1
+
+write(stdout, "Du heißt " & s)
 
 # bug #544
-when false:
-  # yay, fails again
-  type Bar [T; I:range] = array[I, T]
-  proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] =
-    when len(a) != 3: 
-      # Error: constant expression expected
-      {.fatal:"Dimensions have to be 3".}
-    #...
-  block:
-    var a, b: Bar[int, 0..2]
-    discard foo(a, b)
+
+# yay, fails again
+type Bar [T; I:range] = array[I, T]
+proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] =
+  when len(a) != 3:
+    # Error: constant expression expected
+    {.fatal:"Dimensions have to be 3".}
+  #...
+block:
+  var a, b: Bar[int, range[0..2]]
+  discard foo(a, b)
+
+# bug #1788
+
+echo "hello" & char(ord(' ')) & "world"
diff --git a/tests/parser/tprecedence.nim b/tests/parser/tprecedence.nim
index 6b1b250a2..d2c6d0b30 100644
--- a/tests/parser/tprecedence.nim
+++ b/tests/parser/tprecedence.nim
@@ -1,11 +1,15 @@
 discard """
-  output: "true"
+  output: '''holla
+true'''
 """
 
+# Test top level semicolon works properly:
+import os; echo "holla"
+
 # Test the new predence rules
 
 proc `\+` (x, y: int): int = result = x + y
 proc `\*` (x, y: int): int = result = x * y
 
-echo 5 \+ 1 \* 9 == 14
+echo 5 \+ 1 \* 9 == 6*9
 
diff --git a/tests/static/tstaticparammacro.nim b/tests/static/tstaticparammacro.nim
index 7fb9e2014..ebd6caa47 100644
--- a/tests/static/tstaticparammacro.nim
+++ b/tests/static/tstaticparammacro.nim
@@ -10,6 +10,9 @@ AST a
 AST b 
 (e: [55, 66], f: [77, 88])
 55
+10
+20Test
+20
 '''
 """
 
@@ -50,3 +53,22 @@ macro mB(data: static[Tb]): stmt =
 mA(a)
 mB(b)
 
+type
+  Foo[N: static[int], Z: static[string]] = object
+
+macro staticIntMacro(f: static[int]): stmt = echo f
+staticIntMacro 10
+
+var
+  x: Foo[20, "Test"]
+
+macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12): stmt =
+  echo N, Z
+
+genericMacro x
+
+template genericTemplate[N, Z](f: Foo[N, Z], ll = 3, zz = 12): int = N
+
+static:
+  echo genericTemplate(x) # Error: internal error: (filename: compiler/evaltempl.nim, line: 39)
+
diff --git a/tests/stdlib/tmath2.nim b/tests/stdlib/tmath2.nim
index 935b08634..88d96c80a 100644
--- a/tests/stdlib/tmath2.nim
+++ b/tests/stdlib/tmath2.nim
@@ -58,7 +58,7 @@ proc TestLoops() =
       break

     break

 

-  while True:

+  while true:

     break

 

 

@@ -73,7 +73,7 @@ proc main() =
     res: int

     s: string

   #write(stdout, mymax(23, 45))

-  write(stdout, "Hallo! Wie heißt du? ")

+  write(stdout, "Hallo! Wie heisst du? ")

   s = readLine(stdin)

   # test the case statement

   case s

diff --git a/tests/stdlib/tparsefloat.nim b/tests/stdlib/tparsefloat.nim
deleted file mode 100644
index 38ed2db6d..000000000
--- a/tests/stdlib/tparsefloat.nim
+++ /dev/null
@@ -1,3 +0,0 @@
-import strutils
-
-echo ParseFloat("5000") / ParseFloat("10")
diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim
index e5353e4ff..1bc2669c3 100644
--- a/tests/stdlib/tpegs.nim
+++ b/tests/stdlib/tpegs.nim
@@ -397,7 +397,7 @@ proc esc(c: char, reserved = {'\0'..'\255'}): string =
   elif c in reserved: result = '\\' & c
   else: result = $c
   
-proc singleQuoteEsc(c: Char): string = return "'" & esc(c, {'\''}) & "'"
+proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
 
 proc singleQuoteEsc(str: string): string = 
   result = "'"
@@ -421,11 +421,11 @@ proc charSetEscAux(cc: set[char]): string =
       c1 = c2
     inc(c1)
   
-proc CharSetEsc(cc: set[char]): string =
+proc charSetEsc(cc: set[char]): string =
   if card(cc) >= 128+64: 
-    result = "[^" & CharSetEscAux({'\1'..'\xFF'} - cc) & ']'
+    result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
   else: 
-    result = '[' & CharSetEscAux(cc) & ']'
+    result = '[' & charSetEscAux(cc) & ']'
   
 proc toStrAux(r: TPeg, res: var string) = 
   case r.kind
@@ -522,12 +522,12 @@ proc `$` *(r: TPeg): string {.rtl, extern: "npegsToString".} =
 
 type
   TCaptures* {.final.} = object ## contains the captured substrings.
-    matches: array[0..maxSubpatterns-1, tuple[first, last: int]]
+    matches: array[0..MaxSubpatterns-1, tuple[first, last: int]]
     ml: int
     origStart: int
 
 proc bounds*(c: TCaptures, 
-             i: range[0..maxSubpatterns-1]): tuple[first, last: int] = 
+             i: range[0..MaxSubpatterns-1]): tuple[first, last: int] = 
   ## returns the bounds ``[first..last]`` of the `i`'th capture.
   result = c.matches[i]
 
@@ -695,7 +695,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
     while start+result < s.len:
       var x = rawMatch(s, p.sons[0], start+result, c)
       if x >= 0:
-        if idx < maxSubpatterns:
+        if idx < MaxSubpatterns:
           c.matches[idx] = (start, start+result-1)
         #else: silently ignore the capture
         inc(result, x)
@@ -739,7 +739,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
     inc(c.ml)
     result = rawMatch(s, p.sons[0], start, c)
     if result >= 0:
-      if idx < maxSubpatterns:
+      if idx < MaxSubpatterns:
         c.matches[idx] = (start, start+result-1)
       #else: silently ignore the capture
     else:
@@ -836,7 +836,7 @@ iterator findAll*(s: string, pattern: TPeg, start = 0): string =
   while i < s.len:
     var L = matchLen(s, pattern, matches, i)
     if L < 0: break
-    for k in 0..maxSubPatterns-1: 
+    for k in 0..MaxSubPatterns-1: 
       if isNil(matches[k]): break
       yield matches[k]
     inc(i, L)
@@ -866,7 +866,7 @@ template `=~`*(s: string, pattern: TPeg): expr =
   ##     echo("syntax error")
   ##  
   when not definedInScope(matches):
-    var matches {.inject.}: array[0..maxSubpatterns-1, string]
+    var matches {.inject.}: array[0..MaxSubpatterns-1, string]
   match(s, pattern, matches)
 
 # ------------------------- more string handling ------------------------------
@@ -907,7 +907,7 @@ proc replacef*(s: string, sub: TPeg, by: string): string {.
   ##   "var1<-keykey; val2<-key2key2"
   result = ""
   var i = 0
-  var caps: array[0..maxSubpatterns-1, string]
+  var caps: array[0..MaxSubpatterns-1, string]
   while i < s.len:
     var x = matchLen(s, sub, caps, i)
     if x <= 0:
@@ -924,7 +924,7 @@ proc replace*(s: string, sub: TPeg, by = ""): string {.
   ## in `by`.
   result = ""
   var i = 0
-  var caps: array[0..maxSubpatterns-1, string]
+  var caps: array[0..MaxSubpatterns-1, string]
   while i < s.len:
     var x = matchLen(s, sub, caps, i)
     if x <= 0:
@@ -942,7 +942,7 @@ proc parallelReplace*(s: string, subs: varargs[
   ## applied in parallel.
   result = ""
   var i = 0
-  var caps: array[0..maxSubpatterns-1, string]
+  var caps: array[0..MaxSubpatterns-1, string]
   while i < s.len:
     block searchSubs:
       for j in 0..high(subs):
@@ -1055,7 +1055,7 @@ type
   TPegLexer {.inheritable.} = object          ## the lexer object.
     bufpos: int               ## the current position within the buffer
     buf: cstring              ## the buffer itself
-    LineNumber: int           ## the current line number
+    lineNumber: int           ## the current line number
     lineStart: int            ## index of last line start in buffer
     colOffset: int            ## column to add
     filename: string
@@ -1118,38 +1118,38 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
   case c.buf[c.bufpos]
   of 'r', 'R', 'c', 'C': 
     add(tok.literal, '\c')
-    Inc(c.bufpos)
+    inc(c.bufpos)
   of 'l', 'L': 
     add(tok.literal, '\L')
-    Inc(c.bufpos)
+    inc(c.bufpos)
   of 'f', 'F': 
     add(tok.literal, '\f')
     inc(c.bufpos)
   of 'e', 'E': 
     add(tok.literal, '\e')
-    Inc(c.bufpos)
+    inc(c.bufpos)
   of 'a', 'A': 
     add(tok.literal, '\a')
-    Inc(c.bufpos)
+    inc(c.bufpos)
   of 'b', 'B': 
     add(tok.literal, '\b')
-    Inc(c.bufpos)
+    inc(c.bufpos)
   of 'v', 'V': 
     add(tok.literal, '\v')
-    Inc(c.bufpos)
+    inc(c.bufpos)
   of 't', 'T': 
     add(tok.literal, '\t')
-    Inc(c.bufpos)
+    inc(c.bufpos)
   of 'x', 'X': 
     inc(c.bufpos)
     var xi = 0
     handleHexChar(c, xi)
     handleHexChar(c, xi)
     if xi == 0: tok.kind = tkInvalid
-    else: add(tok.literal, Chr(xi))
+    else: add(tok.literal, chr(xi))
   of '0'..'9': 
     var val = ord(c.buf[c.bufpos]) - ord('0')
-    Inc(c.bufpos)
+    inc(c.bufpos)
     var i = 1
     while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): 
       val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
@@ -1159,11 +1159,11 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
     else: tok.kind = tkInvalid
   of '\0'..'\31':
     tok.kind = tkInvalid
-  elif c.buf[c.bufpos] in strutils.letters:
+  elif c.buf[c.bufpos] in strutils.Letters:
     tok.kind = tkInvalid
   else:
     add(tok.literal, c.buf[c.bufpos])
-    Inc(c.bufpos)
+    inc(c.bufpos)
   
 proc skip(c: var TPegLexer) = 
   var pos = c.bufpos
@@ -1171,7 +1171,7 @@ proc skip(c: var TPegLexer) =
   while true: 
     case buf[pos]
     of ' ', '\t': 
-      Inc(pos)
+      inc(pos)
     of '#':
       while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
     of '\c':
@@ -1203,7 +1203,7 @@ proc getString(c: var TPegLexer, tok: var TToken) =
       break      
     else:
       add(tok.literal, buf[pos])
-      Inc(pos)
+      inc(pos)
   c.bufpos = pos
   
 proc getDollar(c: var TPegLexer, tok: var TToken) = 
@@ -1244,7 +1244,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
       break
     else: 
       ch = buf[pos]
-      Inc(pos)
+      inc(pos)
     incl(tok.charset, ch)
     if buf[pos] == '-':
       if buf[pos+1] == ']':
@@ -1264,7 +1264,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
           break
         else: 
           ch2 = buf[pos]
-          Inc(pos)
+          inc(pos)
         for i in ord(ch)+1 .. ord(ch2):
           incl(tok.charset, chr(i))
   c.bufpos = pos
@@ -1275,7 +1275,7 @@ proc getSymbol(c: var TPegLexer, tok: var TToken) =
   var buf = c.buf
   while true: 
     add(tok.literal, buf[pos])
-    Inc(pos)
+    inc(pos)
     if buf[pos] notin strutils.IdentChars: break
   c.bufpos = pos
   tok.kind = tkIdentifier
@@ -1312,11 +1312,11 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
     getCharset(c, tok)
   of '(':
     tok.kind = tkParLe
-    Inc(c.bufpos)
+    inc(c.bufpos)
     add(tok.literal, '(')
   of ')':
     tok.kind = tkParRi
-    Inc(c.bufpos)
+    inc(c.bufpos)
     add(tok.literal, ')')
   of '.': 
     tok.kind = tkAny
diff --git a/tests/stdlib/tsockets.nim b/tests/stdlib/tsockets.nim
deleted file mode 100644
index ff566df74..000000000
--- a/tests/stdlib/tsockets.nim
+++ /dev/null
@@ -1,12 +0,0 @@
-import sockets, os
-var s: TSocket
-s = socket()
-if s == InvalidSocket: osError(osLastError())
-
-s.connect("www.google.com", TPort(80))
-
-var data: string = ""
-s.readLine(data)
-echo(data)
-
-
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index ae9905cde..7c7d71aa2 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -107,12 +107,15 @@ proc dllTests(r: var TResults, cat: Category, options: string) =
 # ------------------------------ GC tests -------------------------------------
 
 proc gcTests(r: var TResults, cat: Category, options: string) =
-  template test(filename: expr): stmt =
+  template testWithoutMs(filename: expr): stmt =
     testSpec r, makeTest("tests/gc" / filename, options, cat, actionRun)
     testSpec r, makeTest("tests/gc" / filename, options &
                   " -d:release", cat, actionRun)
     testSpec r, makeTest("tests/gc" / filename, options &
                   " -d:release -d:useRealtimeGC", cat, actionRun)
+
+  template test(filename: expr): stmt =
+    testWithoutMs filename
     testSpec r, makeTest("tests/gc" / filename, options &
                   " --gc:markAndSweep", cat, actionRun)
     testSpec r, makeTest("tests/gc" / filename, options &
@@ -124,13 +127,15 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
   test "gctest"
   test "gcleak3"
   test "gcleak4"
-  test "gcleak5"
+  # Disabled because it works and takes too long to run:
+  #test "gcleak5"
   test "weakrefs"
   test "cycleleak"
   test "closureleak"
-  test "refarrayleak"
-  test "stackrefleak"
+  testWithoutMs "refarrayleak"
   
+  test "stackrefleak"
+  test "cyclecollector"
 
 # ------------------------- threading tests -----------------------------------
 
diff --git a/tests/threads/ttryrecv.nim b/tests/threads/ttryrecv.nim
new file mode 100644
index 000000000..acccf182c
--- /dev/null
+++ b/tests/threads/ttryrecv.nim
@@ -0,0 +1,35 @@
+discard """
+  outputsub: "channel is empty"
+"""
+
+# bug #1816
+
+from math import random
+from os import sleep
+
+type PComm = ptr TChannel[int]
+
+proc doAction(outC: PComm) {.thread.} =
+  for i in 0.. <5:
+    sleep(random(100))
+    send(outC[], i)
+
+var
+  thr: TThread[PComm]
+  chan: TChannel[int]
+
+open(chan)
+createThread[PComm](thr, doAction, addr(chan))
+
+while true:
+  let (flag, x) = tryRecv(chan)
+  if flag:
+    echo("received from chan: " & $x)
+  else:
+    echo "channel is empty"
+    break
+
+echo "Finished listening"
+
+joinThread(thr)                                                       
+close(chan)
diff --git a/tests/typerel/typedescs.nim b/tests/typerel/typedescs.nim
new file mode 100644
index 000000000..23b9ce64f
--- /dev/null
+++ b/tests/typerel/typedescs.nim
@@ -0,0 +1,7 @@
+# bug #1774
+proc p(T: typedesc) = discard
+
+p(type((5, 6)))       # Compiles
+(type((5, 6))).p      # Doesn't compile (SIGSEGV: Illegal storage access.)
+type T = type((5, 6)) # Doesn't compile (SIGSEGV: Illegal storage access.)
+
diff --git a/tests/types/temptyseqs.nim b/tests/types/temptyseqs.nim
new file mode 100644
index 000000000..f8d22bdb8
--- /dev/null
+++ b/tests/types/temptyseqs.nim
@@ -0,0 +1,26 @@
+discard """
+  output: "1"
+"""
+
+# bug #1708
+let foo = {
+  "1" : (bar: @["1"]),
+  "2" : (baz: @[])
+}
+
+# bug #871
+
+when true:
+  import os
+
+  type
+    In_out = tuple[src, dest, options: string]
+
+  let
+    nil_var: In_out = ("hey"/"there", "something", nil)
+    #nil_var2 = ("hey"/"there", "something", nil)
+
+# bug #1721
+const foo2: seq[string] = @[]
+
+echo foo[0][0][0]
diff --git a/tests/types/tisopr.nim b/tests/types/tisopr.nim
index 3c2b9ee5e..8b7fe4e46 100644
--- a/tests/types/tisopr.nim
+++ b/tests/types/tisopr.nim
@@ -34,3 +34,20 @@ type
 yes s.items is Iter[TNumber]
 no  s.items is Iter[float]
 
+type
+  Foo[N: static[int], T] = object
+    field: array[1..N, T]
+
+  Bar[T] = Foo[4, T]
+  Baz[N: static[int]] = Foo[N, float]
+
+no Foo[2, float] is Foo[3, float]
+no Foo[2, float] is Foo[2, int]
+
+yes Foo[4, string] is Foo[4, string]
+yes Bar[int] is Foo[4, int]
+yes Foo[4, int] is Bar[int]
+
+no Foo[4, int] is Baz[4]
+yes Foo[4, float] is Baz[4]
+
diff --git a/tests/vm/triangle_array.nim b/tests/vm/triangle_array.nim
new file mode 100644
index 000000000..054c66f22
--- /dev/null
+++ b/tests/vm/triangle_array.nim
@@ -0,0 +1,17 @@
+discard """
+  output: "56"
+"""
+
+# bug #1781
+
+proc initCombinations: array[11, array[11, int]] =
+  result[0]          = [1,2,3,4,5,6,7,8,9,10,11]
+  result[1][1 .. 10] =   [12,13,14,15,16,17,18,19,20,21]
+  result[2][2 .. 10] =     [22,23,24,25,26,27,28,29,30]
+  result[3][3 .. 10] =       [31,32,33,34,35,36,37,38]
+  result[4][4 .. 10] =         [39,40,41,42,43,44,45]
+  result[5][5 .. 10] =           [46,47,48,49,50,51]
+  result[6][6 .. 10] =             [52,53,54,55,56]
+
+const combinations = initCombinations()
+echo combinations[6][10]
diff --git a/tests/vm/tstringnil.nim b/tests/vm/tstringnil.nim
index 5070dd6b7..61ce60ee5 100644
--- a/tests/vm/tstringnil.nim
+++ b/tests/vm/tstringnil.nim
@@ -32,7 +32,7 @@ proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: PNimrodNode): tuple[tes
         testObj.testDesc = nil
       else:
         testObj.testDesc = child[2].strVal
-      testObj.testBlock = child[3][6]
+      testObj.testBlock = child[1]
 
       tests.add(testObj)
 
diff --git a/todo.txt b/todo.txt
index 6b1ec569f..b2d8b034e 100644
--- a/todo.txt
+++ b/todo.txt
@@ -3,8 +3,6 @@ version 0.10
 
 - The bitwise 'not' operator will be renamed to 'bnot' to
   prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
-- The 'do' notation might be trimmed so that its only purpose is to pass
-  multiple multi line constructs to a macro.
 
 - c2nim depends on the compiler
 - make nimble part of the distribution
@@ -23,6 +21,7 @@ Low priority:
 - support for exception propagation? (hard to implement)
 - the copying of the 'ref Promise' into the thead local storage only
   happens to work due to the write barrier's implementation
+- clean up the C code generator. Full of cruft.
 
 
 Misc
@@ -62,6 +61,8 @@ version 0.9.x
 - we need a magic thisModule symbol
 - ensure (ref T)(a, b) works as a type conversion and type constructor
 - optimize 'genericReset'; 'newException' leads to code bloat
+- The 'do' notation might be trimmed so that its only purpose is to pass
+  multiple multi line constructs to a macro.
 
 
 version 0.9.X
diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index 9ee3eb9b9..fe1b9a192 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -522,8 +522,8 @@ proc setupDist2(c: var TConfigData) =
 # ------------------ generate ZIP file ---------------------------------------
 when haveZipLib:
   proc zipDist(c: var TConfigData) =
-    var proj = toLower(c.name)
-    var n = "$#_$#.zip" % [proj, c.version]
+    var proj = toLower(c.name) & "-" & c.version
+    var n = "$#.zip" % proj
     if c.outdir.len == 0: n = "build" / n
     else: n = c.outdir / n
     var z: TZipArchive
diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl
index 40e171d41..23bbf3ac9 100644
--- a/tools/niminst/nsis.tmpl
+++ b/tools/niminst/nsis.tmpl
@@ -128,7 +128,7 @@
     ; Write application registry keys
     WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
-    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninstaller.exe"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index 0cf19096d..91aa17e7e 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -48,7 +48,7 @@ proc initConfigData(c: var TConfigData) =
   c.logo = ""
   c.ticker = ""
   c.vars = newStringTable(modeStyleInsensitive)
-  c.gitRepo = "https://github.com/Araq/Nimrod/tree"
+  c.gitRepo = "https://github.com/Araq/Nim/tree"
   c.gitCommit = "master"
   c.numProcessors = countProcessors()
   # Attempts to obtain the git current commit.
@@ -268,24 +268,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
   exec("nim doc2 $# -o:$# $#" %
     [c.nimArgs, destPath / "docgen_sample2.html", src])
 
+proc pathPart(d: string): string = splitFile(d).dir.replace('\\', '/')
+
 proc buildDoc(c: var TConfigData, destPath: string) =
   # call nim for the documentation:
   var
     commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
     i = 0
   for d in items(c.doc):
-    commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
   for d in items(c.srcdoc):
-    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
   for d in items(c.srcdoc2):
-    commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
 
@@ -317,8 +319,8 @@ proc buildAddDoc(c: var TConfigData, destPath: string) =
   # build additional documentation (without the index):
   var commands = newSeq[string](c.webdoc.len)
   for i, doc in pairs(c.webdoc):
-    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, doc.pathPart,
       destPath / changeFileExt(splitFile(doc).name, "html"), doc]
   mexec(commands, c.numProcessors)
 
@@ -402,8 +404,8 @@ proc buildNewsRss(c: var TConfigData, destPath: string) =
   generateRss(destFilename, parseNewsTitles(srcFilename))
 
 proc buildJS(destPath: string) =
-  exec("nim js -d:release --out:$1 web/babelpkglist.nim" %
-      [destPath / "babelpkglist.js"])
+  exec("nim js -d:release --out:$1 web/nimblepkglist.nim" %
+      [destPath / "nimblepkglist.js"])
 
 proc buildWebsite(c: var TConfigData) =
   const
diff --git a/tools/website.tmpl b/tools/website.tmpl
index 2197e361c..0c059fb87 100644
--- a/tools/website.tmpl
+++ b/tools/website.tmpl
@@ -63,7 +63,7 @@
 <span class="tab end">  </span>count += <span class="val">1</span>

 

 echo(<span class="val">"Average line length: "</span>,

-  <span class="kwd">if</span> count: sum / count <span class="kwd">else</span>: <span class="val">0</span>)

+  <span class="kwd">if</span> count &gt; <span class="val">0</span>: sum / count <span class="kwd">else</span>: <span class="val">0</span>)

 </pre>

             </div>

             <div>

diff --git a/web/assets/style.css b/web/assets/style.css
index f12afa838..da4cff05c 100644
--- a/web/assets/style.css
+++ b/web/assets/style.css
@@ -100,8 +100,9 @@ pre .end { background:url("images/tabEnd.png") no-repeat left bottom; }
 		height:844px;
 		background:url("images/glow-line-vert.png") no-repeat; }
 	
-	#slideshow { position:absolute; top:10px; left:10px; width:700px; }
-	#slideshow > div { visibility:hidden; opacity:0; position:absolute; transition:visibility 0s linear 1s, opacity 1s ease-in-out; }
+	#slideshow { position:absolute; top:10px; left:10px; width:700px; height: 1000px; }
+	#slideshow > div {
+	  visibility:hidden; opacity:0; position:absolute; transition:visibility 0s linear 1s, opacity 1s ease-in-out; }
 	#slideshow > div.active { visibility:visible; opacity:1; transition-delay:0s; }
 	#slideshow > div.init { transition-delay:0s; }
 	#slideshow-nav { z-index:3; position:absolute; top:110px;; right:-12px; }
diff --git a/web/community.txt b/web/community.txt
index fc496ca82..f5d6db0e7 100644
--- a/web/community.txt
+++ b/web/community.txt
@@ -34,9 +34,9 @@ Nim's Community
   Github
   ------
 
-  Nim's `source code <http://github.com/Araq/Nimrod>`_ is hosted on Github.
-  Together with the `wiki <http://github.com/Araq/Nimrod/wiki>`_ and
-  `issue tracker <http://github.com/Araq/Nimrod/issues>`_.
+  Nim's `source code <http://github.com/Araq/Nim>`_ is hosted on Github.
+  Together with the `wiki <http://github.com/Araq/Nim/wiki>`_ and
+  `issue tracker <http://github.com/Araq/Nim/issues>`_.
 
   Github also hosts other projects relating to Nim. These projects are a part
   of the `nim-lang organisation <http://github.com/nim-lang>`_.
diff --git a/web/download.txt b/web/download.txt
index 0d3d75756..497781ad6 100644
--- a/web/download.txt
+++ b/web/download.txt
@@ -1,6 +1,6 @@
-You can download the latest version of the Nimrod compiler here.
+You can download the latest version of the Nim compiler here.
 
-**Note:** The Nimrod compiler requires a C compiler to compile software. On
+**Note:** The Nim compiler requires a C compiler to compile software. On
 Windows we recommend that you use
 `Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
 and clang on Mac OS X.
@@ -10,9 +10,8 @@ Binaries
 ========
 
 Unfortunately for now we only provide builds for Windows.
-
-* 32 bit: `nimrod_0.9.6.exe <download/nimrod_0.9.6.exe>`_
-* 64 bit: `nimrod_0.9.6_x64.exe <download/nimrod_0.9.6_x64.exe>`_
+* 32 bit: `nim-0.10.2_x32.exe <download/nim-0.10.2_x32.exe>`_
+* 64 bit: `nim-0.10.2_x64.exe <download/nim-0.10.2_x64.exe>`_
 
 
 Installation based on generated C code
@@ -22,13 +21,13 @@ This installation method is the preferred way for Linux, Mac OS X, and other Uni
 like systems. Binary packages may be provided later.
 
 
-Download `nimrod_0.9.6.zip <download/nimrod_0.9.6.zip>`_, extract it and follow
+Download `nim-0.10.2.zip <download/nim-0.10.2.zip>`_, extract it and follow
 these instructions:
 
 * sh build.sh
 * Add ``$your_install_dir/bin`` to your PATH.
 
-There are other ways to install Nimrod (like using the ``install.sh`` script),
+There are other ways to install Nim (like using the ``install.sh`` script),
 but these tend to cause more problems.
 
 
@@ -38,8 +37,8 @@ Installation from github
 Use the following commands to build the compiler from source.
 Change the branch to suit your needs::
 
-  git clone -b master git://github.com/Araq/Nimrod.git
-  cd Nimrod
+  git clone -b master git://github.com/Araq/Nim.git
+  cd Nim
   git clone -b master --depth 1 git://github.com/nim-lang/csources
   cd csources && sh build.sh
   cd ..
diff --git a/web/index.txt b/web/index.txt
index 1d76c1cda..95cac9316 100644
--- a/web/index.txt
+++ b/web/index.txt
@@ -5,16 +5,16 @@ Home
 Welcome to Nim
 --------------
 
-**Nim** (formerly known as "Nimrod") is a statically typed, imperative 
-programming language that tries to give the programmer ultimate power without 
+**Nim** (formerly known as "Nimrod") is a statically typed, imperative
+programming language that tries to give the programmer ultimate power without
 compromises on runtime efficiency. This means it focuses on compile-time
 mechanisms in all their various forms.
 
-Beneath a nice infix/indentation based syntax with a 
-powerful (AST based, hygienic) macro system lies a semantic model that supports 
-a soft realtime GC on thread local heaps. Asynchronous message passing is used 
-between threads, so no "stop the world" mechanism is necessary. An unsafe 
-shared memory heap is also provided for the increased efficiency that results 
+Beneath a nice infix/indentation based syntax with a
+powerful (AST based, hygienic) macro system lies a semantic model that supports
+a soft realtime GC on thread local heaps. Asynchronous message passing is used
+between threads, so no "stop the world" mechanism is necessary. An unsafe
+shared memory heap is also provided for the increased efficiency that results
 from that model.
 
 
@@ -24,7 +24,7 @@ Nim is efficient
 * Native code generation (currently via compilation to C), not dependent on a
   virtual machine: **Nim produces small executables without dependencies
   for easy redistribution.**
-* A fast **non-tracing** garbage collector that supports soft 
+* A fast **non-tracing** garbage collector that supports soft
   real-time systems (like games).
 * System programming features: Ability to manage your own memory and access the
   hardware directly. Pointers to garbage collected memory are distinguished
@@ -33,22 +33,22 @@ Nim is efficient
 * Cross-module inlining.
 * Dynamic method binding with inlining and without virtual method table.
 * Compile time evaluation of user-defined functions.
-* Whole program dead code elimination: Only *used functions* are included in 
+* Whole program dead code elimination: Only *used functions* are included in
   the executable.
-* Value-based datatypes: For instance, objects and arrays can be allocated on 
+* Value-based datatypes: For instance, objects and arrays can be allocated on
   the stack.
 
 
 Nim is expressive
 =================
 
-* **The Nim compiler and all of the standard library are implemented in 
+* **The Nim compiler and all of the standard libraries are implemented in
   Nim.**
 * Built-in high level datatypes: strings, sets, sequences, etc.
-* Modern type system with local type inference, tuples, variants, 
+* Modern type system with local type inference, tuples, variants,
   generics, etc.
 * User-defineable operators; code with new operators is often easier to read
-  than code which overloads built-in operators. For example, a 
+  than code which overloads built-in operators. For example, a
   ``=~`` operator is defined in the ``re`` module.
 * Macros can modify the abstract syntax tree at compile time.
 
@@ -58,7 +58,7 @@ Nim is elegant
 
 * Macros can use the imperative paradigm to construct parse trees. Nim
   does not require a different coding style for meta programming.
-* Macros cannot change Nim's syntax because there is no need for it. 
+* Macros cannot change Nim's syntax because there is no need for it.
   Nim's syntax is flexible enough.
 * Statements are grouped by indentation but can span multiple lines.
   Indentation must not contain tabulators so the compiler always sees
@@ -72,12 +72,12 @@ Nim plays nice with others
   Porting to other platforms is easy.
 * **The Nim Compiler can also generate C++ or Objective C for easier
   interfacing.**
-* There are lots of bindings: for example, bindings to GTK2, the Windows API, 
-  the POSIX API, OpenGL, SDL, Cairo, Python, Lua, TCL, X11, libzip, PCRE, 
+* There are lots of bindings: for example, bindings to GTK2, the Windows API,
+  the POSIX API, OpenGL, SDL, Cairo, Python, Lua, TCL, X11, libzip, PCRE,
   libcurl, mySQL and SQLite are included in the standard distribution or
   can easily be obtained via the
-  `Nimble package manager <https://github.com/nimrod-code/nimble>`_.
-* A C to Nim conversion utility: New bindings to C libraries are easily 
+  `Nimble package manager <https://github.com/nim-lang/nimble>`_.
+* A C to Nim conversion utility: New bindings to C libraries are easily
   generated by ``c2nim``.
 
 
@@ -85,5 +85,5 @@ Roadmap to 1.0
 ==============
 
 Please have a look at
-this `wiki page <https://github.com/Araq/Nimrod/wiki/Roadmap>`_ for
+this `wiki page <https://github.com/Araq/Nim/wiki/Roadmap>`_ for
 an up-to-date overview.
diff --git a/web/learn.txt b/web/learn.txt
index 25db150a4..854b31668 100644
--- a/web/learn.txt
+++ b/web/learn.txt
@@ -24,7 +24,7 @@ Learning Nim
   - | `Nim on Rosetta Code <http://rosettacode.org/wiki/Category:Nimrod>`_
     | Many different Nim code examples comparable to other languages for reference.
 
-  - | `Nim for C/C++ Programmers <https://github.com/Araq/Nimrod/wiki/Nimrod-for-C-programmers>`_
+  - | `Nim for C/C++ Programmers <https://github.com/Araq/Nim/wiki/Nim-for-C-programmers>`_
     | A useful cheat-sheet for those most familiar with C/C++ languages.
 
 
diff --git a/web/news.txt b/web/news.txt
index c55620431..ee9ad8837 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -2,105 +2,200 @@
 News
 ====
 
-..
-  2014-10-21 Version 0.10.2 released
-  ==================================
-
-  This release is the latest release before the release canditates for version
-  1.0 roll in. Starting with version 0.10.2 the rename of the language to Nim
-  is officially complete. As the list of language changes is quite long it's
-  much more work to update the average Nim project than used to be the case.
-  However there is a new tool, `nimfix <nimfix.html>`_ to help you
-  in updating your code from Nimrod to Nim. This tool is unfortunately not
-  perfect but has been used to update thousands of lines of code successfully.
-
-
-  Changes affecting backwards compatibility
-  -----------------------------------------
-
-  - **The language has been renamed from Nimrod to Nim.** The name of the
-    compiler changed from ``nimrod`` to ``nim`` too.
-  - ``system.fileHandle`` has been renamed to ``system.getFileHandle`` to
-    prevent name conflicts with the new type ``FileHandle``.
-  - Comments are now not part of the AST, as such you cannot use them in place
-    of ``discard``.
-  - Large parts of the stdlib got rid of the T/P type prefixes. Instead most
-    types now simply start with an uppercased letter. The
-    so called "partial case sensitivity" rule is now active allowing for code
-    like ``var foo: Foo`` in more contexts.
-  - String case (or any non-ordinal case) statements
-    without 'else' are deprecated.
-  - Recursive tuple types are not allowed anymore. Use ``object`` instead.
-  - The PEGS module returns ``nil`` instead of ``""`` when an optional capture
-    fails to match.
-  - The re module returns ``nil`` instead of ``""`` when an optional capture
-    fails to match.
-  - The "symmetric set difference" operator (``-+-``) never worked and has been
-    removed.
-  - ``defer`` is a keyword now.
-  - ``func`` is a keyword now.
-  - The ``using`` language feature now needs to be activated via the new
-    ``{.experimental.}`` pragma that enables experimental language features.
-  - Destructors are now officially *experimental*.
-  - Standalone ``except`` and ``finally`` statements are deprecated now.
-    The standalone ``finally`` can be replaced with ``defer``,
-    standalone ``except`` requires an explicit ``try``.
-  - Operators ending in ``>`` are considered as "arrow like" and have their
-    own priority level and are right associative. This means that
-    the ``=>`` and ``->`` operators from the `future <future.html>`_ module
-    work better.
-  - Field names in tuples are now ignored for type comparisons. This allows
-    for greater interoperability between different modules.
-
-
-  Language Additions
-  ------------------
-
-  - The new concurrency model has been implemented including ``locks`` sections,
-    lock levels and object field ``guards``.
-  - The ``parallel`` statement has been implemented.
-  - ``deepCopy`` has been added to the language.
-  - The builtin ``procCall`` can be used to get ``super``-like functionality
-    for multi methods.
-  - There is a new pragma ``{.experimental.}`` that enables experimental
-    language features per module, or you can enable this features on a global
-    level with the ``--experimental`` command line option.
-
-
-  Compiler Additions
-  ------------------
-
-  - The compiler now supports *mixed* Objective C / C++ / C code generation:
-    The modules that use ``importCpp`` or ``importObjc`` are compiled to C++
-    or Objective C code, any other module is compiled to C code. This
-    improves interoperability.
-  - There is a new ``parallel`` statement for safe fork&join parallel computing.
-  - ``guard`` and ``lock`` pragmas have been implemented to support safer
-    concurrent programming.
-  - The following procs are now available at compile-time::
-
-      math.sqrt, math.ln, math.log10, math.log2, math.exp, math.round,
-      math.arccos, math.arcsin, math.arctan, math.arctan2, math.cos, math.cosh,
-      math.hypot, math.sinh, math.sin, math.tan, math.tanh, math.pow,
-      math.trunc, math.floor, math.ceil, math.fmod,
-      os.getEnv, os.existsEnv, os.dirExists, os.fileExists,
-      system.writeFile
-
-  - Two backticks now produce a single backtick within an ``emit`` or ``asm``
-    statement.
-  - There is a new tool, `nimfix <nimfix.html>`_ to help you in updating your
-    code from Nimrod to Nim.
-  
+2014-12-29 Version 0.10.2 released
+==================================
+
+This release marks the completion of a very important change to the project:
+the official renaming from Nimrod to Nim. Version 0.10.2 contains many language
+changes, some of which may break your existing code. For your convenience, we
+added a new tool called `nimfix <nimfix.html>`_ that will help you convert your
+existing projects so that it works with the latest version of the compiler.
+
+Progress towards version 1.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Although Nim is still pre-1.0, we were able to keep the number of breaking
+changes to a minimum so far. Starting with version 1.0, we will not introduce
+any breaking changes between major release versions.
+One of Nim's goals is to ensure that the compiler is as efficient as possible.
+Take a look at the
+`latest benchmarks <https://github.com/logicchains/LPATHBench/blob/master/writeup.md>`_,
+which show that Nim is consistently near
+the top and already nearly as fast as C and C++. Recent developments, such as
+the new ``asyncdispatch`` module will allow you to write efficient web server
+applications using non-blocking code. Nim now also has a built-in thread pool
+for lightweight threading through the use of ``spawn``.
+
+The unpopular "T" and "P" prefixes on types have been deprecated. Nim also
+became more expressive by weakening the distinction between statements and
+expressions. We also added a new and searchable forum, a new website, and our
+documentation generator ``docgen`` has seen major improvements. Many thanks to
+Nick Greenfield for the much more beautiful documentation!
+
+
+
+What's left to be done
+~~~~~~~~~~~~~~~~~~~~~~
+
+The 1.0 release is actually very close. Apart from bug fixes, there are
+two major features missing or incomplete:
+
+* ``static[T]`` needs to be defined precisely and the bugs in the
+  implementation need to be fixed.
+* Overloading of the assignment operator is required for some generic
+  containers and needs to be implemented.
+
+This means that fancy matrix libraries will finally start to work, which used
+to be a major point of pain in the language.
+
+
+Nimble and other Nim tools
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Outside of the language and the compiler itself many Nim tools have seen
+considerable improvements.
+
+Babel the Nim package manager has been renamed to Nimble. Nimble's purpose
+is the installation of packages containing libraries and/or applications
+written in Nim.
+Even though Nimble is still very young it already is very
+functional. It can install packages by name, it does so by accessing a
+packages repository which is hosted on a Github repo. Packages can also be
+installed via a Git repo URL or Mercurial repo URL. The package repository
+is searchable through Nimble. Anyone is free to add their own packages to
+the package repository by forking the
+`nim-lang/packages <https://github.com/nim-lang/packages>`_ repo and creating
+a pull request. Nimble is fully cross-platform and should be fully functional
+on all major operating systems.
+It is of course completely written in Nim.
+
+Changelog
+~~~~~~~~~
+
+Changes affecting backwards compatibility
+-----------------------------------------
+
+- **The language has been renamed from Nimrod to Nim.** The name of the
+  compiler changed from ``nimrod`` to ``nim`` too.
+- ``system.fileHandle`` has been renamed to ``system.getFileHandle`` to
+  prevent name conflicts with the new type ``FileHandle``.
+- Comments are now not part of the AST anymore, as such you cannot use them
+  in place of ``discard``.
+- Large parts of the stdlib got rid of the T/P type prefixes. Instead most
+  types now simply start with an uppercased letter. The
+  so called "partial case sensitivity" rule is now active allowing for code
+  like ``var foo: Foo`` in more contexts.
+- String case (or any non-ordinal case) statements
+  without 'else' are deprecated.
+- Recursive tuple types are not allowed anymore. Use ``object`` instead.
+- The PEGS module returns ``nil`` instead of ``""`` when an optional capture
+  fails to match.
+- The re module returns ``nil`` instead of ``""`` when an optional capture
+  fails to match.
+- The "symmetric set difference" operator (``-+-``) never worked and has been
+  removed.
+- ``defer`` is a keyword now.
+- ``func`` is a keyword now.
+- The ``using`` language feature now needs to be activated via the new
+  ``{.experimental.}`` pragma that enables experimental language features.
+- Destructors are now officially *experimental*.
+- Standalone ``except`` and ``finally`` statements are deprecated now.
+  The standalone ``finally`` can be replaced with ``defer``,
+  standalone ``except`` requires an explicit ``try``.
+- Operators ending in ``>`` are considered as "arrow like" and have their
+  own priority level and are right associative. This means that
+  the ``=>`` and ``->`` operators from the `future <future.html>`_ module
+  work better.
+- Field names in tuples are now ignored for type comparisons. This allows
+  for greater interoperability between different modules.
+- Statement lists are not converted to an implicit ``do`` block anymore. This
+  means the confusing ``nnkDo`` nodes when working with macros are gone for
+  good.
+
+
+Language Additions
+------------------
+
+- The new concurrency model has been implemented including ``locks`` sections,
+  lock levels and object field ``guards``.
+- The ``parallel`` statement has been implemented.
+- ``deepCopy`` has been added to the language.
+- The builtin ``procCall`` can be used to get ``super``-like functionality
+  for multi methods.
+- There is a new pragma ``{.experimental.}`` that enables experimental
+  language features per module, or you can enable these features on a global
+  level with the ``--experimental`` command line option.
 
-  Library Additions
-  -----------------
 
-  - Added module ``fenv`` to control the handling of floating-point rounding and
-    exceptions (overflow, division by zero, etc.).
-  - ``system.setupForeignThreadGc`` can be used for better interaction with
-    foreign libraries that create threads and run a Nim callback from these
-    foreign threads.
+Compiler Additions
+------------------
+
+- The compiler now supports *mixed* Objective C / C++ / C code generation:
+  The modules that use ``importCpp`` or ``importObjc`` are compiled to C++
+  or Objective C code, any other module is compiled to C code. This
+  improves interoperability.
+- There is a new ``parallel`` statement for safe fork&join parallel computing.
+- ``guard`` and ``lock`` pragmas have been implemented to support safer
+  concurrent programming.
+- The following procs are now available at compile-time::
+
+    math.sqrt, math.ln, math.log10, math.log2, math.exp, math.round,
+    math.arccos, math.arcsin, math.arctan, math.arctan2, math.cos,
+    math.cosh, math.hypot, math.sinh, math.sin, math.tan, math.tanh,
+    math.pow, math.trunc, math.floor, math.ceil, math.fmod,
+    os.getEnv, os.existsEnv, os.dirExists, os.fileExists,
+    system.writeFile
+
+- Two backticks now produce a single backtick within an ``emit`` or ``asm``
+  statement.
+- There is a new tool, `nimfix <nimfix.html>`_ to help you in updating your
+  code from Nimrod to Nim.
+- The compiler's output has been prettified.
+
+Library Additions
+-----------------
+
+- Added module ``fenv`` to control the handling of floating-point rounding and
+  exceptions (overflow, division by zero, etc.).
+- ``system.setupForeignThreadGc`` can be used for better interaction with
+  foreign libraries that create threads and run a Nim callback from these
+  foreign threads.
+- List comprehensions have been implemented as a macro in the ``future``
+  module.
+- The new Async module (``asyncnet``) now supports SSL.
+- The ``smtp`` module now has an async implementation.
+- Added module ``asyncfile`` which implements asynchronous file reading
+  and writing.
+- ``osproc.kill`` has been added.
+- ``asyncnet`` and ``asynchttpserver`` now support ``SO_REUSEADDR``.
+
+Bugfixes
+--------
 
+- ``nil`` and ``NULL`` are now preserved between Nim and databases in the
+  ``db_*`` modules.
+- Fixed issue with OS module in non-unicode mode on Windows.
+- Fixed issue with ``x.low``
+  (`#1366 <https://github.com/Araq/Nim/issues/1366>`_).
+- Fixed tuple unpacking issue inside closure iterators
+  (`#1067 <https://github.com/Araq/Nim/issues/1067>`_).
+- Fixed ENDB compilation issues.
+- Many ``asynchttpserver`` fixes.
+- Macros can now keep global state across macro calls
+  (`#903 <https://github.com/Araq/Nim/issues/903>`_).
+- ``osproc`` fixes on Windows.
+- ``osproc.terminate`` fixed.
+- Improvements to exception handling in async procedures.
+  (`#1487 <https://github.com/Araq/Nim/issues/1487>`_).
+- ``try`` now works at compile-time.
+- Fixes ``T = ref T`` to be an illegal recursive type.
+- Self imports are now disallowed.
+- Improved effect inference.
+- Fixes for the ``math`` module on Windows.
+- User defined pragmas will now work for generics that have
+  been instantiated in different modules.
+- Fixed queue exhaustion bug.
+- Many, many more.
 
 2014-12-09 New website design!
 ==============================
diff --git a/web/babelpkglist.nim b/web/nimblepkglist.nim
index aeea57a0d..7070f281b 100644
--- a/web/babelpkglist.nim
+++ b/web/nimblepkglist.nim
@@ -41,6 +41,7 @@ proc processContent(content: string) =
       dot = if desc.high > 0 and desc[desc.high] in endings: "" else: "."
       listItem = li(a(href=pkgWeb, pkg["name"].str), " ", desc & dot)
     if pkg["url"].str.startsWith("git://github.com/nimrod-code") or
+       pkg["url"].str.startsWith("git://github.com/nim-lang") or
        "official" in pkg["tags"].elems:
       officialCount.inc
       officialList.add listItem & "\n"
@@ -52,14 +53,14 @@ proc processContent(content: string) =
 
   officialPkgListDiv.innerHTML =
     p("There are currently " & $officialCount &
-      " official packages in the Babel package repository.") &
+      " official packages in the Nimble package repository.") &
     ul(officialList)
 
   var unofficialPkgListDiv = document.getElementById("unofficialPkgList")
 
   unofficialPkgListDiv.innerHTML =
     p("There are currently " & $unofficialCount &
-      " unofficial packages in the Babel package repository.") &
+      " unofficial packages in the Nimble package repository.") &
     ul(unofficialList)
 
 proc gotPackageList(apiReply: TData) {.exportc.} =
diff --git a/web/question.txt b/web/question.txt
index d3a2dd5c0..c27155858 100644
--- a/web/question.txt
+++ b/web/question.txt
@@ -110,6 +110,7 @@ General
   - Scite: Included
   - Gedit: The `Aporia .lang file <https://github.com/nimrod-code/Aporia/blob/master/share/gtksourceview-2.0/language-specs/nimrod.lang>`_
   - jEdit: https://github.com/exhu/nimrod-misc/tree/master/jedit
+  - TextMate: Available in bundle installer (`Repository <https://github.com/textmate/nim.tmbundle>`_)
 
 
 .. container:: standout
diff --git a/web/ticker.txt b/web/ticker.txt
index a0d2f0a78..64218084e 100644
--- a/web/ticker.txt
+++ b/web/ticker.txt
@@ -1,13 +1,13 @@
+<a class="news" href="news.html#Z2014-12-29-version-0-10-2-released">
+  <h4>Dec 29, 2014</h4>
+  <p>Nim version 0.10.2 has been released!</p>
+</a>
+
 <a class="news" href="news.html#Z2014-12-09-new-website-design">
   <h4>Dec 9, 2014</h4>
   <p>The new website design and forum are now online!</p>
 </a>
 
-<a class="news" href="news.html#Z2014-10-19-version-0-9-6-released">
-  <h4>Oct 19, 2014</h4>
-  <p>Nimrod version 0.9.6 has been released!</p>
-</a>
-
 <a class="news" href="news.html#Z2014-02-11-nimrod-featured-in-dr-dobb-s-journal">
   <h4>Feb 11, 2014</h4>
   <p>Nimrod featured in Dr. Dobb's Journal</p>