summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim94
-rw-r--r--compiler/ccgcalls.nim38
-rw-r--r--compiler/ccgexprs.nim13
-rw-r--r--compiler/ccgstmts.nim5
-rw-r--r--compiler/ccgtypes.nim7
-rw-r--r--compiler/cgen.nim10
-rw-r--r--compiler/installer.ini3
-rw-r--r--compiler/jsgen.nim11
-rw-r--r--compiler/main.nim1
-rw-r--r--compiler/msgs.nim5
-rw-r--r--compiler/options.nim13
-rw-r--r--compiler/pragmas.nim3
-rw-r--r--compiler/renderer.nim23
-rw-r--r--compiler/rodread.nim22
-rw-r--r--compiler/rodwrite.nim189
-rw-r--r--compiler/semexprs.nim1
-rw-r--r--compiler/semfold.nim2
-rw-r--r--compiler/semtempl.nim12
-rw-r--r--compiler/semtypes.nim7
-rw-r--r--compiler/semtypinst.nim20
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--compiler/vm.nim5
-rw-r--r--compiler/vmdeps.nim40
-rw-r--r--compiler/vmgen.nim14
-rw-r--r--config/nimdoc.cfg9
-rw-r--r--doc/lib.txt5
-rw-r--r--doc/nep1.txt208
-rw-r--r--doc/nimc.txt2
-rw-r--r--doc/nimdoc.css5
-rw-r--r--doc/sets_fragment.txt14
-rw-r--r--doc/tools.txt4
-rw-r--r--doc/tut1.txt24
-rw-r--r--examples/wingui.nim9
-rw-r--r--lib/core/typeinfo.nim86
-rw-r--r--lib/core/unsigned.nim53
-rw-r--r--lib/nimbase.h4
-rw-r--r--lib/packages/docutils/rstgen.nim20
-rw-r--r--lib/pure/httpclient.nim5
-rw-r--r--lib/pure/marshal.nim2
-rw-r--r--lib/pure/math.nim68
-rw-r--r--lib/pure/net.nim10
-rw-r--r--lib/pure/os.nim18
-rw-r--r--lib/pure/parsexml.nim4
-rw-r--r--lib/pure/rawsockets.nim16
-rw-r--r--lib/pure/securehash.nim (renamed from compiler/securehash.nim)0
-rw-r--r--lib/pure/selectors.nim3
-rw-r--r--lib/pure/sockets.nim14
-rw-r--r--lib/pure/times.nim25
-rw-r--r--lib/pure/unicode.nim59
-rw-r--r--lib/pure/unittest.nim4
-rw-r--r--lib/system.nim78
-rw-r--r--lib/system/sysstr.nim8
-rw-r--r--tests/ccgbugs/taddhigh.nim16
-rw-r--r--tests/ccgbugs/tmissingderef.nim13
-rw-r--r--tests/ccgbugs/trecursive_closure.nim6
-rw-r--r--tests/cpp/ttypeinfo2.nim6
-rw-r--r--tests/iter/tscheduler.nim1
-rw-r--r--tests/metatype/tstatic_ones.nim28
-rw-r--r--tests/metatype/tstaticvector.nim36
-rw-r--r--tests/typerel/ttypedesc_as_genericparam1.nim6
-rw-r--r--tests/typerel/ttypedesc_as_genericparam2.nim9
-rw-r--r--tests/vm/tslurp.nim10
-rw-r--r--todo.txt6
-rw-r--r--web/documentation.txt7
-rw-r--r--web/news.txt5
-rw-r--r--web/website.ini2
66 files changed, 1024 insertions, 426 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 7ebcdddb1..3a4158204 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -525,6 +525,8 @@ const
   tfOldSchoolExprStmt* = tfVarargs # for now used to distinguish \
     # 'varargs[expr]' from 'varargs[untyped]'. Eventually 'expr' will be
     # deprecated and this mess can be cleaned up.
+  tfVoid* = tfVarargs # for historical reasons we conflated 'void' with
+                      # 'empty' ('@[]' has the type 'seq[empty]').
   skError* = skUnknown
 
   # type flags that are essential for type equality:
@@ -537,35 +539,48 @@ type
     mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mAddr, mTypeOf, mRoof, mPlugin,
     mEcho, mShallowCopy, mSlurp, mStaticExec,
     mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
-    mUnaryLt, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
-    mLengthStr, mLengthArray, mLengthSeq, mXLenStr, mXLenSeq,
+    mUnaryLt, mInc, mDec, mOrd,
+    mNew, mNewFinalize, mNewSeq,
+    mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq,
+    mXLenStr, mXLenSeq,
     mIncl, mExcl, mCard, mChr,
     mGCref, mGCunref,
-
     mAddI, mSubI, mMulI, mDivI, mModI,
     mSucc, mPred,
     mAddF64, mSubF64, mMulF64, mDivF64,
-
-    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI,
-    mMinF64, mMaxF64, mAddU, mSubU, mMulU,
-    mDivU, mModU, mEqI, mLeI,
-    mLtI,
+    mShrI, mShlI, mBitandI, mBitorI, mBitxorI,
+    mMinI, mMaxI,
+    mMinF64, mMaxF64,
+    mAddU, mSubU, mMulU, mDivU, mModU,
+    mEqI, mLeI, mLtI,
     mEqF64, mLeF64, mLtF64,
-    mLeU, mLtU, mLeU64, mLtU64,
-    mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef,
-    mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mEqProc, mUnaryMinusI,
-    mUnaryMinusI64, mAbsI, mNot,
+    mLeU, mLtU,
+    mLeU64, mLtU64,
+    mEqEnum, mLeEnum, mLtEnum,
+    mEqCh, mLeCh, mLtCh,
+    mEqB, mLeB, mLtB,
+    mEqRef, mEqUntracedRef, mLePtr, mLtPtr, mEqCString,
+    mXor, mEqProc,
+    mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
     mUnaryPlusI, mBitnotI,
-    mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64,
-    mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, mToU32,
-    mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, mBoolToStr,
-    mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr,
-    mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
-    mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mSlice,
+    mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
+    mZe8ToI, mZe8ToI64,
+    mZe16ToI, mZe16ToI64,
+    mZe32ToI64, mZeIToI64,
+    mToU8, mToU16, mToU32,
+    mToFloat, mToBiggestFloat,
+    mToInt, mToBiggestInt,
+    mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
+    mStrToStr, mEnumToStr,
+    mAnd, mOr,
+    mEqStr, mLeStr, mLtStr,
+    mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mSymDiffSet,
+    mConStrStr, mSlice,
     mDotDot, # this one is only necessary to give nice compile time warnings
     mFields, mFieldPairs, mOmpParFor,
     mAppendStrCh, mAppendStrStr, mAppendSeqElem,
-    mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
+    mInRange, mInSet, mRepr, mExit,
+    mSetLengthStr, mSetLengthSeq,
     mIsPartOf, mAstToStr, mParallel,
     mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
     mNewString, mNewStringOfCap, mParseBiggestFloat,
@@ -599,23 +614,32 @@ const
     mIncl, mExcl, mCard, mChr,
     mAddI, mSubI, mMulI, mDivI, mModI,
     mAddF64, mSubF64, mMulF64, mDivF64,
-    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI,
-    mMinF64, mMaxF64, mAddU, mSubU, mMulU,
-    mDivU, mModU, mEqI, mLeI,
-    mLtI,
+    mShrI, mShlI, mBitandI, mBitorI, mBitxorI,
+    mMinI, mMaxI,
+    mMinF64, mMaxF64,
+    mAddU, mSubU, mMulU, mDivU, mModU,
+    mEqI, mLeI, mLtI,
     mEqF64, mLeF64, mLtF64,
-    mLeU, mLtU, mLeU64, mLtU64,
-    mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef,
-    mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI,
-    mUnaryMinusI64, mAbsI, mNot,
-    mUnaryPlusI, mBitnotI,
-    mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64,
-    mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, mToU32,
-    mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, mBoolToStr,
-    mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr,
-    mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
-    mPlusSet, mMinusSet, mSymDiffSet, mConStrStr,
-    mAppendStrCh, mAppendStrStr, mAppendSeqElem,
+    mLeU, mLtU,
+    mLeU64, mLtU64,
+    mEqEnum, mLeEnum, mLtEnum,
+    mEqCh, mLeCh, mLtCh,
+    mEqB, mLeB, mLtB,
+    mEqRef, mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor,
+    mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
+    mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
+    mZe8ToI, mZe8ToI64,
+    mZe16ToI, mZe16ToI64,
+    mZe32ToI64, mZeIToI64,
+    mToU8, mToU16, mToU32,
+    mToFloat, mToBiggestFloat,
+    mToInt, mToBiggestInt,
+    mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
+    mStrToStr, mEnumToStr,
+    mAnd, mOr,
+    mEqStr, mLeStr, mLtStr,
+    mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mSymDiffSet,
+    mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
     mInRange, mInSet, mRepr,
     mCopyStr, mCopyStrLast}
   # magics that require special semantic checking and
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index 2dacc25e9..86ecc9db8 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -159,6 +159,17 @@ proc genArgNoParam(p: BProc, n: PNode): Rope =
     initLocExprSingleUse(p, n, a)
     result = rdLoc(a)
 
+template genParamLoop(params) {.dirty.} =
+  if i < sonsLen(typ):
+    assert(typ.n.sons[i].kind == nkSym)
+    let paramType = typ.n.sons[i]
+    if not paramType.typ.isCompileTimeOnly:
+      if params != nil: add(params, ~", ")
+      add(params, genArg(p, ri.sons[i], paramType.sym, ri))
+  else:
+    if params != nil: add(params, ~", ")
+    add(params, genArgNoParam(p, ri.sons[i]))
+
 proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   var op: TLoc
   # this is a hotspot in the compiler
@@ -170,13 +181,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   assert(sonsLen(typ) == sonsLen(typ.n))
   var length = sonsLen(ri)
   for i in countup(1, length - 1):
-    if ri.sons[i].typ.isCompileTimeOnly: continue
-    if params != nil: add(params, ~", ")
-    if i < sonsLen(typ):
-      assert(typ.n.sons[i].kind == nkSym)
-      add(params, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri))
-    else:
-      add(params, genArgNoParam(p, ri.sons[i]))
+    genParamLoop(params)
   fixupCall(p, le, ri, d, op.r, params)
 
 proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
@@ -198,13 +203,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
   var length = sonsLen(ri)
   for i in countup(1, length - 1):
     assert(sonsLen(typ) == sonsLen(typ.n))
-    if ri.sons[i].typ.isCompileTimeOnly: continue
-    if i < sonsLen(typ):
-      assert(typ.n.sons[i].kind == nkSym)
-      add(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri))
-    else:
-      add(pl, genArgNoParam(p, ri.sons[i]))
-    if i < length - 1: add(pl, ~", ")
+    genParamLoop(pl)
 
   template genCallPattern {.dirty.} =
     lineF(p, cpsStmts, callPattern & ";$n", [op.r, pl, pl.addComma, rawProc])
@@ -241,13 +240,14 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
     genCallPattern()
 
 proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
-  if ri.sons[i].typ.isCompileTimeOnly:
-    result = nil
-  elif i < sonsLen(typ):
+  if i < sonsLen(typ):
     # 'var T' is 'T&' in C++. This means we ignore the request of
     # any nkHiddenAddr when it's a 'var T'.
-    assert(typ.n.sons[i].kind == nkSym)
-    if typ.sons[i].kind == tyVar and ri.sons[i].kind == nkHiddenAddr:
+    let paramType = typ.n.sons[i]
+    assert(paramType.kind == nkSym)
+    if paramType.typ.isCompileTimeOnly:
+      result = nil
+    elif typ.sons[i].kind == tyVar and ri.sons[i].kind == nkHiddenAddr:
       result = genArgNoParam(p, ri.sons[i][0])
     else:
       result = genArgNoParam(p, ri.sons[i]) #, typ.n.sons[i].sym)
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 493749848..c237eeffa 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -347,8 +347,8 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     else:
       useStringh(p.module)
       linefmt(p, cpsStmts,
-           "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
-           rdLoc(dest), rdLoc(src))
+           "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
+           rdLoc(dest), rdLoc(src), getTypeDesc(p.module, ty))
   of tyOpenArray, tyVarargs:
     # open arrays are always on the stack - really? What if a sequence is
     # passed to an open array?
@@ -1052,9 +1052,9 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   #    seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
   #    seq->data[seq->len-1] = x;
   let seqAppendPattern = if not p.module.compileToCpp:
-                           "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
+                           "$1 = ($2) #incrSeqV2(&($1)->Sup, sizeof($3));$n"
                          else:
-                           "$1 = ($2) #incrSeq($1, sizeof($3));$n"
+                           "$1 = ($2) #incrSeqV2($1, sizeof($3));$n"
   var a, b, dest: TLoc
   initLocExpr(p, e.sons[1], a)
   initLocExpr(p, e.sons[2], b)
@@ -1064,8 +1064,9 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
       getTypeDesc(p.module, skipTypes(e.sons[2].typ, abstractVar))])
   keepAlive(p, a)
   initLoc(dest, locExpr, b.t, OnHeap)
-  dest.r = rfmt(nil, "$1->data[$1->$2-1]", rdLoc(a), lenField(p))
+  dest.r = rfmt(nil, "$1->data[$1->$2]", rdLoc(a), lenField(p))
   genAssignment(p, dest, b, {needToCopy, afDestIsNil})
+  lineCg(p, cpsStmts, "++$1->$2;$n", rdLoc(a), lenField(p))
   gcUsage(e)
 
 proc genReset(p: BProc, n: PNode) =
@@ -1319,6 +1320,8 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
     putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprAny($1, $2)", [
                 rdLoc(a), genTypeInfo(p.module, t)]))
+  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)]))
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 5129c8023..f12a24fa2 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -1101,7 +1101,10 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
     genGotoVar(p, e.sons[1])
   elif not fieldDiscriminantCheckNeeded(p, e):
     var a: TLoc
-    initLocExpr(p, e.sons[0], a)
+    if e[0].kind in {nkDerefExpr, nkHiddenDeref}:
+      genDeref(p, e[0], a, enforceDeref=true)
+    else:
+      initLocExpr(p, e.sons[0], a)
     if fastAsgn: incl(a.flags, lfNoDeepCopy)
     assert(a.t != nil)
     loadInto(p, e.sons[0], e.sons[1], a)
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 3742fd2fd..84d02d1da 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -323,7 +323,8 @@ proc paramStorageLoc(param: PSym): TStorageLoc =
     result = OnUnknown
 
 proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
-                   check: var IntSet, declareEnvironment=true) =
+                   check: var IntSet, declareEnvironment=true;
+                   weakDep=false) =
   params = nil
   if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]):
     rettype = ~"void"
@@ -341,6 +342,8 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
       add(params, ~"*")
       incl(param.loc.flags, lfIndirect)
       param.loc.s = OnUnknown
+    elif weakDep:
+      add(params, getTypeDescWeak(m, param.typ, check))
     else:
       add(params, getTypeDescAux(m, param.typ, check))
     add(params, ~" ")
@@ -577,7 +580,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
     result = getTypeName(t)
     idTablePut(m.typeCache, t, result)
     var rettype, desc: Rope
-    genProcParams(m, t, rettype, desc, check)
+    genProcParams(m, t, rettype, desc, check, true, true)
     if not isImportedType(t):
       if t.callConv != ccClosure: # procedure vars may need a closure!
         addf(m.s[cfsTypes], "typedef $1_PTR($2, $3) $4;$n",
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 783949403..2e95918cc 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -853,14 +853,14 @@ proc genMainProc(m: BModule) =
     # functions, which might otherwise merge their stack frames.
     PreMainBody =
       "void PreMainInner() {$N" &
-      "\tsystemInit();$N" &
+      "\tsystemInit000();$N" &
       "$1" &
       "$2" &
       "$3" &
       "}$N$N" &
       "void PreMain() {$N" &
       "\tvoid (*volatile inner)();$N" &
-      "\tsystemDatInit();$N" &
+      "\tsystemDatInit000();$N" &
       "\tinner = PreMainInner;$N" &
       "$4$5" &
       "\t(*inner)();$N" &
@@ -950,7 +950,7 @@ proc genMainProc(m: BModule) =
     gBreakpoints.add(m.genFilenames)
 
   let initStackBottomCall =
-    if platform.targetOS == osStandalone: "".rope
+    if platform.targetOS == osStandalone or gSelectedGC == gcNone: "".rope
     else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N")
   inc(m.labels)
   appcg(m, m.s[cfsProcs], PreMainBody, [
@@ -974,8 +974,8 @@ proc getSomeInitName(m: PSym, suffix: string): Rope =
   result.add m.name.s
   result.add suffix
 
-proc getInitName(m: PSym): Rope = getSomeInitName(m, "Init")
-proc getDatInitName(m: PSym): Rope = getSomeInitName(m, "DatInit")
+proc getInitName(m: PSym): Rope = getSomeInitName(m, "Init000")
+proc getDatInitName(m: PSym): Rope = getSomeInitName(m, "DatInit000")
 
 proc registerModuleToMain(m: PSym) =
   var
diff --git a/compiler/installer.ini b/compiler/installer.ini
index 70df9fd24..52a3d0886 100644
--- a/compiler/installer.ini
+++ b/compiler/installer.ini
@@ -103,6 +103,9 @@ Files: "lib/impure/nre/private/*.nim"
 Files: "lib/wrappers/*.nim"
 
 Files: "lib/wrappers/readline/*.nim"
+Files: "lib/wrappers/linenoise/*.nim"
+Files: "lib/wrappers/linenoise/*.c"
+Files: "lib/wrappers/linenoise/*.h"
 Files: "lib/wrappers/sdl/*.nim"
 Files: "lib/wrappers/zip/*.nim"
 Files: "lib/wrappers/zip/libzip_all.c"
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 87408f395..6e317fb7e 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1046,9 +1046,18 @@ proc genArg(p: PProc, n: PNode, r: var TCompRes) =
 proc genArgs(p: PProc, n: PNode, r: var TCompRes) =
   add(r.res, "(")
   var hasArgs = false
+
+  var typ = skipTypes(n.sons[0].typ, abstractInst)
+  assert(typ.kind == tyProc)
+  assert(sonsLen(typ) == sonsLen(typ.n))
+
   for i in countup(1, sonsLen(n) - 1):
     let it = n.sons[i]
-    if it.typ.isCompileTimeOnly: continue
+    if i < sonsLen(typ):
+      assert(typ.n.sons[i].kind == nkSym)
+      let paramType = typ.n.sons[i]
+      if paramType.typ.isCompileTimeOnly: continue
+
     if hasArgs: add(r.res, ", ")
     genArg(p, it, r)
     hasArgs = true
diff --git a/compiler/main.nim b/compiler/main.nim
index ee4a34fbb..47fae7fa7 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -378,3 +378,4 @@ proc mainCommand* =
   when SimulateCaasMemReset:
     resetMemory()
 
+  resetAttributes()
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index f1d1029e4..bb247ea54 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -865,6 +865,11 @@ proc rawMessage*(msg: TMsgKind, args: openArray[string]) =
 proc rawMessage*(msg: TMsgKind, arg: string) =
   rawMessage(msg, [arg])
 
+proc resetAttributes* =
+  if {optUseColors, optStdout} * gGlobalOptions == {optUseColors}:
+    terminal.resetAttributes()
+    stdout.flushFile()
+
 proc writeSurroundingSrc(info: TLineInfo) =
   const indent = "  "
   msgWriteln(indent & $info.sourceLine)
diff --git a/compiler/options.nim b/compiler/options.nim
index f312c877c..af1e21e60 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -330,13 +330,16 @@ proc rawFindFile2(f: string): string =
   result = ""
 
 proc findFile*(f: string): string {.procvar.} =
-  result = f.rawFindFile
-  if result.len == 0:
-    result = f.toLower.rawFindFile
+  if f.isAbsolute:
+    result = if f.existsFile: f else: ""
+  else:
+    result = f.rawFindFile
     if result.len == 0:
-      result = f.rawFindFile2
+      result = f.toLower.rawFindFile
       if result.len == 0:
-        result = f.toLower.rawFindFile2
+        result = f.rawFindFile2
+        if result.len == 0:
+          result = f.toLower.rawFindFile2
 
 proc findModule*(modulename, currentModule: string): string =
   # returns path to module
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 6f37fe756..c771155af 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -276,7 +276,8 @@ proc processNote(c: PContext, n: PNode) =
   if (n.kind == nkExprColonExpr) and (sonsLen(n) == 2) and
       (n.sons[0].kind == nkBracketExpr) and
       (n.sons[0].sons[1].kind == nkIdent) and
-      (n.sons[0].sons[0].kind == nkIdent) and (n.sons[1].kind == nkIdent):
+      (n.sons[0].sons[0].kind == nkIdent):
+      #and (n.sons[1].kind == nkIdent):
     var nk: TNoteKind
     case whichKeyword(n.sons[0].sons[0].ident)
     of wHint:
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 376c0d6f7..7cd8e25ee 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -31,6 +31,7 @@ type
     buf*: string
     pendingNL*: int        # negative if not active; else contains the
                            # indentation value
+    pendingWhitespace: int
     comStack*: seq[PNode]  # comment stack
     flags*: TRenderFlags
     checkAnon: bool        # we're in a context that can contain sfAnon
@@ -83,6 +84,7 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) =
   g.buf = ""
   g.flags = renderFlags
   g.pendingNL = -1
+  g.pendingWhitespace = -1
   g.checkAnon = false
 
 proc addTok(g: var TSrcGen, kind: TTokType, s: string) =
@@ -97,12 +99,21 @@ proc addPendingNL(g: var TSrcGen) =
     addTok(g, tkSpaces, "\n" & spaces(g.pendingNL))
     g.lineLen = g.pendingNL
     g.pendingNL = - 1
+    g.pendingWhitespace = -1
+  elif g.pendingWhitespace >= 0:
+    addTok(g, tkSpaces, spaces(g.pendingWhitespace))
+    g.pendingWhitespace = -1
 
 proc putNL(g: var TSrcGen, indent: int) =
   if g.pendingNL >= 0: addPendingNL(g)
   else: addTok(g, tkSpaces, "\n")
   g.pendingNL = indent
   g.lineLen = indent
+  g.pendingWhitespace = -1
+
+proc previousNL(g: TSrcGen): bool =
+  result = g.pendingNL >= 0 or (g.tokens.len > 0 and
+                                g.tokens[^1].kind == tkSpaces)
 
 proc putNL(g: var TSrcGen) =
   putNL(g, g.indent)
@@ -127,10 +138,13 @@ proc dedent(g: var TSrcGen) =
     dec(g.lineLen, IndentWidth)
 
 proc put(g: var TSrcGen, kind: TTokType, s: string) =
-  addPendingNL(g)
-  if len(s) > 0:
-    addTok(g, kind, s)
-    inc(g.lineLen, len(s))
+  if kind != tkSpaces:
+    addPendingNL(g)
+    if len(s) > 0:
+      addTok(g, kind, s)
+      inc(g.lineLen, len(s))
+  else:
+    g.pendingWhitespace = s.len
 
 proc putLong(g: var TSrcGen, kind: TTokType, s: string, lineLen: int) =
   # use this for tokens over multiple lines.
@@ -1196,6 +1210,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     if renderNoPragmas notin g.flags:
       if g.inPragma <= 0:
         inc g.inPragma
+        #if not previousNL(g):
         put(g, tkSpaces, Space)
         put(g, tkCurlyDotLe, "{.")
         gcomma(g, n, emptyContext)
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index 02e909aac..92ce00240 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -90,7 +90,7 @@
 
 import
   os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
-  ropes, idents, securehash, idgen, types, rodutils, memfiles
+  ropes, idents, securehash, idgen, types, rodutils, memfiles, tables
 
 type
   TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
@@ -136,7 +136,7 @@ type
     readerIndex: int
     line: int            # only used for debugging, but is always in the code
     moduleID: int
-    syms: TIdTable       # already processed symbols
+    syms: Table[int, PSym]       # already processed symbols
     memfile: MemFile     # unfortunately there is no point in time where we
                          # can close this! XXX
     methods*: TSymSeq
@@ -372,11 +372,11 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
   else:
     internalError(info, "decodeSym: no ident")
   #echo "decoding: {", ident.s
-  result = PSym(idTableGet(r.syms, id))
+  result = r.syms[id]
   if result == nil:
     new(result)
     result.id = id
-    idTablePut(r.syms, result, result)
+    r.syms[result.id] = result
     if debugIds: registerID(result)
   elif result.id != id:
     internalError(info, "decodeSym: wrong id")
@@ -481,7 +481,7 @@ proc processInterf(r: PRodReader, module: PSym) =
     var s = newStub(r, w, key)
     s.owner = module
     strTableAdd(module.tab, s)
-    idTablePut(r.syms, s, s)
+    r.syms[s.id] = s
 
 proc processCompilerProcs(r: PRodReader, module: PSym) =
   if r.compilerProcsIdx == 0: internalError("processCompilerProcs")
@@ -491,11 +491,11 @@ proc processCompilerProcs(r: PRodReader, module: PSym) =
     inc(r.pos)
     var key = decodeVInt(r.s, r.pos)
     inc(r.pos)                # #10
-    var s = PSym(idTableGet(r.syms, key))
+    var s = r.syms[key]
     if s == nil:
       s = newStub(r, w, key)
       s.owner = module
-      idTablePut(r.syms, s, s)
+      r.syms[s.id] = s
     strTableAdd(rodCompilerprocs, s)
 
 proc processIndex(r: PRodReader; idx: var TIndex; outf: File = nil) =
@@ -667,7 +667,7 @@ proc newRodReader(modfilename: string, hash: SecureHash,
   r.line = 1
   r.readerIndex = readerIndex
   r.filename = modfilename
-  initIdTable(r.syms)
+  r.syms = initTable[int, PSym]()
   # we terminate the file explicitly with ``\0``, so the cast to `cstring`
   # is safe:
   r.s = cast[cstring](r.memfile.mem)
@@ -737,7 +737,7 @@ proc getReader(moduleId: int): PRodReader =
   return nil
 
 proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
-  result = PSym(idTableGet(r.syms, id))
+  result = r.syms[id]
   if result == nil:
     # load the symbol:
     var d = iiTableGet(r.index.tab, id)
@@ -802,7 +802,7 @@ proc getHash*(fileIdx: int32): SecureHash =
   if gMods[fileIdx].hashDone:
     return gMods[fileIdx].hash
 
-  result = secureHashFile(fileIdx.toFilename)
+  result = secureHashFile(fileIdx.toFullPath)
   gMods[fileIdx].hash = result
 
 template growCache*(cache, pos) =
@@ -859,7 +859,7 @@ proc handleSymbolFile(module: PSym): PRodReader =
   result = gMods[fileIdx].rd
   if result != nil:
     module.id = result.moduleID
-    idTablePut(result.syms, module, module)
+    result.syms[module.id] = module
     processInterf(result, module)
     processCompilerProcs(result, module)
     loadConverters(result)
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index 6f7000efc..d48a9ba40 100644
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -11,14 +11,14 @@
 # rod files is a pass, reading of rod files is not! This is why reading and
 # writing of rod files is split into two different modules.
 
-import 
+import
   intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
   condsyms, ropes, idents, securehash, rodread, passes, importer, idgen,
   rodutils
 
 # implementation
 
-type 
+type
   TRodWriter = object of TPassContext
     module: PSym
     hash: SecureHash
@@ -46,15 +46,15 @@ proc addInterfaceSym(w: PRodWriter, s: PSym)
 proc addStmt(w: PRodWriter, n: PNode)
 proc writeRod(w: PRodWriter)
 
-proc getDefines(): string = 
+proc getDefines(): string =
   result = ""
   for d in definedSymbolNames():
     if result.len != 0: add(result, " ")
     add(result, d)
 
-proc fileIdx(w: PRodWriter, filename: string): int = 
-  for i in countup(0, high(w.files)): 
-    if w.files[i] == filename: 
+proc fileIdx(w: PRodWriter, filename: string): int =
+  for i in countup(0, high(w.files)):
+    if w.files[i] == filename:
       return i
   result = len(w.files)
   setLen(w.files, result + 1)
@@ -63,7 +63,7 @@ proc fileIdx(w: PRodWriter, filename: string): int =
 template filename*(w: PRodWriter): string =
   w.module.filename
 
-proc newRodWriter(hash: SecureHash, module: PSym): PRodWriter = 
+proc newRodWriter(hash: SecureHash, module: PSym): PRodWriter =
   new(result)
   result.sstack = @[]
   result.tstack = @[]
@@ -85,12 +85,12 @@ proc newRodWriter(hash: SecureHash, module: PSym): PRodWriter =
   result.init = ""
   result.origFile = module.info.toFilename
   result.data = newStringOfCap(12_000)
-  
+
 proc addModDep(w: PRodWriter, dep: string) =
   if w.modDeps.len != 0: add(w.modDeps, ' ')
   encodeVInt(fileIdx(w, dep), w.modDeps)
 
-const 
+const
   rodNL = "\x0A"
 
 proc addInclDep(w: PRodWriter, dep: string) =
@@ -110,18 +110,18 @@ proc pushSym(w: PRodWriter, s: PSym) =
   if iiTableGet(w.index.tab, s.id) == InvalidKey:
     w.sstack.add(s)
 
-proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode, 
-                result: var string) = 
-  if n == nil: 
+proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
+                result: var string) =
+  if n == nil:
     # nil nodes have to be stored too:
     result.add("()")
     return
   result.add('(')
-  encodeVInt(ord(n.kind), result) 
+  encodeVInt(ord(n.kind), result)
   # we do not write comments for now
   # Line information takes easily 20% or more of the filesize! Therefore we
   # omit line information if it is the same as the father's line information:
-  if fInfo.fileIndex != n.info.fileIndex: 
+  if fInfo.fileIndex != n.info.fileIndex:
     result.add('?')
     encodeVInt(n.info.col, result)
     result.add(',')
@@ -139,7 +139,7 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
   # No need to output the file index, as this is the serialization of one
   # file.
   var f = n.flags * PersistentNodeFlags
-  if f != {}: 
+  if f != {}:
     result.add('$')
     encodeVInt(cast[int32](f), result)
   if n.typ != nil:
@@ -147,16 +147,16 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
     encodeVInt(n.typ.id, result)
     pushType(w, n.typ)
   case n.kind
-  of nkCharLit..nkInt64Lit: 
+  of nkCharLit..nkInt64Lit:
     if n.intVal != 0:
       result.add('!')
       encodeVBiggestInt(n.intVal, result)
-  of nkFloatLit..nkFloat64Lit: 
-    if n.floatVal != 0.0: 
+  of nkFloatLit..nkFloat64Lit:
+    if n.floatVal != 0.0:
       result.add('!')
       encodeStr($n.floatVal, result)
   of nkStrLit..nkTripleStrLit:
-    if n.strVal != "": 
+    if n.strVal != "":
       result.add('!')
       encodeStr(n.strVal, result)
   of nkIdent:
@@ -167,25 +167,25 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
     encodeVInt(n.sym.id, result)
     pushSym(w, n.sym)
   else:
-    for i in countup(0, sonsLen(n) - 1): 
+    for i in countup(0, sonsLen(n) - 1):
       encodeNode(w, n.info, n.sons[i], result)
   add(result, ')')
 
-proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) = 
+proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
   var oldLen = result.len
   result.add('<')
   if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
-  if loc.s != low(loc.s): 
+  if loc.s != low(loc.s):
     add(result, '*')
     encodeVInt(ord(loc.s), result)
-  if loc.flags != {}: 
+  if loc.flags != {}:
     add(result, '$')
     encodeVInt(cast[int32](loc.flags), result)
   if loc.t != nil:
     add(result, '^')
     encodeVInt(cast[int32](loc.t.id), result)
     pushType(w, loc.t)
-  if loc.r != nil: 
+  if loc.r != nil:
     add(result, '!')
     encodeStr($loc.r, result)
   if oldLen + 1 == result.len:
@@ -193,9 +193,9 @@ proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
     setLen(result, oldLen)
   else:
     add(result, '>')
-  
-proc encodeType(w: PRodWriter, t: PType, result: var string) = 
-  if t == nil: 
+
+proc encodeType(w: PRodWriter, t: PType, result: var string) =
+  if t == nil:
     # nil nodes have to be stored too:
     result.add("[]")
     return
@@ -207,38 +207,38 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
   encodeVInt(ord(t.kind), result)
   add(result, '+')
   encodeVInt(t.id, result)
-  if t.n != nil: 
+  if t.n != nil:
     encodeNode(w, unknownLineInfo(), t.n, result)
-  if t.flags != {}: 
+  if t.flags != {}:
     add(result, '$')
     encodeVInt(cast[int32](t.flags), result)
-  if t.callConv != low(t.callConv): 
+  if t.callConv != low(t.callConv):
     add(result, '?')
     encodeVInt(ord(t.callConv), result)
-  if t.owner != nil: 
+  if t.owner != nil:
     add(result, '*')
     encodeVInt(t.owner.id, result)
     pushSym(w, t.owner)
-  if t.sym != nil: 
+  if t.sym != nil:
     add(result, '&')
     encodeVInt(t.sym.id, result)
     pushSym(w, t.sym)
-  if t.size != - 1: 
+  if t.size != - 1:
     add(result, '/')
     encodeVBiggestInt(t.size, result)
-  if t.align != 2: 
+  if t.align != 2:
     add(result, '=')
     encodeVInt(t.align, result)
   encodeLoc(w, t.loc, result)
-  for i in countup(0, sonsLen(t) - 1): 
-    if t.sons[i] == nil: 
+  for i in countup(0, sonsLen(t) - 1):
+    if t.sons[i] == nil:
       add(result, "^()")
-    else: 
-      add(result, '^') 
+    else:
+      add(result, '^')
       encodeVInt(t.sons[i].id, result)
       pushType(w, t.sons[i])
 
-proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) = 
+proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) =
   add(result, '|')
   encodeVInt(ord(lib.kind), result)
   add(result, '|')
@@ -277,10 +277,10 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
   if s.magic != mNone:
     result.add('@')
     encodeVInt(ord(s.magic), result)
-  if s.options != w.options: 
+  if s.options != w.options:
     result.add('!')
     encodeVInt(cast[int32](s.options), result)
-  if s.position != 0: 
+  if s.position != 0:
     result.add('%')
     encodeVInt(s.position, result)
   if s.offset != - 1:
@@ -308,7 +308,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
       if codeAst != nil:
         # resore the AST:
         s.ast.sons[codePos] = codeAst
-  
+
 proc addToIndex(w: var TIndex, key, val: int) =
   if key - w.lastIdxKey == 1:
     # we do not store a key-diff of 1 to safe space
@@ -329,24 +329,25 @@ when debugWrittenIds:
 
 proc symStack(w: PRodWriter): int =
   var i = 0
-  while i < len(w.sstack): 
+  while i < len(w.sstack):
     var s = w.sstack[i]
     if sfForward in s.flags:
       w.sstack[result] = s
       inc result
     elif iiTableGet(w.index.tab, s.id) == InvalidKey:
       var m = getModule(s)
-      if m == nil: internalError("symStack: module nil: " & s.name.s)
-      if (m.id == w.module.id) or (sfFromGeneric in s.flags): 
+      if m == nil and s.kind != skPackage:
+        internalError("symStack: module nil: " & s.name.s)
+      if s.kind == skPackage or m.id == w.module.id or sfFromGeneric in s.flags:
         # put definition in here
         var L = w.data.len
-        addToIndex(w.index, s.id, L) 
+        addToIndex(w.index, s.id, L)
         when debugWrittenIds: incl(debugWritten, s.id)
         encodeSym(w, s, w.data)
         add(w.data, rodNL)
         # put into interface section if appropriate:
-        if {sfExported, sfFromGeneric} * s.flags == {sfExported} and 
-            s.kind in ExportableSymKinds: 
+        if {sfExported, sfFromGeneric} * s.flags == {sfExported} and
+            s.kind in ExportableSymKinds:
           encodeStr(s.name.s, w.interf)
           add(w.interf, ' ')
           encodeVInt(s.id, w.interf)
@@ -362,26 +363,26 @@ proc symStack(w: PRodWriter): int =
         if s.kind == skMethod and sfDispatcher notin s.flags:
           if w.methods.len != 0: add(w.methods, ' ')
           encodeVInt(s.id, w.methods)
-      elif iiTableGet(w.imports.tab, s.id) == InvalidKey: 
+      elif iiTableGet(w.imports.tab, s.id) == InvalidKey:
         addToIndex(w.imports, s.id, m.id)
         when debugWrittenIds:
-          if not Contains(debugWritten, s.id):
+          if not contains(debugWritten, s.id):
             echo(w.filename)
             debug(s)
             debug(s.owner)
             debug(m)
-            InternalError("Symbol referred to but never written")
+            internalError("Symbol referred to but never written")
     inc(i)
   setLen(w.sstack, result)
 
-proc typeStack(w: PRodWriter): int = 
+proc typeStack(w: PRodWriter): int =
   var i = 0
-  while i < len(w.tstack): 
+  while i < len(w.tstack):
     var t = w.tstack[i]
     if t.kind == tyForward:
       w.tstack[result] = t
       inc result
-    elif iiTableGet(w.index.tab, t.id) == InvalidKey: 
+    elif iiTableGet(w.index.tab, t.id) == InvalidKey:
       var L = w.data.len
       addToIndex(w.index, t.id, L)
       encodeType(w, t, w.data)
@@ -401,24 +402,24 @@ proc processStacks(w: PRodWriter, finalPass: bool) =
   if finalPass and (oldS != 0 or oldT != 0):
     internalError("could not serialize some forwarded symbols/types")
 
-proc rawAddInterfaceSym(w: PRodWriter, s: PSym) = 
+proc rawAddInterfaceSym(w: PRodWriter, s: PSym) =
   pushSym(w, s)
   processStacks(w, false)
 
-proc addInterfaceSym(w: PRodWriter, s: PSym) = 
-  if w == nil: return 
-  if s.kind in ExportableSymKinds and 
-      {sfExported, sfCompilerProc} * s.flags != {}: 
+proc addInterfaceSym(w: PRodWriter, s: PSym) =
+  if w == nil: return
+  if s.kind in ExportableSymKinds and
+      {sfExported, sfCompilerProc} * s.flags != {}:
     rawAddInterfaceSym(w, s)
 
-proc addStmt(w: PRodWriter, n: PNode) = 
+proc addStmt(w: PRodWriter, n: PNode) =
   encodeVInt(w.data.len, w.init)
   add(w.init, rodNL)
   encodeNode(w, unknownLineInfo(), n, w.data)
   add(w.data, rodNL)
   processStacks(w, false)
 
-proc writeRod(w: PRodWriter) = 
+proc writeRod(w: PRodWriter) =
   processStacks(w, true)
   var f: File
   if not open(f, completeGeneratedFilePath(changeFileExt(
@@ -439,12 +440,12 @@ proc writeRod(w: PRodWriter) =
   encodeStr(w.origFile, orig)
   f.write(orig)
   f.write(rodNL)
-  
+
   var hash = "HASH:"
   encodeStr($w.hash, hash)
   f.write(hash)
   f.write(rodNL)
-  
+
   var options = "OPTIONS:"
   encodeVInt(cast[int32](w.options), options)
   f.write(options)
@@ -458,31 +459,31 @@ proc writeRod(w: PRodWriter) =
   var cmd = "CMD:"
   encodeVInt(cast[int32](gCmd), cmd)
   f.write(cmd)
-  f.write(rodNL)  
-  
+  f.write(rodNL)
+
   f.write("DEFINES:")
   f.write(w.defines)
   f.write(rodNL)
-  
+
   var files = "FILES(" & rodNL
-  for i in countup(0, high(w.files)): 
+  for i in countup(0, high(w.files)):
     encodeStr(w.files[i], files)
     files.add(rodNL)
   f.write(files)
   f.write(')' & rodNL)
-  
+
   f.write("INCLUDES(" & rodNL)
   f.write(w.inclDeps)
   f.write(')' & rodNL)
-  
+
   f.write("DEPS:")
   f.write(w.modDeps)
   f.write(rodNL)
-  
+
   f.write("INTERF(" & rodNL)
   f.write(w.interf)
   f.write(')' & rodNL)
-  
+
   f.write("COMPILERPROCS(" & rodNL)
   f.write(w.compilerProcs)
   f.write(')' & rodNL)
@@ -490,11 +491,11 @@ proc writeRod(w: PRodWriter) =
   f.write("INDEX(" & rodNL)
   f.write(w.index.r)
   f.write(')' & rodNL)
-  
+
   f.write("IMPORTS(" & rodNL)
   f.write(w.imports.r)
   f.write(')' & rodNL)
-  
+
   f.write("CONVERTERS:")
   f.write(w.converters)
   f.write(rodNL)
@@ -502,11 +503,11 @@ proc writeRod(w: PRodWriter) =
   f.write("METHODS:")
   f.write(w.methods)
   f.write(rodNL)
-  
+
   f.write("INIT(" & rodNL)
   f.write(w.init)
   f.write(')' & rodNL)
-  
+
   f.write("DATA(" & rodNL)
   f.write(w.data)
   f.write(')' & rodNL)
@@ -514,23 +515,23 @@ proc writeRod(w: PRodWriter) =
   # for reading:
   f.write("\0")
   f.close()
-  
+
   #echo "interf: ", w.interf.len
   #echo "index:  ", w.index.r.len
   #echo "init:   ", w.init.len
   #echo "data:   ", w.data.len
 
-proc process(c: PPassContext, n: PNode): PNode = 
+proc process(c: PPassContext, n: PNode): PNode =
   result = n
-  if c == nil: return 
+  if c == nil: return
   var w = PRodWriter(c)
   case n.kind
   of nkStmtList:
     for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i])
     #var s = n.sons[namePos].sym
     #addInterfaceSym(w, s)
-  of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef, 
-      nkTemplateDef, nkMacroDef: 
+  of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef,
+      nkTemplateDef, nkMacroDef:
     var s = n.sons[namePos].sym
     if s == nil: internalError(n.info, "rodwrite.process")
     if n.sons[bodyPos] == nil:
@@ -539,17 +540,17 @@ proc process(c: PPassContext, n: PNode): PNode =
         sfForward notin s.flags:
       addInterfaceSym(w, s)
   of nkVarSection, nkLetSection, nkConstSection:
-    for i in countup(0, sonsLen(n) - 1): 
+    for i in countup(0, sonsLen(n) - 1):
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue
       addInterfaceSym(w, a.sons[0].sym)
-  of nkTypeSection: 
-    for i in countup(0, sonsLen(n) - 1): 
+  of nkTypeSection:
+    for i in countup(0, sonsLen(n) - 1):
       var a = n.sons[i]
-      if a.kind == nkCommentStmt: continue 
+      if a.kind == nkCommentStmt: continue
       if a.sons[0].kind != nkSym: internalError(a.info, "rodwrite.process")
       var s = a.sons[0].sym
-      addInterfaceSym(w, s) 
+      addInterfaceSym(w, s)
       # this takes care of enum fields too
       # Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum
       # type aliasing! Otherwise the same enum symbol would be included
@@ -557,20 +558,20 @@ proc process(c: PPassContext, n: PNode): PNode =
       #
       #        if (a.sons[2] <> nil) and (a.sons[2].kind = nkEnumTy) then begin
       #          a := s.typ.n;
-      #          for j := 0 to sonsLen(a)-1 do 
-      #            addInterfaceSym(w, a.sons[j].sym);        
-      #        end 
-  of nkImportStmt: 
+      #          for j := 0 to sonsLen(a)-1 do
+      #            addInterfaceSym(w, a.sons[j].sym);
+      #        end
+  of nkImportStmt:
     for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleName(n.sons[i]))
     addStmt(w, n)
-  of nkFromStmt: 
+  of nkFromStmt:
     addModDep(w, getModuleName(n.sons[0]))
     addStmt(w, n)
-  of nkIncludeStmt: 
+  of nkIncludeStmt:
     for i in countup(0, sonsLen(n) - 1): addInclDep(w, getModuleName(n.sons[i]))
-  of nkPragma: 
+  of nkPragma:
     addStmt(w, n)
-  else: 
+  else:
     discard
 
 proc myOpen(module: PSym): PPassContext =
@@ -579,7 +580,7 @@ proc myOpen(module: PSym): PPassContext =
   rawAddInterfaceSym(w, module)
   result = w
 
-proc myClose(c: PPassContext, n: PNode): PNode = 
+proc myClose(c: PPassContext, n: PNode): PNode =
   result = process(c, n)
   var w = PRodWriter(c)
   writeRod(w)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 886f9458d..fba64776d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -33,6 +33,7 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     if result.typ.kind == tyVar: result = newDeref(result)
   elif {efWantStmt, efAllowStmt} * flags != {}:
     result.typ = newTypeS(tyEmpty, c)
+    result.typ.flags.incl tfVoid
   else:
     localError(n.info, errExprXHasNoType,
                renderTree(result, {renderNoComments}))
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 23666656e..729222220 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -435,7 +435,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
      mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
      mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mDotDot,
      mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn,
-     mParallel, mPlugin:
+     mParallel, mPlugin, mGetTypeInfo:
     discard
   of mEqProc:
     result = newIntNodeT(ord(
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 161d22fc1..a138981b7 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -260,6 +260,12 @@ proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start=0) =
       addLocalDecl(c, a.sons[j], symKind)
 
 proc semPattern(c: PContext, n: PNode): PNode
+
+proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
+  result = n
+  for i in 0.. < n.len:
+    result.sons[i] = semTemplBody(c, n.sons[i])
+
 proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   result = n
   semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
@@ -420,9 +426,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
           return symChoice(c.c, n, s, scForceOpen)
         else:
           return symChoice(c.c, n, s, scOpen)
-    result = n
-    for i in countup(0, sonsLen(n) - 1):
-      result.sons[i] = semTemplBody(c, n.sons[i])
+    result = semTemplBodySons(c, n)
 
 proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
   result = n
@@ -475,7 +479,7 @@ proc transformToExpr(n: PNode): PNode =
 
 proc semTemplateDef(c: PContext, n: PNode): PNode =
   var s: PSym
-  if c.p.owner.kind == skModule:
+  if isTopLevel(c):
     s = semIdentVis(c, skTemplate, n.sons[0], {sfExported})
     incl(s.flags, sfGlobal)
   else:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 144a41ff0..b518f0fb9 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1051,6 +1051,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     return newOrPrevType(tyError, prev, c)
   else:
     var m = newCandidate(c, t)
+    m.isNoCall = true
     matches(c, n, copyTree(n), m)
 
     if m.state != csMatch and not m.typedescMatched:
@@ -1338,7 +1339,11 @@ proc processMagicType(c: PContext, m: PSym) =
   of mTypeDesc:
     setMagicType(m, tyTypeDesc, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
-  of mVoidType: setMagicType(m, tyEmpty, 0)
+  of mVoidType:
+    setMagicType(m, tyEmpty, 0)
+    # for historical reasons we conflate 'void' with 'empty' so that '@[]'
+    # has the type 'seq[void]'.
+    m.typ.flags.incl tfVoid
   of mArray:
     setMagicType(m, tyArray, 0)
   of mOpenArray:
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index fc7807228..3ac145eb8 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
+    recursionLimit: int
 
 proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType
 proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
@@ -365,6 +366,19 @@ proc propagateFieldFlags(t: PType, n: PNode) =
   else: discard
 
 proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
+  template bailout =
+    if cl.recursionLimit > 100:
+      # bail out, see bug #2509. But note this caching is in general wrong,
+      # look at this example where TwoVectors should not share the generic
+      # instantiations (bug #3112):
+
+      # type
+      #   Vector[N: static[int]] = array[N, float64]
+      #   TwoVectors[Na, Nb: static[int]] = (Vector[Na], Vector[Nb])
+      result = PType(idTableGet(cl.localCache, t))
+      if result != nil: return result
+    inc cl.recursionLimit
+
   result = t
   if t == nil: return
 
@@ -420,8 +434,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
     result = t
 
   of tyGenericInst:
-    result = PType(idTableGet(cl.localCache, t))
-    if result != nil: return result
+    bailout()
     result = instCopyType(cl, t)
     idTablePut(cl.localCache, t, result)
     for i in 1 .. <result.sonsLen:
@@ -431,8 +444,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
   else:
     if containsGenericType(t):
       #if not cl.allowMetaTypes:
-      result = PType(idTableGet(cl.localCache, t))
-      if result != nil: return result
+      bailout()
       result = instCopyType(cl, t)
       result.size = -1 # needs to be recomputed
       #if not cl.allowMetaTypes:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 540f0a04f..ef1c01b7a 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -47,6 +47,7 @@ type
     coerceDistincts*: bool   # this is an explicit coercion that can strip away
                              # a distrinct type
     typedescMatched*: bool
+    isNoCall*: bool          # misused for generic type instantiations C[T]
     inheritancePenalty: int  # to prefer closest father object type
     errors*: CandidateErrors # additional clarifications to be displayed to the
                              # user if overload resolution fails
@@ -268,6 +269,9 @@ proc concreteType(c: TCandidate, t: PType): PType =
     addSonSkipIntLit(result, t.sons[1]) # XXX: semantic checking for the type?
   of tyNil:
     result = nil              # what should it be?
+  of tyTypeDesc:
+    if c.isNoCall: result = t
+    else: result = nil
   of tySequence, tySet:
     if t.sons[0].kind == tyEmpty: result = nil
     else: result = t
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 6d496d6e1..40d273ceb 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1168,9 +1168,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
                                      c.module)
     of opcGorge:
       decodeBC(rkNode)
+      inc pc
+      let rd = c.code[pc].regA
+
       createStr regs[ra]
       regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
-                                     regs[rc].node.strVal)
+                                     regs[rc].node.strVal, regs[rd].node.strVal)
     of opcNError:
       stackTrace(c, tos, pc, errUser, regs[ra].node.strVal)
     of opcNWarning:
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 88bb7ae24..73016108d 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-import ast, types, msgs, osproc, streams, options, idents
+import ast, types, msgs, osproc, streams, options, idents, securehash
 
 proc readOutput(p: Process): string =
   result = ""
@@ -19,15 +19,35 @@ proc readOutput(p: Process): string =
     result.setLen(result.len - "\n".len)
   discard p.waitForExit
 
-proc opGorge*(cmd, input: string): string =
-  try:
-    var p = startProcess(cmd, options={poEvalCommand})
-    if input.len != 0:
-      p.inputStream.write(input)
-      p.inputStream.close()
-    result = p.readOutput
-  except IOError, OSError:
-    result = ""
+proc opGorge*(cmd, input, cache: string): string =
+  if cache.len > 0:# and optForceFullMake notin gGlobalOptions:
+    let h = secureHash(cmd & "\t" & input & "\t" & cache)
+    let filename = options.toGeneratedFile("gorge_" & $h, "txt")
+    var f: File
+    if open(f, filename):
+      result = f.readAll
+      f.close
+      return
+    var readSuccessful = false
+    try:
+      var p = startProcess(cmd, options={poEvalCommand})
+      if input.len != 0:
+        p.inputStream.write(input)
+        p.inputStream.close()
+      result = p.readOutput
+      readSuccessful = true
+      writeFile(filename, result)
+    except IOError, OSError:
+      if not readSuccessful: result = ""
+  else:
+    try:
+      var p = startProcess(cmd, options={poEvalCommand})
+      if input.len != 0:
+        p.inputStream.write(input)
+        p.inputStream.close()
+      result = p.readOutput
+    except IOError, OSError:
+      result = ""
 
 proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
   try:
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 004adedb9..7abcbdb92 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -599,6 +599,18 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   c.freeTemp(tmp)
   c.freeTemp(tmp2)
 
+proc genBinaryABCD(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
+  let
+    tmp = c.genx(n.sons[1])
+    tmp2 = c.genx(n.sons[2])
+    tmp3 = c.genx(n.sons[3])
+  if dest < 0: dest = c.getTemp(n.typ)
+  c.gABC(n, opc, dest, tmp, tmp2)
+  c.gABC(n, opc, tmp3)
+  c.freeTemp(tmp)
+  c.freeTemp(tmp2)
+  c.freeTemp(tmp3)
+
 proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
   let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
   # uint is uint64 in the VM, we we only need to mask the result for
@@ -932,7 +944,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     c.gABC(n, opcTypeTrait, dest, tmp)
     c.freeTemp(tmp)
   of mSlurp: genUnaryABC(c, n, dest, opcSlurp)
-  of mStaticExec: genBinaryABC(c, n, dest, opcGorge)
+  of mStaticExec: genBinaryABCD(c, n, dest, opcGorge)
   of mNLen: genUnaryABI(c, n, dest, opcLenSeq)
   of mNChild: genBinaryABC(c, n, dest, opcNChild)
   of mNSetChild, mNDel:
diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index e036c3b9a..4773258cf 100644
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -86,6 +86,9 @@ $moduledesc
 $content
 """
 
+doc.listing_start = "<pre class = \"listing\">"
+doc.listing_end = "</pre>"
+
 # * $analytics: Google analytics location, includes <script> tags
 doc.file = """<?xml version="1.0" encoding="utf-8" ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
@@ -578,7 +581,7 @@ pre {
   box-sizing: border-box;
   min-width: calc(100% - 19.5px);
   padding: 9.5px;
-  margin: 0 10px 0px 10px;
+  margin: 0.25em 10px 0.25em 10px;
   font-size: 14px;
   line-height: 20px;
   white-space: pre !important;
@@ -981,6 +984,10 @@ div.align-right {
 
 /* div.align-center * { */
 /*   text-align: left } */
+
+ul.simple > li {
+  margin-bottom: 0.5em }
+
 ol.simple, ul.simple {
   margin-bottom: 1em; }
 
diff --git a/doc/lib.txt b/doc/lib.txt
index 14a13c0d2..6a8f32e07 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -35,11 +35,6 @@ Core
   implicitly by the compiler. Do not import it directly. It relies on compiler
   magic to work.
 
-* `unsigned <unsigned.html>`_
-  This module implements basic arithmetic operators for unsigned integers.
-  To discourage users from using unsigned integers, it's not part
-  of ``system``, but an extra import.
-
 * `threads <threads.html>`_
   Nim thread support. **Note**: This is part of the system module. Do not
   import it explicitly.
diff --git a/doc/nep1.txt b/doc/nep1.txt
new file mode 100644
index 000000000..e44ec8382
--- /dev/null
+++ b/doc/nep1.txt
@@ -0,0 +1,208 @@
+==============================================
+Nim Enhancement Proposal #1 - Standard Library Style Guide
+==============================================
+:Author: Clay Sweetser
+:Version: |nimversion|
+
+.. contents::
+
+
+Introduction
+============
+Although Nim supports a variety of code and formatting styles, it is
+nevertheless beneficial that certain community efforts, such as the standard
+library, should follow a consistent set of style guidelines when suitable.
+This enhancement proposal aims to list a series of guidelines that the standard
+library should follow.
+
+Note that there can be exceptions to these rules. Nim being as flexible as it
+is, there will be parts of this style guide that don't make sense in certain
+contexts. Furthermore, just as
+`Python's style guide<http://legacy.python.org/dev/peps/pep-0008/>`_ changes
+over time, this style guide will too. 
+
+These rules will only be enforced for contributions to the Nim
+codebase and official projects, such as the Nim compiler, the standard library,
+and the various official tools such as C2Nim.
+
+----------------
+Style Guidelines
+----------------
+
+Spacing and Whitespace Conventions
+-----------------------------------
+
+- Lines should be no longer than 80 characters. Limiting the amount of
+  information present on each line makes for more readable code - the reader
+  has smaller chunks to process.
+
+- Two spaces should be used for indentation of blocks; tabstops are not allowed
+  (the compiler enforces this). Using spaces means that the appearance of code
+  is more consistent across editors. Unlike spaces, tabstop width varies across
+  editors, and not all editors provide means of changing this width.
+
+- Although use of whitespace for stylistic reasons other than the ones endorsed
+  by this guide are allowed, careful thought should be put into such practices.
+  Not all editors support automatic alignment of code sections, and re-aligning
+  long sections of code by hand can quickly become tedious.
+
+  .. code-block:: nim
+    # This is bad, as the next time someone comes
+    # to edit this code block, they
+    # must re-align all the assignments again:
+    type
+      WordBool*    = int16
+      CalType*     = int
+      ... # 5 lines later
+      CalId*       = int
+      LongLong*    = int64
+      LongLongPtr* = ptr LongLong
+
+
+Naming Conventions
+-------------------------
+
+Note: While the rules outlined below are the *current* naming conventions,
+these conventions have not always been in place. Previously, the naming
+conventions for identifiers followed the Pascal tradition of prefixes which
+indicated the base type of the identifier - PFoo for pointer and reference
+types, TFoo for value types, EFoo for exceptions, etc. Though this has since
+changed, there are many places in the standard library which still use this
+convention. Such style remains in place purely for legacy reasons, and will be
+changed in the future.
+
+- Type identifiers should be in PascalCase. All other identifiers should be in
+  camelCase with the exception of constants which **may** use PascalCase but
+  are not required to.
+
+  .. code-block:: nim
+    const aConstant = 42
+    const FooBar = 4.2
+
+    var aVariable = "Meep"
+
+    type FooBar = object
+
+  For constants coming from a C/C++ wrapper, ALL_UPPERCASE are allowed, but ugly.
+  (Why shout CONSTANT? Constants do no harm, variables do!)
+
+- When naming types that come in value, pointer, and reference varieties, use a
+  regular name for the variety that is to be used the most, and add a "Obj",
+  "Ref", or "Ptr" suffix for the other varieties. If there is no single variety
+  that will be used the most, add the suffixes to the pointer variants only. The
+  same applies to C/C++ wrappers.
+
+  .. code-block:: nim
+    type
+      Handle = int64 # Will be used most often
+      HandleRef = ref Handle # Will be used less often
+- Exception and Error types should have the "Error" suffix.
+
+  .. code-block:: nim
+    type UnluckyError = object of Exception
+- Unless marked with the `{.pure.}` pragma, members of enums should have an
+  identifying prefix, such as an abbreviation of the enum's name.
+
+  .. code-block:: nim
+    type PathComponent = enum
+      pcDir
+      pcLinkToDir
+      pcFile
+      pcLinkToFile
+- Non-pure enum values should use camelCase whereas pure enum values should use
+  PascalCase.
+
+  .. code-block:: nim
+    type PathComponent {.pure.} = enum
+      Dir
+      LinkToDir
+      File
+      LinkToFile
+- In the age of HTTP, HTML, FTP, TCP, IP, UTF, WWW it is foolish to pretend
+  these are somewhat special words requiring all uppercase. Instead tread them as what they are: Real words. So it's ``parseUrl`` rather than ``parseURL``, ``checkHttpHeader`` instead of ``checkHTTPHeader`` etc.
+
+
+Coding Conventions
+------------------
+
+- The 'return' statement should only be used when it's control-flow properties
+  are required. Use a procedures implicit 'result' variable instead. This
+  improves readability.
+
+- Prefer to return `[]` and `""` instead of `nil`, or throw an exception if
+  that is appropriate.
+
+- Use a proc when possible, only using the more powerful facilities of macros,
+  templates, iterators, and converters when necessary.
+
+- Use the 'let' statement (not the var statement) when declaring variables that
+  do not change within their scope. Using the let statement ensures that
+  variables remain immutable, and gives those who read the code a better idea
+  of the code's purpose.
+
+- For new types, it is usually recommended to have both 'ref' and 'object'
+  versions of the type available for others to use. By making both variants
+  available for use, the type may be allocated both on the stack and the heap.
+
+
+Conventions for multi-line statements and expressions
+-----------------------------------------------------
+
+- Any tuple type declarations that are longer than one line should use the
+  regular object type layout instead. This enhances the readability of the
+  tuple declaration by splitting its members information across multiple lines.
+
+  .. code-block:: nim
+    type
+      ShortTuple = tuple[a: int, b: string]
+
+      ReallyLongTuple = tuple
+        wordyTupleMemberOne: string
+        wordyTupleMemberTwo: int
+        wordyTupleMemberThree: double
+- Similarly, any procedure type declarations that are longer than one line
+  should be formatted in the style of a regular type.
+
+  .. code-block:: nim
+    type
+      EventCallback = proc (
+        timeRecieved: Time
+        errorCode: int
+        event: Event
+      )
+- Multi-line procedure declarations/argument lists should continue on the same
+  column as the opening brace. This style is different from that of procedure
+  type declarations in order to distinguish between the heading of a procedure
+  and its body. If the procedure name is too long to make this style
+  convenient, then one of the styles for multi-line procedure calls (or
+  consider renaming your procedure).
+
+  .. code-block:: nim
+    proc lotsOfArguments(argOne: string, argTwo: int, argThree:float
+                         argFour: proc(), argFive: bool): int
+                        {.heyLookALongPragma.} =
+- Multi-line procedure calls should either have one argument per line (like
+  multi-line type declarations) or continue on the same column as the opening
+  parenthesis (like multi-line procedure declarations).  It is suggested that
+  the former style be used for procedure calls with complex argument
+  structures, and the latter style for procedure calls with simpler argument
+  structures.
+
+  .. code-block:: nim
+    # Each argument on a new line, like type declarations
+    # Best suited for 'complex' procedure calls.
+    readDirectoryChangesW(
+      directoryHandle.THandle,
+      buffer.start,
+      bufferSize.int32,
+      watchSubdir.WinBool,
+      filterFlags,
+      cast[ptr dword](nil),
+      cast[Overlapped](ol),
+      cast[OverlappedCompletionRoutine](nil)
+    )
+
+    # Multiple arguments on new lines, aligned to the opening parenthesis
+    # Best suited for 'simple' procedure calls
+    startProcess(nimExecutable, currentDirectory, compilerArguments
+                 environment, processOptions)
diff --git a/doc/nimc.txt b/doc/nimc.txt
index e90c38002..15c9f2955 100644
--- a/doc/nimc.txt
+++ b/doc/nimc.txt
@@ -388,7 +388,7 @@ Use two backticks to produce a single verbatim backtick.
 
 For a toplevel emit statement the section where in the generated C/C++ file
 the code should be emitted can be influenced via the
-prefixes ``/*TYPESECTION*/`` or ``/*VARSECTION*/``:
+prefixes ``/*TYPESECTION*/`` or ``/*VARSECTION*/`` or ``/*INCLUDESECTION*/``:
 
 .. code-block:: Nim
   {.emit: """/*TYPESECTION*/
diff --git a/doc/nimdoc.css b/doc/nimdoc.css
index e3bab07de..a002b6be1 100644
--- a/doc/nimdoc.css
+++ b/doc/nimdoc.css
@@ -1,4 +1,9 @@
 /*

+NOTE - THIS IS PROBABLY NOT THE CSS FILE YOU WANT

+The CSS text used by Nim's documentation tools (such as 'koch web',

+'rst2html', etc) is contained in 'config\nimdoc.cfg'

+*/

+/*

 :Author: David Goodger

 :Contact: goodger@python.org

 :Date: $Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006) $

diff --git a/doc/sets_fragment.txt b/doc/sets_fragment.txt
index 84b13e672..15f0962ef 100644
--- a/doc/sets_fragment.txt
+++ b/doc/sets_fragment.txt
@@ -1,6 +1,16 @@
 The set type models the mathematical notion of a set. The set's
-basetype can only be an ordinal type. The reason is that sets are implemented
-as high performance bit vectors.
+basetype can only be an ordinal type of a certain size, namely:
+  * ``int8``-``int16``
+  * ``uint8``/``byte``-``uint16``
+  * ``char``
+  * ``enum``
+or equivalent. The reason is that sets are implemented as high 
+performance bit vectors. Attempting to declare a set with a larger type will
+result in an error:
+
+.. code-block:: nim
+
+  var s: set[int64] # Error: set is too large
 
 Sets can be constructed via the set constructor: ``{}`` is the empty set. The
 empty set is type compatible with any concrete set type. The constructor
diff --git a/doc/tools.txt b/doc/tools.txt
index b0a45c575..bad603925 100644
--- a/doc/tools.txt
+++ b/doc/tools.txt
@@ -4,6 +4,10 @@ Tools available with Nim
 
 The standard distribution ships with the following tools:
 
+- | `Documentation generator <docs/docgen.html>`_
+  | The builtin document generator ``nim doc2`` generates HTML documentation
+    from ``.nim`` source files.
+
 - | `Nimsuggest for IDE support <nimsuggest.html>`_
   | Through the ``nimsuggest`` tool, any IDE can query a ``.nim`` source file
     and obtain useful information like definition of symbols or suggestions for
diff --git a/doc/tut1.txt b/doc/tut1.txt
index 34684a850..0d2de3c1e 100644
--- a/doc/tut1.txt
+++ b/doc/tut1.txt
@@ -20,7 +20,8 @@ This document is a tutorial for the programming language *Nim*.
 This tutorial assumes that you are familiar with basic programming concepts
 like variables, types or statements but is kept very basic. The `manual
 <manual.html>`_ contains many more examples of the advanced language features.
-
+All code examples in this tutorial, as well as the ones found in the rest of
+Nim's documentation, follow the `Nim style guide <nep1.html>`.
 
 
 The first program
@@ -1233,8 +1234,8 @@ Example:
 .. code-block:: nim
 
   var
-    x: seq[int] # a sequence of integers
-  x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence
+    x: seq[int] # a reference to a sequence of integers
+  x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence allocated on the heap
 
 Sequence variables are initialized with ``nil``. However, most sequence
 operations cannot deal with ``nil`` (leading to an exception being
@@ -1278,6 +1279,23 @@ The `len <system.html#len,TOpenArray>`_, `low <system.html#low>`_ and `high
 with a compatible base type can be passed to an openarray parameter, the index
 type does not matter.
 
+.. code-block:: nim
+  var 
+    fruits:   seq[string]       # reference to a sequence of strings that is initialized with 'nil'
+    capitals: array[3, string]  # array of strings with a fixed size
+  
+  fruits = @[]                  # creates an empty sequence on the heap that will be referenced by 'fruits'
+  
+  capitals = ["New York", "London", "Berlin"]   # array 'capitals' allows only assignment of three elements
+  fruits.add("Banana")          # sequence 'fruits' is dynamically expandable during runtime
+  fruits.add("Mango")
+  
+  proc openArraySize(oa: openArray[string]): int =
+    oa.len
+  
+  assert openArraySize(fruits) == 2     # procedure accepts a sequence as parameter
+  assert openArraySize(capitals) == 3   # but also an array type
+
 The openarray type cannot be nested: multidimensional openarrays are not
 supported because this is seldom needed and cannot be done efficiently.
 
diff --git a/examples/wingui.nim b/examples/wingui.nim
deleted file mode 100644
index 2c2c387bb..000000000
--- a/examples/wingui.nim
+++ /dev/null
@@ -1,9 +0,0 @@
-# test a Windows GUI application
-
-import
-  windows, shellapi, nb30, mmsystem, shfolder
-
-#proc MessageBox(hWnd: int, lpText, lpCaption: CString, uType: uint): int
-#  {stdcall, import: "MessageBox", header: "<windows.h>"}
-
-discard MessageBox(0, "Hello World!", "Nimrod GUI Application", 0)
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index dc97784c3..1f9fb1072 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -13,7 +13,7 @@
 ## details from its clients, it remains inherently unsafe!
 ##
 ## See the `marshal <marshal.html>`_ module for what this module allows you
-## to do. 
+## to do.
 
 {.push hints: off.}
 
@@ -54,7 +54,7 @@ type
     akUInt16 = 42,      ## any represents an unsigned in16
     akUInt32 = 43,      ## any represents an unsigned int32
     akUInt64 = 44,      ## any represents an unsigned int64
-    
+
   Any* = object          ## can represent any nim value; NOTE: the wrapped
                           ## value can be modified with its wrapper! This means
                           ## that ``Any`` keeps a non-traced pointer to its
@@ -114,7 +114,7 @@ proc newAny(value: pointer, rawType: PNimType): Any =
 
 when declared(system.VarSlot):
   proc toAny*(x: VarSlot): Any {.inline.} =
-    ## constructs a ``Any`` object from a variable slot ``x``. 
+    ## constructs a ``Any`` object from a variable slot ``x``.
     ## This captures `x`'s address, so `x` can be modified with its
     ## ``Any`` wrapper! The client needs to ensure that the wrapper
     ## **does not** live longer than `x`!
@@ -128,16 +128,16 @@ proc toAny*[T](x: var T): Any {.inline.} =
   ## that the wrapper **does not** live longer than `x`!
   result.value = addr(x)
   result.rawType = cast[PNimType](getTypeInfo(x))
-  
-proc kind*(x: Any): AnyKind {.inline.} = 
+
+proc kind*(x: Any): AnyKind {.inline.} =
   ## get the type kind
   result = AnyKind(ord(x.rawType.kind))
 
 proc size*(x: Any): int {.inline.} =
   ## returns the size of `x`'s type.
   result = x.rawType.size
-  
-proc baseTypeKind*(x: Any): AnyKind {.inline.} = 
+
+proc baseTypeKind*(x: Any): AnyKind {.inline.} =
   ## get the base type's kind; ``akNone`` is returned if `x` has no base type.
   if x.rawType.base != nil:
     result = AnyKind(ord(x.rawType.base.kind))
@@ -146,7 +146,7 @@ proc baseTypeSize*(x: Any): int {.inline.} =
   ## returns the size of `x`'s basetype.
   if x.rawType.base != nil:
     result = x.rawType.base.size
-  
+
 proc invokeNew*(x: Any) =
   ## performs ``new(x)``. `x` needs to represent a ``ref``.
   assert x.rawType.kind == tyRef
@@ -183,7 +183,7 @@ proc `[]`*(x: Any, i: int): Any =
   case x.rawType.kind
   of tyArray:
     var bs = x.rawType.base.size
-    if i >=% x.rawType.size div bs: 
+    if i >=% x.rawType.size div bs:
       raise newException(IndexError, "index out of bounds")
     return newAny(x.value +!! i*bs, x.rawType.base)
   of tySequence:
@@ -200,7 +200,7 @@ proc `[]=`*(x: Any, i: int, y: Any) =
   case x.rawType.kind
   of tyArray:
     var bs = x.rawType.base.size
-    if i >=% x.rawType.size div bs: 
+    if i >=% x.rawType.size div bs:
       raise newException(IndexError, "index out of bounds")
     assert y.rawType == x.rawType.base
     genericAssign(x.value +!! i*bs, y.value, y.rawType)
@@ -231,23 +231,23 @@ proc base*(x: Any): Any =
 proc isNil*(x: Any): bool =
   ## `isNil` for an any `x` that represents a sequence, string, cstring,
   ## proc or some pointer type.
-  assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer, 
+  assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer,
                             tySequence, tyProc}
   result = isNil(cast[ppointer](x.value)[])
 
 proc getPointer*(x: Any): pointer =
   ## retrieve the pointer value out of `x`. ``x`` needs to be of kind
-  ## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``, 
+  ## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``,
   ## ``akPointer``, ``akSequence``.
-  assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer, 
+  assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer,
                             tySequence, tyProc}
   result = cast[ppointer](x.value)[]
 
 proc setPointer*(x: Any, y: pointer) =
   ## sets the pointer value of `x`. ``x`` needs to be of kind
-  ## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``, 
+  ## ``akString``, ``akCString``, ``akProc``, ``akRef``, ``akPtr``,
   ## ``akPointer``, ``akSequence``.
-  assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer, 
+  assert x.rawType.kind in {tyString, tyCString, tyRef, tyPtr, tyPointer,
                             tySequence, tyProc}
   cast[ppointer](x.value)[] = y
 
@@ -309,7 +309,7 @@ proc getFieldNode(p: pointer, n: ptr TNimNode,
     if cmpIgnoreStyle(n.name, name) == 0:
       result = n
   of nkList:
-    for i in 0..n.len-1: 
+    for i in 0..n.len-1:
       result = getFieldNode(p, n.sons[i], name)
       if result != nil: break
   of nkCase:
@@ -345,7 +345,7 @@ proc `[]`*(x: Any, fieldName: string): Any =
     result.value = x.value +!! n.offset
     result.rawType = n.typ
   elif x.rawType.kind == tyObject and x.rawType.base != nil:
-    return `[]`(TAny(value: x.value, rawType: x.rawType.base), fieldName)
+    return `[]`(Any(value: x.value, rawType: x.rawType.base), fieldName)
   else:
     raise newException(ValueError, "invalid field name: " & fieldName)
 
@@ -366,22 +366,22 @@ proc getInt*(x: Any): int =
   assert skipRange(x.rawType).kind == tyInt
   result = cast[ptr int](x.value)[]
 
-proc getInt8*(x: Any): int8 = 
+proc getInt8*(x: Any): int8 =
   ## retrieve the int8 value out of `x`. `x` needs to represent an int8.
   assert skipRange(x.rawType).kind == tyInt8
   result = cast[ptr int8](x.value)[]
 
-proc getInt16*(x: Any): int16 = 
+proc getInt16*(x: Any): int16 =
   ## retrieve the int16 value out of `x`. `x` needs to represent an int16.
   assert skipRange(x.rawType).kind == tyInt16
   result = cast[ptr int16](x.value)[]
-  
-proc getInt32*(x: Any): int32 = 
+
+proc getInt32*(x: Any): int32 =
   ## retrieve the int32 value out of `x`. `x` needs to represent an int32.
   assert skipRange(x.rawType).kind == tyInt32
   result = cast[ptr int32](x.value)[]
 
-proc getInt64*(x: Any): int64 = 
+proc getInt64*(x: Any): int64 =
   ## retrieve the int64 value out of `x`. `x` needs to represent an int64.
   assert skipRange(x.rawType).kind == tyInt64
   result = cast[ptr int64](x.value)[]
@@ -517,7 +517,7 @@ proc getEnumOrdinal*(x: Any, name: string): int =
   var n = typ.node
   var s = n.sons
   for i in 0 .. n.len-1:
-    if cmpIgnoreStyle($s[i].name, name) == 0: 
+    if cmpIgnoreStyle($s[i].name, name) == 0:
       if ntfEnumHole notin typ.flags:
         return i
       else:
@@ -527,7 +527,7 @@ proc getEnumOrdinal*(x: Any, name: string): int =
 proc getEnumField*(x: Any, ordinalValue: int): string =
   ## gets the enum field name as a string. `x` needs to represent an enum
   ## but is only used to access the type information. The field name of
-  ## `ordinalValue` is returned. 
+  ## `ordinalValue` is returned.
   var typ = skipRange(x.rawType)
   assert typ.kind == tyEnum
   var e = ordinalValue
@@ -546,17 +546,17 @@ proc getEnumField*(x: Any): string =
   ## gets the enum field name as a string. `x` needs to represent an enum.
   result = getEnumField(x, getBiggestInt(x).int)
 
-proc getFloat*(x: Any): float = 
-  ## retrieve the float value out of `x`. `x` needs to represent an float.  
+proc getFloat*(x: Any): float =
+  ## retrieve the float value out of `x`. `x` needs to represent an float.
   assert skipRange(x.rawType).kind == tyFloat
   result = cast[ptr float](x.value)[]
 
-proc getFloat32*(x: Any): float32 = 
+proc getFloat32*(x: Any): float32 =
   ## retrieve the float32 value out of `x`. `x` needs to represent an float32.
   assert skipRange(x.rawType).kind == tyFloat32
   result = cast[ptr float32](x.value)[]
-  
-proc getFloat64*(x: Any): float64 = 
+
+proc getFloat64*(x: Any): float64 =
   ## retrieve the float64 value out of `x`. `x` needs to represent an float64.
   assert skipRange(x.rawType).kind == tyFloat64
   result = cast[ptr float64](x.value)[]
@@ -579,23 +579,23 @@ proc setBiggestFloat*(x: Any, y: BiggestFloat) =
   of tyFloat64: cast[ptr float64](x.value)[] = y
   else: assert false
 
-proc getString*(x: Any): string = 
+proc getString*(x: Any): string =
   ## retrieve the string value out of `x`. `x` needs to represent a string.
   assert x.rawType.kind == tyString
   if not isNil(cast[ptr pointer](x.value)[]):
     result = cast[ptr string](x.value)[]
 
-proc setString*(x: Any, y: string) = 
+proc setString*(x: Any, y: string) =
   ## sets the string value of `x`. `x` needs to represent a string.
   assert x.rawType.kind == tyString
   cast[ptr string](x.value)[] = y
 
-proc getCString*(x: Any): cstring = 
+proc getCString*(x: Any): cstring =
   ## retrieve the cstring value out of `x`. `x` needs to represent a cstring.
   assert x.rawType.kind == tyCString
   result = cast[ptr cstring](x.value)[]
 
-proc assign*(x, y: Any) = 
+proc assign*(x, y: Any) =
   ## copies the value of `y` to `x`. The assignment operator for ``Any``
   ## does NOT do this; it performs a shallow copy instead!
   assert y.rawType == x.rawType
@@ -637,7 +637,7 @@ proc inclSetElement*(x: Any, elem: int) =
   of 2:
     var a = cast[ptr int16](p)
     a[] = a[] or (1'i16 shl int16(e))
-  of 4: 
+  of 4:
     var a = cast[ptr int32](p)
     a[] = a[] or (1'i32 shl int32(e))
   of 8:
@@ -651,7 +651,7 @@ when isMainModule:
   type
     TE = enum
       blah, blah2
-  
+
     TestObj = object
       test, asd: int
       case test2: TE
@@ -665,7 +665,7 @@ when isMainModule:
   var y = 78
   x[4] = toAny(y)
   assert cast[ptr int](x[2].value)[] == 2
-  
+
   var test2: tuple[name: string, s: int] = ("test", 56)
   var x2 = toAny(test2)
   var i = 0
@@ -675,7 +675,7 @@ when isMainModule:
     of 1: assert n == "s" and $a.kind == "akInt"
     else: assert false
     inc i
-    
+
   var test3: TestObj
   test3.test = 42
   test3.test2 = blah2
@@ -683,27 +683,27 @@ when isMainModule:
   i = 0
   for n, a in fields(x3):
     case i
-    of 0: assert n == "test" and $a.kind == "akInt" 
+    of 0: assert n == "test" and $a.kind == "akInt"
     of 1: assert n == "asd" and $a.kind == "akInt"
     of 2: assert n == "test2" and $a.kind == "akEnum"
     else: assert false
     inc i
-  
+
   var test4: ref string
   new(test4)
   test4[] = "test"
   var x4 = toAny(test4)
   assert($x4[].kind() == "akString")
-  
+
   block:
     # gimme a new scope dammit
     var myarr: array[0..4, array[0..4, string]] = [
-      ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"], 
-      ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"], 
+      ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
+      ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
       ["test", "1", "2", "3", "4"]]
     var m = toAny(myArr)
     for i in 0 .. m.len-1:
       for j in 0 .. m[i].len-1:
         echo getString(m[i][j])
-      
+
 
diff --git a/lib/core/unsigned.nim b/lib/core/unsigned.nim
index 20fcd03aa..93a29e1c9 100644
--- a/lib/core/unsigned.nim
+++ b/lib/core/unsigned.nim
@@ -7,51 +7,12 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements basic arithmetic operators for unsigned integers.
-## To discourage users from using ``unsigned``, it's not part of ``system``,
-## but an extra import.
+## **Warning:** Since version 0.11.4 this module is deprecated.
+##
+## This module implemented basic arithmetic operators for unsigned integers.
+## These operators are now available in the ``system`` module directly.
 
-proc `not`*[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.}
-  ## computes the `bitwise complement` of the integer `x`.
-
-proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.}
-  ## computes the `shift right` operation of `x` and `y`.
-
-proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.}
-  ## computes the `shift left` operation of `x` and `y`.
-
-proc `and`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.}
-  ## computes the `bitwise and` of numbers `x` and `y`.
-
-proc `or`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitorI", noSideEffect.}
-  ## computes the `bitwise or` of numbers `x` and `y`.
-
-proc `xor`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitxorI", noSideEffect.}
-  ## computes the `bitwise xor` of numbers `x` and `y`.
-
-proc `==`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "EqI", noSideEffect.}
-  ## Compares two unsigned integers for equality.
-
-proc `+`*[T: SomeUnsignedInt](x, y: T): T {.magic: "AddU", noSideEffect.}
-  ## Binary `+` operator for unsigned integers.
-
-proc `-`*[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.}
-  ## Binary `-` operator for unsigned integers.
-
-proc `*`*[T: SomeUnsignedInt](x, y: T): T {.magic: "MulU", noSideEffect.}
-  ## Binary `*` operator for unsigned integers.
-
-proc `div`*[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
-  ## computes the integer division. This is roughly the same as
-  ## ``floor(x/y)``.
-
-proc `mod`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ModU", noSideEffect.}
-  ## computes the integer modulo operation. This is the same as
-  ## ``x - (x div y) * y``.
-
-proc `<=`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LeU", noSideEffect.}
-  ## Returns true iff ``x <= y``.
-
-proc `<`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LtU", noSideEffect.}
-  ## Returns true iff ``unsigned(x) < unsigned(y)``.
+{.deprecated.}
 
+export `shr`, `shl`, `and`, `or`, `xor`, `==`, `+`, `-`, `*`, `div`, `mod`,
+  `<=`, `<`
diff --git a/lib/nimbase.h b/lib/nimbase.h
index eea618bac..e796ba735 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -399,6 +399,10 @@ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(
 #  define NIM_EXTERNC
 #endif
 
+/* we have to tinker with TNimType as it's both part of system.nim and
+   typeinfo.nim but system.nim doesn't export it cleanly... */
+typedef struct TNimType TNimType;
+
 /* ---------------- platform specific includes ----------------------- */
 
 /* VxWorks related includes */
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index f9c8198f2..cc21b9382 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -46,6 +46,7 @@ type
     target*: OutputTarget
     config*: StringTableRef
     splitAfter*: int          # split too long entries in the TOC
+    listingCounter: int
     tocPart*: seq[TocEntry]
     hasToc*: bool
     theIndex: string # Contents of the index file to be dumped at the end.
@@ -832,7 +833,7 @@ proc parseCodeBlockParams(d: PDoc, n: PRstNode): CodeBlockParams =
   if result.langStr != "":
     result.lang = getSourceLanguage(result.langStr)
 
-proc buildLinesHTMLTable(params: CodeBlockParams, code: string):
+proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string):
     tuple[beginTable, endTable: string] =
   ## Returns the necessary tags to start/end a code block in HTML.
   ##
@@ -840,20 +841,24 @@ proc buildLinesHTMLTable(params: CodeBlockParams, code: string):
   ## <pre> pair. Otherwise it will build a table and insert an initial column
   ## with all the line numbers, which requires you to pass the `code` to detect
   ## how many lines have to be generated (and starting at which point!).
+  inc d.listingCounter
+  let id = $d.listingCounter
   if not params.numberLines:
-    result = ("<pre>", "</pre>")
+    result = (d.config["doc.listing_start"] % id,
+              d.config["doc.listing_end"] % id)
     return
 
   var codeLines = 1 + code.strip.countLines
   assert codeLines > 0
-  result.beginTable = """<table class="line-nums-table"><tbody><tr><td class="blob-line-nums"><pre>"""
+  result.beginTable = """<table class="line-nums-table"><tbody><tr><td class="blob-line-nums"><pre class="line-nums">"""
   var line = params.startLine
   while codeLines > 0:
     result.beginTable.add($line & "\n")
     line.inc
     codeLines.dec
-  result.beginTable.add("</pre></td><td><pre>")
-  result.endTable = "</pre></td></tr></tbody></table>"
+  result.beginTable.add("</pre></td><td>" & (d.config["doc.listing_start"] % id))
+  result.endTable = (d.config["doc.listing_end"] % id) &
+      "</td></tr></tbody></table>" & (d.config["doc.listing_button"] % id)
 
 proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
   ## Renders a code block, appending it to `result`.
@@ -871,7 +876,7 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
   var m = n.sons[2].sons[0]
   assert m.kind == rnLeaf
 
-  let (blockStart, blockEnd) = params.buildLinesHTMLTable(m.text)
+  let (blockStart, blockEnd) = buildLinesHTMLTable(d, params, m.text)
 
   dispA(d.target, result, blockStart, "\\begin{rstpre}\n", [])
   if params.lang == langNone:
@@ -1209,6 +1214,9 @@ $moduledesc
 $content
 </div>
 """)
+  setConfigVar("doc.listing_start", "<pre class = \"listing\">")
+  setConfigVar("doc.listing_end", "</pre>")
+  setConfigVar("doc.listing_button", "</pre>")
   setConfigVar("doc.body_no_toc", "$moduledesc $content")
   setConfigVar("doc.file", "$content")
   setConfigVar("doc.smiley_format", "/images/smilies/$1.gif")
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 2ca2098b3..e6b8088c5 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -834,11 +834,12 @@ proc post*(client: AsyncHttpClient, url: string, body = "", multipart: Multipart
     else:
       x
   var xb = mpBody.withNewLine() & body
-  client.headers["Content-Type"] = mpHeader.split(": ")[1]
+  if multipart != nil:
+    client.headers["Content-Type"] = mpHeader.split(": ")[1]
   client.headers["Content-Length"] = $len(xb)
 
   result = await client.request(url, httpPOST, xb)
-      
+
 when not defined(testing) and isMainModule:
   when true:
     # Async
diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim
index 49f049e46..173cd1e81 100644
--- a/lib/pure/marshal.nim
+++ b/lib/pure/marshal.nim
@@ -17,7 +17,7 @@
 ## .. code-block:: nim
 ##
 ##   type
-##     A = object
+##     A = object of RootObj
 ##     B = object of A
 ##       f: int
 ##
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index d3f1f3814..821ab738b 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -56,7 +56,7 @@ type
     fcNegInf     ## value is negative infinity
 
 proc classify*(x: float): FloatClass =
-  ## classifies a floating point value. Returns `x`'s class as specified by
+  ## Classifies a floating point value. Returns `x`'s class as specified by
   ## `FloatClass`.
 
   # JavaScript and most C compilers have no classify:
@@ -74,7 +74,7 @@ proc classify*(x: float): FloatClass =
 
 
 proc binom*(n, k: int): int {.noSideEffect.} =
-  ## computes the binomial coefficient
+  ## Computes the binomial coefficient
   if k <= 0: return 1
   if 2*k > n: return binom(n, n-k)
   result = n
@@ -82,18 +82,18 @@ proc binom*(n, k: int): int {.noSideEffect.} =
     result = (result * (n + 1 - i)) div i
 
 proc fac*(n: int): int {.noSideEffect.} =
-  ## computes the faculty/factorial function.
+  ## 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.
+  ## Returns true, if `x` is a power of two, false otherwise.
   ## Zero and negative numbers are not a power of two.
   return (x > 0) and ((x and (x - 1)) == 0)
 
 proc nextPowerOfTwo*(x: int): int {.noSideEffect.} =
-  ## returns `x` rounded up to the nearest power of two.
+  ## Returns `x` rounded up to the nearest power of two.
   ## Zero and negative numbers get rounded up to 1.
   result = x - 1
   when defined(cpu64):
@@ -108,28 +108,28 @@ proc nextPowerOfTwo*(x: int): int {.noSideEffect.} =
   result += 1 + ord(x<=0)
 
 proc countBits32*(n: int32): int {.noSideEffect.} =
-  ## counts the set bits in `n`.
+  ## Counts the set bits in `n`.
   var v = n
   v = v -% ((v shr 1'i32) and 0x55555555'i32)
   v = (v and 0x33333333'i32) +% ((v shr 2'i32) and 0x33333333'i32)
   result = ((v +% (v shr 4'i32) and 0xF0F0F0F'i32) *% 0x1010101'i32) shr 24'i32
 
 proc sum*[T](x: openArray[T]): T {.noSideEffect.} =
-  ## computes the sum of the elements in `x`.
+  ## Computes the sum of the elements in `x`.
   ## If `x` is empty, 0 is returned.
   for i in items(x): result = result + i
 
 template toFloat(f: float): float = f
 
 proc mean*[T](x: openArray[T]): float {.noSideEffect.} =
-  ## computes the mean of the elements in `x`, which are first converted to floats.
+  ## Computes the mean of the elements in `x`, which are first converted to floats.
   ## If `x` is empty, NaN is returned.
   ## ``toFloat(x: T): float`` must be defined.
   for i in items(x): result = result + toFloat(i)
   result = result / toFloat(len(x))
 
 proc variance*[T](x: openArray[T]): float {.noSideEffect.} =
-  ## computes the variance of the elements in `x`.
+  ## Computes the variance of the elements in `x`.
   ## If `x` is empty, NaN is returned.
   ## ``toFloat(x: T): float`` must be defined.
   result = 0.0
@@ -140,41 +140,43 @@ proc variance*[T](x: openArray[T]): float {.noSideEffect.} =
   result = result / toFloat(len(x))
 
 proc random*(max: int): int {.benign.}
-  ## returns a random number in the range 0..max-1. The sequence of
+  ## Returns a random number in the range 0..max-1. The sequence of
   ## random number is always the same, unless `randomize` is called
   ## which initializes the random number generator with a "random"
   ## number, i.e. a tickcount.
 
 proc random*(max: float): float {.benign.}
-  ## returns a random number in the range 0..<max. The sequence of
+  ## Returns a random number in the range 0..<max. The sequence of
   ## random number is always the same, unless `randomize` is called
   ## which initializes the random number generator with a "random"
   ## number, i.e. a tickcount. This has a 16-bit resolution on windows
   ## and a 48-bit resolution on other platforms.
 
 proc randomize*() {.benign.}
-  ## initializes the random number generator with a "random"
+  ## Initializes the random number generator with a "random"
   ## number, i.e. a tickcount. Note: Does nothing for the JavaScript target,
   ## as JavaScript does not support this.
 
 proc randomize*(seed: int) {.benign.}
-  ## initializes the random number generator with a specific seed.
+  ## Initializes the random number generator with a specific seed.
   ## Note: Does nothing for the JavaScript target,
   ## as JavaScript does not support this.
 
 {.push noSideEffect.}
 when not defined(JS):
   proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
-    ## computes the square root of `x`.
+    ## Computes the square root of `x`.
   proc cbrt*(x: float): float {.importc: "cbrt", header: "<math.h>".}
-    ## computes the cubic root of `x`
+    ## Computes the cubic root of `x`
 
   proc ln*(x: float): float {.importc: "log", header: "<math.h>".}
-    ## computes ln(x).
+    ## Computes the natural log of `x`
   proc log10*(x: float): float {.importc: "log10", header: "<math.h>".}
+    ## Computes the common logarithm (base 10) of `x`
   proc log2*(x: float): float = return ln(x) / ln(2.0)
+    ## Computes the binary logarithm (base 2) of `x`
   proc exp*(x: float): float {.importc: "exp", header: "<math.h>".}
-    ## computes e**x.
+    ## Computes the exponential function of `x` (pow(E, x))
 
   proc frexp*(x: float, exponent: var int): float {.
     importc: "frexp", header: "<math.h>".}
@@ -185,11 +187,14 @@ when not defined(JS):
     ## m.
 
   proc round*(x: float): int {.importc: "lrint", header: "<math.h>".}
-    ## converts a float to an int by rounding.
+    ## Converts a float to an int by rounding.
 
   proc arccos*(x: float): float {.importc: "acos", header: "<math.h>".}
+    ## Computes the arc cosine of `x`
   proc arcsin*(x: float): float {.importc: "asin", header: "<math.h>".}
+    ## Computes the arc sine of `x`
   proc arctan*(x: float): float {.importc: "atan", header: "<math.h>".}
+    ## Calculate the arc tangent of `y` / `x`
   proc arctan2*(y, x: float): float {.importc: "atan2", header: "<math.h>".}
     ## Calculate the arc tangent of `y` / `x`.
     ## `atan2` returns the arc tangent of `y` / `x`; it produces correct
@@ -197,16 +202,23 @@ when not defined(JS):
     ## (`x` near 0).
 
   proc cos*(x: float): float {.importc: "cos", header: "<math.h>".}
+    ## Computes the cosine of `x`
   proc cosh*(x: float): float {.importc: "cosh", header: "<math.h>".}
+    ## Computes the hyperbolic cosine of `x`
   proc hypot*(x, y: float): float {.importc: "hypot", header: "<math.h>".}
-    ## same as ``sqrt(x*x + y*y)``.
+    ## Computes the hypotenuse of a right-angle triangle with `x` and
+    ## `y` as its base and height. Equivalent to ``sqrt(x*x + y*y)``.
 
   proc sinh*(x: float): float {.importc: "sinh", header: "<math.h>".}
+    ## Computes the hyperbolic sine of `x`
   proc sin*(x: float): float {.importc: "sin", header: "<math.h>".}
+    ## Computes the sine of `x`
   proc tan*(x: float): float {.importc: "tan", header: "<math.h>".}
+    ## Computes the tangent of `x`
   proc tanh*(x: float): float {.importc: "tanh", header: "<math.h>".}
+    ## Computes the hyperbolic tangent of `x`
   proc pow*(x, y: float): float {.importc: "pow", header: "<math.h>".}
-    ## computes x to power raised of y.
+    ## Computes `x` to power of `y`.
 
   proc erf*(x: float): float {.importc: "erf", header: "<math.h>".}
     ## The error function
@@ -269,10 +281,26 @@ when not defined(JS):
     result = int(rand()) mod max
 
   proc trunc*(x: float): float {.importc: "trunc", header: "<math.h>".}
+    ## Truncates `x` to the decimal point
+    ##
+    ## .. code-block:: nim
+    ##  echo trunc(PI) # 3.0
   proc floor*(x: float): float {.importc: "floor", header: "<math.h>".}
+    ## Computes the floor function (i.e., the largest integer not greater than `x`)
+    ##
+    ## .. code-block:: nim
+    ##  echo floor(-3.5) ## -4.0
   proc ceil*(x: float): float {.importc: "ceil", header: "<math.h>".}
+    ## Computes the ceiling function (i.e., the smallest integer not less than `x`)
+    ##
+    ## .. code-block:: nim
+    ##  echo ceil(-2.1) ## -2.0
 
   proc fmod*(x, y: float): float {.importc: "fmod", header: "<math.h>".}
+    ## Computes the remainder of `x` divided by `y`
+    ##
+    ## .. code-block:: nim
+    ##  echo fmod(-2.5, 0.3) ## -0.1
 
 else:
   proc mathrandom(): float {.importc: "Math.random", nodecl.}
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index d9f4845f3..141543c70 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -294,7 +294,7 @@ proc getSocketError*(socket: Socket): OSErrorCode =
   if result == 0.OSErrorCode:
     result = socket.lastError
   if result == 0.OSErrorCode:
-    raise newException(OSError, "No valid socket error code available")
+    raiseOSError(result, "No valid socket error code available")
 
 proc socketError*(socket: Socket, err: int = -1, async = false,
                   lastError = (-1).OSErrorCode) =
@@ -332,10 +332,8 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
           else:
             let errStr = $ErrErrorString(sslErr, nil)
             raiseSSLError(errStr & ": " & errStr)
-          let osMsg = osErrorMsg osLastError()
-          if osMsg != "":
-            errStr.add ". The OS reports: " & osMsg
-          raise newException(OSError, errStr)
+          let osErr = osLastError()
+          raiseOSError(osErr, errStr)
         of SSL_ERROR_SSL:
           raiseSSLError()
         else: raiseSSLError("Unknown Error")
@@ -921,7 +919,7 @@ proc send*(socket: Socket, data: string,
     socketError(socket, lastError = lastError)
 
   if sent != data.len:
-    raise newException(OSError, "Could not send all data.")
+    raiseOSError(osLastError(), "Could not send all data.")
 
 proc trySend*(socket: Socket, data: string): bool {.tags: [WriteIOEffect].} =
   ## Safe alternative to ``send``. Does not raise an EOS when an error occurs,
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 59a56a1ab..48d255dca 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -621,6 +621,20 @@ proc parentDir*(path: string): string {.
   else:
     result = ""
 
+proc tailDir*(path: string): string {.
+  noSideEffect, rtl, extern: "nos$1".} =
+  ## Returns the tail part of `path`..
+  ##
+  ## | Example: ``tailDir("/usr/local/bin") == "local/bin"``.
+  ## | Example: ``tailDir("usr/local/bin/") == "local/bin"``.
+  ## | Example: ``tailDir("bin") == ""``.
+  var q = 1
+  if len(path) >= 1 and path[len(path)-1] in {DirSep, AltSep}: q = 2
+  for i in 0..len(path)-q:
+    if path[i] in {DirSep, AltSep}:
+      return substr(path, i+1)
+  result = ""
+
 proc isRootDir*(path: string): bool {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Checks whether a given `path` is a root directory
@@ -1022,7 +1036,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
       if moveFileA(source, dest, 0'i32) == 0'i32: raiseOSError(osLastError())
   else:
     if c_rename(source, dest) != 0'i32:
-      raise newException(OSError, $strerror(errno))
+      raiseOSError(osLastError(), $strerror(errno))
 
 when not declared(ENOENT) and not defined(Windows):
   when NoFakeVars:
@@ -1057,7 +1071,7 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].}
           raiseOSError(osLastError())
   else:
     if c_remove(file) != 0'i32 and errno != ENOENT:
-      raise newException(OSError, $strerror(errno))
+      raiseOSError(osLastError(), $strerror(errno))
 
 proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
   tags: [ExecIOEffect].} =
diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim
index e1abb0a4f..f8b2c3d8d 100644
--- a/lib/pure/parsexml.nim
+++ b/lib/pure/parsexml.nim
@@ -535,6 +535,10 @@ proc parseAttribute(my: var XmlParser) =
         pos = lexbase.handleLF(my, pos)
         buf = my.buf
         pendingSpace = true
+      of '/':
+        pos = lexbase.handleRefillChar(my, pos)
+        buf = my.buf
+        add(my.b, '/')
       else:
         if buf[pos] == quote:
           inc(pos)
diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim
index 349b0d97a..7873e7226 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/rawsockets.nim
@@ -207,7 +207,7 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
     when useWinVersion:
       raiseOSError(osLastError())
     else:
-      raise newException(OSError, $gai_strerror(gaiResult))
+      raiseOSError(osLastError(), $gai_strerror(gaiResult))
 
 proc dealloc*(ai: ptr AddrInfo) =
   freeaddrinfo(ai)
@@ -251,7 +251,7 @@ proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
     var s = winlean.getservbyname(name, proto)
   else:
     var s = posix.getservbyname(name, proto)
-  if s == nil: raise newException(OSError, "Service not found.")
+  if s == nil: raiseOSError(osLastError(), "Service not found.")
   result.name = $s.s_name
   result.aliases = cstringArrayToSeq(s.s_aliases)
   result.port = Port(s.s_port)
@@ -267,7 +267,7 @@ proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].}
     var s = winlean.getservbyport(ze(int16(port)).cint, proto)
   else:
     var s = posix.getservbyport(ze(int16(port)).cint, proto)
-  if s == nil: raise newException(OSError, "Service not found.")
+  if s == nil: raiseOSError(osLastError(), "Service not found.")
   result.name = $s.s_name
   result.aliases = cstringArrayToSeq(s.s_aliases)
   result.port = Port(s.s_port)
@@ -286,7 +286,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
     var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen,
                                 cint(posix.AF_INET))
     if s == nil:
-      raise newException(OSError, $hstrerror(h_errno))
+      raiseOSError(osLastError(), $hstrerror(h_errno))
 
   result.name = $s.h_name
   result.aliases = cstringArrayToSeq(s.h_aliases)
@@ -298,7 +298,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
     elif s.h_addrtype == posix.AF_INET6:
       result.addrtype = AF_INET6
     else:
-      raise newException(OSError, "unknown h_addrtype")
+      raiseOSError(osLastError(), "unknown h_addrtype")
   result.addrList = cstringArrayToSeq(s.h_addr_list)
   result.length = int(s.h_length)
 
@@ -319,7 +319,7 @@ proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =
     elif s.h_addrtype == posix.AF_INET6:
       result.addrtype = AF_INET6
     else:
-      raise newException(OSError, "unknown h_addrtype")
+      raiseOSError(osLastError(), "unknown h_addrtype")
   result.addrList = cstringArrayToSeq(s.h_addr_list)
   result.length = int(s.h_length)
 
@@ -335,7 +335,7 @@ proc getSockDomain*(socket: SocketHandle): Domain =
   elif name.sa_family == rawAfInet6:
     result = AF_INET6
   else:
-    raise newException(OSError, "unknown socket family in getSockFamily")
+    raiseOSError(osLastError(), "unknown socket family in getSockFamily")
 
 
 proc getAddrString*(sockAddr: ptr SockAddr): string =
@@ -353,7 +353,7 @@ proc getAddrString*(sockAddr: ptr SockAddr): string =
       if posix.IN6_IS_ADDR_V4MAPPED(addr6) != 0:
         result = result.substr("::ffff:".len)
   else:
-    raise newException(OSError, "unknown socket family in getAddrString")
+    raiseOSError(osLastError(), "unknown socket family in getAddrString")
 
 
 proc getSockName*(socket: SocketHandle): Port =
diff --git a/compiler/securehash.nim b/lib/pure/securehash.nim
index 8ac6acb0e..8ac6acb0e 100644
--- a/compiler/securehash.nim
+++ b/lib/pure/securehash.nim
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
index aa8ad39d1..bfc393a96 100644
--- a/lib/pure/selectors.nim
+++ b/lib/pure/selectors.nim
@@ -295,7 +295,8 @@ proc contains*(s: Selector, key: SelectorKey): bool =
   ## ensures that the keys are equal. File descriptors may not always be
   ## unique especially when an fd is closed and then a new one is opened,
   ## the new one may have the same value.
-  return key.fd in s and s.fds[key.fd] == key
+  when not defined(nimdoc):
+    return key.fd in s and s.fds[key.fd] == key
 
 {.deprecated: [TEvent: Event, PSelectorKey: SelectorKey,
    TReadyInfo: ReadyInfo, PSelector: Selector].}
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index a10255e5b..18b2ab1e9 100644
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -441,7 +441,7 @@ template gaiNim(a, p, h, list: expr): stmt =
       when defined(windows):
         raiseOSError(osLastError())
       else:
-        raise newException(OSError, $gai_strerror(gaiResult))
+        raiseOSError(osLastError(), $gai_strerror(gaiResult))
 
 proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
   tags: [ReadIOEffect].} =
@@ -671,7 +671,7 @@ proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
     var s = winlean.getservbyname(name, proto)
   else:
     var s = posix.getservbyname(name, proto)
-  if s == nil: raise newException(OSError, "Service not found.")
+  if s == nil: raiseOSError(osLastError(), "Service not found.")
   result.name = $s.s_name
   result.aliases = cstringArrayToSeq(s.s_aliases)
   result.port = Port(s.s_port)
@@ -687,7 +687,7 @@ proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].}
     var s = winlean.getservbyport(ze(int16(port)).cint, proto)
   else:
     var s = posix.getservbyport(ze(int16(port)).cint, proto)
-  if s == nil: raise newException(OSError, "Service not found.")
+  if s == nil: raiseOSError(osLastError(), "Service not found.")
   result.name = $s.s_name
   result.aliases = cstringArrayToSeq(s.s_aliases)
   result.port = Port(s.s_port)
@@ -706,7 +706,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
     var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, 
                                 cint(posix.AF_INET))
     if s == nil:
-      raise newException(OSError, $hstrerror(h_errno))
+      raiseOSError(osLastError(), $hstrerror(h_errno))
   
   result.name = $s.h_name
   result.aliases = cstringArrayToSeq(s.h_aliases)
@@ -718,7 +718,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
     elif s.h_addrtype == posix.AF_INET6:
       result.addrtype = AF_INET6
     else:
-      raise newException(OSError, "unknown h_addrtype")
+      raiseOSError(osLastError(), "unknown h_addrtype")
   result.addrList = cstringArrayToSeq(s.h_addr_list)
   result.length = int(s.h_length)
 
@@ -739,7 +739,7 @@ proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =
     elif s.h_addrtype == posix.AF_INET6:
       result.addrtype = AF_INET6
     else:
-      raise newException(OSError, "unknown h_addrtype")
+      raiseOSError(osLastError(), "unknown h_addrtype")
   result.addrList = cstringArrayToSeq(s.h_addr_list)
   result.length = int(s.h_length)
 
@@ -1594,7 +1594,7 @@ proc send*(socket: Socket, data: string) {.tags: [WriteIOEffect].} =
     raiseOSError(osLastError())
 
   if sent != data.len:
-    raise newException(OSError, "Could not send all data.")
+    raiseOSError(osLastError(), "Could not send all data.")
 
 proc sendAsync*(socket: Socket, data: string): int {.tags: [WriteIOEffect].} =
   ## sends data to a non-blocking socket.
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index e4d3f7494..f1315a9fd 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -789,7 +789,8 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
     of "sat":
       info.weekday = dSat
     else:
-      raise newException(ValueError, "invalid day of week ")
+      raise newException(ValueError,
+        "Couldn't parse day of week (ddd), got: " & value[j..j+2])
     j += 3
   of "dddd":
     if value.len >= j+6 and value[j..j+5].cmpIgnoreCase("sunday") == 0:
@@ -814,7 +815,8 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
       info.weekday = dSat
       j += 8
     else:
-      raise newException(ValueError, "invalid day of week ")
+      raise newException(ValueError,
+        "Couldn't parse day of week (dddd), got: " & value)
   of "h", "H":
     var pd = parseInt(value[j..j+1], sv)
     info.hour = sv
@@ -865,7 +867,8 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
     of "dec":
       info.month =  mDec
     else:
-      raise newException(ValueError, "invalid month")
+      raise newException(ValueError,
+        "Couldn't parse month (MMM), got: " & value)
     j += 3
   of "MMMM":
     if value.len >= j+7 and value[j..j+6].cmpIgnoreCase("january") == 0:
@@ -905,7 +908,8 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
       info.month =  mDec
       j += 8
     else:
-      raise newException(ValueError, "invalid month")
+      raise newException(ValueError,
+        "Couldn't parse month (MMMM), got: " & value)
   of "s":
     var pd = parseInt(value[j..j+1], sv)
     info.second = sv
@@ -936,7 +940,8 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
     elif value[j] == '-':
       info.timezone = 0-parseInt($value[j+1])
     else:
-      raise newException(ValueError, "Sign for timezone " & value[j])
+      raise newException(ValueError,
+        "Couldn't parse timezone offset (z), got: " & value[j])
     j += 2
   of "zz":
     if value[j] == '+':
@@ -944,7 +949,8 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
     elif value[j] == '-':
       info.timezone = 0-value[j+1..j+2].parseInt()
     else:
-      raise newException(ValueError, "Sign for timezone " & value[j])
+      raise newException(ValueError,
+        "Couldn't parse timezone offset (zz), got: " & value[j])
     j += 3
   of "zzz":
     if value[j] == '+':
@@ -952,7 +958,8 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
     elif value[j] == '-':
       info.timezone = 0-value[j+1..j+2].parseInt()
     else:
-      raise newException(ValueError, "Sign for timezone " & value[j])
+      raise newException(ValueError,
+        "Couldn't parse timezone offset (zzz), got: " & value[j])
     j += 6
   of "ZZZ":
     info.tzname = value[j..j+2].toUpper()
@@ -1020,10 +1027,10 @@ proc parse*(value, layout: string): TimeInfo =
       # These are literals in both the layout and the value string
       if layout[i] == '\'':
         inc(i)
-        inc(j)
         while layout[i] != '\'' and layout.len-1 > i:
           inc(i)
           inc(j)
+        inc(i)
       else:
         inc(i)
         inc(j)
@@ -1112,6 +1119,8 @@ when isMainModule:
   s = "2006-01-12T15:04:05Z-07:00"
   f = "yyyy-MM-ddTHH:mm:ssZzzz"
   assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
+  f = "yyyy-MM-dd'T'HH:mm:ss'Z'zzz"
+  assert($s.parse(f) == "Thu Jan 12 15:04:05 2006")
   # RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
   s = "2006-01-12T15:04:05.999999999Z-07:00"
   f = "yyyy-MM-ddTHH:mm:ss.999999999Zzzz"
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index 4446eaa0c..5e20db32b 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -27,7 +27,7 @@ proc `==`*(a, b: Rune): bool = return int(a) == int(b)
 template ones(n: expr): expr = ((1 shl n)-1)
 
 proc runeLen*(s: string): int {.rtl, extern: "nuc$1".} =
-  ## returns the number of Unicode characters of the string `s`.
+  ## Returns the number of Unicode characters of the string ``s``
   var i = 0
   while i < len(s):
     if ord(s[i]) <=% 127: inc(i)
@@ -40,7 +40,7 @@ proc runeLen*(s: string): int {.rtl, extern: "nuc$1".} =
     inc(result)
 
 proc runeLenAt*(s: string, i: Natural): int =
-  ## returns the number of bytes the rune starting at ``s[i]`` takes.
+  ## Returns the number of bytes the rune starting at ``s[i]`` takes
   if ord(s[i]) <=% 127: result = 1
   elif ord(s[i]) shr 5 == 0b110: result = 2
   elif ord(s[i]) shr 4 == 0b1110: result = 3
@@ -50,8 +50,8 @@ proc runeLenAt*(s: string, i: Natural): int =
   else: result = 1
 
 template fastRuneAt*(s: string, i: int, result: expr, doInc = true) =
-  ## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true``
-  ## `i` is incremented by the number of bytes that have been processed.
+  ## Returns the Unicode character ``s[i]`` in ``result``. If ``doInc == true``
+  ## ``i`` is incremented by the number of bytes that have been processed.
   bind ones
   if ord(s[i]) <=% 127:
     result = Rune(ord(s[i]))
@@ -106,8 +106,8 @@ template fastRuneAt*(s: string, i: int, result: expr, doInc = true) =
     when doInc: inc(i)
 
 proc validateUtf8*(s: string): int =
-  ## returns the position of the invalid byte in ``s`` if the string ``s`` does
-  ## not hold valid UTF-8 data. Otherwise -1 is returned.
+  ## Returns the position of the invalid byte in ``s`` if the string ``s`` does
+  ## not hold valid UTF-8 data. Otherwise ``-1`` is returned.
   var i = 0
   let L = s.len
   while i < L:
@@ -131,11 +131,11 @@ proc validateUtf8*(s: string): int =
   return -1
 
 proc runeAt*(s: string, i: Natural): Rune =
-  ## returns the unicode character in `s` at byte index `i`
+  ## Returns the unicode character in ``s`` at byte index ``i``
   fastRuneAt(s, i, result, false)
 
 proc toUTF8*(c: Rune): string {.rtl, extern: "nuc$1".} =
-  ## converts a rune into its UTF8 representation
+  ## Converts a rune into its UTF-8 representation
   var i = RuneImpl(c)
   if i <=% 127:
     result = newString(1)
@@ -174,11 +174,11 @@ proc toUTF8*(c: Rune): string {.rtl, extern: "nuc$1".} =
     discard # error, exception?
 
 proc `$`*(rune: Rune): string =
-  ## converts a rune to a string
+  ## Converts a Rune to a string
   rune.toUTF8
 
 proc `$`*(runes: seq[Rune]): string =
-  ## converts a sequence of runes to a string
+  ## Converts a sequence of Runes to a string
   result = ""
   for rune in runes: result.add(rune.toUTF8)
 
@@ -1163,8 +1163,8 @@ proc binarySearch(c: RuneImpl, tab: openArray[RuneImpl], len, stride: int): int
   return -1
 
 proc toLower*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
-  ## Converts `c` into lower case. This works for any Unicode character.
-  ## If possible, prefer `toLower` over `toUpper`.
+  ## Converts ``c`` into lower case. This works for any Unicode character.
+  ## If possible, prefer ``toLower`` over ``toUpper``.
   var c = RuneImpl(c)
   var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3)
   if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]:
@@ -1175,8 +1175,8 @@ proc toLower*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
   return Rune(c)
 
 proc toUpper*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
-  ## Converts `c` into upper case. This works for any Unicode character.
-  ## If possible, prefer `toLower` over `toUpper`.
+  ## Converts ``c`` into upper case. This works for any Unicode character.
+  ## If possible, prefer ``toLower`` over ``toUpper``.
   var c = RuneImpl(c)
   var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3)
   if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]:
@@ -1187,6 +1187,7 @@ proc toUpper*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
   return Rune(c)
 
 proc toTitle*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
+  ## Converts ``c`` to title case
   var c = RuneImpl(c)
   var p = binarySearch(c, toTitleSinglets, len(toTitleSinglets) div 2, 2)
   if p >= 0 and c == toTitleSinglets[p]:
@@ -1194,8 +1195,8 @@ proc toTitle*(c: Rune): Rune {.rtl, extern: "nuc$1", procvar.} =
   return Rune(c)
 
 proc isLower*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
-  ## returns true iff `c` is a lower case Unicode character
-  ## If possible, prefer `isLower` over `isUpper`.
+  ## Returns true iff ``c`` is a lower case Unicode character.
+  ## If possible, prefer ``isLower`` over ``isUpper``.
   var c = RuneImpl(c)
   # Note: toUpperRanges is correct here!
   var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3)
@@ -1206,8 +1207,8 @@ proc isLower*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
     return true
 
 proc isUpper*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
-  ## returns true iff `c` is a upper case Unicode character
-  ## If possible, prefer `isLower` over `isUpper`.
+  ## Returns true iff ``c`` is a upper case Unicode character.
+  ## If possible, prefer ``isLower`` over ``isUpper``.
   var c = RuneImpl(c)
   # Note: toLowerRanges is correct here!
   var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3)
@@ -1218,7 +1219,7 @@ proc isUpper*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
     return true
 
 proc isAlpha*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
-  ## returns true iff `c` is an *alpha* Unicode character (i.e. a letter)
+  ## Returns true iff ``c`` is an *alpha* Unicode character (i.e., a letter)
   if isUpper(c) or isLower(c):
     return true
   var c = RuneImpl(c)
@@ -1230,17 +1231,18 @@ proc isAlpha*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
     return true
 
 proc isTitle*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
+  ## Returns true iff ``c`` is a Unicode titlecase character
   return isUpper(c) and isLower(c)
 
 proc isWhiteSpace*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
-  ## returns true iff `c` is a Unicode whitespace character
+  ## Returns true iff ``c`` is a Unicode whitespace character
   var c = RuneImpl(c)
   var p = binarySearch(c, spaceRanges, len(spaceRanges) div 2, 2)
   if p >= 0 and c >= spaceRanges[p] and c <= spaceRanges[p+1]:
     return true
 
 proc isCombining*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
-  ## returns true iff `c` is a Unicode combining character
+  ## Returns true iff ``c`` is a Unicode combining character
   var c = RuneImpl(c)
 
   # Optimized to return false immediately for ASCII
@@ -1251,7 +1253,7 @@ proc isCombining*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
     (c >= 0xfe20 and c <= 0xfe2f))
 
 iterator runes*(s: string): Rune =
-  ## iterates over any unicode character of the string `s`.
+  ## Iterates over any unicode character of the string ``s``
   var
     i = 0
     result: Rune
@@ -1259,8 +1261,14 @@ iterator runes*(s: string): Rune =
     fastRuneAt(s, i, result, true)
     yield result
 
+proc toRunes*(s: string): seq[Rune] =
+  ## Obtains a sequence containing the Runes in ``s``
+  result = newSeq[Rune]()
+  for r in s.runes:
+    result.add(r)
+
 proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} =
-  ## compares two UTF8 strings and ignores the case. Returns:
+  ## Compares two UTF-8 strings and ignores the case. Returns:
   ##
   ## | 0 iff a == b
   ## | < 0 iff a < b
@@ -1277,8 +1285,8 @@ proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} =
   result = a.len - b.len
 
 proc reversed*(s: string): string =
-  ## returns the reverse of `s`, interpreting it as unicode characters. Unicode
-  ## combining characters are correctly interpreted as well:
+  ## Returns the reverse of ``s``, interpreting it as Unicode characters. 
+  ## Unicode combining characters are correctly interpreted as well:
   ##
   ## .. code-block:: nim
   ##
@@ -1322,3 +1330,4 @@ when isMainModule:
   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̅")
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index 70b314e63..c459023a9 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -105,10 +105,10 @@ template suite*(name: expr, body: stmt): stmt {.immediate, dirty.} =
   ##  [OK] 2 + 2 = 4
   ##  [OK] (2 + -2) != 4
   block:
-    template setup*(setupBody: stmt): stmt {.immediate, dirty.} =
+    template setup(setupBody: stmt): stmt {.immediate, dirty.} =
       template testSetupIMPL: stmt {.immediate, dirty.} = setupBody
 
-    template teardown*(teardownBody: stmt): stmt {.immediate, dirty.} =
+    template teardown(teardownBody: stmt): stmt {.immediate, dirty.} =
       template testTeardownIMPL: stmt {.immediate, dirty.} = teardownBody
 
     body
diff --git a/lib/system.nim b/lib/system.nim
index 1977c2203..91495f31a 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -389,9 +389,9 @@ type
     ## Each exception has to inherit from `Exception`. See the full `exception
     ## hierarchy`_.
     parent*: ref Exception ## parent exception (can be used as a stack)
-    name: cstring ## The exception's name is its Nim identifier.
-                  ## This field is filled automatically in the
-                  ## ``raise`` statement.
+    name*: cstring ## The exception's name is its Nim identifier.
+                   ## This field is filled automatically in the
+                   ## ``raise`` statement.
     msg* {.exportc: "message".}: string ## the exception's message. Not
                                         ## providing an exception message
                                         ## is bad style.
@@ -888,9 +888,52 @@ proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
   ## treats `x` and `y` as unsigned and compares them.
   ## Returns true iff ``unsigned(x) < unsigned(y)``.
 
+# unsigned integer operations:
+proc `not`*[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.}
+  ## computes the `bitwise complement` of the integer `x`.
 
-# floating point operations:
+proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.}
+  ## computes the `shift right` operation of `x` and `y`.
+
+proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.}
+  ## computes the `shift left` operation of `x` and `y`.
+
+proc `and`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.}
+  ## computes the `bitwise and` of numbers `x` and `y`.
+
+proc `or`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitorI", noSideEffect.}
+  ## computes the `bitwise or` of numbers `x` and `y`.
+
+proc `xor`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitxorI", noSideEffect.}
+  ## computes the `bitwise xor` of numbers `x` and `y`.
+
+proc `==`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "EqI", noSideEffect.}
+  ## Compares two unsigned integers for equality.
 
+proc `+`*[T: SomeUnsignedInt](x, y: T): T {.magic: "AddU", noSideEffect.}
+  ## Binary `+` operator for unsigned integers.
+
+proc `-`*[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.}
+  ## Binary `-` operator for unsigned integers.
+
+proc `*`*[T: SomeUnsignedInt](x, y: T): T {.magic: "MulU", noSideEffect.}
+  ## Binary `*` operator for unsigned integers.
+
+proc `div`*[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
+  ## computes the integer division. This is roughly the same as
+  ## ``floor(x/y)``.
+
+proc `mod`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ModU", noSideEffect.}
+  ## computes the integer modulo operation. This is the same as
+  ## ``x - (x div y) * y``.
+
+proc `<=`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LeU", noSideEffect.}
+  ## Returns true iff ``x <= y``.
+
+proc `<`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LtU", noSideEffect.}
+  ## Returns true iff ``unsigned(x) < unsigned(y)``.
+
+# floating point operations:
 proc `+` *(x: float32): float32 {.magic: "UnaryPlusF64", noSideEffect.}
 proc `-` *(x: float32): float32 {.magic: "UnaryMinusF64", noSideEffect.}
 proc `+` *(x, y: float32): float32 {.magic: "AddF64", noSideEffect.}
@@ -1466,8 +1509,7 @@ when not defined(nimrodVM):
       ## or other memory may be corrupted.
       ## The freed memory must belong to its allocating thread!
       ## Use `deallocShared` to deallocate from a shared heap.
-    proc free*[T](p: ptr T) {.inline, benign.} =
-      dealloc(p)
+
     proc allocShared*(size: Natural): pointer {.noconv, rtl, benign.}
       ## allocates a new memory block on the shared heap with at
       ## least ``size`` bytes. The block has to be freed with
@@ -2131,7 +2173,11 @@ proc `$`*[T: tuple|object](x: T): string =
     if not firstElement: result.add(", ")
     result.add(name)
     result.add(": ")
-    result.add($value)
+    when compiles(value.isNil):
+      if value.isNil: result.add "nil"
+      else: result.add($value)
+    else:
+      result.add($value)
     firstElement = false
   result.add(")")
 
@@ -3048,11 +3094,11 @@ proc staticRead*(filename: string): string {.magic: "Slurp".}
   ##
   ## `slurp <#slurp>`_ is an alias for ``staticRead``.
 
-proc gorge*(command: string, input = ""): string {.
+proc gorge*(command: string, input = "", cache = ""): string {.
   magic: "StaticExec".} = discard
   ## This is an alias for `staticExec <#staticExec>`_.
 
-proc staticExec*(command: string, input = ""): string {.
+proc staticExec*(command: string, input = "", cache = ""): string {.
   magic: "StaticExec".} = discard
   ## Executes an external process at compile-time.
   ## if `input` is not an empty string, it will be passed as a standard input
@@ -3065,6 +3111,15 @@ proc staticExec*(command: string, input = ""): string {.
   ## `gorge <#gorge>`_ is an alias for ``staticExec``. Note that you can use
   ## this proc inside a pragma like `passC <nimc.html#passc-pragma>`_ or `passL
   ## <nimc.html#passl-pragma>`_.
+  ##
+  ## If ``cache`` is not empty, the results of ``staticExec`` are cached within
+  ## the ``nimcache`` directory. Use ``--forceBuild`` to get rid of this caching
+  ## behaviour then. ``command & input & cache`` (the concatenated string) is
+  ## used to determine wether the entry in the cache is still valid. You can
+  ## use versioning information for ``cache``:
+  ##
+  ## .. code-block:: nim
+  ##     const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0")
 
 proc `+=`*[T: SomeOrdinal|uint|uint64](x: var T, y: T) {.magic: "Inc", noSideEffect.}
   ## Increments an ordinal
@@ -3286,14 +3341,19 @@ when declared(initDebugger):
 when hasAlloc:
   # XXX: make these the default (or implement the NilObject optimization)
   proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} =
+    ## Adds ``y`` to ``x`` unless ``x`` is not yet initialized; in that case,
+    ## ``x`` becomes ``@[y]``
     if x == nil: x = @[y]
     else: x.add(y)
 
   proc safeAdd*(x: var string, y: char) =
+    ## Adds ``y`` to ``x``. If ``x`` is ``nil`` it is initialized to ``""``
     if x == nil: x = ""
     x.add(y)
 
   proc safeAdd*(x: var string, y: string) =
+    ## Adds ``y`` to ``x`` unless ``x`` is not yet initalized; in that case, ``x``
+    ## becomes ``y``
     if x == nil: x = y
     else: x.add(y)
 
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 33629016f..326c601bd 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -210,6 +210,14 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
                                GenericSeqSize))
   inc(result.len)
 
+proc incrSeqV2(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
+  # incrSeq version 2
+  result = seq
+  if result.len >= result.space:
+    result.reserved = resize(result.space)
+    result = cast[PGenericSeq](growObj(result, elemSize * result.reserved +
+                               GenericSeqSize))
+
 proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
     compilerRtl.} =
   result = seq
diff --git a/tests/ccgbugs/taddhigh.nim b/tests/ccgbugs/taddhigh.nim
new file mode 100644
index 000000000..d6ac8f650
--- /dev/null
+++ b/tests/ccgbugs/taddhigh.nim
@@ -0,0 +1,16 @@
+discard """
+  output: '''@[5, 5, 5]'''
+"""
+
+# bug #1832
+
+var s = @[5]
+
+# Works fine:
+let x = s[s.high]
+s.add x
+
+# Causes the 0 to appear:
+s.add s[s.high]
+
+echo s # @[5, 5, 0]
diff --git a/tests/ccgbugs/tmissingderef.nim b/tests/ccgbugs/tmissingderef.nim
index edff1dd4e..26418800a 100644
--- a/tests/ccgbugs/tmissingderef.nim
+++ b/tests/ccgbugs/tmissingderef.nim
@@ -1,5 +1,7 @@
 discard """
-  output: '''255
+  output: '''[10, 0, 0, 0, 0, 0, 0, 0]
+
+255
 1 1
 0.5'''
 """
@@ -27,4 +29,13 @@ proc mainowar =
   var b = p[]
   echo b[0]
 
+
+# bug 2963
+var
+  a = [8, 7, 3, 10, 0, 0, 0, 1]
+  b = [10, 0, 0, 0, 0, 0, 0, 0]
+  ap = addr a
+ap[] = b
+echo repr(a)
+
 mainowar()
diff --git a/tests/ccgbugs/trecursive_closure.nim b/tests/ccgbugs/trecursive_closure.nim
index 50c363a4a..f64382a8c 100644
--- a/tests/ccgbugs/trecursive_closure.nim
+++ b/tests/ccgbugs/trecursive_closure.nim
@@ -6,3 +6,9 @@ proc f(x: proc: MalType) =
   discard x()
 
 f(nil)
+
+# bug #2823
+
+type A = object #of RootObj <-- Uncomment this to get no errors
+  test: proc(i: A): bool
+var a: proc(i: A): bool # Or comment this line to get no errors
diff --git a/tests/cpp/ttypeinfo2.nim b/tests/cpp/ttypeinfo2.nim
new file mode 100644
index 000000000..64bd43e96
--- /dev/null
+++ b/tests/cpp/ttypeinfo2.nim
@@ -0,0 +1,6 @@
+discard """
+  cmd: "nim cpp $file"
+"""
+# bug #2841
+import typeinfo
+var tt: Any
diff --git a/tests/iter/tscheduler.nim b/tests/iter/tscheduler.nim
index a267f15c4..f4b04f311 100644
--- a/tests/iter/tscheduler.nim
+++ b/tests/iter/tscheduler.nim
@@ -7,6 +7,7 @@ a2 8
 a2 6
 a2 4
 a2 2'''
+  disabled: "true"
 """
 
 import os, strutils, times, algorithm
diff --git a/tests/metatype/tstatic_ones.nim b/tests/metatype/tstatic_ones.nim
new file mode 100644
index 000000000..73a88447d
--- /dev/null
+++ b/tests/metatype/tstatic_ones.nim
@@ -0,0 +1,28 @@
+discard """
+  output: "@[2, 2, 2, 2, 2]"
+"""
+
+# bug #3144
+
+type IntArray[N: static[int]] = array[N, int]
+
+proc `$`(a: IntArray): string = $(@(a))
+
+proc `+=`[N: static[int]](a: var IntArray[N], b: IntArray[N]) =
+  for i in 0 .. < N:
+    a[i] += b[i]
+
+proc zeros(N: static[int]): IntArray[N] =
+  for i in 0 .. < N:
+    result[i] = 0
+
+proc ones(N: static[int]): IntArray[N] =
+  for i in 0 .. < N:
+    result[i] = 1
+
+proc sum[N: static[int]](vs: seq[IntArray[N]]): IntArray[N] =
+  result = zeros(N)
+  for v in vs:
+    result += v
+
+echo sum(@[ones(5), ones(5)])
diff --git a/tests/metatype/tstaticvector.nim b/tests/metatype/tstaticvector.nim
index c9923f469..69ee0e935 100644
--- a/tests/metatype/tstaticvector.nim
+++ b/tests/metatype/tstaticvector.nim
@@ -1,17 +1,39 @@
+discard """
+  output: '''0
+0
+2
+100'''
+"""
 
 type
   RectArray*[R, C: static[int], T] = distinct array[R * C, T]
-   
+
   StaticMatrix*[R, C: static[int], T] = object
     elements*: RectArray[R, C, T]
-   
+
   StaticVector*[N: static[int], T] = StaticMatrix[N, 1, T]
- 
+
 proc foo*[N, T](a: StaticVector[N, T]): T = 0.T
 proc foobar*[N, T](a, b: StaticVector[N, T]): T = 0.T
- 
- 
+
+
 var a: StaticVector[3, int]
- 
+
 echo foo(a) # OK
-echo foobar(a, a) # <--- hangs compiler 
+echo foobar(a, a) # <--- hangs compiler
+
+# bug #3112
+
+type
+  Vector[N: static[int]] = array[N, float64]
+  TwoVectors[Na, Nb: static[int]] = tuple
+    a: Vector[Na]
+    b: Vector[Nb]
+
+when isMainModule:
+  var v: TwoVectors[2, 100]
+  echo v[0].len
+  echo v[1].len
+  #let xx = 50
+  v[1][50] = 0.0
+
diff --git a/tests/typerel/ttypedesc_as_genericparam1.nim b/tests/typerel/ttypedesc_as_genericparam1.nim
new file mode 100644
index 000000000..677bf6fc8
--- /dev/null
+++ b/tests/typerel/ttypedesc_as_genericparam1.nim
@@ -0,0 +1,6 @@
+discard """
+  line: 6
+  errormsg: "type mismatch: got (typedesc[int])"
+"""
+# bug #3079, #1146
+echo repr(int)
diff --git a/tests/typerel/ttypedesc_as_genericparam2.nim b/tests/typerel/ttypedesc_as_genericparam2.nim
new file mode 100644
index 000000000..0b4281269
--- /dev/null
+++ b/tests/typerel/ttypedesc_as_genericparam2.nim
@@ -0,0 +1,9 @@
+discard """
+  line: 9
+  errormsg: "'repr' doesn't support 'void' type"
+"""
+
+# bug #2879
+
+var s: seq[int]
+echo repr(s.new_seq(3))
diff --git a/tests/vm/tslurp.nim b/tests/vm/tslurp.nim
index f9456ce6b..fc3dc6f0a 100644
--- a/tests/vm/tslurp.nim
+++ b/tests/vm/tslurp.nim
@@ -1,6 +1,12 @@
+import os
+
+template getScriptDir(): string =
+  parentDir(instantiationInfo(-1, true).filename)
 
 const
-  myRes = slurp"../../readme.txt"
+  relRes = slurp"../../readme.txt"
+  absRes = slurp(parentDir(parentDir(getScriptDir())) / "readme.txt")
   
-echo myRes
+echo relRes
+echo absRes
 
diff --git a/todo.txt b/todo.txt
index 839d568c8..8734b8f19 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,7 @@
 version 0.11.4
 ==============
 
+- ``unsafeAddr``
 - document special cased varargs[untyped] and varargs[typed]
 
 - The remaining bugs of the lambda lifting pass that is responsible to enable
@@ -10,7 +11,8 @@ version 0.11.4
 - make '--implicitStatic:on' the default; then we can also clean up the
   'static[T]' mess in the compiler!
 
-- Finish the implementation of the 'parallel' statement.
+- Mark the 'parallel' statement as experimental.
+- add "all threads are blocked" detection to 'spawn'
 - Deprecate ``immediate`` for templates and macros
 - make 'nil' work for 'add':
   - resizeString
@@ -21,9 +23,9 @@ version 0.11.4
 version 1.0
 ===========
 
+- map ``string`` and ``seq`` to ``std::string`` and ``std::vector``
 - macro support for '='; bind '=' to a memory region
 - remove   echo $foo  gotcha
-- add "all threads are blocked" detection to 'spawn'
 - figure out why C++ bootstrapping is so much slower
 - nimsuggest: auto-completion needs to work in 'class' macros
 - The bitwise 'not' operator will be renamed to 'bnot' to
diff --git a/web/documentation.txt b/web/documentation.txt
index 67f8b4070..14d88245d 100644
--- a/web/documentation.txt
+++ b/web/documentation.txt
@@ -14,10 +14,17 @@ Nim's Documentation
     - | `Language Manual <docs/manual.html>`_
       | The Nim manual is a draft that will evolve into a proper specification.
 
+    - | `Nim Style Guide <docs/nep1.html>`_
+      | The stylistic conventions that Nim's official projects adhere to.
+
     - | `Compiler User Guide <docs/nimc.html>`_
       | The user guide lists command line arguments, special features of the
         compiler, etc.
 
+    - | `Nim Backend Integration <docs/backends.html>`_
+      | The Backend Integeration guide gives further information of how Nim can
+        interact with C, C++, Objective C and JavaScript.
+
 
 .. container:: standout
 
diff --git a/web/news.txt b/web/news.txt
index cffffffee..a5bc600b9 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -40,6 +40,8 @@ News
     ``varargs[expr]`` instead. The same applies to ``varargs[typed]`` vs
     ``varargs[stmt]``.
   - ``sequtils.delete`` doesn't take confusing default arguments anymore.
+  - ``system.free`` was an error-prone alias to ``system.dealloc`` and has
+    been removed.
 
 
   Library additions
@@ -47,7 +49,8 @@ News
 
   - The nre module has been added, providing a better interface to PCRE than
     re.
-  - The ``expandSymlink`` procedure has been added to the ``os`` module.
+  - The ``expandSymlink`` proc has been added to the ``os`` module.
+  - The ``tailDir`` proc has been added to the ``os`` module.
 
   Language Additions
   ------------------
diff --git a/web/website.ini b/web/website.ini
index fb98d639a..95f0f5b57 100644
--- a/web/website.ini
+++ b/web/website.ini
@@ -31,7 +31,7 @@ file: ticker.txt
 [Documentation]
 doc: "endb;intern;apis;lib;manual.txt;tut1;tut2;nimc;overview;filters"
 doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt"
-doc: "nimfix.txt;nimsuggest.txt"
+doc: "nimfix.txt;nimsuggest.txt;nep1.txt"
 pdf: "manual.txt;lib;tut1;tut2;nimc;niminst;gc"
 srcdoc2: "system.nim"
 srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned"