summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml29
-rwxr-xr-xbootstrap.sh7
-rw-r--r--compiler/aliases.nim2
-rw-r--r--compiler/ast.nim28
-rw-r--r--compiler/ccgexprs.nim177
-rw-r--r--compiler/ccgtypes.nim2
-rw-r--r--compiler/ccgutils.nim5
-rw-r--r--compiler/cgen.nim4
-rw-r--r--compiler/condsyms.nim2
-rw-r--r--compiler/evaltempl.nim5
-rw-r--r--compiler/extccomp.nim29
-rw-r--r--compiler/filter_tmpl.nim4
-rw-r--r--compiler/guards.nim136
-rw-r--r--compiler/installer.ini3
-rw-r--r--compiler/jstypes.nim5
-rw-r--r--compiler/lambdalifting.nim10
-rw-r--r--compiler/lookups.nim2
-rw-r--r--compiler/magicsys.nim38
-rw-r--r--compiler/modules.nim7
-rw-r--r--compiler/msgs.nim31
-rw-r--r--compiler/nim.nim5
-rw-r--r--compiler/options.nim4
-rw-r--r--compiler/parampatterns.nim5
-rw-r--r--compiler/pragmas.nim25
-rw-r--r--compiler/scriptconfig.nim12
-rw-r--r--compiler/semcall.nim9
-rw-r--r--compiler/semdata.nim6
-rw-r--r--compiler/semexprs.nim70
-rw-r--r--compiler/semfold.nim9
-rw-r--r--compiler/semgnrc.nim41
-rw-r--r--compiler/seminst.nim18
-rw-r--r--compiler/semmagic.nim57
-rw-r--r--compiler/semparallel.nim33
-rw-r--r--compiler/sempass2.nim2
-rw-r--r--compiler/semstmts.nim30
-rw-r--r--compiler/semtempl.nim156
-rw-r--r--compiler/semtypes.nim43
-rw-r--r--compiler/semtypinst.nim23
-rw-r--r--compiler/sigmatch.nim9
-rw-r--r--compiler/suggest.nim12
-rw-r--r--compiler/syntaxes.nim7
-rw-r--r--compiler/transf.nim37
-rw-r--r--compiler/types.nim17
-rw-r--r--compiler/vm.nim42
-rw-r--r--compiler/vmgen.nim21
-rw-r--r--compiler/vmhooks.nim8
-rw-r--r--compiler/wordrecg.nim7
-rw-r--r--compiler/writetracking.nim2
-rw-r--r--config/nim.cfg16
-rw-r--r--config/nimdoc.cfg2
-rw-r--r--doc/filelist.txt4
-rw-r--r--doc/filters.txt13
-rw-r--r--doc/lib.txt40
-rw-r--r--doc/manual/generics.txt11
-rw-r--r--doc/manual/pragmas.txt33
-rw-r--r--doc/manual/procs.txt8
-rw-r--r--doc/manual/stmts.txt18
-rw-r--r--doc/manual/syntax.txt8
-rw-r--r--doc/manual/types.txt29
-rw-r--r--doc/nims.txt3
-rw-r--r--doc/subexes.txt2
-rw-r--r--examples/curlex.nim10
-rw-r--r--examples/filterex.nim2
-rw-r--r--examples/iupex1.nim37
-rw-r--r--install.sh.template9
-rw-r--r--install.txt2
-rw-r--r--koch.nim9
-rw-r--r--lib/deprecated/core/unsigned.nim (renamed from lib/core/unsigned.nim)0
-rw-r--r--lib/deprecated/pure/actors.nim (renamed from lib/pure/actors.nim)0
-rw-r--r--lib/deprecated/pure/actors.nim.cfg (renamed from lib/pure/actors.nim.cfg)0
-rw-r--r--lib/deprecated/pure/asyncio.nim (renamed from lib/pure/asyncio.nim)0
-rw-r--r--lib/deprecated/pure/ftpclient.nim (renamed from lib/pure/ftpclient.nim)13
-rw-r--r--lib/deprecated/pure/parseopt.nim (renamed from lib/pure/parseopt.nim)0
-rw-r--r--lib/deprecated/pure/parseurl.nim (renamed from lib/pure/parseurl.nim)0
-rw-r--r--lib/deprecated/pure/rawsockets.nim14
-rw-r--r--lib/deprecated/pure/sockets.nim (renamed from lib/pure/sockets.nim)7
-rw-r--r--lib/impure/graphics.nim577
-rw-r--r--lib/posix/kqueue.nim71
-rw-r--r--lib/posix/posix.nim8
-rw-r--r--lib/pure/asyncdispatch.nim152
-rw-r--r--lib/pure/asyncftpclient.nim75
-rw-r--r--lib/pure/asynchttpserver.nim31
-rw-r--r--lib/pure/asyncnet.nim46
-rw-r--r--lib/pure/base64.nim37
-rw-r--r--lib/pure/basic2d.nim8
-rw-r--r--lib/pure/basic3d.nim2
-rw-r--r--lib/pure/collections/critbits.nim8
-rw-r--r--lib/pure/coro.nim2
-rw-r--r--lib/pure/coro.nimcfg1
-rw-r--r--lib/pure/future.nim4
-rw-r--r--lib/pure/hashes.nim74
-rw-r--r--lib/pure/httpclient.nim8
-rw-r--r--lib/pure/json.nim22
-rw-r--r--lib/pure/math.nim31
-rw-r--r--lib/pure/memfiles.nim13
-rw-r--r--lib/pure/nativesockets.nim (renamed from lib/pure/rawsockets.nim)113
-rw-r--r--lib/pure/net.nim25
-rw-r--r--lib/pure/options.nim64
-rw-r--r--lib/pure/os.nim12
-rw-r--r--lib/pure/ospaths.nim50
-rw-r--r--lib/pure/osproc.nim140
-rw-r--r--lib/pure/rationals.nim69
-rw-r--r--lib/pure/selectors.nim94
-rw-r--r--lib/pure/streams.nim35
-rw-r--r--lib/pure/strtabs.nim6
-rw-r--r--lib/pure/strutils.nim218
-rw-r--r--lib/pure/subexes.nim19
-rw-r--r--lib/pure/times.nim61
-rw-r--r--lib/pure/unicode.nim40
-rw-r--r--lib/pure/uri.nim10
-rw-r--r--lib/pure/xmltree.nim13
-rw-r--r--lib/system.nim148
-rw-r--r--lib/system/alloc.nim60
-rw-r--r--lib/system/gc_common.nim18
-rw-r--r--lib/system/nimscript.nim5
-rw-r--r--lib/system/repr.nim20
-rw-r--r--lib/windows/winlean.nim42
-rw-r--r--readme.md15
-rw-r--r--tests/alias/talias.nim5
-rw-r--r--tests/async/tasyncawait.nim6
-rw-r--r--tests/async/tasyncconnect.nim7
-rw-r--r--tests/async/tasynceverror.nim9
-rw-r--r--tests/async/tasyncexceptions.nim2
-rw-r--r--tests/bind/tbind2.nim2
-rw-r--r--tests/ccgbugs/tnocodegen_for_compiletime.nim9
-rw-r--r--tests/ccgbugs/twrong_discriminant_check.nim30
-rw-r--r--tests/ccgbugs/twrong_string_asgn.nim19
-rw-r--r--tests/compiles/trecursive_generic_in_compiles.nim98
-rw-r--r--tests/cpp/tnativesockets.nim (renamed from tests/cpp/trawsockets.nim)2
-rw-r--r--tests/discard/tvoidcontext.nim12
-rw-r--r--tests/enum/tenummix.nim4
-rw-r--r--tests/gc/gcemscripten.nim59
-rw-r--r--tests/generics/mbind_bracket.nim17
-rw-r--r--tests/generics/tbind_bracket.nim20
-rw-r--r--tests/generics/tmap_auto.nim13
-rw-r--r--tests/generics/tthread_generic.nim2
-rw-r--r--tests/macros/tgensym.nim4
-rw-r--r--tests/manyloc/keineschweine/lib/zlib_helpers.nim2
-rw-r--r--tests/manyloc/nake/nakefile.nim2
-rw-r--r--tests/metatype/tprocbothmeta.nim2
-rw-r--r--tests/metatype/ttypedesc1.nim2
-rw-r--r--tests/metatype/tunresolved_return_type.nim20
-rw-r--r--tests/method/tmapper.nim2
-rw-r--r--tests/misc/tnot.nim7
-rw-r--r--tests/misc/tvarious1.nim2
-rw-r--r--tests/modules/texport.nim2
-rw-r--r--tests/newconfig/tfoo.nim3
-rw-r--r--tests/newconfig/tfoo.nims4
-rw-r--r--tests/objects/tillegal_recursion.nim2
-rw-r--r--tests/parallel/tparfind.nim28
-rw-r--r--tests/parser/tstrongspaces.nim2
-rw-r--r--tests/pragmas/tbitsize.nim22
-rw-r--r--tests/rational/trat_float.nim9
-rw-r--r--tests/rational/trat_init.nim10
-rw-r--r--tests/stdlib/tmemfiles1.nim12
-rw-r--r--tests/stdlib/tmemfiles2.nim39
-rw-r--r--tests/stdlib/tstreams2.nim13
-rw-r--r--tests/system/tfloatToString.nim22
-rw-r--r--tests/system/toString.nim35
-rw-r--r--tests/system/tsettostring.nim8
-rw-r--r--tests/template/sunset.tmpl2
-rw-r--r--tests/template/twrongmapit.nim8
-rw-r--r--tests/testament/categories.nim8
-rw-r--r--tests/testament/specs.nim8
-rw-r--r--tests/testament/tester.nim33
-rw-r--r--tests/typerel/t2plus.nim22
-rw-r--r--tests/typerel/typeof_in_template.nim16
-rw-r--r--tests/types/tauto_excessive.nim20
-rw-r--r--tests/vm/tconstobj.nim26
-rw-r--r--tests/vm/tsimpleglobals.nim16
-rw-r--r--tests/vm/twrongconst.nim2
-rw-r--r--tests/vm/tyaytypedesc.nim21
-rw-r--r--todo.txt2
-rw-r--r--tools/niminst/buildbat.tmpl2
-rw-r--r--tools/niminst/buildsh.tmpl2
-rw-r--r--tools/niminst/deinstall.tmpl2
-rw-r--r--tools/niminst/inno.tmpl2
-rw-r--r--tools/niminst/install.tmpl2
-rw-r--r--tools/niminst/makefile.tmpl2
-rw-r--r--tools/niminst/nsis.tmpl2
-rw-r--r--tools/website.tmpl10
-rw-r--r--web/community.txt6
-rw-r--r--web/news.txt231
-rw-r--r--web/question.txt6
-rw-r--r--web/website.ini2
185 files changed, 3559 insertions, 1437 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..c027386f5
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,29 @@
+sudo: false
+language: c
+os:
+  - linux
+addons:
+  apt:
+    packages:
+    - libcurl4-openssl-dev
+    - libsdl1.2-dev
+before_script:
+  - set -e
+  - wget http://flatassembler.net/fasm-1.71.39.tgz
+  - tar xvf fasm-1.71.39.tgz
+  - git clone --depth 1 https://github.com/nim-lang/csources.git
+  - cd csources
+  - sh build.sh
+  - cd ..
+  - sed -i -e 's,cc = gcc,cc = clang,' config/nim.cfg
+  - export PATH=$(pwd)/bin:$(pwd)/fasm:$PATH
+script:
+  - nim c koch
+  - ./koch boot
+  - ./koch boot -d:release
+  - nim e install_nimble.nims
+  - nimble update
+  - nimble install zip
+  - nimble install opengl
+  - nimble install sdl1
+  - ./koch test all --pedantic
diff --git a/bootstrap.sh b/bootstrap.sh
index ade74a9aa..7f19c2440 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -12,8 +12,11 @@ cd ".."
 
 ./bin/nim c koch
 ./koch boot -d:release
+./koch geninstall
 
-cp -f install.sh.template install.sh
-chmod +x install.sh
+set +x
+
+echo
+echo 'Install Nim using "./install.sh <dir>" or "sudo ./install.sh <dir>".'
 
 exit 0
diff --git a/compiler/aliases.nim b/compiler/aliases.nim
index 3d3fc9a79..4b592ee60 100644
--- a/compiler/aliases.nim
+++ b/compiler/aliases.nim
@@ -146,7 +146,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
     # go down recursively; this is quite demanding:
     const
       Ix0Kinds = {nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
-                  nkCheckedFieldExpr}
+                  nkCheckedFieldExpr, nkHiddenAddr}
       Ix1Kinds = {nkHiddenStdConv, nkHiddenSubConv, nkConv}
       DerefKinds = {nkHiddenDeref, nkDerefExpr}
     case b.kind
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 177b5c5c7..25958f580 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -477,6 +477,8 @@ type
                       # wildcard type.
     tfHasAsgn         # type has overloaded assignment operator
     tfBorrowDot       # distinct type borrows '.'
+    tfTriggersCompileTime # uses the NimNode type which make the proc
+                          # implicitly '.compiletime'
 
   TTypeFlags* = set[TTypeFlag]
 
@@ -537,7 +539,7 @@ const
 type
   TMagic* = enum # symbols that require compiler magic:
     mNone,
-    mDefined, mDefinedInScope, mCompiles,
+    mDefined, mDefinedInScope, mCompiles, mArrGet, mArrPut, mAsgn,
     mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mAddr, mTypeOf, mRoof, mPlugin,
     mEcho, mShallowCopy, mSlurp, mStaticExec,
     mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
@@ -614,6 +616,7 @@ const
   ctfeWhitelist* = {mNone, mUnaryLt, mSucc,
     mPred, mInc, mDec, mOrd, mLengthOpenArray,
     mLengthStr, mLengthArray, mLengthSeq, mXLenStr, mXLenSeq,
+    mArrGet, mArrPut, mAsgn,
     mIncl, mExcl, mCard, mChr,
     mAddI, mSubI, mMulI, mDivI, mModI,
     mAddF64, mSubF64, mMulF64, mDivF64,
@@ -709,6 +712,7 @@ type
     lfSingleUse               # no location yet and will only be used once
   TStorageLoc* = enum
     OnUnknown,                # location is unknown (stack, heap or static)
+    OnStatic,                 # in a static section
     OnStack,                  # location is on hardware stack
     OnHeap                    # location is on heap or global
                               # (reference counting needed)
@@ -734,6 +738,8 @@ type
     name*: Rope
     path*: PNode              # can be a string literal!
 
+  CompilesId* = int ## id that is used for the caching logic within
+                    ## ``system.compiles``. See the seminst module.
   TInstantiation* = object
     sym*: PSym
     concreteTypes*: seq[PType]
@@ -741,6 +747,7 @@ type
                               # needed in caas mode for purging the cache
                               # XXX: it's possible to switch to a
                               # simple ref count here
+    compilesId*: CompilesId
 
   PInstantiation* = ref TInstantiation
 
@@ -777,6 +784,7 @@ type
       tab*: TStrTable         # interface table for modules
     of skLet, skVar, skField, skForVar:
       guard*: PSym
+      bitsize*: int
     else: nil
     magic*: TMagic
     typ*: PType
@@ -1378,6 +1386,9 @@ proc propagateToOwner*(owner, elem: PType) =
       o2.flags.incl tfHasAsgn
       owner.flags.incl tfHasAsgn
 
+  if tfTriggersCompileTime in elem.flags:
+    owner.flags.incl tfTriggersCompileTime
+
   if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
                        tyGenericInvocation, tyPtr}:
     let elemB = elem.skipTypes({tyGenericInst})
@@ -1578,6 +1589,14 @@ proc makeStmtList*(n: PNode): PNode =
     result = newNodeI(nkStmtList, n.info)
     result.add n
 
+proc skipStmtList*(n: PNode): PNode =
+  if n.kind in {nkStmtList, nkStmtListExpr}:
+    for i in 0 .. n.len-2:
+      if n[i].kind notin {nkEmpty, nkCommentStmt}: return n
+    result = n.lastSon
+  else:
+    result = n
+
 proc createMagic*(name: string, m: TMagic): PSym =
   result = newSym(skProc, getIdent(name), nil, unknownLineInfo())
   result.magic = m
@@ -1585,3 +1604,10 @@ proc createMagic*(name: string, m: TMagic): PSym =
 let
   opNot* = createMagic("not", mNot)
   opContains* = createMagic("contains", mInSet)
+
+when false:
+  proc containsNil*(n: PNode): bool =
+    # only for debugging
+    if n.isNil: return true
+    for i in 0 ..< n.safeLen:
+      if n[i].containsNil: return true
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index ba8ced52a..6d69dafa5 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -221,7 +221,7 @@ proc optAsgnLoc(a: TLoc, t: PType, field: Rope): TLoc =
 
 proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   let newflags =
-    if src.k == locData:
+    if src.s == OnStatic:
       flags + {needToCopy}
     elif tfShallow in dest.t.flags:
       flags - {needToCopy}
@@ -238,7 +238,7 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
                       t: PNode) =
   if t == nil: return
   let newflags =
-    if src.k == locData:
+    if src.s == OnStatic:
       flags + {needToCopy}
     elif tfShallow in dest.t.flags:
       flags - {needToCopy}
@@ -287,13 +287,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   of tyRef:
     genRefAssign(p, dest, src, flags)
   of tySequence:
-    if needToCopy notin flags and src.k != locData:
+    if needToCopy notin flags and src.s != OnStatic:
       genRefAssign(p, dest, src, flags)
     else:
       linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
               addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
   of tyString:
-    if needToCopy notin flags and src.k != locData:
+    if needToCopy notin flags and src.s != OnStatic:
       genRefAssign(p, dest, src, flags)
     else:
       if dest.s == OnStack or not usesNativeGC():
@@ -413,7 +413,7 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
   var a: TLoc
   if d.k != locNone:
     # need to generate an assignment here
-    initLoc(a, locData, t, OnUnknown)
+    initLoc(a, locData, t, OnStatic)
     a.r = r
     if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
     else: genAssignment(p, d, a, {needToCopy})
@@ -424,11 +424,11 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
     d.t = t
     d.r = r
 
-proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
+proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope; s=OnUnknown) =
   var a: TLoc
   if d.k != locNone:
     # need to generate an assignment here
-    initLoc(a, locExpr, t, OnUnknown)
+    initLoc(a, locExpr, t, s)
     a.r = r
     if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
     else: genAssignment(p, d, a, {needToCopy})
@@ -685,7 +685,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
         d.s = OnUnknown
         if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
             e.kind == nkHiddenDeref:
-          putIntoDest(p, d, e.typ, rdLoc(a))
+          putIntoDest(p, d, e.typ, rdLoc(a), a.s)
           return
       of tyPtr:
         d.s = OnUnknown         # BUGFIX!
@@ -694,7 +694,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
       let typ = skipTypes(a.t, abstractInst)
       if typ.kind == tyVar and tfVarIsPtr notin typ.flags and
            e.kind == nkHiddenDeref:
-        putIntoDest(p, d, e.typ, rdLoc(a))
+        putIntoDest(p, d, e.typ, rdLoc(a), a.s)
         return
     if enforceDeref and mt == ctPtrToArray:
       # we lie about the type for better C interop: 'ptr array[3,T]' is
@@ -702,23 +702,23 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
       # See tmissingderef. So we get rid of the deref instead. The codegen
       # ends up using 'memcpy' for the array assignment,
       # so the '&' and '*' cancel out:
-      putIntoDest(p, d, a.t.sons[0], rdLoc(a))
+      putIntoDest(p, d, a.t.sons[0], rdLoc(a), a.s)
     else:
-      putIntoDest(p, d, e.typ, "(*$1)" % [rdLoc(a)])
+      putIntoDest(p, d, e.typ, "(*$1)" % [rdLoc(a)], a.s)
 
 proc genAddr(p: BProc, e: PNode, d: var TLoc) =
   # careful  'addr(myptrToArray)' needs to get the ampersand:
   if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
     var a: TLoc
     initLocExpr(p, e.sons[0], a)
-    putIntoDest(p, d, e.typ, "&" & a.r)
+    putIntoDest(p, d, e.typ, "&" & a.r, a.s)
     #Message(e.info, warnUser, "HERE NEW &")
   elif mapType(e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ):
     expr(p, e.sons[0], d)
   else:
     var a: TLoc
     initLocExpr(p, e.sons[0], a)
-    putIntoDest(p, d, e.typ, addrLoc(a))
+    putIntoDest(p, d, e.typ, addrLoc(a), a.s)
 
 template inheritLocation(d: var TLoc, a: TLoc) =
   if d.k == locNone: d.s = a.s
@@ -745,7 +745,18 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
   of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
   else: internalError(e.info, "genTupleElem")
   addf(r, ".Field$1", [rope(i)])
-  putIntoDest(p, d, ty.sons[i], r)
+  putIntoDest(p, d, ty.sons[i], r, a.s)
+
+proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
+  var ty = ty
+  assert r != nil
+  while ty != nil:
+    assert(ty.kind in {tyTuple, tyObject})
+    result = lookupInRecord(ty.n, field.name)
+    if result != nil: break
+    if not p.module.compileToCpp: add(r, ".Sup")
+    ty = getUniqueType(ty.sons[0])
+  if result == nil: internalError(field.info, "genCheckedRecordField")
 
 proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
   var a: TLoc
@@ -756,25 +767,18 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
     # we found a unique tuple type which lacks field information
     # so we use Field$i
     addf(r, ".Field$1", [rope(f.position)])
-    putIntoDest(p, d, f.typ, r)
+    putIntoDest(p, d, f.typ, r, a.s)
   else:
-    var field: PSym = nil
-    while ty != nil:
-      if ty.kind notin {tyTuple, tyObject}:
-        internalError(e.info, "genRecordField")
-      field = lookupInRecord(ty.n, f.name)
-      if field != nil: break
-      if not p.module.compileToCpp: add(r, ".Sup")
-      ty = getUniqueType(ty.sons[0])
-    if field == nil: internalError(e.info, "genRecordField 2 ")
+    let field = lookupFieldAgain(p, ty, f, r)
     if field.loc.r == nil: internalError(e.info, "genRecordField 3")
     addf(r, ".$1", [field.loc.r])
-    putIntoDest(p, d, field.typ, r)
+    putIntoDest(p, d, field.typ, r, a.s)
   #d.s = a.s
 
 proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
 
-proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
+proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym;
+                   origTy: PType) =
   var test, u, v: TLoc
   for i in countup(1, sonsLen(e) - 1):
     var it = e.sons[i]
@@ -786,8 +790,12 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
     assert(disc.kind == nkSym)
     initLoc(test, locNone, it.typ, OnStack)
     initLocExpr(p, it.sons[1], u)
-    initLoc(v, locExpr, disc.typ, OnUnknown)
-    v.r = "$1.$2" % [obj, disc.sym.loc.r]
+    var o = obj
+    let d = lookupFieldAgain(p, origTy, disc.sym, o)
+    initLoc(v, locExpr, d.typ, OnUnknown)
+    v.r = o
+    v.r.add(".")
+    v.r.add(d.loc.r)
     genInExprAux(p, it, u, v, test)
     let id = nodeTableTestOrSet(p.module.dataCache,
                                newStrNode(nkStrLit, field.name.s), gBackendId)
@@ -804,27 +812,16 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
 
 proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
   if optFieldCheck in p.options:
-    var
-      a: TLoc
-      f, field: PSym
-      ty: PType
-      r: Rope
-    ty = genRecordFieldAux(p, e.sons[0], d, a)
-    r = rdLoc(a)
-    f = e.sons[0].sons[1].sym
-    field = nil
-    while ty != nil:
-      assert(ty.kind in {tyTuple, tyObject})
-      field = lookupInRecord(ty.n, f.name)
-      if field != nil: break
-      if not p.module.compileToCpp: add(r, ".Sup")
-      ty = getUniqueType(ty.sons[0])
-    if field == nil: internalError(e.info, "genCheckedRecordField")
+    var a: TLoc
+    let ty = genRecordFieldAux(p, e.sons[0], d, a)
+    var r = rdLoc(a)
+    let f = e.sons[0].sons[1].sym
+    let field = lookupFieldAgain(p, ty, f, r)
     if field.loc.r == nil:
       internalError(e.info, "genCheckedRecordField") # generate the checks:
-    genFieldCheck(p, e, r, field)
+    genFieldCheck(p, e, r, field, ty)
     add(r, rfmt(nil, ".$1", field.loc.r))
-    putIntoDest(p, d, field.typ, r)
+    putIntoDest(p, d, field.typ, r, a.s)
   else:
     genRecordField(p, e.sons[0], d)
 
@@ -851,7 +848,7 @@ proc genArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
         localError(x.info, errIndexOutOfBounds)
   d.inheritLocation(a)
   putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
-              rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first))
+              rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.s)
 
 proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -860,7 +857,7 @@ proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) =
   var ty = skipTypes(a.t, abstractVarRange)
   if d.k == locNone: d.s = a.s
   putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
-              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)))
+              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.s)
 
 proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -871,7 +868,7 @@ proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
             rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
   if d.k == locNone: d.s = a.s
   putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
-              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)))
+              rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.s)
 
 proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -894,7 +891,7 @@ proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
   if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
     a.r = rfmt(nil, "(*$1)", a.r)
   putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
-              rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)))
+              rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.s)
 
 proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
   var ty = skipTypes(n.sons[0].typ, abstractVarRange)
@@ -1150,20 +1147,15 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
   else:
     constructLoc(p, tmp)
   discard getTypeDesc(p.module, t)
+  let ty = getUniqueType(t)
   for i in 1 .. <e.len:
     let it = e.sons[i]
     var tmp2: TLoc
     tmp2.r = r
-    var field: PSym = nil
-    var ty = getUniqueType(t)
-    while ty != nil:
-      field = lookupInRecord(ty.n, it.sons[0].sym.name)
-      if field != nil: break
-      if not p.module.compileToCpp: add(tmp2.r, ".Sup")
-      ty = getUniqueType(ty.sons[0])
-    if field == nil or field.loc.r == nil: internalError(e.info, "genObjConstr")
+    let field = lookupFieldAgain(p, ty, it.sons[0].sym, tmp2.r)
+    if field.loc.r == nil: internalError(e.info, "genObjConstr")
     if it.len == 3 and optFieldCheck in p.options:
-      genFieldCheck(p, it.sons[2], tmp2.r, field)
+      genFieldCheck(p, it.sons[2], tmp2.r, field, ty)
     add(tmp2.r, ".")
     add(tmp2.r, field.loc.r)
     tmp2.k = locTemp
@@ -1272,7 +1264,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
   else:
     r = rfmt(p.module, "($1)", genOfHelper(p, dest, r))
-  putIntoDest(p, d, getSysType(tyBool), r)
+  putIntoDest(p, d, getSysType(tyBool), r, a.s)
 
 proc genOf(p: BProc, n: PNode, d: var TLoc) =
   genOf(p, n.sons[1], n.sons[2].typ, d)
@@ -1284,47 +1276,47 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   case t.kind
   of tyInt..tyInt64, tyUInt..tyUInt64:
     putIntoDest(p, d, e.typ,
-                ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]))
+                ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]), a.s)
   of tyFloat..tyFloat128:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]), a.s)
   of tyBool:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]), a.s)
   of tyChar:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]), a.s)
   of tyEnum, tyOrdinal:
     putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprEnum($1, $2)", [
-                rdLoc(a), genTypeInfo(p.module, t)]))
+                rdLoc(a), genTypeInfo(p.module, t)]), a.s)
   of tyString:
-    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]))
+    putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]), a.s)
   of tySet:
     putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
-                addrLoc(a), genTypeInfo(p.module, t)]))
+                addrLoc(a), genTypeInfo(p.module, t)]), a.s)
   of tyOpenArray, tyVarargs:
     var b: TLoc
     case a.t.kind
     of tyOpenArray, tyVarargs:
-      putIntoDest(p, b, e.typ, "$1, $1Len0" % [rdLoc(a)])
+      putIntoDest(p, b, e.typ, "$1, $1Len0" % [rdLoc(a)], a.s)
     of tyString, tySequence:
       putIntoDest(p, b, e.typ,
-                  "$1->data, $1->$2" % [rdLoc(a), lenField(p)])
+                  "$1->data, $1->$2" % [rdLoc(a), lenField(p)], a.s)
     of tyArray, tyArrayConstr:
       putIntoDest(p, b, e.typ,
-                  "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))])
+                  "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))], a.s)
     else: internalError(e.sons[0].info, "genRepr()")
     putIntoDest(p, d, e.typ,
         ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
-        genTypeInfo(p.module, elemType(t))]))
+        genTypeInfo(p.module, elemType(t))]), a.s)
   of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
      tySequence:
     putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprAny($1, $2)", [
-                rdLoc(a), genTypeInfo(p.module, t)]))
+                rdLoc(a), genTypeInfo(p.module, t)]), a.s)
   of tyEmpty:
     localError(e.info, "'repr' doesn't support 'void' type")
   else:
     putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
-                                   [addrLoc(a), genTypeInfo(p.module, t)]))
+                                   [addrLoc(a), genTypeInfo(p.module, t)]), a.s)
   gcUsage(e)
 
 proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
@@ -1549,13 +1541,13 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
   let etyp = skipTypes(e.typ, abstractRange)
   if etyp.kind in ValueTypes and lfIndirect notin a.flags:
     putIntoDest(p, d, e.typ, "(*($1*) ($2))" %
-        [getTypeDesc(p.module, e.typ), addrLoc(a)])
+        [getTypeDesc(p.module, e.typ), addrLoc(a)], a.s)
   elif etyp.kind == tyProc and etyp.callConv == ccClosure:
     putIntoDest(p, d, e.typ, "(($1) ($2))" %
-        [getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)])
+        [getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)], a.s)
   else:
     putIntoDest(p, d, e.typ, "(($1) ($2))" %
-        [getTypeDesc(p.module, e.typ), rdCharLoc(a)])
+        [getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.s)
 
 proc genCast(p: BProc, e: PNode, d: var TLoc) =
   const floatTypes = {tyFloat..tyFloat128}
@@ -1575,7 +1567,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
     tmp.s = OnStack
     tmp.flags = {}
     expr(p, e.sons[1], tmp)
-    putIntoDest(p, d, e.typ, "LOC$#.dest" % [lbl])
+    putIntoDest(p, d, e.typ, "LOC$#.dest" % [lbl], tmp.s)
   else:
     # I prefer the shorter cast version for pointer types -> generate less
     # C code; plus it's the right thing to do for closures:
@@ -1589,13 +1581,13 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
                                              {tyUInt..tyUInt64}:
     initLocExpr(p, n.sons[0], a)
     putIntoDest(p, d, n.typ, "(($1) ($2))" %
-        [getTypeDesc(p.module, dest), rdCharLoc(a)])
+        [getTypeDesc(p.module, dest), rdCharLoc(a)], a.s)
   else:
     initLocExpr(p, n.sons[0], a)
     putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
         getTypeDesc(p.module, dest), rdCharLoc(a),
         genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
-        rope(magic)]))
+        rope(magic)]), a.s)
 
 proc genConv(p: BProc, e: PNode, d: var TLoc) =
   let destType = e.typ.skipTypes({tyVar, tyGenericInst})
@@ -1607,13 +1599,13 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
 proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
   var a: TLoc
   initLocExpr(p, n.sons[0], a)
-  putIntoDest(p, d, skipTypes(n.typ, abstractVar), "$1->data" % [rdLoc(a)])
+  putIntoDest(p, d, skipTypes(n.typ, abstractVar), "$1->data" % [rdLoc(a)], a.s)
 
 proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
   var a: TLoc
   initLocExpr(p, n.sons[0], a)
   putIntoDest(p, d, skipTypes(n.typ, abstractVar),
-              ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]))
+              ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]), a.s)
   gcUsage(n)
 
 proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
@@ -1741,6 +1733,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mEcho: genEcho(p, e[1].skipConv)
   of mArrToSeq: genArrToSeq(p, e, d)
   of mNLen..mNError, mSlurp..mQuoteAst:
+    echo "from here ", p.prc.name.s, " ", p.prc.info
+    writestacktrace()
     localError(e.info, errXMustBeCompileTime, e.sons[0].sym.name.s)
   of mSpawn:
     let n = lowerings.wrapProcForSpawn(p.module.module, e, e.typ, nil, nil)
@@ -1763,7 +1757,7 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
     var t = getUniqueType(n.typ)
     discard getTypeDesc(p.module, t) # so that any fields are initialized
     var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
-    fillLoc(d, locData, t, "TMP" & rope(id), OnHeap)
+    fillLoc(d, locData, t, "TMP" & rope(id), OnStatic)
     if id == gBackendId:
       # expression not found in the cache:
       inc(gBackendId)
@@ -1849,7 +1843,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
     var tmp = "LOC" & rope(p.labels)
     addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
         [getTypeDesc(p.module, n.typ), tmp, genConstExpr(p, n)])
-    putIntoDest(p, d, n.typ, tmp)
+    putIntoDest(p, d, n.typ, tmp, OnStatic)
   else:
     var tmp, a, b: TLoc
     initLocExpr(p, n.sons[0], a)
@@ -1903,10 +1897,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
               r, genTypeInfo(p.module, dest))
   if n.sons[0].typ.kind != tyObject:
     putIntoDest(p, d, n.typ,
-                "(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)])
+                "(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.s)
   else:
     putIntoDest(p, d, n.typ, "(*($1*) ($2))" %
-                             [getTypeDesc(p.module, dest), addrLoc(a)])
+                             [getTypeDesc(p.module, dest), addrLoc(a)], a.s)
 
 proc downConv(p: BProc, n: PNode, d: var TLoc) =
   if p.module.compileToCpp:
@@ -1938,9 +1932,9 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
         linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r)
       else:
         r = "&" & r
-        putIntoDest(p, d, n.typ, r)
+        putIntoDest(p, d, n.typ, r, a.s)
     else:
-      putIntoDest(p, d, n.typ, r)
+      putIntoDest(p, d, n.typ, r, a.s)
 
 proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
   var t = getUniqueType(n.typ)
@@ -1955,7 +1949,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
          [getTypeDesc(p.module, t), tmp, genConstExpr(p, n)])
 
   if d.k == locNone:
-    fillLoc(d, locData, t, tmp, OnHeap)
+    fillLoc(d, locData, t, tmp, OnStatic)
   else:
     putDataIntoDest(p, d, t, tmp)
 
@@ -1973,6 +1967,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         genProc(p.module, sym)
       putLocIntoDest(p, d, sym.loc)
     of skProc, skConverter, skIterators:
+      if sfCompileTime in sym.flags:
+        localError(n.info, "request to generate code for .compileTime proc: " &
+           sym.name.s)
       genProc(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
         internalError(n.info, "expr: proc not init " & sym.name.s)
@@ -1982,7 +1979,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
         putLocIntoDest(p, d, sym.loc)
       elif isSimpleConst(sym.typ):
-        putIntoDest(p, d, n.typ, genLiteral(p, sym.ast, sym.typ))
+        putIntoDest(p, d, n.typ, genLiteral(p, sym.ast, sym.typ), OnStatic)
       else:
         genComplexConst(p, sym, d)
     of skEnumField:
@@ -2126,7 +2123,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
       # due to a bug/limitation in the lambda lifting, unused inner procs
       # are not transformed correctly. We work around this issue (#411) here
       # by ensuring it's no inner proc (owner is a module):
-      if prc.skipGenericOwner.kind == skModule:
+      if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags:
         if (optDeadCodeElim notin gGlobalOptions and
             sfDeadCodeElim notin getModule(prc).flags) or
             ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 84d02d1da..1ed9ce113 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -441,6 +441,8 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
       elif fieldType.kind == tySequence:
         # we need to use a weak dependency here for trecursive_table.
         addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname])
+      elif field.bitsize != 0:
+        addf(result, "$1 $2:$3;$n", [getTypeDescAux(m, field.loc.t, check), sname, rope($field.bitsize)])
       else:
         # don't use fieldType here because we need the
         # tyGenericInst for C++ template support
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 4ba6643ec..6dfd7b52c 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -99,7 +99,10 @@ proc getUniqueType*(key: PType): PType =
       gCanonicalTypes[k] = key
       result = key
   of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor:
-    internalError("getUniqueType")
+    if key.sym != nil:
+      internalError(key.sym.info, "metatype not eliminated")
+    else:
+      internalError("metatype not eliminated")
   of tyDistinct:
     if key.deepCopy != nil: result = key
     else: result = getUniqueType(lastSon(key))
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 13514818e..f63134b66 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -760,7 +760,7 @@ proc requestConstImpl(p: BProc, sym: PSym) =
   var m = p.module
   useHeader(m, sym)
   if sym.loc.k == locNone:
-    fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown)
+    fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnStatic)
   if lfNoDecl in sym.loc.flags: return
   # declare implementation:
   var q = findPendingModule(m, sym)
@@ -1110,7 +1110,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
 
 proc nullify[T](arr: var T) =
   for i in low(arr)..high(arr):
-    arr[i] = nil
+    arr[i] = Rope(nil)
 
 proc resetModule*(m: BModule) =
   # between two compilations in CAAS mode, we can throw
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 297b865b2..60e8f2826 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -91,3 +91,5 @@ proc initDefines*() =
   defineSymbol("nimnomagic64")
   defineSymbol("nimvarargstyped")
   defineSymbol("nimtypedescfixed")
+  defineSymbol("nimKnowsNimvm")
+  defineSymbol("nimArrIdx")
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 58594a8b7..c33e5be86 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -62,7 +62,7 @@ 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 totalParams = case n.kind
-    of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: <n.len
+    of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: n.len-1
     else: 0
 
   var
@@ -90,8 +90,7 @@ proc evalTemplateArgs(n: PNode, s: PSym): PNode =
   # not supplied by the user
   for i in givenRegularParams+1 .. expectedRegularParams:
     let default = s.typ.n.sons[i].sym.ast
-    internalAssert default != nil
-    if default.kind == nkEmpty:
+    if default.isNil or default.kind == nkEmpty:
       localError(n.info, errWrongNumberOfArguments)
       addSon(result, ast.emptyNode)
     else:
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 02198d06e..3882bdd03 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -14,7 +14,7 @@
 
 import
   lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs,
-  securehash
+  securehash, streams
 
 type
   TSystemCC* = enum
@@ -474,7 +474,7 @@ proc execWithEcho(cmd: string, msg = hintExecuting): int =
 
 proc execExternalProgram*(cmd: string, msg = hintExecuting) =
   if execWithEcho(cmd, msg) != 0:
-    rawMessage(errExecutionOfProgramFailed, "")
+    rawMessage(errExecutionOfProgramFailed, cmd)
 
 proc generateScript(projectFile: string, script: Rope) =
   let (dir, name, ext) = splitFile(projectFile)
@@ -672,6 +672,12 @@ proc callCCompiler*(projectfile: string) =
   var prettyCmds: TStringSeq = @[]
   let prettyCb = proc (idx: int) =
     echo prettyCmds[idx]
+  let runCb = proc (idx: int, p: Process) =
+    let exitCode = p.peekExitCode
+    if exitCode != 0:
+      rawMessage(errGenerated, "execution of an external compiler program '" &
+        cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
+        p.outputStream.readAll.strip)
   compileCFile(toCompile, script, cmds, prettyCmds, false)
   compileCFile(externalToCompile, script, cmds, prettyCmds, true)
   if optCompileOnly notin gGlobalOptions:
@@ -680,22 +686,19 @@ proc callCCompiler*(projectfile: string) =
     if gNumberOfProcessors <= 1:
       for i in countup(0, high(cmds)):
         res = execWithEcho(cmds[i])
-        if res != 0: rawMessage(errExecutionOfProgramFailed, [])
+        if res != 0: rawMessage(errExecutionOfProgramFailed, cmds[i])
     elif optListCmd in gGlobalOptions or gVerbosity > 1:
-      res = execProcesses(cmds, {poEchoCmd, poUsePath, poParentStreams},
-                          gNumberOfProcessors)
+      res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath, poParentStreams},
+                          gNumberOfProcessors, afterRunEvent=runCb)
     elif gVerbosity == 1:
-      res = execProcesses(cmds, {poUsePath, poParentStreams},
-                          gNumberOfProcessors, prettyCb)
+      res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
+                          gNumberOfProcessors, prettyCb, afterRunEvent=runCb)
     else:
-      res = execProcesses(cmds, {poUsePath, poParentStreams},
-                          gNumberOfProcessors)
+      res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
+                          gNumberOfProcessors, afterRunEvent=runCb)
     if res != 0:
       if gNumberOfProcessors <= 1:
-        rawMessage(errExecutionOfProgramFailed, [])
-      else:
-        rawMessage(errGenerated, " execution of an external program failed; " &
-                   "rerun with --parallelBuild:1 to see the error message")
+        rawMessage(errExecutionOfProgramFailed, cmds.join())
   if optNoLinking notin gGlobalOptions:
     # call the linker:
     var it = PStrEntry(toLink.head)
diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim
index d3ab1728c..21810adb9 100644
--- a/compiler/filter_tmpl.nim
+++ b/compiler/filter_tmpl.nim
@@ -67,9 +67,9 @@ proc parseLine(p: var TTmplParser) =
     keyw: string
   j = 0
   while p.x[j] == ' ': inc(j)
-  if (p.x[0] == p.nimDirective) and (p.x[0 + 1] == '!'):
+  if p.x[0] == p.nimDirective and p.x[1] in {'?', '!'}:
     newLine(p)
-  elif (p.x[j] == p.nimDirective):
+  elif p.x[j] == p.nimDirective:
     newLine(p)
     inc(j)
     while p.x[j] == ' ': inc(j)
diff --git a/compiler/guards.nim b/compiler/guards.nim
index bc802ae33..5ad932e48 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -37,6 +37,7 @@ const
   someMod = {mModI}
   someMax = {mMaxI, mMaxF64}
   someMin = {mMinI, mMinF64}
+  someBinaryOp = someAdd+someSub+someMul+someMax+someMin
 
 proc isValue(n: PNode): bool = n.kind in {nkCharLit..nkNilLit}
 proc isLocation(n: PNode): bool = not n.isValue
@@ -165,11 +166,21 @@ proc `|+|`(a, b: PNode): PNode =
   if a.kind in {nkCharLit..nkUInt64Lit}: result.intVal = a.intVal |+| b.intVal
   else: result.floatVal = a.floatVal + b.floatVal
 
+proc `|-|`(a, b: PNode): PNode =
+  result = copyNode(a)
+  if a.kind in {nkCharLit..nkUInt64Lit}: result.intVal = a.intVal |-| b.intVal
+  else: result.floatVal = a.floatVal - b.floatVal
+
 proc `|*|`(a, b: PNode): PNode =
   result = copyNode(a)
   if a.kind in {nkCharLit..nkUInt64Lit}: result.intVal = a.intVal |*| b.intVal
   else: result.floatVal = a.floatVal * b.floatVal
 
+proc `|div|`(a, b: PNode): PNode =
+  result = copyNode(a)
+  if a.kind in {nkCharLit..nkUInt64Lit}: result.intVal = a.intVal div b.intVal
+  else: result.floatVal = a.floatVal / b.floatVal
+
 proc negate(a, b, res: PNode): PNode =
   if b.kind in {nkCharLit..nkUInt64Lit} and b.intVal != low(BiggestInt):
     var b = copyNode(b)
@@ -213,10 +224,16 @@ proc reassociation(n: PNode): PNode =
     if result[2].isValue and
         result[1].getMagic in someAdd and result[1][2].isValue:
       result = opAdd.buildCall(result[1][1], result[1][2] |+| result[2])
+      if result[2].intVal == 0:
+        result = result[1]
   of someMul:
     if result[2].isValue and
         result[1].getMagic in someMul and result[1][2].isValue:
-      result = opAdd.buildCall(result[1][1], result[1][2] |*| result[2])
+      result = opMul.buildCall(result[1][1], result[1][2] |*| result[2])
+      if result[2].intVal == 1:
+        result = result[1]
+      elif result[2].intVal == 0:
+        result = zero()
   else: discard
 
 proc pred(n: PNode): PNode =
@@ -234,7 +251,7 @@ proc canon*(n: PNode): PNode =
       result.sons[i] = canon(n.sons[i])
   elif n.kind == nkSym and n.sym.kind == skLet and
       n.sym.ast.getMagic in (someEq + someAdd + someMul + someMin +
-      someMax + someHigh + {mUnaryLt} + someSub + someLen):
+      someMax + someHigh + {mUnaryLt} + someSub + someLen + someDiv):
     result = n.sym.ast.copyTree
   else:
     result = n
@@ -248,7 +265,7 @@ proc canon*(n: PNode): PNode =
     # high == len+(-1)
     result = opAdd.buildCall(opLen.buildCall(result[1]), minusOne())
   of mUnaryLt:
-    result = buildCall(opAdd, result[1], newIntNode(nkIntLit, -1))
+    result = buildCall(opAdd, result[1], minusOne())
   of someSub:
     # x - 4  -->  x + (-4)
     result = negate(result[1], result[2], result)
@@ -294,6 +311,16 @@ proc canon*(n: PNode): PNode =
         if plus != nil and not isLetLocation(x, true):
           result = buildCall(result[0].sym, plus, y[1])
       else: discard
+    elif x.isValue and y.getMagic in someAdd and y[2].isValue:
+      # 0 <= a.len + 3
+      # -3 <= a.len
+      result.sons[1] = x |-| y[2]
+      result.sons[2] = y[1]
+    elif x.isValue and y.getMagic in someSub and y[2].isValue:
+      # 0 <= a.len - 3
+      # 3 <= a.len
+      result.sons[1] = x |+| y[2]
+      result.sons[2] = y[1]
   else: discard
 
 proc `+@`*(a: PNode; b: BiggestInt): PNode =
@@ -313,6 +340,9 @@ proc usefulFact(n: PNode): PNode =
     if isLetLocation(n.sons[1], true) or isLetLocation(n.sons[2], true):
       # XXX algebraic simplifications!  'i-1 < a.len' --> 'i < a.len+1'
       result = n
+    elif n[1].getMagic in someLen or n[2].getMagic in someLen:
+      # XXX Rethink this whole idea of 'usefulFact' for semparallel
+      result = n
   of mIsNil:
     if isLetLocation(n.sons[1], false) or isVar(n.sons[1]):
       result = n
@@ -366,8 +396,8 @@ proc usefulFact(n: PNode): PNode =
 type
   TModel* = seq[PNode] # the "knowledge base"
 
-proc addFact*(m: var TModel, n: PNode) =
-  let n = usefulFact(n)
+proc addFact*(m: var TModel, nn: PNode) =
+  let n = usefulFact(nn)
   if n != nil: m.add n
 
 proc addFactNeg*(m: var TModel, n: PNode) =
@@ -697,10 +727,57 @@ proc simpleSlice*(a, b: PNode): BiggestInt =
   else:
     result = -1
 
+
+template isMul(x): expr = x.getMagic in someMul
+template isDiv(x): expr = x.getMagic in someDiv
+template isAdd(x): expr = x.getMagic in someAdd
+template isSub(x): expr = x.getMagic in someSub
+template isVal(x): expr = x.kind in {nkCharLit..nkUInt64Lit}
+template isIntVal(x, y): expr = x.intVal == y
+
+import macros
+
+macro `=~`(x: PNode, pat: untyped): bool =
+  proc m(x, pat, conds: NimNode) =
+    case pat.kind
+    of nnkInfix:
+      case $pat[0]
+      of "*": conds.add getAst(isMul(x))
+      of "/": conds.add getAst(isDiv(x))
+      of "+": conds.add getAst(isAdd(x))
+      of "-": conds.add getAst(isSub(x))
+      else:
+        error("invalid pattern")
+      m(newTree(nnkBracketExpr, x, newLit(1)), pat[1], conds)
+      m(newTree(nnkBracketExpr, x, newLit(2)), pat[2], conds)
+    of nnkPar:
+      if pat.len == 1:
+        m(x, pat[0], conds)
+      else:
+        error("invalid pattern")
+    of nnkIdent:
+      let c = newTree(nnkStmtListExpr, newLetStmt(pat, x))
+      conds.add c
+      if ($pat)[^1] == 'c': c.add(getAst(isVal(pat)))
+      else: c.add bindSym"true"
+    of nnkIntLit:
+      conds.add(getAst(isIntVal(pat.intVal)))
+    else:
+      error("invalid pattern")
+
+  var conds = newTree(nnkBracket)
+  m(x, pat, conds)
+  result = nestList(!"and", conds)
+
+
+proc isMinusOne(n: PNode): bool =
+  n.kind in {nkCharLit..nkUInt64Lit} and n.intVal == -1
+
 proc pleViaModel(model: TModel; aa, bb: PNode): TImplication
 
 proc ple(m: TModel; a, b: PNode): TImplication =
   template `<=?`(a,b): expr = ple(m,a,b) == impYes
+  template `>=?`(a,b): expr = ple(m, nkIntLit.newIntNode(b), a) == impYes
 
   #   0 <= 3
   if a.isValue and b.isValue:
@@ -721,6 +798,7 @@ proc ple(m: TModel; a, b: PNode): TImplication =
     if a.intVal <= 0: return impYes
 
   #   x <= y+c  if 0 <= c and x <= y
+  #   x <= y+(-c)  if c <= 0  and y >= x
   if b.getMagic in someAdd and zero() <=? b[2] and a <=? b[1]: return impYes
 
   #   x+c <= y  if c <= 0 and x <= y
@@ -730,10 +808,44 @@ proc ple(m: TModel; a, b: PNode): TImplication =
   if b.getMagic in someMul:
     if a <=? b[1] and one() <=? b[2] and zero() <=? b[1]: return impYes
 
+
+  if a.getMagic in someMul and a[2].isValue and a[1].getMagic in someDiv and
+      a[1][2].isValue:
+    # simplify   (x div 4) * 2 <= y   to  x div (c div d)  <= y
+    if ple(m, buildCall(opDiv, a[1][1], `|div|`(a[1][2], a[2])), b) == impYes:
+      return impYes
+
+  # x*3 + x == x*4. It follows that:
+  # x*3 + y <= x*4  if  y <= x  and 3 <= 4
+  if a =~ x*dc + y and b =~ x2*ec:
+    if sameTree(x, x2):
+      let ec1 = opAdd.buildCall(ec, minusOne())
+      if x >=? 1 and ec >=? 1 and dc >=? 1 and dc <=? ec1 and y <=? x:
+        return impYes
+  elif a =~ x*dc and b =~ x2*ec + y:
+    #echo "BUG cam ehrer e ", a, " <=? ", b
+    if sameTree(x, x2):
+      let ec1 = opAdd.buildCall(ec, minusOne())
+      if x >=? 1 and ec >=? 1 and dc >=? 1 and dc <=? ec1 and y <=? zero():
+        return impYes
+
+  #  x+c <= x+d  if c <= d. Same for *, - etc.
+  if a.getMagic in someBinaryOp and a.getMagic == b.getMagic:
+    if sameTree(a[1], b[1]) and a[2] <=? b[2]: return impYes
+    elif sameTree(a[2], b[2]) and a[1] <=? b[1]: return impYes
+
   #   x div c <= y   if   1 <= c  and  0 <= y  and x <= y:
   if a.getMagic in someDiv:
     if one() <=? a[2] and zero() <=? b and a[1] <=? b: return impYes
 
+    #  x div c <= x div d  if d <= c
+    if b.getMagic in someDiv:
+      if sameTree(a[1], b[1]) and b[2] <=? a[2]: return impYes
+
+    # x div z <= x - 1   if  z <= x
+    if a[2].isValue and b.getMagic in someAdd and b[2].isMinusOne:
+      if a[2] <=? a[1] and sameTree(a[1], b[1]): return impYes
+
   # slightly subtle:
   # x <= max(y, z)  iff x <= y or x <= z
   # note that 'x <= max(x, z)' is a special case of the above rule
@@ -769,11 +881,19 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication =
   for i in 0..m.high:
     let fact = m[i]
     if fact != nil and fact.getMagic in someLe:
-      # x <= y implies a <= b  if  a <= x and y <= b
-      let x = fact[1]
-      let y = fact[2]
       # mark as used:
       m[i] = nil
+      # i <= len-100
+      # i <=? len-1
+      # --> true  if  (len-100) <= (len-1)
+      let x = fact[1]
+      let y = fact[2]
+      if sameTree(x, a) and y.getMagic in someAdd and b.getMagic in someAdd and
+         sameTree(y[1], b[1]):
+        if ple(m, b[2], y[2]) == impYes:
+          return impYes
+
+      # x <= y implies a <= b  if  a <= x and y <= b
       if ple(m, a, x) == impYes:
         if ple(m, y, b) == impYes:
           return impYes
diff --git a/compiler/installer.ini b/compiler/installer.ini
index c8af38886..729c13503 100644
--- a/compiler/installer.ini
+++ b/compiler/installer.ini
@@ -115,6 +115,9 @@ Files: "lib/posix/*.nim"
 Files: "lib/js/*.nim"
 Files: "lib/packages/docutils/*.nim"
 
+Files: "lib/deprecated/core/*.nim"
+Files: "lib/deprecated/pure/*.nim"
+Files: "lib/deprecated/pure/*.cfg"
 
 [Other]
 Files: "examples/*.nim"
diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim
index 851938327..832d9996c 100644
--- a/compiler/jstypes.nim
+++ b/compiler/jstypes.nim
@@ -116,8 +116,7 @@ proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
          [name, genTypeInfo(p, typ.sons[0])])
 
 proc genTypeInfo(p: PProc, typ: PType): Rope =
-  var t = typ
-  if t.kind == tyGenericInst: t = lastSon(t)
+  let t = typ.skipTypes({tyGenericInst})
   result = "NTI$1" % [rope(t.id)]
   if containsOrIncl(p.g.typeInfoGenerated, t.id): return
   case t.kind
@@ -141,7 +140,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
               [result, rope(ord(t.kind))]
     prepend(p.g.typeInfo, s)
     addf(p.g.typeInfo, "$1.base = $2;$n",
-         [result, genTypeInfo(p, typ.sons[1])])
+         [result, genTypeInfo(p, t.sons[1])])
   of tyEnum: genEnumInfo(p, t, result)
   of tyObject: genObjectInfo(p, t, result)
   of tyTuple: genTupleInfo(p, t, result)
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index c669fc745..cccc94756 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -859,11 +859,17 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
         return indirectAccess(newSymNode(it.closureParam), local, n.info)
 
     if local.kind == skClosureIterator:
+      # bug #3354; allow for
+      #iterator iter(): int {.closure.}=
+      #  s.add(iter)
+      #  yield 1
+
+      #if local == o.fn or local == it.fn:
+      #  message(n.info, errRecursiveDependencyX, local.name.s)
+
       # consider: [i1, i2, i1]  Since we merged the iterator's closure
       # with the captured owning variables, we need to generate the
       # closure generation code again:
-      if local == o.fn or local == it.fn:
-        message(n.info, errRecursiveDependencyX, local.name.s)
       # XXX why doesn't this work?
       var closure = PEnv(idTableGet(o.lambdasToEnv, local))
       if closure.isNil:
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 88e32404a..e88589c3e 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -116,7 +116,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
   result.typ = errorType(c)
   incl(result.flags, sfDiscardable)
   # pretend it's imported from some unknown module to prevent cascading errors:
-  if gCmd != cmdInteractive and c.inCompilesContext == 0:
+  if gCmd != cmdInteractive and c.compilesContextId == 0:
     c.importTable.addSym(result)
 
 type
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index 98a4b08bf..40e0728ae 100644
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -14,22 +14,14 @@ import
 
 var systemModule*: PSym
 
-proc registerSysType*(t: PType)
-  # magic symbols in the system module:
-proc getSysType*(kind: TTypeKind): PType
-proc getCompilerProc*(name: string): PSym
-proc registerCompilerProc*(s: PSym)
-proc finishSystem*(tab: TStrTable)
-proc getSysSym*(name: string): PSym
-# implementation
-
 var
   gSysTypes: array[TTypeKind, PType]
   compilerprocs: TStrTable
+  exposed: TStrTable
 
 proc nilOrSysInt*: PType = gSysTypes[tyInt]
 
-proc registerSysType(t: PType) =
+proc registerSysType*(t: PType) =
   if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
 
 proc newSysType(kind: TTypeKind, size: int): PType =
@@ -37,7 +29,7 @@ proc newSysType(kind: TTypeKind, size: int): PType =
   result.size = size
   result.align = size.int16
 
-proc getSysSym(name: string): PSym =
+proc getSysSym*(name: string): PSym =
   result = strTableGet(systemModule.tab, getIdent(name))
   if result == nil:
     rawMessage(errSystemNeeds, name)
@@ -61,7 +53,7 @@ proc getSysMagic*(name: string, m: TMagic): PSym =
 proc sysTypeFromName*(name: string): PType =
   result = getSysSym(name).typ
 
-proc getSysType(kind: TTypeKind): PType =
+proc getSysType*(kind: TTypeKind): PType =
   result = gSysTypes[kind]
   if result == nil:
     case kind
@@ -97,6 +89,7 @@ var
 proc resetSysTypes* =
   systemModule = nil
   initStrTable(compilerprocs)
+  initStrTable(exposed)
   for i in low(gSysTypes)..high(gSysTypes):
     gSysTypes[i] = nil
 
@@ -163,8 +156,8 @@ proc setIntLitType*(result: PNode) =
       result.typ = getSysType(tyInt64)
   else: internalError(result.info, "invalid int size")
 
-proc getCompilerProc(name: string): PSym =
-  var ident = getIdent(name, hashIgnoreStyle(name))
+proc getCompilerProc*(name: string): PSym =
+  let ident = getIdent(name)
   result = strTableGet(compilerprocs, ident)
   if result == nil:
     result = strTableGet(rodCompilerprocs, ident)
@@ -173,9 +166,22 @@ proc getCompilerProc(name: string): PSym =
       if result.kind == skStub: loadStub(result)
       if result.kind == skAlias: result = result.owner
 
-proc registerCompilerProc(s: PSym) =
+proc registerCompilerProc*(s: PSym) =
   strTableAdd(compilerprocs, s)
 
-proc finishSystem(tab: TStrTable) = discard
+proc registerNimScriptSymbol*(s: PSym) =
+  # Nimscript symbols must be al unique:
+  let conflict = strTableGet(exposed, s.name)
+  if conflict == nil:
+    strTableAdd(exposed, s)
+  else:
+    localError(s.info, "symbol conflicts with other .exportNims symbol at: " &
+      $conflict.info)
+
+proc getNimScriptSymbol*(name: string): PSym =
+  strTableGet(exposed, getIdent(name))
+
+proc resetNimScriptSymbols*() = initStrTable(exposed)
 
 initStrTable(compilerprocs)
+initStrTable(exposed)
diff --git a/compiler/modules.nim b/compiler/modules.nim
index 85c99c4ec..3893d377e 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -78,6 +78,13 @@ proc resetModule*(fileIdx: int32) =
   if fileIdx <% cgendata.gModules.len:
     cgendata.gModules[fileIdx] = nil
 
+proc resetModule*(module: PSym) =
+  let conflict = getModule(module.position.int32)
+  if conflict == nil: return
+  doAssert conflict == module
+  resetModule(module.position.int32)
+  initStrTable(module.tab)
+
 proc resetAllModules* =
   for i in 0..gCompiledModules.high:
     if gCompiledModules[i] != nil:
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 8b3b11f4a..4dd134177 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -203,7 +203,7 @@ const
     errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier",
     errTypeExpected: "type expected",
     errSystemNeeds: "system module needs \'$1\'",
-    errExecutionOfProgramFailed: "execution of an external program failed",
+    errExecutionOfProgramFailed: "execution of an external program failed: '$1'",
     errNotOverloadable: "overloaded \'$1\' leads to ambiguous calls",
     errInvalidArgForX: "invalid argument for \'$1\'",
     errStmtHasNoEffect: "statement has no effect",
@@ -469,10 +469,10 @@ type
     fullPath: string           # This is a canonical full filesystem path
     projPath*: string          # This is relative to the project's root
     shortName*: string         # short name of the module
-    quotedName*: Rope         # cached quoted short name for codegen
+    quotedName*: Rope          # cached quoted short name for codegen
                                # purposes
 
-    lines*: seq[Rope]         # the source code of the module
+    lines*: seq[Rope]          # the source code of the module
                                #   used for better error messages and
                                #   embedding the original source in the
                                #   generated code
@@ -514,6 +514,7 @@ const
     {low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
                                          warnProveField, warnProveIndex,
                                          warnGcUnsafe,
+                                         hintPath, hintConf,
                                          hintDependency,
                                          hintExecuting,
                                          hintCodeBegin, hintCodeEnd,
@@ -630,8 +631,11 @@ var
 
 proc suggestWriteln*(s: string) =
   if eStdOut in errorOutputs:
-    if isNil(writelnHook): writeLine(stdout, s)
-    else: writelnHook(s)
+    if isNil(writelnHook):
+      writeLine(stdout, s)
+      flushFile(stdout)
+    else:
+      writelnHook(s)
 
 proc msgQuit*(x: int8) = quit x
 proc msgQuit*(x: string) = quit x
@@ -725,7 +729,9 @@ var gTrackPos*: TLineInfo
 
 proc outWriteln*(s: string) =
   ## Writes to stdout. Always.
-  if eStdOut in errorOutputs: writeLine(stdout, s)
+  if eStdOut in errorOutputs:
+    writeLine(stdout, s)
+    flushFile(stdout)
 
 proc msgWriteln*(s: string) =
   ## Writes to stdout. If --stdout option is given, writes to stderr instead.
@@ -735,9 +741,13 @@ proc msgWriteln*(s: string) =
   if not isNil(writelnHook):
     writelnHook(s)
   elif optStdout in gGlobalOptions:
-    if eStdErr in errorOutputs: writeLine(stderr, s)
+    if eStdErr in errorOutputs:
+      writeLine(stderr, s)
+      flushFile(stderr)
   else:
-    if eStdOut in errorOutputs: writeLine(stdout, s)
+    if eStdOut in errorOutputs:
+      writeLine(stdout, s)
+      flushFile(stdout)
 
 macro callIgnoringStyle(theProc: typed, first: typed,
                         args: varargs[expr]): stmt =
@@ -772,13 +782,16 @@ template styledMsgWriteln*(args: varargs[expr]) =
   if not isNil(writelnHook):
     callIgnoringStyle(callWritelnHook, nil, args)
   elif optStdout in gGlobalOptions:
-    if eStdErr in errorOutputs: callIgnoringStyle(writeLine, stderr, args)
+    if eStdErr in errorOutputs:
+      callIgnoringStyle(writeLine, stderr, args)
+      flushFile(stderr)
   else:
     if eStdOut in errorOutputs:
       if optUseColors in gGlobalOptions:
         callStyledEcho(args)
       else:
         callIgnoringStyle(writeLine, stdout, args)
+      flushFile stdout
 
 proc coordToStr(coord: int): string =
   if coord == -1: result = "???"
diff --git a/compiler/nim.nim b/compiler/nim.nim
index 51f4cae92..1293ec922 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -48,7 +48,7 @@ proc handleCmdLine() =
         gProjectFull = canonicalizePath(gProjectName)
       except OSError:
         gProjectFull = gProjectName
-      var p = splitFile(gProjectFull)
+      let p = splitFile(gProjectFull)
       gProjectPath = p.dir
       gProjectName = p.name
     else:
@@ -59,6 +59,9 @@ proc handleCmdLine() =
       runNimScript(scriptFile)
       # 'nim foo.nims' means to just run the NimScript file and do nothing more:
       if scriptFile == gProjectFull: return
+    elif fileExists(gProjectPath / "config.nims"):
+      # directory wide NimScript file
+      runNimScript(gProjectPath / "config.nims")
     # now process command line arguments again, because some options in the
     # command line can overwite the config file's settings
     extccomp.initVars()
diff --git a/compiler/options.nim b/compiler/options.nim
index adb340fea..23c76acc5 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -86,7 +86,7 @@ type                          # please make sure we have under 32 options
     gcNone, gcBoehm, gcGo, gcMarkAndSweep, gcRefc, gcV2, gcGenerational
 
   IdeCmd* = enum
-    ideNone, ideSug, ideCon, ideDef, ideUse
+    ideNone, ideSug, ideCon, ideDef, ideUse, ideDus
 
 var
   gIdeCmd*: IdeCmd
@@ -421,6 +421,7 @@ proc parseIdeCmd*(s: string): IdeCmd =
   of "con": ideCon
   of "def": ideDef
   of "use": ideUse
+  of "dus": ideDus
   else: ideNone
 
 proc `$`*(c: IdeCmd): string =
@@ -429,4 +430,5 @@ proc `$`*(c: IdeCmd): string =
   of ideCon: "con"
   of ideDef: "def"
   of ideUse: "use"
+  of ideDus: "dus"
   of ideNone: "none"
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index ae391945a..978583c14 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -225,8 +225,11 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
     result = isAssignable(owner, n.sons[0], isUnsafeAddr)
   of nkCallKinds:
     # builtin slice keeps lvalue-ness:
-    if getMagic(n) == mSlice:
+    if getMagic(n) in {mArrGet, mSlice}:
       result = isAssignable(owner, n.sons[1], isUnsafeAddr)
+  of nkStmtList, nkStmtListExpr:
+    if n.typ != nil:
+      result = isAssignable(owner, n.lastSon, isUnsafeAddr)
   else:
     discard
 
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 1c51251fe..79d7884fa 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -25,18 +25,19 @@ const
     wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
     wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
     wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
-    wOverride, wConstructor}
+    wOverride, wConstructor, wExportNims}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas+{wBase}
   templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
-    wDelegator}
+    wDelegator, wExportNims}
   macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
     wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
-    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator}
+    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
+    wExportNims}
   iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
     wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
     wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
-    wTags, wLocks, wGcSafe}
+    wTags, wLocks, wGcSafe, wExportNims}
   exprPragmas* = {wLine, wLocks, wNoRewrite}
   stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
     wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
@@ -54,15 +55,15 @@ const
     wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
     wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
     wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
-    wBorrow, wGcSafe}
+    wBorrow, wGcSafe, wExportNims}
   fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
-    wImportCpp, wImportObjC, wError, wGuard}
+    wImportCpp, wImportObjC, wError, wGuard, wBitsize}
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
     wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
     wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
-    wGensym, wInject, wCodegenDecl, wGuard, wGoto}
+    wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims}
   constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
-    wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
+    wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims}
   letPragmas* = varPragmas
   procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
                       wThread, wRaises, wLocks, wTags, wGcSafe}
@@ -844,6 +845,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         if sym == nil: pragmaLockStmt(c, it)
         elif sym.typ == nil: invalidPragma(it)
         else: sym.typ.lockLevel = pragmaLocks(c, it)
+      of wBitsize:
+        if sym == nil or sym.kind != skField or it.kind != nkExprColonExpr:
+          invalidPragma(it)
+        else:
+          sym.bitsize = expectIntLit(c, it)
       of wGuard:
         if sym == nil or sym.kind notin {skVar, skLet, skField}:
           invalidPragma(it)
@@ -854,6 +860,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           invalidPragma(it)
         else:
           sym.flags.incl sfGoto
+      of wExportNims:
+        if sym == nil: invalidPragma(it)
+        else: magicsys.registerNimScriptSymbol(sym)
       of wInjectStmt:
         if it.kind != nkExprColonExpr:
           localError(it.info, errExprExpected)
diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim
index 8499ebd98..22cd282fd 100644
--- a/compiler/scriptconfig.nim
+++ b/compiler/scriptconfig.nim
@@ -105,6 +105,13 @@ proc setupVM*(module: PSym; scriptName: string): PEvalContext =
     setResult(a, strutils.cmpIgnoreCase(a.getString 0, a.getString 1))
   cbconf setCommand:
     options.command = a.getString 0
+    let arg = a.getString 1
+    if arg.len > 0:
+      gProjectName = arg
+      try:
+        gProjectFull = canonicalizePath(gProjectPath / gProjectName)
+      except OSError:
+        gProjectFull = gProjectName
   cbconf getCommand:
     setResult(a, options.command)
   cbconf switch:
@@ -133,4 +140,7 @@ proc runNimScript*(scriptName: string) =
   # ensure we load 'system.nim' again for the real non-config stuff!
   resetAllModulesHard()
   vm.globalCtx = nil
-  initDefines()
+  # do not remove the defined symbols
+  #initDefines()
+  undefSymbol("nimscript")
+  undefSymbol("nimconfig")
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 2f181b5f3..381093531 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -95,7 +95,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
   # Gives a detailed error message; this is separated from semOverloadedCall,
   # as semOverlodedCall is already pretty slow (and we need this information
   # only in case of an error).
-  if c.inCompilesContext > 0:
+  if c.compilesContextId > 0:
     # fail fast:
     globalError(n.info, errTypeMismatch, "")
   if errors.isNil or errors.len == 0:
@@ -235,7 +235,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
     internalAssert result.state == csMatch
     #writeMatches(result)
     #writeMatches(alt)
-    if c.inCompilesContext > 0:
+    if c.compilesContextId > 0:
       # quick error message for performance of 'compiles' built-in:
       globalError(n.info, errGenerated, "ambiguous call")
     elif gErrorCounter == 0:
@@ -308,7 +308,10 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
   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)
+      if x.calleeSym.magic in {mArrGet, mArrPut}:
+        finalCallee = x.calleeSym
+      else:
+        finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
     else:
       # For macros and templates, the resolved generic params
       # are added as normal params.
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 345a8c0d1..9b2f2e2ce 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -45,7 +45,8 @@ type
   TExprFlag* = enum
     efLValue, efWantIterator, efInTypeof,
     efWantStmt, efAllowStmt, efDetermineType,
-    efAllowDestructor, efWantValue, efOperand, efNoSemCheck
+    efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
+    efNoProcvarCheck
   TExprFlags* = set[TExprFlag]
 
   TTypeAttachedOp* = enum
@@ -70,7 +71,8 @@ type
     inTypeClass*: int          # > 0 if we are in a user-defined type class
     inGenericContext*: int     # > 0 if we are in a generic type
     inUnrolledContext*: int    # > 0 if we are unrolling a loop
-    inCompilesContext*: int    # > 0 if we are in a ``compiles`` magic
+    compilesContextId*: int    # > 0 if we are in a ``compiles`` magic
+    compilesContextIdGenerator*: int
     inGenericInst*: int        # > 0 if we are instantiating a generic
     converters*: TSymSeq       # sequence of converters
     patterns*: TSymSeq         # sequence of pattern matchers
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 3ff04a4fc..4792702dc 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -52,7 +52,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result.typ = errorType(c)
   else:
     # XXX tyGenericInst here?
-    semProcvarCheck(c, result)
+    if efNoProcvarCheck notin flags: semProcvarCheck(c, result)
     if result.typ.kind == tyVar: result = newDeref(result)
     semDestructorCheck(c, result, flags)
 
@@ -452,18 +452,18 @@ proc changeType(n: PNode, newType: PType, check: bool) =
     let tup = newType.skipTypes({tyGenericInst})
     if tup.kind != tyTuple:
       if tup.kind == tyObject: return
-      internalError(n.info, "changeType: no tuple type for constructor")
+      globalError(n.info, "no tuple type for constructor")
     elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
       # named tuple?
       for i in countup(0, sonsLen(n) - 1):
         var m = n.sons[i].sons[0]
         if m.kind != nkSym:
-          internalError(m.info, "changeType(): invalid tuple constr")
+          globalError(m.info, "invalid tuple constructor")
           return
         if tup.n != nil:
           var f = getSymFromList(tup.n, m.sym.name)
           if f == nil:
-            internalError(m.info, "changeType(): invalid identifier")
+            globalError(m.info, "unknown identifier: " & m.sym.name.s)
             return
           changeType(n.sons[i].sons[1], f.typ, check)
         else:
@@ -818,7 +818,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     # This is a proc variable, apply normal overload resolution
     let m = resolveIndirectCall(c, n, nOrig, t)
     if m.state != csMatch:
-      if c.inCompilesContext > 0:
+      if c.compilesContextId > 0:
         # speed up error generation:
         globalError(n.info, errTypeMismatch, "")
         return emptyNode
@@ -1156,7 +1156,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
     result.add(x[0])
     return
   checkMinSonsLen(n, 2)
-  n.sons[0] = semExprWithType(c, n.sons[0])
+  n.sons[0] = semExprWithType(c, n.sons[0], {efNoProcvarCheck})
   let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
   case arr.kind
   of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
@@ -1196,7 +1196,17 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
       localError(n.info, errIndexTypesDoNotMatch)
     result = n
   else:
-    c.p.bracketExpr = n.sons[0]
+    let s = if n.sons[0].kind == nkSym: n.sons[0].sym
+            elif n[0].kind in nkSymChoices: n.sons[0][0].sym
+            else: nil
+    if s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators:
+      # type parameters: partial generic specialization
+      n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
+      result = explicitGenericInstantiation(c, n, s)
+    elif s != nil and s.kind == skType:
+      result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
+    else:
+      c.p.bracketExpr = n.sons[0]
 
 proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   let oldBracketExpr = c.p.bracketExpr
@@ -1250,7 +1260,7 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
 template resultTypeIsInferrable(typ: PType): expr =
   typ.isMetaType and typ.kind != tyTypeDesc
 
-proc semAsgn(c: PContext, n: PNode): PNode =
+proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
   checkSonsLen(n, 2)
   var a = n.sons[0]
   case a.kind
@@ -1273,12 +1283,15 @@ proc semAsgn(c: PContext, n: PNode): PNode =
     # --> `[]=`(a, i, x)
     let oldBracketExpr = c.p.bracketExpr
     a = semSubscript(c, a, {efLValue})
-    if a == nil:
+    if a == nil and mode != noOverloadedSubscript:
       result = buildOverloadedSubscripts(n.sons[0], getIdent"[]=")
       add(result, n[1])
       result = semExprNoType(c, result)
       c.p.bracketExpr = oldBracketExpr
       return result
+    elif a == nil:
+      localError(n.info, "could not resolve: " & $n[0])
+      return n
     c.p.bracketExpr = oldBracketExpr
   of nkCurlyExpr:
     # a{i} = x -->  `{}=`(a, i, x)
@@ -1323,7 +1336,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
           typeMismatch(n, lhs.typ, rhs.typ)
 
     n.sons[1] = fitNode(c, le, rhs)
-    if tfHasAsgn in lhs.typ.flags and not lhsIsResult:
+    if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
+        mode != noOverloadedAsgn:
       return overloadedAsgn(c, lhs, n.sons[1])
 
     fixAbstractType(c, n)
@@ -1622,7 +1636,9 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   # watch out, hacks ahead:
   let oldErrorCount = msgs.gErrorCounter
   let oldErrorMax = msgs.gErrorMax
-  inc c.inCompilesContext
+  let oldCompilesId = c.compilesContextId
+  inc c.compilesContextIdGenerator
+  c.compilesContextId = c.compilesContextIdGenerator
   # do not halt after first error:
   msgs.gErrorMax = high(int)
 
@@ -1646,6 +1662,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   except ERecoverableError:
     discard
   # undo symbol table changes (as far as it's possible):
+  c.compilesContextId = oldCompilesId
   c.generics = oldGenerics
   c.inGenericContext = oldInGenericContext
   c.inUnrolledContext = oldInUnrolledContext
@@ -1654,7 +1671,6 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   msgs.setInfoContextLen(oldContextLen)
   setLen(gOwners, oldOwnerLen)
   c.currentScope = oldScope
-  dec c.inCompilesContext
   errorOutputs = oldErrorOutputs
   msgs.gErrorCounter = oldErrorCount
   msgs.gErrorMax = oldErrorMax
@@ -1715,6 +1731,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   of mTypeOf:
     checkSonsLen(n, 2)
     result = semTypeOf(c, n.sons[1])
+  #of mArrGet: result = semArrGet(c, n, flags)
+  #of mArrPut: result = semArrPut(c, n, flags)
+  #of mAsgn: result = semAsgnOpr(c, n)
   of mDefined: result = semDefined(c, setMs(n, s), false)
   of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
   of mCompiles: result = semCompiles(c, setMs(n, s), flags)
@@ -2066,6 +2085,19 @@ proc semExport(c: PContext, n: PNode): PNode =
     c.module.ast.add x
   result = n
 
+proc shouldBeBracketExpr(n: PNode): bool =
+  assert n.kind in nkCallKinds
+  let a = n.sons[0]
+  if a.kind in nkCallKinds:
+    let b = a[0]
+    if b.kind in nkSymChoices:
+      for i in 0..<b.len:
+        if b[i].sym.magic == mArrGet:
+          let be = newNodeI(nkBracketExpr, n.info)
+          for i in 1..<a.len: be.add(a[i])
+          n.sons[0] = be
+          return true
+
 proc setGenericParams(c: PContext, n: PNode) =
   for i in 1 .. <n.len:
     n[i].typ = semTypeNode(c, n[i], nil)
@@ -2173,7 +2205,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       else:
         #liMessage(n.info, warnUser, renderTree(n));
         result = semIndirectOp(c, n, flags)
-    elif n[0].kind == nkBracketExpr and isSymChoice(n[0][0]):
+    elif (n[0].kind == nkBracketExpr or shouldBeBracketExpr(n)) and
+        isSymChoice(n[0][0]):
       # indirectOp can deal with explicit instantiations; the fixes
       # the 'newSeq[T](x)' bug
       setGenericParams(c, n.sons[0])
@@ -2194,16 +2227,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
         result = semExpr(c, result, flags)
   of nkBracketExpr:
     checkMinSonsLen(n, 1)
-    var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
-    if (s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators) or
-        n[0].kind in nkSymChoices:
-      # type parameters: partial generic specialization
-      n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
-      result = explicitGenericInstantiation(c, n, s)
-    elif s != nil and s.kind in {skType}:
-      result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
-    else:
-      result = semArrayAccess(c, n, flags)
+    result = semArrayAccess(c, n, flags)
   of nkCurlyExpr:
     result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
   of nkPragmaExpr:
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 2ab43a9c9..5fe4e3299 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -430,17 +430,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
   of mCompileOptionArg:
     result = newIntNodeT(ord(
       testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
-  of mNewString, mNewStringOfCap,
-     mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
-     mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
-     mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mDotDot,
-     mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn,
-     mParallel, mPlugin, mGetTypeInfo:
-    discard
   of mEqProc:
     result = newIntNodeT(ord(
         exprStructuralEquivalent(a, b, strictSymEquality=true)), n)
-  else: internalError(a.info, "evalOp(" & $m & ')')
+  else: discard
 
 proc getConstIfExpr(c: PSym, n: PNode): PNode =
   result = nil
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index e3b598919..620453277 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -30,6 +30,7 @@ type
   GenericCtx = object
     toMixin: IntSet
     cursorInBody: bool # only for nimsuggest
+    bracketExpr: PNode
 
 type
   TSemGenericFlag = enum
@@ -227,6 +228,10 @@ proc semGenericStmt(c: PContext, n: PNode,
         discard
       of skProc, skMethod, skIterators, skConverter, skModule:
         result.sons[0] = symChoice(c, fn, s, scOption)
+        # do not check of 's.magic==mRoof' here because it might be some
+        # other '^' but after overload resolution the proper one:
+        if ctx.bracketExpr != nil and n.len == 2 and s.name.s == "^":
+          result.add ctx.bracketExpr
         first = 1
       of skGenericParam:
         result.sons[0] = newSymNodeTypeDesc(s, fn.info)
@@ -251,6 +256,40 @@ proc semGenericStmt(c: PContext, n: PNode,
     let flags = if mixinContext: flags+{withinMixin} else: flags
     for i in countup(first, sonsLen(result) - 1):
       result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
+  of nkCurlyExpr:
+    result = newNodeI(nkCall, n.info)
+    result.add newIdentNode(getIdent("{}"), n.info)
+    for i in 0 ..< n.len: result.add(n[i])
+    result = semGenericStmt(c, result, flags, ctx)
+  of nkBracketExpr:
+    result = newNodeI(nkCall, n.info)
+    result.add newIdentNode(getIdent("[]"), n.info)
+    for i in 0 ..< n.len: result.add(n[i])
+    withBracketExpr ctx, n.sons[0]:
+      result = semGenericStmt(c, result, flags, ctx)
+  of nkAsgn, nkFastAsgn:
+    checkSonsLen(n, 2)
+    let a = n.sons[0]
+    let b = n.sons[1]
+
+    let k = a.kind
+    case k
+    of nkCurlyExpr:
+      result = newNodeI(nkCall, n.info)
+      result.add newIdentNode(getIdent("{}="), n.info)
+      for i in 0 ..< a.len: result.add(a[i])
+      result.add(b)
+      result = semGenericStmt(c, result, flags, ctx)
+    of nkBracketExpr:
+      result = newNodeI(nkCall, n.info)
+      result.add newIdentNode(getIdent("[]="), n.info)
+      for i in 0 ..< a.len: result.add(a[i])
+      result.add(b)
+      withBracketExpr ctx, a.sons[0]:
+        result = semGenericStmt(c, result, flags, ctx)
+    else:
+      for i in countup(0, sonsLen(n) - 1):
+        result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
   of nkIfStmt:
     for i in countup(0, sonsLen(n)-1):
       n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
@@ -357,7 +396,7 @@ proc semGenericStmt(c: PContext, n: PNode,
         of nkEnumFieldDef: a = n.sons[i].sons[0]
         of nkIdent: a = n.sons[i]
         else: illFormedAst(n)
-        addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c))
+        addDecl(c, newSymS(skUnknown, getIdentNode(a), c))
   of nkObjectTy, nkTupleTy, nkTupleClassTy:
     discard
   of nkFormalParams:
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 370990326..abc5600c3 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -47,10 +47,11 @@ proc sameInstantiation(a, b: TInstantiation): bool =
                           flags = {ExactTypeDescValues}): return
     result = true
 
-proc genericCacheGet(genericSym: PSym, entry: TInstantiation): PSym =
+proc genericCacheGet(genericSym: PSym, entry: TInstantiation;
+                     id: CompilesId): PSym =
   if genericSym.procInstCache != nil:
     for inst in genericSym.procInstCache:
-      if sameInstantiation(entry, inst[]):
+      if inst.compilesId == id and sameInstantiation(entry, inst[]):
         return inst.sym
 
 proc removeDefaultParamValues(n: PNode) =
@@ -164,7 +165,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
   addDecl(c, prc)
 
   pushInfoContext(info)
-  var cl = initTypeVars(c, pt, info)
+  var cl = initTypeVars(c, pt, info, nil)
   var result = instCopyType(cl, prc.typ)
   let originalParams = result.n
   result.n = originalParams.shallowCopy
@@ -221,6 +222,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   # NOTE: for access of private fields within generics from a different module
   # we set the friend module:
   c.friendModules.add(getModule(fn))
+  let oldInTypeClass = c.inTypeClass
+  c.inTypeClass = 0
   let oldScope = c.currentScope
   while not isTopLevel(c): c.currentScope = c.currentScope.parent
   result = copySym(fn, false)
@@ -244,14 +247,18 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     inc i
   pushProcCon(c, result)
   instantiateProcType(c, pt, result, info)
+  if tfTriggersCompileTime in result.typ.flags:
+    incl(result.flags, sfCompileTime)
   n.sons[genericParamsPos] = ast.emptyNode
-  var oldPrc = genericCacheGet(fn, entry[])
+  var oldPrc = genericCacheGet(fn, entry[], c.compilesContextId)
   if oldPrc == nil:
     # we MUST not add potentially wrong instantiations to the caching mechanism.
     # This means recursive instantiations behave differently when in
     # a ``compiles`` context but this is the lesser evil. See
     # bug #1055 (tevilcompiles).
-    if c.inCompilesContext == 0: fn.procInstCache.safeAdd(entry)
+    #if c.compilesContextId == 0:
+    entry.compilesId = c.compilesContextId
+    fn.procInstCache.safeAdd(entry)
     c.generics.add(makeInstPair(fn, entry))
     if n.sons[pragmasPos].kind != nkEmpty:
       pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
@@ -269,4 +276,5 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   c.currentScope = oldScope
   discard c.friendModules.pop()
   dec(c.instCounter)
+  c.inTypeClass = oldInTypeClass
   if result.kind == skMethod: finishMethod(c, result)
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 5d16470b0..deef38ae3 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -26,6 +26,41 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
   result.add typExpr
   result.typ = makeTypeDesc(c, typExpr.typ.skipTypes({tyTypeDesc, tyIter}))
 
+type
+  SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn
+
+proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode
+proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode
+
+proc skipAddr(n: PNode): PNode {.inline.} =
+  (if n.kind == nkHiddenAddr: n.sons[0] else: n)
+
+proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
+  result = newNodeI(nkBracketExpr, n.info)
+  for i in 1..<n.len: result.add(n[i])
+  let oldBracketExpr = c.p.bracketExpr
+  result = semSubscript(c, result, flags)
+  c.p.bracketExpr = oldBracketExpr
+  if result.isNil:
+    localError(n.info, "could not resolve: " & $n)
+    result = n
+
+proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
+  # rewrite `[]=`(a, i, x)  back to ``a[i] = x``.
+  let b = newNodeI(nkBracketExpr, n.info)
+  b.add(n[1].skipAddr)
+  for i in 2..n.len-2: b.add(n[i])
+  result = newNodeI(nkAsgn, n.info, 2)
+  result.sons[0] = b
+  result.sons[1] = n.lastSon
+  result = semAsgn(c, result, noOverloadedSubscript)
+
+proc semAsgnOpr(c: PContext; n: PNode): PNode =
+  result = newNodeI(nkAsgn, n.info, 2)
+  result.sons[0] = n[1]
+  result.sons[1] = n[2]
+  result = semAsgn(c, result, noOverloadedAsgn)
+
 proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode =
   var r = isPartOf(n[1], n[2])
   result = newIntNodeT(ord(r), n)
@@ -125,6 +160,9 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
   of mTypeOf:
     checkSonsLen(n, 2)
     result = semTypeOf(c, n.sons[1])
+  of mArrGet: result = semArrGet(c, n, flags)
+  of mArrPut: result = semArrPut(c, n, flags)
+  of mAsgn: result = semAsgnOpr(c, n)
   of mIsPartOf: result = semIsPartOf(c, n, flags)
   of mTypeTrait: result = semTypeTraits(c, n)
   of mAstToStr:
@@ -145,25 +183,28 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
       if isNegative(n.sons[1]) or (n.len > 2 and isNegative(n.sons[2])):
         localError(n.info, "use '^' instead of '-'; negative indexing is obsolete")
   of mRoof:
-    # error correction:
-    result = n.sons[1]
-    if c.p.bracketExpr.isNil:
+    let bracketExpr = if n.len == 3: n.sons[2] else: c.p.bracketExpr
+    if bracketExpr.isNil:
       localError(n.info, "no surrounding array access context for '^'")
-    elif c.p.bracketExpr.checkForSideEffects != seNoSideEffect:
+      result = n.sons[1]
+    elif bracketExpr.checkForSideEffects != seNoSideEffect:
       localError(n.info, "invalid context for '^' as '$#' has side effects" %
-        renderTree(c.p.bracketExpr))
-    elif c.p.bracketExpr.typ.isStrangeArray:
+        renderTree(bracketExpr))
+      result = n.sons[1]
+    elif bracketExpr.typ.isStrangeArray:
       localError(n.info, "invalid context for '^' as len!=high+1 for '$#'" %
-        renderTree(c.p.bracketExpr))
+        renderTree(bracketExpr))
+      result = n.sons[1]
     else:
       # ^x  is rewritten to: len(a)-x
       let lenExpr = newNodeI(nkCall, n.info)
       lenExpr.add newIdentNode(getIdent"len", n.info)
-      lenExpr.add c.p.bracketExpr
+      lenExpr.add bracketExpr
       let lenExprB = semExprWithType(c, lenExpr)
       if lenExprB.typ.isNil or not isOrdinalType(lenExprB.typ):
         localError(n.info, "'$#' has to be of an ordinal type for '^'" %
           renderTree(lenExpr))
+        result = n.sons[1]
       else:
         result = newNodeIT(nkCall, n.info, getSysType(tyInt))
         result.add newSymNode(createMagic("-", mSubI), n.info)
diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim
index 36c63d038..b04ba4657 100644
--- a/compiler/semparallel.nim
+++ b/compiler/semparallel.nim
@@ -128,10 +128,10 @@ template `?`(x): expr = x.renderTree
 proc checkLe(c: AnalysisCtx; a, b: PNode) =
   case proveLe(c.guards, a, b)
   of impUnknown:
-    localError(a.info, "cannot prove: " & ?a & " <= " & ?b)
+    localError(a.info, "cannot prove: " & ?a & " <= " & ?b & " (bounds check)")
   of impYes: discard
   of impNo:
-    localError(a.info, "can prove: " & ?a & " > " & ?b)
+    localError(a.info, "can prove: " & ?a & " > " & ?b & " (bounds check)")
 
 proc checkBounds(c: AnalysisCtx; arr, idx: PNode) =
   checkLe(c, arr.lowBound, idx)
@@ -156,19 +156,23 @@ proc addSlice(c: var AnalysisCtx; n: PNode; x, le, ri: PNode) =
 
 proc overlap(m: TModel; x,y,c,d: PNode) =
   #  X..Y and C..D overlap iff (X <= D and C <= Y)
-  case proveLe(m, x, d)
+  case proveLe(m, c, y)
   of impUnknown:
-    localError(x.info,
-      "cannot prove: $# > $#; required for ($#)..($#) disjoint from ($#)..($#)" %
-        [?x, ?d, ?x, ?y, ?c, ?d])
+    case proveLe(m, x, d)
+    of impNo: discard
+    of impUnknown, impYes:
+      localError(x.info,
+        "cannot prove: $# > $#; required for ($#)..($#) disjoint from ($#)..($#)" %
+            [?c, ?y, ?x, ?y, ?c, ?d])
   of impYes:
-    case proveLe(m, c, y)
+    case proveLe(m, x, d)
     of impUnknown:
       localError(x.info,
         "cannot prove: $# > $#; required for ($#)..($#) disjoint from ($#)..($#)" %
-          [?c, ?y, ?x, ?y, ?c, ?d])
+          [?x, ?d, ?x, ?y, ?c, ?d])
     of impYes:
-      localError(x.info, "($#)..($#) not disjoint from ($#)..($#)" % [?x, ?y, ?c, ?d])
+      localError(x.info, "($#)..($#) not disjoint from ($#)..($#)" %
+                [?c, ?y, ?x, ?y, ?c, ?d])
     of impNo: discard
   of impNo: discard
 
@@ -278,10 +282,12 @@ proc analyseCall(c: var AnalysisCtx; n: PNode; op: PSym) =
         slot.stride = min(slot.stride, incr)
     analyseSons(c, n)
   elif op.name.s == "[]" and op.fromSystem:
-    c.addSlice(n, n[1], n[2][1], n[2][2])
+    let slice = n[2].skipStmtList
+    c.addSlice(n, n[1], slice[1], slice[2])
     analyseSons(c, n)
   elif op.name.s == "[]=" and op.fromSystem:
-    c.addSlice(n, n[1], n[2][1], n[2][2])
+    let slice = n[2].skipStmtList
+    c.addSlice(n, n[1], slice[1], slice[2])
     analyseSons(c, n)
   else:
     analyseSons(c, n)
@@ -395,8 +401,9 @@ proc transformSlices(n: PNode): PNode =
       result = copyNode(n)
       result.add opSlice.newSymNode
       result.add n[1]
-      result.add n[2][1]
-      result.add n[2][2]
+      let slice = n[2].skipStmtList
+      result.add slice[1]
+      result.add slice[2]
       return result
   if n.safeLen > 0:
     result = shallowCopy(n)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 272412b04..ef014963c 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -855,6 +855,8 @@ proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
   newSeq(effects.sons, effectListLen)
   effects.sons[exceptionEffects] = newNodeI(nkArgList, s.info)
   effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
+  effects.sons[usesEffects] = ast.emptyNode
+  effects.sons[writeEffects] = ast.emptyNode
 
   t.exc = effects.sons[exceptionEffects]
   t.tags = effects.sons[tagEffects]
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index ffda6a1bb..adb1c81c1 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -957,27 +957,35 @@ proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode =
 proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
   var n = n
 
-  n = replaceTypesInBody(c, pt, n)
-  result = n
+  let original = n.sons[namePos].sym
+  let s = copySym(original, false)
+  incl(s.flags, sfFromGeneric)
 
+  n = replaceTypesInBody(c, pt, n, original)
+  result = n
+  s.ast = result
+  n.sons[namePos].sym = s
   n.sons[genericParamsPos] = emptyNode
-  n.sons[paramsPos] = n.typ.n
-
+  let params = n.typ.n
+  n.sons[paramsPos] = params
+  s.typ = n.typ
+  for i in 1..<params.len:
+    if params[i].typ.kind in {tyTypeDesc, tyGenericParam,
+                              tyFromExpr, tyFieldAccessor}+tyTypeClasses:
+      localError(params[i].info, "cannot infer type of parameter: " &
+                 params[i].sym.name.s)
   openScope(c)
-  var s = n.sons[namePos].sym
   pushOwner(s)
-  addParams(c, n.typ.n, skProc)
+  addParams(c, params, skProc)
   pushProcCon(c, s)
   addResult(c, n.typ.sons[0], n.info, skProc)
   addResultNode(c, n)
   let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
-  n.sons[bodyPos] = transformBody(c.module, semBody, n.sons[namePos].sym)
+  n.sons[bodyPos] = transformBody(c.module, semBody, s)
   popProcCon(c)
   popOwner()
   closeScope(c)
 
-  s.ast = result
-
   # alternative variant (not quite working):
   # var prc = arg[0].sym
   # let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
@@ -1033,6 +1041,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
                  "signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
     incl(s.flags, sfUsed)
   of "=":
+    if s.magic == mAsgn: return
     incl(s.flags, sfUsed)
     let t = s.typ
     if t.len == 3 and t.sons[0] == nil and t.sons[1].kind == tyVar:
@@ -1131,6 +1140,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
         # semParamList(c, n.sons[ParamsPos], nil, s)
   else:
     s.typ = newProcType(c, n.info)
+  if tfTriggersCompileTime in s.typ.flags: incl(s.flags, sfCompileTime)
   if n.sons[patternPos].kind != nkEmpty:
     n.sons[patternPos] = semPattern(c, n.sons[patternPos])
   if s.kind in skIterators:
@@ -1425,7 +1435,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
             localError(result.info, "type class predicate failed")
         of tyUnknown: continue
         else: discard
-      if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
+      if n.sons[i].typ == enforceVoidContext: #or usesResult(n.sons[i]):
         voidContext = true
         n.typ = enforceVoidContext
       if i == last and (length == 1 or efWantValue in flags):
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 4d1eae48f..2dda8276d 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -110,6 +110,13 @@ type
     toBind, toMixin, toInject: IntSet
     owner: PSym
     cursorInBody: bool # only for nimsuggest
+    bracketExpr: PNode
+
+template withBracketExpr(ctx, x, body: untyped) =
+  let old = ctx.bracketExpr
+  ctx.bracketExpr = x
+  body
+  ctx.bracketExpr = old
 
 proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
   case n.kind
@@ -281,6 +288,47 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
   for i in 0.. < n.len:
     result.sons[i] = semTemplBody(c, n.sons[i])
 
+proc wrapInBind(c: var TemplCtx; n: PNode; opr: string): PNode =
+  let ident = getIdent(opr)
+  if ident.id in c.toInject: return n
+
+  let s = searchInScopes(c.c, ident)
+  if s != nil:
+    var callee: PNode
+    if contains(c.toBind, s.id):
+      callee = symChoice(c.c, n, s, scClosed)
+    elif contains(c.toMixin, s.name.id):
+      callee = symChoice(c.c, n, s, scForceOpen)
+    elif s.owner == c.owner and sfGenSym in s.flags:
+      # template tmp[T](x: var seq[T]) =
+      # var yz: T
+      incl(s.flags, sfUsed)
+      callee = newSymNode(s, n.info)
+      styleCheckUse(n.info, s)
+    else:
+      callee = semTemplSymbol(c.c, n, s)
+
+    let call = newNodeI(nkCall, n.info)
+    call.add(callee)
+    for i in 0 .. n.len-1: call.add(n[i])
+    result = newNodeI(nkBind, n.info, 2)
+    result.sons[0] = n
+    result.sons[1] = call
+  else:
+    result = n
+
+proc oprIsRoof(n: PNode): bool =
+  const roof = "^"
+  case n.kind
+  of nkIdent: result = n.ident.s == roof
+  of nkSym: result = n.sym.name.s == roof
+  of nkAccQuoted:
+    if n.len == 1:
+      result = oprIsRoof(n.sons[0])
+  of nkOpenSymChoice, nkClosedSymChoice:
+    result = oprIsRoof(n.sons[0])
+  else: discard
+
 proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   result = n
   semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
@@ -423,24 +471,64 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
     result.sons[1] = semTemplBody(c, n.sons[1])
   of nkPragma:
     result = onlyReplaceParams(c, n)
-  else:
+  of nkBracketExpr:
+    result = newNodeI(nkCall, n.info)
+    result.add newIdentNode(getIdent("[]"), n.info)
+    for i in 0 ..< n.len: result.add(n[i])
+    let n0 = semTemplBody(c, n.sons[0])
+    withBracketExpr c, n0:
+      result = semTemplBodySons(c, result)
+  of nkCurlyExpr:
+    result = newNodeI(nkCall, n.info)
+    result.add newIdentNode(getIdent("{}"), n.info)
+    for i in 0 ..< n.len: result.add(n[i])
+    result = semTemplBodySons(c, result)
+  of nkAsgn, nkFastAsgn:
+    checkSonsLen(n, 2)
+    let a = n.sons[0]
+    let b = n.sons[1]
+
+    let k = a.kind
+    case k
+    of nkBracketExpr:
+      result = newNodeI(nkCall, n.info)
+      result.add newIdentNode(getIdent("[]="), n.info)
+      for i in 0 ..< a.len: result.add(a[i])
+      result.add(b)
+      let a0 = semTemplBody(c, a.sons[0])
+      withBracketExpr c, a0:
+        result = semTemplBodySons(c, result)
+    of nkCurlyExpr:
+      result = newNodeI(nkCall, n.info)
+      result.add newIdentNode(getIdent("{}="), n.info)
+      for i in 0 ..< a.len: result.add(a[i])
+      result.add(b)
+      result = semTemplBodySons(c, result)
+    else:
+      result = semTemplBodySons(c, n)
+  of nkCallKinds-{nkPostfix}:
+    result = semTemplBodySons(c, n)
+    if c.bracketExpr != nil and n.len == 2 and oprIsRoof(n.sons[0]):
+      result.add c.bracketExpr
+  of nkDotExpr, nkAccQuoted:
     # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
     # so we use the generic code for nkDotExpr too
-    if n.kind == nkDotExpr or n.kind == nkAccQuoted:
-      let s = qualifiedLookUp(c.c, n, {})
-      if s != nil:
-        # do not symchoice a quoted template parameter (bug #2390):
-        if s.owner == c.owner and s.kind == skParam and
-            n.kind == nkAccQuoted and n.len == 1:
-          incl(s.flags, sfUsed)
-          styleCheckUse(n.info, s)
-          return newSymNode(s, n.info)
-        elif contains(c.toBind, s.id):
-          return symChoice(c.c, n, s, scClosed)
-        elif contains(c.toMixin, s.name.id):
-          return symChoice(c.c, n, s, scForceOpen)
-        else:
-          return symChoice(c.c, n, s, scOpen)
+    let s = qualifiedLookUp(c.c, n, {})
+    if s != nil:
+      # do not symchoice a quoted template parameter (bug #2390):
+      if s.owner == c.owner and s.kind == skParam and
+          n.kind == nkAccQuoted and n.len == 1:
+        incl(s.flags, sfUsed)
+        styleCheckUse(n.info, s)
+        return newSymNode(s, n.info)
+      elif contains(c.toBind, s.id):
+        return symChoice(c.c, n, s, scClosed)
+      elif contains(c.toMixin, s.name.id):
+        return symChoice(c.c, n, s, scForceOpen)
+      else:
+        return symChoice(c.c, n, s, scOpen)
+    result = semTemplBodySons(c, n)
+  else:
     result = semTemplBodySons(c, n)
 
 proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
@@ -471,27 +559,6 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
     for i in countup(0, sonsLen(n) - 1):
       result.sons[i] = semTemplBodyDirty(c, n.sons[i])
 
-proc transformToExpr(n: PNode): PNode =
-  var realStmt: int
-  result = n
-  case n.kind
-  of nkStmtList:
-    realStmt = - 1
-    for i in countup(0, sonsLen(n) - 1):
-      case n.sons[i].kind
-      of nkCommentStmt, nkEmpty, nkNilLit:
-        discard
-      else:
-        if realStmt == - 1: realStmt = i
-        else: realStmt = - 2
-    if realStmt >= 0: result = transformToExpr(n.sons[realStmt])
-    else: n.kind = nkStmtListExpr
-  of nkBlockStmt:
-    n.kind = nkBlockExpr
-    #nkIfStmt: n.kind = nkIfExpr // this is not correct!
-  else:
-    discard
-
 proc semTemplateDef(c: PContext, n: PNode): PNode =
   var s: PSym
   if isTopLevel(c):
@@ -549,9 +616,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
     n.sons[bodyPos] = semTemplBodyDirty(ctx, n.sons[bodyPos])
   else:
     n.sons[bodyPos] = semTemplBody(ctx, n.sons[bodyPos])
-  if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:
-    n.sons[bodyPos] = transformToExpr(n.sons[bodyPos])
-    # only parameters are resolved, no type checking is performed
+  # only parameters are resolved, no type checking is performed
   semIdeForTemplateOrGeneric(c, n.sons[bodyPos], ctx.cursorInBody)
   closeScope(c)
   popOwner()
@@ -604,6 +669,11 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
       localError(n.info, errInvalidExpression)
       result = n
 
+  proc stupidStmtListExpr(n: PNode): bool =
+    for i in 0 .. n.len-2:
+      if n[i].kind notin {nkEmpty, nkCommentStmt}: return false
+    result = true
+
   result = n
   case n.kind
   of nkIdent:
@@ -629,6 +699,12 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
         localError(n.info, errInvalidExpression)
     else:
       localError(n.info, errInvalidExpression)
+  of nkStmtList, nkStmtListExpr:
+    if stupidStmtListExpr(n):
+      result = semPatternBody(c, n.lastSon)
+    else:
+      for i in countup(0, sonsLen(n) - 1):
+        result.sons[i] = semPatternBody(c, n.sons[i])
   of nkCallKinds:
     let s = qualifiedLookUp(c.c, n.sons[0], {})
     if s != nil:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 5ae3d16c0..65cb9421b 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -718,12 +718,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   if paramType == nil: return # (e.g. proc return type)
 
   proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
-    let finalTypId = if typId != nil: typId
-                     else: getIdent(paramName & ":type")
     if genericParams == nil:
       # This happens with anonymous proc types appearing in signatures
       # XXX: we need to lift these earlier
       return
+    let finalTypId = if typId != nil: typId
+                     else: getIdent(paramName & ":type")
     # is this a bindOnce type class already present in the param list?
     for i in countup(0, genericParams.len - 1):
       if genericParams.sons[i].sym.name.id == finalTypId.id:
@@ -757,7 +757,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
 
   case paramType.kind:
   of tyAnything:
-    result = addImplicitGeneric(newTypeS(tyGenericParam, c))
+    result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
 
   of tyStatic:
     # proc(a: expr{string}, b: expr{nkLambda})
@@ -868,6 +868,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   of tyExpr:
     if procKind notin {skMacro, skTemplate}:
       result = addImplicitGeneric(newTypeS(tyAnything, c))
+      #result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
 
   of tyGenericParam:
     markUsed(info, paramType.sym)
@@ -970,18 +971,26 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
   elif kind == skIterator:
     # XXX This is special magic we should likely get rid of
     r = newTypeS(tyExpr, c)
+    message(n.info, warnDeprecated, "implicit return type for 'iterator'")
 
   if r != nil:
     # turn explicit 'void' return type into 'nil' because the rest of the
     # compiler only checks for 'nil':
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
       # 'auto' as a return type does not imply a generic:
-      if r.kind != tyExpr:
+      if r.kind == tyAnything:
+        # 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
+        # compiler is hardly aware of 'auto':
+        r = newTypeS(tyExpr, c)
+      elif r.kind != tyExpr:
         if r.sym == nil or sfAnon notin r.sym.flags:
           let lifted = liftParamType(c, kind, genericParams, r, "result",
                                      n.sons[0].info)
-          if lifted != nil: r = lifted
-          r.flags.incl tfRetType
+          if lifted != nil:
+            r = lifted
+            #if r.kind != tyGenericParam:
+            #echo "came here for ", typeToString(r)
+            r.flags.incl tfRetType
         r = skipIntLit(r)
         if kind == skIterator:
           # see tchainediterators
@@ -1148,7 +1157,17 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     else:
       result = semAnonTuple(c, n, prev)
   of nkCallKinds:
-    if isRange(n):
+    let x = n[0]
+    let ident = case x.kind
+                of nkIdent: x.ident
+                of nkSym: x.sym.name
+                of nkClosedSymChoice, nkOpenSymChoice: x[0].sym.name
+                else: nil
+    if ident != nil and ident.s == "[]":
+      let b = newNodeI(nkBracketExpr, n.info)
+      for i in 1..<n.len: b.add(n[i])
+      result = semTypeNode(c, b, prev)
+    elif ident != nil and ident.id == ord(wDotDot):
       result = semRangeAux(c, n, prev)
     elif n[0].kind notin nkIdentKinds:
       result = semTypeExpr(c, n)
@@ -1335,8 +1354,11 @@ proc processMagicType(c: PContext, m: PSym) =
   of mIntSetBaseType: setMagicType(m, tyRange, intSize)
   of mNil: setMagicType(m, tyNil, ptrSize)
   of mExpr:
-    setMagicType(m, tyExpr, 0)
-    if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
+    if m.name.s == "auto":
+      setMagicType(m, tyAnything, 0)
+    else:
+      setMagicType(m, tyExpr, 0)
+      if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
   of mStmt:
     setMagicType(m, tyStmt, 0)
     if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt
@@ -1364,7 +1386,8 @@ proc processMagicType(c: PContext, m: PSym) =
   of mOrdinal:
     setMagicType(m, tyOrdinal, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
-  of mPNimrodNode: discard
+  of mPNimrodNode:
+    incl m.typ.flags, tfTriggersCompileTime
   of mShared:
     setMagicType(m, tyObject, 0)
     m.typ.n = newNodeI(nkRecList, m.info)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 3ac145eb8..f643fb903 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -90,6 +90,7 @@ type
     allowMetaTypes*: bool     # allow types such as seq[Number]
                               # i.e. the result contains unresolved generics
     skipTypedesc*: bool       # wether we should skip typeDescs
+    owner*: PSym              # where this instantiation comes from
     recursionLimit: int
 
 proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType
@@ -208,6 +209,9 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
 
 proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
   if s == nil: return nil
+  # symbol is not our business:
+  if cl.owner != nil and s.owner != cl.owner:
+    return s
   result = PSym(idTableGet(cl.symMap, s))
   if result == nil:
     result = copySym(s, false)
@@ -477,22 +481,33 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
 
       else: discard
 
-proc initTypeVars*(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars =
+proc initTypeVars*(p: PContext, pt: TIdTable, info: TLineInfo;
+                   owner: PSym): TReplTypeVars =
   initIdTable(result.symMap)
   copyIdTable(result.typeMap, pt)
   initIdTable(result.localCache)
   result.info = info
   result.c = p
+  result.owner = owner
 
-proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode): PNode =
-  var cl = initTypeVars(p, pt, n.info)
+proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode;
+                         owner: PSym): PNode =
+  var cl = initTypeVars(p, pt, n.info, owner)
+  pushInfoContext(n.info)
+  result = replaceTypeVarsN(cl, n)
+  popInfoContext()
+
+proc replaceTypesForLambda*(p: PContext, pt: TIdTable, n: PNode;
+                            original, new: PSym): PNode =
+  var cl = initTypeVars(p, pt, n.info, original)
+  idTablePut(cl.symMap, original, new)
   pushInfoContext(n.info)
   result = replaceTypeVarsN(cl, n)
   popInfoContext()
 
 proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
                            t: PType): PType =
-  var cl = initTypeVars(p, pt, info)
+  var cl = initTypeVars(p, pt, info, nil)
   pushInfoContext(info)
   result = replaceTypeVarsT(cl, t)
   popInfoContext()
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 61f1a7444..642f50330 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -511,6 +511,9 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
 proc matchUserTypeClass*(c: PContext, m: var TCandidate,
                          ff, a: PType): TTypeRelation =
   var body = ff.skipTypes({tyUserTypeClassInst})
+  if c.inTypeClass > 20:
+    localError(body.n[3].info, $body.n[3] & " too nested for type matching")
+    return isNone
 
   openScope(c)
   inc c.inTypeClass
@@ -590,7 +593,7 @@ proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode =
   # 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)
+  let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil)
   result = c.c.semExpr(c.c, instantiated)
 
 proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
@@ -1691,6 +1694,10 @@ proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
   matchesAux(c, n, nOrig, m, marker)
 
 proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
+  if m.calleeSym != nil and m.calleeSym.magic in {mArrGet, mArrPut}:
+    m.state = csMatch
+    m.call = n
+    return
   var marker = initIntSet()
   matchesAux(c, n, nOrig, m, marker)
   if m.state == csNoMatch: return
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index c15a56c54..18d723315 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -309,6 +309,10 @@ proc suggestSym*(info: TLineInfo; s: PSym) {.inline.} =
     findUsages(info, s)
   elif gIdeCmd == ideDef:
     findDefinition(info, s)
+  elif gIdeCmd == ideDus and s != nil:
+    if isTracked(info, s.name.s.len):
+      suggestResult(symToSuggest(s, isLocal=false, $ideDef))
+    findUsages(info, s)
 
 proc markUsed(info: TLineInfo; s: PSym) =
   incl(s.flags, sfUsed)
@@ -335,8 +339,8 @@ proc suggestExpr*(c: PContext, node: PNode) =
     if cp == cpNone: return
   var outputs = 0
   # This keeps semExpr() from coming here recursively:
-  if c.inCompilesContext > 0: return
-  inc(c.inCompilesContext)
+  if c.compilesContextId > 0: return
+  inc(c.compilesContextId)
 
   if gIdeCmd == ideSug:
     var n = if nfIsCursor in node.flags: node else: findClosestDot(node)
@@ -365,8 +369,8 @@ proc suggestExpr*(c: PContext, node: PNode) =
         addSon(a, x)
       suggestCall(c, a, n, outputs)
 
-  dec(c.inCompilesContext)
-  if outputs > 0 and gIdeCmd != ideUse: suggestQuit()
+  dec(c.compilesContextId)
+  if outputs > 0 and gIdeCmd notin {ideUse, ideDus}: suggestQuit()
 
 proc suggestStmt*(c: PContext, n: PNode) =
   suggestExpr(c, n)
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index 91cfdbefd..021910544 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -92,10 +92,15 @@ proc parsePipe(filename: string, inputStream: PLLStream): PNode =
     var line = newStringOfCap(80)
     discard llStreamReadLine(s, line)
     var i = utf8Bom(line)
+    var linenumber = 1
     if containsShebang(line, i):
       discard llStreamReadLine(s, line)
       i = 0
-    if line[i] == '#' and line[i+1] == '!':
+      inc linenumber
+    if line[i] == '#' and line[i+1] in {'?', '!'}:
+      if line[i+1] == '!':
+        message(newLineInfo(filename, linenumber, 1),
+                warnDeprecated, "use '#?' instead; '#!'")
       inc(i, 2)
       while line[i] in Whitespace: inc(i)
       var q: TParser
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 4ca40ab74..0ea9f7d80 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -139,23 +139,26 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
     if it.kind == nkCommentStmt:
       result[i] = PTransNode(it)
     elif it.kind == nkIdentDefs:
-      if it.sons[0].kind != nkSym: internalError(it.info, "transformVarSection")
-      internalAssert(it.len == 3)
-      var newVar = copySym(it.sons[0].sym)
-      incl(newVar.flags, sfFromGeneric)
-      # fixes a strange bug for rodgen:
-      #include(it.sons[0].sym.flags, sfFromGeneric);
-      newVar.owner = getCurrOwner(c)
-      idNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
-      var defs = newTransNode(nkIdentDefs, it.info, 3)
-      if importantComments():
-        # keep documentation information:
-        PNode(defs).comment = it.comment
-      defs[0] = newSymNode(newVar).PTransNode
-      defs[1] = it.sons[1].PTransNode
-      defs[2] = transform(c, it.sons[2])
-      newVar.ast = defs[2].PNode
-      result[i] = defs
+      if it.sons[0].kind == nkSym:
+        internalAssert(it.len == 3)
+        var newVar = copySym(it.sons[0].sym)
+        incl(newVar.flags, sfFromGeneric)
+        # fixes a strange bug for rodgen:
+        #include(it.sons[0].sym.flags, sfFromGeneric);
+        newVar.owner = getCurrOwner(c)
+        idNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
+        var defs = newTransNode(nkIdentDefs, it.info, 3)
+        if importantComments():
+          # keep documentation information:
+          PNode(defs).comment = it.comment
+        defs[0] = newSymNode(newVar).PTransNode
+        defs[1] = it.sons[1].PTransNode
+        defs[2] = transform(c, it.sons[2])
+        newVar.ast = defs[2].PNode
+        result[i] = defs
+      else:
+        # has been transformed into 'param.x' for closure iterators, so keep it:
+        result[i] = PTransNode(it)
     else:
       if it.kind != nkVarTuple:
         internalError(it.info, "transformVarSection: not nkVarTuple")
diff --git a/compiler/types.nim b/compiler/types.nim
index 5f3a74aca..66fb657fc 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1265,13 +1265,16 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
       else: result = 8
     a = result
   of tySet:
-    length = lengthOrd(typ.sons[0])
-    if length <= 8: result = 1
-    elif length <= 16: result = 2
-    elif length <= 32: result = 4
-    elif length <= 64: result = 8
-    elif align(length, 8) mod 8 == 0: result = align(length, 8) div 8
-    else: result = align(length, 8) div 8 + 1
+    if typ.sons[0].kind == tyGenericParam:
+      result = szUnknownSize
+    else:
+      length = lengthOrd(typ.sons[0])
+      if length <= 8: result = 1
+      elif length <= 16: result = 2
+      elif length <= 32: result = 4
+      elif length <= 64: result = 8
+      elif align(length, 8) mod 8 == 0: result = align(length, 8) div 8
+      else: result = align(length, 8) div 8 + 1
     a = result
   of tyRange:
     result = computeSizeAux(typ.sons[0], a)
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 05d00c19f..ded66d3d0 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -311,7 +311,7 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
           if f.position == x:
             dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
             return
-        internalError("opConv for enum")
+        dest.node.strVal = styp.sym.name.s & " " & $x
     of tyInt..tyInt64:
       dest.node.strVal = $src.intVal
     of tyUInt..tyUInt64:
@@ -320,8 +320,19 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
       dest.node.strVal = if src.intVal == 0: "false" else: "true"
     of tyFloat..tyFloat128:
       dest.node.strVal = $src.floatVal
-    of tyString, tyCString:
+    of tyString:
       dest.node.strVal = src.node.strVal
+    of tyCString:
+      if src.node.kind == nkBracket:
+        # Array of chars
+        var strVal = ""
+        for son in src.node.sons:
+          let c = char(son.intVal)
+          if c == '\0': break
+          strVal.add(c)
+        dest.node.strVal = strVal
+      else:
+        dest.node.strVal = src.node.strVal
     of tyChar:
       dest.node.strVal = $chr(src.intVal)
     else:
@@ -1400,6 +1411,31 @@ proc execute(c: PCtx, start: int): PNode =
   newSeq(tos.slots, c.prc.maxSlots)
   result = rawExecute(c, start, tos).regToNode
 
+proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
+  if sym.kind in routineKinds:
+    if sym.typ.len-1 != args.len:
+      localError(sym.info,
+        "NimScript: expected $# arguments, but got $#" % [
+        $(sym.typ.len-1), $args.len])
+    else:
+      let start = genProc(c, sym)
+
+      var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
+      let maxSlots = sym.offset
+      newSeq(tos.slots, maxSlots)
+
+      # setup parameters:
+      if not isEmptyType(sym.typ.sons[0]) or sym.kind == skMacro:
+        putIntoReg(tos.slots[0], getNullValue(sym.typ.sons[0], sym.info))
+      # XXX We could perform some type checking here.
+      for i in 1.. <sym.typ.len:
+        putIntoReg(tos.slots[i], args[i-1])
+
+      result = rawExecute(c, start, tos).regToNode
+  else:
+    localError(sym.info,
+      "NimScript: attempt to call non-routine: " & sym.name.s)
+
 proc evalStmt*(c: PCtx, n: PNode) =
   let n = transformExpr(c.module, n)
   let start = genStmt(c, n)
@@ -1461,6 +1497,8 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
   let n = transformExpr(module, n)
   setupGlobalCtx(module)
   var c = globalCtx
+  let oldMode = c.mode
+  defer: c.mode = oldMode
   c.mode = mode
   let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
   if c.code[start].opcode == opcEof: return emptyNode
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 32982602b..92db0d513 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -37,7 +37,7 @@ when hasFFI:
   import evalffi
 
 type
-  TGenFlag = enum gfNone, gfAddrOf
+  TGenFlag = enum gfAddrOf, gfFieldAccess
   TGenFlags = set[TGenFlag]
 
 proc debugInfo(info: TLineInfo): string =
@@ -535,7 +535,7 @@ proc genIndex(c: PCtx; n: PNode; arr: PType): TRegister =
 proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
   case le.kind
   of nkBracketExpr:
-    let dest = c.genx(le.sons[0], {gfAddrOf})
+    let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess})
     let idx = c.genIndex(le.sons[1], le.sons[0].typ)
     c.gABC(le, opcWrArr, dest, idx, value)
     c.freeTemp(dest)
@@ -543,7 +543,7 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
   of nkDotExpr, nkCheckedFieldExpr:
     # XXX field checks here
     let left = if le.kind == nkDotExpr: le else: le.sons[0]
-    let dest = c.genx(left.sons[0], {gfAddrOf})
+    let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess})
     let idx = genField(left.sons[1])
     c.gABC(left, opcWrObj, dest, idx, value)
     c.freeTemp(dest)
@@ -1216,7 +1216,7 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
 proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   case le.kind
   of nkBracketExpr:
-    let dest = c.genx(le.sons[0], {gfAddrOf})
+    let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess})
     let idx = c.genIndex(le.sons[1], le.sons[0].typ)
     let tmp = c.genx(ri)
     if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
@@ -1228,7 +1228,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   of nkDotExpr, nkCheckedFieldExpr:
     # XXX field checks here
     let left = if le.kind == nkDotExpr: le else: le.sons[0]
-    let dest = c.genx(left.sons[0], {gfAddrOf})
+    let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess})
     let idx = genField(left.sons[1])
     let tmp = c.genx(ri)
     c.preventFalseAlias(left, opcWrObj, dest, idx, tmp)
@@ -1321,7 +1321,7 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
       c.gABx(n, opcLdGlobal, cc, s.position)
       c.gABC(n, opcNodeToReg, dest, cc)
       c.freeTemp(cc)
-    elif gfAddrOf in flags:
+    elif {gfAddrOf, gfFieldAccess} * flags == {gfAddrOf}:
       c.gABx(n, opcLdGlobalAddr, dest, s.position)
     else:
       c.gABx(n, opcLdGlobal, dest, s.position)
@@ -1377,9 +1377,11 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
   genObjAccess(c, n.sons[0], dest, flags)
 
 proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
-  if n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
-      tyString, tyCString}:
+  let arrayType = n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind
+  if arrayType in {tyString, tyCString}:
     genArrAccess2(c, n, dest, opcLdStrIdx, {})
+  elif arrayType == tyTypeDesc:
+    c.genTypeLit(n.typ, dest)
   else:
     genArrAccess2(c, n, dest, opcLdArr, flags)
 
@@ -1771,6 +1773,9 @@ proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int =
     d = 0
   c.gABC(n, opcEof, d)
 
+  #echo renderTree(n)
+  #c.echoCode(result)
+
 proc genParams(c: PCtx; params: PNode) =
   # res.sym.position is already 0
   c.prc.slots[0] = (inUse: true, kind: slotFixedVar)
diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim
index 5dd27feda..576b0565f 100644
--- a/compiler/vmhooks.nim
+++ b/compiler/vmhooks.nim
@@ -30,6 +30,14 @@ proc setResult*(a: VmArgs; v: string) =
   s[a.ra].node = newNode(nkStrLit)
   s[a.ra].node.strVal = v
 
+proc setResult*(a: VmArgs; n: PNode) =
+  var s: seq[TFullReg]
+  move(s, cast[seq[TFullReg]](a.slots))
+  if s[a.ra].kind != rkNode:
+    myreset(s[a.ra])
+    s[a.ra].kind = rkNode
+  s[a.ra].node = n
+
 proc setResult*(a: VmArgs; v: seq[string]) =
   var s: seq[TFullReg]
   move(s, cast[seq[TFullReg]](a.slots))
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 23f012ea5..0a0534118 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -42,7 +42,7 @@ type
     wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
     wImportCpp, wImportObjC,
     wImportCompilerProc,
-    wImportc, wExportc, wIncompleteStruct, wRequiresInit,
+    wImportc, wExportc, wExportNims, wIncompleteStruct, wRequiresInit,
     wAlign, wNodecl, wPure, wSideeffect, wHeader,
     wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib,
     wCompilerproc, wProcVar, wBase,
@@ -82,6 +82,7 @@ type
     wStdIn, wStdOut, wStdErr,
 
     wInOut, wByCopy, wByRef, wOneWay,
+    wBitsize,
 
   TSpecialWords* = set[TSpecialWord]
 
@@ -125,7 +126,8 @@ const
 
     "immediate", "constructor", "destructor", "delegator", "override",
     "importcpp", "importobjc",
-    "importcompilerproc", "importc", "exportc", "incompletestruct",
+    "importcompilerproc", "importc", "exportc", "exportnims",
+    "incompletestruct",
     "requiresinit", "align", "nodecl", "pure", "sideeffect",
     "header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib",
     "compilerproc", "procvar", "base",
@@ -168,6 +170,7 @@ const
     "stdin", "stdout", "stderr",
 
     "inout", "bycopy", "byref", "oneway",
+    "bitsize",
     ]
 
 proc findStr*(a: openArray[string], s: string): int =
diff --git a/compiler/writetracking.nim b/compiler/writetracking.nim
index 38258b07a..141b496c1 100644
--- a/compiler/writetracking.nim
+++ b/compiler/writetracking.nim
@@ -200,7 +200,7 @@ proc deps(w: var W; n: PNode) =
 
 proc possibleAliases(w: var W; result: var seq[ptr TSym]) =
   # this is an expensive fixpoint iteration. We could speed up this analysis
-  # by a smarter data-structure but we wait until prolifing shows us it's
+  # by a smarter data-structure but we wait until profiling shows us it's
   # expensive. Usually 'w.assignments' is small enough.
   var alreadySeen = initIntSet()
   template addNoDup(x) =
diff --git a/config/nim.cfg b/config/nim.cfg
index 56bfbc64d..b8608b3ce 100644
--- a/config/nim.cfg
+++ b/config/nim.cfg
@@ -27,28 +27,20 @@ mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc"
   cs:partial
 @end
 
-path="$lib/core"
-
-path="$lib/pure"
+path="$lib/deprecated/core"
+path="$lib/deprecated/pure"
 path="$lib/pure/collections"
 path="$lib/pure/concurrency"
 path="$lib/impure"
 path="$lib/wrappers"
-# path="$lib/wrappers/cairo"
-# path="$lib/wrappers/gtk"
-# path="$lib/wrappers/lua"
-# path="$lib/wrappers/opengl"
-path="$lib/wrappers/pcre"
 path="$lib/wrappers/linenoise"
-path="$lib/wrappers/sdl"
-# path="$lib/wrappers/x11"
-path="$lib/wrappers/zip"
-path="$lib/wrappers/libffi"
 path="$lib/windows"
 path="$lib/posix"
 path="$lib/js"
 path="$lib/pure/unidecode"
 path="$lib/arch"
+path="$lib/core"
+path="$lib/pure"
 
 @if nimbabel:
   nimblepath="$home/.nimble/pkgs/"
diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index 4773258cf..23151b275 100644
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -145,7 +145,7 @@ body {
   font-weight: 400;
   font-size: 14px;
   line-height: 20px;
-  color: #2d2d2d;
+  color: #666;
   background-color: rgba(252, 248, 244, 0.75); }
 
 /* Skeleton grid */
diff --git a/doc/filelist.txt b/doc/filelist.txt
index beff8f6c8..71379b40d 100644
--- a/doc/filelist.txt
+++ b/doc/filelist.txt
@@ -4,12 +4,12 @@ Short description of Nim's modules
 ==============  ==========================================================
 Module          Description
 ==============  ==========================================================
-nim          main module: parses the command line and calls
+nim             main module: parses the command line and calls
                 ``main.MainCommand``
 main            implements the top-level command dispatching
 nimconf         implements the config file reader
 syntaxes        dispatcher for the different parsers and filters
-filter_tmpl     standard template filter (``#! stdtempl``)
+filter_tmpl     standard template filter (``#? stdtempl``)
 lexbase         buffer handling of the lexical analyser
 lexer           lexical analyser
 parser          Nim's parser
diff --git a/doc/filters.txt b/doc/filters.txt
index afbd61e3c..46bc6c3e5 100644
--- a/doc/filters.txt
+++ b/doc/filters.txt
@@ -8,9 +8,9 @@ A `Source Code Filter` transforms the input character stream to an in-memory
 output stream before parsing. A filter can be used to provide templating
 systems or preprocessors.
 
-To use a filter for a source file the *shebang* notation is used::
+To use a filter for a source file the ``#?`` notation is used::
 
-  #! stdtmpl(subsChar = '$', metaChar = '#')
+  #? stdtmpl(subsChar = '$', metaChar = '#')
   #proc generateXML(name, age: string): string =
   #  result = ""
   <xml>
@@ -20,7 +20,8 @@ To use a filter for a source file the *shebang* notation is used::
 
 As the example shows, passing arguments to a filter can be done
 just like an ordinary procedure call with named or positional arguments. The
-available parameters depend on the invoked filter.
+available parameters depend on the invoked filter. Before version 0.12.0 of
+the language ``#!`` was used instead of ``#?``.
 
 
 Pipe operator
@@ -28,7 +29,7 @@ Pipe operator
 
 Filters can be combined with the ``|`` pipe operator::
 
-  #! strip(startswith="<") | stdtmpl
+  #? strip(startswith="<") | stdtmpl
   #proc generateXML(name, age: string): string =
   #  result = ""
   <xml>
@@ -104,7 +105,7 @@ Parameters and their defaults:
 
 Example::
 
-  #! stdtmpl | standard
+  #? stdtmpl | standard
   #proc generateHTMLPage(title, currentTab, content: string,
   #                      tabs: openArray[string]): string =
   #  result = ""
@@ -172,7 +173,7 @@ produces ``$``.
 The template engine is quite flexible. It is easy to produce a procedure that
 writes the template code directly to a file::
 
-  #! stdtmpl(emit="f.write") | standard
+  #? stdtmpl(emit="f.write") | standard
   #proc writeHTMLPage(f: File, title, currentTab, content: string,
   #                   tabs: openArray[string]) =
   <head><title>$title</title></head>
diff --git a/doc/lib.txt b/doc/lib.txt
index 6a8f32e07..3dc58eebf 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -122,7 +122,7 @@ String handling
   This module contains various string matchers for email addresses, etc.
 
 * `subexes <subexes.html>`_
-  This module implements advanted string substitution operations.
+  This module implements advanced string substitution operations.
 
 
 Generic Operating System Services
@@ -201,12 +201,6 @@ Internet Protocols and Support
 * `scgi <scgi.html>`_
   This module implements helpers for SCGI applications.
 
-* `sockets <sockets.html>`_
-  This module implements a simple portable type-safe sockets layer.
-
-* `asyncio <asyncio.html>`_
-  This module implements an asynchronous event loop for sockets.
-
 * `browsers <browsers.html>`_
   This module implements procs for opening URLs with the user's default
   browser.
@@ -220,9 +214,6 @@ Internet Protocols and Support
 * `smtp <smtp.html>`_
   This module implement a simple SMTP client.
 
-* `ftpclient <ftpclient.html>`_
-  This module implements an FTP client.
-
 * `cookies <cookies.html>`_
   This module contains helper procs for parsing and generating cookies.
 
@@ -253,7 +244,7 @@ Internet Protocols and Support
   This module implements a high-level sockets API. It will replace the
   ``sockets`` module in the future.
 
-* `rawsockets <rawsockets.html>`_
+* `nativesockets <nativesockets.html>`_
   This module implements a low-level sockets API.
 
 * `selectors <selectors.html>`_
@@ -265,8 +256,6 @@ Parsers
 
 * `parseopt <parseopt.html>`_
   The ``parseopt`` module implements a command line option parser.
-  **Deprecated since version 0.9.3:** Use the `parseopt2
-  <parseopt2.html>`_ module instead.
 
 * `parseopt2 <parseopt2.html>`_
   The ``parseopt2`` module implements a command line option parser. This
@@ -397,6 +386,31 @@ Modules for JS backend
   Declaration of the Document Object Model for the JS backend.
 
 
+Deprecated modules
+------------------
+
+* `asyncio <asyncio.html>`_
+  This module implements an asynchronous event loop for sockets.
+  **Deprecated since version 0.11.2:**
+  Use the `asyncnet <asyncnet.html>`_ together with the
+  `asyncdispatch <asyncdispatch.html>`_ module instead.
+
+* `ftpclient <ftpclient.html>`_
+  This module implements an FTP client.
+  **Deprecated since version 0.11.3:**
+  Use the `asyncftpclient <asyncftpclient.html>`_ module instead.
+
+* `sockets <sockets.html>`_
+  This module implements a simple portable type-safe sockets layer.
+  **Deprecated since version 0.11.2:**
+  Use the `net <net.html>`_ or the `rawsockets <rawsockets.html>`_ module
+  instead.
+
+* `rawsockets <rawsockets.html>`_
+  **Deprecated since version 0.11.4:**
+  This module has been renamed to `nativesockets <nativesockets.html>`_.
+
+
 Impure libraries
 ================
 
diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt
index 8f7dcd580..c6206d030 100644
--- a/doc/manual/generics.txt
+++ b/doc/manual/generics.txt
@@ -116,7 +116,7 @@ type class           matches
 ``array``            any array type
 ``set``              any set type
 ``seq``              any seq type
-``auto``             any type
+``any``              any type
 ==================   ===================================================
 
 Furthermore, every generic type automatically creates a type class of the same
@@ -163,15 +163,6 @@ module to illustrate this:
 Alternatively, the ``distinct`` type modifier can be applied to the type class
 to allow each param matching the type class to bind to a different type.
 
-If a proc param doesn't have a type specified, Nim will use the
-``distinct auto`` type class (also known as ``any``). Note this behavior is
-deprecated for procs; templates, however, support them:
-
-.. code-block:: nim
-  # allow any combination of param types
-  proc concat(a, b): string = $a & $b # deprecated
-  proc concat(a, b: any): string = $a & $b # preferred
-
 Procs written with the implicitly generic style will often need to refer to the
 type parameters of the matched generic type. They can be easily accessed using
 the dot syntax:
diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt
index 8166994a9..f89194c9a 100644
--- a/doc/manual/pragmas.txt
+++ b/doc/manual/pragmas.txt
@@ -72,7 +72,20 @@ compileTime pragma
 ------------------
 The ``compileTime`` pragma is used to mark a proc or variable to be used at
 compile time only. No code will be generated for it. Compile time procs are
-useful as helpers for macros.
+useful as helpers for macros. Since version 0.12.0 of the language, a proc
+that uses ``system.NimNode`` within its parameter types is implictly declared
+``compileTime``:
+
+.. code-block:: nim
+  proc astHelper(n: NimNode): NimNode =
+    result = n
+
+Is the same as:
+
+.. code-block:: nim
+  proc astHelper(n: NimNode): NimNode {.compileTime.} =
+    result = n
+
 
 noReturn pragma
 ---------------
@@ -518,6 +531,24 @@ Implementation Specific Pragmas
 This section describes additional pragmas that the current Nim implementation
 supports but which should not be seen as part of the language specification.
 
+Bitsize pragma
+--------------
+
+The ``bitsize`` pragma is for object field members. It declares the field as
+a bitfield in C/C++.
+
+.. code-block:: Nim
+  type
+    mybitfield = object
+      flag {.bitsize:1.}: cuint
+
+generates:
+
+.. code-block:: C
+  struct mybitfield {
+    unsigned int flag:1;
+  };
+
 
 Volatile pragma
 ---------------
diff --git a/doc/manual/procs.txt b/doc/manual/procs.txt
index 9d00b7e3c..ee74b2ea6 100644
--- a/doc/manual/procs.txt
+++ b/doc/manual/procs.txt
@@ -137,6 +137,14 @@ to supply any type of first argument for procedures:
 Another way to look at the method call syntax is that it provides the missing
 postfix notation.
 
+The method call syntax conflicts with explicit generic instantiations:
+``p[T](x)`` cannot be written as ``x.p[T]`` because ``x.p[T]`` is always
+parsed as ``(x.p)[T]``.
+
+**Future directions**: ``p[.T.]`` might be introduced as an alternative syntax
+to pass explict types to a generic and then ``x.p[.T.]`` can be parsed as
+``x.(p[.T.])``.
+
 See also: `Limitations of the method call syntax`_.
 
 
diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt
index 062c08d7c..a833d7b7d 100644
--- a/doc/manual/stmts.txt
+++ b/doc/manual/stmts.txt
@@ -60,6 +60,24 @@ An empty ``discard`` statement is often used as a null statement:
     else: discard
 
 
+Void context
+------------
+
+In a list of statements every expression except the last one needs to have the
+type ``void``. In addition to this rule an assignment to the builtin ``result``
+symbol also triggers a ``void`` context:
+
+.. code-block:: nim
+  proc invalid*(): string =
+    result = "foo"
+    "invalid"  # Error: value of type 'string' has to be discarded
+
+.. code-block:: nim
+  proc valid*(): string =
+    let x = 317
+    "valid"
+
+
 Var statement
 -------------
 
diff --git a/doc/manual/syntax.txt b/doc/manual/syntax.txt
index 99af15948..c444a3995 100644
--- a/doc/manual/syntax.txt
+++ b/doc/manual/syntax.txt
@@ -68,13 +68,13 @@ Strong spaces
 -------------
 
 The number of spaces preceding a non-keyword operator affects precedence
-if the experimental parser directive ``#!strongSpaces`` is used. Indentation
+if the experimental parser directive ``#?strongSpaces`` is used. Indentation
 is not used to determine the number of spaces. If 2 or more operators have the
 same number of preceding spaces the precedence table applies, so ``1 + 3 * 4``
 is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``:
 
 .. code-block:: nim
-  #! strongSpaces
+  #? strongSpaces
   if foo+4 * 4 == 8  and  b&c | 9  ++
       bar:
     echo ""
@@ -86,7 +86,7 @@ Furthermore whether an operator is used a prefix operator is affected by the
 number of spaces:
 
 .. code-block:: nim
-  #! strongSpaces
+  #? strongSpaces
   echo $foo
   # is parsed as
   echo($foo)
@@ -95,7 +95,7 @@ This also affects whether ``[]``, ``{}``, ``()`` are parsed as constructors
 or as accessors:
 
 .. code-block:: nim
-  #! strongSpaces
+  #? strongSpaces
   echo (1,2)
   # is parsed as
   echo((1,2))
diff --git a/doc/manual/types.txt b/doc/manual/types.txt
index 44a20d093..babf3286f 100644
--- a/doc/manual/types.txt
+++ b/doc/manual/types.txt
@@ -490,6 +490,11 @@ to an open array parameter.
 The openarray type cannot be nested: multidimensional openarrays are not
 supported because this is seldom needed and cannot be done efficiently.
 
+.. code-block:: nim
+  proc testOpenArray(x: openArray[int]) = echo repr(x)
+
+  testOpenArray([1,2,3])  # array[]
+  testOpenArray(@[1,2,3]) # seq[]
 
 Varargs
 -------
@@ -1228,3 +1233,27 @@ However, a ``void`` type cannot be inferred in generic code:
 
 The ``void`` type is only valid for parameters and return types; other symbols
 cannot have the type ``void``.
+
+
+Auto type
+---------
+
+The ``auto`` type can only be used for return types and parameters. For return
+types it causes the compiler to infer the type from the routine body:
+
+.. code-block:: nim
+  proc returnsInt(): auto = 1984
+
+For parameters it currently creates implicitly generic routines:
+
+.. code-block:: nim
+  proc foo(a, b: auto) = discard
+
+Is the same as:
+
+.. code-block:: nim
+  proc foo[T1, T2](a: T1, b: T2) = discard
+
+However later versions of the language might change this to mean "infer the
+parameters' types from the body". Then the above ``foo`` would be rejected as
+the parameters' types can not be infered from an empty ``discard`` statement.
diff --git a/doc/nims.txt b/doc/nims.txt
index 2b9df4a87..7c76efe42 100644
--- a/doc/nims.txt
+++ b/doc/nims.txt
@@ -9,7 +9,8 @@ system.
 
 So instead of a ``myproject.nim.cfg`` configuration file, you can use
 a ``myproject.nims`` file that simply contains Nim code controlling the
-compilation process.
+compilation process. For a directory wide configuration, use ``config.nims``
+instead of ``nim.cfg``.
 
 The VM cannot deal with ``importc``, the FFI is not available, so there are not
 many stdlib modules that you can use with Nim's VM. However, at least the
diff --git a/doc/subexes.txt b/doc/subexes.txt
index f43983e09..54304f033 100644
--- a/doc/subexes.txt
+++ b/doc/subexes.txt
@@ -1,7 +1,7 @@
 Substitution Expressions (subex)
 ================================
 
-A *subex* (*Substitution Expression*) represents an advanted string
+A *subex* (*Substitution Expression*) represents an advanced string
 substitution. In contrast to a `regex`:idx: which deals with string analysis, a
 *subex* deals with string synthesis.
 
diff --git a/examples/curlex.nim b/examples/curlex.nim
deleted file mode 100644
index 21786a6ee..000000000
--- a/examples/curlex.nim
+++ /dev/null
@@ -1,10 +0,0 @@
-import
-  libcurl
-
-var hCurl = easy_init()
-if hCurl != nil:
-  discard easy_setopt(hCurl, OPT_VERBOSE, true)
-  discard easy_setopt(hCurl, OPT_URL, "http://nim-lang.org/")
-  discard easy_perform(hCurl)
-  easy_cleanup(hCurl)
-
diff --git a/examples/filterex.nim b/examples/filterex.nim
index d9bfb6782..083945254 100644
--- a/examples/filterex.nim
+++ b/examples/filterex.nim
@@ -1,4 +1,4 @@
-#! stdtmpl | standard
+#? stdtmpl | standard
 #proc generateHTMLPage(title, currentTab, content: string,
 #                      tabs: openArray[string]): string =
 #  result = ""
diff --git a/examples/iupex1.nim b/examples/iupex1.nim
deleted file mode 100644
index f768fb23f..000000000
--- a/examples/iupex1.nim
+++ /dev/null
@@ -1,37 +0,0 @@
-# Example IUP program
-
-# iupTabs: Creates a iupTabs control.
-
-import iup
-
-discard iup.open(nil, nil)
-
-var vbox1 = iup.vbox(iup.label("Inside Tab A"), iup.button("Button A", ""), nil)
-var vbox2 = iup.vbox(iup.label("Inside Tab B"), iup.button("Button B", ""), nil)
-
-iup.setAttribute(vbox1, "TABTITLE", "Tab A")
-iup.setAttribute(vbox2, "TABTITLE", "Tab B")
-
-var tabs1 = iup.tabs(vbox1, vbox2, nil)
-
-vbox1 = iup.vbox(iup.label("Inside Tab C"), iup.button("Button C", ""), nil)
-vbox2 = iup.vbox(iup.label("Inside Tab D"), iup.button("Button D", ""), nil)
-
-iup.setAttribute(vbox1, "TABTITLE", "Tab C")
-iup.setAttribute(vbox2, "TABTITLE", "Tab D")
-
-var tabs2 = iup.tabs(vbox1, vbox2, nil)
-iup.setAttribute(tabs2, "TABTYPE", "LEFT")
-
-var box = iup.hbox(tabs1, tabs2, nil)
-iup.setAttribute(box, "MARGIN", "10x10")
-iup.setAttribute(box, "GAP", "10")
-
-var dlg = iup.dialog(box)
-iup.setAttribute(dlg, "TITLE", "iupTabs")
-iup.setAttribute(dlg, "SIZE", "200x100")
-
-discard showXY(dlg, IUP_CENTER, IUP_CENTER)
-discard mainLoop()
-close()
-
diff --git a/install.sh.template b/install.sh.template
deleted file mode 100644
index 1292abdab..000000000
--- a/install.sh.template
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-set -e
-set -x
-
-if [ "$1" != "" ]; then
-	exec ./koch install "$1"
-else
-	exec ./koch install
-fi
diff --git a/install.txt b/install.txt
index ef367639c..55e8d8ce5 100644
--- a/install.txt
+++ b/install.txt
@@ -62,7 +62,7 @@ Currently, the following C compilers are supported under Windows:
 
 However, most testing is done with GCC.
 
-Bootstrapping from Github
+Bootstrapping from GitHub
 -------------------------
 
 Take a look at the readme file on github `here <https://github.com/nim-lang/Nim#readme>`_
diff --git a/koch.nim b/koch.nim
index 8992271bf..3d1a22b9c 100644
--- a/koch.nim
+++ b/koch.nim
@@ -41,6 +41,7 @@ Options:
 Possible Commands:
   boot [options]           bootstraps with given command line options
   install [bindir]         installs to given directory; Unix only!
+  geninstall               generate ./install.sh; Unix only!
   clean                    cleans Nim project; removes generated files
   web [options]            generates the website and the full documentation
   website [options]        generates only the website
@@ -127,9 +128,12 @@ proc nsis(args: string) =
   exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" &
         " nsis compiler/installer.ini") % [VersionAsString, $(sizeof(pointer)*8)])
 
+proc geninstall(args="") =
+  exec("$# cc -r $# --var:version=$# --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini $#" %
+       [findNim(), compileNimInst, VersionAsString, args])
+
 proc install(args: string) =
-  exec("$# cc -r $# --var:version=$# --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" %
-       [findNim(), compileNimInst, VersionAsString])
+  geninstall()
   exec("sh ./install.sh $#" % args)
 
 proc web(args: string) =
@@ -373,6 +377,7 @@ of cmdArgument:
   of "zip": zip(op.cmdLineRest)
   of "xz": xz(op.cmdLineRest)
   of "nsis": nsis(op.cmdLineRest)
+  of "geninstall": geninstall(op.cmdLineRest)
   of "install": install(op.cmdLineRest)
   of "test", "tests": tests(op.cmdLineRest)
   of "update":
diff --git a/lib/core/unsigned.nim b/lib/deprecated/core/unsigned.nim
index 93a29e1c9..93a29e1c9 100644
--- a/lib/core/unsigned.nim
+++ b/lib/deprecated/core/unsigned.nim
diff --git a/lib/pure/actors.nim b/lib/deprecated/pure/actors.nim
index f0791f954..f0791f954 100644
--- a/lib/pure/actors.nim
+++ b/lib/deprecated/pure/actors.nim
diff --git a/lib/pure/actors.nim.cfg b/lib/deprecated/pure/actors.nim.cfg
index c6bb9c545..c6bb9c545 100644
--- a/lib/pure/actors.nim.cfg
+++ b/lib/deprecated/pure/actors.nim.cfg
diff --git a/lib/pure/asyncio.nim b/lib/deprecated/pure/asyncio.nim
index 5fd45b215..5fd45b215 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/deprecated/pure/asyncio.nim
diff --git a/lib/pure/ftpclient.nim b/lib/deprecated/pure/ftpclient.nim
index 778ba6857..1188c0795 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/deprecated/pure/ftpclient.nim
@@ -11,9 +11,14 @@ include "system/inclrtl"
 import sockets, strutils, parseutils, times, os, asyncio
 
 from asyncnet import nil
-from rawsockets import nil
+from nativesockets import nil
 from asyncdispatch import PFuture
-
+## **Note**: This module is deprecated since version 0.11.3.
+## You should use the async version of this module
+## `asyncftpclient <asyncftpclient.html>`_.
+##
+## ----
+##
 ## This module **partially** implements an FTP client as specified
 ## by `RFC 959 <http://tools.ietf.org/html/rfc959>`_.
 ##
@@ -36,6 +41,8 @@ from asyncdispatch import PFuture
 ## **Warning:** The API of this module is unstable, and therefore is subject
 ## to change.
 
+{.deprecated.}
+
 type
   FtpBase*[SockType] = ref FtpBaseObj[SockType]
   FtpBaseObj*[SockType] = object
@@ -48,7 +55,7 @@ type
     user*, pass*: string
     address*: string
     when SockType is asyncnet.AsyncSocket:
-      port*: rawsockets.Port
+      port*: nativesockets.Port
     else:
       port*: Port
 
diff --git a/lib/pure/parseopt.nim b/lib/deprecated/pure/parseopt.nim
index 218f5ab81..218f5ab81 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/deprecated/pure/parseopt.nim
diff --git a/lib/pure/parseurl.nim b/lib/deprecated/pure/parseurl.nim
index 6d58e8a73..6d58e8a73 100644
--- a/lib/pure/parseurl.nim
+++ b/lib/deprecated/pure/parseurl.nim
diff --git a/lib/deprecated/pure/rawsockets.nim b/lib/deprecated/pure/rawsockets.nim
new file mode 100644
index 000000000..ee77b232e
--- /dev/null
+++ b/lib/deprecated/pure/rawsockets.nim
@@ -0,0 +1,14 @@
+import nativesockets
+export nativesockets
+
+{.warning: "rawsockets module is deprecated, use nativesockets instead".}
+
+template newRawSocket*(domain, sockType, protocol: cint): expr =
+  {.warning: "newRawSocket is deprecated, use newNativeSocket instead".}
+  newNativeSocket(domain, sockType, protocol)
+
+template newRawSocket*(domain: Domain = AF_INET,
+                       sockType: SockType = SOCK_STREAM,
+                       protocol: Protocol = IPPROTO_TCP): expr =
+  {.warning: "newRawSocket is deprecated, use newNativeSocket instead".}
+  newNativeSocket(domain, sockType, protocol)
diff --git a/lib/pure/sockets.nim b/lib/deprecated/pure/sockets.nim
index 29f0bf87d..5d6fa0078 100644
--- a/lib/pure/sockets.nim
+++ b/lib/deprecated/pure/sockets.nim
@@ -9,7 +9,7 @@
 
 ## **Warning:** Since version 0.10.2 this module is deprecated.
 ## Use the `net <net.html>`_ or the
-## `rawsockets <rawsockets.html>`_ module instead.
+## `nativesockets <nativesockets.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
@@ -314,10 +314,7 @@ when defined(ssl):
     of protSSLv23:
       newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support.
     of protSSLv2:
-      when not defined(linux) and not defined(OpenBSD):
-        newCTX = SSL_CTX_new(SSLv2_method())
-      else:
-        raiseSslError()
+      raiseSslError("SSLv2 is no longer secure and has been deprecated, use protSSLv3")
     of protSSLv3:
       newCTX = SSL_CTX_new(SSLv3_method())
     of protTLSv1:
diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim
deleted file mode 100644
index 8bd769fd8..000000000
--- a/lib/impure/graphics.nim
+++ /dev/null
@@ -1,577 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf, Dominik Picheta
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements graphical output for Nim; the current
-## implementation uses SDL but the interface is meant to support multiple
-## backends some day. There is no need to init SDL as this module does that
-## implicitly.
-
-import colors, math
-from sdl import PSurface # Bug
-from sdl_ttf import openFont, closeFont
-
-type
-  Rect* = tuple[x, y, width, height: int]
-  Point* = tuple[x, y: int]
-
-  PSurface* = ref Surface ## a surface to draw onto
-  Surface* {.pure, final.} = object
-    w*, h*: Natural
-    s*: sdl.PSurface
-
-  EGraphics* = object of IOError
-
-  Font {.pure, final.} = object
-    f: sdl_ttf.PFont
-    color: sdl.Color
-  PFont* = ref Font ## represents a font
-{.deprecated: [TSurface: Surface, TFont: Font, TRect: Rect, TPoint: Point].}
-
-proc toSdlColor*(c: Color): sdl.Color =
-  ## Convert colors.Color to sdl.Color
-  var x = c.extractRGB
-  result.r = x.r and 0xff
-  result.g = x.g and 0xff
-  result.b = x.b and 0xff
-
-proc createSdlColor*(sur: PSurface, c: Color, alpha: int = 0): int32 =
-  ## Creates a color using ``sdl.MapRGBA``.
-  var x = c.extractRGB
-  return sdl.mapRGBA(sur.s.format, x.r and 0xff, x.g and 0xff,
-                     x.b and 0xff, alpha and 0xff)
-
-proc toSdlRect*(r: Rect): sdl.Rect =
-  ## Convert ``graphics.Rect`` to ``sdl.Rect``.
-  result.x = int16(r.x)
-  result.y = int16(r.y)
-  result.w = uint16(r.width)
-  result.h = uint16(r.height)
-
-proc raiseEGraphics =
-  raise newException(EGraphics, $sdl.getError())
-
-proc surfaceFinalizer(s: PSurface) = sdl.freeSurface(s.s)
-
-proc newSurface*(width, height: int): PSurface =
-  ## creates a new surface.
-  new(result, surfaceFinalizer)
-  result.w = width
-  result.h = height
-  result.s = sdl.createRGBSurface(sdl.SWSURFACE, width, height,
-      32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0)
-  if result.s == nil:
-    raiseEGraphics()
-
-  assert(not sdl.mustLock(result.s))
-
-proc fontFinalizer(f: PFont) = closeFont(f.f)
-
-proc newFont*(name = "VeraMono.ttf", size = 9, color = colBlack): PFont =
-  ## Creates a new font object. Raises ``EIO`` if the font cannot be loaded.
-  new(result, fontFinalizer)
-  result.f = openFont(name, size.cint)
-  if result.f == nil:
-    raise newException(IOError, "Could not open font file: " & name)
-  result.color = toSdlColor(color)
-
-var
-  defaultFont*: PFont ## default font that is used; this needs to initialized
-                      ## by the client!
-
-proc initDefaultFont*(name = "VeraMono.ttf", size = 9, color = colBlack) =
-  ## initializes the `defaultFont` var.
-  defaultFont = newFont(name, size, color)
-
-proc newScreenSurface*(width, height: int): PSurface =
-  ## Creates a new screen surface
-  new(result, surfaceFinalizer)
-  result.w = width
-  result.h = height
-  result.s = sdl.setVideoMode(width, height, 0, 0)
-  if result.s == nil:
-    raiseEGraphics()
-
-proc writeToBMP*(sur: PSurface, filename: string) =
-  ## Saves the contents of the surface `sur` to the file `filename` as a
-  ## BMP file.
-  if sdl.saveBMP(sur.s, filename) != 0:
-    raise newException(IOError, "cannot write: " & filename)
-
-type
-  Pixels = array[0..1000_000-1, int32]
-  PPixels = ptr Pixels
-{.deprecated: [TPixels: Pixels].}
-
-template setPix(video, pitch, x, y, col: expr): stmt =
-  video[y * pitch + x] = int32(col)
-
-template getPix(video, pitch, x, y: expr): expr =
-  colors.Color(video[y * pitch + x])
-
-const
-  ColSize = 4
-
-proc getPixel(sur: PSurface, x, y: Natural): colors.Color {.inline.} =
-  assert x <% sur.w
-  assert y <% sur.h
-  result = getPix(cast[PPixels](sur.s.pixels), sur.s.pitch.int div ColSize,
-                  x, y)
-
-proc setPixel(sur: PSurface, x, y: Natural, col: colors.Color) {.inline.} =
-  assert x <% sur.w
-  assert y <% sur.h
-  var pixs = cast[PPixels](sur.s.pixels)
-  #pixs[y * (sur.s.pitch div colSize) + x] = int(col)
-  setPix(pixs, sur.s.pitch.int div ColSize, x, y, col)
-
-proc `[]`*(sur: PSurface, p: Point): Color =
-  ## get pixel at position `p`. No range checking is done!
-  result = getPixel(sur, p.x, p.y)
-
-proc `[]`*(sur: PSurface, x, y: int): Color =
-  ## get pixel at position ``(x, y)``. No range checking is done!
-  result = getPixel(sur, x, y)
-
-proc `[]=`*(sur: PSurface, p: Point, col: Color) =
-  ## set the pixel at position `p`. No range checking is done!
-  setPixel(sur, p.x, p.y, col)
-
-proc `[]=`*(sur: PSurface, x, y: int, col: Color) =
-  ## set the pixel at position ``(x, y)``. No range checking is done!
-  setPixel(sur, x, y, col)
-
-proc blit*(destSurf: PSurface, destRect: Rect, srcSurf: PSurface,
-           srcRect: Rect) =
-  ## Copies ``srcSurf`` into ``destSurf``
-  var destTRect, srcTRect: sdl.Rect
-
-  destTRect.x = int16(destRect.x)
-  destTRect.y = int16(destRect.y)
-  destTRect.w = uint16(destRect.width)
-  destTRect.h = uint16(destRect.height)
-
-  srcTRect.x = int16(srcRect.x)
-  srcTRect.y = int16(srcRect.y)
-  srcTRect.w = uint16(srcRect.width)
-  srcTRect.h = uint16(srcRect.height)
-
-  if sdl.blitSurface(srcSurf.s, addr(srcTRect), destSurf.s, addr(destTRect)) != 0:
-    raiseEGraphics()
-
-proc textBounds*(text: string, font = defaultFont): tuple[width, height: int] =
-  var w, h: cint
-  if sdl_ttf.sizeUTF8(font.f, text, w, h) < 0: raiseEGraphics()
-  result.width = int(w)
-  result.height = int(h)
-
-proc drawText*(sur: PSurface, p: Point, text: string, font = defaultFont) =
-  ## Draws text with a transparent background, at location ``p`` with the given
-  ## font.
-  var textSur: PSurface # This surface will have the text drawn on it
-  new(textSur, surfaceFinalizer)
-
-  # Render the text
-  textSur.s = sdl_ttf.renderTextBlended(font.f, text, font.color)
-  # Merge the text surface with sur
-  sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
-
-proc drawText*(sur: PSurface, p: Point, text: string,
-               bg: Color, font = defaultFont) =
-  ## Draws text, at location ``p`` with font ``font``. ``bg``
-  ## is the background color.
-  var textSur: PSurface # This surface will have the text drawn on it
-  new(textSur, surfaceFinalizer)
-  textSur.s = sdl_ttf.renderTextShaded(font.f, text, font.color, toSdlColor(bg))
-  # Merge the text surface with sur
-  sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
-
-proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) =
-  ## draws a circle with center `p` and radius `r` with the given color
-  ## onto the surface `sur`.
-  var video = cast[PPixels](sur.s.pixels)
-  var pitch = sur.s.pitch.int div ColSize
-  var a = 1 - r
-  var py = r
-  var px = 0
-  var x = p.x
-  var y = p.y
-  while px <= py + 1:
-    if x+px <% sur.w:
-      if y+py <% sur.h: setPix(video, pitch, x+px, y+py, color)
-      if y-py <% sur.h: setPix(video, pitch, x+px, y-py, color)
-
-    if x-px <% sur.w:
-      if y+py <% sur.h: setPix(video, pitch, x-px, y+py, color)
-      if y-py <% sur.h: setPix(video, pitch, x-px, y-py, color)
-
-    if x+py <% sur.w:
-      if y+px <% sur.h: setPix(video, pitch, x+py, y+px, color)
-      if y-px <% sur.h: setPix(video, pitch, x+py, y-px, color)
-
-    if x-py <% sur.w:
-      if y+px <% sur.h: setPix(video, pitch, x-py, y+px, color)
-      if y-px <% sur.h: setPix(video, pitch, x-py, y-px, color)
-
-    if a < 0:
-      a = a + (2 * px + 3)
-    else:
-      a = a + (2 * (px - py) + 5)
-      py = py - 1
-    px = px + 1
-
-proc `>-<`(val: int, s: PSurface): int {.inline.} =
-  return if val < 0: 0 elif val >= s.w: s.w-1 else: val
-
-proc `>|<`(val: int, s: PSurface): int {.inline.} =
-  return if val < 0: 0 elif val >= s.h: s.h-1 else: val
-
-proc drawLine*(sur: PSurface, p1, p2: Point, color: Color) =
-  ## draws a line between the two points `p1` and `p2` with the given color
-  ## onto the surface `sur`.
-  var stepx, stepy: int = 0
-  var x0 = p1.x >-< sur
-  var x1 = p2.x >-< sur
-  var y0 = p1.y >|< sur
-  var y1 = p2.y >|< sur
-  var dy = y1 - y0
-  var dx = x1 - x0
-  if dy < 0:
-    dy = -dy
-    stepy = -1
-  else:
-    stepy = 1
-  if dx < 0:
-    dx = -dx
-    stepx = -1
-  else:
-    stepx = 1
-  dy = dy * 2
-  dx = dx * 2
-  var video = cast[PPixels](sur.s.pixels)
-  var pitch = sur.s.pitch.int div ColSize
-  setPix(video, pitch, x0, y0, color)
-  if dx > dy:
-    var fraction = dy - (dx div 2)
-    while x0 != x1:
-      if fraction >= 0:
-        y0 = y0 + stepy
-        fraction = fraction - dx
-      x0 = x0 + stepx
-      fraction = fraction + dy
-      setPix(video, pitch, x0, y0, color)
-  else:
-    var fraction = dx - (dy div 2)
-    while y0 != y1:
-      if fraction >= 0:
-        x0 = x0 + stepx
-        fraction = fraction - dy
-      y0 = y0 + stepy
-      fraction = fraction + dx
-      setPix(video, pitch, x0, y0, color)
-
-proc drawHorLine*(sur: PSurface, x, y, w: Natural, color: Color) =
-  ## draws a horizontal line from (x,y) to (x+w-1, y).
-  var video = cast[PPixels](sur.s.pixels)
-  var pitch = sur.s.pitch.int div ColSize
-
-  if y >= 0 and y <= sur.s.h:
-    for i in 0 .. min(sur.s.w-x, w)-1:
-      setPix(video, pitch, x + i, y, color)
-
-proc drawVerLine*(sur: PSurface, x, y, h: Natural, color: Color) =
-  ## draws a vertical line from (x,y) to (x, y+h-1).
-  var video = cast[PPixels](sur.s.pixels)
-  var pitch = sur.s.pitch.int div ColSize
-
-  if x >= 0 and x <= sur.s.w:
-    for i in 0 .. min(sur.s.h-y, h)-1:
-      setPix(video, pitch, x, y + i, color)
-
-proc fillCircle*(s: PSurface, p: Point, r: Natural, color: Color) =
-  ## draws a circle with center `p` and radius `r` with the given color
-  ## onto the surface `sur` and fills it.
-  var a = 1 - r
-  var py: int = r
-  var px = 0
-  var x = p.x
-  var y = p.y
-  while px <= py:
-    # Fill up the middle half of the circle
-    drawVerLine(s, x + px, y, py + 1, color)
-    drawVerLine(s, x + px, y - py, py, color)
-    if px != 0:
-      drawVerLine(s, x - px, y, py + 1, color)
-      drawVerLine(s, x - px, y - py, py, color)
-    if a < 0:
-      a = a + (2 * px + 3)
-    else:
-      a = a + (2 * (px - py) + 5)
-      py = py - 1
-      # Fill up the left/right half of the circle
-      if py >= px:
-        drawVerLine(s, x + py + 1, y, px + 1, color)
-        drawVerLine(s, x + py + 1, y - px, px, color)
-        drawVerLine(s, x - py - 1, y, px + 1, color)
-        drawVerLine(s, x - py - 1, y - px,  px, color)
-    px = px + 1
-
-proc drawRect*(sur: PSurface, r: Rect, color: Color) =
-  ## draws a rectangle.
-  var video = cast[PPixels](sur.s.pixels)
-  var pitch = sur.s.pitch.int div ColSize
-  if (r.x >= 0 and r.x <= sur.s.w) and (r.y >= 0 and r.y <= sur.s.h):
-    var minW = min(sur.s.w - r.x, r.width)
-    var minH = min(sur.s.h - r.y, r.height)
-
-    # Draw Top
-    for i in 0 .. minW - 1:
-      setPix(video, pitch, r.x + i, r.y, color)
-      setPix(video, pitch, r.x + i, r.y + minH - 1, color) # Draw bottom
-
-    # Draw left side
-    for i in 0 .. minH - 1:
-      setPix(video, pitch, r.x, r.y + i, color)
-      setPix(video, pitch, r.x + minW - 1, r.y + i, color) # Draw right side
-
-proc fillRect*(sur: PSurface, r: Rect, col: Color) =
-  ## Fills a rectangle using sdl's ``FillRect`` function.
-  var rect = toSdlRect(r)
-  if sdl.fillRect(sur.s, addr(rect), sur.createSdlColor(col)) == -1:
-    raiseEGraphics()
-
-proc plot4EllipsePoints(sur: PSurface, cx, cy, x, y: Natural, col: Color) =
-  var video = cast[PPixels](sur.s.pixels)
-  var pitch = sur.s.pitch.int div ColSize
-  if cx+x <= sur.s.w-1:
-    if cy+y <= sur.s.h-1: setPix(video, pitch, cx+x, cy+y, col)
-    if cy-y <= sur.s.h-1: setPix(video, pitch, cx+x, cy-y, col)
-  if cx-x <= sur.s.w-1:
-    if cy+y <= sur.s.h-1: setPix(video, pitch, cx-x, cy+y, col)
-    if cy-y <= sur.s.h-1: setPix(video, pitch, cx-x, cy-y, col)
-
-proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural,
-                  col: Color) =
-  ## Draws an ellipse, ``CX`` and ``CY`` specify the center X and Y of the
-  ## ellipse, ``XRadius`` and ``YRadius`` specify half the width and height
-  ## of the ellipse.
-  var
-    x, y: Natural
-    xChange, yChange: int
-    ellipseError: Natural
-    twoASquare, twoBSquare: Natural
-    stoppingX, stoppingY: Natural
-
-  twoASquare = 2 * xRadius * xRadius
-  twoBSquare = 2 * yRadius * yRadius
-  x = xRadius
-  y = 0
-  xChange = yRadius * yRadius * (1 - 2 * xRadius)
-  yChange = xRadius * xRadius
-  ellipseError = 0
-  stoppingX = twoBSquare * xRadius
-  stoppingY = 0
-
-  while stoppingX >=  stoppingY: # 1st set of points, y` > - 1
-    sur.plot4EllipsePoints(cx, cy, x, y, col)
-    inc(y)
-    inc(stoppingY, twoASquare)
-    inc(ellipseError, yChange)
-    inc(yChange, twoASquare)
-    if (2 * ellipseError + xChange) > 0 :
-      dec(x)
-      dec(stoppingX, twoBSquare)
-      inc(ellipseError, xChange)
-      inc(xChange, twoBSquare)
-
-  # 1st point set is done; start the 2nd set of points
-  x = 0
-  y = yRadius
-  xChange = yRadius * yRadius
-  yChange = xRadius * xRadius * (1 - 2 * yRadius)
-  ellipseError = 0
-  stoppingX = 0
-  stoppingY = twoASquare * yRadius
-  while stoppingX <= stoppingY:
-    sur.plot4EllipsePoints(cx, cy, x, y, col)
-    inc(x)
-    inc(stoppingX, twoBSquare)
-    inc(ellipseError, xChange)
-    inc(xChange,twoBSquare)
-    if (2 * ellipseError + yChange) > 0:
-      dec(y)
-      dec(stoppingY, twoASquare)
-      inc(ellipseError, yChange)
-      inc(yChange,twoASquare)
-
-
-proc plotAA(sur: PSurface, x, y: int, c: float, color: Color) =
-  if (x > 0 and x < sur.s.w) and (y > 0 and y < sur.s.h):
-    var video = cast[PPixels](sur.s.pixels)
-    var pitch = sur.s.pitch.int div ColSize
-
-    var pixColor = getPix(video, pitch, x, y)
-
-    setPix(video, pitch, x, y,
-           pixColor.intensity(1.0 - c) + color.intensity(c))
-
-
-template ipart(x: expr): expr = floor(x)
-template cround(x: expr): expr = ipart(x + 0.5)
-template fpart(x: expr): expr = x - ipart(x)
-template rfpart(x: expr): expr = 1.0 - fpart(x)
-
-proc drawLineAA*(sur: PSurface, p1, p2: Point, color: Color) =
-  ## Draws a anti-aliased line from ``p1`` to ``p2``, using Xiaolin Wu's
-  ## line algorithm
-  var (x1, x2, y1, y2) = (p1.x.toFloat(), p2.x.toFloat(),
-                          p1.y.toFloat(), p2.y.toFloat())
-  var dx = x2 - x1
-  var dy = y2 - y1
-
-  var ax = dx
-  if ax < 0'f64:
-    ax = 0'f64 - ax
-  var ay = dy
-  if ay < 0'f64:
-    ay = 0'f64 - ay
-
-  if ax < ay:
-    swap(x1, y1)
-    swap(x2, y2)
-    swap(dx, dy)
-
-  template doPlot(x, y: int, c: float, color: Color): stmt =
-    if ax < ay:
-      sur.plotAA(y, x, c, color)
-    else:
-      sur.plotAA(x, y, c, color)
-
-  if x2 < x1:
-    swap(x1, x2)
-    swap(y1, y2)
-
-  var gradient = dy / dx
-  # handle first endpoint
-  var xend = cround(x1)
-  var yend = y1 + gradient * (xend - x1)
-  var xgap = rfpart(x1 + 0.5)
-  var xpxl1 = int(xend) # this will be used in the main loop
-  var ypxl1 = int(ipart(yend))
-  doPlot(xpxl1, ypxl1, rfpart(yend)*xgap, color)
-  doPlot(xpxl1, ypxl1 + 1, fpart(yend)*xgap, color)
-  var intery = yend + gradient # first y-intersection for the main loop
-
-  # handle second endpoint
-  xend = cround(x2)
-  yend = y2 + gradient * (xend - x2)
-  xgap = fpart(x2 + 0.5)
-  var xpxl2 = int(xend) # this will be used in the main loop
-  var ypxl2 = int(ipart(yend))
-  doPlot(xpxl2, ypxl2, rfpart(yend) * xgap, color)
-  doPlot(xpxl2, ypxl2 + 1, fpart(yend) * xgap, color)
-
-  # main loop
-  var x = xpxl1 + 1
-  while x <= xpxl2-1:
-    doPlot(x, int(ipart(intery)), rfpart(intery), color)
-    doPlot(x, int(ipart(intery)) + 1, fpart(intery), color)
-    intery = intery + gradient
-    inc(x)
-
-proc fillSurface*(sur: PSurface, color: Color) =
-  ## Fills the entire surface with ``color``.
-  if sdl.fillRect(sur.s, nil, sur.createSdlColor(color)) == -1:
-    raiseEGraphics()
-
-template withEvents*(surf: PSurface, event: expr, actions: stmt): stmt {.
-  immediate.} =
-  ## Simple template which creates an event loop. ``Event`` is the name of the
-  ## variable containing the Event object.
-  while true:
-    var event: sdl.Event
-    if sdl.waitEvent(addr(event)) == 1:
-      actions
-
-if sdl.init(sdl.INIT_VIDEO) < 0: raiseEGraphics()
-if sdl_ttf.init() < 0: raiseEGraphics()
-
-when not defined(testing) and isMainModule:
-  var surf = newScreenSurface(800, 600)
-
-  surf.fillSurface(colWhite)
-
-  # Draw the shapes
-  surf.drawLineAA((150, 170), (400, 471), colTan)
-  surf.drawLine((100, 170), (400, 471), colRed)
-
-  surf.drawEllipse(200, 300, 200, 30, colSeaGreen)
-  surf.drawHorLine(1, 300, 400, colViolet)
-  # Check if the ellipse is the size it's suppose to be.
-  surf.drawVerLine(200, 300 - 30 + 1, 60, colViolet) # ^^ | i suppose it is
-
-  surf.drawEllipse(400, 300, 300, 300, colOrange)
-  surf.drawEllipse(5, 5, 5, 5, colGreen)
-
-  surf.drawHorLine(5, 5, 900, colRed)
-  surf.drawVerLine(5, 60, 800, colRed)
-  surf.drawCircle((600, 500), 60, colRed)
-
-  surf.fillRect((50, 50, 100, 100), colFuchsia)
-  surf.fillRect((150, 50, 100, 100), colGreen)
-  surf.drawRect((50, 150, 100, 100), colGreen)
-  surf.drawRect((150, 150, 100, 100), colAqua)
-  surf.drawRect((250, 150, 100, 100), colBlue)
-  surf.drawHorLine(250, 150, 100, colRed)
-
-  surf.drawLineAA((592, 160), (592, 280), colPurple)
-
-  #surf.drawText((300, 300), "TEST", colMidnightBlue)
-  #var textSize = textBounds("TEST")
-  #surf.drawText((300, 300 + textSize.height), $textSize.width & ", " &
-  #  $textSize.height, colDarkGreen)
-
-  var mouseStartX = -1
-  var mouseStartY = -1
-  withEvents(surf, event):
-    var eventp = addr(event)
-    case event.kind:
-    of sdl.QUITEV:
-      break
-    of sdl.KEYDOWN:
-      var evk = sdl.evKeyboard(eventp)
-      if evk.keysym.sym == sdl.K_LEFT:
-        surf.drawHorLine(395, 300, 50, colBlack)
-        echo("Drawing")
-      elif evk.keysym.sym == sdl.K_ESCAPE:
-        break
-      else:
-        echo(evk.keysym.sym)
-    of sdl.MOUSEBUTTONDOWN:
-      var mbd = sdl.evMouseButton(eventp)
-      if mouseStartX == -1 or mouseStartY == -1:
-        mouseStartX = int(mbd.x)
-        mouseStartY = int(mbd.y)
-      else:
-        surf.drawLineAA((mouseStartX, mouseStartY), (int(mbd.x), int(mbd.y)), colPurple)
-        mouseStartX = -1
-        mouseStartY = -1
-
-    of sdl.MOUSEMOTION:
-      var mm = sdl.evMouseMotion(eventp)
-      if mouseStartX != -1 and mouseStartY != -1:
-        surf.drawLineAA((mouseStartX, mouseStartY), (int(mm.x), int(mm.y)), colPurple)
-      #echo(mm.x, " ", mm.y, " ", mm.yrel)
-
-    else:
-      discard "echo(event.kind)"
-
-    sdl.updateRect(surf.s, 0, 0, 800, 600)
-
-  surf.writeToBMP("test.bmp")
-  sdl.quit()
diff --git a/lib/posix/kqueue.nim b/lib/posix/kqueue.nim
new file mode 100644
index 000000000..511ada9ac
--- /dev/null
+++ b/lib/posix/kqueue.nim
@@ -0,0 +1,71 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Adam Strzelecki
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+{.deadCodeElim:on.}
+
+from posix import Timespec
+
+# Filters:
+const
+  EVFILT_READ*     = -1
+  EVFILT_WRITE*    = -2
+  EVFILT_AIO*      = -3
+  EVFILT_VNODE*    = -4
+  EVFILT_PROC*     = -5
+  EVFILT_SIGNAL*   = -6
+  EVFILT_TIMER*    = -7
+  EVFILT_MACHPORT* = -8
+  EVFILT_FS*       = -9
+  EVFILT_USER*     = -10
+  # -11 is unused
+  EVFILT_VM*       = -12
+
+# Actions:
+const
+  EV_ADD*      = 0x0001 ## Add event to queue (implies enable).
+                        ## Re-adding an existing element modifies it.
+  EV_DELETE*   = 0x0002 ## Delete event from queue.
+  EV_ENABLE*   = 0x0004 ## Enable event.
+  EV_DISABLE*  = 0x0008 ## Disable event (not reported).
+
+# Flags:
+const
+  EV_ONESHOT*  = 0x0010 ## Only report one occurrence.
+  EV_CLEAR*    = 0x0020 ## Clear event state after reporting.
+  EV_RECEIPT*  = 0x0040 ## Force EV_ERROR on success, data == 0
+  EV_DISPATCH* = 0x0080 ## Disable event after reporting.
+
+# Return values:
+const
+  EV_EOF*      = 0x8000 ## EOF detected
+  EV_ERROR*    = 0x4000 ## Error, data contains errno
+
+type
+  KEvent* {.importc: "struct kevent",
+            header: "<sys/event.h>", pure, final.} = object
+    ident*: cuint    ## identifier for this event  (uintptr_t)
+    filter*: cshort  ## filter for event
+    flags*: cushort  ## general flags
+    fflags*: cuint   ## filter-specific flags
+    data*: cuint     ## filter-specific data  (intptr_t)
+    #udata*: ptr void ## opaque user data identifier
+
+proc kqueue*(): cint {.importc: "kqueue", header: "<sys/event.h>".}
+  ## Creates new queue and returns its descriptor.
+
+proc kevent*(kqFD: cint,
+             changelist: ptr KEvent, nchanges: cint,
+             eventlist: ptr KEvent, nevents: cint, timeout: ptr Timespec): cint
+     {.importc: "kevent", header: "<sys/event.h>".}
+  ## Manipulates queue for given ``kqFD`` descriptor.
+
+proc EV_SET*(event: ptr KEvent, ident: cuint, filter: cshort, flags: cushort,
+             fflags: cuint, data: cuint, udata: ptr void)
+     {.importc: "EV_SET", header: "<sys/event.h>".}
+  ## Fills event with given data.
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index d264dc02a..5f1dfcfcd 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -1810,7 +1810,7 @@ proc ntohs*(a1: int16): int16 {.importc, header: "<arpa/inet.h>".}
 proc inet_addr*(a1: cstring): InAddrT {.importc, header: "<arpa/inet.h>".}
 proc inet_ntoa*(a1: InAddr): cstring {.importc, header: "<arpa/inet.h>".}
 proc inet_ntop*(a1: cint, a2: pointer, a3: cstring, a4: int32): cstring {.
-  importc, header: "<arpa/inet.h>".}
+  importc:"(char *)$1", header: "<arpa/inet.h>".}
 proc inet_pton*(a1: cint, a2: cstring, a3: pointer): cint {.
   importc, header: "<arpa/inet.h>".}
 
@@ -2316,7 +2316,7 @@ proc timer_settime*(a1: Timer, a2: cint, a3: var Itimerspec,
 proc tzset*() {.importc, header: "<time.h>".}
 
 
-proc wait*(a1: var cint): Pid {.importc, header: "<sys/wait.h>".}
+proc wait*(a1: ptr cint): Pid {.importc, discardable, header: "<sys/wait.h>".}
 proc waitid*(a1: cint, a2: Id, a3: var SigInfo, a4: cint): cint {.
   importc, header: "<sys/wait.h>".}
 proc waitpid*(a1: Pid, a2: var cint, a3: cint): Pid {.
@@ -2381,7 +2381,7 @@ proc sched_setscheduler*(a1: Pid, a2: cint, a3: var Sched_param): cint {.
 proc sched_yield*(): cint {.importc, header: "<sched.h>".}
 
 proc strerror*(errnum: cint): cstring {.importc, header: "<string.h>".}
-proc hstrerror*(herrnum: cint): cstring {.importc, header: "<netdb.h>".}
+proc hstrerror*(herrnum: cint): cstring {.importc:"(char *)$1", header: "<netdb.h>".}
 
 proc FD_CLR*(a1: cint, a2: var TFdSet) {.importc, header: "<sys/select.h>".}
 proc FD_ISSET*(a1: cint | SocketHandle, a2: var TFdSet): cint {.
@@ -2565,7 +2565,7 @@ proc endprotoent*() {.importc, header: "<netdb.h>".}
 proc endservent*() {.importc, header: "<netdb.h>".}
 proc freeaddrinfo*(a1: ptr AddrInfo) {.importc, header: "<netdb.h>".}
 
-proc gai_strerror*(a1: cint): cstring {.importc, header: "<netdb.h>".}
+proc gai_strerror*(a1: cint): cstring {.importc:"(char *)$1", header: "<netdb.h>".}
 
 proc getaddrinfo*(a1, a2: cstring, a3: ptr AddrInfo,
                   a4: var ptr AddrInfo): cint {.importc, header: "<netdb.h>".}
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index f49388b17..cc337452f 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -11,7 +11,7 @@ include "system/inclrtl"
 
 import os, oids, tables, strutils, macros, times
 
-import rawsockets, net
+import nativesockets, net
 
 export Port, SocketFlag
 
@@ -126,6 +126,7 @@ export Port, SocketFlag
 ## * Can't await in a ``except`` body
 ## * Forward declarations for async procs are broken,
 ##   link includes workaround: https://github.com/nim-lang/Nim/issues/3182.
+## * FutureVar[T] needs to be completed manually.
 
 # TODO: Check if yielded future is nil and throw a more meaningful exception
 
@@ -145,10 +146,15 @@ type
   Future*[T] = ref object of FutureBase ## Typed future.
     value: T ## Stored value
 
-{.deprecated: [PFutureBase: FutureBase, PFuture: Future].}
+  FutureVar*[T] = distinct Future[T]
+
+  FutureError* = object of Exception
+    cause*: FutureBase
 
+{.deprecated: [PFutureBase: FutureBase, PFuture: Future].}
 
-var currentID = 0
+when not defined(release):
+  var currentID = 0
 proc newFuture*[T](fromProc: string = "unspecified"): Future[T] =
   ## Creates a new future.
   ##
@@ -162,18 +168,39 @@ proc newFuture*[T](fromProc: string = "unspecified"): Future[T] =
     result.fromProc = fromProc
     currentID.inc()
 
+proc newFutureVar*[T](fromProc = "unspecified"): FutureVar[T] =
+  ## Create a new ``FutureVar``. This Future type is ideally suited for
+  ## situations where you want to avoid unnecessary allocations of Futures.
+  ##
+  ## Specifying ``fromProc``, which is a string specifying the name of the proc
+  ## that this future belongs to, is a good habit as it helps with debugging.
+  result = FutureVar[T](newFuture[T](fromProc))
+
+proc clean*[T](future: FutureVar[T]) =
+  ## Resets the ``finished`` status of ``future``.
+  Future[T](future).finished = false
+  Future[T](future).error = nil
+
 proc checkFinished[T](future: Future[T]) =
+  ## Checks whether `future` is finished. If it is then raises a
+  ## ``FutureError``.
   when not defined(release):
     if future.finished:
-      echo("<-----> ", future.id, " ", future.fromProc)
-      echo(future.stackTrace)
-      echo("-----")
+      var msg = ""
+      msg.add("An attempt was made to complete a Future more than once. ")
+      msg.add("Details:")
+      msg.add("\n  Future ID: " & $future.id)
+      msg.add("\n  Created in proc: " & future.fromProc)
+      msg.add("\n  Stack trace to moment of creation:")
+      msg.add("\n" & indent(future.stackTrace.strip(), 4))
       when T is string:
-        echo("Contents: ", future.value.repr)
-      echo("<----->")
-      echo("Future already finished, cannot finish twice.")
-      echo getStackTrace()
-      assert false
+        msg.add("\n  Contents (string): ")
+        msg.add("\n" & indent(future.value.repr, 4))
+      msg.add("\n  Stack trace to moment of secondary completion:")
+      msg.add("\n" & indent(getStackTrace().strip(), 4))
+      var err = newException(FutureError, msg)
+      err.cause = future
+      raise err
 
 proc complete*[T](future: Future[T], val: T) =
   ## Completes ``future`` with value ``val``.
@@ -194,6 +221,15 @@ proc complete*(future: Future[void]) =
   if future.cb != nil:
     future.cb()
 
+proc complete*[T](future: FutureVar[T]) =
+  ## Completes a ``FutureVar``.
+  template fut: expr = Future[T](future)
+  checkFinished(fut)
+  assert(fut.error == nil)
+  fut.finished = true
+  if fut.cb != nil:
+    fut.cb()
+
 proc fail*[T](future: Future[T], error: ref Exception) =
   ## Completes ``future`` with ``error``.
   #assert(not future.finished, "Future already finished, cannot finish twice.")
@@ -230,15 +266,17 @@ proc `callback=`*[T](future: Future[T],
   ## If future has already completed then ``cb`` will be called immediately.
   future.callback = proc () = cb(future)
 
-proc echoOriginalStackTrace[T](future: Future[T]) =
+proc injectStacktrace[T](future: Future[T]) =
   # TODO: Come up with something better.
   when not defined(release):
-    echo("Original stack trace in ", future.fromProc, ":")
+    var msg = ""
+    msg.add("\n  " & future.fromProc & "'s lead up to read of failed Future:")
+
     if not future.errorStackTrace.isNil and future.errorStackTrace != "":
-      echo(future.errorStackTrace)
+      msg.add("\n" & indent(future.errorStackTrace.strip(), 4))
     else:
-      echo("Empty or nil stack trace.")
-    echo("Continuing...")
+      msg.add("\n    Empty or nil stack trace.")
+    future.error.msg.add(msg)
 
 proc read*[T](future: Future[T]): T =
   ## Retrieves the value of ``future``. Future must be finished otherwise
@@ -247,7 +285,7 @@ proc read*[T](future: Future[T]): T =
   ## If the result of the future is an error then that error will be raised.
   if future.finished:
     if future.error != nil:
-      echoOriginalStackTrace(future)
+      injectStacktrace(future)
       raise future.error
     when T isnot void:
       return future.value
@@ -264,6 +302,13 @@ proc readError*[T](future: Future[T]): ref Exception =
   else:
     raise newException(ValueError, "No error in future.")
 
+proc mget*[T](future: FutureVar[T]): var T =
+  ## Returns a mutable value stored in ``future``.
+  ##
+  ## Unlike ``read``, this function will not raise an exception if the
+  ## Future has not been finished.
+  result = Future[T](future).value
+
 proc finished*[T](future: Future[T]): bool =
   ## Determines whether ``future`` has completed.
   ##
@@ -282,7 +327,7 @@ proc asyncCheck*[T](future: Future[T]) =
   future.callback =
     proc () =
       if future.failed:
-        echoOriginalStackTrace(future)
+        injectStacktrace(future)
         raise future.error
 
 proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
@@ -430,7 +475,7 @@ when defined(windows) or defined(nimdoc):
                       addr bytesRet, nil, nil) == 0
 
   proc initAll() =
-    let dummySock = newRawSocket()
+    let dummySock = newNativeSocket()
     if not initPointer(dummySock, connectExPtr, WSAID_CONNECTEX):
       raiseOSError(osLastError())
     if not initPointer(dummySock, acceptExPtr, WSAID_ACCEPTEX):
@@ -483,7 +528,7 @@ when defined(windows) or defined(nimdoc):
                   RemoteSockaddr, RemoteSockaddrLength)
 
   proc connect*(socket: AsyncFD, address: string, port: Port,
-    domain = rawsockets.AF_INET): Future[void] =
+    domain = nativesockets.AF_INET): Future[void] =
     ## Connects ``socket`` to server at ``address:port``.
     ##
     ## Returns a ``Future`` which will complete when the connection succeeds
@@ -566,7 +611,7 @@ when defined(windows) or defined(nimdoc):
     var retFuture = newFuture[string]("recv")
     var dataBuf: TWSABuf
     dataBuf.buf = cast[cstring](alloc0(size))
-    dataBuf.len = size
+    dataBuf.len = size.ULONG
 
     var bytesReceived: Dword
     var flagsio = flags.toOSFlags().Dword
@@ -661,7 +706,7 @@ when defined(windows) or defined(nimdoc):
     #buf[] = '\0'
     var dataBuf: TWSABuf
     dataBuf.buf = buf
-    dataBuf.len = size
+    dataBuf.len = size.ULONG
 
     var bytesReceived: Dword
     var flagsio = flags.toOSFlags().Dword
@@ -732,7 +777,7 @@ when defined(windows) or defined(nimdoc):
 
     var dataBuf: TWSABuf
     dataBuf.buf = data # since this is not used in a callback, this is fine
-    dataBuf.len = data.len
+    dataBuf.len = data.len.ULONG
 
     var bytesReceived, lowFlags: Dword
     var ol = PCustomOverlapped()
@@ -782,7 +827,7 @@ when defined(windows) or defined(nimdoc):
     verifyPresence(socket)
     var retFuture = newFuture[tuple[address: string, client: AsyncFD]]("acceptAddr")
 
-    var clientSock = newRawSocket()
+    var clientSock = newNativeSocket()
     if clientSock == osInvalidSocket: raiseOSError(osLastError())
 
     const lpOutputLen = 1024
@@ -855,17 +900,17 @@ when defined(windows) or defined(nimdoc):
 
     return retFuture
 
-  proc newAsyncRawSocket*(domain, sockType, protocol: cint): AsyncFD =
+  proc newAsyncNativeSocket*(domain, sockType, protocol: cint): AsyncFD =
     ## Creates a new socket and registers it with the dispatcher implicitly.
-    result = newRawSocket(domain, sockType, protocol).AsyncFD
+    result = newNativeSocket(domain, sockType, protocol).AsyncFD
     result.SocketHandle.setBlocking(false)
     register(result)
 
-  proc newAsyncRawSocket*(domain: Domain = rawsockets.AF_INET,
-               sockType: SockType = SOCK_STREAM,
-               protocol: Protocol = IPPROTO_TCP): AsyncFD =
+  proc newAsyncNativeSocket*(domain: Domain = nativesockets.AF_INET,
+                             sockType: SockType = SOCK_STREAM,
+                             protocol: Protocol = IPPROTO_TCP): AsyncFD =
     ## Creates a new socket and registers it with the dispatcher implicitly.
-    result = newRawSocket(domain, sockType, protocol).AsyncFD
+    result = newNativeSocket(domain, sockType, protocol).AsyncFD
     result.SocketHandle.setBlocking(false)
     register(result)
 
@@ -928,18 +973,18 @@ else:
     var data = PData(fd: fd, readCBs: @[], writeCBs: @[])
     p.selector.register(fd.SocketHandle, {}, data.RootRef)
 
-  proc newAsyncRawSocket*(domain: cint, sockType: cint,
-      protocol: cint): AsyncFD =
-    result = newRawSocket(domain, sockType, protocol).AsyncFD
+  proc newAsyncNativeSocket*(domain: cint, sockType: cint,
+                             protocol: cint): AsyncFD =
+    result = newNativeSocket(domain, sockType, protocol).AsyncFD
     result.SocketHandle.setBlocking(false)
     when defined(macosx):
       result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
     register(result)
 
-  proc newAsyncRawSocket*(domain: Domain = AF_INET,
-               sockType: SockType = SOCK_STREAM,
-               protocol: Protocol = IPPROTO_TCP): AsyncFD =
-    result = newRawSocket(domain, sockType, protocol).AsyncFD
+  proc newAsyncNativeSocket*(domain: Domain = AF_INET,
+                             sockType: SockType = SOCK_STREAM,
+                             protocol: Protocol = IPPROTO_TCP): AsyncFD =
+    result = newNativeSocket(domain, sockType, protocol).AsyncFD
     result.SocketHandle.setBlocking(false)
     when defined(macosx):
       result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
@@ -947,8 +992,8 @@ else:
 
   proc closeSocket*(sock: AsyncFD) =
     let disp = getGlobalDispatcher()
-    sock.SocketHandle.close()
     disp.selector.unregister(sock.SocketHandle)
+    sock.SocketHandle.close()
 
   proc unregister*(fd: AsyncFD) =
     getGlobalDispatcher().selector.unregister(fd.SocketHandle)
@@ -1423,16 +1468,25 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
   hint("Processing " & prc[0].getName & " as an async proc.")
 
   let returnType = prc[3][0]
+  var baseType: NimNode
   # Verify that the return type is a Future[T]
-  if returnType.kind == nnkIdent:
-    error("Expected return type of 'Future' got '" & $returnType & "'")
-  elif returnType.kind == nnkBracketExpr:
-    if $returnType[0] != "Future":
-      error("Expected return type of 'Future' got '" & $returnType[0] & "'")
+  if returnType.kind == nnkBracketExpr:
+    let fut = repr(returnType[0])
+    if fut != "Future":
+      error("Expected return type of 'Future' got '" & fut & "'")
+    baseType = returnType[1]
+  elif returnType.kind in nnkCallKinds and $returnType[0] == "[]":
+    let fut = repr(returnType[1])
+    if fut != "Future":
+      error("Expected return type of 'Future' got '" & fut & "'")
+    baseType = returnType[2]
+  elif returnType.kind == nnkEmpty:
+    baseType = returnType
+  else:
+    error("Expected return type of 'Future' got '" & repr(returnType) & "'")
 
   let subtypeIsVoid = returnType.kind == nnkEmpty or
-        (returnType.kind == nnkBracketExpr and
-         returnType[1].kind == nnkIdent and returnType[1].ident == !"void")
+        (baseType.kind == nnkIdent and returnType[1].ident == !"void")
 
   var outerProcBody = newNimNode(nnkStmtList, prc[6])
 
@@ -1440,7 +1494,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
   var retFutureSym = genSym(nskVar, "retFuture")
   var subRetType =
     if returnType.kind == nnkEmpty: newIdentNode("void")
-    else: returnType[1]
+    else: baseType
   outerProcBody.add(
     newVarStmt(retFutureSym,
       newCall(
@@ -1464,7 +1518,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
       newIdentNode("off")))) # -> {.push warning[resultshadowed]: off.}
 
     procBody.insert(1, newNimNode(nnkVarSection, prc[6]).add(
-      newIdentDefs(newIdentNode("result"), returnType[1]))) # -> var result: T
+      newIdentDefs(newIdentNode("result"), baseType))) # -> var result: T
 
     procBody.insert(2, newNimNode(nnkPragma).add(
       newIdentNode("pop"))) # -> {.pop.})
@@ -1505,8 +1559,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
   result[6] = outerProcBody
 
   #echo(treeRepr(result))
-  if prc[0].getName == "hubConnectionLoop":
-    echo(toStrLit(result))
+  #if prc[0].getName == "hubConnectionLoop":
+  #  echo(toStrLit(result))
 
 macro async*(prc: stmt): stmt {.immediate.} =
   ## Macro which processes async procedures into the appropriate
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
index fe4577ed9..b806f4235 100644
--- a/lib/pure/asyncftpclient.nim
+++ b/lib/pure/asyncftpclient.nim
@@ -6,23 +6,74 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implement an asynchronous FTP client.
+## This module implements an asynchronous FTP client. It allows you to connect
+## to an FTP server and perform operations on it such as for example:
 ##
-## Examples
-## --------
+## * The upload of new files.
+## * The removal of existing files.
+## * Download of files.
+## * Changing of files' permissions.
+## * Navigation through the FTP server's directories.
 ##
-## .. code-block::nim
+## Connecting to an FTP server
+## ------------------------
 ##
-##      var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
-##      proc main(ftp: AsyncFtpClient) {.async.} =
+## In order to begin any sort of transfer of files you must first
+## connect to an FTP server. You can do so with the ``connect`` procedure.
+##
+##   .. code-block::nim
+##      import asyncdispatch, asyncftpclient
+##      proc main() {.async.} =
+##        var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
+##        await ftp.connect()
+##        echo("Connected")
+##      waitFor(main())
+##
+## A new ``main`` async procedure must be declared to allow the use of the
+## ``await`` keyword. The connection will complete asynchronously and the
+## client will be connected after the ``await ftp.connect()`` call.
+##
+## Uploading a new file
+## --------------------
+##
+## After a connection is made you can use the ``store`` procedure to upload
+## a new file to the FTP server. Make sure to check you are in the correct
+## working directory before you do so with the ``pwd`` procedure, you can also
+## instead specify an absolute path.
+##
+##   .. code-block::nim
+##      import asyncdispatch, asyncftpclient
+##      proc main() {.async.} =
+##        var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
 ##        await ftp.connect()
-##        echo await ftp.pwd()
-##        echo await ftp.listDirs()
-##        await ftp.store("payload.jpg", "payload.jpg")
-##        await ftp.retrFile("payload.jpg", "payload2.jpg")
-##        echo("Finished")
+##        let currentDir = await ftp.pwd()
+##        assert currentDir == "/home/user/"
+##        await ftp.store("file.txt", "file.txt")
+##        echo("File finished uploading")
+##      waitFor(main())
 ##
-##      waitFor main(ftp)
+## Checking the progress of a file transfer
+## ----------------------------------------
+##
+## The progress of either a file upload or a file download can be checked
+## by specifying a ``onProgressChanged`` procedure to the ``store`` or
+## ``retrFile`` procedures.
+##
+##   .. code-block::nim
+##      import asyncdispatch, asyncftpclient
+##
+##      proc onProgressChanged(total, progress: BiggestInt,
+##                              speed: float): Future[void] =
+##        echo("Uploaded ", progress, " of ", total, " bytes")
+##        echo("Current speed: ", speed, " kb/s")
+##
+##      proc main() {.async.} =
+##        var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
+##        await ftp.connect()
+##        await ftp.store("file.txt", "/home/user/file.txt", onProgressChanged)
+##        echo("File finished uploading")
+##      waitFor(main())
+
 
 import asyncdispatch, asyncnet, strutils, parseutils, os, times
 
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index f9085e4bf..5d74896bf 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -67,6 +67,12 @@ type
     Http409 = "409 Conflict",
     Http410 = "410 Gone",
     Http411 = "411 Length Required",
+    Http412 = "412 Precondition Failed",
+    Http413 = "413 Request Entity Too Large",
+    Http414 = "414 Request-URI Too Long",
+    Http415 = "415 Unsupported Media Type",
+    Http416 = "416 Requested Range Not Satisfiable",
+    Http417 = "417 Expectation Failed",
     Http418 = "418 I'm a teapot",
     Http500 = "500 Internal Server Error",
     Http501 = "501 Not Implemented",
@@ -151,7 +157,8 @@ proc processClient(client: AsyncSocket, address: string,
   var request: Request
   request.url = initUri()
   request.headers = newStringTable(modeCaseInsensitive)
-  var line = newStringOfCap(80)
+  var lineFut = newFutureVar[string]("asynchttpserver.processClient")
+  lineFut.mget() = newStringOfCap(80)
   var key, value = ""
 
   while not client.isClosed:
@@ -165,14 +172,15 @@ proc processClient(client: AsyncSocket, address: string,
     request.client = client
 
     # First line - GET /path HTTP/1.1
-    line.setLen(0)
-    await client.recvLineInto(addr line) # TODO: Timeouts.
-    if line == "":
+    lineFut.mget().setLen(0)
+    lineFut.clean()
+    await client.recvLineInto(lineFut) # TODO: Timeouts.
+    if lineFut.mget == "":
       client.close()
       return
 
     var i = 0
-    for linePart in line.split(' '):
+    for linePart in lineFut.mget.split(' '):
       case i
       of 0: request.reqMethod.shallowCopy(linePart.normalize)
       of 1: parseUri(linePart, request.url)
@@ -184,20 +192,21 @@ proc processClient(client: AsyncSocket, address: string,
             "Invalid request protocol. Got: " & linePart)
           continue
       else:
-        await request.respond(Http400, "Invalid request. Got: " & line)
+        await request.respond(Http400, "Invalid request. Got: " & lineFut.mget)
         continue
       inc i
 
     # Headers
     while true:
       i = 0
-      line.setLen(0)
-      await client.recvLineInto(addr line)
+      lineFut.mget.setLen(0)
+      lineFut.clean()
+      await client.recvLineInto(lineFut)
 
-      if line == "":
+      if lineFut.mget == "":
         client.close(); return
-      if line == "\c\L": break
-      let (key, value) = parseHeader(line)
+      if lineFut.mget == "\c\L": break
+      let (key, value) = parseHeader(lineFut.mget)
       request.headers[key] = value
 
     if request.reqMethod == "post":
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 9139200f3..6b19a48be 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -56,7 +56,7 @@
 ##
 
 import asyncdispatch
-import rawsockets
+import nativesockets
 import net
 import os
 
@@ -112,8 +112,8 @@ proc newAsyncSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
   ##
   ## This procedure will also create a brand new file descriptor for
   ## this socket.
-  result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol), domain,
-      sockType, protocol, buffered)
+  result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol),
+                          domain, sockType, protocol, buffered)
 
 proc newAsyncSocket*(domain, sockType, protocol: cint,
     buffered = true): AsyncSocket =
@@ -121,8 +121,9 @@ proc newAsyncSocket*(domain, sockType, protocol: cint,
   ##
   ## This procedure will also create a brand new file descriptor for
   ## this socket.
-  result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol),
-      Domain(domain), SockType(sockType), Protocol(protocol), buffered)
+  result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol),
+                          Domain(domain), SockType(sockType),
+                          Protocol(protocol), buffered)
 
 when defined(ssl):
   proc getSslError(handle: SslPtr, err: cint): cint =
@@ -316,7 +317,7 @@ proc accept*(socket: AsyncSocket,
         retFut.complete(future.read.client)
   return retFut
 
-proc recvLineInto*(socket: AsyncSocket, resString: ptr string,
+proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string],
     flags = {SocketFlag.SafeDisconn}) {.async.} =
   ## Reads a line of data from ``socket`` into ``resString``.
   ##
@@ -338,16 +339,23 @@ proc recvLineInto*(socket: AsyncSocket, resString: ptr string,
   ## **Warning**: ``recvLineInto`` currently uses a raw pointer to a string for
   ## performance reasons. This will likely change soon to use FutureVars.
   assert SocketFlag.Peek notin flags ## TODO:
+  assert(not resString.mget.isNil(),
+         "String inside resString future needs to be initialised")
   result = newFuture[void]("asyncnet.recvLineInto")
 
+  # TODO: Make the async transformation check for FutureVar params and complete
+  # them when the result future is completed.
+  # Can we replace the result future with the FutureVar?
+
   template addNLIfEmpty(): stmt =
-    if resString[].len == 0:
-      resString[].add("\c\L")
+    if resString.mget.len == 0:
+      resString.mget.add("\c\L")
 
   if socket.isBuffered:
     if socket.bufLen == 0:
       let res = socket.readIntoBuf(flags)
       if res == 0:
+        resString.complete()
         return
 
     var lastR = false
@@ -355,7 +363,8 @@ proc recvLineInto*(socket: AsyncSocket, resString: ptr string,
       if socket.currPos >= socket.bufLen:
         let res = socket.readIntoBuf(flags)
         if res == 0:
-          resString[].setLen(0)
+          resString.mget.setLen(0)
+          resString.complete()
           return
 
       case socket.buffer[socket.currPos]
@@ -365,13 +374,15 @@ proc recvLineInto*(socket: AsyncSocket, resString: ptr string,
       of '\L':
         addNLIfEmpty()
         socket.currPos.inc()
+        resString.complete()
         return
       else:
         if lastR:
           socket.currPos.inc()
+          resString.complete()
           return
         else:
-          resString[].add socket.buffer[socket.currPos]
+          resString.mget.add socket.buffer[socket.currPos]
       socket.currPos.inc()
   else:
     var c = ""
@@ -379,18 +390,22 @@ proc recvLineInto*(socket: AsyncSocket, resString: ptr string,
       let recvFut = recv(socket, 1, flags)
       c = recvFut.read()
       if c.len == 0:
-        resString[].setLen(0)
+        resString.mget.setLen(0)
+        resString.complete()
         return
       if c == "\r":
         let recvFut = recv(socket, 1, flags) # Skip \L
         c = recvFut.read()
         assert c == "\L"
         addNLIfEmpty()
+        resString.complete()
         return
       elif c == "\L":
         addNLIfEmpty()
+        resString.complete()
         return
-      resString[].add c
+      resString.mget.add c
+  resString.complete()
 
 proc recvLine*(socket: AsyncSocket,
     flags = {SocketFlag.SafeDisconn}): Future[string] {.async.} =
@@ -416,8 +431,11 @@ proc recvLine*(socket: AsyncSocket,
       result.add("\c\L")
   assert SocketFlag.Peek notin flags ## TODO:
 
-  result = ""
-  await socket.recvLineInto(addr result, flags)
+  # TODO: Optimise this
+  var resString = newFutureVar[string]("asyncnet.recvLine")
+  resString.mget() = ""
+  await socket.recvLineInto(resString, flags)
+  result = resString.mget()
 
 proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
   ## Marks ``socket`` as accepting connections.
diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim
index deab39c7c..32d37ce02 100644
--- a/lib/pure/base64.nim
+++ b/lib/pure/base64.nim
@@ -8,6 +8,38 @@
 #
 
 ## This module implements a base64 encoder and decoder.
+##
+## Encoding data
+## -------------
+##
+## In order to encode some text simply call the ``encode`` procedure:
+##
+##   .. code-block::nim
+##      import base64
+##      let encoded = encode("Hello World")
+##      echo(encoded) # SGVsbG8gV29ybGQ=
+##
+## Apart from strings you can also encode lists of integers or characters:
+##
+##   .. code-block::nim
+##      import base64
+##      let encodedInts = encode([1,2,3])
+##      echo(encodedInts) # AQID
+##      let encodedChars = encode(['h','e','y'])
+##      echo(encodedChars) # aGV5
+##
+## The ``encode`` procedure takes an ``openarray`` so both arrays and sequences
+## can be passed as parameters.
+##
+## Decoding data
+## -------------
+##
+## To decode a base64 encoded data string simply call the ``decode``
+## procedure:
+##
+##   .. code-block::nim
+##      import base64
+##      echo(decode("SGVsbG8gV29ybGQ=")) # Hello World
 
 const
   cb64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
@@ -64,11 +96,16 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat
 proc encode*[T:SomeInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string =
   ## encodes `s` into base64 representation. After `lineLen` characters, a
   ## `newline` is added.
+  ##
+  ## This procedure encodes an openarray (array or sequence) of either integers
+  ## or characters.
   encodeInternal(s, lineLen, newLine)
 
 proc encode*(s: string, lineLen = 75, newLine="\13\10"): string =
   ## encodes `s` into base64 representation. After `lineLen` characters, a
   ## `newline` is added.
+  ##
+  ## This procedure encodes a string.
   encodeInternal(s, lineLen, newLine)
 
 proc decodeByte(b: char): int {.inline.} =
diff --git a/lib/pure/basic2d.nim b/lib/pure/basic2d.nim
index ad8f8653d..7d74424fa 100644
--- a/lib/pure/basic2d.nim
+++ b/lib/pure/basic2d.nim
@@ -18,6 +18,8 @@ import strutils
 ##
 ## Quick start example:
 ##
+## .. code-block:: nim
+##
 ##   # Create a matrix which first rotates, then scales and at last translates
 ##
 ##   var m:Matrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0)
@@ -93,11 +95,11 @@ let
   IDMATRIX*:Matrix2d=matrix2d(1.0,0.0,0.0,1.0,0.0,0.0)
     ## Quick access to an identity matrix
   ORIGO*:Point2d=point2d(0.0,0.0)
-    ## Quick acces to point (0,0)
+    ## Quick access to point (0,0)
   XAXIS*:Vector2d=vector2d(1.0,0.0)
-    ## Quick acces to an 2d x-axis unit vector
+    ## Quick access to an 2d x-axis unit vector
   YAXIS*:Vector2d=vector2d(0.0,1.0)
-    ## Quick acces to an 2d y-axis unit vector
+    ## Quick access to an 2d y-axis unit vector
 
 
 # ***************************************
diff --git a/lib/pure/basic3d.nim b/lib/pure/basic3d.nim
index 7fea54d58..424c191f8 100644
--- a/lib/pure/basic3d.nim
+++ b/lib/pure/basic3d.nim
@@ -23,6 +23,8 @@ import times
 ##
 ## Quick start example:
 ##
+## .. code-block:: nim
+##
 ##   # Create a matrix which first rotates, then scales and at last translates
 ##
 ##   var m:Matrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0)
diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim
index 424bcdcca..09b20fd45 100644
--- a/lib/pure/collections/critbits.nim
+++ b/lib/pure/collections/critbits.nim
@@ -123,6 +123,14 @@ proc containsOrIncl*(c: var CritBitTree[void], key: string): bool =
   var n = rawInsert(c, key)
   result = c.count == oldCount
 
+proc inc*(c: var CritBitTree[int]; key: string) =
+  ## counts the 'key'.
+  let oldCount = c.count
+  var n = rawInsert(c, key)
+  if c.count == oldCount:
+    # not a new key:
+    inc n.val
+
 proc incl*(c: var CritBitTree[void], key: string) =
   ## includes `key` in `c`.
   discard rawInsert(c, key)
diff --git a/lib/pure/coro.nim b/lib/pure/coro.nim
index 8fa529474..c5724f26f 100644
--- a/lib/pure/coro.nim
+++ b/lib/pure/coro.nim
@@ -119,7 +119,7 @@ proc wait*(c: proc(), interval=0.01) =
   while alive(c):
     suspend interval
 
-when isMainModule:
+when defined(nimCoroutines) and isMainModule:
   var stackCheckValue = 1100220033
   proc c2()
 
diff --git a/lib/pure/coro.nimcfg b/lib/pure/coro.nimcfg
new file mode 100644
index 000000000..b011bc585
--- /dev/null
+++ b/lib/pure/coro.nimcfg
@@ -0,0 +1 @@
+-d:nimCoroutines
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
index 661afd7b3..4767266e5 100644
--- a/lib/pure/future.nim
+++ b/lib/pure/future.nim
@@ -75,7 +75,7 @@ macro `=>`*(p, b: expr): expr {.immediate.} =
         identDefs.add(newEmptyNode())
       of nnkIdent:
         identDefs.add(c)
-        identDefs.add(newEmptyNode())
+        identDefs.add(newIdentNode("auto"))
         identDefs.add(newEmptyNode())
       of nnkInfix:
         if c[0].kind == nnkIdent and c[0].ident == !"->":
@@ -93,7 +93,7 @@ macro `=>`*(p, b: expr): expr {.immediate.} =
   of nnkIdent:
     var identDefs = newNimNode(nnkIdentDefs)
     identDefs.add(p)
-    identDefs.add(newEmptyNode())
+    identDefs.add(newIdentNode("auto"))
     identDefs.add(newEmptyNode())
     params.add(identDefs)
   of nnkInfix:
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 61c16129b..11af81149 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -8,9 +8,10 @@
 #
 
 ## This module implements efficient computations of hash values for diverse
-## Nim types. All the procs are based on these two building blocks: the `!&
-## proc <#!&>`_ used to start or mix a hash value, and the `!$ proc <#!$>`_
-## used to *finish* the hash value.  If you want to implement hash procs for
+## Nim types. All the procs are based on these two building blocks:
+## - `!& proc <#!&>`_ used to start or mix a hash value, and
+## - `!$ proc <#!$>`_ used to *finish* the hash value.
+## If you want to implement hash procs for
 ## your custom types you will end up writing the following kind of skeleton of
 ## code:
 ##
@@ -108,7 +109,7 @@ proc hash*(x: int): Hash {.inline.} =
   result = x
 
 proc hash*(x: int64): Hash {.inline.} =
-  ## efficient hashing of integers
+  ## efficient hashing of int64 integers
   result = toU32(x)
 
 proc hash*(x: char): Hash {.inline.} =
@@ -126,6 +127,16 @@ proc hash*(x: string): Hash =
     h = h !& ord(x[i])
   result = !$h
 
+proc hash*(sBuf: string, sPos, ePos: int): Hash =
+  ## efficient hashing of a string buffer, from starting
+  ## position `sPos` to ending position `ePos`
+  ##
+  ## ``hash(myStr, 0, myStr.high)`` is equivalent to ``hash(myStr)``
+  var h: Hash = 0
+  for i in sPos..ePos:
+    h = h !& ord(sBuf[i])
+  result = !$h
+
 proc hashIgnoreStyle*(x: string): Hash =
   ## efficient hashing of strings; style is ignored
   var h: Hash = 0
@@ -145,6 +156,27 @@ proc hashIgnoreStyle*(x: string): Hash =
 
   result = !$h
 
+proc hashIgnoreStyle*(sBuf: string, sPos, ePos: int): Hash =
+  ## efficient hashing of a string buffer, from starting
+  ## position `sPos` to ending position `ePos`; style is ignored
+  ##
+  ## ``hashIgnoreStyle(myBuf, 0, myBuf.high)`` is equivalent
+  ## to ``hashIgnoreStyle(myBuf)``
+  var h: Hash = 0
+  var i = sPos
+  while i <= ePos:
+    var c = sBuf[i]
+    if c == '_':
+      inc(i)
+    elif isMagicIdentSeparatorRune(cstring(sBuf), i):
+      inc(i, magicIdentSeparatorRuneByteWidth)
+    else:
+      if c in {'A'..'Z'}:
+        c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
+      h = h !& ord(c)
+      inc(i)
+  result = !$h
+
 proc hashIgnoreCase*(x: string): Hash =
   ## efficient hashing of strings; case is ignored
   var h: Hash = 0
@@ -155,7 +187,22 @@ proc hashIgnoreCase*(x: string): Hash =
     h = h !& ord(c)
   result = !$h
 
+proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
+  ## efficient hashing of a string buffer, from starting
+  ## position `sPos` to ending position `ePos`; case is ignored
+  ##
+  ## ``hashIgnoreCase(myBuf, 0, myBuf.high)`` is equivalent
+  ## to ``hashIgnoreCase(myBuf)``
+  var h: Hash = 0
+  for i in sPos..ePos:
+    var c = sBuf[i]
+    if c in {'A'..'Z'}:
+      c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
+    h = h !& ord(c)
+  result = !$h
+
 proc hash*(x: float): Hash {.inline.} =
+  ## efficient hashing of floats.
   var y = x + 1.0
   result = cast[ptr Hash](addr(y))[]
 
@@ -173,10 +220,29 @@ proc hash*[T: tuple](x: T): Hash =
   result = !$result
 
 proc hash*[A](x: openArray[A]): Hash =
+  ## efficient hashing of arrays and sequences.
   for it in items(x): result = result !& hash(it)
   result = !$result
 
+proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash =
+  ## efficient hashing of portions of arrays and sequences.
+  ##
+  ## ``hash(myBuf, 0, myBuf.high)`` is equivalent to ``hash(myBuf)``
+  for i in sPos..ePos:
+    result = result !& hash(aBuf[i])
+  result = !$result
+
 proc hash*[A](x: set[A]): Hash =
+  ## efficient hashing of sets.
   for it in items(x): result = result !& hash(it)
   result = !$result
 
+when isMainModule:
+  doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) )
+  doAssert( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") )
+  doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
+  let xx = @['H','e','l','l','o']
+  let ss = "Hello"
+  doAssert( hash(xx) == hash(ss) )
+  doAssert( hash(xx) == hash(xx, 0, xx.high) )
+  doAssert( hash(ss) == hash(ss, 0, ss.high) )
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 30b838b7e..a5d4ec1a1 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -81,7 +81,7 @@
 
 import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math
 import asyncnet, asyncdispatch
-import rawsockets
+import nativesockets
 
 type
   Response* = tuple[
@@ -764,10 +764,10 @@ proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} =
     let port =
       if url.port == "":
         if url.scheme.toLower() == "https":
-          rawsockets.Port(443)
+          nativesockets.Port(443)
         else:
-          rawsockets.Port(80)
-      else: rawsockets.Port(url.port.parseInt)
+          nativesockets.Port(80)
+      else: nativesockets.Port(url.port.parseInt)
 
     if url.scheme.toLower() == "https":
       when defined(ssl):
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 540a1a8eb..06d5a13e2 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -622,9 +622,12 @@ proc getNum*(n: JsonNode, default: BiggestInt = 0): BiggestInt =
 proc getFNum*(n: JsonNode, default: float = 0.0): float =
   ## Retrieves the float value of a `JFloat JsonNode`.
   ##
-  ## Returns ``default`` if ``n`` is not a ``JFloat``, or if ``n`` is nil.
-  if n.isNil or n.kind != JFloat: return default
-  else: return n.fnum
+  ## Returns ``default`` if ``n`` is not a ``JFloat`` or ``JInt``, or if ``n`` is nil.
+  if n.isNil: return default
+  case n.kind
+  of JFloat: return n.fnum
+  of JInt: return float(n.num)
+  else: return default
 
 proc getBVal*(n: JsonNode, default: bool = false): bool =
   ## Retrieves the bool value of a `JBool JsonNode`.
@@ -1074,9 +1077,9 @@ when not defined(js):
     ## for nice error messages.
     var p: JsonParser
     p.open(s, filename)
+    defer: p.close()
     discard getTok(p) # read first token
     result = p.parseJson()
-    p.close()
 
   proc parseJson*(buffer: string): JsonNode =
     ## Parses JSON from `buffer`.
@@ -1203,6 +1206,17 @@ when isMainModule:
   testJson{["c", "d"]} = %true
   assert(testJson["c"]["d"].bval)
 
+  # make sure no memory leek when parsing invalid string
+  let startMemory = getOccupiedMem()
+  for i in 0 .. 10000:
+    try:
+      discard parseJson"""{ invalid"""
+    except:
+      discard
+  # memory diff should less than 2M
+  assert(abs(getOccupiedMem() - startMemory) < 2 * 1024 * 1024)
+
+
   # test `$`
   let stringified = $testJson
   let parsedAgain = parseJson(stringified)
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index c1d5c9439..391a880ae 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -21,6 +21,20 @@ include "system/inclrtl"
 {.push debugger:off .} # the user does not want to trace a part
                        # of the standard library!
 
+proc binom*(n, k: int): int {.noSideEffect.} =
+  ## Computes the binomial coefficient
+  if k <= 0: return 1
+  if 2*k > n: return binom(n, n-k)
+  result = n
+  for i in countup(2, k):
+    result = (result * (n + 1 - i)) div i
+
+proc fac*(n: int): int {.noSideEffect.} =
+  ## Computes the faculty/factorial function.
+  result = 1
+  for i in countup(2, n):
+    result = result * i
+
 {.push checks:off, line_dir:off, stack_trace:off.}
 
 when defined(Posix) and not defined(haiku):
@@ -72,21 +86,6 @@ proc classify*(x: float): FloatClass =
   return fcNormal
   # XXX: fcSubnormal is not detected!
 
-
-proc binom*(n, k: int): int {.noSideEffect.} =
-  ## Computes the binomial coefficient
-  if k <= 0: return 1
-  if 2*k > n: return binom(n, n-k)
-  result = n
-  for i in countup(2, k):
-    result = (result * (n + 1 - i)) div i
-
-proc fac*(n: int): int {.noSideEffect.} =
-  ## Computes the faculty/factorial function.
-  result = 1
-  for i in countup(2, n):
-    result = result * i
-
 proc isPowerOfTwo*(x: int): bool {.noSideEffect.} =
   ## Returns true, if `x` is a power of two, false otherwise.
   ## Zero and negative numbers are not a power of two.
@@ -476,7 +475,7 @@ when isMainModule and not defined(JS):
     return sqrt(num)
 
   # check gamma function
-  assert(tgamma(5.0) == 24.0) # 4!
+  assert($tgamma(5.0) == $24.0) # 4!
   assert(lgamma(1.0) == 0.0) # ln(1.0) == 0.0
   assert(erf(6.0) > erf(5.0))
   assert(erfc(6.0) < erfc(5.0))
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 27b989597..b9c574944 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -32,8 +32,9 @@ type
     size*: int       ## size of the memory mapped file
 
     when defined(windows):
-      fHandle: int
-      mapHandle: int
+      fHandle: Handle
+      mapHandle: Handle
+      wasOpened: bool   ## only close if wasOpened
     else:
       handle: cint
 
@@ -115,7 +116,8 @@ proc open*(filename: string, mode: FileMode = fmRead,
     template callCreateFile(winApiProc, filename: expr): expr =
       winApiProc(
         filename,
-        if readonly: GENERIC_READ else: GENERIC_ALL,
+        # GENERIC_ALL != (GENERIC_READ or GENERIC_WRITE)
+        if readonly: GENERIC_READ else: GENERIC_READ or GENERIC_WRITE,
         FILE_SHARE_READ,
         nil,
         if newFileSize != -1: CREATE_ALWAYS else: OPEN_EXISTING,
@@ -172,6 +174,8 @@ proc open*(filename: string, mode: FileMode = fmRead,
       if mappedSize != -1: result.size = min(fileSize, mappedSize).int
       else: result.size = fileSize.int
 
+    result.wasOpened = true
+
   else:
     template fail(errCode: OSErrorCode, msg: expr) =
       rollback()
@@ -226,7 +230,7 @@ proc close*(f: var MemFile) =
   var lastErr: OSErrorCode
 
   when defined(windows):
-    if f.fHandle != INVALID_HANDLE_VALUE:
+    if f.fHandle != INVALID_HANDLE_VALUE and f.wasOpened:
       error = unmapViewOfFile(f.mem) == 0
       lastErr = osLastError()
       error = (closeHandle(f.mapHandle) == 0) or error
@@ -243,6 +247,7 @@ proc close*(f: var MemFile) =
   when defined(windows):
     f.fHandle = 0
     f.mapHandle = 0
+    f.wasOpened = false
   else:
     f.handle = 0
 
diff --git a/lib/pure/rawsockets.nim b/lib/pure/nativesockets.nim
index 7873e7226..c9e067a3e 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/nativesockets.nim
@@ -93,8 +93,8 @@ when useWinVersion:
     IOC_IN* = int(-2147483648)
     FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or
                              (102 shl 8) or 126
-    rawAfInet = winlean.AF_INET
-    rawAfInet6 = winlean.AF_INET6
+    nativeAfInet = winlean.AF_INET
+    nativeAfInet6 = winlean.AF_INET6
 
   proc ioctlsocket*(s: SocketHandle, cmd: clong,
                    argptr: ptr clong): cint {.
@@ -102,8 +102,8 @@ when useWinVersion:
 else:
   let
     osInvalidSocket* = posix.INVALID_SOCKET
-    rawAfInet = posix.AF_INET
-    rawAfInet6 = posix.AF_INET6
+    nativeAfInet = posix.AF_INET
+    nativeAfInet6 = posix.AF_INET6
 
 proc `==`*(a, b: Port): bool {.borrow.}
   ## ``==`` for ports.
@@ -157,12 +157,14 @@ else:
     result = cint(ord(p))
 
 
-proc newRawSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
-             protocol: Protocol = IPPROTO_TCP): SocketHandle =
+proc newNativeSocket*(domain: Domain = AF_INET,
+                      sockType: SockType = SOCK_STREAM,
+                      protocol: Protocol = IPPROTO_TCP): SocketHandle =
   ## Creates a new socket; returns `InvalidSocket` if an error occurs.
   socket(toInt(domain), toInt(sockType), toInt(protocol))
 
-proc newRawSocket*(domain: cint, sockType: cint, protocol: cint): SocketHandle =
+proc newNativeSocket*(domain: cint, sockType: cint,
+                      protocol: cint): SocketHandle =
   ## Creates a new socket; returns `InvalidSocket` if an error occurs.
   ##
   ## Use this overload if one of the enums specified above does
@@ -201,7 +203,9 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
   hints.ai_family = toInt(domain)
   hints.ai_socktype = toInt(sockType)
   hints.ai_protocol = toInt(protocol)
-  hints.ai_flags = AI_V4MAPPED
+  # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092
+  when not defined(freebsd):
+    hints.ai_flags = AI_V4MAPPED
   var gaiResult = getaddrinfo(address, $port, addr(hints), result)
   if gaiResult != 0'i32:
     when useWinVersion:
@@ -229,17 +233,17 @@ proc ntohs*(x: int16): int16 =
   when cpuEndian == bigEndian: result = x
   else: result = (x shr 8'i16) or (x shl 8'i16)
 
-proc htonl*(x: int32): int32 =
+template htonl*(x: int32): expr =
   ## 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)
+  nativesockets.ntohl(x)
 
-proc htons*(x: int16): int16 =
+template htons*(x: int16): expr =
   ## 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)
+  nativesockets.ntohs(x)
 
 proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
   ## Searches the database from the beginning and finds the first entry for
@@ -280,7 +284,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
 
   when useWinVersion:
     var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
-                                  cint(rawsockets.AF_INET))
+                                  cint(AF_INET))
     if s == nil: raiseOSError(osLastError())
   else:
     var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen,
@@ -330,9 +334,9 @@ proc getSockDomain*(socket: SocketHandle): Domain =
   if getsockname(socket, cast[ptr SockAddr](addr(name)),
                  addr(namelen)) == -1'i32:
     raiseOSError(osLastError())
-  if name.sa_family == rawAfInet:
+  if name.sa_family == nativeAfInet:
     result = AF_INET
-  elif name.sa_family == rawAfInet6:
+  elif name.sa_family == nativeAfInet6:
     result = AF_INET6
   else:
     raiseOSError(osLastError(), "unknown socket family in getSockFamily")
@@ -340,12 +344,11 @@ proc getSockDomain*(socket: SocketHandle): Domain =
 
 proc getAddrString*(sockAddr: ptr SockAddr): string =
   ## return the string representation of address within sockAddr
-  if sockAddr.sa_family == rawAfInet:
+  if sockAddr.sa_family == nativeAfInet:
     result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr)
-  elif sockAddr.sa_family == rawAfInet6:
+  elif sockAddr.sa_family == nativeAfInet6:
     when not useWinVersion:
       # TODO: Windows
-      var v6addr = cast[ptr Sockaddr_in6](sockAddr).sin6_addr
       result = newString(posix.INET6_ADDRSTRLEN)
       let addr6 = addr cast[ptr Sockaddr_in6](sockAddr).sin6_addr
       discard posix.inet_ntop(posix.AF_INET6, addr6, result.cstring,
@@ -369,7 +372,79 @@ proc getSockName*(socket: SocketHandle): Port =
   if getsockname(socket, cast[ptr SockAddr](addr(name)),
                  addr(namelen)) == -1'i32:
     raiseOSError(osLastError())
-  result = Port(rawsockets.ntohs(name.sin_port))
+  result = Port(nativesockets.ntohs(name.sin_port))
+
+proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
+  ## returns the socket's local address and port number.
+  ##
+  ## Similar to POSIX's `getsockname`:idx:.
+  case domain
+  of AF_INET:
+    var name: Sockaddr_in
+    when useWinVersion:
+      name.sin_family = int16(ord(AF_INET))
+    else:
+      name.sin_family = posix.AF_INET
+    var namelen = sizeof(name).SockLen
+    if getsockname(socket, cast[ptr SockAddr](addr(name)),
+                   addr(namelen)) == -1'i32:
+      raiseOSError(osLastError())
+    result = ($inet_ntoa(name.sin_addr),
+              Port(nativesockets.ntohs(name.sin_port)))
+  of AF_INET6:
+    var name: Sockaddr_in6
+    when useWinVersion:
+      name.sin6_family = int16(ord(AF_INET6))
+    else:
+      name.sin6_family = posix.AF_INET6
+    var namelen = sizeof(name).SockLen
+    if getsockname(socket, cast[ptr SockAddr](addr(name)),
+                   addr(namelen)) == -1'i32:
+      raiseOSError(osLastError())
+    # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
+    var buf: array[64, char]
+    if inet_ntop(name.sin6_family.cint,
+                 addr name, buf.cstring, sizeof(buf).int32).isNil:
+      raiseOSError(osLastError())
+    result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
+  else:
+    raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
+
+proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
+  ## returns the socket's peer address and port number.
+  ##
+  ## Similar to POSIX's `getpeername`:idx:
+  case domain
+  of AF_INET:
+    var name: Sockaddr_in
+    when useWinVersion:
+      name.sin_family = int16(ord(AF_INET))
+    else:
+      name.sin_family = posix.AF_INET
+    var namelen = sizeof(name).SockLen
+    if getpeername(socket, cast[ptr SockAddr](addr(name)),
+                   addr(namelen)) == -1'i32:
+      raiseOSError(osLastError())
+    result = ($inet_ntoa(name.sin_addr),
+              Port(nativesockets.ntohs(name.sin_port)))
+  of AF_INET6:
+    var name: Sockaddr_in6
+    when useWinVersion:
+      name.sin6_family = int16(ord(AF_INET6))
+    else:
+      name.sin6_family = posix.AF_INET6
+    var namelen = sizeof(name).SockLen
+    if getpeername(socket, cast[ptr SockAddr](addr(name)),
+                   addr(namelen)) == -1'i32:
+      raiseOSError(osLastError())
+    # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
+    var buf: array[64, char]
+    if inet_ntop(name.sin6_family.cint,
+                 addr name, buf.cstring, sizeof(buf).int32).isNil:
+      raiseOSError(osLastError())
+    result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
+  else:
+    raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
 
 proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
   tags: [ReadIOEffect].} =
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 141543c70..d1016011e 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -10,7 +10,7 @@
 ## This module implements a high-level cross-platform sockets interface.
 
 {.deadCodeElim: on.}
-import rawsockets, os, strutils, unsigned, parseutils, times
+import nativesockets, os, strutils, unsigned, parseutils, times
 export Port, `$`, `==`
 
 const useWinVersion = defined(Windows) or defined(nimdoc)
@@ -145,7 +145,7 @@ proc newSocket*(domain, sockType, protocol: cint, buffered = true): Socket =
   ## Creates a new socket.
   ##
   ## If an error occurs EOS will be raised.
-  let fd = newRawSocket(domain, sockType, protocol)
+  let fd = newNativeSocket(domain, sockType, protocol)
   if fd == osInvalidSocket:
     raiseOSError(osLastError())
   result = newSocket(fd, domain.Domain, sockType.SockType, protocol.Protocol,
@@ -156,7 +156,7 @@ proc newSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
   ## Creates a new socket.
   ##
   ## If an error occurs EOS will be raised.
-  let fd = newRawSocket(domain, sockType, protocol)
+  let fd = newNativeSocket(domain, sockType, protocol)
   if fd == osInvalidSocket:
     raiseOSError(osLastError())
   result = newSocket(fd, domain, sockType, protocol, buffered)
@@ -223,10 +223,7 @@ when defined(ssl):
     of protSSLv23:
       newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support.
     of protSSLv2:
-      when not defined(linux):
-        newCTX = SSL_CTX_new(SSLv2_method())
-      else:
-        raiseSslError()
+      raiseSslError("SSLv2 is no longer secure and has been deprecated, use protSSLv3")
     of protSSLv3:
       newCTX = SSL_CTX_new(SSLv3_method())
     of protTLSv1:
@@ -357,7 +354,7 @@ proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
   ## queue of pending connections.
   ##
   ## Raises an EOS error upon failure.
-  if rawsockets.listen(socket.fd, backlog) < 0'i32:
+  if nativesockets.listen(socket.fd, backlog) < 0'i32:
     raiseOSError(osLastError())
 
 proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
@@ -533,6 +530,18 @@ proc getSockOpt*(socket: Socket, opt: SOBool, level = SOL_SOCKET): bool {.
   var res = getSockOptInt(socket.fd, cint(level), toCInt(opt))
   result = res != 0
 
+proc getLocalAddr*(socket: Socket): (string, Port) =
+  ## Get the socket's local address and port number.
+  ##
+  ## This is high-level interface for `getsockname`:idx:.
+  getLocalAddr(socket.fd, socket.domain)
+
+proc getPeerAddr*(socket: Socket): (string, Port) =
+  ## Get the socket's peer address and port number.
+  ##
+  ## This is high-level interface for `getpeername`:idx:.
+  getPeerAddr(socket.fd, socket.domain)
+
 proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {.
   tags: [WriteIOEffect].} =
   ## Sets option ``opt`` to a boolean value specified by ``value``.
diff --git a/lib/pure/options.nim b/lib/pure/options.nim
index ef01e1260..3122d58b1 100644
--- a/lib/pure/options.nim
+++ b/lib/pure/options.nim
@@ -108,6 +108,36 @@ proc get*[T](self: Option[T]): T =
     raise UnpackError(msg : "Can't obtain a value from a `none`")
   self.val
 
+proc get*[T](self: Option[T], otherwise: T): T =
+  ## Returns the contents of this option or `otherwise` if the option is none.
+  if self.isSome:
+    self.val
+  else:
+    otherwise
+
+
+proc map*[T](self: Option[T], callback: proc (input: T)) =
+  ## Applies a callback to the value in this Option
+  if self.has:
+    callback(self.val)
+
+proc map*[T, R](self: Option[T], callback: proc (input: T): R): Option[R] =
+  ## Applies a callback to the value in this Option and returns an option
+  ## containing the new value. If this option is None, None will be returned
+  if self.has:
+    some[R]( callback(self.val) )
+  else:
+    none(R)
+
+proc filter*[T](self: Option[T], callback: proc (input: T): bool): Option[T] =
+  ## Applies a callback to the value in this Option. If the callback returns
+  ## `true`, the option is returned as a Some. If it returns false, it is
+  ## returned as a None.
+  if self.has and not callback(self.val):
+    none(T)
+  else:
+    self
+
 
 proc `==`*(a, b: Option): bool =
   ## Returns ``true`` if both ``Option``s are ``none``,
@@ -115,8 +145,16 @@ proc `==`*(a, b: Option): bool =
   (a.has and b.has and a.val == b.val) or (not a.has and not b.has)
 
 
+proc `$`*[T]( self: Option[T] ): string =
+  ## Returns the contents of this option or `otherwise` if the option is none.
+  if self.has:
+    "Some(" & $self.val & ")"
+  else:
+    "None[" & T.name & "]"
+
+
 when isMainModule:
-  import unittest
+  import unittest, sequtils
 
   suite "optionals":
     # work around a bug in unittest
@@ -158,3 +196,27 @@ when isMainModule:
         check false
       when compiles(none(string) == none(int)):
         check false
+
+    test "get with a default value":
+      check( some("Correct").get("Wrong") == "Correct" )
+      check( stringNone.get("Correct") == "Correct" )
+
+    test "$":
+      check( $(some("Correct")) == "Some(Correct)" )
+      check( $(stringNone) == "None[string]" )
+
+    test "map with a void result":
+      var procRan = 0
+      some(123).map(proc (v: int) = procRan = v)
+      check procRan == 123
+      intNone.map(proc (v: int) = check false)
+
+    test "map":
+      check( some(123).map(proc (v: int): int = v * 2) == some(246) )
+      check( intNone.map(proc (v: int): int = v * 2).isNone )
+
+    test "filter":
+      check( some(123).filter(proc (v: int): bool = v == 123) == some(123) )
+      check( some(456).filter(proc (v: int): bool = v == 123).isNone )
+      check( intNone.filter(proc (v: int): bool = check false).isNone )
+
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index f413371cb..c01228563 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -810,11 +810,12 @@ type
 
 {.deprecated: [TPathComponent: PathComponent].}
 
-iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {.
+iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] {.
   tags: [ReadDirEffect].} =
   ## walks over the directory `dir` and yields for each directory or file in
   ## `dir`. The component type and full path for each item is returned.
-  ## Walking is not recursive.
+  ## Walking is not recursive. If ``relative`` is true the resulting path is
+  ## shortened to be relative to ``dir``.
   ## Example: This directory structure::
   ##   dirA / dirB / fileB1.txt
   ##        / dirC
@@ -843,7 +844,9 @@ iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {.
             k = pcDir
           if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
             k = succ(k)
-          yield (k, dir / extractFilename(getFilename(f)))
+          let xx = if relative: extractFilename(getFilename(f))
+                   else: dir / extractFilename(getFilename(f))
+          yield (k, xx)
         if findNextFile(h, f) == 0'i32: break
       findClose(h)
   else:
@@ -855,7 +858,8 @@ iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {.
         var y = $x.d_name
         if y != "." and y != "..":
           var s: Stat
-          y = dir / y
+          if not relative:
+            y = dir / y
           var k = pcFile
 
           when defined(linux) or defined(macosx) or defined(bsd):
diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim
index 99f6bcd4d..e9f5bee0a 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -10,6 +10,10 @@
 # Included by the ``os`` module but a module in its own right for NimScript
 # support.
 
+when isMainModule:
+  {.pragma: rtl.}
+  import strutils
+
 when defined(nimscript) or (defined(nimdoc) and not declared(os)):
   {.pragma: rtl.}
   {.push hint[ConvFromXtoItselfNotNeeded]:off.}
@@ -22,8 +26,10 @@ when not declared(getEnv) or defined(nimscript):
                                               ## to an environment variable
 
     ReadDirEffect* = object of ReadIOEffect   ## effect that denotes a write
-                                              ## operation to the directory structure
-    WriteDirEffect* = object of WriteIOEffect ## effect that denotes a write operation to
+                                              ## operation to the directory
+                                              ## structure
+    WriteDirEffect* = object of WriteIOEffect ## effect that denotes a write
+                                              ## operation to
                                               ## the directory structure
 
     OSErrorCode* = distinct int32 ## Specifies an OS Error Code.
@@ -59,13 +65,13 @@ when not declared(getEnv) or defined(nimscript):
       AltSep* = '/'
         ## An alternative character used by the operating system to separate
         ## pathname components, or the same as `DirSep` if only one separator
-        ## character exists. This is set to '/' on Windows systems where `DirSep`
-        ## is a backslash.
+        ## character exists. This is set to '/' on Windows systems
+        ## where `DirSep` is a backslash.
 
       PathSep* = ':'
         ## The character conventionally used by the operating system to separate
-        ## search patch components (as in PATH), such as ':' for POSIX or ';' for
-        ## Windows.
+        ## search patch components (as in PATH), such as ':' for POSIX
+        ## or ';' for Windows.
 
       FileSystemCaseSensitive* = true
         ## true if the file system is case sensitive, false otherwise. Used by
@@ -100,7 +106,8 @@ when not declared(getEnv) or defined(nimscript):
     #  MacOS directory separator is a colon ":" which is the only character not
     #  allowed in filenames.
     #
-    #  A path containing no colon or which begins with a colon is a partial path.
+    #  A path containing no colon or which begins with a colon is a partial
+    #  path.
     #  E.g. ":kalle:petter" ":kalle" "kalle"
     #
     #  All other paths are full (absolute) paths. E.g. "HD:kalle:" "HD:"
@@ -202,9 +209,9 @@ when not declared(getEnv) or defined(nimscript):
 
   proc joinPath*(parts: varargs[string]): string {.noSideEffect,
     rtl, extern: "nos$1OpenArray".} =
-    ## The same as `joinPath(head, tail)`, but works with any number of directory
-    ## parts. You need to pass at least one element or the proc will assert in
-    ## debug builds and crash on release builds.
+    ## The same as `joinPath(head, tail)`, but works with any number of
+    ## directory parts. You need to pass at least one element or the proc
+    ## will assert in debug builds and crash on release builds.
     result = parts[0]
     for i in 1..high(parts):
       result = joinPath(result, parts[i])
@@ -312,8 +319,8 @@ when not declared(getEnv) or defined(nimscript):
       if inclusive: yield path
 
   proc `/../` * (head, tail: string): string {.noSideEffect.} =
-    ## The same as ``parentDir(head) / tail`` unless there is no parent directory.
-    ## Then ``head / tail`` is performed instead.
+    ## The same as ``parentDir(head) / tail`` unless there is no parent
+    ## directory. Then ``head / tail`` is performed instead.
     let sepPos = parentDirPos(head)
     if sepPos >= 0:
       result = substr(head, 0, sepPos-1) / tail
@@ -496,7 +503,8 @@ when defined(nimdoc) and not declared(os):
   proc existsFile(x: string): bool = discard
 
 when declared(getEnv) or defined(nimscript):
-  proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
+  proc getHomeDir*(): string {.rtl, extern: "nos$1",
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Returns the home directory of the current user.
     ##
     ## This proc is wrapped by the expandTilde proc for the convenience of
@@ -504,18 +512,21 @@ when declared(getEnv) or defined(nimscript):
     when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
     else: return string(getEnv("HOME")) & "/"
 
-  proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
+  proc getConfigDir*(): string {.rtl, extern: "nos$1",
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Returns the config directory of the current user for applications.
     when defined(windows): return string(getEnv("APPDATA")) & "\\"
     else: return string(getEnv("HOME")) & "/.config/"
 
-  proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
+  proc getTempDir*(): string {.rtl, extern: "nos$1",
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Returns the temporary directory of the current user for applications to
     ## save temporary files in.
     when defined(windows): return string(getEnv("TEMP")) & "\\"
     else: return "/tmp/"
 
-  proc expandTilde*(path: string): string {.tags: [ReadEnvEffect].} =
+  proc expandTilde*(path: string): string {.
+    tags: [ReadEnvEffect, ReadIOEffect].} =
     ## Expands a path starting with ``~/`` to a full path.
     ##
     ## If `path` starts with the tilde character and is followed by `/` or `\\`
@@ -523,8 +534,8 @@ when declared(getEnv) or defined(nimscript):
     ## the getHomeDir() proc, otherwise the input path will be returned without
     ## modification.
     ##
-    ## The behaviour of this proc is the same on the Windows platform despite not
-    ## having this convention. Example:
+    ## The behaviour of this proc is the same on the Windows platform despite
+    ## not having this convention. Example:
     ##
     ## .. code-block:: nim
     ##   let configFile = expandTilde("~" / "appname.cfg")
@@ -545,7 +556,8 @@ when declared(getEnv) or defined(nimscript):
           yield substr(s, first, last-1)
           inc(last)
 
-  proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect].} =
+  proc findExe*(exe: string): string {.
+    tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect].} =
     ## Searches for `exe` in the current working directory and then
     ## in directories listed in the ``PATH`` environment variable.
     ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 7431be702..fa20afff0 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -24,6 +24,20 @@ when defined(linux):
   import linux
 
 type
+  ProcessOption* = enum ## options that can be passed `startProcess`
+    poEchoCmd,           ## echo the command before execution
+    poUsePath,           ## Asks system to search for executable using PATH environment
+                         ## variable.
+                         ## On Windows, this is the default.
+    poEvalCommand,       ## Pass `command` directly to the shell, without quoting.
+                         ## Use it only if `command` comes from trused source.
+    poStdErrToStdOut,    ## merge stdout and stderr to the stdout stream
+    poParentStreams,     ## use the parent's streams
+    poInteractive        ## optimize the buffer handling for responsiveness for
+                         ## UI applications. Currently this only affects
+                         ## Windows: Named pipes are used so that you can peek
+                         ## at the process' output streams.
+
   ProcessObj = object of RootObj
     when defined(windows):
       fProcessHandle: Handle
@@ -34,18 +48,10 @@ type
       inStream, outStream, errStream: Stream
       id: Pid
     exitCode: cint
+    options: set[ProcessOption]
 
   Process* = ref ProcessObj ## represents an operating system process
 
-  ProcessOption* = enum ## options that can be passed `startProcess`
-    poEchoCmd,           ## echo the command before execution
-    poUsePath,           ## Asks system to search for executable using PATH environment
-                         ## variable.
-                         ## On Windows, this is the default.
-    poEvalCommand,       ## Pass `command` directly to the shell, without quoting.
-                         ## Use it only if `command` comes from trused source.
-    poStdErrToStdOut,    ## merge stdout and stderr to the stdout stream
-    poParentStreams      ## use the parent's streams
 
 {.deprecated: [TProcess: ProcessObj, PProcess: Process,
   TProcessOption: ProcessOption].}
@@ -242,7 +248,8 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
 proc execProcesses*(cmds: openArray[string],
                     options = {poStdErrToStdOut, poParentStreams},
                     n = countProcessors(),
-                    beforeRunEvent: proc(idx: int) = nil): int
+                    beforeRunEvent: proc(idx: int) = nil,
+                    afterRunEvent: proc(idx: int, p: Process) = nil): int
                     {.rtl, extern: "nosp$1",
                     tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} =
   ## executes the commands `cmds` in parallel. Creates `n` processes
@@ -272,6 +279,7 @@ proc execProcesses*(cmds: openArray[string],
             err.add("\n")
           echo(err)
         result = max(waitForExit(q[r]), result)
+        if afterRunEvent != nil: afterRunEvent(r, q[r])
         if q[r] != nil: close(q[r])
         if beforeRunEvent != nil:
           beforeRunEvent(i)
@@ -285,6 +293,7 @@ proc execProcesses*(cmds: openArray[string],
           if not running(q[r]):
             #echo(outputStream(q[r]).readLine())
             result = max(waitForExit(q[r]), result)
+            if afterRunEvent != nil: afterRunEvent(r, q[r])
             if q[r] != nil: close(q[r])
             if beforeRunEvent != nil:
               beforeRunEvent(i)
@@ -293,6 +302,7 @@ proc execProcesses*(cmds: openArray[string],
             if i > high(cmds): break
     for j in 0..m-1:
       result = max(waitForExit(q[j]), result)
+      if afterRunEvent != nil: afterRunEvent(j, q[j])
       if q[j] != nil: close(q[j])
   else:
     for i in 0..high(cmds):
@@ -300,9 +310,10 @@ proc execProcesses*(cmds: openArray[string],
         beforeRunEvent(i)
       var p = startProcess(cmds[i], options=options + {poEvalCommand})
       result = max(waitForExit(p), result)
+      if afterRunEvent != nil: afterRunEvent(i, p)
       close(p)
 
-proc select*(readfds: var seq[Process], timeout = 500): int
+proc select*(readfds: var seq[Process], timeout = 500): int {.benign.}
   ## `select` with a sensible Nim interface. `timeout` is in milliseconds.
   ## Specify -1 for no timeout. Returns the number of processes that are
   ## ready to read from. The processes that are ready to be read from are
@@ -352,7 +363,7 @@ when defined(Windows) and not defined(useNimRtl):
     # TRUE and n (>0) bytes returned (good data).
     # FALSE and bytes returned undefined (system error).
     if a == 0 and br != 0: raiseOSError(osLastError())
-    s.atTheEnd = br < bufLen
+    s.atTheEnd = br == 0 #< bufLen
     result = br
 
   proc hsWriteData(s: Stream, buffer: pointer, bufLen: int) =
@@ -394,13 +405,68 @@ when defined(Windows) and not defined(useNimRtl):
   #var
   #  O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int
   #  O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int
+  proc myDup(h: Handle; inherit: WinBool=1): Handle =
+    let thisProc = getCurrentProcess()
+    if duplicateHandle(thisProc, h,
+                       thisProc, addr result,0,inherit,
+                       DUPLICATE_SAME_ACCESS) == 0:
+      raiseOSError(osLastError())
+
+  proc createAllPipeHandles(si: var STARTUPINFO;
+                            stdin, stdout, stderr: var Handle) =
+    var sa: SECURITY_ATTRIBUTES
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
+    sa.lpSecurityDescriptor = nil
+    sa.bInheritHandle = 1
+    let pipeOutName = newWideCString(r"\\.\pipe\stdout")
+    let pipeInName = newWideCString(r"\\.\pipe\stdin")
+    let pipeOut = createNamedPipe(pipeOutName,
+      dwOpenMode=PIPE_ACCESS_INBOUND or FILE_FLAG_WRITE_THROUGH,
+      dwPipeMode=PIPE_NOWAIT,
+      nMaxInstances=1,
+      nOutBufferSize=1024, nInBufferSize=1024,
+      nDefaultTimeOut=0,addr sa)
+    if pipeOut == INVALID_HANDLE_VALUE:
+      raiseOSError(osLastError())
+    let pipeIn = createNamedPipe(pipeInName,
+      dwOpenMode=PIPE_ACCESS_OUTBOUND or FILE_FLAG_WRITE_THROUGH,
+      dwPipeMode=PIPE_NOWAIT,
+      nMaxInstances=1,
+      nOutBufferSize=1024, nInBufferSize=1024,
+      nDefaultTimeOut=0,addr sa)
+    if pipeIn == INVALID_HANDLE_VALUE:
+      raiseOSError(osLastError())
+
+    si.hStdOutput = createFileW(pipeOutName,
+        FILE_WRITE_DATA or SYNCHRONIZE, 0, addr sa,
+        OPEN_EXISTING, # very important flag!
+        FILE_ATTRIBUTE_NORMAL,
+        0 # no template file for OPEN_EXISTING
+      )
+    if si.hStdOutput == INVALID_HANDLE_VALUE:
+      raiseOSError(osLastError())
+    si.hStdError = myDup(si.hStdOutput)
+    si.hStdInput = createFileW(pipeInName,
+        FILE_READ_DATA or SYNCHRONIZE, 0, addr sa,
+        OPEN_EXISTING, # very important flag!
+        FILE_ATTRIBUTE_NORMAL,
+        0 # no template file for OPEN_EXISTING
+      )
+    if si.hStdOutput == INVALID_HANDLE_VALUE:
+      raiseOSError(osLastError())
+
+    stdin = myDup(pipeIn, 0)
+    stdout = myDup(pipeOut, 0)
+    discard closeHandle(pipeIn)
+    discard closeHandle(pipeOut)
+    stderr = stdout
 
   proc createPipeHandles(rdHandle, wrHandle: var Handle) =
-    var piInheritablePipe: SECURITY_ATTRIBUTES
-    piInheritablePipe.nLength = sizeof(SECURITY_ATTRIBUTES).cint
-    piInheritablePipe.lpSecurityDescriptor = nil
-    piInheritablePipe.bInheritHandle = 1
-    if createPipe(rdHandle, wrHandle, piInheritablePipe, 1024) == 0'i32:
+    var sa: SECURITY_ATTRIBUTES
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
+    sa.lpSecurityDescriptor = nil
+    sa.bInheritHandle = 1
+    if createPipe(rdHandle, wrHandle, sa, 1024) == 0'i32:
       raiseOSError(osLastError())
 
   proc fileClose(h: Handle) {.inline.} =
@@ -417,16 +483,20 @@ when defined(Windows) and not defined(useNimRtl):
       success: int
       hi, ho, he: Handle
     new(result)
+    result.options = options
     si.cb = sizeof(si).cint
     if poParentStreams notin options:
       si.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or
-      createPipeHandles(si.hStdInput, hi)
-      createPipeHandles(ho, si.hStdOutput)
-      if poStdErrToStdOut in options:
-        si.hStdError = si.hStdOutput
-        he = ho
+      if poInteractive notin options:
+        createPipeHandles(si.hStdInput, hi)
+        createPipeHandles(ho, si.hStdOutput)
+        if poStdErrToStdOut in options:
+          si.hStdError = si.hStdOutput
+          he = ho
+        else:
+          createPipeHandles(he, si.hStdError)
       else:
-        createPipeHandles(he, si.hStdError)
+        createAllPipeHandles(si, hi, ho, he)
       result.inHandle = FileHandle(hi)
       result.outHandle = FileHandle(ho)
       result.errHandle = FileHandle(he)
@@ -469,6 +539,7 @@ when defined(Windows) and not defined(useNimRtl):
 
     if e != nil: dealloc(e)
     if success == 0:
+      if poInteractive in result.options: close(result)
       const errInvalidParameter = 87.int
       const errFileNotFound = 2.int
       if lastError.int in {errInvalidParameter, errFileNotFound}:
@@ -482,12 +553,12 @@ when defined(Windows) and not defined(useNimRtl):
     result.id = procInfo.dwProcessId
 
   proc close(p: Process) =
-    when false:
-      # somehow this does not work on Windows:
+    if poInteractive in p.options:
+      # somehow this is not always required on Windows:
       discard closeHandle(p.inHandle)
       discard closeHandle(p.outHandle)
       discard closeHandle(p.errHandle)
-      discard closeHandle(p.FProcessHandle)
+      #discard closeHandle(p.FProcessHandle)
 
   proc suspend(p: Process) =
     discard suspendThread(p.fProcessHandle)
@@ -564,7 +635,7 @@ when defined(Windows) and not defined(useNimRtl):
     assert readfds.len <= MAXIMUM_WAIT_OBJECTS
     var rfds: WOHandleArray
     for i in 0..readfds.len()-1:
-      rfds[i] = readfds[i].fProcessHandle
+      rfds[i] = readfds[i].outHandle #fProcessHandle
 
     var ret = waitForMultipleObjects(readfds.len.int32,
                                      addr(rfds), 0'i32, timeout.int32)
@@ -578,6 +649,11 @@ when defined(Windows) and not defined(useNimRtl):
       readfds.del(i)
       return 1
 
+  proc hasData*(p: Process): bool =
+    var x: int32
+    if peekNamedPipe(p.outHandle, lpTotalBytesAvail=addr x):
+      result = x > 0
+
 elif not defined(useNimRtl):
   const
     readIdx = 0
@@ -635,6 +711,7 @@ elif not defined(useNimRtl):
     var
       pStdin, pStdout, pStderr: array [0..1, cint]
     new(result)
+    result.options = options
     result.exitCode = -3 # for ``waitForExit``
     if poParentStreams notin options:
       if pipe(pStdin) != 0'i32 or pipe(pStdout) != 0'i32 or
@@ -960,6 +1037,15 @@ elif not defined(useNimRtl):
 
     pruneProcessSet(readfds, (rd))
 
+  proc hasData*(p: Process): bool =
+    var rd: TFdSet
+
+    FD_ZERO(rd)
+    let m = max(0, int(p.outHandle))
+    FD_SET(cint(p.outHandle), rd)
+
+    result = int(select(cint(m+1), addr(rd), nil, nil, nil)) == 1
+
 
 proc execCmdEx*(command: string, options: set[ProcessOption] = {
                 poStdErrToStdOut, poUsePath}): tuple[
diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim
index 60d09c71a..72c64befc 100644
--- a/lib/pure/rationals.nim
+++ b/lib/pure/rationals.nim
@@ -18,8 +18,9 @@ type Rational*[T] = object
   ## a rational number, consisting of a numerator and denominator
   num*, den*: T
 
-proc initRational*[T](num, den: T): Rational[T] =
+proc initRational*[T:SomeInteger](num, den: T): Rational[T] =
   ## Create a new rational number.
+  assert(den != 0, "a denominator of zero value is invalid")
   result.num = num
   result.den = den
 
@@ -33,11 +34,68 @@ proc `$`*[T](x: Rational[T]): string =
   ## Turn a rational number into a string.
   result = $x.num & "/" & $x.den
 
-proc toRational*[T](x: T): Rational[T] =
+proc toRational*[T:SomeInteger](x: T): Rational[T] =
   ## Convert some integer `x` to a rational number.
   result.num = x
   result.den = 1
 
+proc toRationalSub(x: float, n: int): Rational[int] =
+  var
+    a = 0
+    b, c, d = 1
+  result = 0 // 1   # rational 0
+  while b <= n and d <= n:
+    let ac = (a+c)
+    let bd = (b+d)
+    # scale by 1000 so not overflow for high precision
+    let mediant = (ac/1000) / (bd/1000)
+    if x == mediant:
+      if bd <= n:
+        result.num = ac
+        result.den = bd
+        return result
+      elif d > b:
+        result.num = c
+        result.den = d
+        return result
+      else:
+        result.num = a
+        result.den = b
+        return result
+    elif x > mediant:
+      a = ac
+      b = bd
+    else:
+      c = ac
+      d = bd
+  if (b > n):
+    return initRational(c, d)
+  return initRational(a, b)
+
+proc toRational*(x: float, n: int = high(int)): Rational[int] =
+  ## Calculate the best rational numerator and denominator
+  ## that approximates to `x`, where the denominator is
+  ## smaller than `n` (default is the largest possible
+  ## int to give maximum resolution)
+  ##
+  ## The algorithm is based on the Farey sequence named
+  ## after John Farey
+  ##
+  ## .. code-block:: Nim
+  ##  import math, rationals
+  ##  for i in 1..10:
+  ##    let t = (10 ^ (i+3)).int
+  ##    let x = toRational(PI, t)
+  ##    let newPI = x.num / x.den
+  ##    echo x, " ", newPI, " error: ", PI - newPI, "  ", t
+  if x > 1:
+    result = toRationalSub(1.0/x, n)
+    swap(result.num, result.den)
+  elif x == 1.0:
+    result = 1 // 1
+  else:
+    result = toRationalSub(x, n)
+
 proc toFloat*[T](x: Rational[T]): float =
   ## Convert a rational number `x` to a float.
   x.num / x.den
@@ -47,7 +105,7 @@ proc toInt*[T](x: Rational[T]): int =
   ## `x` does not contain an integer value.
   x.num div x.den
 
-proc reduce*[T](x: var Rational[T]) =
+proc reduce*[T:SomeInteger](x: var Rational[T]) =
   ## Reduce rational `x`.
   let common = gcd(x.num, x.den)
   if x.den > 0:
@@ -287,3 +345,8 @@ when isMainModule:
   assert toRational(5) == 5//1
   assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
   assert toInt(z) == 0
+
+  assert toRational(0.98765432) == 12345679 // 12500000
+  assert toRational(0.1, 1000000) == 1 // 10
+  assert toRational(0.9, 1000000) == 9 // 10
+  assert toRational(PI) == 80143857 // 25510582
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
index bfc393a96..ca969c761 100644
--- a/lib/pure/selectors.nim
+++ b/lib/pure/selectors.nim
@@ -13,6 +13,8 @@ import os, unsigned, hashes
 
 when defined(linux):
   import posix, epoll
+elif defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd):
+  import posix, kqueue, times
 elif defined(windows):
   import winlean
 else:
@@ -79,7 +81,6 @@ when defined(nimdoc):
   proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey =
     ## Retrieves the selector key for ``fd``.
 
-
 elif defined(linux):
   type
     Selector* = object
@@ -99,15 +100,13 @@ elif defined(linux):
     result.data.fd = fd.cint
 
   proc register*(s: var Selector, fd: SocketHandle, events: set[Event],
-      data: SelectorData) =
+                 data: SelectorData) =
     var event = createEventStruct(events, fd)
     if events != {}:
       if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0:
         raiseOSError(osLastError())
 
-    var key = SelectorKey(fd: fd, events: events, data: data)
-
-    s.fds[fd] = key
+    s.fds[fd] = SelectorKey(fd: fd, events: events, data: data)
 
   proc update*(s: var Selector, fd: SocketHandle, events: set[Event]) =
     if s.fds[fd].events != events:
@@ -154,11 +153,6 @@ elif defined(linux):
       raiseOSError(err)
 
   proc select*(s: var Selector, timeout: int): seq[ReadyInfo] =
-    ##
-    ## The ``events`` field of the returned ``key`` contains the original events
-    ## for which the ``fd`` was bound. This is contrary to the ``events`` field
-    ## of the ``TReadyInfo`` tuple which determines which events are ready
-    ## on the ``fd``.
     result = @[]
     let evNum = epoll_wait(s.epollFD, addr s.events[0], 64.cint, timeout.cint)
     if evNum < 0:
@@ -204,6 +198,86 @@ elif defined(linux):
     ## Retrieves the selector key for ``fd``.
     return s.fds[fd]
 
+elif defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd):
+  type
+    Selector* = object
+      kqFD: cint
+      events: array[64, KEvent]
+      when MultiThreaded:
+        fds: SharedTable[SocketHandle, SelectorKey]
+      else:
+        fds: Table[SocketHandle, SelectorKey]
+
+  template modifyKQueue(kqFD: cint, fd: SocketHandle, event: Event,
+                        op: cushort) =
+    var kev = KEvent(ident:  fd.cuint,
+                     filter: if event == EvRead: EVFILT_READ else: EVFILT_WRITE,
+                     flags:  op)
+    if kevent(kqFD, addr kev, 1, nil, 0, nil) == -1:
+      raiseOSError(osLastError())
+
+  proc register*(s: var Selector, fd: SocketHandle, events: set[Event],
+                 data: SelectorData) =
+    for event in events:
+      modifyKQueue(s.kqFD, fd, event, EV_ADD)
+    s.fds[fd] = SelectorKey(fd: fd, events: events, data: data)
+
+  proc update*(s: var Selector, fd: SocketHandle, events: set[Event]) =
+    let previousEvents = s.fds[fd].events
+    if previousEvents != events:
+      for event in events-previousEvents:
+        modifyKQueue(s.kqFD, fd, event, EV_ADD)
+      for event in previousEvents-events:
+        modifyKQueue(s.kqFD, fd, event, EV_DELETE)
+      s.fds.mget(fd).events = events
+
+  proc unregister*(s: var Selector, fd: SocketHandle) =
+    for event in s.fds[fd].events:
+      modifyKQueue(s.kqFD, fd, event, EV_DELETE)
+    s.fds.del(fd)
+
+  proc close*(s: var Selector) =
+    when MultiThreaded: deinitSharedTable(s.fds)
+    if s.kqFD.close() != 0: raiseOSError(osLastError())
+
+  proc select*(s: var Selector, timeout: int): seq[ReadyInfo] =
+    result = @[]
+    var tv = Timespec(tv_sec: timeout.Time, tv_nsec: 0)
+    let evNum = kevent(s.kqFD, nil, 0, addr s.events[0], 64.cint, addr tv)
+    if evNum < 0:
+      let err = osLastError()
+      if err.cint == EINTR:
+        return @[]
+      raiseOSError(err)
+    if evNum == 0: return @[]
+    for i in 0 .. <evNum:
+      let fd = s.events[i].ident.SocketHandle
+
+      var evSet: set[Event] = {}
+      if  (s.events[i].flags and EV_EOF) != 0: evSet = evSet + {EvError}
+      if   s.events[i].filter == EVFILT_READ:  evSet = evSet + {EvRead}
+      elif s.events[i].filter == EVFILT_WRITE: evSet = evSet + {EvWrite}
+      let selectorKey = s.fds[fd]
+      assert selectorKey.fd != 0.SocketHandle
+      result.add((selectorKey, evSet))
+
+  proc newSelector*(): Selector =
+    result.kqFD = kqueue()
+    if result.kqFD < 0:
+      raiseOSError(osLastError())
+    when MultiThreaded:
+      result.fds = initSharedTable[SocketHandle, SelectorKey]()
+    else:
+      result.fds = initTable[SocketHandle, SelectorKey]()
+
+  proc contains*(s: Selector, fd: SocketHandle): bool =
+    ## Determines whether selector contains a file descriptor.
+    s.fds.hasKey(fd) # and s.fds[fd].events != {}
+
+  proc `[]`*(s: Selector, fd: SocketHandle): SelectorKey =
+    ## Retrieves the selector key for ``fd``.
+    return s.fds[fd]
+
 elif not defined(nimdoc):
   # TODO: kqueue for bsd/mac os x.
   type
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 8aa8d35d8..38e91fee4 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -11,6 +11,26 @@
 ## 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.
+##
+## Examples:
+##
+## .. code-block:: Nim
+##
+##  import streams
+##  var
+##    ss = newStringStream("""The first line
+##  the second line
+##  the third line""")
+##    line = ""
+##  while ss.readLine(line):
+##    echo line
+##  ss.close()
+##
+##  var fs = newFileStream("somefile.txt", fmRead)
+##  if not isNil(fs):
+##    while fs.readLine(line):
+##      echo line
+##    fs.close()
 
 include "system/inclrtl"
 
@@ -81,6 +101,19 @@ proc readData*(s: Stream, buffer: pointer, bufLen: int): int =
   ## low level proc that reads data into an untyped `buffer` of `bufLen` size.
   result = s.readDataImpl(s, buffer, bufLen)
 
+proc readAll*(s: Stream): string =
+  ## Reads all available data.
+  const bufferSize = 1000
+  result = newString(bufferSize)
+  var r = 0
+  while true:
+    let readBytes = readData(s, addr(result[r]), bufferSize)
+    if readBytes < bufferSize:
+      setLen(result, r+readBytes)
+      break
+    inc r, bufferSize
+    setLen(result, r+bufferSize)
+
 proc readData*(s, unused: Stream, buffer: pointer,
                bufLen: int): int {.deprecated.} =
   ## low level proc that reads data into an untyped `buffer` of `bufLen` size.
@@ -371,7 +404,7 @@ when not defined(js):
     result.writeDataImpl = fsWriteData
     result.flushImpl = fsFlush
 
-  proc newFileStream*(filename: string, mode: FileMode): FileStream =
+  proc newFileStream*(filename: string, mode: FileMode = fmRead): FileStream =
     ## creates a new stream from the file named `filename` with the mode `mode`.
     ## If the file cannot be opened, nil is returned. See the `system
     ## <system.html>`_ module for a list of available FileMode enums.
diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim
index 86f81aa43..1ce9067a7 100644
--- a/lib/pure/strtabs.nim
+++ b/lib/pure/strtabs.nim
@@ -173,6 +173,9 @@ proc clear*(s: StringTableRef, mode: StringTableMode) =
   s.mode = mode
   s.counter = 0
   s.data.setLen(startSize)
+  for i in 0..<s.data.len:
+    if not isNil(s.data[i].key):
+      s.data[i].key = nil
 
 proc newStringTable*(keyValuePairs: varargs[string],
                      mode: StringTableMode): StringTableRef {.
@@ -248,3 +251,6 @@ when isMainModule:
   x.mget("11") = "23"
   assert x["11"] == "23"
 
+  x.clear(modeCaseInsensitive)
+  x["11"] = "22"
+  assert x["11"] == "22"
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index ae3bd7f63..a78fed4b9 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -60,6 +60,132 @@ const
     ##   doAssert "01234".find(invalid) == -1
     ##   doAssert "01A34".find(invalid) == 2
 
+proc isAlpha*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaChar".}=
+  ## Checks whether or not `c` is alphabetical.
+  ##
+  ## This checks a-z, A-Z ASCII characters only.
+  return c in Letters
+
+proc isAlphaNumeric*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaNumericChar".}=
+  ## Checks whether or not `c` is alphanumeric.
+  ##
+  ## This checks a-z, A-Z, 0-9 ASCII characters only.
+  return c in Letters or c in Digits
+
+proc isDigit*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsDigitChar".}=
+  ## Checks whether or not `c` is a number.
+  ##
+  ## This checks 0-9 ASCII characters only.
+  return c in Digits
+
+proc isSpace*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsSpaceChar".}=
+  ## Checks whether or not `c` is a whitespace character.
+  return c in Whitespace
+
+proc isLower*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsLowerChar".}=
+  ## Checks whether or not `c` is a lower case character.
+  ##
+  ## This checks ASCII characters only.
+  return c in {'a'..'z'}
+
+proc isUpper*(c: char): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsUpperChar".}=
+  ## Checks whether or not `c` is an upper case character.
+  ##
+  ## This checks ASCII characters only.
+  return c in {'A'..'Z'}
+
+proc isAlpha*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaStr".}=
+  ## Checks whether or not `s` is alphabetical.
+  ##
+  ## This checks a-z, A-Z ASCII characters only.
+  ## Returns true if all characters in `s` are
+  ## alphabetic and there is at least one character
+  ## in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isAlpha() and result
+
+proc isAlphaNumeric*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsAlphaNumericStr".}=
+  ## Checks whether or not `s` is alphanumeric.
+  ##
+  ## This checks a-z, A-Z, 0-9 ASCII characters only.
+  ## Returns true if all characters in `s` are
+  ## alpanumeric and there is at least one character
+  ## in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isAlphaNumeric() and result
+
+proc isDigit*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsDigitStr".}=
+  ## Checks whether or not `s` is a numeric value.
+  ##
+  ## This checks 0-9 ASCII characters only.
+  ## Returns true if all characters in `s` are
+  ## numeric and there is at least one character
+  ## in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isDigit() and result
+
+proc isSpace*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsSpaceStr".}=
+  ## Checks whether or not `s` is completely whitespace.
+  ##
+  ## Returns true if all characters in `s` are whitespace
+  ## characters and there is at least one character in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isSpace() and result
+
+proc isLower*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsLowerStr".}=
+  ## Checks whether or not `s` contains all lower case characters.
+  ##
+  ## This checks ASCII characters only.
+  ## Returns true if all characters in `s` are lower case
+  ## and there is at least one character  in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isLower() and result
+
+proc isUpper*(s: string): bool {.noSideEffect, procvar,
+  rtl, extern: "nsuIsUpperStr".}=
+  ## Checks whether or not `s` contains all upper case characters.
+  ##
+  ## This checks ASCII characters only.
+  ## Returns true if all characters in `s` are upper case
+  ## and there is at least one character in `s`.
+  if s.len() == 0:
+    return false
+
+  result = true
+  for c in s:
+    result = c.isUpper() and result
+
 proc toLower*(c: char): char {.noSideEffect, procvar,
   rtl, extern: "nsuToLowerChar".} =
   ## Converts `c` into lower case.
@@ -169,7 +295,8 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
     inc(j)
 
 
-proc strip*(s: string, leading = true, trailing = true, chars: set[char] = Whitespace): string
+proc strip*(s: string, leading = true, trailing = true,
+            chars: set[char] = Whitespace): string
   {.noSideEffect, rtl, extern: "nsuStrip".} =
   ## Strips `chars` from `s` and returns the resulting string.
   ##
@@ -504,7 +631,8 @@ proc repeat*(c: char, count: Natural): string {.noSideEffect,
   ##
   ## .. code-block:: nim
   ##   proc tabexpand(indent: int, text: string, tabsize: int = 4) =
-  ##     echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize), text
+  ##     echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize),
+  ##         text
   ##
   ##   tabexpand(4, "At four")
   ##   tabexpand(5, "At five")
@@ -533,11 +661,13 @@ template spaces*(n: Natural): string =  repeat(' ',n)
   ##   echo text1 & spaces(max(0, width - text1.len)) & "|"
   ##   echo text2 & spaces(max(0, width - text2.len)) & "|"
 
-proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} = repeat(c, count)
+proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} =
   ## deprecated: use repeat() or spaces()
+  repeat(c, count)
 
-proc repeatStr*(count: Natural, s: string): string {.deprecated.} = repeat(s, count)
+proc repeatStr*(count: Natural, s: string): string {.deprecated.} =
   ## deprecated: use repeat(string, count) or string.repeat(count)
+  repeat(s, count)
 
 proc align*(s: string, count: Natural, padding = ' '): string {.
   noSideEffect, rtl, extern: "nsuAlignString".} =
@@ -630,6 +760,22 @@ proc wordWrap*(s: string, maxLineWidth = 80,
       result.add(lastSep & word)
       lastSep.setLen(0)
 
+proc indent*(s: string, count: Natural, padding: string = " "): string
+    {.noSideEffect, rtl, extern: "nsuIndent".} =
+  ## Indents each line in ``s`` by ``count`` amount of ``padding``.
+  ##
+  ## **Note:** This currently does not preserve the specific new line characters
+  ## used.
+  result = ""
+  var i = 0
+  for line in s.splitLines():
+    if i != 0:
+      result.add("\n")
+    for j in 1..count:
+      result.add(padding)
+    result.add(line)
+    i.inc
+
 proc unindent*(s: string, eatAllIndent = false): string {.
                noSideEffect, rtl, extern: "nsuUnindent".} =
   ## Unindents `s`.
@@ -834,8 +980,8 @@ proc rfind*(s: string, sub: char, start: int = -1): int {.noSideEffect,
     if sub == s[i]: return i
   return -1
 
-proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
-  rtl, extern: "nsuCountString".} =
+proc count*(s: string, sub: string, overlapping: bool = false): int {.
+  noSideEffect, rtl, extern: "nsuCountString".} =
   ## Count the occurrences of a substring `sub` in the string `s`.
   ## Overlapping occurrences of `sub` only count when `overlapping`
   ## is set to true.
@@ -1433,7 +1579,8 @@ proc removeSuffix*(s: var string, chars: set[char] = Newlines) {.
 
   s.setLen(last + 1)
 
-proc removeSuffix*(s: var string, c: char) {.rtl, extern: "nsuRemoveSuffixChar".} =
+proc removeSuffix*(s: var string, c: char) {.
+  rtl, extern: "nsuRemoveSuffixChar".} =
   ## Removes a single character (in-place) from a string.
   ## .. code-block:: nim
   ##   var
@@ -1499,6 +1646,61 @@ when isMainModule:
   doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo"
   doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo"
   doAssert strip("stripme but don't strip this stripme",
-                 chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) == " but don't strip this "
+                 chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) ==
+                 " but don't strip this "
   doAssert strip("sfoofoofoos", leading = false, chars = {'s'}) == "sfoofoofoo"
   doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos"
+
+  doAssert "  foo\n  bar".indent(4, "Q") == "QQQQ  foo\nQQQQ  bar"
+
+  doAssert isAlpha('r')
+  doAssert isAlpha('A')
+  doAssert(not isAlpha('$'))
+
+  doAssert isAlpha("Rasp")
+  doAssert isAlpha("Args")
+  doAssert(not isAlpha("$Tomato"))
+  
+  doAssert isAlphaNumeric('3')
+  doAssert isAlphaNumeric('R')
+  doAssert(not isAlphaNumeric('!'))
+
+  doAssert isAlphaNumeric("34ABc")
+  doAssert isAlphaNumeric("Rad")
+  doAssert isAlphaNumeric("1234")
+  doAssert(not isAlphaNumeric("@nose"))
+
+  doAssert isDigit('3')
+  doAssert(not isDigit('a'))
+  doAssert(not isDigit('%'))
+
+  doAssert isDigit("12533")
+  doAssert(not isDigit("12.33"))
+  doAssert(not isDigit("A45b"))
+
+  doAssert isSpace('\t')
+  doAssert isSpace('\l')
+  doAssert(not isSpace('A'))
+
+  doAssert isSpace("\t\l \v\r\f")
+  doAssert isSpace("       ")
+  doAssert(not isSpace("ABc   \td"))
+
+  doAssert isLower('a')
+  doAssert isLower('z')
+  doAssert(not isLower('A'))
+  doAssert(not isLower('5'))
+  doAssert(not isLower('&'))
+
+  doAssert isLower("abcd")
+  doAssert(not isLower("abCD"))
+  doAssert(not isLower("33aa"))
+
+  doAssert isUpper('A')
+  doAssert(not isUpper('b'))
+  doAssert(not isUpper('5'))
+  doAssert(not isUpper('%'))
+
+  doAssert isUpper("ABC")
+  doAssert(not isUpper("AAcc"))
+  doAssert(not isUpper("A#$"))
diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim
index 2d1adc0eb..5824ace81 100644
--- a/lib/pure/subexes.nim
+++ b/lib/pure/subexes.nim
@@ -351,6 +351,7 @@ proc format*(formatstr: Subex, a: varargs[string, `$`]): string {.noSideEffect,
 {.pop.}
 
 when isMainModule:
+  from strutils import replace
 
   proc `%`(formatstr: string, a: openarray[string]): string =
     result = newStringOfCap(formatstr.len + a.len shl 4)
@@ -382,18 +383,18 @@ when isMainModule:
   doAssert "${$1}" % "1" == "1"
   doAssert "${$$-1} $$1" % "1" == "1 $1"
 
-  doAssert "$#($', '10c'\n    '{#..})" % ["doAssert", "longishA", "longish"] ==
+  doAssert(("$#($', '10c'\n    '{#..})" % ["doAssert", "longishA", "longish"]).replace(" \n", "\n") ==
            """doAssert(
     longishA,
-    longish)"""
+    longish)""")
 
-  assert "type MyEnum* = enum\n  $', '2i'\n  '{..}" % ["fieldA",
-    "fieldB", "FiledClkad", "fieldD", "fieldE", "longishFieldName"] ==
+  doAssert(("type MyEnum* = enum\n  $', '2i'\n  '{..}" % ["fieldA",
+    "fieldB", "FiledClkad", "fieldD", "fieldE", "longishFieldName"]).replace(" \n", "\n") ==
     strutils.unindent """
       type MyEnum* = enum
         fieldA, fieldB,
         FiledClkad, fieldD,
-        fieldE, longishFieldName"""
+        fieldE, longishFieldName""")
 
   doAssert subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)"
 
@@ -401,12 +402,10 @@ when isMainModule:
 
   doAssert subex"$['''|'|''''|']']#" % "0" == "'|"
 
-  assert subex("type\n  Enum = enum\n    $', '40c'\n    '{..}") % [
-    "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"] ==
+  doAssert((subex("type\n  Enum = enum\n    $', '40c'\n    '{..}") % [
+    "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"]).replace(" \n", "\n") ==
     strutils.unindent """
       type
         Enum = enum
           fieldNameA, fieldNameB, fieldNameC,
-          fieldNameD"""
-
-
+          fieldNameD""")
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index aa4ae5ace..3142952e7 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -11,6 +11,26 @@
 ## This module contains routines and types for dealing with time.
 ## This module is available for the `JavaScript target
 ## <backends.html#the-javascript-target>`_.
+##
+## Examples:
+##
+## .. code-block:: nim
+##
+##  import times, os
+##  var
+##    t = cpuTime()
+##
+##  sleep(100)   # replace this with something to be timed
+##  echo "Time taken: ",cpuTime() - t
+##
+##  echo "My formatted time: ", format(getLocalTime(getTime()), "d MMMM yyyy HH:mm")
+##  echo "Using predefined formats: ", getClockStr(), " ", getDateStr()
+##
+##  echo "epochTime() float value: ", epochTime()
+##  echo "getTime()   float value: ", toSeconds(getTime())
+##  echo "cpuTime()   float value: ", cpuTime()
+##  echo "An hour from now      : ", getLocalTime(getTime()) + initInterval(0,0,0,1)
+##  echo "An hour from (UTC) now: ", getGmTime(getTime()) + initInterval(0,0,0,1)
 
 {.push debugger:off.} # the user does not want to trace a part
                       # of the standard library!
@@ -288,10 +308,10 @@ proc `+`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
   ## very accurate.
   let t = toSeconds(timeInfoToTime(a))
   let secs = toSeconds(a, interval)
-  if a.tzname == "UTC":
-    result = getGMTime(fromSeconds(t + secs))
-  else:
-    result = getLocalTime(fromSeconds(t + secs))
+  #if a.tzname == "UTC":
+  #  result = getGMTime(fromSeconds(t + secs))
+  #else:
+  result = getLocalTime(fromSeconds(t + secs))
 
 proc `-`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
   ## subtracts ``interval`` time.
@@ -300,10 +320,10 @@ proc `-`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
   ## when you subtract so much that you reach the Julian calendar.
   let t = toSeconds(timeInfoToTime(a))
   let secs = toSeconds(a, interval)
-  if a.tzname == "UTC":
-    result = getGMTime(fromSeconds(t - secs))
-  else:
-    result = getLocalTime(fromSeconds(t - secs))
+  #if a.tzname == "UTC":
+  #  result = getGMTime(fromSeconds(t - secs))
+  #else:
+  result = getLocalTime(fromSeconds(t - secs))
 
 when not defined(JS):
   proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
@@ -1269,3 +1289,28 @@ when isMainModule:
   assert getDayOfWeekJulian(21, 9, 1970) == dMon
   assert getDayOfWeekJulian(1, 1, 2000) == dSat
   assert getDayOfWeekJulian(1, 1, 2021) == dFri
+
+  # toSeconds tests with GM and Local timezones
+  #var t4 = getGMTime(fromSeconds(876124714)) # Mon  6 Oct 08:58:34 BST 1997
+  var t4L = getLocalTime(fromSeconds(876124714))
+  assert toSeconds(timeInfoToTime(t4L)) == 876124714    # fromSeconds is effectively "localTime"
+  assert toSeconds(timeInfoToTime(t4L)) + t4L.timezone.float == toSeconds(timeInfoToTime(t4))
+
+  assert toSeconds(t4, initInterval(seconds=0)) == 0.0
+  assert toSeconds(t4L, initInterval(milliseconds=1)) == toSeconds(t4, initInterval(milliseconds=1))
+  assert toSeconds(t4L, initInterval(seconds=1)) == toSeconds(t4, initInterval(seconds=1))
+  assert toSeconds(t4L, initInterval(minutes=1)) == toSeconds(t4, initInterval(minutes=1))
+  assert toSeconds(t4L, initInterval(hours=1)) == toSeconds(t4, initInterval(hours=1))
+  assert toSeconds(t4L, initInterval(days=1)) == toSeconds(t4, initInterval(days=1))
+  assert toSeconds(t4L, initInterval(months=1)) == toSeconds(t4, initInterval(months=1))
+  assert toSeconds(t4L, initInterval(years=1)) == toSeconds(t4, initInterval(years=1))
+
+  # adding intervals
+  var
+    a1L = toSeconds(timeInfoToTime(t4L + initInterval(hours = 1))) + t4L.timezone.float
+    a1G = toSeconds(timeInfoToTime(t4)) + 60.0 * 60.0
+  assert a1L == a1G
+  # subtracting intervals
+  a1L = toSeconds(timeInfoToTime(t4L - initInterval(hours = 1))) + t4L.timezone.float
+  a1G = toSeconds(timeInfoToTime(t4)) - (60.0 * 60.0)
+  assert a1L == a1G
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index 396957f6c..b059a7315 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -1319,15 +1319,43 @@ proc reversed*(s: string): string =
 
   reverseUntil(len(s))
 
+proc graphemeLen*(s: string; i: Natural): Natural =
+  ## The number of bytes belonging to 's[i]' including following combining
+  ## characters.
+  var j = i.int
+  var r, r2: Rune
+  if j < s.len:
+    fastRuneAt(s, j, r, true)
+    result = j-i
+    while j < s.len:
+      fastRuneAt(s, j, r2, true)
+      if not isCombining(r2): break
+      result = j-i
+
+proc lastRune*(s: string; last: int): (Rune, int) =
+  ## length of the last rune in 's[0..last]'. Returns the rune and its length
+  ## in bytes.
+  if s[last] <= chr(127):
+    result = (Rune(s[last]), 1)
+  else:
+    var L = 0
+    while last-L >= 0 and ord(s[last-L]) shr 6 == 0b10: inc(L)
+    var r: Rune
+    fastRuneAt(s, last-L, r, false)
+    result = (r, L+1)
+
 when isMainModule:
   let
     someString = "öÑ"
     someRunes = @[runeAt(someString, 0), runeAt(someString, 2)]
     compared = (someString == $someRunes)
-  assert compared == true
+  doAssert compared == true
 
-  assert reversed("Reverse this!") == "!siht esreveR"
-  assert reversed("先秦兩漢") == "漢兩秦先"
-  assert reversed("as⃝df̅") == "f̅ds⃝a"
-  assert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
-  assert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
+  doAssert reversed("Reverse this!") == "!siht esreveR"
+  doAssert reversed("先秦兩漢") == "漢兩秦先"
+  doAssert reversed("as⃝df̅") == "f̅ds⃝a"
+  doAssert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
+  doAssert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
+  const test = "as⃝"
+  doAssert lastRune(test, test.len-1)[1] == 3
+  doAssert graphemeLen("è", 0) == 2
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index 492de3b46..abb1a462d 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -142,6 +142,7 @@ proc parseUri*(uri: string): Uri =
   parseUri(uri, result)
 
 proc removeDotSegments(path: string): string =
+  if path.len == 0: return ""
   var collection: seq[string] = @[]
   let endsWithSlash = path[path.len-1] == '/'
   var i = 0
@@ -432,3 +433,12 @@ when isMainModule:
   block:
     let test = parseUri("http://example.com/foo/") / "/bar/asd"
     doAssert test.path == "/foo/bar/asd"
+
+  # removeDotSegments tests
+  block:
+    # empty test
+    doAssert removeDotSegments("") == ""
+
+  # bug #3207
+  block:
+    doAssert parseUri("http://qq/1").combine(parseUri("https://qqq")).`$` == "https://qqq"
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 1c8573986..7c97a0a56 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -104,10 +104,23 @@ proc tag*(n: XmlNode): string {.inline.} =
   assert n.k == xnElement
   result = n.fTag
 
+proc `tag=`*(n: XmlNode, tag: string) {.inline.} =
+  ## sets the tag name of `n`. `n` has to be an ``xnElement`` node.
+  assert n.k == xnElement
+  n.fTag = tag
+
 proc add*(father, son: XmlNode) {.inline.} =
   ## adds the child `son` to `father`.
   add(father.s, son)
 
+proc insert*(father, son: XmlNode, index: int) {.inline.} =
+  ## insert the child `son` to a given position in `father`.
+  assert father.k == xnElement and son.k == xnElement
+  if len(father.s) > index:
+    insert(father.s, son, index)
+  else:
+    insert(father.s, son, len(father.s))
+
 proc len*(n: XmlNode): int {.inline.} =
   ## returns the number `n`'s children.
   if n.k == xnElement: result = len(n.s)
diff --git a/lib/system.nim b/lib/system.nim
index e0bfbe8ea..f7178adcc 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -78,7 +78,7 @@ type
   stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
   typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
   void* {.magic: "VoidType".}   ## meta type to denote the absence of any type
-  auto* = expr ## meta type for automatic type determination
+  auto* {.magic: Expr.} ## meta type for automatic type determination
   any* = distinct auto ## meta type for any supported type
   untyped* {.magic: Expr.} ## meta type to denote an expression that
                            ## is not resolved (for templates)
@@ -104,7 +104,7 @@ type
   SomeNumber* = SomeInteger|SomeReal
     ## type class matching all number types
 
-proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
+proc defined*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
   ## Special compile-time procedure that checks whether `x` is
   ## defined.
   ## `x` is an external symbol introduced through the compiler's
@@ -125,7 +125,7 @@ when defined(nimalias):
     TNumber: SomeNumber,
     TOrdinal: SomeOrdinal].}
 
-proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
+proc declared*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
   ## Special compile-time procedure that checks whether `x` is
   ## declared. `x` has to be an identifier or a qualified identifier.
   ## This can be used to check whether a library provides a certain
@@ -140,11 +140,11 @@ when defined(useNimRtl):
   {.deadCodeElim: on.}
 
 proc definedInScope*(x: expr): bool {.
-  magic: "DefinedInScope", noSideEffect, deprecated.}
+  magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
   ## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
 
 proc declaredInScope*(x: expr): bool {.
-  magic: "DefinedInScope", noSideEffect.}
+  magic: "DefinedInScope", noSideEffect, compileTime.}
   ## Special compile-time procedure that checks whether `x` is
   ## declared in the current scope. `x` has to be an identifier.
 
@@ -160,7 +160,7 @@ proc unsafeAddr*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
   ## Cannot be overloaded.
   discard
 
-proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect.} =
+proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect, compileTime.} =
   ## Builtin 'type' operator for accessing the type of an expression.
   ## Cannot be overloaded.
   discard
@@ -221,11 +221,21 @@ proc high*[T](x: T): T {.magic: "High", noSideEffect.}
   ## the highest possible value of an ordinal value `x`. As a special
   ## semantic rule, `x` may also be a type identifier.
   ## ``high(int)`` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:.
+  ##
+  ## .. code-block:: nim
+  ##  var arr = [1,2,3,4,5,6,7]
+  ##  high(arr) #=> 6
+  ##  high(2) #=> 9223372036854775807
 
 proc low*[T](x: T): T {.magic: "Low", noSideEffect.}
   ## returns the lowest possible index of an array, a sequence, a string or
   ## the lowest possible value of an ordinal value `x`. As a special
   ## semantic rule, `x` may also be a type identifier.
+  ##
+  ## .. code-block:: nim
+  ##  var arr = [1,2,3,4,5,6,7]
+  ##  high(arr) #=> 0
+  ##  high(2) #=> -9223372036854775808
 
 type
   range*{.magic: "Range".}[T] ## Generic type to construct range types.
@@ -239,6 +249,14 @@ type
   seq*{.magic: "Seq".}[T]  ## Generic type to construct sequences.
   set*{.magic: "Set".}[T]  ## Generic type to construct bit sets.
 
+when defined(nimArrIdx):
+  # :array|openarray|string|seq|cstring|tuple
+  proc `[]`*[I: Ordinal;T](a: T; i: I): T {.
+    noSideEffect, magic: "ArrGet".}
+  proc `[]=`*[I: Ordinal;T,S](a: T; i: I;
+    x: S) {.noSideEffect, magic: "ArrPut".}
+  proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
+
 type
   Slice*[T] = object ## builtin slice type
     a*, b*: T        ## the bounds
@@ -576,6 +594,10 @@ proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.}
   ## its usage is discouraged - using ``new`` for the most cases suffices
   ## that one never needs to know ``x``'s size. As a special semantic rule,
   ## ``x`` may also be a type identifier (``sizeof(int)`` is valid).
+  ##
+  ## .. code-block:: nim
+  ##  sizeof('A') #=> 1
+  ##  sizeof(2) #=> 8
 
 when defined(nimtypedescfixed):
   proc sizeof*(x: typedesc): int {.magic: "SizeOf", noSideEffect.}
@@ -602,11 +624,21 @@ proc inc*[T: Ordinal|uint|uint64](x: var T, y = 1) {.magic: "Inc", noSideEffect.
   ## increments the ordinal ``x`` by ``y``. If such a value does not
   ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
   ## short notation for: ``x = succ(x, y)``.
+  ##
+  ## .. code-block:: nim
+  ##  var i = 2
+  ##  inc(i) #=> 3
+  ##  inc(i, 3) #=> 6
 
 proc dec*[T: Ordinal|uint|uint64](x: var T, y = 1) {.magic: "Dec", noSideEffect.}
   ## decrements the ordinal ``x`` by ``y``. If such a value does not
   ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
   ## short notation for: ``x = pred(x, y)``.
+  ##
+  ## .. code-block:: nim
+  ##  var i = 2
+  ##  dec(i) #=> 1
+  ##  dec(i, 3) #=> -2
 
 proc newSeq*[T](s: var seq[T], len: Natural) {.magic: "NewSeq", noSideEffect.}
   ## creates a new sequence of type ``seq[T]`` with length ``len``.
@@ -651,11 +683,22 @@ proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
   ## returns the length of an array, an openarray, a sequence or a string.
   ## This is roughly the same as ``high(T)-low(T)+1``, but its resulting type is
   ## always an int.
+  ##
+  ## .. code-block:: nim
+  ##  var arr = [1,1,1,1,1]
+  ##  len(arr) #=> 5
+  ##  for i in 0..<arr.len:
+  ##    echo arr[i] #=> 1,1,1,1,1
 
 # set routines:
 proc incl*[T](x: var set[T], y: T) {.magic: "Incl", noSideEffect.}
   ## includes element ``y`` to the set ``x``. This is the same as
   ## ``x = x + {y}``, but it might be more efficient.
+  ##
+  ## .. code-block:: nim
+  ##  var a = initSet[int](4)
+  ##  a.incl(2) #=> {2}
+  ##  a.incl(3) #=> {2, 3}
 
 template incl*[T](s: var set[T], flags: set[T]) =
   ## includes the set of flags to the set ``x``.
@@ -664,6 +707,10 @@ template incl*[T](s: var set[T], flags: set[T]) =
 proc excl*[T](x: var set[T], y: T) {.magic: "Excl", noSideEffect.}
   ## excludes element ``y`` to the set ``x``. This is the same as
   ## ``x = x - {y}``, but it might be more efficient.
+  ##
+  ## .. code-block:: nim
+  ##  var b = {2,3,5,6,12,545}
+  ##  b.excl(5)  #=> {2,3,6,12,545}
 
 template excl*[T](s: var set[T], flags: set[T]) =
   ## excludes the set of flags to ``x``.
@@ -672,12 +719,22 @@ template excl*[T](s: var set[T], flags: set[T]) =
 proc card*[T](x: set[T]): int {.magic: "Card", noSideEffect.}
   ## returns the cardinality of the set ``x``, i.e. the number of elements
   ## in the set.
+  ##
+  ## .. code-block:: nim
+  ##  var i = {1,2,3,4}
+  ##  card(i) #=> 4
 
 proc ord*[T](x: T): int {.magic: "Ord", noSideEffect.}
   ## returns the internal int value of an ordinal value ``x``.
+  ##
+  ## .. code-block:: nim
+  ##  ord('A') #=> 65
 
 proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.}
   ## converts an int in the range 0..255 to a character.
+  ##
+  ## .. code-block:: nim
+  ##  chr(65) #=> A
 
 # --------------------------------------------------------------------------
 # built-in operators
@@ -1175,9 +1232,12 @@ const
 
   seqShallowFlag = low(int)
 
-let nimvm* {.magic: "Nimvm".}: bool = false
+when defined(nimKnowsNimvm):
+  let nimvm* {.magic: "Nimvm".}: bool = false
     ## may be used only in "when" expression.
     ## It is true in Nim VM context and false otherwise
+else:
+  const nimvm*: bool = false
 
 proc compileOption*(option: string): bool {.
   magic: "CompileOption", noSideEffect.}
@@ -1196,7 +1256,7 @@ proc compileOption*(option, arg: string): bool {.
   ##     echo "compiled with optimization for size and uses Boehm's GC"
 
 const
-  hasThreadSupport = compileOption("threads")
+  hasThreadSupport = compileOption("threads") and not defined(nimscript)
   hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
   taintMode = compileOption("taintmode")
 
@@ -1288,6 +1348,10 @@ proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
   ## containers should also call their adding proc `add` for consistency.
   ## Generic code becomes much easier to write if the Nim naming scheme is
   ## respected.
+  ##
+  ## .. code-block:: nim
+  ##   var s: seq[string] = @["test2","test2"]
+  ##   s.add("test") #=> @[test2, test2, test]
   let xl = x.len
   setLen(x, xl + y.len)
   for i in 0..high(y): x[xl+i] = y[i]
@@ -1302,31 +1366,66 @@ proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
 proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
   ## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
   ## This is an O(1) operation.
-  let xl = x.len
-  shallowCopy(x[i], x[xl-1])
-  setLen(x, xl-1)
+  ##
+  ## .. code-block:: nim
+  ##  var i = @[1,2,3,4,5]
+  ##  i.del(2) #=> @[1, 2, 5, 4]
+  let xl = x.len - 1
+  shallowCopy(x[i], x[xl])
+  setLen(x, xl)
 
 proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
   ## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
   ## This is an O(n) operation.
-  let xl = x.len
-  for j in i..xl-2: shallowCopy(x[j], x[j+1])
-  setLen(x, xl-1)
+  ##
+  ## .. code-block:: nim
+  ##  var i = @[1,2,3,4,5]
+  ##  i.delete(2) #=> @[1, 2, 4, 5]
+  template defaultImpl =
+    let xl = x.len
+    for j in i..xl-2: shallowCopy(x[j], x[j+1])
+    setLen(x, xl-1)
+
+  when nimvm:
+    defaultImpl()
+  else:
+    when defined(js):
+      {.emit: "`x`[`x`_Idx].splice(`i`, 1);".}
+    else:
+      defaultImpl()
 
 proc insert*[T](x: var seq[T], item: T, i = 0.Natural) {.noSideEffect.} =
   ## inserts `item` into `x` at position `i`.
-  let xl = x.len
-  setLen(x, xl+1)
-  var j = xl-1
-  while j >= i:
-    shallowCopy(x[j+1], x[j])
-    dec(j)
+  ##
+  ## .. code-block:: nim
+  ##  var i = @[1,2,3,4,5]
+  ##  i.insert(2,4) #=> @[1, 2, 3, 4, 2, 5]
+  template defaultImpl =
+    let xl = x.len
+    setLen(x, xl+1)
+    var j = xl-1
+    while j >= i:
+      shallowCopy(x[j+1], x[j])
+      dec(j)
+  when nimvm:
+    defaultImpl()
+  else:
+    when defined(js):
+      {.emit: "`x`[`x`_Idx].splice(`i`, 0, null);".}
+    else:
+      defaultImpl()
   x[i] = item
 
 proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.}
   ## takes any Nim variable and returns its string representation. It
   ## works even for complex data graphs with cycles. This is a great
   ## debugging tool.
+  ##
+  ## .. code-block:: nim
+  ##  var s: seq[string] = @["test2","test2"]
+  ##  var i = @[1,2,3,4,5]
+  ##  repr(s) #=> 0x1055eb050[0x1055ec050"test2", 0x1055ec078"test2"]
+  ##  repr(i) #=> 0x1055ed050[1, 2, 3, 4, 5]
 
 type
   ByteAddress* = int
@@ -2216,7 +2315,9 @@ proc `$`*[T: tuple|object](x: T): string =
     firstElement = false
   result.add(")")
 
-proc collectionToString[T](x: T, b, e: string): string =
+proc collectionToString[T: set | seq](x: T, b, e: string): string =
+  when x is seq:
+    if x.isNil: return "nil"
   result = b
   var firstElement = true
   for value in items(x):
@@ -3373,7 +3474,7 @@ when hasAlloc:
       x[j+i] = item[j]
       inc(j)
 
-proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
+proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect, compileTime.} =
   ## Special compile-time procedure that checks whether `x` can be compiled
   ## without any semantic error.
   ## This can be used to check whether a type supports some operation:
@@ -3437,7 +3538,7 @@ when hasAlloc and not defined(nimscript) and not defined(JS):
 
   include "system/deepcopy"
 
-proc procCall*(x: expr) {.magic: "ProcCall".} =
+proc procCall*(x: expr) {.magic: "ProcCall", compileTime.} =
   ## special magic to prohibit dynamic binding for `method`:idx: calls.
   ## This is similar to `super`:idx: in ordinary OO languages.
   ##
@@ -3446,6 +3547,7 @@ proc procCall*(x: expr) {.magic: "ProcCall".} =
   ##   procCall someMethod(a, b)
   discard
 
+proc `^`*[T](x: int; y: openArray[T]): int {.noSideEffect, magic: "Roof".}
 proc `^`*(x: int): int {.noSideEffect, magic: "Roof".} =
   ## builtin `roof`:idx: operator that can be used for convenient array access.
   ## ``a[^x]`` is rewritten to ``a[a.len-x]``. However currently the ``a``
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 13a10e46f..3ebbc8c1e 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -27,10 +27,60 @@ sysAssert(roundup(65, 8) == 72, "roundup broken 2")
 # some platforms have really weird unmap behaviour: unmap(blockStart, PageSize)
 # really frees the whole block. Happens for Linux/PowerPC for example. Amd64
 # and x86 are safe though; Windows is special because MEM_RELEASE can only be
-# used with a size of 0:
-const weirdUnmap = not (defined(amd64) or defined(i386)) or defined(windows)
+# used with a size of 0. We also allow unmapping to be turned off with
+# -d:nimAllocNoUnmap:
+const doNotUnmap = not (defined(amd64) or defined(i386)) or
+                   defined(windows) or defined(nimAllocNoUnmap)
 
-when defined(posix):
+
+when defined(emscripten):
+  const
+    PROT_READ  = 1             # page can be read
+    PROT_WRITE = 2             # page can be written
+    MAP_PRIVATE = 2'i32        # Changes are private
+
+  var MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint
+  type 
+    PEmscriptenMMapBlock = ptr EmscriptenMMapBlock
+    EmscriptenMMapBlock {.pure, inheritable.} = object
+      realSize: int        # size of previous chunk; for coalescing
+      realPointer: pointer     # if < PageSize it is a small chunk
+
+  proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
+            off: int): pointer {.header: "<sys/mman.h>".}
+
+  proc munmap(adr: pointer, len: int) {.header: "<sys/mman.h>".}
+
+  proc osAllocPages(block_size: int): pointer {.inline.} =
+    let realSize = block_size + sizeof(EmscriptenMMapBlock) + PageSize + 1
+    result = mmap(nil, realSize, PROT_READ or PROT_WRITE,
+                             MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
+    if result == nil or result == cast[pointer](-1):
+      raiseOutOfMem()
+
+    let realPointer = result
+    let pos = cast[int](result)
+
+    # Convert pointer to PageSize correct one.
+    var new_pos = cast[ByteAddress](pos) +% (PageSize - (pos %% PageSize))
+    if (new_pos-pos)< sizeof(EmscriptenMMapBlock):
+      new_pos = new_pos +% PageSize
+    result = cast[pointer](new_pos)
+
+    var mmapDescrPos = cast[ByteAddress](result) -% sizeof(EmscriptenMMapBlock)
+
+    var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
+    mmapDescr.realSize = realSize
+    mmapDescr.realPointer = realPointer
+
+    c_fprintf(c_stdout, "[Alloc] size %d %d realSize:%d realPos:%d\n", block_size, cast[int](result), realSize, cast[int](realPointer))
+
+  proc osDeallocPages(p: pointer, size: int) {.inline} =
+    var mmapDescrPos = cast[ByteAddress](p) -% sizeof(EmscriptenMMapBlock)
+    var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
+    munmap(mmapDescr.realPointer, mmapDescr.realSize)
+
+elif defined(posix):
   const
     PROT_READ  = 1             # page can be read
     PROT_WRITE = 2             # page can be written
@@ -478,7 +528,7 @@ proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
           excl(a.chunkStarts, pageIndex(c))
           c = cast[PBigChunk](le)
 
-  if c.size < ChunkOsReturn or weirdUnmap:
+  if c.size < ChunkOsReturn or doNotUnmap:
     incl(a, a.chunkStarts, pageIndex(c))
     updatePrevSize(a, c, c.size)
     listAdd(a.freeChunksList, c)
@@ -762,7 +812,7 @@ proc deallocOsPages(a: var MemRegion) =
   # we free every 'ordinarily' allocated page by iterating over the page bits:
   for p in elements(a.chunkStarts):
     var page = cast[PChunk](p shl PageShift)
-    when not weirdUnmap:
+    when not doNotUnmap:
       var size = if page.size < PageSize: PageSize else: page.size
       osDeallocPages(page, size)
     else:
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index ceb362378..47e8b4b1f 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -95,7 +95,9 @@ proc setupForeignThreadGc*() =
 # ----------------- stack management --------------------------------------
 #  inspired from Smart Eiffel
 
-when defined(sparc):
+when defined(emscripten):
+  const stackIncreases = true
+elif defined(sparc):
   const stackIncreases = false
 elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
      defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820):
@@ -162,9 +164,9 @@ elif stackIncreases:
   proc isOnStack(p: pointer): bool =
     var stackTop {.volatile.}: pointer
     stackTop = addr(stackTop)
-    var a = cast[TAddress](gch.stackBottom)
-    var b = cast[TAddress](stackTop)
-    var x = cast[TAddress](p)
+    var a = cast[ByteAddress](gch.stackBottom)
+    var b = cast[ByteAddress](stackTop)
+    var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
 
   var
@@ -173,14 +175,14 @@ elif stackIncreases:
       # in a platform independent way
 
   template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
-    var registers: C_JmpBuf
+    var registers {.noinit.}: C_JmpBuf
     if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
-      var max = cast[TAddress](gch.stackBottom)
-      var sp = cast[TAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
+      var max = cast[ByteAddress](gch.stackBottom)
+      var sp = cast[ByteAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
       # sp will traverse the JMP_BUF as well (jmp_buf size is added,
       # otherwise sp would be below the registers structure).
       while sp >=% max:
-        gcMark(gch, cast[ppointer](sp)[])
+        gcMark(gch, cast[PPointer](sp)[])
         sp = sp -% sizeof(pointer)
 
 else:
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
index 4841749a9..22430348c 100644
--- a/lib/system/nimscript.nim
+++ b/lib/system/nimscript.nim
@@ -31,7 +31,8 @@ proc moveFile(src, dest: string) {.
   tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
 proc copyFile(src, dest: string) {.
   tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
-proc createDir(dir: string) {.tags: [WriteIOEffect], raises: [OSError].} = builtin
+proc createDir(dir: string) {.tags: [WriteIOEffect], raises: [OSError].} =
+  builtin
 proc getOsError: string = builtin
 proc setCurrentDir(dir: string) = builtin
 proc getCurrentDir(): string = builtin
@@ -56,7 +57,7 @@ proc getCommand*(): string =
   ## "c", "js", "build", "help".
   builtin
 
-proc setCommand*(cmd: string) =
+proc setCommand*(cmd: string; project="") =
   ## Sets the Nim command that should be continued with after this Nimscript
   ## has finished.
   builtin
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index b4188527f..1f81a0813 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -21,9 +21,22 @@ proc reprPointer(x: pointer): string {.compilerproc.} =
   return $buf
 
 proc `$`(x: uint64): string =
-  var buf: array [0..59, char]
-  discard c_sprintf(buf, "%llu", x)
-  return $buf
+  if x == 0:
+    result = "0"
+  else:
+    var buf: array [60, char]
+    var i = 0
+    var n = x
+    while n != 0:
+      let nn = n div 10'u64
+      buf[i] = char(n - 10'u64 * nn + ord('0'))
+      inc i
+      n = nn
+
+    let half = i div 2
+    # Reverse
+    for t in 0 .. < half: swap(buf[t], buf[i-t-1])
+    result = $buf
 
 proc reprStrAux(result: var string, s: string) =
   if cast[pointer](s) == nil:
@@ -294,4 +307,3 @@ when not defined(useNimRtl):
       reprAux(result, addr(p), typ, cl)
     add result, "\n"
     deinitReprClosure(cl)
-
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 24015dd3a..89d86c62a 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -18,7 +18,7 @@ const
 type
   Handle* = int
   LONG* = int32
-  ULONG* = int
+  ULONG* = int32
   PULONG* = ptr int
   WINBOOL* = int32
   DWORD* = int32
@@ -108,6 +108,13 @@ const
 
   CREATE_UNICODE_ENVIRONMENT* = 1024'i32
 
+  PIPE_ACCESS_DUPLEX* = 0x00000003'i32
+  PIPE_ACCESS_INBOUND* = 1'i32
+  PIPE_ACCESS_OUTBOUND* = 2'i32
+  PIPE_NOWAIT* = 0x00000001'i32
+  SYNCHRONIZE* = 0x00100000'i32
+  FILE_FLAG_WRITE_THROUGH* = 0x80000000'i32
+
 proc closeHandle*(hObject: Handle): WINBOOL {.stdcall, dynlib: "kernel32",
     importc: "CloseHandle".}
 
@@ -125,6 +132,19 @@ proc createPipe*(hReadPipe, hWritePipe: var Handle,
                  nSize: int32): WINBOOL{.
     stdcall, dynlib: "kernel32", importc: "CreatePipe".}
 
+proc createNamedPipe*(lpName: WideCString,
+                     dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize,
+                     nInBufferSize, nDefaultTimeOut: int32,
+                     lpSecurityAttributes: ptr SECURITY_ATTRIBUTES): Handle {.
+    stdcall, dynlib: "kernel32", importc: "CreateNamedPipeW".}
+
+proc peekNamedPipe*(hNamedPipe: Handle, lpBuffer: pointer=nil,
+                    nBufferSize: int32 = 0,
+                    lpBytesRead: ptr int32 = nil,
+                    lpTotalBytesAvail: ptr int32 = nil,
+                    lpBytesLeftThisMessage: ptr int32 = nil): bool {.
+    stdcall, dynlib: "kernel32", importc: "PeekNamedPipe".}
+
 when useWinUnicode:
   proc createProcessW*(lpApplicationName, lpCommandLine: WideCString,
                      lpProcessAttributes: ptr SECURITY_ATTRIBUTES,
@@ -409,7 +429,7 @@ type
     bytes*: array[0..15, char]
 
   Sockaddr_in6* {.importc: "SOCKADDR_IN6",
-                   header: "winsock2.h".} = object
+                   header: "ws2tcpip.h".} = object
     sin6_family*: int16
     sin6_port*: int16 # unsigned
     sin6_flowinfo*: int32 # unsigned
@@ -511,6 +531,9 @@ proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
 proc getsockname*(s: SocketHandle, name: ptr SockAddr,
                   namelen: ptr SockLen): cint {.
   stdcall, importc: "getsockname", dynlib: ws2dll.}
+proc getpeername*(s: SocketHandle, name: ptr SockAddr,
+                  namelen: ptr SockLen): cint {.
+  stdcall, importc, dynlib: ws2dll.}
 proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
                  optlen: ptr SockLen): cint {.
   stdcall, importc: "getsockopt", dynlib: ws2dll.}
@@ -572,6 +595,9 @@ proc freeaddrinfo*(ai: ptr AddrInfo) {.
 proc inet_ntoa*(i: InAddr): cstring {.
   stdcall, importc, dynlib: ws2dll.}
 
+proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
+            stringBufSize: int32): cstring {.stdcall, importc, dynlib: ws2dll.}
+
 const
   MAXIMUM_WAIT_OBJECTS* = 0x00000040
 
@@ -609,12 +635,24 @@ const
 
   FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32
   FILE_FLAG_OPEN_REPARSE_POINT* = 0x00200000'i32
+  DUPLICATE_SAME_ACCESS* = 2
+  FILE_READ_DATA* = 0x00000001 # file & pipe
+  FILE_WRITE_DATA* = 0x00000002 # file & pipe
 
 # Error Constants
 const
   ERROR_ACCESS_DENIED* = 5
   ERROR_HANDLE_EOF* = 38
 
+proc duplicateHandle*(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE,
+                      hTargetProcessHandle: HANDLE,
+                      lpTargetHandle: ptr HANDLE,
+                      dwDesiredAccess: DWORD, bInheritHandle: WINBOOL,
+                      dwOptions: DWORD): WINBOOL{.stdcall, dynlib: "kernel32",
+    importc: "DuplicateHandle".}
+proc getCurrentProcess*(): HANDLE{.stdcall, dynlib: "kernel32",
+                                   importc: "GetCurrentProcess".}
+
 when useWinUnicode:
   proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD,
                     lpSecurityAttributes: pointer,
diff --git a/readme.md b/readme.md
index 6aa562f2a..57fc223d3 100644
--- a/readme.md
+++ b/readme.md
@@ -1,4 +1,8 @@
 # Nim Compiler
+
+[![Join the chat at https://gitter.im/nim-lang/Nim](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nim-lang/Nim?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+
 This repo contains the Nim compiler, Nim's stdlib, tools and
 documentation.
 
@@ -75,11 +79,11 @@ All rights reserved.
 # Build Status
 [**Build Waterfall**][waterfall]
 
-|        | Linux                                                                                                  | Windows                               | Mac                           |
-| ------ | -----                                                                                                  | -------                               | ---                           |
-| x86    | ![linux-x86][linux-x86-img]                                                                            | ![windows-x86][windows-x86-img]       | ![mac-x86][mac-x86-img]       |
-| x86_64 | ![linux-x86_64][linux-x86_64-img]                                                                      | ![windows-x86_64][windows-x86_64-img] | ![mac-x86_64][mac-x86_64-img] |
-| arm    | ![linux-armv5][linux-arm5-img]<br/> ![linux-armv6][linux-arm6-img]<br/> ![linux-armv7][linux-arm7-img] |                                       |                               |
+|        | Linux | Windows | Mac |
+| ------ | ----- | ------- | --- |
+| x86    | ![linux-x86][linux-x86-img] | ![windows-x86][windows-x86-img] | 
+| x86_64 | ![linux-x86_64][linux-x86_64-img] | ![windows-x86_64][windows-x86_64-img] | ![mac-x86_64][mac-x86_64-img] |
+| arm    | ![linux-armv5][linux-arm5-img]<br/> ![linux-armv6][linux-arm6-img]<br/> ![linux-armv7][linux-arm7-img]
 
 [linux-x86-img]:      http://buildbot.nim-lang.org/buildstatusimage?builder=linux-x32-builder
 [linux-x86_64-img]:   http://buildbot.nim-lang.org/buildstatusimage?builder=linux-x64-builder
@@ -90,7 +94,6 @@ All rights reserved.
 [windows-x86-img]:    http://buildbot.nim-lang.org/buildstatusimage?builder=windows-x32-builder
 [windows-x86_64-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=windows-x64-builder
 
-[mac-x86-img]:        http://buildbot.nim-lang.org/buildstatusimage?builder=mac-x32-builder
 [mac-x86_64-img]:     http://buildbot.nim-lang.org/buildstatusimage?builder=mac-x64-builder
 
 [waterfall]: http://buildbot.nim-lang.org/waterfall
diff --git a/tests/alias/talias.nim b/tests/alias/talias.nim
index 6addc4704..810ea2095 100644
--- a/tests/alias/talias.nim
+++ b/tests/alias/talias.nim
@@ -30,7 +30,7 @@ type
     c: char
     se: seq[TA]
 
-proc p(param1, param2: TC): TC =
+proc p(param1, param2: TC, param3: var TC): TC =
   var
     local: TC
     plocal: ptr TC
@@ -43,6 +43,7 @@ proc p(param1, param2: TC): TC =
   plocal2[] ?<| local
 
   param1 ?<| param2
+  local ?<| param3
 
   local.arr[0] !<| param1
   local.arr !<| param1
@@ -62,5 +63,5 @@ var
 a <| a
 a !<| b
 
-discard p(x, x)
+discard p(x, x, x)
 
diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim
index e5895abe1..443f769cd 100644
--- a/tests/async/tasyncawait.nim
+++ b/tests/async/tasyncawait.nim
@@ -2,7 +2,7 @@ discard """
   file: "tasyncawait.nim"
   output: "5000"
 """
-import asyncdispatch, rawsockets, net, strutils, os
+import asyncdispatch, nativesockets, net, strutils, os
 
 var msgCount = 0
 
@@ -18,7 +18,7 @@ proc sendMessages(client: TAsyncFD) {.async.} =
 
 proc launchSwarm(port: TPort) {.async.} =
   for i in 0 .. <swarmSize:
-    var sock = newAsyncRawSocket()
+    var sock = newAsyncNativeSocket()
 
     await connect(sock, "localhost", port)
     await sendMessages(sock)
@@ -38,7 +38,7 @@ proc readMessages(client: TAsyncFD) {.async.} =
         doAssert false
 
 proc createServer(port: TPort) {.async.} =
-  var server = newAsyncRawSocket()
+  var server = newAsyncNativeSocket()
   block:
     var name: Sockaddr_in
     when defined(windows):
diff --git a/tests/async/tasyncconnect.nim b/tests/async/tasyncconnect.nim
index bc63b8e82..3dac379b2 100644
--- a/tests/async/tasyncconnect.nim
+++ b/tests/async/tasyncconnect.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tasyncconnect.nim"
   exitcode: 1
-  outputsub: "Error: unhandled exception: Connection refused [Exception]"
+  outputsub: "Error: unhandled exception: Connection refused"
 """
 
 import
@@ -15,10 +15,11 @@ const
 
 
 when defined(windows) or defined(nimdoc):
-    discard
+    # TODO: just make it work on Windows for now.
+    quit("Error: unhandled exception: Connection refused")
 else:
     proc testAsyncConnect() {.async.} =
-        var s = newAsyncRawSocket()
+        var s = newAsyncNativeSocket()
 
         await s.connect(testHost, testPort)
 
diff --git a/tests/async/tasynceverror.nim b/tests/async/tasynceverror.nim
index 5575cfe82..22b4fe9a7 100644
--- a/tests/async/tasynceverror.nim
+++ b/tests/async/tasynceverror.nim
@@ -1,13 +1,13 @@
 discard """
   file: "tasynceverror.nim"
   exitcode: 1
-  outputsub: "Error: unhandled exception: Connection reset by peer [Exception]"
+  outputsub: "Error: unhandled exception: Connection reset by peer"
 """
 
 import
     asyncdispatch,
     asyncnet,
-    rawsockets,
+    nativesockets,
     os
 
 
@@ -17,10 +17,11 @@ const
 
 
 when defined(windows) or defined(nimdoc):
-    discard
+    # TODO: just make it work on Windows for now.
+    quit("Error: unhandled exception: Connection reset by peer")
 else:
     proc createListenSocket(host: string, port: Port): TAsyncFD =
-        result = newAsyncRawSocket()
+        result = newAsyncNativeSocket()
 
         SocketHandle(result).setSockOptInt(SOL_SOCKET, SO_REUSEADDR, 1)
 
diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim
index c4379f7d8..aab08e30f 100644
--- a/tests/async/tasyncexceptions.nim
+++ b/tests/async/tasyncexceptions.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tasyncexceptions.nim"
   exitcode: 1
-  outputsub: "Error: unhandled exception: foobar [Exception]"
+  outputsub: "Error: unhandled exception: foobar"
 """
 import asyncdispatch
 
diff --git a/tests/bind/tbind2.nim b/tests/bind/tbind2.nim
index d2219765d..0e0cbd788 100644
--- a/tests/bind/tbind2.nim
+++ b/tests/bind/tbind2.nim
@@ -1,6 +1,6 @@
 discard """
   file: "tbind2.nim"
-  line: 14
+  line: 12
   errormsg: "ambiguous call"
 """
 # Test the new ``bind`` keyword for templates
diff --git a/tests/ccgbugs/tnocodegen_for_compiletime.nim b/tests/ccgbugs/tnocodegen_for_compiletime.nim
new file mode 100644
index 000000000..a88ba4b32
--- /dev/null
+++ b/tests/ccgbugs/tnocodegen_for_compiletime.nim
@@ -0,0 +1,9 @@
+# bug #1679
+import macros, tables, hashes
+proc hash(v: NimNode): Hash = 4  # performance is for suckers
+macro test(body: stmt): stmt {.immediate.} =
+  var a = initCountTable[NimNode]()
+  a.inc(body)
+
+test:
+  1 + 1
diff --git a/tests/ccgbugs/twrong_discriminant_check.nim b/tests/ccgbugs/twrong_discriminant_check.nim
new file mode 100644
index 000000000..a802f45ef
--- /dev/null
+++ b/tests/ccgbugs/twrong_discriminant_check.nim
@@ -0,0 +1,30 @@
+discard """
+  output: "(kind: None)"
+"""
+
+when true:
+  # bug #2637
+
+  type
+    OptionKind = enum
+      None,
+      Some
+
+    Option*[T] = object
+      case kind: OptionKind
+      of None:
+        discard
+      of Some:
+        value*: T
+
+  proc none*[T](): Option[T] =
+    Option[T](kind: None)
+
+  proc none*(T: typedesc): Option[T] = none[T]()
+
+
+  proc test(): Option[int] =
+    int.none
+
+  echo test()
+
diff --git a/tests/ccgbugs/twrong_string_asgn.nim b/tests/ccgbugs/twrong_string_asgn.nim
new file mode 100644
index 000000000..b62e70e7c
--- /dev/null
+++ b/tests/ccgbugs/twrong_string_asgn.nim
@@ -0,0 +1,19 @@
+discard """
+  output: "adf"
+"""
+
+import asyncdispatch
+const
+  test = ["adf"]
+
+proc foo() {.async.} =
+  for i in test:
+    echo(i)
+
+var finished = false
+let x = foo()
+x.callback =
+  proc () =
+    finished = true
+
+while not finished: discard
diff --git a/tests/compiles/trecursive_generic_in_compiles.nim b/tests/compiles/trecursive_generic_in_compiles.nim
new file mode 100644
index 000000000..77bf0bb02
--- /dev/null
+++ b/tests/compiles/trecursive_generic_in_compiles.nim
@@ -0,0 +1,98 @@
+# bug #3313
+import unittest, future
+
+type
+  ListNodeKind = enum
+    lnkNil, lnkCons
+  List*[T] = ref object
+    ## List ADT
+    case kind: ListNodeKind
+    of lnkNil:
+      discard
+    of lnkCons:
+      value: T
+      next: List[T] not nil
+
+proc Cons*[T](head: T, tail: List[T]): List[T] =
+  ## Constructs non empty list
+  List[T](kind: lnkCons, value: head, next: tail)
+
+proc Nil*[T](): List[T] =
+  ## Constructs empty list
+  List[T](kind: lnkNil)
+
+proc head*[T](xs: List[T]): T =
+  ## Returns list's head
+  xs.value
+
+# TODO
+# proc headOption*[T](xs: List[T]): Option[T] = ???
+
+proc tail*[T](xs: List[T]): List[T] =
+  ## Returns list's tail
+  case xs.kind
+  of lnkCons: xs.next
+  else: xs
+
+proc isEmpty*(xs: List): bool =
+  ## Checks  if list is empty
+  xs.kind == lnkNil
+
+proc `==`*[T](xs, ys: List[T]): bool =
+  ## Compares two lists
+  if (xs.isEmpty, ys.isEmpty) == (true, true): true
+  elif (xs.isEmpty, ys.isEmpty) == (false, false): xs.head == ys.head and xs.tail == ys.tail
+  else: false
+
+proc asList*[T](xs: varargs[T]): List[T] =
+  ## Creates list from varargs
+  proc initListImpl(i: int, xs: openarray[T]): List[T] =
+    if i > high(xs):
+      Nil[T]()
+    else:
+      Cons(xs[i], initListImpl(i+1, xs))
+  initListImpl(0, xs)
+
+proc foldRight*[T,U](xs: List[T], z: U, f: (T, U) -> U): U =
+  case xs.isEmpty
+  of true: z
+  else: f(xs.head, xs.tail.foldRight(z, f))
+
+proc dup*[T](xs: List[T]): List[T] =
+  ## Duplicates the list
+  xs.foldRight(Nil[T](), (x: T, xs: List[T]) => Cons(x, xs))
+
+type
+  ListFormat = enum
+    lfADT, lfSTD
+
+proc asString[T](xs: List[T], f = lfSTD): string =
+  proc asAdt(xs: List[T]): string =
+    case xs.isEmpty
+    of true: "Nil"
+    else: "Cons(" & $xs.head & ", " & xs.tail.asAdt & ")"
+
+  proc asStd(xs: List[T]): string =
+    "List(" & xs.foldLeft("", (s: string, v: T) =>
+      (if s == "": $v else: s & ", " & $v)) & ")"
+
+  case f
+  of lfADT: xs.asAdt
+  else: xs.asStd
+
+proc `$`*[T](xs: List[T]): string =
+  ## Converts list to string
+  result = xs.asString
+
+proc foldLeft*[T,U](xs: List[T], z: U, f: (U, T) -> U): U =
+  case xs.isEmpty
+  of true: z
+  else: foldLeft(xs.tail, f(z, xs.head), f)
+
+suite "unittest compilation error":
+
+  test "issue 3313":
+    let lst = lc[$x | (x <- 'a'..'z'), string].asList
+
+    let lstCopy = lst.dup
+    check: lstCopy == lst
diff --git a/tests/cpp/trawsockets.nim b/tests/cpp/tnativesockets.nim
index bc129de57..6108380a8 100644
--- a/tests/cpp/trawsockets.nim
+++ b/tests/cpp/tnativesockets.nim
@@ -2,4 +2,4 @@ discard """
   cmd: "nim cpp $file"
 """
 
-import rawsockets
+import nativesockets
diff --git a/tests/discard/tvoidcontext.nim b/tests/discard/tvoidcontext.nim
new file mode 100644
index 000000000..c3ea68bae
--- /dev/null
+++ b/tests/discard/tvoidcontext.nim
@@ -0,0 +1,12 @@
+discard """
+  errormsg: "value of type 'string' has to be discarded"
+  line: 12
+"""
+
+proc valid*(): string =
+  let x = 317
+  "valid"
+
+proc invalid*(): string =
+  result = "foo"
+  "invalid"
diff --git a/tests/enum/tenummix.nim b/tests/enum/tenummix.nim
index 4352cdd81..c7db4e056 100644
--- a/tests/enum/tenummix.nim
+++ b/tests/enum/tenummix.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tenummix.nim"
-  line: 11
+  tfile: "tenummix.nim"
+  tline: 11
   errormsg: "type mismatch"
 """
 
diff --git a/tests/gc/gcemscripten.nim b/tests/gc/gcemscripten.nim
new file mode 100644
index 000000000..bbef13d98
--- /dev/null
+++ b/tests/gc/gcemscripten.nim
@@ -0,0 +1,59 @@
+discard """
+  outputsub: "77\n77"
+"""
+
+## Check how GC/Alloc works in Emscripten
+import strutils
+
+type
+  X = ref XObj
+  XObj = object
+    name: string
+    value: int
+when defined(allow_print):
+  const print = true
+else:
+  const print = false
+
+proc myResult3*(i:int):X {.exportc.} =
+  if print: echo "3"
+  new(result)
+  if print: echo "3-2"
+  result.value = i
+
+proc myResult5*(i:int, x:X):X {.exportc.} =
+  if print: echo "5"
+  system.GC_fullCollect()
+  new(result)
+  if print: echo "5-2"
+  result.value = i
+  x.value = i+1
+  if result.value == x.value:
+    echo "This should not happen. Just allocated variable points to parameter"
+
+proc myResult2*(val: string, i: int): X {.exportc.} =
+  if print: echo "2-1"
+  result = myResult3(i)
+  if print: echo "2-2"
+  system.GC_fullCollect()
+  if print: echo "2-3"
+  var t = new(X)
+  if print: echo "2-4"
+  result.name = val
+  if t.name == "qwe":
+    echo "This should not happen. Variable is GC collected and new one on same place are allocated."
+  if print: echo "2-5"
+
+proc myResult4*(val: string, i: int): X {.exportc.} =
+  if print: echo "4-1"
+  result = myResult5(i, X())
+  if print: echo "4-2"
+
+var x = myResult2("qwe", 77)
+echo intToStr(x.value)
+
+var x2 = myResult4("qwe", 77)
+echo intToStr(x2.value)
+
+
+
diff --git a/tests/generics/mbind_bracket.nim b/tests/generics/mbind_bracket.nim
new file mode 100644
index 000000000..4bf18b471
--- /dev/null
+++ b/tests/generics/mbind_bracket.nim
@@ -0,0 +1,17 @@
+
+import tables
+
+type
+  UUIDObject* = ref object
+    uuid: string
+
+  Registry*[T] = ref object
+    objects: Table[string, T]
+
+proc newRegistry*[T](): Registry[T] =
+  result = Registry[T]()
+  result.objects = initTable[string, T](128)
+
+proc register*[T](self: Registry[T], obj: T) =
+  self.objects[obj.uuid] = obj
+
diff --git a/tests/generics/tbind_bracket.nim b/tests/generics/tbind_bracket.nim
new file mode 100644
index 000000000..d0c5e2c6b
--- /dev/null
+++ b/tests/generics/tbind_bracket.nim
@@ -0,0 +1,20 @@
+discard """
+  output: "317"
+"""
+
+# bug #2599
+
+import mbind_bracket
+
+# also test that `[]` can be passed now as a first class construct:
+
+template takeBracket(x, a, i: untyped) =
+  echo x(a, i)
+
+var a: array[10, int]
+a[8] = 317
+
+takeBracket(`[]`, a, 8)
+
+let reg = newRegistry[UUIDObject]()
+reg.register(UUIDObject())
diff --git a/tests/generics/tmap_auto.nim b/tests/generics/tmap_auto.nim
new file mode 100644
index 000000000..dea9b571f
--- /dev/null
+++ b/tests/generics/tmap_auto.nim
@@ -0,0 +1,13 @@
+import future
+
+let x = map(@[1, 2, 3], x => x+10)
+assert x == @[11, 12, 13]
+
+let y = map(@[(1,"a"), (2,"b"), (3,"c")], x => $x[0] & x[1])
+assert y == @["1a", "2b", "3c"]
+
+proc eatsTwoArgProc[T,S,U](a: T, b: S, f: proc(t: T, s: S): U): U =
+  f(a,b)
+
+let z = eatsTwoArgProc(1, "a", (t,s) => $t & s)
+assert z == "1a"
diff --git a/tests/generics/tthread_generic.nim b/tests/generics/tthread_generic.nim
index d34b24628..e8946caf6 100644
--- a/tests/generics/tthread_generic.nim
+++ b/tests/generics/tthread_generic.nim
@@ -3,7 +3,7 @@ discard """
 """
 
 type
-  TThreadFuncArgs[T] = object of TObject
+  TThreadFuncArgs[T] = object of RootObj
     a: proc(): T {.thread.}
     b: proc(val: T) {.thread.}
 
diff --git a/tests/macros/tgensym.nim b/tests/macros/tgensym.nim
index b3aef0a2c..a4d1a3606 100644
--- a/tests/macros/tgensym.nim
+++ b/tests/macros/tgensym.nim
@@ -1,6 +1,6 @@
-import rawsockets, asyncdispatch, macros
+import nativesockets, asyncdispatch, macros
 var p = newDispatcher()
-var sock = newAsyncRawSocket()
+var sock = newAsyncNativeSocket()
 
 proc convertReturns(node, retFutureSym: NimNode): NimNode {.compileTime.} =
   case node.kind
diff --git a/tests/manyloc/keineschweine/lib/zlib_helpers.nim b/tests/manyloc/keineschweine/lib/zlib_helpers.nim
index 5241a77c0..076475964 100644
--- a/tests/manyloc/keineschweine/lib/zlib_helpers.nim
+++ b/tests/manyloc/keineschweine/lib/zlib_helpers.nim
@@ -1,4 +1,4 @@
-import zlib
+import zip/zlib
 
 proc compress*(source: string): string =
   var
diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim
index 6dc453e8d..2fe07ec17 100644
--- a/tests/manyloc/nake/nakefile.nim
+++ b/tests/manyloc/nake/nakefile.nim
@@ -1,5 +1,5 @@
 import nake
-import httpclient, zipfiles, times, math
+import httpclient, zip/zipfiles, times, math
 nakeImports
 
 randomize()
diff --git a/tests/metatype/tprocbothmeta.nim b/tests/metatype/tprocbothmeta.nim
index ad12c5d26..ba061dda2 100644
--- a/tests/metatype/tprocbothmeta.nim
+++ b/tests/metatype/tprocbothmeta.nim
@@ -1,5 +1,5 @@
 
-proc myFun[A,B](x: A): B =
+proc myFun[A](x: A): auto =
   result = float(x+10)
 
 proc myMap[T,S](sIn: seq[T], f: proc (q: T): S): seq[S] =
diff --git a/tests/metatype/ttypedesc1.nim b/tests/metatype/ttypedesc1.nim
index 19072d966..d78c62a94 100644
--- a/tests/metatype/ttypedesc1.nim
+++ b/tests/metatype/ttypedesc1.nim
@@ -7,7 +7,7 @@ type
 
 proc getTypeName(t: typedesc): string = t.name
 
-proc foo(T: typedesc[float], a: expr): string =
+proc foo(T: typedesc[float], a: auto): string =
   result = "float " & $(a.len > 5)
 
 proc foo(T: typedesc[TFoo], a: int): string =
diff --git a/tests/metatype/tunresolved_return_type.nim b/tests/metatype/tunresolved_return_type.nim
new file mode 100644
index 000000000..f67e065ea
--- /dev/null
+++ b/tests/metatype/tunresolved_return_type.nim
@@ -0,0 +1,20 @@
+discard """
+  errormsg: "cannot instantiate: 'T'"
+  line: 12
+"""
+
+# bug #2594
+
+
+type
+  ResultValue* = int64
+
+proc toNumber[T: int|uint|int64|uint64](v: ResultValue): T =
+  if v < low(T) or v > high(T):
+    raise newException(RangeError, "protocol error")
+  return T(v)
+
+#proc toNumber[T](v: int32): T =
+#  return (v)
+
+echo toNumber(23)
diff --git a/tests/method/tmapper.nim b/tests/method/tmapper.nim
index 0008d9033..75b36e69a 100644
--- a/tests/method/tmapper.nim
+++ b/tests/method/tmapper.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "invalid declaration order; cannot attach 'step' to method defined here: tmapper.nim(22,7)"
+  errormsg: "invalid declaration order; cannot attach 'step' to method defined here: tests/method/tmapper.nim(22,7)"
   line: 25
 """
 
diff --git a/tests/misc/tnot.nim b/tests/misc/tnot.nim
index 60d23c035..8c75c6bc0 100644
--- a/tests/misc/tnot.nim
+++ b/tests/misc/tnot.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tnot.nim"
-  line: 14
+  tfile: "tnot.nim"
+  tline: 14
   errormsg: "type mismatch"
 """
 # BUG: following compiles, but should not:
@@ -17,6 +17,3 @@ proc main =
         echo "No"
 
 main()
-
-
-
diff --git a/tests/misc/tvarious1.nim b/tests/misc/tvarious1.nim
index 9d7cf6584..1d5ad876a 100644
--- a/tests/misc/tvarious1.nim
+++ b/tests/misc/tvarious1.nim
@@ -22,7 +22,7 @@ import queues
 
 type
   TWidget = object
-    names: TQueue[string]
+    names: Queue[string]
 
 var w = TWidget(names: initQueue[string]())
 
diff --git a/tests/modules/texport.nim b/tests/modules/texport.nim
index 0890fb369..a8c217ab8 100644
--- a/tests/modules/texport.nim
+++ b/tests/modules/texport.nim
@@ -5,7 +5,7 @@ discard """
 import mexporta
 
 # bug #1029:
-from rawsockets import accept
+from nativesockets import accept
 
 # B.TMyObject has been imported implicitly here:
 var x: TMyObject
diff --git a/tests/newconfig/tfoo.nim b/tests/newconfig/tfoo.nim
index 0ace7c88a..d593d4a75 100644
--- a/tests/newconfig/tfoo.nim
+++ b/tests/newconfig/tfoo.nim
@@ -4,4 +4,7 @@ discard """
   msg: '''[NimScript] exec: gcc -v'''
 """
 
+when not defined(definedefine):
+  {.fatal: "wrong nim script configuration".}
+
 echo "hello world!"
diff --git a/tests/newconfig/tfoo.nims b/tests/newconfig/tfoo.nims
index 90205cddb..519a868d5 100644
--- a/tests/newconfig/tfoo.nims
+++ b/tests/newconfig/tfoo.nims
@@ -3,6 +3,9 @@ mode = ScriptMode.Whatif
 
 exec "gcc -v"
 
+# test that ospaths actually compiles:
+import ospaths
+
 --forceBuild
 
 task listDirs, "lists every subdirectory":
@@ -10,5 +13,6 @@ task listDirs, "lists every subdirectory":
     echo "DIR ", x
 
 task default, "default target":
+  --define: definedefine
   setCommand "c"
 
diff --git a/tests/objects/tillegal_recursion.nim b/tests/objects/tillegal_recursion.nim
index 171a04f87..222139101 100644
--- a/tests/objects/tillegal_recursion.nim
+++ b/tests/objects/tillegal_recursion.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "illegal recursion in type 'object'"
+  errormsg: "inheritance only works with non-final objects"
   line: 7
 """
 # bug #1691
diff --git a/tests/parallel/tparfind.nim b/tests/parallel/tparfind.nim
new file mode 100644
index 000000000..9de5012f5
--- /dev/null
+++ b/tests/parallel/tparfind.nim
@@ -0,0 +1,28 @@
+discard """
+  output: "500"
+"""
+
+import threadpool, sequtils
+
+{.experimental.}
+
+proc linearFind(a: openArray[int]; x, offset: int): int =
+  for i, y in a:
+    if y == x: return i+offset
+  result = -1
+
+proc parFind(a: seq[int]; x: int): int =
+  var results: array[4, int]
+  parallel:
+    if a.len >= 4:
+      let chunk = a.len div 4
+      results[0] = spawn linearFind(a[0 ..< chunk], x, 0)
+      results[1] = spawn linearFind(a[chunk ..< chunk*2], x, chunk)
+      results[2] = spawn linearFind(a[chunk*2 ..< chunk*3], x, chunk*2)
+      results[3] = spawn linearFind(a[chunk*3 ..< a.len], x, chunk*3)
+  result = max(results)
+
+
+let data = toSeq(0..1000)
+echo parFind(data, 500)
+
diff --git a/tests/parser/tstrongspaces.nim b/tests/parser/tstrongspaces.nim
index e70b91988..cb0219976 100644
--- a/tests/parser/tstrongspaces.nim
+++ b/tests/parser/tstrongspaces.nim
@@ -1,4 +1,4 @@
-#! strongSpaces
+#? strongSpaces
 
 discard """
   output: '''35
diff --git a/tests/pragmas/tbitsize.nim b/tests/pragmas/tbitsize.nim
new file mode 100644
index 000000000..7a44944d2
--- /dev/null
+++ b/tests/pragmas/tbitsize.nim
@@ -0,0 +1,22 @@
+discard """
+ccodeCheck: "\\i @'unsigned int flag:1;' .*"
+"""
+
+type
+  bits* = object
+    flag* {.bitsize: 1.}: cuint
+    opts* {.bitsize: 4.}: cint
+
+var
+  b: bits
+
+assert b.flag == 0
+b.flag = 1
+assert b.flag == 1
+b.flag = 2
+assert b.flag == 0
+
+b.opts = 7
+assert b.opts == 7
+b.opts = 9
+assert b.opts == -7
diff --git a/tests/rational/trat_float.nim b/tests/rational/trat_float.nim
new file mode 100644
index 000000000..24797c4a0
--- /dev/null
+++ b/tests/rational/trat_float.nim
@@ -0,0 +1,9 @@
+discard """
+  file: "trat_float.nim"
+  line: "9,19"
+  errormsg: '''type mismatch: got'''
+"""
+import rationals
+var
+  # this fails - no floats as num or den
+  r = initRational(1.0'f, 1.0'f)
diff --git a/tests/rational/trat_init.nim b/tests/rational/trat_init.nim
new file mode 100644
index 000000000..df29ff6e3
--- /dev/null
+++ b/tests/rational/trat_init.nim
@@ -0,0 +1,10 @@
+discard """
+  file: "trat_init.nim"
+  exitcode: "1"
+"""
+import rationals
+var
+  z = Rational[int](num: 0, den: 1)
+  o = initRational(num=1, den=1)
+  a = initRational(1, 2)
+  r = initRational(1, 0)  # this fails - no zero denominator
diff --git a/tests/stdlib/tmemfiles1.nim b/tests/stdlib/tmemfiles1.nim
new file mode 100644
index 000000000..8b66dfcc1
--- /dev/null
+++ b/tests/stdlib/tmemfiles1.nim
@@ -0,0 +1,12 @@
+discard """
+  file: "tmemfiles1.nim"
+"""
+import memfiles, os
+var
+  mm: MemFile
+  fn = "test.mmap"
+# Create a new file
+mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 20)
+mm.close()
+mm.close()
+if fileExists(fn): removeFile(fn)
diff --git a/tests/stdlib/tmemfiles2.nim b/tests/stdlib/tmemfiles2.nim
new file mode 100644
index 000000000..026443e93
--- /dev/null
+++ b/tests/stdlib/tmemfiles2.nim
@@ -0,0 +1,39 @@
+discard """
+  file: "tmemfiles2.nim"
+  disabled: true
+  output: '''Full read size: 20
+Half read size: 10 Data: Hello'''
+"""
+# doesn't work on windows. fmReadWrite doesn't create a file.
+import memfiles, os
+var
+  mm, mm_full, mm_half: MemFile
+  fn = "test.mmap"
+  p: pointer
+
+if fileExists(fn): removeFile(fn)
+
+# Create a new file, data all zeros
+mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 20)
+mm.close()
+
+# read, change
+mm_full = memfiles.open(fn, mode = fmWrite, mappedSize = -1)
+echo "Full read size: ",mm_full.size
+p = mm_full.mapMem(fmReadWrite, 20, 0)
+var p2 = cast[cstring](p)
+p2[0] = 'H'
+p2[1] = 'e'
+p2[2] = 'l'
+p2[3] = 'l'
+p2[4] = 'o'
+p2[5] = '\0'
+mm_full.unmapMem(p, 20)
+mm_full.close()
+
+# read half, and verify data change
+mm_half = memfiles.open(fn, mode = fmRead, mappedSize = 10)
+echo "Half read size: ",mm_half.size, " Data: ", cast[cstring](mm_half.mem)
+mm_half.close()
+
+if fileExists(fn): removeFile(fn)
diff --git a/tests/stdlib/tstreams2.nim b/tests/stdlib/tstreams2.nim
new file mode 100644
index 000000000..90102d8e3
--- /dev/null
+++ b/tests/stdlib/tstreams2.nim
@@ -0,0 +1,13 @@
+discard """
+  file: "tstreams2.nim"
+  output: '''fs is: nil'''
+"""
+import streams
+var
+  fs = newFileStream("amissingfile.txt")
+  line = ""
+echo "fs is: ",repr(fs)
+if not isNil(fs):
+  while fs.readLine(line):
+    echo line
+  fs.close()
diff --git a/tests/system/tfloatToString.nim b/tests/system/tfloatToString.nim
deleted file mode 100644
index bb45a91d7..000000000
--- a/tests/system/tfloatToString.nim
+++ /dev/null
@@ -1,22 +0,0 @@
-discard """
-  output:'''2.3242
-2.982
-123912.1
-123912.1823
-5.0
-1e+100
-inf
--inf
-nan
-'''
-"""
-
-echo($(2.3242))
-echo($(2.982))
-echo($(123912.1))
-echo($(123912.1823))
-echo($(5.0))
-echo($(1e100))
-echo($(1e1000000))
-echo($(-1e1000000))
-echo($(0.0/0.0))
diff --git a/tests/system/toString.nim b/tests/system/toString.nim
index 52e7a4b92..a2337f5dd 100644
--- a/tests/system/toString.nim
+++ b/tests/system/toString.nim
@@ -1,9 +1,42 @@
 discard """
   output:'''@[23, 45]
-@[, foo, bar]'''
+@[, foo, bar]
+{a, b, c}
+2.3242
+2.982
+123912.1
+123912.1823
+5.0
+1e+100
+inf
+-inf
+nan
+nil
+nil'''
 """
 
 echo($(@[23, 45]))
 echo($(@["", "foo", "bar"]))
 #echo($(["", "foo", "bar"]))
 #echo($([23, 45]))
+
+# bug #2395
+
+let alphaSet: set[char] = {'a'..'c'}
+echo alphaSet
+
+echo($(2.3242))
+echo($(2.982))
+echo($(123912.1))
+echo($(123912.1823))
+echo($(5.0))
+echo($(1e100))
+echo($(1e1000000))
+echo($(-1e1000000))
+echo($(0.0/0.0))
+
+# nil tests
+var x: seq[string]
+var y: string
+echo(x)
+echo(y)
diff --git a/tests/system/tsettostring.nim b/tests/system/tsettostring.nim
deleted file mode 100644
index c6846ee99..000000000
--- a/tests/system/tsettostring.nim
+++ /dev/null
@@ -1,8 +0,0 @@
-discard """
-  output: "{a, b, c}"
-"""
-
-# bug #2395
-
-let alphaSet: set[char] = {'a'..'c'}
-echo alphaSet
diff --git a/tests/template/sunset.tmpl b/tests/template/sunset.tmpl
index 6475bac4e..465b12a5e 100644
--- a/tests/template/sunset.tmpl
+++ b/tests/template/sunset.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl
+#? stdtmpl
 #proc sunsetTemplate*(current, ticker, content: string,
 #                     tabs: openarray[array[0..1, string]]): string = 
 #  result = ""
diff --git a/tests/template/twrongmapit.nim b/tests/template/twrongmapit.nim
index bca1292b8..0a6d694f6 100644
--- a/tests/template/twrongmapit.nim
+++ b/tests/template/twrongmapit.nim
@@ -1,7 +1,5 @@
 discard """
-  errormsg: "'"
-  file: "sequtils.nim"
-  line: 435
+  output: "####"
 """
 # unfortunately our tester doesn't support multiple lines of compiler
 # error messages yet...
@@ -29,4 +27,6 @@ when ATTEMPT == 0:
 # bug #1543
 import sequtils
 
-(var i= @[""];i).mapIt(it)
+(var i = @[""];i).mapIt(it)
+# now works:
+echo "##", i[0], "##"
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 10e39b20a..33ce086d3 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -89,8 +89,11 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) =
     var libpath = getEnv"LD_LIBRARY_PATH".string
     # Temporarily add the lib directory to LD_LIBRARY_PATH:
     putEnv("LD_LIBRARY_PATH", "lib:" & libpath)
+    defer: putEnv("LD_LIBRARY_PATH", libpath)
     var serverDll = DynlibFormat % "server"
     safeCopyFile("tests/dll" / serverDll, "lib" / serverDll)
+    var nimrtlDll = DynlibFormat % "nimrtl"
+    safeCopyFile("tests/dll" / nimrtlDll, "lib" / nimrtlDll)
 
   testSpec r, makeTest("tests/dll/client.nim", options & " -d:useNimRtl",
                        cat, actionRun)
@@ -127,6 +130,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
     testSpec r, makeTest("tests/gc" / filename, options &
                   " -d:release --gc:boehm", cat, actionRun)
 
+  test "gcemscripten"
   test "growobjcrash"
   test "gcbench"
   test "gcleak"
@@ -345,7 +349,7 @@ proc `&?.`(a, b: string): string =
   # candidate for the stdlib?
   result = if a.endswith(b): a else: a & b
 
-proc processCategory(r: var TResults, cat: Category, options: string) =
+proc processCategory(r: var TResults, cat: Category, options: string, fileGlob: string = "t*.nim") =
   case cat.string.normalize
   of "rodfiles":
     discard # Disabled for now
@@ -382,5 +386,5 @@ proc processCategory(r: var TResults, cat: Category, options: string) =
   of "nimble-all":
     testNimblePackages(r, cat, pfAll)
   else:
-    for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"):
+    for name in os.walkFiles("tests" & DirSep &.? cat.string / fileGlob):
       testSpec r, makeTest(name, options, cat)
diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim
index 99640f22c..bab17d2cd 100644
--- a/tests/testament/specs.nim
+++ b/tests/testament/specs.nim
@@ -44,6 +44,8 @@ type
     file*, cmd*: string
     outp*: string
     line*, column*: int
+    tfile*: string
+    tline*, tcolumn*: int
     exitCode*: int
     msg*: string
     ccodeCheck*: string
@@ -101,6 +103,9 @@ proc specDefaults*(result: var TSpec) =
   result.cmd = cmdTemplate
   result.line = 0
   result.column = 0
+  result.tfile = ""
+  result.tline = 0
+  result.tcolumn = 0
 
 proc parseSpec*(filename: string): TSpec =
   specDefaults(result)
@@ -116,6 +121,9 @@ proc parseSpec*(filename: string): TSpec =
     of "file": result.file = e.value
     of "line": discard parseInt(e.value, result.line)
     of "column": discard parseInt(e.value, result.column)
+    of "tfile": result.tfile = e.value
+    of "tline": discard parseInt(e.value, result.tline)
+    of "tcolumn": discard parseInt(e.value, result.tcolumn)
     of "output":
       result.action = actionRun
       result.outp = e.value
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index b138c9909..636093a7f 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -23,6 +23,7 @@ const
 Command:
   all                         run all tests
   c|category <category>       run all the tests of a certain category
+  r|run <test>                run single test file
   html [commit]               generate $1 from the database; uses the latest
                               commit or a specific one (use -1 for the commit
                               before latest etc)
@@ -52,6 +53,8 @@ type
 let
   pegLineError =
     peg"{[^(]*} '(' {\d+} ', ' {\d+} ') ' ('Error') ':' \s* {.*}"
+  pegLineTemplate =
+    peg"{[^(]*} '(' {\d+} ', ' {\d+} ') ' 'template/generic instantiation from here'.*"
   pegOtherError = peg"'Error:' \s* {.*}"
   pegSuccess = peg"'Hint: operation successful'.*"
   pegOfInterest = pegLineError / pegOtherError
@@ -65,6 +68,7 @@ proc callCompiler(cmdTemplate, filename, options: string,
   let outp = p.outputStream
   var suc = ""
   var err = ""
+  var tmpl = ""
   var x = newStringOfCap(120)
   result.nimout = ""
   while outp.readLine(x.TaintedString) or running(p):
@@ -72,6 +76,9 @@ proc callCompiler(cmdTemplate, filename, options: string,
     if x =~ pegOfInterest:
       # `err` should contain the last error/warning message
       err = x
+    elif x =~ pegLineTemplate and err == "":
+      # `tmpl` contains the last template expansion before the error
+      tmpl = x
     elif x =~ pegSuccess:
       suc = x
   close(p)
@@ -80,6 +87,13 @@ proc callCompiler(cmdTemplate, filename, options: string,
   result.outp = ""
   result.line = 0
   result.column = 0
+  result.tfile = ""
+  result.tline = 0
+  result.tcolumn = 0
+  if tmpl =~ pegLineTemplate:
+    result.tfile = extractFilename(matches[0])
+    result.tline = parseInt(matches[1])
+    result.tcolumn = parseInt(matches[2])
   if err =~ pegLineError:
     result.file = extractFilename(matches[0])
     result.line = parseInt(matches[1])
@@ -153,7 +167,7 @@ proc addResult(r: var TResults, test: TTest,
 proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
   if strip(expected.msg) notin strip(given.msg):
     r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
-  elif extractFilename(expected.file) != extractFilename(given.file) and
+  elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and
       "internal error:" notin expected.msg:
     r.addResult(test, expected.file, given.file, reFilesDiffer)
   elif expected.line   != given.line   and expected.line   != 0 or
@@ -161,6 +175,14 @@ proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
     r.addResult(test, $expected.line & ':' & $expected.column,
                       $given.line    & ':' & $given.column,
                       reLinesDiffer)
+  elif expected.tfile != "" and extractFilename(expected.tfile) != extractFilename(given.tfile) and
+      "internal error:" notin expected.msg:
+    r.addResult(test, expected.tfile, given.tfile, reFilesDiffer)
+  elif expected.tline   != given.tline   and expected.tline   != 0 or
+       expected.tcolumn != given.tcolumn and expected.tcolumn != 0:
+    r.addResult(test, $expected.tline & ':' & $expected.tcolumn,
+                      $given.tline    & ':' & $given.tcolumn,
+                      reLinesDiffer)
   else:
     r.addResult(test, expected.msg, given.msg, reSuccess)
     inc(r.passed)
@@ -212,6 +234,8 @@ proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec;
       expectedmsg = expected.nimout
       givenmsg = given.nimout.strip
       nimoutCheck(test, expectedmsg, given)
+  else:
+    givenmsg = given.nimout.strip
   if given.err == reSuccess: inc(r.passed)
   r.addResult(test, expectedmsg, givenmsg, given.err)
 
@@ -279,7 +303,7 @@ proc testSpec(r: var TResults, test: TTest) =
       return
 
     let exeCmd = (if isJsTarget: nodejs & " " else: "") & exeFile
-    let (buf, exitCode) = execCmdEx(exeCmd)
+    var (buf, exitCode) = execCmdEx(exeCmd, options = {poStdErrToStdOut})
     let bufB = if expected.sortoutput: makeDeterministic(strip(buf.string))
                else: strip(buf.string)
     let expectedOut = strip(expected.outp)
@@ -376,6 +400,11 @@ proc main() =
     var cat = Category(p.key)
     p.next
     processCategory(r, cat, p.cmdLineRest.string)
+  of "r", "run":
+    let (dir, file) = splitPath(p.key.string)
+    let (_, subdir) = splitPath(dir)
+    var cat = Category(subdir)
+    processCategory(r, cat, p.cmdLineRest.string, file)
   of "html":
     var commit = 0
     discard parseInt(p.cmdLineRest.string, commit)
diff --git a/tests/typerel/t2plus.nim b/tests/typerel/t2plus.nim
new file mode 100644
index 000000000..08378b804
--- /dev/null
+++ b/tests/typerel/t2plus.nim
@@ -0,0 +1,22 @@
+discard """
+  output: "2.0"
+"""
+
+{.warning[TypelessParam]: off.}
+
+import future
+
+# bug #3329
+
+proc foldRight[T,U](lst: seq[T], v: U, f: (T, U) -> U): U =
+  result = v
+  for x in lst:
+    result = f(x, result)
+
+proc mean[T: SomeNumber](xs: seq[T]): T =
+  xs.foldRight(0.T, (xBAZ: auto, yBAZ: auto) => xBAZ + yBAZ) / T(xs.len)
+
+when isMainModule:
+  let x = mean(@[1.float, 2, 3])
+  echo x
+
diff --git a/tests/typerel/typeof_in_template.nim b/tests/typerel/typeof_in_template.nim
new file mode 100644
index 000000000..9ec06f2e3
--- /dev/null
+++ b/tests/typerel/typeof_in_template.nim
@@ -0,0 +1,16 @@
+discard """
+  output: '''@[a, c]'''
+"""
+
+# bug #3230
+
+import sequtils
+
+const
+  test_strings = ["a", "b", "c"]
+
+proc is_doc(x: string): bool = x == "b"
+
+let
+  tests = @test_strings.filter_it(not it.is_doc)
+echo tests
diff --git a/tests/types/tauto_excessive.nim b/tests/types/tauto_excessive.nim
new file mode 100644
index 000000000..2626b0cf4
--- /dev/null
+++ b/tests/types/tauto_excessive.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''10
+10.0
+1.0hiho'''
+"""
+
+# bug #3224
+proc f(x: auto): auto =
+  result = $(x+10)
+
+proc f(x, y: auto): auto =
+  result = $(x+y)
+
+
+echo f(0)     # prints 10
+echo f(0.0)  # prints 10.0
+
+proc `+`(a, b: string): string = a & b
+
+echo f(0.7, 0.3), f("hi", "ho")
diff --git a/tests/vm/tconstobj.nim b/tests/vm/tconstobj.nim
index 414708945..51f30fb78 100644
--- a/tests/vm/tconstobj.nim
+++ b/tests/vm/tconstobj.nim
@@ -1,8 +1,9 @@
 discard """
-  output: '''(name: hello)'''
+  output: '''(name: hello)
+(-1, 0)'''
 """
 
-# bug #2774
+# bug #2774, bug #3195
 
 type Foo = object
   name: string
@@ -12,3 +13,24 @@ const fooArray = [
 ]
 
 echo fooArray[0]
+
+
+type
+    Position = object
+        x, y: int
+
+proc `$`(pos: Position): string =
+    result = "(" & $pos.x & ", " & $pos.y & ")"
+
+proc newPos(x, y: int): Position =
+    result = Position(x: x, y: y)
+
+const
+     offset: array[1..4, Position] = [
+         newPos(-1, 0),
+         newPos(1, 0),
+         newPos(0, -1),
+         newPos(0, 1)
+     ]
+
+echo offset[1]
diff --git a/tests/vm/tsimpleglobals.nim b/tests/vm/tsimpleglobals.nim
new file mode 100644
index 000000000..27bfdce50
--- /dev/null
+++ b/tests/vm/tsimpleglobals.nim
@@ -0,0 +1,16 @@
+discard """
+  msg: "abc xyz bb"
+"""
+
+# bug #2473
+type
+  Test = tuple[a,b: string]
+
+static:
+  var s:seq[Test] = @[(a:"a", b:"b")]
+  s[0] = (a:"aa", b:"bb")
+
+  var x: Test
+  x.a = "abc"
+  x.b = "xyz"
+  echo x.a, " ", x.b, " ", s[0].b
diff --git a/tests/vm/twrongconst.nim b/tests/vm/twrongconst.nim
index 68ab2757c..424ed080e 100644
--- a/tests/vm/twrongconst.nim
+++ b/tests/vm/twrongconst.nim
@@ -1,6 +1,6 @@
 discard """
   errormsg: "cannot evaluate at compile time: x"
-  line: 9
+  line: 7
 """
 
 var x: array[100, char]
diff --git a/tests/vm/tyaytypedesc.nim b/tests/vm/tyaytypedesc.nim
new file mode 100644
index 000000000..a3ad9b707
--- /dev/null
+++ b/tests/vm/tyaytypedesc.nim
@@ -0,0 +1,21 @@
+discard """
+  output: "ntWhitespace"
+"""
+
+# bug #3357
+
+type NodeType* = enum
+  ntWhitespace
+
+type TokenType* = enum
+  ttWhitespace
+
+proc enumTable*[A, B, C](a: openarray[tuple[key: A, val: B]], ret: typedesc[C]): C =
+  for item in a:
+    result[item.key] = item.val
+
+const tokenTypeToNodeType = {
+  ttWhitespace: ntWhitespace,
+}.enumTable(array[ttWhitespace..ttWhitespace, NodeType])
+
+echo tokenTypeToNodeType[ttWhitespace]
diff --git a/todo.txt b/todo.txt
index c645f45e9..306b7008e 100644
--- a/todo.txt
+++ b/todo.txt
@@ -23,9 +23,7 @@ version 1.0
 - nimsuggest: auto-completion needs to work in 'class' macros
 - The bitwise 'not' operator will be renamed to 'bnot' to
   prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
-- iterators always require a return type
 - split docgen into separate tool
-- special rule for ``[]=``, items, pairs
 - BUG: echo with template `$`*(info: TLineInfo): expr = toFileLineCol(info)
 - make 'nil' work for 'add':
   - resizeString
diff --git a/tools/niminst/buildbat.tmpl b/tools/niminst/buildbat.tmpl
index 2c6a2b5a8..2a8da144d 100644
--- a/tools/niminst/buildbat.tmpl
+++ b/tools/niminst/buildbat.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl(subsChar='?') | standard
+#? stdtmpl(subsChar='?') | standard
 #proc generateBuildBatchScript(c: ConfigData, winIndex, cpuIndex: int): string = 
 #  result = "@echo off\nREM Generated by niminst\n"
 SET CC=gcc
diff --git a/tools/niminst/buildsh.tmpl b/tools/niminst/buildsh.tmpl
index 52da351be..463a1ad52 100644
--- a/tools/niminst/buildsh.tmpl
+++ b/tools/niminst/buildsh.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl(subsChar='?') | standard
+#? stdtmpl(subsChar='?') | standard
 #proc generateBuildShellScript(c: ConfigData): string = 
 #  result = "#! /bin/sh\n# Generated from niminst\n" &
 #           "# Template is in tools/niminst/buildsh.tmpl\n" &
diff --git a/tools/niminst/deinstall.tmpl b/tools/niminst/deinstall.tmpl
index c4717a257..7349abcb4 100644
--- a/tools/niminst/deinstall.tmpl
+++ b/tools/niminst/deinstall.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl(subsChar='?') | standard
+#? stdtmpl(subsChar='?') | standard
 #proc generateDeinstallScript(c: ConfigData): string = 
 #  result = "#! /bin/sh\n# Generated by niminst\n"
 #  var proj = c.name.toLower
diff --git a/tools/niminst/inno.tmpl b/tools/niminst/inno.tmpl
index 4acf0557c..ef2da8a75 100644
--- a/tools/niminst/inno.tmpl
+++ b/tools/niminst/inno.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl | standard
+#? stdtmpl | standard
 #proc generateInnoSetup(c: ConfigData): string =
 #  result = ""
 ; Default Template for NimInst
diff --git a/tools/niminst/install.tmpl b/tools/niminst/install.tmpl
index 3ec42c287..14d88e07d 100644
--- a/tools/niminst/install.tmpl
+++ b/tools/niminst/install.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl(subsChar = '?') | standard
+#? stdtmpl(subsChar = '?') | standard
 #proc generateInstallScript(c: ConfigData): string = 
 #  result = "#! /bin/sh\n# Generated by niminst\n"
 #  var proj = c.name.toLower
diff --git a/tools/niminst/makefile.tmpl b/tools/niminst/makefile.tmpl
index 8ab3b89d1..6615ddc02 100644
--- a/tools/niminst/makefile.tmpl
+++ b/tools/niminst/makefile.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl(subsChar='?') | standard
+#? stdtmpl(subsChar='?') | standard
 #proc generateMakefile(c: ConfigData): string = 
 #  result = "# Generated from niminst\n" &
 #           "# Template is in tools/niminst/makefile.tmpl\n" &
diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl
index 843a8cf44..abf462388 100644
--- a/tools/niminst/nsis.tmpl
+++ b/tools/niminst/nsis.tmpl
@@ -1,4 +1,4 @@
-#! stdtmpl(subsChar='?') | standard
+#? stdtmpl(subsChar='?') | standard
 #proc generateNsisSetup(c: ConfigData): string =
 #  result = "; NSIS script generated by niminst\n" &
 #           "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"
diff --git a/tools/website.tmpl b/tools/website.tmpl
index bc3ed8e2c..3209aac51 100644
--- a/tools/website.tmpl
+++ b/tools/website.tmpl
@@ -1,5 +1,5 @@
-#! stdtmpl | standard
-#proc generateHTMLPage(c: var TConfigData, currentTab, content, rss: string): string = 
+#? stdtmpl | standard
+#proc generateHTMLPage(c: var TConfigData, currentTab, content, rss: string): string =
 #  result = ""
 <!DOCTYPE html>
 <html>
@@ -23,7 +23,7 @@
       # if t != "index" and t != "community" and t != "news":
       #   let name = c.tabs[i].key
       #   if currentTab == t:
-            <a class="active" 
+            <a class="active"
       #   else:
             <a
       #   end if
@@ -104,7 +104,7 @@ p.greet() <span class="cmt"># or greet(p)</span>
 <span class="cmt"># declare a C procedure..</span>
 <span class="kwd">proc</span> <span class="def">unsafeScanf</span>(f: <span class="typ">File</span>, s: <span class="typ">cstring</span>)
 <span class="tab">  </span>{.varargs,
-<span class="tab">    </span>importc: <span class="val">"fscanf"</span>, 
+<span class="tab">    </span>importc: <span class="val">"fscanf"</span>,
 <span class="tab end">    </span>header: <span class="val">"&lt;stdio.h&gt;"</span>.}
 
 <span class="cmt"># ..and use it...</span>
@@ -191,7 +191,7 @@ runForever()
 				</div>
 			</div>
 		</footer>
-  
+
 #  if currentTab == "index":
   <script src="assets/index.js"></script>
 # end if
diff --git a/web/community.txt b/web/community.txt
index 4b8c481b9..b8a6c7372 100644
--- a/web/community.txt
+++ b/web/community.txt
@@ -41,14 +41,14 @@ Nim's Community
 
 .. container:: standout
 
-  Github
+  GitHub
   ------
 
-  Nim's `source code <http://github.com/nim-lang/Nim>`_ is hosted on Github.
+  Nim's `source code <http://github.com/nim-lang/Nim>`_ is hosted on GitHub.
   Together with the `wiki <http://github.com/nim-lang/Nim/wiki>`_ and
   `issue tracker <http://github.com/nim-lang/Nim/issues>`_.
 
-  Github also hosts other projects relating to Nim. These projects are a part
+  GitHub also hosts other projects relating to Nim. These projects are a part
   of the `nim-lang organisation <http://github.com/nim-lang>`_.
   This includes the `Nimble package manager <https://github.com/nim-lang/nimble>`_
   and its `package repository <http://github.com/nim-lang/packages>`_.
diff --git a/web/news.txt b/web/news.txt
index ac6f8ae09..2b6079620 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -3,12 +3,15 @@ News
 ====
 
 ..
-  2015-05-05 Version 0.11.4 released
+  2015-xx-xx Version 0.11.4 released
   ==================================
 
   Changes affecting backwards compatibility
   -----------------------------------------
 
+  - The ``rawsockets`` module has been renamed to ``nativesockets`` to avoid
+    confusion with TCP/IP raw sockets, so ``newNativeSocket`` should be used
+    instead of ``newRawSocket``.
   - The ``miliseconds`` property of ``times.TimeInterval`` is now ``milliseconds``.
     Code accessing that property is deprecated and code using ``miliseconds``
     during object initialization or as a named parameter of ``initInterval()``
@@ -58,7 +61,7 @@ News
     of all the DLLs the standard library needs. This means that the following
     DLLs are now split into 32 and 64 versions:
 
-    * ``prce.dll``: Split into ``prce32.dll`` and ``prce64.dll``.
+    * ``pcre.dll``: Split into ``pcre32.dll`` and ``pcre64.dll``.
     * ``pdcurses.dll``: Split into ``pdcurses32.dll`` and ``pdcurses64.dll``.
     * ``sqlite3.dll``: Split into ``sqlite3_32.dll`` and ``sqlite3_64.dll``.
     * ``ssleay32.dll``: Split into ``ssleay32.dll`` and ``ssleay64.dll``.
@@ -71,6 +74,19 @@ News
     are likely to break as well.
   - Base methods now need to be annotated with the ``base`` pragma. This makes
     multi methods less error-prone to use with the effect system.
+  - Nim's parser directive ``#!`` is now ``#?`` in order to produce no conflicts
+    with Unix's ``#!``.
+  - An implicit return type for an iterator is now deprecated. Use ``auto`` if
+    you want more type inference.
+  - The type ``auto`` is now a "multi-bind" metatype, so the following compiles:
+
+    .. code-block:: nim
+      proc f(x, y: auto): auto =
+        result = $x & y
+
+      echo f(0, "abc")
+  - The ``ftpclient`` module is now deprecated in favour of the
+    ``asyncdispatch`` module.
 
 
   Library Additions
@@ -84,6 +100,7 @@ News
     to benchmark it.
   - ``strutils.formatFloat`` and ``formatBiggestFloat`` do not depend on the C
     locale anymore and now take an optional ``decimalSep = '.'`` parameter.
+  - Added ``unicode.lastRune``, ``unicode.graphemeLen``.
 
 
   Compiler Additions
@@ -91,6 +108,11 @@ News
 
   - The compiler now supports a new configuration system based on
     `NimScript <docs/nims.html>`_.
+  - The compiler finally considers symbol binding rules in templates and
+    generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators
+    (issue `#2599 <https://github.com/nim-lang/Nim/issues/2599>`_).
+  - The compiler now supports a `bitsize pragma <docs/manual.html#pragmas-bitsize-pragma>`_
+    for constructing bitfields.
 
 
   Language Additions
@@ -103,15 +125,214 @@ News
   - Added ``macros.getImpl`` that can be used to access the implementation of
     a routine or a constant. This allows for example for user-defined inlining
     of function calls.
-  - Tuple unpacking finally works in a non-var/let context: ``(x, y) == f()``
+  - Tuple unpacking finally works in a non-var/let context: ``(x, y) = f()``
     is allowed. Note that this doesn't declare ``x`` and ``y`` variables, for
-    this ``let (x, y) == f()`` still needs to be used.
+    this ``let (x, y) = f()`` still needs to be used.
   - ``when nimvm`` can now be used for compiletime versions of some code
     sections. Click `here <docs/manual.html#when-nimvm-statement>`_ for details.
+  - Usage of the type ``NimNode`` in a proc now implicitly annotates the proc
+    with ``.compileTime``. This means generics work much better for ``NimNode``.
 
 
   Bugfixes
   --------
+  - Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with it(Child), where Child = object of Base"
+    (`#2662 <https://github.com/Araq/Nim/issues/2662>`_)
+  - Fixed "repr() misses base object field in 2nd level derived object"
+    (`#2749 <https://github.com/Araq/Nim/issues/2749>`_)
+  - Fixed "nimsuggest doesn't work more than once on the non-main file"
+    (`#2694 <https://github.com/Araq/Nim/issues/2694>`_)
+  - Fixed "JS Codegen. Passing arguments by var in certain cases leads to invalid JS."
+    (`#2798 <https://github.com/Araq/Nim/issues/2798>`_)
+  - Fixed ""check" proc in unittest.nim prevents the propagation of changes to var parameters."
+    (`#964 <https://github.com/Araq/Nim/issues/964>`_)
+  - Fixed "Excessive letters in integer literals are not an error"
+    (`#2523 <https://github.com/Araq/Nim/issues/2523>`_)
+  - Fixed "Unicode dashes as "lisp'ish" alternative to hump and snake notation"
+    (`#2811 <https://github.com/Araq/Nim/issues/2811>`_)
+  - Fixed "Bad error message when trying to construct an object incorrectly"
+    (`#2584 <https://github.com/Araq/Nim/issues/2584>`_)
+  - Fixed "Determination of GC safety of globals is broken "
+    (`#2854 <https://github.com/Araq/Nim/issues/2854>`_)
+  - Fixed "v2 gc crashes compiler"
+    (`#2687 <https://github.com/Araq/Nim/issues/2687>`_)
+  - Fixed "Compile error using object in const array"
+    (`#2774 <https://github.com/Araq/Nim/issues/2774>`_)
+  - Fixed "httpclient async requests with method httpPOST isn't sending Content-Length header"
+    (`#2884 <https://github.com/Araq/Nim/issues/2884>`_)
+  - Fixed "Streams module not working with JS backend"
+    (`#2148 <https://github.com/Araq/Nim/issues/2148>`_)
+  - Fixed "Sign of certain short constants is wrong"
+    (`#1179 <https://github.com/Araq/Nim/issues/1179>`_)
+  - Fixed "Symlinks to directories reported as symlinks to files"
+    (`#1985 <https://github.com/Araq/Nim/issues/1985>`_)
+  - Fixed "64-bit literals broken on x86"
+    (`#2909 <https://github.com/Araq/Nim/issues/2909>`_)
+  - Fixed "import broken for certain names"
+    (`#2904 <https://github.com/Araq/Nim/issues/2904>`_)
+  - Fixed "Invalid UTF-8 strings in JavaScript"
+    (`#2917 <https://github.com/Araq/Nim/issues/2917>`_)
+  - Fixed "[JS][Codegen] Initialising object doesn't create unmentioned fields."
+
+    (`#2617 <https://github.com/Araq/Nim/issues/2617>`_)
+  - Fixed "Table returned from proc computed at compile time is missing keys:"
+    (`#2297 <https://github.com/Araq/Nim/issues/2297>`_)
+  - Fixed "Clarify copyright status for some files"
+    (`#2949 <https://github.com/Araq/Nim/issues/2949>`_)
+  - Fixed "math.nim: trigonometry: radians to degrees conversion"
+    (`#2881 <https://github.com/Araq/Nim/issues/2881>`_)
+  - Fixed "xoring unsigned integers yields RangeError in certain conditions"
+    (`#2979 <https://github.com/Araq/Nim/issues/2979>`_)
+  - Fixed "Directly checking equality between procs"
+    (`#2985 <https://github.com/Araq/Nim/issues/2985>`_)
+  - Fixed "Compiler crashed, but there have to be meaningful error message"
+    (`#2974 <https://github.com/Araq/Nim/issues/2974>`_)
+  - Fixed "repr is broken"
+    (`#2992 <https://github.com/Araq/Nim/issues/2992>`_)
+  - Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a default"
+    (`#2976 <https://github.com/Araq/Nim/issues/2976>`_)
+  - Fixed "Compilation broken on windows"
+    (`#2996 <https://github.com/Araq/Nim/issues/2996>`_)
+  - Fixed "'u64 literal conversion compiler error"
+    (`#2731 <https://github.com/Araq/Nim/issues/2731>`_)
+  - Fixed "Importing 'impure' libraries while using threads causes segfaults"
+    (`#2672 <https://github.com/Araq/Nim/issues/2672>`_)
+  - Fixed "Uncatched exception in async procedure on raise statement"
+    (`#3014 <https://github.com/Araq/Nim/issues/3014>`_)
+  - Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #1898)"
+    (`#3005 <https://github.com/Araq/Nim/issues/3005>`_)
+  - Fixed "IndexError when rebuilding Nim on iteration 2"
+    (`#3018 <https://github.com/Araq/Nim/issues/3018>`_)
+  - Fixed "Assigning large const set to variable looses some information"
+    (`#2880 <https://github.com/Araq/Nim/issues/2880>`_)
+  - Fixed "Inconsistent generics behavior"
+    (`#3022 <https://github.com/Araq/Nim/issues/3022>`_)
+  - Fixed "Compiler breaks on float64 division"
+    (`#3028 <https://github.com/Araq/Nim/issues/3028>`_)
+  - Fixed "Confusing error message comparing string to nil "
+    (`#2935 <https://github.com/Araq/Nim/issues/2935>`_)
+  - Fixed "convert 64bit number to float on 32bit"
+    (`#1463 <https://github.com/Araq/Nim/issues/1463>`_)
+  - Fixed "Type redefinition and construction will break nim check"
+    (`#3032 <https://github.com/Araq/Nim/issues/3032>`_)
+  - Fixed "XmlParser fails on very large XML files without new lines"
+    (`#2429 <https://github.com/Araq/Nim/issues/2429>`_)
+  - Fixed "Error parsing arguments with whitespaces"
+    (`#2874 <https://github.com/Araq/Nim/issues/2874>`_)
+  - Fixed "Crash when missing one arg and used a named arg"
+    (`#2993 <https://github.com/Araq/Nim/issues/2993>`_)
+  - Fixed "Wrong number of arguments in assert will break nim check"
+    (`#3044 <https://github.com/Araq/Nim/issues/3044>`_)
+  - Fixed "Wrong const definition will break nim check"
+    (`#3041 <https://github.com/Araq/Nim/issues/3041>`_)
+  - Fixed "Wrong set declaration will break nim check"
+    (`#3040 <https://github.com/Araq/Nim/issues/3040>`_)
+  - Fixed "Compiler segfault (type section)"
+    (`#2540 <https://github.com/Araq/Nim/issues/2540>`_)
+  - Fixed "Segmentation fault when compiling this code"
+    (`#3038 <https://github.com/Araq/Nim/issues/3038>`_)
+  - Fixed "Kill nim i"
+    (`#2633 <https://github.com/Araq/Nim/issues/2633>`_)
+  - Fixed "Nim check will break on wrong array declaration"
+    (`#3048 <https://github.com/Araq/Nim/issues/3048>`_)
+  - Fixed "boolVal seems to be broken"
+    (`#3046 <https://github.com/Araq/Nim/issues/3046>`_)
+  - Fixed "Nim check crashes on wrong set/array declaration inside ref object"
+    (`#3062 <https://github.com/Araq/Nim/issues/3062>`_)
+  - Fixed "Nim check crashes on incorrect generic arg definition"
+    (`#3051 <https://github.com/Araq/Nim/issues/3051>`_)
+  - Fixed "Nim check crashes on iterating nonexistent var"
+    (`#3053 <https://github.com/Araq/Nim/issues/3053>`_)
+  - Fixed "Nim check crashes on wrong param set declaration + iteration"
+    (`#3054 <https://github.com/Araq/Nim/issues/3054>`_)
+  - Fixed "Wrong sharing of static_t instantations"
+    (`#3112 <https://github.com/Araq/Nim/issues/3112>`_)
+  - Fixed "Automatically generated proc conflicts with user-defined proc when .exportc.'ed"
+    (`#3134 <https://github.com/Araq/Nim/issues/3134>`_)
+  - Fixed "getTypeInfo call crashes nim"
+    (`#3099 <https://github.com/Araq/Nim/issues/3099>`_)
+  - Fixed "Array ptr dereference"
+    (`#2963 <https://github.com/Araq/Nim/issues/2963>`_)
+  - Fixed "Internal error when `repr`-ing a type directly"
+    (`#3079 <https://github.com/Araq/Nim/issues/3079>`_)
+  - Fixed "unknown type name 'TNimType' after importing typeinfo module"
+    (`#2841 <https://github.com/Araq/Nim/issues/2841>`_)
+  - Fixed "Can export a template twice and from inside a block"
+    (`#1738 <https://github.com/Araq/Nim/issues/1738>`_)
+  - Fixed "C Codegen: C Types are defined after their usage in certain cases"
+    (`#2823 <https://github.com/Araq/Nim/issues/2823>`_)
+  - Fixed "s.high refers to the current seq instead of the old one"
+    (`#1832 <https://github.com/Araq/Nim/issues/1832>`_)
+  - Fixed "Error while unmarshaling null values"
+    (`#3149 <https://github.com/Araq/Nim/issues/3149>`_)
+  - Fixed "Inference of `static[T]` in sequences"
+    (`#3144 <https://github.com/Araq/Nim/issues/3144>`_)
+  - Fixed "Argument named "closure" to proc inside template interfere with closure pragma"
+    (`#3171 <https://github.com/Araq/Nim/issues/3171>`_)
+  - Fixed "Internal error with aliasing inside template"
+    (`#3158 <https://github.com/Araq/Nim/issues/3158>`_)
+  - Fixed "Cardinality of sets prints unexpected value"
+    (`#3135 <https://github.com/Araq/Nim/issues/3135>`_)
+  - Fixed "Nim crashes on const assignment from function returning var ref object"
+    (`#3103 <https://github.com/Araq/Nim/issues/3103>`_)
+  - Fixed "`repr` cstring"
+    (`#3080 <https://github.com/Araq/Nim/issues/3080>`_)
+  - Fixed "Nim check crashes on wrong enum declaration"
+    (`#3052 <https://github.com/Araq/Nim/issues/3052>`_)
+  - Fixed "Compiler assertion when evaluating template with static[T]"
+    (`#1858 <https://github.com/Araq/Nim/issues/1858>`_)
+  - Fixed "Erroneous overflow in iterators when compiler built with overflowChecks enabled"
+    (`#3140 <https://github.com/Araq/Nim/issues/3140>`_)
+  - Fixed "Unicode dashes as "lisp'ish" alternative to hump and snake notation"
+    (`#2811 <https://github.com/Araq/Nim/issues/2811>`_)
+  - Fixed "Calling discardable proc from a defer is an error."
+    (`#3185 <https://github.com/Araq/Nim/issues/3185>`_)
+  - Fixed "Defer statement at the end of a block produces ICE"
+    (`#3186 <https://github.com/Araq/Nim/issues/3186>`_)
+  - Fixed "Call to `createU` fails to compile"
+    (`#3193 <https://github.com/Araq/Nim/issues/3193>`_)
+  - Fixed "VM crash when accessing array's element"
+    (`#3192 <https://github.com/Araq/Nim/issues/3192>`_)
+  - Fixed "Unexpected proc invoked when different modules add procs to a type from a 3rd module"
+    (`#2664 <https://github.com/Araq/Nim/issues/2664>`_)
+  - Fixed "Nim crashes on conditional declaration inside a template"
+    (`#2670 <https://github.com/Araq/Nim/issues/2670>`_)
+  - Fixed "Iterator names conflict within different scopes"
+    (`#2752 <https://github.com/Araq/Nim/issues/2752>`_)
+  - Fixed "VM: Cannot assign int value to ref variable"
+    (`#1329 <https://github.com/Araq/Nim/issues/1329>`_)
+  - Fixed "Incorrect code generated for tagged unions with enums not starting at zero"
+    (`#3096 <https://github.com/Araq/Nim/issues/3096>`_)
+  - Fixed "Compile time procs using forward declarations are silently ignored"
+    (`#3066 <https://github.com/Araq/Nim/issues/3066>`_)
+  - Fixed "re binding error in generic"
+    (`#1965 <https://github.com/Araq/Nim/issues/1965>`_)
+  - Fixed "os.getCreationTime is incorrect/impossible on Posix systems"
+    (`#1058 <https://github.com/Araq/Nim/issues/1058>`_)
+  - Fixed "Improve error message for osproc.startProcess when command does not exist"
+    (`#2183 <https://github.com/Araq/Nim/issues/2183>`_)
+  - Fixed "gctest segfaults with --gc:markandsweep on x86_64"
+    (`#2305 <https://github.com/Araq/Nim/issues/2305>`_)
+  - Fixed "Coroutine changes break compilation on unsupported architectures"
+    (`#3245 <https://github.com/Araq/Nim/issues/3245>`_)
+  - Fixed "Bugfix: Windows 32bit  TinyCC support issue fixed"
+    (`#3237 <https://github.com/Araq/Nim/issues/3237>`_)
+  - Fixed "db_mysql getValue() followed by exec() causing error"
+    (`#3220 <https://github.com/Araq/Nim/issues/3220>`_)
+  - Fixed "xmltree.newEntity creates xnCData instead of xnEntity"
+    (`#3282 <https://github.com/Araq/Nim/issues/3282>`_)
+  - Fixed "Methods and modules don't work together"
+    (`#2590 <https://github.com/Araq/Nim/issues/2590>`_)
+  - Fixed "String slicing not working in the vm"
+    (`#3300 <https://github.com/Araq/Nim/issues/3300>`_)
+  - Fixed "internal error: evalOp(mTypeOf)"
+    (`#3230 <https://github.com/Araq/Nim/issues/3230>`_)
+  - Fixed "#! source code prefix collides with Unix Shebang"
+    (`#2559 <https://github.com/Araq/Nim/issues/2559>`_)
+  - Fixed "wrong codegen for constant object"
+    (`#3195 <https://github.com/Araq/Nim/issues/3195>`_)
+  - Fixed "Doc comments inside procs with implicit returns don't work"
+    (`#1528 <https://github.com/Araq/Nim/issues/1528>`_)
 
 
 2015-05-04 Version 0.11.2 released
@@ -576,7 +797,7 @@ 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
+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
diff --git a/web/question.txt b/web/question.txt
index 46ea7161c..da38760f5 100644
--- a/web/question.txt
+++ b/web/question.txt
@@ -94,9 +94,9 @@ General FAQ
   What about JVM/CLR backends?
   ----------------------------
 
-  A JVM backend is almost impossible. The JVM is not expressive enough. It has
-  never been designed as a general purpose VM anyway. A CLR backend is possible
-  but would require much work.
+  JVM/CLR support is not in the nearest plans. However, since these VMs support FFI to C
+  it should be possible to create native Nim bridges, that transparenlty generate all the
+  glue code thanks to powerful metaprogramming capabilities of Nim.
 
 
 .. container:: standout
diff --git a/web/website.ini b/web/website.ini
index c160d624d..dcfea8bf4 100644
--- a/web/website.ini
+++ b/web/website.ini
@@ -9,7 +9,7 @@ Authors: "Andreas Rumpf and contributors"
 # Everything after ; is the ID
 Community: "community.html;link_forum"
 Aporia_IDE: "https://github.com/nim-lang/Aporia;link_aporia"
-Github_Repo: "http://github.com/Araq/Nim;link_github"
+GitHub_Repo: "http://github.com/Araq/Nim;link_github"
 
 
 [Tabs]