summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim384
-rw-r--r--compiler/astalgo.nim46
-rw-r--r--compiler/ccgexprs.nim89
-rw-r--r--compiler/ccgtypes.nim148
-rw-r--r--compiler/ccgutils.nim64
-rw-r--r--compiler/commands.nim20
-rw-r--r--compiler/evalffi.nim1
-rw-r--r--compiler/evaltempl.nim10
-rw-r--r--compiler/extccomp.nim3
-rw-r--r--compiler/filter_tmpl.nim18
-rw-r--r--compiler/importer.nim2
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/lexer.nim6
-rw-r--r--compiler/llstream.nim2
-rw-r--r--compiler/lookups.nim2
-rw-r--r--compiler/main.nim2
-rw-r--r--compiler/modules.nim2
-rw-r--r--compiler/msgs.nim16
-rw-r--r--compiler/nim.nim2
-rw-r--r--compiler/nimlexbase.nim2
-rw-r--r--compiler/options.nim8
-rw-r--r--compiler/parser.nim3
-rw-r--r--compiler/passes.nim6
-rw-r--r--compiler/renderer.nim16
-rw-r--r--compiler/sem.nim46
-rw-r--r--compiler/semcall.nim119
-rw-r--r--compiler/semexprs.nim429
-rw-r--r--compiler/semgnrc.nim2
-rw-r--r--compiler/seminst.nim32
-rw-r--r--compiler/sempass2.nim2
-rw-r--r--compiler/semstmts.nim17
-rw-r--r--compiler/semtypes.nim275
-rw-r--r--compiler/semtypinst.nim5
-rw-r--r--compiler/service.nim7
-rw-r--r--compiler/sigmatch.nim283
-rw-r--r--compiler/types.nim501
-rw-r--r--compiler/typesrenderer.nim1
-rw-r--r--compiler/vm.nim58
-rw-r--r--doc/advopt.txt3
-rw-r--r--doc/basicopt.txt2
-rw-r--r--doc/lib.txt3
-rw-r--r--koch.nim2
-rw-r--r--lib/core/macros.nim35
-rw-r--r--lib/core/typeinfo.nim4
-rw-r--r--lib/impure/re.nim6
-rw-r--r--lib/nimbase.h18
-rw-r--r--lib/packages/docutils/rst.nim4
-rw-r--r--lib/packages/docutils/rstast.nim10
-rw-r--r--lib/packages/docutils/rstgen.nim6
-rw-r--r--lib/pure/algorithm.nim28
-rw-r--r--lib/pure/asyncdispatch.nim62
-rw-r--r--lib/pure/asyncfile.nim4
-rw-r--r--lib/pure/collections/sequtils.nim33
-rw-r--r--lib/pure/collections/tables.nim6
-rw-r--r--lib/pure/complex.nim77
-rw-r--r--lib/pure/hashes.nim4
-rw-r--r--lib/pure/httpclient.nim10
-rw-r--r--lib/pure/json.nim2
-rw-r--r--lib/pure/lexbase.nim2
-rw-r--r--lib/pure/parseopt.nim9
-rw-r--r--lib/pure/parsexml.nim40
-rw-r--r--lib/pure/pegs.nim310
-rw-r--r--lib/pure/rationals.nim62
-rw-r--r--lib/pure/redis.nim16
-rw-r--r--lib/pure/streams.nim10
-rw-r--r--lib/pure/strutils.nim41
-rw-r--r--lib/pure/times.nim8
-rw-r--r--lib/pure/unicode.nim22
-rw-r--r--lib/pure/uri.nim10
-rw-r--r--lib/pure/xmldom.nim12
-rw-r--r--lib/system/deepcopy.nim4
-rw-r--r--lib/system/gc.nim2
-rw-r--r--lib/system/gc2.nim2
-rw-r--r--lib/system/hti.nim6
-rw-r--r--lib/system/sysio.nim4
-rw-r--r--lib/system/sysstr.nim56
-rw-r--r--readme.md3
-rw-r--r--tests/actiontable/tactiontable2.nim3
-rw-r--r--tests/assert/tfailedassert.nim4
-rw-r--r--tests/ccgbugs/tmissingderef.nim30
-rw-r--r--tests/ccgbugs/trecursive_closure.nim8
-rw-r--r--tests/ccgbugs/tstringslice.nim10
-rw-r--r--tests/ccgbugs/tuple_canon.nim80
-rw-r--r--tests/clearmsg/tconsttypemismatch.nim8
-rw-r--r--tests/cpp/trawsockets.nim2
-rw-r--r--tests/cpp/ttypeinfo.nim2
-rw-r--r--tests/deprecated/tdeprecated.nim4
-rw-r--r--tests/destructor/tdestructor2.nim10
-rw-r--r--tests/exception/tdefer1.nim18
-rw-r--r--tests/generics/tgeneric3.nim2
-rw-r--r--tests/generics/twrong_floatlit_type.nim118
-rw-r--r--tests/global/tglobal.nim2
-rw-r--r--tests/manyloc/argument_parser/argument_parser.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim6
-rw-r--r--tests/manyloc/keineschweine/enet_server/enet_server.nim2
-rw-r--r--tests/manyloc/keineschweine/keineschweine.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/map_filter.nim4
-rw-r--r--tests/manyloc/keineschweine/lib/zlib_helpers.nim10
-rw-r--r--tests/manyloc/keineschweine/server/old_sg_server.nim2
-rw-r--r--tests/misc/parsecomb.nim105
-rw-r--r--tests/misc/tparsecombnum.nim55
-rw-r--r--tests/objects/tobjpragma.nim3
-rw-r--r--tests/overload/tprefer_tygenericinst.nim17
-rw-r--r--tests/overload/tsymtabchange_during_or.nim24
-rw-r--r--tests/stdlib/tmarshal.nim12
-rw-r--r--tests/stdlib/tstrutil.nim10
-rw-r--r--tests/template/texponential_eval.nim47
-rw-r--r--tests/testament/categories.nim47
-rw-r--r--tests/testament/tester.nim30
-rw-r--r--tests/trmacros/tor.nim2
-rw-r--r--tests/vm/tconsteval.nim2
-rw-r--r--todo.txt5
-rw-r--r--tools/nimgrep.nim2
-rw-r--r--tools/nimweb.nim4
-rw-r--r--web/website.ini1
115 files changed, 2571 insertions, 1693 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 6afc1db26..36e86a6f1 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -9,12 +9,12 @@
 
 # abstract syntax tree + symbol table
 
-import 
-  msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, 
+import
+  msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
   intsets, idgen
 
 type
-  TCallingConvention* = enum 
+  TCallingConvention* = enum
     ccDefault,                # proc has no explicit calling convention
     ccStdCall,                # procedure is stdcall
     ccCDecl,                  # cdecl
@@ -26,12 +26,12 @@ type
     ccClosure,                # proc has a closure
     ccNoConvention            # needed for generating proper C procs sometimes
 
-const 
-  CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall", 
+const
+  CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall",
     "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall",
     "closure", "noconv"]
 
-type 
+type
   TNodeKind* = enum # order is extremely important, because ranges are used
                     # to check whether a node belongs to a certain class
     nkNone,               # unknown node kind: indicates an error
@@ -64,13 +64,13 @@ type
                           # end of atoms
     nkMetaNode_Obsolete,  # difficult to explain; represents itself
                           # (used for macros)
-    nkDotCall,            # used to temporarily flag a nkCall node; 
+    nkDotCall,            # used to temporarily flag a nkCall node;
                           # this is used
                           # for transforming ``s.len`` to ``len(s)``
 
     nkCommand,            # a call like ``p 2, 4`` without parenthesis
     nkCall,               # a call like p(x, y) or an operation like +(a, b)
-    nkCallStrLit,         # a call with a string literal 
+    nkCallStrLit,         # a call with a string literal
                           # x"abc" has two sons: nkIdent, nkRStrLit
                           # x"""abc""" has two sons: nkIdent, nkTripleStrLit
     nkInfix,              # a call like (a + b)
@@ -126,7 +126,7 @@ type
 
     nkAsgn,               # a = b
     nkFastAsgn,           # internal node for a fast ``a = b``
-                          # (no string copy) 
+                          # (no string copy)
     nkGenericParams,      # generic parameters
     nkFormalParams,       # formal parameters
     nkOfInherit,          # inherited from symbol
@@ -192,10 +192,11 @@ type
 
     nkWith,               # distinct with `foo`
     nkWithout,            # distinct without `foo`
-    
+
     nkTypeOfExpr,         # type(1+2)
     nkObjectTy,           # object body
     nkTupleTy,            # tuple body
+    nkTupleClassTy,       # tuple type class
     nkTypeClassTy,        # user-defined type class
     nkStaticTy,           # ``static[T]``
     nkRecList,            # list of object parts
@@ -226,7 +227,7 @@ type
   TSymFlag* = enum    # already 32 flags!
     sfUsed,           # read access of sym (for warnings) or simply used
     sfExported,       # symbol is exported from module
-    sfFromGeneric,    # symbol is instantiation of a generic; this is needed 
+    sfFromGeneric,    # symbol is instantiation of a generic; this is needed
                       # for symbol file generation; such symbols should always
                       # be written into the ROD file
     sfGlobal,         # symbol is at global scope
@@ -284,9 +285,9 @@ const
 
   sfAnon* = sfDiscardable
     # symbol name that was generated by the compiler
-    # the compiler will avoid printing such names 
+    # the compiler will avoid printing such names
     # in user messages.
-      
+
   sfNoForward* = sfRegister
     # forward declarations are not required (per module)
 
@@ -300,7 +301,7 @@ const
   # getting ready for the future expr/stmt merge
   nkWhen* = nkWhenStmt
   nkWhenExpr* = nkWhenStmt
-  nkEffectList* = nkArgList 
+  nkEffectList* = nkArgList
   # hacks ahead: an nkEffectList is a node with 4 children:
   exceptionEffects* = 0 # exceptions at position 0
   usesEffects* = 1      # read effects at position 1
@@ -321,7 +322,7 @@ type
                          # unless this is an instance of a generic alias type.
                          # then realInstance will be the tyGenericInst of the
                          # completely (recursively) resolved alias.
-                         
+
     tyGenericParam,      # ``a`` in the above patterns
     tyDistinct,
     tyEnum,
@@ -340,14 +341,14 @@ type
     tyInt, tyInt8, tyInt16, tyInt32, tyInt64, # signed integers
     tyFloat, tyFloat32, tyFloat64, tyFloat128,
     tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
-    tyBigNum, 
-    tyConst, tyMutable, tyVarargs, 
+    tyBigNum,
+    tyConst, tyMutable, tyVarargs,
     tyIter, # unused
     tyProxy # used as errornous type (for idetools)
-    
+
     tyBuiltInTypeClass #\
       # Type such as the catch-all object, tuple, seq, etc
-    
+
     tyUserTypeClass #\
       # the body of a user-defined type class
 
@@ -357,24 +358,24 @@ type
       # tyGenericInst represents concrete types, while
       # this is still a "generic param" that will bind types
       # and resolves them during sigmatch and instantiation.
-    
+
     tyCompositeTypeClass #\
       # Type such as seq[Number]
-      # The notes for tyUserTypeClassInst apply here as well 
+      # The notes for tyUserTypeClassInst apply here as well
       # sons[0]: the original expression used by the user.
       # sons[1]: fully expanded and instantiated meta type
       # (potentially following aliases)
-    
+
     tyAnd, tyOr, tyNot #\
       # boolean type classes such as `string|int`,`not seq`,
       # `Sortable and Enumable`, etc
-    
+
     tyAnything #\
       # a type class matching any type
-    
+
     tyStatic #\
       # a value known at compile type (the underlying type is .base)
-    
+
     tyFromExpr #\
       # This is a type representing an expression that depends
       # on generic parameters (the expression is stored in t.n)
@@ -390,7 +391,7 @@ type
       # sons[0]: type of containing object or tuple
       # sons[1]: field type
       # .n: nkDotExpr storing the field name
-    
+
 static:
   # remind us when TTypeKind stops to fit in a single 64-bit word
   assert TTypeKind.high.ord <= 63
@@ -408,7 +409,7 @@ const
                     tyAnd, tyOr, tyNot, tyAnything}
 
   tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses
- 
+
 type
   TTypeKinds* = set[TTypeKind]
 
@@ -429,7 +430,7 @@ type
     nfExprCall  # this is an attempt to call a regular expression
     nfIsRef     # this node is a 'ref' node; used for the VM
     nfIsCursor  # this node is attached a cursor; used for idetools
- 
+
   TNodeFlags* = set[TNodeFlag]
   TTypeFlag* = enum   # keep below 32 for efficiency reasons (now: 28)
     tfVarargs,        # procedure has C styled varargs
@@ -448,7 +449,7 @@ type
                       # proc foo(L: static[int]): array[L, int]
                       # can be attached to ranges to indicate that the range
                       # depends on unresolved static params.
-    tfRetType,        # marks return types in proc (used to detect type classes 
+    tfRetType,        # marks return types in proc (used to detect type classes
                       # used as return types for return type inference)
     tfCapturesEnv,    # whether proc really captures some environment
     tfByCopy,         # pass object/tuple by copy (C backend)
@@ -456,7 +457,7 @@ type
     tfIterator,       # type is really an iterator, not a tyProc
     tfShared,         # type is 'shared'
     tfNotNil,         # type cannot be 'nil'
-    
+
     tfNeedsInit,      # type constains a "not nil" constraint somewhere or some
                       # other type so that it requires inititalization
     tfVarIsPtr,       # 'var' type is translated like 'ptr' even in C++ mode
@@ -520,7 +521,7 @@ const
   tfGcSafe* = tfThread
   tfObjHasKids* = tfEnumHasHoles
   skError* = skUnknown
-  
+
   # type flags that are essential for type equality:
   eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr}
 
@@ -531,29 +532,29 @@ type
     mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf,
     mEcho, mShallowCopy, mSlurp, mStaticExec,
     mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
-    mUnaryLt, mSucc, 
-    mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray, 
-    mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref, 
-    mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64, 
+    mUnaryLt, mSucc,
+    mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
+    mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,
+    mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
     mDivI64, mModI64,
     mAddF64, mSubF64, mMulF64, mDivF64,
-    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, 
+    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI,
     mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64,
-    mMinF64, mMaxF64, mAddU, mSubU, mMulU, 
+    mMinF64, mMaxF64, mAddU, mSubU, mMulU,
     mDivU, mModU, mEqI, mLeI,
-    mLtI, 
-    mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64, 
-    mLeU, mLtU, mLeU64, mLtU64, 
-    mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef, 
+    mLtI,
+    mEqI64, mLeI64, mLtI64, 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, mAbsI64, mNot, 
-    mUnaryPlusI, mBitnotI, mUnaryPlusI64, 
-    mBitnotI64, 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, mConArrArr, mConArrT, 
+    mUnaryMinusI64, mAbsI, mAbsI64, mNot,
+    mUnaryPlusI, mBitnotI, mUnaryPlusI64,
+    mBitnotI64, 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, mConArrArr, mConArrT,
     mConTArr, mConTT, mSlice,
     mFields, mFieldPairs, mOmpParFor,
     mAppendStrCh, mAppendStrStr, mAppendSeqElem,
@@ -584,36 +585,36 @@ type
 
 # things that we can evaluate safely at compile time, even if not asked for it:
 const
-  ctfeWhitelist* = {mNone, mUnaryLt, mSucc, 
-    mPred, mInc, mDec, mOrd, mLengthOpenArray, 
-    mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, 
-    mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64, 
+  ctfeWhitelist* = {mNone, mUnaryLt, mSucc,
+    mPred, mInc, mDec, mOrd, mLengthOpenArray,
+    mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr,
+    mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
     mDivI64, mModI64, mAddF64, mSubF64, mMulF64, mDivF64,
-    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, 
+    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI,
     mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64,
-    mMinF64, mMaxF64, mAddU, mSubU, mMulU, 
+    mMinF64, mMaxF64, mAddU, mSubU, mMulU,
     mDivU, mModU, mEqI, mLeI,
-    mLtI, 
-    mEqI64, mLeI64, mLtI64, 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, mAbsI64, mNot, 
-    mUnaryPlusI, mBitnotI, mUnaryPlusI64, 
-    mBitnotI64, 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, mConArrArr, mConArrT, 
+    mLtI,
+    mEqI64, mLeI64, mLtI64, 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, mAbsI64, mNot,
+    mUnaryPlusI, mBitnotI, mUnaryPlusI64,
+    mBitnotI64, 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, mConArrArr, mConArrT,
     mConTArr, mConTT,
-    mAppendStrCh, mAppendStrStr, mAppendSeqElem, 
+    mAppendStrCh, mAppendStrStr, mAppendSeqElem,
     mInRange, mInSet, mRepr,
     mCopyStr, mCopyStrLast}
   # magics that require special semantic checking and
   # thus cannot be overloaded (also documented in the spec!):
   SpecialSemMagics* = {
-    mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf, 
+    mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
     mEcho, mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr}
 
 type
@@ -634,21 +635,21 @@ type
       floatVal*: BiggestFloat
     of nkStrLit..nkTripleStrLit:
       strVal*: string
-    of nkSym: 
+    of nkSym:
       sym*: PSym
-    of nkIdent: 
+    of nkIdent:
       ident*: PIdent
     else:
       sons*: TNodeSeq
     comment*: string
-  
+
   TSymSeq* = seq[PSym]
   TStrTable* = object         # a table[PIdent] of PSym
     counter*: int
     data*: TSymSeq
-  
+
   # -------------- backend information -------------------------------
-  TLocKind* = enum 
+  TLocKind* = enum
     locNone,                  # no location
     locTemp,                  # temporary location
     locLocalVar,              # location is a local variable
@@ -660,7 +661,7 @@ type
     locData,                  # location is a constant
     locCall,                  # location is a call expression
     locOther                  # location is something other
-  TLocFlag* = enum 
+  TLocFlag* = enum
     lfIndirect,               # backend introduced a pointer
     lfParamCopy,              # backend introduced a parameter copy (LLVM)
     lfNoDeepCopy,             # no need for a deep copy
@@ -670,13 +671,13 @@ type
     lfHeader,                 # include header file for symbol
     lfImportCompilerProc,     # ``importc`` of a compilerproc
     lfSingleUse               # no location yet and will only be used once
-  TStorageLoc* = enum 
+  TStorageLoc* = enum
     OnUnknown,                # location is unknown (stack, heap or static)
     OnStack,                  # location is on hardware stack
     OnHeap                    # location is on heap or global
                               # (reference counting needed)
   TLocFlags* = set[TLocFlag]
-  TLoc* = object     
+  TLoc* = object
     k*: TLocKind              # kind of location
     s*: TStorageLoc
     flags*: TLocFlags         # location's flags
@@ -688,7 +689,7 @@ type
 
   # ---------------- end of backend information ------------------------------
 
-  TLibKind* = enum 
+  TLibKind* = enum
     libHeader, libDynamic
   TLib* = object of lists.TListEntry # also misused for headers!
     kind*: TLibKind
@@ -696,17 +697,17 @@ type
     isOverriden*: bool
     name*: PRope
     path*: PNode              # can be a string literal!
-  
+
   TInstantiation* = object
     sym*: PSym
     concreteTypes*: seq[PType]
     usedBy*: seq[int32]       # list of modules using the generic
                               # needed in caas mode for purging the cache
-                              # XXX: it's possible to switch to a 
+                              # XXX: it's possible to switch to a
                               # simple ref count here
-  
+
   PInstantiation* = ref TInstantiation
- 
+
   TScope* = object
     depthLevel*: int
     symbols*: TStrTable
@@ -773,7 +774,7 @@ type
     constraint*: PNode        # additional constraints like 'lit|result'; also
                               # misused for the codegenDecl pragma in the hope
                               # it won't cause problems
-  
+
   TTypeSeq* = seq[PType]
   TLockLevel* = distinct int16
   TType* {.acyclic.} = object of TIdObj # \
@@ -806,7 +807,7 @@ type
     lockLevel*: TLockLevel    # lock level as required for deadlock checking
     loc*: TLoc
 
-  TPair*{.final.} = object 
+  TPair*{.final.} = object
     key*, val*: RootRef
 
   TPairSeq* = seq[TPair]
@@ -814,7 +815,7 @@ type
     counter*: int
     data*: TPairSeq
 
-  TIdPair*{.final.} = object 
+  TIdPair*{.final.} = object
     key*: PIdObj
     val*: RootRef
 
@@ -823,7 +824,7 @@ type
     counter*: int
     data*: TIdPairSeq
 
-  TIdNodePair*{.final.} = object 
+  TIdNodePair*{.final.} = object
     key*: PIdObj
     val*: PNode
 
@@ -832,7 +833,7 @@ type
     counter*: int
     data*: TIdNodePairSeq
 
-  TNodePair*{.final.} = object 
+  TNodePair*{.final.} = object
     h*: THash                 # because it is expensive to compute!
     key*: PNode
     val*: int
@@ -844,7 +845,7 @@ type
     data*: TNodePairSeq
 
   TObjectSeq* = seq[RootRef]
-  TObjectSet*{.final.} = object 
+  TObjectSet*{.final.} = object
     counter*: int
     data*: TObjectSeq
 
@@ -855,27 +856,27 @@ type
 # same name as an imported module. This is necessary because of
 # the poor naming choices in the standard library.
 
-const 
+const
   OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator,
     skConverter, skModule, skTemplate, skMacro}
 
-  GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody, 
+  GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody,
     tyGenericParam}
-  
-  StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray, 
+
+  StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray,
     tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray,
     tyVarargs}
-  
+
   ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in::
                                  # var x = expr
-    tyBool, tyChar, tyEnum, tyArray, tyObject, 
+    tyBool, tyChar, tyEnum, tyArray, tyObject,
     tySet, tyTuple, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,
-    tyPointer, 
+    tyPointer,
     tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
     tyUInt..tyUInt64}
   IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64,
     tyFloat..tyFloat128, tyUInt..tyUInt64}
-  ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet, 
+  ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet,
                                     tyTuple, tySequence}
   NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
     tyProc, tyString, tyError}
@@ -926,17 +927,17 @@ proc discardSons*(father: PNode)
 proc len*(n: PNode): int {.inline.} =
   if isNil(n.sons): result = 0
   else: result = len(n.sons)
-  
+
 proc safeLen*(n: PNode): int {.inline.} =
   ## works even for leaves.
   if n.kind in {nkNone..nkNilLit} or isNil(n.sons): result = 0
   else: result = len(n.sons)
-  
+
 proc add*(father, son: PNode) =
   assert son != nil
   if isNil(father.sons): father.sons = @[]
   add(father.sons, son)
-  
+
 proc `[]`*(n: PNode, i: int): PNode {.inline.} =
   result = n.sons[i]
 
@@ -946,13 +947,10 @@ template `{}=`*(n: PNode, i: int, s: PNode): stmt =
   n.sons[i -| n] = s
 
 when defined(useNodeIds):
-  const nodeIdToDebug* = -1 # 884953 # 612794
-  #612840 # 612905 # 614635 # 614637 # 614641
-  # 423408
-  #429107 # 430443 # 441048 # 441090 # 441153
+  const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879
   var gNodeId: int
 
-proc newNode*(kind: TNodeKind): PNode = 
+proc newNode*(kind: TNodeKind): PNode =
   new(result)
   result.kind = kind
   #result.info = UnknownLineInfo() inlined:
@@ -966,24 +964,24 @@ proc newNode*(kind: TNodeKind): PNode =
       writeStackTrace()
     inc gNodeId
 
-proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode = 
+proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
   result = newNode(kind)
   result.intVal = intVal
 
-proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode = 
+proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode =
   result = newIntNode(kind, intVal)
   result.typ = typ
 
-proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode = 
+proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode =
   result = newNode(kind)
   result.floatVal = floatVal
 
-proc newStrNode*(kind: TNodeKind, strVal: string): PNode = 
+proc newStrNode*(kind: TNodeKind, strVal: string): PNode =
   result = newNode(kind)
   result.strVal = strVal
 
 proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
-             info: TLineInfo): PSym = 
+             info: TLineInfo): PSym =
   # generates a symbol and initializes the hash field too
   new(result)
   result.name = name
@@ -994,7 +992,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
   result.owner = owner
   result.offset = - 1
   result.id = getID()
-  when debugIds: 
+  when debugIds:
     registerId(result)
   #if result.id < 2000:
   #  MessageOut(name.s & " has id: " & toString(result.id))
@@ -1036,54 +1034,54 @@ proc appendToModule*(m: PSym, n: PNode) =
   else:
     assert m.ast.kind == nkStmtList
     m.ast.sons.add(n)
-  
+
 const                         # for all kind of hash tables:
   GrowthFactor* = 2           # must be power of 2, > 0
   StartSize* = 8              # must be power of 2, > 0
 
-proc copyStrTable*(dest: var TStrTable, src: TStrTable) = 
+proc copyStrTable*(dest: var TStrTable, src: TStrTable) =
   dest.counter = src.counter
-  if isNil(src.data): return 
+  if isNil(src.data): return
   setLen(dest.data, len(src.data))
   for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
-  
-proc copyIdTable*(dest: var TIdTable, src: TIdTable) = 
+
+proc copyIdTable*(dest: var TIdTable, src: TIdTable) =
   dest.counter = src.counter
-  if isNil(src.data): return 
+  if isNil(src.data): return
   newSeq(dest.data, len(src.data))
   for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
-  
-proc copyTable*(dest: var TTable, src: TTable) = 
+
+proc copyTable*(dest: var TTable, src: TTable) =
   dest.counter = src.counter
-  if isNil(src.data): return 
+  if isNil(src.data): return
   setLen(dest.data, len(src.data))
   for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
-  
-proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) = 
+
+proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) =
   dest.counter = src.counter
-  if isNil(src.data): return 
+  if isNil(src.data): return
   setLen(dest.data, len(src.data))
   for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
-  
-proc discardSons*(father: PNode) = 
+
+proc discardSons*(father: PNode) =
   father.sons = nil
 
 proc withInfo*(n: PNode, info: TLineInfo): PNode =
   n.info = info
   return n
 
-proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode = 
+proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode =
   result = newNode(nkIdent)
   result.ident = ident
   result.info = info
 
-proc newSymNode*(sym: PSym): PNode = 
+proc newSymNode*(sym: PSym): PNode =
   result = newNode(nkSym)
   result.sym = sym
   result.typ = sym.typ
   result.info = sym.info
 
-proc newSymNode*(sym: PSym, info: TLineInfo): PNode = 
+proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
   result = newNode(nkSym)
   result.sym = sym
   result.typ = sym.typ
@@ -1128,12 +1126,12 @@ proc newNode*(kind: TNodeKind, info: TLineInfo, sons: TNodeSeq = @[],
       writeStackTrace()
     inc gNodeId
 
-proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode = 
+proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
   result = newNode(kind)
   result.info = info
   result.typ = typ
 
-proc addSon*(father, son: PNode) = 
+proc addSon*(father, son: PNode) =
   assert son != nil
   if isNil(father.sons): father.sons = @[]
   add(father.sons, son)
@@ -1159,7 +1157,7 @@ proc `$`*(x: TLockLevel): string =
   elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
   else: result = $int16(x)
 
-proc newType*(kind: TTypeKind, owner: PSym): PType = 
+proc newType*(kind: TTypeKind, owner: PSym): PType =
   new(result)
   result.kind = kind
   result.owner = owner
@@ -1171,7 +1169,7 @@ proc newType*(kind: TTypeKind, owner: PSym): PType =
     registerId(result)
   #if result.id < 2000:
   #  messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
-  
+
 proc mergeLoc(a: var TLoc, b: TLoc) =
   if a.k == low(a.k): a.k = b.k
   if a.s == low(a.s): a.s = b.s
@@ -1180,37 +1178,37 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
   if a.r == nil: a.r = b.r
   #if a.a == 0: a.a = b.a
 
-proc newSons*(father: PNode, length: int) = 
-  if isNil(father.sons): 
+proc newSons*(father: PNode, length: int) =
+  if isNil(father.sons):
     newSeq(father.sons, length)
   else:
     setLen(father.sons, length)
 
-proc newSons*(father: PType, length: int) = 
-  if isNil(father.sons): 
+proc newSons*(father: PType, length: int) =
+  if isNil(father.sons):
     newSeq(father.sons, length)
   else:
     setLen(father.sons, length)
 
-proc sonsLen*(n: PType): int = 
+proc sonsLen*(n: PType): int =
   if isNil(n.sons): result = 0
   else: result = len(n.sons)
 
-proc len*(n: PType): int = 
+proc len*(n: PType): int =
   if isNil(n.sons): result = 0
   else: result = len(n.sons)
-  
-proc sonsLen*(n: PNode): int = 
+
+proc sonsLen*(n: PNode): int =
   if isNil(n.sons): result = 0
   else: result = len(n.sons)
-  
-proc lastSon*(n: PNode): PNode = 
+
+proc lastSon*(n: PNode): PNode =
   result = n.sons[sonsLen(n) - 1]
 
-proc lastSon*(n: PType): PType = 
+proc lastSon*(n: PType): PType =
   result = n.sons[sonsLen(n) - 1]
 
-proc assignType*(dest, src: PType) = 
+proc assignType*(dest, src: PType) =
   dest.kind = src.kind
   dest.flags = src.flags
   dest.callConv = src.callConv
@@ -1230,23 +1228,23 @@ proc assignType*(dest, src: PType) =
       dest.sym = src.sym
   newSons(dest, sonsLen(src))
   for i in countup(0, sonsLen(src) - 1): dest.sons[i] = src.sons[i]
-  
-proc copyType*(t: PType, owner: PSym, keepId: bool): PType = 
+
+proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
   result = newType(t.kind, owner)
   assignType(result, t)
-  if keepId: 
+  if keepId:
     result.id = t.id
-  else: 
+  else:
     when debugIds: registerId(result)
   result.sym = t.sym          # backend-info should not be copied
-  
-proc copySym*(s: PSym, keepId: bool = false): PSym = 
+
+proc copySym*(s: PSym, keepId: bool = false): PSym =
   result = newSym(s.kind, s.name, s.owner, s.info)
   #result.ast = nil            # BUGFIX; was: s.ast which made problems
   result.typ = s.typ
   if keepId:
     result.id = s.id
-  else: 
+  else:
     result.id = getID()
     when debugIds: registerId(result)
   result.flags = s.flags
@@ -1273,19 +1271,19 @@ proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym =
   result.annex = s.annex
   # XXX once usedGenerics is used, ensure module aliases keep working!
   assert s.usedGenerics == nil
-  
-proc initStrTable*(x: var TStrTable) = 
+
+proc initStrTable*(x: var TStrTable) =
   x.counter = 0
   newSeq(x.data, StartSize)
 
 proc newStrTable*: TStrTable =
   initStrTable(result)
 
-proc initTable(x: var TTable) = 
+proc initTable(x: var TTable) =
   x.counter = 0
   newSeq(x.data, StartSize)
 
-proc initIdTable*(x: var TIdTable) = 
+proc initIdTable*(x: var TIdTable) =
   x.counter = 0
   newSeq(x.data, StartSize)
 
@@ -1295,15 +1293,15 @@ proc resetIdTable*(x: var TIdTable) =
   setLen(x.data, 0)
   setLen(x.data, StartSize)
 
-proc initObjectSet*(x: var TObjectSet) = 
+proc initObjectSet*(x: var TObjectSet) =
   x.counter = 0
   newSeq(x.data, StartSize)
 
-proc initIdNodeTable*(x: var TIdNodeTable) = 
+proc initIdNodeTable*(x: var TIdNodeTable) =
   x.counter = 0
   newSeq(x.data, StartSize)
 
-proc initNodeTable*(x: var TNodeTable) = 
+proc initNodeTable*(x: var TNodeTable) =
   x.counter = 0
   newSeq(x.data, StartSize)
 
@@ -1327,11 +1325,11 @@ proc propagateToOwner*(owner, elem: PType) =
       owner.flags.incl tfNotNil
     elif owner.kind notin HaveTheirOwnEmpty:
       owner.flags.incl tfNeedsInit
-  
+
   if tfNeedsInit in elem.flags:
     if owner.kind in HaveTheirOwnEmpty: discard
     else: owner.flags.incl tfNeedsInit
-    
+
   if elem.isMetaType:
     owner.flags.incl tfHasMeta
 
@@ -1348,15 +1346,15 @@ proc addSonNilAllowed*(father, son: PNode) =
   if isNil(father.sons): father.sons = @[]
   add(father.sons, son)
 
-proc delSon*(father: PNode, idx: int) = 
-  if isNil(father.sons): return 
+proc delSon*(father: PNode, idx: int) =
+  if isNil(father.sons): return
   var length = sonsLen(father)
   for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1]
   setLen(father.sons, length - 1)
 
-proc copyNode*(src: PNode): PNode = 
+proc copyNode*(src: PNode): PNode =
   # does not copy its sons!
-  if src == nil: 
+  if src == nil:
     return nil
   result = newNode(src.kind)
   result.info = src.info
@@ -1373,7 +1371,7 @@ proc copyNode*(src: PNode): PNode =
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
   else: discard
 
-proc shallowCopy*(src: PNode): PNode = 
+proc shallowCopy*(src: PNode): PNode =
   # does not copy its sons, but provides space for them:
   if src == nil: return nil
   result = newNode(src.kind)
@@ -1391,9 +1389,9 @@ proc shallowCopy*(src: PNode): PNode =
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
   else: newSeq(result.sons, sonsLen(src))
 
-proc copyTree*(src: PNode): PNode = 
+proc copyTree*(src: PNode): PNode =
   # copy a whole syntax tree; performs deep copying
-  if src == nil: 
+  if src == nil:
     return nil
   result = newNode(src.kind)
   result.info = src.info
@@ -1408,20 +1406,20 @@ proc copyTree*(src: PNode): PNode =
   of nkSym: result.sym = src.sym
   of nkIdent: result.ident = src.ident
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
-  else: 
+  else:
     newSeq(result.sons, sonsLen(src))
-    for i in countup(0, sonsLen(src) - 1): 
+    for i in countup(0, sonsLen(src) - 1):
       result.sons[i] = copyTree(src.sons[i])
 
-proc hasSonWith(n: PNode, kind: TNodeKind): bool = 
-  for i in countup(0, sonsLen(n) - 1): 
-    if n.sons[i].kind == kind: 
+proc hasSonWith*(n: PNode, kind: TNodeKind): bool =
+  for i in countup(0, sonsLen(n) - 1):
+    if n.sons[i].kind == kind:
       return true
   result = false
 
-proc hasNilSon*(n: PNode): bool = 
-  for i in countup(0, safeLen(n) - 1): 
-    if n.sons[i] == nil: 
+proc hasNilSon*(n: PNode): bool =
+  for i in countup(0, safeLen(n) - 1):
+    if n.sons[i] == nil:
       return true
     elif hasNilSon(n.sons[i]):
       return true
@@ -1435,47 +1433,47 @@ proc containsNode*(n: PNode, kinds: TNodeKinds): bool =
     for i in countup(0, sonsLen(n) - 1):
       if n.kind in kinds or containsNode(n.sons[i], kinds): return true
 
-proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool = 
+proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool =
   case n.kind
   of nkEmpty..nkNilLit: result = n.kind == kind
-  else: 
-    for i in countup(0, sonsLen(n) - 1): 
-      if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind): 
+  else:
+    for i in countup(0, sonsLen(n) - 1):
+      if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
         return true
     result = false
 
-proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) = 
-  for i in countup(0, sonsLen(n) - 1): 
+proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) =
+  for i in countup(0, sonsLen(n) - 1):
     if n.sons[i].kind == oldKind: n.sons[i].kind = newKind
-  
-proc sonsNotNil(n: PNode): bool = 
-  for i in countup(0, sonsLen(n) - 1): 
-    if n.sons[i] == nil: 
+
+proc sonsNotNil(n: PNode): bool =
+  for i in countup(0, sonsLen(n) - 1):
+    if n.sons[i] == nil:
       return false
   result = true
 
-proc getInt*(a: PNode): BiggestInt = 
+proc getInt*(a: PNode): BiggestInt =
   case a.kind
   of nkIntLit..nkUInt64Lit: result = a.intVal
-  else: 
+  else:
     internalError(a.info, "getInt")
     result = 0
 
-proc getFloat*(a: PNode): BiggestFloat = 
+proc getFloat*(a: PNode): BiggestFloat =
   case a.kind
   of nkFloatLit..nkFloat128Lit: result = a.floatVal
-  else: 
+  else:
     internalError(a.info, "getFloat")
     result = 0.0
 
-proc getStr*(a: PNode): string = 
+proc getStr*(a: PNode): string =
   case a.kind
   of nkStrLit..nkTripleStrLit: result = a.strVal
-  else: 
+  else:
     internalError(a.info, "getStr")
     result = ""
 
-proc getStrOrChar*(a: PNode): string = 
+proc getStrOrChar*(a: PNode): string =
   case a.kind
   of nkStrLit..nkTripleStrLit: result = a.strVal
   of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
@@ -1483,7 +1481,7 @@ proc getStrOrChar*(a: PNode): string =
     internalError(a.info, "getStrOrChar")
     result = ""
 
-proc isGenericRoutine*(s: PSym): bool = 
+proc isGenericRoutine*(s: PSym): bool =
   case s.kind
   of skProcKinds:
     result = sfFromGeneric in s.flags or
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index e9b82d74b..c53e53b88 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -203,9 +203,9 @@ proc mustRehash(length, counter: int): bool =
   assert(length > counter)
   result = (length * 2 < counter * 3) or (length - counter < 4)
 
-proc spaces(x: int): PRope = 
+proc rspaces(x: int): PRope = 
   # returns x spaces
-  result = toRope(repeatChar(x))
+  result = toRope(spaces(x))
 
 proc toYamlChar(c: char): string = 
   case c
@@ -253,7 +253,7 @@ proc typeToYamlAux(n: PType, marker: var IntSet,
                    indent, maxRecDepth: int): PRope
 proc strTableToYaml(n: TStrTable, marker: var IntSet, indent: int, 
                     maxRecDepth: int): PRope = 
-  var istr = spaces(indent + 2)
+  var istr = rspaces(indent + 2)
   result = toRope("[")
   var mycount = 0
   for i in countup(0, high(n.data)): 
@@ -262,20 +262,20 @@ proc strTableToYaml(n: TStrTable, marker: var IntSet, indent: int,
       appf(result, "$N$1$2", 
            [istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)])
       inc(mycount)
-  if mycount > 0: appf(result, "$N$1", [spaces(indent)])
+  if mycount > 0: appf(result, "$N$1", [rspaces(indent)])
   app(result, "]")
   assert(mycount == n.counter)
 
 proc ropeConstr(indent: int, c: openArray[PRope]): PRope = 
   # array of (name, value) pairs
-  var istr = spaces(indent + 2)
+  var istr = rspaces(indent + 2)
   result = toRope("{")
   var i = 0
   while i <= high(c): 
     if i > 0: app(result, ",")
     appf(result, "$N$1\"$2\": $3", [istr, c[i], c[i + 1]])
     inc(i, 2)
-  appf(result, "$N$1}", [spaces(indent)])
+  appf(result, "$N$1}", [rspaces(indent)])
 
 proc symToYamlAux(n: PSym, marker: var IntSet, indent: int, 
                   maxRecDepth: int): PRope = 
@@ -310,9 +310,9 @@ proc typeToYamlAux(n: PType, marker: var IntSet, indent: int,
       result = toRope("[")
       for i in countup(0, sonsLen(n) - 1): 
         if i > 0: app(result, ",")
-        appf(result, "$N$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i], 
+        appf(result, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(n.sons[i], 
             marker, indent + 4, maxRecDepth - 1)])
-      appf(result, "$N$1]", [spaces(indent + 2)])
+      appf(result, "$N$1]", [rspaces(indent + 2)])
     else: 
       result = toRope("null")
     result = ropeConstr(indent, [toRope("kind"), 
@@ -331,7 +331,7 @@ proc treeToYamlAux(n: PNode, marker: var IntSet, indent: int,
   if n == nil: 
     result = toRope("null")
   else: 
-    var istr = spaces(indent + 2)
+    var istr = rspaces(indent + 2)
     result = ropef("{$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
     if maxRecDepth != 0: 
       appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
@@ -359,12 +359,12 @@ proc treeToYamlAux(n: PNode, marker: var IntSet, indent: int,
           appf(result, ",$N$1\"sons\": [", [istr])
           for i in countup(0, sonsLen(n) - 1): 
             if i > 0: app(result, ",")
-            appf(result, "$N$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i], 
+            appf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(n.sons[i], 
                 marker, indent + 4, maxRecDepth - 1)])
           appf(result, "$N$1]", [istr])
       appf(result, ",$N$1\"typ\": $2", 
            [istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)])
-    appf(result, "$N$1}", [spaces(indent)])
+    appf(result, "$N$1}", [rspaces(indent)])
 
 proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope = 
   var marker = initIntSet()
@@ -387,6 +387,9 @@ proc debugType(n: PType, maxRecDepth=100): PRope =
     if n.sym != nil: 
       app(result, " ")
       app(result, n.sym.name.s)
+    if n.kind in IntegralTypes and n.n != nil:
+      app(result, ", node: ")
+      app(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true))
     if (n.kind != tyString) and (sonsLen(n) > 0) and maxRecDepth != 0:
       app(result, "(")
       for i in countup(0, sonsLen(n) - 1):
@@ -405,7 +408,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
   if n == nil: 
     result = toRope("null")
   else: 
-    var istr = spaces(indent + 2)
+    var istr = rspaces(indent + 2)
     result = ropef("{$N$1\"kind\": $2", 
                    [istr, makeYamlString($n.kind)])
     if maxRecDepth != 0: 
@@ -437,29 +440,29 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
           appf(result, ",$N$1\"sons\": [", [istr])
           for i in countup(0, sonsLen(n) - 1): 
             if i > 0: app(result, ",")
-            appf(result, "$N$1$2", [spaces(indent + 4), debugTree(n.sons[i], 
+            appf(result, "$N$1$2", [rspaces(indent + 4), debugTree(n.sons[i], 
                 indent + 4, maxRecDepth - 1, renderType)])
           appf(result, "$N$1]", [istr])
     appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
-    appf(result, "$N$1}", [spaces(indent)])
+    appf(result, "$N$1}", [rspaces(indent)])
 
 proc debug(n: PSym) =
   if n == nil:
-    writeln(stdout, "null")
+    msgWriteln("null")
   elif n.kind == skUnknown:
-    writeln(stdout, "skUnknown")
+    msgWriteln("skUnknown")
   else:
     #writeln(stdout, ropeToStr(symToYaml(n, 0, 1)))
-    writeln(stdout, "$1_$2: $3, $4, $5, $6" % [
+    msgWriteln("$1_$2: $3, $4, $5, $6" % [
       n.name.s, $n.id, flagsToStr(n.flags).ropeToStr, 
       flagsToStr(n.loc.flags).ropeToStr, lineInfoToStr(n.info).ropeToStr,
       $n.kind])
 
 proc debug(n: PType) = 
-  writeln(stdout, ropeToStr(debugType(n)))
+  msgWriteln(ropeToStr(debugType(n)))
 
 proc debug(n: PNode) = 
-  writeln(stdout, ropeToStr(debugTree(n, 0, 100)))
+  msgWriteln(ropeToStr(debugTree(n, 0, 100)))
 
 const 
   EmptySeq = @[]
@@ -678,9 +681,8 @@ proc initIdentIter(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym =
   else: result = nextIdentIter(ti, tab)
   
 proc nextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym = 
-  var h, start: THash
-  h = ti.h and high(tab.data)
-  start = h
+  var h = ti.h and high(tab.data)
+  var start = h
   result = tab.data[h]
   while result != nil: 
     if result.name.id == ti.name.id: break 
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 3bc0d8afb..564d1fd36 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -56,11 +56,6 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
     case skipTypes(ty, abstractVarRange).kind
     of tyChar, tyNil:
       result = intLiteral(n.intVal)
-    of tyInt:
-      if n.intVal >= low(int32) and n.intVal <= high(int32):
-        result = int32Literal(int32(n.intVal))
-      else:
-        result = intLiteral(n.intVal)
     of tyBool:
       if n.intVal != 0: result = ~"NIM_TRUE"
       else: result = ~"NIM_FALSE"
@@ -89,7 +84,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
       var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
       if id == gBackendId:
         # string literal not found in the cache:
-        result = ropecg(p.module, "((#NimStringDesc*) &$1)", 
+        result = ropecg(p.module, "((#NimStringDesc*) &$1)",
                         [getStrLit(p.module, n.strVal)])
       else:
         result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [toRope(id)])
@@ -158,7 +153,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
     of skVar, skForVar, skResult, skLet:
       if sfGlobal in n.sym.flags: result = OnHeap
       else: result = OnStack
-    of skConst: 
+    of skConst:
       if sfGlobal in n.sym.flags: result = OnHeap
       else: result = OnUnknown
     else: result = OnUnknown
@@ -236,7 +231,7 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   for i in 0 .. <t.len:
     let t = t.sons[i]
     let field = ropef("Field$1", i.toRope)
-    genAssignment(p, optAsgnLoc(dest, t, field), 
+    genAssignment(p, optAsgnLoc(dest, t, field),
                      optAsgnLoc(src, t, field), newflags)
 
 proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
@@ -252,20 +247,20 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
   case t.kind
   of nkSym:
     let field = t.sym
-    genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r), 
+    genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r),
                      optAsgnLoc(src, field.typ, field.loc.r), newflags)
   of nkRecList:
     for child in items(t): genOptAsgnObject(p, dest, src, newflags, child)
   else: discard
 
 proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
-  # Consider: 
+  # Consider:
   # type TMyFastString {.shallow.} = string
   # Due to the implementation of pragmas this would end up to set the
   # tfShallow flag for the built-in string type too! So we check only
   # here for this flag, where it is reasonably safe to do so
   # (for objects, etc.):
-  if needToCopy notin flags or 
+  if needToCopy notin flags or
       tfShallow in skipTypes(dest.t, abstractVarRange).flags:
     if dest.s == OnStack or not usesNativeGC():
       useStringh(p.module)
@@ -510,7 +505,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
     var storage: PRope
     var size = getSize(t)
     if size < platform.intSize:
-      storage = toRope("NI") 
+      storage = toRope("NI")
     else:
       storage = getTypeDesc(p.module, t)
     var tmp = getTempName()
@@ -547,7 +542,7 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       "(($4)($1) - ($4)($2))", # SubF64
       "(($4)($1) * ($4)($2))", # MulF64
       "(($4)($1) / ($4)($2))", # DivF64
-      
+
       "($4)((NU$3)($1) >> (NU$3)($2))", # ShrI
       "($4)((NU$3)($1) << (NU$3)($2))", # ShlI
       "($4)($1 & $2)",      # BitandI
@@ -617,7 +612,7 @@ proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
   initLocExpr(p, e.sons[1], a)
   initLocExpr(p, e.sons[2], b)
   if a.t.callConv == ccClosure:
-    putIntoDest(p, d, e.typ, 
+    putIntoDest(p, d, e.typ,
       ropef("($1.ClPrc == $2.ClPrc && $1.ClEnv == $2.ClEnv)", [
       rdLoc(a), rdLoc(b)]))
   else:
@@ -721,7 +716,7 @@ template inheritLocation(d: var TLoc, a: TLoc) =
   if d.k == locNone: d.s = a.s
   if d.heapRoot == nil:
     d.heapRoot = if a.heapRoot != nil: a.heapRoot else: a.r
-  
+
 proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
   initLocExpr(p, e.sons[0], a)
   if e.sons[1].kind != nkSym: internalError(e.info, "genRecordFieldAux")
@@ -954,7 +949,7 @@ proc genEcho(p: BProc, n: PNode) =
     initLocExpr(p, n.sons[i], a)
     appf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
   linefmt(p, cpsStmts, "printf($1$2);$n",
-          makeCString(repeatStr(n.len, "%s") & tnl), args)
+          makeCString(repeat("%s", n.len) & tnl), args)
 
 proc gcUsage(n: PNode) =
   if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree)
@@ -1061,7 +1056,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   genAssignment(p, dest, b, {needToCopy, afDestIsNil})
   gcUsage(e)
 
-proc genReset(p: BProc, n: PNode) = 
+proc genReset(p: BProc, n: PNode) =
   var a: TLoc
   initLocExpr(p, n.sons[1], a)
   linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
@@ -1120,14 +1115,14 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
   else:
     call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args)
     genAssignment(p, dest, call, {needToKeepAlive})
-  
+
 proc genNewSeq(p: BProc, e: PNode) =
   var a, b: TLoc
   initLocExpr(p, e.sons[1], a)
   initLocExpr(p, e.sons[2], b)
   genNewSeqAux(p, a, b.rdLoc)
   gcUsage(e)
-  
+
 proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
   var tmp: TLoc
   var t = e.typ.skipTypes(abstractInst)
@@ -1168,7 +1163,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     d = tmp
   else:
     genAssignment(p, d, tmp, {})
-  
+
 proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
   var arr: TLoc
   if d.k == locNone:
@@ -1192,7 +1187,7 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
     getTemp(p, t.typ, d)
   # generate call to newSeq before adding the elements per hand:
   var L = int(lengthOrd(t.sons[1].typ))
-  
+
   genNewSeqAux(p, d, intLiteral(L))
   initLocExpr(p, t.sons[1], a)
   for i in countup(0, L - 1):
@@ -1202,7 +1197,7 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
     initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.s)
     arr.r = rfmt(nil, "$1[$2]", rdLoc(a), intLiteral(i))
     genAssignment(p, elem, arr, {afDestIsNil, needToCopy})
-  
+
 proc genNewFinalize(p: BProc, e: PNode) =
   var
     a, b, f: TLoc
@@ -1258,7 +1253,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
       app(r, ~".Sup")
       t = skipTypes(t.sons[0], typedescInst)
   if isObjLackingTypeField(t):
-    globalError(x.info, errGenerated, 
+    globalError(x.info, errGenerated,
       "no 'of' operator available for pure objects")
   if nilCheck != nil:
     r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
@@ -1275,7 +1270,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   var t = skipTypes(e.sons[1].typ, abstractVarRange)
   case t.kind
   of tyInt..tyInt64, tyUInt..tyUInt64:
-    putIntoDest(p, d, e.typ, 
+    putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]))
   of tyFloat..tyFloat128:
     putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
@@ -1298,13 +1293,13 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
     of tyOpenArray, tyVarargs:
       putIntoDest(p, b, e.typ, ropef("$1, $1Len0", [rdLoc(a)]))
     of tyString, tySequence:
-      putIntoDest(p, b, e.typ, 
+      putIntoDest(p, b, e.typ,
                   ropef("$1->data, $1->$2", [rdLoc(a), lenField(p)]))
     of tyArray, tyArrayConstr:
       putIntoDest(p, b, e.typ,
                   ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
     else: internalError(e.sons[0].info, "genRepr()")
-    putIntoDest(p, d, e.typ, 
+    putIntoDest(p, d, e.typ,
         ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
         genTypeInfo(p.module, elemType(t))]))
   of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
@@ -1433,7 +1428,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
     # do not emit the set, but generate a bunch of comparisons; and if we do
     # so, we skip the unnecessary range check: This is a semantical extension
     # that code now relies on. :-/ XXX
-    let ea = if e.sons[2].kind in {nkChckRange, nkChckRange64}: 
+    let ea = if e.sons[2].kind in {nkChckRange, nkChckRange64}:
                e.sons[2].sons[0]
              else:
                e.sons[2]
@@ -1518,7 +1513,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       initLocExpr(p, e.sons[2], b)
       if d.k == locNone: getTemp(p, a.t, d)
       lineF(p, cpsStmts,
-           "for ($1 = 0; $1 < $2; $1++) $n" & 
+           "for ($1 = 0; $1 < $2; $1++) $n" &
            "  $3[$1] = $4[$1] $6 $5[$1];$n", [
           rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b),
           toRope(lookupOpr[op])])
@@ -1549,7 +1544,7 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
 
 proc genCast(p: BProc, e: PNode, d: var TLoc) =
   const floatTypes = {tyFloat..tyFloat128}
-  let 
+  let
     destt = skipTypes(e.typ, abstractRange)
     srct = skipTypes(e.sons[1].typ, abstractRange)
   if destt.kind in floatTypes or srct.kind in floatTypes:
@@ -1656,7 +1651,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mRepr: genRepr(p, e, d)
   of mGetTypeInfo: genGetTypeInfo(p, e, d)
   of mSwap: genSwap(p, e, d)
-  of mUnaryLt: 
+  of mUnaryLt:
     if optOverflowCheck notin p.options: unaryExpr(p, e, d, "($1 - 1)")
     else: unaryExpr(p, e, d, "#subInt($1, 1)")
   of mPred:
@@ -1830,10 +1825,10 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
 proc isConstClosure(n: PNode): bool {.inline.} =
   result = n.sons[0].kind == nkSym and isRoutine(n.sons[0].sym) and
       n.sons[1].kind == nkNilLit
-      
+
 proc genClosure(p: BProc, n: PNode, d: var TLoc) =
   assert n.kind == nkClosure
-  
+
   if isConstClosure(n):
     inc(p.labels)
     var tmp = con("LOC", toRope(p.labels))
@@ -1920,7 +1915,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
     if isRef:
       # it can happen that we end up generating '&&x->Sup' here, so we pack
       # the '&x->Sup' into a temporary and then those address is taken
-      # (see bug #837). However sometimes using a temporary is not correct: 
+      # (see bug #837). However sometimes using a temporary is not correct:
       # init(TFigure(my)) # where it is passed to a 'var TFigure'. We test
       # this by ensuring the destination is also a pointer:
       if d.k == locNone and skipTypes(n.typ, abstractInst).kind in {tyRef, tyPtr, tyVar}:
@@ -1937,13 +1932,13 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
   discard getTypeDesc(p.module, t) # so that any fields are initialized
   var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
   var tmp = con("TMP", toRope(id))
-  
+
   if id == gBackendId:
     # expression not found in the cache:
     inc(gBackendId)
     appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
          [getTypeDesc(p.module, t), tmp, genConstExpr(p, n)])
-  
+
   if d.k == locNone:
     fillLoc(d, locData, t, tmp, OnHeap)
   else:
@@ -1984,7 +1979,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         internalError n.info, "expr: var not init " & sym.name.s & "_" & $sym.id
       if sfThread in sym.flags:
         accessThreadLocalVar(p, sym)
-        if emulatedThreadVars(): 
+        if emulatedThreadVars():
           putIntoDest(p, d, sym.loc.t, con("NimTV->", sym.loc.r))
         else:
           putLocIntoDest(p, d, sym.loc)
@@ -2001,7 +1996,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         #echo "FAILED FOR PRCO ", p.prc.name.s
         #debug p.prc.typ.n
         #echo renderTree(p.prc.ast, {renderIds})
-        internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)          
+        internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
       putLocIntoDest(p, d, sym.loc)
     else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
   of nkNilLit:
@@ -2101,9 +2096,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
     # we have to emit the type information for object types here to support
     # separate compilation:
     genTypeSection(p.module, n)
-  of nkCommentStmt, nkIteratorDef, nkIncludeStmt, 
-     nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, 
-     nkFromStmt, nkTemplateDef, nkMacroDef: 
+  of nkCommentStmt, nkIteratorDef, nkIncludeStmt,
+     nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
+     nkFromStmt, nkTemplateDef, nkMacroDef:
     discard
   of nkPragma: genPragma(p, n)
   of nkPragmaBlock: expr(p, n.lastSon, d)
@@ -2118,8 +2113,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
             sfDeadCodeElim notin getModule(prc).flags) or
             ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
             (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
-            (prc.kind == skMethod): 
-          # we have not only the header: 
+            (prc.kind == skMethod):
+          # we have not only the header:
           if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags:
             genProc(p.module, prc)
   of nkParForStmt: genParForStmt(p, n)
@@ -2142,7 +2137,7 @@ proc genConstSimpleList(p: BProc, n: PNode): PRope =
 
 proc genConstSeq(p: BProc, n: PNode, t: PType): PRope =
   var data = ropef("{{$1, $1}", n.len.toRope)
-  if n.len > 0: 
+  if n.len > 0:
     # array part needs extra curlies:
     data.app(", {")
     for i in countup(0, n.len - 1):
@@ -2150,14 +2145,14 @@ proc genConstSeq(p: BProc, n: PNode, t: PType): PRope =
       data.app genConstExpr(p, n.sons[i])
     data.app("}")
   data.app("}")
-  
+
   inc(gBackendId)
   result = con("CNSTSEQ", gBackendId.toRope)
-  
+
   appcg(p.module, cfsData,
-        "NIM_CONST struct {$n" & 
+        "NIM_CONST struct {$n" &
         "  #TGenericSeq Sup;$n" &
-        "  $1 data[$2];$n" & 
+        "  $1 data[$2];$n" &
         "} $3 = $4;$n", [
         getTypeDesc(p.module, t.sons[0]), n.len.toRope, result, data])
 
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 0220d2066..9a5a3ab34 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -226,71 +226,8 @@ proc fillResult(param: PSym) =
     incl(param.loc.flags, lfIndirect)
     param.loc.s = OnUnknown
 
-proc getParamTypeDesc(m: BModule, t: PType, check: var IntSet): PRope =
-  when false:
-    if t.Kind in {tyRef, tyPtr, tyVar}:
-      var b = skipTypes(t.lastson, typedescInst)
-      if b.kind == tySet and mapSetType(b) == ctArray:
-        return getTypeDescAux(m, b, check)
-  result = getTypeDescAux(m, t, check)
-
-proc paramStorageLoc(param: PSym): TStorageLoc =
-  if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {tyArray, tyOpenArray}:
-    result = OnStack
-  else:
-    result = OnUnknown
-
-proc genProcParams(m: BModule, t: PType, rettype, params: var PRope, 
-                   check: var IntSet, declareEnvironment=true) = 
-  params = nil
-  if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]): 
-    rettype = ~"void"
-  else: 
-    rettype = getTypeDescAux(m, t.sons[0], check)
-  for i in countup(1, sonsLen(t.n) - 1): 
-    if t.n.sons[i].kind != nkSym: internalError(t.n.info, "genProcParams")
-    var param = t.n.sons[i].sym
-    if isCompileTimeOnly(param.typ): continue
-    if params != nil: app(params, ~", ")
-    fillLoc(param.loc, locParam, param.typ, mangleName(param),
-            param.paramStorageLoc)
-    app(params, getParamTypeDesc(m, param.typ, check))
-    if ccgIntroducedPtr(param): 
-      app(params, ~"*")
-      incl(param.loc.flags, lfIndirect)
-      param.loc.s = OnUnknown
-    app(params, ~" ")
-    app(params, param.loc.r)
-    # declare the len field for open arrays:
-    var arr = param.typ
-    if arr.kind == tyVar: arr = arr.sons[0]
-    var j = 0
-    while arr.kind in {tyOpenArray, tyVarargs}:
-      # this fixes the 'sort' bug:
-      if param.typ.kind == tyVar: param.loc.s = OnUnknown
-      # need to pass hidden parameter:
-      appf(params, ", NI $1Len$2", [param.loc.r, j.toRope])
-      inc(j)
-      arr = arr.sons[0]
-  if (t.sons[0] != nil) and isInvalidReturnType(t.sons[0]):
-    var arr = t.sons[0]
-    if params != nil: app(params, ", ")
-    app(params, getTypeDescAux(m, arr, check))
-    if (mapReturnType(t.sons[0]) != ctArray):
-      app(params, "*")
-    appf(params, " Result", [])
-  if t.callConv == ccClosure and declareEnvironment: 
-    if params != nil: app(params, ", ")
-    app(params, "void* ClEnv")
-  if tfVarargs in t.flags: 
-    if params != nil: app(params, ", ")
-    app(params, "...")
-  if params == nil: app(params, "void)")
-  else: app(params, ")")
-  params = con("(", params)
-
 proc typeNameOrLiteral(t: PType, literal: string): PRope = 
-  if (t.sym != nil) and (sfImportc in t.sym.flags) and (t.sym.magic == mNone): 
+  if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone: 
     result = getTypeName(t)
   else: 
     result = toRope(literal)
@@ -327,7 +264,10 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
     result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.kind])
   of tyDistinct, tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.sons[0])
   else: result = nil
-  
+
+proc pushType(m: BModule, typ: PType) = 
+  add(m.typeStack, typ)
+
 proc getTypePre(m: BModule, typ: PType): PRope = 
   if typ == nil: result = toRope("void")
   else: 
@@ -354,6 +294,81 @@ proc getTypeForward(m: BModule, typ: PType): PRope =
           [structOrUnion(typ), result])
     idTablePut(m.forwTypeCache, typ, result)
   else: internalError("getTypeForward(" & $typ.kind & ')')
+
+proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): PRope =
+  ## like getTypeDescAux but creates only a *weak* dependency. In other words
+  ## we know we only need a pointer to it so we only generate a struct forward
+  ## declaration:
+  var etB = t.skipTypes(abstractInst)
+  case etB.kind
+  of tyObject, tyTuple:
+    if isImportedCppType(etB) and t.kind == tyGenericInst:
+      result = getTypeDescAux(m, t, check)
+    else:
+      let x = getUniqueType(etB)
+      result = getTypeForward(m, x)
+      pushType(m, x)
+  else:
+    result = getTypeDescAux(m, t, check)
+
+proc paramStorageLoc(param: PSym): TStorageLoc =
+  if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {tyArray, tyOpenArray}:
+    result = OnStack
+  else:
+    result = OnUnknown
+
+proc genProcParams(m: BModule, t: PType, rettype, params: var PRope, 
+                   check: var IntSet, declareEnvironment=true) = 
+  params = nil
+  if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]): 
+    rettype = ~"void"
+  else: 
+    rettype = getTypeDescAux(m, t.sons[0], check)
+  for i in countup(1, sonsLen(t.n) - 1): 
+    if t.n.sons[i].kind != nkSym: internalError(t.n.info, "genProcParams")
+    var param = t.n.sons[i].sym
+    if isCompileTimeOnly(param.typ): continue
+    if params != nil: app(params, ~", ")
+    fillLoc(param.loc, locParam, param.typ, mangleName(param),
+            param.paramStorageLoc)
+    if ccgIntroducedPtr(param): 
+      app(params, getTypeDescWeak(m, param.typ, check))
+      app(params, ~"*")
+      incl(param.loc.flags, lfIndirect)
+      param.loc.s = OnUnknown
+    else:
+      app(params, getTypeDescAux(m, param.typ, check))
+    app(params, ~" ")
+    app(params, param.loc.r)
+    # declare the len field for open arrays:
+    var arr = param.typ
+    if arr.kind == tyVar: arr = arr.sons[0]
+    var j = 0
+    while arr.kind in {tyOpenArray, tyVarargs}:
+      # this fixes the 'sort' bug:
+      if param.typ.kind == tyVar: param.loc.s = OnUnknown
+      # need to pass hidden parameter:
+      appf(params, ", NI $1Len$2", [param.loc.r, j.toRope])
+      inc(j)
+      arr = arr.sons[0]
+  if (t.sons[0] != nil) and isInvalidReturnType(t.sons[0]):
+    var arr = t.sons[0]
+    if params != nil: app(params, ", ")
+    if (mapReturnType(t.sons[0]) != ctArray):
+      app(params, getTypeDescWeak(m, arr, check))
+      app(params, "*")
+    else:
+      app(params, getTypeDescAux(m, arr, check))
+    appf(params, " Result", [])
+  if t.callConv == ccClosure and declareEnvironment: 
+    if params != nil: app(params, ", ")
+    app(params, "void* ClEnv")
+  if tfVarargs in t.flags:
+    if params != nil: app(params, ", ")
+    app(params, "...")
+  if params == nil: app(params, "void)")
+  else: app(params, ")")
+  params = con("(", params)
   
 proc mangleRecFieldName(field: PSym, rectype: PType): PRope = 
   if (rectype.sym != nil) and
@@ -473,9 +488,6 @@ proc getTupleDesc(m: BModule, typ: PType, name: PRope,
   else: app(result, desc)
   app(result, "};" & tnl)
 
-proc pushType(m: BModule, typ: PType) = 
-  add(m.typeStack, typ)
-
 proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = 
   # returns only the type's name
   var t = getUniqueType(typ)
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 134619d4a..25c1a12e5 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -9,31 +9,31 @@
 
 # This module declares some helpers for the C code generator.
 
-import 
-  ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg, 
+import
+  ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg,
   platform, trees
 
 proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
   case n.kind
-  of nkStmtList: 
-    for i in 0 .. < n.len: 
+  of nkStmtList:
+    for i in 0 .. < n.len:
       result = getPragmaStmt(n[i], w)
       if result != nil: break
   of nkPragma:
-    for i in 0 .. < n.len: 
+    for i in 0 .. < n.len:
       if whichPragma(n[i]) == w: return n[i]
   else: discard
 
 proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool =
   result = getPragmaStmt(n, w) != nil
 
-proc hashString*(s: string): BiggestInt = 
+proc hashString*(s: string): BiggestInt =
   # has to be the same algorithm as system.hashString!
-  if CPU[targetCPU].bit == 64: 
+  if CPU[targetCPU].bit == 64:
     # we have to use the same bitwidth
     # as the target CPU
     var b = 0'i64
-    for i in countup(0, len(s) - 1): 
+    for i in countup(0, len(s) - 1):
       b = b +% ord(s[i])
       b = b +% `shl`(b, 10)
       b = b xor `shr`(b, 6)
@@ -41,9 +41,9 @@ proc hashString*(s: string): BiggestInt =
     b = b xor `shr`(b, 11)
     b = b +% `shl`(b, 15)
     result = b
-  else: 
+  else:
     var a = 0'i32
-    for i in countup(0, len(s) - 1): 
+    for i in countup(0, len(s) - 1):
       a = a +% ord(s[i]).int32
       a = a +% `shl`(a, 10'i32)
       a = a xor `shr`(a, 6'i32)
@@ -52,11 +52,11 @@ proc hashString*(s: string): BiggestInt =
     a = a +% `shl`(a, 15'i32)
     result = a
 
-var 
+var
   gTypeTable: array[TTypeKind, TIdTable]
   gCanonicalTypes: array[TTypeKind, PType]
 
-proc initTypeTables() = 
+proc initTypeTables() =
   for i in countup(low(TTypeKind), high(TTypeKind)): initIdTable(gTypeTable[i])
 
 proc resetCaches* =
@@ -67,7 +67,7 @@ proc resetCaches* =
 
 when false:
   proc echoStats*() =
-    for i in countup(low(TTypeKind), high(TTypeKind)): 
+    for i in countup(low(TTypeKind), high(TTypeKind)):
       echo i, " ", gTypeTable[i].counter
 
 proc slowSearch(key: PType; k: TTypeKind): PType =
@@ -78,28 +78,28 @@ proc slowSearch(key: PType; k: TTypeKind): PType =
   if idTableHasObjectAsKey(gTypeTable[k], key): return key
   for h in countup(0, high(gTypeTable[k].data)):
     var t = PType(gTypeTable[k].data[h].key)
-    if t != nil and sameBackendType(t, key): 
+    if t != nil and sameBackendType(t, key):
       return t
   idTablePut(gTypeTable[k], key, key)
   result = key
 
-proc getUniqueType*(key: PType): PType = 
+proc getUniqueType*(key: PType): PType =
   # this is a hotspot in the compiler!
-  if key == nil: return 
+  if key == nil: return
   var k = key.kind
   case k
   of tyBool, tyChar, tyInt..tyUInt64:
     # no canonicalization for integral types, so that e.g. ``pid_t`` is
     # produced instead of ``NI``.
     result = key
-  of  tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString, 
+  of  tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
       tyCString, tyNone, tyBigNum:
     result = gCanonicalTypes[k]
     if result == nil:
       gCanonicalTypes[k] = key
       result = key
   of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor:
-    internalError("GetUniqueType")
+    internalError("getUniqueType")
   of tyDistinct:
     if key.deepCopy != nil: result = key
     else: result = getUniqueType(lastSon(key))
@@ -127,21 +127,21 @@ proc getUniqueType*(key: PType): PType =
     if tfFromGeneric notin key.flags:
       # fast case; lookup per id suffices:
       result = PType(idTableGet(gTypeTable[k], key))
-      if result == nil: 
+      if result == nil:
         idTablePut(gTypeTable[k], key, key)
         result = key
     else:
       # ugly slow case: need to compare by structure
       if idTableHasObjectAsKey(gTypeTable[k], key): return key
-      for h in countup(0, high(gTypeTable[k].data)): 
+      for h in countup(0, high(gTypeTable[k].data)):
         var t = PType(gTypeTable[k].data[h].key)
-        if t != nil and sameType(t, key): 
+        if t != nil and sameBackendType(t, key):
           return t
       idTablePut(gTypeTable[k], key, key)
-      result = key    
+      result = key
   of tyEnum:
     result = PType(idTableGet(gTypeTable[k], key))
-    if result == nil: 
+    if result == nil:
       idTablePut(gTypeTable[k], key, key)
       result = key
   of tyProc:
@@ -151,16 +151,16 @@ proc getUniqueType*(key: PType): PType =
       # ugh, we need the canon here:
       result = slowSearch(key, k)
 
-proc tableGetType*(tab: TIdTable, key: PType): RootRef = 
+proc tableGetType*(tab: TIdTable, key: PType): RootRef =
   # returns nil if we need to declare this type
   result = idTableGet(tab, key)
-  if (result == nil) and (tab.counter > 0): 
+  if (result == nil) and (tab.counter > 0):
     # we have to do a slow linear search because types may need
     # to be compared by their structure:
-    for h in countup(0, high(tab.data)): 
+    for h in countup(0, high(tab.data)):
       var t = PType(tab.data[h].key)
-      if t != nil: 
-        if sameType(t, key): 
+      if t != nil:
+        if sameType(t, key):
           return tab.data[h].val
 
 proc makeSingleLineCString*(s: string): string =
@@ -193,16 +193,16 @@ proc mangle*(name: string): string =
     else:
       add(result, "HEX" & toHex(ord(c), 2))
 
-proc makeLLVMString*(s: string): PRope = 
+proc makeLLVMString*(s: string): PRope =
   const MaxLineLength = 64
   result = nil
   var res = "c\""
-  for i in countup(0, len(s) - 1): 
-    if (i + 1) mod MaxLineLength == 0: 
+  for i in countup(0, len(s) - 1):
+    if (i + 1) mod MaxLineLength == 0:
       app(result, toRope(res))
       setLen(res, 0)
     case s[i]
-    of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\': 
+    of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\':
       add(res, '\\')
       add(res, toHex(ord(s[i]), 2))
     else: add(res, s[i])
diff --git a/compiler/commands.nim b/compiler/commands.nim
index c52515c76..a2d02e469 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -326,7 +326,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
   of "link": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: addFileToLink(arg)
-  of "debuginfo": 
+  of "debuginfo":
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optCDebug)
   of "embedsrc":
@@ -374,10 +374,20 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
   of "threadanalysis": processOnOffSwitchG({optThreadAnalysis}, arg, pass, info)
   of "stacktrace": processOnOffSwitch({optStackTrace}, arg, pass, info)
   of "linetrace": processOnOffSwitch({optLineTrace}, arg, pass, info)
-  of "debugger": 
-    processOnOffSwitch({optEndb}, arg, pass, info)
-    if optEndb in gOptions: defineSymbol("endb")
-    else: undefSymbol("endb")
+  of "debugger":
+    case arg.normalize
+    of "on", "endb":
+      gOptions.incl optEndb
+      defineSymbol("endb")
+    of "off":
+      gOptions.excl optEndb
+      undefSymbol("endb")
+    of "native", "gdb":
+      incl(gGlobalOptions, optCDebug)
+      gOptions = gOptions + {optLineDir} - {optEndb}
+      undefSymbol("endb")
+    else:
+      localError(info, "expected endb|gdb but found " & arg)
   of "profiler": 
     processOnOffSwitch({optProfiler}, arg, pass, info)
     if optProfiler in gOptions: defineSymbol("profiler")
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index b98679ac6..b1a23802d 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -164,6 +164,7 @@ proc packObject(x: PNode, typ: PType, res: pointer) =
       let field = getField(typ.n, i)
       pack(it, field.typ, res +! field.offset)
     else:
+      # XXX: todo
       globalError(x.info, "cannot pack unnamed tuple")
 
 const maxPackDepth = 20
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 29657a2ae..8959aa4df 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -10,7 +10,7 @@
 ## Template evaluation engine. Now hygienic.
 
 import
-  strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer, 
+  strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
   rodread
 
 type
@@ -49,7 +49,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
     result.add copyNode(c, templ, actual)
   else:
     var res = copyNode(c, templ, actual)
-    for i in countup(0, sonsLen(templ) - 1): 
+    for i in countup(0, sonsLen(templ) - 1):
       evalTemplateAux(templ.sons[i], actual, c, res)
     result.add res
 
@@ -86,9 +86,9 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode =
   ctx.owner = tmpl
   ctx.genSymOwner = genSymOwner
   initIdTable(ctx.mapping)
-  
+
   let body = tmpl.getBody
-  if isAtom(body): 
+  if isAtom(body):
     result = newNodeI(nkPar, body.info)
     evalTemplateAux(body, args, ctx, result)
     if result.len == 1: result = result.sons[0]
@@ -102,5 +102,5 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode =
     if ctx.instLines: result.info = n.info
     for i in countup(0, safeLen(body) - 1):
       evalTemplateAux(body.sons[i], args, ctx, result)
-  
+
   dec(evalTemplateCounter)
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 5f6033e57..8888632b9 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -572,6 +572,9 @@ proc footprint(filename: string): TCrc32 =
       getCompileCFileCmd(filename, true)
 
 proc externalFileChanged(filename: string): bool = 
+  if gCmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
+    return false
+
   var crcFile = toGeneratedFile(filename.withPackageName, "crc")
   var currentCrc = int(footprint(filename))
   var f: File
diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim
index 7b975dbaa..5d1f73be4 100644
--- a/compiler/filter_tmpl.nim
+++ b/compiler/filter_tmpl.nim
@@ -37,11 +37,11 @@ const
   PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '.', '_'}
 
 proc newLine(p: var TTmplParser) = 
-  llStreamWrite(p.outp, repeatChar(p.emitPar, ')'))
+  llStreamWrite(p.outp, repeat(')', p.emitPar))
   p.emitPar = 0
   if p.info.line > int16(1): llStreamWrite(p.outp, "\n")
   if p.pendingExprLine:
-    llStreamWrite(p.outp, repeatChar(2))
+    llStreamWrite(p.outp, spaces(2))
     p.pendingExprLine = false
   
 proc scanPar(p: var TTmplParser, d: int) = 
@@ -88,24 +88,24 @@ proc parseLine(p: var TTmplParser) =
       else: 
         p.info.col = int16(j)
         localError(p.info, errXNotAllowedHere, "end")
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, "#end")
     of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator, 
        wConverter, wMacro, wTemplate, wMethod: 
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, substr(p.x, d))
       inc(p.indent, 2)
     of wElif, wOf, wElse, wExcept, wFinally: 
-      llStreamWrite(p.outp, repeatChar(p.indent - 2))
+      llStreamWrite(p.outp, spaces(p.indent - 2))
       llStreamWrite(p.outp, substr(p.x, d))
     of wLet, wVar, wConst, wType:
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, substr(p.x, d))
       if not p.x.contains({':', '='}):
         # no inline element --> treat as block:
         inc(p.indent, 2)
     else:
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, substr(p.x, d))
     p.state = psDirective
   else: 
@@ -120,11 +120,11 @@ proc parseLine(p: var TTmplParser) =
       # next line of string literal:
       llStreamWrite(p.outp, p.conc)
       llStreamWrite(p.outp, "\n")
-      llStreamWrite(p.outp, repeatChar(p.indent + 2))
+      llStreamWrite(p.outp, spaces(p.indent + 2))
       llStreamWrite(p.outp, "\"")
     of psDirective: 
       newLine(p)
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, p.emit)
       llStreamWrite(p.outp, "(\"")
       inc(p.emitPar)
diff --git a/compiler/importer.nim b/compiler/importer.nim
index fbf3be4f2..57a1e542b 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -27,7 +27,7 @@ proc getModuleName*(n: PNode): string =
     result = n.ident.s
   of nkSym:
     result = n.sym.name.s
-  of nkInfix:
+  of nkInfix, nkPrefix:
     if n.sons[0].kind == nkIdent and n.sons[0].ident.id == getIdent("as").id:
       # XXX hack ahead:
       n.kind = nkImportAs
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 34f842d4a..87847204f 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -780,7 +780,7 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
     moveInto(p, stmt, r)
     appf(p.body, "}$n" | "end$n")
   if p.target == targetJS:
-    app(p.body, repeatChar(toClose, '}') & tnl)
+    app(p.body, repeat('}', toClose) & tnl)
   else:
     for i in 1..toClose: appf(p.body, "end$n")
 
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index fc40192b8..c86762121 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -181,10 +181,8 @@ proc prettyTok*(tok: TToken): string =
   else: result = tokToStr(tok)
   
 proc printTok*(tok: TToken) = 
-  write(stdout, tok.line, ":", tok.col, "\t")
-  write(stdout, TokTypeToStr[tok.tokType])
-  write(stdout, " ")
-  writeln(stdout, tokToStr(tok))
+  msgWriteln($tok.line & ":" & $tok.col & "\t" &
+      TokTypeToStr[tok.tokType] & " " & tokToStr(tok))
 
 var dummyIdent: PIdent
 
diff --git a/compiler/llstream.nim b/compiler/llstream.nim
index 69475965d..18ca4aec7 100644
--- a/compiler/llstream.nim
+++ b/compiler/llstream.nim
@@ -35,7 +35,7 @@ proc llStreamOpen*(data: string): PLLStream =
   result.s = data
   result.kind = llsString
 
-proc llStreamOpen*(f: var File): PLLStream = 
+proc llStreamOpen*(f: File): PLLStream = 
   new(result)
   result.f = f
   result.kind = llsFile
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 21d07f280..6d3379bb9 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -176,7 +176,7 @@ proc addInterfaceDeclAux(c: PContext, sym: PSym) =
   if sfExported in sym.flags:
     # add to interface:
     if c.module != nil: strTableAdd(c.module.tab, sym)
-    else: internalError(sym.info, "AddInterfaceDeclAux")
+    else: internalError(sym.info, "addInterfaceDeclAux")
 
 proc addInterfaceDeclAt*(c: PContext, scope: PScope, sym: PSym) =
   addDeclAt(scope, sym)
diff --git a/compiler/main.nim b/compiler/main.nim
index 42a782c02..f7592a891 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -62,7 +62,7 @@ proc commandCompileToC =
   compileProject()
   cgenWriteModules()
   if gCmd != cmdRun:
-    extccomp.callCCompiler(changeFileExt(gProjectFull, ""))
+    extccomp.callCCompiler(if gProjectName == "-": "stdinfile" else: changeFileExt(gProjectFull, ""))
 
   if isServing:
     # caas will keep track only of the compilation commands
diff --git a/compiler/modules.nim b/compiler/modules.nim
index db05ccc6c..a2b739efc 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -116,7 +116,7 @@ proc newModule(fileIdx: int32): PSym =
   result.kind = skModule
   let filename = fileIdx.toFullPath
   result.name = getIdent(splitFile(filename).name)
-  if not isNimIdentifier(result.name.s):
+  if result.name.s != "-" and not isNimIdentifier(result.name.s):
     rawMessage(errInvalidModuleName, result.name.s)
   
   result.info = newLineInfo(fileIdx, 1, 1)
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index ed28fea69..e15cdc86d 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -330,7 +330,7 @@ const
     errUsingNoSymbol: "'$1' is not a variable, constant or a proc name",
     errMacroBodyDependsOnGenericTypes: "the macro body cannot be compiled, " &
                                        "because the parameter '$1' has a generic type",
-    errDestructorNotGenericEnough: "Destructor signarue is too specific. " &
+    errDestructorNotGenericEnough: "Destructor signature is too specific. " &
                                    "A destructor must be associated will all instantiations of a generic type",
     errInlineIteratorsAsProcParams: "inline iterators can be used as parameters only for " &
                                     "templates, macros and other inline iterators",
@@ -443,7 +443,7 @@ type
   TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
   TNoteKinds* = set[TNoteKind]
 
-  TFileInfo*{.final.} = object 
+  TFileInfo* = object 
     fullPath: string           # This is a canonical full filesystem path
     projPath*: string          # This is relative to the project's root
     shortName*: string         # short name of the module
@@ -458,7 +458,7 @@ type
                                # and parsed; usually 'nil' but is used
                                # for 'nimsuggest'
 
-  TLineInfo*{.final.} = object # This is designed to be as small as possible,
+  TLineInfo* = object          # This is designed to be as small as possible,
                                # because it is used
                                # in syntax nodes. We save space here by using 
                                # two int16 and an int32.
@@ -493,7 +493,7 @@ proc toCChar*(c: char): string =
 
 proc makeCString*(s: string): PRope =
   # BUGFIX: We have to split long strings into many ropes. Otherwise
-  # this could trigger an InternalError(). See the ropes module for
+  # this could trigger an internalError(). See the ropes module for
   # further information.
   const 
     MaxLineLength = 64
@@ -696,7 +696,9 @@ proc msgWriteln*(s: string) =
 
   #if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
 
-  if optStdout in gGlobalOptions:
+  if not isNil(writelnHook):
+    writelnHook(s)
+  elif optStdout in gGlobalOptions:
     if eStdErr in errorOutputs: writeln(stderr, s)
   else:
     if eStdOut in errorOutputs: writeln(stdout, s)
@@ -720,7 +722,7 @@ type
 proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
   template quit =
     if defined(debug) or gVerbosity >= 3 or msg == errInternal:
-      if stackTraceAvailable():
+      if stackTraceAvailable() and isNil(writelnHook):
         writeStackTrace()
       else:
         msgWriteln("No stack traceback available\nTo create a stacktrace, rerun compilation with ./koch temp " & options.command & " <file>")
@@ -782,7 +784,7 @@ proc rawMessage*(msg: TMsgKind, arg: string) =
 proc writeSurroundingSrc(info: TLineInfo) =
   const indent = "  "
   msgWriteln(indent & info.sourceLine.ropeToStr)
-  msgWriteln(indent & repeatChar(info.col, ' ') & '^')
+  msgWriteln(indent & spaces(info.col) & '^')
 
 proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string =
   let frmt = case msg
diff --git a/compiler/nim.nim b/compiler/nim.nim
index 215f1986e..b8ba2c6da 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -61,6 +61,8 @@ proc handleCmdLine() =
         if gCmd == cmdRun:
           tccgen.run(commands.arguments)
       if optRun in gGlobalOptions:
+        if gProjectName == "-":
+          gProjectFull = "stdinfile"
         if gCmd == cmdCompileToJS:
           var ex: string
           if options.outFile.len > 0:
diff --git a/compiler/nimlexbase.nim b/compiler/nimlexbase.nim
index e18e1c22a..f5db5ca4f 100644
--- a/compiler/nimlexbase.nim
+++ b/compiler/nimlexbase.nim
@@ -166,4 +166,4 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
     inc(i)
   result.add("\n")
   if marker: 
-    result.add(repeatChar(getColNumber(L, L.bufpos)) & '^' & "\n")
+    result.add(spaces(getColNumber(L, L.bufpos)) & '^' & "\n")
diff --git a/compiler/options.nim b/compiler/options.nim
index d6d9389f5..1b4a624ab 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -283,19 +283,19 @@ when noTimeMachine:
       var p = startProcess("/usr/bin/tmutil", args = ["addexclusion", dir])
       discard p.waitForExit
       p.close
-    except E_Base, EOS:
+    except Exception:
       discard
 
-proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string = 
+proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
   var (head, tail) = splitPath(f)
   #if len(head) > 0: head = removeTrailingDirSep(shortenDir(head & dirSep))
   var subdir = getGeneratedPath() # / head
   if createSubDir:
-    try: 
+    try:
       createDir(subdir)
       when noTimeMachine:
        excludeDirFromTimeMachine(subdir)
-    except OSError: 
+    except OSError:
       writeln(stdout, "cannot create directory: " & subdir)
       quit(1)
   result = joinPath(subdir, tail)
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 8fbf033d8..9e4d45cd2 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -865,6 +865,7 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
   #|     [' optInd  (identColonEquals (comma/semicolon)?)*  optPar ']'
   #| extTupleDecl = 'tuple'
   #|     COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
+  #| tupleClass = 'tuple'
   result = newNodeP(nkTupleTy, p)
   getTok(p)
   if p.tok.tokType == tkBracketLe:
@@ -894,6 +895,8 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
             parMessage(p, errIdentifierExpected, p.tok)
             break
           if not sameInd(p): break
+  else:
+    result = newNodeP(nkTupleClassTy, p)
 
 proc parseParamList(p: var TParser, retColon = true): PNode =
   #| paramList = '(' declColonEquals ^* (comma/semicolon) ')'
diff --git a/compiler/passes.nim b/compiler/passes.nim
index f9c3d75f9..96088bd88 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -170,7 +170,11 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
     openPasses(a, module)
     if stream == nil: 
       let filename = fileIdx.toFullPathConsiderDirty
-      s = llStreamOpen(filename, fmRead)
+      if module.name.s == "-":
+        module.name.s = "stdinfile"
+        s = llStreamOpen(stdin)
+      else:
+        s = llStreamOpen(filename, fmRead)
       if s == nil: 
         rawMessage(errCannotOpenFile, filename)
         return
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 204bfbf94..ccf3837ed 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -92,7 +92,7 @@ proc addTok(g: var TSrcGen, kind: TTokType, s: string) =
 
 proc addPendingNL(g: var TSrcGen) = 
   if g.pendingNL >= 0: 
-    addTok(g, tkSpaces, "\n" & repeatChar(g.pendingNL))
+    addTok(g, tkSpaces, "\n" & spaces(g.pendingNL))
     g.lineLen = g.pendingNL
     g.pendingNL = - 1
 
@@ -190,7 +190,7 @@ proc putComment(g: var TSrcGen, s: string) =
       if not isCode and (g.lineLen + (j - i) > MaxLineLen): 
         put(g, tkComment, com)
         optNL(g, ind)
-        com = '#' & repeatChar(comIndent)
+        com = '#' & spaces(comIndent)
       while s[i] > ' ': 
         add(com, s[i])
         inc(i)
@@ -280,7 +280,7 @@ proc gcom(g: var TSrcGen, n: PNode) =
         (g.lineLen < LineCommentColumn): 
       var ml = maxLineLength(n.comment)
       if ml + LineCommentColumn <= MaxLineLen: 
-        put(g, tkSpaces, repeatChar(LineCommentColumn - g.lineLen))
+        put(g, tkSpaces, spaces(LineCommentColumn - g.lineLen))
     putComment(g, n.comment)  #assert(g.comStack[high(g.comStack)] = n);
   
 proc gcoms(g: var TSrcGen) = 
@@ -395,6 +395,7 @@ proc lsub(n: PNode): int =
   of nkClosedSymChoice, nkOpenSymChoice: 
     result = lsons(n) + len("()") + sonsLen(n) - 1
   of nkTupleTy: result = lcomma(n) + len("tuple[]")
+  of nkTupleClassTy: result = len("tuple")
   of nkDotExpr: result = lsons(n) + 1
   of nkBind: result = lsons(n) + len("bind_")
   of nkBindStmt: result = lcomma(n) + len("bind_")
@@ -1292,10 +1293,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
       gsub(g, n.sons[0])
   of nkTupleTy: 
     put(g, tkTuple, "tuple")
-    if sonsLen(n) > 0:
-      put(g, tkBracketLe, "[")
-      gcomma(g, n)
-      put(g, tkBracketRi, "]")
+    put(g, tkBracketLe, "[")
+    gcomma(g, n)
+    put(g, tkBracketRi, "]")
+  of nkTupleClassTy:
+    put(g, tkTuple, "tuple")
   of nkMetaNode_Obsolete:
     put(g, tkParLe, "(META|")
     gsub(g, n.sons[0])
diff --git a/compiler/sem.nim b/compiler/sem.nim
index a90948245..36c0342cd 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -65,8 +65,8 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
         echo "passing to safeSemExpr: ", renderTree(n)
       discard safeSemExpr(c, n)
 
-proc typeMismatch(n: PNode, formal, actual: PType) = 
-  if formal.kind != tyError and actual.kind != tyError: 
+proc typeMismatch(n: PNode, formal, actual: PType) =
+  if formal.kind != tyError and actual.kind != tyError:
     localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
         typeToString(actual) & ") " &
         `%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
@@ -113,7 +113,7 @@ proc commonType*(x, y: PType): PType =
     else:
       result = newType(tyTypeDesc, a.owner)
       rawAddSon(result, newType(tyNone, a.owner))
-  elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and 
+  elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and
       a.kind == b.kind:
     # check for seq[empty] vs. seq[int]
     let idx = ord(b.kind in {tyArray, tyArrayConstr})
@@ -163,7 +163,7 @@ proc commonType*(x, y: PType): PType =
         result = newType(k, r.owner)
         result.addSonSkipIntLit(r)
 
-proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = 
+proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
   result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info)
 
 proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
@@ -182,7 +182,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
                  allowed: TSymFlags): PSym
   # identifier with visability
-proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, 
+proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
                         allowed: TSymFlags): PSym
 proc semStmtScope(c: PContext, n: PNode): PNode
 
@@ -190,7 +190,7 @@ proc typeAllowedCheck(info: TLineInfo; typ: PType; kind: TSymKind) =
   let t = typeAllowed(typ, kind)
   if t != nil:
     if t == typ: localError(info, "invalid type: '" & typeToString(typ) & "'")
-    else: localError(info, "invalid type: '" & typeToString(t) & 
+    else: localError(info, "invalid type: '" & typeToString(t) &
                            "' in this context: '" & typeToString(typ) & "'")
 
 proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
@@ -226,7 +226,7 @@ when false:
         result = newSymNode(getSysSym"void")
       else:
         result.typ = makeTypeDesc(c, result.typ)
-    
+
     result.handleIsOperator = proc (n: PNode): PNode =
       result = isOpImpl(c, n)
 
@@ -248,7 +248,7 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
     if result == nil:
       result = arg
       # for 'tcnstseq' we support [] to become 'seq'
-      if eOrig.typ.skipTypes(abstractInst).kind == tySequence and 
+      if eOrig.typ.skipTypes(abstractInst).kind == tySequence and
          arg.typ.skipTypes(abstractInst).kind == tyArrayConstr:
         arg.typ = eOrig.typ
 
@@ -320,7 +320,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
   else:
     case s.typ.sons[0].kind
     of tyExpr:
-      # BUGFIX: we cannot expect a type here, because module aliases would not 
+      # BUGFIX: we cannot expect a type here, because module aliases would not
       # work then (see the ``tmodulealias`` test)
       # semExprWithType(c, result)
       result = semExpr(c, result, flags)
@@ -355,18 +355,18 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
     result = semAfterMacroCall(c, result, sym, flags)
   popInfoContext()
 
-proc forceBool(c: PContext, n: PNode): PNode = 
+proc forceBool(c: PContext, n: PNode): PNode =
   result = fitNode(c, getSysType(tyBool), n)
   if result == nil: result = n
 
-proc semConstBoolExpr(c: PContext, n: PNode): PNode = 
+proc semConstBoolExpr(c: PContext, n: PNode): PNode =
   let nn = semExprWithType(c, n)
   result = fitNode(c, getSysType(tyBool), nn)
   if result == nil:
     localError(n.info, errConstExprExpected)
     return nn
   result = getConstExpr(c.module, result)
-  if result == nil: 
+  if result == nil:
     localError(n.info, errConstExprExpected)
     result = nn
 
@@ -403,9 +403,9 @@ proc myOpen(module: PSym): PPassContext =
   pushOwner(c.module)
   c.importTable = openScope(c)
   c.importTable.addSym(module) # a module knows itself
-  if sfSystemModule in module.flags: 
+  if sfSystemModule in module.flags:
     magicsys.systemModule = module # set global variable!
-  else: 
+  else:
     c.importTable.addSym magicsys.systemModule # import the "System" identifier
     importAllSymbols(c, magicsys.systemModule)
   c.topLevelScope = openScope(c)
@@ -415,13 +415,13 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
   result = myOpen(module)
   for m in items(rd.methods): methodDef(m, true)
 
-proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
+proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
   result = semStmt(c, n)
   # BUGFIX: process newly generated generics here, not at the end!
   if c.lastGenericIdx < c.generics.len:
     var a = newNodeI(nkStmtList, n.info)
     addCodeForGenerics(c, a)
-    if sonsLen(a) > 0: 
+    if sonsLen(a) > 0:
       # a generic has been added to `a`:
       if result.kind != nkEmpty: addSon(a, result)
       result = a
@@ -429,17 +429,17 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
   if gCmd == cmdInteractive and not isEmptyType(result.typ):
     result = buildEchoStmt(c, result)
   result = transformStmt(c.module, result)
-    
-proc recoverContext(c: PContext) = 
+
+proc recoverContext(c: PContext) =
   # clean up in case of a semantic error: We clean up the stacks, etc. This is
-  # faster than wrapping every stack operation in a 'try finally' block and 
+  # faster than wrapping every stack operation in a 'try finally' block and
   # requires far less code.
   c.currentScope = c.topLevelScope
   while getCurrOwner().kind != skModule: popOwner()
   while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
 
-proc myProcess(context: PPassContext, n: PNode): PNode = 
-  var c = PContext(context)    
+proc myProcess(context: PPassContext, n: PNode): PNode =
+  var c = PContext(context)
   # no need for an expensive 'try' if we stop after the first error anyway:
   if msgs.gErrorMax <= 1:
     result = semStmtAndGenerateGenerics(c, n)
@@ -455,8 +455,8 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
       if getCurrentException() of ESuggestDone: result = nil
       else: result = ast.emptyNode
       #if gCmd == cmdIdeTools: findSuggest(c, n)
-    
-proc myClose(context: PPassContext, n: PNode): PNode = 
+
+proc myClose(context: PPassContext, n: PNode): PNode =
   var c = PContext(context)
   closeScope(c)         # close module's scope
   rawCloseScope(c)      # imported symbols; don't check for unused ones!
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 9077f34e9..647e75b3a 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -7,16 +7,16 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements semantic checking for calls. 
+## This module implements semantic checking for calls.
 # included from sem.nim
 
 proc sameMethodDispatcher(a, b: PSym): bool =
   result = false
-  if a.kind == skMethod and b.kind == skMethod: 
+  if a.kind == skMethod and b.kind == skMethod:
     var aa = lastSon(a.ast)
     var bb = lastSon(b.ast)
     if aa.kind == nkSym and bb.kind == nkSym:
-      if aa.sym == bb.sym: 
+      if aa.sym == bb.sym:
         result = true
     else:
       discard
@@ -31,7 +31,7 @@ proc sameMethodDispatcher(a, b: PSym): bool =
       # to avoid subtle problems, the call remains ambiguous and needs to
       # be disambiguated by the programmer; this way the right generic is
       # instantiated.
-  
+
 proc determineType(c: PContext, s: PSym)
 
 proc pickBestCandidate(c: PContext, headSymbol: PNode,
@@ -41,67 +41,80 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
                        best, alt: var TCandidate,
                        errors: var CandidateErrors) =
   var o: TOverloadIter
-  var sym = initOverloadIter(o, c, headSymbol)
-  var symScope = o.lastOverloadScope
+  # thanks to the lazy semchecking for operands, we need to iterate over the
+  # symbol table *before* any call to 'initCandidate' which might invoke
+  # semExpr which might modify the symbol table in cases like
+  # 'init(a, 1, (var b = new(Type2); b))'.
+  var symx = initOverloadIter(o, c, headSymbol)
+  let symScope = o.lastOverloadScope
+
+  var syms: seq[tuple[a: PSym, b: int]] = @[]
+  while symx != nil:
+    if symx.kind in filter: syms.add((symx, o.lastOverloadScope))
+    symx = nextOverloadIter(o, c, headSymbol)
+  if syms.len == 0: return
 
   var z: TCandidate
-  
-  if sym == nil: return
-  initCandidate(c, best, sym, initialBinding, symScope)
-  initCandidate(c, alt, sym, initialBinding, symScope)
+  initCandidate(c, best, syms[0][0], initialBinding, symScope)
+  initCandidate(c, alt, syms[0][0], initialBinding, symScope)
   best.state = csNoMatch
-  
-  while sym != nil:
-    if sym.kind in filter:
-      determineType(c, sym)
-      initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
-      z.calleeSym = sym
-      matches(c, n, orig, z)
-      if errors != nil:
-        errors.safeAdd(sym)
-        if z.errors != nil:
-          for err in z.errors:
-            errors.add(err)
-      if z.state == csMatch:
-        # little hack so that iterators are preferred over everything else:
-        if sym.kind in skIterators: inc(z.exactMatches, 200)
-        case best.state
-        of csEmpty, csNoMatch: best = z
-        of csMatch:
-          var cmp = cmpCandidates(best, z)
-          if cmp < 0: best = z   # x is better than the best so far
-          elif cmp == 0: alt = z # x is as good as the best so far
-          else: discard
-        #if sym.name.s == "*" and (n.info ?? "temp5.nim"):
-        #  echo "Matches ", n.info, " ", typeToString(sym.typ)
-        #  debug sym
-        #  writeMatches(z)
-    sym = nextOverloadIter(o, c, headSymbol)
+
+  for i in 0 .. <syms.len:
+    let sym = syms[i][0]
+    determineType(c, sym)
+    initCandidate(c, z, sym, initialBinding, syms[i][1])
+    z.calleeSym = sym
+
+    #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
+    #  gDebug = true
+    matches(c, n, orig, z)
+    if errors != nil:
+      errors.safeAdd(sym)
+      if z.errors != nil:
+        for err in z.errors:
+          errors.add(err)
+    if z.state == csMatch:
+      # little hack so that iterators are preferred over everything else:
+      if sym.kind in skIterators: inc(z.exactMatches, 200)
+      case best.state
+      of csEmpty, csNoMatch: best = z
+      of csMatch:
+        var cmp = cmpCandidates(best, z)
+        if cmp < 0: best = z   # x is better than the best so far
+        elif cmp == 0: alt = z # x is as good as the best so far
+        else: discard
+      #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
+      #  echo "Matches ", n.info, " ", typeToString(sym.typ)
+      #  debug sym
+      #  writeMatches(z)
+      #  for i in 1 .. <len(z.call):
+      #    z.call[i].typ.debug
+      #  quit 1
 
 proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
   # Gives a detailed error message; this is separated from semOverloadedCall,
   # as semOverlodedCall is already pretty slow (and we need this information
   # only in case of an error).
-  if c.inCompilesContext > 0: 
+  if c.inCompilesContext > 0:
     # fail fast:
     globalError(n.info, errTypeMismatch, "")
   if errors.isNil or errors.len == 0:
     localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
     return
 
-  # to avoid confusing errors like: 
+  # to avoid confusing errors like:
   #   got (SslPtr, SocketHandle)
-  #   but expected one of: 
+  #   but expected one of:
   #   openssl.SSL_set_fd(ssl: SslPtr, fd: SocketHandle): cint
   # we do a pre-analysis. If all types produce the same string, we will add
   # module information.
   let proto = describeArgs(c, n, 1, preferName)
-  
+
   var prefer = preferName
   for err in errors:
     var errProto = ""
     let n = err.typ.n
-    for i in countup(1, n.len - 1): 
+    for i in countup(1, n.len - 1):
       var p = n.sons[i]
       if p.kind == nkSym:
         add(errProto, typeToString(p.sym.typ, preferName))
@@ -153,9 +166,9 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
 
     n.sons.insert(hiddenArg, 1)
     orig.sons.insert(hiddenArg, 1)
-    
+
     pickBest(f)
- 
+
     if result.state != csMatch:
       n.sons.delete(1)
       orig.sons.delete(1)
@@ -173,7 +186,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
       # we are going to try multiple variants
       n.sons[0..1] = [nil, n[1], calleeName]
       orig.sons[0..1] = [nil, orig[1], calleeName]
-      
+
       template tryOp(x) =
         let op = newIdentNode(getIdent(x), n.info)
         n.sons[0] = op
@@ -182,7 +195,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
 
       if nfExplicitCall in n.flags:
         tryOp ".()"
-   
+
       if result.state in {csEmpty, csNoMatch}:
         tryOp "."
 
@@ -193,7 +206,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
       n.sons[0..1] = [callOp, n[1], calleeName]
       orig.sons[0..1] = [callOp, orig[1], calleeName]
       pickBest(callOp)
-   
+
     if overloadsState == csEmpty and result.state == csEmpty:
       localError(n.info, errUndeclaredIdentifier, considerQuotedIdent(f).s)
       return
@@ -218,7 +231,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
     internalAssert result.state == csMatch
     #writeMatches(result)
     #writeMatches(alt)
-    if c.inCompilesContext > 0: 
+    if c.inCompilesContext > 0:
       # quick error message for performance of 'compiles' built-in:
       globalError(n.info, errGenerated, "ambiguous call")
     elif gErrorCounter == 0:
@@ -248,7 +261,7 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
     for i in 1 .. <n.len:
       instGenericConvertersArg(c, n.sons[i], x)
 
-proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode = 
+proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
   var m: TCandidate
   initCandidate(c, m, f)
   result = paramTypesMatch(m, f, a, arg, nil)
@@ -319,7 +332,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
       # get rid of the deref again for a better error message:
       n.sons[1] = n.sons[1].sons[0]
       notFoundError(c, n, errors)
-  else: 
+  else:
     notFoundError(c, n, errors)
   # else: result = errorNode(c, n)
 
@@ -335,7 +348,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
   styleCheckUse(n.info, s)
   result = newSymNode(newInst, n.info)
 
-proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
+proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
   assert n.kind == nkBracketExpr
   for i in 1..sonsLen(n)-1:
     n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
@@ -355,11 +368,11 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     # XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
     # It's good enough for now.
     result = newNodeI(a.kind, n.info)
-    for i in countup(0, len(a)-1): 
+    for i in countup(0, len(a)-1):
       var candidate = a.sons[i].sym
       if candidate.kind in {skProc, skMethod, skConverter,
                             skIterator, skClosureIterator}:
-        # it suffices that the candidate has the proper number of generic 
+        # it suffices that the candidate has the proper number of generic
         # type parameters:
         if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
           result.add(explicitGenericSym(c, n, candidate))
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 89469ae50..3d2ba2568 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -24,7 +24,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   # same as 'semExprWithType' but doesn't check for proc vars
   result = semExpr(c, n, flags + {efOperand})
-  if result.kind == nkEmpty: 
+  if result.kind == nkEmpty:
     # do not produce another redundant error message:
     #raiseRecoverableError("")
     result = errorNode(c, n)
@@ -34,19 +34,19 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   elif efWantStmt in flags:
     result.typ = newTypeS(tyEmpty, c)
   else:
-    localError(n.info, errExprXHasNoType, 
+    localError(n.info, errExprXHasNoType,
                renderTree(result, {renderNoComments}))
     result.typ = errorType(c)
 
 proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   result = semExpr(c, n, flags+{efWantValue})
-  if result.isNil or result.kind == nkEmpty: 
+  if result.isNil or result.kind == nkEmpty:
     # do not produce another redundant error message:
     #raiseRecoverableError("")
     result = errorNode(c, n)
   if result.typ == nil or result.typ == enforceVoidContext:
     # we cannot check for 'void' in macros ...
-    localError(n.info, errExprXHasNoType, 
+    localError(n.info, errExprXHasNoType,
                renderTree(result, {renderNoComments}))
     result.typ = errorType(c)
   else:
@@ -61,7 +61,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # do not produce another redundant error message:
     result = errorNode(c, n)
   if result.typ == nil:
-    localError(n.info, errExprXHasNoType, 
+    localError(n.info, errExprXHasNoType,
                renderTree(result, {renderNoComments}))
     result.typ = errorType(c)
   else:
@@ -70,19 +70,19 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
 
 proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
   result = symChoice(c, n, s, scClosed)
-  
+
 proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
   result = copyTree(s.ast)
   result.typ = s.typ
   result.info = n.info
-  
-proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = 
+
+proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   case s.kind
   of skConst:
     markUsed(n.info, s)
     styleCheckUse(n.info, s)
     case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
-    of  tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, 
+    of  tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
         tyTuple, tySet, tyUInt..tyUInt64:
       if s.magic == mNone: result = inlineConst(n, s)
       else: result = newSymNode(s, n.info)
@@ -167,7 +167,7 @@ proc checkConversionBetweenObjects(castDest, src: PType): TConvStatus =
     else:
       convOK
 
-const 
+const
   IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
 
 proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
@@ -201,10 +201,10 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
 
 proc isCastable(dst, src: PType): bool =
   ## Checks whether the source type can be casted to the destination type.
-  ## Casting is very unrestrictive; casts are allowed as long as 
+  ## Casting is very unrestrictive; casts are allowed as long as
   ## castDest.size >= src.size, and typeAllowed(dst, skParam)
   #const
-  #  castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString, 
+  #  castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString,
   #                       tySequence, tyPointer, tyNil, tyOpenArray,
   #                       tyProc, tySet, tyEnum, tyBool, tyChar}
   if skipTypes(dst, abstractInst-{tyOpenArray}).kind == tyOpenArray:
@@ -213,7 +213,7 @@ proc isCastable(dst, src: PType): bool =
 
   dstSize = computeSize(dst)
   srcSize = computeSize(src)
-  if dstSize < 0: 
+  if dstSize < 0:
     result = false
   elif srcSize < 0:
     result = false
@@ -225,7 +225,7 @@ proc isCastable(dst, src: PType): bool =
         (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
   if result and src.kind == tyNil:
     result = dst.size <= platform.ptrSize
-  
+
 proc isSymChoice(n: PNode): bool {.inline.} =
   result = n.kind in nkSymChoices
 
@@ -249,7 +249,7 @@ proc semConv(c: PContext, n: PNode): PNode =
   maybeLiftType(targetType, c, n[0].info)
   result.addSon copyTree(n.sons[0])
   var op = semExprWithType(c, n.sons[1])
-  
+
   if targetType.isMetaType:
     let final = inferWithMetatype(c, targetType, op, true)
     result.addSon final
@@ -258,7 +258,7 @@ proc semConv(c: PContext, n: PNode): PNode =
 
   result.typ = targetType
   addSon(result, op)
-  
+
   if not isSymChoice(op):
     let status = checkConvertible(c, result.typ, op.typ)
     case status
@@ -286,7 +286,7 @@ proc semConv(c: PContext, n: PNode): PNode =
         return it
     localError(n.info, errUseQualifier, op.sons[0].sym.name.s)
 
-proc semCast(c: PContext, n: PNode): PNode = 
+proc semCast(c: PContext, n: PNode): PNode =
   ## Semantically analyze a casting ("cast[type](param)")
   if optSafeCode in gGlobalOptions: localError(n.info, errCastNotInSafeMode)
   #incl(c.p.owner.flags, sfSideEffect)
@@ -295,25 +295,25 @@ proc semCast(c: PContext, n: PNode): PNode =
   result.typ = semTypeNode(c, n.sons[0], nil)
   addSon(result, copyTree(n.sons[0]))
   addSon(result, semExprWithType(c, n.sons[1]))
-  if not isCastable(result.typ, result.sons[1].typ): 
-    localError(result.info, errExprCannotBeCastedToX, 
+  if not isCastable(result.typ, result.sons[1].typ):
+    localError(result.info, errExprCannotBeCastedToX,
                typeToString(result.typ))
 
-proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = 
-  const 
+proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
+  const
     opToStr: array[mLow..mHigh, string] = ["low", "high"]
-  if sonsLen(n) != 2: 
+  if sonsLen(n) != 2:
     localError(n.info, errXExpectsTypeOrValue, opToStr[m])
-  else: 
+  else:
     n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
     var typ = skipTypes(n.sons[1].typ, abstractVarRange +
                                        {tyTypeDesc, tyFieldAccessor})
     case typ.kind
-    of tySequence, tyString, tyCString, tyOpenArray, tyVarargs: 
+    of tySequence, tyString, tyCString, tyOpenArray, tyVarargs:
       n.typ = getSysType(tyInt)
-    of tyArrayConstr, tyArray: 
+    of tyArrayConstr, tyArray:
       n.typ = typ.sons[0] # indextype
-    of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: 
+    of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32:
       # do not skip the range!
       n.typ = n.sons[1].typ.skipTypes(abstractVar + {tyFieldAccessor})
     of tyGenericParam:
@@ -334,8 +334,8 @@ proc semSizeof(c: PContext, n: PNode): PNode =
   n.typ = getSysType(tyInt)
   result = n
 
-proc semOf(c: PContext, n: PNode): PNode = 
-  if sonsLen(n) == 3: 
+proc semOf(c: PContext, n: PNode): PNode =
+  if sonsLen(n) == 3:
     n.sons[1] = semExprWithType(c, n.sons[1])
     n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
     #restoreOldStyleType(n.sons[1])
@@ -373,7 +373,7 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
   internalAssert n.sonsLen == 3 and
     n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
     n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
-  
+
   let t1 = n[1].typ.skipTypes({tyTypeDesc, tyFieldAccessor})
 
   if n[2].kind in {nkStrLit..nkTripleStrLit}:
@@ -381,7 +381,7 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
     of "closure":
       let t = skipTypes(t1, abstractRange)
       result = newIntNode(nkIntLit, ord(t.kind == tyProc and
-                                        t.callConv == ccClosure and 
+                                        t.callConv == ccClosure and
                                         tfIterator notin t.flags))
     else: discard
   else:
@@ -400,7 +400,7 @@ proc semIs(c: PContext, n: PNode): PNode =
 
   result = n
   n.typ = getSysType(tyBool)
- 
+
   n.sons[1] = semExprWithType(c, n[1], {efDetermineType, efWantIterator})
   if n[2].kind notin {nkStrLit..nkTripleStrLit}:
     let t2 = semTypeNode(c, n[2], nil)
@@ -420,7 +420,7 @@ proc semOpAux(c: PContext, n: PNode) =
   const flags = {efDetermineType}
   for i in countup(1, n.sonsLen-1):
     var a = n.sons[i]
-    if a.kind == nkExprEqExpr and sonsLen(a) == 2: 
+    if a.kind == nkExprEqExpr and sonsLen(a) == 2:
       var info = a.sons[0].info
       a.sons[0] = newIdentNode(considerQuotedIdent(a.sons[0]), info)
       a.sons[1] = semExprWithType(c, a.sons[1], flags)
@@ -428,7 +428,7 @@ proc semOpAux(c: PContext, n: PNode) =
     else:
       n.sons[i] = semExprWithType(c, a, flags)
 
-proc overloadedCallOpr(c: PContext, n: PNode): PNode = 
+proc overloadedCallOpr(c: PContext, n: PNode): PNode =
   # quick check if there is *any* () operator overloaded:
   var par = getIdent("()")
   if searchInScopes(c, par) == nil:
@@ -457,7 +457,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
           return
         if tup.n != nil:
           var f = getSymFromList(newType.n, m.sym.name)
-          if f == nil: 
+          if f == nil:
             internalError(m.info, "changeType(): invalid identifier")
             return
           changeType(n.sons[i].sons[1], f.typ, check)
@@ -481,10 +481,10 @@ proc changeType(n: PNode, newType: PType, check: bool) =
   else: discard
   n.typ = newType
 
-proc arrayConstrType(c: PContext, n: PNode): PType = 
+proc arrayConstrType(c: PContext, n: PNode): PType =
   var typ = newTypeS(tyArrayConstr, c)
   rawAddSon(typ, nil)     # index type
-  if sonsLen(n) == 0: 
+  if sonsLen(n) == 0:
     rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
   else:
     var x = n.sons[0]
@@ -494,35 +494,35 @@ proc arrayConstrType(c: PContext, n: PNode): PType =
   typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
   result = typ
 
-proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = 
+proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = newNodeI(nkBracket, n.info)
   result.typ = newTypeS(tyArrayConstr, c)
   rawAddSon(result.typ, nil)     # index type
-  if sonsLen(n) == 0: 
+  if sonsLen(n) == 0:
     rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
   else:
     var x = n.sons[0]
     var lastIndex: BiggestInt = 0
     var indexType = getSysType(tyInt)
-    if x.kind == nkExprColonExpr and sonsLen(x) == 2: 
+    if x.kind == nkExprColonExpr and sonsLen(x) == 2:
       var idx = semConstExpr(c, x.sons[0])
       lastIndex = getOrdValue(idx)
       indexType = idx.typ
       x = x.sons[1]
-    
+
     let yy = semExprWithType(c, x)
     var typ = yy.typ
     addSon(result, yy)
     #var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
-    for i in countup(1, sonsLen(n) - 1): 
+    for i in countup(1, sonsLen(n) - 1):
       x = n.sons[i]
-      if x.kind == nkExprColonExpr and sonsLen(x) == 2: 
+      if x.kind == nkExprColonExpr and sonsLen(x) == 2:
         var idx = semConstExpr(c, x.sons[0])
         idx = fitNode(c, indexType, idx)
         if lastIndex+1 != getOrdValue(idx):
           localError(x.info, errInvalidOrderInArrayConstructor)
         x = x.sons[1]
-      
+
       let xx = semExprWithType(c, x, flags*{efAllowDestructor})
       result.add xx
       typ = commonType(typ, xx.typ)
@@ -534,21 +534,21 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
       result.sons[i] = fitNode(c, typ, result.sons[i])
   result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
 
-proc fixAbstractType(c: PContext, n: PNode) = 
+proc fixAbstractType(c: PContext, n: PNode) =
   # XXX finally rewrite that crap!
-  for i in countup(1, sonsLen(n) - 1): 
+  for i in countup(1, sonsLen(n) - 1):
     var it = n.sons[i]
     case it.kind
     of nkHiddenStdConv, nkHiddenSubConv:
       if it.sons[1].kind == nkBracket:
         it.sons[1].typ = arrayConstrType(c, it.sons[1])
         #it.sons[1] = semArrayConstr(c, it.sons[1])
-      if skipTypes(it.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: 
+      if skipTypes(it.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
         #if n.sons[0].kind == nkSym and IdentEq(n.sons[0].sym.name, "[]="):
         #  debug(n)
-        
+
         var s = skipTypes(it.sons[1].typ, abstractVar)
-        if s.kind == tyArrayConstr and s.sons[1].kind == tyEmpty: 
+        if s.kind == tyArrayConstr and s.sons[1].kind == tyEmpty:
           s = copyType(s, getCurrOwner(), false)
           skipTypes(s, abstractVar).sons[1] = elemType(
               skipTypes(it.typ, abstractVar))
@@ -558,32 +558,32 @@ proc fixAbstractType(c: PContext, n: PNode) =
           skipTypes(s, abstractVar).sons[0] = elemType(
               skipTypes(it.typ, abstractVar))
           it.sons[1].typ = s
-          
+
       elif skipTypes(it.sons[1].typ, abstractVar).kind in
-          {tyNil, tyArrayConstr, tyTuple, tySet}: 
+          {tyNil, tyArrayConstr, tyTuple, tySet}:
         var s = skipTypes(it.typ, abstractVar)
         if s.kind != tyExpr:
           changeType(it.sons[1], s, check=true)
         n.sons[i] = it.sons[1]
-    of nkBracket: 
+    of nkBracket:
       # an implicitly constructed array (passed to an open array):
       n.sons[i] = semArrayConstr(c, it, {})
-    else: 
+    else:
       discard
-      #if (it.typ == nil): 
-      #  InternalError(it.info, "fixAbstractType: " & renderTree(it))  
-  
-proc skipObjConv(n: PNode): PNode = 
+      #if (it.typ == nil):
+      #  InternalError(it.info, "fixAbstractType: " & renderTree(it))
+
+proc skipObjConv(n: PNode): PNode =
   case n.kind
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv: 
-    if skipTypes(n.sons[1].typ, abstractPtrs).kind in {tyTuple, tyObject}: 
+  of nkHiddenStdConv, nkHiddenSubConv, nkConv:
+    if skipTypes(n.sons[1].typ, abstractPtrs).kind in {tyTuple, tyObject}:
       result = n.sons[1]
-    else: 
+    else:
       result = n
   of nkObjUpConv, nkObjDownConv: result = n.sons[0]
   else: result = n
 
-proc isAssignable(c: PContext, n: PNode): TAssignableResult = 
+proc isAssignable(c: PContext, n: PNode): TAssignableResult =
   result = parampatterns.isAssignable(c.p.owner, n)
 
 proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
@@ -597,49 +597,49 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
     if isAssignable(c, n) notin {arLValue, arLocalLValue}:
       localError(n.info, errVarForOutParamNeeded)
 
-proc analyseIfAddressTaken(c: PContext, n: PNode): PNode = 
+proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
   result = n
   case n.kind
   of nkSym:
     # n.sym.typ can be nil in 'check' mode ...
     if n.sym.typ != nil and
-        skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar: 
+        skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar:
       incl(n.sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
-  of nkDotExpr: 
+  of nkDotExpr:
     checkSonsLen(n, 2)
-    if n.sons[1].kind != nkSym: 
+    if n.sons[1].kind != nkSym:
       internalError(n.info, "analyseIfAddressTaken")
       return
-    if skipTypes(n.sons[1].sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar: 
+    if skipTypes(n.sons[1].sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar:
       incl(n.sons[1].sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
-  of nkBracketExpr: 
+  of nkBracketExpr:
     checkMinSonsLen(n, 1)
-    if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind != tyVar: 
+    if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind != tyVar:
       if n.sons[0].kind == nkSym: incl(n.sons[0].sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
-  else: 
+  else:
     result = newHiddenAddrTaken(c, n)
-  
-proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = 
+
+proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
   checkMinSonsLen(n, 1)
-  const 
-    FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, 
-      mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, 
+  const
+    FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl,
+      mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap,
       mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy}
-  
+
   # get the real type of the callee
   # it may be a proc var with a generic alias type, so we skip over them
   var t = n.sons[0].typ.skipTypes({tyGenericInst})
 
-  if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams: 
+  if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams:
     # BUGFIX: check for L-Value still needs to be done for the arguments!
     # note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
-    for i in countup(1, sonsLen(n) - 1): 
+    for i in countup(1, sonsLen(n) - 1):
       if i < sonsLen(t) and t.sons[i] != nil and
-          skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar: 
-        if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}: 
+          skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
+        if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}:
           if n.sons[i].kind != nkHiddenAddr:
             localError(n.sons[i].info, errVarForOutParamNeeded)
     return
@@ -653,14 +653,14 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
         skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
       if n.sons[i].kind != nkHiddenAddr:
         n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
-  
+
 include semmagic
 
 proc evalAtCompileTime(c: PContext, n: PNode): PNode =
   result = n
   if n.kind notin nkCallKinds or n.sons[0].kind != nkSym: return
   var callee = n.sons[0].sym
-  
+
   # constant folding that is necessary for correctness of semantic pass:
   if callee.magic != mNone and callee.magic in ctfeWhitelist and n.typ != nil:
     var call = newNodeIT(nkCall, n.info, n.typ)
@@ -678,7 +678,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
       if result.isNil: result = n
       else: return result
     result.typ = semfold.getIntervalType(callee.magic, call)
-  
+
   block maybeLabelAsStatic:
     # XXX: temporary work-around needed for tlateboundstatic.
     # This is certainly not correct, but it will get the job
@@ -696,15 +696,15 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
   # optimization pass: not necessary for correctness of the semantic pass
   if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
      {sfForward, sfImportc} * callee.flags == {} and n.typ != nil:
-    if sfCompileTime notin callee.flags and 
+    if sfCompileTime notin callee.flags and
         optImplicitStatic notin gOptions: return
 
     if callee.magic notin ctfeWhitelist: return
     if callee.kind notin {skProc, skConverter} or callee.isGenericRoutine:
       return
-    
+
     if n.typ != nil and typeAllowed(n.typ, skConst) != nil: return
-    
+
     var call = newNodeIT(nkCall, n.info, n.typ)
     call.add(n.sons[0])
     for i in 1 .. < n.len:
@@ -714,7 +714,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
     #echo "NOW evaluating at compile time: ", call.renderTree
     if sfCompileTime in callee.flags:
       result = evalStaticExpr(c.module, call, c.p.owner)
-      if result.isNil: 
+      if result.isNil:
         localError(n.info, errCannotInterpretNodeX, renderTree(call))
       else: result = fixupTypeAfterEval(c, result, n)
     else:
@@ -737,17 +737,17 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
                                      flags: TExprFlags): PNode =
   if flags*{efInTypeof, efWantIterator} != {}:
     # consider: 'for x in pReturningArray()' --> we don't want the restriction
-    # to 'skIterators' anymore; skIterators are preferred in sigmatch already 
+    # to 'skIterators' anymore; skIterators are preferred in sigmatch already
     # for typeof support.
     # for ``type(countup(1,3))``, see ``tests/ttoseq``.
     result = semOverloadedCall(c, n, nOrig,
       {skProc, skMethod, skConverter, skMacro, skTemplate}+skIterators)
   else:
-    result = semOverloadedCall(c, n, nOrig, 
+    result = semOverloadedCall(c, n, nOrig,
       {skProc, skMethod, skConverter, skMacro, skTemplate})
- 
+
   if result != nil:
-    if result.sons[0].kind != nkSym: 
+    if result.sons[0].kind != nkSym:
       internalError("semOverloadedCallAnalyseEffects")
       return
     let callee = result.sons[0].sym
@@ -759,7 +759,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
         # error correction, prevents endless for loop elimination in transf.
         # See bug #2051:
         result.sons[0] = newSymNode(errorSym(c, n))
-      if sfNoSideEffect notin callee.flags: 
+      if sfNoSideEffect notin callee.flags:
         if {sfImportc, sfSideEffect} * callee.flags != {}:
           incl(c.p.owner.flags, sfSideEffect)
 
@@ -808,11 +808,11 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
       else:
         var hasErrorType = false
         var msg = msgKindToString(errTypeMismatch)
-        for i in countup(1, sonsLen(n) - 1): 
+        for i in countup(1, sonsLen(n) - 1):
           if i > 1: add(msg, ", ")
           let nt = n.sons[i].typ
           add(msg, typeToString(nt))
-          if nt.kind == tyError: 
+          if nt.kind == tyError:
             hasErrorType = true
             break
         if not hasErrorType:
@@ -824,7 +824,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     else:
       result = m.call
       instGenericConvertersSons(c, result, m)
-    # we assume that a procedure that calls something indirectly 
+    # we assume that a procedure that calls something indirectly
     # has side-effects:
     if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
   elif t != nil and t.kind == tyTypeDesc:
@@ -834,7 +834,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     result = overloadedCallOpr(c, n)
     # Now that nkSym does not imply an iteration over the proc/iterator space,
     # the old ``prc`` (which is likely an nkIdent) has to be restored:
-    if result == nil: 
+    if result == nil:
       # XXX: hmm, what kind of symbols will end up here?
       # do we really need to try the overload resolution?
       n.sons[0] = prc
@@ -869,7 +869,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
   if c.inTypeClass == 0:
     result = evalAtCompileTime(c, result)
 
-proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = 
+proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # this seems to be a hotspot in the compiler!
   let nOrig = n.copyTree
   #semLazyOpAux(c, n)
@@ -877,7 +877,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   if result != nil: result = afterCallActions(c, result, nOrig, flags)
   else: result = errorNode(c, n)
 
-proc buildEchoStmt(c: PContext, n: PNode): PNode = 
+proc buildEchoStmt(c: PContext, n: PNode): PNode =
   # we MUST not check 'n' for semantics again here! But for now we give up:
   result = newNodeI(nkCall, n.info)
   var e = strTableGet(magicsys.systemModule.tab, getIdent"echo")
@@ -892,8 +892,8 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
 proc semExprNoType(c: PContext, n: PNode): PNode =
   result = semExpr(c, n, {efWantStmt})
   discardCheck(c, result)
-  
-proc isTypeExpr(n: PNode): bool = 
+
+proc isTypeExpr(n: PNode): bool =
   case n.kind
   of nkType, nkTypeOfExpr: result = true
   of nkSym: result = n.sym.kind == skType
@@ -904,24 +904,24 @@ proc createSetType(c: PContext; baseType: PType): PType =
   result = newTypeS(tySet, c)
   rawAddSon(result, baseType)
 
-proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent, 
-                                 check: var PNode): PSym = 
+proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
+                                 check: var PNode): PSym =
   # transform in a node that contains the runtime check for the
   # field, if it is in a case-part...
   result = nil
   case r.kind
-  of nkRecList: 
-    for i in countup(0, sonsLen(r) - 1): 
+  of nkRecList:
+    for i in countup(0, sonsLen(r) - 1):
       result = lookupInRecordAndBuildCheck(c, n, r.sons[i], field, check)
-      if result != nil: return 
-  of nkRecCase: 
+      if result != nil: return
+  of nkRecCase:
     checkMinSonsLen(r, 2)
     if (r.sons[0].kind != nkSym): illFormedAst(r)
     result = lookupInRecordAndBuildCheck(c, n, r.sons[0], field, check)
-    if result != nil: return 
+    if result != nil: return
     let setType = createSetType(c, r.sons[0].typ)
     var s = newNodeIT(nkCurly, r.info, setType)
-    for i in countup(1, sonsLen(r) - 1): 
+    for i in countup(1, sonsLen(r) - 1):
       var it = r.sons[i]
       case it.kind
       of nkOfBranch:
@@ -957,14 +957,14 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
           addSon(check, notExpr)
           return
       else: illFormedAst(it)
-  of nkSym: 
+  of nkSym:
     if r.sym.name.id == field.id: result = r.sym
   else: illFormedAst(n)
 
-proc makeDeref(n: PNode): PNode = 
+proc makeDeref(n: PNode): PNode =
   var t = skipTypes(n.typ, {tyGenericInst})
   result = n
-  if t.kind == tyVar: 
+  if t.kind == tyVar:
     result = newNodeIT(nkHiddenDeref, n.info, t.sons[0])
     addSon(result, n)
     t = skipTypes(t.sons[0], {tyGenericInst})
@@ -1079,7 +1079,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
           check.sons[0] = n
           check.typ = n.typ
           result = check
-  elif ty.kind == tyTuple and ty.n != nil: 
+  elif ty.kind == tyTuple and ty.n != nil:
     f = getSymFromList(ty.n, i)
     if f != nil:
       markUsed(n.sons[1].info, f)
@@ -1106,8 +1106,8 @@ proc dotTransformation(c: PContext, n: PNode): PNode =
     result.flags.incl nfDotField
     addSon(result, newIdentNode(i, n[1].info))
     addSon(result, copyTree(n[0]))
-  
-proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = 
+
+proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # this is difficult, because the '.' is used in many different contexts
   # in Nim. We first allow types in the semantic checking.
   result = builtinFieldAccess(c, n, flags)
@@ -1118,7 +1118,7 @@ proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode =
   result = newNodeI(nkCall, n.info)
   result.add(newIdentNode(ident, n.info))
   for i in 0 .. n.len-1: result.add(n[i])
-  
+
 proc semDeref(c: PContext, n: PNode): PNode =
   checkSonsLen(n, 1)
   n.sons[0] = semExprWithType(c, n.sons[0])
@@ -1127,12 +1127,12 @@ proc semDeref(c: PContext, n: PNode): PNode =
   case t.kind
   of tyRef, tyPtr: n.typ = t.lastSon
   else: result = nil
-  #GlobalError(n.sons[0].info, errCircumNeedsPointer) 
+  #GlobalError(n.sons[0].info, errCircumNeedsPointer)
 
 proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if not a built-in subscript operator; also called for the
   ## checking of assignments
-  if sonsLen(n) == 1: 
+  if sonsLen(n) == 1:
     var x = semDeref(c, n)
     if x == nil: return nil
     result = newNodeIT(nkDerefExpr, x.info, x.typ)
@@ -1142,12 +1142,12 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
   n.sons[0] = semExprWithType(c, n.sons[0])
   var arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
   case arr.kind
-  of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString, 
+  of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
      tyCString:
     if n.len != 2: return nil
     n.sons[0] = makeDeref(n.sons[0])
-    for i in countup(1, sonsLen(n) - 1): 
-      n.sons[i] = semExprWithType(c, n.sons[i], 
+    for i in countup(1, sonsLen(n) - 1):
+      n.sons[i] = semExprWithType(c, n.sons[i],
                                   flags*{efInTypeof, efDetermineType})
     var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
     var arg = indexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
@@ -1157,28 +1157,28 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
       result.typ = elemType(arr)
     #GlobalError(n.info, errIndexTypesDoNotMatch)
   of tyTypeDesc:
-    # The result so far is a tyTypeDesc bound 
+    # The result so far is a tyTypeDesc bound
     # a tyGenericBody. The line below will substitute
     # it with the instantiated type.
     result = n
     result.typ = makeTypeDesc(c, semTypeNode(c, n, nil))
     #result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
-  of tyTuple: 
+  of tyTuple:
     checkSonsLen(n, 2)
     n.sons[0] = makeDeref(n.sons[0])
     # [] operator for tuples requires constant expression:
     n.sons[1] = semConstExpr(c, n.sons[1])
     if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal}).kind in
-        {tyInt..tyInt64}: 
+        {tyInt..tyInt64}:
       var idx = getOrdValue(n.sons[1])
       if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)]
       else: localError(n.info, errInvalidIndexValueForTuple)
-    else: 
+    else:
       localError(n.info, errIndexTypesDoNotMatch)
     result = n
   else: discard
-  
-proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = 
+
+proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = semSubscript(c, n, flags)
   if result == nil:
     # overloaded [] operator:
@@ -1195,7 +1195,7 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
   result.flags.incl nfDotSetter
   let orig = newNode(nkCall, n.info, sons = @[setterId, aOrig[0], nOrig[1]])
   result = semOverloadedCallAnalyseEffects(c, result, orig, {})
-  
+
   if result != nil:
     result = afterCallActions(c, result, nOrig, {})
     #fixAbstractType(c, result)
@@ -1216,7 +1216,7 @@ proc takeImplicitAddr(c: PContext, n: PNode): PNode =
       localError(n.info, errExprHasNoAddress)
   result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
   result.add(n)
-  
+
 proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
   if le.kind == nkHiddenDeref:
     var x = le.sons[0]
@@ -1265,7 +1265,7 @@ proc semAsgn(c: PContext, n: PNode): PNode =
   # a = b # both are vars, means: a[] = b[]
   # a = b # b no 'var T' means: a = addr(b)
   var le = a.typ
-  if skipTypes(le, {tyGenericInst}).kind != tyVar and 
+  if skipTypes(le, {tyGenericInst}).kind != tyVar and
       isAssignable(c, a) == arNone:
     # Direct assignment to a discriminant is allowed!
     localError(a.info, errXCannotBeAssignedTo,
@@ -1275,7 +1275,7 @@ proc semAsgn(c: PContext, n: PNode): PNode =
       lhs = n.sons[0]
       lhsIsResult = lhs.kind == nkSym and lhs.sym.kind == skResult
     var
-      rhs = semExprWithType(c, n.sons[1], 
+      rhs = semExprWithType(c, n.sons[1],
         if lhsIsResult: {efAllowDestructor} else: {})
     if lhsIsResult:
       n.typ = enforceVoidContext
@@ -1300,13 +1300,13 @@ proc semReturn(c: PContext, n: PNode): PNode =
                         skClosureIterator}:
     if n.sons[0].kind != nkEmpty:
       # transform ``return expr`` to ``result = expr; return``
-      if c.p.resultSym != nil: 
+      if c.p.resultSym != nil:
         var a = newNodeI(nkAsgn, n.sons[0].info)
         addSon(a, newSymNode(c.p.resultSym))
         addSon(a, n.sons[0])
         n.sons[0] = semAsgn(c, a)
         # optimize away ``result = result``:
-        if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym: 
+        if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym:
           n.sons[0] = ast.emptyNode
       else:
         localError(n.info, errNoReturnTypeDeclared)
@@ -1315,7 +1315,7 @@ proc semReturn(c: PContext, n: PNode): PNode =
 
 proc semProcBody(c: PContext, n: PNode): PNode =
   openScope(c)
-  
+
   result = semExpr(c, n)
   if c.p.resultSym != nil and not isEmptyType(result.typ):
     # transform ``expr`` to ``result = expr``, but not if the expr is already
@@ -1339,7 +1339,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
       result = semAsgn(c, a)
   else:
     discardCheck(c, result)
-  
+
   if c.p.owner.kind notin {skMacro, skTemplate} and
      c.p.resultSym != nil and c.p.resultSym.typ.isMetaType:
     if isEmptyType(result.typ):
@@ -1362,14 +1362,14 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
       if e.kind == tyVar:
         if n.sons[0].kind == nkPar:
           n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
-        elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and 
+        elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
              n.sons[0].sons[1].kind == nkPar:
           var a = n.sons[0].sons[1]
           a.sons[i] = takeImplicitAddr(c, a.sons[i])
         else:
           localError(n.sons[0].info, errXExpected, "tuple constructor")
   else: discard
-  
+
 proc semYield(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
@@ -1387,14 +1387,14 @@ proc semYield(c: PContext, n: PNode): PNode =
       if adjustedRes.kind != tyExpr:
         n.sons[0] = fitNode(c, adjustedRes, n.sons[0])
       if n.sons[0].typ == nil: internalError(n.info, "semYield")
-      
+
       if resultTypeIsInferrable(adjustedRes):
         let inferred = n.sons[0].typ
         if restype.kind == tyIter:
           restype.sons[0] = inferred
         else:
           iterType.sons[0] = inferred
-      
+
       semYieldVarResult(c, n, adjustedRes)
     else:
       localError(n.info, errCannotReturnExpr)
@@ -1402,25 +1402,25 @@ proc semYield(c: PContext, n: PNode): PNode =
     localError(n.info, errGenerated, "yield statement must yield a value")
 
 proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
-  if onlyCurrentScope: 
+  if onlyCurrentScope:
     result = localSearchInScope(c, i)
-  else: 
+  else:
     result = searchInScopes(c, i) # no need for stub loading
 
-proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = 
+proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
   case n.kind
-  of nkIdent: 
+  of nkIdent:
     result = lookUpForDefined(c, n.ident, onlyCurrentScope)
   of nkDotExpr:
     result = nil
-    if onlyCurrentScope: return 
+    if onlyCurrentScope: return
     checkSonsLen(n, 2)
     var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope)
     if m != nil and m.kind == skModule:
       let ident = considerQuotedIdent(n[1])
       if m == c.module:
         result = strTableGet(c.topLevelScope.symbols, ident)
-      else: 
+      else:
         result = strTableGet(m.tab, ident)
   of nkAccQuoted:
     result = lookUpForDefined(c, considerQuotedIdent(n), onlyCurrentScope)
@@ -1432,7 +1432,7 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
     localError(n.info, errIdentifierExpected, renderTree(n))
     result = nil
 
-proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = 
+proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
   checkSonsLen(n, 2)
   # we replace this node by a 'true' or 'false' node:
   result = newIntNode(nkIntLit, 0)
@@ -1441,7 +1441,7 @@ proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
       localError(n.info, "obsolete usage of 'defined', use 'declared' instead")
     elif condsyms.isDefined(n.sons[1].ident):
       result.intVal = 1
-  elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: 
+  elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil:
     result.intVal = 1
   result.info = n.info
   result.typ = getSysType(tyBool)
@@ -1544,7 +1544,7 @@ proc processQuotations(n: var PNode, op: string,
         n.sons[0] = newIdentNode(getIdent(examinedOp.substr(op.len)), n.info)
   elif n.kind == nkAccQuoted and op == "``":
     returnQuote n[0]
- 
+
   for i in 0 .. <n.safeLen:
     processQuotations(n.sons[i], op, quotes, ids)
 
@@ -1556,7 +1556,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
     doBlk = n{-1}
     op = if n.len == 3: expectString(c, n[1]) else: "``"
     quotes = newSeq[PNode](1)
-      # the quotes will be added to a nkCall statement 
+      # the quotes will be added to a nkCall statement
       # leave some room for the callee symbol
     ids = newSeq[PNode]()
       # this will store the generated param names
@@ -1565,7 +1565,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
     localError(n.info, errXExpected, "block")
 
   processQuotations(doBlk.sons[bodyPos], op, quotes, ids)
-  
+
   doBlk.sons[namePos] = newAnonSym(skTemplate, n.info).newSymNode
   if ids.len > 0:
     doBlk.sons[paramsPos] = newNodeI(nkFormalParams, n.info)
@@ -1573,7 +1573,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
     ids.add getSysSym("expr").newSymNode # params type
     ids.add emptyNode # no default value
     doBlk[paramsPos].add newNode(nkIdentDefs, n.info, ids)
-  
+
   var tmpl = semTemplateDef(c, doBlk)
   quotes[0] = tmpl[namePos]
   result = newNode(nkCall, n.info, @[
@@ -1588,7 +1588,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   inc c.inCompilesContext
   # do not halt after first error:
   msgs.gErrorMax = high(int)
-  
+
   # open a scope for temporary symbol inclusions:
   let oldScope = c.currentScope
   openScope(c)
@@ -1597,7 +1597,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   let oldErrorOutputs = errorOutputs
   errorOutputs = {}
   let oldContextLen = msgs.getInfoContextLen()
-  
+
   let oldInGenericContext = c.inGenericContext
   let oldInUnrolledContext = c.inUnrolledContext
   let oldInGenericInst = c.inGenericInst
@@ -1625,7 +1625,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
 proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # we replace this node by a 'true' or 'false' node:
   if sonsLen(n) != 2: return semDirectOp(c, n, flags)
-  
+
   result = newIntNode(nkIntLit, ord(tryExpr(c, n[1], flags) != nil))
   result.info = n.info
   result.typ = getSysType(tyBool)
@@ -1652,7 +1652,7 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
   let sym = magicsys.getCompilerProc("nimCreateFlowVar")
   if sym == nil:
     localError(info, errSystemNeeds, "nimCreateFlowVar")
-  var bindings: TIdTable 
+  var bindings: TIdTable
   initIdTable(bindings)
   bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t)
   result = c.semGenerateInstance(c, sym, bindings, info)
@@ -1662,12 +1662,12 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
     result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC}
     result.loc.r = nil
 
-proc setMs(n: PNode, s: PSym): PNode = 
+proc setMs(n: PNode, s: PSym): PNode =
   result = n
   n.sons[0] = newSymNode(s)
   n.sons[0].info = n.info
 
-proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = 
+proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   # this is a hotspot in the compiler!
   # DON'T forget to update ast.SpecialSemMagics if you add a magic here!
   result = n
@@ -1713,36 +1713,36 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
   # If semCheck is set to false, ``when`` will return the verbatim AST of
   # the correct branch. Otherwise the AST will be passed through semStmt.
   result = nil
-  
+
   template setResult(e: expr) =
     if semCheck: result = semStmt(c, e) # do not open a new scope!
     else: result = e
 
-  for i in countup(0, sonsLen(n) - 1): 
+  for i in countup(0, sonsLen(n) - 1):
     var it = n.sons[i]
     case it.kind
-    of nkElifBranch, nkElifExpr: 
+    of nkElifBranch, nkElifExpr:
       checkSonsLen(it, 2)
       var e = semConstExpr(c, it.sons[0])
-      if e.kind != nkIntLit: 
+      if e.kind != nkIntLit:
         # can happen for cascading errors, assume false
         # InternalError(n.info, "semWhen")
         discard
       elif e.intVal != 0 and result == nil:
-        setResult(it.sons[1]) 
+        setResult(it.sons[1])
     of nkElse, nkElseExpr:
       checkSonsLen(it, 1)
-      if result == nil: 
+      if result == nil:
         setResult(it.sons[0])
     else: illFormedAst(n)
   if result == nil:
-    result = newNodeI(nkEmpty, n.info) 
+    result = newNodeI(nkEmpty, n.info)
   # The ``when`` statement implements the mechanism for platform dependent
   # code. Thus we try to ensure here consistent ID allocation after the
   # ``when`` statement.
   idSynchronizationPoint(200)
 
-proc semSetConstr(c: PContext, n: PNode): PNode = 
+proc semSetConstr(c: PContext, n: PNode): PNode =
   result = newNodeI(nkCurly, n.info)
   result.typ = newTypeS(tySet, c)
   if sonsLen(n) == 0:
@@ -1750,31 +1750,31 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
   else:
     # only semantic checking for all elements, later type checking:
     var typ: PType = nil
-    for i in countup(0, sonsLen(n) - 1): 
-      if isRange(n.sons[i]): 
+    for i in countup(0, sonsLen(n) - 1):
+      if isRange(n.sons[i]):
         checkSonsLen(n.sons[i], 3)
         n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
         n.sons[i].sons[2] = semExprWithType(c, n.sons[i].sons[2])
-        if typ == nil: 
-          typ = skipTypes(n.sons[i].sons[1].typ, 
+        if typ == nil:
+          typ = skipTypes(n.sons[i].sons[1].typ,
                           {tyGenericInst, tyVar, tyOrdinal})
         n.sons[i].typ = n.sons[i].sons[2].typ # range node needs type too
       elif n.sons[i].kind == nkRange:
         # already semchecked
         if typ == nil:
-          typ = skipTypes(n.sons[i].sons[0].typ, 
+          typ = skipTypes(n.sons[i].sons[0].typ,
                           {tyGenericInst, tyVar, tyOrdinal})
       else:
         n.sons[i] = semExprWithType(c, n.sons[i])
-        if typ == nil: 
+        if typ == nil:
           typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
     if not isOrdinalType(typ):
       localError(n.info, errOrdinalTypeExpected)
       typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
-    elif lengthOrd(typ) > MaxSetElements: 
+    elif lengthOrd(typ) > MaxSetElements:
       typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
     addSonSkipIntLit(result.typ, typ)
-    for i in countup(0, sonsLen(n) - 1): 
+    for i in countup(0, sonsLen(n) - 1):
       var m: PNode
       if isRange(n.sons[i]):
         m = newNodeI(nkRange, n.sons[i].info)
@@ -1786,7 +1786,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
       addSon(result, m)
 
 proc semTableConstr(c: PContext, n: PNode): PNode =
-  # we simply transform ``{key: value, key2, key3: value}`` to 
+  # we simply transform ``{key: value, key2, key3: value}`` to
   # ``[(key, value), (key2, value2), (key3, value2)]``
   result = newNodeI(nkBracket, n.info)
   var lastKey = 0
@@ -1815,7 +1815,7 @@ type
 
 proc checkPar(n: PNode): TParKind =
   var length = sonsLen(n)
-  if length == 0: 
+  if length == 0:
     result = paTuplePositions # ()
   elif length == 1:
     if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
@@ -1845,7 +1845,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
     var id: PIdent
     if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
     else: id = n.sons[i].sons[0].sym.name
-    if containsOrIncl(ids, id.id): 
+    if containsOrIncl(ids, id.id):
       localError(n.sons[i].info, errFieldInitTwice, id.s)
     n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
                                         flags*{efAllowDestructor})
@@ -1858,14 +1858,22 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
     addSon(result, n.sons[i])
   result.typ = typ
 
-proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = 
+proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = n                  # we don't modify n, but compute the type:
   var typ = newTypeS(tyTuple, c)  # leave typ.n nil!
-  for i in countup(0, sonsLen(n) - 1): 
+  for i in countup(0, sonsLen(n) - 1):
     n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor})
     addSonSkipIntLit(typ, n.sons[i].typ)
   result.typ = typ
 
+proc isTupleType(n: PNode): bool =
+  if n.len == 0:
+    return false # don't interpret () as type
+  for i in countup(0, n.len - 1):
+    if n[i].typ == nil or n[i].typ.kind != tyTypeDesc:
+      return false
+  return true
+
 proc checkInitialized(n: PNode, ids: IntSet, info: TLineInfo) =
   case n.kind
   of nkRecList:
@@ -1991,10 +1999,10 @@ proc setGenericParams(c: PContext, n: PNode) =
   for i in 1 .. <n.len:
     n[i].typ = semTypeNode(c, n[i], nil)
 
-proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
+proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   result = n
   if gCmd == cmdIdeTools: suggestExpr(c, n)
-  if nfSem in n.flags: return 
+  if nfSem in n.flags: return
   case n.kind
   of nkIdent, nkAccQuoted:
     var s = lookUp(c, n)
@@ -2011,43 +2019,43 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # because of the changed symbol binding, this does not mean that we
     # don't have to check the symbol for semantics here again!
     result = semSym(c, n, n.sym, flags)
-  of nkEmpty, nkNone, nkCommentStmt: 
+  of nkEmpty, nkNone, nkCommentStmt:
     discard
-  of nkNilLit: 
+  of nkNilLit:
     result.typ = getSysType(tyNil)
   of nkIntLit:
     if result.typ == nil: setIntLitType(result)
   of nkInt8Lit:
     if result.typ == nil: result.typ = getSysType(tyInt8)
-  of nkInt16Lit: 
+  of nkInt16Lit:
     if result.typ == nil: result.typ = getSysType(tyInt16)
-  of nkInt32Lit: 
+  of nkInt32Lit:
     if result.typ == nil: result.typ = getSysType(tyInt32)
-  of nkInt64Lit: 
+  of nkInt64Lit:
     if result.typ == nil: result.typ = getSysType(tyInt64)
   of nkUIntLit:
     if result.typ == nil: result.typ = getSysType(tyUInt)
-  of nkUInt8Lit: 
+  of nkUInt8Lit:
     if result.typ == nil: result.typ = getSysType(tyUInt8)
-  of nkUInt16Lit: 
+  of nkUInt16Lit:
     if result.typ == nil: result.typ = getSysType(tyUInt16)
-  of nkUInt32Lit: 
+  of nkUInt32Lit:
     if result.typ == nil: result.typ = getSysType(tyUInt32)
-  of nkUInt64Lit: 
+  of nkUInt64Lit:
     if result.typ == nil: result.typ = getSysType(tyUInt64)
-  of nkFloatLit: 
+  of nkFloatLit:
     if result.typ == nil: result.typ = getFloatLitType(result)
-  of nkFloat32Lit: 
+  of nkFloat32Lit:
     if result.typ == nil: result.typ = getSysType(tyFloat32)
-  of nkFloat64Lit: 
+  of nkFloat64Lit:
     if result.typ == nil: result.typ = getSysType(tyFloat64)
-  of nkFloat128Lit: 
+  of nkFloat128Lit:
     if result.typ == nil: result.typ = getSysType(tyFloat128)
-  of nkStrLit..nkTripleStrLit: 
+  of nkStrLit..nkTripleStrLit:
     if result.typ == nil: result.typ = getSysType(tyString)
-  of nkCharLit: 
+  of nkCharLit:
     if result.typ == nil: result.typ = getSysType(tyChar)
-  of nkDotExpr: 
+  of nkDotExpr:
     result = semFieldAccess(c, n, flags)
     if result.kind == nkDotCall:
       result.kind = nkCall
@@ -2055,11 +2063,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkBind:
     message(n.info, warnDeprecated, "bind")
     result = semExpr(c, n.sons[0], flags)
-  of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy, nkStaticTy:
+  of nkTypeOfExpr, nkTupleTy, nkTupleClassTy, nkRefTy..nkEnumTy, nkStaticTy:
     var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter})
     result.typ = makeTypeDesc(c, typ)
     #result = symNodeFromType(c, typ, n.info)
-  of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: 
+  of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
     # check if it is an expression macro:
     checkMinSonsLen(n, 1)
     let mode = if nfDotField in n.flags: {} else: {checkUndeclared}
@@ -2084,7 +2092,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
           result = semConv(c, n)
         elif n.len == 1:
           result = semObjConstr(c, n, flags)
-        elif contains(c.ambiguousSymbols, s.id): 
+        elif contains(c.ambiguousSymbols, s.id):
           localError(n.info, errUseQualifier, s.name.s)
         elif s.magic == mNone: result = semDirectOp(c, n, flags)
         else: result = semMagic(c, n, s, flags)
@@ -2123,13 +2131,20 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       result = semArrayAccess(c, n, flags)
   of nkCurlyExpr:
     result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
-  of nkPragmaExpr: 
+  of nkPragmaExpr:
     # which pragmas are allowed for expressions? `likely`, `unlikely`
     internalError(n.info, "semExpr() to implement") # XXX: to implement
-  of nkPar: 
+  of nkPar:
     case checkPar(n)
     of paNone: result = errorNode(c, n)
-    of paTuplePositions: result = semTuplePositionsConstr(c, n, flags)
+    of paTuplePositions:
+      var tupexp = semTuplePositionsConstr(c, n, flags)
+      if isTupleType(tupexp):
+        # reinterpret as type
+        var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter})
+        result.typ = makeTypeDesc(c, typ)
+      else:
+        result = tupexp
     of paTupleFields: result = semTupleFieldsConstr(c, n, flags)
     of paSingle: result = semExpr(c, n.sons[0], flags)
   of nkCurly: result = semSetConstr(c, n)
@@ -2142,7 +2157,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result = n
     checkSonsLen(n, 1)
     n.sons[0] = semExprWithType(c, n.sons[0])
-    if isAssignable(c, n.sons[0]) notin {arLValue, arLocalLValue}: 
+    if isAssignable(c, n.sons[0]) notin {arLValue, arLocalLValue}:
       localError(n.info, errExprHasNoAddress)
     n.typ = makePtrType(c, n.sons[0].typ)
   of nkHiddenAddr, nkHiddenDeref:
@@ -2150,13 +2165,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     n.sons[0] = semExpr(c, n.sons[0], flags)
   of nkCast: result = semCast(c, n)
   of nkIfExpr, nkIfStmt: result = semIf(c, n)
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv: 
+  of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv:
     checkSonsLen(n, 2)
-  of nkStringToCString, nkCStringToString, nkObjDownConv, nkObjUpConv: 
+  of nkStringToCString, nkCStringToString, nkObjDownConv, nkObjUpConv:
     checkSonsLen(n, 1)
-  of nkChckRangeF, nkChckRange64, nkChckRange: 
+  of nkChckRangeF, nkChckRange64, nkChckRange:
     checkSonsLen(n, 3)
-  of nkCheckedFieldExpr: 
+  of nkCheckedFieldExpr:
     checkMinSonsLen(n, 2)
   of nkTableConstr:
     result = semTableConstr(c, n)
@@ -2191,16 +2206,16 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkConverterDef: result = semConverterDef(c, n)
   of nkMacroDef: result = semMacroDef(c, n)
   of nkTemplateDef: result = semTemplateDef(c, n)
-  of nkImportStmt: 
+  of nkImportStmt:
     if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "import")
     result = evalImport(c, n)
   of nkImportExceptStmt:
     if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "import")
     result = evalImportExcept(c, n)
-  of nkFromStmt: 
+  of nkFromStmt:
     if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "from")
     result = evalFrom(c, n)
-  of nkIncludeStmt: 
+  of nkIncludeStmt:
     if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "include")
     result = evalInclude(c, n)
   of nkExportStmt, nkExportExceptStmt:
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 2601f05ac..db910600b 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -356,7 +356,7 @@ proc semGenericStmt(c: PContext, n: PNode,
         of nkIdent: a = n.sons[i]
         else: illFormedAst(n)
         addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c))
-  of nkObjectTy, nkTupleTy:
+  of nkObjectTy, nkTupleTy, nkTupleClassTy:
     discard
   of nkFormalParams:
     checkMinSonsLen(n, 1)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index a10f27519..dc36ecf34 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -11,12 +11,12 @@
 # included from sem.nim
 
 proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
-                                 entry: var TInstantiation) = 
-  if n.kind != nkGenericParams: 
+                                 entry: var TInstantiation) =
+  if n.kind != nkGenericParams:
     internalError(n.info, "instantiateGenericParamList; no generic params")
   newSeq(entry.concreteTypes, n.len)
   for i, a in n.pairs:
-    if a.kind != nkSym: 
+    if a.kind != nkSym:
       internalError(a.info, "instantiateGenericParamList; no symbol")
     var q = a.sym
     if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
@@ -27,13 +27,13 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
     var t = PType(idTableGet(pt, q.typ))
     if t == nil:
       if tfRetType in q.typ.flags:
-        # keep the generic type and allow the return type to be bound 
+        # keep the generic type and allow the return type to be bound
         # later by semAsgn in return type inference scenario
         t = q.typ
       else:
         localError(a.info, errCannotInstantiateX, s.name.s)
         t = errorType(c)
-    elif t.kind == tyGenericParam: 
+    elif t.kind == tyGenericParam:
       localError(a.info, errCannotInstantiateX, q.name.s)
       t = errorType(c)
     elif t.kind == tyGenericInvocation:
@@ -58,17 +58,17 @@ proc genericCacheGet(genericSym: PSym, entry: TInstantiation): PSym =
       if sameInstantiation(entry, inst[]):
         return inst.sym
 
-proc removeDefaultParamValues(n: PNode) = 
+proc removeDefaultParamValues(n: PNode) =
   # we remove default params, because they cannot be instantiated properly
   # and they are not needed anyway for instantiation (each param is already
   # provided).
   when false:
-    for i in countup(1, sonsLen(n)-1): 
+    for i in countup(1, sonsLen(n)-1):
       var a = n.sons[i]
       if a.kind != nkIdentDefs: IllFormedAst(a)
       var L = a.len
       if a.sons[L-1].kind != nkEmpty and a.sons[L-2].kind != nkEmpty:
-        # ``param: typ = defaultVal``. 
+        # ``param: typ = defaultVal``.
         # We don't need defaultVal for semantic checking and it's wrong for
         # ``cmp: proc (a, b: T): int = cmp``. Hm, for ``cmp = cmp`` that is
         # not possible... XXX We don't solve this issue here.
@@ -97,7 +97,7 @@ proc addProcDecls(c: PContext, fn: PSym) =
     var param = fn.typ.n.sons[i].sym
     param.owner = fn
     addParamOrResult(c, param, fn.kind)
-  
+
   maybeAddResult(c, fn, fn.ast)
 
 proc instantiateBody(c: PContext, n, params: PNode, result: PSym) =
@@ -132,9 +132,9 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
       closeScope(c)
       popInfoContext()
 
-proc sideEffectsCheck(c: PContext, s: PSym) = 
+proc sideEffectsCheck(c: PContext, s: PSym) =
   if {sfNoSideEffect, sfSideEffect} * s.flags ==
-      {sfNoSideEffect, sfSideEffect}: 
+      {sfNoSideEffect, sfSideEffect}:
     localError(s.info, errXhasSideEffects, s.name.s)
 
 proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
@@ -162,18 +162,18 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
   # Alas, doing this here is probably not enough, because another
   # proc signature could appear in the params:
   # proc foo[T](a: proc (x: T, b: type(x.y))
-  #   
+  #
   # The solution would be to move this logic into semtypinst, but
   # at this point semtypinst have to become part of sem, because it
   # will need to use openScope, addDecl, etc.
   addDecl(c, prc)
-  
+
   pushInfoContext(info)
   var cl = initTypeVars(c, pt, info)
   var result = instCopyType(cl, prc.typ)
   let originalParams = result.n
   result.n = originalParams.shallowCopy
-  
+
   for i in 1 .. <result.len:
     # twrong_field_caching requires these 'resetIdTable' calls:
     if i > 1: resetIdTable(cl.symMap)
@@ -198,10 +198,10 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
   resetIdTable(cl.symMap)
   result.sons[0] = replaceTypeVarsT(cl, result.sons[0])
   result.n.sons[0] = originalParams[0].copyTree
-  
+
   eraseVoidParams(result)
   skipIntLiteralParams(result)
- 
+
   prc.typ = result
   maybeAddResult(c, prc, prc.ast)
   popInfoContext()
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 60153e052..14644a8d6 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -138,7 +138,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
   if g.kind == skUnknown:
     var field: PSym = nil
     var ty = n.sons[0].typ.skipTypes(abstractPtrs)
-    if ty.kind == tyTuple:
+    if ty.kind == tyTuple and not ty.n.isNil:
       field = lookupInRecord(ty.n, g.name)
     else:
       while ty != nil and ty.kind == tyObject:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 42471bae7..ccfd74607 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -692,7 +692,7 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
           assignType(s.typ, t)
           s.typ.id = t.id     # same id
       checkConstructedType(s.info, s.typ)
-      if s.typ.kind in {tyObject, tyTuple}:
+      if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
         checkForMetaFields(s.typ.n)
     let aa = a.sons[2]
     if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
@@ -757,7 +757,8 @@ proc lookupMacro(c: PContext, n: PNode): PSym =
   else:
     result = searchInScopes(c, considerQuotedIdent(n), {skMacro, skTemplate})
 
-proc semProcAnnotation(c: PContext, prc: PNode): PNode =
+proc semProcAnnotation(c: PContext, prc: PNode;
+                       validPragmas: TSpecialWords): PNode =
   var n = prc.sons[pragmasPos]
   if n == nil or n.kind == nkEmpty: return
   for i in countup(0, <n.len):
@@ -782,12 +783,18 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
       x.add(it.sons[1])
     x.add(prc)
     # recursion assures that this works for multiple macro annotations too:
-    return semStmt(c, x)
+    result = semStmt(c, x)
+    # since a proc annotation can set pragmas, we process these here again.
+    # This is required for SqueakNim-like export pragmas.
+    if result.kind in procDefs and result[namePos].kind == nkSym and 
+        result[pragmasPos].kind != nkEmpty:
+      pragma(c, result[namePos].sym, result[pragmasPos], validPragmas)
+    return
 
 proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # XXX semProcAux should be good enough for this now, we will eventually
   # remove semLambda
-  result = semProcAnnotation(c, n)
+  result = semProcAnnotation(c, n, lambdaPragmas)
   if result != nil: return result
   result = n
   checkSonsLen(n, bodyPos + 1)
@@ -943,7 +950,7 @@ proc isForwardDecl(s: PSym): bool =
 proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
                 validPragmas: TSpecialWords,
                 phase = stepRegisterSymbol): PNode =
-  result = semProcAnnotation(c, n)
+  result = semProcAnnotation(c, n, validPragmas)
   if result != nil: return result
   result = n
   checkSonsLen(n, bodyPos + 1)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 9f2f755a0..ac0636211 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -10,14 +10,14 @@
 # this module does the semantic checking of type declarations
 # included from sem.nim
 
-proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType = 
-  if prev == nil: 
+proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
+  if prev == nil:
     result = newTypeS(kind, c)
-  else: 
+  else:
     result = prev
     if result.kind == tyForward: result.kind = kind
 
-proc newConstraint(c: PContext, k: TTypeKind): PType = 
+proc newConstraint(c: PContext, k: TTypeKind): PType =
   result = newTypeS(tyBuiltInTypeClass, c)
   result.addSonSkipIntLit(newTypeS(k, c))
 
@@ -32,22 +32,22 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
   result = newOrPrevType(tyEnum, prev, c)
   result.n = newNodeI(nkEnumTy, n.info)
   checkMinSonsLen(n, 1)
-  if n.sons[0].kind != nkEmpty: 
+  if n.sons[0].kind != nkEmpty:
     base = semTypeNode(c, n.sons[0].sons[0], nil)
-    if base.kind != tyEnum: 
+    if base.kind != tyEnum:
       localError(n.sons[0].info, errInheritanceOnlyWithEnums)
     counter = lastOrd(base) + 1
   rawAddSon(result, base)
   let isPure = result.sym != nil and sfPure in result.sym.flags
   var hasNull = false
-  for i in countup(1, sonsLen(n) - 1): 
+  for i in countup(1, sonsLen(n) - 1):
     case n.sons[i].kind
-    of nkEnumFieldDef: 
+    of nkEnumFieldDef:
       e = newSymS(skEnumField, n.sons[i].sons[0], c)
       var v = semConstExpr(c, n.sons[i].sons[1])
       var strVal: PNode = nil
-      case skipTypes(v.typ, abstractInst-{tyTypeDesc}).kind 
-      of tyTuple: 
+      case skipTypes(v.typ, abstractInst-{tyTypeDesc}).kind
+      of tyTuple:
         if sonsLen(v) == 2:
           strVal = v.sons[1] # second tuple part is the string value
           if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
@@ -63,14 +63,14 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
         x = getOrdValue(v)
       if i != 1:
         if x != counter: incl(result.flags, tfEnumHasHoles)
-        if x < counter: 
+        if x < counter:
           localError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
           x = counter
       e.ast = strVal # might be nil
       counter = x
-    of nkSym: 
+    of nkSym:
       e = n.sons[i].sym
-    of nkIdent, nkAccQuoted: 
+    of nkIdent, nkAccQuoted:
       e = newSymS(skEnumField, n.sons[i], c)
     else:
       illFormedAst(n[i])
@@ -87,28 +87,28 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
     inc(counter)
   if not hasNull: incl(result.flags, tfNeedsInit)
 
-proc semSet(c: PContext, n: PNode, prev: PType): PType = 
+proc semSet(c: PContext, n: PNode, prev: PType): PType =
   result = newOrPrevType(tySet, prev, c)
-  if sonsLen(n) == 2: 
+  if sonsLen(n) == 2:
     var base = semTypeNode(c, n.sons[1], nil)
     addSonSkipIntLit(result, base)
     if base.kind == tyGenericInst: base = lastSon(base)
     if base.kind != tyGenericParam:
-      if not isOrdinalType(base): 
+      if not isOrdinalType(base):
         localError(n.info, errOrdinalTypeExpected)
-      elif lengthOrd(base) > MaxSetElements: 
+      elif lengthOrd(base) > MaxSetElements:
         localError(n.info, errSetTooBig)
   else:
     localError(n.info, errXExpectsOneTypeParam, "set")
     addSonSkipIntLit(result, errorType(c))
-  
-proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, 
-                  prev: PType): PType = 
+
+proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
+                  prev: PType): PType =
   result = newOrPrevType(kind, prev, c)
-  if sonsLen(n) == 2: 
+  if sonsLen(n) == 2:
     var base = semTypeNode(c, n.sons[1], nil)
     addSonSkipIntLit(result, base)
-  else: 
+  else:
     localError(n.info, errXExpectsOneTypeParam, kindStr)
     addSonSkipIntLit(result, errorType(c))
 
@@ -140,23 +140,23 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
     var base = semTypeNode(c, n.lastSon, nil)
     addSonSkipIntLit(result, base)
 
-proc semVarType(c: PContext, n: PNode, prev: PType): PType = 
-  if sonsLen(n) == 1: 
+proc semVarType(c: PContext, n: PNode, prev: PType): PType =
+  if sonsLen(n) == 1:
     result = newOrPrevType(tyVar, prev, c)
     var base = semTypeNode(c, n.sons[0], nil)
-    if base.kind == tyVar: 
+    if base.kind == tyVar:
       localError(n.info, errVarVarTypeNotAllowed)
       base = base.sons[0]
     addSonSkipIntLit(result, base)
   else:
     result = newConstraint(c, tyVar)
 
-proc semDistinct(c: PContext, n: PNode, prev: PType): PType = 
+proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
   if n.len == 0: return newConstraint(c, tyDistinct)
   result = newOrPrevType(tyDistinct, prev, c)
   addSonSkipIntLit(result, semTypeNode(c, n.sons[0], nil))
   if n.len > 1: result.n = n[1]
-  
+
 proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
   assert isRange(n)
   checkSonsLen(n, 3)
@@ -164,11 +164,11 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
   result.n = newNodeI(nkRange, n.info)
   if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty):
     localError(n.info, errRangeIsEmpty)
-  
+
   var range: array[2, PNode]
   range[0] = semExprWithType(c, n[1], {efDetermineType})
   range[1] = semExprWithType(c, n[2], {efDetermineType})
-  
+
   var rangeT: array[2, PType]
   for i in 0..1:
     rangeT[i] = range[i].typ.skipTypes({tyStatic}).skipIntLit
@@ -179,13 +179,13 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
     localError(n.info, errOrdinalTypeExpected)
   elif enumHasHoles(rangeT[0]):
     localError(n.info, errEnumXHasHoles, rangeT[0].sym.name.s)
-  
+
   for i in 0..1:
     if hasGenericArguments(range[i]):
       result.n.addSon makeStaticExpr(c, range[i])
     else:
       result.n.addSon semConstExpr(c, range[i])
- 
+
   if weakLeValue(result.n[0], result.n[1]) == impNo:
     localError(n.info, errRangeIsEmpty)
 
@@ -201,10 +201,10 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
         incl(result.flags, tfNeedsInit)
       elif n.sons[1].kind in {nkCharLit..nkUInt64Lit} and n.sons[1].intVal < 0:
         incl(result.flags, tfNeedsInit)
-      elif n.sons[0].kind in {nkFloatLit..nkFloat64Lit} and 
+      elif n.sons[0].kind in {nkFloatLit..nkFloat64Lit} and
           n.sons[0].floatVal > 0.0:
         incl(result.flags, tfNeedsInit)
-      elif n.sons[1].kind in {nkFloatLit..nkFloat64Lit} and 
+      elif n.sons[1].kind in {nkFloatLit..nkFloat64Lit} and
           n.sons[1].floatVal < 0.0:
         incl(result.flags, tfNeedsInit)
     else:
@@ -243,13 +243,13 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
     else:
       let x = semConstExpr(c, e)
       if x.kind in {nkIntLit..nkUInt64Lit}:
-        result = makeRangeType(c, 0, x.intVal-1, n.info, 
+        result = makeRangeType(c, 0, x.intVal-1, n.info,
                              x.typ.skipTypes({tyTypeDesc}))
       else:
         result = x.typ.skipTypes({tyTypeDesc})
         #localError(n[1].info, errConstExprExpected)
 
-proc semArray(c: PContext, n: PNode, prev: PType): PType = 
+proc semArray(c: PContext, n: PNode, prev: PType): PType =
   var base: PType
   result = newOrPrevType(tyArray, prev, c)
   if sonsLen(n) == 3:
@@ -260,20 +260,20 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
     if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}:
       if not isOrdinalType(indx):
         localError(n.sons[1].info, errOrdinalTypeExpected)
-      elif enumHasHoles(indx): 
+      elif enumHasHoles(indx):
         localError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
     base = semTypeNode(c, n.sons[2], nil)
     addSonSkipIntLit(result, base)
-  else: 
+  else:
     localError(n.info, errArrayExpectsTwoTypeParams)
     result = newOrPrevType(tyError, prev, c)
-  
-proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = 
+
+proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
   result = newOrPrevType(tyOrdinal, prev, c)
-  if sonsLen(n) == 2: 
+  if sonsLen(n) == 2:
     var base = semTypeNode(c, n.sons[1], nil)
-    if base.kind != tyGenericParam: 
-      if not isOrdinalType(base): 
+    if base.kind != tyGenericParam:
+      if not isOrdinalType(base):
         localError(n.sons[1].info, errOrdinalTypeExpected)
     addSonSkipIntLit(result, base)
   else:
@@ -281,7 +281,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
     result = newOrPrevType(tyError, prev, c)
 
 proc semTypeIdent(c: PContext, n: PNode): PSym =
-  if n.kind == nkSym: 
+  if n.kind == nkSym:
     result = n.sym
   else:
     when defined(nimfix):
@@ -307,7 +307,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
         result = result.typ.sym.copySym
         result.typ = copyType(result.typ, result.typ.owner, true)
         result.typ.flags.incl tfUnresolved
-      
+
       if result.kind == skGenericParam:
         if result.typ.kind == tyGenericParam and result.typ.len == 0 and
            tfWildcard in result.typ.flags:
@@ -319,7 +319,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
           localError(n.info, errTypeExpected)
           return errorSym(c, n)
 
-      if result.kind != skType: 
+      if result.kind != skType:
         # this implements the wanted ``var v: V, x: V`` feature ...
         var ov: TOverloadIter
         var amb = initOverloadIter(ov, c, n)
@@ -344,48 +344,54 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
     else:
       localError(n.info, errIdentifierExpected)
       result = errorSym(c, n)
-  
+
+proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
+  if sonsLen(n) == 0:
+    localError(n.info, errTypeExpected)
+  result = newOrPrevType(tyTuple, prev, c)
+  for i in countup(0, sonsLen(n) - 1):
+    addSonSkipIntLit(result, semTypeNode(c, n.sons[i], nil))
+
 proc semTuple(c: PContext, n: PNode, prev: PType): PType = 
-  if n.sonsLen == 0: return newConstraint(c, tyTuple)
   var typ: PType
   result = newOrPrevType(tyTuple, prev, c)
   result.n = newNodeI(nkRecList, n.info)
   var check = initIntSet()
   var counter = 0
-  for i in countup(0, sonsLen(n) - 1): 
+  for i in countup(0, sonsLen(n) - 1):
     var a = n.sons[i]
     if (a.kind != nkIdentDefs): illFormedAst(a)
     checkMinSonsLen(a, 3)
     var length = sonsLen(a)
-    if a.sons[length - 2].kind != nkEmpty: 
+    if a.sons[length - 2].kind != nkEmpty:
       typ = semTypeNode(c, a.sons[length - 2], nil)
     else:
       localError(a.info, errTypeExpected)
       typ = errorType(c)
-    if a.sons[length - 1].kind != nkEmpty: 
+    if a.sons[length - 1].kind != nkEmpty:
       localError(a.sons[length - 1].info, errInitHereNotAllowed)
-    for j in countup(0, length - 3): 
+    for j in countup(0, length - 3):
       var field = newSymG(skField, a.sons[j], c)
       field.typ = typ
       field.position = counter
       inc(counter)
-      if containsOrIncl(check, field.name.id): 
+      if containsOrIncl(check, field.name.id):
         localError(a.sons[j].info, errAttemptToRedefine, field.name.s)
       else:
         addSon(result.n, newSymNode(field))
         addSonSkipIntLit(result, typ)
       if gCmd == cmdPretty: styleCheckDef(a.sons[j].info, field)
 
-proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, 
-                 allowed: TSymFlags): PSym = 
+proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
+                 allowed: TSymFlags): PSym =
   # identifier with visibility
-  if n.kind == nkPostfix: 
-    if sonsLen(n) == 2 and n.sons[0].kind == nkIdent: 
+  if n.kind == nkPostfix:
+    if sonsLen(n) == 2 and n.sons[0].kind == nkIdent:
       # for gensym'ed identifiers the identifier may already have been
       # transformed to a symbol and we need to use that here:
       result = newSymG(kind, n.sons[1], c)
       var v = n.sons[0].ident
-      if sfExported in allowed and v.id == ord(wStar): 
+      if sfExported in allowed and v.id == ord(wStar):
         incl(result.flags, sfExported)
       else:
         localError(n.sons[0].info, errInvalidVisibilityX, v.s)
@@ -393,7 +399,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
       illFormedAst(n)
   else:
     result = newSymG(kind, n, c)
-  
+
 proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
                         allowed: TSymFlags): PSym =
   if n.kind == nkPragmaExpr:
@@ -415,31 +421,31 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
 proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
   let ex = t[branchIndex][currentEx].skipConv
   for i in countup(1, branchIndex):
-    for j in countup(0, sonsLen(t.sons[i]) - 2): 
+    for j in countup(0, sonsLen(t.sons[i]) - 2):
       if i == branchIndex and j == currentEx: break
       if overlap(t.sons[i].sons[j].skipConv, ex):
         localError(ex.info, errDuplicateCaseLabel)
-  
+
 proc semBranchRange(c: PContext, t, a, b: PNode, covered: var BiggestInt): PNode =
   checkMinSonsLen(t, 1)
   let ac = semConstExpr(c, a)
   let bc = semConstExpr(c, b)
   let at = fitNode(c, t.sons[0].typ, ac).skipConvTakeType
   let bt = fitNode(c, t.sons[0].typ, bc).skipConvTakeType
-  
+
   result = newNodeI(nkRange, a.info)
   result.add(at)
   result.add(bt)
   if emptyRange(ac, bc): localError(b.info, errRangeIsEmpty)
   else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
 
-proc semCaseBranchRange(c: PContext, t, b: PNode, 
-                        covered: var BiggestInt): PNode = 
+proc semCaseBranchRange(c: PContext, t, b: PNode,
+                        covered: var BiggestInt): PNode =
   checkSonsLen(b, 3)
   result = semBranchRange(c, t, b.sons[1], b.sons[2], covered)
 
-proc semCaseBranchSetElem(c: PContext, t, b: PNode, 
-                          covered: var BiggestInt): PNode = 
+proc semCaseBranchSetElem(c: PContext, t, b: PNode,
+                          covered: var BiggestInt): PNode =
   if isRange(b):
     checkSonsLen(b, 3)
     result = semBranchRange(c, t, b.sons[1], b.sons[2], covered)
@@ -450,10 +456,10 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode,
     result = fitNode(c, t.sons[0].typ, b)
     inc(covered)
 
-proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, 
-                   covered: var BiggestInt) = 
-  
-  for i in countup(0, sonsLen(branch) - 2): 
+proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
+                   covered: var BiggestInt) =
+
+  for i in countup(0, sonsLen(branch) - 2):
     var b = branch.sons[i]
     if b.kind == nkRange:
       branch.sons[i] = b
@@ -480,7 +486,7 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
           var L = branch.len
           swap(branch.sons[L-2], branch.sons[L-1])
     checkForOverlap(c, t, i, branchIndex)
-    
+
 proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
                       father: PNode, rectype: PType)
 proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
@@ -514,11 +520,11 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
     else: illFormedAst(n)
     delSon(b, sonsLen(b) - 1)
     semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
-  if chckCovered and (covered != lengthOrd(a.sons[0].typ)): 
+  if chckCovered and (covered != lengthOrd(a.sons[0].typ)):
     localError(a.info, errNotAllCasesCovered)
   addSon(father, a)
 
-proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, 
+proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
                       father: PNode, rectype: PType) =
   if n == nil: return
   case n.kind
@@ -556,12 +562,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
       semRecordNodeAux(c, branch, check, pos, father, rectype)
   of nkRecCase:
     semRecordCase(c, n, check, pos, father, rectype)
-  of nkNilLit: 
+  of nkNilLit:
     if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info))
   of nkRecList:
     # attempt to keep the nesting at a sane level:
     var a = if father.kind == nkRecList: father else: copyNode(n)
-    for i in countup(0, sonsLen(n) - 1): 
+    for i in countup(0, sonsLen(n) - 1):
       semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
     if a != father: addSon(father, a)
   of nkIdentDefs:
@@ -570,10 +576,10 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
     var a: PNode
     if father.kind != nkRecList and length>=4: a = newNodeI(nkRecList, n.info)
     else: a = ast.emptyNode
-    if n.sons[length-1].kind != nkEmpty: 
+    if n.sons[length-1].kind != nkEmpty:
       localError(n.sons[length-1].info, errInitHereNotAllowed)
     var typ: PType
-    if n.sons[length-2].kind == nkEmpty: 
+    if n.sons[length-2].kind == nkEmpty:
       localError(n.info, errTypeExpected)
       typ = errorType(c)
     else:
@@ -586,7 +592,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
       f.typ = typ
       f.position = pos
       if (rec != nil) and ({sfImportc, sfExportc} * rec.flags != {}) and
-          (f.loc.r == nil): 
+          (f.loc.r == nil):
         f.loc.r = toRope(f.name.s)
         f.flags = f.flags + ({sfImportc, sfExportc} * rec.flags)
       inc(pos)
@@ -598,8 +604,8 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
     if a.kind != nkEmpty: addSon(father, a)
   of nkEmpty: discard
   else: illFormedAst(n)
-  
-proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int, 
+
+proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
                            n: PNode) =
   case n.kind
   of nkRecCase:
@@ -618,31 +624,31 @@ proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
     inc(pos)
   else: internalError(n.info, "addInheritedFieldsAux()")
 
-proc skipGenericInvocation(t: PType): PType {.inline.} = 
+proc skipGenericInvocation(t: PType): PType {.inline.} =
   result = t
   if result.kind == tyGenericInvocation:
     result = result.sons[0]
   if result.kind == tyGenericBody:
     result = lastSon(result)
 
-proc addInheritedFields(c: PContext, check: var IntSet, pos: var int, 
+proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
                         obj: PType) =
   assert obj.kind == tyObject
-  if (sonsLen(obj) > 0) and (obj.sons[0] != nil): 
+  if (sonsLen(obj) > 0) and (obj.sons[0] != nil):
     addInheritedFields(c, check, pos, obj.sons[0].skipGenericInvocation)
   addInheritedFieldsAux(c, check, pos, obj.n)
 
 proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
   if n.sonsLen == 0: return newConstraint(c, tyObject)
   var check = initIntSet()
-  var pos = 0 
+  var pos = 0
   var base: PType = nil
   # n.sons[0] contains the pragmas (if any). We process these later...
   checkSonsLen(n, 3)
-  if n.sons[1].kind != nkEmpty: 
+  if n.sons[1].kind != nkEmpty:
     base = skipTypes(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs)
     var concreteBase = skipGenericInvocation(base).skipTypes(skipPtrs)
-    if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: 
+    if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags:
       addInheritedFields(c, check, pos, concreteBase)
     else:
       if concreteBase.kind != tyError:
@@ -723,7 +729,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     genericParams.addSon(newSymNode(s))
     result = typeClass
     addDecl(c, s)
- 
+
   # XXX: There are codegen errors if this is turned into a nested proc
   template liftingWalk(typ: PType, anonFlag = false): expr =
     liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag)
@@ -742,7 +748,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   case paramType.kind:
   of tyAnything:
     result = addImplicitGeneric(newTypeS(tyGenericParam, c))
-  
+
   of tyStatic:
     # proc(a: expr{string}, b: expr{nkLambda})
     # overload on compile time values and AST trees
@@ -753,7 +759,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
       localError(info, errMacroBodyDependsOnGenericTypes, paramName)
     result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
     result.flags.incl({tfHasStatic, tfUnresolved})
-  
+
   of tyTypeDesc:
     if tfUnresolved notin paramType.flags:
       # naked typedescs are not bindOnce types
@@ -761,12 +767,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
          paramTypId.id == typedescId.id: paramTypId = nil
       result = addImplicitGeneric(
         c.newTypeWithSons(tyTypeDesc, @[paramType.base]))
-  
+
   of tyDistinct:
     if paramType.sonsLen == 1:
       # disable the bindOnce behavior for the type class
       result = liftingWalk(paramType.sons[0], true)
-  
+
   of tySequence, tySet, tyArray, tyOpenArray,
      tyVar, tyPtr, tyRef, tyProc:
     # XXX: this is a bit strange, but proc(s: seq)
@@ -785,22 +791,22 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
         if lifted != nil:
           paramType.sons[i] = lifted
           result = paramType
-  
+
   of tyGenericBody:
     result = newTypeS(tyGenericInvocation, c)
     result.rawAddSon(paramType)
-      
+
     for i in 0 .. paramType.sonsLen - 2:
       if paramType.sons[i].kind == tyStatic:
         result.rawAddSon makeTypeFromExpr(c, ast.emptyNode) # aka 'tyUnknown'
       else:
         result.rawAddSon newTypeS(tyAnything, c)
-      
+
     if paramType.lastSon.kind == tyUserTypeClass:
       result.kind = tyUserTypeClassInst
       result.rawAddSon paramType.lastSon
       return addImplicitGeneric(result)
-   
+
     result = instGenericContainer(c, paramType.sym.info, result,
                                   allowMetaTypes = true)
     result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
@@ -832,7 +838,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     if liftBody != nil:
       result = liftBody
       result.shouldHaveMeta
- 
+
   of tyGenericInvocation:
     for i in 1 .. <paramType.sonsLen:
       let lifted = liftingWalk(paramType.sons[i])
@@ -844,18 +850,18 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
 
   of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
     result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
-  
+
   of tyExpr:
     if procKind notin {skMacro, skTemplate}:
       result = addImplicitGeneric(newTypeS(tyAnything, c))
-  
+
   of tyGenericParam:
     markUsed(info, paramType.sym)
     styleCheckUse(info, paramType.sym)
     if tfWildcard in paramType.flags:
       paramType.flags.excl tfWildcard
       paramType.sym.kind = skType
-    
+
   else: discard
 
   # result = liftingWalk(paramType)
@@ -872,7 +878,7 @@ proc newProcType(c: PContext; info: TLineInfo; prev: PType = nil): PType =
   result.callConv = lastOptionEntry(c).defaultCC
   result.n = newNodeI(nkFormalParams, info)
   rawAddSon(result, nil) # return type
-  # result.n[0] used to be `nkType`, but now it's `nkEffectList` because 
+  # result.n[0] used to be `nkType`, but now it's `nkEffectList` because
   # the effects are now stored in there too ... this is a bit hacky, but as
   # usual we desperately try to save memory:
   addSon(result.n, newNodeI(nkEffectList, info))
@@ -909,7 +915,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       typ = semParamType(c, a.sons[length-2], constraint)
 
     if hasDefault:
-      def = semExprWithType(c, a.sons[length-1]) 
+      def = semExprWithType(c, a.sons[length-1])
       # check type compatibility between def.typ and typ:
       if typ == nil:
         typ = def.typ
@@ -927,7 +933,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       typ = newTypeS(tdef, c)
 
     if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
-    for j in countup(0, length-3): 
+    for j in countup(0, length-3):
       var arg = newSymG(skParam, a.sons[j], c)
       let lifted = liftParamType(c, kind, genericParams, typ,
                                  arg.name.s, arg.info)
@@ -937,7 +943,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       arg.constraint = constraint
       inc(counter)
       if def != nil and def.kind != nkEmpty: arg.ast = copyTree(def)
-      if containsOrIncl(check, arg.name.id): 
+      if containsOrIncl(check, arg.name.id):
         localError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
       addSon(result.n, newSymNode(arg))
       rawAddSon(result, finalType)
@@ -950,9 +956,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
   elif kind == skIterator:
     # XXX This is special magic we should likely get rid of
     r = newTypeS(tyExpr, c)
-  
+
   if r != nil:
-    # turn explicit 'void' return type into 'nil' because the rest of the 
+    # turn explicit 'void' return type into 'nil' because the rest of the
     # compiler only checks for 'nil':
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
       # 'auto' as a return type does not imply a generic:
@@ -988,8 +994,8 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
     n.sons[length - 1].typ = result
   else:
     result = nil
-  
-proc semBlockType(c: PContext, n: PNode, prev: PType): PType = 
+
+proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
   inc(c.p.nestedBlockCounter)
   checkSonsLen(n, 2)
   openScope(c)
@@ -1009,7 +1015,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     localError(n.info, "cannot instantiate the '$1' $2" %
                        [s.name.s, ($s.kind).substr(2).toLower])
     return newOrPrevType(tyError, prev, c)
-  
+
   var t = s.typ
   if t.kind == tyCompositeTypeClass and t.base.kind == tyGenericBody:
     t = t.base
@@ -1036,7 +1042,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
   else:
     var m = newCandidate(c, t)
     matches(c, n, copyTree(n), m)
-    
+
     if m.state != csMatch:
       var err = "cannot instantiate " & typeToString(t) & "\n" &
                 "got: (" & describeArgs(c, n) & ")\n" &
@@ -1045,12 +1051,12 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
       return newOrPrevType(tyError, prev, c)
 
     var isConcrete = true
- 
+
     for i in 1 .. <m.call.len:
       let typ = m.call[i].typ.skipTypes({tyTypeDesc})
       if containsGenericType(typ): isConcrete = false
       addToResult(typ)
-   
+
     if isConcrete:
       if s.ast == nil and s.typ.kind != tyCompositeTypeClass:
         # XXX: What kind of error is this? is it still relevant?
@@ -1081,7 +1087,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
   let
     pragmas = n[1]
     inherited = n[2]
-    
+
   if inherited.kind != nkEmpty:
     for n in inherited.sons:
       let typ = semTypeNode(c, n, nil)
@@ -1114,12 +1120,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     checkSonsLen(n, 1)
     let typExpr = semExprWithType(c, n.sons[0], {efInTypeof})
     result = typExpr.typ.skipTypes({tyIter})
-  of nkPar: 
+  of nkPar:
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
     else:
-      # XXX support anon tuple here
-      localError(n.info, errTypeExpected)
-      result = newOrPrevType(tyError, prev, c)
+      result = semAnonTuple(c, n, prev)
   of nkCallKinds:
     if isRange(n):
       result = semRangeAux(c, n, prev)
@@ -1197,7 +1201,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         result = makeTypeFromExpr(c, preprocessed.copyTree)
   of nkIdent, nkAccQuoted:
     var s = semTypeIdent(c, n)
-    if s.typ == nil: 
+    if s.typ == nil:
       if s.kind != skError: localError(n.info, errTypeExpected)
       result = newOrPrevType(tyError, prev, c)
     elif s.kind == skParam and s.typ.kind == tyTypeDesc:
@@ -1205,19 +1209,19 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       result = s.typ.base
     elif prev == nil:
       result = s.typ
-    else: 
+    else:
       assignType(prev, s.typ)
       # bugfix: keep the fresh id for aliases to integral types:
       if s.typ.kind notin {tyBool, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
-                           tyUInt..tyUInt64}: 
+                           tyUInt..tyUInt64}:
         prev.id = s.typ.id
       result = prev
   of nkSym:
     if n.sym.kind == skType and n.sym.typ != nil:
       var t = n.sym.typ
-      if prev == nil: 
+      if prev == nil:
         result = t
-      else: 
+      else:
         assignType(prev, t)
         result = prev
       markUsed(n.info, n.sym)
@@ -1227,6 +1231,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       result = newOrPrevType(tyError, prev, c)
   of nkObjectTy: result = semObjectNode(c, n, prev)
   of nkTupleTy: result = semTuple(c, n, prev)
+  of nkTupleClassTy: result = newConstraint(c, tyTuple)
   of nkTypeClassTy: result = semTypeClass(c, n, prev)
   of nkRefTy: result = semAnyRef(c, n, tyRef, prev)
   of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
@@ -1267,12 +1272,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     result = newOrPrevType(tyError, prev, c)
   n.typ = result
 
-proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
+proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
   m.typ.kind = kind
   m.typ.align = size.int16
   m.typ.size = size
-  
-proc processMagicType(c: PContext, m: PSym) = 
+
+proc processMagicType(c: PContext, m: PSym) =
   case m.magic
   of mInt: setMagicType(m, tyInt, intSize)
   of mInt8: setMagicType(m, tyInt8, 1)
@@ -1290,21 +1295,21 @@ proc processMagicType(c: PContext, m: PSym) =
   of mFloat128: setMagicType(m, tyFloat128, 16)
   of mBool: setMagicType(m, tyBool, 1)
   of mChar: setMagicType(m, tyChar, 1)
-  of mString: 
+  of mString:
     setMagicType(m, tyString, ptrSize)
     rawAddSon(m.typ, getSysType(tyChar))
-  of mCstring: 
+  of mCstring:
     setMagicType(m, tyCString, ptrSize)
     rawAddSon(m.typ, getSysType(tyChar))
   of mPointer: setMagicType(m, tyPointer, ptrSize)
-  of mEmptySet: 
+  of mEmptySet:
     setMagicType(m, tySet, 1)
     rawAddSon(m.typ, newTypeS(tyEmpty, c))
   of mIntSetBaseType: setMagicType(m, tyRange, intSize)
   of mNil: setMagicType(m, tyNil, ptrSize)
   of mExpr: setMagicType(m, tyExpr, 0)
   of mStmt: setMagicType(m, tyStmt, 0)
-  of mTypeDesc: 
+  of mTypeDesc:
     setMagicType(m, tyTypeDesc, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
   of mVoidType: setMagicType(m, tyEmpty, 0)
@@ -1318,8 +1323,8 @@ proc processMagicType(c: PContext, m: PSym) =
     setMagicType(m, tyRange, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
   of mSet:
-    setMagicType(m, tySet, 0) 
-  of mSeq: 
+    setMagicType(m, tySet, 0)
+  of mSeq:
     setMagicType(m, tySequence, 0)
   of mOrdinal:
     setMagicType(m, tyOrdinal, 0)
@@ -1335,13 +1340,13 @@ proc processMagicType(c: PContext, m: PSym) =
     incl m.typ.flags, tfShared
     rawAddSon(m.typ, sysTypeFromName"shared")
   else: localError(m.info, errTypeExpected)
-  
+
 proc semGenericConstraints(c: PContext, x: PType): PType =
   result = newTypeWithSons(c, tyGenericParam, @[x])
 
-proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = 
+proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
   result = copyNode(n)
-  if n.kind != nkGenericParams: 
+  if n.kind != nkGenericParams:
     illFormedAst(n)
     return
   for i in countup(0, sonsLen(n)-1):
@@ -1351,7 +1356,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
     var def = a{-1}
     let constraint = a{-2}
     var typ: PType
-    
+
     if constraint.kind != nkEmpty:
       typ = semTypeNode(c, constraint, nil)
       if typ.kind != tyStatic or typ.len == 0:
@@ -1360,7 +1365,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
             typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
         else:
           typ = semGenericConstraints(c, typ)
-    
+
     if def.kind != nkEmpty:
       def = semConstExpr(c, def)
       if typ == nil:
@@ -1372,7 +1377,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
         def.typ = def.typ.skipTypes({tyTypeDesc})
         if not containsGenericType(def.typ):
           def = fitNode(c, typ, def)
-    
+
     if typ == nil:
       typ = newTypeS(tyGenericParam, c)
       if father == nil: typ.flags.incl tfWildcard
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 86826567e..012782730 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -341,6 +341,8 @@ proc skipIntLiteralParams*(t: PType) =
 proc propagateFieldFlags(t: PType, n: PNode) =
   # This is meant for objects and tuples
   # The type must be fully instantiated!
+  if n.isNil:
+    return
   internalAssert n.kind != nkRecWhen
   case n.kind
   of nkSym:
@@ -390,9 +392,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
       else:
         result = n.typ
 
-  of tyInt:
+  of tyInt, tyFloat:
     result = skipIntLit(t)
-    # XXX now there are also float literals
   
   of tyTypeDesc:
     let lookup = PType(idTableGet(cl.typeMap, t)) # lookupTypeVar(cl, t)
diff --git a/compiler/service.nim b/compiler/service.nim
index 1d51ef2a1..7cb9d7d29 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -33,7 +33,12 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
     parseopt.next(p)
     case p.kind
     of cmdEnd: break
-    of cmdLongoption, cmdShortOption: processSwitch(pass, p)
+    of cmdLongoption, cmdShortOption:
+      if p.key == " ":
+        p.key = "-"
+        if processArgument(pass, p, argsCount): break
+      else:
+        processSwitch(pass, p)
     of cmdArgument:
       if processArgument(pass, p, argsCount): break
   if pass == passCmd2:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 90d889eb0..6fb50f8e5 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -10,7 +10,7 @@
 ## This module implements the signature matching for resolving
 ## the call to overloaded procs, generic procs and operators.
 
-import 
+import
   intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
   magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees,
   nimfix.pretty
@@ -19,7 +19,7 @@ when not defined(noDocgen):
   import docgen
 
 type
-  TCandidateState* = enum 
+  TCandidateState* = enum
     csEmpty, csMatch, csNoMatch
 
   CandidateErrors* = seq[PSym]
@@ -62,10 +62,10 @@ type
     isGeneric,
     isFromIntLit,            # conversion *from* int literal; proven safe
     isEqual
-  
+
 const
   isNilConversion = isConvertible # maybe 'isIntConv' fits better?
-    
+
 proc markUsed*(info: TLineInfo, s: PSym)
 
 template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
@@ -91,7 +91,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) =
   initIdTable(c.bindings)
 
 proc put(t: var TIdTable, key, val: PType) {.inline.} =
-  idTablePut(t, key, val)
+  idTablePut(t, key, val.skipIntLit)
 
 proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
                     binding: PNode, calleeScope = -1) =
@@ -128,7 +128,7 @@ proc newCandidate*(ctx: PContext, callee: PSym,
 proc newCandidate*(ctx: PContext, callee: PType): TCandidate =
   initCandidate(ctx, result, callee)
 
-proc copyCandidate(a: var TCandidate, b: TCandidate) = 
+proc copyCandidate(a: var TCandidate, b: TCandidate) =
   a.c = b.c
   a.exactMatches = b.exactMatches
   a.subtypeMatches = b.subtypeMatches
@@ -176,7 +176,7 @@ proc complexDisambiguation(a, b: PType): int =
       let bb = b.sons[1].sumGeneric
       var a = a
       var b = b
-      
+
       if aa < bb: swap(a, b)
       # all must be better
       for i in 2 .. <min(a.len, b.len):
@@ -203,7 +203,7 @@ proc cmpCandidates*(a, b: TCandidate): int =
   # prefer more specialized generic over more general generic:
   result = complexDisambiguation(a.callee, b.callee)
 
-proc writeMatches*(c: TCandidate) = 
+proc writeMatches*(c: TCandidate) =
   writeln(stdout, "exact matches: " & $c.exactMatches)
   writeln(stdout, "generic matches: " & $c.genericMatches)
   writeln(stdout, "subtype matches: " & $c.subtypeMatches)
@@ -225,7 +225,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
   result = ""
   for i in countup(startIdx, n.len - 1):
     var arg = n.sons[i]
-    if n.sons[i].kind == nkExprEqExpr: 
+    if n.sons[i].kind == nkExprEqExpr:
       add(result, renderTree(n.sons[i].sons[0]))
       add(result, ": ")
       if arg.typ.isNil:
@@ -241,9 +241,9 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
     if i != sonsLen(n) - 1: add(result, ", ")
 
 proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation
-proc concreteType(c: TCandidate, t: PType): PType = 
+proc concreteType(c: TCandidate, t: PType): PType =
   case t.kind
-  of tyArrayConstr: 
+  of tyArrayConstr:
     # make it an array
     result = newType(tyArray, t.owner)
     addSonSkipIntLit(result, t.sons[0]) # XXX: t.owner is wrong for ID!
@@ -255,7 +255,7 @@ proc concreteType(c: TCandidate, t: PType): PType =
     else: result = t
   of tyGenericParam, tyAnything:
     result = t
-    while true: 
+    while true:
       result = PType(idTableGet(c.bindings, t))
       if result == nil:
         break # it's ok, no match
@@ -267,15 +267,15 @@ proc concreteType(c: TCandidate, t: PType): PType =
     result = t
   else:
     result = t                # Note: empty is valid here
-  
-proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = 
-  if a.kind == f.kind: 
+
+proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
+  if a.kind == f.kind:
     result = isEqual
   else:
     let ab = skipTypes(a, {tyRange})
     let k = ab.kind
     if k == f.kind: result = isSubrange
-    elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64, 
+    elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
                                    tyUInt..tyUInt64} and
         isIntLit(ab) and ab.n.intVal >= firstOrd(f) and
                          ab.n.intVal <= lastOrd(f):
@@ -286,7 +286,7 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
       result = isIntConv
     elif k >= min and k <= max:
       result = isConvertible
-    elif a.kind == tyRange and a.sons[0].kind in {tyInt..tyInt64, 
+    elif a.kind == tyRange and a.sons[0].kind in {tyInt..tyInt64,
                                                   tyUInt8..tyUInt32} and
                          a.n[0].intVal >= firstOrd(f) and
                          a.n[1].intVal <= lastOrd(f):
@@ -318,12 +318,12 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
       if f.kind == tyFloat32: result = isConvertible
       else: result = isIntConv
     else: result = isNone
-  
+
 proc isObjectSubtype(a, f: PType): int =
   var t = a
   assert t.kind == tyObject
   var depth = 0
-  while t != nil and not sameObjectTypes(f, t): 
+  while t != nil and not sameObjectTypes(f, t):
     assert t.kind == tyObject
     t = t.sons[0]
     if t == nil: break
@@ -332,17 +332,17 @@ proc isObjectSubtype(a, f: PType): int =
   if t != nil:
     result = depth
 
-proc minRel(a, b: TTypeRelation): TTypeRelation = 
+proc minRel(a, b: TTypeRelation): TTypeRelation =
   if a <= b: result = a
   else: result = b
-  
+
 proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
   result = isNone
   if sameType(f, a): result = isEqual
   elif sonsLen(a) == sonsLen(f):
     result = isEqual
     let firstField = if f.kind == tyTuple: 0
-                     else: 1 
+                     else: 1
     for i in countup(firstField, sonsLen(f) - 1):
       var m = typeRel(c, f.sons[i], a.sons[i])
       if m < isSubtype: return isNone
@@ -373,7 +373,7 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
       # We are matching a generic proc (as proc param)
       # to another generic type appearing in the proc
       # signature. There is a change that the target
-      # type is already fully-determined, so we are 
+      # type is already fully-determined, so we are
       # going to try resolve it
       f = generateTypeInstance(c.c, c.bindings, c.call.info, f)
       if f == nil or f.isMetaType:
@@ -388,17 +388,17 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
 
   if result <= isSubtype or inconsistentVarTypes(f, a):
     result = isNone
- 
+
   if result == isEqual:
     inc c.exactMatches
-    
+
 proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
   case a.kind
   of tyProc:
     if sonsLen(f) != sonsLen(a): return
     result = isEqual      # start with maximum; also correct for no
                           # params at all
-    
+
     template checkParam(f, a) =
       result = minRel(result, procParamTypeRel(c, f, a))
       if result == isNone: return
@@ -407,7 +407,7 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
     # return type!
     for i in 1 .. <f.sonsLen:
       checkParam(f.sons[i], a.sons[i])
-    
+
     if f.sons[0] != nil:
       if a.sons[0] != nil:
         checkParam(f.sons[0], a.sons[0])
@@ -487,14 +487,14 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
       else:
         param = paramSym skType
         param.typ = makeTypeDesc(c, typ)
-      
+
       addDecl(c, param)
 
   for param in body.n[0]:
     var
       dummyName: PNode
       dummyType: PType
-    
+
     if param.kind == nkVarTy:
       dummyName = param[0]
       dummyType = if a.kind != tyVar: makeVarType(c, a)
@@ -520,7 +520,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
       of nkTypeSection: discard
       of nkConstDef: discard
       else: discard
-    
+
   return isGeneric
 
 proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool =
@@ -554,7 +554,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # typeRel can be used to establish various relationships between types:
   #
   # 1) When used with concrete types, it will check for type equivalence
-  # or a subtype relationship. 
+  # or a subtype relationship.
   #
   # 2) When used with a concrete type against a type class (such as generic
   # signature of a proc), it will check whether the concrete type is a member
@@ -569,9 +569,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   result = isNone
   assert(f != nil)
-  
+
   if f.kind == tyExpr:
-    put(c.bindings, f, aOrig)
+    if aOrig != nil: put(c.bindings, f, aOrig)
     return isGeneric
 
   assert(aOrig != nil)
@@ -582,7 +582,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # start the param matching process. This could be done in `prepareOperand`
   # for example, but unfortunately `prepareOperand` is not called in certain
   # situation when nkDotExpr are rotated to nkDotCalls
-  
+
   if a.kind == tyGenericInst and
       skipTypes(f, {tyVar}).kind notin {
         tyGenericBody, tyGenericInvocation,
@@ -626,9 +626,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       # seq[!int] vs seq[!number]
       # seq[float] matches the first, but not the second
       # we must turn the problem around:
-      # is number a subset of int? 
+      # is number a subset of int?
       return typeRel(c, a.lastSon, f.lastSon)
- 
+
     else:
       # negative type classes are essentially infinite,
       # so only the `any` type class is their superset
@@ -727,20 +727,20 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     of tyOpenArray, tyVarargs:
       result = typeRel(c, base(f), base(a))
       if result < isGeneric: result = isNone
-    of tyArrayConstr: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty): 
+    of tyArrayConstr:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
         result = isSubtype    # [] is allowed here
-      elif typeRel(c, base(f), a.sons[1]) >= isGeneric: 
+      elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
         result = isSubtype
-    of tyArray: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty): 
+    of tyArray:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
         result = isSubtype
-      elif typeRel(c, base(f), a.sons[1]) >= isGeneric: 
+      elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
         result = isConvertible
-    of tySequence: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
+    of tySequence:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
         result = isConvertible
-      elif typeRel(c, base(f), a.sons[0]) >= isGeneric: 
+      elif typeRel(c, base(f), a.sons[0]) >= isGeneric:
         result = isConvertible
     else: discard
   of tySequence:
@@ -768,7 +768,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyForward: internalError("forward type in typeRel()")
   of tyNil:
     if a.kind == f.kind: result = isEqual
-  of tyTuple: 
+  of tyTuple:
     if a.kind == tyTuple: result = recordRel(c, f, a)
   of tyObject:
     if a.kind == tyObject:
@@ -783,13 +783,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyDistinct:
     if (a.kind == tyDistinct) and sameDistinctTypes(f, a): result = isEqual
     elif c.coerceDistincts: result = typeRel(c, f.base, a)
-  of tySet: 
-    if a.kind == tySet: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
+  of tySet:
+    if a.kind == tySet:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
         result = isSubtype
-      else: 
+      else:
         result = typeRel(c, f.sons[0], a.sons[0])
-        if result <= isConvertible: 
+        if result <= isConvertible:
           result = isNone     # BUGFIX!
   of tyPtr, tyRef:
     if a.kind == f.kind:
@@ -823,9 +823,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       if a.len == 1: result = isConvertible
     of tyCString: result = isConvertible
     else: discard
-  of tyString: 
+  of tyString:
     case a.kind
-    of tyString: 
+    of tyString:
       if tfNotNil in f.flags and tfNotNil notin a.flags:
         result = isNilConversion
       else:
@@ -848,7 +848,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     of tyArray:
       if (firstOrd(a.sons[0]) == 0) and
           (skipTypes(a.sons[0], {tyRange}).kind in {tyInt..tyInt64}) and
-          (a.sons[1].kind == tyChar): 
+          (a.sons[1].kind == tyChar):
         result = isConvertible
     else: discard
 
@@ -863,7 +863,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         let ff = rootf.sons[i]
         let aa = roota.sons[i]
         result = typeRel(c, ff, aa)
-        if result == isNone: return        
+        if result == isNone: return
         if ff.kind == tyRange and result != isEqual: return isNone
       result = isGeneric
       # XXX See bug #2220. A[int] should match A[int] better than some generic X
@@ -883,13 +883,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
       # simply no match for now:
       discard
-    elif x.kind == tyGenericInst and 
+    elif x.kind == tyGenericInst and
           (f.sons[0] == x.sons[0]) and
           (sonsLen(x) - 1 == sonsLen(f)):
       for i in countup(1, sonsLen(f) - 1):
         if x.sons[i].kind == tyGenericParam:
           internalError("wrong instantiated type!")
-        elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return 
+        elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return
       result = isGeneric
     else:
       result = typeRel(c, f.sons[0], x)
@@ -900,7 +900,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
           if x == nil or x.kind in {tyGenericInvocation, tyGenericParam}:
             internalError("wrong instantiated type!")
           put(c.bindings, f.sons[i], x)
-  
+
   of tyAnd:
     considerPreviousT:
       for branch in f.sons:
@@ -914,7 +914,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       for branch in f.sons:
         if typeRel(c, branch, aOrig) >= isSubtype:
           bindingRet isGeneric
-       
+
       return isNone
 
   of tyNot:
@@ -922,7 +922,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       for branch in f.sons:
         if typeRel(c, branch, aOrig) != isNone:
           return isNone
-      
+
       bindingRet isGeneric
 
   of tyAnything:
@@ -961,7 +961,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     if x == nil:
       if c.callee.kind == tyGenericBody and
          f.kind == tyGenericParam and not c.typedescMatched:
-        # XXX: The fact that generic types currently use tyGenericParam for 
+        # XXX: The fact that generic types currently use tyGenericParam for
         # their parameters is really a misnomer. tyGenericParam means "match
         # any value" and what we need is "match any type", which can be encoded
         # by a tyTypeDesc params. Unfortunately, this requires more substantial
@@ -1004,7 +1004,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       result = isGeneric
     else:
       result = typeRel(c, x, a) # check if it fits
-  
+
   of tyStatic:
     let prev = PType(idTableGet(c.bindings, f))
     if prev == nil:
@@ -1034,12 +1034,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       # when `f` is an unresolved typedesc, `a` could be any
       # type, so we should not perform this check earlier
       if a.kind != tyTypeDesc: return isNone
-    
+
       if f.base.kind == tyNone:
         result = isGeneric
       else:
         result = typeRel(c, f.base, a.base)
-      
+
       if result != isNone:
         put(c.bindings, f, a)
     else:
@@ -1049,9 +1049,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         result = typeRel(c, prev.base, a.base)
       else:
         result = isNone
- 
+
   of tyIter:
-    if a.kind == tyIter or 
+    if a.kind == tyIter or
       (a.kind == tyProc and tfIterator in a.flags):
       result = typeRel(c, f.base, a.base)
     else:
@@ -1059,7 +1059,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   of tyStmt:
     result = isGeneric
-  
+
   of tyProxy:
     result = isEqual
 
@@ -1078,11 +1078,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     else:
       localError(f.n.info, errTypeExpected)
       result = isNone
-  
+
   else:
     internalAssert false
-  
-proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation = 
+
+proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
   var m: TCandidate
   initCandidate(c, m, f)
   result = typeRel(m, f, a)
@@ -1095,9 +1095,9 @@ proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
   if result == nil:
     internalError(arg.info, "getInstantiatedType")
     result = errorType(c)
-  
-proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, 
-                  c: PContext): PNode = 
+
+proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
+                  c: PContext): PNode =
   result = newNodeI(kind, arg.info)
   if containsGenericType(f):
     if not m.hasFauxMatch:
@@ -1110,10 +1110,10 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
   addSon(result, ast.emptyNode)
   addSon(result, arg)
 
-proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                   arg: PNode): PNode = 
+proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
+                   arg: PNode): PNode =
   result = nil
-  for i in countup(0, len(c.converters) - 1): 
+  for i in countup(0, len(c.converters) - 1):
     var src = c.converters[i].typ.sons[1]
     var dest = c.converters[i].typ.sons[0]
     # for generic type converters we need to check 'src <- a' before
@@ -1121,12 +1121,12 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
     # see tests/tgenericconverter:
     let srca = typeRel(m, src, a)
     if srca notin {isEqual, isGeneric}: continue
-    
+
     let destIsGeneric = containsGenericType(dest)
     if destIsGeneric:
       dest = generateTypeInstance(c, m.bindings, arg, dest)
     let fdest = typeRel(m, f, dest)
-    if fdest in {isEqual, isGeneric}: 
+    if fdest in {isEqual, isGeneric}:
       markUsed(arg.info, c.converters[i])
       var s = newSymNode(c.converters[i])
       s.typ = c.converters[i].typ
@@ -1138,8 +1138,8 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
       m.genericConverter = srca == isGeneric or destIsGeneric
       return result
 
-proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                    arg: PNode): PNode = 
+proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
+                    arg: PNode): PNode =
   # arg.typ can be nil in 'suggest':
   if isNil(arg.typ): return nil
 
@@ -1181,12 +1181,12 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     arg = argSemantized
     argType = argType
     c = m.c
-  
+
   if tfHasStatic in fMaybeStatic.flags:
     # XXX: When implicit statics are the default
     # this will be done earlier - we just have to
     # make sure that static types enter here
-     
+
     # XXX: weaken tyGenericParam and call it tyGenericPlaceholder
     # and finally start using tyTypedesc for generic types properly.
     if argType.kind == tyGenericParam and tfWildcard in argType.flags:
@@ -1205,11 +1205,11 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
         arg.typ.sons = @[evaluated.typ]
         arg.typ.n = evaluated
         argType = arg.typ
- 
+
   var
     a = if c.inTypeClass > 0: argType.skipTypes({tyTypeDesc, tyFieldAccessor})
         else: argType
- 
+
     r = typeRel(m, f, a)
 
   if r != isNone and m.calleeSym != nil and
@@ -1232,7 +1232,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     elif f.kind == tyStatic:
       return arg.typ.n
     else:
-      return argOrig
+      return argSemantized # argOrig
 
   if r != isNone and f.isInlineIterator:
     var inlined = newTypeS(tyStatic, c)
@@ -1244,19 +1244,18 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
   case r
   of isConvertible:
     inc(m.convMatches)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
   of isIntConv:
     # I'm too lazy to introduce another ``*matches`` field, so we conflate
     # ``isIntConv`` and ``isIntLit`` here:
     inc(m.intConvMatches)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isSubtype: 
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
+  of isSubtype:
     inc(m.subtypeMatches)
-    result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
+    result = implicitConv(nkHiddenSubConv, f, arg, m, c)
   of isSubrange:
     inc(m.subtypeMatches)
-    #result = copyTree(arg)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
   of isInferred, isInferredConvertible:
     inc(m.genericMatches)
     if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
@@ -1269,40 +1268,32 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
       result = implicitConv(nkHiddenStdConv, f, result, m, c)
   of isGeneric:
     inc(m.genericMatches)
-    when true:
-      if skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
-        result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-      elif arg.typ != nil and arg.typ.isEmptyContainer:
-        result = arg.copyTree
-        result.typ = getInstantiatedType(c, arg, m, f)
-      else:
-        result = arg
-    else:
-      # XXX Why is this ever necessary? arg's type should not be retrofitted
-      # to match formal's type in this way!
-      result = copyTree(arg)
+    if arg.typ == nil:
+      result = arg
+    elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
+      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+    elif arg.typ.isEmptyContainer:
+      result = arg.copyTree
       result.typ = getInstantiatedType(c, arg, m, f)
-      # BUG: f may not be the right key!
-      if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
-        result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-        # BUGFIX: use ``result.typ`` and not `f` here
+    else:
+      result = arg
   of isFromIntLit:
     # too lazy to introduce another ``*matches`` field, so we conflate
     # ``isIntConv`` and ``isIntLit`` here:
     inc(m.intConvMatches, 256)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isEqual: 
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
+  of isEqual:
     inc(m.exactMatches)
-    result = copyTree(arg)
+    result = arg
     if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
-      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+      result = implicitConv(nkHiddenStdConv, f, arg, m, c)
   of isNone:
     # do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
     if a.kind in {tyProxy, tyUnknown}:
       inc(m.genericMatches)
       m.fauxMatch = a.kind
-      return copyTree(arg)
-    result = userConvMatch(c, m, f, a, arg) 
+      return arg
+    result = userConvMatch(c, m, f, a, arg)
     # check for a base type match, which supports varargs[T] without []
     # constructor in a call:
     if result == nil and f.kind == tyVarargs:
@@ -1323,7 +1314,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
                       arg, argOrig: PNode): PNode =
   if arg == nil or arg.kind notin nkSymChoices:
     result = paramTypesMatchAux(m, f, a, arg, argOrig)
-  else: 
+  else:
     # CAUTION: The order depends on the used hashing scheme. Thus it is
     # incorrect to simply use the first fitting match. However, to implement
     # this correctly is inefficient. We have to copy `m` here to be able to
@@ -1337,28 +1328,28 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
     y.calleeSym = m.calleeSym
     z.calleeSym = m.calleeSym
     var best = -1
-    for i in countup(0, sonsLen(arg) - 1): 
+    for i in countup(0, sonsLen(arg) - 1):
       if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}+skIterators:
         copyCandidate(z, m)
         var r = typeRel(z, f, arg.sons[i].typ)
-        if r != isNone: 
+        if r != isNone:
           case x.state
-          of csEmpty, csNoMatch: 
+          of csEmpty, csNoMatch:
             x = z
             best = i
             x.state = csMatch
-          of csMatch: 
+          of csMatch:
             var cmp = cmpCandidates(x, z)
             if cmp < 0:
               best = i
               x = z
             elif cmp == 0:
               y = z           # z is as good as x
-    if x.state == csEmpty: 
+    if x.state == csEmpty:
       result = nil
-    elif y.state == csMatch and cmpCandidates(x, y) == 0: 
-      if x.state != csMatch: 
-        internalError(arg.info, "x.state is not csMatch") 
+    elif y.state == csMatch and cmpCandidates(x, y) == 0:
+      if x.state != csMatch:
+        internalError(arg.info, "x.state is not csMatch")
       # ambiguous: more than one symbol fits!
       # See tsymchoice_for_expr as an example. 'f.kind == tyExpr' should match
       # anyway:
@@ -1371,7 +1362,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
       result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
                                   argOrig)
 
-proc setSon(father: PNode, at: int, son: PNode) = 
+proc setSon(father: PNode, at: int, son: PNode) =
   if sonsLen(father) <= at: setLen(father.sons, at + 1)
   father.sons[at] = son
 
@@ -1415,7 +1406,7 @@ proc incrIndexType(t: PType) =
   inc t.sons[0].n.sons[1].intVal
 
 proc matchesAux(c: PContext, n, nOrig: PNode,
-                m: var TCandidate, marker: var IntSet) = 
+                m: var TCandidate, marker: var IntSet) =
   template checkConstraint(n: expr) {.immediate, dirty.} =
     if not formal.constraint.isNil:
       if matchNodeKinds(formal.constraint, n):
@@ -1445,20 +1436,20 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       # named param
       # check if m.callee has such a param:
       prepareNamedParam(n.sons[a])
-      if n.sons[a].sons[0].kind != nkIdent: 
+      if n.sons[a].sons[0].kind != nkIdent:
         localError(n.sons[a].info, errNamedParamHasToBeIdent)
         m.state = csNoMatch
-        return 
+        return
       formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
-      if formal == nil: 
+      if formal == nil:
         # no error message!
         m.state = csNoMatch
-        return 
-      if containsOrIncl(marker, formal.position): 
+        return
+      if containsOrIncl(marker, formal.position):
         # already in namedParams:
         localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
         m.state = csNoMatch
-        return 
+        return
       m.baseTypeMatch = false
       n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1])
       n.sons[a].typ = n.sons[a].sons[1].typ
@@ -1468,7 +1459,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         m.state = csNoMatch
         return
       checkConstraint(n.sons[a].sons[1])
-      if m.baseTypeMatch: 
+      if m.baseTypeMatch:
         #assert(container == nil)
         container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
         addSon(container, arg)
@@ -1505,7 +1496,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           m.state = csNoMatch
           return
       else:
-        if m.callee.n.sons[f].kind != nkSym: 
+        if m.callee.n.sons[f].kind != nkSym:
           internalError(n.sons[a].info, "matches")
           return
         formal = m.callee.n.sons[f].sym
@@ -1513,7 +1504,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           # already in namedParams:
           localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
           m.state = csNoMatch
-          return 
+          return
         m.baseTypeMatch = false
         n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
         var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
@@ -1526,7 +1517,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           if container.isNil:
             container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
           addSon(container, arg)
-          setSon(m.call, formal.position + 1, 
+          setSon(m.call, formal.position + 1,
                  implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
           #if f != formalLen - 1: container = nil
 
@@ -1601,7 +1592,7 @@ when not declared(tests):
 
 tests:
   var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
-  
+
   proc `|` (t1, t2: PType): PType =
     result = newType(tyOr, dummyOwner)
     result.rawAddSon(t1)
@@ -1622,12 +1613,12 @@ tests:
 
   proc array(x: int, t: PType): PType =
     result = newType(tyArray, dummyOwner)
-    
+
     var n = newNodeI(nkRange, UnknownLineInfo())
     addSon(n, newIntNode(nkIntLit, 0))
     addSon(n, newIntNode(nkIntLit, x))
     let range = newType(tyRange, dummyOwner)
-    
+
     result.rawAddSon(range)
     result.rawAddSon(t)
 
@@ -1662,7 +1653,7 @@ tests:
     template no(x, y) =
       test astToStr(x) & " is not " & astToStr(y):
         check typeRel(c, y, x) == isNone
-    
+
     yes seq(any), array(10, int) | seq(any)
     # Sure, seq[any] is directly included
 
@@ -1670,16 +1661,16 @@ tests:
     yes seq(int), seq(number)
     # Sure, the int sequence is certainly
     # part of the number sequences (and all sequences)
-    
+
     no seq(any), seq(float)
     # Nope, seq[any] includes types that are not seq[float] (e.g. seq[int])
 
     yes seq(int|string), seq(any)
     # Sure
- 
+
     yes seq(int&string), seq(any)
     # Again
-    
+
     yes seq(int&string), seq(int)
     # A bit more complicated
     # seq[int&string] is not a real type, but it's analogous to
@@ -1688,23 +1679,23 @@ tests:
     no seq(int|string), seq(int|float)
     # Nope, seq[string] is not included in not included in
     # the seq[int|float] set
-    
+
     no seq(!(int|string)), seq(string)
     # A sequence that is neither seq[int] or seq[string]
     # is obviously not seq[string]
-     
+
     no seq(!int), seq(number)
     # Now your head should start to hurt a bit
     # A sequence that is not seq[int] is not necessarily a number sequence
     # it could well be seq[string] for example
-    
+
     yes seq(!(int|string)), seq(!string)
     # all sequnece types besides seq[int] and seq[string]
     # are subset of all sequence types that are not seq[string]
 
     no seq(!(int|string)), seq(!(string|TFoo))
     # Nope, seq[TFoo] is included in the first set, but not in the second
-    
+
     no seq(!string), seq(!number)
     # Nope, seq[int] in included in the first set, but not in the second
 
@@ -1712,7 +1703,7 @@ tests:
     yes seq(!int), seq(any)
     no seq(any), seq(!any)
     no seq(!int), seq(!any)
-    
+
     yes int, ordinal
     no  string, ordinal
 
diff --git a/compiler/types.nim b/compiler/types.nim
index 5c3be7553..5f506f10f 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -9,20 +9,20 @@
 
 # this module contains routines for accessing and iterating over types
 
-import 
+import
   intsets, ast, astalgo, trees, msgs, strutils, platform, renderer
 
 proc firstOrd*(t: PType): BiggestInt
 proc lastOrd*(t: PType): BiggestInt
 proc lengthOrd*(t: PType): BiggestInt
-type 
+type
   TPreferedDesc* = enum
     preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
 
 proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
 proc base*(t: PType): PType
   # ------------------- type iterator: ----------------------------------------
-type 
+type
   TTypeIter* = proc (t: PType, closure: RootRef): bool {.nimcall.} # true if iteration should stop
   TTypeMutator* = proc (t: PType, closure: RootRef): PType {.nimcall.} # copy t and mutate it
   TTypePredicate* = proc (t: PType): bool {.nimcall.}
@@ -32,7 +32,7 @@ proc iterOverType*(t: PType, iter: TTypeIter, closure: RootRef): bool
 proc mutateType*(t: PType, iter: TTypeMutator, closure: RootRef): PType
   # Returns result of `iter`.
 
-type 
+type
   TParamsEquality* = enum     # they are equal, but their
                               # identifiers or their return
                               # type differ (i.e. they cannot be
@@ -59,7 +59,7 @@ const
   abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal,
                    tyTypeDesc}
 
-  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable, 
+  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable,
                tyTypeDesc}
   typedescPtrs* = abstractPtrs + {tyTypeDesc}
   typedescInst* = abstractInst + {tyTypeDesc}
@@ -75,9 +75,9 @@ proc getSize*(typ: PType): BiggestInt
 proc isPureObject*(typ: PType): bool
 proc invalidGenericInst*(f: PType): bool
   # for debugging
-type 
-  TTypeFieldResult* = enum 
-    frNone,                   # type has no object type field 
+type
+  TTypeFieldResult* = enum
+    frNone,                   # type has no object type field
     frHeader,                 # type has an object type field only in the header
     frEmbedded                # type has an object type field somewhere embedded
 
@@ -86,15 +86,15 @@ proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult
   # made or intializing of the type field suffices or if there is no type field
   # at all in this type.
 
-proc invalidGenericInst(f: PType): bool = 
+proc invalidGenericInst(f: PType): bool =
   result = f.kind == tyGenericInst and lastSon(f) == nil
 
-proc isPureObject(typ: PType): bool = 
+proc isPureObject(typ: PType): bool =
   var t = typ
   while t.kind == tyObject and t.sons[0] != nil: t = t.sons[0]
   result = t.sym != nil and sfPure in t.sym.flags
 
-proc getOrdValue(n: PNode): BiggestInt = 
+proc getOrdValue(n: PNode): BiggestInt =
   case n.kind
   of nkCharLit..nkUInt64Lit: result = n.intVal
   of nkNilLit: result = 0
@@ -109,21 +109,21 @@ proc isIntLit*(t: PType): bool {.inline.} =
 proc isFloatLit*(t: PType): bool {.inline.} =
   result = t.kind == tyFloat and t.n != nil and t.n.kind == nkFloatLit
 
-proc isCompatibleToCString(a: PType): bool = 
-  if a.kind == tyArray: 
+proc isCompatibleToCString(a: PType): bool =
+  if a.kind == tyArray:
     if (firstOrd(a.sons[0]) == 0) and
-        (skipTypes(a.sons[0], {tyRange, tyConst, 
-                               tyMutable, tyGenericInst}).kind in 
+        (skipTypes(a.sons[0], {tyRange, tyConst,
+                               tyMutable, tyGenericInst}).kind in
             {tyInt..tyInt64, tyUInt..tyUInt64}) and
-        (a.sons[1].kind == tyChar): 
+        (a.sons[1].kind == tyChar):
       result = true
-  
-proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string = 
+
+proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string =
   result = sym.owner.name.s & '.' & sym.name.s & '('
   var n = sym.typ.n
-  for i in countup(1, sonsLen(n) - 1): 
+  for i in countup(1, sonsLen(n) - 1):
     var p = n.sons[i]
-    if p.kind == nkSym: 
+    if p.kind == nkSym:
       add(result, p.sym.name.s)
       add(result, ": ")
       add(result, typeToString(p.sym.typ, prefer))
@@ -134,7 +134,7 @@ proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string =
   if n.sons[0].typ != nil:
     result.add(": " & typeToString(n.sons[0].typ, prefer))
 
-proc elemType*(t: PType): PType = 
+proc elemType*(t: PType): PType =
   assert(t != nil)
   case t.kind
   of tyGenericInst, tyDistinct: result = elemType(lastSon(t))
@@ -142,10 +142,10 @@ proc elemType*(t: PType): PType =
   else: result = t.lastSon
   assert(result != nil)
 
-proc skipGeneric(t: PType): PType = 
+proc skipGeneric(t: PType): PType =
   result = t
   while result.kind == tyGenericInst: result = lastSon(result)
-      
+
 proc isOrdinalType(t: PType): bool =
   assert(t != nil)
   # caution: uint, uint64 are no ordinal types!
@@ -153,134 +153,134 @@ proc isOrdinalType(t: PType): bool =
       (t.kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
        isOrdinalType(t.sons[0])
 
-proc enumHasHoles(t: PType): bool = 
+proc enumHasHoles(t: PType): bool =
   var b = t
   while b.kind in {tyConst, tyMutable, tyRange, tyGenericInst}: b = b.sons[0]
   result = b.kind == tyEnum and tfEnumHasHoles in b.flags
 
-proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, 
+proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
                      closure: RootRef): bool
-proc iterOverNode(marker: var IntSet, n: PNode, iter: TTypeIter, 
-                  closure: RootRef): bool = 
-  if n != nil: 
+proc iterOverNode(marker: var IntSet, n: PNode, iter: TTypeIter,
+                  closure: RootRef): bool =
+  if n != nil:
     case n.kind
-    of nkNone..nkNilLit: 
+    of nkNone..nkNilLit:
       # a leaf
       result = iterOverTypeAux(marker, n.typ, iter, closure)
-    else: 
-      for i in countup(0, sonsLen(n) - 1): 
+    else:
+      for i in countup(0, sonsLen(n) - 1):
         result = iterOverNode(marker, n.sons[i], iter, closure)
-        if result: return 
-  
-proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, 
-                     closure: RootRef): bool = 
+        if result: return
+
+proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
+                     closure: RootRef): bool =
   result = false
-  if t == nil: return 
+  if t == nil: return
   result = iter(t, closure)
-  if result: return 
-  if not containsOrIncl(marker, t.id): 
+  if result: return
+  if not containsOrIncl(marker, t.id):
     case t.kind
-    of tyGenericInst, tyGenericBody: 
+    of tyGenericInst, tyGenericBody:
       result = iterOverTypeAux(marker, lastSon(t), iter, closure)
-    else: 
-      for i in countup(0, sonsLen(t) - 1): 
+    else:
+      for i in countup(0, sonsLen(t) - 1):
         result = iterOverTypeAux(marker, t.sons[i], iter, closure)
-        if result: return 
+        if result: return
       if t.n != nil: result = iterOverNode(marker, t.n, iter, closure)
-  
-proc iterOverType(t: PType, iter: TTypeIter, closure: RootRef): bool = 
+
+proc iterOverType(t: PType, iter: TTypeIter, closure: RootRef): bool =
   var marker = initIntSet()
   result = iterOverTypeAux(marker, t, iter, closure)
 
-proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
+proc searchTypeForAux(t: PType, predicate: TTypePredicate,
                       marker: var IntSet): bool
 
-proc searchTypeNodeForAux(n: PNode, p: TTypePredicate, 
-                          marker: var IntSet): bool = 
+proc searchTypeNodeForAux(n: PNode, p: TTypePredicate,
+                          marker: var IntSet): bool =
   result = false
   case n.kind
-  of nkRecList: 
-    for i in countup(0, sonsLen(n) - 1): 
+  of nkRecList:
+    for i in countup(0, sonsLen(n) - 1):
       result = searchTypeNodeForAux(n.sons[i], p, marker)
-      if result: return 
-  of nkRecCase: 
+      if result: return
+  of nkRecCase:
     assert(n.sons[0].kind == nkSym)
     result = searchTypeNodeForAux(n.sons[0], p, marker)
-    if result: return 
-    for i in countup(1, sonsLen(n) - 1): 
+    if result: return
+    for i in countup(1, sonsLen(n) - 1):
       case n.sons[i].kind
-      of nkOfBranch, nkElse: 
+      of nkOfBranch, nkElse:
         result = searchTypeNodeForAux(lastSon(n.sons[i]), p, marker)
-        if result: return 
+        if result: return
       else: internalError("searchTypeNodeForAux(record case branch)")
-  of nkSym: 
+  of nkSym:
     result = searchTypeForAux(n.sym.typ, p, marker)
   else: internalError(n.info, "searchTypeNodeForAux()")
-  
-proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
-                      marker: var IntSet): bool = 
+
+proc searchTypeForAux(t: PType, predicate: TTypePredicate,
+                      marker: var IntSet): bool =
   # iterates over VALUE types!
   result = false
-  if t == nil: return 
-  if containsOrIncl(marker, t.id): return 
+  if t == nil: return
+  if containsOrIncl(marker, t.id): return
   result = predicate(t)
-  if result: return 
+  if result: return
   case t.kind
-  of tyObject: 
+  of tyObject:
     result = searchTypeForAux(t.sons[0], predicate, marker)
     if not result: result = searchTypeNodeForAux(t.n, predicate, marker)
-  of tyGenericInst, tyDistinct: 
+  of tyGenericInst, tyDistinct:
     result = searchTypeForAux(lastSon(t), predicate, marker)
-  of tyArray, tyArrayConstr, tySet, tyTuple: 
-    for i in countup(0, sonsLen(t) - 1): 
+  of tyArray, tyArrayConstr, tySet, tyTuple:
+    for i in countup(0, sonsLen(t) - 1):
       result = searchTypeForAux(t.sons[i], predicate, marker)
-      if result: return 
-  else: 
+      if result: return
+  else:
     discard
 
-proc searchTypeFor(t: PType, predicate: TTypePredicate): bool = 
+proc searchTypeFor(t: PType, predicate: TTypePredicate): bool =
   var marker = initIntSet()
   result = searchTypeForAux(t, predicate, marker)
 
-proc isObjectPredicate(t: PType): bool = 
+proc isObjectPredicate(t: PType): bool =
   result = t.kind == tyObject
 
-proc containsObject(t: PType): bool = 
+proc containsObject(t: PType): bool =
   result = searchTypeFor(t, isObjectPredicate)
 
-proc isObjectWithTypeFieldPredicate(t: PType): bool = 
+proc isObjectWithTypeFieldPredicate(t: PType): bool =
   result = t.kind == tyObject and t.sons[0] == nil and
       not (t.sym != nil and {sfPure, sfInfixCall} * t.sym.flags != {}) and
       tfFinal notin t.flags
 
-proc analyseObjectWithTypeFieldAux(t: PType, 
-                                   marker: var IntSet): TTypeFieldResult = 
+proc analyseObjectWithTypeFieldAux(t: PType,
+                                   marker: var IntSet): TTypeFieldResult =
   var res: TTypeFieldResult
   result = frNone
-  if t == nil: return 
+  if t == nil: return
   case t.kind
-  of tyObject: 
-    if (t.n != nil): 
-      if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker): 
+  of tyObject:
+    if (t.n != nil):
+      if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
         return frEmbedded
-    for i in countup(0, sonsLen(t) - 1): 
+    for i in countup(0, sonsLen(t) - 1):
       res = analyseObjectWithTypeFieldAux(t.sons[i], marker)
-      if res == frEmbedded: 
+      if res == frEmbedded:
         return frEmbedded
       if res == frHeader: result = frHeader
-    if result == frNone: 
+    if result == frNone:
       if isObjectWithTypeFieldPredicate(t): result = frHeader
-  of tyGenericInst, tyDistinct, tyConst, tyMutable: 
+  of tyGenericInst, tyDistinct, tyConst, tyMutable:
     result = analyseObjectWithTypeFieldAux(lastSon(t), marker)
-  of tyArray, tyArrayConstr, tyTuple: 
-    for i in countup(0, sonsLen(t) - 1): 
+  of tyArray, tyArrayConstr, tyTuple:
+    for i in countup(0, sonsLen(t) - 1):
       res = analyseObjectWithTypeFieldAux(t.sons[i], marker)
-      if res != frNone: 
+      if res != frNone:
         return frEmbedded
-  else: 
+  else:
     discard
 
-proc analyseObjectWithTypeField(t: PType): TTypeFieldResult = 
+proc analyseObjectWithTypeField(t: PType): TTypeFieldResult =
   var marker = initIntSet()
   result = analyseObjectWithTypeFieldAux(t, marker)
 
@@ -288,7 +288,7 @@ proc isGCRef(t: PType): bool =
   result = t.kind in GcTypeKinds or
     (t.kind == tyProc and t.callConv == ccClosure)
 
-proc containsGarbageCollectedRef(typ: PType): bool = 
+proc containsGarbageCollectedRef(typ: PType): bool =
   # returns true if typ contains a reference, sequence or string (all the
   # things that are garbage-collected)
   result = searchTypeFor(typ, isGCRef)
@@ -296,47 +296,47 @@ proc containsGarbageCollectedRef(typ: PType): bool =
 proc isTyRef(t: PType): bool =
   result = t.kind == tyRef or (t.kind == tyProc and t.callConv == ccClosure)
 
-proc containsTyRef*(typ: PType): bool = 
+proc containsTyRef*(typ: PType): bool =
   # returns true if typ contains a 'ref'
   result = searchTypeFor(typ, isTyRef)
 
-proc isHiddenPointer(t: PType): bool = 
+proc isHiddenPointer(t: PType): bool =
   result = t.kind in {tyString, tySequence}
 
-proc containsHiddenPointer(typ: PType): bool = 
+proc containsHiddenPointer(typ: PType): bool =
   # returns true if typ contains a string, table or sequence (all the things
   # that need to be copied deeply)
   result = searchTypeFor(typ, isHiddenPointer)
 
 proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool
-proc canFormAcycleNode(marker: var IntSet, n: PNode, startId: int): bool = 
+proc canFormAcycleNode(marker: var IntSet, n: PNode, startId: int): bool =
   result = false
-  if n != nil: 
+  if n != nil:
     result = canFormAcycleAux(marker, n.typ, startId)
-    if not result: 
+    if not result:
       case n.kind
-      of nkNone..nkNilLit: 
+      of nkNone..nkNilLit:
         discard
-      else: 
-        for i in countup(0, sonsLen(n) - 1): 
+      else:
+        for i in countup(0, sonsLen(n) - 1):
           result = canFormAcycleNode(marker, n.sons[i], startId)
-          if result: return 
-  
-proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool = 
+          if result: return
+
+proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
   result = false
-  if typ == nil: return 
-  if tfAcyclic in typ.flags: return 
+  if typ == nil: return
+  if tfAcyclic in typ.flags: return
   var t = skipTypes(typ, abstractInst-{tyTypeDesc})
-  if tfAcyclic in t.flags: return 
+  if tfAcyclic in t.flags: return
   case t.kind
   of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
      tyVarargs:
-    if not containsOrIncl(marker, t.id): 
-      for i in countup(0, sonsLen(t) - 1): 
+    if not containsOrIncl(marker, t.id):
+      for i in countup(0, sonsLen(t) - 1):
         result = canFormAcycleAux(marker, t.sons[i], startId)
-        if result: return 
+        if result: return
       if t.n != nil: result = canFormAcycleNode(marker, t.n, startId)
-    else: 
+    else:
       result = t.id == startId
     # Inheritance can introduce cyclic types, however this is not relevant
     # as the type that is passed to 'new' is statically known!
@@ -351,29 +351,29 @@ proc canFormAcycle(typ: PType): bool =
   var marker = initIntSet()
   result = canFormAcycleAux(marker, typ, typ.id)
 
-proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, 
+proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator,
                    closure: RootRef): PType
-proc mutateNode(marker: var IntSet, n: PNode, iter: TTypeMutator, 
-                closure: RootRef): PNode = 
+proc mutateNode(marker: var IntSet, n: PNode, iter: TTypeMutator,
+                closure: RootRef): PNode =
   result = nil
-  if n != nil: 
+  if n != nil:
     result = copyNode(n)
     result.typ = mutateTypeAux(marker, n.typ, iter, closure)
     case n.kind
-    of nkNone..nkNilLit: 
+    of nkNone..nkNilLit:
       # a leaf
       discard
-    else: 
-      for i in countup(0, sonsLen(n) - 1): 
+    else:
+      for i in countup(0, sonsLen(n) - 1):
         addSon(result, mutateNode(marker, n.sons[i], iter, closure))
-  
-proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, 
-                   closure: RootRef): PType = 
+
+proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator,
+                   closure: RootRef): PType =
   result = nil
-  if t == nil: return 
+  if t == nil: return
   result = iter(t, closure)
-  if not containsOrIncl(marker, t.id): 
-    for i in countup(0, sonsLen(t) - 1): 
+  if not containsOrIncl(marker, t.id):
+    for i in countup(0, sonsLen(t) - 1):
       result.sons[i] = mutateTypeAux(marker, result.sons[i], iter, closure)
     if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure)
   assert(result != nil)
@@ -393,7 +393,7 @@ proc rangeToStr(n: PNode): string =
   assert(n.kind == nkRange)
   result = valueToString(n.sons[0]) & ".." & valueToString(n.sons[1])
 
-const 
+const
   typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
     "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
     "GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
@@ -414,7 +414,7 @@ const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
 proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
   var t = typ
   result = ""
-  if t == nil: return 
+  if t == nil: return
   if prefer in preferToResolveSymbols and t.sym != nil and
        sfAnon notin t.sym.flags:
     if t.kind == tyInt and isIntLit(t):
@@ -484,47 +484,51 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     result = "expr"
   of tyFromExpr, tyFieldAccessor:
     result = renderTree(t.n)
-  of tyArray: 
-    if t.sons[0].kind == tyRange: 
+  of tyArray:
+    if t.sons[0].kind == tyRange:
       result = "array[" & rangeToStr(t.sons[0].n) & ", " &
           typeToString(t.sons[1]) & ']'
-    else: 
+    else:
       result = "array[" & typeToString(t.sons[0]) & ", " &
           typeToString(t.sons[1]) & ']'
-  of tyArrayConstr: 
+  of tyArrayConstr:
     result = "Array constructor[" & rangeToStr(t.sons[0].n) & ", " &
         typeToString(t.sons[1]) & ']'
-  of tySequence: 
+  of tySequence:
     result = "seq[" & typeToString(t.sons[0]) & ']'
-  of tyOrdinal: 
+  of tyOrdinal:
     result = "ordinal[" & typeToString(t.sons[0]) & ']'
-  of tySet: 
+  of tySet:
     result = "set[" & typeToString(t.sons[0]) & ']'
-  of tyOpenArray: 
+  of tyOpenArray:
     result = "openarray[" & typeToString(t.sons[0]) & ']'
   of tyDistinct:
     result = "distinct " & typeToString(t.sons[0],
       if prefer == preferModuleInfo: preferModuleInfo else: preferName)
-  of tyTuple: 
+  of tyTuple:
     # we iterate over t.sons here, because t.n may be nil
-    result = "tuple["
-    if t.n != nil: 
+    if t.n != nil:
+      result = "tuple["
       assert(sonsLen(t.n) == sonsLen(t))
-      for i in countup(0, sonsLen(t.n) - 1): 
+      for i in countup(0, sonsLen(t.n) - 1):
         assert(t.n.sons[i].kind == nkSym)
         add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
         if i < sonsLen(t.n) - 1: add(result, ", ")
-    else: 
-      for i in countup(0, sonsLen(t) - 1): 
+      add(result, ']')
+    elif sonsLen(t) == 0:
+      result = "tuple[]"
+    else:
+      result = "("
+      for i in countup(0, sonsLen(t) - 1):
         add(result, typeToString(t.sons[i]))
         if i < sonsLen(t) - 1: add(result, ", ")
-    add(result, ']')
-  of tyPtr, tyRef, tyVar, tyMutable, tyConst: 
+      add(result, ')')
+  of tyPtr, tyRef, tyVar, tyMutable, tyConst:
     result = typeToStr[t.kind]
     if t.len >= 2:
       setLen(result, result.len-1)
       result.add '['
-      for i in countup(0, sonsLen(t) - 1): 
+      for i in countup(0, sonsLen(t) - 1):
         add(result, typeToString(t.sons[i]))
         if i < sonsLen(t) - 1: add(result, ", ")
       result.add ']'
@@ -536,7 +540,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       result.add("(" & typeToString(t.sons[0]) & ")")
   of tyProc:
     result = if tfIterator in t.flags: "iterator (" else: "proc ("
-    for i in countup(1, sonsLen(t) - 1): 
+    for i in countup(1, sonsLen(t) - 1):
       add(result, typeToString(t.sons[i]))
       if i < sonsLen(t) - 1: add(result, ", ")
     add(result, ')')
@@ -554,29 +558,29 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     if len(prag) != 0: add(result, "{." & prag & ".}")
   of tyVarargs, tyIter:
     result = typeToStr[t.kind] % typeToString(t.sons[0])
-  else: 
+  else:
     result = typeToStr[t.kind]
   if tfShared in t.flags: result = "shared " & result
   if tfNotNil in t.flags: result.add(" not nil")
 
-proc resultType(t: PType): PType = 
+proc resultType(t: PType): PType =
   assert(t.kind == tyProc)
   result = t.sons[0]          # nil is allowed
-  
-proc base(t: PType): PType = 
+
+proc base(t: PType): PType =
   result = t.sons[0]
 
-proc firstOrd(t: PType): BiggestInt = 
+proc firstOrd(t: PType): BiggestInt =
   case t.kind
   of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
     result = 0
   of tySet, tyVar: result = firstOrd(t.sons[0])
   of tyArray, tyArrayConstr: result = firstOrd(t.sons[0])
-  of tyRange: 
+  of tyRange:
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
     result = getOrdValue(t.n.sons[0])
-  of tyInt: 
+  of tyInt:
     if platform.intSize == 4: result = - (2147483646) - 2
     else: result = 0x8000000000000000'i64
   of tyInt8: result = - 128
@@ -584,11 +588,11 @@ proc firstOrd(t: PType): BiggestInt =
   of tyInt32: result = - 2147483646 - 2
   of tyInt64: result = 0x8000000000000000'i64
   of tyUInt..tyUInt64: result = 0
-  of tyEnum: 
+  of tyEnum:
     # if basetype <> nil then return firstOrd of basetype
-    if (sonsLen(t) > 0) and (t.sons[0] != nil): 
+    if (sonsLen(t) > 0) and (t.sons[0] != nil):
       result = firstOrd(t.sons[0])
-    else: 
+    else:
       assert(t.n.sons[0].kind == nkSym)
       result = t.n.sons[0].sym.position
   of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc, tyFieldAccessor:
@@ -600,31 +604,31 @@ proc firstOrd(t: PType): BiggestInt =
     internalError("invalid kind for first(" & $t.kind & ')')
     result = 0
 
-proc lastOrd(t: PType): BiggestInt = 
+proc lastOrd(t: PType): BiggestInt =
   case t.kind
   of tyBool: result = 1
   of tyChar: result = 255
   of tySet, tyVar: result = lastOrd(t.sons[0])
   of tyArray, tyArrayConstr: result = lastOrd(t.sons[0])
-  of tyRange: 
+  of tyRange:
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
     result = getOrdValue(t.n.sons[1])
-  of tyInt: 
+  of tyInt:
     if platform.intSize == 4: result = 0x7FFFFFFF
     else: result = 0x7FFFFFFFFFFFFFFF'i64
   of tyInt8: result = 0x0000007F
   of tyInt16: result = 0x00007FFF
   of tyInt32: result = 0x7FFFFFFF
   of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyUInt: 
+  of tyUInt:
     if platform.intSize == 4: result = 0xFFFFFFFF
     else: result = 0x7FFFFFFFFFFFFFFF'i64
   of tyUInt8: result = 0xFF
   of tyUInt16: result = 0xFFFF
   of tyUInt32: result = 0xFFFFFFFF
   of tyUInt64: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyEnum: 
+  of tyEnum:
     assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
     result = t.n.sons[sonsLen(t.n) - 1].sym.position
   of tyGenericInst, tyDistinct, tyConst, tyMutable,
@@ -638,7 +642,7 @@ proc lastOrd(t: PType): BiggestInt =
     internalError("invalid kind for last(" & $t.kind & ')')
     result = 0
 
-proc lengthOrd(t: PType): BiggestInt = 
+proc lengthOrd(t: PType): BiggestInt =
   case t.kind
   of tyInt64, tyInt32, tyInt: result = lastOrd(t)
   of tyDistinct, tyConst, tyMutable: result = lengthOrd(t.sons[0])
@@ -654,7 +658,7 @@ type
     dcEqOrDistinctOf       ## a equals b or a is distinct of b
 
   TTypeCmpFlag* = enum
-    IgnoreTupleFields
+    IgnoreTupleFields      ## NOTE: Only set this flag for backends!
     IgnoreCC
     ExactTypeDescValues
     ExactGenericParams
@@ -673,7 +677,7 @@ type
 proc initSameTypeClosure: TSameTypeClosure =
   # we do the initialization lazily for performance (avoids memory allocations)
   discard
-  
+
 proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool =
   result = not isNil(c.s) and c.s.contains((a.id, b.id))
   if not result:
@@ -700,17 +704,17 @@ proc sameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
     if a == nil or b == nil: result = false
     else: result = sameType(a, b, flags)
 
-proc equalParam(a, b: PSym): TParamsEquality = 
+proc equalParam(a, b: PSym): TParamsEquality =
   if sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}) and
       exprStructuralEquivalent(a.constraint, b.constraint):
-    if a.ast == b.ast: 
+    if a.ast == b.ast:
       result = paramsEqual
-    elif a.ast != nil and b.ast != nil: 
+    elif a.ast != nil and b.ast != nil:
       if exprStructuralEquivalent(a.ast, b.ast): result = paramsEqual
       else: result = paramsIncompatible
-    elif a.ast != nil: 
+    elif a.ast != nil:
       result = paramsEqual
-    elif b.ast != nil: 
+    elif b.ast != nil:
       result = paramsIncompatible
   else:
     result = paramsNotEqual
@@ -723,70 +727,70 @@ proc sameConstraints(a, b: PNode): bool =
       return false
   return true
 
-proc equalParams(a, b: PNode): TParamsEquality = 
+proc equalParams(a, b: PNode): TParamsEquality =
   result = paramsEqual
   var length = sonsLen(a)
-  if length != sonsLen(b): 
+  if length != sonsLen(b):
     result = paramsNotEqual
-  else: 
-    for i in countup(1, length - 1): 
+  else:
+    for i in countup(1, length - 1):
       var m = a.sons[i].sym
       var n = b.sons[i].sym
       assert((m.kind == skParam) and (n.kind == skParam))
       case equalParam(m, n)
-      of paramsNotEqual: 
+      of paramsNotEqual:
         return paramsNotEqual
-      of paramsEqual: 
+      of paramsEqual:
         discard
-      of paramsIncompatible: 
+      of paramsIncompatible:
         result = paramsIncompatible
-      if (m.name.id != n.name.id): 
+      if (m.name.id != n.name.id):
         # BUGFIX
         return paramsNotEqual # paramsIncompatible;
       # continue traversal! If not equal, we can return immediately; else
       # it stays incompatible
     if not sameTypeOrNil(a.sons[0].typ, b.sons[0].typ, {ExactTypeDescValues}):
-      if (a.sons[0].typ == nil) or (b.sons[0].typ == nil): 
+      if (a.sons[0].typ == nil) or (b.sons[0].typ == nil):
         result = paramsNotEqual # one proc has a result, the other not is OK
-      else: 
+      else:
         result = paramsIncompatible # overloading by different
                                     # result types does not work
-  
-proc sameLiteral(x, y: PNode): bool = 
-  if x.kind == y.kind: 
+
+proc sameLiteral(x, y: PNode): bool =
+  if x.kind == y.kind:
     case x.kind
     of nkCharLit..nkInt64Lit: result = x.intVal == y.intVal
     of nkFloatLit..nkFloat64Lit: result = x.floatVal == y.floatVal
     of nkNilLit: result = true
     else: assert(false)
-  
-proc sameRanges(a, b: PNode): bool = 
+
+proc sameRanges(a, b: PNode): bool =
   result = sameLiteral(a.sons[0], b.sons[0]) and
            sameLiteral(a.sons[1], b.sons[1])
 
-proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool = 
+proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
   # two tuples are equivalent iff the names, types and positions are the same;
   # however, both types may not have any field names (t.n may be nil) which
   # complicates the matter a bit.
   if sonsLen(a) == sonsLen(b):
     result = true
-    for i in countup(0, sonsLen(a) - 1): 
+    for i in countup(0, sonsLen(a) - 1):
       var x = a.sons[i]
       var y = b.sons[i]
       if IgnoreTupleFields in c.flags:
-        x = skipTypes(x, {tyRange})
-        y = skipTypes(y, {tyRange})
-      
+        x = skipTypes(x, {tyRange, tyGenericInst})
+        y = skipTypes(y, {tyRange, tyGenericInst})
+
       result = sameTypeAux(x, y, c)
-      if not result: return 
+      if not result: return
     if a.n != nil and b.n != nil and IgnoreTupleFields notin c.flags:
-      for i in countup(0, sonsLen(a.n) - 1): 
-        # check field names: 
+      for i in countup(0, sonsLen(a.n) - 1):
+        # check field names:
         if a.n.sons[i].kind == nkSym and b.n.sons[i].kind == nkSym:
           var x = a.n.sons[i].sym
           var y = b.n.sons[i].sym
           result = x.name.id == y.name.id
-          if not result: break 
+          if not result: break
         else: internalError(a.n.info, "sameTuple")
 
 template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
@@ -797,7 +801,7 @@ template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
     # expensive structural equality test; however due to the way generic and
     # objects work, if one of the types does **not** contain tfFromGeneric,
     # they cannot be equal. The check ``a.sym.id == b.sym.id`` checks
-    # for the same origin and is essential because we don't want "pure" 
+    # for the same origin and is essential because we don't want "pure"
     # structural type equivalence:
     #
     # type
@@ -823,8 +827,13 @@ proc sameEnumTypes*(a, b: PType): bool {.inline.} =
 proc sameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
   if a == b:
     result = true
-  elif (a != nil) and (b != nil) and (a.kind == b.kind):
-    if sameTypeOrNilAux(a.typ, b.typ, c):
+  elif a != nil and b != nil and a.kind == b.kind:
+    var x = a.typ
+    var y = b.typ
+    if IgnoreTupleFields in c.flags:
+      if x != nil: x = skipTypes(x, {tyRange, tyGenericInst})
+      if y != nil: y = skipTypes(y, {tyRange, tyGenericInst})
+    if sameTypeOrNilAux(x, y, c):
       case a.kind
       of nkSym:
         # same symbol as string is enough:
@@ -835,9 +844,9 @@ proc sameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
       of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
       of nkEmpty, nkNilLit, nkType: result = true
       else:
-        if sonsLen(a) == sonsLen(b): 
-          for i in countup(0, sonsLen(a) - 1): 
-            if not sameObjectTree(a.sons[i], b.sons[i], c): return 
+        if sonsLen(a) == sonsLen(b):
+          for i in countup(0, sonsLen(a) - 1):
+            if not sameObjectTree(a.sons[i], b.sons[i], c): return
           result = true
 
 proc sameObjectStructures(a, b: PType, c: var TSameTypeClosure): bool =
@@ -853,7 +862,7 @@ proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool =
   result = true
   for i in countup(0, sonsLen(a) - 1):
     result = sameTypeOrNilAux(a.sons[i], b.sons[i], c)
-    if not result: return 
+    if not result: return
 
 proc isGenericAlias*(t: PType): bool =
   return t.kind == tyGenericInst and t.lastSon.kind == tyGenericInst
@@ -866,7 +875,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     # believe it or not, the direct check for ``containsOrIncl(c, a, b)``
     # increases bootstrapping time from 2.4s to 3.3s on my laptop! So we cheat
     # again: Since the recursion check is only to not get caught in an endless
-    # recursion, we use a counter and only if it's value is over some 
+    # recursion, we use a counter and only if it's value is over some
     # threshold we perform the expensive exact cycle check:
     if c.recCheck < 3:
       inc c.recCheck
@@ -874,11 +883,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
       if containsOrIncl(c, a, b): return true
 
   proc sameFlags(a, b: PType): bool {.inline.} =
-    result = eqTypeFlags*a.flags == eqTypeFlags*b.flags   
+    result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
 
   if x == y: return true
   var a = skipTypes(x, {tyGenericInst})
-  var b = skipTypes(y, {tyGenericInst})  
+  var b = skipTypes(y, {tyGenericInst})
   assert(a != nil)
   assert(b != nil)
   if a.kind != b.kind:
@@ -891,7 +900,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     of dcEqOrDistinctOf:
       while a.kind == tyDistinct: a = a.sons[0]
       if a.kind != b.kind: return false
-  
+
   if x.kind == tyGenericInst:
     let
       lhs = x.skipGenericAlias
@@ -916,11 +925,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
       result = sameObjectStructures(a, b, c) and sameFlags(a, b)
   of tyDistinct:
     cycleCheck()
-    if c.cmp == dcEq:      
+    if c.cmp == dcEq:
       if sameFlags(a, b):
         ifFastObjectTypeCheckFailed(a, b):
-          result = sameTypeAux(a.sons[0], b.sons[0], c)     
-    else: 
+          result = sameTypeAux(a.sons[0], b.sons[0], c)
+    else:
       result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b)
   of tyEnum, tyForward:
     # XXX generic enums do not make much sense, but require structural checking
@@ -957,13 +966,13 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
         sameValue(a.n.sons[0], b.n.sons[0]) and
         sameValue(a.n.sons[1], b.n.sons[1])
   of tyGenericInst: discard
-  of tyNone: result = false  
+  of tyNone: result = false
 
 proc sameBackendType*(x, y: PType): bool =
   var c = initSameTypeClosure()
   c.flags.incl IgnoreTupleFields
   result = sameTypeAux(x, y, c)
-  
+
 proc compareTypes*(x, y: PType,
                    cmp: TDistinctCompare = dcEq,
                    flags: TTypeCmpFlags = {}): bool =
@@ -972,8 +981,8 @@ proc compareTypes*(x, y: PType,
   c.cmp = cmp
   c.flags = flags
   result = sameTypeAux(x, y, c)
-  
-proc inheritanceDiff*(a, b: PType): int = 
+
+proc inheritanceDiff*(a, b: PType): int =
   # | returns: 0 iff `a` == `b`
   # | returns: -x iff `a` is the x'th direct superclass of `b`
   # | returns: +x iff `a` is the x'th direct subclass of `b`
@@ -985,14 +994,14 @@ proc inheritanceDiff*(a, b: PType): int =
   result = 0
   while x != nil:
     x = skipTypes(x, skipPtrs)
-    if sameObjectTypes(x, b): return 
+    if sameObjectTypes(x, b): return
     x = x.sons[0]
     dec(result)
   var y = b
   result = 0
   while y != nil:
     y = skipTypes(y, skipPtrs)
-    if sameObjectTypes(y, a): return 
+    if sameObjectTypes(y, a): return
     y = y.sons[0]
     inc(result)
   result = high(int)
@@ -1066,7 +1075,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     if kind == skConst: return t
     var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc})
     case t2.kind
-    of tyVar: 
+    of tyVar:
       if taHeap notin flags: result = t2 # ``var var`` is illegal on the heap
     of tyOpenArray:
       if kind != skParam: result = t
@@ -1075,9 +1084,9 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
       if kind notin {skParam, skResult}: result = t
       else: result = typeAllowedAux(marker, t2, kind, flags)
   of tyProc:
-    for i in countup(1, sonsLen(t) - 1): 
+    for i in countup(1, sonsLen(t) - 1):
       result = typeAllowedAux(marker, t.sons[i], skParam, flags)
-      if result != nil: break 
+      if result != nil: break
     if result.isNil and t.sons[0] != nil:
       result = typeAllowedAux(marker, t.sons[0], skResult, flags)
   of tyExpr, tyStmt, tyTypeDesc, tyStatic:
@@ -1092,7 +1101,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     result = t
   of tyNil:
     if kind != skConst: result = t
-  of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer: 
+  of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer:
     result = nil
   of tyOrdinal:
     if kind != skParam: result = t
@@ -1132,13 +1141,13 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     # prevent cascading errors:
     result = nil
 
-proc typeAllowed*(t: PType, kind: TSymKind): PType = 
+proc typeAllowed*(t: PType, kind: TSymKind): PType =
   # returns 'nil' on success and otherwise the part of the type that is
   # wrong!
   var marker = initIntSet()
   result = typeAllowedAux(marker, t, kind, {})
 
-proc align(address, alignment: BiggestInt): BiggestInt = 
+proc align(address, alignment: BiggestInt): BiggestInt =
   result = (address + (alignment - 1)) and not (alignment - 1)
 
 const
@@ -1147,17 +1156,17 @@ const
   szUnknownSize* = -1
 
 proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt
-proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt = 
+proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt =
   var maxAlign, maxSize, b, res: BiggestInt
   case n.kind
-  of nkRecCase: 
+  of nkRecCase:
     assert(n.sons[0].kind == nkSym)
     result = computeRecSizeAux(n.sons[0], a, currOffset)
     maxSize = 0
     maxAlign = 1
-    for i in countup(1, sonsLen(n) - 1): 
+    for i in countup(1, sonsLen(n) - 1):
       case n.sons[i].kind
-      of nkOfBranch, nkElse: 
+      of nkOfBranch, nkElse:
         res = computeRecSizeAux(lastSon(n.sons[i]), b, currOffset)
         if res < 0: return res
         maxSize = max(maxSize, res)
@@ -1166,17 +1175,17 @@ proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt =
     currOffset = align(currOffset, maxAlign) + maxSize
     result = align(result, maxAlign) + maxSize
     a = maxAlign
-  of nkRecList: 
+  of nkRecList:
     result = 0
     maxAlign = 1
-    for i in countup(0, sonsLen(n) - 1): 
+    for i in countup(0, sonsLen(n) - 1):
       res = computeRecSizeAux(n.sons[i], b, currOffset)
       if res < 0: return res
       currOffset = align(currOffset, b) + res
       result = align(result, b) + res
       if b > maxAlign: maxAlign = b
     a = maxAlign
-  of nkSym: 
+  of nkSym:
     result = computeSizeAux(n.sym.typ, a)
     n.sym.offset = int(currOffset)
   else:
@@ -1193,31 +1202,31 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     # size already computed
     result = typ.size
     a = typ.align
-    return 
+    return
   typ.size = szIllegalRecursion # mark as being computed
   case typ.kind
-  of tyInt, tyUInt: 
+  of tyInt, tyUInt:
     result = intSize
     a = result
-  of tyInt8, tyUInt8, tyBool, tyChar: 
+  of tyInt8, tyUInt8, tyBool, tyChar:
     result = 1
     a = result
-  of tyInt16, tyUInt16: 
+  of tyInt16, tyUInt16:
     result = 2
     a = result
-  of tyInt32, tyUInt32, tyFloat32: 
+  of tyInt32, tyUInt32, tyFloat32:
     result = 4
     a = result
-  of tyInt64, tyUInt64, tyFloat64: 
+  of tyInt64, tyUInt64, tyFloat64:
     result = 8
     a = result
   of tyFloat128:
     result = 16
     a = result
-  of tyFloat: 
+  of tyFloat:
     result = floatSize
     a = result
-  of tyProc: 
+  of tyProc:
     if typ.callConv == ccClosure: result = 2 * ptrSize
     else: result = ptrSize
     a = ptrSize
@@ -1232,17 +1241,17 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     let elemSize = computeSizeAux(typ.sons[1], a)
     if elemSize < 0: return elemSize
     result = lengthOrd(typ.sons[0]) * elemSize
-  of tyEnum: 
-    if firstOrd(typ) < 0: 
+  of tyEnum:
+    if firstOrd(typ) < 0:
       result = 4              # use signed int32
-    else: 
+    else:
       length = lastOrd(typ)   # BUGFIX: use lastOrd!
       if length + 1 < `shl`(1, 8): result = 1
       elif length + 1 < `shl`(1, 16): result = 2
       elif length + 1 < `shl`(BiggestInt(1), 32): result = 4
       else: result = 8
     a = result
-  of tySet: 
+  of tySet:
     length = lengthOrd(typ.sons[0])
     if length <= 8: result = 1
     elif length <= 16: result = 2
@@ -1251,32 +1260,32 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     elif align(length, 8) mod 8 == 0: result = align(length, 8) div 8
     else: result = align(length, 8) div 8 + 1
     a = result
-  of tyRange: 
+  of tyRange:
     result = computeSizeAux(typ.sons[0], a)
-  of tyTuple: 
+  of tyTuple:
     result = 0
     maxAlign = 1
-    for i in countup(0, sonsLen(typ) - 1): 
+    for i in countup(0, sonsLen(typ) - 1):
       res = computeSizeAux(typ.sons[i], a)
       if res < 0: return res
       maxAlign = max(maxAlign, a)
       result = align(result, a) + res
     result = align(result, maxAlign)
     a = maxAlign
-  of tyObject: 
-    if typ.sons[0] != nil: 
+  of tyObject:
+    if typ.sons[0] != nil:
       result = computeSizeAux(typ.sons[0], a)
-      if result < 0: return 
+      if result < 0: return
       maxAlign = a
-    elif isObjectWithTypeFieldPredicate(typ): 
+    elif isObjectWithTypeFieldPredicate(typ):
       result = intSize
       maxAlign = result
-    else: 
+    else:
       result = 0
       maxAlign = 1
     currOffset = result
     result = computeRecSizeAux(typ.n, a, currOffset)
-    if result < 0: return 
+    if result < 0: return
     if a < maxAlign: a = maxAlign
     result = align(result, a)
   of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst, tyIter:
@@ -1290,7 +1299,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
   typ.size = result
   typ.align = int16(a)
 
-proc computeSize(typ: PType): BiggestInt = 
+proc computeSize(typ: PType): BiggestInt =
   var a: BiggestInt = 1
   result = computeSizeAux(typ, a)
 
@@ -1299,7 +1308,7 @@ proc getReturnType*(s: PSym): PType =
   assert s.kind in skProcKinds
   result = s.typ.sons[0]
 
-proc getSize(typ: PType): BiggestInt = 
+proc getSize(typ: PType): BiggestInt =
   result = computeSize(typ)
   if result < 0: internalError("getSize: " & $typ.kind)
 
@@ -1317,7 +1326,7 @@ proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
 
   return false
 
-proc containsGenericType*(t: PType): bool = 
+proc containsGenericType*(t: PType): bool =
   result = iterOverType(t, containsGenericTypeIter, nil)
 
 proc baseOfDistinct*(t: PType): PType =
@@ -1336,7 +1345,7 @@ proc baseOfDistinct*(t: PType): PType =
 
 proc safeInheritanceDiff*(a, b: PType): int =
   # same as inheritanceDiff but checks for tyError:
-  if a.kind == tyError or b.kind == tyError: 
+  if a.kind == tyError or b.kind == tyError:
     result = -1
   else:
     result = inheritanceDiff(a, b)
@@ -1356,7 +1365,7 @@ proc compatibleEffects*(formal, actual: PType): bool =
   assert formal.kind == tyProc and actual.kind == tyProc
   internalAssert formal.n.sons[0].kind == nkEffectList
   internalAssert actual.n.sons[0].kind == nkEffectList
-  
+
   var spec = formal.n.sons[0]
   if spec.len != 0:
     var real = actual.n.sons[0]
diff --git a/compiler/typesrenderer.nim b/compiler/typesrenderer.nim
index 995fe7f50..700356ab7 100644
--- a/compiler/typesrenderer.nim
+++ b/compiler/typesrenderer.nim
@@ -68,7 +68,6 @@ proc renderType(n: PNode): string =
       assert n[i].kind == nkIdent
       result.add(',' & typeStr)
   of nkTupleTy:
-    assert len(n) > 0
     result = "tuple["
     for i in 0 .. <len(n): result.add(renderType(n[i]) & ',')
     result[<len(result)] = ']'
diff --git a/compiler/vm.nim b/compiler/vm.nim
index e96b89f49..f0a0135e8 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -239,7 +239,7 @@ proc pushSafePoint(f: PStackFrame; pc: int) =
 
 proc popSafePoint(f: PStackFrame) = discard f.safePoints.pop()
 
-proc cleanUpOnException(c: PCtx; tos: PStackFrame): 
+proc cleanUpOnException(c: PCtx; tos: PStackFrame):
                                               tuple[pc: int, f: PStackFrame] =
   let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs)
   var f = tos
@@ -257,7 +257,7 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
       let exceptType = c.types[c.code[pc2].regBx-wordExcess].skipTypes(
                           abstractPtrs)
       if inheritanceDiff(exceptType, raisedType) <= 0:
-        # mark exception as handled but keep it in B for 
+        # mark exception as handled but keep it in B for
         # the getCurrentException() builtin:
         c.currentExceptionB = c.currentExceptionA
         c.currentExceptionA = nil
@@ -349,14 +349,14 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
       if dest.kind != rkFloat:
         myreset(dest); dest.kind = rkFloat
       case skipTypes(srctyp, abstractRange).kind
-      of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar: 
+      of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
         dest.floatVal = toFloat(src.intVal.int)
       else:
         dest.floatVal = src.floatVal
     else:
       asgnComplex(dest, src)
 
-proc compile(c: PCtx, s: PSym): int = 
+proc compile(c: PCtx, s: PSym): int =
   result = vmgen.genProc(c, s)
   when debugEchoCode: c.echoCode result
   #c.echoCode
@@ -396,10 +396,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       pc = tos.comesFrom
       tos = tos.next
       let retVal = regs[0]
-      if tos.isNil: 
+      if tos.isNil:
         #echo "RET ", retVal.rendertree
         return retVal
-      
+
       move(regs, tos.slots)
       assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
       if c.code[pc].opcode == opcIndCallAsgn:
@@ -653,7 +653,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcSubu:
       decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal -% regs[rc].intVal
-    of opcMulu: 
+    of opcMulu:
       decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal *% regs[rc].intVal
     of opcDivu:
@@ -726,7 +726,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcLeSet:
       decodeBC(rkInt)
       regs[ra].intVal = ord(containsSets(regs[rb].node, regs[rc].node))
-    of opcEqSet: 
+    of opcEqSet:
       decodeBC(rkInt)
       regs[ra].intVal = ord(equalSets(regs[rb].node, regs[rc].node))
     of opcLtSet:
@@ -737,9 +737,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcMulSet:
       decodeBC(rkNode)
       createSet(regs[ra])
-      move(regs[ra].node.sons, 
+      move(regs[ra].node.sons,
             nimsets.intersectSets(regs[rb].node, regs[rc].node).sons)
-    of opcPlusSet: 
+    of opcPlusSet:
       decodeBC(rkNode)
       createSet(regs[ra])
       move(regs[ra].node.sons,
@@ -753,7 +753,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       decodeBC(rkNode)
       createSet(regs[ra])
       move(regs[ra].node.sons,
-           nimsets.symdiffSets(regs[rb].node, regs[rc].node).sons)    
+           nimsets.symdiffSets(regs[rb].node, regs[rc].node).sons)
     of opcConcatStr:
       decodeBC(rkNode)
       createStr regs[ra]
@@ -776,10 +776,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         stackTrace(c, tos, pc, errNilAccess)
     of opcEcho:
       let rb = instr.regB
-      for i in ra..ra+rb-1:
-        #if regs[i].kind != rkNode: debug regs[i]
-        write(stdout, regs[i].node.strVal)
-      writeln(stdout, "")
+      if rb == 1:
+        msgWriteln(regs[ra].node.strVal)
+      else:
+        var outp = ""
+        for i in ra..ra+rb-1:
+          #if regs[i].kind != rkNode: debug regs[i]
+          outp.add(regs[i].node.strVal)
+        msgWriteln(outp)
     of opcContainsSet:
       decodeBC(rkInt)
       regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].regToNode))
@@ -789,7 +793,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       assert c.code[pc].opcode == opcSubStr
       let rd = c.code[pc].regA
       createStr regs[ra]
-      regs[ra].node.strVal = substr(regs[rb].node.strVal, 
+      regs[ra].node.strVal = substr(regs[rb].node.strVal,
                                     regs[rc].intVal.int, regs[rd].intVal.int)
     of opcParseFloat:
       decodeBC(rkInt)
@@ -892,12 +896,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       # we know the next instruction is a 'fjmp':
       let branch = c.constants[instr.regBx-wordExcess]
       var cond = false
-      for j in countup(0, sonsLen(branch) - 2): 
-        if overlap(regs[ra].regToNode, branch.sons[j]): 
+      for j in countup(0, sonsLen(branch) - 2):
+        if overlap(regs[ra].regToNode, branch.sons[j]):
           cond = true
           break
       assert c.code[pc+1].opcode == opcFJmp
-      inc pc 
+      inc pc
       # we skip this instruction so that the final 'inc(pc)' skips
       # the following jump
       if not cond:
@@ -1269,7 +1273,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNSetIntVal:
       decodeB(rkNode)
       var dest = regs[ra].node
-      if dest.kind in {nkCharLit..nkInt64Lit} and 
+      if dest.kind in {nkCharLit..nkInt64Lit} and
          regs[rb].kind in {rkInt}:
         dest.intVal = regs[rb].intVal
       else:
@@ -1277,24 +1281,24 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNSetFloatVal:
       decodeB(rkNode)
       var dest = regs[ra].node
-      if dest.kind in {nkFloatLit..nkFloat64Lit} and 
+      if dest.kind in {nkFloatLit..nkFloat64Lit} and
          regs[rb].kind in {rkFloat}:
         dest.floatVal = regs[rb].floatVal
-      else: 
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
     of opcNSetSymbol:
       decodeB(rkNode)
       var dest = regs[ra].node
       if dest.kind == nkSym and regs[rb].node.kind == nkSym:
         dest.sym = regs[rb].node.sym
-      else: 
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
     of opcNSetIdent:
       decodeB(rkNode)
       var dest = regs[ra].node
       if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
         dest.ident = regs[rb].node.ident
-      else: 
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "ident")
     of opcNSetType:
       decodeB(rkNode)
@@ -1305,7 +1309,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNSetStrVal:
       decodeB(rkNode)
       var dest = regs[ra].node
-      if dest.kind in {nkStrLit..nkTripleStrLit} and 
+      if dest.kind in {nkStrLit..nkTripleStrLit} and
          regs[rb].kind in {rkNode}:
         dest.strVal = regs[rb].node.strVal
       else:
@@ -1431,8 +1435,9 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
   newSeq(tos.slots, c.prc.maxSlots)
   #for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos).regToNode
+  if result.info.line < 0: result.info = n.info
 
-proc evalConstExpr*(module: PSym, e: PNode): PNode = 
+proc evalConstExpr*(module: PSym, e: PNode): PNode =
   result = evalConstExprAux(module, nil, e, emConst)
 
 proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
@@ -1492,6 +1497,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   # temporary storage:
   #for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos).regToNode
+  if result.info.line < 0: result.info = n.info
   if cyclicTree(result): globalError(n.info, errCyclicTree)
   dec(evalMacroCounter)
   c.callsite = nil
diff --git a/doc/advopt.txt b/doc/advopt.txt
index 7b3695532..d4b1b7e57 100644
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -48,7 +48,6 @@ Advanced options:
   --os:SYMBOL               set the target operating system (cross-compilation)
   --cpu:SYMBOL              set the target processor (cross-compilation)
   --debuginfo               enables debug information
-  --debugger:on|off         turn Embedded Nim Debugger on|off
   -t, --passC:OPTION        pass an option to the C compiler
   -l, --passL:OPTION        pass an option to the linker
   --cincludes:DIR           modify the C compiler header search path
@@ -88,7 +87,5 @@ Advanced options:
   --parallelBuild:0|1|...   perform a parallel build
                             value = number of processors (0 for auto-detect)
   --verbosity:0|1|2|3       set Nim's verbosity level (1 is default)
-  --cs:none|partial         set case sensitivity level (default: none);
-                            do not use! this setting affects the whole language
   --experimental            enable experimental language features
   -v, --version             show detailed version information
diff --git a/doc/basicopt.txt b/doc/basicopt.txt
index 27b10badc..7d08f1159 100644
--- a/doc/basicopt.txt
+++ b/doc/basicopt.txt
@@ -6,7 +6,6 @@ Command:
   //compile, c                compile project with default code generator (C)
   //doc                       generate the documentation for inputfile
   //doc2                      generate the documentation for the whole project
-  //i                         start Nim in interactive mode (limited)
 
 Arguments:
   arguments are passed to the program being run (if --run option is selected)
@@ -30,6 +29,7 @@ Options:
   --infChecks:on|off        turn Inf checks on|off
   --deadCodeElim:on|off     whole program dead code elimination on|off
   --opt:none|speed|size     optimize not at all or for speed|size
+  --debugger:native|endb    use native debugger (gdb) | ENDB (experimental)
   --app:console|gui|lib|staticlib
                             generate a console app|GUI app|DLL|static library
   -r, --run                 run the compiled program with given arguments
diff --git a/doc/lib.txt b/doc/lib.txt
index 76920c6a9..385e7a91a 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -175,6 +175,9 @@ Generic Operating System Services
   This module implements the ability to monitor a directory/file for changes
   using Posix's inotify API.
 
+* `asyncfile <asyncfile.html>`_
+  This module implements asynchronous file reading and writing using
+  ``asyncdispatch``.
 
 Math libraries
 --------------
diff --git a/koch.nim b/koch.nim
index d365262c1..34cb1317d 100644
--- a/koch.nim
+++ b/koch.nim
@@ -347,7 +347,7 @@ proc temp(args: string) =
   if args.len > 0: exec(finalDest & " " & args)
 
 proc showHelp() = 
-  quit(HelpText % [VersionAsString & repeatChar(44-len(VersionAsString)), 
+  quit(HelpText % [VersionAsString & spaces(44-len(VersionAsString)), 
                    CompileDate, CompileTime], QuitSuccess)
 
 var op = initOptParser()
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index dbfb2ceb3..f73dbd241 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -60,7 +60,7 @@ type
     nnkStmtListType, nnkBlockType,
     nnkWith, nnkWithout,
     nnkTypeOfExpr, nnkObjectTy,
-    nnkTupleTy, nnkTypeClassTy, nnkStaticTy,
+    nnkTupleTy, nnkTupleClassTy, nnkTypeClassTy, nnkStaticTy,
     nnkRecList, nnkRecCase, nnkRecWhen,
     nnkRefTy, nnkPtrTy, nnkVarTy,
     nnkConstTy, nnkMutableTy,
@@ -343,7 +343,7 @@ proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
   ## checks that `n` is of kind `k`. If this is not the case,
   ## compilation aborts with an error message. This is useful for writing
   ## macros that check the AST that is passed to them.
-  if n.kind != k: error("macro expects a node of kind: " & $k)
+  if n.kind != k: error("Expected a node of kind " & $k & ", got " & $n.kind)
 
 proc expectMinLen*(n: PNimrodNode, min: int) {.compileTime.} =
   ## checks that `n` has at least `min` children. If this is not the case,
@@ -456,10 +456,11 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime, benign.} =
   of nnkSym: add(result, $n.symbol)
   of nnkNone: assert false
   else:
-    add(result, lispRepr(n[0]))
-    for j in 1..n.len-1:
-      add(result, ", ")
-      add(result, lispRepr(n[j]))
+    if n.len > 0:
+      add(result, lispRepr(n[0]))
+      for j in 1..n.len-1:
+        add(result, ", ")
+        add(result, lispRepr(n[j]))
 
   add(result, ")")
 
@@ -580,10 +581,8 @@ const
   CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
     nnkCallStrLit, nnkHiddenCallConv}
 
-from strutils import cmpIgnoreStyle, format
-
 proc expectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} =
-  assert n.kind in k, "Expected one of $1, got $2".format(k, n.kind)
+  assert n.kind in k, "Expected one of " & $k & ", got " & $n.kind
 
 proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyNode()];
     body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} =
@@ -653,7 +652,7 @@ proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}=
 
 
 template badNodeKind(k; f): stmt{.immediate.} =
-  assert false, "Invalid node kind $# for macros.`$2`".format(k, f)
+  assert false, "Invalid node kind " & $k & " for macros.`" & $f & "`"
 
 proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
   case someProc.kind:
@@ -775,6 +774,22 @@ proc copy*(node: PNimrodNode): PNimrodNode {.compileTime.} =
   ## An alias for copyNimTree().
   return node.copyNimTree()
 
+proc cmpIgnoreStyle(a, b: cstring): int {.noSideEffect.} =
+  proc toLower(c: char): char {.inline.} =
+    if c in {'A'..'Z'}: result = chr(ord(c) + (ord('a') - ord('A')))
+    else: result = c
+  var i = 0
+  var j = 0
+  while true:
+    while a[i] == '_': inc(i)
+    while b[j] == '_': inc(j) # BUGFIX: typo
+    var aa = toLower(a[i])
+    var bb = toLower(b[j])
+    result = ord(aa) - ord(bb)
+    if result != 0 or aa == '\0': break
+    inc(i)
+    inc(j)
+
 proc eqIdent* (a, b: string): bool = cmpIgnoreStyle(a, b) == 0
   ## Check if two idents are identical.
 
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 0046924a1..c3ff66591 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -66,9 +66,9 @@ type
   ppointer = ptr pointer
   pbyteArray = ptr array[0.. 0xffff, int8]
 
-  TGenSeq = object
+  TGenericSeq {.importc.} = object
     len, space: int
-  PGenSeq = ptr TGenSeq
+  PGenSeq = ptr TGenericSeq
 
 const
   GenericSeqSize = (2 * sizeof(int))
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index 7d5ff8948..921a24fd1 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -66,7 +66,7 @@ proc rawCompile(pattern: string, flags: cint): PPcre =
     offset: cint
   result = pcre.compile(pattern, flags, addr(msg), addr(offset), nil)
   if result == nil:
-    raiseInvalidRegex($msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n")
+    raiseInvalidRegex($msg & "\n" & pattern & "\n" & spaces(offset) & "^\n")
 
 proc finalizeRegEx(x: Regex) = 
   # XXX This is a hack, but PCRE does not export its "free" function properly.
@@ -291,7 +291,7 @@ proc replace*(s: string, sub: Regex, by = ""): string =
   ## accessed in `by`. Examples:
   ##
   ## .. code-block:: nim
-  ##   "var1=key; var2=key2".replace(re"(\w+)'='(\w+)")
+  ##   "var1=key; var2=key2".replace(re"(\w+)=(\w+)")
   ##
   ## Results in:
   ##
@@ -313,7 +313,7 @@ proc replacef*(s: string, sub: Regex, by: string): string =
   ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
   ##
   ## .. code-block:: nim
-  ## "var1=key; var2=key2".replacef(re"(\w+)'='(\w+)", "$1<-$2$2")
+  ##   "var1=key; var2=key2".replacef(re"(\w+)=(\w+)", "$1<-$2$2")
   ##
   ## Results in:
   ##
diff --git a/lib/nimbase.h b/lib/nimbase.h
index af21c8945..e9dad0bb7 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -67,7 +67,7 @@ __clang__
 #endif
 
 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
-#  define NIM_THREADVAR __declspec(thread) 
+#  define NIM_THREADVAR __declspec(thread)
 #else
 #  define NIM_THREADVAR __thread
 #endif
@@ -103,7 +103,11 @@ __clang__
 #  define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
 #  define N_SAFECALL_PTR(rettype, name) rettype (__safecall *name)
 
-#  define N_LIB_EXPORT  extern __declspec(dllexport)
+#  ifdef __cplusplus
+#    define N_LIB_EXPORT  extern "C" __declspec(dllexport)
+#  else
+#    define N_LIB_EXPORT  extern __declspec(dllexport)
+#  endif
 #  define N_LIB_IMPORT  extern __declspec(dllimport)
 #else
 #  define N_CDECL(rettype, name) rettype name
@@ -118,7 +122,11 @@ __clang__
 #  define N_FASTCALL_PTR(rettype, name) rettype (*name)
 #  define N_SAFECALL_PTR(rettype, name) rettype (*name)
 
-#  define N_LIB_EXPORT  extern
+#  ifdef __cplusplus
+#    define N_LIB_EXPORT  extern "C"
+#  else
+#    define N_LIB_EXPORT  extern
+#  endif
 #  define N_LIB_IMPORT  extern
 #endif
 
@@ -345,7 +353,7 @@ struct TFrame {
 #define nimln(n, file) \
   F.line = n; F.filename = file;
 
-#define NIM_POSIX_INIT  __attribute__((constructor)) 
+#define NIM_POSIX_INIT  __attribute__((constructor))
 
 #if defined(_MSCVER) && defined(__i386__)
 __declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
@@ -380,7 +388,7 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
 #endif
 
 /* Test to see if Nim and the C compiler agree on the size of a pointer.
-   On disagreement, your C compiler will say something like: 
+   On disagreement, your C compiler will say something like:
    "error: 'assert_numbits' declared as an array with a negative size" */
 typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
 #endif
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index 95d49bad7..97784898e 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -189,7 +189,7 @@ proc getIndent(L: var TLexer, tok: var TToken) =
   tok.line = L.line
   L.col = tok.ival
   tok.ival = max(tok.ival - L.baseIndent, 0)
-  tok.symbol = "\n" & repeatChar(tok.ival)
+  tok.symbol = "\n" & spaces(tok.ival)
 
 proc rawGetTok(L: var TLexer, tok: var TToken) = 
   tok.symbol = ""
@@ -963,7 +963,7 @@ proc parseLiteralBlock(p: var TRstParser): PRstNode =
           break 
         else: 
           add(n.text, "\n")
-          add(n.text, repeatChar(p.tok[p.idx].ival - indent))
+          add(n.text, spaces(p.tok[p.idx].ival - indent))
           inc(p.idx)
       else: 
         add(n.text, p.tok[p.idx].symbol)
diff --git a/lib/packages/docutils/rstast.nim b/lib/packages/docutils/rstast.nim
index 52af672df..614001d76 100644
--- a/lib/packages/docutils/rstast.nim
+++ b/lib/packages/docutils/rstast.nim
@@ -110,7 +110,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
   const 
     lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+']
   if n == nil: return
-  var ind = repeatChar(d.indent)
+  var ind = spaces(d.indent)
   case n.kind
   of rnInner: 
     renderRstSons(d, n, result)
@@ -124,7 +124,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
 
     result.add("\n")
     result.add(ind)
-    result.add repeatChar(headlineLen, lvlToChar[n.level])
+    result.add repeat(lvlToChar[n.level], headlineLen)
   of rnOverline:
     result.add("\n")
     result.add(ind)
@@ -132,7 +132,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
     var headline = ""
     renderRstSons(d, n, headline)
     
-    let lvl = repeatChar(headline.len - d.indent, lvlToChar[n.level])
+    let lvl = repeat(lvlToChar[n.level], headline.len - d.indent)
     result.add(lvl)
     result.add("\n")
     result.add(headline)
@@ -143,7 +143,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
   of rnTransition: 
     result.add("\n\n")
     result.add(ind)
-    result.add repeatChar(78-d.indent, '-')
+    result.add repeat('-', 78-d.indent)
     result.add("\n\n")
   of rnParagraph:
     result.add("\n\n")
@@ -196,7 +196,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
     result.add ':'
     result.add tmp
     result.add ':'
-    result.add repeatChar(L - tmp.len - 2)
+    result.add spaces(L - tmp.len - 2)
     renderRstToRst(d, n.sons[1], result)
     
     dec(d.indent, L)
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index e1e590877..a385336d6 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -461,9 +461,9 @@ proc indentToLevel(level: var int, newLevel: int): string =
   if level == newLevel:
     return
   if newLevel > level:
-    result = repeatStr(newLevel - level, "<ul>")
+    result = repeat("<ul>", newLevel - level)
   else:
-    result = repeatStr(level - newLevel, "</ul>")
+    result = repeat("</ul>", level - newLevel)
   level = newLevel
 
 proc generateDocumentationTOC(entries: seq[TIndexEntry]): string =
@@ -701,7 +701,7 @@ proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
   # Generate index entry using spaces to indicate TOC level for the output HTML.
   assert n.level >= 0
   setIndexTerm(d, refname, tmp.stripTOCHTML,
-    repeatChar(max(0, n.level), ' ') & tmp)
+    spaces(max(0, n.level)) & tmp)
 
 proc renderOverline(d: PDoc, n: PRstNode, result: var string) = 
   if d.meta[metaTitle].len == 0:
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 20bfc5c7c..20976e788 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -187,6 +187,34 @@ proc sort*[T](a: var openArray[T],
       dec(m, s*2)
     s = s*2
 
+proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.}, order = SortOrder.Ascending): seq[T] =
+  ## returns `a` sorted by `cmp` in the specified `order`.
+  result = newSeq[T](a.len)
+  for i in 0 .. a.high:
+    result[i] = a[i]
+  sort(result, cmp, order)
+
+template sortByIt*(seq1, op: expr): expr =
+  ## Convenience template around the ``sorted`` proc to reduce typing.
+  ##
+  ## The template injects the ``it`` variable which you can use directly in an
+  ## expression. Example:
+  ##
+  ## .. code-block:: nim
+  ##
+  ##     var users: seq[tuple[id: int, name: string]] =
+  ##       @[(0, "Smith"), (1, "Pratt"), (2, "Sparrow")]
+  ##
+  ##     echo users.sortByIt(it.name)
+  ##
+  var result {.gensym.} = sorted(seq1, proc(x, y: type(seq1[0])): int =
+    var it {.inject.} = x
+    let a = op
+    it = y
+    let b = op
+    result = cmp(a, b))
+  result
+
 proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
   ## produces the Cartesian product of the array. Warning: complexity
   ## may explode.
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index d6ed66030..bf905ed49 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -121,7 +121,7 @@ export Port, SocketFlag
 ##
 ## Limitations/Bugs
 ## ----------------
-## 
+##
 ## * ``except`` statement (without `try`) does not work inside async procedures.
 ## * The effect system (``raises: []``) does not work with async procedures.
 ## * Can't await in a ``except`` body
@@ -379,7 +379,7 @@ when defined(windows) or defined(nimdoc):
     if p.handles.len == 0 and p.timers.len == 0:
       raise newException(ValueError,
         "No handles or timers registered in dispatcher.")
-    
+
     let llTimeout =
       if timeout ==  -1: winlean.INFINITE
       else: timeout.int32
@@ -436,12 +436,12 @@ when defined(windows) or defined(nimdoc):
     if not initPointer(dummySock, getAcceptExSockAddrsPtr, WSAID_GETACCEPTEXSOCKADDRS):
       raiseOSError(osLastError())
 
-  proc connectEx(s: SocketHandle, name: ptr SockAddr, namelen: cint, 
+  proc connectEx(s: SocketHandle, name: ptr SockAddr, namelen: cint,
                   lpSendBuffer: pointer, dwSendDataLength: Dword,
                   lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool =
     if connectExPtr.isNil: raise newException(ValueError, "Need to initialise ConnectEx().")
     let fun =
-      cast[proc (s: SocketHandle, name: ptr SockAddr, namelen: cint, 
+      cast[proc (s: SocketHandle, name: ptr SockAddr, namelen: cint,
          lpSendBuffer: pointer, dwSendDataLength: Dword,
          lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](connectExPtr)
 
@@ -475,7 +475,7 @@ when defined(windows) or defined(nimdoc):
                  dwRemoteAddressLength: Dword, LocalSockaddr: ptr ptr SockAddr,
                  LocalSockaddrLength: LPInt, RemoteSockaddr: ptr ptr SockAddr,
                 RemoteSockaddrLength: LPInt) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
-    
+
     fun(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
                   dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
                   RemoteSockaddr, RemoteSockaddrLength)
@@ -514,7 +514,7 @@ when defined(windows) or defined(nimdoc):
             else:
               retFuture.fail(newException(OSError, osErrorMsg(errcode)))
       )
-      
+
       var ret = connectEx(socket.SocketHandle, it.ai_addr,
                           sizeof(Sockaddr_in).cint, nil, 0, nil,
                           cast[POVERLAPPED](ol))
@@ -565,7 +565,7 @@ when defined(windows) or defined(nimdoc):
     var dataBuf: TWSABuf
     dataBuf.buf = cast[cstring](alloc0(size))
     dataBuf.len = size
-    
+
     var bytesReceived: Dword
     var flagsio = flags.toOSFlags().Dword
     var ol = PCustomOverlapped()
@@ -612,9 +612,9 @@ when defined(windows) or defined(nimdoc):
       # the empty string (which signals a disconnection) when there is
       # nothing left to read.
       retFuture.complete("")
-      # TODO: "For message-oriented sockets, where a zero byte message is often 
-      # allowable, a failure with an error code of WSAEDISCON is used to 
-      # indicate graceful closure." 
+      # TODO: "For message-oriented sockets, where a zero byte message is often
+      # allowable, a failure with an error code of WSAEDISCON is used to
+      # indicate graceful closure."
       # ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
     else:
       # Request to read completed immediately.
@@ -748,7 +748,7 @@ when defined(windows) or defined(nimdoc):
 
     # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
     let ret = acceptEx(socket.SocketHandle, clientSock, addr lpOutputBuf[0],
-                       dwReceiveDataLength, 
+                       dwReceiveDataLength,
                        dwLocalAddressLength,
                        dwRemoteAddressLength,
                        addr dwBytesReceived, cast[POVERLAPPED](ol))
@@ -803,7 +803,7 @@ else:
   else:
     from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
                       MSG_NOSIGNAL
-  
+
   type
     TAsyncFD* = distinct cint
     TCallback = proc (fd: TAsyncFD): bool {.closure,gcsafe.}
@@ -849,7 +849,7 @@ else:
     result = newRawSocket(domain, typ, protocol).TAsyncFD
     result.SocketHandle.setBlocking(false)
     register(result)
-  
+
   proc closeSocket*(sock: TAsyncFD) =
     let disp = getGlobalDispatcher()
     sock.SocketHandle.close()
@@ -864,14 +864,14 @@ else:
       raise newException(ValueError, "File descriptor not registered.")
     p.selector[fd.SocketHandle].data.PData.readCBs.add(cb)
     update(fd, p.selector[fd.SocketHandle].events + {EvRead})
-  
+
   proc addWrite*(fd: TAsyncFD, cb: TCallback) =
     let p = getGlobalDispatcher()
     if fd.SocketHandle notin p.selector:
       raise newException(ValueError, "File descriptor not registered.")
     p.selector[fd.SocketHandle].data.PData.writeCBs.add(cb)
     update(fd, p.selector[fd.SocketHandle].events + {EvWrite})
-  
+
   proc poll*(timeout = 500) =
     let p = getGlobalDispatcher()
     for info in p.selector.select(timeout):
@@ -892,7 +892,7 @@ else:
           if not cb(data.fd):
             # Callback wants to be called again.
             data.readCBs.add(cb)
-      
+
       if EvWrite in info.events:
         let currentCBs = data.writeCBs
         data.writeCBs = @[]
@@ -900,7 +900,7 @@ else:
           if not cb(data.fd):
             # Callback wants to be called again.
             data.writeCBs.add(cb)
-      
+
       if info.key in p.selector:
         var newEvents: set[Event]
         if data.readCBs.len != 0: newEvents = {EvRead}
@@ -913,16 +913,16 @@ else:
         discard
 
     processTimers(p)
-  
+
   proc connect*(socket: TAsyncFD, address: string, port: Port,
     af = AF_INET): Future[void] =
     var retFuture = newFuture[void]("connect")
-    
+
     proc cb(fd: TAsyncFD): bool =
       # We have connected.
       retFuture.complete()
       return true
-    
+
     var aiList = getAddrInfo(address, port, af)
     var success = false
     var lastError: OSErrorCode
@@ -952,7 +952,7 @@ else:
   proc recv*(socket: TAsyncFD, size: int,
              flags = {SocketFlag.SafeDisconn}): Future[string] =
     var retFuture = newFuture[string]("recv")
-    
+
     var readBuffer = newString(size)
 
     proc cb(sock: TAsyncFD): bool =
@@ -983,9 +983,9 @@ else:
   proc send*(socket: TAsyncFD, data: string,
              flags = {SocketFlag.SafeDisconn}): Future[void] =
     var retFuture = newFuture[void]("send")
-    
+
     var written = 0
-    
+
     proc cb(sock: TAsyncFD): bool =
       result = true
       let netSize = data.len-written
@@ -1222,7 +1222,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
   of nnkTryStmt:
     # try: await x; except: ...
     result = newNimNode(nnkStmtList, node)
-    template wrapInTry(n, tryBody: PNimrodNode) =
+    template wrapInTry(n, tryBody: expr) =
       var temp = n
       n[0] = tryBody
       tryBody = temp
@@ -1315,14 +1315,14 @@ macro async*(prc: stmt): stmt {.immediate.} =
     if returnType.kind == nnkEmpty: newIdentNode("void")
     else: returnType[1]
   outerProcBody.add(
-    newVarStmt(retFutureSym, 
+    newVarStmt(retFutureSym,
       newCall(
         newNimNode(nnkBracketExpr, prc[6]).add(
           newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
           subRetType),
       newLit(prc[0].getName)))) # Get type from return type of this proc
-  
-  # -> iterator nameIter(): FutureBase {.closure.} = 
+
+  # -> iterator nameIter(): FutureBase {.closure.} =
   # ->   var result: T
   # ->   <proc_body>
   # ->   complete(retFuture, result)
@@ -1337,7 +1337,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   else:
     # -> complete(retFuture)
     procBody.add(newCall(newIdentNode("complete"), retFutureSym))
-  
+
   var closureIterator = newProc(iteratorNameSym, [newIdentNode("FutureBase")],
                                 procBody, nnkIteratorDef)
   closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure"))
@@ -1351,7 +1351,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
 
   # -> return retFuture
   outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym)
-  
+
   result = prc
 
   # Remove the 'async' pragma.
@@ -1377,7 +1377,7 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
   ## If a full line is read ``\r\L`` is not
   ## added to ``line``, however if solely ``\r\L`` is read then ``line``
   ## will be set to it.
-  ## 
+  ##
   ## If the socket is disconnected, ``line`` will be set to ``""``.
   ##
   ## If the socket is disconnected in the middle of a line (before ``\r\L``
@@ -1388,7 +1388,7 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
   ##
   ## **Note**: This procedure is mostly used for testing. You likely want to
   ## use ``asyncnet.recvLine`` instead.
-  
+
   template addNLIfEmpty(): stmt =
     if result.len == 0:
       result.add("\c\L")
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim
index 752c01eac..844c2ab55 100644
--- a/lib/pure/asyncfile.nim
+++ b/lib/pure/asyncfile.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements asynchronous file handling.
+## This module implements asynchronous file reading and writing.
 ##
 ## .. code-block:: Nim
 ##    import asyncfile, asyncdispatch, os
@@ -30,7 +30,7 @@ else:
   import posix
 
 type
-  AsyncFile = ref object
+  AsyncFile* = ref object
     fd: TAsyncFd
     offset: int64
 
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index e690e8eba..edb904cc6 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -47,6 +47,24 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
       result[i] = itm
       inc(i)
 
+proc repeat*[T](s: seq[T], n: Natural): seq[T] =
+  ## Returns a new sequence with the items of `s` repeated `n` times.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:
+  ##
+  ##   let
+  ##     s = @[1, 2, 3]
+  ##     total = s.repeat(3)
+  ##   assert total == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
+  result = newSeq[T](n * s.len)
+  var o = 0
+  for x in 1..n:
+    for e in s:
+      result[o] = e
+      inc o
+
 proc deduplicate*[T](seq1: seq[T]): seq[T] =
   ## Returns a new sequence without duplicates.
   ##
@@ -86,7 +104,7 @@ proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
   newSeq(result, m)
   for i in 0 .. m-1: result[i] = (seq1[i], seq2[i])
 
-proc distribute*[T](s: seq[T], num: int, spread = true): seq[seq[T]] =
+proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
   ## Splits and distributes a sequence `s` into `num` sub sequences.
   ##
   ## Returns a sequence of `num` sequences. For some input values this is the
@@ -113,11 +131,12 @@ proc distribute*[T](s: seq[T], num: int, spread = true): seq[seq[T]] =
   ##   assert numbers.distribute(6)[0] == @[1, 2]
   ##   assert numbers.distribute(6)[5] == @[7]
   assert(not s.isNil, "`s` can't be nil")
-  assert(num > 0, "`num` has to be greater than zero")
   if num < 2:
     result = @[s]
     return
 
+  let num = int(num) # XXX probably only needed because of .. bug
+
   # Create the result and calculate the stride size and the remainder if any.
   result = newSeq[seq[T]](num)
   var
@@ -587,4 +606,14 @@ when isMainModule:
     seq2D[0][1] = true
     doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
 
+  block: # repeat tests
+    let
+      a = @[1, 2, 3]
+      b: seq[int] = @[]
+    
+    doAssert a.repeat(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
+    doAssert a.repeat(0) == @[]
+    #doAssert a.repeat(-1) == @[] # will not compile!
+    doAssert b.repeat(3) == @[]
+
   echo "Finished doc tests"
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index 959688d6a..93a7591ac 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -196,7 +196,11 @@ proc mget*[A, B](t: var Table[A, B], key: A): var B =
   var hc: THash
   var index = rawGet(t, key, hc)
   if index >= 0: result = t.data[index].val
-  else: raise newException(KeyError, "key not found: " & $key)
+  else:
+    when compiles($key):
+      raise newException(KeyError, "key not found: " & $key)
+    else:
+      raise newException(KeyError, "key not found")
 
 iterator allValues*[A, B](t: Table[A, B]; key: A): B =
   ## iterates over any value in the table `t` that belongs to the given `key`.
diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim
index 9f1546eed..8577bf7a1 100644
--- a/lib/pure/complex.nim
+++ b/lib/pure/complex.nim
@@ -274,27 +274,86 @@ proc tan*(z: Complex): Complex =
   ## Returns the tangent of `z`.
   result = sin(z)/cos(z)
 
+proc arctan*(z: Complex): Complex =
+  ## Returns the inverse tangent of `z`.
+  var i: Complex = (0.0,1.0)
+  result = 0.5*i*(ln(1-i*z)-ln(1+i*z))
+
 proc cot*(z: Complex): Complex =
   ## Returns the cotangent of `z`.
   result = cos(z)/sin(z)
 
+proc arccot*(z: Complex): Complex =
+  ## Returns the inverse cotangent of `z`.
+  var i: Complex = (0.0,1.0)
+  result = 0.5*i*(ln(1-i/z)-ln(1+i/z))
+
 proc sec*(z: Complex): Complex =
   ## Returns the secant of `z`.
   result = 1.0/cos(z)
 
+proc arcsec*(z: Complex): Complex =
+  ## Returns the inverse secant of `z`.
+  var i: Complex = (0.0,1.0)
+  result = -i*ln(i*sqrt(1-1/(z*z))+1/z)
+
 proc csc*(z: Complex): Complex =
   ## Returns the cosecant of `z`.
   result = 1.0/sin(z)
 
+proc arccsc*(z: Complex): Complex =
+  ## Returns the inverse cosecant of `z`.
+  var i: Complex = (0.0,1.0)
+  result = -i*ln(sqrt(1-1/(z*z))+i/z)
+
 
 proc sinh*(z: Complex): Complex =
   ## Returns the hyperbolic sine of `z`.
   result = 0.5*(exp(z)-exp(-z))
 
+proc arcsinh*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic sine of `z`.
+  result = ln(z+sqrt(z*z+1))
+
 proc cosh*(z: Complex): Complex =
   ## Returns the hyperbolic cosine of `z`.
   result = 0.5*(exp(z)+exp(-z))
 
+proc arccosh*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic cosine of `z`.
+  result = ln(z+sqrt(z*z-1))
+
+proc tanh*(z: Complex): Complex =
+  ## Returns the hyperbolic tangent of `z`.
+  result = sinh(z)/cosh(z)
+
+proc arctanh*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic tangent of `z`.
+  result = 0.5*(ln((1+z)/(1-z)))
+
+proc sech*(z: Complex): Complex =
+  ## Returns the hyperbolic secant of `z`.
+  result = 2/(exp(z)+exp(-z))
+
+proc arcsech*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic secant of `z`.
+  result = ln(1/z+sqrt(1/z+1)*sqrt(1/z-1))
+
+proc csch*(z: Complex): Complex =
+  ## Returns the hyperbolic cosecant of `z`.
+  result = 2/(exp(z)-exp(-z))
+
+proc arccsch*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic cosecant of `z`.
+  result = ln(1/z+sqrt(1/(z*z)+1))
+
+proc coth*(z: Complex): Complex =
+  ## Returns the hyperbolic cotangent of `z`.
+  result = cosh(z)/sinh(z)
+
+proc arccoth*(z: Complex): Complex =
+  ## Returns the inverse hyperbolic cotangent of `z`.
+  result = 0.5*(ln(1+1/z)-ln(1-1/z))
 
 proc phase*(z: Complex): float =
   ## Returns the phase of `z`.
@@ -306,9 +365,9 @@ proc polar*(z: Complex): tuple[r, phi: float] =
   result.phi = phase(z)
 
 proc rect*(r: float, phi: float): Complex =
-  ## Returns the complex number with poolar coordinates `r` and `phi`.
+  ## Returns the complex number with polar coordinates `r` and `phi`.
   result.re = r * cos(phi)
-  result.im = sin(phi)
+  result.im = r * sin(phi)
 
 
 proc `$`*(z: Complex): string =
@@ -363,10 +422,22 @@ when isMainModule:
   assert( csc(a) =~ 1.0/sin(a) )
   assert( arcsin(a) =~ (0.427078586392476, 1.528570919480998) )
   assert( arccos(a) =~ (1.14371774040242, -1.52857091948100) )
+  assert( arctan(a) =~ (1.338972522294494, 0.402359478108525) )
 
   assert( cosh(a) =~ (-0.642148124715520, 1.068607421382778) )
   assert( sinh(a) =~ (-0.489056259041294, 1.403119250622040) )
+  assert( tanh(a) =~ (1.1667362572409199,-0.243458201185725) )
+  assert( sech(a) =~ 1/cosh(a) )
+  assert( csch(a) =~ 1/sinh(a) )
+  assert( coth(a) =~ 1/tanh(a) )
+  assert( arccosh(a) =~ (1.528570919480998, 1.14371774040242) )
+  assert( arcsinh(a) =~ (1.469351744368185, 1.06344002357775) )
+  assert( arctanh(a) =~ (0.173286795139986, 1.17809724509617) )
+  assert( arcsech(a) =~ arccosh(1/a) )
+  assert( arccsch(a) =~ arcsinh(1/a) )
+  assert( arccoth(a) =~ arctanh(1/a) )
 
   assert( phase(a) == 1.1071487177940904 )
-  assert( polar(a) =~ (2.23606797749979, 1.1071487177940904) )
+  var t = polar(a)
+  assert( rect(t.r, t.phi) =~ a )
   assert( rect(1.0, 2.0) =~ (-0.4161468365471424, 0.9092974268256817) )
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 30daaf2dc..a16342d44 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -33,8 +33,8 @@
 ##  proc hash(x: Something): THash =
 ##    ## Computes a THash from `x`.
 ##    var h: THash = 0
-##    h = h &! hash(x.foo)
-##    h = h &! hash(x.bar)
+##    h = h !& hash(x.foo)
+##    h = h !& hash(x.bar)
 ##    result = !$h
 
 import 
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 37af14df3..f11101511 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -390,8 +390,11 @@ proc request*(url: string, httpMethod: string, extraHeaders = "",
   ## server takes longer than specified an ETimeout exception will be raised.
   var r = if proxy == nil: parseUri(url) else: proxy.url
   var headers = substr(httpMethod, len("http"))
+  # TODO: Use generateHeaders further down once it supports proxies.
   if proxy == nil:
-    headers.add(" " & r.path)
+    headers.add ' '
+    if r.path[0] != '/': headers.add '/'
+    headers.add(r.path)
     if r.query.len > 0:
       headers.add("?" & r.query)
   else:
@@ -567,9 +570,12 @@ proc downloadFile*(url: string, outputFilename: string,
 
 proc generateHeaders(r: Uri, httpMethod: string,
                      headers: StringTableRef): string =
+  # TODO: Use this in the blocking HttpClient once it supports proxies.
   result = substr(httpMethod, len("http"))
   # TODO: Proxies
-  result.add(" " & r.path)
+  result.add ' '
+  if r.path[0] != '/': result.add '/'
+  result.add(r.path)
   if r.query.len > 0:
     result.add("?" & r.query)
   result.add(" HTTP/1.1\c\L")
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 2038b246d..5041fe2f6 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -816,7 +816,7 @@ proc copy*(p: JsonNode): JsonNode =
 # ------------- pretty printing ----------------------------------------------
 
 proc indent(s: var string, i: int) = 
-  s.add(repeatChar(i))
+  s.add(spaces(i))
 
 proc newIndent(curr, indent: int, ml: bool): int =
   if ml: return curr + indent
diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim
index a3a3d7b5c..23a87d9f8 100644
--- a/lib/pure/lexbase.nim
+++ b/lib/pure/lexbase.nim
@@ -165,5 +165,5 @@ proc getCurrentLine(L: BaseLexer, marker: bool = true): string =
     inc(i)
   add(result, "\n")
   if marker:
-    add(result, repeatChar(getColNumber(L, L.bufpos)) & "^\n")
+    add(result, spaces(getColNumber(L, L.bufpos)) & "^\n")
 
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index b1e2444c3..4c92a7cdf 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -11,9 +11,12 @@
 ## It supports one convenience iterator over all command line options and some
 ## lower-level features.
 ##
-## **Deprecated since version 0.9.3:** Use the `parseopt2 <parseopt2.html>`_
-## module instead as this version has issues with spaces in arguments.
-{.deprecated.}
+## Supported syntax:
+##
+## 1. short options - ``-abcd``, where a, b, c, d are names
+## 2. long option - ``--foo:bar``, ``--foo=bar`` or ``--foo``
+## 3. argument - everything else
+
 {.push debugger: off.}
 
 include "system/inclrtl"
diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim
index b957c0cf7..b8f422c31 100644
--- a/lib/pure/parsexml.nim
+++ b/lib/pure/parsexml.nim
@@ -128,6 +128,7 @@ proc open*(my: var XmlParser, input: Stream, filename: string,
   my.kind = xmlError
   my.a = ""
   my.b = ""
+  my.c = ""
   my.options = options
   
 proc close*(my: var XmlParser) {.inline.} = 
@@ -138,43 +139,43 @@ proc kind*(my: XmlParser): XmlEventKind {.inline.} =
   ## returns the current event type for the XML parser
   return my.kind
 
-proc charData*(my: XmlParser): string {.inline.} = 
+template charData*(my: XmlParser): string =
   ## returns the character data for the events: ``xmlCharData``, 
   ## ``xmlWhitespace``, ``xmlComment``, ``xmlCData``, ``xmlSpecial``
   assert(my.kind in {xmlCharData, xmlWhitespace, xmlComment, xmlCData, 
                      xmlSpecial})
-  return my.a
+  my.a
 
-proc elementName*(my: XmlParser): string {.inline.} = 
+template elementName*(my: XmlParser): string =
   ## returns the element name for the events: ``xmlElementStart``, 
   ## ``xmlElementEnd``, ``xmlElementOpen``
   assert(my.kind in {xmlElementStart, xmlElementEnd, xmlElementOpen})
-  return my.a
+  my.a
 
-proc entityName*(my: XmlParser): string {.inline.} = 
+template entityName*(my: XmlParser): string =
   ## returns the entity name for the event: ``xmlEntity``
   assert(my.kind == xmlEntity)
-  return my.a
+  my.a
   
-proc attrKey*(my: XmlParser): string {.inline.} = 
+template attrKey*(my: XmlParser): string =
   ## returns the attribute key for the event ``xmlAttribute``
   assert(my.kind == xmlAttribute)
-  return my.a
+  my.a
   
-proc attrValue*(my: XmlParser): string {.inline.} = 
+template attrValue*(my: XmlParser): string =
   ## returns the attribute value for the event ``xmlAttribute``
   assert(my.kind == xmlAttribute)
-  return my.b
+  my.b
 
-proc piName*(my: XmlParser): string {.inline.} = 
+template piName*(my: XmlParser): string =
   ## returns the processing instruction name for the event ``xmlPI``
   assert(my.kind == xmlPI)
-  return my.a
+  my.a
 
-proc piRest*(my: XmlParser): string {.inline.} = 
+template piRest*(my: XmlParser): string =
   ## returns the rest of the processing instruction for the event ``xmlPI``
   assert(my.kind == xmlPI)
-  return my.b
+  my.b
 
 proc rawData*(my: XmlParser): string {.inline.} =
   ## returns the underlying 'data' string by reference.
@@ -446,13 +447,15 @@ proc parseTag(my: var XmlParser) =
     # an attribute follows:
     my.kind = xmlElementOpen
     my.state = stateAttr
-    my.c = my.a # save for later
+    # save for later:
+    my.c.setLen(my.a.len)
+    my.c[0..my.c.high] = my.a[0..my.a.high]
   else:
     my.kind = xmlElementStart
     if my.buf[my.bufpos] == '/' and my.buf[my.bufpos+1] == '>':
       inc(my.bufpos, 2)
       my.state = stateEmptyElementTag
-      my.c = nil
+      my.c.setLen(0)
     elif my.buf[my.bufpos] == '>':
       inc(my.bufpos)  
     else:
@@ -621,8 +624,9 @@ proc next*(my: var XmlParser) =
   of stateEmptyElementTag:
     my.state = stateNormal
     my.kind = xmlElementEnd
-    if not isNil(my.c):
-      my.a = my.c
+    if my.c.len > 0:
+      my.a.setLen(my.c.len)
+      my.a[0..my.a.high] = my.c[0..my.c.high]
   of stateError: 
     my.kind = xmlError
     my.state = stateNormal
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 419554de5..04c75ecae 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -29,7 +29,7 @@ when useUnicode:
 const
   InlineThreshold = 5  ## number of leaves; -1 to disable inlining
   MaxSubpatterns* = 20 ## defines the maximum number of subpatterns that
-                       ## can be captured. More subpatterns cannot be captured! 
+                       ## can be captured. More subpatterns cannot be captured!
 
 type
   PegKind = enum
@@ -85,14 +85,14 @@ type
     of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns]
     else: sons: seq[TNode]
   NonTerminal* = ref NonTerminalObj
-  
+
   Peg* = TNode ## type that represents a PEG
 
 {.deprecated: [TPeg: Peg].}
 
 proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} =
   ## constructs a PEG from a terminal string
-  if t.len != 1:  
+  if t.len != 1:
     result.kind = pkTerminal
     result.term = t
   else:
@@ -116,7 +116,7 @@ proc term*(t: char): Peg {.nosideEffect, rtl, extern: "npegs$1Char".} =
   assert t != '\0'
   result.kind = pkChar
   result.ch = t
-  
+
 proc charSet*(s: set[char]): Peg {.nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a PEG from a character set `s`
   assert '\0' notin s
@@ -129,12 +129,12 @@ proc add(d: var Peg, s: Peg) {.inline.} = add(d.sons, s)
 
 proc addChoice(dest: var Peg, elem: Peg) =
   var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkCharChoice: 
+  if L >= 0 and dest.sons[L].kind == pkCharChoice:
     # caution! Do not introduce false aliasing here!
     case elem.kind
     of pkCharChoice:
       dest.sons[L] = charSet(dest.sons[L].charChoice[] + elem.charChoice[])
-    of pkChar: 
+    of pkChar:
       dest.sons[L] = charSet(dest.sons[L].charChoice[] + {elem.ch})
     else: add(dest, elem)
   else: add(dest, elem)
@@ -158,12 +158,12 @@ proc `/`*(a: varargs[Peg]): Peg {.
 
 proc addSequence(dest: var Peg, elem: Peg) =
   var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkTerminal: 
+  if L >= 0 and dest.sons[L].kind == pkTerminal:
     # caution! Do not introduce false aliasing here!
     case elem.kind
-    of pkTerminal: 
+    of pkTerminal:
       dest.sons[L] = term(dest.sons[L].term & elem.term)
-    of pkChar: 
+    of pkChar:
       dest.sons[L] = term(dest.sons[L].term & elem.ch)
     else: add(dest, elem)
   else: add(dest, elem)
@@ -172,7 +172,7 @@ proc sequence*(a: varargs[Peg]): Peg {.
   nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a sequence with all the PEGs from `a`
   multipleOp(pkSequence, addSequence)
- 
+
 proc `?`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsOptional".} =
   ## constructs an optional for the PEG `a`
   if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar,
@@ -207,7 +207,7 @@ proc `!*`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsSearch".} =
   result.kind = pkSearch
   result.sons = @[a]
 
-proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl, 
+proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl,
                              extern: "npgegsCapturedSearch".} =
   ## constructs a "captured search" for the PEG `a`
   result.kind = pkCapturedSearch
@@ -216,7 +216,7 @@ proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl,
 proc `+`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyPosRep".} =
   ## constructs a "greedy positive repetition" with the PEG `a`
   return sequence(a, *a)
-  
+
 proc `&`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsAndPredicate".} =
   ## constructs an "and predicate" with the PEG `a`
   result.kind = pkAndPredicate
@@ -239,33 +239,33 @@ proc newLine*: Peg {.inline.} =
   ## constructs the PEG `newline`:idx: (``\n``)
   result.kind = pkNewLine
 
-proc unicodeLetter*: Peg {.inline.} = 
+proc unicodeLetter*: Peg {.inline.} =
   ## constructs the PEG ``\letter`` which matches any Unicode letter.
   result.kind = pkLetter
-  
-proc unicodeLower*: Peg {.inline.} = 
+
+proc unicodeLower*: Peg {.inline.} =
   ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter.
-  result.kind = pkLower 
+  result.kind = pkLower
 
-proc unicodeUpper*: Peg {.inline.} = 
+proc unicodeUpper*: Peg {.inline.} =
   ## constructs the PEG ``\upper`` which matches any Unicode uppercase letter.
   result.kind = pkUpper
-  
-proc unicodeTitle*: Peg {.inline.} = 
+
+proc unicodeTitle*: Peg {.inline.} =
   ## constructs the PEG ``\title`` which matches any Unicode title letter.
   result.kind = pkTitle
 
-proc unicodeWhitespace*: Peg {.inline.} = 
-  ## constructs the PEG ``\white`` which matches any Unicode 
+proc unicodeWhitespace*: Peg {.inline.} =
+  ## constructs the PEG ``\white`` which matches any Unicode
   ## whitespace character.
   result.kind = pkWhitespace
 
-proc startAnchor*: Peg {.inline.} = 
-  ## constructs the PEG ``^`` which matches the start of the input.  
+proc startAnchor*: Peg {.inline.} =
+  ## constructs the PEG ``^`` which matches the start of the input.
   result.kind = pkStartAnchor
 
-proc endAnchor*: Peg {.inline.} = 
-  ## constructs the PEG ``$`` which matches the end of the input.  
+proc endAnchor*: Peg {.inline.} =
+  ## constructs the PEG ``$`` which matches the end of the input.
   result = !any()
 
 proc capture*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsCapture".} =
@@ -274,21 +274,21 @@ proc capture*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsCapture".} =
   result.sons = @[a]
 
 proc backref*(index: range[1..MaxSubpatterns]): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a back reference of the given `index`. `index` starts counting
   ## from 1.
   result.kind = pkBackRef
   result.index = index-1
 
 proc backrefIgnoreCase*(index: range[1..MaxSubpatterns]): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a back reference of the given `index`. `index` starts counting
   ## from 1. Ignores case for matching.
   result.kind = pkBackRefIgnoreCase
   result.index = index-1
 
 proc backrefIgnoreStyle*(index: range[1..MaxSubpatterns]): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".}= 
+  nosideEffect, rtl, extern: "npegs$1".}=
   ## constructs a back reference of the given `index`. `index` starts counting
   ## from 1. Ignores style for matching.
   result.kind = pkBackRefIgnoreStyle
@@ -298,7 +298,7 @@ proc spaceCost(n: Peg): int =
   case n.kind
   of pkEmpty: discard
   of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar,
-     pkGreedyRepChar, pkCharChoice, pkGreedyRepSet, 
+     pkGreedyRepChar, pkCharChoice, pkGreedyRepSet,
      pkAny..pkWhitespace, pkGreedyAny:
     result = 1
   of pkNonTerminal:
@@ -310,7 +310,7 @@ proc spaceCost(n: Peg): int =
       if result >= InlineThreshold: break
 
 proc nonterminal*(n: NonTerminal): Peg {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## constructs a PEG that consists of the nonterminal symbol
   assert n != nil
   if ntDeclared in n.flags and spaceCost(n.rule) < InlineThreshold:
@@ -331,7 +331,7 @@ proc newNonTerminal*(name: string, line, column: int): NonTerminal {.
 template letters*: expr =
   ## expands to ``charset({'A'..'Z', 'a'..'z'})``
   charSet({'A'..'Z', 'a'..'z'})
-  
+
 template digits*: expr =
   ## expands to ``charset({'0'..'9'})``
   charSet({'0'..'9'})
@@ -339,11 +339,11 @@ template digits*: expr =
 template whitespace*: expr =
   ## expands to ``charset({' ', '\9'..'\13'})``
   charSet({' ', '\9'..'\13'})
-  
+
 template identChars*: expr =
   ## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})``
   charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})
-  
+
 template identStartChars*: expr =
   ## expands to ``charset({'A'..'Z', 'a'..'z', '_'})``
   charSet({'a'..'z', 'A'..'Z', '_'})
@@ -352,14 +352,14 @@ template ident*: expr =
   ## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier
   sequence(charSet({'a'..'z', 'A'..'Z', '_'}),
            *charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'}))
-  
+
 template natural*: expr =
   ## same as ``\d+``
   +digits
 
 # ------------------------- debugging -----------------------------------------
 
-proc esc(c: char, reserved = {'\0'..'\255'}): string = 
+proc esc(c: char, reserved = {'\0'..'\255'}): string =
   case c
   of '\b': result = "\\b"
   of '\t': result = "\\t"
@@ -374,38 +374,38 @@ proc esc(c: char, reserved = {'\0'..'\255'}): string =
   elif c < ' ' or c >= '\128': result = '\\' & $ord(c)
   elif c in reserved: result = '\\' & c
   else: result = $c
-  
+
 proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
 
-proc singleQuoteEsc(str: string): string = 
+proc singleQuoteEsc(str: string): string =
   result = "'"
   for c in items(str): add result, esc(c, {'\''})
   add result, '\''
-  
-proc charSetEscAux(cc: set[char]): string = 
+
+proc charSetEscAux(cc: set[char]): string =
   const reserved = {'^', '-', ']'}
   result = ""
   var c1 = 0
-  while c1 <= 0xff: 
-    if chr(c1) in cc: 
+  while c1 <= 0xff:
+    if chr(c1) in cc:
       var c2 = c1
       while c2 < 0xff and chr(succ(c2)) in cc: inc(c2)
-      if c1 == c2: 
+      if c1 == c2:
         add result, esc(chr(c1), reserved)
-      elif c2 == succ(c1): 
+      elif c2 == succ(c1):
         add result, esc(chr(c1), reserved) & esc(chr(c2), reserved)
-      else: 
+      else:
         add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved)
       c1 = c2
     inc(c1)
-  
+
 proc charSetEsc(cc: set[char]): string =
-  if card(cc) >= 128+64: 
+  if card(cc) >= 128+64:
     result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
-  else: 
+  else:
     result = '[' & charSetEscAux(cc) & ']'
-  
-proc toStrAux(r: Peg, res: var string) = 
+
+proc toStrAux(r: Peg, res: var string) =
   case r.kind
   of pkEmpty: add(res, "()")
   of pkAny: add(res, '.')
@@ -469,25 +469,25 @@ proc toStrAux(r: Peg, res: var string) =
     toStrAux(r.sons[0], res)
   of pkCapture:
     add(res, '{')
-    toStrAux(r.sons[0], res)    
+    toStrAux(r.sons[0], res)
     add(res, '}')
-  of pkBackRef: 
+  of pkBackRef:
     add(res, '$')
     add(res, $r.index)
-  of pkBackRefIgnoreCase: 
+  of pkBackRefIgnoreCase:
     add(res, "i$")
     add(res, $r.index)
-  of pkBackRefIgnoreStyle: 
+  of pkBackRefIgnoreStyle:
     add(res, "y$")
     add(res, $r.index)
   of pkRule:
-    toStrAux(r.sons[0], res)    
+    toStrAux(r.sons[0], res)
     add(res, " <- ")
     toStrAux(r.sons[1], res)
   of pkList:
     for i in 0 .. high(r.sons):
       toStrAux(r.sons[i], res)
-      add(res, "\n")  
+      add(res, "\n")
   of pkStartAnchor:
     add(res, '^')
 
@@ -506,8 +506,8 @@ type
 
 {.deprecated: [TCaptures: Captures].}
 
-proc bounds*(c: Captures, 
-             i: range[0..MaxSubpatterns-1]): tuple[first, last: int] = 
+proc bounds*(c: Captures,
+             i: range[0..MaxSubpatterns-1]): tuple[first, last: int] =
   ## returns the bounds ``[first..last]`` of the `i`'th capture.
   result = c.matches[i]
 
@@ -527,7 +527,7 @@ when not useUnicode:
 
 proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
                nosideEffect, rtl, extern: "npegs$1".} =
-  ## low-level matching proc that implements the PEG interpreter. Use this 
+  ## low-level matching proc that implements the PEG interpreter. Use this
   ## for maximum efficiency (every other PEG operation ends up calling this
   ## proc).
   ## Returns -1 if it does not match, else the length of the match
@@ -541,7 +541,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       result = runeLenAt(s, start)
     else:
       result = -1
-  of pkLetter: 
+  of pkLetter:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -550,7 +550,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       else: result = -1
     else:
       result = -1
-  of pkLower: 
+  of pkLower:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -559,7 +559,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       else: result = -1
     else:
       result = -1
-  of pkUpper: 
+  of pkUpper:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -568,16 +568,16 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       else: result = -1
     else:
       result = -1
-  of pkTitle: 
+  of pkTitle:
     if s[start] != '\0':
       var a: Rune
       result = start
       fastRuneAt(s, result, a)
-      if isTitle(a): dec(result, start) 
+      if isTitle(a): dec(result, start)
       else: result = -1
     else:
       result = -1
-  of pkWhitespace: 
+  of pkWhitespace:
     if s[start] != '\0':
       var a: Rune
       result = start
@@ -641,7 +641,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
     when false: echo "leave: ", p.nt.name
     if result < 0: c.ml = oldMl
   of pkSequence:
-    var oldMl = c.ml  
+    var oldMl = c.ml
     result = 0
     for i in 0..high(p.sons):
       var x = rawMatch(s, p.sons[i], start+result, c)
@@ -723,11 +723,11 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
       #else: silently ignore the capture
     else:
       c.ml = idx
-  of pkBackRef..pkBackRefIgnoreStyle: 
+  of pkBackRef..pkBackRefIgnoreStyle:
     if p.index >= c.ml: return -1
     var (a, b) = c.matches[p.index]
     var n: Peg
-    n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) 
+    n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef))
     n.term = s.substr(a, b)
     result = rawMatch(s, n, start, c)
   of pkStartAnchor:
@@ -755,7 +755,7 @@ proc match*(s: string, pattern: Peg, matches: var openArray[string],
   result = rawMatch(s, pattern, start, c) == len(s) - start
   if result: fillMatches(s, matches, c)
 
-proc match*(s: string, pattern: Peg, 
+proc match*(s: string, pattern: Peg,
             start = 0): bool {.nosideEffect, rtl, extern: "npegs$1".} =
   ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
   var c: Captures
@@ -773,7 +773,7 @@ proc matchLen*(s: string, pattern: Peg, matches: var openArray[string],
   result = rawMatch(s, pattern, start, c)
   if result >= 0: fillMatches(s, matches, c)
 
-proc matchLen*(s: string, pattern: Peg, 
+proc matchLen*(s: string, pattern: Peg,
                start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} =
   ## the same as ``match``, but it returns the length of the match,
   ## if there is no match, -1 is returned. Note that a match length
@@ -797,11 +797,11 @@ proc find*(s: string, pattern: Peg, matches: var openArray[string],
       return i
   return -1
   # could also use the pattern here: (!P .)* P
-  
+
 proc findBounds*(s: string, pattern: Peg, matches: var openArray[string],
                  start = 0): tuple[first, last: int] {.
                  nosideEffect, rtl, extern: "npegs$1Capture".} =
-  ## returns the starting position and end position of ``pattern`` in ``s`` 
+  ## returns the starting position and end position of ``pattern`` in ``s``
   ## and the captured
   ## substrings in the array ``matches``. If it does not match, nothing
   ## is written into ``matches`` and (-1,0) is returned.
@@ -814,8 +814,8 @@ proc findBounds*(s: string, pattern: Peg, matches: var openArray[string],
       fillMatches(s, matches, c)
       return (i, i+L-1)
   return (-1, 0)
-  
-proc find*(s: string, pattern: Peg, 
+
+proc find*(s: string, pattern: Peg,
            start = 0): int {.nosideEffect, rtl, extern: "npegs$1".} =
   ## returns the starting position of ``pattern`` in ``s``. If it does not
   ## match, -1 is returned.
@@ -824,8 +824,8 @@ proc find*(s: string, pattern: Peg,
   for i in start .. s.len-1:
     if rawMatch(s, pattern, i, c) >= 0: return i
   return -1
-  
-iterator findAll*(s: string, pattern: Peg, start = 0): string = 
+
+iterator findAll*(s: string, pattern: Peg, start = 0): string =
   ## yields all matching *substrings* of `s` that match `pattern`.
   var c: Captures
   c.origStart = start
@@ -838,23 +838,23 @@ iterator findAll*(s: string, pattern: Peg, start = 0): string =
     else:
       yield substr(s, i, i+L-1)
       inc(i, L)
-    
+
 proc findAll*(s: string, pattern: Peg, start = 0): seq[string] {.
-  nosideEffect, rtl, extern: "npegs$1".} = 
+  nosideEffect, rtl, extern: "npegs$1".} =
   ## returns all matching *substrings* of `s` that match `pattern`.
   ## If it does not match, @[] is returned.
   accumulateResult(findAll(s, pattern, start))
 
 when not defined(nimhygiene):
   {.pragma: inject.}
-  
+
 template `=~`*(s: string, pattern: Peg): bool =
-  ## This calls ``match`` with an implicit declared ``matches`` array that 
-  ## can be used in the scope of the ``=~`` call: 
-  ## 
+  ## This calls ``match`` with an implicit declared ``matches`` array that
+  ## can be used in the scope of the ``=~`` call:
+  ##
   ## .. code-block:: nim
   ##
-  ##   if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}": 
+  ##   if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}":
   ##     # matches a key=value pair:
   ##     echo("Key: ", matches[0])
   ##     echo("Value: ", matches[1])
@@ -865,7 +865,7 @@ template `=~`*(s: string, pattern: Peg): bool =
   ##     echo("comment: ", matches[0])
   ##   else:
   ##     echo("syntax error")
-  ##  
+  ##
   bind MaxSubpatterns
   when not declaredInScope(matches):
     var matches {.inject.}: array[0..MaxSubpatterns-1, string]
@@ -902,7 +902,7 @@ proc replacef*(s: string, sub: Peg, by: string): string {.
   ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
   ##
   ## .. code-block:: nim
-  ##   "var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2")
+  ##   "var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2")
   ##
   ## Results in:
   ##
@@ -941,10 +941,10 @@ proc replace*(s: string, sub: Peg, by = ""): string {.
       add(result, by)
       inc(i, x)
   add(result, substr(s, i))
-  
+
 proc parallelReplace*(s: string, subs: varargs[
                       tuple[pattern: Peg, repl: string]]): string {.
-                      nosideEffect, rtl, extern: "npegs$1".} = 
+                      nosideEffect, rtl, extern: "npegs$1".} =
   ## Returns a modified copy of `s` with the substitutions in `subs`
   ## applied in parallel.
   result = ""
@@ -964,8 +964,8 @@ proc parallelReplace*(s: string, subs: varargs[
       add(result, s[i])
       inc(i)
   # copy the rest:
-  add(result, substr(s, i))  
-  
+  add(result, substr(s, i))
+
 proc transformFile*(infile, outfile: string,
                     subs: varargs[tuple[pattern: Peg, repl: string]]) {.
                     rtl, extern: "npegs$1".} =
@@ -974,7 +974,7 @@ proc transformFile*(infile, outfile: string,
   ## error occurs. This is supposed to be used for quick scripting.
   var x = readFile(infile).string
   writeFile(outfile, x.parallelReplace(subs))
-  
+
 iterator split*(s: string, sep: Peg): string =
   ## Splits the string `s` into substrings.
   ##
@@ -1049,14 +1049,14 @@ type
     tkBackref,          ## '$'
     tkDollar,           ## '$'
     tkHat               ## '^'
-  
+
   TToken {.final.} = object  ## a token
     kind: TTokKind           ## the type of the token
     modifier: TModifier
     literal: string          ## the parsed (string) literal
     charset: set[char]       ## if kind == tkCharSet
     index: int               ## if kind == tkBackref
-  
+
   PegLexer {.inheritable.} = object          ## the lexer object.
     bufpos: int               ## the current position within the buffer
     buf: cstring              ## the buffer itself
@@ -1086,7 +1086,7 @@ proc handleLF(L: var PegLexer, pos: int): int =
   result = pos+1
   L.lineStart = result
 
-proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) = 
+proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) =
   L.buf = input
   L.bufpos = 0
   L.lineNumber = line
@@ -1094,69 +1094,69 @@ proc init(L: var PegLexer, input, filename: string, line = 1, col = 0) =
   L.lineStart = 0
   L.filename = filename
 
-proc getColumn(L: PegLexer): int {.inline.} = 
+proc getColumn(L: PegLexer): int {.inline.} =
   result = abs(L.bufpos - L.lineStart) + L.colOffset
 
-proc getLine(L: PegLexer): int {.inline.} = 
+proc getLine(L: PegLexer): int {.inline.} =
   result = L.lineNumber
-  
+
 proc errorStr(L: PegLexer, msg: string, line = -1, col = -1): string =
   var line = if line < 0: getLine(L) else: line
   var col = if col < 0: getColumn(L) else: col
   result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg]
 
-proc handleHexChar(c: var PegLexer, xi: var int) = 
+proc handleHexChar(c: var PegLexer, xi: var int) =
   case c.buf[c.bufpos]
-  of '0'..'9': 
+  of '0'..'9':
     xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
     inc(c.bufpos)
-  of 'a'..'f': 
+  of 'a'..'f':
     xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
     inc(c.bufpos)
-  of 'A'..'F': 
+  of 'A'..'F':
     xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
     inc(c.bufpos)
   else: discard
 
-proc getEscapedChar(c: var PegLexer, tok: var TToken) = 
+proc getEscapedChar(c: var PegLexer, tok: var TToken) =
   inc(c.bufpos)
   case c.buf[c.bufpos]
-  of 'r', 'R', 'c', 'C': 
+  of 'r', 'R', 'c', 'C':
     add(tok.literal, '\c')
     inc(c.bufpos)
-  of 'l', 'L': 
+  of 'l', 'L':
     add(tok.literal, '\L')
     inc(c.bufpos)
-  of 'f', 'F': 
+  of 'f', 'F':
     add(tok.literal, '\f')
     inc(c.bufpos)
-  of 'e', 'E': 
+  of 'e', 'E':
     add(tok.literal, '\e')
     inc(c.bufpos)
-  of 'a', 'A': 
+  of 'a', 'A':
     add(tok.literal, '\a')
     inc(c.bufpos)
-  of 'b', 'B': 
+  of 'b', 'B':
     add(tok.literal, '\b')
     inc(c.bufpos)
-  of 'v', 'V': 
+  of 'v', 'V':
     add(tok.literal, '\v')
     inc(c.bufpos)
-  of 't', 'T': 
+  of 't', 'T':
     add(tok.literal, '\t')
     inc(c.bufpos)
-  of 'x', 'X': 
+  of 'x', 'X':
     inc(c.bufpos)
     var xi = 0
     handleHexChar(c, xi)
     handleHexChar(c, xi)
     if xi == 0: tok.kind = tkInvalid
     else: add(tok.literal, chr(xi))
-  of '0'..'9': 
+  of '0'..'9':
     var val = ord(c.buf[c.bufpos]) - ord('0')
     inc(c.bufpos)
     var i = 1
-    while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): 
+    while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}):
       val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
       inc(c.bufpos)
       inc(i)
@@ -1169,32 +1169,32 @@ proc getEscapedChar(c: var PegLexer, tok: var TToken) =
   else:
     add(tok.literal, c.buf[c.bufpos])
     inc(c.bufpos)
-  
-proc skip(c: var PegLexer) = 
+
+proc skip(c: var PegLexer) =
   var pos = c.bufpos
   var buf = c.buf
-  while true: 
+  while true:
     case buf[pos]
-    of ' ', '\t': 
+    of ' ', '\t':
       inc(pos)
     of '#':
       while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
     of '\c':
       pos = handleCR(c, pos)
       buf = c.buf
-    of '\L': 
+    of '\L':
       pos = handleLF(c, pos)
       buf = c.buf
-    else: 
+    else:
       break                   # EndOfFile also leaves the loop
   c.bufpos = pos
-  
-proc getString(c: var PegLexer, tok: var TToken) = 
+
+proc getString(c: var PegLexer, tok: var TToken) =
   tok.kind = tkStringLit
   var pos = c.bufpos + 1
   var buf = c.buf
   var quote = buf[pos-1]
-  while true: 
+  while true:
     case buf[pos]
     of '\\':
       c.bufpos = pos
@@ -1205,13 +1205,13 @@ proc getString(c: var PegLexer, tok: var TToken) =
       break
     elif buf[pos] == quote:
       inc(pos)
-      break      
+      break
     else:
       add(tok.literal, buf[pos])
       inc(pos)
   c.bufpos = pos
-  
-proc getDollar(c: var PegLexer, tok: var TToken) = 
+
+proc getDollar(c: var PegLexer, tok: var TToken) =
   var pos = c.bufpos + 1
   var buf = c.buf
   if buf[pos] in {'0'..'9'}:
@@ -1223,8 +1223,8 @@ proc getDollar(c: var PegLexer, tok: var TToken) =
   else:
     tok.kind = tkDollar
   c.bufpos = pos
-  
-proc getCharSet(c: var PegLexer, tok: var TToken) = 
+
+proc getCharSet(c: var PegLexer, tok: var TToken) =
   tok.kind = tkCharSet
   tok.charset = {}
   var pos = c.bufpos + 1
@@ -1247,7 +1247,7 @@ proc getCharSet(c: var PegLexer, tok: var TToken) =
     of '\C', '\L', '\0':
       tok.kind = tkInvalid
       break
-    else: 
+    else:
       ch = buf[pos]
       inc(pos)
     incl(tok.charset, ch)
@@ -1267,18 +1267,18 @@ proc getCharSet(c: var PegLexer, tok: var TToken) =
         of '\C', '\L', '\0':
           tok.kind = tkInvalid
           break
-        else: 
+        else:
           ch2 = buf[pos]
           inc(pos)
         for i in ord(ch)+1 .. ord(ch2):
           incl(tok.charset, chr(i))
   c.bufpos = pos
   if caret: tok.charset = {'\1'..'\xFF'} - tok.charset
-  
-proc getSymbol(c: var PegLexer, tok: var TToken) = 
+
+proc getSymbol(c: var PegLexer, tok: var TToken) =
   var pos = c.bufpos
   var buf = c.buf
-  while true: 
+  while true:
     add(tok.literal, buf[pos])
     inc(pos)
     if buf[pos] notin strutils.IdentChars: break
@@ -1294,7 +1294,7 @@ proc getBuiltin(c: var PegLexer, tok: var TToken) =
     tok.kind = tkEscaped
     getEscapedChar(c, tok) # may set tok.kind to tkInvalid
 
-proc getTok(c: var PegLexer, tok: var TToken) = 
+proc getTok(c: var PegLexer, tok: var TToken) =
   tok.kind = tkInvalid
   tok.modifier = modNone
   setLen(tok.literal, 0)
@@ -1309,11 +1309,11 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     else:
       tok.kind = tkCurlyLe
       add(tok.literal, '{')
-  of '}': 
+  of '}':
     tok.kind = tkCurlyRi
     inc(c.bufpos)
     add(tok.literal, '}')
-  of '[': 
+  of '[':
     getCharSet(c, tok)
   of '(':
     tok.kind = tkParLe
@@ -1323,7 +1323,7 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     tok.kind = tkParRi
     inc(c.bufpos)
     add(tok.literal, ')')
-  of '.': 
+  of '.':
     tok.kind = tkAny
     inc(c.bufpos)
     add(tok.literal, '.')
@@ -1331,16 +1331,16 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     tok.kind = tkAnyRune
     inc(c.bufpos)
     add(tok.literal, '_')
-  of '\\': 
+  of '\\':
     getBuiltin(c, tok)
   of '\'', '"': getString(c, tok)
   of '$': getDollar(c, tok)
-  of '\0': 
+  of '\0':
     tok.kind = tkEof
     tok.literal = "[EOF]"
   of 'a'..'z', 'A'..'Z', '\128'..'\255':
     getSymbol(c, tok)
-    if c.buf[c.bufpos] in {'\'', '"'} or 
+    if c.buf[c.bufpos] in {'\'', '"'} or
         c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}:
       case tok.literal
       of "i": tok.modifier = modIgnoreCase
@@ -1388,7 +1388,7 @@ proc getTok(c: var PegLexer, tok: var TToken) =
     tok.kind = tkAt
     inc(c.bufpos)
     add(tok.literal, '@')
-    if c.buf[c.bufpos] == '@': 
+    if c.buf[c.bufpos] == '@':
       tok.kind = tkCurlyAt
       inc(c.bufpos)
       add(tok.literal, '@')
@@ -1407,7 +1407,7 @@ proc arrowIsNextTok(c: PegLexer): bool =
   result = c.buf[pos] == '<' and c.buf[pos+1] == '-'
 
 # ----------------------------- parser ----------------------------------------
-    
+
 type
   EInvalidPeg* = object of ValueError ## raised if an invalid
                                          ## PEG has been detected
@@ -1425,7 +1425,7 @@ proc pegError(p: PegParser, msg: string, line = -1, col = -1) =
   e.msg = errorStr(p, msg, line, col)
   raise e
 
-proc getTok(p: var PegParser) = 
+proc getTok(p: var PegParser) =
   getTok(p, p.tok)
   if p.tok.kind == tkInvalid: pegError(p, "invalid token")
 
@@ -1475,7 +1475,7 @@ proc builtin(p: var PegParser): Peg =
   of "white": result = unicodeWhitespace()
   else: pegError(p, "unknown built-in: " & p.tok.literal)
 
-proc token(terminal: Peg, p: PegParser): Peg = 
+proc token(terminal: Peg, p: PegParser): Peg =
   if p.skip.kind == pkEmpty: result = terminal
   else: result = sequence(p.skip, terminal)
 
@@ -1496,7 +1496,7 @@ proc primary(p: var PegParser): Peg =
   else: discard
   case p.tok.kind
   of tkIdentifier:
-    if p.identIsVerbatim: 
+    if p.identIsVerbatim:
       var m = p.tok.modifier
       if m == modNone: m = p.modifier
       result = modifiedTerm(p.tok.literal, m).token(p)
@@ -1539,17 +1539,17 @@ proc primary(p: var PegParser): Peg =
   of tkEscaped:
     result = term(p.tok.literal[0]).token(p)
     getTok(p)
-  of tkDollar: 
+  of tkDollar:
     result = endAnchor()
     getTok(p)
-  of tkHat: 
+  of tkHat:
     result = startAnchor()
     getTok(p)
   of tkBackref:
     var m = p.tok.modifier
     if m == modNone: m = p.modifier
     result = modifiedBackref(p.tok.index, m).token(p)
-    if p.tok.index < 0 or p.tok.index > p.captures: 
+    if p.tok.index < 0 or p.tok.index > p.captures:
       pegError(p, "invalid back reference index: " & $p.tok.index)
     getTok(p)
   else:
@@ -1573,7 +1573,7 @@ proc seqExpr(p: var PegParser): Peg =
   while true:
     case p.tok.kind
     of tkAmp, tkNot, tkAt, tkStringLit, tkCharSet, tkParLe, tkCurlyLe,
-       tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref, 
+       tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref,
        tkHat, tkCurlyAt:
       result = sequence(result, primary(p))
     of tkIdentifier:
@@ -1587,7 +1587,7 @@ proc parseExpr(p: var PegParser): Peg =
   while p.tok.kind == tkBar:
     getTok(p)
     result = result / seqExpr(p)
-  
+
 proc parseRule(p: var PegParser): NonTerminal =
   if p.tok.kind == tkIdentifier and arrowIsNextTok(p):
     result = getNonTerminal(p, p.tok.literal)
@@ -1601,7 +1601,7 @@ proc parseRule(p: var PegParser): NonTerminal =
     incl(result.flags, ntDeclared) # NOW inlining may be attempted
   else:
     pegError(p, "rule expected, but found: " & p.tok.literal)
-  
+
 proc rawParse(p: var PegParser): Peg =
   ## parses a rule or a PEG expression
   while p.tok.kind == tkBuiltin:
@@ -1680,7 +1680,7 @@ when isMainModule:
   assert(not match("W_HI_L", peg"\y 'while'"))
   assert(not match("W_HI_Le", peg"\y v'while'"))
   assert match("W_HI_Le", peg"y'while'")
-  
+
   assert($ +digits == $peg"\d+")
   assert "0158787".match(peg"\d+")
   assert "ABC 0232".match(peg"\w+\s+\d+")
@@ -1693,14 +1693,14 @@ when isMainModule:
 
   var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident)
   assert matchLen("key1=  cal9", pattern) == 11
-  
+
   var ws = newNonTerminal("ws", 1, 1)
   ws.rule = *whitespace
-  
+
   var expr = newNonTerminal("expr", 1, 1)
   expr.rule = sequence(capture(ident), *sequence(
                 nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr)))
-  
+
   var c: Captures
   var s = "a+b +  c +d+e+f"
   assert rawMatch(s, expr.rule, 0, c) == len(s)
@@ -1722,7 +1722,7 @@ when isMainModule:
     assert matches[0] == "abc"
   else:
     assert false
-  
+
   var g2 = peg"""S <- A B / C D
                  A <- 'a'+
                  B <- 'b'+
@@ -1753,13 +1753,13 @@ when isMainModule:
 
   for x in findAll("abcdef", peg"^{.}", 3):
     assert x == "d"
-    
+
   if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')":
     assert matches[0] == "f"
     assert matches[1] == "a, b"
   else:
     assert false
-  
+
   assert match("eine übersicht und außerdem", peg"(\letter \white*)+")
   # ß is not a lower cased letter?!
   assert match("eine übersicht und auerdem", peg"(\lower \white*)+")
diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim
index 40c61f1d9..04aa8316a 100644
--- a/lib/pure/rationals.nim
+++ b/lib/pure/rationals.nim
@@ -22,6 +22,16 @@ proc initRational*[T](num, den: T): Rational[T] =
   result.num = num
   result.den = den
 
+proc `//`*[T](num, den: T): Rational[T] = initRational[T](num, den)
+  ## A friendlier version of `initRational`. Example usage:
+  ##
+  ## .. code-block:: nim
+  ##   var x = 1//3 + 1//5
+
+proc `$`*[T](x: Rational[T]): string =
+  ## Turn a rational number into a string.
+  result = $x.num & "/" & $x.den
+
 proc toRational*[T](x: SomeInteger): Rational[T] =
   ## Convert some integer `x` to a rational number.
   result.num = x
@@ -200,26 +210,26 @@ when isMainModule:
     z = Rational[int](num: 0, den: 1)
     o = initRational(num=1, den=1)
     a = initRational(1, 2)
-    b = initRational(-1, -2)
-    m1 = initRational(-1, 1)
-    tt = initRational(10, 2)
+    b = -1 // -2
+    m1 = -1 // 1
+    tt = 10 // 2
 
   assert( a     == a )
   assert( (a-a) == z )
   assert( (a+b) == o )
   assert( (a/b) == o )
-  assert( (a*b) == initRational(1, 4) )
-  assert( (3/a) == initRational(6,1) )
-  assert( (a/3) == initRational(1,6) )
-  assert( a*b   == initRational(1,4) )
+  assert( (a*b) == 1 // 4 )
+  assert( (3/a) == 6 // 1 )
+  assert( (a/3) == 1 // 6 )
+  assert( a*b   == 1 // 4 )
   assert( tt*z  == z )
   assert( 10*a  == tt )
   assert( a*10  == tt )
   assert( tt/10 == a  )
-  assert( a-m1  == initRational(3, 2) )
-  assert( a+m1  == initRational(-1, 2) )
-  assert( m1+tt == initRational(16, 4) )
-  assert( m1-tt == initRational(6, -1) )
+  assert( a-m1  == 3 // 2 )
+  assert( a+m1  == -1 // 2 )
+  assert( m1+tt == 16 // 4 )
+  assert( m1-tt == 6 // -1 )
 
   assert( z < o )
   assert( z <= o )
@@ -238,28 +248,28 @@ when isMainModule:
   assert( not(b > a) )
   assert( cmp(a, b) == 0 )
 
-  var x = initRational(1,3)
+  var x = 1//3
 
-  x *= initRational(5,1)
-  assert( x == initRational(5,3) )
-  x += initRational(2,9)
-  assert( x == initRational(17,9) )
-  x -= initRational(9,18)
-  assert( x == initRational(25,18) )
-  x /= initRational(1,2)
-  assert( x == initRational(50,18) )
+  x *= 5//1
+  assert( x == 5//3 )
+  x += 2 // 9
+  assert( x == 17//9 )
+  x -= 9//18
+  assert( x == 25//18 )
+  x /= 1//2
+  assert( x == 50//18 )
 
-  var y = initRational(1,3)
+  var y = 1//3
 
   y *= 4
-  assert( y == initRational(4,3) )
+  assert( y == 4//3 )
   y += 5
-  assert( y == initRational(19,3) )
+  assert( y == 19//3 )
   y -= 2
-  assert( y == initRational(13,3) )
+  assert( y == 13//3 )
   y /= 9
-  assert( y == initRational(13,27) )
+  assert( y == 13//27 )
 
-  assert toRational[int, int](5) == initRational(5,1)
+  assert toRational[int, int](5) == 5//1
   assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
   assert toInt(z) == 0
diff --git a/lib/pure/redis.nim b/lib/pure/redis.nim
index 52d81b3a4..64d3e1470 100644
--- a/lib/pure/redis.nim
+++ b/lib/pure/redis.nim
@@ -798,6 +798,22 @@ proc zunionstore*(r: Redis, destination: string, numkeys: string,
   
   return r.readInteger()
 
+# HyperLogLog
+
+proc pfadd*(r: Redis, key: string, elements: varargs[string]): RedisInteger = 
+  ## Add variable number of elements into special 'HyperLogLog' set type
+  r.sendCommand("PFADD", key, elements)
+  return r.readInteger()
+
+proc pfcount*(r: Redis, key: string): RedisInteger =
+  ## Count approximate number of elements in 'HyperLogLog'
+  r.sendCommand("PFCOUNT", key)
+  return r.readInteger()
+
+proc pfmerge*(r: Redis, destination: string, sources: varargs[string]) =
+  ## Merge several source HyperLogLog's into one specified by destKey
+  r.sendCommand("PFMERGE", destination, sources)
+  raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
 # Pub/Sub
 
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 67c80e592..e706f2016 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -224,10 +224,12 @@ proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int =
 
 proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) = 
   var s = StringStream(s)
-  if bufLen > 0: 
-    setLen(s.data, s.data.len + bufLen)
-    copyMem(addr(s.data[s.pos]), buffer, bufLen)
-    inc(s.pos, bufLen)
+  if bufLen <= 0:
+    return
+  if s.pos + bufLen > s.data.len:
+    setLen(s.data, s.pos + bufLen)
+  copyMem(addr(s.data[s.pos]), buffer, bufLen)
+  inc(s.pos, bufLen)
 
 proc ssClose(s: Stream) =
   var s = StringStream(s)
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 39f468ee3..655203cda 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -499,26 +499,47 @@ proc parseEnum*[T: enum](s: string, default: T): T =
       return e
   result = default
 
-proc repeatChar*(count: int, c: char = ' '): string {.noSideEffect,
+proc repeat*(c: char, count: int): string {.noSideEffect,
   rtl, extern: "nsuRepeatChar".} =
   ## Returns a string of length `count` consisting only of
   ## the character `c`. You can use this proc to left align strings. Example:
   ##
   ## .. code-block:: nim
+  ##   proc tabexpand(indent: int, text: string, tabsize: int = 4) =
+  ##     echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize), text
+  ##
+  ##   tabexpand(4, "At four")
+  ##   tabexpand(5, "At five")
+  ##   tabexpand(6, "At six")
+  result = newString(count)
+  for i in 0..count-1: result[i] = c
+
+proc repeat*(s: string, n: int): string {.noSideEffect,
+  rtl, extern: "nsuRepeatStr".} =
+  ## Returns String `s` concatenated `n` times.  Example:
+  ##
+  ## .. code-block:: nim
+  ##   echo "+++ STOP ".repeat(4), "+++"
+  result = newStringOfCap(n * s.len)
+  for i in 1..n: result.add(s)
+
+template spaces*(n: int): string =  repeat(' ',n)
+  ## Returns a String with `n` space characters. You can use this proc
+  ## to left align strings. Example:
+  ##
+  ## .. code-block:: nim
   ##   let
   ##     width = 15
   ##     text1 = "Hello user!"
   ##     text2 = "This is a very long string"
-  ##   echo text1 & repeatChar(max(0, width - text1.len)) & "|"
-  ##   echo text2 & repeatChar(max(0, width - text2.len)) & "|"
-  result = newString(count)
-  for i in 0..count-1: result[i] = c
+  ##   echo text1 & spaces(max(0, width - text1.len)) & "|"
+  ##   echo text2 & spaces(max(0, width - text2.len)) & "|"
 
-proc repeatStr*(count: int, s: string): string {.noSideEffect,
-  rtl, extern: "nsuRepeatStr".} =
-  ## Returns `s` concatenated `count` times.
-  result = newStringOfCap(count*s.len)
-  for i in 0..count-1: result.add(s)
+proc repeatChar*(count: int, c: char = ' '): string {.deprecated.} = repeat(c, count)
+  ## deprecated: use repeat() or spaces()
+
+proc repeatStr*(count: int, s: string): string {.deprecated.} = repeat(s, count)
+  ## deprecated: use repeat(string, count) or string.repeat(count)
 
 proc align*(s: string, count: int, padding = ' '): string {.
   noSideEffect, rtl, extern: "nsuAlignString".} =
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index e32ea786a..c39667611 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -628,25 +628,25 @@ proc formatToken(info: TimeInfo, token: string, buf: var string) =
     var fr = ($info.year).len()-2
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 2: fyear = repeatChar(2-fyear.len(), '0') & fyear
+    if fyear.len != 2: fyear = repeat('0', 2-fyear.len()) & fyear
     buf.add(fyear)
   of "yyy":
     var fr = ($info.year).len()-3
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 3: fyear = repeatChar(3-fyear.len(), '0') & fyear
+    if fyear.len != 3: fyear = repeat('0', 3-fyear.len()) & fyear
     buf.add(fyear)
   of "yyyy":
     var fr = ($info.year).len()-4
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 4: fyear = repeatChar(4-fyear.len(), '0') & fyear
+    if fyear.len != 4: fyear = repeat('0', 4-fyear.len()) & fyear
     buf.add(fyear)
   of "yyyyy":
     var fr = ($info.year).len()-5
     if fr < 0: fr = 0
     var fyear = ($info.year)[fr .. ($info.year).len()-1]
-    if fyear.len != 5: fyear = repeatChar(5-fyear.len(), '0') & fyear
+    if fyear.len != 5: fyear = repeat('0', 5-fyear.len()) & fyear
     buf.add(fyear)
   of "z":
     let hrs = (info.timezone div 60) div 60
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index 42e6a3195..a6f8f916b 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -118,21 +118,35 @@ proc toUTF8*(c: Rune): string {.rtl, extern: "nuc$1".} =
   elif i <=% 0x07FF:
     result = newString(2)
     result[0] = chr((i shr 6) or 0b110_00000)
-    result[1] = chr((i and ones(6)) or 0b10_000000)
+    result[1] = chr((i and ones(6)) or 0b10_0000_00)
   elif i <=% 0xFFFF:
     result = newString(3)
     result[0] = chr(i shr 12 or 0b1110_0000)
     result[1] = chr(i shr 6 and ones(6) or 0b10_0000_00)
     result[2] = chr(i and ones(6) or 0b10_0000_00)
-  elif i <=% 0x0010FFFF:
+  elif i <=% 0x001FFFFF:
     result = newString(4)
     result[0] = chr(i shr 18 or 0b1111_0000)
     result[1] = chr(i shr 12 and ones(6) or 0b10_0000_00)
     result[2] = chr(i shr 6 and ones(6) or 0b10_0000_00)
     result[3] = chr(i and ones(6) or 0b10_0000_00)
+  elif i <=% 0x03FFFFFF:
+    result = newString(5)
+    result[0] = chr(i shr 24 or 0b111110_00)
+    result[1] = chr(i shr 18 and ones(6) or 0b10_0000_00)
+    result[2] = chr(i shr 12 and ones(6) or 0b10_0000_00)
+    result[3] = chr(i shr 6 and ones(6) or 0b10_0000_00)
+    result[4] = chr(i and ones(6) or 0b10_0000_00)
+  elif i <=% 0x7FFFFFFF:
+    result = newString(6)
+    result[0] = chr(i shr 30 or 0b1111110_0)
+    result[1] = chr(i shr 24 and ones(6) or 0b10_0000_00)
+    result[2] = chr(i shr 18 and ones(6) or 0b10_0000_00)
+    result[3] = chr(i shr 12 and ones(6) or 0b10_0000_00)
+    result[4] = chr(i shr 6 and ones(6) or 0b10_0000_00)
+    result[5] = chr(i and ones(6) or 0b10_0000_00)
   else:
-    result = newString(1)
-    result[0] = chr(i)
+    discard # error, exception?
 
 proc `$`*(rune: Rune): string =
   ## converts a rune to a string
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index 9a6e273a8..b0afb75f9 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -286,6 +286,16 @@ proc `$`*(u: Uri): string =
 
 when isMainModule:
   block:
+    let str = "http://localhost"
+    let test = parseUri(str)
+    doAssert test.path == ""
+
+  block:
+    let str = "http://localhost/"
+    let test = parseUri(str)
+    doAssert test.path == "/"
+
+  block:
     let str = "http://localhost:8080/test"
     let test = parseUri(str)
     doAssert test.scheme == "http"
diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index 2e55ff182..6242e589e 100644
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -1083,7 +1083,7 @@ proc addEscaped(s: string): string =
     else: result.add(c)
 
 proc nodeToXml(n: PNode, indent: int = 0): string =
-  result = repeatChar(indent, ' ') & "<" & n.nodeName
+  result = spaces(indent) & "<" & n.nodeName
   if not isNil(n.attributes):
     for i in items(n.attributes):
       result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"")
@@ -1098,23 +1098,23 @@ proc nodeToXml(n: PNode, indent: int = 0): string =
       of ElementNode:
         result.add(nodeToXml(i, indent + 2))
       of TextNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add(addEscaped(i.nodeValue))
       of CDataSectionNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add("<![CDATA[" & i.nodeValue & "]]>")
       of ProcessingInstructionNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add("<?" & PProcessingInstruction(i).target & " " &
                           PProcessingInstruction(i).data & " ?>")
       of CommentNode:
-        result.add(repeatChar(indent * 2, ' '))
+        result.add(spaces(indent * 2))
         result.add("<!-- " & i.nodeValue & " -->")
       else:
         continue
       result.add("\n")
     # Add the ending tag - </tag>
-    result.add(repeatChar(indent, ' ') & "</" & n.nodeName & ">")
+    result.add(spaces(indent) & "</" & n.nodeName & ">")
 
 proc `$`*(doc: PDocument): string =
   ## Converts a PDocument object into a string representation of it's XML
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
index 7a26a17c5..093c0f3a7 100644
--- a/lib/system/deepcopy.nim
+++ b/lib/system/deepcopy.nim
@@ -34,9 +34,9 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} =
 
 proc copyDeepString(src: NimString): NimString {.inline.} =
   if src != nil:
-    result = rawNewString(src.space)
+    result = rawNewStringNoInit(src.len)
     result.len = src.len
-    c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+    c_memcpy(result.data, src.data, src.len + 1)
 
 proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
   var
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 1f4279c8f..9de0c6503 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -117,7 +117,7 @@ proc usrToCell(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
   result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
 
-proc canbeCycleRoot(c: PCell): bool {.inline.} =
+proc canBeCycleRoot(c: PCell): bool {.inline.} =
   result = ntfAcyclic notin c.typ.flags
 
 proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index ae2d2c85d..b8a61d627 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -593,7 +593,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
         return
     add(gch.zct, res)
 
-proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1: bool): pointer =
+proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1 = false): pointer =
   # generates a new object and sets its reference counter to 0
   acquire(gch)
   sysAssert(allocInv(gch.region), "rawNewObj begin")
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index 7dee054ac..aff0c0e6f 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -11,7 +11,7 @@ when declared(NimString):
   # we are in system module:
   {.pragma: codegenType, compilerproc.}
 else:
-  {.pragma: codegenType.}
+  {.pragma: codegenType, importc.}
 
 type 
   # This should be he same as ast.TTypeKind
@@ -65,7 +65,7 @@ type
     tyBigNum,
 
   TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
-  TNimNode {.codegenType, final.} = object
+  TNimNode {.codegenType.} = object
     kind: TNimNodeKind
     offset: int
     typ: ptr TNimType
@@ -78,7 +78,7 @@ type
     ntfAcyclic = 1,    # type cannot form a cycle
     ntfEnumHole = 2    # enum has holes and thus `$` for them needs the slow
                        # version
-  TNimType {.codegenType, final.} = object
+  TNimType {.codegenType.} = object
     size: int
     kind: TNimKind
     flags: set[TNimTypeFlag]
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index a05398a09..48adb895d 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -145,8 +145,8 @@ proc readAllFile(file: File): string =
 proc readAll(file: File): TaintedString = 
   # Separate handling needed because we need to buffer when we
   # don't know the overall length of the File.
-  var len = rawFileSize(file)
-  if len >= 0:
+  let len = if file != stdin: rawFileSize(file) else: -1
+  if len > 0:
     result = readAllFile(file, len).TaintedString
   else:
     result = readAllBuffer(file).TaintedString
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 9d9cc0070..11780a9aa 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -30,18 +30,30 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
   if a == b: return true
   if a == nil or b == nil: return false
   return a.len == b.len and
-    c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32
+    c_memcmp(a.data, b.data, a.len) == 0'i32
 
 when declared(allocAtomic):
   template allocStr(size: expr): expr =
     cast[NimString](allocAtomic(size))
+
+  template allocStrNoInit(size: expr): expr =
+    cast[NimString](boehmAllocAtomic(size))
 else:
   template allocStr(size: expr): expr =
     cast[NimString](newObj(addr(strDesc), size))
 
+  template allocStrNoInit(size: expr): expr =
+    cast[NimString](rawNewObj(addr(strDesc), size, gch))
+
+proc rawNewStringNoInit(space: int): NimString {.compilerProc.} =
+  var s = space
+  if s < 7: s = 7
+  result = allocStrNoInit(sizeof(TGenericSeq) + s + 1)
+  result.reserved = s
+
 proc rawNewString(space: int): NimString {.compilerProc.} =
   var s = space
-  if s < 8: s = 7
+  if s < 7: s = 7
   result = allocStr(sizeof(TGenericSeq) + s + 1)
   result.reserved = s
 
@@ -53,10 +65,10 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.} =
   var start = max(start, 0)
   var len = min(last, s.len-1) - start + 1
   if len > 0:
-    result = rawNewString(len)
+    result = rawNewStringNoInit(len)
     result.len = len
-    c_memcpy(result.data, addr(s.data[start]), len * sizeof(char))
-    #result.data[len] = '\0'
+    c_memcpy(result.data, addr(s.data[start]), len)
+    result.data[len] = '\0'
   else:
     result = rawNewString(len)
 
@@ -64,10 +76,9 @@ proc copyStr(s: NimString, start: int): NimString {.compilerProc.} =
   result = copyStrLast(s, start, s.len-1)
 
 proc toNimStr(str: cstring, len: int): NimString {.compilerProc.} =
-  result = rawNewString(len)
+  result = rawNewStringNoInit(len)
   result.len = len
-  c_memcpy(result.data, str, (len+1) * sizeof(char))
-  #result.data[len] = '\0' # readline relies on this!
+  c_memcpy(result.data, str, len + 1)
 
 proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
   result = toNimStr(str, c_strlen(str))
@@ -77,23 +88,24 @@ proc copyString(src: NimString): NimString {.compilerRtl.} =
     if (src.reserved and seqShallowFlag) != 0:
       result = src
     else:
-      result = rawNewString(src.space)
+      result = rawNewStringNoInit(src.len)
       result.len = src.len
-      c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+      c_memcpy(result.data, src.data, src.len + 1)
 
 proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
   if src != nil:
-    var s = src.space
-    if s < 8: s = 7
     when declared(newObjRC1):
+      var s = src.len
+      if s < 7: s = 7
       result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) +
                                s+1))
+      result.reserved = s
     else:
-      result = allocStr(sizeof(TGenericSeq) + s + 1)
-    result.reserved = s
+      result = rawNewStringNoInit(src.len)
     result.len = src.len
     c_memcpy(result.data, src.data, src.len + 1)
 
+
 proc hashString(s: string): int {.compilerproc.} =
   # the compiler needs exactly the same hash function!
   # this used to be used for efficient generation of string case statements
@@ -113,7 +125,7 @@ proc addChar(s: NimString, c: char): NimString =
   if result.len >= result.space:
     result.reserved = resize(result.space)
     result = cast[NimString](growObj(result,
-      sizeof(TGenericSeq) + (result.reserved+1) * sizeof(char)))
+      sizeof(TGenericSeq) + result.reserved + 1))
   result.data[result.len] = c
   result.data[result.len+1] = '\0'
   inc(result.len)
@@ -157,7 +169,7 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
     result = cast[NimString](growObj(dest, sizeof(TGenericSeq) + sp + 1))
     result.reserved = sp
     #result = rawNewString(sp)
-    #copyMem(result, dest, dest.len * sizeof(char) + sizeof(TGenericSeq))
+    #copyMem(result, dest, dest.len + sizeof(TGenericSeq))
     # DO NOT UPDATE LEN YET: dest.len = newLen
 
 proc appendString(dest, src: NimString) {.compilerproc, inline.} =
@@ -264,7 +276,17 @@ proc nimFloatToStr(f: float): string {.compilerproc.} =
     buf[n] = '.'
     buf[n+1] = '0'
     buf[n+2] = '\0'
-  result = $buf
+  # On Windows nice numbers like '1.#INF', '-1.#INF' or '1.#NAN' are produced.
+  # We want to get rid of these here:
+  if buf[n-1] == 'N':
+    result = "nan"
+  elif buf[n-1] == 'F':
+    if buf[0] == '-':
+      result = "-inf"
+    else:
+      result = "inf"
+  else:
+    result = $buf
 
 proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc,
   header: "<stdlib.h>", noSideEffect.}
diff --git a/readme.md b/readme.md
index 2252ea52b..e716c0d0d 100644
--- a/readme.md
+++ b/readme.md
@@ -39,8 +39,7 @@ $ bin/nim c koch
 $ ./koch boot -d:release
 ```
 
-``koch install [dir]`` may then be used to install Nim, or you can simply
-add it to your PATH. More ``koch`` related options are documented in
+``koch install [dir]`` may then be used to install Nim, but lots of things don't work then so don't do that. Add it to your PATH instead. More ``koch`` related options are documented in
 [doc/koch.txt](doc/koch.txt).
 
 The above steps can be performed on Windows in a similar fashion, the
diff --git a/tests/actiontable/tactiontable2.nim b/tests/actiontable/tactiontable2.nim
index 99bb3dca0..fbc65a67d 100644
--- a/tests/actiontable/tactiontable2.nim
+++ b/tests/actiontable/tactiontable2.nim
@@ -1,6 +1,5 @@
 discard """
-  line: 21
-  errormsg: "invalid type: 'Table[string, proc (string){.gcsafe.}]'"
+  output: "action 3 arg"
 """
 
 import tables
diff --git a/tests/assert/tfailedassert.nim b/tests/assert/tfailedassert.nim
index 8766321bf..16769f529 100644
--- a/tests/assert/tfailedassert.nim
+++ b/tests/assert/tfailedassert.nim
@@ -3,14 +3,14 @@ discard """
 WARNING: false first assertion from bar
 ERROR: false second assertion from bar
 -1
-tests/assert/tfailedassert.nim:27 false assertion from foo
+tfailedassert.nim:27 false assertion from foo
 '''
 """
 
 type
   TLineInfo = tuple[filename: string, line: int]
 
-  TMyError = object of E_Base
+  TMyError = object of Exception
     lineinfo: TLineInfo
 
   EMyError = ref TMyError
diff --git a/tests/ccgbugs/tmissingderef.nim b/tests/ccgbugs/tmissingderef.nim
new file mode 100644
index 000000000..edff1dd4e
--- /dev/null
+++ b/tests/ccgbugs/tmissingderef.nim
@@ -0,0 +1,30 @@
+discard """
+  output: '''255
+1 1
+0.5'''
+"""
+
+# bug #1181
+
+type
+  TFoo = object
+    x: int32
+
+proc mainowar =
+  var foo: TFoo
+  foo.x = 0xff
+  var arr1 = cast[ptr array[4, uint8]](addr foo)[] # Fails.
+  echo arr1[when cpuEndian == littleEndian: 0 else: 3]
+
+  var i = 1i32
+  let x = addr i
+  var arr2 = cast[ptr array[4, uint8]](x)[] # Fails.
+  echo arr2[when cpuEndian == littleEndian: 0 else: 3], " ", i
+
+  # bug #1715
+  var a: array[2, float32] = [0.5'f32, 0.7]
+  let p = addr a
+  var b = p[]
+  echo b[0]
+
+mainowar()
diff --git a/tests/ccgbugs/trecursive_closure.nim b/tests/ccgbugs/trecursive_closure.nim
new file mode 100644
index 000000000..50c363a4a
--- /dev/null
+++ b/tests/ccgbugs/trecursive_closure.nim
@@ -0,0 +1,8 @@
+# bug #2233
+type MalType = object
+  fun: proc: MalType
+
+proc f(x: proc: MalType) =
+  discard x()
+
+f(nil)
diff --git a/tests/ccgbugs/tstringslice.nim b/tests/ccgbugs/tstringslice.nim
new file mode 100644
index 000000000..66b3bbbe4
--- /dev/null
+++ b/tests/ccgbugs/tstringslice.nim
@@ -0,0 +1,10 @@
+
+# bug #794
+type TRange = range[0..3]
+
+const str = "123456789"
+
+for i in TRange.low .. TRange.high:
+  echo str[i]                          #This works fine
+  echo str[int(i) .. int(TRange.high)] #So does this
+  echo str[i .. TRange.high]           #The compiler complains about this
diff --git a/tests/ccgbugs/tuple_canon.nim b/tests/ccgbugs/tuple_canon.nim
new file mode 100644
index 000000000..960e2aae9
--- /dev/null
+++ b/tests/ccgbugs/tuple_canon.nim
@@ -0,0 +1,80 @@
+# bug #2250
+
+import
+    math, strutils
+
+type
+    Meters = float
+    Point2[T] = tuple[x, y: T]
+
+    HexState* = enum
+        hsOn, hsOff
+
+    Index = uint16
+
+    HexGrid* = object
+        w, h: int                       ## Width and height of the hex grid.
+        radius: Meters                  ## Radius of circle that circumscribes a hexagon.
+        grid: seq[HexState]             ## Information on what hexes are drawn.
+
+    HexVtxIndex = enum
+        hiA, hiB, hiC, hiD, hiE, hiF
+
+    HexCoord* = Point2[int]
+
+const
+    HexDY = sqrt(1.0 - (0.5 * 0.5))     # dy from center to midpoint of 1-2
+    HexDX = sqrt(1.0 - (HexDY * HexDY)) # dx from center to midpoint of 1-5 (0.5)
+
+
+let
+    hexOffsets : array[HexVtxIndex, Point2[float]] = [
+                  (-1.0, 0.0),
+                  (-HexDX, -HexDY),
+                  (HexDX, -HexDY),
+                  (1.0, 0.0),
+                  (HexDX, HexDY),
+                  (-HexDX, HexDY)]
+
+    evenSharingOffsets : array[HexVtxIndex, tuple[hc: HexCoord; idx: HexVtxIndex]] = [
+            ((0,0), hiA),
+            ((0,0), hiB),
+            ((1,-1), hiA),
+            ((1,0), hiB),
+            ((1,0), hiA),
+            ((0,1), hiB)]
+
+    oddSharingOffsets : array[HexVtxIndex, tuple[hc: HexCoord; idx: HexVtxIndex]] = [
+            ((0,0), hiA),
+            ((0,0), hiB),
+            ((1,0), hiA),
+            ((1,1), hiB),
+            ((1,1), hiA),
+            ((0,1), hiB)]
+
+template odd*(i: int) : expr =
+    (i and 1) != 0
+
+proc vidx(hg: HexGrid; col, row: int; i: HexVtxIndex) : Index =
+    #NOTE: this variation compiles
+    #var offset : type(evenSharingOffsets[i])
+    #
+    #if odd(col):
+    #    offset = oddSharingOffsets[i]
+    #else:
+    #    offset = evenSharingOffsets[i]
+
+    let
+        #NOTE: this line generates the bad code
+        offset = (if odd(col): oddSharingOffsets[i] else: evenSharingOffsets[i])
+        x = col + 1 + offset.hc.x
+        y = row + 1 + offset.hc.y
+
+    result = Index(x*2 + y * (hg.w + 2)*2 + int(offset.idx))
+
+proc go() =
+    var hg : HexGrid
+
+    echo "vidx ", $vidx(hg, 1, 2, hiC)
+
+go()
diff --git a/tests/clearmsg/tconsttypemismatch.nim b/tests/clearmsg/tconsttypemismatch.nim
new file mode 100644
index 000000000..edf480348
--- /dev/null
+++ b/tests/clearmsg/tconsttypemismatch.nim
@@ -0,0 +1,8 @@
+discard """
+  file: "tconsttypemismatch.nim"
+  line: 7
+  errormsg: "type mismatch"
+"""
+# bug #2252
+const foo: int = 1000 / 30
+
diff --git a/tests/cpp/trawsockets.nim b/tests/cpp/trawsockets.nim
index d034245d0..bc129de57 100644
--- a/tests/cpp/trawsockets.nim
+++ b/tests/cpp/trawsockets.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $target"
+  cmd: "nim cpp $file"
 """
 
 import rawsockets
diff --git a/tests/cpp/ttypeinfo.nim b/tests/cpp/ttypeinfo.nim
index e72883dbf..1529c86e9 100644
--- a/tests/cpp/ttypeinfo.nim
+++ b/tests/cpp/ttypeinfo.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim cpp $target"
+  cmd: "nim cpp $file"
 """
 
 import typeinfo
diff --git a/tests/deprecated/tdeprecated.nim b/tests/deprecated/tdeprecated.nim
index f41f0a72f..ed3d2733a 100644
--- a/tests/deprecated/tdeprecated.nim
+++ b/tests/deprecated/tdeprecated.nim
@@ -1,6 +1,5 @@
 discard """
-  line: 9
-  errormsg: "'a' is deprecated [Deprecated]"
+  nimout: "'a' is deprecated [Deprecated]"
 """
 
 var
@@ -8,4 +7,3 @@ var
   
 a[8] = 1
 
-
diff --git a/tests/destructor/tdestructor2.nim b/tests/destructor/tdestructor2.nim
index 1bdf4993b..6f966d861 100644
--- a/tests/destructor/tdestructor2.nim
+++ b/tests/destructor/tdestructor2.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 20
-  errormsg: " usage of a type with a destructor in a non destructible context"
+  line: 23
+  nimout: " usage of a type with a destructor in a non destructible context"
 """
 
 {.experimental.}
@@ -19,5 +19,9 @@ proc open: TMyObj =
 
 proc `$`(x: TMyObj): string = $x.y
 
-echo open()
+proc foo =
+  discard open()
+
+# XXX doesn't trigger this yet:
+#echo open()
 
diff --git a/tests/exception/tdefer1.nim b/tests/exception/tdefer1.nim
new file mode 100644
index 000000000..61439530a
--- /dev/null
+++ b/tests/exception/tdefer1.nim
@@ -0,0 +1,18 @@
+discard """
+  output: '''hi
+hi'''
+"""
+
+# bug #1742
+
+template test(): expr =
+    let a = 0
+    defer: echo "hi"
+    a
+
+let i = test()
+
+import strutils
+let x = try: parseInt("133a")
+        except: -1
+        finally: echo "hi"
diff --git a/tests/generics/tgeneric3.nim b/tests/generics/tgeneric3.nim
index 6fb929efb..289bf1fd5 100644
--- a/tests/generics/tgeneric3.nim
+++ b/tests/generics/tgeneric3.nim
@@ -188,7 +188,7 @@ proc traceTree[T,D](root: PNode[T,D]) =
     write stdout, space
 
   proc doTrace(n: PNode[T,D], level: int) =
-    var space = repeatChar(2 * level)
+    var space = spaces(2 * level)
     traceln(space)
     write stdout, "node: "
     if n == nil:
diff --git a/tests/generics/twrong_floatlit_type.nim b/tests/generics/twrong_floatlit_type.nim
new file mode 100644
index 000000000..2db8b4353
--- /dev/null
+++ b/tests/generics/twrong_floatlit_type.nim
@@ -0,0 +1,118 @@
+discard """
+  errormsg: "type mismatch"
+  line: 116
+"""
+
+# bug #2169
+import strutils, math
+
+type
+  Point2D*[S] = object
+    x*, y*: S
+  Matrix2x3*[S] = distinct array[6, S] ## Row major order
+
+  Vector2D*[S] = object
+    x*, y*: S
+
+proc `[]`*[T](m: Matrix2x3[T], i: int): T = array[6, T](m)[i]
+
+template M11*[T](m: Matrix2x3[T]): T = m[0]
+template M12*[T](m: Matrix2x3[T]): T = m[1]
+template M13*[T](m: Matrix2x3[T]): T = m[2]
+template M21*[T](m: Matrix2x3[T]): T = m[3]
+template M22*[T](m: Matrix2x3[T]): T = m[4]
+template M23*[T](m: Matrix2x3[T]): T = m[5]
+
+proc identity*[T](): Matrix2x3[T] =
+    Matrix2x3[T]([T(1.0), 0.0, 0.0,   0.0, 1.0, 0.0])
+
+proc translation*[T](p: Point2D[T]): Matrix2x3[T] =
+    Matrix2x3[T]([T(1.0), T(0.0), p.x, T(0.0), T(1.0), p.y])
+
+proc translation*[T](p: Vector2D[T]): Matrix2x3[T] =
+    Matrix2x3[T]([T(1.0), T(0.0), p.x, T(0.0), T(1.0), p.y])
+
+proc scale*[T](v: Vector2D[T]): Matrix2x3[T] =
+    Matrix2x3[T]([v.x, T(0.0), T(0.0), T(0.0), v.y, T(0.0)])
+
+proc rotation*[T](th: T): Matrix2x3[T] = 
+    let 
+        c = T(cos(th.float))
+        s = T(sin(th.float))
+ 
+    Matrix2x3[T]([c, -s, T(0.0),   s, c, T(0.0)])
+ 
+proc `*`*[T](a, b: Matrix2x3[T]): Matrix2x3[T] = 
+    # Here we pretend that row 3 is [0,0,0,1] without
+    # actually storing it in the matrix.
+    Matrix2x3[T]([a.M11*b.M11 + a.M12*b.M21, 
+                  a.M11*b.M12 + a.M12*b.M22, 
+                  a.M11*b.M13 + a.M12*b.M23 + a.M13, 
+ 
+                  a.M21*b.M11 + a.M22*b.M21,
+                  a.M21*b.M12 + a.M22*b.M22,
+                  a.M21*b.M13 + a.M22*b.M23 + a.M23])
+ 
+proc `*`*[T](a: Matrix2x3[T], p: Point2D[T]): Point2D[T] = 
+    let 
+        x = a.M11*p.x + a.M12*p.y + a.M13
+        y = a.M21*p.x + a.M22*p.y + a.M23
+ 
+    Point2D[T](x: x, y: y)
+ 
+# making these so things like "line" that need a constructor don't stick out.
+# 2x2 determinant:  |a b|
+#                   |c d|  = ad - bc
+ 
+# String rendering
+#
+template ff[S](x: S): string = 
+    formatFloat(float(x), ffDefault, 0)
+ 
+proc `$`*[S](p: Point2D[S]): string = 
+    "P($1, $2)" % [ff(p.x), ff(p.y)]
+ 
+proc `$`*[S](p: Vector2D[S]): string = 
+    "V($1, $2)" % [ff(p.x), ff(p.y)]
+ 
+proc `$`*[S](m: Matrix2x3[S]): string =
+    "M($1 $2 $3/$4 $5 $6)" % [ff(m.M11), ff(m.M12), ff(m.M13), 
+                              ff(m.M21), ff(m.M22), ff(m.M23)]
+
+#
+# Vector operators.
+proc `-`*[S](a: Vector2D[S]): Vector2D[S] =
+  Vector2D[S](x: -a.x, y: -a.y)
+
+proc `+`*[S](a, b: Vector2D[S]): Vector2D[S] =
+  Vector2D[S](x: a.x + b.x, y: a.y + b.y)
+
+proc `-`*[S](a, b: Vector2D[S]): Vector2D[S] =
+  Vector2D[S](x: a.x - b.x, y: a.y - b.y)
+
+proc `*`*[S](v: Vector2D[S], sc: S): Vector2D[S] =
+  Vector2D[S](x: v.x*sc, y: v.y*sc)
+
+proc `*`*[S](sc: S, v: Vector2D[S]): Vector2D[S] =
+  Vector2D[S](x: v.x*sc, y: v.y*sc)
+
+proc `/`*[S](v: Vector2D[S], sc: S): Vector2D[S] =
+  Vector2D[S](x: v.x/sc, y: v.y/sc)
+
+proc `/`*[S](sc: S; v: Vector2D[S]): Vector2D[S] =
+  Vector2D[S](x: sc/v.x, y: sc/v.y)
+
+proc `/`*[S](a, b: Vector2D[S]): Vector2D[S] = 
+  Vector2D[S](x: a.x/b.x, y: a.y/b.y)
+#proc vec[S](x, y: S): Vector2D[S]
+proc vec[S](x, y: S): Vector2D[S] =
+  Vector2D[S](x: x, y: y)
+
+if isMainModule:
+  # Comment out this let, and the program will fail to
+  # compile with a type mismatch, as expected.
+
+  let s3 = scale(vec(4.0, 4.0))
+  let barf = translation(Point2D[float32](x: 1, y: 1)) * rotation(float(0.7))
+
+  echo "Badness ", barf
diff --git a/tests/global/tglobal.nim b/tests/global/tglobal.nim
index 84c4510c1..d44a62afc 100644
--- a/tests/global/tglobal.nim
+++ b/tests/global/tglobal.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "toop1.nim"
   output: "in globalaux2: 10\ntotal globals: 2\nint value: 100\nstring value: second"
+  disabled: "true"
 """
 
 import globalaux, globalaux2
diff --git a/tests/manyloc/argument_parser/argument_parser.nim b/tests/manyloc/argument_parser/argument_parser.nim
index a507a08e4..060610ae0 100644
--- a/tests/manyloc/argument_parser/argument_parser.nim
+++ b/tests/manyloc/argument_parser/argument_parser.nim
@@ -471,7 +471,7 @@ proc build_help*(expected: seq[Tparameter_specification] = @[],
   let width = prefixes.map(proc (x: string): int = 3 + len(x)).max
 
   for line in zip(prefixes, helps):
-    result.add(line.a & repeatChar(width - line.a.len) & line.b)
+    result.add(line.a & spaces(width - line.a.len) & line.b)
 
 
 proc echo_help*(expected: seq[Tparameter_specification] = @[],
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim b/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim
index a9759687f..3c5a7835c 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim
@@ -1,5 +1,5 @@
 import streams
-from strutils import repeatChar
+from strutils import repeat
 
 proc readPaddedStr*(s: PStream, length: int, padChar = '\0'): TaintedString = 
   var lastChr = length
@@ -10,7 +10,7 @@ proc readPaddedStr*(s: PStream, length: int, padChar = '\0'): TaintedString =
 proc writePaddedStr*(s: PStream, str: string, length: int, padChar = '\0') =
   if str.len < length:
     s.write(str)
-    s.write(repeatChar(length - str.len, padChar))
+    s.write(repeat(padChar, length - str.len))
   elif str.len > length:
     s.write(str.substr(0, length - 1))
   else:
@@ -37,7 +37,7 @@ when isMainModule:
   testStream.setPosition 0
   testStream.writePaddedStr("Sup", 10)
   echo(repr(testStream), testStream.data.len)
-  doAssert testStream.data == "Sup"&repeatChar(7, '\0')
+  doAssert testStream.data == "Sup"&repeat('\0', 7)
   
   testStream.setPosition 0
   res = testStream.readPaddedStr(10)
diff --git a/tests/manyloc/keineschweine/enet_server/enet_server.nim b/tests/manyloc/keineschweine/enet_server/enet_server.nim
index 6dd1a6a7f..c2e893273 100644
--- a/tests/manyloc/keineschweine/enet_server/enet_server.nim
+++ b/tests/manyloc/keineschweine/enet_server/enet_server.nim
@@ -144,7 +144,7 @@ when isMainModule:
     discard """block:
       var 
         TestFile: FileChallengePair
-        contents = repeatStr(2, "abcdefghijklmnopqrstuvwxyz")
+        contents = repeat("abcdefghijklmnopqrstuvwxyz", 2)
       testFile.challenge = newScFileChallenge("foobar.test", FZoneCfg, contents.len.int32) 
       testFile.file = checksumStr(contents)
       myAssets.add testFile"""
diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim
index 0a5dc1efc..525d8a054 100644
--- a/tests/manyloc/keineschweine/keineschweine.nim
+++ b/tests/manyloc/keineschweine/keineschweine.nim
@@ -113,7 +113,7 @@ when defined(recordMode):
     isRecording = false
   proc zeroPad*(s: string; minLen: int): string =
     if s.len < minLen:
-      result = repeatChar(minLen - s.len, '0')
+      result = repeat(0, minLen - s.len)
       result.add s
     else:
       result = s
diff --git a/tests/manyloc/keineschweine/lib/map_filter.nim b/tests/manyloc/keineschweine/lib/map_filter.nim
index 966b84b6a..5776c9225 100644
--- a/tests/manyloc/keineschweine/lib/map_filter.nim
+++ b/tests/manyloc/keineschweine/lib/map_filter.nim
@@ -27,9 +27,9 @@ when isMainModule:
   var res = t.map(proc(z: int): int = result = z * 10)
   dumpSeq res
 
-  from strutils import toHex, repeatStr
+  from strutils import toHex
   var foocakes = t.map(proc(z: int): string = 
-    result = toHex((z * 23).biggestInt, 4))
+    result = toHex((z * 23).BiggestInt, 4))
   dumpSeq foocakes
 
   t.mapInPlace(proc(z: int): int = result = z * 30)
diff --git a/tests/manyloc/keineschweine/lib/zlib_helpers.nim b/tests/manyloc/keineschweine/lib/zlib_helpers.nim
index 9a6542d75..fcd0e8d24 100644
--- a/tests/manyloc/keineschweine/lib/zlib_helpers.nim
+++ b/tests/manyloc/keineschweine/lib/zlib_helpers.nim
@@ -24,17 +24,17 @@ when isMainModule:
   import strutils
   var r = compress("Hello")
   echo repr(r)
-  var l = "Hello".len
-  var rr = uncompress(r, l)
+  var ln = "Hello".len
+  var rr = uncompress(r, ln)
   echo repr(rr)
   assert rr == "Hello"
 
-  proc `*`(a: string; b: int): string {.inline.} = result = repeatStr(b, a)
+  proc `*`(a: string; b: int): string {.inline.} = result = repeat(a, b)
   var s = "yo dude sup bruh homie" * 50
   r = compress(s)
   echo s.len, " -> ", r.len
 
-  l = s.len
-  rr = uncompress(r, l)
+  ln = s.len
+  rr = uncompress(r, ln)
   echo r.len, " -> ", rr.len
   assert rr == s
\ No newline at end of file
diff --git a/tests/manyloc/keineschweine/server/old_sg_server.nim b/tests/manyloc/keineschweine/server/old_sg_server.nim
index ac85cbf62..1e57c12a1 100644
--- a/tests/manyloc/keineschweine/server/old_sg_server.nim
+++ b/tests/manyloc/keineschweine/server/old_sg_server.nim
@@ -174,7 +174,7 @@ when isMainModule:
   block:
     var 
       TestFile: FileChallengePair
-      contents = repeatStr(2, "abcdefghijklmnopqrstuvwxyz")
+      contents = repeat("abcdefghijklmnopqrstuvwxyz", 2)
     testFile.challenge = newScFileChallenge("foobar.test", FZoneCfg, contents.len.int32) 
     testFile.file = checksumStr(contents)
     myAssets.add testFile
diff --git a/tests/misc/parsecomb.nim b/tests/misc/parsecomb.nim
new file mode 100644
index 000000000..68a61373f
--- /dev/null
+++ b/tests/misc/parsecomb.nim
@@ -0,0 +1,105 @@
+type Input[T] = object
+  toks: seq[T]
+  index: int
+
+type
+  ResultKind* = enum rkSuccess, rkFailure
+  Result*[T, O] = object
+    case kind*: ResultKind
+    of rkSuccess:
+      output*: O
+      input: Input[T]
+    of rkFailure:
+      nil
+
+type
+  Parser*[T, O] = distinct proc (input: Input[T]): Result[T, O]
+
+proc unit*[T, O](v: O): Parser[T, O] =
+  Parser(proc (inp: Input[T]): Result[T, O] =
+    Result[T, O](kind: rkSuccess, output: v, input: inp))
+
+proc fail*[T, O](): Parser[T, O] =
+  Parser(proc (inp: Input[T]): Result[T, O] =
+    Result(kind: rkFailure))
+
+method runInput[T, O](self: Parser[T, O], inp: Input[T]): Result[T, O] =
+  # hmmm ..
+  type tmp = proc (input: Input[T]): Result[T, O]
+  # XXX: above needed for now, as without the `tmp` bit below, it compiles to invalid C.
+  tmp(self)(inp)
+
+method run*[T, O](self: Parser[T, O], toks: seq[T]): Result[T, O] =
+  self.runInput(Input[T](toks: toks, index: 0))
+
+method chain*[T, O1, O2](self: Parser[T, O1], nextp: proc (v: O1): Parser[T, O2]): Parser[T, O2] =
+  Parser(proc (inp: Input[T]): Result[T, O2] =
+    let r = self.runInput(inp)
+    case r.kind:
+    of rkSuccess:
+      nextp(r.output).runInput(r.input)
+    of rkFailure:
+      Result[T, O2](kind: rkFailure))
+
+method skip[T](self: Input[T], n: int): Input[T] =
+  Input[T](toks: self.toks, index: self.index + n)
+
+proc pskip*[T](n: int): Parser[T, tuple[]] =
+  Parser(proc (inp: Input[T]): Result[T, tuple[]] =
+    if inp.index + n <= inp.toks.len:
+      Result[T, tuple[]](kind: rkSuccess, output: (), input: inp.skip(n))
+    else:
+      Result[T, tuple[]](kind: rkFailure))
+
+proc tok*[T](t: T): Parser[T, T] =
+  Parser(proc (inp: Input[T]): Result[T, T] =
+    if inp.index < inp.toks.len and inp.toks[inp.index] == t:
+      pskip[T](1).then(unit[T, T](t)).runInput(inp)
+    else:
+      Result[T, T](kind: rkFailure))
+
+proc `+`*[T, O](first: Parser[T, O], second: Parser[T, O]): Parser[T, O] =
+  Parser(proc (inp: Input[T]): Result[T, O] =
+    let r = first.runInput(inp)
+    case r.kind
+    of rkSuccess:
+      r
+    else:
+      second.runInput(inp))
+
+# end of primitives (definitions involving Parser(..))
+
+method map*[T, O1, O2](self: Parser[T, O1], p: proc (v: O1): O2): Parser[T, O2] =
+  self.chain(proc (v: O1): Parser[T, O2] =
+    unit[T, O2](p(v)))
+
+method then*[T, O1, O2](self: Parser[T, O1], next: Parser[T, O2]): Parser[T, O2] =
+  self.chain(proc (v: O1): Parser[T, O2] =
+    next)
+
+proc `*`*[T, O1, O2](first: Parser[T, O1], second: Parser[T, O2]): Parser[T, (O1, O2)] =
+  first.chain(proc (v1: O1): Parser[T, (O1, O2)] =
+    second.map(proc (v2: O2): (O1, O2) =
+      (v1, v2)))
+
+proc repeat0*[T, O](inner: Parser[T, O]): Parser[T, seq[O]] =
+  var nothing = unit[T, seq[O]](@[])
+  inner.chain(proc(v: O): Parser[T, seq[O]] =
+    repeat0(inner).map(proc(vs: seq[O]): seq[O] =
+      @[v] & vs)) + nothing
+
+proc repeat1*[T, O](inner: Parser[T, O]): Parser[T, seq[O]] =
+  inner.chain(proc(v: O): Parser[T, seq[O]] =
+    repeat0(inner).map(proc(vs: seq[O]): seq[O] =
+      @[v] & vs))
+
+proc leftRec*[T, O, A](inner: Parser[T, O], after: Parser[T, A], fold: proc(i: O, a: A): O): Parser[T, O] =
+  (inner*repeat0(after)).map(proc(ias: (O, seq[A])): O =
+    var (i, asx) = ias
+    for a in asx:
+      i = fold(i, a)
+    i)
+
+proc lazy*[T, O](inner: proc(): Parser[T, O]): Parser[T, O] =
+  unit[T, tuple[]](()).chain(proc(v: tuple[]): Parser[T, O] =
+    inner())
diff --git a/tests/misc/tparsecombnum.nim b/tests/misc/tparsecombnum.nim
new file mode 100644
index 000000000..6fe539813
--- /dev/null
+++ b/tests/misc/tparsecombnum.nim
@@ -0,0 +1,55 @@
+import parsecomb
+
+discard """
+  output: "-289096"
+"""
+
+type Num = int
+
+# forward stuff
+var exp3: Parser[string, Num]
+var exp = lazy(proc(): Parser[string, Num] = exp3)
+
+var digit = (proc(): Parser[string, Num] =
+  result = tok("0").then(unit[string, Num](Num(0)))
+  for n in 1..9:
+    result = result + tok($n).then(unit[string, Num](Num(n)))
+)()
+
+var num = repeat1(digit).map(proc(ds: seq[Num]): Num =
+  result = 0
+  for d in ds:
+    result = result*10 + d)
+
+type Op = proc(a, b: Num): Num
+
+var plusOp = tok("+").then(unit[string, Op](proc(a, b: Num): Num = a + b))
+var minusOp = tok("-").then(unit[string, Op](proc(a, b: Num): Num = a - b))
+var timesOp = tok("*").then(unit[string, Op](proc(a, b: Num): Num = a*b))
+var divideOp = tok("/").then(unit[string, Op](proc(a, b: Num): Num = a div b))
+
+var paren = (tok("(") * exp * tok(")")).map(proc(ler: ((string, Num), string)): Num =
+  var (le, r) = ler
+  var (l, e) = le
+  e)
+
+proc foldOp(a: Num, ob: (Op, Num)): Num =
+  var (o, b) = ob
+  o(a, b)
+
+var exp0 = paren + num
+var exp1 = exp0.leftRec((timesOp + divideOp)*exp0, foldOp)
+var exp2 = exp1.leftRec((plusOp + minusOp)*exp1, foldOp)
+exp3 = exp2
+
+proc strsplit(s: string): seq[string] =
+  result = @[]
+  for i in 0 .. s.len - 1:
+    result.add($s[i])
+
+var r = exp.run("523-(1243+411/744*1642/1323)*233".strsplit)
+case r.kind:
+of rkSuccess:
+  echo r.output
+of rkFailure:
+  echo "failed"
diff --git a/tests/objects/tobjpragma.nim b/tests/objects/tobjpragma.nim
index f9fbd5e40..dda8057b6 100644
--- a/tests/objects/tobjpragma.nim
+++ b/tests/objects/tobjpragma.nim
@@ -7,8 +7,11 @@ discard """
 1
 2
 3'''
+  disabled: "true"
 """
 
+# Disabled since some versions of GCC ignore the 'packed' attribute
+
 # Test 
 
 type
diff --git a/tests/overload/tprefer_tygenericinst.nim b/tests/overload/tprefer_tygenericinst.nim
new file mode 100644
index 000000000..2700bed5e
--- /dev/null
+++ b/tests/overload/tprefer_tygenericinst.nim
@@ -0,0 +1,17 @@
+discard """
+  output: "Version 2 was called."
+  disabled: true
+"""
+
+# bug #2220
+
+type A[T] = object
+type B = A[int]
+
+proc p[X](x: X) =
+  echo "Version 1 was called."
+
+proc p(x: B) =
+  echo "Version 2 was called."
+
+p(B()) # This call reported as ambiguous.
diff --git a/tests/overload/tsymtabchange_during_or.nim b/tests/overload/tsymtabchange_during_or.nim
new file mode 100644
index 000000000..b5551bcc7
--- /dev/null
+++ b/tests/overload/tsymtabchange_during_or.nim
@@ -0,0 +1,24 @@
+
+# bug #2229
+
+type Type1 = object
+        id: int
+
+type Type2 = object
+    id: int
+
+proc init(self: var Type1, a: int, b: ref Type2) =
+    echo "1"
+
+proc init(self: var Type2, a: int) =
+    echo """
+        Works when this proc commented out
+        Otherwise error:
+        test.nim(14, 4) Error: ambiguous call; both test.init(self: var Type1, a: int, b: ref Type2) and test.init(self: var Type1, a: int, b: ref Type2) match for: (Type1, int literal(1), ref Type2)
+    """
+
+var a: Type1
+init(a, 1, (
+    var b = new(Type2);
+    b
+))
diff --git a/tests/stdlib/tmarshal.nim b/tests/stdlib/tmarshal.nim
index 1b83aab53..a778d2f77 100644
--- a/tests/stdlib/tmarshal.nim
+++ b/tests/stdlib/tmarshal.nim
@@ -6,11 +6,11 @@ import marshal
 
 template testit(x: expr) = discard $$to[type(x)]($$x)
 
-var x: 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"]]

-testit(x)

+var x: 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"]]
+testit(x)
 var test2: tuple[name: string, s: int] = ("tuple test", 56)
 testit(test2)
 
@@ -24,7 +24,7 @@ type
     of blah:
       help: string
     else:
-      nil
+      discard
       
   PNode = ref TNode
   TNode = object
diff --git a/tests/stdlib/tstrutil.nim b/tests/stdlib/tstrutil.nim
index ce9094bc0..3db484faa 100644
--- a/tests/stdlib/tstrutil.nim
+++ b/tests/stdlib/tstrutil.nim
@@ -46,7 +46,13 @@ assert "/1/2/3".rfind('0') == -1
 assert(toHex(100i16, 32) == "00000000000000000000000000000064")
 assert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
 
-main()
-#OUT ha/home/a1xyz/usr/bin
+assert(' '.repeat(8)== "        ")
+assert(" ".repeat(8) == "        ")
+assert(spaces(8) == "        ")
 
+assert(' '.repeat(0) == "")
+assert(" ".repeat(0) == "")
+assert(spaces(0) == "")
 
+main()
+#OUT ha/home/a1xyz/usr/bin
diff --git a/tests/template/texponential_eval.nim b/tests/template/texponential_eval.nim
new file mode 100644
index 000000000..32af9e8f7
--- /dev/null
+++ b/tests/template/texponential_eval.nim
@@ -0,0 +1,47 @@
+# bug #1940
+
+discard """
+  nimout: '''===
+merge (A) with (B)
+merge (A B) with (C)
+merge (A B C) with (D)
+merge (A B C D) with (E)
+merge (A B C D E) with (F)
+==='''
+"""
+
+type SqlStmt = tuple
+  sql: string
+  parts: int
+
+proc sql(q: string): SqlStmt =
+  result.sql = q
+  result.parts = 1
+
+template `&%%`(x, y: SqlStmt): SqlStmt =
+  const a = x
+  const b = y
+
+  static:
+    #echo "some merge"
+    echo "merge (", a.sql, ") with (", b.sql, ")"
+
+
+  const newSql = a.sql & " " & b.sql
+  const newParts = a.parts + b.parts
+
+  SqlStmt((sql: newSql, parts: newParts))
+
+static:
+  echo "==="
+
+let c =(sql("A") &%%
+        sql("B")) &%%
+        sql("C")  &%%
+        sql("D") &%%
+        sql("E") &%%
+        sql("F")
+echo c.sql
+
+static:
+  echo "==="
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index ed4d27cab..323abd768 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -230,17 +230,17 @@ proc testStdlib(r: var TResults, pattern, options: string, cat: Category) =
     else:
       testNoSpec r, makeTest(test, options, cat, actionCompile)
 
-# ----------------------------- babel ----------------------------------------
+# ----------------------------- nimble ----------------------------------------
 type PackageFilter = enum
   pfCoreOnly
   pfExtraOnly
   pfAll
 
 let 
-  babelExe = findExe("babel")
-  babelDir = getHomeDir() / ".babel"
-  packageDir = babelDir / "pkgs"
-  packageIndex = babelDir / "packages.json"
+  nimbleExe = findExe("nimble")
+  nimbleDir = getHomeDir() / ".nimble"
+  packageDir = nimbleDir / "pkgs"
+  packageIndex = nimbleDir / "packages.json"
 
 proc waitForExitEx(p: Process): int =
   var outp = outputStream(p)
@@ -255,7 +255,7 @@ proc waitForExitEx(p: Process): int =
 
 proc getPackageDir(package: string): string =
   ## TODO - Replace this with dom's version comparison magic.
-  var commandOutput = execCmdEx("babel path $#" % package)
+  var commandOutput = execCmdEx("nimble path $#" % package)
   if commandOutput.exitCode != QuitSuccess:
     return ""
   else:
@@ -268,7 +268,7 @@ iterator listPackages(filter: PackageFilter): tuple[name, url: string] =
     let
       name = package["name"].str
       url = package["url"].str
-      isCorePackage = "nimrod-code" in normalize(url)
+      isCorePackage = "nim-lang" in normalize(url)
     case filter:
     of pfCoreOnly:
       if isCorePackage:
@@ -279,13 +279,13 @@ iterator listPackages(filter: PackageFilter): tuple[name, url: string] =
     of pfAll:
       yield (name, url)
 
-proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) =
-  if babelExe == "":
-    echo("[Warning] - Cannot run babel tests: Babel binary not found.")
+proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) =
+  if nimbleExe == "":
+    echo("[Warning] - Cannot run nimble tests: Nimble binary not found.")
     return
 
-  if execCmd("$# update" % babelExe) == QuitFailure:
-    echo("[Warning] - Cannot run babel tests: Babel update failed.")
+  if execCmd("$# update" % nimbleExe) == QuitFailure:
+    echo("[Warning] - Cannot run nimble tests: Nimble update failed.")
     return
 
   let packageFileTest = makeTest("PackageFileParsed", "", cat)
@@ -294,7 +294,7 @@ proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) =
       var test = makeTest(name, "", cat)
       echo(url)
       let
-        installProcess = startProcess(babelExe, "", ["install", "-y", name])
+        installProcess = startProcess(nimbleExe, "", ["install", "-y", name])
         installStatus = waitForExitEx(installProcess)
       installProcess.close
       if installStatus != QuitSuccess:
@@ -302,9 +302,8 @@ proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) =
         continue
 
       let
-        buildPath = getPackageDir(name)[0.. -3]
-      let
-        buildProcess = startProcess(babelExe, buildPath, ["build"])
+        buildPath = getPackageDir(name).strip
+        buildProcess = startProcess(nimbleExe, buildPath, ["build"])
         buildStatus = waitForExitEx(buildProcess)
       buildProcess.close
       if buildStatus != QuitSuccess:
@@ -312,13 +311,13 @@ proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) =
       r.addResult(test, "", "", reSuccess)
     r.addResult(packageFileTest, "", "", reSuccess)
   except JsonParsingError:
-    echo("[Warning] - Cannot run babel tests: Invalid package file.")
+    echo("[Warning] - Cannot run nimble tests: Invalid package file.")
     r.addResult(packageFileTest, "", "", reBuildFailed)
 
 
 # ----------------------------------------------------------------------------
 
-const AdditionalCategories = ["debugger", "examples", "lib", "babel-core"]
+const AdditionalCategories = ["debugger", "examples", "lib"]
 
 proc `&.?`(a, b: string): string =
   # candidate for the stdlib?
@@ -356,12 +355,12 @@ proc processCategory(r: var TResults, cat: Category, options: string) =
     compileExample(r, "examples/*.nim", options, cat)
     compileExample(r, "examples/gtk/*.nim", options, cat)
     compileExample(r, "examples/talk/*.nim", options, cat)
-  of "babel-core":
-    testBabelPackages(r, cat, pfCoreOnly)
-  of "babel-extra":
-    testBabelPackages(r, cat, pfExtraOnly)
-  of "babel-all":
-    testBabelPackages(r, cat, pfAll)
+  of "nimble-core":
+    testNimblePackages(r, cat, pfCoreOnly)
+  of "nimble-extra":
+    testNimblePackages(r, cat, pfExtraOnly)
+  of "nimble-all":
+    testNimblePackages(r, cat, pfAll)
   else:
     for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"):
       testSpec r, makeTest(name, options, cat)
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index 881a41ce6..0a0d08173 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -141,7 +141,7 @@ proc generatedFile(path, name: string, target: TTarget): string =
     (if target == targetJS: path.splitPath.tail & "_" else: "compiler_") &
     name.changeFileExt(ext)
 
-proc codegenCheck(test: TTest, check: string, given: var TSpec) =
+proc codegenCheck(test: TTest, check: string, given: var TSpec, r: var TResults) =
   if check.len > 0:
     try:
       let (path, name, ext2) = test.name.splitFile
@@ -154,19 +154,29 @@ proc codegenCheck(test: TTest, check: string, given: var TSpec) =
       given.err = reInvalidPeg
     except IOError:
       given.err = reCodeNotFound
+    r.addResult(test, "", given.msg, given.err)
 
-proc nimoutCheck(test: TTest; expectedNimout: string; given: var TSpec) =
+proc nimoutCheck(test: TTest; expectedNimout: string; given: var TSpec, r: var TResults) =
   if expectedNimout.len > 0:
     let exp = expectedNimout.strip.replace("\C\L", "\L")
     let giv = given.nimout.strip.replace("\C\L", "\L")
     if exp notin giv:
       given.err = reMsgsDiffer
+    r.addResult(test, exp, giv, given.err)
+
 
 proc makeDeterministic(s: string): string =
   var x = splitLines(s)
   sort(x, system.cmp)
   result = join(x, "\n")
 
+proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec, r: var TResults) =
+  if given.err == reSuccess:
+    codegenCheck(test, expected.ccodeCheck, given, r)
+    nimoutCheck(test, expected.nimout, given, r)
+  if given.err == reSuccess: inc(r.passed)
+
+
 proc testSpec(r: var TResults, test: TTest) =
   # major entry point for a single test
   let tname = test.name.addFileExt(".nim")
@@ -179,13 +189,9 @@ proc testSpec(r: var TResults, test: TTest) =
   else:
     case expected.action
     of actionCompile:
-      var given = callCompiler(expected.cmd, test.name, test.options,
-                               test.target)
-      if given.err == reSuccess:
-        codegenCheck(test, expected.ccodeCheck, given)
-        nimoutCheck(test, expected.nimout, given)
-      r.addResult(test, "", given.msg, given.err)
-      if given.err == reSuccess: inc(r.passed)
+      var given = callCompiler(expected.cmd, test.name,
+        test.options & " --hint[Path]:off --hint[Processing]:off", test.target)
+      compilerOutputTests(test, given, expected, r)
     of actionRun:
       var given = callCompiler(expected.cmd, test.name, test.options,
                                test.target)
@@ -215,11 +221,7 @@ proc testSpec(r: var TResults, test: TTest) =
             if bufB != strip(expected.outp):
               if not (expected.substr and expected.outp in bufB):
                 given.err = reOutputsDiffer
-            if given.err == reSuccess:
-              codeGenCheck(test, expected.ccodeCheck, given)
-              nimoutCheck(test, expected.nimout, given)
-            if given.err == reSuccess: inc(r.passed)
-            r.addResult(test, expected.outp, buf.string, given.err)
+            compilerOutputTests(test, given, expected, r)
         else:
           r.addResult(test, expected.outp, "executable not found", reExeNotFound)
     of actionReject:
diff --git a/tests/trmacros/tor.nim b/tests/trmacros/tor.nim
index dc72a96cd..500851582 100644
--- a/tests/trmacros/tor.nim
+++ b/tests/trmacros/tor.nim
@@ -1,5 +1,5 @@
 discard """
-  output: '''3060
+  output: '''3030
 true
 3'''
 """
diff --git a/tests/vm/tconsteval.nim b/tests/vm/tconsteval.nim
index 96a1bafe8..4459931c5 100644
--- a/tests/vm/tconsteval.nim
+++ b/tests/vm/tconsteval.nim
@@ -24,7 +24,7 @@ Possible Commands:
   csource [options]        builds the C sources for installation
   zip                      builds the installation ZIP package
   inno                     builds the Inno Setup installer
-""" % [NimVersion & repeatChar(44-len(NimVersion)), 
+""" % [NimVersion & spaces(44-len(NimVersion)), 
        CompileDate, CompileTime]
 
 echo HelpText
diff --git a/todo.txt b/todo.txt
index 3fed10aeb..1d180f737 100644
--- a/todo.txt
+++ b/todo.txt
@@ -5,6 +5,8 @@ version 0.10.4
 - make 'nil' work for 'add' and 'len'
 - get rid of 'mget'; aka priority of 'var' needs to be 'var{lvalue}'
 - 'result' shadowing warning
+- disallow negative indexing
+- improve the parser; deal with  echo $foo  gotcha
 
 
 version 1.0
@@ -75,8 +77,7 @@ version 0.9.X
 =============
 
 - macros as type pragmas
-- lazy overloading resolution:
-  * special case ``tyStmt``
+- document how lazy overloading resolution works
 - document NimMain and check whether it works for threading
 
 GC
diff --git a/tools/nimgrep.nim b/tools/nimgrep.nim
index aeae86300..72e4adc07 100644
--- a/tools/nimgrep.nim
+++ b/tools/nimgrep.nim
@@ -109,7 +109,7 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int],
   for i in t.last+1 .. y: stdout.write(s[i])
   stdout.write("\n")
   if showRepl:
-    stdout.write(repeatChar(alignment-1), "-> ")
+    stdout.write(spaces(alignment-1), "-> ")
     for i in x .. t.first-1: stdout.write(s[i])
     writeColored(repl)
     for i in t.last+1 .. y: stdout.write(s[i])
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index 8213cf418..a7301195e 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -99,8 +99,8 @@ macro updated(e: expr): expr {.immediate.} =
 proc updatedDate(year, month, day: string): string =
   ## wrapper around the update macro with easy input.
   result = updated("$1-$2-$3T00:00:00Z" % [year,
-    repeatStr(2 - len(month), "0") & month,
-    repeatStr(2 - len(day), "0") & day])
+    repeat("0", 2 - len(month)) & month,
+    repeat("0", 2 - len(day)) & day])
 
 macro entry(e: expr): expr {.immediate.} =
   ## generates the rss xml ``entry`` element.
diff --git a/web/website.ini b/web/website.ini
index 696829764..6266f05bb 100644
--- a/web/website.ini
+++ b/web/website.ini
@@ -59,6 +59,7 @@ srcdoc2: "pure/nimprof;pure/unittest;packages/docutils/highlite"
 srcdoc2: "packages/docutils/rst;packages/docutils/rstast"
 srcdoc2: "packages/docutils/rstgen;pure/logging;pure/asyncdispatch;pure/asyncnet"
 srcdoc2: "pure/rawsockets;pure/asynchttpserver;pure/net;pure/selectors;pure/future"
+srcdoc2: "pure/asyncfile"
 srcdoc2: "pure/md5"
 srcdoc2: "posix/posix"
 srcdoc2: "pure/fenv"