summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim37
-rw-r--r--compiler/astalgo.nim48
-rw-r--r--compiler/ccgcalls.nim13
-rw-r--r--compiler/ccgexprs.nim54
-rw-r--r--compiler/ccgstmts.nim43
-rw-r--r--compiler/ccgtrav.nim2
-rw-r--r--compiler/ccgtypes.nim20
-rw-r--r--compiler/ccgutils.nim12
-rw-r--r--compiler/cgen.nim43
-rw-r--r--compiler/commands.nim11
-rw-r--r--compiler/condsyms.nim55
-rw-r--r--compiler/docgen.nim2
-rw-r--r--compiler/guards.nim2
-rw-r--r--compiler/importer.nim12
-rw-r--r--compiler/jsgen.nim34
-rw-r--r--compiler/lambdalifting.nim13
-rw-r--r--compiler/lexer.nim4
-rw-r--r--compiler/llstream.nim2
-rw-r--r--compiler/lookups.nim136
-rw-r--r--compiler/lowerings.nim71
-rw-r--r--compiler/nimfix/nimfix.nim106
-rw-r--r--compiler/nimfix/nimfix.nim.cfg17
-rw-r--r--compiler/nimfix/pretty.nim152
-rw-r--r--compiler/nimfix/prettybase.nim93
-rw-r--r--compiler/nimrod.ini35
-rw-r--r--compiler/nimrod.nim2
-rw-r--r--compiler/nversion.nim2
-rw-r--r--compiler/options.nim2
-rw-r--r--compiler/pragmas.nim125
-rw-r--r--compiler/procfind.nim11
-rw-r--r--compiler/renderer.nim2
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semcall.nim2
-rw-r--r--compiler/semdestruct.nim3
-rw-r--r--compiler/semexprs.nim67
-rw-r--r--compiler/semgnrc.nim16
-rw-r--r--compiler/seminst.nim3
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/semparallel.nim14
-rw-r--r--compiler/sempass2.nim49
-rw-r--r--compiler/semstmts.nim56
-rw-r--r--compiler/semtypinst.nim10
-rw-r--r--compiler/testability.nim2
-rw-r--r--compiler/transf.nim108
-rw-r--r--compiler/types.nim48
-rw-r--r--compiler/vm.nim15
-rw-r--r--compiler/vmdef.nim4
-rw-r--r--compiler/vmdeps.nim2
-rw-r--r--compiler/vmgen.nim29
-rw-r--r--compiler/wordrecg.nim12
-rw-r--r--config/nim.cfg139
-rw-r--r--config/nimdoc.cfg6
-rw-r--r--config/nimrod.cfg5
-rw-r--r--copying.txt8
-rw-r--r--doc/backends.txt58
-rw-r--r--doc/basicopt.txt3
-rw-r--r--doc/exception_hierarchy_fragment.txt31
-rw-r--r--doc/keywords.txt2
-rw-r--r--doc/koch.txt7
-rw-r--r--doc/lib.txt11
-rw-r--r--doc/manual.txt216
-rw-r--r--doc/nimdoc.css5
-rw-r--r--doc/nimrodc.txt10
-rw-r--r--doc/spawn.txt4
-rw-r--r--doc/tut1.txt199
-rw-r--r--doc/tut2.txt63
-rw-r--r--examples/0mq/client.nim14
-rw-r--r--examples/0mq/server.nim11
-rw-r--r--examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj20
-rw-r--r--examples/cross_calculator/ios/scripts/xcode_prebuild.sh2
-rw-r--r--install.txt2
-rw-r--r--koch.nim37
-rw-r--r--lib/core/macros.nim8
-rw-r--r--lib/core/typeinfo.nim2
-rw-r--r--lib/impure/db_mysql.nim24
-rw-r--r--lib/impure/db_postgres.nim125
-rw-r--r--lib/impure/fenv.nim113
-rw-r--r--lib/impure/re.nim2
-rw-r--r--lib/impure/zipfiles.nim2
-rw-r--r--lib/packages/docutils/highlite.nim2
-rw-r--r--lib/posix/posix.nim52
-rw-r--r--lib/pure/asyncdispatch.nim264
-rw-r--r--lib/pure/asyncftpclient.nim295
-rw-r--r--lib/pure/asynchttpserver.nim35
-rw-r--r--lib/pure/asyncio.nim43
-rw-r--r--lib/pure/asyncnet.nim17
-rw-r--r--lib/pure/collections/sequtils.nim24
-rw-r--r--lib/pure/collections/sets.nim22
-rw-r--r--lib/pure/concurrency/cpuinfo.nim11
-rw-r--r--lib/pure/concurrency/threadpool.nim24
-rw-r--r--lib/pure/cookies.nim15
-rw-r--r--lib/pure/ftpclient.nim258
-rw-r--r--lib/pure/httpclient.nim3
-rw-r--r--lib/pure/irc.nim503
-rw-r--r--lib/pure/json.nim631
-rw-r--r--lib/pure/math.nim20
-rw-r--r--lib/pure/memfiles.nim4
-rw-r--r--lib/pure/net.nim590
-rw-r--r--lib/pure/nimprof.nim10
-rw-r--r--lib/pure/os.nim59
-rw-r--r--lib/pure/osproc.nim2
-rw-r--r--lib/pure/parseopt.nim4
-rw-r--r--lib/pure/parseopt2.nim2
-rw-r--r--lib/pure/pegs.nim2
-rw-r--r--lib/pure/rawsockets.nim2
-rw-r--r--lib/pure/ropes.nim4
-rw-r--r--lib/pure/strutils.nim35
-rw-r--r--lib/pure/subexes.nim3
-rw-r--r--lib/pure/times.nim78
-rw-r--r--lib/pure/typetraits.nim23
-rw-r--r--lib/pure/unittest.nim6
-rw-r--r--lib/pure/xmltree.nim4
-rw-r--r--lib/system.nim333
-rw-r--r--lib/system/ansi_c.nim25
-rw-r--r--lib/system/arithm.nim40
-rw-r--r--lib/system/assign.nim4
-rw-r--r--lib/system/atomics.nim56
-rw-r--r--lib/system/channels.nim11
-rw-r--r--lib/system/deepcopy.nim141
-rw-r--r--lib/system/excpt.nim10
-rw-r--r--lib/system/gc.nim4
-rw-r--r--lib/system/gc2.nim2
-rw-r--r--lib/system/hti.nim3
-rw-r--r--lib/system/jssys.nim4
-rw-r--r--lib/system/mmdisp.nim28
-rw-r--r--lib/system/repr.nim16
-rw-r--r--lib/system/sysspawn.nim2
-rw-r--r--lib/system/sysstr.nim4
-rw-r--r--lib/system/threads.nim88
-rw-r--r--lib/system/widestrs.nim8
-rw-r--r--lib/windows/ole2.nim208
-rw-r--r--lib/windows/winlean.nim1
-rw-r--r--lib/wrappers/postgres.nim2
-rw-r--r--lib/wrappers/sdl/sdl_ttf.nim10
-rw-r--r--lib/wrappers/zmq.nim322
-rw-r--r--readme.md6
-rw-r--r--readme.txt60
-rw-r--r--tests/assert/tuserassert.nim2
-rw-r--r--tests/async/tasyncexceptions.nim40
-rw-r--r--tests/async/tasynciossl.nim3
-rw-r--r--tests/ccgbugs/tmissinginit.nim30
-rw-r--r--tests/closure/tforum.nim44
-rw-r--r--tests/controlflow/tbreak.nim44
-rw-r--r--tests/converter/tconvert.nim34
-rw-r--r--tests/destructor/tdestructor.nim6
-rw-r--r--tests/destructor/tdestructor2.nim2
-rw-r--r--tests/effects/teffects1.nim2
-rw-r--r--tests/effects/tgcsafe.nim16
-rw-r--r--tests/enum/tenumitems.nim2
-rw-r--r--tests/generics/mdotlookup.nim8
-rw-r--r--tests/generics/tdotlookup.nim5
-rw-r--r--tests/init/tuninit1.nim2
-rw-r--r--tests/misc/tissue710.nim10
-rw-r--r--tests/misc/tstrange.nim9
-rw-r--r--tests/misc/tunsignedcmp.nim15
-rw-r--r--tests/misc/tvarious1.nim9
-rw-r--r--tests/modules/texport.nim3
-rw-r--r--tests/modules/tselfimport.nim9
-rw-r--r--tests/objvariant/tcheckedfield1.nim2
-rw-r--r--tests/overload/toverl4.nim77
-rw-r--r--tests/parallel/tdeepcopy.nim18
-rw-r--r--tests/range/tmatrix3.nim4
-rw-r--r--tests/system/toString.nim8
-rw-r--r--tests/testament/specs.nim2
-rw-r--r--tests/threads/tthreadanalysis.nim4
-rw-r--r--tests/threads/tthreadheapviolation1.nim4
-rw-r--r--tests/vm/twrongarray.nim17
-rw-r--r--tests/vm/twrongconst.nim2
-rw-r--r--todo.txt24
-rw-r--r--tools/niminst/EnvVarUpdate.nsh346
-rw-r--r--tools/niminst/inno.tmpl6
-rw-r--r--tools/niminst/niminst.nim57
-rw-r--r--tools/niminst/nsis.tmpl258
-rw-r--r--tools/nimweb.nim74
-rw-r--r--web/download.txt125
-rw-r--r--web/news.txt89
-rw-r--r--web/nimrod.ini13
-rw-r--r--web/question.txt17
-rw-r--r--web/ticker.txt5
179 files changed, 5503 insertions, 3113 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index bdb8d1c23..0c828a6d9 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -263,7 +263,7 @@ type
     sfNamedParamCall, # symbol needs named parameter call syntax in target
                       # language; for interfacing with Objective C
     sfDiscardable,    # returned value may be discarded implicitly
-    sfDestructor,     # proc is destructor
+    sfOverriden,      # proc is overriden
     sfGenSym          # symbol is 'gensym'ed; do not add to symbol table
 
   TSymFlags* = set[TSymFlag]
@@ -291,6 +291,8 @@ const
 
   sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't
                        # require RC ops
+  sfCompileToCpp* = sfInfixCall       # compile the module as C++ code
+  sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
 
 const
   # getting ready for the future expr/stmt merge
@@ -476,7 +478,7 @@ type
                           # and first phase symbol lookup in generics
     skConditional,        # symbol for the preprocessor (may become obsolete)
     skDynLib,             # symbol represents a dynamic library; this is used
-                          # internally; it does not exist in Nimrod code
+                          # internally; it does not exist in Nim code
     skParam,              # a parameter
     skGenericParam,       # a generic parameter; eq in ``proc x[eq=`==`]()``
     skTemp,               # a temporary variable (introduced by compiler)
@@ -501,7 +503,8 @@ type
     skStub,               # symbol is a stub and not yet loaded from the ROD
                           # file (it is loaded on demand, which may
                           # mean: never)
-    skPackage             # symbol is a package (used for canonicalization)
+    skPackage,            # symbol is a package (used for canonicalization)
+    skAlias               # an alias (needs to be resolved immediately)
   TSymKinds* = set[TSymKind]
 
 const
@@ -678,7 +681,7 @@ type
     heapRoot*: PRope          # keeps track of the enclosing heap object that
                               # owns this location (required by GC algorithms
                               # employing heap snapshots or sliding views)
-    a*: int                   # location's "address", i.e. slot for temporaries
+    a*: int
 
   # ---------------- end of backend information ------------------------------
 
@@ -731,8 +734,9 @@ type
       # check for the owner when touching 'usedGenerics'.
       usedGenerics*: seq[PInstantiation]
       tab*: TStrTable         # interface table for modules
+    of skLet, skVar, skField:
+      guard*: PSym
     else: nil
-
     magic*: TMagic
     typ*: PType
     name*: PIdent
@@ -785,12 +789,13 @@ type
                               # the body of the user-defined type class
                               # formal param list
                               # else: unused
-    destructor*: PSym         # destructor. warning: nil here may not necessary
-                              # mean that there is no destructor.
-                              # see instantiateDestructor in types.nim
     owner*: PSym              # the 'owner' of the type
     sym*: PSym                # types have the sym associated with them
                               # it is used for converting types to strings
+    destructor*: PSym         # destructor. warning: nil here may not necessary
+                              # mean that there is no destructor.
+                              # see instantiateDestructor in semdestruct.nim
+    deepCopy*: PSym           # overriden 'deepCopy' operation
     size*: BiggestInt         # the size of the type in bytes
                               # -1 means that the size is unkwown
     align*: int               # the type's alignment requirements
@@ -871,7 +876,7 @@ const
     tyProc, tyString, tyError}
   ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType,
     skIterator, skClosureIterator,
-    skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
+    skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
   PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
                                       nfDotSetter, nfDotField,
                                       nfIsRef}
@@ -1161,7 +1166,6 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
   result.sons = @[name, pattern, genericParams, params,
                   pragmas, exceptions, body]
 
-
 proc newType(kind: TTypeKind, owner: PSym): PType = 
   new(result)
   result.kind = kind
@@ -1171,8 +1175,8 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
   result.id = getID()
   when debugIds:
     registerId(result)
-  #if result.id < 2000 then
-  #  MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
+  #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
@@ -1190,6 +1194,7 @@ proc assignType(dest, src: PType) =
   dest.size = src.size
   dest.align = src.align
   dest.destructor = src.destructor
+  dest.deepCopy = src.deepCopy
   # this fixes 'type TLock = TSysLock':
   if src.sym != nil:
     if dest.sym != nil:
@@ -1227,6 +1232,8 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
   result.position = s.position
   result.loc = s.loc
   result.annex = s.annex      # BUGFIX
+  if result.kind in {skVar, skLet, skField}:
+    result.guard = s.guard
 
 proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym =
   result = newSym(s.kind, newIdent, s.owner, info)
@@ -1311,6 +1318,10 @@ proc newSons(father: PNode, length: int) =
     setLen(father.sons, length)
 
 proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
+  ## Used throughout the compiler code to test whether a type tree contains or
+  ## doesn't contain a specific type/types - it is often the case that only the
+  ## last child nodes of a type tree need to be searched. This is a really hot
+  ## path within the compiler!
   result = t
   while result.kind in kinds: result = lastSon(result)
 
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index dbf13f764..eb7ffc63e 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -116,17 +116,16 @@ proc iiTablePut*(t: var TIITable, key, val: int)
 
 # implementation
 
-proc skipConv*(n: PNode): PNode = 
-  case n.kind
-  of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
-    result = n.sons[0]
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv:
-    result = n.sons[1]
-  else: result = n
-
-proc skipConvTakeType*(n: PNode): PNode =
-  result = n.skipConv
-  result.typ = n.typ
+proc skipConvAndClosure*(n: PNode): PNode =
+  result = n
+  while true:
+    case result.kind
+    of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64,
+       nkClosure:
+      result = result.sons[0]
+    of nkHiddenStdConv, nkHiddenSubConv, nkConv:
+      result = result.sons[1]
+    else: break
 
 proc sameValue*(a, b: PNode): bool = 
   result = false
@@ -379,29 +378,30 @@ proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope =
   var marker = initIntSet()
   result = symToYamlAux(n, marker, indent, maxRecDepth)
 
-proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope
-proc debugType(n: PType): PRope = 
+proc debugTree(n: PNode, indent: int, maxRecDepth: int; renderType=false): PRope
+proc debugType(n: PType, maxRecDepth=100): PRope = 
   if n == nil: 
     result = toRope("null")
-  else: 
+  else:
     result = toRope($n.kind)
     if n.sym != nil: 
       app(result, " ")
       app(result, n.sym.name.s)
-    if (n.kind != tyString) and (sonsLen(n) > 0): 
+    if (n.kind != tyString) and (sonsLen(n) > 0) and maxRecDepth != 0:
       app(result, "(")
-      for i in countup(0, sonsLen(n) - 1): 
+      for i in countup(0, sonsLen(n) - 1):
         if i > 0: app(result, ", ")
-        if n.sons[i] == nil: 
+        if n.sons[i] == nil:
           app(result, "null")
-        else: 
-          app(result, debugType(n.sons[i])) 
-      if n.kind == tyObject and n.n != nil: 
+        else:
+          app(result, debugType(n.sons[i], maxRecDepth-1))
+      if n.kind == tyObject and n.n != nil:
         app(result, ", node: ")
-        app(result, debugTree(n.n, 2, 100))
+        app(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true))
       app(result, ")")
 
-proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = 
+proc debugTree(n: PNode, indent: int, maxRecDepth: int;
+               renderType=false): PRope = 
   if n == nil: 
     result = toRope("null")
   else: 
@@ -425,6 +425,8 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
             [istr, toRope(n.sym.name.s), toRope(n.sym.id)])
         #     [istr, symToYaml(n.sym, indent, maxRecDepth), 
         #     toRope(n.sym.id)])
+        if renderType and n.sym.typ != nil:
+          appf(result, ",$N$1\"typ\": $2", [istr, debugType(n.sym.typ, 2)])
       of nkIdent: 
         if n.ident != nil: 
           appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
@@ -436,7 +438,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
           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], 
-                indent + 4, maxRecDepth - 1)])
+                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)])
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index 71e23aa1d..adcc95e84 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -29,7 +29,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
       # beware of 'result = p(result)'. We may need to allocate a temporary:
       if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
         # Great, we can use 'd':
-        if d.k == locNone: getTemp(p, typ.sons[0], d)
+        if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true)
         elif d.k notin {locExpr, locTemp} and not hasNoInit(ri):
           # reset before pass as 'result' var:
           resetLoc(p, d)
@@ -38,7 +38,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
         line(p, cpsStmts, pl)
       else:
         var tmp: TLoc
-        getTemp(p, typ.sons[0], tmp)
+        getTemp(p, typ.sons[0], tmp, needsInit=true)
         app(pl, addrLoc(tmp))
         app(pl, ~");$n")
         line(p, cpsStmts, pl)
@@ -195,7 +195,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
       # beware of 'result = p(result)'. We may need to allocate a temporary:
       if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
         # Great, we can use 'd':
-        if d.k == locNone: getTemp(p, typ.sons[0], d)
+        if d.k == locNone:
+          getTemp(p, typ.sons[0], d, needsInit=true)
         elif d.k notin {locExpr, locTemp} and not hasNoInit(ri):
           # reset before pass as 'result' var:
           resetLoc(p, d)
@@ -203,7 +204,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
         genCallPattern()
       else:
         var tmp: TLoc
-        getTemp(p, typ.sons[0], tmp)
+        getTemp(p, typ.sons[0], tmp, needsInit=true)
         app(pl, addrLoc(tmp))
         genCallPattern()
         genAssignment(p, d, tmp, {}) # no need for deep copying
@@ -278,14 +279,14 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
       # beware of 'result = p(result)'. We always allocate a temporary:
       if d.k in {locTemp, locNone}:
         # We already got a temp. Great, special case it:
-        if d.k == locNone: getTemp(p, typ.sons[0], d)
+        if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true)
         app(pl, ~"Result: ")
         app(pl, addrLoc(d))
         app(pl, ~"];$n")
         line(p, cpsStmts, pl)
       else:
         var tmp: TLoc
-        getTemp(p, typ.sons[0], tmp)
+        getTemp(p, typ.sons[0], tmp, needsInit=true)
         app(pl, addrLoc(tmp))
         app(pl, ~"];$n")
         line(p, cpsStmts, pl)
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 691feeb47..b5817de05 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -359,6 +359,32 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
   else: internalError("genAssignment: " & $ty.kind)
 
+proc genDeepCopy(p: BProc; dest, src: TLoc) =
+  var ty = skipTypes(dest.t, abstractVarRange)
+  case ty.kind
+  of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr:
+    # XXX optimize this
+    linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
+            addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
+  of tySequence, tyString:
+    linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
+            addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
+  of tyOpenArray, tyVarargs:
+    linefmt(p, cpsStmts,
+         "#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
+         addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
+  of tySet:
+    if mapType(ty) == ctArray:
+      useStringh(p.module)
+      linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
+              rdLoc(dest), rdLoc(src), toRope(getSize(dest.t)))
+    else:
+      linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
+  of tyPointer, tyChar, tyBool, tyEnum, tyCString,
+     tyInt..tyUInt64, tyRange, tyVar:
+    linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
+  else: internalError("genDeepCopy: " & $ty.kind)
+
 proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
   if d.k == locNone: getTemp(p, typ, d)
 
@@ -1191,7 +1217,6 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) =
   genOf(p, n.sons[1], n.sons[2].typ, d)
 
 proc genRepr(p: BProc, e: PNode, d: var TLoc) =
-  # XXX we don't generate keep alive info for now here
   var a: TLoc
   initLocExpr(p, e.sons[1], a)
   var t = skipTypes(e.sons[1].typ, abstractVarRange)
@@ -1260,6 +1285,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
     else: unaryExpr(p, e, d, "$1Len0")
   of tyCString:
+    useStringh(p.module)
     if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
     else: unaryExpr(p, e, d, "strlen($1)")
   of tyString, tySequence:
@@ -1578,25 +1604,25 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mGetTypeInfo: genGetTypeInfo(p, e, d)
   of mSwap: genSwap(p, e, d)
   of mUnaryLt: 
-    if not (optOverflowCheck in p.options): unaryExpr(p, e, d, "($1 - 1)")
+    if optOverflowCheck notin p.options: unaryExpr(p, e, d, "($1 - 1)")
     else: unaryExpr(p, e, d, "#subInt($1, 1)")
   of mPred:
     # XXX: range checking?
-    if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "($1 - $2)")
+    if optOverflowCheck notin p.options: binaryExpr(p, e, d, "($1 - $2)")
     else: binaryExpr(p, e, d, "#subInt($1, $2)")
   of mSucc:
     # XXX: range checking?
-    if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "($1 + $2)")
+    if optOverflowCheck notin p.options: binaryExpr(p, e, d, "($1 + $2)")
     else: binaryExpr(p, e, d, "#addInt($1, $2)")
   of mInc:
-    if not (optOverflowCheck in p.options):
+    if optOverflowCheck notin p.options:
       binaryStmt(p, e, d, "$1 += $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
       binaryStmt(p, e, d, "$1 = #addInt64($1, $2);$n")
     else:
       binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n")
   of ast.mDec:
-    if not (optOverflowCheck in p.options):
+    if optOverflowCheck notin p.options:
       binaryStmt(p, e, d, "$1 -= $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
       binaryStmt(p, e, d, "$1 = #subInt64($1, $2);$n")
@@ -1659,6 +1685,12 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mParallel:
     let n = semparallel.liftParallel(p.module.module, e)
     expr(p, n, d)
+  of mDeepCopy:
+    var a, b: TLoc
+    let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1]
+    initLocExpr(p, x, a)
+    initLocExpr(p, e.sons[2], b)
+    genDeepCopy(p, a, b)
   else: internalError(e.info, "genMagicExpr: " & $op)
 
 proc genConstExpr(p: BProc, n: PNode): PRope
@@ -1878,7 +1910,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
     of skVar, skForVar, skResult, skLet:
       if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
-        internalError(n.info, "expr: var not init " & sym.name.s)
+        #echo "FAILED FOR PRCO ", p.prc.name.s
+        internalError n.info, "expr: var not init " & sym.name.s & "_" & $sym.id
       if sfThread in sym.flags:
         accessThreadLocalVar(p, sym)
         if emulatedThreadVars(): 
@@ -1889,11 +1922,14 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         putLocIntoDest(p, d, sym.loc)
     of skTemp:
       if sym.loc.r == nil or sym.loc.t == nil:
-        internalError(n.info, "expr: temp not init " & sym.name.s)
+        #echo "FAILED FOR PRCO ", p.prc.name.s
+        #echo renderTree(p.prc.ast, {renderIds})
+        internalError(n.info, "expr: temp not init " & sym.name.s & "_" & $sym.id)
       putLocIntoDest(p, d, sym.loc)
     of skParam:
       if sym.loc.r == nil or sym.loc.t == nil:
-        internalError(n.info, "expr: param not init " & sym.name.s)
+        #echo "FAILED FOR PRCO ", p.prc.name.s
+        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:
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index a8cfa57e4..037594e89 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -24,10 +24,29 @@ proc registerGcRoot(p: BProc, v: PSym) =
     linefmt(p.module.initProc, cpsStmts,
       "#nimRegisterGlobalMarker($1);$n", prc)
 
+proc isAssignedImmediately(n: PNode): bool {.inline.} =
+  if n.kind == nkEmpty: return false
+  if isInvalidReturnType(n.typ):
+    # var v = f()
+    # is transformed into: var v;  f(addr v)
+    # where 'f' **does not** initialize the result!
+    return false
+  result = true
+
 proc genVarTuple(p: BProc, n: PNode) = 
   var tup, field: TLoc
   if n.kind != nkVarTuple: internalError(n.info, "genVarTuple")
   var L = sonsLen(n)
+
+  # if we have a something that's been captured, use the lowering instead:
+  var useLowering = false
+  for i in countup(0, L-3):
+    if n[i].kind != nkSym:
+      useLowering = true; break
+  if useLowering:
+    genStmts(p, lowerTupleUnpacking(n, p.prc))
+    return
+
   genLineDir(p, n)
   initLocExpr(p, n.sons[L-1], tup)
   var t = tup.t
@@ -40,7 +59,7 @@ proc genVarTuple(p: BProc, n: PNode) =
       registerGcRoot(p, v)
     else:
       assignLocalVar(p, v)
-      initLocalVar(p, v, immediateAsgn=true)
+      initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1]))
     initLoc(field, locExpr, t.sons[i], tup.s)
     if t.kind == tyTuple: 
       field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
@@ -146,12 +165,16 @@ proc genBreakState(p: BProc, n: PNode) =
   #  lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
 
 proc genVarPrototypeAux(m: BModule, sym: PSym)
+
 proc genSingleVar(p: BProc, a: PNode) =
   var v = a.sons[0].sym
   if sfCompileTime in v.flags: return
   var targetProc = p
-  var immediateAsgn = a.sons[2].kind != nkEmpty
   if sfGlobal in v.flags:
+    if v.flags * {sfImportc, sfExportc} == {sfImportc} and
+        a.sons[2].kind == nkEmpty and
+        v.loc.flags * {lfHeader, lfNoDecl} != {}:
+      return
     if sfPure in v.flags:
       # v.owner.kind != skModule:
       targetProc = p.module.preInitProc
@@ -170,9 +193,9 @@ proc genSingleVar(p: BProc, a: PNode) =
     registerGcRoot(p, v)
   else:
     assignLocalVar(p, v)
-    initLocalVar(p, v, immediateAsgn)
+    initLocalVar(p, v, isAssignedImmediately(a.sons[2]))
 
-  if immediateAsgn:
+  if a.sons[2].kind != nkEmpty:
     genLineDir(targetProc, a)
     loadInto(targetProc, a.sons[0], a.sons[2], v.loc)
 
@@ -809,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   discard cgsym(p.module, "E_Base")
   linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
   linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
-  linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
+  if isDefined("nimStdSetjmp"):
+    linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
+  elif isDefined("nimSigSetjmp"):
+    linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint)
+  elif isDefined("nimRawSetjmp"):
+    linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint)
+  else:
+    linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
   startBlock(p, "if ($1.status == 0) {$n", [safePoint])
   var length = sonsLen(t)
   add(p.nestedTryStmts, t)
@@ -891,6 +921,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
         app(result, x)
         app(result, "\\n\"\n")
   else:
+    res.add(tnl)
     result = res.toRope
 
 proc genAsmStmt(p: BProc, t: PNode) = 
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index 26f474659..a5bf9e7a7 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -19,7 +19,7 @@ type
 
 proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType)
 proc genCaseRange(p: BProc, branch: PNode)
-proc getTemp(p: BProc, t: PType, result: var TLoc)
+proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false)
 
 proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
   if n == nil: return
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 8e762ce27..fc6febc6f 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -122,6 +122,7 @@ proc mapSetType(typ: PType): TCTypeKind =
   else: result = ctArray
 
 proc mapType(typ: PType): TCTypeKind = 
+  ## Maps a nimrod type to a C type
   case typ.kind
   of tyNone, tyStmt: result = ctVoid
   of tyBool: result = ctBool
@@ -453,7 +454,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
     appf(result, " {$n", [name])
 
   var desc = getRecordFields(m, typ, check)
-  if (desc == nil) and not hasField: 
+  if desc == nil and not hasField: 
     appf(result, "char dummy;$n", [])
   else: 
     app(result, desc)
@@ -722,7 +723,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope =
   if objtype.sym == nil: 
     internalError(d.info, "anonymous obj with discriminator")
   result = ropef("NimDT_$1_$2", [
-    toRope(objtype.sym.name.s.mangle), toRope(d.name.s.mangle)])
+    toRope(objtype.id), toRope(d.name.s.mangle)])
 
 proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope = 
   discard cgsym(m, "TNimNode")
@@ -895,11 +896,20 @@ type
 
 include ccgtrav
 
-proc genTypeInfo(m: BModule, t: PType): PRope = 
+proc genDeepCopyProc(m: BModule; s: PSym; result: PRope) =
+  genProc(m, s)
+  appf(m.s[cfsTypeInit3], "$1.deepcopy = (N_NIMCALL_PTR(void*, void*)) $2;$n",
+     [result, s.loc.r])
+
+proc genTypeInfo(m: BModule, t: PType): PRope =
+  let origType = t
   var t = getUniqueType(t)
   result = ropef("NTI$1", [toRope(t.id)])
   if containsOrIncl(m.typeInfoMarker, t.id):
     return con("(&".toRope, result, ")".toRope)
+  
+  # getUniqueType doesn't skip tyDistinct when that has an overriden operation:
+  while t.kind == tyDistinct: t = t.lastSon
   let owner = t.skipTypes(typedescPtrs).owner.getModule
   if owner != m.module:
     # make sure the type info is created in the owner module
@@ -936,6 +946,10 @@ proc genTypeInfo(m: BModule, t: PType): PRope =
     # results are not deterministic!
     genTupleInfo(m, t, result)
   else: internalError("genTypeInfo(" & $t.kind & ')')
+  if t.deepCopy != nil:
+    genDeepCopyProc(m, t.deepCopy, result)
+  elif origType.deepCopy != nil:
+    genDeepCopyProc(m, origType.deepCopy, result)  
   result = con("(&".toRope, result, ")".toRope)
 
 proc genTypeSection(m: BModule, n: PNode) = 
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 04983d6a4..65957584a 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -89,9 +89,15 @@ proc getUniqueType*(key: PType): PType =
   of tyTypeDesc, tyTypeClasses, tyGenericParam,
      tyFromExpr, tyFieldAccessor:
     internalError("GetUniqueType")
-  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable,
-     tyConst, tyIter, tyStatic:
+  of tyDistinct:
+    if key.deepCopy != nil: result = key
+    else: result = getUniqueType(lastSon(key))
+  of tyGenericInst, tyOrdinal, tyMutable, tyConst, tyIter, tyStatic:
     result = getUniqueType(lastSon(key))
+    #let obj = lastSon(key)
+    #if obj.sym != nil and obj.sym.name.s == "TOption":
+    #  echo "for ", typeToString(key), " I returned "
+    #  debug result
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
      tyOpenArray, tyArray, tySet, tyRange, tyTuple,
      tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
@@ -124,7 +130,7 @@ proc getUniqueType*(key: PType): PType =
         if t != nil and sameType(t, key): 
           return t
       idTablePut(gTypeTable[k], key, key)
-      result = key
+      result = key    
   of tyEnum:
     result = PType(idTableGet(gTypeTable[k], key))
     if result == nil: 
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index e2f3b5ab0..359fa3309 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -13,7 +13,7 @@ import
   ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
   options, intsets,
   nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
-  times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
+  times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms,
   rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings,
   semparallel
 
@@ -295,6 +295,7 @@ proc postStmtActions(p: BProc) {.inline.} =
 
 proc accessThreadLocalVar(p: BProc, s: PSym)
 proc emulatedThreadVars(): bool {.inline.}
+proc genProc(m: BModule, prc: PSym)
 
 include "ccgtypes.nim"
 
@@ -398,7 +399,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
     if not immediateAsgn:
       constructLoc(p, v.loc)
 
-proc getTemp(p: BProc, t: PType, result: var TLoc) = 
+proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = 
   inc(p.labels)
   if gCmd == cmdCompileToLLVM: 
     result.r = con("%LOC", toRope(p.labels))
@@ -410,7 +411,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) =
   result.t = getUniqueType(t)
   result.s = OnStack
   result.flags = {}
-  constructLoc(p, result, isTemp=true)
+  constructLoc(p, result, not needsInit)
 
 proc keepAlive(p: BProc, toKeepAlive: TLoc) =
   when false:
@@ -574,7 +575,6 @@ proc fixLabel(p: BProc, labl: TLabel) =
 
 proc genVarPrototype(m: BModule, sym: PSym)
 proc requestConstImpl(p: BProc, sym: PSym)
-proc genProc(m: BModule, prc: PSym)
 proc genStmts(p: BProc, t: PNode)
 proc expr(p: BProc, n: PNode, d: var TLoc)
 proc genProcPrototype(m: BModule, sym: PSym)
@@ -949,13 +949,23 @@ proc genFilenames(m: BModule): PRope =
 
 proc genMainProc(m: BModule) =
   const 
+    # The use of a volatile function pointer to call Pre/NimMainInner
+    # prevents inlining of the NimMainInner function and dependent
+    # functions, which might otherwise merge their stack frames.
     PreMainBody =
-      "\tsystemDatInit();$N" &
+      "void PreMainInner() {$N" &
       "\tsystemInit();$N" &
       "$1" &
       "$2" &
       "$3" &
-      "$4"
+      "}$N$N" &
+      "void PreMain() {$N" &
+      "\tvoid (*volatile inner)();$N" &
+      "\tsystemDatInit();$N" &
+      "\tinner = PreMainInner;$N" &
+      "$4" &
+      "\t(*inner)();$N" &
+      "}$N$N"
 
     MainProcs =
       "\tNimMain();$N"
@@ -964,9 +974,15 @@ proc genMainProc(m: BModule) =
       MainProcs & "\treturn nim_program_result;$N"
 
     NimMainBody =
+      "N_CDECL(void, NimMainInner)(void) {$N" &
+        "$1" &
+      "}$N$N" &
       "N_CDECL(void, NimMain)(void) {$N" &
+        "\tvoid (*volatile inner)();$N" &
         "\tPreMain();$N" &
-        "$1" &
+        "\tinner = NimMainInner;$N" &
+        "$2" &
+        "\t(*inner)();$N" &
       "}$N$N"
 
     PosixNimMain =
@@ -1034,14 +1050,15 @@ proc genMainProc(m: BModule) =
   if optEndb in gOptions:
     gBreakpoints.app(m.genFilenames)
   
-  let initStackBottomCall = if emulatedThreadVars() or
-                              platform.targetOS == osStandalone: "".toRope
-                            else: ropecg(m, "\t#initStackBottom();$N")
+  let initStackBottomCall =
+    if emulatedThreadVars() or
+      platform.targetOS == osStandalone: "".toRope
+    else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N")
   inc(m.labels)
-  appcg(m, m.s[cfsProcs], "void PreMain() {$N" & PreMainBody & "}$N$N", [
-    mainDatInit, initStackBottomCall, gBreakpoints, otherModsInit])
+  appcg(m, m.s[cfsProcs], PreMainBody, [
+    mainDatInit, gBreakpoints, otherModsInit, initStackBottomCall])
 
-  appcg(m, m.s[cfsProcs], nimMain, [mainModInit, toRope(m.labels)])
+  appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, toRope(m.labels)])
   if optNoMain notin gGlobalOptions:
     appcg(m, m.s[cfsProcs], otherMain, [])
 
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 7219c168a..cea965f5c 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) =
                                  platform.OS[platform.hostOS].name, 
                                  CPU[platform.hostCPU].name]))
 
-    const gitHash = gorge("git log -n 1 --format=%H")
+    discard """const gitHash = gorge("git log -n 1 --format=%H")
     if gitHash.strip.len == 40:
-      msgWriteln("git hash: " & gitHash)
+      msgWriteln("git hash: " & gitHash)"""
 
     msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
       usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &
@@ -315,6 +315,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
   of "undef", "u": 
     expectArg(switch, arg, pass, info)
     undefSymbol(arg)
+  of "symbol":
+    expectArg(switch, arg, pass, info)
+    declareSymbol(arg)  
   of "compile": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: processCompile(arg)
@@ -390,7 +393,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
   of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info)
   of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info)
   of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
-  of "threads": processOnOffSwitchG({optThreads}, arg, pass, info)
+  of "threads":
+    processOnOffSwitchG({optThreads}, arg, pass, info)
+    if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe)
   of "tlsemulation": processOnOffSwitchG({optTlsEmulation}, arg, pass, info)
   of "taintmode": processOnOffSwitchG({optTaintMode}, arg, pass, info)
   of "implicitstatic":
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 76026a59d..6d144ad96 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -19,6 +19,9 @@ var gSymbols: PStringTable
 proc defineSymbol*(symbol: string) = 
   gSymbols[symbol] = "true"
 
+proc declareSymbol*(symbol: string) = 
+  gSymbols[symbol] = "unknown"
+
 proc undefSymbol*(symbol: string) = 
   gSymbols[symbol] = "false"
 
@@ -27,6 +30,7 @@ proc isDefined*(symbol: string): bool =
     result = gSymbols[symbol] == "true"
   
 proc isDefined*(symbol: PIdent): bool = isDefined(symbol.s)
+proc isDeclared*(symbol: PIdent): bool = gSymbols.hasKey(symbol.s)
 
 iterator definedSymbolNames*: string =
   for key, val in pairs(gSymbols):
@@ -37,6 +41,38 @@ proc countDefinedSymbols*(): int =
   for key, val in pairs(gSymbols):
     if val == "true": inc(result)
 
+# For ease of bootstrapping, we keep there here and not in the global config
+# file for now:
+const
+  additionalSymbols = """
+    x86 itanium x8664
+    msdos mswindows win32 unix posix sunos bsd macintosh RISCOS doslike hpux
+    mac
+
+    hppa hp9000 hp9000s300 hp9000s700 hp9000s800 hp9000s820 ELATE sparcv9
+
+    ecmascript js nimrodvm nimffi nimdoc cpp objc
+    gcc llvmgcc clang lcc bcc dmc wcc vcc tcc pcc ucc icl
+    boehmgc gcmarkandsweep gcgenerational nogc gcUseBitvectors
+    endb profiler
+    executable guiapp consoleapp library dll staticlib
+
+    quick
+    release debug
+    useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler
+    nodejs kwin nimfix
+
+    usesysassert usegcassert tinyC useFFI
+    useStdoutAsStdmsg createNimRtl
+    booting fulldebug corruption nimsuperops noSignalHandler useGnuReadline
+    noCaas noDocGen noBusyWaiting nativeStackTrace useNodeIds selftest
+    reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize
+    debugExecProcesses pcreDll useLipzipSrc
+    preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime
+
+    nimStdSetjmp nimRawSetjmp nimSigSetjmp
+  """.split
+
 proc initDefines*() = 
   gSymbols = newStringTable(modeStyleInsensitive)
   defineSymbol("nimrod") # 'nimrod' is always defined
@@ -51,8 +87,20 @@ proc initDefines*() =
   defineSymbol("nimnewshared")
   defineSymbol("nimrequiresnimframe")
   defineSymbol("nimparsebiggestfloatmagic")
+  defineSymbol("nimalias")
   
   # add platform specific symbols:
+  for c in low(CPU)..high(CPU):
+    declareSymbol("cpu" & $CPU[c].bit)
+    declareSymbol(normalize(EndianToStr[CPU[c].endian]))
+    declareSymbol(CPU[c].name)
+  for o in low(platform.OS)..high(platform.OS):
+    declareSymbol(platform.OS[o].name)
+
+  for a in additionalSymbols:
+    declareSymbol(a)
+
+  # -----------------------------------------------------------
   case targetCPU
   of cpuI386: defineSymbol("x86")
   of cpuIa64: defineSymbol("itanium")
@@ -88,5 +136,10 @@ proc initDefines*() =
   defineSymbol(normalize(EndianToStr[CPU[targetCPU].endian]))
   defineSymbol(CPU[targetCPU].name)
   defineSymbol(platform.OS[targetOS].name)
+  declareSymbol("emulatedthreadvars")
   if platform.OS[targetOS].props.contains(ospLacksThreadVars):
     defineSymbol("emulatedthreadvars")
+  case targetOS
+  of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx:
+    defineSymbol("nimRawSetjmp")
+  else: discard
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 4c9803401..434e2a65b 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -383,6 +383,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
   var seeSrcRope: PRope = nil
   let docItemSeeSrc = getConfigVar("doc.item.seesrc")
   if docItemSeeSrc.len > 0 and options.docSeeSrcUrl.len > 0:
+    # XXX toFilename doesn't really work. We need to ensure that this keeps
+    # returning a relative path.
     let urlRope = ropeFormatNamedVars(options.docSeeSrcUrl,
       ["path", "line"], [n.info.toFilename.toRope, toRope($n.info.line)])
     dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
diff --git a/compiler/guards.nim b/compiler/guards.nim
index 4cf06fe02..431de6156 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -758,7 +758,7 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication =
       result = impliesLe(fact, a, b)
       if result != impUnknown: return result
       if sameTree(y, a):
-        result = ple(m, x, b)
+        result = ple(m, b, x)
         if result != impUnknown: return result
 
 proc pleViaModel(model: TModel; aa, bb: PNode): TImplication =
diff --git a/compiler/importer.nim b/compiler/importer.nim
index b4cae017e..33ed7e055 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -92,7 +92,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
     if s.kind == skConverter: addConverter(c, s)
     if hasPattern(s): addPattern(c, s)
 
-proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = 
+proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =        
   let ident = lookups.considerQuotedIdent(n)
   let s = strTableGet(fromMod.tab, ident)
   if s == nil:
@@ -153,12 +153,14 @@ proc importModuleAs(n: PNode, realModule: PSym): PSym =
     localError(n.info, errGenerated, "module alias must be an identifier")
   elif n.sons[1].ident.id != realModule.name.id:
     # some misguided guy will write 'import abc.foo as foo' ...
-    result = createModuleAlias(realModule, n.sons[1].ident, n.sons[1].info)
+    result = createModuleAlias(realModule, n.sons[1].ident, realModule.info)
 
-proc myImportModule(c: PContext, n: PNode): PSym =
+proc myImportModule(c: PContext, n: PNode): PSym = 
   var f = checkModuleName(n)
   if f != InvalidFileIDX:
     result = importModuleAs(n, gImportModule(c.module, f))
+    if result.info.fileIndex == n.info.fileIndex:
+      localError(n.info, errGenerated, "A module cannot import itself")
     if sfDeprecated in result.flags:
       message(n.info, warnDeprecated, result.name.s)
 
@@ -171,7 +173,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
       # ``addDecl`` needs to be done before ``importAllSymbols``!
       addDecl(c, m)             # add symbol to symbol table of module
       importAllSymbolsExcept(c, m, emptySet)
-      importForwarded(c, m.ast, emptySet)
+      #importForwarded(c, m.ast, emptySet)
 
 proc evalFrom(c: PContext, n: PNode): PNode = 
   result = n
@@ -196,4 +198,4 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
       let ident = lookups.considerQuotedIdent(n.sons[i])
       exceptSet.incl(ident.id)
     importAllSymbolsExcept(c, m, exceptSet)
-    importForwarded(c, m.ast, exceptSet)
+    #importForwarded(c, m.ast, exceptSet)
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 96d8b3d11..dfe498e47 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -10,6 +10,25 @@
 # This is the JavaScript code generator.
 # Soon also a Luajit code generator. ;-)
 
+discard """
+The JS code generator contains only 2 tricks:
+
+Trick 1
+-------
+Some locations (for example 'var int') require "fat pointers" (``etyBaseIndex``)
+which are pairs (array, index). The derefence operation is then 'array[index]'.
+Check ``mapType`` for the details.
+
+Trick 2
+-------
+It is preferable to generate '||' and '&&' if possible since that is more
+idiomatic and hence should be friendlier for the JS JIT implementation. However
+code like ``foo and (let bar = baz())`` cannot be translated this way. Instead
+the expressions need to be transformed into statements. ``isSimpleExpr``
+implements the required case distinction.
+"""
+
+
 import
   ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
   options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
@@ -833,8 +852,8 @@ proc genSwap(p: PProc, n: PNode) =
                  "local $1 = $2; $2 = $3; $3 = $1;$n", [
                  tmp, a.address, b.address])
     tmp = tmp2
-  appf(p.body, "var $1 = $2; $2 = $3; $3 = $1" | 
-               "local $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res])
+  appf(p.body, "var $1 = $2; $2 = $3; $3 = $1;" |
+               "local $1 = $2; $2 = $3; $3 = $1;", [tmp, a.res, b.res])
 
 proc getFieldPosition(f: PNode): int =
   case f.kind
@@ -881,14 +900,15 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
     a, b: TCompRes
     first: BiggestInt
   r.typ = etyBaseIndex
-  gen(p, n.sons[0], a)
-  gen(p, n.sons[1], b)
+  let m = if n.kind == nkHiddenAddr: n.sons[0] else: n
+  gen(p, m.sons[0], a)
+  gen(p, m.sons[1], b)
   internalAssert a.typ != etyBaseIndex and b.typ != etyBaseIndex
   r.address = a.res
-  var typ = skipTypes(n.sons[0].typ, abstractPtrs)
+  var typ = skipTypes(m.sons[0].typ, abstractPtrs)
   if typ.kind in {tyArray, tyArrayConstr}: first = firstOrd(typ.sons[0])
   else: first = 0
-  if optBoundsCheck in p.options and not isConstExpr(n.sons[1]): 
+  if optBoundsCheck in p.options and not isConstExpr(m.sons[1]):
     useMagic(p, "chckIndx")
     r.res = ropef("chckIndx($1, $2, $3.length)-$2", 
                   [b.res, toRope(first), a.res])
@@ -1351,7 +1371,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
   of mEcho: genEcho(p, n, r)
   of mSlurp, mStaticExec:
     localError(n.info, errXMustBeCompileTime, n.sons[0].sym.name.s)
-  of mCopyStr: binaryExpr(p, n, r, "", "($1.slice($2,-1))")
+  of mCopyStr: binaryExpr(p, n, r, "", "($1.slice($2))")
   of mCopyStrLast: ternaryExpr(p, n, r, "", "($1.slice($2, ($3)+1).concat(0))")
   of mNewString: unaryExpr(p, n, r, "mnewString", "mnewString($1)")
   of mNewStringOfCap: unaryExpr(p, n, r, "mnewString", "mnewString(0)")    
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index bdad0e471..62e13b9c4 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -843,8 +843,15 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
       # every local goes through the closure:
       #if not containsOrIncl(o.capturedVars, local.id):
       #  addField(it.obj, local)
-      addUniqueField(it.obj, local)
-      return indirectAccess(newSymNode(it.closureParam), local, n.info)
+      if contains(o.capturedVars, local.id):
+        # change 'local' to 'closure.local', unless it's a 'byCopy' variable:
+        # if sfByCopy notin local.flags:
+        result = idNodeTableGet(o.localsToAccess, local)
+        assert result != nil, "cannot find: " & local.name.s
+        return result
+      else:
+        addUniqueField(it.obj, local)
+        return indirectAccess(newSymNode(it.closureParam), local, n.info)
 
     var closure = PEnv(idTableGet(o.lambdasToEnv, local))
     if local.kind == skClosureIterator:
@@ -942,7 +949,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
       discard transformOuterProcBody(o, body, initIter(fn))
       result = ex
     finishEnvironments(o)
-    #if fn.name.s == "cbOuter":
+    #if fn.name.s == "parseLong":
     #  echo rendertree(result, {renderIds})
 
 proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 0e4dfc2ac..ea51a1399 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -40,7 +40,7 @@ type
     tkFinally, tkFor, tkFrom,
     tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkInterface, 
     tkIs, tkIsnot, tkIterator,
-    tkLambda, tkLet,
+    tkLet,
     tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin, 
     tkObject, tkOf, tkOr, tkOut, 
     tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkStatic,
@@ -75,7 +75,7 @@ const
     "elif", "else", "end", "enum", "except", "export",
     "finally", "for", "from", "generic", "if", 
     "import", "in", "include", "interface", "is", "isnot", "iterator",
-    "lambda", "let", 
+    "let", 
     "macro", "method", "mixin", "mod", 
     "nil", "not", "notin", "object", "of", "or", 
     "out", "proc", "ptr", "raise", "ref", "return", 
diff --git a/compiler/llstream.nim b/compiler/llstream.nim
index 86bfeaabd..5aefd468a 100644
--- a/compiler/llstream.nim
+++ b/compiler/llstream.nim
@@ -77,7 +77,7 @@ proc llStreamClose(s: PLLStream) =
   of llsFile: 
     close(s.f)
 
-when not defined(readLineFromStdin): 
+when not declared(readLineFromStdin): 
   # fallback implementation:
   proc readLineFromStdin(prompt: string, line: var string): bool =
     stdout.write(prompt)
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index aee64f52f..d486585ef 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -11,7 +11,7 @@
 
 import 
   intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, 
-  renderer, wordrecg, idgen
+  renderer, wordrecg, idgen, nimfix.prettybase
 
 proc ensureNoMissingOrUnusedSymbols(scope: PScope)
 
@@ -40,11 +40,8 @@ proc considerQuotedIdent*(n: PNode): PIdent =
 template addSym*(scope: PScope, s: PSym) =
   strTableAdd(scope.symbols, s)
 
-proc addUniqueSym*(scope: PScope, s: PSym): TResult =
-  if strTableIncl(scope.symbols, s):
-    result = Failure
-  else:
-    result = Success
+proc addUniqueSym*(scope: PScope, s: PSym): bool =
+  result = not strTableIncl(scope.symbols, s)
 
 proc openScope*(c: PContext): PScope {.discardable.} =
   result = PScope(parent: c.currentScope,
@@ -65,6 +62,17 @@ iterator walkScopes*(scope: PScope): PScope =
     yield current
     current = current.parent
 
+proc skipAlias*(s: PSym; n: PNode): PSym =
+  if s == nil or s.kind != skAlias:
+    result = s
+  else:
+    result = s.owner
+    if gCmd == cmdPretty:
+      prettybase.replaceDeprecated(n.info, s, result)
+    else:
+      message(n.info, warnDeprecated, "use " & result.name.s & " instead; " &
+              s.name.s)
+
 proc localSearchInScope*(c: PContext, s: PIdent): PSym =
   result = strTableGet(c.currentScope.symbols, s)
 
@@ -139,14 +147,14 @@ proc wrongRedefinition*(info: TLineInfo, s: string) =
     localError(info, errAttemptToRedefine, s)
   
 proc addDecl*(c: PContext, sym: PSym) =
-  if c.currentScope.addUniqueSym(sym) == Failure:
+  if not c.currentScope.addUniqueSym(sym):
     wrongRedefinition(sym.info, sym.name.s)
 
 proc addPrelimDecl*(c: PContext, sym: PSym) =
   discard c.currentScope.addUniqueSym(sym)
 
 proc addDeclAt*(scope: PScope, sym: PSym) =
-  if scope.addUniqueSym(sym) == Failure:
+  if not scope.addUniqueSym(sym):
     wrongRedefinition(sym.info, sym.name.s)
 
 proc addInterfaceDeclAux(c: PContext, sym: PSym) = 
@@ -163,7 +171,7 @@ proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
   if fn.kind notin OverloadableSyms: 
     internalError(fn.info, "addOverloadableSymAt")
     return
-  var check = strTableGet(scope.symbols, fn.name)
+  let check = strTableGet(scope.symbols, fn.name)
   if check != nil and check.kind notin OverloadableSyms: 
     wrongRedefinition(fn.info, fn.name.s)
   else:
@@ -179,20 +187,41 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
   addOverloadableSymAt(scope, sym)
   addInterfaceDeclAux(c, sym)
 
+when defined(nimfix):
+  import strutils
+
+  # when we cannot find the identifier, retry with a changed identifer:
+  proc altSpelling(x: PIdent): PIdent =
+    case x.s[0]
+    of 'A'..'Z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
+    of 'a'..'z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
+    else: result = x
+
+  template fixSpelling(n: PNode; ident: PIdent; op: expr) =
+    let alt = ident.altSpelling
+    result = op(c, alt).skipAlias(n)
+    if result != nil:
+      prettybase.replaceDeprecated(n.info, ident, alt)
+      return result
+else:
+  template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard
+
 proc lookUp*(c: PContext, n: PNode): PSym = 
   # Looks up a symbol. Generates an error in case of nil.
   case n.kind
   of nkIdent:
-    result = searchInScopes(c, n.ident)
-    if result == nil: 
+    result = searchInScopes(c, n.ident).skipAlias(n)
+    if result == nil:
+      fixSpelling(n, n.ident, searchInScopes)
       localError(n.info, errUndeclaredIdentifier, n.ident.s)
       result = errorSym(c, n)
   of nkSym:
     result = n.sym
   of nkAccQuoted:
     var ident = considerQuotedIdent(n)
-    result = searchInScopes(c, ident)
+    result = searchInScopes(c, ident).skipAlias(n)
     if result == nil:
+      fixSpelling(n, ident, searchInScopes)
       localError(n.info, errUndeclaredIdentifier, ident.s)
       result = errorSym(c, n)
   else:
@@ -206,36 +235,38 @@ type
   TLookupFlag* = enum 
     checkAmbiguity, checkUndeclared
 
-proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = 
+proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
   case n.kind
   of nkIdent, nkAccQuoted:
     var ident = considerQuotedIdent(n)
-    result = searchInScopes(c, ident)
-    if result == nil and checkUndeclared in flags: 
+    result = searchInScopes(c, ident).skipAlias(n)
+    if result == nil and checkUndeclared in flags:
+      fixSpelling(n, ident, searchInScopes)
       localError(n.info, errUndeclaredIdentifier, ident.s)
       result = errorSym(c, n)
-    elif checkAmbiguity in flags and result != nil and 
-        contains(c.ambiguousSymbols, result.id): 
+    elif checkAmbiguity in flags and result != nil and
+        contains(c.ambiguousSymbols, result.id):
       localError(n.info, errUseQualifier, ident.s)
   of nkSym:
     result = n.sym
-    if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id): 
+    if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id):
       localError(n.info, errUseQualifier, n.sym.name.s)
-  of nkDotExpr: 
+  of nkDotExpr:
     result = nil
     var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
-    if (m != nil) and (m.kind == skModule): 
+    if m != nil and m.kind == skModule:
       var ident: PIdent = nil
-      if n.sons[1].kind == nkIdent: 
+      if n.sons[1].kind == nkIdent:
         ident = n.sons[1].ident
-      elif n.sons[1].kind == nkAccQuoted: 
+      elif n.sons[1].kind == nkAccQuoted:
         ident = considerQuotedIdent(n.sons[1])
-      if ident != nil: 
-        if m == c.module: 
-          result = strTableGet(c.topLevelScope.symbols, ident)
-        else: 
-          result = strTableGet(m.tab, ident)
-        if result == nil and checkUndeclared in flags: 
+      if ident != nil:
+        if m == c.module:
+          result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n)
+        else:
+          result = strTableGet(m.tab, ident).skipAlias(n)
+        if result == nil and checkUndeclared in flags:
+          fixSpelling(n.sons[1], ident, searchInScopes)
           localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
           result = errorSym(c, n.sons[1])
       elif n.sons[1].kind == nkSym:
@@ -256,7 +287,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
     o.scope = c.currentScope
     o.mode = oimNoQualifier
     while true:
-      result = initIdentIter(o.it, o.scope.symbols, ident)
+      result = initIdentIter(o.it, o.scope.symbols, ident).skipAlias(n)
       if result != nil:
         break
       else:
@@ -277,11 +308,12 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       if ident != nil: 
         if o.m == c.module: 
           # a module may access its private members:
-          result = initIdentIter(o.it, c.topLevelScope.symbols, ident)
+          result = initIdentIter(o.it, c.topLevelScope.symbols,
+                                 ident).skipAlias(n)
           o.mode = oimSelfModule
-        else: 
-          result = initIdentIter(o.it, o.m.tab, ident)
-      else: 
+        else:
+          result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n)
+      else:
         localError(n.sons[1].info, errIdentifierExpected, 
                    renderTree(n.sons[1]))
         result = errorSym(c, n.sons[1])
@@ -307,18 +339,18 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
     result = nil
   of oimNoQualifier: 
     if o.scope != nil:
-      result = nextIdentIter(o.it, o.scope.symbols)
+      result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n)
       while result == nil:
         o.scope = o.scope.parent
         if o.scope == nil: break
-        result = initIdentIter(o.it, o.scope.symbols, o.it.name)
+        result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n)
         # BUGFIX: o.it.name <-> n.ident
     else: 
       result = nil
   of oimSelfModule: 
-    result = nextIdentIter(o.it, c.topLevelScope.symbols)
+    result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n)
   of oimOtherModule: 
-    result = nextIdentIter(o.it, o.m.tab)
+    result = nextIdentIter(o.it, o.m.tab).skipAlias(n)
   of oimSymChoice: 
     if o.symChoiceIndex < sonsLen(n):
       result = n.sons[o.symChoiceIndex].sym
@@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       o.mode = oimSymChoiceLocalLookup
       o.scope = c.currentScope
       result = firstIdentExcluding(o.it, o.scope.symbols,
-                                   n.sons[0].sym.name, o.inSymChoice)
+                                   n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
       while result == nil:
         o.scope = o.scope.parent
         if o.scope == nil: break
         result = firstIdentExcluding(o.it, o.scope.symbols,
-                                     n.sons[0].sym.name, o.inSymChoice)
+                                     n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
   of oimSymChoiceLocalLookup:
-    result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice)
+    result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n)
     while result == nil:
       o.scope = o.scope.parent
       if o.scope == nil: break
       result = firstIdentExcluding(o.it, o.scope.symbols,
-                                   n.sons[0].sym.name, o.inSymChoice)
+                                   n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
   
   if result != nil and result.kind == skStub: loadStub(result)
 
-when false:
-  proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode,
-                                       flags = {checkUndeclared}): PSym =
-    var o: TOverloadIter
-    result = initOverloadIter(o, c, n)
-    var a = result
-    while a != nil:
-      if sfImmediate in a.flags: return a
-      a = nextOverloadIter(o, c, n)
-    if result == nil and checkUndeclared in flags: 
-      localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s)
-      result = errorSym(c, n)
+proc pickSym*(c: PContext, n: PNode; kind: TSymKind;
+              flags: TSymFlags = {}): PSym =
+  var o: TOverloadIter
+  var a = initOverloadIter(o, c, n)
+  while a != nil:
+    if a.kind == kind and flags <= a.flags:
+      return a
+    a = nextOverloadIter(o, c, n)
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 5b61a9cae..e1fb09e44 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -56,6 +56,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
   
   result.add newAsgnStmt(newSymNode(temp), value)
   for i in 0 .. n.len-3:
+    if n.sons[i].kind == nkSym: v.addVar(n.sons[i])
     result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i))
 
 proc createObj*(owner: PSym, info: TLineInfo): PType =
@@ -122,8 +123,8 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
     if t == nil: break
     t = t.skipTypes(abstractInst)
   #if field == nil:
+  #  echo "FIELD ", b
   #  debug deref.typ
-  #  echo deref.typ.id
   internalAssert field != nil
   addSon(deref, a)
   result = newNodeI(nkDotExpr, info)
@@ -185,14 +186,14 @@ proc callProc(a: PNode): PNode =
 # - a proc returning non GC'ed memory --> pass as hidden 'var' parameter
 # - not in a parallel environment --> requires a flowVar for memory safety
 type
-  TSpawnResult = enum
+  TSpawnResult* = enum
     srVoid, srFlowVar, srByVar
   TFlowVarKind = enum
     fvInvalid # invalid type T for 'FlowVar[T]'
     fvGC      # FlowVar of a GC'ed type
     fvBlob    # FlowVar of a blob type
 
-proc spawnResult(t: PType; inParallel: bool): TSpawnResult =
+proc spawnResult*(t: PType; inParallel: bool): TSpawnResult =
   if t.isEmptyType: srVoid
   elif inParallel and not containsGarbageCollectedRef(t): srByVar
   else: srFlowVar
@@ -202,7 +203,8 @@ proc flowVarKind(t: PType): TFlowVarKind =
   elif containsGarbageCollectedRef(t): fvInvalid
   else: fvBlob
 
-proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym =
+proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType;
+                 v: PNode): PSym =
   result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info)
   result.typ = typ
   incl(result.flags, sfFromGeneric)
@@ -210,8 +212,14 @@ proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym =
   var vpart = newNodeI(nkIdentDefs, varSection.info, 3)
   vpart.sons[0] = newSymNode(result)
   vpart.sons[1] = ast.emptyNode
-  vpart.sons[2] = v
+  vpart.sons[2] = if varInit.isNil: v else: ast.emptyNode
   varSection.add vpart
+  if varInit != nil:
+    let deepCopyCall = newNodeI(nkCall, varInit.info, 3)
+    deepCopyCall.sons[0] = newSymNode(createMagic("deepCopy", mDeepCopy))
+    deepCopyCall.sons[1] = newSymNode(result)
+    deepCopyCall.sons[2] = v
+    varInit.add deepCopyCall
 
 discard """
 We generate roughly this:
@@ -244,24 +252,24 @@ stmtList:
 """
 
 proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
-                       varSection, call, barrier, fv: PNode;
+                       varSection, varInit, call, barrier, fv: PNode;
                        spawnKind: TSpawnResult): PSym =
   var body = newNodeI(nkStmtList, f.info)
   var threadLocalBarrier: PSym
   if barrier != nil:
-    var varSection = newNodeI(nkVarSection, barrier.info)
-    threadLocalBarrier = addLocalVar(varSection, argsParam.owner, 
+    var varSection2 = newNodeI(nkVarSection, barrier.info)
+    threadLocalBarrier = addLocalVar(varSection2, nil, argsParam.owner, 
                                      barrier.typ, barrier)
-    body.add varSection
+    body.add varSection2
     body.add callCodeGenProc("barrierEnter", threadLocalBarrier.newSymNode)
   var threadLocalProm: PSym
   if spawnKind == srByVar:
-    threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv)
+    threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv)
   elif fv != nil:
     internalAssert fv.typ.kind == tyGenericInst
-    threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv)
-    
+    threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv)
   body.add varSection
+  body.add varInit
   if fv != nil and spawnKind != srByVar:
     # generate:
     #   fv.owner = threadParam
@@ -314,7 +322,8 @@ proc createCastExpr(argsParam: PSym; objType: PType): PNode =
   result.typ.rawAddSon(objType)
 
 proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, 
-                             castExpr, call, varSection, result: PNode) =
+                             castExpr, call, 
+                             varSection, varInit, result: PNode) =
   let formals = n[0].typ.n
   let tmpName = getIdent(genPrefix)
   for i in 1 .. <n.len:
@@ -323,8 +332,8 @@ proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym,
     var argType = n[i].typ.skipTypes(abstractInst)
     if i < formals.len and formals[i].typ.kind == tyVar:
       localError(n[i].info, "'spawn'ed function cannot have a 'var' parameter")
-    elif containsTyRef(argType):
-      localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
+    #elif containsTyRef(argType):
+    #  localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
 
     let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
     var field = newSym(skField, fieldname, objType.owner, n.info)
@@ -332,8 +341,8 @@ proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym,
     objType.addField(field)
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])
 
-    let temp = addLocalVar(varSection, objType.owner, argType,
-                           indirectAccess(castExpr, field, n.info))    
+    let temp = addLocalVar(varSection, varInit, objType.owner, argType,
+                           indirectAccess(castExpr, field, n.info))
     call.add(newSymNode(temp))
 
 proc getRoot*(n: PNode): PSym =
@@ -367,7 +376,8 @@ proc genHigh(n: PNode): PNode =
     result.sons[1] = n
 
 proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
-                             castExpr, call, varSection, result: PNode) =
+                             castExpr, call, 
+                             varSection, varInit, result: PNode) =
   let formals = n[0].typ.n
   let tmpName = getIdent(genPrefix)
   # we need to copy the foreign scratch object fields into local variables
@@ -376,8 +386,8 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
     let n = n[i]
     let argType = skipTypes(if i < formals.len: formals[i].typ else: n.typ,
                             abstractInst)
-    if containsTyRef(argType):
-      localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
+    #if containsTyRef(argType):
+    #  localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
 
     let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
     var field = newSym(skField, fieldname, objType.owner, n.info)
@@ -403,7 +413,7 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
         result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])
         result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3])
 
-        let threadLocal = addLocalVar(varSection, objType.owner, fieldA.typ,
+        let threadLocal = addLocalVar(varSection,nil, objType.owner, fieldA.typ,
                                       indirectAccess(castExpr, fieldA, n.info))
         slice.sons[2] = threadLocal.newSymNode
       else:
@@ -417,7 +427,7 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
       # the array itself does not need to go through a thread local variable:
       slice.sons[1] = genDeref(indirectAccess(castExpr, field, n.info))
 
-      let threadLocal = addLocalVar(varSection, objType.owner, fieldB.typ,
+      let threadLocal = addLocalVar(varSection,nil, objType.owner, fieldB.typ,
                                     indirectAccess(castExpr, fieldB, n.info))
       slice.sons[3] = threadLocal.newSymNode
       call.add slice
@@ -428,7 +438,7 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
       field.typ = a.typ
       objType.addField(field)
       result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
-      let threadLocal = addLocalVar(varSection, objType.owner, field.typ,
+      let threadLocal = addLocalVar(varSection,nil, objType.owner, field.typ,
                                     indirectAccess(castExpr, field, n.info))
       call.add(genDeref(threadLocal.newSymNode))
     else:
@@ -436,7 +446,8 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym;
       field.typ = argType
       objType.addField(field)
       result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n)
-      let threadLocal = addLocalVar(varSection, objType.owner, field.typ,
+      let threadLocal = addLocalVar(varSection, varInit,
+                                    objType.owner, field.typ,
                                     indirectAccess(castExpr, field, n.info))
       call.add(threadLocal.newSymNode)
 
@@ -504,10 +515,13 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
 
   call.add(fn)
   var varSection = newNodeI(nkVarSection, n.info)
+  var varInit = newNodeI(nkStmtList, n.info)
   if barrier.isNil:
-    setupArgsForConcurrency(n, objType, scratchObj, castExpr, call, varSection, result)
-  else: 
-    setupArgsForParallelism(n, objType, scratchObj, castExpr, call, varSection, result)
+    setupArgsForConcurrency(n, objType, scratchObj, castExpr, call, 
+                            varSection, varInit, result)
+  else:
+    setupArgsForParallelism(n, objType, scratchObj, castExpr, call, 
+                            varSection, varInit, result)
 
   var barrierAsExpr: PNode = nil
   if barrier != nil:
@@ -539,7 +553,8 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
     fvAsExpr = indirectAccess(castExpr, field, n.info)
     result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest))
 
-  let wrapper = createWrapperProc(fn, threadParam, argsParam, varSection, call,
+  let wrapper = createWrapperProc(fn, threadParam, argsParam, 
+                                  varSection, varInit, call,
                                   barrierAsExpr, fvAsExpr, spawnKind)
   result.add callCodeGenProc("nimSpawn", wrapper.newSymNode,
                              genAddrOf(scratchObj.newSymNode))
diff --git a/compiler/nimfix/nimfix.nim b/compiler/nimfix/nimfix.nim
new file mode 100644
index 000000000..e561b6d4d
--- /dev/null
+++ b/compiler/nimfix/nimfix.nim
@@ -0,0 +1,106 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code.
+
+import strutils, os, parseopt
+import options, commands, modules, sem, passes, passaux, pretty, msgs, nimconf,
+  extccomp, condsyms, lists
+
+const Usage = """
+Nimfix - Tool to patch Nim code
+Usage:
+  nimfix [options] projectflie.nim
+
+Options:
+  --overwriteFiles:on|off          overwrite the original nim files.
+                                   DEFAULT is ON!
+  --wholeProject                   overwrite every processed file.
+  --checkExtern:on|off             style check also extern names
+  --styleCheck:on|off|auto         performs style checking for identifiers
+                                   and suggests an alternative spelling; 
+                                   'auto' corrects the spelling.
+
+In addition, all command line options of Nim are supported.
+"""
+
+proc mainCommand =
+  #msgs.gErrorMax = high(int)  # do not stop after first error
+  registerPass verbosePass
+  registerPass semPass
+  gCmd = cmdPretty
+  appendStr(searchPaths, options.libpath)
+  if gProjectFull.len != 0:
+    # current path is always looked first for modules
+    prependStr(searchPaths, gProjectPath)
+
+  compileProject()
+  pretty.overwriteFiles()
+
+proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
+  var p = parseopt.initOptParser(cmd)
+  var argsCount = 0
+  gOnlyMainfile = true
+  while true: 
+    parseopt.next(p)
+    case p.kind
+    of cmdEnd: break 
+    of cmdLongoption, cmdShortOption: 
+      case p.key.normalize
+      of "overwritefiles":
+        case p.val.normalize
+        of "on": gOverWrite = true
+        of "off": gOverWrite = false
+        else: localError(gCmdLineInfo, errOnOrOffExpected)
+      of "checkextern":
+        case p.val.normalize
+        of "on": gCheckExtern = true
+        of "off": gCheckExtern = false
+        else: localError(gCmdLineInfo, errOnOrOffExpected)
+      of "stylecheck": 
+        case p.val.normalize
+        of "off": gStyleCheck = StyleCheck.None
+        of "on": gStyleCheck = StyleCheck.Warn
+        of "auto": gStyleCheck = StyleCheck.Auto
+        else: localError(gCmdLineInfo, errOnOrOffExpected)
+      of "wholeproject": gOnlyMainfile = false
+      else:
+        processSwitch(pass, p)
+    of cmdArgument:
+      options.gProjectName = unixToNativePath(p.key)
+      # if processArgument(pass, p, argsCount): break
+
+proc handleCmdLine() =
+  if paramCount() == 0:
+    stdout.writeln(Usage)
+  else:
+    processCmdLine(passCmd1, "")
+    if gProjectName != "":
+      try:
+        gProjectFull = canonicalizePath(gProjectName)
+      except OSError:
+        gProjectFull = gProjectName
+      var p = splitFile(gProjectFull)
+      gProjectPath = p.dir
+      gProjectName = p.name
+    else:
+      gProjectPath = getCurrentDir()
+    loadConfigs(DefaultConfig) # load all config files
+    # now process command line arguments again, because some options in the
+    # command line can overwite the config file's settings
+    extccomp.initVars()
+    processCmdLine(passCmd2, "")
+    mainCommand()
+
+when compileOption("gc", "v2") or compileOption("gc", "refc"):
+  GC_disableMarkAndSweep()
+
+condsyms.initDefines()
+defineSymbol "nimfix"
+handleCmdline()
diff --git a/compiler/nimfix/nimfix.nim.cfg b/compiler/nimfix/nimfix.nim.cfg
new file mode 100644
index 000000000..31a41e080
--- /dev/null
+++ b/compiler/nimfix/nimfix.nim.cfg
@@ -0,0 +1,17 @@
+# Special configuration file for the Nim project
+# gc:markAndSweep
+
+hint[XDeclaredButNotUsed]:off
+path:"$projectPath/../.."
+
+path:"$lib/packages/docutils"
+path:"$nim/compiler"
+
+define:useStdoutAsStdmsg
+symbol:nimfix
+define:nimfix
+
+cs:partial
+#define:useNodeIds
+define:booting
+define:noDocgen
diff --git a/compiler/nimfix/pretty.nim b/compiler/nimfix/pretty.nim
new file mode 100644
index 000000000..acac574af
--- /dev/null
+++ b/compiler/nimfix/pretty.nim
@@ -0,0 +1,152 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements the code "prettifier". This is part of the toolchain
+## to convert Nim code into a consistent style.
+
+import 
+  strutils, os, options, ast, astalgo, msgs, ropes, idents,
+  intsets, strtabs, semdata, prettybase
+
+type
+  StyleCheck* {.pure.} = enum None, Warn, Auto
+
+var
+  gOverWrite* = true
+  gStyleCheck*: StyleCheck
+  gCheckExtern*, gOnlyMainfile*: bool
+
+proc overwriteFiles*() =
+  let doStrip = options.getConfigVar("pretty.strip").normalize == "on"
+  for i in 0 .. high(gSourceFiles):
+    if gSourceFiles[i].dirty and not gSourceFiles[i].isNimfixFile and
+        (not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx):
+      let newFile = if gOverWrite: gSourceFiles[i].fullpath
+                    else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim")
+      try:
+        var f = open(newFile, fmWrite)
+        for line in gSourceFiles[i].lines:
+          if doStrip:
+            f.write line.strip(leading = false, trailing = true)
+          else:
+            f.write line
+          f.write(gSourceFiles[i].newline)
+        f.close
+      except IOError:
+        rawMessage(errCannotOpenFile, newFile)
+
+proc `=~`(s: string, a: openArray[string]): bool =
+  for x in a:
+    if s.startsWith(x): return true
+
+proc beautifyName(s: string, k: TSymKind): string =
+  # minimal set of rules here for transition:
+  # GC_ is allowed
+
+  let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
+  if allUpper and k in {skConst, skEnumField, skType}: return s
+  result = newStringOfCap(s.len)
+  var i = 0
+  case k
+  of skType, skGenericParam:
+    # Types should start with a capital unless builtins like 'int' etc.:
+    if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
+             "char", "byte", "bool", "openArray", "seq", "array", "void",
+             "pointer", "float", "csize", "cdouble", "cchar", "cschar",
+             "cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any",
+             "range", "openarray", "varargs", "set", "cfloat"
+             ]:
+      result.add s[i]
+    else:
+      result.add toUpper(s[i])
+  of skConst, skEnumField:
+    # for 'const' we keep how it's spelt; either upper case or lower case:
+    result.add s[0]
+  else:
+    # as a special rule, don't transform 'L' to 'l'
+    if s.len == 1 and s[0] == 'L': result.add 'L'
+    elif '_' in s: result.add(s[i])
+    else: result.add toLower(s[0])
+  inc i
+  while i < s.len:
+    if s[i] == '_':
+      if i > 0 and s[i-1] in {'A'..'Z'}:
+        # don't skip '_' as it's essential for e.g. 'GC_disable'
+        result.add('_')
+        inc i
+        result.add s[i]
+      else:
+        inc i
+        result.add toUpper(s[i])
+    elif allUpper:
+      result.add toLower(s[i])
+    else:
+      result.add s[i]
+    inc i
+
+proc replaceInFile(info: TLineInfo; newName: string) =
+  loadFile(info)
+  
+  let line = gSourceFiles[info.fileIndex].lines[info.line-1]
+  var first = min(info.col.int, line.len)
+  if first < 0: return
+  #inc first, skipIgnoreCase(line, "proc ", first)
+  while first > 0 and line[first-1] in prettybase.Letters: dec first
+  if first < 0: return
+  if line[first] == '`': inc first
+  
+  let last = first+identLen(line, first)-1
+  if differ(line, first, last, newName):
+    # last-first+1 != newName.len or 
+    var x = line.substr(0, first-1) & newName & line.substr(last+1)    
+    system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
+    gSourceFiles[info.fileIndex].dirty = true
+
+proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) =
+  let beau = beautifyName(s, k)
+  if s != beau:
+    if gStyleCheck == StyleCheck.Auto: 
+      sym.name = getIdent(beau)
+      replaceInFile(info, beau)
+    else:
+      message(info, hintName, beau)
+
+proc styleCheckDefImpl(info: TLineInfo; s: PSym; k: TSymKind) =
+  # operators stay as they are:
+  if k in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: return
+  if k in {skType, skGenericParam} and sfAnon in s.flags: return
+  if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern:
+    checkStyle(info, s.name.s, k, s)
+
+template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) =
+  when defined(nimfix):
+    if gStyleCheck != StyleCheck.None: styleCheckDefImpl(info, s, k)
+
+template styleCheckDef*(info: TLineInfo; s: PSym) =
+  styleCheckDef(info, s, s.kind)
+template styleCheckDef*(s: PSym) =
+  styleCheckDef(s.info, s, s.kind)
+
+proc styleCheckUseImpl(info: TLineInfo; s: PSym) =
+  if info.fileIndex < 0: return
+  # we simply convert it to what it looks like in the definition
+  # for consistency
+  
+  # operators stay as they are:
+  if s.kind in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters:
+    return
+  if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
+  let newName = s.name.s
+
+  replaceInFile(info, newName)
+  #if newName == "File": writeStackTrace()
+
+template styleCheckUse*(info: TLineInfo; s: PSym) =
+  when defined(nimfix):
+    if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s)
diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim
new file mode 100644
index 000000000..8e0f5db6d
--- /dev/null
+++ b/compiler/nimfix/prettybase.nim
@@ -0,0 +1,93 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+import ast, msgs, strutils, idents, lexbase, streams
+from os import splitFile
+
+type
+  TSourceFile* = object
+    lines*: seq[string]
+    dirty*, isNimfixFile*: bool
+    fullpath*, newline*: string
+    fileIdx*: int32
+
+var
+  gSourceFiles*: seq[TSourceFile] = @[]
+
+proc loadFile*(info: TLineInfo) =
+  let i = info.fileIndex
+  if i >= gSourceFiles.len:
+    gSourceFiles.setLen(i+1)
+  if gSourceFiles[i].lines.isNil:
+    gSourceFiles[i].fileIdx = info.fileIndex
+    gSourceFiles[i].lines = @[]
+    let path = info.toFullPath
+    gSourceFiles[i].fullpath = path
+    gSourceFiles[i].isNimfixFile = path.splitFile.ext == ".nimfix"
+    # we want to die here for IOError:
+    for line in lines(path):
+      gSourceFiles[i].lines.add(line)
+    # extract line ending of the file:
+    var lex: TBaseLexer
+    open(lex, newFileStream(path, fmRead))
+    var pos = lex.bufpos
+    while true:
+      case lex.buf[pos]
+      of '\c': 
+        gSourceFiles[i].newline = "\c\L"
+        break
+      of '\L', '\0':
+        gSourceFiles[i].newline = "\L"
+        break
+      else: discard
+      inc pos
+    close(lex)
+
+const
+  Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
+
+proc identLen*(line: string, start: int): int =
+  while start+result < line.len and line[start+result] in Letters:
+    inc result
+
+proc differ*(line: string, a, b: int, x: string): bool =
+  let y = line[a..b]
+  result = cmpIgnoreStyle(y, x) == 0 and y != x
+
+proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) =
+  loadFile(info)
+
+  let line = gSourceFiles[info.fileIndex].lines[info.line-1]
+  var first = min(info.col.int, line.len)
+  if first < 0: return
+  #inc first, skipIgnoreCase(line, "proc ", first)
+  while first > 0 and line[first-1] in Letters: dec first
+  if first < 0: return
+  if line[first] == '`': inc first
+  
+  let last = first+identLen(line, first)-1
+  if cmpIgnoreStyle(line[first..last], oldSym.s) == 0:
+    var x = line.substr(0, first-1) & newSym.s & line.substr(last+1)
+    system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
+    gSourceFiles[info.fileIndex].dirty = true
+    #if newSym.s == "File": writeStackTrace()
+
+proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) =
+  replaceDeprecated(info, oldSym.name, newSym.name)
+
+proc replaceComment*(info: TLineInfo) =
+  loadFile(info)
+
+  let line = gSourceFiles[info.fileIndex].lines[info.line-1]
+  var first = info.col.int
+  if line[first] != '#': inc first
+
+  var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape
+  system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
+  gSourceFiles[info.fileIndex].dirty = true
diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini
index 44e16cec8..7135b3490 100644
--- a/compiler/nimrod.ini
+++ b/compiler/nimrod.ini
@@ -1,3 +1,6 @@
+; This config file holds configuration information about the Nim compiler
+; and project.
+
 [Project]
 Name: "Nimrod"
 Version: "$version"
@@ -34,11 +37,11 @@ Files: "config/nimdoc.cfg"
 Files: "config/nimdoc.tex.cfg"
 
 [Documentation]
-Files: "doc/*.txt"
-Files: "doc/*.html"
-Files: "doc/*.cfg"
-Files: "doc/*.pdf"
-Files: "doc/*.ini"
+; Files: "doc/*.html"
+; Files: "doc/*.cfg"
+; Files: "doc/*.pdf"
+; Files: "doc/*.ini"
+Files: "doc/overview.html"
 Start: "doc/overview.html"
 
 
@@ -61,13 +64,9 @@ Files: "compiler/readme.txt"
 Files: "compiler/nimrod.ini"
 Files: "compiler/nimrod.cfg"
 Files: "compiler/*.nim"
-Files: "compiler/c2nim/*.nim"
-Files: "compiler/c2nim/*.cfg"
-Files: "compiler/pas2nim/*.nim"
-Files: "compiler/pas2nim/*.cfg"
-
-Files: "build/empty.txt"
-Files: "bin/empty.txt"
+Files: "doc/*.txt"
+Files: "compiler/nimfix/*.nim"
+Files: "compiler/nimfix/*.cfg"
 
 
 [Lib]
@@ -115,17 +114,22 @@ Files: "examples/*.tmpl"
 
 [Windows]
 Files: "bin/nimrod.exe"
+Files: "bin/nimrod_debug.exe"
 Files: "bin/c2nim.exe"
 Files: "bin/niminst.exe"
 Files: "bin/nimgrep.exe"
 
 Files: "dist/*.dll"
 Files: "koch.exe"
-Files: "dist/mingw"
+; Files: "dist/mingw"
 Files: "start.bat"
 BinPath: r"bin;dist\mingw\bin;dist"
-InnoSetup: "Yes"
 
+;           Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
+Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|doc\overview.html"
+Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
+Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe"
+; for now only NSIS supports optional downloads
 
 [UnixBin]
 Files: "bin/nimrod"
@@ -140,6 +144,9 @@ UninstallScript: "yes"
 path = r"c:\Program Files (x86)\Inno Setup 5\iscc.exe"
 flags = "/Q"
 
+[NSIS]
+path = r"c:\Program Files (x86)\NSIS\makensis.exe"
+flags = "/V0"
 
 [C_Compiler]
 path = r""
diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim
index ea7621b09..618d98698 100644
--- a/compiler/nimrod.nim
+++ b/compiler/nimrod.nim
@@ -79,7 +79,7 @@ proc handleCmdLine() =
           var ex = quoteShell(binPath)
           execExternalProgram(ex & ' ' & service.arguments)
 
-when defined(GC_setMaxPause):
+when declared(GC_setMaxPause):
   GC_setMaxPause 2_000
 
 when compileOption("gc", "v2") or compileOption("gc", "refc"):
diff --git a/compiler/nversion.nim b/compiler/nversion.nim
index 3c868ed2a..bd1f79ac6 100644
--- a/compiler/nversion.nim
+++ b/compiler/nversion.nim
@@ -14,7 +14,7 @@ const
   MaxSetElements* = 1 shl 16  # (2^16) to support unicode character sets?
   VersionMajor* = 0
   VersionMinor* = 9
-  VersionPatch* = 5
+  VersionPatch* = 6
   VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
 
   RodFileVersion* = "1215"       # modify this if the rod-format changes!
diff --git a/compiler/options.nim b/compiler/options.nim
index 58a340d21..02719cacc 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -95,7 +95,7 @@ var
                          optBoundsCheck, optOverflowCheck, optAssert, optWarns, 
                          optHints, optStackTrace, optLineTrace,
                          optPatterns, optNilCheck}
-  gGlobalOptions*: TGlobalOptions = {}
+  gGlobalOptions*: TGlobalOptions = {optThreadAnalysis}
   gExitcode*: int8
   gCmd*: TCommands = cmdNone  # the command
   gSelectedGC* = gcRefc       # the selected GC
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index a17773aa4..d73494c6e 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -24,7 +24,8 @@ const
     wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
     wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
     wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
-    wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe}
+    wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
+    wOverride}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas
   templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
@@ -35,8 +36,8 @@ const
   iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, 
     wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
     wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
-    wTags, wUses, wOperator, wGcSafe}
-  exprPragmas* = {wLine}
+    wTags, wLocks, wGcSafe}
+  exprPragmas* = {wLine, wLocks}
   stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
     wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
     wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
@@ -44,27 +45,27 @@ const
     wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
     wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
     wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
-    wInjectStmt}
+    wInjectStmt, wDeprecated}
   lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
     wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
     wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
-    wRaises, wUses, wTags, wGcSafe}
+    wRaises, wLocks, wTags, wGcSafe}
   typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, 
     wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
     wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
     wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
     wBorrow, wGcSafe}
   fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, 
-    wImportCpp, wImportObjC, wError}
+    wImportCpp, wImportObjC, wError, wGuard}
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, 
     wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
     wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
-    wGensym, wInject, wCodegenDecl}
+    wGensym, wInject, wCodegenDecl, wGuard}
   constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
     wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
   letPragmas* = varPragmas
   procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
-                      wThread, wRaises, wUses, wTags, wGcSafe}
+                      wThread, wRaises, wLocks, wTags, wGcSafe}
   allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
 
 proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
@@ -127,12 +128,16 @@ proc processImportCpp(s: PSym, extname: string) =
   incl(s.flags, sfImportc)
   incl(s.flags, sfInfixCall)
   excl(s.flags, sfForward)
+  let m = s.getModule()
+  incl(m.flags, sfCompileToCpp)
 
 proc processImportObjC(s: PSym, extname: string) =
   setExternName(s, extname)
   incl(s.flags, sfImportc)
   incl(s.flags, sfNamedParamCall)
   excl(s.flags, sfForward)
+  let m = s.getModule()
+  incl(m.flags, sfCompileToObjC)
 
 proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
   result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
@@ -513,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
   else:
     invalidPragma(n)
 
-proc pragmaUses(c: PContext, n: PNode) =
-  proc processExc(c: PContext, x: PNode): PNode =
-    if x.kind in {nkAccQuoted, nkIdent, nkSym,
-                  nkOpenSymChoice, nkClosedSymChoice}:
-      if considerQuotedIdent(x).s == "*":
-        return newSymNode(ast.anyGlobal)
-    result = c.semExpr(c, x)
-    if result.kind != nkSym or sfGlobal notin result.sym.flags:
-      localError(x.info, "'$1' is not a global variable" % result.renderTree)
-      result = newSymNode(ast.anyGlobal)
-    
-  if n.kind == nkExprColonExpr:
-    let it = n.sons[1]
-    if it.kind notin {nkCurly, nkBracket}:
-      n.sons[1] = processExc(c, it)
-    else:
-      for i in 0 .. <it.len:
-        it.sons[i] = processExc(c, it.sons[i])
-  else:
-    invalidPragma(n)
-
 proc typeBorrow(sym: PSym, n: PNode) =
   if n.kind == nkExprColonExpr:
     let it = n.sons[1]
@@ -541,11 +525,50 @@ proc typeBorrow(sym: PSym, n: PNode) =
       localError(n.info, "a type can only borrow `.` for now")
   incl(sym.typ.flags, tfBorrowDot)
 
+proc markCompilerProc(s: PSym) =
+  makeExternExport(s, "$1", s.info)
+  incl(s.flags, sfCompilerProc)
+  incl(s.flags, sfUsed)
+  registerCompilerProc(s)
+
+proc deprecatedStmt(c: PContext; pragma: PNode) =
+  let pragma = pragma[1]
+  if pragma.kind != nkBracket:
+    localError(pragma.info, "list of key:value pairs expected"); return
+  for n in pragma:
+    if n.kind in {nkExprColonExpr, nkExprEqExpr}:
+      let dest = qualifiedLookUp(c, n[1])
+      let src = considerQuotedIdent(n[0])
+      let alias = newSym(skAlias, src, dest, n[0].info)
+      incl(alias.flags, sfExported)
+      if sfCompilerProc in dest.flags: markCompilerProc(alias)
+      addInterfaceDecl(c, alias)
+    else:
+      localError(n.info, "key:value pair expected")
+
+proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
+  if it.kind != nkExprColonExpr: 
+    invalidPragma(it); return
+  let n = it[1]
+  if n.kind == nkSym:
+    result = n.sym
+  elif kind == skField:
+    # First check if the guard is a global variable:
+    result = qualifiedLookUp(c, n, {})
+    if result.isNil or result.kind notin {skLet, skVar} or
+        sfGlobal notin result.flags:
+      # We return a dummy symbol; later passes over the type will repair it.
+      # Generic instantiation needs to know about this too. But we're lazy
+      # and perform the lookup on demand instead.
+      result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info)
+  else:
+    result = qualifiedLookUp(c, n)
+
 proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
                   validPragmas: TSpecialWords): bool =
   var it = n.sons[i]
   var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
-  if key.kind == nkIdent: 
+  if key.kind == nkIdent:
     var userPragma = strTableGet(c.userPragmas, key.ident)
     if userPragma != nil: 
       inc c.instCounter
@@ -577,11 +600,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wAlign:
           if sym.typ == nil: invalidPragma(it)
           var align = expectIntLit(c, it)
-          if not isPowerOfTwo(align) and align != 0: 
+          if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
             localError(it.info, errPowerOfTwoExpected)
           else: 
-            sym.typ.align = align              
-        of wSize: 
+            sym.typ.align = align.int16
+        of wSize:
           if sym.typ == nil: invalidPragma(it)
           var size = expectIntLit(c, it)
           if not isPowerOfTwo(size) or size <= 0 or size > 8: 
@@ -628,11 +651,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           # implies nodecl, because otherwise header would not make sense
           if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
         of wDestructor:
-          if sym.typ.sons.len == 2:
-            sym.flags.incl sfDestructor
-          else:
-            invalidPragma(it)
-        of wNosideeffect: 
+          sym.flags.incl sfOverriden
+          if sym.name.s.normalize != "destroy":
+            localError(n.info, errGenerated, "destructor has to be named 'destroy'")
+        of wOverride:
+          sym.flags.incl sfOverriden
+        of wNosideeffect:
           noVal(it)
           incl(sym.flags, sfNoSideEffect)
           if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
@@ -646,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           processDynLib(c, it, sym)
         of wCompilerproc:
           noVal(it)           # compilerproc may not get a string!
-          if sfFromGeneric notin sym.flags:
-            makeExternExport(sym, "$1", it.info)
-            incl(sym.flags, sfCompilerProc)
-            incl(sym.flags, sfUsed) # suppress all those stupid warnings
-            registerCompilerProc(sym)
-        of wProcVar: 
+          if sfFromGeneric notin sym.flags: markCompilerProc(sym)
+        of wProcVar:
           noVal(it)
           incl(sym.flags, sfProcvar)
-        of wDeprecated: 
-          noVal(it)
-          if sym != nil: incl(sym.flags, sfDeprecated)
+        of wDeprecated:
+          if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
+          elif sym != nil: incl(sym.flags, sfDeprecated)
           else: incl(c.module.flags, sfDeprecated)
         of wVarargs: 
           noVal(it)
@@ -787,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           if sym == nil: invalidPragma(it)
         of wLine: pragmaLine(c, it)
         of wRaises, wTags: pragmaRaisesOrTags(c, it)
-        of wUses: pragmaUses(c, it)
-        of wOperator:
-          if sym == nil: invalidPragma(it)
-          else: sym.position = expectIntLit(c, it)
+        of wGuard:
+          if sym == nil or sym.kind notin {skVar, skLet, skField}:
+            invalidPragma(it)
+          else:
+            sym.guard = pragmaGuard(c, it, sym.kind)
         of wInjectStmt:
           if it.kind != nkExprColonExpr:
             localError(it.info, errExprExpected)
diff --git a/compiler/procfind.nim b/compiler/procfind.nim
index 0354d585d..9f52cc117 100644
--- a/compiler/procfind.nim
+++ b/compiler/procfind.nim
@@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
   var it: TIdentIter
   result = initIdentIter(it, scope.symbols, fn.name)
   while result != nil:
-    if result.kind in skProcKinds and
-       sameType(result.typ, fn.typ, flags): return
+    if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags):
+      case equalParams(result.typ.n, fn.typ.n)
+      of paramsEqual:
+        return
+      of paramsIncompatible:
+        localError(fn.info, errNotOverloadable, fn.name.s)
+        return
+      of paramsNotEqual:
+        discard
 
     result = nextIdentIter(it, scope.symbols)
   
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 0b1312ccc..c97b2f321 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -925,7 +925,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: 
     gsub(g, n.sons[0])
   of nkLambda:
-    putWithSpace(g, tkLambda, "proc")
+    putWithSpace(g, tkProc, "proc")
     gsub(g, n.sons[paramsPos])
     gsub(g, n.sons[pragmasPos])
     put(g, tkSpaces, Space)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 8025ef70d..26a59334c 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -16,7 +16,7 @@ import
   procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
   intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
   evaltempl, patterns, parampatterns, sempass2, pretty, semmacrosanity,
-  semparallel
+  semparallel, lowerings
 
 # implementation
 
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 65a2d7ab8..927b23cf2 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -81,6 +81,8 @@ proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) =
   if c.inCompilesContext > 0: 
     # fail fast:
     globalError(n.info, errTypeMismatch, "")
+  if errors.len == 0:
+    localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
   var result = msgKindToString(errTypeMismatch)
   add(result, describeArgs(c, n, 1))
   add(result, ')')
diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim
index 791bef823..3c30dc1bd 100644
--- a/compiler/semdestruct.nim
+++ b/compiler/semdestruct.nim
@@ -125,8 +125,7 @@ proc instantiateDestructor(c: PContext, typ: PType): PType =
   # The destructor is either user-defined or automatically
   # generated by the compiler in a member-wise fashion.
   var t = skipTypes(typ, {tyConst, tyMutable}).skipGenericAlias
-  let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base
-                                  else: t
+  let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base else: t
   
   if typeHoldingUserDefinition.destructor != nil:
     # XXX: This is not entirely correct for recursive types, but we need
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 7deb46af9..58cef36f9 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -185,13 +185,15 @@ proc isCastable(dst, src: PType): bool =
   #  castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString, 
   #                       tySequence, tyPointer, tyNil, tyOpenArray,
   #                       tyProc, tySet, tyEnum, tyBool, tyChar}
+  if skipTypes(dst, abstractInst-{tyOpenArray}).kind == tyOpenArray:
+    return false
   var dstSize, srcSize: BiggestInt
 
   dstSize = computeSize(dst)
   srcSize = computeSize(src)
   if dstSize < 0: 
     result = false
-  elif srcSize < 0: 
+  elif srcSize < 0:
     result = false
   elif not typeAllowed(dst, skParam):
     result = false
@@ -199,6 +201,8 @@ proc isCastable(dst, src: PType): bool =
     result = (dstSize >= srcSize) or
         (skipTypes(dst, abstractInst).kind in IntegralTypes) or
         (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
@@ -592,7 +596,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
   const 
     FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, 
       mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, 
-      mAppendSeqElem, mNewSeq, mReset, mShallowCopy}
+      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
@@ -658,7 +662,7 @@ 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 == {}:
+     {sfForward, sfImportc} * callee.flags == {} and n.typ != nil:
     if sfCompileTime notin callee.flags and 
         optImplicitStatic notin gOptions: return
 
@@ -1370,20 +1374,19 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
     if onlyCurrentScope: return 
     checkSonsLen(n, 2)
     var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope)
-    if (m != nil) and (m.kind == skModule): 
-      if (n.sons[1].kind == nkIdent): 
-        var ident = n.sons[1].ident
-        if m == c.module: 
-          result = strTableGet(c.topLevelScope.symbols, ident)
-        else: 
-          result = strTableGet(m.tab, ident)
+    if m != nil and m.kind == skModule:
+      let ident = considerQuotedIdent(n[1])
+      if m == c.module:
+        result = strTableGet(c.topLevelScope.symbols, ident)
       else: 
-        localError(n.sons[1].info, errIdentifierExpected, "")
+        result = strTableGet(m.tab, ident)
   of nkAccQuoted:
     result = lookUpForDefined(c, considerQuotedIdent(n), onlyCurrentScope)
   of nkSym:
     result = n.sym
-  else: 
+  of nkOpenSymChoice, nkClosedSymChoice:
+    result = n.sons[0].sym
+  else:
     localError(n.info, errIdentifierExpected, renderTree(n))
     result = nil
 
@@ -1391,10 +1394,16 @@ 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)
-  if lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: 
-    result.intVal = 1
-  elif not onlyCurrentScope and (n.sons[1].kind == nkIdent) and
-      condsyms.isDefined(n.sons[1].ident): 
+  if not onlyCurrentScope and considerQuotedIdent(n[0]).s == "defined":
+    if n.sons[1].kind != nkIdent:
+      localError(n.info, "obsolete usage of 'defined', use 'declared' instead")
+    elif condsyms.isDefined(n.sons[1].ident):
+      result.intVal = 1
+    elif not condsyms.isDeclared(n.sons[1].ident):
+      message(n.info, warnUser,
+        "undeclared conditional symbol; use --symbol to declare it: " &
+        n[1].ident.s)
+  elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: 
     result.intVal = 1
   result.info = n.info
   result.typ = getSysType(tyBool)
@@ -1605,6 +1614,11 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
   initIdTable(bindings)
   bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t)
   result = c.semGenerateInstance(c, sym, bindings, info)
+  # since it's an instantiation, we unmark it as a compilerproc. Otherwise
+  # codegen would fail:
+  if sfCompilerProc in result.flags:
+    result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC}
+    result.loc.r = nil
 
 proc setMs(n: PNode, s: PSym): PNode = 
   result = n
@@ -1643,10 +1657,10 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     result = setMs(n, s)
     result.sons[1] = semExpr(c, n.sons[1])
     if not result[1].typ.isEmptyType:
-      if c.inParallelStmt > 0:
-        result.typ = result[1].typ
-      else:
+      if spawnResult(result[1].typ, c.inParallelStmt > 0) == srFlowVar:
         result.typ = createFlowVar(c, result[1].typ, n.info)
+      else:
+        result.typ = result[1].typ
       result.add instantiateCreateFlowVarCall(c, result[1].typ, n.info).newSymNode
   else: result = semDirectOp(c, n, flags)
 
@@ -1758,8 +1772,9 @@ proc checkPar(n: PNode): TParKind =
   var length = sonsLen(n)
   if length == 0: 
     result = paTuplePositions # ()
-  elif length == 1: 
-    result = paSingle         # (expr)
+  elif length == 1:
+    if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
+    else: result = paSingle         # (expr)
   else:
     if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
     else: result = paTuplePositions
@@ -1920,11 +1935,13 @@ proc semExport(c: PContext, n: PNode): PNode =
     while s != nil:
       if s.kind in ExportableSymKinds+{skModule}:
         x.add(newSymNode(s, a.info))
+        strTableAdd(c.module.tab, s)
       s = nextOverloadIter(o, c, a)
-  if c.module.ast.isNil:
-    c.module.ast = newNodeI(nkStmtList, n.info)
-  assert c.module.ast.kind == nkStmtList
-  c.module.ast.add x
+  when false:
+    if c.module.ast.isNil:
+      c.module.ast = newNodeI(nkStmtList, n.info)
+    assert c.module.ast.kind == nkStmtList
+    c.module.ast.add x
   result = n
 
 proc setGenericParams(c: PContext, n: PNode) =
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 934434951..a004d1465 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -36,10 +36,11 @@ proc semGenericStmtScope(c: PContext, n: PNode,
 template macroToExpand(s: expr): expr =
   s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags)
 
-proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = 
+proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
+                          ctx: var TIntSet): PNode =
   incl(s.flags, sfUsed)
   case s.kind
-  of skUnknown: 
+  of skUnknown:
     # Introduced in this pass! Leave it as an identifier.
     result = n
   of skProc, skMethod, skIterators, skConverter:
@@ -48,11 +49,13 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
     if macroToExpand(s):
       let n = fixImmediateParams(n)
       result = semTemplateExpr(c, n, s, {efNoSemCheck})
+      result = semGenericStmt(c, result, {}, ctx)
     else:
       result = symChoice(c, n, s, scOpen)
   of skMacro: 
     if macroToExpand(s):
       result = semMacroExpr(c, n, n, s, {efNoSemCheck})
+      result = semGenericStmt(c, result, {}, ctx)
     else:
       result = symChoice(c, n, s, scOpen)
   of skGenericParam: 
@@ -80,7 +83,7 @@ proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
     elif s.name.id in ctx:
       result = symChoice(c, n, s, scForceOpen)
     else:
-      result = semGenericStmtSymbol(c, n, s)
+      result = semGenericStmtSymbol(c, n, s, ctx)
   # else: leave as nkIdent
 
 proc newDot(n, b: PNode): PNode =
@@ -95,8 +98,9 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
   
   var s = qualifiedLookUp(c, n, luf)
   if s != nil:
-    result = semGenericStmtSymbol(c, n, s)
+    result = semGenericStmtSymbol(c, n, s, ctx)
   else:
+    n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
     result = n
     let n = n[1]
     let ident = considerQuotedIdent(n)
@@ -107,7 +111,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
       elif s.name.id in ctx:
         result = newDot(result, symChoice(c, n, s, scForceOpen))
       else:
-        let sym = semGenericStmtSymbol(c, n, s)
+        let sym = semGenericStmtSymbol(c, n, s, ctx)
         if sym.kind == nkSym:
           result = newDot(result, symChoice(c, n, s, scForceOpen))
         else:
@@ -158,6 +162,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       of skMacro:
         if macroToExpand(s):
           result = semMacroExpr(c, n, n, s, {efNoSemCheck})
+          result = semGenericStmt(c, result, {}, ctx)
         else:
           n.sons[0] = symChoice(c, n.sons[0], s, scOption)
           result = n
@@ -165,6 +170,7 @@ proc semGenericStmt(c: PContext, n: PNode,
         if macroToExpand(s):
           let n = fixImmediateParams(n)
           result = semTemplateExpr(c, n, s, {efNoSemCheck})
+          result = semGenericStmt(c, result, {}, ctx)
         else:
           n.sons[0] = symChoice(c, n.sons[0], s, scOption)
           result = n
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index b93d7ca15..b205eb09a 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -33,7 +33,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
         localError(a.info, errCannotInstantiateX, s.name.s)
         t = errorType(c)
     elif t.kind == tyGenericParam: 
-      internalError(a.info, "instantiateGenericParamList: " & q.name.s)
+      localError(a.info, errCannotInstantiateX, q.name.s)
+      t = errorType(c)
     elif t.kind == tyGenericInvokation:
       #t = instGenericContainer(c, a, t)
       t = generateTypeInstance(c, pt, a, t)
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index f943e7006..d4aeba32a 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -126,7 +126,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
     result.typ = getSysType(tyString)
   of mInstantiationInfo: result = semInstantiationInfo(c, n)
   of mOrd: result = semOrd(c, n)
-  of mHigh: result = semLowHigh(c, n, mHigh)
+  of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic)
   of mShallowCopy: result = semShallowCopy(c, n, flags)
   of mNBindSym: result = semBindSym(c, n)
   of mLocals: result = semLocals(c, n)
diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim
index c594a4788..7c489c3b6 100644
--- a/compiler/semparallel.nim
+++ b/compiler/semparallel.nim
@@ -23,7 +23,7 @@
 
 import
   ast, astalgo, idents, lowerings, magicsys, guards, sempass2, msgs,
-  renderer
+  renderer, types
 from trees import getMagic
 from strutils import `%`
 
@@ -406,12 +406,17 @@ proc transformSpawn(owner: PSym; n, barrier: PNode): PNode =
         if result.isNil:
           result = newNodeI(nkStmtList, n.info)
           result.add n
-        result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0])
-        it.sons[it.len-1] = emptyNode
+        let t = b[1][0].typ.sons[0]
+        if spawnResult(t, true) == srByVar:
+          result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0])
+          it.sons[it.len-1] = emptyNode
+        else:
+          it.sons[it.len-1] = wrapProcForSpawn(owner, m, b.typ, barrier, nil)
     if result.isNil: result = n
   of nkAsgn, nkFastAsgn:
     let b = n[1]
-    if getMagic(b) == mSpawn:
+    if getMagic(b) == mSpawn and (let t = b[1][0].typ.sons[0];
+        spawnResult(t, true) == srByVar):
       let m = transformSlices(b)
       return wrapProcForSpawn(owner, m, b.typ, barrier, n[0])
     result = transformSpawnSons(owner, n, barrier)
@@ -462,4 +467,3 @@ proc liftParallel*(owner: PSym; n: PNode): PNode =
   result.add callCodeGenProc("openBarrier", barrier)
   result.add transformSpawn(owner, body, barrier)
   result.add callCodeGenProc("closeBarrier", barrier)
-
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index c8ce5e787..da4adcf49 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -115,7 +115,7 @@ proc useVar(a: PEffects, n: PNode) =
       a.addUse(copyNode(n))
     if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and 
         tfGcSafe notin s.typ.flags:
-      message(n.info, warnGcUnsafe, renderTree(n))
+      if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
       a.gcUnsafe = true
 
 type
@@ -315,7 +315,6 @@ proc documentRaises*(n: PNode) =
   if n.sons[namePos].kind != nkSym: return
   documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects)
   documentEffect(n, n.sons[pragmasPos], wTags, tagEffects)
-  documentEffect(n, n.sons[pragmasPos], wUses, usesEffects)
 
 template notGcSafe(t): expr = {tfGcSafe, tfNoSideEffect} * t.flags == {}
 
@@ -332,13 +331,9 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
   mergeTags(tracked, tagSpec, n)
 
   if notGcSafe(s.typ) and sfImportc notin s.flags:
-    message(n.info, warnGcUnsafe, renderTree(n))
+    if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
     tracked.gcUnsafe = true
 
-  when trackGlobals:
-    let usesSpec = effectSpec(pragma, wUses)
-    mergeUses(tracked, usesSpec, n)
-
 proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
   let n = n.skipConv
   if paramType != nil and tfNotNil in paramType.flags and 
@@ -358,7 +353,7 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
     of impYes: discard
 
 proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
-  let op = n.typ
+  let op = skipConvAndClosure(n).typ
   if op != nil and op.kind == tyProc and n.kind != nkNilLit:
     internalAssert op.n.sons[0].kind == nkEffectList
     var effectList = op.n.sons[0]
@@ -367,21 +362,24 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
       propagateEffects(tracked, n, s.sym)
     elif effectList.len == 0:
       if isForwardedProc(n):
+        # we have no explicit effects but it's a forward declaration and so it's
+        # stated there are no additional effects, so simply propagate them:
         propagateEffects(tracked, n, n.sym)
       else:
+        # we have no explicit effects so assume the worst:
         addEffect(tracked, createRaise(n))
         addTag(tracked, createTag(n))
         when trackGlobals: addUse(tracked, createAnyGlobal(n))
-      # assume GcUnsafe unless in its type:
-      if notGcSafe(op): 
-        message(n.info, warnGcUnsafe, renderTree(n))
+      # assume GcUnsafe unless in its type; 'forward' does not matter:
+      if notGcSafe(op):
+        if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
         tracked.gcUnsafe = true
     else:
       mergeEffects(tracked, effectList.sons[exceptionEffects], n)
       mergeTags(tracked, effectList.sons[tagEffects], n)
       when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n)
       if notGcSafe(op):
-        message(n.info, warnGcUnsafe, renderTree(n))
+        if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
         tracked.gcUnsafe = true
   notNilCheck(tracked, n, paramType)
 
@@ -510,9 +508,6 @@ proc track(tracked: PEffects, n: PNode) =
     if op != nil and op.kind == tyProc and op.n.sons[0].kind == nkEffectList:
       if a.kind == nkSym and a.sym == tracked.owner:
         tracked.isRecursive = true
-      elif notGcSafe(op) and not importedFromC(a):
-        message(n.info, warnGcUnsafe, renderTree(n))
-        tracked.gcUnsafe = true
       var effectList = op.n.sons[0]
       if a.kind == nkSym and a.sym.kind == skMethod:
         propagateEffects(tracked, n, a.sym)
@@ -528,6 +523,11 @@ proc track(tracked: PEffects, n: PNode) =
         mergeEffects(tracked, effectList.sons[exceptionEffects], n)
         mergeTags(tracked, effectList.sons[tagEffects], n)
         when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n)
+        if notGcSafe(op) and not importedFromC(a):
+          # and it's not a recursive call:
+          if not (a.kind == nkSym and a.sym == tracked.owner):
+            message(n.info, warnGcUnsafe, renderTree(n))
+            tracked.gcUnsafe = true
     for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i))
     if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
       # may not look like an assignment, but it is:
@@ -636,10 +636,6 @@ proc checkMethodEffects*(disp, branch: PSym) =
   if not isNil(tagsSpec):
     checkRaisesSpec(tagsSpec, actual.sons[tagEffects],
       "can have an unlisted effect: ", hints=off, subtypeRelation)
-  let usesSpec = effectSpec(p, wUses)
-  if not isNil(usesSpec):
-    checkRaisesSpec(usesSpec, actual.sons[usesEffects],
-      "may use an unlisted global variable: ", hints=off, symbolPredicate)
   if sfThread in disp.flags and notGcSafe(branch.typ):
     localError(branch.info, "base method is GC-safe, but '$1' is not" % 
                                 branch.name.s)
@@ -651,16 +647,13 @@ proc setEffectsForProcType*(t: PType, n: PNode) =
   let
     raisesSpec = effectSpec(n, wRaises)
     tagsSpec = effectSpec(n, wTags)
-    usesSpec = effectSpec(n, wUses)
-  if not isNil(raisesSpec) or not isNil(tagsSpec) or not isNil(usesSpec):
+  if not isNil(raisesSpec) or not isNil(tagsSpec):
     internalAssert effects.len == 0
     newSeq(effects.sons, effectListLen)
     if not isNil(raisesSpec):
       effects.sons[exceptionEffects] = raisesSpec
     if not isNil(tagsSpec):
       effects.sons[tagEffects] = tagsSpec
-    if not isNil(usesSpec):
-      effects.sons[usesEffects] = usesSpec
 
 proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
   newSeq(effects.sons, effectListLen)
@@ -705,16 +698,10 @@ proc trackProc*(s: PSym, body: PNode) =
     # after the check, use the formal spec:
     effects.sons[tagEffects] = tagsSpec
 
-  when trackGlobals:
-    let usesSpec = effectSpec(p, wUses)
-    if not isNil(usesSpec):
-      checkRaisesSpec(usesSpec, t.uses,
-        "uses an unlisted global variable: ", hints=on, symbolPredicate)
-      effects.sons[usesEffects] = usesSpec
   if optThreadAnalysis in gGlobalOptions:
     if sfThread in s.flags and t.gcUnsafe:
-      localError(s.info, warnGcUnsafe2, s.name.s)
-      #localError(s.info, "'$1' is not GC-safe" % s.name.s)
+      #localError(s.info, warnGcUnsafe2, s.name.s)
+      localError(s.info, "'$1' is not GC-safe" % s.name.s)
     if not t.gcUnsafe: s.typ.flags.incl tfGcSafe
 
 proc trackTopLevelStmt*(module: PSym; n: PNode) =
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 4d06b201e..d394a2ae5 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -22,20 +22,23 @@ proc semDiscard(c: PContext, n: PNode): PNode =
 proc semBreakOrContinue(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
-  if n.sons[0].kind != nkEmpty: 
-    var s: PSym
-    case n.sons[0].kind
-    of nkIdent: s = lookUp(c, n.sons[0])
-    of nkSym: s = n.sons[0].sym
-    else: illFormedAst(n)
-    if s.kind == skLabel and s.owner.id == c.p.owner.id: 
-      var x = newSymNode(s)
-      x.info = n.info
-      incl(s.flags, sfUsed)
-      n.sons[0] = x
-      suggestSym(x.info, s)
+  if n.sons[0].kind != nkEmpty:
+    if n.kind != nkContinueStmt:
+      var s: PSym
+      case n.sons[0].kind
+      of nkIdent: s = lookUp(c, n.sons[0])
+      of nkSym: s = n.sons[0].sym
+      else: illFormedAst(n)
+      if s.kind == skLabel and s.owner.id == c.p.owner.id:
+        var x = newSymNode(s)
+        x.info = n.info
+        incl(s.flags, sfUsed)
+        n.sons[0] = x
+        suggestSym(x.info, s)
+      else:
+        localError(n.info, errInvalidControlFlowX, s.name.s)
     else:
-      localError(n.info, errInvalidControlFlowX, s.name.s)
+      localError(n.info, errGenerated, "'continue' cannot have a label")
   elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0): 
     localError(n.info, errInvalidControlFlowX, 
                renderTree(n, {renderNoComments}))
@@ -1009,6 +1012,31 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
     addResult(c, s.typ.sons[0], n.info, s.kind)
     addResultNode(c, n)
 
+proc semOverride(c: PContext, s: PSym, n: PNode) =
+  case s.name.s.normalize
+  of "destroy": doDestructorStuff(c, s, n)
+  of "deepcopy":
+    if s.typ.len == 2 and
+        s.typ.sons[1].skipTypes(abstractInst).kind in {tyRef, tyPtr} and
+        sameType(s.typ.sons[1], s.typ.sons[0]):
+      # Note: we store the deepCopy in the base of the pointer to mitigate
+      # the problem that pointers are structural types:
+      let t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst)
+      if t.kind in {tyObject, tyDistinct, tyEnum}:
+        if t.deepCopy.isNil: t.deepCopy = s
+        else: 
+          localError(n.info, errGenerated,
+                     "cannot bind another 'deepCopy' to: " & typeToString(t))
+      else:
+        localError(n.info, errGenerated,
+                   "cannot bind 'deepCopy' to: " & typeToString(t))
+    else:
+      localError(n.info, errGenerated,
+                 "signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
+  of "=": discard
+  else: localError(n.info, errGenerated,
+                   "'destroy' or 'deepCopy' expected for 'override'")
+
 type
   TProcCompilationSteps = enum
     stepRegisterSymbol,
@@ -1125,7 +1153,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     popOwner()
     pushOwner(s)
   s.options = gOptions
-  if sfDestructor in s.flags: doDestructorStuff(c, s, n)
+  if sfOverriden in s.flags: semOverride(c, s, n)
   if n.sons[bodyPos].kind != nkEmpty:
     # for DLL generation it is annoying to check for sfImportc!
     if sfBorrow in s.flags:
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 33de40f34..9f0a4100d 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -137,7 +137,7 @@ proc hasGenericArguments*(n: PNode): bool =
     return false
 
 proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode =
-  # This is needed fo tgenericshardcases
+  # This is needed for tgenericshardcases
   # It's possible that a generic param will be used in a proc call to a
   # typedesc accepting proc. After generic param substitution, such procs
   # should be optionally instantiated with the correct type. In order to
@@ -216,12 +216,16 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
     result.typ = replaceTypeVarsT(cl, s.typ)
     result.ast = replaceTypeVarsN(cl, s.ast)
     
-proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
+proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType = 
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil:
     if cl.allowMetaTypes or tfRetType in t.flags: return
     localError(t.sym.info, errCannotInstantiateX, typeToString(t))
     result = errorType(cl.c)
+    # In order to prevent endless recursions, we must remember
+    # this bad lookup and replace it with errorType everywhere.
+    # These code paths are only active in nimrod check
+    idTablePut(cl.typeMap, t, result)
   elif result.kind == tyGenericParam and not cl.allowMetaTypes:
     internalError(cl.info, "substitution with generic parameter")
 
@@ -353,7 +357,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
 
   of tyGenericBody:
     localError(cl.info, errCannotInstantiateX, typeToString(t))
-    result = t
+    result = errorType(cl.c)
     #result = replaceTypeVarsT(cl, lastSon(t))
 
   of tyFromExpr:
diff --git a/compiler/testability.nim b/compiler/testability.nim
index ceefd0a5e..4587a5344 100644
--- a/compiler/testability.nim
+++ b/compiler/testability.nim
@@ -1,5 +1,5 @@
 template tests*(body: stmt) {.immediate.} =
   when defined(selftest):
-    when not defined(unittest): import unittest
+    when not declared(unittest): import unittest
     body
 
diff --git a/compiler/transf.nim b/compiler/transf.nim
index dece1ac18..b9b06675e 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -13,7 +13,7 @@
 # * inlines iterators
 # * inlines constants
 # * performes constant folding
-# * converts "continue" to "break"
+# * converts "continue" to "break"; disambiguates "break"
 # * introduces method dispatchers
 # * performs lambda lifting for closure support
 
@@ -44,7 +44,6 @@ type
     inlining: int            # > 0 if we are in inlining context (copy vars)
     nestedProcs: int         # > 0 if we are in a nested proc
     contSyms, breakSyms: seq[PSym]  # to transform 'continue' and 'break'
-    inLoop: int              # > 0 if we are in a loop
   PTransf = ref TTransfContext
 
 proc newTransNode(a: PNode): PTransNode {.inline.} = 
@@ -201,6 +200,18 @@ proc newLabel(c: PTransf, n: PNode): PSym =
   result = newSym(skLabel, nil, getCurrOwner(c), n.info)
   result.name = getIdent(genPrefix & $result.id)
 
+proc freshLabels(c: PTransf, n: PNode; symMap: var TIdTable) =
+  if n.kind in {nkBlockStmt, nkBlockExpr}:
+    if n.sons[0].kind == nkSym:
+      let x = newLabel(c, n[0])
+      idTablePut(symMap, n[0].sym, x)
+      n.sons[0].sym = x
+  if n.kind == nkSym and n.sym.kind == skLabel:
+    let x = PSym(idTableGet(symMap, n.sym))
+    if x != nil: n.sym = x
+  else:
+    for i in 0 .. <safeLen(n): freshLabels(c, n.sons[i], symMap)
+
 proc transformBlock(c: PTransf, n: PNode): PTransNode =
   var labl: PSym
   if n.sons[0].kind != nkEmpty:
@@ -213,14 +224,6 @@ proc transformBlock(c: PTransf, n: PNode): PTransNode =
   discard c.breakSyms.pop
   result[0] = newSymNode(labl).PTransNode
 
-proc transformBreak(c: PTransf, n: PNode): PTransNode =
-  if c.inLoop > 0 or n.sons[0].kind != nkEmpty:
-    result = n.PTransNode
-  else:
-    let labl = c.breakSyms[c.breakSyms.high]
-    result = transformSons(c, n)
-    result[0] = newSymNode(labl).PTransNode
-
 proc transformLoopBody(c: PTransf, n: PNode): PTransNode =  
   # What if it contains "continue" and "break"? "break" needs 
   # an explicit label too, but not the same!
@@ -239,6 +242,37 @@ proc transformLoopBody(c: PTransf, n: PNode): PTransNode =
   else: 
     result = transform(c, n)
 
+proc transformWhile(c: PTransf; n: PNode): PTransNode =
+  if c.inlining > 0:
+    result = transformSons(c, n)
+  else:
+    let labl = newLabel(c, n)
+    c.breakSyms.add(labl)
+    result = newTransNode(nkBlockStmt, n.info, 2)
+    result[0] = newSymNode(labl).PTransNode
+
+    var body = newTransNode(n)
+    for i in 0..n.len-2:
+      body[i] = transform(c, n.sons[i])
+    body[<n.len] = transformLoopBody(c, n.sons[<n.len])
+    result[1] = body
+    discard c.breakSyms.pop
+
+proc transformBreak(c: PTransf, n: PNode): PTransNode =
+  if n.sons[0].kind != nkEmpty or c.inlining > 0:
+    result = n.PTransNode
+    when false:
+      let lablCopy = idNodeTableGet(c.transCon.mapping, n.sons[0].sym)
+      if lablCopy.isNil:
+        result = n.PTransNode
+      else:
+        result = newTransNode(n.kind, n.info, 1)
+        result[0] = lablCopy.PTransNode
+  else:
+    let labl = c.breakSyms[c.breakSyms.high]
+    result = transformSons(c, n)
+    result[0] = newSymNode(labl).PTransNode
+
 proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) = 
   # XXX: BUG: what if `n` is an expression with side-effects?
   for i in countup(0, sonsLen(c.transCon.forStmt) - 3): 
@@ -424,20 +458,32 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
 
   var length = sonsLen(n)
   var call = n.sons[length - 2]
+
+  let labl = newLabel(c, n)
+  c.breakSyms.add(labl)
+  result = newTransNode(nkBlockStmt, n.info, 2)
+  result[0] = newSymNode(labl).PTransNode
+
   if call.typ.kind != tyIter and
     (call.kind notin nkCallKinds or call.sons[0].kind != nkSym or 
       call.sons[0].sym.kind != skIterator):
     n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
-    return lambdalifting.liftForLoop(n).PTransNode
-    #InternalError(call.info, "transformFor")
+    result[1] = lambdalifting.liftForLoop(n).PTransNode
+    discard c.breakSyms.pop
+    return result
   
   #echo "transforming: ", renderTree(n)
-  result = newTransNode(nkStmtList, n.info, 0)
+  var stmtList = newTransNode(nkStmtList, n.info, 0)
+  
   var loopBody = transformLoopBody(c, n.sons[length-1])
+
+  result[1] = stmtList
+  discard c.breakSyms.pop
+
   var v = newNodeI(nkVarSection, n.info)
   for i in countup(0, length - 3): 
     addVar(v, copyTree(n.sons[i])) # declare new vars
-  add(result, v.PTransNode)
+  add(stmtList, v.PTransNode)
   
   # Bugfix: inlined locals belong to the invoking routine, not to the invoked
   # iterator!
@@ -453,27 +499,32 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
     var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym 
     if arg.typ.kind == tyIter: continue
     case putArgInto(arg, formal.typ)
-    of paDirectMapping: 
+    of paDirectMapping:
       idNodeTablePut(newC.mapping, formal, arg)
-    of paFastAsgn: 
+    of paFastAsgn:
       # generate a temporary and produce an assignment statement:
       var temp = newTemp(c, formal.typ, formal.info)
       addVar(v, newSymNode(temp))
-      add(result, newAsgnStmt(c, newSymNode(temp), arg.PTransNode))
+      add(stmtList, newAsgnStmt(c, newSymNode(temp), arg.PTransNode))
       idNodeTablePut(newC.mapping, formal, newSymNode(temp))
     of paVarAsgn:
       assert(skipTypes(formal.typ, abstractInst).kind == tyVar)
       idNodeTablePut(newC.mapping, formal, arg)
       # XXX BUG still not correct if the arg has a side effect!
-  var body = iter.getBody
+  var body = iter.getBody.copyTree
   pushInfoContext(n.info)
+  # XXX optimize this somehow. But the check "c.inlining" is not correct:
+  var symMap: TIdTable
+  initIdTable symMap
+  freshLabels(c, body, symMap)
+
   inc(c.inlining)
-  add(result, transform(c, body))
-  #findWrongOwners(c, result.pnode)
+  add(stmtList, transform(c, body))
+  #findWrongOwners(c, stmtList.pnode)
   dec(c.inlining)
   popInfoContext()
   popTransCon(c)
-  # echo "transformed: ", result.PNode.renderTree
+  # echo "transformed: ", stmtList.PNode.renderTree
   
 proc getMagicOp(call: PNode): TMagic = 
   if call.sons[0].kind == nkSym and
@@ -643,25 +694,16 @@ proc transform(c: PTransf, n: PNode): PTransNode =
         if n.kind == nkMethodDef: methodDef(s, false)
     result = PTransNode(n)
   of nkForStmt: 
-    inc c.inLoop
     result = transformFor(c, n)
-    dec c.inLoop
   of nkParForStmt:
-    inc c.inLoop
     result = transformSons(c, n)
-    dec c.inLoop
   of nkCaseStmt: result = transformCase(c, n)
   of nkContinueStmt:
     result = PTransNode(newNodeI(nkBreakStmt, n.info))
     var labl = c.contSyms[c.contSyms.high]
     add(result, PTransNode(newSymNode(labl)))
   of nkBreakStmt: result = transformBreak(c, n)
-  of nkWhileStmt: 
-    inc c.inLoop
-    result = newTransNode(n)
-    result[0] = transform(c, n.sons[0])
-    result[1] = transformLoopBody(c, n.sons[1])
-    dec c.inLoop
+  of nkWhileStmt: result = transformWhile(c, n)
   of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, 
      nkCallStrLit: 
     result = transformCall(c, n)
@@ -740,6 +782,8 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
     #  result = lambdalifting.liftIterator(prc, result)
     incl(result.flags, nfTransf)
     when useEffectSystem: trackProc(prc, result)
+    if prc.name.s == "testbody":
+      echo renderTree(result)
 
 proc transformStmt*(module: PSym, n: PNode): PNode =
   if nfTransf in n.flags:
diff --git a/compiler/types.nim b/compiler/types.nim
index 786eea14e..c04413857 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -99,7 +99,7 @@ proc isPureObject(typ: PType): bool =
 
 proc getOrdValue(n: PNode): BiggestInt = 
   case n.kind
-  of nkCharLit..nkInt64Lit: result = n.intVal
+  of nkCharLit..nkUInt64Lit: result = n.intVal
   of nkNilLit: result = 0
   of nkHiddenStdConv: result = getOrdValue(n.sons[1])
   else:
@@ -582,7 +582,10 @@ proc firstOrd(t: PType): BiggestInt =
   of tyGenericInst, tyDistinct, tyConst, tyMutable,
      tyTypeDesc, tyFieldAccessor:
     result = firstOrd(lastSon(t))
-  else: 
+  of tyOrdinal:
+    if t.len > 0: result = firstOrd(lastSon(t))
+    else: internalError("invalid kind for first(" & $t.kind & ')')
+  else:
     internalError("invalid kind for first(" & $t.kind & ')')
     result = 0
 
@@ -617,7 +620,10 @@ proc lastOrd(t: PType): BiggestInt =
      tyTypeDesc, tyFieldAccessor:
     result = lastOrd(lastSon(t))
   of tyProxy: result = 0
-  else: 
+  of tyOrdinal:
+    if t.len > 0: result = lastOrd(lastSon(t))
+    else: internalError("invalid kind for last(" & $t.kind & ')')
+  else:
     internalError("invalid kind for last(" & $t.kind & ')')
     result = 0
 
@@ -907,9 +913,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
           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, tyProxy:
+  of tyEnum, tyForward:
     # XXX generic enums do not make much sense, but require structural checking
     result = a.id == b.id and sameFlags(a, b)
+  of tyError:
+    result = b.kind == tyError
   of tyTuple:
     cycleCheck()
     result = sameTuple(a, b, c) and sameFlags(a, b)
@@ -1363,3 +1371,35 @@ proc containsCompileTimeOnly*(t: PType): bool =
       if t.sons[i] != nil and isCompileTimeOnly(t.sons[i]):
         return true
   return false
+
+type
+  OrdinalType* = enum
+    NoneLike, IntLike, FloatLike
+
+proc classify*(t: PType): OrdinalType =
+  ## for convenient type checking:
+  if t == nil:
+    result = NoneLike
+  else:
+    case skipTypes(t, abstractVarRange).kind
+    of tyFloat..tyFloat128: result = FloatLike
+    of tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyChar, tyEnum:
+      result = IntLike
+    else: result = NoneLike
+
+proc skipConv*(n: PNode): PNode =
+  result = n
+  case n.kind
+  of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
+    # only skip the conversion if it doesn't lose too important information
+    # (see bug #1334)
+    if n.sons[0].typ.classify == n.typ.classify:
+      result = n.sons[0]
+  of nkHiddenStdConv, nkHiddenSubConv, nkConv:
+    if n.sons[1].typ.classify == n.typ.classify:
+      result = n.sons[1]
+  else: discard
+
+proc skipConvTakeType*(n: PNode): PNode =
+  result = n.skipConv
+  result.typ = n.typ
diff --git a/compiler/vm.nim b/compiler/vm.nim
index aedbb92b4..e40acca6c 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -87,9 +87,7 @@ proc bailOut(c: PCtx; tos: PStackFrame) =
 when not defined(nimComputedGoto):
   {.pragma: computedGoto.}
 
-proc myreset(n: var TFullReg) =
-  when defined(system.reset): 
-    reset(n)
+proc myreset(n: var TFullReg) = reset(n)
 
 template ensureKind(k: expr) {.immediate, dirty.} =
   if regs[ra].kind != k:
@@ -1080,6 +1078,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNKind:
       decodeB(rkInt)
       regs[ra].intVal = ord(regs[rb].node.kind)
+      c.comesFromHeuristic = regs[rb].node.info
     of opcNIntVal:
       decodeB(rkInt)
       let a = regs[rb].node
@@ -1255,8 +1254,16 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         internalError(c.debug[pc],
           "request to create a NimNode of invalid kind")
       let cc = regs[rc].node
+
       regs[ra].node = newNodeI(TNodeKind(int(k)),
-        if cc.kind == nkNilLit: c.debug[pc] else: cc.info)
+        if cc.kind != nkNilLit:
+          cc.info
+        elif c.comesFromHeuristic.line > -1:
+          c.comesFromHeuristic
+        elif c.callsite != nil and c.callsite.safeLen > 1:
+          c.callsite[1].info
+        else:
+          c.debug[pc])
       regs[ra].node.flags.incl nfIsRef
     of opcNCopyNimNode:
       decodeB(rkNode)
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 873d8eebd..cad48abea 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -188,6 +188,7 @@ type
     features*: TSandboxFlags
     traceActive*: bool
     loopIterations*: int
+    comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces
 
   TPosition* = distinct int
 
@@ -196,7 +197,8 @@ type
 proc newCtx*(module: PSym): PCtx =
   PCtx(code: @[], debug: @[],
     globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
-    prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations)
+    prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations,
+    comesFromHeuristic: unknownLineInfo())
 
 proc refresh*(c: PCtx, module: PSym) =
   c.module = module
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 9a213d813..fdd8276cc 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -12,11 +12,11 @@ import ast, types, msgs, osproc, streams, options
 proc readOutput(p: PProcess): string =
   result = ""
   var output = p.outputStream
-  discard p.waitForExit
   while not output.atEnd:
     result.add(output.readLine)
     result.add("\n")
   result.setLen(result.len - "\n".len)
+  discard p.waitForExit
 
 proc opGorge*(cmd, input: string): string =
   var p = startCmd(cmd)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index fd0c3fc69..a4ddc2e15 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -43,18 +43,19 @@ type
 proc debugInfo(info: TLineInfo): string =
   result = info.toFilename.splitFile.name & ":" & $info.line
 
-proc codeListing(c: PCtx, result: var string, start=0) =
+proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
   # first iteration: compute all necessary labels:
   var jumpTargets = initIntSet()
   
-  for i in start.. < c.code.len:
+  let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1)
+  for i in start..last:
     let x = c.code[i]
     if x.opcode in relativeJumps:
       jumpTargets.incl(i+x.regBx-wordExcess)
 
   # for debugging purposes
   var i = start
-  while i < c.code.len:
+  while i <= last:
     if i in jumpTargets: result.addf("L$1:\n", i)
     let x = c.code[i]
 
@@ -82,9 +83,9 @@ proc codeListing(c: PCtx, result: var string, start=0) =
     result.add("\n")
     inc i
 
-proc echoCode*(c: PCtx, start=0) {.deprecated.} =
+proc echoCode*(c: PCtx, start=0; last = -1) {.deprecated.} =
   var buf = ""
-  codeListing(c, buf, start)
+  codeListing(c, buf, start, last)
   echo buf
 
 proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
@@ -495,6 +496,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
   c.freeTempRange(x, n.len)
 
 template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
+proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym)
 
 proc needsAsgnPatch(n: PNode): bool = 
   n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
@@ -637,8 +639,10 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
   c.freeTemp(tmp)
 
 proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
+  var x = n.sons[1]
+  if x.kind in {nkAddr, nkHiddenAddr}: x = x.sons[0]
   let
-    dest = c.genx(n.sons[1], {gfAddrOf})
+    dest = c.genx(x)
     tmp = c.genx(n.sons[2])
   c.gABC(n, opc, dest, tmp, 0)
   #c.genAsgnPatch(n.sons[1], dest)
@@ -1053,6 +1057,8 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
   # nkAddr we must not use 'unneededIndirection', but for deref we use it.
   if not isAddr and unneededIndirection(n.sons[0]):
     gen(c, n.sons[0], dest, newflags)
+  elif isAddr and isGlobal(n.sons[0]):
+    gen(c, n.sons[0], dest, flags+{gfAddrOf})
   else:
     let tmp = c.genx(n.sons[0], newflags)
     if dest < 0: dest = c.getTemp(n.typ)
@@ -1093,6 +1099,8 @@ proc setSlot(c: PCtx; v: PSym) =
   # XXX generate type initialization here?
   if v.position == 0:
     if c.prc.maxSlots == 0: c.prc.maxSlots = 1
+    if c.prc.maxSlots >= high(TRegister):
+      internalError(v.info, "cannot generate code; too many registers required")
     v.position = c.prc.maxSlots
     c.prc.slots[v.position] = (inUse: true,
         kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
@@ -1116,10 +1124,9 @@ proc checkCanEval(c: PCtx; n: PNode) =
   # we need to ensure that we don't evaluate 'x' here:
   # proc foo() = var x ...
   let s = n.sym
-  if s.position == 0:
-    if s.kind in {skVar, skTemp, skLet, skParam, skResult} and 
-        not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
-      cannotEval(n)
+  if s.kind in {skVar, skTemp, skLet, skParam, skResult} and 
+      not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
+    cannotEval(n)
 
 proc isTemp(c: PCtx; dest: TDest): bool =
   result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown
@@ -1246,6 +1253,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
       c.gABx(n, opcLdGlobal, cc, s.position)
       c.gABC(n, opcNodeToReg, dest, cc)
       c.freeTemp(cc)
+    elif gfAddrOf in flags:
+      c.gABx(n, opcLdGlobalAddr, dest, s.position)
     else:
       c.gABx(n, opcLdGlobal, dest, s.position)
   else:
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index fbe005031..d81031917 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -27,7 +27,7 @@ type
     wContinue, wConverter, wDiscard, wDistinct, wDiv, wDo, 
     wElif, wElse, wEnd, wEnum, wExcept, wExport,
     wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, 
-    wInclude, wInterface, wIs, wIsnot, wIterator, wLambda, wLet,
+    wInclude, wInterface, wIs, wIsnot, wIterator, wLet,
     wMacro, wMethod, wMixin, wMod, wNil, 
     wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, 
     wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, 
@@ -39,7 +39,7 @@ type
 
     wDestroy,
     
-    wImmediate, wDestructor, wDelegator,
+    wImmediate, wDestructor, wDelegator, wOverride,
     wImportCpp, wImportObjC,
     wImportCompilerProc,
     wImportc, wExportc, wIncompleteStruct, wRequiresInit,
@@ -64,7 +64,7 @@ type
     wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt,
     wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, 
     wAsmNoStackFrame,
-    wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wUses,
+    wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
 
     wAuto, wBool, wCatch, wChar, wClass,
     wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@@ -107,7 +107,7 @@ const
     "elif", "else", "end", "enum", "except", "export", 
     "finally", "for", "from", "generic", "if", 
     "import", "in", "include", "interface", "is", "isnot", "iterator",
-    "lambda", "let",
+    "let",
     "macro", "method", "mixin", "mod", "nil", "not", "notin",
     "object", "of", "or", 
     "out", "proc", "ptr", "raise", "ref", "return",
@@ -122,7 +122,7 @@ const
 
     "destroy",
     
-    "immediate", "destructor", "delegator",
+    "immediate", "destructor", "delegator", "override",
     "importcpp", "importobjc",
     "importcompilerproc", "importc", "exportc", "incompletestruct",
     "requiresinit", "align", "nodecl", "pure", "sideeffect",
@@ -147,7 +147,7 @@ const
     "computedgoto", "injectstmt",
     "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
     "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
-    "guard", "uses",
+    "guard", "locks",
     
     "auto", "bool", "catch", "char", "class",
     "const_cast", "default", "delete", "double",
diff --git a/config/nim.cfg b/config/nim.cfg
new file mode 100644
index 000000000..df3835ace
--- /dev/null
+++ b/config/nim.cfg
@@ -0,0 +1,139 @@
+# Configuration file for the Nimrod Compiler.
+# (c) 2013 Andreas Rumpf
+
+# Feel free to edit the default values as you need.
+
+# You may set environment variables with
+# @putenv "key" "val"
+# Environment variables cannot be used in the options, however!
+
+cc = gcc
+
+# example of how to setup a cross-compiler:
+arm.linux.gcc.exe = "arm-linux-gcc"
+arm.linux.gcc.linkerexe = "arm-linux-gcc"
+
+path="$lib/core"
+path="$lib/pure"
+path="$lib/pure/collections"
+path="$lib/pure/concurrency"
+path="$lib/impure"
+path="$lib/wrappers"
+# path="$lib/wrappers/cairo"
+# path="$lib/wrappers/gtk"
+# path="$lib/wrappers/lua"
+# path="$lib/wrappers/opengl"
+path="$lib/wrappers/pcre"
+path="$lib/wrappers/readline"
+path="$lib/wrappers/sdl"
+# path="$lib/wrappers/x11"
+path="$lib/wrappers/zip"
+path="$lib/wrappers/libffi"
+path="$lib/windows"
+path="$lib/posix"
+path="$lib/js"
+path="$lib/pure/unidecode"
+
+@if nimbabel:
+  babelpath="$home/.babel/pkgs/"
+@end
+
+@if release or quick:
+  obj_checks:off
+  field_checks:off
+  range_checks:off
+  bound_checks:off
+  overflow_checks:off
+  assertions:off
+  stacktrace:off
+  linetrace:off
+  debugger:off
+  line_dir:off
+  dead_code_elim:on
+@end
+
+@if release:
+  opt:speed
+@end
+
+# additional options always passed to the compiler:
+--parallel_build: "0" # 0 to auto-detect number of processors
+
+hint[LineTooLong]=off
+#hint[XDeclaredButNotUsed]=off
+
+@if unix:
+  @if not bsd:
+    # -fopenmp
+    gcc.options.linker = "-ldl"
+    gpp.options.linker = "-ldl"
+    clang.options.linker = "-ldl"
+    tcc.options.linker = "-ldl"
+  @end
+  @if bsd or haiku:
+    # BSD got posix_spawn only recently, so we deactivate it for osproc:
+    define:useFork
+    # at least NetBSD has problems with thread local storage:
+    tlsEmulation:on
+  @end
+@end
+
+# Configuration for the Intel C/C++ compiler:
+@if windows:
+  icl.options.speed = "/Ox /arch:SSE2"
+  icl.options.always = "/nologo"
+@end
+
+# Configuration for the GNU C/C++ compiler:
+@if windows:
+  #gcc.path = r"$nimrod\dist\mingw\bin"
+  @if gcc:
+    tlsEmulation:on
+  @end
+@end
+
+@if macosx:
+  cc = clang
+  tlsEmulation:on
+  gcc.options.always = "-w -fasm-blocks"
+  gpp.options.always = "-w -fasm-blocks -fpermissive"
+@else:
+  gcc.options.always = "-w"
+  gpp.options.always = "-w -fpermissive"
+@end
+
+gcc.options.speed = "-O3 -fno-strict-aliasing"
+gcc.options.size = "-Os"
+gcc.options.debug = "-g3 -O0"
+
+gpp.options.speed = "-O3 -fno-strict-aliasing"
+gpp.options.size = "-Os"
+gpp.options.debug = "-g3 -O0"
+#passl = "-pg"
+
+# Configuration for the LLVM GCC compiler:
+llvm_gcc.options.debug = "-g"
+llvm_gcc.options.always = "-w"
+llvm_gcc.options.speed = "-O2"
+llvm_gcc.options.size = "-Os"
+
+# Configuration for the LLVM CLang compiler:
+clang.options.debug = "-g"
+clang.options.always = "-w"
+clang.options.speed = "-O3"
+clang.options.size = "-Os"
+
+# Configuration for the Visual C/C++ compiler:
+vcc.options.linker = "/DEBUG /Zi /Fd\"$projectName.pdb\" /F33554432" # set the stack size to 8 MB
+vcc.options.debug = "/Zi /Fd\"$projectName.pdb\""
+vcc.options.always = "/nologo"
+vcc.options.speed = "/Ox /arch:SSE2"
+vcc.options.size = "/O1"
+
+# Configuration for the Digital Mars C/C++ compiler:
+@if windows:
+  dmc.path = r"$nimrod\dist\dm\bin"
+@end
+
+# Configuration for the Tiny C Compiler:
+tcc.options.always = "-w"
diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index dc241db50..975c7c06a 100644
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -41,7 +41,6 @@ doc.item = """
 <dt id="$itemSym"><a name="$itemSymOrID"></a><pre>$header</pre></dt>
 <dd>
 $desc
-$seeSrc
 </dd>
 """
 
@@ -93,6 +92,11 @@ doc.file = """<?xml version="1.0" encoding="utf-8" ?>
 <title>$title</title>
 <style type="text/css">
 
+body {
+  color: black;
+  background: white;
+}
+
 span.DecNumber {color: blue}
 span.BinNumber {color: blue}
 span.HexNumber {color: blue}
diff --git a/config/nimrod.cfg b/config/nimrod.cfg
index df3835ace..075b65d63 100644
--- a/config/nimrod.cfg
+++ b/config/nimrod.cfg
@@ -130,10 +130,5 @@ vcc.options.always = "/nologo"
 vcc.options.speed = "/Ox /arch:SSE2"
 vcc.options.size = "/O1"
 
-# Configuration for the Digital Mars C/C++ compiler:
-@if windows:
-  dmc.path = r"$nimrod\dist\dm\bin"
-@end
-
 # Configuration for the Tiny C Compiler:
 tcc.options.always = "-w"
diff --git a/copying.txt b/copying.txt
index 4041ca027..254b91c77 100644
--- a/copying.txt
+++ b/copying.txt
@@ -1,7 +1,7 @@
-===============================================================================
-Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/
- 
-Copyright (C) 2004-2014 Andreas Rumpf. All rights reserved.
+=====================================================
+Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/
+
+Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved.
  
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/doc/backends.txt b/doc/backends.txt
index 26576e733..c2dbb0af6 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -322,6 +322,64 @@ earlier, JavaScript doesn't require an initialisation call to ``NimMain`` or
 similar function and you can call the exported Nimrod proc directly.
 
 
+Nimcache naming logic
+---------------------
+
+The `nimcache`:idx: directory is generated during compilation and will hold
+either temporary or final files depending on your backend target. The default
+name for the directory is ``nimcache`` but you can use the ``--nimcache``
+`compiler switch <nimrodc.html#command-line-switches>`_ to change it.
+
+Nimcache and C like targets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The C like backends will place their temporary ``.c``, ``.cpp`` or ``.m`` files
+in the ``nimcache`` directory. The naming of these files follows the pattern
+``babelPackageName_`` + ``nimrodSource``:
+
+* Filenames for modules imported from `Babel packages
+  <https://github.com/nimrod-code/babel>`_ will end up with
+  ``babelPackageName_module.c``. For example, if you import the
+  ``argument_parser`` module from the same name Babel package you
+  will end up with a ``argument_parser_argument_parser.c`` file
+  under ``nimcache``.  The name of the Babel package comes from the
+  ``proj.babel`` file, the actual contents are not read by the
+  compiler.
+
+* Filenames for non babel packages (like your project) will be
+  renamed from ``.nim`` to have the extension of your target backend
+  (from now on ``.c`` for these examples), but otherwise nothing
+  else will change. This will quickly break if your project consists
+  of a main ``proj.nim`` file which includes a ``utils/proj.nim``
+  file: both ``proj.nim`` files will generate the same name ``proj.c``
+  output in the ``nimcache`` directory overwriting themselves!
+
+* Filenames for modules found in the standard library will be named
+  ``stdlib_module.c``. Unless you are doing something special, you
+  will end up with at least ``stdlib_system.c``, since the `system
+  module <system.html>`_ is always imported automatically. Same for
+  the `hashes module <hashes.html>`_ which will be named
+  ``stdlib_hashes.c``. The ``stdlib_`` prefix comes from the *fake*
+  ``lib/stdlib.babel`` file.
+
+To find the name of a Babel package the compiler searches for a ``*.babel``
+file in the parent directory hierarchy of whatever module you are compiling.
+Even if you are in a subdirectory of your project, a parent ``*.babel`` file
+will influence the naming of the nimcache name. This means that on Unix systems
+creating the file ``~/foo.babel`` will automatically prefix all nimcache files
+not part of another package with the string ``foo_``.
+
+
+Nimcache and the Javascript target
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Unless you explicitly use the ``-o:filename.js`` switch as mentioned in the
+previous examples, the compiler will create a ``filename.js`` file in the
+``nimcache`` directory using the name of your input nimrod file. There are no
+other temporary files generated, the output is always a single self contained
+``.js`` file.
+
+
 Memory management
 =================
 
diff --git a/doc/basicopt.txt b/doc/basicopt.txt
index 3a29b7829..390623828 100644
--- a/doc/basicopt.txt
+++ b/doc/basicopt.txt
@@ -13,6 +13,7 @@ Options:
   -p, --path:PATH           add path to search paths
   -d, --define:SYMBOL       define a conditional symbol
   -u, --undef:SYMBOL        undefine a conditional symbol
+  --symbol:SYMBOL           declare a conditional symbol
   -f, --forceBuild          force rebuilding of all modules
   --stackTrace:on|off       turn stack tracing on|off
   --lineTrace:on|off        turn line tracing on|off
@@ -34,3 +35,5 @@ Options:
   -r, --run                 run the compiled program with given arguments
   --advanced                show advanced command line switches
   -h, --help                show this help
+
+Note: Even single letter options require the colon: -p:PATH.
diff --git a/doc/exception_hierarchy_fragment.txt b/doc/exception_hierarchy_fragment.txt
new file mode 100644
index 000000000..6ca68921f
--- /dev/null
+++ b/doc/exception_hierarchy_fragment.txt
@@ -0,0 +1,31 @@
+* `E_Base <system.html#E_Base>`_
+  * `EAccessViolation <system.html#EAccessViolation>`_
+  * `EArithmetic <system.html#EArithmetic>`_
+    * `EDivByZero <system.html#EDivByZero>`_
+    * `EOverflow <system.html#EOverflow>`_
+  * `EAssertionFailed <system.html#EAssertionFailed>`_
+  * `EAsynch <system.html#EAsynch>`_
+    * `EControlC <system.html#EControlC>`_
+  * `EDeadThread <system.html#EDeadThread>`_
+  * `EFloatingPoint <system.html#EFloatingPoint>`_
+    * `EFloatDivByZero <system.html#EFloatDivByZero>`_
+    * `EFloatInexact <system.html#EFloatInexact>`_
+    * `EFloatInvalidOp <system.html#EFloatInvalidOp>`_
+    * `EFloatOverflow <system.html#EFloatOverflow>`_
+    * `EFloatUnderflow <system.html#EFloatUnderflow>`_
+  * `EInvalidField <system.html#EInvalidField>`_
+  * `EInvalidIndex <system.html#EInvalidIndex>`_
+  * `EInvalidObjectAssignment <system.html#EInvalidObjectAssignment>`_
+  * `EInvalidObjectConversion <system.html#EInvalidObjectConversion>`_
+  * `EInvalidValue <system.html#EInvalidValue>`_
+    * `EInvalidKey <system.html#EInvalidKey>`_
+  * `ENoExceptionToReraise <system.html#ENoExceptionToReraise>`_
+  * `EOutOfRange <system.html#EOutOfRange>`_
+  * `ESynch <system.html#ESynch>`_
+    * `EOutOfMemory <system.html#EOutOfMemory>`_
+    * `EResourceExhausted <system.html#EResourceExhausted>`_
+    * `EStackOverflow <system.html#EStackOverflow>`_
+    * `ESystem <system.html#ESystem>`_
+      * `EIO <system.html#EIO>`_
+      * `EOS <system.html#EOS>`_
+        * `EInvalidLibrary <system.html#EInvalidLibrary>`_
diff --git a/doc/keywords.txt b/doc/keywords.txt
index 60b100398..a43b35475 100644
--- a/doc/keywords.txt
+++ b/doc/keywords.txt
@@ -6,7 +6,7 @@ elif else end enum except export
 finally for from
 generic
 if import in include interface is isnot iterator
-lambda let
+let
 macro method mixin mod
 nil not notin
 object of or out
diff --git a/doc/koch.txt b/doc/koch.txt
index 032151808..7be2be6d4 100644
--- a/doc/koch.txt
+++ b/doc/koch.txt
@@ -138,6 +138,13 @@ from rst to HTML. It also repeats the same operation but places the result in
 the ``web/upload`` which can be used to update the website at
 http://nimrod-lang.org.
 
+By default the documentation will be built in parallel using the number of
+available CPU cores. If any documentation build sub commands fail, they will
+be rerun in serial fashion so that meaninful error output can be gathered for
+inspection. The ``--parallelBuild:n`` switch or configuration option can be
+used to force a specific number of parallel jobs or run everything serially
+from the start (``n == 1``).
+
 zip command
 -----------
 
diff --git a/doc/lib.txt b/doc/lib.txt
index 5bacfcc4f..26ea1b735 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -56,7 +56,10 @@ Core
 
 * `typeinfo <typeinfo.html>`_
   Provides (unsafe) access to Nimrod's run time type information. 
-  
+
+* `typetraits <typetraits.html>`_
+  This module defines compile-time reflection procs for working with types.
+
 * `actors <actors.html>`_
   Actor support for Nimrod; implemented as a layer on top of the threads and
   channels modules.
@@ -447,10 +450,6 @@ Other
   This module contains code for reading from `stdin`:idx:. On UNIX the GNU
   readline library is wrapped and set up.
 
-* `zmq <zmq.html>`_
-  Nimrod 0mq wrapper. This file contains the low level C wrappers as well as
-  some higher level constructs.
-
 
 Wrappers
 ========
@@ -463,8 +462,6 @@ Windows specific
 
 * `windows <windows.html>`_
   Contains a wrapper for the Win32 API.
-* `ole2 <ole2.html>`_
-  Contains GUIDs for OLE2 automation support.
 * `shellapi <shellapi.html>`_
   Contains a wrapper for the ``shellapi.h`` header.
 * `shfolder <shfolder.html>`_
diff --git a/doc/manual.txt b/doc/manual.txt
index 53700ae80..c150d27e2 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -1421,7 +1421,7 @@ Examples:
   proc forEach(c: proc (x: int) {.cdecl.}) =
     ...
 
-  forEach(printItem)  # this will NOT work because calling conventions differ
+  forEach(printItem)  # this will NOT compile because calling conventions differ
 
   
 .. code-block:: nimrod
@@ -2467,7 +2467,7 @@ variable to use:
 
 When the compiler reaches the second ``add`` call, both ``a`` and ``b`` could
 be used with the proc, so one gets ``Error: expression '(a|b)' has no type (or
-is ambiguous)``. To solve this you would need to nest ``using`` with a
+is ambiguous)``. To solve this one would need to nest ``using`` with a
 ``block`` statement so as to control the reach of the ``using`` statement.
 
 If expression
@@ -4317,7 +4317,7 @@ Nimrod offers a special family of dot operators that can be used to
 intercept and rewrite proc call and field access attempts, referring
 to previously undeclared symbol names. They can be used to provide a
 fluent interface to objects lying outside the static confines of the
-Nimrod's type system such as values from dynamic scripting languages
+type system such as values from dynamic scripting languages
 or dynamic file formats such as JSON or XML.
 
 When Nimrod encounters an expression that cannot be resolved by the
@@ -4349,8 +4349,8 @@ This operator will be matched against both field accesses and method calls.
 operator `.()`
 ---------------
 This operator will be matched exclusively against method calls. It has higher
-precedence than the `.` operator and this allows you to handle expressions like
-`x.y` and `x.y()` differently if you are interfacing with a scripting language
+precedence than the `.` operator and this allows one to handle expressions like
+`x.y` and `x.y()` differently if one is interfacing with a scripting language
 for example.
 
 operator `.=`
@@ -4361,6 +4361,117 @@ This operator will be matched against assignments to missing fields.
   a.b = c # becomes `.=`(a, "b", c)
 
 
+Type bound operations
+=====================
+
+There are 3 operations that are bound to a type:
+
+1. Assignment
+2. Destruction
+3. Deep copying for communication between threads
+
+These operations can be *overriden* instead of *overloaded*. This means the
+implementation is automatically lifted to structured types. For instance if type
+``T`` has an overriden assignment operator ``=`` this operator is also used
+for assignments of the type ``seq[T]``. Since these operations are bound to a
+type they have to be bound to a nominal type for reasons of simplicity of
+implementation: This means an overriden ``deepCopy`` for ``ref T`` is really
+bound to ``T`` and not to ``ref T``. This also means that one cannot override
+``deepCopy`` for both ``ptr T`` and ``ref T`` at the same time; instead a
+helper distinct or object type has to be used for one pointer type.
+
+
+operator `=`
+------------
+
+**Note**: Overriding the assignment operator has not yet been implemented.
+
+This operator is the assignment operator. Note that in the contexts 
+like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for
+parameter passing no assignment is performed. The ``override`` pragma is
+optional for overriding ``=``.
+
+
+destructors
+-----------
+
+A destructor must have a single parameter with a concrete type (the name of a
+generic type is allowed too). The name of the destructor has to be ``destroy``
+and it need to be annotated with the ``override`` pragma.
+
+``destroy(v)`` will be automatically invoked for every local stack 
+variable ``v`` that goes out of scope.
+
+If a structured type features a field with destructable type and 
+the user has not provided an explicit implementation, a destructor for the
+structured type will be automatically generated. Calls to any base class 
+destructors in both user-defined and generated destructors will be inserted.
+
+A destructor is attached to the type it destructs; expressions of this type
+can then only be used in *destructible contexts* and as parameters:
+
+.. code-block:: nimrod
+  type
+    TMyObj = object
+      x, y: int
+      p: pointer
+      
+  proc destroy(o: var TMyObj) {.override.} =
+    if o.p != nil: dealloc o.p
+    
+  proc open: TMyObj =
+    result = TMyObj(x: 1, y: 2, p: alloc(3))
+ 
+  proc work(o: TMyObj) =
+    echo o.x
+    # No destructor invoked here for 'o' as 'o' is a parameter.
+
+  proc main() =
+    # destructor automatically invoked at the end of the scope:
+    var x = open()
+    # valid: pass 'x' to some other proc:
+    work(x)
+    
+    # Error: usage of a type with a destructor in a non destructible context
+    echo open()
+
+A destructible context is currently only the following:
+
+1. The ``expr`` in ``var x = expr``.
+2. The ``expr`` in ``let x = expr``.
+3. The ``expr`` in ``return expr``.
+4. The ``expr`` in ``result = expr`` where ``result`` is the special symbol
+   introduced by the compiler.
+
+These rules ensure that the construction is tied to a variable and can easily
+be destructed at its scope exit. Later versions of the language will improve
+the support of destructors.
+
+Be aware that destructors are not called for objects allocated with ``new``.
+This may change in future versions of language, but for now the ``finalizer``
+parameter to ``new`` has to be used.
+
+
+deepCopy
+--------
+
+``deepCopy`` is a builtin that is invoked whenever data is passed to
+a ``spawn``'ed proc to ensure memory safety. The programmer can override its
+behaviour for a specific ``ref`` or ``ptr`` type ``T``. (Later versions of the
+language may weaken this restriction.)
+
+The signature has to be:
+
+.. code-block:: nimrod
+  proc deepCopy(x: T): T {.override.}
+
+This mechanism is used by most data structures that support shared memory like
+channels to implement thread safe automatic memory management.
+
+The builtin ``deepCopy`` can even clone closures and their environments. See
+the documentation of `spawn`_ for details.
+
+
 Term rewriting macros
 =====================
 
@@ -4930,6 +5041,27 @@ first implementation to play with a language feature before a nicer syntax
 to access the feature becomes available.
 
 
+deprecated pragma
+-----------------
+
+The deprecated pragma is used to mark a symbol as deprecated:
+
+.. code-block:: nimrod
+  proc p() {.deprecated.}
+  var x {.deprecated.}: char
+
+It can also be used as a statement. Then it takes a list of *renamings*. The
+upcoming ``nimfix`` tool can automatically update the code and perform these
+renamings:
+
+.. code-block:: nimrod
+  type
+    File = object
+    Stream = ref object
+  {.deprecated: [TFile: File, PStream: Stream].}
+
+
+
 noSideEffect pragma
 -------------------
 The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side
@@ -4955,62 +5087,14 @@ destructor pragma
 -----------------
 
 The ``destructor`` pragma is used to mark a proc to act as a type destructor.
-The proc must have a single parameter with a concrete type (the name of a
-generic type is allowed too).
-
-Destructors will be automatically invoked when a local stack variable goes 
-out of scope.
-
-If a record type features a field with destructable type and 
-the user have not provided explicit implementation, Nimrod will automatically
-generate a destructor for the record type. Nimrod will automatically insert
-calls to any base class destructors in both user-defined and generated
-destructors.
-
-A destructor is attached to the type it destructs; expressions of this type
-can then only be used in *destructible contexts* and as parameters:
-
-.. code-block:: nimrod
-  type
-    TMyObj = object
-      x, y: int
-      p: pointer
-      
-  proc destruct(o: var TMyObj) {.destructor.} =
-    if o.p != nil: dealloc o.p
-    
-  proc open: TMyObj =
-    result = TMyObj(x: 1, y: 2, p: alloc(3))
- 
-  proc work(o: TMyObj) =
-    echo o.x
-    # No destructor invoked here for 'o' as 'o' is a parameter.
-
-  proc main() =
-    # destructor automatically invoked at the end of the scope:
-    var x = open()
-    # valid: pass 'x' to some other proc:
-    work(x)
-    
-    # Error: usage of a type with a destructor in a non destructible context
-    echo open()
+Its usage is deprecated, use the ``override`` pragma instead.
+See `type bound operations`_.
 
-A destructible context is currently only the following:
 
-1. The ``expr`` in ``var x = expr``.
-2. The ``expr`` in ``let x = expr``.
-3. The ``expr`` in ``return expr``.
-4. The ``expr`` in ``result = expr`` where ``result`` is the special symbol
-   introduced by the compiler.
-
-These rules ensure that the construction is tied to a variable and can easily
-be destructed at its scope exit. Later versions of the language will improve
-the support of destructors.
-
-Be aware that destructors are not called for objects allocated with ``new``.
-This may change in future versions of language, but for now use 
-the ``finalizer`` parameter to ``new``.
+override pragma
+---------------
 
+See `type bound operations`_ instead.
 
 procvar pragma
 --------------
@@ -5260,7 +5344,7 @@ See `Ordinary vs immediate templates`_.
 compilation option pragmas
 --------------------------
 The listed pragmas here can be used to override the code generation options
-for a section of code.
+for a proc/method/converter.
 
 The implementation currently provides the following possible options (various
 others may be added later).
@@ -5460,10 +5544,10 @@ spelled*:
   proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
 
 Note that this pragma is somewhat of a misnomer: Other backends will provide
-the same feature under the same name. Also, if you are interfacing with C++
-you can use the `ImportCpp pragma <nimrodc.html#importcpp-pragma>`_ and
+the same feature under the same name. Also, if one is interfacing with C++
+the `ImportCpp pragma <nimrodc.html#importcpp-pragma>`_ and
 interfacing with Objective-C the `ImportObjC pragma
-<nimrodc.html#importobjc-pragma>`_.
+<nimrodc.html#importobjc-pragma>`_ can be used.
 
 
 Exportc pragma
@@ -5751,12 +5835,14 @@ used instead. `spawn`:idx: is used to pass a task to the thread pool:
 
 Currently the expression that ``spawn`` takes is however quite restricted: 
 
-* It must be a call expresion ``f(a, ...)``.
+* It must be a call expression ``f(a, ...)``.
 * ``f`` must be ``gcsafe``.
 * ``f`` must not have the calling convention ``closure``.
-* ``f``'s parameters may not be of type ``var`` nor may they contain ``ref``.
-  This means you have to use raw ``ptr``'s for data passing reminding the
+* ``f``'s parameters may not be of type ``var``.
+  This means one has to use raw ``ptr``'s for data passing reminding the
   programmer to be careful.
+* ``ref`` parameters are deeply copied which is a subtle semantic change and
+  can cause performance problems but ensures memory safety.
 * For *safe* data exchange between ``f`` and the caller a global ``TChannel``
   needs to be used. Other means will be provided soon.
 
diff --git a/doc/nimdoc.css b/doc/nimdoc.css
index 6154f0b2e..e3bab07de 100644
--- a/doc/nimdoc.css
+++ b/doc/nimdoc.css
@@ -16,6 +16,11 @@ customize this style sheet.
    Andreas Rumpf

 */

 

+body {

+  color: black;

+  background: white;

+}

+

 /* used to remove borders from tables and images */

 .borderless, table.borderless td, table.borderless th {

   border: 0 }

diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt
index 90fad7f9c..016f0ed50 100644
--- a/doc/nimrodc.txt
+++ b/doc/nimrodc.txt
@@ -152,10 +152,12 @@ the first matching file is used.
 

 Generated C code directory

 --------------------------

-The generated files that Nimrod produces all go into a subdirectory called

-``nimcache`` in your project directory. This makes it easy to delete all

-generated files.

-

+The generated files that Nimrod produces all go into a subdirectory called
+``nimcache`` in your project directory. This makes it easy to delete all
+generated files. Files generated in this directory follow a naming logic which
+you can read about in the `Nimrod Backend Integration document
+<backends.html#nimcache-naming-logic>`_.
+
 However, the generated C code is not platform independent. C code generated for

 Linux does not compile on Windows, for instance. The comment on top of the

 C file lists the OS, CPU and CC the file has been compiled for.

diff --git a/doc/spawn.txt b/doc/spawn.txt
index ed500f3a5..c5c96ecf8 100644
--- a/doc/spawn.txt
+++ b/doc/spawn.txt
@@ -53,13 +53,13 @@ restrictions / changes:
 * ``spawn`` within a ``parallel`` section has special semantics.
 * Every location of the form ``a[i]`` and ``a[i..j]`` and ``dest`` where
   ``dest`` is part of the pattern ``dest = spawn f(...)`` has to be
-  provable disjoint. This is called the *disjoint check*.
+  provably disjoint. This is called the *disjoint check*.
 * Every other complex location ``loc`` that is used in a spawned
   proc (``spawn f(loc)``) has to be immutable for the duration of
   the ``parallel`` section. This is called the *immutability check*. Currently
   it is not specified what exactly "complex location" means. We need to make
   this an optimization!
-* Every array access has to be provable within bounds. This is called 
+* Every array access has to be provably within bounds. This is called 
   the *bounds check*.
 * Slices are optimized so that no copy is performed. This optimization is not
   yet performed for ordinary slices outside of a ``parallel`` section. Slices
diff --git a/doc/tut1.txt b/doc/tut1.txt
index 55eb0ebd7..ee642ce17 100644
--- a/doc/tut1.txt
+++ b/doc/tut1.txt
@@ -17,10 +17,9 @@ Introduction
 
 
 This document is a tutorial for the programming language *Nimrod*. 
-This tutorial assumes that you are familiar with basic programming concepts 
-like variables, types or statements but is kept very basic. The manual 
-contains many more examples of the advanced language features.
-
+This tutorial assumes that you are familiar with basic programming concepts
+like variables, types or statements but is kept very basic. The `manual
+<manual.html>`_ contains many more examples of the advanced language features.
 
 
 
@@ -40,9 +39,9 @@ Save this code to the file "greetings.nim". Now compile and run it::
 
   nimrod compile --run greetings.nim
 
-With the ``--run`` switch Nimrod executes the file automatically
-after compilation. You can give your program command line arguments by
-appending them after the filename::
+With the ``--run`` `switch <nimrodc.html#command-line-switches>`_ Nimrod
+executes the file automatically after compilation. You can give your program
+command line arguments by appending them after the filename::
 
   nimrod compile --run greetings.nim arg1 arg2
 
@@ -54,9 +53,10 @@ To compile a release version use::
   
   nimrod c -d:release greetings.nim
 
-By default the Nimrod compiler generates a large amount of runtime checks 
-aiming for your debugging pleasure. With ``-d:release`` these checks are 
-turned off and optimizations are turned on.
+By default the Nimrod compiler generates a large amount of runtime checks
+aiming for your debugging pleasure. With ``-d:release`` these checks are
+`turned off and optimizations are turned on
+<nimrodc.html#compile-time-symbols>`_.
 
 Though it should be pretty obvious what the program does, I will explain the
 syntax: statements which are not indented are executed when the program
@@ -65,9 +65,10 @@ done with spaces only, tabulators are not allowed.
 
 String literals are enclosed in double quotes. The ``var`` statement declares
 a new variable named ``name`` of type ``string`` with the value that is
-returned by the ``readLine`` procedure. Since the compiler knows that
-``readLine`` returns a string, you can leave out the type in the declaration
-(this is called `local type inference`:idx:). So this will work too:
+returned by the `readLine <system.html#readLine,TFile>`_ procedure. Since the
+compiler knows that `readLine <system.html#readLine,TFile>`_ returns a string,
+you can leave out the type in the declaration (this is called `local type
+inference`:idx:). So this will work too:
 
 .. code-block:: Nimrod
   var name = readLine(stdin)
@@ -75,10 +76,10 @@ returned by the ``readLine`` procedure. Since the compiler knows that
 Note that this is basically the only form of type inference that exists in
 Nimrod: it is a good compromise between brevity and readability.
 
-The "hello world" program contains several identifiers that are already
-known to the compiler: ``echo``, ``readLine``, etc. These built-ins are
-declared in the system_ module which is implicitly imported by any other
-module.
+The "hello world" program contains several identifiers that are already known
+to the compiler: ``echo``, `readLine <system.html#readLine,TFile>`_, etc.
+These built-ins are declared in the system_ module which is implicitly
+imported by any other module.
 
 
 Lexical elements
@@ -154,11 +155,11 @@ the syntax, watch their indentation:
   when false:
     brokenCode()
 
-Another option is to use the `discard`_ statement together with
-*long string literals* to create block comments:
+Another option is to use the `discard statement`_ together with *long string
+literals* to create block comments:
 
 .. code-block:: nimrod
-  discard """ You can have any nimrod code text commented 
+  discard """ You can have any Nimrod code text commented
   out inside this with no indentation restrictions.
         yes("May I ask a pointless question?") """
 
@@ -257,10 +258,10 @@ that can not be re-assigned, ``const`` means "enforce compile time evaluation
 and put it into a data section":
 
 .. code-block::
-  const input = readline(stdin) # Error: constant expression expected
+  const input = readLine(stdin) # Error: constant expression expected
   
 .. code-block::
-  let input = readline(stdin)   # works
+  let input = readLine(stdin)   # works
 
 
 Control flow statements
@@ -285,9 +286,10 @@ The if statement is one way to branch the control flow:
   else:
     echo("Hi, ", name, "!")
 
-There can be zero or more elif parts, and the else part is optional. The
-keyword ``elif`` is short for ``else if``, and is useful to avoid excessive
-indentation. (The ``""`` is the empty string. It contains no characters.)
+There can be zero or more ``elif`` parts, and the ``else`` part is optional.
+The keyword ``elif`` is short for ``else if``, and is useful to avoid
+excessive indentation. (The ``""`` is the empty string. It contains no
+characters.)
 
 
 Case statement
@@ -338,7 +340,7 @@ the compiler that for every other value nothing should be done:
   of 3, 8: echo("The number is 3 or 8")
   else: discard
 
-The empty ``discard`` statement is a *do nothing* statement. The compiler knows
+The empty `discard statement`_ is a *do nothing* statement. The compiler knows
 that a case statement with an else part cannot fail and thus the error 
 disappears. Note that it is impossible to cover all possible string values: 
 that is why there is no such check for string cases.
@@ -370,7 +372,8 @@ For statement
 -------------
 
 The ``for`` statement is a construct to loop over any element an *iterator*
-provides. The example uses the built-in ``countup`` iterator:
+provides. The example uses the built-in `countup <system.html#countup>`_
+iterator:
 
 .. code-block:: nimrod
   echo("Counting to ten: ")
@@ -378,11 +381,11 @@ provides. The example uses the built-in ``countup`` iterator:
     echo($i)
   # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
 
-The built-in ``$`` operator turns an integer (``int``) and many other types
-into a string. The variable ``i`` is implicitly declared by the ``for`` loop
-and has the type ``int``, because that is what ``countup`` returns. ``i`` runs
-through the values 1, 2, .., 10. Each value is ``echo``-ed. This code does
-the same:
+The built-in `$ <system.html#$>`_ operator turns an integer (``int``) and many
+other types into a string. The variable ``i`` is implicitly declared by the
+``for`` loop and has the type ``int``, because that is what `countup
+<system.html#countup>`_ returns. ``i`` runs through the values 1, 2, .., 10.
+Each value is ``echo``-ed. This code does the same:
 
 .. code-block:: nimrod
   echo("Counting to 10: ")
@@ -400,8 +403,8 @@ Counting down can be achieved as easily (but is less often needed):
     echo($i)
   # --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
 
-Since counting up occurs so often in programs, Nimrod also has a ``..`` iterator
-that does the same:
+Since counting up occurs so often in programs, Nimrod also has a `..
+<system.html#...i,S,T>`_ iterator that does the same:
 
 .. code-block:: nimrod
   for i in 1..10:
@@ -553,9 +556,10 @@ an expression is allowed:
 Procedures
 ==========
 
-To define new commands like ``echo``, ``readline`` in the examples, the concept
-of a `procedure` is needed. (Some languages call them *methods* or
-*functions*.) In Nimrod new procedures are defined with the ``proc`` keyword:
+To define new commands like `echo <system.html#echo>`_ and `readLine
+<system.html#readLine,TFile>`_ in the examples, the concept of a `procedure`
+is needed. (Some languages call them *methods* or *functions*.) In Nimrod new
+procedures are defined with the ``proc`` keyword:
 
 .. code-block:: nimrod
   proc yes(question: string): bool =
@@ -649,7 +653,7 @@ a tuple as a return value instead of using var parameters.
 Discard statement
 -----------------
 To call a procedure that returns a value just for its side effects and ignoring
-its return value, a discard statement **has** to be used. Nimrod does not
+its return value, a ``discard`` statement **has** to be used. Nimrod does not
 allow to silently throw away a return value:
 
 .. code-block:: nimrod
@@ -665,8 +669,8 @@ been declared with the ``discardable`` pragma:
     
   p(3, 4) # now valid
 
-The discard statement can also be used to create block comments as described
-in the `Comments`_.
+The ``discard`` statement can also be used to create block comments as
+described in the `Comments`_ section.
 
 
 Named arguments
@@ -730,12 +734,12 @@ Nimrod provides the ability to overload procedures similar to C++:
   echo(toString(13))   # calls the toString(x: int) proc
   echo(toString(true)) # calls the toString(x: bool) proc
 
-(Note that ``toString`` is usually the ``$`` operator in Nimrod.)
-The compiler chooses the most appropriate proc for the ``toString`` calls. How
-this overloading resolution algorithm works exactly is not discussed here
-(it will be specified in the manual soon).
-However, it does not lead to nasty surprises and is based on a quite simple
-unification algorithm. Ambiguous calls are reported as errors.
+(Note that ``toString`` is usually the `$ <system.html#$>`_ operator in
+Nimrod.) The compiler chooses the most appropriate proc for the ``toString``
+calls. How this overloading resolution algorithm works exactly is not
+discussed here (it will be specified in the manual soon).  However, it does
+not lead to nasty surprises and is based on a quite simple unification
+algorithm. Ambiguous calls are reported as errors.
 
 
 Operators
@@ -758,7 +762,7 @@ User defined operators are allowed. Nothing stops you from defining your own
 The operator's precedence is determined by its first character. The details
 can be found in the manual.
 
-To define a new operator enclose the operator in "``":
+To define a new operator enclose the operator in backticks "``":
 
 .. code-block:: nimrod
   proc `$` (x: myDataType): string = ...
@@ -811,7 +815,8 @@ Let's return to the boring counting example:
   for i in countup(1, 10):
     echo($i)
 
-Can a ``countup`` proc be written that supports this loop? Lets try:
+Can a `countup <system.html#countup>`_ proc be written that supports this
+loop? Lets try:
 
 .. code-block:: nimrod
   proc countup(a, b: int): int =
@@ -976,24 +981,25 @@ type:
 The common operators ``+ - * /  <  <=  ==  !=  >  >=`` are defined for
 floats and follow the IEEE standard.
 
-Automatic type conversion in expressions with different kinds
-of floating point types is performed: the smaller type is
-converted to the larger. Integer types are **not** converted to floating point
-types automatically and vice versa. The ``toInt`` and ``toFloat`` procs can be
-used for these conversions.
+Automatic type conversion in expressions with different kinds of floating
+point types is performed: the smaller type is converted to the larger. Integer
+types are **not** converted to floating point types automatically and vice
+versa. The `toInt <system.html#toInt>`_ and `toFloat <system.html#toFloat>`_
+procs can be used for these conversions.
 
 
 Internal type representation
 ============================
 
-As mentioned earlier, the built-in ``$`` (stringify) operator turns any basic
-type into a string, which you can then print to the screen with the ``echo``
-proc. However, advanced types, or types you may define yourself won't work with
-the ``$`` operator until you define one for them. Sometimes you just want to
-debug the current value of a complex type without having to write its ``$``
-operator.  You can use then the ``repr`` proc which works with any type and
-even complex data graphs with cycles. The following example shows that even for
-basic types there is a difference between the ``$`` and ``repr`` outputs:
+As mentioned earlier, the built-in `$ <system.html#$>`_ (stringify) operator
+turns any basic type into a string, which you can then print to the screen
+with the ``echo`` proc. However, advanced types, or types you may define
+yourself won't work with the ``$`` operator until you define one for them.
+Sometimes you just want to debug the current value of a complex type without
+having to write its ``$`` operator.  You can use then the `repr
+<system.html#repr>`_ proc which works with any type and even complex data
+graphs with cycles. The following example shows that even for basic types
+there is a difference between the ``$`` and ``repr`` outputs:
 
 .. code-block:: nimrod
   var
@@ -1087,9 +1093,10 @@ Operation             Comment
 ``pred(x, n)``        returns the `n`'th predecessor of `x`
 -----------------     --------------------------------------------------------
 
-The ``inc dec succ pred`` operations can fail by raising an `EOutOfRange` or
-`EOverflow` exception. (If the code has been compiled with the proper runtime
-checks turned on.)
+The `inc <system.html#inc>`_, `dec <system.html#dec>`_, `succ
+<system.html#succ>`_ and `pred <system.html#pred>`_ operations can fail by
+raising an `EOutOfRange` or `EOverflow` exception. (If the code has been
+compiled with the proper runtime checks turned on.)
 
 
 Subranges
@@ -1107,12 +1114,12 @@ to 5. Assigning any other value to a variable of type ``TSubrange`` is a
 compile-time or runtime error. Assignments from the base type to one of its
 subrange types (and vice versa) are allowed.
 
-The ``system`` module defines the important ``natural`` type as
-``range[0..high(int)]`` (``high`` returns the maximal value). Other programming
-languages mandate the usage of unsigned integers for natural numbers. This is
-often **wrong**: you don't want unsigned arithmetic (which wraps around) just
-because the numbers cannot be negative. Nimrod's ``natural`` type helps to
-avoid this common programming error.
+The ``system`` module defines the important `Natural <system.html#Natural>`_
+type as ``range[0..high(int)]`` (`high <system.html#high>`_ returns the
+maximal value). Other programming languages mandate the usage of unsigned
+integers for natural numbers. This is often **wrong**: you don't want unsigned
+arithmetic (which wraps around) just because the numbers cannot be negative.
+Nimrod's ``Natural`` type helps to avoid this common programming error.
 
 
 Sets
@@ -1145,8 +1152,9 @@ checks can be disabled via pragmas or invoking the compiler with the
 Arrays are value types, like any other Nimrod type. The assignment operator
 copies the whole array contents.
 
-The built-in ``len`` proc returns the array's length. ``low(a)`` returns the
-lowest valid index for the array `a` and ``high(a)`` the highest valid index.
+The built-in `len <system.html#len,TOpenArray>`_ proc returns the array's
+length. `low(a) <system.html#low>`_ returns the lowest valid index for the
+array `a` and `high(a) <system.html#high>`_ the highest valid index.
 
 .. code-block:: nimrod
   type
@@ -1218,13 +1226,14 @@ Sequences are similar to arrays but of dynamic length which may change
 during runtime (like strings). Since sequences are resizable they are always
 allocated on the heap and garbage collected.
 
-Sequences are always indexed with an ``int`` starting at position 0.
-The ``len``, ``low`` and ``high`` operations are available for sequences too.
-The notation ``x[i]`` can be used to access the i-th element of ``x``.
+Sequences are always indexed with an ``int`` starting at position 0.  The `len
+<system.html#len,seq[T]>`_, `low <system.html#low>`_ and `high
+<system.html#high>`_ operations are available for sequences too.  The notation
+``x[i]`` can be used to access the i-th element of ``x``.
 
 Sequences can be constructed by the array constructor ``[]`` in conjunction
 with the array to sequence operator ``@``. Another way to allocate space for
-a sequence is to call the built-in ``newSeq`` procedure.
+a sequence is to call the built-in `newSeq <system.html#newSeq>`_ procedure.
 
 A sequence may be passed to an openarray parameter.
 
@@ -1245,10 +1254,11 @@ object on the heap, so there is a trade-off to be made here.
 The ``for`` statement can be used with one or two variables when used with a
 sequence. When you use the one variable form, the variable will hold the value
 provided by the sequence. The ``for`` statement is looping over the results
-from the ``items()`` iterator from the `system <system.html>`_ module.  But if
-you use the two variable form, the first variable will hold the index position
-and the second variable will hold the value. Here the ``for`` statement is
-looping over the results from the ``pairs()`` iterator from the `system
+from the `items() <system.html#items.i,seq[T]>`_ iterator from the `system
+<system.html>`_ module.  But if you use the two variable form, the first
+variable will hold the index position and the second variable will hold the
+value. Here the ``for`` statement is looping over the results from the
+`pairs() <system.html#pairs.i,seq[T]>`_ iterator from the `system
 <system.html>`_ module.  Examples:
 
 .. code-block:: nimrod
@@ -1269,12 +1279,13 @@ Open arrays
 -----------
 **Note**: Openarrays can only be used for parameters.
 
-Often fixed size arrays turn out to be too inflexible; procedures should
-be able to deal with arrays of different sizes. The `openarray`:idx: type
-allows this. Openarrays are always indexed with an ``int`` starting at
-position 0. The ``len``, ``low`` and ``high`` operations are available
-for open arrays too. Any array with a compatible base type can be passed to
-an openarray parameter, the index type does not matter.
+Often fixed size arrays turn out to be too inflexible; procedures should be
+able to deal with arrays of different sizes. The `openarray`:idx: type allows
+this. Openarrays are always indexed with an ``int`` starting at position 0.
+The `len <system.html#len,TOpenArray>`_, `low <system.html#low>`_ and `high
+<system.html#high>`_ operations are available for open arrays too.  Any array
+with a compatible base type can be passed to an openarray parameter, the index
+type does not matter.
 
 The openarray type cannot be nested: multidimensional openarrays are not
 supported because this is seldom needed and cannot be done efficiently.
@@ -1312,8 +1323,9 @@ type conversions in this context:
   # is transformed by the compiler to:
   myWriteln(stdout, [$123, $"def", $4.0])
 
-In this example ``$`` is applied to any argument that is passed to the 
-parameter ``a``. Note that ``$`` applied to strings is a nop.
+In this example `$ <system.html#$>`_ is applied to any argument that is passed
+to the parameter ``a``. Note that `$ <system.html#$>`_ applied to strings is a
+nop.
 
 
 Slices
@@ -1392,11 +1404,12 @@ having the same field types.
 
 Tuples can be *unpacked* during variable assignment (and only then!). This can
 be handy to assign directly the fields of the tuples to individually named
-variables. An example of this is the ``splitFile`` proc from the `os module
-<os.html>`_ which returns the directory, name and extension of a path at the
-same time. For tuple unpacking to work you have to use parenthesis around the
-values you want to assign the unpacking to, otherwise you will be assigning the
-same value to all the individual variables! Example:
+variables. An example of this is the `splitFile <os.html#splitFile>`_ proc
+from the `os module <os.html>`_ which returns the directory, name and
+extension of a path at the same time. For tuple unpacking to work you have to
+use parenthesis around the values you want to assign the unpacking to,
+otherwise you will be assigning the same value to all the individual
+variables! Example:
 
 .. code-block:: nimrod
 
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 1e23618e0..582a6b3e4 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -23,11 +23,13 @@ features.**
 
 Pragmas
 =======
+
 Pragmas are Nimrod's method to give the compiler additional information/
-commands without introducing a massive number of new keywords. Pragmas are 
-enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial 
-does not cover pragmas. See the `manual <manual.html>`_ 
-or `user guide <nimrodc.html>`_ for a description of the available pragmas.
+commands without introducing a massive number of new keywords. Pragmas are
+enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial
+does not cover pragmas. See the `manual <manual.html#pragmas>`_ or `user guide
+<nimrodc.html#additional-features>`_ for a description of the available
+pragmas.
 
 
 Object Oriented Programming
@@ -421,9 +423,10 @@ the rest of the procedure - that is not within a ``finally`` clause -
 is not executed (if an exception occurs).
 
 If you need to *access* the actual exception object or message inside an
-``except`` branch you can use the getCurrentException() and
-getCurrentExceptionMsg() procs from the `system <system.html>`_ module.
-Example:
+``except`` branch you can use the `getCurrentException()
+<system.html#getCurrentException>`_ and `getCurrentExceptionMsg()
+<system.html#getCurrentExceptionMsg>`_ procs from the `system <system.html>`_
+module.  Example:
 
 .. code-block:: nimrod
   try:
@@ -435,48 +438,6 @@ Example:
     echo "Got exception ", repr(e), " with message ", msg
 
 
-Exception hierarchy
--------------------
-
-If you want to create your own exceptions you can inherit from E_Base, but you
-can also inherit from one of the existing exceptions if they fit your purpose.
-The exception tree is::
-
-  * E_Base
-    * EAsynch
-      * EControlC
-    * ESynch
-      * ESystem
-        * EIO
-        * EOS
-          * EInvalidLibrary
-      * EResourceExhausted
-      * EOutOfMemory
-      * EStackOverflow
-    * EArithmetic
-      * EDivByZero
-      * EOverflow
-    * EAccessViolation
-    * EAssertionFailed
-    * EInvalidValue
-      * EInvalidKey
-    * EInvalidIndex
-    * EInvalidField
-    * EOutOfRange
-    * ENoExceptionToReraise
-    * EInvalidObjectAssignment
-    * EInvalidObjectConversion
-    * EFloatingPoint
-      * EFloatInvalidOp
-      * EFloatDivByZero
-      * EFloatOverflow
-      * EFloatUnderflow
-      * EFloatInexact
-    * EDeadThread
-
-See the `system <system.html>`_ module for a description of each exception.
-
-
 Annotating procs with raised exceptions
 ---------------------------------------
 
@@ -663,8 +624,8 @@ statement:
   declareInNewScope(b, int)
   b = 42  # does not work, `b` is unknown
 
-(The manual explains why the ``immediate`` pragma is needed for these 
-templates.)
+(The `manual explains <manual.html#ordinary-vs-immediate-templates>`_  why the
+``immediate`` pragma is needed for these templates.)
 
 If there is a ``stmt`` parameter it should be the last in the template
 declaration. The reason is that statements can be passed to a template
diff --git a/examples/0mq/client.nim b/examples/0mq/client.nim
deleted file mode 100644
index e75e5c7a2..000000000
--- a/examples/0mq/client.nim
+++ /dev/null
@@ -1,14 +0,0 @@
-import zmq
-
-var connection = zmq.open("tcp://localhost:5555", server=false)
-
-echo("Connecting...")
-
-for i in 0..10:
-  echo("Sending hello...", i)
-  send(connection, "Hello")
-  
-  var reply = receive(connection)
-  echo("Received ...", reply)
-
-close(connection)
diff --git a/examples/0mq/server.nim b/examples/0mq/server.nim
deleted file mode 100644
index 0fadf8b97..000000000
--- a/examples/0mq/server.nim
+++ /dev/null
@@ -1,11 +0,0 @@
-import zmq
-
-var connection = zmq.open("tcp://*:5555", server=true)
-
-while True:
-  var request = receive(connection)
-  echo("Received: ", request)
-  send(connection, "World")
-  
-close(connection)
-
diff --git a/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj
index 36b43d31b..71cebc18a 100644
--- a/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj
+++ b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj
@@ -13,7 +13,7 @@
 		D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424A15BC87B6005EFF20 /* AppDelegate.m */; };
 		D531424E15BC87B6005EFF20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424B15BC87B6005EFF20 /* main.m */; };
 		D531427215BC94B1005EFF20 /* backend.m in Sources */ = {isa = PBXBuildFile; fileRef = D531426F15BC94B1005EFF20 /* backend.m */; };
-		D531427415BC94B1005EFF20 /* system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* system.m */; };
+		D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* stdlib_system.m */; };
 		D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5B6F94615FA8D4C0084A85B /* NRViewController.m */; };
 /* End PBXBuildFile section */
 
@@ -30,7 +30,7 @@
 		D531426715BC91EF005EFF20 /* tags.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = tags.sh; path = scripts/tags.sh; sourceTree = "<group>"; };
 		D531426815BC91EF005EFF20 /* xcode_prebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = xcode_prebuild.sh; path = scripts/xcode_prebuild.sh; sourceTree = "<group>"; };
 		D531426F15BC94B1005EFF20 /* backend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = backend.m; path = build/nimcache/backend.m; sourceTree = "<group>"; };
-		D531427115BC94B1005EFF20 /* system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = system.m; path = build/nimcache/system.m; sourceTree = "<group>"; };
+		D531427115BC94B1005EFF20 /* stdlib_system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = stdlib_system.m; path = build/nimcache/stdlib_system.m; sourceTree = "<group>"; };
 		D592E19015C7120F005258EA /* backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = backend.h; path = build/nimcache/backend.h; sourceTree = "<group>"; };
 		D592E19115C71415005258EA /* nimbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nimbase.h; path = build/nimcache/nimbase.h; sourceTree = "<group>"; };
 		D5B6F94515FA8D4C0084A85B /* NRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NRViewController.h; path = src/NRViewController.h; sourceTree = "<group>"; };
@@ -135,7 +135,7 @@
 				D592E19015C7120F005258EA /* backend.h */,
 				D531426F15BC94B1005EFF20 /* backend.m */,
 				D592E19115C71415005258EA /* nimbase.h */,
-				D531427115BC94B1005EFF20 /* system.m */,
+				D531427115BC94B1005EFF20 /* stdlib_system.m */,
 			);
 			name = nimrod;
 			sourceTree = "<group>";
@@ -229,7 +229,7 @@
 				D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */,
 				D531424E15BC87B6005EFF20 /* main.m in Sources */,
 				D531427215BC94B1005EFF20 /* backend.m in Sources */,
-				D531427415BC94B1005EFF20 /* system.m in Sources */,
+				D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */,
 				D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -259,11 +259,7 @@
 				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
-				OTHER_LDFLAGS = (
-					"-weak_library",
-					/usr/lib/libSystem.B.dylib,
-				);
+				IPHONEOS_DEPLOYMENT_TARGET = 4.3;
 				SDKROOT = iphoneos;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};
@@ -284,12 +280,8 @@
 				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.3;
 				OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
-				OTHER_LDFLAGS = (
-					"-weak_library",
-					/usr/lib/libSystem.B.dylib,
-				);
 				SDKROOT = iphoneos;
 				TARGETED_DEVICE_FAMILY = "1,2";
 				VALIDATE_PRODUCT = YES;
diff --git a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh
index c6d38f164..90bafd74e 100644
--- a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh
+++ b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh
@@ -22,7 +22,7 @@ DEST_NIMBASE=build/nimcache/nimbase.h
 if [ -d src ]
 then
 	$PATH_TO_NIMROD objc --noMain  --app:lib \
-		--nimcache:build/nimcache --compileOnly \
+		--nimcache:./build/nimcache --compileOnly \
 		--header --cpu:i386 ../nimrod_backend/backend.nim
 	if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ]
 	then
diff --git a/install.txt b/install.txt
index 2883c8495..4543e4ece 100644
--- a/install.txt
+++ b/install.txt
@@ -58,8 +58,6 @@ Currently, the following C compilers are supported under Windows:
   | http://www.mingw.org/download.shtml
 - | LLVM with Clang or GNU C/C++ frontend
   | http://llvm.org/releases/download.html
-- | Digital Mars C++
-  | http://www.digitalmars.com/download/freecompiler.html
 
 However, most testing is done with GCC.
 
diff --git a/koch.nim b/koch.nim
index dff6ede98..293ffb148 100644
--- a/koch.nim
+++ b/koch.nim
@@ -43,7 +43,7 @@ Possible Commands:
   web                      generates the website
   csource [options]        builds the C sources for installation
   zip                      builds the installation ZIP package
-  inno [options]           builds the Inno Setup installer (for Windows)
+  nsis [options]           builds the NSIS Setup installer (for Windows)
   tests [options]          run the testsuite
   update                   updates nimrod to the latest version from github
                            (compile koch with -d:withUpdate to enable)
@@ -77,6 +77,14 @@ proc tryExec(cmd: string): bool =
   echo(cmd)
   result = execShellCmd(cmd) == 0
 
+proc safeRemove(filename: string) =
+  if existsFile(filename): removeFile(filename)
+
+proc copyExe(source, dest: string) =
+  safeRemove(dest)
+  copyFile(dest=dest, source=source)
+  inclFilePermissions(dest, {fpUserExec})
+
 const
   compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
 
@@ -84,23 +92,28 @@ proc csource(args: string) =
   exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" %
        [args, NimrodVersion, compileNimInst, findNim()])
 
-proc zip(args: string) = 
-  exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" %
+proc zip(args: string) =
+  exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nimrod.ini" %
        [NimrodVersion, compileNimInst, findNim()])
+  exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nimrod.ini" %
+       ["tools/niminst/niminst".exe, NimrodVersion])
   
 proc buildTool(toolname, args: string) = 
   exec("$# cc $# $#" % [findNim(), args, toolname])
   copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
 
-proc inno(args: string) =
+proc nsis(args: string) =
   # make sure we have generated the niminst executables:
   buildTool("tools/niminst/niminst", args)
   buildTool("tools/nimgrep", args)
-  exec("tools" / "niminst" / "niminst --var:version=$# inno compiler/nimrod" % 
-       NimrodVersion)
+  # produce 'nimrod_debug.exe':
+  exec "nimrod c compiler" / "nimrod.nim"
+  copyExe("compiler/nimrod".exe, "bin/nimrod_debug".exe)
+  exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" &
+        " nsis compiler/nimrod") % NimrodVersion)
 
 proc install(args: string) = 
-  exec("$# cc -r $# --var:version=$# scripts compiler/nimrod.ini" %
+  exec("$# cc -r $# --var:version=$# --var:mingw=mingw32 scripts compiler/nimrod.ini" %
        [findNim(), compileNimInst, NimrodVersion])
   exec("sh ./install.sh $#" % args)
 
@@ -135,16 +148,8 @@ proc findStartNimrod: string =
   echo("Found no nimrod compiler and every attempt to build one failed!")
   quit("FAILURE")
 
-proc safeRemove(filename: string) = 
-  if existsFile(filename): removeFile(filename)
-
 proc thVersion(i: int): string = 
   result = ("compiler" / "nimrod" & $i).exe
-
-proc copyExe(source, dest: string) =
-  safeRemove(dest)
-  copyFile(dest=dest, source=source)
-  inclFilePermissions(dest, {fpUserExec})
   
 proc boot(args: string) =
   var output = "compiler" / "nimrod".exe
@@ -302,7 +307,7 @@ of cmdArgument:
   of "web": web(op.cmdLineRest)
   of "csource", "csources": csource(op.cmdLineRest)
   of "zip": zip(op.cmdLineRest)
-  of "inno": inno(op.cmdLineRest)
+  of "nsis": nsis(op.cmdLineRest)
   of "install": install(op.cmdLineRest)
   of "test", "tests": tests(op.cmdLineRest)
   of "update": 
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 334a4b8c7..455f99c9e 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -620,6 +620,8 @@ proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
     someProc[high(someProc)] = val
   else:
     badNodeKind someProc.kind, "body=" 
+
+proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.}
   
 
 proc `$`*(node: PNimrodNode): string {.compileTime.} =
@@ -627,7 +629,9 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
   case node.kind
   of nnkIdent:
     result = $node.ident
-  of nnkStrLit:
+  of nnkPostfix:
+    result = $node.basename.ident & "*"
+  of nnkStrLit..nnkTripleStrLit:
     result = node.strVal
   else: 
     badNodeKind node.kind, "$"
@@ -669,7 +673,7 @@ proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
       a[i + 1] = a[i]
     a[pos] = b
 
-proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.} =
+proc basename*(a: PNimrodNode): PNimrodNode =
   ## Pull an identifier from prefix/postfix expressions
   case a.kind
   of nnkIdent: return a
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 57e11664b..8df1b3dfb 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -102,7 +102,7 @@ proc newAny(value: pointer, rawType: PNimType): TAny =
   result.value = value
   result.rawType = rawType
 
-when defined(system.TVarSlot):
+when declared(system.TVarSlot):
   proc toAny*(x: TVarSlot): TAny {.inline.} =
     ## constructs a ``TAny`` object from a variable slot ``x``. 
     ## This captures `x`'s address, so `x` can be modified with its
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
index eec4daf00..ce48a32ed 100644
--- a/lib/impure/db_mysql.nim
+++ b/lib/impure/db_mysql.nim
@@ -57,7 +57,8 @@ when false:
       binding: seq[MYSQL_BIND]
     discard mysql_stmt_close(stmt)
 
-proc dbQuote(s: string): string =
+proc dbQuote*(s: string): string =
+  ## DB quotes the string.
   result = "'"
   for c in items(s):
     if c == '\'': add(result, "''")
@@ -69,7 +70,10 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
   var a = 0
   for c in items(string(formatstr)):
     if c == '?':
-      add(result, dbQuote(args[a]))
+      if args[a] == nil:
+        add(result, "NULL")
+      else:
+        add(result, dbQuote(args[a]))
       inc(a)
     else: 
       add(result, c)
@@ -115,7 +119,10 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
       if row == nil: break
       for i in 0..L-1: 
         setLen(result[i], 0)
-        add(result[i], row[i])
+        if row[i] == nil:
+          result[i] = nil
+        else:
+          add(result[i], row[i])
       yield result
     properFreeResult(sqlres, row)
 
@@ -132,7 +139,10 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
     if row != nil: 
       for i in 0..L-1: 
         setLen(result[i], 0)
-        add(result[i], row[i])
+        if row[i] == nil:
+          result[i] = nil
+        else:
+          add(result[i], row[i])
     properFreeResult(sqlres, row)
 
 proc getAllRows*(db: TDbConn, query: TSqlQuery, 
@@ -150,7 +160,11 @@ proc getAllRows*(db: TDbConn, query: TSqlQuery,
       if row == nil: break
       setLen(result, j+1)
       newSeq(result[j], L)
-      for i in 0..L-1: result[j][i] = $row[i]
+      for i in 0..L-1:
+        if row[i] == nil:
+          result[j][i] = nil
+        else:
+          result[j][i] = $row[i]
       inc(j)
     mysql.FreeResult(sqlres)
 
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
index f6ae93303..510cb8e45 100644
--- a/lib/impure/db_postgres.nim
+++ b/lib/impure/db_postgres.nim
@@ -19,12 +19,13 @@ type
   EDb* = object of EIO ## exception that is raised if a database error occurs
   
   TSqlQuery* = distinct string ## an SQL query string
+  TSqlPrepared* = distinct string ## a identifier for the prepared queries
 
   FDb* = object of FIO ## effect that denotes a database operation
   FReadDb* = object of FDB   ## effect that denotes a read operation
   FWriteDb* = object of FDB  ## effect that denotes a write operation
-  
-proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
+
+proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
   ## constructs a TSqlQuery from the string `query`. This is supposed to be 
   ## used as a raw-string-literal modifier:
   ## ``sql"update user set counter = counter + 1"``
@@ -33,21 +34,22 @@ proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
   ## on, later versions will check the string for valid syntax.
   result = TSqlQuery(query)
  
-proc dbError(db: TDbConn) {.noreturn.} = 
+proc dbError*(db: TDbConn) {.noreturn.} =
   ## raises an EDb exception.
   var e: ref EDb
   new(e)
   e.msg = $PQerrorMessage(db)
   raise e
 
-proc dbError*(msg: string) {.noreturn.} = 
+proc dbError*(msg: string) {.noreturn.} =
   ## raises an EDb exception with message `msg`.
   var e: ref EDb
   new(e)
   e.msg = msg
   raise e
 
-proc dbQuote(s: string): string =
+proc dbQuote*(s: string): string =
+  ## DB quotes the string.
   result = "'"
   for c in items(s):
     if c == '\'': add(result, "''")
@@ -59,43 +61,78 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
   var a = 0
   for c in items(string(formatstr)):
     if c == '?':
-      add(result, dbQuote(args[a]))
+      if args[a] == nil:
+        add(result, "NULL")
+      else:
+        add(result, dbQuote(args[a]))
       inc(a)
-    else: 
+    else:
       add(result, c)
   
-proc tryExec*(db: TDbConn, query: TSqlQuery, 
+proc tryExec*(db: TDbConn, query: TSqlQuery,
               args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
+  var arr = allocCStringArray(args)
+  var res = PQexecParams(db, query.string, int32(args.len), nil, arr,
+                        nil, nil, 0)
+  deallocCStringArray(arr)
   result = PQresultStatus(res) == PGRES_COMMAND_OK
   PQclear(res)
 
 proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
   tags: [FReadDB, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
+  var arr = allocCStringArray(args)
+  var res = PQexecParams(db, query.string, int32(args.len), nil, arr,
+                        nil, nil, 0)
+  deallocCStringArray(arr)
   if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
   PQclear(res)
-  
+
+proc exec*(db: TDbConn, stmtName: TSqlPrepared,
+          args: varargs[string]) {.tags: [FReadDB, FWriteDb].} =
+  var arr = allocCStringArray(args)
+  var res = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
+                           nil, nil, 0)
+  deallocCStringArray(arr)
+  if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
+  PQclear(res)
+
 proc newRow(L: int): TRow =
   newSeq(result, L)
   for i in 0..L-1: result[i] = ""
   
-proc setupQuery(db: TDbConn, query: TSqlQuery, 
-                args: varargs[string]): PPGresult = 
-  var q = dbFormat(query, args)
-  result = PQExec(db, q)
-  if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db)
-  
+proc setupQuery(db: TDbConn, query: TSqlQuery,
+                args: varargs[string]): PPGresult =
+  var arr = allocCStringArray(args)
+  result = PQexecParams(db, query.string, int32(args.len), nil, arr,
+                        nil, nil, 0)
+  deallocCStringArray(arr)
+  if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
+
+proc setupQuery(db: TDbConn, stmtName: TSqlPrepared,
+                 args: varargs[string]): PPGresult =
+  var arr = allocCStringArray(args)
+  result = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
+                          nil, nil, 0)
+  deallocCStringArray(arr)
+  if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
+
+proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery;
+              nParams: int): TSqlPrepared =
+  var res = PQprepare(db, stmtName, query.string, int32(nParams), nil)
+  if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
+  return TSqlPrepared(stmtName)
+   
 proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
   for col in 0..cols-1:
     setLen(r[col], 0)
     var x = PQgetvalue(res, line, col)
-    add(r[col], x)
-  
+    if x == nil:
+      r[col] = nil
+    else:
+      add(r[col], x)
+
 iterator fastRows*(db: TDbConn, query: TSqlQuery,
                    args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## executes the query and iterates over the result dataset. This is very 
@@ -109,6 +146,17 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
     yield result
   PQclear(res)
 
+iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared,
+                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+  ## executes the prepared query and iterates over the result dataset.
+  var res = setupQuery(db, stmtName, args)
+  var L = PQnfields(res)
+  var result = newRow(L)
+  for i in 0..PQntuples(res)-1:
+    setRow(res, result, i, L)
+    yield result
+  PQclear(res)
+
 proc getRow*(db: TDbConn, query: TSqlQuery,
              args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## retrieves a single row. If the query doesn't return any rows, this proc
@@ -119,40 +167,55 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
   setRow(res, result, 0, L)
   PQclear(res)
 
-proc getAllRows*(db: TDbConn, query: TSqlQuery, 
+proc getRow*(db: TDbConn, stmtName: TSqlPrepared,
+              args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+    var res = setupQuery(db, stmtName, args)
+    var L = PQnfields(res)
+    result = newRow(L)
+    setRow(res, result, 0, L)
+    PQclear(res)
+
+proc getAllRows*(db: TDbConn, query: TSqlQuery,
                  args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
   for r in FastRows(db, query, args):
     result.add(r)
 
-iterator rows*(db: TDbConn, query: TSqlQuery, 
+proc getAllRows*(db: TDbConn, stmtName: TSqlPrepared,
+                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
+  ## executes the prepared query and returns the whole result dataset.
+  result = @[]
+  for r in FastRows(db, stmtName, args):
+    result.add(r)
+
+iterator rows*(db: TDbConn, query: TSqlQuery,
                args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## same as `FastRows`, but slower and safe.
   for r in items(GetAllRows(db, query, args)): yield r
 
-proc getValue*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
+proc getValue*(db: TDbConn, query: TSqlQuery,
+               args: varargs[string, `$`]): string {.tags: [FReadDB].} =
   ## executes the query and returns the first column of the first row of the
   ## result dataset. Returns "" if the dataset contains no rows or the database
   ## value is NULL.
   var x = PQgetvalue(setupQuery(db, query, args), 0, 0)
   result = if isNil(x): "" else: $x
   
-proc tryInsertID*(db: TDbConn, query: TSqlQuery, 
+proc tryInsertID*(db: TDbConn, query: TSqlQuery,
                   args: varargs[string, `$`]): int64  {.tags: [FWriteDb].}=
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row or -1 in case of an error. For Postgre this adds
   ## ``RETURNING id`` to the query, so it only works if your primary key is
   ## named ``id``. 
-  var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), 
+  var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"),
     args), 0, 0)
   if not isNil(x):
     result = ParseBiggestInt($x)
   else:
     result = -1
 
-proc insertID*(db: TDbConn, query: TSqlQuery, 
+proc insertID*(db: TDbConn, query: TSqlQuery,
                args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row. For Postgre this adds
@@ -161,9 +224,9 @@ proc insertID*(db: TDbConn, query: TSqlQuery,
   result = TryInsertID(db, query, args)
   if result < 0: dbError(db)
   
-proc execAffectedRows*(db: TDbConn, query: TSqlQuery, 
+proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
                        args: varargs[string, `$`]): int64 {.tags: [
-                       FReadDB, FWriteDb].} = 
+                       FReadDB, FWriteDb].} =
   ## executes the query (typically "UPDATE") and returns the
   ## number of affected rows.
   var q = dbFormat(query, args)
@@ -172,7 +235,7 @@ proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
   result = parseBiggestInt($PQcmdTuples(res))
   PQclear(res)
 
-proc close*(db: TDbConn) {.tags: [FDb].} = 
+proc close*(db: TDbConn) {.tags: [FDb].} =
   ## closes the database connection.
   if db != nil: PQfinish(db)
 
diff --git a/lib/impure/fenv.nim b/lib/impure/fenv.nim
new file mode 100644
index 000000000..9d7c8809b
--- /dev/null
+++ b/lib/impure/fenv.nim
@@ -0,0 +1,113 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Floating-point environment. Handling of floating-point rounding and
+## exceptions (overflow, zero-devide, etc.).
+
+{.deadCodeElim:on.}
+
+when defined(Posix) and not defined(haiku):
+  {.passl: "-lm".}
+
+var
+  FE_DIVBYZERO* {.importc, header: "<fenv.h>".}: cint
+    ## division by zero
+  FE_INEXACT* {.importc, header: "<fenv.h>".}: cint
+    ## inexact result
+  FE_INVALID* {.importc, header: "<fenv.h>".}: cint
+    ## invalid operation
+  FE_OVERFLOW* {.importc, header: "<fenv.h>".}: cint
+    ## result not representable due to overflow
+  FE_UNDERFLOW* {.importc, header: "<fenv.h>".}: cint
+    ## result not representable due to underflow
+  FE_ALL_EXCEPT* {.importc, header: "<fenv.h>".}: cint
+    ## bitwise OR of all supported exceptions
+  FE_DOWNWARD* {.importc, header: "<fenv.h>".}: cint
+    ## round toward -Inf
+  FE_TONEAREST* {.importc, header: "<fenv.h>".}: cint
+    ## round to nearest
+  FE_TOWARDZERO* {.importc, header: "<fenv.h>".}: cint
+    ## round toward 0
+  FE_UPWARD* {.importc, header: "<fenv.h>".}: cint
+    ## round toward +Inf
+  FE_DFL_ENV* {.importc, header: "<fenv.h>".}: cint
+    ## macro of type pointer to fenv_t to be used as the argument
+    ## to functions taking an argument of type fenv_t; in this
+    ## case the default environment will be used
+
+type
+  TFloatClass* = enum ## describes the class a floating point value belongs to.
+                      ## This is the type that is returned by `classify`.
+    fcNormal,    ## value is an ordinary nonzero floating point value
+    fcSubnormal, ## value is a subnormal (a very small) floating point value
+    fcZero,      ## value is zero
+    fcNegZero,   ## value is the negative zero
+    fcNan,       ## value is Not-A-Number (NAN)
+    fcInf,       ## value is positive infinity
+    fcNegInf     ## value is negative infinity
+
+  Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} =
+    object ## Represents the entire floating-point environment. The
+           ## floating-point environment refers collectively to any
+           ## floating-point status flags and control modes supported
+           ## by the implementation.
+  Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} =
+    object ## Represents the floating-point status flags collectively,
+           ## including any status the implementation associates with the
+           ## flags. A floating-point status flag is a system variable
+           ## whose value is set (but never cleared) when a floating-point
+           ## exception is raised, which occurs as a side effect of
+           ## exceptional floating-point arithmetic to provide auxiliary
+           ## information. A floating-point control mode is a system variable
+           ## whose value may be set by the user to affect the subsequent
+           ## behavior of floating-point arithmetic.
+
+proc feclearexcept*(excepts: cint): cint {.importc, header: "<fenv.h>".}
+  ## Clear the supported exceptions represented by `excepts`.
+
+proc fegetexceptflag*(flagp: ptr Tfexcept, excepts: cint): cint {.
+  importc, header: "<fenv.h>".}
+  ## Store implementation-defined representation of the exception flags
+  ## indicated by `excepts` in the object pointed to by `flagp`.
+
+proc feraiseexcept*(excepts: cint): cint {.importc, header: "<fenv.h>".}
+  ## Raise the supported exceptions represented by `excepts`.
+
+proc fesetexceptflag*(flagp: ptr Tfexcept, excepts: cint): cint {.
+  importc, header: "<fenv.h>".}
+  ## Set complete status for exceptions indicated by `excepts` according to
+  ## the representation in the object pointed to by `flagp`.
+
+proc fetestexcept*(excepts: cint): cint {.importc, header: "<fenv.h>".}
+  ## Determine which of subset of the exceptions specified by `excepts` are
+  ## currently set.
+
+proc fegetround*(): cint {.importc, header: "<fenv.h>".}
+  ## Get current rounding direction.
+
+proc fesetround*(roundingDirection: cint): cint {.importc, header: "<fenv.h>".}
+  ## Establish the rounding direction represented by `roundingDirection`.
+
+proc fegetenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
+  ## Store the current floating-point environment in the object pointed
+  ## to by `envp`.
+
+proc feholdexcept*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
+  ## Save the current environment in the object pointed to by `envp`, clear
+  ## exception flags and install a non-stop mode (if available) for all
+  ## exceptions.
+
+proc fesetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
+  ## Establish the floating-point environment represented by the object
+  ## pointed to by `envp`.
+
+proc feupdateenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
+  ## Save current exceptions in temporary storage, install environment
+  ## represented by object pointed to by `envp` and raise exceptions
+  ## according to saved exceptions.
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index f6511dab4..ac07b2d6b 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -243,7 +243,7 @@ template `=~` *(s: string, pattern: TRegex): expr =
   ##     echo("syntax error")
   ##
   bind maxSubPatterns
-  when not definedInScope(matches):
+  when not declaredInScope(matches):
     var matches {.inject.}: array[0..MaxSubpatterns-1, string]
   match(s, pattern, matches)
 
diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim
index 1726449d8..b9f89dda0 100644
--- a/lib/impure/zipfiles.nim
+++ b/lib/impure/zipfiles.nim
@@ -56,6 +56,8 @@ proc addFile*(z: var TZipArchive, dest, src: string) =
   ## Adds the file `src` to the archive `z` with the name `dest`. `dest`
   ## may contain a path that will be created. 
   assert(z.mode != fmRead) 
+  if not fileExists(src):
+    raise newException(EIO, "File '" & src & "' does not exist")
   var zipsrc = zip_source_file(z.w, src, 0, -1)
   if zipsrc == nil:
     #echo("Dest: " & dest)
diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim
index 80fbf3a51..ff371f4e1 100644
--- a/lib/packages/docutils/highlite.nim
+++ b/lib/packages/docutils/highlite.nim
@@ -50,7 +50,7 @@ const
     "break", "case", "cast", "const", "continue", "converter", "discard",
     "distinct", "div", "do", "elif", "else", "end", "enum", "except", "export",
     "finally", "for", "from", "generic", "if", "import", "in", "include",
-    "interface", "is", "isnot", "iterator", "lambda", "let", "macro", "method",
+    "interface", "is", "isnot", "iterator", "let", "macro", "method",
     "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc",
     "ptr", "raise", "ref", "return", "shl", "shr", "static",
     "template", "try", "tuple", "type", "using", "var", "when", "while", "with",
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index a5ee05abb..9334ceeae 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -99,22 +99,6 @@ type
     l_pid*: TPid      ## Process ID of the process holding the lock;
                       ## returned with F_GETLK.
 
-  Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} =
-    object ## Represents the entire floating-point environment. The
-           ## floating-point environment refers collectively to any
-           ## floating-point status flags and control modes supported
-           ## by the implementation.
-  Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} =
-    object ## Represents the floating-point status flags collectively,
-           ## including any status the implementation associates with the
-           ## flags. A floating-point status flag is a system variable
-           ## whose value is set (but never cleared) when a floating-point
-           ## exception is raised, which occurs as a side effect of
-           ## exceptional floating-point arithmetic to provide auxiliary
-           ## information. A floating-point control mode is a system variable
-           ## whose value may be set by the user to affect the subsequent
-           ## behavior of floating-point arithmetic.
-
   TFTW* {.importc: "struct FTW", header: "<ftw.h>", final, pure.} = object
     base*: cint
     level*: cint
@@ -834,18 +818,6 @@ var
     ## The application expects to access the specified data once and
     ## then not reuse it thereafter.
 
-  FE_DIVBYZERO* {.importc, header: "<fenv.h>".}: cint
-  FE_INEXACT* {.importc, header: "<fenv.h>".}: cint
-  FE_INVALID* {.importc, header: "<fenv.h>".}: cint
-  FE_OVERFLOW* {.importc, header: "<fenv.h>".}: cint
-  FE_UNDERFLOW* {.importc, header: "<fenv.h>".}: cint
-  FE_ALL_EXCEPT* {.importc, header: "<fenv.h>".}: cint
-  FE_DOWNWARD* {.importc, header: "<fenv.h>".}: cint
-  FE_TONEAREST* {.importc, header: "<fenv.h>".}: cint
-  FE_TOWARDZERO* {.importc, header: "<fenv.h>".}: cint
-  FE_UPWARD* {.importc, header: "<fenv.h>".}: cint
-  FE_DFL_ENV* {.importc, header: "<fenv.h>".}: cint
-
 when not defined(haiku) and not defined(OpenBSD):
   var
     MM_HARD* {.importc, header: "<fmtmsg.h>".}: cint
@@ -1579,6 +1551,16 @@ var
   MSG_OOB* {.importc, header: "<sys/socket.h>".}: cint
     ## Out-of-band data.
 
+
+when defined(linux):
+  var
+    MAP_POPULATE* {.importc, header: "<sys/mman.h>".}: cint
+      ## Populate (prefault) page tables for a mapping.
+else:
+  var
+    MAP_POPULATE*: cint = 0
+
+
 when defined(macosx):
   var
     MSG_HAVEMORE* {.importc, header: "<sys/socket.h>".}: cint
@@ -1811,20 +1793,6 @@ proc posix_fadvise*(a1: cint, a2, a3: TOff, a4: cint): cint {.
 proc posix_fallocate*(a1: cint, a2, a3: TOff): cint {.
   importc, header: "<fcntl.h>".}
 
-proc feclearexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
-proc fegetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.
-  importc, header: "<fenv.h>".}
-proc feraiseexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
-proc fesetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.
-  importc, header: "<fenv.h>".}
-proc fetestexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
-proc fegetround*(): cint {.importc, header: "<fenv.h>".}
-proc fesetround*(a1: cint): cint {.importc, header: "<fenv.h>".}
-proc fegetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
-proc feholdexcept*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
-proc fesetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
-proc feupdateenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
-
 when not defined(haiku) and not defined(OpenBSD):
   proc fmtmsg*(a1: int, a2: cstring, a3: cint,
               a4, a5, a6: cstring): cint {.importc, header: "<fmtmsg.h>".}
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index d410f8ce1..0ea8ef43b 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -9,7 +9,7 @@
 
 include "system/inclrtl"
 
-import os, oids, tables, strutils, macros
+import os, oids, tables, strutils, macros, times
 
 import rawsockets, net
 
@@ -27,12 +27,12 @@ export TPort, TSocketFlags
 ## **Note:** This module is still largely experimental.
 
 
-# TODO: Discarded void PFutures need to be checked for exception.
 # TODO: ``except`` statement (without `try`) does not work.
 # TODO: Multiple exception names in a ``except`` don't work.
 # TODO: The effect system (raises: []) has trouble with my try transformation.
 # TODO: Can't await in a 'except' body
 # TODO: getCurrentException(Msg) don't work
+# TODO: Check if yielded future is nil and throw a more meaningful exception
 
 # -- Futures
 
@@ -41,27 +41,41 @@ type
     cb: proc () {.closure,gcsafe.}
     finished: bool
     error*: ref EBase
-    stackTrace: string ## For debugging purposes only.
+    errorStackTrace*: string
+    when not defined(release):
+      stackTrace: string ## For debugging purposes only.
+      id: int
+      fromProc: string
 
   PFuture*[T] = ref object of PFutureBase
     value: T
 
-proc newFuture*[T](): PFuture[T] =
+var currentID* = 0
+proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] =
   ## Creates a new future.
+  ##
+  ## Specifying ``fromProc``, which is a string specifying the name of the proc
+  ## that this future belongs to, is a good habit as it helps with debugging.
   new(result)
   result.finished = false
-  result.stackTrace = getStackTrace()
+  when not defined(release):
+    result.stackTrace = getStackTrace()
+    result.id = currentID
+    result.fromProc = fromProc
+    currentID.inc()
 
 proc checkFinished[T](future: PFuture[T]) =
-  if future.finished:
-    echo("<----->")
-    echo(future.stackTrace)
-    echo("-----")
-    when T is string:
-      echo("Contents: ", future.value.repr)
-    echo("<----->")
-    echo("Future already finished, cannot finish twice.")
-    assert false
+  when not defined(release):
+    if future.finished:
+      echo("<-----> ", future.id, " ", future.fromProc)
+      echo(future.stackTrace)
+      echo("-----")
+      when T is string:
+        echo("Contents: ", future.value.repr)
+      echo("<----->")
+      echo("Future already finished, cannot finish twice.")
+      echo getStackTrace()
+      assert false
 
 proc complete*[T](future: PFuture[T], val: T) =
   ## Completes ``future`` with value ``val``.
@@ -88,6 +102,8 @@ proc fail*[T](future: PFuture[T], error: ref EBase) =
   checkFinished(future)
   future.finished = true
   future.error = error
+  future.errorStackTrace =
+    if getStackTrace(error) == "": getStackTrace() else: getStackTrace(error)
   if future.cb != nil:
     future.cb()
   else:
@@ -115,13 +131,24 @@ proc `callback=`*[T](future: PFuture[T],
   ## If future has already completed then ``cb`` will be called immediately.
   future.callback = proc () = cb(future)
 
+proc echoOriginalStackTrace[T](future: PFuture[T]) =
+  # TODO: Come up with something better.
+  when not defined(release):
+    echo("Original stack trace in ", future.fromProc, ":")
+    if not future.errorStackTrace.isNil() and future.errorStackTrace != "":
+      echo(future.errorStackTrace)
+    else:
+      echo("Empty or nil stack trace.")
+
 proc read*[T](future: PFuture[T]): T =
   ## Retrieves the value of ``future``. Future must be finished otherwise
   ## this function will fail with a ``EInvalidValue`` exception.
   ##
   ## If the result of the future is an error then that error will be raised.
   if future.finished:
-    if future.error != nil: raise future.error
+    if future.error != nil:
+      echoOriginalStackTrace(future)
+      raise future.error
     when T isnot void:
       return future.value
   else:
@@ -150,7 +177,44 @@ proc asyncCheck*[T](future: PFuture[T]) =
   ## This should be used instead of ``discard`` to discard void futures.
   future.callback =
     proc () =
-      if future.failed: raise future.error
+      if future.failed:
+        echoOriginalStackTrace(future)
+        raise future.error
+
+proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] =
+  ## Returns a future which will complete once both ``fut1`` and ``fut2``
+  ## complete.
+  var retFuture = newFuture[void]("asyncdispatch.`and`")
+  fut1.callback =
+    proc () =
+      if fut2.finished: retFuture.complete()
+  fut2.callback =
+    proc () =
+      if fut1.finished: retFuture.complete()
+  return retFuture
+
+proc `or`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] =
+  ## Returns a future which will complete once either ``fut1`` or ``fut2``
+  ## complete.
+  var retFuture = newFuture[void]("asyncdispatch.`or`")
+  proc cb() =
+    if not retFuture.finished: retFuture.complete()
+  fut1.callback = cb
+  fut2.callback = cb
+  return retFuture
+
+type
+  PDispatcherBase = ref object of PObject
+    timers: seq[tuple[finishAt: float, fut: PFuture[void]]]
+
+proc processTimers(p: PDispatcherBase) =
+  var oldTimers = p.timers
+  p.timers = @[]
+  for t in oldTimers:
+    if epochTime() >= t.finishAt:
+      t.fut.complete()
+    else:
+      p.timers.add(t)
 
 when defined(windows) or defined(nimdoc):
   import winlean, sets, hashes
@@ -162,7 +226,7 @@ when defined(windows) or defined(nimdoc):
       cb: proc (sock: TAsyncFD, bytesTransferred: DWORD,
                 errcode: TOSErrorCode) {.closure,gcsafe.}
 
-    PDispatcher* = ref object
+    PDispatcher* = ref object of PDispatcherBase
       ioPort: THandle
       handles: TSet[TAsyncFD]
 
@@ -181,6 +245,7 @@ when defined(windows) or defined(nimdoc):
     new result
     result.ioPort = CreateIOCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)
     result.handles = initSet[TAsyncFD]()
+    result.timers = @[]
 
   var gDisp{.threadvar.}: PDispatcher ## Global dispatcher
   proc getGlobalDispatcher*(): PDispatcher =
@@ -207,8 +272,9 @@ when defined(windows) or defined(nimdoc):
   proc poll*(timeout = 500) =
     ## Waits for completion events and processes them.
     let p = getGlobalDispatcher()
-    if p.handles.len == 0:
-      raise newException(EInvalidValue, "No handles registered in dispatcher.")
+    if p.handles.len == 0 and p.timers.len == 0:
+      raise newException(EInvalidValue,
+        "No handles or timers registered in dispatcher.")
     
     let llTimeout =
       if timeout ==  -1: winlean.INFINITE
@@ -242,6 +308,9 @@ when defined(windows) or defined(nimdoc):
           discard
         else: osError(errCode)
 
+    # Timer processing.
+    processTimers(p)
+
   var connectExPtr: pointer = nil
   var acceptExPtr: pointer = nil
   var getAcceptExSockAddrsPtr: pointer = nil
@@ -314,7 +383,7 @@ when defined(windows) or defined(nimdoc):
     ## Returns a ``PFuture`` which will complete when the connection succeeds
     ## or an error occurs.
     verifyPresence(socket)
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("connect")
     # Apparently ``ConnectEx`` expects the socket to be initially bound:
     var saddr: Tsockaddr_in
     saddr.sin_family = int16(toInt(af))
@@ -384,7 +453,7 @@ when defined(windows) or defined(nimdoc):
     #     '\0' in the message currently signifies a socket disconnect. Who
     #     knows what will happen when someone sends that to our socket.
     verifyPresence(socket)
-    var retFuture = newFuture[string]()    
+    var retFuture = newFuture[string]("recv")
     var dataBuf: TWSABuf
     dataBuf.buf = cast[cstring](alloc0(size))
     dataBuf.len = size
@@ -405,7 +474,10 @@ when defined(windows) or defined(nimdoc):
               copyMem(addr data[0], addr dataBuf.buf[0], bytesCount)
               retFuture.complete($data)
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            if flags.isDisconnectionError(errcode):
+              retFuture.complete("")
+            else:
+              retFuture.fail(newException(EOS, osErrorMsg(errcode)))
         if dataBuf.buf != nil:
           dealloc dataBuf.buf
           dataBuf.buf = nil
@@ -459,7 +531,7 @@ when defined(windows) or defined(nimdoc):
     ## Sends ``data`` to ``socket``. The returned future will complete once all
     ## data has been sent.
     verifyPresence(socket)
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("send")
 
     var dataBuf: TWSABuf
     dataBuf.buf = data # since this is not used in a callback, this is fine
@@ -474,7 +546,10 @@ when defined(windows) or defined(nimdoc):
           if errcode == TOSErrorCode(-1):
             retFuture.complete()
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            if flags.isDisconnectionError(errcode):
+              retFuture.complete()
+            else:
+              retFuture.fail(newException(EOS, osErrorMsg(errcode)))
     )
 
     let ret = WSASend(socket.TSocketHandle, addr dataBuf, 1, addr bytesReceived,
@@ -494,15 +569,21 @@ when defined(windows) or defined(nimdoc):
       # free ``ol``.
     return retFuture
 
-  proc acceptAddr*(socket: TAsyncFD): 
+  proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: TAsyncFD]] =
     ## Accepts a new connection. Returns a future containing the client socket
     ## corresponding to that connection and the remote address of the client.
     ## The future will complete when the connection is successfully accepted.
     ##
-    ## The resulting client socket is automatically registered to dispatcher.
+    ## The resulting client socket is automatically registered to the
+    ## dispatcher.
+    ##
+    ## The ``accept`` call may result in an error if the connecting socket
+    ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+    ## flag is specified then this error will not be raised and instead
+    ## accept will be called again.
     verifyPresence(socket)
-    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]()
+    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr")
 
     var clientSock = newRawSocket()
     if clientSock == osInvalidSocket: osError(osLastError())
@@ -534,6 +615,18 @@ when defined(windows) or defined(nimdoc):
          client: clientSock.TAsyncFD)
       )
 
+    template failAccept(errcode): stmt =
+      if flags.isDisconnectionError(errcode):
+        var newAcceptFut = acceptAddr(socket, flags)
+        newAcceptFut.callback =
+          proc () =
+            if newAcceptFut.failed:
+              retFuture.fail(newAcceptFut.readError)
+            else:
+              retFuture.complete(newAcceptFut.read)
+      else:
+        retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+
     var ol = PCustomOverlapped()
     GC_ref(ol)
     ol.data = TCompletionData(sock: socket, cb:
@@ -542,7 +635,7 @@ when defined(windows) or defined(nimdoc):
           if errcode == TOSErrorCode(-1):
             completeAccept()
           else:
-            retFuture.fail(newException(EOS, osErrorMsg(errcode)))
+            failAccept(errcode)
     )
 
     # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
@@ -555,7 +648,7 @@ when defined(windows) or defined(nimdoc):
     if not ret:
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
-        retFuture.fail(newException(EOS, osErrorMsg(err)))
+        failAccept(err)
         GC_unref(ol)
     else:
       completeAccept()
@@ -606,7 +699,7 @@ else:
       readCBs: seq[TCallback]
       writeCBs: seq[TCallback]
 
-    PDispatcher* = ref object
+    PDispatcher* = ref object of PDispatcherBase
       selector: PSelector
 
   proc `==`*(x, y: TAsyncFD): bool {.borrow.}
@@ -614,6 +707,7 @@ else:
   proc newDispatcher*(): PDispatcher =
     new result
     result.selector = newSelector()
+    result.timers = @[]
 
   var gDisp{.threadvar.}: PDispatcher ## Global dispatcher
   proc getGlobalDispatcher*(): PDispatcher =
@@ -693,10 +787,12 @@ else:
       else:
         # FD no longer a part of the selector. Likely been closed
         # (e.g. socket disconnected).
+
+    processTimers(p)
   
   proc connect*(socket: TAsyncFD, address: string, port: TPort,
     af = AF_INET): PFuture[void] =
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("connect")
     
     proc cb(sock: TAsyncFD): bool =
       # We have connected.
@@ -731,7 +827,7 @@ else:
 
   proc recv*(socket: TAsyncFD, size: int,
              flags = {TSocketFlags.SafeDisconn}): PFuture[string] =
-    var retFuture = newFuture[string]()
+    var retFuture = newFuture[string]("recv")
     
     var readBuffer = newString(size)
 
@@ -762,7 +858,7 @@ else:
 
   proc send*(socket: TAsyncFD, data: string,
              flags = {TSocketFlags.SafeDisconn}): PFuture[void] =
-    var retFuture = newFuture[void]()
+    var retFuture = newFuture[void]("send")
     
     var written = 0
     
@@ -792,9 +888,10 @@ else:
     addWrite(socket, cb)
     return retFuture
 
-  proc acceptAddr*(socket: TAsyncFD): 
+  proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: TAsyncFD]] =
-    var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]()
+    var retFuture = newFuture[tuple[address: string,
+        client: TAsyncFD]]("acceptAddr")
     proc cb(sock: TAsyncFD): bool =
       result = true
       var sockAddress: Tsockaddr_in
@@ -807,19 +904,31 @@ else:
         if lastError.int32 == EINTR:
           return false
         else:
-          retFuture.fail(newException(EOS, osErrorMsg(lastError)))
+          if flags.isDisconnectionError(lastError):
+            return false
+          else:
+            retFuture.fail(newException(EOS, osErrorMsg(lastError)))
       else:
         register(client.TAsyncFD)
         retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.TAsyncFD))
     addRead(socket, cb)
     return retFuture
 
-proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] =
+proc sleepAsync*(ms: int): PFuture[void] =
+  ## Suspends the execution of the current async procedure for the next
+  ## ``ms`` miliseconds.
+  var retFuture = newFuture[void]("sleepAsync")
+  let p = getGlobalDispatcher()
+  p.timers.add((epochTime() + (ms / 1000), retFuture))
+  return retFuture
+
+proc accept*(socket: TAsyncFD,
+    flags = {TSocketFlags.SafeDisconn}): PFuture[TAsyncFD] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection.
   ## The future will complete when the connection is successfully accepted.
-  var retFut = newFuture[TAsyncFD]()
-  var fut = acceptAddr(socket)
+  var retFut = newFuture[TAsyncFD]("accept")
+  var fut = acceptAddr(socket, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
       assert future.finished
@@ -845,11 +954,16 @@ template createCb*(retFutureSym, iteratorNameSym,
         else:
           next.callback = cb
     except:
-      retFutureSym.fail(getCurrentException())
+      if retFutureSym.finished:
+        # Take a look at tasyncexceptions for the bug which this fixes.
+        # That test explains it better than I can here.
+        raise
+      else:
+        retFutureSym.fail(getCurrentException())
   cb()
   #{.pop.}
 proc generateExceptionCheck(futSym,
-    exceptBranch, rootReceiver: PNimrodNode): PNimrodNode {.compileTime.} =
+    exceptBranch, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} =
   if exceptBranch == nil:
     result = rootReceiver
   else:
@@ -869,20 +983,21 @@ proc generateExceptionCheck(futSym,
            )
          )
       )
-    let elseNode = newNimNode(nnkElse)
-    elseNode.add newNimNode(nnkStmtList)
+    let elseNode = newNimNode(nnkElse, fromNode)
+    elseNode.add newNimNode(nnkStmtList, fromNode)
     elseNode[0].add rootReceiver
     result.add elseNode
 
 template createVar(result: var PNimrodNode, futSymName: string,
                    asyncProc: PNimrodNode,
-                   valueReceiver, rootReceiver: expr) =
-  result = newNimNode(nnkStmtList)
+                   valueReceiver, rootReceiver: expr,
+                   fromNode: PNimrodNode) =
+  result = newNimNode(nnkStmtList, fromNode)
   var futSym = genSym(nskVar, "future")
   result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y
-  result.add newNimNode(nnkYieldStmt).add(futSym) # -> yield future<x>
+  result.add newNimNode(nnkYieldStmt, fromNode).add(futSym) # -> yield future<x>
   valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read
-  result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver)
+  result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver, fromNode)
 
 proc processBody(node, retFutureSym: PNimrodNode,
                  subTypeIsVoid: bool,
@@ -891,7 +1006,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
   result = node
   case node.kind
   of nnkReturnStmt:
-    result = newNimNode(nnkStmtList)
+    result = newNimNode(nnkStmtList, node)
     if node[0].kind == nnkEmpty:
       if not subtypeIsVoid:
         result.add newCall(newIdentNode("complete"), retFutureSym,
@@ -902,36 +1017,36 @@ proc processBody(node, retFutureSym: PNimrodNode,
       result.add newCall(newIdentNode("complete"), retFutureSym,
         node[0].processBody(retFutureSym, subtypeIsVoid, exceptBranch))
 
-    result.add newNimNode(nnkReturnStmt).add(newNilLit())
+    result.add newNimNode(nnkReturnStmt, node).add(newNilLit())
     return # Don't process the children of this return stmt
-  of nnkCommand:
+  of nnkCommand, nnkCall:
     if node[0].kind == nnkIdent and node[0].ident == !"await":
       case node[1].kind
-      of nnkIdent:
+      of nnkIdent, nnkInfix:
         # await x
-        result = newNimNode(nnkYieldStmt).add(node[1]) # -> yield x
-      of nnkCall:
+        result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x
+      of nnkCall, nnkCommand:
         # await foo(p, x)
         var futureValue: PNimrodNode
         result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue,
-                  futureValue)
+                  futureValue, node)
       else:
         error("Invalid node kind in 'await', got: " & $node[1].kind)
-    elif node[1].kind == nnkCommand and node[1][0].kind == nnkIdent and
-         node[1][0].ident == !"await":
+    elif node.len > 1 and node[1].kind == nnkCommand and
+         node[1][0].kind == nnkIdent and node[1][0].ident == !"await":
       # foo await x
       var newCommand = node
       result.createVar("future" & $node[0].toStrLit, node[1][1], newCommand[1],
-                newCommand)
+                newCommand, node)
 
   of nnkVarSection, nnkLetSection:
     case node[0][2].kind
     of nnkCommand:
-      if node[0][2][0].ident == !"await":
+      if node[0][2][0].kind == nnkIdent and node[0][2][0].ident == !"await":
         # var x = await y
         var newVarSection = node # TODO: Should this use copyNimNode?
         result.createVar("future" & $node[0][0].ident, node[0][2][1],
-          newVarSection[0][2], newVarSection)
+          newVarSection[0][2], newVarSection, node)
     else: discard
   of nnkAsgn:
     case node[1].kind
@@ -939,7 +1054,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
       if node[1][0].ident == !"await":
         # x = await y
         var newAsgn = node
-        result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn)
+        result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn, node)
     else: discard
   of nnkDiscardStmt:
     # discard await x
@@ -947,10 +1062,10 @@ proc processBody(node, retFutureSym: PNimrodNode,
           node[0][0].ident == !"await":
       var newDiscard = node
       result.createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1],
-                newDiscard[0], newDiscard)
+                newDiscard[0], newDiscard, node)
   of nnkTryStmt:
     # try: await x; except: ...
-    result = newNimNode(nnkStmtList)
+    result = newNimNode(nnkStmtList, node)
     proc processForTry(n: PNimrodNode, i: var int,
                        res: PNimrodNode): bool {.compileTime.} =
       result = false
@@ -1009,7 +1124,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
         (returnType.kind == nnkBracketExpr and
          returnType[1].kind == nnkIdent and returnType[1].ident == !"void")
 
-  var outerProcBody = newNimNode(nnkStmtList)
+  var outerProcBody = newNimNode(nnkStmtList, prc[6])
 
   # -> var retFuture = newFuture[T]()
   var retFutureSym = genSym(nskVar, "retFuture")
@@ -1019,9 +1134,10 @@ macro async*(prc: stmt): stmt {.immediate.} =
   outerProcBody.add(
     newVarStmt(retFutureSym, 
       newCall(
-        newNimNode(nnkBracketExpr).add(
+        newNimNode(nnkBracketExpr, prc[6]).add(
           newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
-          subRetType)))) # Get type from return type of this proc
+          subRetType),
+      newLit(prc[0].getName)))) # Get type from return type of this proc
   
   # -> iterator nameIter(): PFutureBase {.closure.} = 
   # ->   var result: T
@@ -1030,7 +1146,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   var iteratorNameSym = genSym(nskIterator, $prc[0].getName & "Iter")
   var procBody = prc[6].processBody(retFutureSym, subtypeIsVoid, nil)
   if not subtypeIsVoid:
-    procBody.insert(0, newNimNode(nnkVarSection).add(
+    procBody.insert(0, newNimNode(nnkVarSection, prc[6]).add(
       newIdentDefs(newIdentNode("result"), returnType[1]))) # -> var result: T
     procBody.add(
       newCall(newIdentNode("complete"),
@@ -1041,7 +1157,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   
   var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")],
                                 procBody, nnkIteratorDef)
-  closureIterator[4] = newNimNode(nnkPragma).add(newIdentNode("closure"))
+  closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure"))
   outerProcBody.add(closureIterator)
 
   # -> createCb(retFuture)
@@ -1051,7 +1167,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
   outerProcBody.add procCb
 
   # -> return retFuture
-  outerProcBody.add newNimNode(nnkReturnStmt).add(retFutureSym)
+  outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym)
   
   result = prc
 
@@ -1068,8 +1184,8 @@ macro async*(prc: stmt): stmt {.immediate.} =
   result[6] = outerProcBody
 
   #echo(treeRepr(result))
-  #if prc[0].getName == "routeReq":
-  #echo(toStrLit(result))
+  #if prc[0].getName == "getFile":
+  #  echo(toStrLit(result))
 
 proc recvLine*(socket: TAsyncFD): PFuture[string] {.async.} =
   ## Reads a line of data from ``socket``. Returned future will complete once
@@ -1110,3 +1226,11 @@ proc runForever*() =
   ## Begins a never ending global dispatcher poll loop.
   while true:
     poll()
+
+proc waitFor*[T](fut: PFuture[T]) =
+  ## **Blocks** the current thread until the specified future completes.
+  while not fut.finished:
+    poll()
+
+  if fut.failed:
+    raise fut.error
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
new file mode 100644
index 000000000..f1b1d1400
--- /dev/null
+++ b/lib/pure/asyncftpclient.nim
@@ -0,0 +1,295 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+import asyncdispatch, asyncnet, strutils, parseutils, os, times
+
+from ftpclient import TFtpBase, EInvalidReply, TFtpEvent
+from net import bufferSize
+
+type
+  TAsyncFtpClient* = TFtpBase[PAsyncSocket]
+  PAsyncFtpClient* = ref TAsyncFtpClient
+
+  ProgressChangedProc* =
+    proc (total, progress: BiggestInt, speed: float):
+      PFuture[void] {.closure, gcsafe.}
+
+proc expectReply(ftp: PAsyncFtpClient): PFuture[TaintedString] =
+  result = ftp.csock.recvLine()
+
+proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} =
+  ## Send a message to the server, and wait for a primary reply.
+  ## ``\c\L`` is added for you.
+  await ftp.csock.send(m & "\c\L")
+  return await ftp.expectReply()
+
+proc assertReply(received: TaintedString, expected: varargs[string]) =
+  for i in items(expected):
+    if received.string.startsWith(i): return
+  raise newException(EInvalidReply,
+                     "Expected reply '$1' got: $2" %
+                     [expected.join("' or '"), received.string])
+
+proc pasv(ftp: PAsyncFtpClient) {.async.} =
+  ## Negotiate a data connection.
+  ftp.dsock = newAsyncSocket()
+
+  var pasvMsg = (await ftp.send("PASV")).string.strip.TaintedString
+  assertReply(pasvMsg, "227")
+  var betweenParens = captureBetween(pasvMsg.string, '(', ')')
+  var nums = betweenParens.split(',')
+  var ip = nums[0.. -3]
+  var port = nums[-2.. -1]
+  var properPort = port[0].parseInt()*256+port[1].parseInt()
+  await ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
+  ftp.dsockConnected = True
+
+proc normalizePathSep(path: string): string =
+  return replace(path, '\\', '/')
+
+proc connect*(ftp: PAsyncFtpClient) {.async.} =
+  ## Connect to the FTP server specified by ``ftp``.
+  await ftp.csock.connect(ftp.address, ftp.port)
+
+  var reply = await ftp.expectReply()
+  if reply.startsWith("120"):
+    # 120 Service ready in nnn minutes.
+    # We wait until we receive 220.
+    reply = await ftp.expectReply()
+  assertReply(reply, "220")
+
+  if ftp.user != "":
+    assertReply(await(ftp.send("USER " & ftp.user)), "230", "331")
+
+  if ftp.pass != "":
+    assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
+
+proc pwd*(ftp: PAsyncFtpClient): PFuture[TaintedString] {.async.} =
+  ## Returns the current working directory.
+  let wd = await ftp.send("PWD")
+  assertReply wd, "257"
+  return wd.string.captureBetween('"').TaintedString # "
+
+proc cd*(ftp: PAsyncFtpClient, dir: string) {.async.} =
+  ## Changes the current directory on the remote FTP server to ``dir``.
+  assertReply(await(ftp.send("CWD " & dir.normalizePathSep)), "250")
+
+proc cdup*(ftp: PAsyncFtpClient) {.async.} =
+  ## Changes the current directory to the parent of the current directory.
+  assertReply(await(ftp.send("CDUP")), "200")
+
+proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} =
+  ## Downloads text data in ASCII mode
+  result = ""
+  assert ftp.dsockConnected
+  while ftp.dsockConnected:
+    let r = await ftp.dsock.recvLine()
+    if r.string == "":
+      ftp.dsockConnected = false
+    else:
+      result.add(r.string & "\n")
+
+  assertReply(await(ftp.expectReply()), "226")
+
+proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} =
+  ## Returns a list of filenames in the given directory. If ``dir`` is "",
+  ## the current directory is used. If ``async`` is true, this
+  ## function will return immediately and it will be your job to
+  ## use asyncio's ``poll`` to progress this operation.
+  await ftp.pasv()
+
+  assertReply(await(ftp.send("NLST " & dir.normalizePathSep)), ["125", "150"])
+
+  result = splitLines(await ftp.getLines())
+
+proc existsFile*(ftp: PAsyncFtpClient, file: string): PFuture[bool] {.async.} =
+  ## Determines whether ``file`` exists.
+  var files = await ftp.listDirs()
+  for f in items(files):
+    if f.normalizePathSep == file.normalizePathSep: return true
+
+proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} =
+  ## Creates a directory ``dir``. If ``recursive`` is true, the topmost
+  ## subdirectory of ``dir`` will be created first, following the secondmost...
+  ## etc. this allows you to give a full path as the ``dir`` without worrying
+  ## about subdirectories not existing.
+  if not recursive:
+    assertReply(await(ftp.send("MKD " & dir.normalizePathSep)), "257")
+  else:
+    var reply = TaintedString""
+    var previousDirs = ""
+    for p in split(dir, {os.dirSep, os.altSep}):
+      if p != "":
+        previousDirs.add(p)
+        reply = await ftp.send("MKD " & previousDirs)
+        previousDirs.add('/')
+    assertReply reply, "257"
+
+proc chmod*(ftp: PAsyncFtpClient, path: string,
+            permissions: set[TFilePermission]) {.async.} =
+  ## Changes permission of ``path`` to ``permissions``.
+  var userOctal = 0
+  var groupOctal = 0
+  var otherOctal = 0
+  for i in items(permissions):
+    case i
+    of fpUserExec: userOctal.inc(1)
+    of fpUserWrite: userOctal.inc(2)
+    of fpUserRead: userOctal.inc(4)
+    of fpGroupExec: groupOctal.inc(1)
+    of fpGroupWrite: groupOctal.inc(2)
+    of fpGroupRead: groupOctal.inc(4)
+    of fpOthersExec: otherOctal.inc(1)
+    of fpOthersWrite: otherOctal.inc(2)
+    of fpOthersRead: otherOctal.inc(4)
+
+  var perm = $userOctal & $groupOctal & $otherOctal
+  assertReply(await(ftp.send("SITE CHMOD " & perm &
+                    " " & path.normalizePathSep)), "200")
+
+proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} =
+  ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
+  ## working directory.
+  await ftp.pasv()
+
+  let reply = await ftp.send("LIST" & " " & dir.normalizePathSep)
+  assertReply(reply, ["125", "150"])
+
+  result = await ftp.getLines()
+
+proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} =
+  ## Retrieves ``file``. File must be ASCII text.
+  await ftp.pasv()
+  let reply = await ftp.send("RETR " & file.normalizePathSep)
+  assertReply(reply, ["125", "150"])
+
+  result = await ftp.getLines()
+
+proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt,
+             onProgressChanged: ProgressChangedProc) {.async.} =
+  assert ftp.dsockConnected
+  var progress = 0
+  var progressInSecond = 0
+  var countdownFut = sleepAsync(1000)
+  var dataFut = ftp.dsock.recv(bufferSize)
+  while ftp.dsockConnected:
+    await dataFut or countdownFut
+    if countdownFut.finished:
+      asyncCheck onProgressChanged(total, progress,
+          progressInSecond.float)
+      progressInSecond = 0
+      countdownFut = sleepAsync(1000)
+
+    if dataFut.finished:
+      let data = dataFut.read
+      if data != "":
+        progress.inc(data.len)
+        progressInSecond.inc(data.len)
+        file.write(data)
+        dataFut = ftp.dsock.recv(bufferSize)
+      else:
+        ftp.dsockConnected = False
+
+  assertReply(await(ftp.expectReply()), "226")
+
+proc defaultOnProgressChanged*(total, progress: BiggestInt,
+    speed: float): PFuture[void] {.nimcall,gcsafe.} =
+  ## Default FTP ``onProgressChanged`` handler. Does nothing.
+  result = newFuture[void]()
+  #echo(total, " ", progress, " ", speed)
+  result.complete()
+
+proc retrFile*(ftp: PAsyncFtpClient, file, dest: string,
+               onProgressChanged = defaultOnProgressChanged) {.async.} =
+  ## Downloads ``file`` and saves it to ``dest``.
+  ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function
+  ## when the download is finished. The event's ``filename`` field will be equal
+  ## to ``file``.
+  var destFile = open(dest, mode = fmWrite)
+  await ftp.pasv()
+  var reply = await ftp.send("RETR " & file.normalizePathSep)
+  assertReply reply, ["125", "150"]
+  if {'(', ')'} notin reply.string:
+    raise newException(EInvalidReply, "Reply has no file size.")
+  var fileSize: biggestInt
+  if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0:
+    raise newException(EInvalidReply, "Reply has no file size.")
+
+  await getFile(ftp, destFile, fileSize, onProgressChanged)
+
+proc doUpload(ftp: PAsyncFtpClient, file: TFile,
+              onProgressChanged: ProgressChangedProc) {.async.} =
+  assert ftp.dsockConnected
+
+  let total = file.getFileSize()
+  var data = newStringOfCap(4000)
+  var progress = 0
+  var progressInSecond = 0
+  var countdownFut = sleepAsync(1000)
+  var sendFut: PFuture[void] = nil
+  while ftp.dsockConnected:
+    if sendFut == nil or sendFut.finished:
+      progress.inc(data.len)
+      progressInSecond.inc(data.len)
+      # TODO: Async file reading.
+      let len = file.readBuffer(addr(data[0]), 4000)
+      setLen(data, len)
+      if len == 0:
+        # File finished uploading.
+        ftp.dsock.close()
+        ftp.dsockConnected = false
+
+        assertReply(await(ftp.expectReply()), "226")
+      else:
+        sendFut = ftp.dsock.send(data)
+
+    if countdownFut.finished:
+      asyncCheck onProgressChanged(total, progress, progressInSecond.float)
+      progressInSecond = 0
+      countdownFut = sleepAsync(1000)
+
+    await countdownFut or sendFut
+
+proc storeFile*(ftp: PAsyncFtpClient, file, dest: string,
+            onProgressChanged = defaultOnProgressChanged) {.async.} =
+  ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
+  ## function asynchronously is recommended to view the progress of
+  ## the download.
+  ## The ``EvStore`` event is passed to the specified ``handleEvent`` function
+  ## when the upload is finished, and the ``filename`` field will be
+  ## equal to ``file``.
+  var destFile = open(file)
+  await ftp.pasv()
+
+  let reply = await ftp.send("STOR " & dest.normalizePathSep)
+  assertReply reply, ["125", "150"]
+
+  await doUpload(ftp, destFile, onProgressChanged)
+
+proc newAsyncFtpClient*(address: string, port = TPort(21),
+    user, pass = ""): PAsyncFtpClient =
+  ## Creates a new ``PAsyncFtpClient`` object.
+  new result
+  result.user = user
+  result.pass = pass
+  result.address = address
+  result.port = port
+  result.dsockConnected = false
+  result.csock = newAsyncSocket()
+
+when isMainModule:
+  var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test")
+  proc main(ftp: PAsyncFtpClient) {.async.} =
+    await ftp.connect()
+    echo await ftp.pwd()
+    echo await ftp.listDirs()
+    await ftp.storeFile("payload.jpg", "payload.jpg")
+    await ftp.retrFile("payload.jpg", "payload2.jpg")
+    echo("Finished")
+
+  waitFor main(ftp)
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index ee6658fd1..c8bd5cfc1 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -11,14 +11,14 @@
 ##
 ## **Note:** This module is still largely experimental.
 
-import strtabs, asyncnet, asyncdispatch, parseutils, parseurl, strutils
+import strtabs, asyncnet, asyncdispatch, parseutils, uri, strutils
 type
   TRequest* = object
     client*: PAsyncSocket # TODO: Separate this into a Response object?
     reqMethod*: string
     headers*: PStringTable
     protocol*: tuple[orig: string, major, minor: int]
-    url*: TURL
+    url*: TUri
     hostname*: string ## The hostname of the client that made the request.
     body*: string
 
@@ -97,7 +97,8 @@ proc sendStatus(client: PAsyncSocket, status: string): PFuture[void] =
   client.send("HTTP/1.1 " & status & "\c\L")
 
 proc processClient(client: PAsyncSocket, address: string,
-                 callback: proc (request: TRequest): PFuture[void]) {.async.} =
+                   callback: proc (request: TRequest):
+                      PFuture[void] {.closure, gcsafe.}) {.async.} =
   while true:
     # GET /path HTTP/1.1
     # Header: val
@@ -135,7 +136,7 @@ proc processClient(client: PAsyncSocket, address: string,
       request.headers[kv.key] = kv.value
 
     request.reqMethod = reqMethod
-    request.url = parseUrl(path)
+    request.url = parseUri(path)
     try:
       request.protocol = protocol.parseProtocol()
     except EInvalidValue:
@@ -184,7 +185,7 @@ proc processClient(client: PAsyncSocket, address: string,
       break
 
 proc serve*(server: PAsyncHttpServer, port: TPort,
-            callback: proc (request: TRequest): PFuture[void],
+            callback: proc (request: TRequest): PFuture[void] {.closure,gcsafe.},
             address = "") {.async.} =
   ## Starts the process of listening for incoming HTTP connections on the
   ## specified address and port.
@@ -199,19 +200,23 @@ proc serve*(server: PAsyncHttpServer, port: TPort,
     #var (address, client) = await server.socket.acceptAddr()
     var fut = await server.socket.acceptAddr()
     asyncCheck processClient(fut.client, fut.address, callback)
+    #echo(f.isNil)
+    #echo(f.repr)
 
 proc close*(server: PAsyncHttpServer) =
   ## Terminates the async http server instance.
   server.socket.close()
 
 when isMainModule:
-  var server = newAsyncHttpServer()
-  proc cb(req: TRequest) {.async.} =
-    #echo(req.reqMethod, " ", req.url)
-    #echo(req.headers)
-    let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT",
-        "Content-type": "text/plain; charset=utf-8"}
-    await req.respond(Http200, "Hello World", headers.newStringTable())
-
-  asyncCheck server.serve(TPort(5555), cb)
-  runForever()
+  proc main =
+    var server = newAsyncHttpServer()
+    proc cb(req: TRequest) {.async.} =
+      #echo(req.reqMethod, " ", req.url)
+      #echo(req.headers)
+      let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT",
+          "Content-type": "text/plain; charset=utf-8"}
+      await req.respond(Http200, "Hello World", headers.newStringTable())
+
+    asyncCheck server.serve(TPort(5555), cb)
+    runForever()
+  main()
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index c68ca4350..6b67bf4b5 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -671,25 +671,26 @@ when isMainModule:
         testRead(s, 2)
     disp.register(client)
 
-  var d = newDispatcher()
-  
-  var s = AsyncSocket()
-  s.connect("amber.tenthbit.net", TPort(6667))
-  s.handleConnect = 
-    proc (s: PAsyncSocket) =
-      testConnect(s, 1)
-  s.handleRead = 
-    proc (s: PAsyncSocket) =
-      testRead(s, 1)
-  d.register(s)
-  
-  var server = AsyncSocket()
-  server.handleAccept =
-    proc (s: PAsyncSocket) = 
-      testAccept(s, d, 78)
-  server.bindAddr(TPort(5555))
-  server.listen()
-  d.register(server)
-  
-  while d.poll(-1): discard
+  proc main =
+    var d = newDispatcher()
+    
+    var s = AsyncSocket()
+    s.connect("amber.tenthbit.net", TPort(6667))
+    s.handleConnect = 
+      proc (s: PAsyncSocket) =
+        testConnect(s, 1)
+    s.handleRead = 
+      proc (s: PAsyncSocket) =
+        testRead(s, 1)
+    d.register(s)
+    
+    var server = AsyncSocket()
+    server.handleAccept =
+      proc (s: PAsyncSocket) = 
+        testAccept(s, d, 78)
+    server.bindAddr(TPort(5555))
+    server.listen()
+    d.register(server)
     
+    while d.poll(-1): discard
+  main()
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 374ac77e3..5095d9461 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -36,9 +36,9 @@
 ##       let client = await server.accept()
 ##       clients.add client
 ##
-##       processClient(client)
+##       asyncCheck processClient(client)
 ##
-##   serve()
+##   asyncCheck serve()
 ##   runForever()
 ##
 ##
@@ -135,13 +135,13 @@ proc send*(socket: PAsyncSocket, data: string,
   assert socket != nil
   result = send(socket.fd.TAsyncFD, data, flags)
 
-proc acceptAddr*(socket: PAsyncSocket): 
+proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}):
       PFuture[tuple[address: string, client: PAsyncSocket]] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection and the remote address of the client.
   ## The future will complete when the connection is successfully accepted.
-  var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]()
-  var fut = acceptAddr(socket.fd.TAsyncFD)
+  var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]("asyncnet.acceptAddr")
+  var fut = acceptAddr(socket.fd.TAsyncFD, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) =
       assert future.finished
@@ -153,12 +153,13 @@ proc acceptAddr*(socket: PAsyncSocket):
         retFuture.complete(resultTup)
   return retFuture
 
-proc accept*(socket: PAsyncSocket): PFuture[PAsyncSocket] =
+proc accept*(socket: PAsyncSocket,
+    flags = {TSocketFlags.SafeDisconn}): PFuture[PAsyncSocket] =
   ## Accepts a new connection. Returns a future containing the client socket
   ## corresponding to that connection.
   ## The future will complete when the connection is successfully accepted.
-  var retFut = newFuture[PAsyncSocket]()
-  var fut = acceptAddr(socket)
+  var retFut = newFuture[PAsyncSocket]("asyncnet.accept")
+  var fut = acceptAddr(socket, flags)
   fut.callback =
     proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) =
       assert future.finished
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index c50c4165b..2629e9f40 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -409,6 +409,23 @@ template mapIt*(varSeq, pred: expr) =
     let it {.inject.} = varSeq[i]
     varSeq[i] = pred
 
+template newSeqWith*(len: int, init: expr): expr =
+  ## creates a new sequence, calling `init` to initialize each value. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var seq2D = newSeqWith(20, newSeq[bool](10))
+  ##   seq2D[0][0] = true
+  ##   seq2D[1][0] = true
+  ##   seq2D[0][1] = true
+  ##
+  ##   import math
+  ##   var seqRand = newSeqWith(20, random(10))
+  ##   echo seqRand
+  var result {.gensym.} = newSeq[type(init)](len)
+  for i in 0 .. <len:
+    result[i] = init
+  result
+
 when isMainModule:
   import strutils
   block: # concat test
@@ -557,4 +574,11 @@ when isMainModule:
     doAssert b.distribute(5, true)[4].len == 5
     doAssert b.distribute(5, false)[4].len == 2
 
+  block: # newSeqWith tests
+    var seq2D = newSeqWith(4, newSeq[bool](2))
+    seq2D[0][0] = true
+    seq2D[1][0] = true
+    seq2D[0][1] = true
+    doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
+
   echo "Finished doc tests"
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 42cdc682f..ce901963e 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -128,7 +128,7 @@ proc mget*[A](s: var TSet[A], key: A): var A =
   ## for sharing.
   assert s.isValid, "The set needs to be initialized."
   var index = rawGet(s, key)
-  if index >= 0: result = t.data[index].key
+  if index >= 0: result = s.data[index].key
   else: raise newException(EInvalidKey, "key not found: " & $key)
 
 proc contains*[A](s: TSet[A], key: A): bool =
@@ -713,6 +713,24 @@ proc `$`*[A](s: TOrderedSet[A]): string =
   assert s.isValid, "The set needs to be initialized."
   dollarImpl()
 
+proc `==`*[A](s, t: TOrderedSet[A]): bool =
+  ## Equality for ordered sets.
+  if s.counter != t.counter: return false
+  var h = s.first
+  var g = s.first
+  var compared = 0
+  while h >= 0 and g >= 0:
+    var nxh = s.data[h].next
+    var nxg = t.data[g].next
+    if s.data[h].slot == seFilled and s.data[g].slot == seFilled:
+      if s.data[h].key == s.data[g].key:
+        inc compared
+      else:
+        return false
+    h = nxh
+    g = nxg
+  result = compared == s.counter
+
 proc testModule() =
   ## Internal micro test to validate docstrings and such.
   block isValidTest:
@@ -858,7 +876,7 @@ proc testModule() =
     var b = initOrderedSet[int]()
     for x in [2, 4, 5]: b.incl(x)
     assert($a == $b)
-    # assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
+    assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
 
   block initBlocks:
     var a: TOrderedSet[int]
diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim
index dfa819f64..8d7f28f8e 100644
--- a/lib/pure/concurrency/cpuinfo.nim
+++ b/lib/pure/concurrency/cpuinfo.nim
@@ -18,15 +18,24 @@ when not defined(windows):
 
 when defined(linux):
   import linux
+  
+when defined(freebsd) or defined(macosx):
+  {.emit:"#include <sys/types.h>".}
+
+when defined(openbsd) or defined(netbsd):
+  {.emit:"#include <sys/param.h>".}
 
 when defined(macosx) or defined(bsd):
+  # we HAVE to emit param.h before sysctl.h so we cannot use .header here
+  # either. The amount of archaic bullshit in Poonix based OSes is just insane.
+  {.emit:"#include <sys/sysctl.h>".}
   const
     CTL_HW = 6
     HW_AVAILCPU = 25
     HW_NCPU = 3
   proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
               a: var csize, b: pointer, c: int): cint {.
-             importc: "sysctl", header: "<sys/sysctl.h>".}
+              importc: "sysctl", nodecl.}
 
 proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
   ## returns the numer of the processors/cores the machine has.
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index fd1041918..f46822d94 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -9,6 +9,9 @@
 
 ## Implements Nimrod's 'spawn'.
 
+when not compileOption("threads"):
+  {.error: "Threadpool requires --threads:on option.".}
+
 import cpuinfo, cpuload, locks
 
 {.push stackTrace:off.}
@@ -92,7 +95,7 @@ type
 
   FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]'
   FlowVarBaseObj = object of TObject
-    ready, usesCondVar: bool
+    ready, usesCondVar, awaited: bool
     cv: CondVar #\
     # for 'awaitAny' support
     ai: ptr AwaitInfo
@@ -126,15 +129,15 @@ type
 proc await*(fv: FlowVarBase) =
   ## waits until the value for the flowVar arrives. Usually it is not necessary
   ## to call this explicitly.
-  if fv.usesCondVar:
-    fv.usesCondVar = false
+  if fv.usesCondVar and not fv.awaited:
+    fv.awaited = true
     await(fv.cv)
     destroyCondVar(fv.cv)
 
 proc finished(fv: FlowVarBase) =
   doAssert fv.ai.isNil, "flowVar is still attached to an 'awaitAny'"
   # we have to protect against the rare cases where the owner of the flowVar
-  # simply disregards the flowVar and yet the "flowVarr" has not yet written
+  # simply disregards the flowVar and yet the "flowVar" has not yet written
   # anything to it:
   await(fv)
   if fv.data.isNil: return
@@ -207,6 +210,7 @@ proc `^`*[T](fv: FlowVar[T]): T =
   ## blocks until the value is available and then returns this value.
   await(fv)
   when T is string or T is seq:
+    # XXX closures? deepCopy?
     result = cast[T](fv.data)
   else:
     result = fv.blob
@@ -264,6 +268,10 @@ proc slave(w: ptr Worker) {.thread.} =
       w.shutdown = false
       atomicDec currentPoolSize
 
+var
+  workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
+  workersData: array[MaxThreadPoolSize, Worker]
+
 proc setMinPoolSize*(size: range[1..MaxThreadPoolSize]) =
   ## sets the minimal thread pool size. The default value of this is 4.
   minPoolSize = size
@@ -272,10 +280,10 @@ proc setMaxPoolSize*(size: range[1..MaxThreadPoolSize]) =
   ## sets the minimal thread pool size. The default value of this
   ## is ``MaxThreadPoolSize``.
   maxPoolSize = size
-
-var
-  workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
-  workersData: array[MaxThreadPoolSize, Worker]
+  if currentPoolSize > maxPoolSize:
+    for i in maxPoolSize..currentPoolSize-1:
+      let w = addr(workersData[i])
+      w.shutdown = true
 
 proc activateThread(i: int) {.noinline.} =
   workersData[i].taskArrived = createCondVar()
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index d1cf36a87..49bf92980 100644
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
@@ -28,8 +28,9 @@ proc parseCookies*(s: string): PStringTable =
     if s[i] == '\0': break
     inc(i) # skip ';'
 
-proc setCookie*(key, value: string, domain = "", path = "", 
-                expires = "", noName = false): string =
+proc setCookie*(key, value: string, domain = "", path = "",
+                expires = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   result = ""
@@ -38,16 +39,20 @@ proc setCookie*(key, value: string, domain = "", path = "",
   if domain != "": result.add("; Domain=" & domain)
   if path != "": result.add("; Path=" & path)
   if expires != "": result.add("; Expires=" & expires)
+  if secure: result.add("; secure")
+  if httpOnly: result.add("; HttpOnly")
 
 proc setCookie*(key, value: string, expires: TTimeInfo,
-                domain = "", path = "", noName = false): string =
+                domain = "", path = "", noName = false,
+                secure = false, httpOnly = false): string =
   ## Creates a command in the format of 
   ## ``Set-Cookie: key=value; Domain=...; ...``
   ##
   ## **Note:** UTC is assumed as the timezone for ``expires``.
   
   return setCookie(key, value, domain, path,
-            format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noname)
+                   format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"),
+                   noname, secure, httpOnly)
   
 when isMainModule:
   var tim = TTime(int(getTime()) + 76 * (60 * 60 * 24))
@@ -55,5 +60,3 @@ when isMainModule:
   echo(setCookie("test", "value", tim.getGMTime()))
   
   echo parseCookies("uid=1; kp=2")
-  
-                
\ No newline at end of file
diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim
index 53f6688b9..e8d3f762e 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/pure/ftpclient.nim
@@ -10,6 +10,10 @@ include "system/inclrtl"
 
 import sockets, strutils, parseutils, times, os, asyncio
 
+from asyncnet import nil
+from rawsockets import nil
+from asyncdispatch import PFuture
+
 ## This module **partially** implements an FTP client as specified
 ## by `RFC 959 <http://tools.ietf.org/html/rfc959>`_. 
 ## 
@@ -34,34 +38,32 @@ import sockets, strutils, parseutils, times, os, asyncio
 
 
 type
-  TFTPClient* = object of TObject
-    case isAsync: bool
-    of false:
-      csock: TSocket # Command connection socket
-      dsock: TSocket # Data connection socket
-    else:
-      dummyA, dummyB: pointer # workaround a Nimrod API issue
-      asyncCSock: PAsyncSocket
-      asyncDSock: PAsyncSocket
+  PFtpBase*[SockType] = ref TFtpBase[SockType]
+  TFtpBase*[SockType] = object
+    csock*: SockType
+    dsock*: SockType
+    when SockType is asyncio.PAsyncSocket:
       handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.}
       disp: PDispatcher
       asyncDSockID: PDelegate
-    user, pass: string
-    address: string
-    port: TPort
+    user*, pass*: string
+    address*: string
+    when SockType is asyncnet.PAsyncSocket:
+      port*: rawsockets.TPort
+    else:
+      port*: TPort
     
-    jobInProgress: bool
-    job: ref TFTPJob
+    jobInProgress*: bool
+    job*: PFTPJob[SockType]
 
-    dsockConnected: bool
-
-  PFTPClient* = ref TFTPClient
+    dsockConnected*: bool
 
   FTPJobType* = enum
     JRetrText, JRetr, JStore
 
-  TFTPJob = object
-    prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall, gcsafe.}
+  PFtpJob[T] = ref TFtpJob[T]
+  TFTPJob[T] = object
+    prc: proc (ftp: PFTPBase[T], async: bool): bool {.nimcall, gcsafe.}
     case typ*: FTPJobType
     of JRetrText:
       lines: string
@@ -75,8 +77,11 @@ type
       toStore: string # Data left to upload (Only used with async)
     else: nil
 
+  TFtpClient* = TFtpBase[TSocket]
+  PFtpClient* = ref TFTPClient
+
   PAsyncFTPClient* = ref TAsyncFTPClient ## Async alternative to TFTPClient.
-  TAsyncFTPClient* = object of TFTPClient
+  TAsyncFTPClient* = TFtpBase[asyncio.PAsyncSocket]
 
   FTPEventType* = enum
     EvTransferProgress, EvLines, EvRetr, EvStore
@@ -106,30 +111,30 @@ proc ftpClient*(address: string, port = TPort(21),
   result.address = address
   result.port = port
 
-  result.isAsync = false
   result.dsockConnected = false
   result.csock = socket()
   if result.csock == InvalidSocket: osError(osLastError())
 
-proc getDSock(ftp: PFTPClient): TSocket =
-  if ftp.isAsync: return ftp.asyncDSock else: return ftp.dsock
+proc getDSock[T](ftp: PFTPBase[T]): TSocket =
+  return ftp.dsock
 
-proc getCSock(ftp: PFTPClient): TSocket =
-  if ftp.isAsync: return ftp.asyncCSock else: return ftp.csock
+proc getCSock[T](ftp: PFTPBase[T]): TSocket =
+  return ftp.csock
 
 template blockingOperation(sock: TSocket, body: stmt) {.immediate.} =
-  if ftp.isAsync:
-    sock.setBlocking(true)
   body
-  if ftp.isAsync:
-    sock.setBlocking(false)
 
-proc expectReply(ftp: PFTPClient): TaintedString =
+template blockingOperation(sock: asyncio.PAsyncSocket, body: stmt) {.immediate.} =
+  sock.setBlocking(true)
+  body
+  sock.setBlocking(false)
+
+proc expectReply[T](ftp: PFtpBase[T]): TaintedString =
   result = TaintedString""
   blockingOperation(ftp.getCSock()):
     ftp.getCSock().readLine(result)
 
-proc send*(ftp: PFTPClient, m: string): TaintedString =
+proc send*[T](ftp: PFtpBase[T], m: string): TaintedString =
   ## Send a message to the server, and wait for a primary reply.
   ## ``\c\L`` is added for you.
   blockingOperation(ftp.getCSock()):
@@ -149,8 +154,8 @@ proc assertReply(received: TaintedString, expected: varargs[string]) =
                      "Expected reply '$1' got: $2" %
                      [expected.join("' or '"), received.string])
 
-proc createJob(ftp: PFTPClient,
-               prc: proc (ftp: PFTPClient, async: bool): bool {.
+proc createJob[T](ftp: PFtpBase[T],
+               prc: proc (ftp: PFtpBase[T], async: bool): bool {.
                           nimcall,gcsafe.},
                cmd: FTPJobType) =
   if ftp.jobInProgress:
@@ -165,7 +170,7 @@ proc createJob(ftp: PFTPClient,
   of JRetr, JStore:
     ftp.job.toStore = ""
 
-proc deleteJob(ftp: PFTPClient) =
+proc deleteJob[T](ftp: PFtpBase[T]) =
   assert ftp.jobInProgress
   ftp.jobInProgress = false
   case ftp.job.typ
@@ -173,12 +178,9 @@ proc deleteJob(ftp: PFTPClient) =
     ftp.job.lines = ""
   of JRetr, JStore:
     ftp.job.file.close()
-  if ftp.isAsync:
-    ftp.asyncDSock.close()
-  else:
-    ftp.dsock.close()
+  ftp.dsock.close()
 
-proc handleTask(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ in {JRetr, JStore}:
       if epochTime() - ftp.job.lastProgressReport >= 1.0:
@@ -193,12 +195,12 @@ proc handleTask(s: PAsyncSocket, ftp: PFTPClient) =
         ftp.job.oneSecond = 0
         ftp.handleEvent(PAsyncFTPClient(ftp), r)
 
-proc handleWrite(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleWrite(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
     if ftp.job.typ == JStore:
       assert (not ftp.job.prc(ftp, true))
 
-proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleConnect(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   ftp.dsockConnected = true
   assert(ftp.jobInProgress)
   if ftp.job.typ == JStore:
@@ -206,30 +208,32 @@ proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) =
   else:
     s.delHandleWrite()
 
-proc handleRead(s: PAsyncSocket, ftp: PFTPClient) =
+proc handleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   assert ftp.jobInProgress
   assert ftp.job.typ != JStore
   # This can never return true, because it shouldn't check for code 
   # 226 from csock.
   assert(not ftp.job.prc(ftp, true))
 
-proc pasv(ftp: PFTPClient) =
+proc pasv[T](ftp: PFtpBase[T]) =
   ## Negotiate a data connection.
-  if not ftp.isAsync:
+  when T is TSocket:
     ftp.dsock = socket()
     if ftp.dsock == InvalidSocket: osError(osLastError())
-  else:
-    ftp.asyncDSock = AsyncSocket()
-    ftp.asyncDSock.handleRead =
+  elif T is PAsyncSocket:
+    ftp.dsock = AsyncSocket()
+    ftp.dsock.handleRead =
       proc (s: PAsyncSocket) =
         handleRead(s, ftp)
-    ftp.asyncDSock.handleConnect =
+    ftp.dsock.handleConnect =
       proc (s: PAsyncSocket) =
         handleConnect(s, ftp)
-    ftp.asyncDSock.handleTask =
+    ftp.dsock.handleTask =
       proc (s: PAsyncSocket) =
         handleTask(s, ftp)
-    ftp.disp.register(ftp.asyncDSock)
+    ftp.disp.register(ftp.dsock)
+  else:
+    {.fatal: "Incorrect socket instantiation".}
   
   var pasvMsg = ftp.send("PASV").string.strip.TaintedString
   assertReply(pasvMsg, "227")
@@ -238,23 +242,24 @@ proc pasv(ftp: PFTPClient) =
   var ip = nums[0.. -3]
   var port = nums[-2.. -1]
   var properPort = port[0].parseInt()*256+port[1].parseInt()
-  if ftp.isAsync:
-    ftp.asyncDSock.connect(ip.join("."), TPort(properPort.toU16))
+  ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
+  when T is PAsyncSocket:
     ftp.dsockConnected = False
   else:
-    ftp.dsock.connect(ip.join("."), TPort(properPort.toU16))
     ftp.dsockConnected = True
 
 proc normalizePathSep(path: string): string =
   return replace(path, '\\', '/')
 
-proc connect*(ftp: PFTPClient) =
+proc connect*[T](ftp: PFtpBase[T]) =
   ## Connect to the FTP server specified by ``ftp``.
-  if ftp.isAsync:
-    blockingOperation(ftp.asyncCSock):
-      ftp.asyncCSock.connect(ftp.address, ftp.port)
-  else:
+  when T is PAsyncSocket:
+    blockingOperation(ftp.csock):
+      ftp.csock.connect(ftp.address, ftp.port)
+  elif T is TSocket:
     ftp.csock.connect(ftp.address, ftp.port)
+  else:
+    {.fatal: "Incorrect socket instantiation".}
 
   # TODO: Handle 120? or let user handle it.
   assertReply ftp.expectReply(), "220"
@@ -279,25 +284,27 @@ proc cdup*(ftp: PFTPClient) =
   ## Changes the current directory to the parent of the current directory.
   assertReply ftp.send("CDUP"), "200"
 
-proc getLines(ftp: PFTPClient, async: bool = false): bool =
+proc getLines[T](ftp: PFtpBase[T], async: bool = false): bool =
   ## Downloads text data in ASCII mode
   ## Returns true if the download is complete.
   ## It doesn't if `async` is true, because it doesn't check for 226 then.
   if ftp.dsockConnected:
     var r = TaintedString""
-    if ftp.isAsync:
+    when T is PAsyncSocket:
       if ftp.asyncDSock.readLine(r):
         if r.string == "":
           ftp.dsockConnected = false
         else:
           ftp.job.lines.add(r.string & "\n")
-    else:
+    elif T is TSocket:
       assert(not async)
       ftp.dsock.readLine(r)
       if r.string == "":
         ftp.dsockConnected = false
       else:
         ftp.job.lines.add(r.string & "\n")
+    else:
+      {.fatal: "Incorrect socket instantiation".}
   
   if not async:
     var readSocks: seq[TSocket] = @[ftp.getCSock()]
@@ -307,14 +314,14 @@ proc getLines(ftp: PFTPClient, async: bool = false): bool =
         assertReply ftp.expectReply(), "226"
         return true
 
-proc listDirs*(ftp: PFTPClient, dir: string = "",
+proc listDirs*[T](ftp: PFtpBase[T], dir: string = "",
                async = false): seq[string] =
   ## Returns a list of filenames in the given directory. If ``dir`` is "",
   ## the current directory is used. If ``async`` is true, this
   ## function will return immediately and it will be your job to
   ## use asyncio's ``poll`` to progress this operation.
 
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
 
   assertReply ftp.send("NLST " & dir.normalizePathSep), ["125", "150"]
@@ -384,12 +391,12 @@ proc chmod*(ftp: PFTPClient, path: string,
   assertReply ftp.send("SITE CHMOD " & perm &
                        " " & path.normalizePathSep), "200"
 
-proc list*(ftp: PFTPClient, dir: string = "", async = false): string =
+proc list*[T](ftp: PFtpBase[T], dir: string = "", async = false): string =
   ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current
   ## working directory. If ``async`` is true, this function will return
   ## immediately and it will be your job to call asyncio's 
   ## ``poll`` to progress this operation.
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
 
   assertReply(ftp.send("LIST" & " " & dir.normalizePathSep), ["125", "150"])
@@ -401,11 +408,11 @@ proc list*(ftp: PFTPClient, dir: string = "", async = false): string =
   else:
     return ""
 
-proc retrText*(ftp: PFTPClient, file: string, async = false): string =
+proc retrText*[T](ftp: PFtpBase[T], file: string, async = false): string =
   ## Retrieves ``file``. File must be ASCII text.
   ## If ``async`` is true, this function will return immediately and
   ## it will be your job to call asyncio's ``poll`` to progress this operation.
-  ftp.createJob(getLines, JRetrText)
+  ftp.createJob(getLines[T], JRetrText)
   ftp.pasv()
   assertReply ftp.send("RETR " & file.normalizePathSep), ["125", "150"]
   
@@ -416,15 +423,17 @@ proc retrText*(ftp: PFTPClient, file: string, async = false): string =
   else:
     return ""
 
-proc getFile(ftp: PFTPClient, async = false): bool =
+proc getFile[T](ftp: PFtpBase[T], async = false): bool =
   if ftp.dsockConnected:
     var r = "".TaintedString
     var bytesRead = 0
     var returned = false
     if async:
-      if not ftp.isAsync: raise newException(EFTP, "FTPClient must be async.")
-      bytesRead = ftp.AsyncDSock.recvAsync(r, BufferSize)
-      returned = bytesRead != -1
+      when T is TSocket:
+        raise newException(EFTP, "FTPClient must be async.")
+      else:
+        bytesRead = ftp.dsock.recvAsync(r, BufferSize)
+        returned = bytesRead != -1
     else: 
       bytesRead = getDSock(ftp).recv(r, BufferSize)
       returned = true
@@ -443,13 +452,13 @@ proc getFile(ftp: PFTPClient, async = false): bool =
         assertReply ftp.expectReply(), "226"
         return true
 
-proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) =
+proc retrFile*[T](ftp: PFtpBase[T], file, dest: string, async = false) =
   ## Downloads ``file`` and saves it to ``dest``. Usage of this function
   ## asynchronously is recommended to view the progress of the download.
   ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function 
   ## when the download is finished, and the ``filename`` field will be equal
   ## to ``file``.
-  ftp.createJob(getFile, JRetr)
+  ftp.createJob(getFile[T], JRetr)
   ftp.job.file = open(dest, mode = fmWrite)
   ftp.pasv()
   var reply = ftp.send("RETR " & file.normalizePathSep)
@@ -468,11 +477,11 @@ proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) =
     while not ftp.job.prc(ftp, false): discard
     ftp.deleteJob()
 
-proc doUpload(ftp: PFTPClient, async = false): bool =
+proc doUpload[T](ftp: PFtpBase[T], async = false): bool =
   if ftp.dsockConnected:
     if ftp.job.toStore.len() > 0:
       assert(async)
-      let bytesSent = ftp.asyncDSock.sendAsync(ftp.job.toStore)
+      let bytesSent = ftp.dsock.sendAsync(ftp.job.toStore)
       if bytesSent == ftp.job.toStore.len:
         ftp.job.toStore = ""
       elif bytesSent != ftp.job.toStore.len and bytesSent != 0:
@@ -485,7 +494,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       setLen(s, len)
       if len == 0:
         # File finished uploading.
-        if ftp.isAsync: ftp.asyncDSock.close() else: ftp.dsock.close()
+        ftp.dsock.close()
         ftp.dsockConnected = false
   
         if not async:
@@ -496,7 +505,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       if not async:
         getDSock(ftp).send(s)
       else:
-        let bytesSent = ftp.asyncDSock.sendAsync(s)
+        let bytesSent = ftp.dsock.sendAsync(s)
         if bytesSent == 0:
           ftp.job.toStore.add(s)
         elif bytesSent != s.len:
@@ -506,14 +515,14 @@ proc doUpload(ftp: PFTPClient, async = false): bool =
       ftp.job.progress.inc(len)
       ftp.job.oneSecond.inc(len)
 
-proc store*(ftp: PFTPClient, file, dest: string, async = false) =
+proc store*[T](ftp: PFtpBase[T], file, dest: string, async = false) =
   ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this
   ## function asynchronously is recommended to view the progress of
   ## the download.
   ## The ``EvStore`` event is passed to the specified ``handleEvent`` function 
   ## when the upload is finished, and the ``filename`` field will be 
   ## equal to ``file``.
-  ftp.createJob(doUpload, JStore)
+  ftp.createJob(doUpload[T], JStore)
   ftp.job.file = open(file)
   ftp.job.total = ftp.job.file.getFileSize()
   ftp.job.lastProgressReport = epochTime()
@@ -526,16 +535,12 @@ proc store*(ftp: PFTPClient, file, dest: string, async = false) =
     while not ftp.job.prc(ftp, false): discard
     ftp.deleteJob()
 
-proc close*(ftp: PFTPClient) =
+proc close*[T](ftp: PFTPBase[T]) =
   ## Terminates the connection to the server.
   assertReply ftp.send("QUIT"), "221"
   if ftp.jobInProgress: ftp.deleteJob()
-  if ftp.isAsync:
-    ftp.asyncCSock.close()
-    ftp.asyncDSock.close()
-  else:
-    ftp.csock.close()
-    ftp.dsock.close()
+  ftp.csock.close()
+  ftp.dsock.close()
 
 proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
   if ftp.jobInProgress:
@@ -572,66 +577,65 @@ proc asyncFTPClient*(address: string, port = TPort(21),
   dres.pass = pass
   dres.address = address
   dres.port = port
-  dres.isAsync = true
   dres.dsockConnected = false
   dres.handleEvent = handleEvent
-  dres.asyncCSock = AsyncSocket()
-  dres.asyncCSock.handleRead =
+  dres.csock = AsyncSocket()
+  dres.csock.handleRead =
     proc (s: PAsyncSocket) =
       csockHandleRead(s, dres)
   result = dres
 
 proc register*(d: PDispatcher, ftp: PAsyncFTPClient): PDelegate {.discardable.} =
   ## Registers ``ftp`` with dispatcher ``d``.
-  assert ftp.isAsync
   ftp.disp = d
-  return ftp.disp.register(ftp.asyncCSock)
+  return ftp.disp.register(ftp.csock)
 
 when isMainModule:
-  var d = newDispatcher()
-  let hev =
-    proc (ftp: PAsyncFTPClient, event: TFTPEvent) =
-      case event.typ
-      of EvStore:
-        echo("Upload finished!")
-        ftp.retrFile("payload.JPG", "payload2.JPG", async = true)
-      of EvTransferProgress:
-        var time: int64 = -1
-        if event.speed != 0:
-          time = (event.bytesTotal - event.bytesFinished) div event.speed
-        echo(event.currentJob)
-        echo(event.speed div 1000, " kb/s. - ",
-             event.bytesFinished, "/", event.bytesTotal,
-             " - ", time, " seconds")
-        echo(d.len)
-      of EvRetr:
-        echo("Download finished!")
-        ftp.close()
-        echo d.len
-      else: assert(false)
-  var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev)
-  
-  d.register(ftp)
-  d.len.echo()
-  ftp.connect()
-  echo "connected"
-  ftp.store("payload.JPG", "payload.JPG", async = true)
-  d.len.echo()
-  echo "uploading..."
-  while true:
-    if not d.poll(): break
-
+  proc main =
+    var d = newDispatcher()
+    let hev =
+      proc (ftp: PAsyncFTPClient, event: TFTPEvent) =
+        case event.typ
+        of EvStore:
+          echo("Upload finished!")
+          ftp.retrFile("payload.jpg", "payload2.jpg", async = true)
+        of EvTransferProgress:
+          var time: int64 = -1
+          if event.speed != 0:
+            time = (event.bytesTotal - event.bytesFinished) div event.speed
+          echo(event.currentJob)
+          echo(event.speed div 1000, " kb/s. - ",
+               event.bytesFinished, "/", event.bytesTotal,
+               " - ", time, " seconds")
+          echo(d.len)
+        of EvRetr:
+          echo("Download finished!")
+          ftp.close()
+          echo d.len
+        else: assert(false)
+    var ftp = asyncFTPClient("example.com", user = "foo", pass = "bar", handleEvent = hev)
+    
+    d.register(ftp)
+    d.len.echo()
+    ftp.connect()
+    echo "connected"
+    ftp.store("payload.jpg", "payload.jpg", async = true)
+    d.len.echo()
+    echo "uploading..."
+    while true:
+      if not d.poll(): break
+  main()
 
 when isMainModule and false:
-  var ftp = ftpClient("picheta.me", user = "asdasd", pass = "asfwq")
+  var ftp = ftpClient("example.com", user = "foo", pass = "bar")
   ftp.connect()
   echo ftp.pwd()
   echo ftp.list()
   echo("uploading")
-  ftp.store("payload.JPG", "payload.JPG", async = false)
+  ftp.store("payload.jpg", "payload.jpg", async = false)
 
   echo("Upload complete")
-  ftp.retrFile("payload.JPG", "payload2.JPG", async = false)
+  ftp.retrFile("payload.jpg", "payload2.jpg", async = false)
 
   echo("Download complete")
   sleep(5000)
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 9bacc80d6..4db6ac6ed 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -654,8 +654,7 @@ when isMainModule:
       resp = await client.request("http://nimrod-lang.org/download.html")
       echo("Got response: ", resp.status)
 
-    asyncCheck main()
-    runForever()
+    waitFor main()
 
   else:
     #downloadFile("http://force7.de/nimrod/index.html", "nimrodindex.html")
diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim
deleted file mode 100644
index 49d9a9a34..000000000
--- a/lib/pure/irc.nim
+++ /dev/null
@@ -1,503 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2012 Dominik Picheta
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements an asynchronous IRC client.
-## 
-## Currently this module requires at least some knowledge of the IRC protocol.
-## It provides a function for sending raw messages to the IRC server, together
-## with some basic functions like sending a message to a channel. 
-## It automizes the process of keeping the connection alive, so you don't
-## need to reply to PING messages. In fact, the server is also PING'ed to check 
-## the amount of lag.
-##
-## .. code-block:: Nimrod
-##
-##   var client = irc("picheta.me", joinChans = @["#bots"])
-##   client.connect()
-##   while True:
-##     var event: TIRCEvent
-##     if client.poll(event):
-##       case event.typ
-##       of EvConnected: nil
-##       of EvDisconnected:
-##         client.reconnect()
-##       of EvMsg:
-##         # Write your message reading code here.
-## 
-## **Warning:** The API of this module is unstable, and therefore is subject
-## to change.
-
-include "system/inclrtl"
-
-import sockets, strutils, parseutils, times, asyncio, os
-
-type
-  TIRC* = object of TObject
-    address: string
-    port: TPort
-    nick, user, realname, serverPass: string
-    case isAsync: bool
-    of true:
-      handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure, gcsafe.}
-      asyncSock: PAsyncSocket
-      myDispatcher: PDispatcher
-    of false:
-      dummyA: pointer
-      dummyB: pointer # workaround a Nimrod API issue
-      dummyC: pointer
-      sock: TSocket
-    status: TInfo
-    lastPing: float
-    lastPong: float
-    lag: float
-    channelsToJoin: seq[string]
-    msgLimit: bool
-    messageBuffer: seq[tuple[timeToSend: float, m: string]]
-    lastReconnect: float
-
-  PIRC* = ref TIRC
-
-  PAsyncIRC* = ref TAsyncIRC
-  TAsyncIRC* = object of TIRC
-
-  TIRCMType* = enum
-    MUnknown,
-    MNumeric,
-    MPrivMsg,
-    MJoin,
-    MPart,
-    MMode,
-    MTopic,
-    MInvite,
-    MKick,
-    MQuit,
-    MNick,
-    MNotice,
-    MPing,
-    MPong,
-    MError
-  
-  TIRCEventType* = enum
-    EvMsg, EvConnected, EvDisconnected
-  TIRCEvent* = object ## IRC Event
-    case typ*: TIRCEventType
-    of EvConnected:
-      ## Connected to server.
-      ## Only occurs with AsyncIRC.
-      nil
-    of EvDisconnected: 
-      ## Disconnected from the server
-      nil
-    of EvMsg:              ## Message from the server
-      cmd*: TIRCMType      ## Command (e.g. PRIVMSG)
-      nick*, user*, host*, servername*: string
-      numeric*: string     ## Only applies to ``MNumeric``
-      params*: seq[string] ## Parameters of the IRC message
-      origin*: string      ## The channel/user that this msg originated from
-      raw*: string         ## Raw IRC message
-      timestamp*: TTime    ## UNIX epoch time the message was received
-  
-proc send*(irc: PIRC, message: string, sendImmediately = false) =
-  ## Sends ``message`` as a raw command. It adds ``\c\L`` for you.
-  var sendMsg = true
-  if irc.msgLimit and not sendImmediately:
-    var timeToSend = epochTime()
-    if irc.messageBuffer.len() >= 3:
-      timeToSend = (irc.messageBuffer[irc.messageBuffer.len()-1][0] + 2.0)
-
-    irc.messageBuffer.add((timeToSend, message))
-    sendMsg = false
-
-  if sendMsg:
-    try:
-      if irc.isAsync:
-        irc.asyncSock.send(message & "\c\L")
-      else:
-        irc.sock.send(message & "\c\L")
-    except EOS:
-      # Assuming disconnection of every EOS could be bad,
-      # but I can't exactly check for EBrokenPipe.
-      irc.status = SockClosed
-
-proc privmsg*(irc: PIRC, target, message: string) =
-  ## Sends ``message`` to ``target``. ``Target`` can be a channel, or a user.
-  irc.send("PRIVMSG $1 :$2" % [target, message])
-
-proc notice*(irc: PIRC, target, message: string) =
-  ## Sends ``notice`` to ``target``. ``Target`` can be a channel, or a user. 
-  irc.send("NOTICE $1 :$2" % [target, message])
-
-proc join*(irc: PIRC, channel: string, key = "") =
-  ## Joins ``channel``.
-  ## 
-  ## If key is not ``""``, then channel is assumed to be key protected and this
-  ## function will join the channel using ``key``.
-  if key == "":
-    irc.send("JOIN " & channel)
-  else:
-    irc.send("JOIN " & channel & " " & key)
-
-proc part*(irc: PIRC, channel, message: string) =
-  ## Leaves ``channel`` with ``message``.
-  irc.send("PART " & channel & " :" & message)
-
-proc close*(irc: PIRC) =
-  ## Closes connection to an IRC server.
-  ##
-  ## **Warning:** This procedure does not send a ``QUIT`` message to the server.
-  irc.status = SockClosed
-  if irc.isAsync:
-    irc.asyncSock.close()
-  else:
-    irc.sock.close()
-
-proc isNumber(s: string): bool =
-  ## Checks if `s` contains only numbers.
-  var i = 0
-  while s[i] in {'0'..'9'}: inc(i)
-  result = i == s.len and s.len > 0
-
-proc parseMessage(msg: string): TIRCEvent =
-  result.typ       = EvMsg
-  result.cmd       = MUnknown
-  result.raw       = msg
-  result.timestamp = times.getTime()
-  var i = 0
-  # Process the prefix
-  if msg[i] == ':':
-    inc(i) # Skip `:`
-    var nick = ""
-    i.inc msg.parseUntil(nick, {'!', ' '}, i)
-    result.nick = ""
-    result.serverName = ""
-    if msg[i] == '!':
-      result.nick = nick
-      inc(i) # Skip `!`
-      i.inc msg.parseUntil(result.user, {'@'}, i)
-      inc(i) # Skip `@`
-      i.inc msg.parseUntil(result.host, {' '}, i)
-      inc(i) # Skip ` `
-    else:
-      result.serverName = nick
-      inc(i) # Skip ` `
-  
-  # Process command
-  var cmd = ""
-  i.inc msg.parseUntil(cmd, {' '}, i)
-
-  if cmd.isNumber:
-    result.cmd = MNumeric
-    result.numeric = cmd
-  else:
-    case cmd
-    of "PRIVMSG": result.cmd = MPrivMsg
-    of "JOIN": result.cmd = MJoin
-    of "PART": result.cmd = MPart
-    of "PONG": result.cmd = MPong
-    of "PING": result.cmd = MPing
-    of "MODE": result.cmd = MMode
-    of "TOPIC": result.cmd = MTopic
-    of "INVITE": result.cmd = MInvite
-    of "KICK": result.cmd = MKick
-    of "QUIT": result.cmd = MQuit
-    of "NICK": result.cmd = MNick
-    of "NOTICE": result.cmd = MNotice
-    of "ERROR": result.cmd = MError
-    else: result.cmd = MUnknown
-  
-  # Don't skip space here. It is skipped in the following While loop.
-  
-  # Params
-  result.params = @[]
-  var param = ""
-  while msg[i] != '\0' and msg[i] != ':':
-    inc(i) # Skip ` `.
-    i.inc msg.parseUntil(param, {' ', ':', '\0'}, i)
-    if param != "":
-      result.params.add(param)
-      param.setlen(0)
-  
-  if msg[i] == ':':
-    inc(i) # Skip `:`.
-    result.params.add(msg[i..msg.len-1])
-
-proc connect*(irc: PIRC) =
-  ## Connects to an IRC server as specified by ``irc``.
-  assert(irc.address != "")
-  assert(irc.port != TPort(0))
-  
-  irc.sock.connect(irc.address, irc.port)
- 
-  irc.status = SockConnected
-  
-  # Greet the server :)
-  if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true)
-  irc.send("NICK " & irc.nick, true)
-  irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true)
-
-proc reconnect*(irc: PIRC, timeout = 5000) =
-  ## Reconnects to an IRC server.
-  ##
-  ## ``Timeout`` specifies the time to wait in miliseconds between multiple
-  ## consecutive reconnections.
-  ##
-  ## This should be used when an ``EvDisconnected`` event occurs.
-  let secSinceReconnect = int(epochTime() - irc.lastReconnect)
-  if secSinceReconnect < timeout:
-    sleep(timeout - secSinceReconnect)
-  irc.sock = socket()
-  if irc.sock == InvalidSocket: osError(osLastError())
-  irc.connect()
-  irc.lastReconnect = epochTime()
-
-proc irc*(address: string, port: TPort = 6667.TPort,
-         nick = "NimrodBot",
-         user = "NimrodBot",
-         realname = "NimrodBot", serverPass = "",
-         joinChans: seq[string] = @[],
-         msgLimit: bool = true): PIRC =
-  ## Creates a ``TIRC`` object.
-  new(result)
-  result.address = address
-  result.port = port
-  result.nick = nick
-  result.user = user
-  result.realname = realname
-  result.serverPass = serverPass
-  result.lastPing = epochTime()
-  result.lastPong = -1.0
-  result.lag = -1.0
-  result.channelsToJoin = joinChans
-  result.msgLimit = msgLimit
-  result.messageBuffer = @[]
-  result.status = SockIdle
-  result.sock = socket()
-  if result.sock == InvalidSocket: osError(osLastError())
-
-proc processLine(irc: PIRC, line: string): TIRCEvent =
-  if line.len == 0:
-    irc.close()
-    result.typ = EvDisconnected
-  else:
-    result = parseMessage(line)
-    # Get the origin
-    result.origin = result.params[0]
-    if result.origin == irc.nick and
-       result.nick != "": result.origin = result.nick
-
-    if result.cmd == MError:
-      irc.close()
-      result.typ = EvDisconnected
-      return
-
-    if result.cmd == MPing:
-      irc.send("PONG " & result.params[0])
-    if result.cmd == MPong:
-      irc.lag = epochTime() - parseFloat(result.params[result.params.high])
-      irc.lastPong = epochTime()
-    if result.cmd == MNumeric:
-      if result.numeric == "001":
-        # Check the nickname.
-        if irc.nick != result.params[0]:
-          assert ' ' notin result.params[0]
-          irc.nick = result.params[0]
-        for chan in items(irc.channelsToJoin):
-          irc.join(chan)
-    if result.cmd == MNick:
-      if result.nick == irc.nick:
-        irc.nick = result.params[0]
-    
-proc processOther(irc: PIRC, ev: var TIRCEvent): bool =
-  result = false
-  if epochTime() - irc.lastPing >= 20.0:
-    irc.lastPing = epochTime()
-    irc.send("PING :" & formatFloat(irc.lastPing), true)
-
-  if epochTime() - irc.lastPong >= 120.0 and irc.lastPong != -1.0:
-    irc.close()
-    ev.typ = EvDisconnected # TODO: EvTimeout?
-    return true
-  
-  for i in 0..irc.messageBuffer.len-1:
-    if epochTime() >= irc.messageBuffer[0][0]:
-      irc.send(irc.messageBuffer[0].m, true)
-      irc.messageBuffer.delete(0)
-    else:
-      break # messageBuffer is guaranteed to be from the quickest to the
-            # later-est.
-
-proc poll*(irc: PIRC, ev: var TIRCEvent,
-           timeout: int = 500): bool =
-  ## This function parses a single message from the IRC server and returns 
-  ## a TIRCEvent.
-  ##
-  ## This function should be called often as it also handles pinging
-  ## the server.
-  ##
-  ## This function provides a somewhat asynchronous IRC implementation, although
-  ## it should only be used for simple things for example an IRC bot which does
-  ## not need to be running many time critical tasks in the background. If you
-  ## require this, use the asyncio implementation.
-  
-  if not (irc.status == SockConnected):
-    # Do not close the socket here, it is already closed!
-    ev.typ = EvDisconnected
-  var line = TaintedString""
-  var socks = @[irc.sock]
-  var ret = socks.select(timeout)
-  if ret == -1: osError(osLastError())
-  if socks.len() != 0 and ret != 0:
-    irc.sock.readLine(line)
-    ev = irc.processLine(line.string)
-    result = true
-
-  if processOther(irc, ev): result = true
-
-proc getLag*(irc: PIRC): float =
-  ## Returns the latency between this client and the IRC server in seconds.
-  ## 
-  ## If latency is unknown, returns -1.0.
-  return irc.lag
-
-proc isConnected*(irc: PIRC): bool =
-  ## Returns whether this IRC client is connected to an IRC server.
-  return irc.status == SockConnected
-
-proc getNick*(irc: PIRC): string =
-  ## Returns the current nickname of the client.
-  return irc.nick
-
-# -- Asyncio dispatcher
-
-proc handleConnect(s: PAsyncSocket, irc: PAsyncIRC) =  
-  # Greet the server :)
-  if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true)
-  irc.send("NICK " & irc.nick, true)
-  irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true)
-  irc.status = SockConnected
-  
-  var ev: TIRCEvent
-  ev.typ = EvConnected
-  irc.handleEvent(irc, ev)
-
-proc handleRead(s: PAsyncSocket, irc: PAsyncIRC) =
-  var line = "".TaintedString
-  var ret = s.readLine(line)
-  if ret:
-    if line == "":
-      var ev: TIRCEvent
-      irc.close()
-      ev.typ = EvDisconnected
-      irc.handleEvent(irc, ev)
-    else:
-      var ev = irc.processLine(line.string)
-      irc.handleEvent(irc, ev)
-  
-proc handleTask(s: PAsyncSocket, irc: PAsyncIRC) =
-  var ev: TIRCEvent
-  if irc.processOther(ev):
-    irc.handleEvent(irc, ev)
-
-proc register*(d: PDispatcher, irc: PAsyncIRC) =
-  ## Registers ``irc`` with dispatcher ``d``.
-  irc.asyncSock.handleConnect =
-    proc (s: PAsyncSocket) =
-      handleConnect(s, irc)
-  irc.asyncSock.handleRead =
-    proc (s: PAsyncSocket) =
-      handleRead(s, irc)
-  irc.asyncSock.handleTask =
-    proc (s: PAsyncSocket) =
-      handleTask(s, irc)
-  d.register(irc.asyncSock)
-  irc.myDispatcher = d
-
-proc connect*(irc: PAsyncIRC) =
-  ## Equivalent of connect for ``TIRC`` but specifically created for asyncio.
-  assert(irc.address != "")
-  assert(irc.port != TPort(0))
-  
-  irc.asyncSock.connect(irc.address, irc.port)
-
-proc reconnect*(irc: PAsyncIRC, timeout = 5000) =
-  ## Reconnects to an IRC server.
-  ##
-  ## ``Timeout`` specifies the time to wait in miliseconds between multiple
-  ## consecutive reconnections.
-  ##
-  ## This should be used when an ``EvDisconnected`` event occurs.
-  ##
-  ## When successfully reconnected an ``EvConnected`` event will occur.
-  let secSinceReconnect = int(epochTime() - irc.lastReconnect)
-  if secSinceReconnect < timeout:
-    sleep(timeout - secSinceReconnect)
-  irc.asyncSock = AsyncSocket()
-  irc.myDispatcher.register(irc)
-  irc.connect()
-  irc.lastReconnect = epochTime()
-
-proc asyncIRC*(address: string, port: TPort = 6667.TPort,
-              nick = "NimrodBot",
-              user = "NimrodBot",
-              realname = "NimrodBot", serverPass = "",
-              joinChans: seq[string] = @[],
-              msgLimit: bool = true,
-              ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure,gcsafe.}
-              ): PAsyncIRC =
-  ## Use this function if you want to use asyncio's dispatcher.
-  ## 
-  ## **Note:** Do **NOT** use this if you're writing a simple IRC bot which only
-  ## requires one task to be run, i.e. this should not be used if you want a
-  ## synchronous IRC client implementation, use ``irc`` for that.
-  
-  new(result)
-  result.isAsync = true
-  result.address = address
-  result.port = port
-  result.nick = nick
-  result.user = user
-  result.realname = realname
-  result.serverPass = serverPass
-  result.lastPing = epochTime()
-  result.lastPong = -1.0
-  result.lag = -1.0
-  result.channelsToJoin = joinChans
-  result.msgLimit = msgLimit
-  result.messageBuffer = @[]
-  result.handleEvent = ircEvent
-  result.asyncSock = AsyncSocket()
-  
-when isMainModule:
-  #var m = parseMessage("ERROR :Closing Link: dom96.co.cc (Ping timeout: 252 seconds)")
-  #echo(repr(m))
-
-
-  
-  var client = irc("amber.tenthbit.net", nick="TestBot1234",
-                   joinChans = @["#flood"])
-  client.connect()
-  while true:
-    var event: TIRCEvent
-    if client.poll(event):
-      case event.typ
-      of EvConnected:
-        discard
-      of EvDisconnected:
-        break
-      of EvMsg:
-        if event.cmd == MPrivMsg:
-          var msg = event.params[event.params.high]
-          if msg == "|test": client.privmsg(event.origin, "hello")
-          if msg == "|excessFlood":
-            for i in 0..10:
-              client.privmsg(event.origin, "TEST" & $i)
-
-        #echo( repr(event) )
-      #echo("Lag: ", formatFloat(client.getLag()))
-  
-    
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index a45900f29..5d51c2d87 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -7,47 +7,71 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements a simple high performance `JSON`:idx:
-## parser. JSON (JavaScript Object Notation) is a lightweight 
-## data-interchange format that is easy for humans to read and write 
-## (unlike XML). It is easy for machines to parse and generate.
-## JSON is based on a subset of the JavaScript Programming Language,
-## Standard ECMA-262 3rd Edition - December 1999.
+## This module implements a simple high performance `JSON`:idx: parser. `JSON
+## (JavaScript Object Notation) <http://www.json.org>`_ is a lightweight
+## data-interchange format that is easy for humans to read and write (unlike
+## XML). It is easy for machines to parse and generate.  JSON is based on a
+## subset of the JavaScript Programming Language, `Standard ECMA-262 3rd
+## Edition - December 1999
+## <http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf>`_.
 ##
-## Usage example:
+## Parsing small values quickly can be done with the convenience `parseJson()
+## <#parseJson,string>`_ proc which returns the whole JSON tree.  If you are
+## parsing very big JSON inputs or want to skip most of the items in them you
+## can initialize your own `TJsonParser <#TJsonParser>`_ with the `open()
+## <#open>`_ proc and call `next() <#next>`_ in a loop to process the
+## individual parsing events.
+##
+## If you need to create JSON objects from your Nimrod types you can call procs
+## like `newJObject() <#newJObject>`_ (or their equivalent `%()
+## <#%,openArray[tuple[string,PJsonNode]]>`_ generic constructor). For
+## consistency you can provide your own ``%`` operators for custom object
+## types:
 ##
 ## .. code-block:: nimrod
-##  let
-##    small_json = """{"test": 1.3, "key2": true}"""
-##    jobj = parseJson(small_json)
-##  assert (jobj.kind == JObject)
-##  echo($jobj["test"].fnum)
-##  echo($jobj["key2"].bval)
+##   type
+##     Person = object ## Generic person record.
+##       age: int      ## The age of the person.
+##       name: string  ## The name of the person.
 ##
-## Results in:
+##   proc `%`(p: Person): PJsonNode =
+##     ## Converts a Person into a PJsonNode.
+##     result = %[("age", %p.age), ("name", %p.name)]
 ##
-## .. code-block:: nimrod
+##   proc test() =
+##     # Tests making some jsons.
+##     var p: Person
+##     p.age = 24
+##     p.name = "Minah"
+##     echo(%p) # { "age": 24,  "name": "Minah"}
+##
+##     p.age = 33
+##     p.name = "Sojin"
+##     echo(%p) # { "age": 33,  "name": "Sojin"}
 ##
-##   1.3000000000000000e+00
-##   true
+## If you don't need special logic in your Nimrod objects' serialization code
+## you can also use the `marshal module <marshal.html>`_ which converts objects
+## directly to JSON.
 
 import 
   hashes, strutils, lexbase, streams, unicode
 
 type 
-  TJsonEventKind* = enum ## enumeration of all events that may occur when parsing
-    jsonError,           ## an error ocurred during parsing
-    jsonEof,             ## end of file reached
-    jsonString,          ## a string literal
-    jsonInt,             ## an integer literal
-    jsonFloat,           ## a float literal
-    jsonTrue,            ## the value ``true``
-    jsonFalse,           ## the value ``false``
-    jsonNull,            ## the value ``null``
-    jsonObjectStart,     ## start of an object: the ``{`` token
-    jsonObjectEnd,       ## end of an object: the ``}`` token
-    jsonArrayStart,      ## start of an array: the ``[`` token
-    jsonArrayEnd         ## start of an array: the ``]`` token
+  TJsonEventKind* = enum ## Events that may occur when parsing. \
+    ##
+    ## You compare these values agains the result of the `kind() proc <#kind>`_.
+    jsonError,           ## An error ocurred during parsing.
+    jsonEof,             ## End of file reached.
+    jsonString,          ## A string literal.
+    jsonInt,             ## An integer literal.
+    jsonFloat,           ## A float literal.
+    jsonTrue,            ## The value ``true``.
+    jsonFalse,           ## The value ``false``.
+    jsonNull,            ## The value ``null``.
+    jsonObjectStart,     ## Start of an object: the ``{`` token.
+    jsonObjectEnd,       ## End of an object: the ``}`` token.
+    jsonArrayStart,      ## Start of an array: the ``[`` token.
+    jsonArrayEnd         ## Start of an array: the ``]`` token.
     
   TTokKind = enum        # must be synchronized with TJsonEventKind!
     tkError,
@@ -65,7 +89,7 @@ type
     tkColon,
     tkComma
     
-  TJsonError* = enum       ## enumeration that lists all errors that can occur
+  TJsonError = enum        ## enumeration that lists all errors that can occur
     errNone,               ## no error
     errInvalidToken,       ## invalid token
     errStringExpected,     ## string expected
@@ -82,7 +106,9 @@ type
     stateEof, stateStart, stateObject, stateArray, stateExpectArrayComma,
     stateExpectObjectComma, stateExpectColon, stateExpectValue
 
-  TJsonParser* = object of TBaseLexer ## the parser object.
+  TJsonParser* = object of TBaseLexer ## The JSON parser object. \
+    ##
+    ## Create a variable of this type and use `open() <#open>`_ on it.
     a: string
     tok: TTokKind
     kind: TJsonEventKind
@@ -117,59 +143,129 @@ const
   ]
 
 proc open*(my: var TJsonParser, input: PStream, filename: string) =
-  ## initializes the parser with an input stream. `Filename` is only used
-  ## for nice error messages.
-  lexbase.open(my, input)
+  ## Initializes the JSON parser with an `input stream <streams.html>`_.
+  ##
+  ## The `filename` parameter is not strictly required and is used only for
+  ## nice error messages. You can pass ``nil`` as long as you never use procs
+  ## like `errorMsg() <#errorMsg>`_ or `errorMsgExpected()
+  ## <#errorMsgExpected>`_ but passing a dummy filename like ``<input string>``
+  ## is safer and more user friendly. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   import json, streams
+  ##
+  ##   var
+  ##     s = newStringStream("some valid json")
+  ##     p: TJsonParser
+  ##   p.open(s, "<input string>")
+  ##
+  ## Once opened, you can process JSON parsing events with the `next()
+  ## <#next>`_ proc.
   my.filename = filename
   my.state = @[stateStart]
   my.kind = jsonError
   my.a = ""
   
-proc close*(my: var TJsonParser) {.inline.} = 
-  ## closes the parser `my` and its associated input stream.
+proc close*(my: var TJsonParser) {.inline.} =
+  ## Closes the parser `my` and its associated input stream.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var
+  ##     s = newStringStream("some valid json")
+  ##     p: TJsonParser
+  ##   p.open(s, "<input string>")
+  ##   finally: p.close
+  ##   # write here parsing of input
   lexbase.close(my)
 
 proc str*(my: TJsonParser): string {.inline.} = 
-  ## returns the character data for the events: ``jsonInt``, ``jsonFloat``, 
-  ## ``jsonString``
+  ## Returns the character data for the `events <#TJsonEventKind>`_
+  ## ``jsonInt``, ``jsonFloat`` and ``jsonString``.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds when used
+  ## with other event types. See `next() <#next>`_ for an usage example.
   assert(my.kind in {jsonInt, jsonFloat, jsonString})
   return my.a
 
 proc getInt*(my: TJsonParser): BiggestInt {.inline.} = 
-  ## returns the number for the event: ``jsonInt``
+  ## Returns the number for the `jsonInt <#TJsonEventKind>`_ event.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds when used
+  ## with other event types. See `next() <#next>`_ for an usage example.
   assert(my.kind == jsonInt)
   return parseBiggestInt(my.a)
 
 proc getFloat*(my: TJsonParser): float {.inline.} = 
-  ## returns the number for the event: ``jsonFloat``
+  ## Returns the number for the `jsonFloat <#TJsonEventKind>`_ event.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds when used
+  ## with other event types. See `next() <#next>`_ for an usage example.
   assert(my.kind == jsonFloat)
   return parseFloat(my.a)
 
 proc kind*(my: TJsonParser): TJsonEventKind {.inline.} = 
-  ## returns the current event type for the JSON parser
+  ## Returns the current event type for the `JSON parser <#TJsonParser>`_.
+  ##
+  ## Call this proc just after `next() <#next>`_ to act on the new event.
   return my.kind
   
 proc getColumn*(my: TJsonParser): int {.inline.} = 
-  ## get the current column the parser has arrived at.
+  ## Get the current column the parser has arrived at.
+  ##
+  ## While this is mostly used by procs like `errorMsg() <#errorMsg>`_ you can
+  ## use it as well to show user warnings if you are validating JSON values
+  ## during parsing. See `next() <#next>`_ for the full example:
+  ##
+  ## .. code-block:: nimrod
+  ##   case parser.kind
+  ##   ...
+  ##   of jsonString:
+  ##     let inputValue = parser.str
+  ##     if previousValues.contains(inputValue):
+  ##       echo "$1($2, $3) Warning: repeated value '$4'" % [
+  ##         parser.getFilename, $parser.getLine, $parser.getColumn,
+  ##          inputValue]
+  ##   ...
   result = getColNumber(my, my.bufpos)
 
 proc getLine*(my: TJsonParser): int {.inline.} = 
-  ## get the current line the parser has arrived at.
+  ## Get the current line the parser has arrived at.
+  ##
+  ## While this is mostly used by procs like `errorMsg() <#errorMsg>`_ you can
+  ## use it as well to indicate user warnings if you are validating JSON values
+  ## during parsing. See `next() <#next>`_ and `getColumn() <#getColumn>`_ for
+  ## examples.
   result = my.lineNumber
 
 proc getFilename*(my: TJsonParser): string {.inline.} = 
-  ## get the filename of the file that the parser processes.
+  ## Get the filename of the file that the parser is processing.
+  ##
+  ## This is the value you pass to the `open() <#open>`_ proc.  While this is
+  ## mostly used by procs like `errorMsg() <#errorMsg>`_ you can use it as well
+  ## to indicate user warnings if you are validating JSON values during
+  ## parsing. See `next() <#next>`_ and `getColumn() <#getColumn>`_ for
+  ## examples.
   result = my.filename
   
 proc errorMsg*(my: TJsonParser): string = 
-  ## returns a helpful error message for the event ``jsonError``
+  ## Returns a helpful error message for the `jsonError <#TJsonEventKind>`_
+  ## event.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds when used
+  ## with other event types. See `next() <#next>`_ for an usage example.
   assert(my.kind == jsonError)
   result = "$1($2, $3) Error: $4" % [
     my.filename, $getLine(my), $getColumn(my), errorMessages[my.err]]
 
 proc errorMsgExpected*(my: TJsonParser, e: string): string = 
-  ## returns an error message "`e` expected" in the same format as the
-  ## other error messages 
+  ## Returns an error message "`e` expected".
+  ##
+  ## The message is in the same format as the other error messages which
+  ## include the parser filename, line and column values. This is used by
+  ## `raiseParseErr() <#raiseParseErr>`_ to raise  an `EJsonParsingError
+  ## <#EJsonParsingError>`_.
   result = "$1($2, $3) Error: $4" % [
     my.filename, $getLine(my), $getColumn(my), e & " expected"]
 
@@ -382,7 +478,32 @@ proc getTok(my: var TJsonParser): TTokKind =
   my.tok = result
 
 proc next*(my: var TJsonParser) = 
-  ## retrieves the first/next event. This controls the parser.
+  ## Retrieves the first/next event for the `JSON parser <#TJsonParser>`_.
+  ##
+  ## You are meant to call this method inside an infinite loop. After each
+  ## call, check the result of the `kind() <#kind>`_ proc to know what has to
+  ## be done next (eg. break out due to end of file). Here is a basic example
+  ## which simply echoes all found elements by the parser:
+  ##
+  ## .. code-block:: nimrod
+  ##   parser.open(stream, "<input string>")
+  ##   while true:
+  ##     parser.next
+  ##     case parser.kind
+  ##     of jsonError:
+  ##       echo parser.errorMsg
+  ##       break
+  ##     of jsonEof: break
+  ##     of jsonString: echo parser.str
+  ##     of jsonInt: echo parser.getInt
+  ##     of jsonFloat: echo parser.getFloat
+  ##     of jsonTrue: echo "true"
+  ##     of jsonFalse: echo "false"
+  ##     of jsonNull: echo "null"
+  ##     of jsonObjectStart: echo "{"
+  ##     of jsonObjectEnd: echo "}"
+  ##     of jsonArrayStart: echo "["
+  ##     of jsonArrayEnd: echo "]"
   var tk = getTok(my)
   var i = my.state.len-1
   # the following code is a state machine. If we had proper coroutines,
@@ -502,7 +623,16 @@ proc next*(my: var TJsonParser) =
 # ------------- higher level interface ---------------------------------------
 
 type
-  TJsonNodeKind* = enum ## possible JSON node types
+  TJsonNodeKind* = enum ## Possible `JSON node <#TJsonNodeKind>`_ types. \
+    ##
+    ## To build nodes use the helper procs
+    ## `newJNull() <#newJNull>`_,
+    ## `newJBool() <#newJBool>`_,
+    ## `newJInt() <#newJInt>`_,
+    ## `newJFloat() <#newJFloat>`_,
+    ## `newJString() <#newJString>`_,
+    ## `newJObject() <#newJObject>`_ and
+    ## `newJArray() <#newJArray>`_.
     JNull,
     JBool,
     JInt,
@@ -511,8 +641,9 @@ type
     JObject,
     JArray
     
-  PJsonNode* = ref TJsonNode ## JSON node 
-  TJsonNode* {.final, pure, acyclic.} = object
+  PJsonNode* = ref TJsonNode ## Reference to a `JSON node <#TJsonNode>`_.
+  TJsonNode* {.final, pure, acyclic.} = object ## `Object variant \
+    ## <manual.html#object-variants>`_ wrapping all possible JSON types.
     case kind*: TJsonNodeKind
     of JString:
       str*: string
@@ -529,14 +660,36 @@ type
     of JArray:
       elems*: seq[PJsonNode]
 
-  EJsonParsingError* = object of EInvalidValue ## is raised for a JSON error
+  EJsonParsingError* = object of EInvalidValue ## Raised during JSON parsing. \
+    ##
+    ## Example:
+    ##
+    ## .. code-block:: nimrod
+    ##   let smallJson = """{"test: 1.3, "key2": true}"""
+    ##   try:
+    ##     discard parseJson(smallJson)
+    ##     # --> Bad JSON! input(1, 18) Error: : expected
+    ##   except EJsonParsingError:
+    ##     echo "Bad JSON! " & getCurrentExceptionMsg()
 
 proc raiseParseErr*(p: TJsonParser, msg: string) {.noinline, noreturn.} =
-  ## raises an `EJsonParsingError` exception.
+  ## Raises an `EJsonParsingError <#EJsonParsingError>`_ exception.
+  ##
+  ## The message for the exception will be built passing the `msg` parameter to
+  ## the `errorMsgExpected() <#errorMsgExpected>`_ proc.
   raise newException(EJsonParsingError, errorMsgExpected(p, msg))
 
 proc newJString*(s: string): PJsonNode =
-  ## Creates a new `JString PJsonNode`.
+  ## Creates a new `JString PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJString("A string")
+  ##   echo node
+  ##   # --> "A string"
+  ##
+  ## Or you can use the shorter `%() proc <#%,string>`_.
   new(result)
   result.kind = JString
   result.str = s
@@ -547,80 +700,206 @@ proc newJStringMove(s: string): PJsonNode =
   shallowCopy(result.str, s)
 
 proc newJInt*(n: BiggestInt): PJsonNode =
-  ## Creates a new `JInt PJsonNode`.
+  ## Creates a new `JInt PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJInt(900_100_200_300)
+  ##   echo node
+  ##   # --> 900100200300
+  ##
+  ## Or you can use the shorter `%() proc <#%,BiggestInt>`_.
   new(result)
   result.kind = JInt
   result.num  = n
 
 proc newJFloat*(n: float): PJsonNode =
-  ## Creates a new `JFloat PJsonNode`.
+  ## Creates a new `JFloat PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJFloat(3.14)
+  ##   echo node
+  ##   # --> 3.14
+  ##
+  ## Or you can use the shorter `%() proc <#%,float>`_.
   new(result)
   result.kind = JFloat
   result.fnum  = n
 
 proc newJBool*(b: bool): PJsonNode =
-  ## Creates a new `JBool PJsonNode`.
+  ## Creates a new `JBool PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJBool(true)
+  ##   echo node
+  ##   # --> true
+  ##
+  ## Or you can use the shorter `%() proc <#%,bool>`_.
   new(result)
   result.kind = JBool
   result.bval = b
 
 proc newJNull*(): PJsonNode =
-  ## Creates a new `JNull PJsonNode`.
+  ## Creates a new `JNull PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJNull()
+  ##   echo node
+  ##   # --> null
   new(result)
 
 proc newJObject*(): PJsonNode =
-  ## Creates a new `JObject PJsonNode`
+  ## Creates a new `JObject PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## The `PJsonNode <#PJsonNode>`_ will be initialized with an empty ``fields``
+  ## sequence to which you can add new elements. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJObject()
+  ##   node.add("age", newJInt(24))
+  ##   node.add("name", newJString("Minah"))
+  ##   echo node
+  ##   # --> { "age": 24,  "name": "Minah"}
+  ##
+  ## Or you can use the shorter `%() proc
+  ## <#%,openArray[tuple[string,PJsonNode]]>`_.
   new(result)
   result.kind = JObject
   result.fields = @[]
 
 proc newJArray*(): PJsonNode =
-  ## Creates a new `JArray PJsonNode`
+  ## Creates a new `JArray PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## The `PJsonNode <#PJsonNode>`_ will be initialized with an empty ``elems``
+  ## sequence to which you can add new elements. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJArray()
+  ##   node.add(newJString("Mixing types"))
+  ##   node.add(newJInt(42))
+  ##   node.add(newJString("is madness"))
+  ##   node.add(newJFloat(3.14))
+  ##   echo node
+  ##   # --> [ "Mixing types",  42,  "is madness",  3.14]
+  ##
+  ## Or you can use the shorter `%() proc <#%,openArray[PJsonNode]>`_.
   new(result)
   result.kind = JArray
   result.elems = @[]
 
 
 proc `%`*(s: string): PJsonNode =
-  ## Generic constructor for JSON data. Creates a new `JString PJsonNode`.
+  ## Creates a new `JString PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = %"A string"
+  ##   echo node
+  ##   # --> "A string"
+  ##
+  ## This generic constructor is equivalent to the `newJString()
+  ## <#newJString>`_ proc.
   new(result)
   result.kind = JString
   result.str = s
 
 proc `%`*(n: BiggestInt): PJsonNode =
-  ## Generic constructor for JSON data. Creates a new `JInt PJsonNode`.
+  ## Creates a new `JInt PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = %900_100_200_300
+  ##   echo node
+  ##   # --> 900100200300
+  ##
+  ## This generic constructor is equivalent to the `newJInt() <#newJInt>`_
+  ## proc.
   new(result)
   result.kind = JInt
   result.num  = n
 
 proc `%`*(n: float): PJsonNode =
-  ## Generic constructor for JSON data. Creates a new `JFloat PJsonNode`.
+  ## Creates a new `JFloat PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = %3.14
+  ##   echo node
+  ##   # --> 3.14
+  ##
+  ## This generic constructor is equivalent to the `newJFloat() <#newJFloat>`_
+  ## proc.
   new(result)
   result.kind = JFloat
   result.fnum  = n
 
 proc `%`*(b: bool): PJsonNode =
-  ## Generic constructor for JSON data. Creates a new `JBool PJsonNode`.
+  ## Creates a new `JBool PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = %true
+  ##   echo node
+  ##   # --> true
+  ##
+  ## This generic constructor is equivalent to the `newJBool() <#newJBool>`_
+  ## proc.
   new(result)
   result.kind = JBool
   result.bval = b
 
 proc `%`*(keyVals: openArray[tuple[key: string, val: PJsonNode]]): PJsonNode =
-  ## Generic constructor for JSON data. Creates a new `JObject PJsonNode`
+  ## Creates a new `JObject PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Unlike the `newJObject() <#newJObject>`_ proc, which returns an object
+  ## that has to be further manipulated, you can use this generic constructor
+  ## to create JSON objects with all their fields in one go. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let node = %[("age", %24), ("name", %"Minah")]
+  ##   echo node
+  ##   # --> { "age": 24,  "name": "Minah"}
   new(result)
   result.kind = JObject
   newSeq(result.fields, keyVals.len)
   for i, p in pairs(keyVals): result.fields[i] = p
 
 proc `%`*(elements: openArray[PJsonNode]): PJsonNode =
-  ## Generic constructor for JSON data. Creates a new `JArray PJsonNode`
+  ## Creates a new `JArray PJsonNode <#TJsonNodeKind>`_.
+  ##
+  ## Unlike the `newJArray() <#newJArray>`_ proc, which returns an object
+  ## that has to be further manipulated, you can use this generic constructor
+  ## to create JSON arrays with all their values in one go. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let node = %[%"Mixing types", %42,
+  ##     %"is madness", %3.14,]
+  ##   echo node
+  ##   # --> [ "Mixing types",  42,  "is madness",  3.14]
   new(result)
   result.kind = JArray
   newSeq(result.elems, elements.len)
   for i, p in pairs(elements): result.elems[i] = p
 
 proc `==`* (a,b: PJsonNode): bool =
-  ## Check two nodes for equality
+  ## Check two `PJsonNode <#PJsonNode>`_ nodes for equality.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   assert(%1 == %1)
+  ##   assert(%1 != %2)
   if a.isNil:
     if b.isNil: return true
     return false
@@ -644,7 +923,21 @@ proc `==`* (a,b: PJsonNode): bool =
       a.fields == b.fields
 
 proc hash* (n:PJsonNode): THash =
-  ## Compute the hash for a JSON node
+  ## Computes the hash for a JSON node.
+  ##
+  ## The `THash <hashes.html#THash>`_ allows JSON nodes to be used as keys for
+  ## `sets <sets.html>`_ or `tables <tables.html>`_. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   import json, sets
+  ##
+  ##   var
+  ##     uniqueValues = initSet[PJsonNode]()
+  ##     values = %[%1, %2, %1, %2, %3]
+  ##   for value in values.elems:
+  ##     discard uniqueValues.containsOrIncl(value)
+  ##   echo uniqueValues
+  ##   # --> {1, 2, 3}
   case n.kind
   of JArray:
     result = hash(n.elems)
@@ -662,17 +955,40 @@ proc hash* (n:PJsonNode): THash =
     result = hash(0)
 
 proc len*(n: PJsonNode): int = 
-  ## If `n` is a `JArray`, it returns the number of elements.
-  ## If `n` is a `JObject`, it returns the number of pairs.
-  ## Else it returns 0.
+  ## Returns the number of children items for this `PJsonNode <#PJsonNode>`_.
+  ##
+  ## If `n` is a `JArray <#TJsonNodeKind>`_, it will return the number of
+  ## elements.  If `n` is a `JObject <#TJsonNodeKind>`_, it will return the
+  ## number of key-value pairs. For all other types this proc returns zero.
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let
+  ##     n1 = %[("age", %33), ("name", %"Sojin")]
+  ##     n2 = %[%1, %2, %3, %4, %5, %6, %7]
+  ##     n3 = %"Some odd string we have here"
+  ##   echo n1.len # --> 2
+  ##   echo n2.len # --> 7
+  ##   echo n3.len # --> 0
+  ##
   case n.kind
   of JArray: result = n.elems.len
   of JObject: result = n.fields.len
   else: discard
 
 proc `[]`*(node: PJsonNode, name: string): PJsonNode =
-  ## Gets a field from a `JObject`, which must not be nil.
-  ## If the value at `name` does not exist, returns nil
+  ## Gets a named field from a `JObject <#TJsonNodeKind>`_ `PJsonNode
+  ## <#PJsonNode>`_.
+  ##
+  ## Returns the value for `name` or nil if `node` doesn't contain such a
+  ## field.  This proc will `assert <system.html#assert>`_ in debug builds if
+  ## `name` is ``nil`` or `node` is not a ``JObject``. On release builds it
+  ## will likely crash. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let node = %[("age", %40), ("name", %"Britney")]
+  ##   echo node["name"]
+  ##   # --> "Britney"
   assert(not isNil(node))
   assert(node.kind == JObject)
   for key, item in items(node.fields):
@@ -681,35 +997,92 @@ proc `[]`*(node: PJsonNode, name: string): PJsonNode =
   return nil
   
 proc `[]`*(node: PJsonNode, index: int): PJsonNode =
-  ## Gets the node at `index` in an Array. Result is undefined if `index`
-  ## is out of bounds
+  ## Gets the `index` item from a `JArray <#TJsonNodeKind>`_ `PJsonNode
+  ## <#PJsonNode>`_.
+  ##
+  ## Returns the specified item. Result is undefined if `index` is out of
+  ## bounds.  This proc will `assert <system.html#assert>`_ in debug builds if
+  ## `node` is ``nil`` or not a ``JArray``. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let node = %[%"Mixing types", %42,
+  ##     %"is madness", %3.14,]
+  ##   echo node[2]
+  ##   # --> "is madness"
   assert(not isNil(node))
   assert(node.kind == JArray)
   return node.elems[index]
 
 proc hasKey*(node: PJsonNode, key: string): bool =
-  ## Checks if `key` exists in `node`.
+  ## Returns `true` if `key` exists in a `JObject <#TJsonNodeKind>`_ `PJsonNode
+  ## <#PJsonNode>`_.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds if `node` is
+  ## not a ``JObject``. On release builds it will likely crash. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let node = %[("age", %40), ("name", %"Britney")]
+  ##   echo node.hasKey("email")
+  ##   # --> false
   assert(node.kind == JObject)
   for k, item in items(node.fields):
     if k == key: return true
 
 proc existsKey*(node: PJsonNode, key: string): bool {.deprecated.} = node.hasKey(key)
-  ## Deprecated for `hasKey`
+  ## Deprecated for `hasKey() <#hasKey>`_.
 
 proc add*(father, child: PJsonNode) = 
-  ## Adds `child` to a JArray node `father`. 
+  ## Adds `child` to a `JArray <#TJsonNodeKind>`_ `PJsonNode <#PJsonNode>`_
+  ## `father` node.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds if `node` is
+  ## not a ``JArray``. On release builds it will likely crash. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = %[%"Mixing types", %42]
+  ##   node.add(%"is madness")
+  ##   echo node
+  ##   # --> false
   assert father.kind == JArray
   father.elems.add(child)
 
 proc add*(obj: PJsonNode, key: string, val: PJsonNode) = 
-  ## Adds ``(key, val)`` pair to the JObject node `obj`. For speed
-  ## reasons no check for duplicate keys is performed!
-  ## But ``[]=`` performs the check.
+  ## Adds ``(key, val)`` pair to a `JObject <#TJsonNodeKind>`_ `PJsonNode
+  ## <#PJsonNode>`_ `obj` node.
+  ##
+  ## For speed reasons no check for duplicate keys is performed!  But ``[]=``
+  ## performs the check.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds if `node` is
+  ## not a ``JObject``. On release builds it will likely crash. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJObject()
+  ##   node.add("age", newJInt(12))
+  ##   # This is wrong! But we need speed…
+  ##   node.add("age", newJInt(24))
+  ##   echo node
+  ##   # --> { "age": 12,  "age": 24}
   assert obj.kind == JObject
   obj.fields.add((key, val))
 
 proc `[]=`*(obj: PJsonNode, key: string, val: PJsonNode) =
-  ## Sets a field from a `JObject`. Performs a check for duplicate keys.
+  ## Sets a field from a `JObject <#TJsonNodeKind>`_ `PJsonNode
+  ## <#PJsonNode>`_ `obj` node.
+  ##
+  ## Unlike the `add() <#add,PJsonNode,string,PJsonNode>`_ proc this will
+  ## perform a check for duplicate keys and replace existing values.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds if `node` is
+  ## not a ``JObject``. On release builds it will likely crash. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = newJObject()
+  ##   node["age"] = %12
+  ##   # The new value replaces the previous one.
+  ##   node["age"] = %24
+  ##   echo node
+  ##   # --> { "age": 24}
   assert(obj.kind == JObject)
   for i in 0..obj.fields.len-1:
     if obj.fields[i].key == key: 
@@ -736,6 +1109,18 @@ proc `{}=`*(node: PJsonNode, names: varargs[string], value: PJsonNode) =
 
 proc delete*(obj: PJsonNode, key: string) =
   ## Deletes ``obj[key]`` preserving the order of the other (key, value)-pairs.
+  ##
+  ## If `key` doesn't exist in `obj` ``EInvalidIndex`` will be raised.  This
+  ## proc will `assert <system.html#assert>`_ in debug builds if `node` is not
+  ## a ``JObject``. On release builds it will likely crash. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = %[("age", %37), ("name", %"Chris"), ("male", %false)]
+  ##   echo node
+  ##   # --> { "age": 37,  "name": "Chris",  "male": false}
+  ##   node.delete("age")
+  ##   echo node
+  ##   # --> { "name": "Chris",  "male": false}
   assert(obj.kind == JObject)
   for i in 0..obj.fields.len-1:
     if obj.fields[i].key == key:
@@ -744,7 +1129,9 @@ proc delete*(obj: PJsonNode, key: string) =
   raise newException(EInvalidIndex, "key not in object")
 
 proc copy*(p: PJsonNode): PJsonNode =
-  ## Performs a deep copy of `a`.
+  ## Performs a deep copy of `p`.
+  ##
+  ## Modifications to the copy won't affect the original.
   case p.kind
   of JString:
     result = newJString(p.str)
@@ -779,6 +1166,12 @@ proc nl(s: var string, ml: bool) =
 
 proc escapeJson*(s: string): string = 
   ## Converts a string `s` to its JSON representation.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   echo """name: "Torbjørn"""".escapeJson
+  ##   # --> "name: \"Torbj\u00F8rn\""
   result = newStringOfCap(s.len + s.len shr 3)
   result.add("\"")
   for x in runes(s):
@@ -850,24 +1243,58 @@ proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = true,
     result.add("null")
 
 proc pretty*(node: PJsonNode, indent = 2): string =
-  ## Converts `node` to its JSON Representation, with indentation and
-  ## on multiple lines.
+  ## Converts `node` to a pretty JSON representation.
+  ##
+  ## The representation will have indentation use multiple lines. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let node = %[("age", %33), ("name", %"Sojin")]
+  ##   echo node
+  ##   # --> { "age": 33,  "name": "Sojin"}
+  ##   echo node.pretty
+  ##   # --> {
+  ##   #       "age": 33,
+  ##   #       "name": "Sojin"
+  ##   #     }
   result = ""
   toPretty(result, node, indent)
 
 proc `$`*(node: PJsonNode): string =
-  ## Converts `node` to its JSON Representation on one line.
+  ## Converts `node` to its JSON representation on one line.
   result = ""
   toPretty(result, node, 1, false)
 
 iterator items*(node: PJsonNode): PJsonNode =
-  ## Iterator for the items of `node`. `node` has to be a JArray.
+  ## Iterator for the items of `node`.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds if `node` is
+  ## not a `JArray <#TJsonNodeKind>`_. On release builds it will likely crash.
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let numbers = %[%1, %2, %3]
+  ##   for n in numbers.items:
+  ##     echo "Number ", n
+  ##   ## --> Number 1
+  ##   ##     Number 2
+  ##   ##     Number 3
   assert node.kind == JArray
   for i in items(node.elems):
     yield i
 
 iterator pairs*(node: PJsonNode): tuple[key: string, val: PJsonNode] =
-  ## Iterator for the child elements of `node`. `node` has to be a JObject.
+  ## Iterator for the child elements of `node`.
+  ##
+  ## This proc will `assert <system.html#assert>`_ in debug builds if `node` is
+  ## not a `JObject <#TJsonNodeKind>`_. On release builds it will likely crash.
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   var node = %[("age", %37), ("name", %"Chris")]
+  ##   for key, value in node.pairs:
+  ##     echo "Key: ", key, ", value: ", value
+  ##   # --> Key: age, value: 37
+  ##   #     Key: name, value: "Chris"
   assert node.kind == JObject
   for key, val in items(node.fields):
     yield (key, val)
@@ -926,8 +1353,12 @@ proc parseJson(p: var TJsonParser): PJsonNode =
 
 when not defined(js):
   proc parseJson*(s: PStream, filename: string): PJsonNode =
-    ## Parses from a stream `s` into a `PJsonNode`. `filename` is only needed
-    ## for nice error messages.
+    ## Generic convenience proc to parse stream `s` into a `PJsonNode`.
+    ##
+    ## This wraps around `open() <#open>`_ and `next() <#next>`_ to return the
+    ## full JSON DOM. Errors will be raised as exceptions, this requires the
+    ## `filename` parameter to not be ``nil`` to avoid crashes.
+    assert(not isNil(filename))
     var p: TJsonParser
     p.open(s, filename)
     discard getTok(p) # read first token
@@ -936,10 +1367,28 @@ when not defined(js):
 
   proc parseJson*(buffer: string): PJsonNode =
     ## Parses JSON from `buffer`.
+    ##
+    ## Specialized version around `parseJson(PStream, string)
+    ## <#parseJson,PStream,string>`_. Example:
+    ##
+    ## .. code-block:: nimrod
+    ##  let
+    ##    smallJson = """{"test": 1.3, "key2": true}"""
+    ##    jobj = parseJson(smallJson)
+    ##  assert jobj.kind == JObject
+    ##
+    ##  assert jobj["test"].kind == JFloat
+    ##  echo jobj["test"].fnum # --> 1.3
+    ##
+    ##  assert jobj["key2"].kind == JBool
+    ##  echo jobj["key2"].bval # --> true
     result = parseJson(newStringStream(buffer), "input")
 
   proc parseFile*(filename: string): PJsonNode =
     ## Parses `file` into a `PJsonNode`.
+    ##
+    ## Specialized version around `parseJson(PStream, string)
+    ## <#parseJson,PStream,string>`_.
     var stream = newFileStream(filename, fmRead)
     if stream == nil:
       raise newException(EIO, "cannot read from file: " & filename)
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 2f7a696b9..97c7b0e05 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -40,17 +40,6 @@ const
                                            ## after the decimal point 
                                            ## for Nimrod's ``float`` type.
 
-type
-  TFloatClass* = enum ## describes the class a floating point value belongs to.
-                      ## This is the type that is returned by `classify`.
-    fcNormal,    ## value is an ordinary nonzero floating point value
-    fcSubnormal, ## value is a subnormal (a very small) floating point value
-    fcZero,      ## value is zero
-    fcNegZero,   ## value is the negative zero
-    fcNan,       ## value is Not-A-Number (NAN)
-    fcInf,       ## value is positive infinity
-    fcNegInf     ## value is negative infinity
-
 proc classify*(x: float): TFloatClass = 
   ## classifies a floating point value. Returns `x`'s class as specified by
   ## `TFloatClass`.
@@ -219,7 +208,7 @@ when not defined(JS):
 
   proc randomize(seed: int) =
     srand(cint(seed))
-    when defined(srand48): srand48(seed)
+    when declared(srand48): srand48(seed)
   proc random(max: int): int =
     result = int(rand()) mod max
 
@@ -279,8 +268,13 @@ proc `mod`*(x, y: float): float =
   result = if y == 0.0: x else: x - y * (x/y).floor
 
 proc random*[T](x: TSlice[T]): T =
+  ## For a slice `a .. b` returns a value in the range `a .. b-1`.
   result = random(x.b - x.a) + x.a
-  
+
+proc random[T](a: openarray[T]): T =
+  ## returns a random element from the openarray `a`.
+  result = a[random(a.low..a.len)]
+
 type
   TRunningStat* {.pure,final.} = object  ## an accumulator for statistical data
     n*: int                              ## number of pushed data
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 31fefc6c8..ffeb0beff 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -54,7 +54,7 @@ proc mapMem*(m: var TMemFile, mode: TFileMode = fmRead,
       nil,
       mappedSize,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: MAP_PRIVATE else: MAP_SHARED,
+      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
       m.handle, offset)
     if result == cast[pointer](MAP_FAILED):
       osError(osLastError())
@@ -207,7 +207,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
       nil,
       result.size,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: MAP_PRIVATE else: MAP_SHARED,
+      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
       result.handle,
       offset)
 
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index ddc2bbe2d..696527467 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -11,292 +11,10 @@
 
 {.deadCodeElim: on.}
 import rawsockets, os, strutils, unsigned, parseutils, times
-export TPort, `$`
+export TPort, `$`, `==`
 
 const useWinVersion = defined(Windows) or defined(nimdoc)
 
-type
-  IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
-    IPv6, ## IPv6 address
-    IPv4  ## IPv4 address
-
-  TIpAddress* = object ## stores an arbitrary IP address    
-    case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
-    of IpAddressFamily.IPv6:
-      address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
-                                       ## case of IPv6
-    of IpAddressFamily.IPv4:
-      address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
-                                      ## case of IPv4
-
-proc IPv4_any*(): TIpAddress =
-  ## Returns the IPv4 any address, which can be used to listen on all available
-  ## network adapters
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [0'u8, 0, 0, 0])
-
-proc IPv4_loopback*(): TIpAddress =
-  ## Returns the IPv4 loopback address (127.0.0.1)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [127'u8, 0, 0, 1])
-
-proc IPv4_broadcast*(): TIpAddress =
-  ## Returns the IPv4 broadcast address (255.255.255.255)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv4,
-    address_v4: [255'u8, 255, 255, 255])
-
-proc IPv6_any*(): TIpAddress =
-  ## Returns the IPv6 any address (::0), which can be used
-  ## to listen on all available network adapters 
-  result = TIpAddress(
-    family: IpAddressFamily.IPv6,
-    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
-
-proc IPv6_loopback*(): TIpAddress =
-  ## Returns the IPv6 loopback address (::1)
-  result = TIpAddress(
-    family: IpAddressFamily.IPv6,
-    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
-
-proc `==`*(lhs, rhs: TIpAddress): bool =
-  ## Compares two IpAddresses for Equality. Returns two if the addresses are equal
-  if lhs.family != rhs.family: return false
-  if lhs.family == IpAddressFamily.IPv4:
-    for i in low(lhs.address_v4) .. high(lhs.address_v4):
-      if lhs.address_v4[i] != rhs.address_v4[i]: return false
-  else: # IPv6
-    for i in low(lhs.address_v6) .. high(lhs.address_v6):
-      if lhs.address_v6[i] != rhs.address_v6[i]: return false
-  return true
-
-proc `$`*(address: TIpAddress): string =
-  ## Converts an TIpAddress into the textual representation
-  result = ""
-  case address.family
-  of IpAddressFamily.IPv4:
-    for i in 0 .. 3:
-      if i != 0:
-        result.add('.')
-      result.add($address.address_v4[i])
-  of IpAddressFamily.IPv6:
-    var
-      currentZeroStart = -1
-      currentZeroCount = 0
-      biggestZeroStart = -1
-      biggestZeroCount = 0
-    # Look for the largest block of zeros
-    for i in 0..7:
-      var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0
-      if isZero:
-        if currentZeroStart == -1:
-          currentZeroStart = i
-          currentZeroCount = 1
-        else:
-          currentZeroCount.inc()
-        if currentZeroCount > biggestZeroCount:
-          biggestZeroCount = currentZeroCount
-          biggestZeroStart = currentZeroStart
-      else:
-        currentZeroStart = -1
-
-    if biggestZeroCount == 8: # Special case ::0
-      result.add("::")
-    else: # Print address
-      var printedLastGroup = false
-      for i in 0..7:
-        var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8
-        word = word or cast[uint16](address.address_v6[i*2+1])
-
-        if biggestZeroCount != 0 and # Check if group is in skip group
-          (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)):
-          if i == biggestZeroStart: # skip start
-            result.add("::")
-          printedLastGroup = false
-        else:
-          if printedLastGroup:
-            result.add(':')
-          var
-            afterLeadingZeros = false
-            mask = 0xF000'u16
-          for j in 0'u16..3'u16:
-            var val = (mask and word) shr (4'u16*(3'u16-j))
-            if val != 0 or afterLeadingZeros:
-              if val < 0xA:
-                result.add(chr(uint16(ord('0'))+val))
-              else: # val >= 0xA
-                result.add(chr(uint16(ord('a'))+val-0xA))
-              afterLeadingZeros = true
-            mask = mask shr 4
-          printedLastGroup = true
-
-proc parseIPv4Address(address_str: string): TIpAddress =
-  ## Parses IPv4 adresses
-  ## Raises EInvalidValue on errors
-  var
-    byteCount = 0
-    currentByte:uint16 = 0
-    seperatorValid = false
-
-  result.family = IpAddressFamily.IPv4
-
-  for i in 0 .. high(address_str):
-    if address_str[i] in strutils.Digits: # Character is a number
-      currentByte = currentByte * 10 +
-        cast[uint16](ord(address_str[i]) - ord('0'))
-      if currentByte > 255'u16:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Value is out of range")
-      seperatorValid = true
-    elif address_str[i] == '.': # IPv4 address separator
-      if not seperatorValid or byteCount >= 3:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. The address consists of too many groups")
-      result.address_v4[byteCount] = cast[uint8](currentByte)
-      currentByte = 0
-      byteCount.inc
-      seperatorValid = false
-    else:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. Address contains an invalid character")
-
-  if byteCount != 3 or not seperatorValid:
-    raise newException(EInvalidValue, "Invalid IP Address")
-  result.address_v4[byteCount] = cast[uint8](currentByte)
-
-proc parseIPv6Address(address_str: string): TIpAddress =
-  ## Parses IPv6 adresses
-  ## Raises EInvalidValue on errors
-  result.family = IpAddressFamily.IPv6
-  if address_str.len < 2:
-    raise newException(EInvalidValue, "Invalid IP Address")
-
-  var
-    groupCount = 0
-    currentGroupStart = 0
-    currentShort:uint32 = 0
-    seperatorValid = true
-    dualColonGroup = -1
-    lastWasColon = false
-    v4StartPos = -1
-    byteCount = 0
-
-  for i,c in address_str:
-    if c == ':':
-      if not seperatorValid:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Address contains an invalid seperator")
-      if lastWasColon:        
-        if dualColonGroup != -1:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address contains more than one \"::\" seperator")
-        dualColonGroup = groupCount
-        seperatorValid = false
-      elif i != 0 and i != high(address_str):
-        if groupCount >= 8:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. The address consists of too many groups")
-        result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
-        result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
-        currentShort = 0
-        groupCount.inc()        
-        if dualColonGroup != -1: seperatorValid = false
-      elif i == 0: # only valid if address starts with ::
-        if address_str[1] != ':':
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address may not start with \":\"")
-      else: # i == high(address_str) - only valid if address ends with ::
-        if address_str[high(address_str)-1] != ':': 
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Address may not end with \":\"")
-      lastWasColon = true
-      currentGroupStart = i + 1
-    elif c == '.': # Switch to parse IPv4 mode
-      if i < 3 or not seperatorValid or groupCount >= 7:
-        raise newException(EInvalidValue, "Invalid IP Address")
-      v4StartPos = currentGroupStart
-      currentShort = 0
-      seperatorValid = false
-      break
-    elif c in strutils.HexDigits:
-      if c in strutils.Digits: # Normal digit
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0'))
-      elif c >= 'a' and c <= 'f': # Lower case hex
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10
-      else: # Upper case hex
-        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10
-      if currentShort > 65535'u32:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Value is out of range")
-      lastWasColon = false
-      seperatorValid = true
-    else:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. Address contains an invalid character")
-
-
-  if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff
-    if seperatorValid: # Copy remaining data
-      if groupCount >= 8:
-        raise newException(EInvalidValue,
-          "Invalid IP Address. The address consists of too many groups")
-      result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
-      result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
-      groupCount.inc()
-  else: # Must parse IPv4 address
-    for i,c in address_str[v4StartPos..high(address_str)]:
-      if c in strutils.Digits: # Character is a number
-        currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
-        if currentShort > 255'u32:
-          raise newException(EInvalidValue,
-            "Invalid IP Address. Value is out of range")
-        seperatorValid = true
-      elif c == '.': # IPv4 address separator
-        if not seperatorValid or byteCount >= 3:
-          raise newException(EInvalidValue, "Invalid IP Address")
-        result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
-        currentShort = 0
-        byteCount.inc()
-        seperatorValid = false
-      else: # Invalid character
-        raise newException(EInvalidValue,
-          "Invalid IP Address. Address contains an invalid character")
-
-    if byteCount != 3 or not seperatorValid:
-      raise newException(EInvalidValue, "Invalid IP Address")
-    result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
-    groupCount += 2
-
-  # Shift and fill zeros in case of ::
-  if groupCount > 8:
-    raise newException(EInvalidValue,
-      "Invalid IP Address. The address consists of too many groups")
-  elif groupCount < 8: # must fill
-    if dualColonGroup == -1:
-      raise newException(EInvalidValue,
-        "Invalid IP Address. The address consists of too few groups")
-    var toFill = 8 - groupCount # The number of groups to fill
-    var toShift = groupCount - dualColonGroup # Nr of known groups after ::
-    for i in 0..2*toShift-1: # shift
-      result.address_v6[15-i] = result.address_v6[groupCount*2-i-1]
-    for i in 0..2*toFill-1: # fill with 0s
-      result.address_v6[dualColonGroup*2+i] = 0
-  elif dualColonGroup != -1:
-    raise newException(EInvalidValue,
-      "Invalid IP Address. The address consists of too many groups")
-
-proc parseIpAddress*(address_str: string): TIpAddress =
-  ## Parses an IP address
-  ## Raises EInvalidValue on error
-  if address_str == nil:
-    raise newException(EInvalidValue, "IP Address string is nil")
-  if address_str.contains(':'):
-    return parseIPv6Address(address_str)
-  else:
-    return parseIPv4Address(address_str)
-
 when defined(ssl):
   import openssl
 
@@ -361,7 +79,7 @@ proc isDisconnectionError*(flags: set[TSocketFlags],
   when useWinVersion:
     TSocketFlags.SafeDisconn in flags and
       lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
-                          WSAEDISCON}
+                          WSAEDISCON, ERROR_NETNAME_DELETED}
   else:
     TSocketFlags.SafeDisconn in flags and
       lastError.int32 in {ECONNRESET, EPIPE, ENETRESET} 
@@ -569,8 +287,8 @@ proc bindAddr*(socket: PSocket, port = TPort(0), address = "") {.
       osError(osLastError())
     dealloc(aiList)
 
-proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
-  tags: [FReadIO].} =
+proc acceptAddr*(server: PSocket, client: var PSocket, address: var string,
+                 flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
   ## Blocks until a connection is being made from a client. When a connection
   ## is made sets ``client`` to the client socket and ``address`` to the address
   ## of the connecting client.
@@ -581,6 +299,11 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
   ##
   ## **Note**: ``client`` must be initialised (with ``new``), this function 
   ## makes no effort to initialise the ``client`` variable.
+  ##
+  ## The ``accept`` call may result in an error if the connecting socket
+  ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+  ## flag is specified then this error will not be raised and instead
+  ## accept will be called again.
   assert(client != nil)
   var sockAddress: Tsockaddr_in
   var addrLen = sizeof(sockAddress).TSocklen
@@ -589,6 +312,8 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {.
   
   if sock == osInvalidSocket:
     let err = osLastError()
+    if flags.isDisconnectionError(err):
+      acceptAddr(server, client, address, flags)
     osError(err)
   else:
     client.fd = sock
@@ -658,15 +383,20 @@ when false: #defined(ssl):
       acceptAddrPlain(AcceptNoClient, AcceptSuccess):
         doHandshake()
 
-proc accept*(server: PSocket, client: var PSocket) {.tags: [FReadIO].} =
+proc accept*(server: PSocket, client: var PSocket,
+             flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} =
   ## Equivalent to ``acceptAddr`` but doesn't return the address, only the
   ## socket.
   ## 
   ## **Note**: ``client`` must be initialised (with ``new``), this function
   ## makes no effort to initialise the ``client`` variable.
-  
+  ##
+  ## The ``accept`` call may result in an error if the connecting socket
+  ## disconnects during the duration of the ``accept``. If the ``SafeDisconn``
+  ## flag is specified then this error will not be raised and instead
+  ## accept will be called again.
   var addrDummy = ""
-  acceptAddr(server, client, addrDummy)
+  acceptAddr(server, client, addrDummy, flags)
 
 proc close*(socket: PSocket) =
   ## Closes a socket.
@@ -1173,3 +903,285 @@ proc isSSL*(socket: PSocket): bool = return socket.isSSL
 
 proc getFD*(socket: PSocket): TSocketHandle = return socket.fd
   ## Returns the socket's file descriptor
+
+type
+  IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
+    IPv6, ## IPv6 address
+    IPv4  ## IPv4 address
+
+  TIpAddress* = object ## stores an arbitrary IP address    
+    case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
+    of IpAddressFamily.IPv6:
+      address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
+                                       ## case of IPv6
+    of IpAddressFamily.IPv4:
+      address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
+                                      ## case of IPv4
+
+proc IPv4_any*(): TIpAddress =
+  ## Returns the IPv4 any address, which can be used to listen on all available
+  ## network adapters
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [0'u8, 0, 0, 0])
+
+proc IPv4_loopback*(): TIpAddress =
+  ## Returns the IPv4 loopback address (127.0.0.1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [127'u8, 0, 0, 1])
+
+proc IPv4_broadcast*(): TIpAddress =
+  ## Returns the IPv4 broadcast address (255.255.255.255)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [255'u8, 255, 255, 255])
+
+proc IPv6_any*(): TIpAddress =
+  ## Returns the IPv6 any address (::0), which can be used
+  ## to listen on all available network adapters 
+  result = TIpAddress(
+    family: IpAddressFamily.IPv6,
+    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+proc IPv6_loopback*(): TIpAddress =
+  ## Returns the IPv6 loopback address (::1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv6,
+    address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
+
+proc `==`*(lhs, rhs: TIpAddress): bool =
+  ## Compares two IpAddresses for Equality. Returns two if the addresses are equal
+  if lhs.family != rhs.family: return false
+  if lhs.family == IpAddressFamily.IPv4:
+    for i in low(lhs.address_v4) .. high(lhs.address_v4):
+      if lhs.address_v4[i] != rhs.address_v4[i]: return false
+  else: # IPv6
+    for i in low(lhs.address_v6) .. high(lhs.address_v6):
+      if lhs.address_v6[i] != rhs.address_v6[i]: return false
+  return true
+
+proc `$`*(address: TIpAddress): string =
+  ## Converts an TIpAddress into the textual representation
+  result = ""
+  case address.family
+  of IpAddressFamily.IPv4:
+    for i in 0 .. 3:
+      if i != 0:
+        result.add('.')
+      result.add($address.address_v4[i])
+  of IpAddressFamily.IPv6:
+    var
+      currentZeroStart = -1
+      currentZeroCount = 0
+      biggestZeroStart = -1
+      biggestZeroCount = 0
+    # Look for the largest block of zeros
+    for i in 0..7:
+      var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0
+      if isZero:
+        if currentZeroStart == -1:
+          currentZeroStart = i
+          currentZeroCount = 1
+        else:
+          currentZeroCount.inc()
+        if currentZeroCount > biggestZeroCount:
+          biggestZeroCount = currentZeroCount
+          biggestZeroStart = currentZeroStart
+      else:
+        currentZeroStart = -1
+
+    if biggestZeroCount == 8: # Special case ::0
+      result.add("::")
+    else: # Print address
+      var printedLastGroup = false
+      for i in 0..7:
+        var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8
+        word = word or cast[uint16](address.address_v6[i*2+1])
+
+        if biggestZeroCount != 0 and # Check if group is in skip group
+          (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)):
+          if i == biggestZeroStart: # skip start
+            result.add("::")
+          printedLastGroup = false
+        else:
+          if printedLastGroup:
+            result.add(':')
+          var
+            afterLeadingZeros = false
+            mask = 0xF000'u16
+          for j in 0'u16..3'u16:
+            var val = (mask and word) shr (4'u16*(3'u16-j))
+            if val != 0 or afterLeadingZeros:
+              if val < 0xA:
+                result.add(chr(uint16(ord('0'))+val))
+              else: # val >= 0xA
+                result.add(chr(uint16(ord('a'))+val-0xA))
+              afterLeadingZeros = true
+            mask = mask shr 4
+          printedLastGroup = true
+
+proc parseIPv4Address(address_str: string): TIpAddress =
+  ## Parses IPv4 adresses
+  ## Raises EInvalidValue on errors
+  var
+    byteCount = 0
+    currentByte:uint16 = 0
+    seperatorValid = false
+
+  result.family = IpAddressFamily.IPv4
+
+  for i in 0 .. high(address_str):
+    if address_str[i] in strutils.Digits: # Character is a number
+      currentByte = currentByte * 10 +
+        cast[uint16](ord(address_str[i]) - ord('0'))
+      if currentByte > 255'u16:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Value is out of range")
+      seperatorValid = true
+    elif address_str[i] == '.': # IPv4 address separator
+      if not seperatorValid or byteCount >= 3:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. The address consists of too many groups")
+      result.address_v4[byteCount] = cast[uint8](currentByte)
+      currentByte = 0
+      byteCount.inc
+      seperatorValid = false
+    else:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. Address contains an invalid character")
+
+  if byteCount != 3 or not seperatorValid:
+    raise newException(EInvalidValue, "Invalid IP Address")
+  result.address_v4[byteCount] = cast[uint8](currentByte)
+
+proc parseIPv6Address(address_str: string): TIpAddress =
+  ## Parses IPv6 adresses
+  ## Raises EInvalidValue on errors
+  result.family = IpAddressFamily.IPv6
+  if address_str.len < 2:
+    raise newException(EInvalidValue, "Invalid IP Address")
+
+  var
+    groupCount = 0
+    currentGroupStart = 0
+    currentShort:uint32 = 0
+    seperatorValid = true
+    dualColonGroup = -1
+    lastWasColon = false
+    v4StartPos = -1
+    byteCount = 0
+
+  for i,c in address_str:
+    if c == ':':
+      if not seperatorValid:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Address contains an invalid seperator")
+      if lastWasColon:        
+        if dualColonGroup != -1:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address contains more than one \"::\" seperator")
+        dualColonGroup = groupCount
+        seperatorValid = false
+      elif i != 0 and i != high(address_str):
+        if groupCount >= 8:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. The address consists of too many groups")
+        result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
+        result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
+        currentShort = 0
+        groupCount.inc()        
+        if dualColonGroup != -1: seperatorValid = false
+      elif i == 0: # only valid if address starts with ::
+        if address_str[1] != ':':
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address may not start with \":\"")
+      else: # i == high(address_str) - only valid if address ends with ::
+        if address_str[high(address_str)-1] != ':': 
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Address may not end with \":\"")
+      lastWasColon = true
+      currentGroupStart = i + 1
+    elif c == '.': # Switch to parse IPv4 mode
+      if i < 3 or not seperatorValid or groupCount >= 7:
+        raise newException(EInvalidValue, "Invalid IP Address")
+      v4StartPos = currentGroupStart
+      currentShort = 0
+      seperatorValid = false
+      break
+    elif c in strutils.HexDigits:
+      if c in strutils.Digits: # Normal digit
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0'))
+      elif c >= 'a' and c <= 'f': # Lower case hex
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10
+      else: # Upper case hex
+        currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10
+      if currentShort > 65535'u32:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Value is out of range")
+      lastWasColon = false
+      seperatorValid = true
+    else:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. Address contains an invalid character")
+
+
+  if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff
+    if seperatorValid: # Copy remaining data
+      if groupCount >= 8:
+        raise newException(EInvalidValue,
+          "Invalid IP Address. The address consists of too many groups")
+      result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8)
+      result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
+      groupCount.inc()
+  else: # Must parse IPv4 address
+    for i,c in address_str[v4StartPos..high(address_str)]:
+      if c in strutils.Digits: # Character is a number
+        currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
+        if currentShort > 255'u32:
+          raise newException(EInvalidValue,
+            "Invalid IP Address. Value is out of range")
+        seperatorValid = true
+      elif c == '.': # IPv4 address separator
+        if not seperatorValid or byteCount >= 3:
+          raise newException(EInvalidValue, "Invalid IP Address")
+        result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
+        currentShort = 0
+        byteCount.inc()
+        seperatorValid = false
+      else: # Invalid character
+        raise newException(EInvalidValue,
+          "Invalid IP Address. Address contains an invalid character")
+
+    if byteCount != 3 or not seperatorValid:
+      raise newException(EInvalidValue, "Invalid IP Address")
+    result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort)
+    groupCount += 2
+
+  # Shift and fill zeros in case of ::
+  if groupCount > 8:
+    raise newException(EInvalidValue,
+      "Invalid IP Address. The address consists of too many groups")
+  elif groupCount < 8: # must fill
+    if dualColonGroup == -1:
+      raise newException(EInvalidValue,
+        "Invalid IP Address. The address consists of too few groups")
+    var toFill = 8 - groupCount # The number of groups to fill
+    var toShift = groupCount - dualColonGroup # Nr of known groups after ::
+    for i in 0..2*toShift-1: # shift
+      result.address_v6[15-i] = result.address_v6[groupCount*2-i-1]
+    for i in 0..2*toFill-1: # fill with 0s
+      result.address_v6[dualColonGroup*2+i] = 0
+  elif dualColonGroup != -1:
+    raise newException(EInvalidValue,
+      "Invalid IP Address. The address consists of too many groups")
+
+proc parseIpAddress*(address_str: string): TIpAddress =
+  ## Parses an IP address
+  ## Raises EInvalidValue on error
+  if address_str == nil:
+    raise newException(EInvalidValue, "IP Address string is nil")
+  if address_str.contains(':'):
+    return parseIPv6Address(address_str)
+  else:
+    return parseIPv4Address(address_str)
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index ab7cd1944..6f94d0656 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -26,7 +26,7 @@ const
   withThreads = compileOption("threads")
   tickCountCorrection = 50_000
 
-when not defined(system.TStackTrace):
+when not declared(system.TStackTrace):
   type TStackTrace = array [0..20, cstring]
 
 # We use a simple hash table of bounded size to keep track of the stack traces:
@@ -146,7 +146,7 @@ proc `//`(a, b: int): string =
   result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2))
 
 proc writeProfile() {.noconv.} =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     system.profilerHook = nil
   const filename = "profile_results.txt"
   echo "writing " & filename & "..."
@@ -189,16 +189,16 @@ var
   disabled: int
 
 proc disableProfiling*() =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     atomicDec disabled
     system.profilerHook = nil
 
 proc enableProfiling*() =
-  when defined(system.TStackTrace):
+  when declared(system.TStackTrace):
     if atomicInc(disabled) >= 0:
       system.profilerHook = hook
 
-when defined(system.TStackTrace):
+when declared(system.TStackTrace):
   system.profilerHook = hook
   addQuitProc(writeProfile)
 
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index a70bfa7f1..71089494f 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -365,8 +365,9 @@ when defined(windows):
     template getFilename(f: expr): expr = $f.cFilename
 
   proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} =
+    # Note - takes advantage of null delimiter in the cstring
     const dot = ord('.')
-    result = f.cFileName[0].int == dot and(f.cFileName[1].int == 0 or
+    result = f.cFileName[0].int == dot and (f.cFileName[1].int == 0 or
              f.cFileName[1].int == dot and f.cFileName[2].int == 0)
 
 proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
@@ -997,7 +998,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
   if c_rename(source, dest) != 0'i32:
     raise newException(EOS, $strerror(errno))
 
-when not defined(ENOENT) and not defined(Windows):
+when not declared(ENOENT) and not defined(Windows):
   when NoFakeVars:
     const ENOENT = cint(2) # 2 on most systems including Solaris
   else:
@@ -1331,10 +1332,10 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
 
 proc rawCreateDir(dir: string) =
   when defined(solaris):
-    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST and errno != ENOSYS:
+    if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST and errno != ENOSYS:
       osError(osLastError())
   elif defined(unix):
-    if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST:
+    if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST:
       osError(osLastError())
   else:
     when useWinUnicode:
@@ -1457,7 +1458,8 @@ proc parseCmdLine*(c: string): seq[string] {.
   var a = ""
   while true:
     setLen(a, 0)
-    while c[i] == ' ' or c[i] == '\t': inc(i)
+    # eat all delimiting whitespace
+    while c[i] == ' ' or c[i] == '\t' or c [i] == '\l' or c [i] == '\r' : inc(i)
     when defined(windows):
       # parse a single argument according to the above rules:
       if c[i] == '\0': break
@@ -1614,11 +1616,11 @@ when defined(nimdoc):
     ##
     ## **Availability**: On Posix there is no portable way to get the command
     ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `defined() <system.html#defined>`_.
+    ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nimrod
-    ##   when defined(paramCount):
+    ##   when declared(paramCount):
     ##     # Use paramCount() here
     ##   else:
     ##     # Do something else!
@@ -1637,11 +1639,11 @@ when defined(nimdoc):
     ##
     ## **Availability**: On Posix there is no portable way to get the command
     ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `defined() <system.html#defined>`_.
+    ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nimrod
-    ##   when defined(paramStr):
+    ##   when declared(paramStr):
     ##     # Use paramStr() here
     ##   else:
     ##     # Do something else!
@@ -1681,7 +1683,7 @@ elif not defined(createNimRtl):
     # Docstring in nimdoc block.
     result = cmdCount-1
 
-when defined(paramCount) or defined(nimdoc):
+when declared(paramCount) or defined(nimdoc):
   proc commandLineParams*(): seq[TaintedString] =
     ## Convenience proc which returns the command line parameters.
     ##
@@ -1690,11 +1692,11 @@ when defined(paramCount) or defined(nimdoc):
     ##
     ## **Availability**: On Posix there is no portable way to get the command
     ## line from a DLL and thus the proc isn't defined in this environment. You
-    ## can test for its availability with `defined() <system.html#defined>`_.
+    ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
     ## .. code-block:: nimrod
-    ##   when defined(commandLineParams):
+    ##   when declared(commandLineParams):
     ##     # Use commandLineParams() here
     ##   else:
     ##     # Do something else!
@@ -1713,7 +1715,7 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
 
 when not (defined(windows) or defined(macosx)):
   proc getApplHeuristic(): string =
-    when defined(paramStr):
+    when declared(paramStr):
       result = string(paramStr(0))
       # POSIX guaranties that this contains the executable
       # as it has been executed by the calling process
@@ -1860,12 +1862,12 @@ proc expandTilde*(path: string): string =
 
 when defined(Windows):
   type
-    DeviceId = int32
-    FileId = int64
+    DeviceId* = int32
+    FileId* = int64
 else:
   type
-    DeviceId = TDev
-    FileId = TIno
+    DeviceId* = TDev
+    FileId* = TIno
 
 type
   FileInfo* = object
@@ -1908,6 +1910,7 @@ template rawToFormalFileInfo(rawInfo, formalInfo): expr =
     if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
       formalInfo.kind = succ(result.kind)
 
+
   else:
     template checkAndIncludeMode(rawMode, formalMode: expr) = 
       if (rawInfo.st_mode and rawMode) != 0'i32:
@@ -1994,4 +1997,26 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo =
         osError(osLastError())
     rawToFormalFileInfo(rawInfo, result)
 
+proc isHidden*(path: string): bool =
+  ## Determines whether a given path is hidden or not. Returns false if the
+  ## file doesn't exist. The given path must be accessible from the current
+  ## working directory of the program.
+  ## 
+  ## On Windows, a file is hidden if the file's 'hidden' attribute is set.
+  ## On Unix-like systems, a file is hidden if it starts with a '.' (period)
+  ## and is not *just* '.' or '..' ' ."
+  when defined(Windows):
+    wrapUnary(attributes, getFileAttributesW, path)
+    if attributes != -1'i32:
+      result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32
+  else:
+    if fileExists(path):
+      let
+        fileName = extractFilename(path)
+        nameLen = len(fileName)
+      if nameLen == 2:
+        result = (fileName[0] == '.') and (fileName[1] != '.')
+      elif nameLen > 2:
+        result = (fileName[0] == '.') and (fileName[3] != '.')
+
 {.pop.}
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index c74fa1ceb..3c181bf53 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -643,7 +643,7 @@ elif not defined(useNimRtl):
     data.workingDir = workingDir
 
 
-    when defined(posix_spawn) and not defined(useFork) and 
+    when declared(posix_spawn) and not defined(useFork) and 
         not defined(useClone) and not defined(linux):
       pid = startProcessAuxSpawn(data)
     else:
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index 68ae537c7..f43853fe6 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -37,7 +37,7 @@ type
                               ## or the argument, ``value`` is not "" if
                               ## the option was given a value
 
-when defined(os.paramCount):
+when declared(os.paramCount):
   # we cannot provide this for NimRtl creation on Posix, because we can't 
   # access the command line arguments then!
 
@@ -127,7 +127,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.
   ## retrieves the rest of the command line that has not been parsed yet.
   result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString
 
-when defined(initOptParser):
+when declared(initOptParser):
 
   iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] =
     ## This is an convenience iterator for iterating over the command line.
diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim
index 5e79d8a18..7638171d1 100644
--- a/lib/pure/parseopt2.nim
+++ b/lib/pure/parseopt2.nim
@@ -119,7 +119,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.rtl, extern: "npo$1", deprecat
 type
   TGetoptResult* = tuple[kind: TCmdLineKind, key, val: TaintedString]
 
-when defined(paramCount):
+when declared(paramCount):
   iterator getopt*(): TGetoptResult =
     ## This is an convenience iterator for iterating over the command line.
     ## This uses the TOptParser object. Example:
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 68b1ab223..efe169c1d 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -870,7 +870,7 @@ template `=~`*(s: string, pattern: TPeg): bool =
   ##     echo("syntax error")
   ##  
   bind maxSubpatterns
-  when not definedInScope(matches):
+  when not declaredInScope(matches):
     var matches {.inject.}: array[0..MaxSubpatterns-1, string]
   match(s, pattern, matches)
 
diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim
index d96741846..fea09dfa2 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/rawsockets.nim
@@ -22,7 +22,7 @@ const useWinVersion = defined(Windows) or defined(nimdoc)
 when useWinVersion:
   import winlean
   export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
-         WSAEDISCON
+         WSAEDISCON, ERROR_NETNAME_DELETED
 else:
   import posix
   export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index 4a6c3f530..eb3792bce 100644
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -58,8 +58,8 @@ proc newRope(data: string): PRope =
   result.data = data
 
 var 
-  cache: PRope                # the root of the cache tree
-  N: PRope                    # dummy rope needed for splay algorithm
+  cache {.threadvar.}: PRope     # the root of the cache tree
+  N {.threadvar.}: PRope         # dummy rope needed for splay algorithm
 
 when countCacheMisses:
   var misses, hits: int
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 6f8924d83..1d17de233 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -803,6 +803,36 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} =
     if result != -1: return
   return -1
 
+proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
+  rtl, extern: "nsuCountString".} =
+  ## Count the occurences of a substring `sub` in the string `s`.
+  ## Overlapping occurences of `sub` only count when `overlapping`
+  ## is set to true.
+  var i = 0
+  while true:
+    i = s.find(sub, i)
+    if i < 0:
+      break
+    if overlapping:
+      inc i
+    else:
+      i += sub.len
+    inc result
+
+proc count*(s: string, sub: char): int {.noSideEffect,
+  rtl, extern: "nsuCountChar".} =
+  ## Count the occurences of the character `sub` in the string `s`.
+  for c in s:
+    if c == sub:
+      inc result
+
+proc count*(s: string, subs: set[char]): int {.noSideEffect,
+  rtl, extern: "nsuCountCharSet".} =
+  ## Count the occurences of the group of character `subs` in the string `s`.
+  for c in s:
+    if c in subs:
+      inc result
+
 proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
   ## Returns ``'"' & s & '"'`` if `s` contains a space and does not
   ## start with a quote, else returns `s`.
@@ -1354,3 +1384,8 @@ when isMainModule:
   doAssert parseEnum[TMyEnum]("enu_D") == enuD
 
   doAssert parseEnum("invalid enum value", enC) == enC
+
+  doAssert count("foofoofoo", "foofoo") == 1
+  doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
+  doAssert count("foofoofoo", 'f') == 3
+  doAssert count("foofoofoobar", {'f','b'}) == 4
diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim
index 92797744a..ed87610d6 100644
--- a/lib/pure/subexes.nim
+++ b/lib/pure/subexes.nim
@@ -84,7 +84,8 @@ proc getFormatArg(p: var TFormatParser, a: openArray[string]): int =
   if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result)
   p.i = i
 
-proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string)
+proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) {.
+  noSideEffect.}
 
 proc emitChar(p: var TFormatParser, x: var string, ch: char) {.inline.} =
   x.add(ch)
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 498511899..8b33d2c73 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -63,44 +63,44 @@ elif defined(windows):
 elif defined(JS):
   type
     TTime* {.final, importc.} = object
-      getDay: proc (): int {.tags: [], raises: [].}
-      getFullYear: proc (): int {.tags: [], raises: [].}
-      getHours: proc (): int {.tags: [], raises: [].}
-      getMilliseconds: proc (): int {.tags: [], raises: [].}
-      getMinutes: proc (): int {.tags: [], raises: [].}
-      getMonth: proc (): int {.tags: [], raises: [].}
-      getSeconds: proc (): int {.tags: [], raises: [].}
-      getTime: proc (): int {.tags: [], raises: [].}
-      getTimezoneOffset: proc (): int {.tags: [], raises: [].}
-      getDate: proc (): int {.tags: [], raises: [].}
-      getUTCDate: proc (): int {.tags: [], raises: [].}
-      getUTCFullYear: proc (): int {.tags: [], raises: [].}
-      getUTCHours: proc (): int {.tags: [], raises: [].}
-      getUTCMilliseconds: proc (): int {.tags: [], raises: [].}
-      getUTCMinutes: proc (): int {.tags: [], raises: [].}
-      getUTCMonth: proc (): int {.tags: [], raises: [].}
-      getUTCSeconds: proc (): int {.tags: [], raises: [].}
-      getUTCDay: proc (): int {.tags: [], raises: [].}
-      getYear: proc (): int {.tags: [], raises: [].}
-      parse: proc (s: cstring): TTime {.tags: [], raises: [].}
-      setDate: proc (x: int) {.tags: [], raises: [].}
-      setFullYear: proc (x: int) {.tags: [], raises: [].}
-      setHours: proc (x: int) {.tags: [], raises: [].}
-      setMilliseconds: proc (x: int) {.tags: [], raises: [].}
-      setMinutes: proc (x: int) {.tags: [], raises: [].}
-      setMonth: proc (x: int) {.tags: [], raises: [].}
-      setSeconds: proc (x: int) {.tags: [], raises: [].}
-      setTime: proc (x: int) {.tags: [], raises: [].}
-      setUTCDate: proc (x: int) {.tags: [], raises: [].}
-      setUTCFullYear: proc (x: int) {.tags: [], raises: [].}
-      setUTCHours: proc (x: int) {.tags: [], raises: [].}
-      setUTCMilliseconds: proc (x: int) {.tags: [], raises: [].}
-      setUTCMinutes: proc (x: int) {.tags: [], raises: [].}
-      setUTCMonth: proc (x: int) {.tags: [], raises: [].}
-      setUTCSeconds: proc (x: int) {.tags: [], raises: [].}
-      setYear: proc (x: int) {.tags: [], raises: [].}
-      toGMTString: proc (): cstring {.tags: [], raises: [].}
-      toLocaleString: proc (): cstring {.tags: [], raises: [].}
+      getDay: proc (): int {.tags: [], raises: [], gcsafe.}
+      getFullYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      getHours: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMinutes: proc (): int {.tags: [], raises: [], gcsafe.}
+      getMonth: proc (): int {.tags: [], raises: [], gcsafe.}
+      getSeconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getTime: proc (): int {.tags: [], raises: [], gcsafe.}
+      getTimezoneOffset: proc (): int {.tags: [], raises: [], gcsafe.}
+      getDate: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCDate: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCFullYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCHours: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMinutes: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCMonth: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCSeconds: proc (): int {.tags: [], raises: [], gcsafe.}
+      getUTCDay: proc (): int {.tags: [], raises: [], gcsafe.}
+      getYear: proc (): int {.tags: [], raises: [], gcsafe.}
+      parse: proc (s: cstring): TTime {.tags: [], raises: [], gcsafe.}
+      setDate: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setHours: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setMonth: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setTime: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCDate: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCHours: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCMonth: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setUTCSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      setYear: proc (x: int) {.tags: [], raises: [], gcsafe.}
+      toGMTString: proc (): cstring {.tags: [], raises: [], gcsafe.}
+      toLocaleString: proc (): cstring {.tags: [], raises: [], gcsafe.}
 
 type
   TTimeInfo* = object of TObject ## represents a time in different parts
@@ -513,7 +513,7 @@ elif defined(JS):
     result.setFullYear(timeInfo.year)
     result.setDate(timeInfo.monthday)
   
-  proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
+  proc `$`(timeInfo: TTimeInfo): string = return $(timeInfoToTime(timeInfo))
   proc `$`(time: TTime): string = return $time.toLocaleString()
     
   proc `-` (a, b: TTime): int64 = 
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index e7bd363cf..3203ee699 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -11,7 +11,26 @@
 ## working with types
 
 proc name*(t: typedesc): string {.magic: "TypeTrait".}
-  ## Returns the name of the given type
+  ## Returns the name of the given type.
+  ##
+  ## Example:
+  ##
+  ## .. code-block::
+  ##
+  ##   import typetraits
+  ##
+  ##   proc `$`*[T](some:typedesc[T]): string = name(T)
+  ##
+  ##   template test(x): stmt =
+  ##     echo "type: ", type(x), ", value: ", x
+  ##
+  ##   test 42
+  ##   # --> type: int, value: 42
+  ##   test "Foo"
+  ##   # --> type: string, value: Foo
+  ##   test(@['A','B'])
+  ##   # --> type: seq[char], value: @[A, B]
+
 
 proc arity*(t: typedesc): int {.magic: "TypeTrait".}
-  ## Returns the arity of the given type
\ No newline at end of file
+  ## Returns the arity of the given type
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index f5640a1b4..7cc95f0ad 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -19,7 +19,7 @@
 import
   macros
 
-when defined(stdout):
+when declared(stdout):
   import os
 
 when not defined(ECMAScript):
@@ -99,7 +99,7 @@ template fail* =
   when not defined(ECMAScript):
     if AbortOnError: quit(1)
  
-  when defined(TestStatusIMPL):
+  when declared(TestStatusIMPL):
     TestStatusIMPL = FAILED
   else:
     program_result += 1
@@ -188,7 +188,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
   result = getAst(expectBody(errorTypes, exp.lineinfo, body))
 
 
-when defined(stdout):
+when declared(stdout):
   ## Reading settings
   var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string
 
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 95b48a850..1af7db7d5 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -151,6 +151,8 @@ proc addEscaped*(result: var string, s: string) =
     of '>': result.add("&gt;")
     of '&': result.add("&amp;")
     of '"': result.add("&quot;")
+    of '\'': result.add("&#x27;")
+    of '/': result.add("&#x2F;")
     else: result.add(c)
 
 proc escape*(s: string): string = 
@@ -164,6 +166,8 @@ proc escape*(s: string): string =
   ##  ``>``          ``&gt;``
   ##  ``&``          ``&amp;``
   ##  ``"``          ``&quot;``
+  ##  ``'``          ``&#x27;``
+  ##  ``/``          ``&#x2F;``
   ## ------------    -------------------
   result = newStringOfCap(s.len)
   addEscaped(result, s)
diff --git a/lib/system.nim b/lib/system.nim
index d77b4fdee..0df8849f5 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -13,6 +13,21 @@
 ## Each module implicitly imports the System module; it must not be listed
 ## explicitly. Because of this there cannot be a user-defined module named
 ## ``system``.
+##
+## Exception hierarchy
+## ===================
+##
+## For visual convenience here is the exception inheritance hierarchy
+## represented as a tree:
+##
+## .. include:: ../doc/exception_hierarchy_fragment.txt
+##
+## Module system
+## =============
+##
+
+# That lonesome header above is to prevent :idx: entries from being mentioned
+# in the global index as part of the previous header (Exception hierarchy).
 
 type
   int* {.magic: Int.} ## default integer type; bitwidth depends on
@@ -83,16 +98,8 @@ type
 
 proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ## Special compile-time procedure that checks whether `x` is
-  ## defined. `x` has to be an identifier or a qualified identifier.
-  ## This can be used to check whether a library provides a certain
-  ## feature or not:
-  ##
-  ## .. code-block:: Nimrod
-  ##   when not defined(strutils.toUpper):
-  ##     # provide our own toUpper proc here, because strutils is
-  ##     # missing it.
-  ##
-  ## You can also check external symbols introduced through the compiler's
+  ## defined.
+  ## `x` is an external symbol introduced through the compiler's
   ## `-d:x switch <nimrodc.html#compile-time-symbols>`_ to enable build time
   ## conditionals:
   ##
@@ -101,13 +108,28 @@ proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ##     # Do here programmer friendly expensive sanity checks.
   ##   # Put here the normal code
 
+proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
+  ## Special compile-time procedure that checks whether `x` is
+  ## declared. `x` has to be an identifier or a qualified identifier.
+  ## This can be used to check whether a library provides a certain
+  ## feature or not:
+  ##
+  ## .. code-block:: Nimrod
+  ##   when not defined(strutils.toUpper):
+  ##     # provide our own toUpper proc here, because strutils is
+  ##     # missing it.
+
 when defined(useNimRtl):
   {.deadCodeElim: on.}
 
 proc definedInScope*(x: expr): bool {.
+  magic: "DefinedInScope", noSideEffect, deprecated.}
+  ## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
+
+proc declaredInScope*(x: expr): bool {.
   magic: "DefinedInScope", noSideEffect.}
   ## Special compile-time procedure that checks whether `x` is
-  ## defined in the current scope. `x` has to be an identifier.
+  ## declared in the current scope. `x` has to be an identifier.
 
 proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
   ## Boolean not; returns true iff ``x == false``.
@@ -301,9 +323,11 @@ type
   FWriteIO* = object of FIO    ## Effect describing a write IO operation.
   FExecIO* = object of FIO     ## Effect describing an executing IO operation.
 
-  E_Base* {.compilerproc.} = object of TObject ## base exception class;
-                                               ## each exception has to
-                                               ## inherit from `E_Base`.
+  E_Base* {.compilerproc.} = object of TObject ## \
+    ## Base exception class.
+    ##
+    ## Each exception has to inherit from `E_Base`. See the full `exception
+    ## hierarchy`_.
     parent: ref E_Base        ## parent exception (can be used as a stack)
     name: cstring             ## The exception's name is its Nimrod identifier.
                               ## This field is filled automatically in the
@@ -313,99 +337,142 @@ type
                                         ## is bad style.
     trace: string
 
-  EAsynch* = object of E_Base ## Abstract exception class for
-                              ## *asynchronous exceptions* (interrupts).
-                              ## This is rarely needed: Most
-                              ## exception types inherit from `ESynch`
-  ESynch* = object of E_Base  ## Abstract exception class for
-                              ## *synchronous exceptions*. Most exceptions
-                              ## should be inherited (directly or indirectly)
-                              ## from ESynch.
-  ESystem* = object of ESynch ## Abstract class for exceptions that the runtime
-                              ## system raises.
-  EIO* = object of ESystem    ## raised if an IO error occured.
-  EOS* = object of ESystem    ## raised if an operating system service failed.
+  EAsynch* = object of E_Base ## \
+    ## Abstract exception class for *asynchronous exceptions* (interrupts).
+    ##
+    ## This is rarely needed: most exception types inherit from `ESynch
+    ## <#ESynch>`_. See the full `exception hierarchy`_.
+  EControlC* = object of EAsynch ## \
+    ## Raised for Ctrl+C key presses in console applications.
+    ##
+    ## See the full `exception hierarchy`_.
+  ESynch* = object of E_Base ## \
+    ## Abstract exception class for *synchronous exceptions*.
+    ##
+    ## Most exceptions should be inherited (directly or indirectly) from
+    ## `ESynch` instead of from `EAsynch <#EAsynch>`_. See the full `exception
+    ## hierarchy`_.
+  ESystem* = object of ESynch ## \
+    ## Abstract class for exceptions that the runtime system raises.
+    ##
+    ## See the full `exception hierarchy`_.
+  EIO* = object of ESystem ## \
+    ## Raised if an IO error occured.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOS* = object of ESystem ## \
+    ## Raised if an operating system service failed.
+    ##
+    ## See the full `exception hierarchy`_.
     errorCode*: int32 ## OS-defined error code describing this error.
-  EInvalidLibrary* = object of EOS ## raised if a dynamic library
-                                   ## could not be loaded.
-  EResourceExhausted* = object of ESystem ## raised if a resource request
-                                          ## could not be fullfilled.
-  EArithmetic* = object of ESynch       ## raised if any kind of arithmetic
-                                        ## error occured.
-  EDivByZero* {.compilerproc.} =
-    object of EArithmetic ## is the exception class for integer divide-by-zero
-                          ## errors.
-  EOverflow* {.compilerproc.} =
-    object of EArithmetic  ## is the exception class for integer calculations
-                           ## whose results are too large to fit in the
-                           ## provided bits.
-
-  EAccessViolation* {.compilerproc.} =
-    object of ESynch ## the exception class for invalid memory access errors
-
-  EAssertionFailed* {.compilerproc.} =
-    object of ESynch  ## is the exception class for Assert
-                      ## procedures that is raised if the
-                      ## assertion proves wrong
-
-  EControlC* = object of EAsynch        ## is the exception class for Ctrl+C
-                                        ## key presses in console applications.
-
-  EInvalidValue* = object of ESynch     ## is the exception class for string
-                                        ## and object conversion errors.
-  EInvalidKey* = object of EInvalidValue ## is the exception class if a key
-                                         ## cannot be found in a table.
-
-  EOutOfMemory* = object of ESystem     ## is the exception class for
-                                        ## unsuccessful attempts to allocate
-                                        ## memory.
-
-  EInvalidIndex* = object of ESynch     ## is raised if an array index is out
-                                        ## of bounds.
-  EInvalidField* = object of ESynch     ## is raised if a record field is not
-                                        ## accessible because its dicriminant's
-                                        ## value does not fit.
-
-  EOutOfRange* = object of ESynch       ## is raised if a range check error
-                                        ## occurred.
-
-  EStackOverflow* = object of ESystem   ## is raised if the hardware stack
-                                        ## used for subroutine calls overflowed.
-
-  ENoExceptionToReraise* = object of ESynch ## is raised if there is no
-                                            ## exception to reraise.
-
-  EInvalidObjectAssignment* =
-    object of ESynch ## is raised if an object gets assigned to its
-                     ## parent's object.
-
-  EInvalidObjectConversion* =
-    object of ESynch ## is raised if an object is converted to an incompatible
-                     ## object type.
-
-  EFloatingPoint* = object of ESynch ## base class for floating point exceptions
-  EFloatInvalidOp* {.compilerproc.} = 
-    object of EFloatingPoint ## Invalid operation according to IEEE: Raised by 
-                             ## 0.0/0.0, for example.
-  EFloatDivByZero* {.compilerproc.} = 
-    object of EFloatingPoint ## Division by zero. Divisor is zero and dividend 
-                             ## is a finite nonzero number.
-  EFloatOverflow* {.compilerproc.} = 
-    object of EFloatingPoint ## Overflow. Operation produces a result 
-                             ## that exceeds the range of the exponent
-  EFloatUnderflow* {.compilerproc.} = 
-    object of EFloatingPoint ## Underflow. Operation produces a result 
-                             ## that is too small to be represented as 
-                             ## a normal number
-  EFloatInexact* {.compilerproc.} = 
-    object of EFloatingPoint ## Inexact. Operation produces a result
-                             ## that cannot be represented with infinite
-                             ## precision -- for example, 2.0 / 3.0, log(1.1) 
-                             ## NOTE: Nimrod currently does not detect these!
-  EDeadThread* =
-    object of ESynch ## is raised if it is attempted to send a message to a
-                     ## dead thread.
-                     
+  EInvalidLibrary* = object of EOS ## \
+    ## Raised if a dynamic library could not be loaded.
+    ##
+    ## See the full `exception hierarchy`_.
+  EResourceExhausted* = object of ESystem ## \
+    ## Raised if a resource request could not be fullfilled.
+    ##
+    ## See the full `exception hierarchy`_.
+  EArithmetic* = object of ESynch ## \
+    ## Raised if any kind of arithmetic error occured.
+    ##
+    ## See the full `exception hierarchy`_.
+  EDivByZero* {.compilerproc.} = object of EArithmetic ## \
+    ## Raised for runtime integer divide-by-zero errors.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOverflow* {.compilerproc.} = object of EArithmetic ## \
+    ## Raised for runtime integer overflows.
+    ##
+    ## This happens for calculations whose results are too large to fit in the
+    ## provided bits.  See the full `exception hierarchy`_.
+  EAccessViolation* {.compilerproc.} = object of ESynch ## \
+    ## Raised for invalid memory access errors
+    ##
+    ## See the full `exception hierarchy`_.
+  EAssertionFailed* {.compilerproc.} = object of ESynch ## \
+    ## Raised when assertion is proved wrong.
+    ##
+    ## Usually the result of using the `assert() template <#assert>`_.  See the
+    ## full `exception hierarchy`_.
+  EInvalidValue* = object of ESynch ## \
+    ## Raised for string and object conversion errors.
+  EInvalidKey* = object of EInvalidValue ## \
+    ## Raised if a key cannot be found in a table.
+    ##
+    ## Mostly used by the `tables <tables.html>`_ module, it can also be raised
+    ## by other collection modules like `sets <sets.html>`_ or `strtabs
+    ## <strtabs.html>`_. See the full `exception hierarchy`_.
+  EOutOfMemory* = object of ESystem ## \
+    ## Raised for unsuccessful attempts to allocate memory.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidIndex* = object of ESynch ## \
+    ## Raised if an array index is out of bounds.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidField* = object of ESynch ## \
+    ## Raised if a record field is not accessible because its dicriminant's
+    ## value does not fit.
+    ##
+    ## See the full `exception hierarchy`_.
+  EOutOfRange* = object of ESynch ## \
+    ## Raised if a range check error occurred.
+    ##
+    ## See the full `exception hierarchy`_.
+  EStackOverflow* = object of ESystem ## \
+    ## Raised if the hardware stack used for subroutine calls overflowed.
+    ##
+    ## See the full `exception hierarchy`_.
+  ENoExceptionToReraise* = object of ESynch ## \
+    ## Raised if there is no exception to reraise.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidObjectAssignment* = object of ESynch ## \
+    ## Raised if an object gets assigned to its parent's object.
+    ##
+    ## See the full `exception hierarchy`_.
+  EInvalidObjectConversion* = object of ESynch ## \
+    ## Raised if an object is converted to an incompatible object type.
+    ##
+    ## See the full `exception hierarchy`_.
+  EFloatingPoint* = object of ESynch ## \
+    ## Base class for floating point exceptions.
+    ##
+    ## See the full `exception hierarchy`_.
+  EFloatInvalidOp* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised by invalid operations according to IEEE.
+    ##
+    ## Raised by ``0.0/0.0``, for example.  See the full `exception
+    ## hierarchy`_.
+  EFloatDivByZero* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised by division by zero.
+    ##
+    ## Divisor is zero and dividend is a finite nonzero number.  See the full
+    ## `exception hierarchy`_.
+  EFloatOverflow* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for overflows.
+    ##
+    ## The operation produced a result that exceeds the range of the exponent.
+    ## See the full `exception hierarchy`_.
+  EFloatUnderflow* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for underflows.
+    ##
+    ## The operation produced a result that is too small to be represented as a
+    ## normal number. See the full `exception hierarchy`_.
+  EFloatInexact* {.compilerproc.} = object of EFloatingPoint ## \
+    ## Raised for inexact results.
+    ##
+    ## The operation produced a result that cannot be represented with infinite
+    ## precision -- for example: ``2.0 / 3.0, log(1.1)``
+    ##
+    ## **NOTE**: Nimrod currently does not detect these!  See the full
+    ## `exception hierarchy`_.
+  EDeadThread* = object of ESynch ## \
+    ## Raised if it is attempted to send a message to a dead thread.
+    ##
+    ## See the full `exception hierarchy`_.
+
   TResult* = enum Failure, Success
 
 proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
@@ -782,13 +849,13 @@ proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
   ##   assert((1..3).contains(4) == false)
   result = s.a <= value and value <= s.b
 
-template `in` * (x, y: expr): expr {.immediate.} = contains(y, x)
+template `in` * (x, y: expr): expr {.immediate, dirty.} = contains(y, x)
   ## Sugar for contains
   ##
   ## .. code-block:: Nimrod
   ##   assert(1 in (1..3) == true)
   ##   assert(5 in (1..3) == false)
-template `notin` * (x, y: expr): expr {.immediate.} = not contains(y, x)
+template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x)
   ## Sugar for not containing
   ##
   ## .. code-block:: Nimrod
@@ -1930,16 +1997,16 @@ when not defined(nimrodVM) and hostOS != "standalone":
     ## returns an informative string about the GC's activity. This may be useful
     ## for tweaking.
     
-  proc GC_ref*[T](x: ref T) {.magic: "GCref".}
-  proc GC_ref*[T](x: seq[T]) {.magic: "GCref".}
-  proc GC_ref*(x: string) {.magic: "GCref".}
+  proc GC_ref*[T](x: ref T) {.magic: "GCref", gcsafe.}
+  proc GC_ref*[T](x: seq[T]) {.magic: "GCref", gcsafe.}
+  proc GC_ref*(x: string) {.magic: "GCref", gcsafe.}
     ## marks the object `x` as referenced, so that it will not be freed until
     ## it is unmarked via `GC_unref`. If called n-times for the same object `x`,
     ## n calls to `GC_unref` are needed to unmark `x`. 
     
-  proc GC_unref*[T](x: ref T) {.magic: "GCunref".}
-  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref".}
-  proc GC_unref*(x: string) {.magic: "GCunref".}
+  proc GC_unref*[T](x: ref T) {.magic: "GCunref", gcsafe.}
+  proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", gcsafe.}
+  proc GC_unref*(x: string) {.magic: "GCunref", gcsafe.}
     ## see the documentation of `GC_ref`.
 
 template accumulateResult*(iter: expr) =
@@ -2058,7 +2125,7 @@ template newException*(exceptn: typedesc, message: string): expr =
 when hostOS == "standalone":
   include panicoverride
 
-when not defined(sysFatal):
+when not declared(sysFatal):
   template sysFatal(exceptn: typedesc, message: string) =
     when hostOS == "standalone":
       panic(message)
@@ -2110,11 +2177,17 @@ when not defined(JS): #and not defined(NimrodVM):
       # WARNING: This is very fragile! An array size of 8 does not work on my
       # Linux 64bit system. -- That's because the stack direction is the other
       # way round.
-      when defined(setStackBottom):
+      when declared(setStackBottom):
         var locals {.volatile.}: pointer
         locals = addr(locals)
         setStackBottom(locals)
 
+    proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} =
+      # We need to keep initStackBottom around for now to avoid
+      # bootstrapping problems.
+      when declared(setStackBottom):
+        setStackBottom(locals)
+
     var
       strDesc: TNimType
 
@@ -2383,7 +2456,7 @@ when not defined(JS): #and not defined(NimrodVM):
       hasRaiseAction: bool
       raiseAction: proc (e: ref E_Base): bool {.closure.}
   
-  when defined(initAllocator):
+  when declared(initAllocator):
     initAllocator()
   when hasThreadSupport:
     include "system/syslocks"
@@ -2500,11 +2573,11 @@ when not defined(JS): #and not defined(NimrodVM):
     include "system/assign"
     include "system/repr"
 
-    proc getCurrentException*(): ref E_Base {.compilerRtl, inl.} =
+    proc getCurrentException*(): ref E_Base {.compilerRtl, inl, gcsafe.} =
       ## retrieves the current exception; if there is none, nil is returned.
       result = currException
 
-    proc getCurrentExceptionMsg*(): string {.inline.} =
+    proc getCurrentExceptionMsg*(): string {.inline, gcsafe.} =
       ## retrieves the error message that was attached to the current
       ## exception; if there is none, "" is returned.
       var e = getCurrentException()
@@ -2956,7 +3029,7 @@ proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} =
   ##     echo "'+' for integers is available"
   discard
 
-when defined(initDebugger):
+when declared(initDebugger):
   initDebugger()
 
 when hostOS != "standalone":
@@ -2997,18 +3070,12 @@ proc locals*(): TObject {.magic: "Locals", noSideEffect.} =
   ##   # -> B is 1
   discard
 
-proc deepCopy*[T](x: T): T {.magic: "DeepCopy", noSideEffect.} =
-  ## performs a deep copy of `x`. This is also used by the code generator
-  ## for the implementation of ``spawn``.
-  discard
+when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS):
+  proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
+    ## performs a deep copy of `x`. This is also used by the code generator
+    ## for the implementation of ``spawn``.
+    discard
 
-{.pop.} #{.push warning[GcMem]: off.}
+  include "system/deepcopy"
 
-when not defined(booting):
-  type
-    semistatic*[T] = static[T] | T
-    # indicates a param of proc specialized for each static value,
-    # but also accepting run-time values
-
-  template isStatic*(x): expr = compiles(static(x))
-    # checks whether `x` is a value known at compile-time
+{.pop.} #{.push warning[GcMem]: off.}
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 511a006d3..673d55582 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -39,7 +39,7 @@ var
   c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar
 
 # constants faked as variables:
-when not defined(SIGINT):
+when not declared(SIGINT):
   when NoFakeVars:
     when defined(windows):
       const
@@ -78,10 +78,23 @@ when defined(macosx):
 else:
   template SIGBUS: expr = SIGSEGV
 
-proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
-  header: "<setjmp.h>", importc: "longjmp".}
-proc c_setjmp(jmpb: C_JmpBuf): cint {.
-  header: "<setjmp.h>", importc: "setjmp".}
+when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "<setjmp.h>", importc: "siglongjmp".}
+  template c_setjmp(jmpb: C_JmpBuf): cint =
+    proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
+      header: "<setjmp.h>", importc: "sigsetjmp".}
+    c_sigsetjmp(jmpb, 0)
+elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "<setjmp.h>", importc: "_longjmp".}
+  proc c_setjmp(jmpb: C_JmpBuf): cint {.
+    header: "<setjmp.h>", importc: "_setjmp".}
+else:
+  proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
+    header: "<setjmp.h>", importc: "longjmp".}
+  proc c_setjmp(jmpb: C_JmpBuf): cint {.
+    header: "<setjmp.h>", importc: "setjmp".}
 
 proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
   importc: "signal", header: "<signal.h>".}
@@ -132,7 +145,7 @@ proc c_realloc(p: pointer, newsize: int): pointer {.
   importc: "realloc", header: "<stdlib.h>".}
 
 when hostOS != "standalone":
-  when not defined(errno):
+  when not declared(errno):
     when defined(NimrodVM):
       var vmErrnoWrapper {.importc.}: ptr cint
       template errno: expr = 
diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim
index d9b3aebac..7672947cd 100644
--- a/lib/system/arithm.nim
+++ b/lib/system/arithm.nim
@@ -114,63 +114,69 @@ when asmVersion and not defined(gcc) and not defined(llvm_gcc):
   proc addInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     # a in eax, and b in edx
     asm """
-        mov eax, `a`
-        add eax, `b`
+        mov eax, ecx
+        add eax, edx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc subInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        sub eax, `b`
+        mov eax, ecx
+        sub eax, edx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc negInt(a: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
+        mov eax, ecx
         neg eax
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc divInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         idiv ecx
         jno  theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
   proc modInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         idiv ecx
         jno theEnd
         call `raiseOverflow`
       theEnd:
         mov eax, edx
+        ret
     """
 
   proc mulInt(a, b: int): int {.compilerProc, asmNoStackFrame.} =
     asm """
-        mov eax, `a`
-        mov ecx, `b`
+        mov eax, ecx
+        mov ecx, edx
         xor edx, edx
         imul ecx
         jno theEnd
         call `raiseOverflow`
       theEnd:
+        ret
     """
 
 elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
@@ -241,26 +247,26 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
     """
 
 # Platform independent versions of the above (slower!)
-when not defined(addInt):
+when not declared(addInt):
   proc addInt(a, b: int): int {.compilerProc, inline.} =
     result = a +% b
     if (result xor a) >= 0 or (result xor b) >= 0:
       return result
     raiseOverflow()
 
-when not defined(subInt):
+when not declared(subInt):
   proc subInt(a, b: int): int {.compilerProc, inline.} =
     result = a -% b
     if (result xor a) >= 0 or (result xor not b) >= 0:
       return result
     raiseOverflow()
 
-when not defined(negInt):
+when not declared(negInt):
   proc negInt(a: int): int {.compilerProc, inline.} =
     if a != low(int): return -a
     raiseOverflow()
 
-when not defined(divInt):
+when not declared(divInt):
   proc divInt(a, b: int): int {.compilerProc, inline.} =
     if b == 0:
       raiseDivByZero()
@@ -268,13 +274,13 @@ when not defined(divInt):
       raiseOverflow()
     return a div b
 
-when not defined(modInt):
+when not declared(modInt):
   proc modInt(a, b: int): int {.compilerProc, inline.} =
     if b == 0:
       raiseDivByZero()
     return a mod b
 
-when not defined(mulInt):
+when not declared(mulInt):
   #
   # This code has been inspired by Python's source code.
   # The native int product x*y is either exactly right or *way* off, being
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index 2ae945fb1..0e27eb57f 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -89,14 +89,10 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
     copyMem(dest, src, mt.size) # copy raw bits
 
 proc genericAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
-  GC_disable()
   genericAssignAux(dest, src, mt, false)
-  GC_enable()
 
 proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
-  GC_disable()
   genericAssignAux(dest, src, mt, true)
-  GC_enable()
 
 when false:
   proc debugNimType(t: PNimType) =
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 43b3f0438..3ef9d00ec 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -7,30 +7,36 @@
 #    distribution, for details about the copyright.
 #
 
-## Atomic operations for Nimrod.
+# Atomic operations for Nimrod.
 {.push stackTrace:off.}
 
 const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
 
 when someGcc and hasThreadSupport:
-  type 
-    AtomMemModel* = enum
-      ATOMIC_RELAXED,  ## No barriers or synchronization. 
-      ATOMIC_CONSUME,  ## Data dependency only for both barrier and
-                       ## synchronization with another thread.
-      ATOMIC_ACQUIRE,  ## Barrier to hoisting of code and synchronizes with
-                       ## release (or stronger) 
-                       ## semantic stores from another thread.
-      ATOMIC_RELEASE,  ## Barrier to sinking of code and synchronizes with
-                       ## acquire (or stronger) 
-                       ## semantic loads from another thread. 
-      ATOMIC_ACQ_REL,  ## Full barrier in both directions and synchronizes
-                       ## with acquire loads 
-                       ## and release stores in another thread.
-      ATOMIC_SEQ_CST   ## Full barrier in both directions and synchronizes
-                       ## with acquire loads 
-                       ## and release stores in all threads.
-
+  type AtomMemModel* = distinct cint
+  var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel
+    ## No barriers or synchronization.
+  var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel
+    ## Data dependency only for both barrier and
+    ## synchronization with another thread.
+  var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel
+    ## Barrier to hoisting of code and synchronizes with
+    ## release (or stronger) 
+    ## semantic stores from another thread.
+  var ATOMIC_RELEASE* {.importc: "__ATOMIC_RELEASE", nodecl.}: AtomMemModel
+    ## Barrier to sinking of code and synchronizes with
+    ## acquire (or stronger) 
+    ## semantic loads from another thread. 
+  var ATOMIC_ACQ_REL* {.importc: "__ATOMIC_ACQ_REL", nodecl.}: AtomMemModel
+    ## Full barrier in both directions and synchronizes
+    ## with acquire loads 
+    ## and release stores in another thread.
+  var ATOMIC_SEQ_CST* {.importc: "__ATOMIC_SEQ_CST", nodecl.}: AtomMemModel
+    ## Full barrier in both directions and synchronizes
+    ## with acquire loads 
+    ## and release stores in all threads.
+
+  type
     TAtomType* = TNumber|pointer|ptr|char
       ## Type Class representing valid types for use with atomic procs
 
@@ -166,15 +172,15 @@ else:
     result = p[]
 
 proc atomicInc*(memLoc: var int, x: int = 1): int =
-  when defined(gcc) and hasThreadSupport:
+  when someGcc and hasThreadSupport:
     result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED)
   else:
     inc(memLoc, x)
     result = memLoc
   
 proc atomicDec*(memLoc: var int, x: int = 1): int =
-  when defined(gcc) and hasThreadSupport:
-    when defined(atomic_sub_fetch):
+  when someGcc and hasThreadSupport:
+    when declared(atomic_sub_fetch):
       result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
     else:
       result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
@@ -196,19 +202,19 @@ else:
   # XXX is this valid for 'int'?
 
 
-when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)):
+when (defined(x86) or defined(amd64)) and someGcc:
   proc cpuRelax {.inline.} =
     {.emit: """asm volatile("pause" ::: "memory");""".}
 elif (defined(x86) or defined(amd64)) and defined(vcc):
   proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".}
-elif defined(intelc):
+elif defined(icl):
   proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".}
 elif false:
   from os import sleep
 
   proc cpuRelax {.inline.} = os.sleep(1)
 
-when not defined(fence) and hasThreadSupport:
+when not declared(fence) and hasThreadSupport:
   # XXX fixme
   proc fence*() {.inline.} =
     var dummy: bool
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index e5535dbdc..a5d5c0802 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -14,7 +14,7 @@
 ## **Note:** The current implementation of message passing is slow and does

 ## not work with cyclic data structures.

   
-when not defined(NimString): 
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 

 type

@@ -226,15 +226,16 @@ proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
   llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

   releaseSys(q.lock)

 
-proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvaliable: bool,
+proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
                                                   msg: TMsg] =
   ## try to receives a message from the channel `c` if available. Otherwise
   ## it returns ``(false, default(msg))``.
   var q = cast[PRawChannel](addr(c))

-  if q.mask != ChannelDeadMask:

-    lockChannel(q):

+  if q.mask != ChannelDeadMask:
+    if tryAcquireSys(q.lock):

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

+      result.dataAvailable = true

+      releaseSys(q.lock)

 

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

   ## returns the current number of messages in the channel `c`. Returns -1

diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
new file mode 100644
index 000000000..e7eb1cdb4
--- /dev/null
+++ b/lib/system/deepcopy.nim
@@ -0,0 +1,141 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) {.gcsafe.}
+proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  case n.kind
+  of nkSlot:
+    genericDeepCopyAux(cast[pointer](d +% n.offset), 
+                       cast[pointer](s +% n.offset), n.typ)
+  of nkList:
+    for i in 0..n.len-1:
+      genericDeepCopyAux(dest, src, n.sons[i])
+  of nkCase:
+    var dd = selectBranch(dest, n)
+    var m = selectBranch(src, n)
+    # reset if different branches are in use; note different branches also
+    # imply that's not self-assignment (``x = x``)!
+    if m != dd and dd != nil: 
+      genericResetAux(dest, dd)
+    copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
+            n.typ.size)
+    if m != nil:
+      genericDeepCopyAux(dest, src, m)
+  of nkNone: sysAssert(false, "genericDeepCopyAux")
+
+proc copyDeepString(src: NimString): NimString {.inline.} =
+  if src != nil:
+    result = rawNewString(src.space)
+    result.len = src.len
+    c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  sysAssert(mt != nil, "genericDeepCopyAux 2")
+  case mt.kind
+  of tyString:
+    var x = cast[PPointer](dest)
+    var s2 = cast[PPointer](s)[]
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+    else:
+      unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
+  of tySequence:
+    var s2 = cast[PPointer](src)[]
+    var seq = cast[PGenericSeq](s2)
+    var x = cast[PPointer](dest)
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+      return
+    sysAssert(dest != nil, "genericDeepCopyAux 3")
+    unsureAsgnRef(x, newSeq(mt, seq.len))
+    var dst = cast[TAddress](cast[PPointer](dest)[])
+    for i in 0..seq.len-1:
+      genericDeepCopyAux(
+        cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
+        cast[pointer](cast[TAddress](s2) +% i *% mt.base.size +%
+                     GenericSeqSize),
+        mt.base)
+  of tyObject:
+    # we need to copy m_type field for tyObject, as it could be empty for
+    # sequence reallocations:
+    var pint = cast[ptr PNimType](dest)
+    pint[] = cast[ptr PNimType](src)[]
+    if mt.base != nil:
+      genericDeepCopyAux(dest, src, mt.base)
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyTuple:
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyArray, tyArrayConstr:
+    for i in 0..(mt.size div mt.base.size)-1:
+      genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
+                         cast[pointer](s +% i*% mt.base.size), mt.base)
+  of tyRef:
+    if mt.base.deepCopy != nil:
+      let z = mt.base.deepCopy(cast[PPointer](src)[])
+      unsureAsgnRef(cast[PPointer](dest), z)
+    else:
+      # we modify the header of the cell temporarily; instead of the type
+      # field we store a forwarding pointer. XXX This is bad when the cloning
+      # fails due to OOM etc.
+      let s2 = cast[PPointer](src)[]
+      if s2 == nil:
+        unsureAsgnRef(cast[PPointer](dest), s2)
+        return
+      when declared(usrToCell):
+        # unfortunately we only have cycle detection for our native GCs.
+        let x = usrToCell(s2)
+        let forw = cast[int](x.typ)
+        if (forw and 1) == 1:
+          # we stored a forwarding pointer, so let's use that:
+          let z = cast[pointer](forw and not 1)
+          unsureAsgnRef(cast[PPointer](dest), z)
+        else:
+          let realType = x.typ
+          let z = newObj(realType, realType.base.size)
+          
+          unsureAsgnRef(cast[PPointer](dest), z)
+          x.typ = cast[PNimType](cast[int](z) or 1)
+          genericDeepCopyAux(z, s2, realType.base)
+          x.typ = realType
+      else:
+        let realType = mt
+        let z = newObj(realType, realType.base.size)        
+        unsureAsgnRef(cast[PPointer](dest), z)
+        genericDeepCopyAux(z, s2, realType.base)        
+  of tyPtr:
+    # no cycle check here, but also not really required
+    if mt.base.deepCopy != nil:
+      cast[PPointer](dest)[] = mt.base.deepCopy(cast[PPointer](s)[])
+    else:
+      cast[PPointer](dest)[] = cast[PPointer](s)[]
+  else:
+    copyMem(dest, src, mt.size)
+
+proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  genericDeepCopyAux(dest, src, mt)
+
+proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  # also invoked for 'string'
+  var src = src
+  genericDeepCopy(dest, addr(src), mt)
+
+proc genericDeepCopyOpenArray(dest, src: pointer, len: int,
+                            mt: PNimType) {.compilerproc.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  for i in 0..len-1:
+    genericDeepCopy(cast[pointer](d +% i*% mt.base.size),
+                    cast[pointer](s +% i*% mt.base.size), mt.base)
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index e1a5a958f..3c5436afb 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -38,11 +38,11 @@ proc chckRangeF(x, a, b: float): float {.inline, compilerproc, gcsafe.}
 proc chckNil(p: pointer) {.noinline, compilerproc, gcsafe.}
 
 var
-  framePtr {.rtlThreadVar.}: PFrame
-  excHandler {.rtlThreadVar.}: PSafePoint
+  framePtr {.threadvar.}: PFrame
+  excHandler {.threadvar.}: PSafePoint
     # list of exception handlers
     # a global variable for the root of all try blocks
-  currException {.rtlThreadVar.}: ref E_Base
+  currException {.threadvar.}: ref E_Base
 
 proc popFrame {.compilerRtl, inl.} =
   framePtr = framePtr.prev
@@ -307,7 +307,7 @@ when not defined(noSignalHandler):
         action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
       else:
         block platformSpecificSignal:
-          when defined(SIGPIPE):
+          when declared(SIGPIPE):
             if s == SIGPIPE:
               action("SIGPIPE: Pipe closed.\n")
               break platformSpecificSignal
@@ -336,7 +336,7 @@ when not defined(noSignalHandler):
     c_signal(SIGFPE, signalHandler)
     c_signal(SIGILL, signalHandler)
     c_signal(SIGBUS, signalHandler)
-    when defined(SIGPIPE):
+    when declared(SIGPIPE):
       c_signal(SIGPIPE, signalHandler)
 
   registerSignalHandler() # call it in initialization section
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 3b85fe600..0c1fc7748 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -30,7 +30,7 @@ const
                                           # cycles instead of the complex
                                           # algorithm
 
-when withRealTime and not defined(getTicks):
+when withRealTime and not declared(getTicks):
   include "system/timers"
 when defined(memProfiler):
   proc nimProfile(requestedSize: int)
@@ -413,7 +413,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
 {.push stackTrace: off, profiler:off.}
 proc gcInvariant*() =
   sysAssert(allocInv(gch.region), "injected")
-  when defined(markForDebug):
+  when declared(markForDebug):
     markForDebug(gch)
 {.pop.}
 
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index 31c99a601..132da9885 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -26,7 +26,7 @@ const
                       # this seems to be a good value
   withRealTime = defined(useRealtimeGC)
 
-when withRealTime and not defined(getTicks):
+when withRealTime and not declared(getTicks):
   include "system/timers"
 when defined(memProfiler):
   proc nimProfile(requestedSize: int)
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index 64174e60f..ef8f50831 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-when defined(NimString): 
+when declared(NimString): 
   # we are in system module:
   {.pragma: codegenType, compilerproc.}
 else:
@@ -86,6 +86,7 @@ type
     node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
     finalizer: pointer # the finalizer for the type
     marker: proc (p: pointer, op: int) {.nimcall, gcsafe.} # marker proc for GC
+    deepcopy: proc (p: pointer): pointer {.nimcall, gcsafe.}
   PNimType = ptr TNimType
   
 # node.len may be the ``first`` element of a set
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 8766906e3..423f63e2a 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -515,7 +515,7 @@ proc isFatPointer(ti: PNimType): bool =
 
 proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
 
-proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} =
+proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} =
   case n.kind
   of nkNone: sysAssert(false, "nimCopyAux")
   of nkSlot:
@@ -566,7 +566,7 @@ proc nimCopy(x: pointer, ti: PNimType): pointer =
   else:
     result = x
 
-proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} =
+proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} =
   case ti.kind
   of tyPtr, tyRef, tyVar, tyNil:
     if not isFatPointer(ti):
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index a09b6cf93..606743f51 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -131,6 +131,14 @@ when defined(boehmgc):
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = boehmDealloc(p)
 
+    when hasThreadSupport:
+      proc getFreeSharedMem(): int =
+        boehmGetFreeBytes()
+      proc getTotalSharedMem(): int =
+        boehmGetHeapSize()
+      proc getOccupiedSharedMem(): int =
+        getTotalSharedMem() - getFreeSharedMem()
+
     #boehmGCincremental()
 
     proc GC_disable() = boehmGC_disable()
@@ -164,11 +172,11 @@ when defined(boehmgc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   type
@@ -180,7 +188,7 @@ when defined(boehmgc):
   proc alloc0(r: var TMemRegion, size: int): pointer =
     result = alloc(size)
     zeroMem(result, size)
-  proc dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)  
+  proc dealloc(r: var TMemRegion, p: pointer) = boehmDealloc(p)  
   proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
   proc deallocOsPages() {.inline.} = discard
 
@@ -239,11 +247,11 @@ elif defined(nogc) and defined(useMalloc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   type
@@ -292,11 +300,11 @@ elif defined(nogc):
   proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
   proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
   
-  proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
-  proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
+  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
   var allocator {.rtlThreadVar.}: TMemRegion
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index f8f949668..8e1bc5f26 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -121,7 +121,7 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
 type
   TReprClosure {.final.} = object # we cannot use a global variable here
                                   # as this wouldn't be thread-safe
-    when defined(TCellSet):
+    when declared(TCellSet):
       marked: TCellSet
     recdepth: int       # do not recurse endlessly
     indent: int         # indentation
@@ -130,16 +130,16 @@ when not defined(useNimRtl):
   proc initReprClosure(cl: var TReprClosure) =
     # Important: cellsets does not lock the heap when doing allocations! We
     # have to do it here ...
-    when hasThreadSupport and hasSharedHeap and defined(heapLock):
+    when hasThreadSupport and hasSharedHeap and declared(heapLock):
       AcquireSys(HeapLock)
-    when defined(TCellSet):
+    when declared(TCellSet):
       init(cl.marked)
     cl.recdepth = -1      # default is to display everything!
     cl.indent = 0
 
   proc deinitReprClosure(cl: var TReprClosure) =
-    when defined(TCellSet): deinit(cl.marked)
-    when hasThreadSupport and hasSharedHeap and defined(heapLock): 
+    when declared(TCellSet): deinit(cl.marked)
+    when hasThreadSupport and hasSharedHeap and declared(heapLock): 
       ReleaseSys(HeapLock)
 
   proc reprBreak(result: var string, cl: TReprClosure) =
@@ -201,7 +201,7 @@ when not defined(useNimRtl):
   proc reprRef(result: var string, p: pointer, typ: PNimType,
                cl: var TReprClosure) =
     # we know that p is not nil here:
-    when defined(TCellSet):
+    when declared(TCellSet):
       when defined(boehmGC) or defined(nogc):
         var cell = cast[PCell](p)
       else:
@@ -221,7 +221,7 @@ when not defined(useNimRtl):
     dec(cl.recdepth)
     case typ.kind
     of tySet: reprSetAux(result, p, typ)
-    of tyArray: reprArray(result, p, typ, cl)
+    of tyArray, tyArrayConstr: reprArray(result, p, typ, cl)
     of tyTuple: reprRecord(result, p, typ, cl)
     of tyObject: 
       var t = cast[ptr PNimType](p)[]
@@ -275,7 +275,7 @@ when not defined(useNimRtl):
       cl: TReprClosure
     initReprClosure(cl)
     result = ""
-    if typ.kind in {tyObject, tyTuple, tyArray, tySet}:
+    if typ.kind in {tyObject, tyTuple, tyArray, tyArrayConstr, tySet}:
       reprAux(result, p, typ, cl)
     else:
       var p = p
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 95cdba65d..5161104a9 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -9,7 +9,7 @@
 
 ## Implements Nimrod's 'spawn'.
 
-when not defined(NimString): 
+when not declared(NimString): 
   {.error: "You must not import this module explicitly".}
 
 {.push stackTrace:off.}
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 9db8ce378..bc79bb254 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -32,7 +32,7 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
   return a.len == b.len and
     c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32
 
-when defined(allocAtomic):
+when declared(allocAtomic):
   template allocStr(size: expr): expr =
     cast[NimString](allocAtomic(size))
 else:
@@ -85,7 +85,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
   if src != nil:
     var s = src.space
     if s < 8: s = 7
-    when defined(newObjRC1):
+    when declared(newObjRC1):
       result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) +
                                s+1))
     else:
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index d3b3aa457..c30c57fb9 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -1,17 +1,17 @@
 #
 #
-#            Nimrod's Runtime Library
+#            Nim's Runtime Library
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## Thread support for Nimrod. **Note**: This is part of the system module.
+## Thread support for Nim. **Note**: This is part of the system module.
 ## Do not import it directly. To activate thread support you need to compile
 ## with the ``--threads:on`` command line switch.
 ##
-## Nimrod's memory model for threads is quite different from other common 
+## Nim's memory model for threads is quite different from other common 
 ## programming languages (C, Pascal): Each thread has its own
 ## (garbage collected) heap and sharing of memory is restricted. This helps
 ## to prevent race conditions and improves efficiency. See `the manual for
@@ -19,7 +19,7 @@
 ##
 ## Example:
 ##
-## .. code-block:: nimrod
+## .. code-block:: Nim
 ##
 ##  import locks
 ##
@@ -39,7 +39,7 @@
 ##    createThread(thr[i], threadFunc, (i*10, i*10+5))
 ##  joinThreads(thr)
   
-when not defined(NimString): 
+when not declared(NimString): 
   {.error: "You must not import this module explicitly".}
 
 const
@@ -190,7 +190,7 @@ var globalsSlot = threadVarAlloc()
 
 when emulatedThreadVars:
   proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} =
-    result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls)
+    result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls)
 
 when useStackMaskHack:
   proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
@@ -210,7 +210,7 @@ when not defined(useNimRtl):
     initGC()
     
   when emulatedThreadVars:
-    if NimThreadVarsSize() > sizeof(TThreadLocalStorage):
+    if nimThreadVarsSize() > sizeof(TThreadLocalStorage):
       echo "too large thread local storage size requested"
       quit 1
   
@@ -245,14 +245,14 @@ when not defined(useNimRtl):
     # the GC can examine the stacks?
     proc stopTheWord() = discard
     
-# We jump through some hops here to ensure that Nimrod thread procs can have
-# the Nimrod calling convention. This is needed because thread procs are 
+# We jump through some hops here to ensure that Nim thread procs can have
+# the Nim calling convention. This is needed because thread procs are 
 # ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just
 # use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway.
 
 type
   TThread* {.pure, final.}[TArg] =
-      object of TGcThread ## Nimrod thread. A thread is a heavy object (~14K)
+      object of TGcThread ## Nim thread. A thread is a heavy object (~14K)
                           ## that **must not** be part of a message! Use
                           ## a ``TThreadId`` for that.
     when TArg is void:
@@ -267,7 +267,7 @@ when not defined(boehmgc) and not hasSharedHeap:
   proc deallocOsPages()
 
 template threadProcWrapperBody(closure: expr) {.immediate.} =
-  when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure)
+  when declared(globalsSlot): threadVarSetValue(globalsSlot, closure)
   var t = cast[ptr TThread[TArg]](closure)
   when useStackMaskHack:
     var tls: TThreadLocalStorage
@@ -275,13 +275,13 @@ template threadProcWrapperBody(closure: expr) {.immediate.} =
     # init the GC for this thread:
     setStackBottom(addr(t))
     initGC()
-  when defined(registerThread):
+  when declared(registerThread):
     t.stackBottom = addr(t)
     registerThread(t)
   when TArg is void: t.dataFn()
   else: t.dataFn(t.data)
-  when defined(registerThread): unregisterThread(t)
-  when defined(deallocOsPages): deallocOsPages()
+  when declared(registerThread): unregisterThread(t)
+  when declared(deallocOsPages): deallocOsPages()
   # Since an unhandled exception terminates the whole process (!), there is
   # no need for a ``try finally`` here, nor would it be correct: The current
   # exception is tried to be re-raised by the code-gen after the ``finally``!
@@ -305,22 +305,26 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
   ## returns true if `t` is running.
   result = t.dataFn != nil
 
-proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = 
-  ## waits for the thread `t` to finish.
-  when hostOS == "windows":
+when hostOS == "windows":
+  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = 
+    ## waits for the thread `t` to finish.
     discard waitForSingleObject(t.sys, -1'i32)
-  else:
-    discard pthread_join(t.sys, nil)
 
-proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = 
-  ## waits for every thread in `t` to finish.
-  when hostOS == "windows":
+  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = 
+    ## waits for every thread in `t` to finish.
     var a: array[0..255, TSysThread]
     sysAssert a.len >= t.len, "a.len >= t.len"
     for i in 0..t.high: a[i] = t[i].sys
-    discard waitForMultipleObjects(t.len.int32, 
+    discard waitForMultipleObjects(t.len.int32,
                                    cast[ptr TSysThread](addr(a)), 1, -1)
-  else:
+
+else:
+  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
+    ## waits for the thread `t` to finish.
+    discard pthread_join(t.sys, nil)
+
+  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
+    ## waits for every thread in `t` to finish.
     for i in 0..t.high: joinThread(t[i])
 
 when false:
@@ -332,25 +336,35 @@ when false:
       discard TerminateThread(t.sys, 1'i32)
     else:
       discard pthread_cancel(t.sys)
-    when defined(registerThread): unregisterThread(addr(t))
+    when declared(registerThread): unregisterThread(addr(t))
     t.dataFn = nil
 
-proc createThread*[TArg](t: var TThread[TArg], 
-                         tp: proc (arg: TArg) {.thread.}, 
-                         param: TArg) =
-  ## creates a new thread `t` and starts its execution. Entry point is the
-  ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
-  ## don't need to pass any data to the thread.
-  when TArg isnot void: t.data = param
-  t.dataFn = tp
-  when hasSharedHeap: t.stackSize = ThreadStackSize
-  when hostOS == "windows":
+when hostOS == "windows":
+  proc createThread*[TArg](t: var TThread[TArg],
+                           tp: proc (arg: TArg) {.thread.}, 
+                           param: TArg) =
+    ## creates a new thread `t` and starts its execution. Entry point is the
+    ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
+    ## don't need to pass any data to the thread.
+    when TArg isnot void: t.data = param
+    t.dataFn = tp
+    when hasSharedHeap: t.stackSize = ThreadStackSize
     var dummyThreadId: int32
     t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
                          addr(t), 0'i32, dummyThreadId)
     if t.sys <= 0:
       raise newException(EResourceExhausted, "cannot create thread")
-  else:
+
+else:
+  proc createThread*[TArg](t: var TThread[TArg], 
+                           tp: proc (arg: TArg) {.thread.}, 
+                           param: TArg) =
+    ## creates a new thread `t` and starts its execution. Entry point is the
+    ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
+    ## don't need to pass any data to the thread.
+    when TArg isnot void: t.data = param
+    t.dataFn = tp
+    when hasSharedHeap: t.stackSize = ThreadStackSize
     var a {.noinit.}: Tpthread_attr
     pthread_attr_init(a)
     pthread_attr_setstacksize(a, ThreadStackSize)
@@ -364,7 +378,7 @@ proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} =
 proc myThreadId*[TArg](): TThreadId[TArg] =
   ## returns the thread ID of the thread that calls this proc. This is unsafe
   ## because the type ``TArg`` is not checked for consistency!
-  result = cast[TThreadId[TArg]](ThreadVarGetValue(globalsSlot))
+  result = cast[TThreadId[TArg]](threadVarGetValue(globalsSlot))
 
 when false:
   proc mainThreadId*[TArg](): TThreadId[TArg] =
diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim
index e2a5d87e9..cd64ff410 100644
--- a/lib/system/widestrs.nim
+++ b/lib/system/widestrs.nim
@@ -7,10 +7,10 @@
 #    distribution, for details about the copyright.
 #
 
-## Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
-## module! Do not import it directly!
+# Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
+# module! Do not import it directly!
 
-when not defined(NimString):
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 
 type
@@ -103,7 +103,7 @@ proc newWideCString*(source: cstring, L: int): WideCString =
 proc newWideCString*(s: cstring): WideCString =
   if s.isNil: return nil
 
-  when not defined(c_strlen):
+  when not declared(c_strlen):
     proc c_strlen(a: cstring): int {.
       header: "<string.h>", noSideEffect, importc: "strlen".}
 
diff --git a/lib/windows/ole2.nim b/lib/windows/ole2.nim
deleted file mode 100644
index ec0ab8f5d..000000000
--- a/lib/windows/ole2.nim
+++ /dev/null
@@ -1,208 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2006 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-import 
-  windows
-
-const 
-  GUID_NULL*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000000])
-  IID_IUnknown*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IClassFactory*: TGUID = (D1: 0x00000001, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMarshal*: TGUID = (D1: 0x00000003, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMalloc*: TGUID = (D1: 0x00000002, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStdMarshalInfo*: TGUID = (D1: 0x00000018, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IExternalConnection*: TGUID = (D1: 0x00000019, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IEnumUnknown*: TGUID = (D1: 0x00000100, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IBindCtx*: TGUID = (D1: 0x0000000E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumMoniker*: TGUID = (D1: 0x00000102, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRunnableObject*: TGUID = (D1: 0x00000126, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRunningObjectTable*: TGUID = (D1: 0x00000010, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IPersist*: TGUID = (D1: 0x0000010C, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistStream*: TGUID = (D1: 0x00000109, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IMoniker*: TGUID = (D1: 0x0000000F, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumString*: TGUID = (D1: 0x00000101, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStream*: TGUID = (D1: 0x0000000C, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumStatStg*: TGUID = (D1: 0x0000000D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IStorage*: TGUID = (D1: 0x0000000B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistFile*: TGUID = (D1: 0x0000010B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IPersistStorage*: TGUID = (D1: 0x0000010A, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ILockBytes*: TGUID = (D1: 0x0000000A, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumFormatEtc*: TGUID = (D1: 0x00000103, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumStatData*: TGUID = (D1: 0x00000105, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRootStorage*: TGUID = (D1: 0x00000012, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IAdviseSink*: TGUID = (D1: 0x0000010F, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IAdviseSink2*: TGUID = (D1: 0x00000125, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDataObject*: TGUID = (D1: 0x0000010E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDataAdviseHolder*: TGUID = (D1: 0x00000110, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IMessageFilter*: TGUID = (D1: 0x00000016, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IRpcChannelBuffer*: TGUID = (D1: 0xD5F56B60, D2: 0x0000593B, 
-    D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
-  IID_IRpcProxyBuffer*: TGUID = (D1: 0xD5F56A34, D2: 0x0000593B, D3: 0x0000101A, D4: [
-      0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, 
-      0x000000BF, 0x0000007A])
-  IID_IRpcStubBuffer*: TGUID = (D1: 0xD5F56AFC, D2: 0x0000593B, D3: 0x0000101A, D4: [
-      0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, 
-      0x000000BF, 0x0000007A])
-  IID_IPSFactoryBuffer*: TGUID = (D1: 0xD5F569D0, D2: 0x0000593B, 
-    D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
-  IID_ICreateTypeInfo*: TGUID = (D1: 0x00020405, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ICreateTypeLib*: TGUID = (D1: 0x00020406, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDispatch*: TGUID = (D1: 0x00020400, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumVariant*: TGUID = (D1: 0x00020404, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeComp*: TGUID = (D1: 0x00020403, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeInfo*: TGUID = (D1: 0x00020401, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_ITypeLib*: TGUID = (D1: 0x00020402, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IErrorInfo*: TGUID = (D1: 0x1CF2B120, D2: 0x0000547D, D3: 0x0000101B, D4: [
-      0x0000008E, 0x00000065, 0x00000008, 0x00000000, 0x0000002B, 0x0000002B, 
-      0x000000D1, 0x00000019])
-  IID_ICreateErrorInfo*: TGUID = (D1: 0x22F03340, D2: 0x0000547D, 
-    D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
-  IID_ISupportErrorInfo*: TGUID = (D1: 0xDF0B3D60, D2: 0x0000548F, 
-    D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, 
-                         0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
-  IID_IOleAdviseHolder*: TGUID = (D1: 0x00000111, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleCache*: TGUID = (D1: 0x0000011E, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleCache2*: TGUID = (D1: 0x00000128, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleCacheControl*: TGUID = (D1: 0x00000129, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IParseDisplayName*: TGUID = (D1: 0x0000011A, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleContainer*: TGUID = (D1: 0x0000011B, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleClientSite*: TGUID = (D1: 0x00000118, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleObject*: TGUID = (D1: 0x00000112, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleWindow*: TGUID = (D1: 0x00000114, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleLink*: TGUID = (D1: 0x0000011D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IOleItemContainer*: TGUID = (D1: 0x0000011C, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceUIWindow*: TGUID = (D1: 0x00000115, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceActiveObject*: TGUID = (D1: 0x00000117, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceFrame*: TGUID = (D1: 0x00000116, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceObject*: TGUID = (D1: 0x00000113, D2: 0x00000000, 
-    D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, 
-                         0x00000000, 0x00000000, 0x00000000, 0x00000046])
-  IID_IOleInPlaceSite*: TGUID = (D1: 0x00000119, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IViewObject*: TGUID = (D1: 0x0000010D, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IViewObject2*: TGUID = (D1: 0x00000127, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDropSource*: TGUID = (D1: 0x00000121, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IDropTarget*: TGUID = (D1: 0x00000122, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
-  IID_IEnumOleVerb*: TGUID = (D1: 0x00000104, D2: 0x00000000, D3: 0x00000000, D4: [
-      0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
-      0x00000000, 0x00000046])
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index dcae6ffaf..09696b67f 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -664,6 +664,7 @@ const
   WSAEDISCON* = 10101
   WSAENETRESET* = 10052
   WSAETIMEDOUT* = 10060
+  ERROR_NETNAME_DELETED* = 64
 
 proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE,
                              CompletionKey: DWORD,
diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim
index d99e5651c..ce78d3435 100644
--- a/lib/wrappers/postgres.nim
+++ b/lib/wrappers/postgres.nim
@@ -213,6 +213,8 @@ proc PQexecParams*(conn: PPGconn, command: cstring, nParams: int32,
                    paramTypes: POid, paramValues: cstringArray, 
                    paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
     cdecl, dynlib: dllName, importc: "PQexecParams".}
+proc PQprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
+    paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
 proc PQexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32, 
                      paramValues: cstringArray, 
                      paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
diff --git a/lib/wrappers/sdl/sdl_ttf.nim b/lib/wrappers/sdl/sdl_ttf.nim
index f501e31d8..45247df4d 100644
--- a/lib/wrappers/sdl/sdl_ttf.nim
+++ b/lib/wrappers/sdl/sdl_ttf.nim
@@ -333,11 +333,5 @@ proc VERSION*(X: var sdl.Tversion) =
   X.patch = PATCHLEVEL
 
 
-when not (defined(Workaround_RenderText_Solid)): 
-  proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{.
-      cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
-else: 
-  proc RenderText_Solid(font: PFont, text: cstring, fg: TColor): PSurface = 
-    var Black: TColor         # initialized to zero
-    result = RenderText_Shaded(font, text, fg, Black)
-
+proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{.
+    cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
diff --git a/lib/wrappers/zmq.nim b/lib/wrappers/zmq.nim
deleted file mode 100644
index 9826ab813..000000000
--- a/lib/wrappers/zmq.nim
+++ /dev/null
@@ -1,322 +0,0 @@
-# Nimrod wrapper of 0mq
-# Generated by c2nim with modifications and enhancement from Andreas Rumpf
-# Original licence follows:
-
-#
-#    Copyright (c) 2007-2011 iMatix Corporation
-#    Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file
-#
-#    This file is part of 0MQ.
-#
-#    0MQ is free software; you can redistribute it and/or modify it under
-#    the terms of the GNU Lesser General Public License as published by
-#    the Free Software Foundation; either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    0MQ is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Lesser General Public License for more details.
-#
-#    You should have received a copy of the GNU Lesser General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-
-# Generated from zmq version 2.1.5
-
-## Nimrod 0mq wrapper. This file contains the low level C wrappers as well as
-## some higher level constructs. The higher level constructs are easily
-## recognizable because they are the only ones that have documentation.
-##
-## Example of a client:
-## 
-## .. code-block:: nimrod
-##   import zmq
-##   
-##   var connection = zmq.open("tcp://localhost:5555", server=false)
-##   echo("Connecting...")
-##   for i in 0..10:
-##     echo("Sending hello...", i)
-##     send(connection, "Hello")
-##     var reply = receive(connection)
-##     echo("Received ...", reply)
-##   close(connection)
-##
-## Example of a server:
-##
-## .. code-block:: nimrod
-##   
-##   import zmq
-##   var connection = zmq.open("tcp://*:5555", server=true)
-##   while True:
-##     var request = receive(connection)
-##     echo("Received: ", request)
-##     send(connection, "World")
-##   close(connection)
-
-{.deadCodeElim: on.}
-when defined(windows): 
-  const 
-    zmqdll* = "zmq.dll"
-elif defined(macosx): 
-  const 
-    zmqdll* = "libzmq.dylib"
-else:
-  const 
-    zmqdll* = "libzmq.so"
-
-# A number random enough not to collide with different errno ranges on      
-# different OSes. The assumption is that error_t is at least 32-bit type.  
-const 
-  HAUSNUMERO* = 156384712
-  # On Windows platform some of the standard POSIX errnos are not defined.    
-  ENOTSUP* = (HAUSNUMERO + 1)
-  EPROTONOSUPPORT* = (HAUSNUMERO + 2)
-  ENOBUFS* = (HAUSNUMERO + 3)
-  ENETDOWN* = (HAUSNUMERO + 4)
-  EADDRINUSE* = (HAUSNUMERO + 5)
-  EADDRNOTAVAIL* = (HAUSNUMERO + 6)
-  ECONNREFUSED* = (HAUSNUMERO + 7)
-  EINPROGRESS* = (HAUSNUMERO + 8)
-  # Native 0MQ error codes.  
-  EFSM* = (HAUSNUMERO + 51)
-  ENOCOMPATPROTO* = (HAUSNUMERO + 52)
-  ETERM* = (HAUSNUMERO + 53)
-  EMTHREAD* = (HAUSNUMERO + 54)
-  #  Maximal size of "Very Small Message". VSMs are passed by value            
-  #  to avoid excessive memory allocation/deallocation.                        
-  #  If VMSs larger than 255 bytes are required, type of 'vsm_size'            
-  #  field in msg_t structure should be modified accordingly.
-  MAX_VSM_SIZE* = 30
-
-  POLLIN* = 1
-  POLLOUT* = 2
-  POLLERR* = 4
-
-  STREAMER* = 1
-  FORWARDER* = 2
-  QUEUE* = 3
-
-  PAIR* = 0
-  PUB* = 1
-  SUB* = 2
-  REQ* = 3
-  REP* = 4
-  DEALER* = 5
-  ROUTER* = 6
-  PULL* = 7
-  PUSH* = 8
-  XPUB* = 9
-  XSUB* = 10
-  XREQ* = DEALER      #  Old alias, remove in 3.x               
-  XREP* = ROUTER      #  Old alias, remove in 3.x               
-  UPSTREAM* = PULL    #  Old alias, remove in 3.x               
-  DOWNSTREAM* = PUSH  #  Old alias, remove in 3.x        
-
-type
-  #  Message types. These integers may be stored in 'content' member of the    
-  #  message instead of regular pointer to the data. 
-  TMsgTypes* = enum
-    DELIMITER = 31,
-    VSM = 32
-  #  Message flags. MSG_SHARED is strictly speaking not a message flag     
-  #  (it has no equivalent in the wire format), however, making  it a flag     
-  #  allows us to pack the stucture tighter and thus improve performance.   
-  TMsgFlags* = enum 
-    MSG_MORE = 1,
-    MSG_SHARED = 128,
-    MSG_MASK = 129         # Merges all the flags 
-  #  A message. Note that 'content' is not a pointer to the raw data.          
-  #  Rather it is pointer to zmq::msg_content_t structure                      
-  #  (see src/msg_content.hpp for its definition).    
-  TMsg*{.pure, final.} = object 
-    content*: pointer
-    flags*: char
-    vsm_size*: char
-    vsm_data*: array[0..MAX_VSM_SIZE - 1, char]
-
-  TFreeFn = proc (data, hint: pointer) {.noconv.}
-
-  TContext {.final, pure.} = object
-  PContext* = ptr TContext
-  
-  # Socket Types
-  TSocket {.final, pure.} = object
-  PSocket* = ptr TSocket       
-
-  #  Socket options.                                                           
-  TSockOptions* = enum
-    HWM = 1,
-    SWAP = 3,
-    AFFINITY = 4,
-    IDENTITY = 5,
-    SUBSCRIBE = 6,
-    UNSUBSCRIBE = 7,
-    RATE = 8,
-    RECOVERY_IVL = 9,
-    MCAST_LOOP = 10,
-    SNDBUF = 11,
-    RCVBUF = 12,
-    RCVMORE = 13,
-    FD = 14,
-    EVENTS = 15,
-    theTYPE = 16,
-    LINGER = 17,
-    RECONNECT_IVL = 18,
-    BACKLOG = 19,
-    RECOVERY_IVL_MSEC = 20, #  opt. recovery time, reconcile in 3.x   
-    RECONNECT_IVL_MAX = 21
-
-  #  Send/recv options.                                                        
-  TSendRecvOptions* = enum
-    NOBLOCK, SNDMORE
-  
-  TPollItem*{.pure, final.} = object 
-    socket*: PSocket
-    fd*: cint
-    events*: cshort
-    revents*: cshort
-  
-#  Run-time API version detection                                            
-
-proc version*(major: var cint, minor: var cint, patch: var cint){.cdecl, 
-    importc: "zmq_version", dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ errors.                                                               
-#****************************************************************************
-
-#  This function retrieves the errno as it is known to 0MQ library. The goal 
-#  of this function is to make the code 100% portable, including where 0MQ   
-#  compiled with certain CRT library (on Windows) is linked to an            
-#  application that uses different CRT library.                              
-
-proc errno*(): cint{.cdecl, importc: "zmq_errno", dynlib: zmqdll.}
-#  Resolves system errors and 0MQ errors to human-readable string.
-
-proc strerror*(errnum: cint): cstring {.cdecl, importc: "zmq_strerror", 
-    dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ message definition.                                                   
-#****************************************************************************
-
-proc msg_init*(msg: var TMsg): cint{.cdecl, importc: "zmq_msg_init", 
-    dynlib: zmqdll.}
-proc msg_init*(msg: var TMsg, size: int): cint{.cdecl, 
-    importc: "zmq_msg_init_size", dynlib: zmqdll.}
-proc msg_init*(msg: var TMsg, data: cstring, size: int, 
-               ffn: TFreeFn, hint: pointer): cint{.cdecl, 
-    importc: "zmq_msg_init_data", dynlib: zmqdll.}
-proc msg_close*(msg: var TMsg): cint {.cdecl, importc: "zmq_msg_close", 
-    dynlib: zmqdll.}
-proc msg_move*(dest, src: var TMsg): cint{.cdecl, 
-    importc: "zmq_msg_move", dynlib: zmqdll.}
-proc msg_copy*(dest, src: var TMsg): cint{.cdecl, 
-    importc: "zmq_msg_copy", dynlib: zmqdll.}
-proc msg_data*(msg: var TMsg): cstring {.cdecl, importc: "zmq_msg_data", 
-    dynlib: zmqdll.}
-proc msg_size*(msg: var TMsg): int {.cdecl, importc: "zmq_msg_size", 
-    dynlib: zmqdll.}
-    
-#****************************************************************************
-#  0MQ infrastructure (a.k.a. context) initialisation & termination.         
-#****************************************************************************
-
-proc init*(io_threads: cint): PContext {.cdecl, importc: "zmq_init", 
-    dynlib: zmqdll.}
-proc term*(context: PContext): cint {.cdecl, importc: "zmq_term", 
-                                        dynlib: zmqdll.}
-#****************************************************************************
-#  0MQ socket definition.                                                    
-#****************************************************************************                                                         
-
-proc socket*(context: PContext, theType: cint): PSocket {.cdecl, 
-    importc: "zmq_socket", dynlib: zmqdll.}
-proc close*(s: PSocket): cint{.cdecl, importc: "zmq_close", dynlib: zmqdll.}
-proc setsockopt*(s: PSocket, option: cint, optval: pointer, 
-                     optvallen: int): cint {.cdecl, importc: "zmq_setsockopt", 
-    dynlib: zmqdll.}
-proc getsockopt*(s: PSocket, option: cint, optval: pointer, 
-                 optvallen: ptr int): cint{.cdecl, 
-    importc: "zmq_getsockopt", dynlib: zmqdll.}
-proc bindAddr*(s: PSocket, address: cstring): cint{.cdecl, importc: "zmq_bind", 
-    dynlib: zmqdll.}
-proc connect*(s: PSocket, address: cstring): cint{.cdecl, 
-    importc: "zmq_connect", dynlib: zmqdll.}
-proc send*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, 
-    importc: "zmq_send", dynlib: zmqdll.}
-proc recv*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, 
-    importc: "zmq_recv", dynlib: zmqdll.}
-#****************************************************************************
-#  I/O multiplexing.                                                         
-#****************************************************************************
-
-proc poll*(items: ptr TPollItem, nitems: cint, timeout: int): cint{.
-    cdecl, importc: "zmq_poll", dynlib: zmqdll.}
-    
-#****************************************************************************
-#  Built-in devices                                                          
-#****************************************************************************
-
-proc device*(device: cint, insocket, outsocket: PSocket): cint{.
-    cdecl, importc: "zmq_device", dynlib: zmqdll.}
-    
-type
-  EZmq* = object of ESynch ## exception that is raised if something fails
-  TConnection* {.pure, final.} = object ## a connection
-    c*: PContext  ## the embedded context
-    s*: PSocket   ## the embedded socket
-  
-  TConnectionMode* = enum ## connection mode
-    conPAIR = 0,
-    conPUB = 1,
-    conSUB = 2,
-    conREQ = 3,
-    conREP = 4,
-    conDEALER = 5,
-    conROUTER = 6,
-    conPULL = 7,
-    conPUSH = 8,
-    conXPUB = 9,
-    conXSUB = 10
-  
-proc zmqError*() {.noinline, noreturn.} =
-  ## raises EZmq with error message from `zmq.strerror`.
-  var e: ref EZmq
-  new(e)
-  e.msg = $strerror(errno())
-  raise e
-  
-proc open*(address: string, server: bool, mode: TConnectionMode = conDEALER,
-           numthreads = 4): TConnection =
-  ## opens a new connection. If `server` is true, it uses `bindAddr` for the
-  ## underlying socket, otherwise it opens the socket with `connect`.
-  result.c = init(cint(numthreads))
-  if result.c == nil: zmqError()
-  result.s = socket(result.c, cint(ord(mode)))
-  if result.s == nil: zmqError()
-  if server:
-    if bindAddr(result.s, address) != 0'i32: zmqError()
-  else:
-    if connect(result.s, address) != 0'i32: zmqError()
-  
-proc close*(c: TConnection) =
-  ## closes the connection.
-  if close(c.s) != 0'i32: zmqError()
-  if term(c.c) != 0'i32: zmqError()
-  
-proc send*(c: TConnection, msg: string) =
-  ## sends a message over the connection.
-  var m: TMsg
-  if msg_init(m, msg.len) != 0'i32: zmqError()
-  copyMem(msg_data(m), cstring(msg), msg.len)
-  if send(c.s, m, 0'i32) != 0'i32: zmqError()
-  discard msg_close(m)
-  
-proc receive*(c: TConnection): string =
-  ## receives a message from a connection.
-  var m: TMsg
-  if msg_init(m) != 0'i32: zmqError()
-  if recv(c.s, m, 0'i32) != 0'i32: zmqError()
-  result = newString(msg_size(m))
-  copyMem(addr(result[0]), msg_data(m), result.len)
-  discard msg_close(m)
diff --git a/readme.md b/readme.md
index e8c081d4e..85bf480a0 100644
--- a/readme.md
+++ b/readme.md
@@ -39,9 +39,7 @@ $ bin/nimrod c koch
 $ ./koch boot -d:release
 ```
 
-``koch install [dir]`` may then be used to install Nimrod, or you can simply
-add it to your PATH. More ``koch`` related options are documented in
-[doc/koch.txt](doc/koch.txt).
+Add Nimrod to your PATH afterwards.
 
 The above steps can be performed on Windows in a similar fashion, the
 ``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
@@ -62,5 +60,5 @@ allowing you to create commercial applications.
 
 Read copying.txt for more details.
 
-Copyright (c) 2004-2014 Andreas Rumpf.
+Copyright (c) 2006-2014 Andreas Rumpf.
 All rights reserved.
diff --git a/readme.txt b/readme.txt
index 3f6aef05c..f9e5054fe 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,60 +1,12 @@
-# Nimrod Compiler
-This repo contains the Nimrod compiler, Nimrod's stdlib, tools and 
+This package contains the Nimrod compiler, Nimrod's stdlib, tools and 
 documentation.
 
-## Compiling
-Compiling the Nimrod compiler is quite straightforward. Because
-the Nimrod compiler itself is written in the Nimrod programming language
-the C source of an older version of the compiler are needed to bootstrap the
-latest version. The C sources are available in a separate repo [here](http://github.com/nimrod-code/csources).
+Nimrod is a compiled, garbage-collected systems programming language which has
+an excellent productivity/performance ratio. Nimrod's design focuses on
+efficiency, expressiveness, elegance (in the order of priority).
 
-Pre-compiled snapshots of the compiler are also available on
-[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not 
-currently be built for.
+Read install.txt for instructions of how to build and install it.
 
-The compiler currently supports the following platform and architecture 
-combinations:
-  
-  * Windows (Windows XP or greater) - x86 and x86_64
-  * Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l
-  * Mac OS X 10.04 or higher - x86, x86_64 and ppc64
-  
-In reality a lot more are supported, however they are not tested regularly.
-
-To build from source you will need:
-
-  * gcc 3.x or later recommended. Other alternatives which may work
-    are: clang, Visual C++, Intel's C++ compiler
-  * git or wget
-
-If you are on a fairly modern *nix system, the following steps should work:
-
-```
-$ git clone git://github.com/Araq/Nimrod.git
-$ cd Nimrod
-$ git clone --depth 1 git://github.com/nimrod-code/csources
-$ cd csources && ./build.sh
-$ cd ..
-$ bin/nimrod c koch
-$ ./koch boot -d:release
-```
-
-``koch install [dir]`` may then be used to install Nimrod, or you can simply
-add it to your PATH. 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
-``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
-instead of ``build.sh``.
-
-## Getting help
-A [forum](http://forum.nimrod-lang.org/) is available if you have any
-questions, and you can also get help in the IRC channel on
-[Freenode](irc://irc.freenode.net/nimrod) in #nimrod. If you ask questions on
-[StackOverflow use the nimrod
-tag](http://stackoverflow.com/questions/tagged/nimrod).
-
-## License
 The compiler and the standard library are licensed under the MIT license, 
 except for some modules where the documentation suggests otherwise. This means 
 that you can use any license for your own programs developed with Nimrod, 
@@ -62,5 +14,5 @@ allowing you to create commercial applications.
 
 Read copying.txt for more details.
 
-Copyright (c) 2004-2014 Andreas Rumpf.
+Copyright (c) 2006-2014 Andreas Rumpf.
 All rights reserved.
diff --git a/tests/assert/tuserassert.nim b/tests/assert/tuserassert.nim
index 8710ee486..57b229ca9 100644
--- a/tests/assert/tuserassert.nim
+++ b/tests/assert/tuserassert.nim
@@ -3,7 +3,7 @@ discard """
 """
 
 template myAssert(cond: expr) = 
-  when rand(3) < 3:
+  when 3 <= 3:
     let c = cond.astToStr
     if not cond:
       echo c, "ugh"
diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim
new file mode 100644
index 000000000..ca73c6a3d
--- /dev/null
+++ b/tests/async/tasyncexceptions.nim
@@ -0,0 +1,40 @@
+discard """
+  file: "tasyncexceptions.nim"
+  exitcode: 1
+  outputsub: "Error: unhandled exception: foobar [E_Base]"
+"""
+import asyncdispatch
+
+proc accept(): PFuture[int] {.async.} =
+  await sleepAsync(100)
+  result = 4
+
+proc recvLine(fd: int): PFuture[string] {.async.} =
+  await sleepAsync(100)
+  return "get"
+
+proc processClient(fd: int) {.async.} =
+  # these finish synchronously, we need some async delay to emulate this bug.
+  var line = await recvLine(fd)
+  var foo = line[0]
+  if foo == 'g':
+    raise newException(EBase, "foobar")
+  
+
+proc serve() {.async.} =
+
+  while true:
+    var fut = await accept()
+    await processClient(fut)
+
+when isMainModule:
+  proc main =
+    var fut = serve()
+    fut.callback =
+      proc () =
+        if fut.failed:
+          # This test ensures that this exception crashes the application
+          # as it is not handled.
+          raise fut.error
+    runForever()
+  main()
diff --git a/tests/async/tasynciossl.nim b/tests/async/tasynciossl.nim
index 26c4c587c..6b38fcf7b 100644
--- a/tests/async/tasynciossl.nim
+++ b/tests/async/tasynciossl.nim
@@ -5,7 +5,8 @@ discard """
 """
 import sockets, asyncio, strutils, times
 
-var disp = newDispatcher()
+var disp {.threadvar.}: PDispatcher
+disp = newDispatcher()
 var msgCount = 0
 
 when defined(ssl):
diff --git a/tests/ccgbugs/tmissinginit.nim b/tests/ccgbugs/tmissinginit.nim
new file mode 100644
index 000000000..d440608e6
--- /dev/null
+++ b/tests/ccgbugs/tmissinginit.nim
@@ -0,0 +1,30 @@
+discard """
+  output: '''0
+0
+0
+0
+[[a = nil,
+b = nil]]'''
+"""
+
+# bug #1475
+type
+  Crash = object
+    a: string
+    b: seq[string]
+
+proc initCrash(): Crash = discard
+
+proc test() =
+  var blongname = [initCrash()]
+  echo repr(blongname)
+
+# bug #1434
+proc bug: array[1, int] = discard
+
+echo bug()[0]
+echo bug()[0]
+echo bug()[0]
+echo bug()[0]
+
+when isMainModule: test()
diff --git a/tests/closure/tforum.nim b/tests/closure/tforum.nim
new file mode 100644
index 000000000..4f6a16ff7
--- /dev/null
+++ b/tests/closure/tforum.nim
@@ -0,0 +1,44 @@
+discard """
+  output: '''asdas
+processClient end
+false
+'''
+"""
+
+type
+  PAsyncHttpServer = ref object
+    value: string
+  PFutureBase = ref object
+    callback: proc () {.closure.}
+    value: string
+    failed: bool
+
+proc accept(server: PAsyncHttpServer): PFutureBase =
+  new(result)
+  result.callback = proc () =
+    discard
+  server.value = "hahaha"
+
+proc processClient(): PFutureBase =
+  new(result)
+
+proc serve(server: PAsyncHttpServer): PFutureBase =
+  iterator serveIter(): PFutureBase {.closure.} =
+    echo server.value
+    while true:
+      var acceptAddrFut = server.accept()
+      yield acceptAddrFut
+      var fut = acceptAddrFut.value
+
+      var f = processClient()
+      f.callback =
+        proc () =
+          echo("processClient end")
+          echo(f.failed)
+      yield f
+  var x = serveIter
+  for i in 0 .. 1:
+    result = x()
+    result.callback()
+
+discard serve(PAsyncHttpServer(value: "asdas"))
diff --git a/tests/controlflow/tbreak.nim b/tests/controlflow/tbreak.nim
new file mode 100644
index 000000000..7deab4caf
--- /dev/null
+++ b/tests/controlflow/tbreak.nim
@@ -0,0 +1,44 @@
+discard """
+  output: '''10
+true true
+true false
+false true
+false false'''
+"""
+
+var
+  x = false
+  run = true
+
+while run:
+  run = false
+  block myblock:
+    if true:
+      break
+    echo "leaving myblock"
+  x = true
+doAssert(x)
+
+# bug #1418
+iterator foo: int =
+  for x in 0 .. 9:
+    for y in [10,20,30,40,50,60,70,80,90]:
+      yield x + y
+
+for p in foo():
+  echo p
+  break
+
+iterator permutations: int =
+  yield 10
+
+for p in permutations():
+  break
+
+# regression:
+proc main =
+  for x in [true, false]:
+    for y in [true, false]:
+      echo x, " ", y
+
+main()
diff --git a/tests/converter/tconvert.nim b/tests/converter/tconvert.nim
index a8ddcf119..a37140234 100644
--- a/tests/converter/tconvert.nim
+++ b/tests/converter/tconvert.nim
@@ -1,5 +1,3 @@
-import
-  Cairo
 
 converter FloatConversion64(x: int): float64 = return toFloat(x)
 converter FloatConversion32(x: int): float32 = return toFloat(x)
@@ -7,34 +5,10 @@ converter FloatConversionPlain(x: int): float = return toFloat(x)
 
 const width = 500
 const height = 500
-const outFile = "CairoTest.png"
-
-var surface = Cairo.ImageSurfaceCreate(CAIRO.FORMAT_RGB24, width, height)
-var ç = Cairo.Create(surface)
-
-ç.SetSourceRGB(1, 1, 1)
-ç.Paint()
-
-ç.SetLineWidth(10)
-ç.SetLineCap(CAIRO.LINE_CAP_ROUND)
-
-const count = 12
-var winc = width / count
-var hinc = width / count
-for i in 1 .. count-1:
-  var amount = i / count
-  ç.SetSourceRGB(0, 1 - amount, amount)
-  ç.MoveTo(i * winc, hinc)
-  ç.LineTo(width - i * winc, height - hinc)
-  ç.Stroke()
-
-  ç.SetSourceRGB(1 - amount, 0, amount)
-  ç.MoveTo(winc, i * hinc)
-  ç.LineTo(width - winc, height - i * hinc)
-  ç.Stroke()
-
-echo(surface.WriteToPNG(outFile))
-surface.Destroy()
+
+proc ImageSurfaceCreate(w, h: float) = discard
+
+ImageSurfaceCreate(width, height)
 
 type TFoo = object
 
diff --git a/tests/destructor/tdestructor.nim b/tests/destructor/tdestructor.nim
index e5236aaab..f0ea3c5c6 100644
--- a/tests/destructor/tdestructor.nim
+++ b/tests/destructor/tdestructor.nim
@@ -55,14 +55,14 @@ type
         q: TMyGeneric3[TMyObj, int, int]
       r: string
 
-proc destruct(o: var TMyObj) {.destructor.} =
+proc destroy(o: var TMyObj) {.override.} =
   if o.p != nil: dealloc o.p
   echo "myobj destroyed"
 
-proc destroy(o: var TMyGeneric1) {.destructor.} =
+proc destroy(o: var TMyGeneric1) {.override.} =
   echo "mygeneric1 destroyed"
 
-proc destroy[A, B](o: var TMyGeneric2[A, B]) {.destructor.} =
+proc destroy[A, B](o: var TMyGeneric2[A, B]) {.override.} =
   echo "mygeneric2 destroyed"
 
 proc open: TMyObj =
diff --git a/tests/destructor/tdestructor2.nim b/tests/destructor/tdestructor2.nim
index da9192a3f..a5b62860c 100644
--- a/tests/destructor/tdestructor2.nim
+++ b/tests/destructor/tdestructor2.nim
@@ -8,7 +8,7 @@ type
     x, y: int
     p: pointer
     
-proc destruct(o: var TMyObj) {.destructor.} =
+proc destroy(o: var TMyObj) {.override.} =
   if o.p != nil: dealloc o.p
   
 proc open: TMyObj =
diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim
index 0014cff46..f73230ff9 100644
--- a/tests/effects/teffects1.nim
+++ b/tests/effects/teffects1.nim
@@ -1,5 +1,5 @@
 discard """
-  line: 1913
+  line: 2136
   file: "system.nim"
   errormsg: "can raise an unlisted exception: ref EIO"
 """
diff --git a/tests/effects/tgcsafe.nim b/tests/effects/tgcsafe.nim
new file mode 100644
index 000000000..87388238a
--- /dev/null
+++ b/tests/effects/tgcsafe.nim
@@ -0,0 +1,16 @@
+discard """
+  line: 15
+  errormsg: "'mainUnsafe' is not GC-safe"
+"""
+
+proc mymap(x: proc ()) =
+  x()
+
+var
+  myglob: string
+
+proc mainSafe() {.gcsafe.} =
+  mymap(proc () = echo "foo")
+
+proc mainUnsafe() {.gcsafe.} =
+  mymap(proc () = myglob = "bar"; echo "foo", myglob)
diff --git a/tests/enum/tenumitems.nim b/tests/enum/tenumitems.nim
index b6eee5ba8..b92cff6bf 100644
--- a/tests/enum/tenumitems.nim
+++ b/tests/enum/tenumitems.nim
@@ -1,6 +1,6 @@
 discard """
   line: 7
-  errormsg: "type mismatch"
+  errormsg: "expression 'items' cannot be called"
 """
 
 type a = enum b,c,d
diff --git a/tests/generics/mdotlookup.nim b/tests/generics/mdotlookup.nim
index 7a5e0ccbf..0c4d0c87c 100644
--- a/tests/generics/mdotlookup.nim
+++ b/tests/generics/mdotlookup.nim
@@ -6,3 +6,11 @@ type MyObj = object
 proc foo*(b: any) =
   var o: MyObj
   echo b.baz, " ", o.x.baz, " ", b.baz()
+
+import sets
+
+var intset = initSet[int]()
+
+proc func*[T](a: T) =
+  if a in intset: echo("true")
+  else: echo("false")
diff --git a/tests/generics/tdotlookup.nim b/tests/generics/tdotlookup.nim
index b886cd8c9..d3deca7fc 100644
--- a/tests/generics/tdotlookup.nim
+++ b/tests/generics/tdotlookup.nim
@@ -1,7 +1,10 @@
 discard """
-  output: '''5 5 5'''
+  output: '''5 5 5
+false'''
 """
 
 import mdotlookup
 
 foo(7)
+# bug #1444
+func(4)
diff --git a/tests/init/tuninit1.nim b/tests/init/tuninit1.nim
index 2a994b187..57443a7d3 100644
--- a/tests/init/tuninit1.nim
+++ b/tests/init/tuninit1.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "'y' might not have been initialized"
+  msg: "Warning: 'y' might not have been initialized [Uninit]"
   line:34
 """
 
diff --git a/tests/misc/tissue710.nim b/tests/misc/tissue710.nim
new file mode 100644
index 000000000..9e8735eb3
--- /dev/null
+++ b/tests/misc/tissue710.nim
@@ -0,0 +1,10 @@
+discard """
+  file: "tissue710.nim"
+  line: 8
+  errorMsg: "expression '||' cannot be called"
+"""
+var sum = 0
+for x in 3..1000:
+  if (x mod 3 == 0) || (x mod 5 == 0):
+    sum += x
+echo(sum)
diff --git a/tests/misc/tstrange.nim b/tests/misc/tstrange.nim
index 3947755fc..8742011bb 100644
--- a/tests/misc/tstrange.nim
+++ b/tests/misc/tstrange.nim
@@ -1,6 +1,8 @@
 discard """
   file: "tstrange.nim"
-  output: "hallo4"
+  output: '''hallo40
+1
+2'''
 """
 # test for extremely strange bug

 

@@ -19,5 +21,8 @@ gen("hallo")
 write(stdout, ack(5, 4))

 #OUT hallo4

 

-
+# bug #1442
+let h=3
+for x in 0.. <h.int:
+  echo x
 
diff --git a/tests/misc/tunsignedcmp.nim b/tests/misc/tunsignedcmp.nim
new file mode 100644
index 000000000..a66fbaae1
--- /dev/null
+++ b/tests/misc/tunsignedcmp.nim
@@ -0,0 +1,15 @@
+discard """
+  output: '''true
+true
+true'''
+"""
+
+# bug 1420
+import unsigned
+
+var x = 40'u32
+var y = 30'u32
+echo x > y # works
+
+echo((40'i32) > (30'i32))
+echo((40'u32) > (30'u32)) # Error: ordinal type expected
diff --git a/tests/misc/tvarious1.nim b/tests/misc/tvarious1.nim
index 6e4612ae3..1f2da2ae5 100644
--- a/tests/misc/tvarious1.nim
+++ b/tests/misc/tvarious1.nim
@@ -3,7 +3,8 @@ discard """
   output: '''1
 0
 Whopie
-12'''
+12
+1.7'''
 """
 
 echo len([1_000_000]) #OUT 1
@@ -39,3 +40,9 @@ var val12 = TSomeRange(hour: 12)
 
 value = $(if val12.hour > 12: val12.hour - 12 else: val12.hour)
 echo value
+
+# bug #1334
+
+var ys = @[4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2] 
+#var x = int(ys.high / 2) #echo ys[x] # Works 
+echo ys[int(ys.high / 2)] # Doesn't work
diff --git a/tests/modules/texport.nim b/tests/modules/texport.nim
index 99228dfce..9515f9060 100644
--- a/tests/modules/texport.nim
+++ b/tests/modules/texport.nim
@@ -4,6 +4,9 @@ discard """
 
 import mexporta
 
+# bug #1029:
+from rawsockets import accept
+
 # B.TMyObject has been imported implicitly here: 
 var x: TMyObject
 echo($x, q(0), q"0")
diff --git a/tests/modules/tselfimport.nim b/tests/modules/tselfimport.nim
new file mode 100644
index 000000000..ddb3a5b09
--- /dev/null
+++ b/tests/modules/tselfimport.nim
@@ -0,0 +1,9 @@
+discard """
+  file: "tselfimport.nim"
+  line: 7
+  errormsg: "A module cannot import itself"
+"""
+import strutils as su # guard against regression
+import tselfimport #ERROR
+echo("Hello World")
+
diff --git a/tests/objvariant/tcheckedfield1.nim b/tests/objvariant/tcheckedfield1.nim
index 5ade3a13a..1963ceb8d 100644
--- a/tests/objvariant/tcheckedfield1.nim
+++ b/tests/objvariant/tcheckedfield1.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "cannot prove that field 'x.s' is accessible"
+  msg: "Warning: cannot prove that field 'x.s' is accessible [ProveField]"
   line:51
 """
 
diff --git a/tests/overload/toverl4.nim b/tests/overload/toverl4.nim
new file mode 100644
index 000000000..6bb3a53d1
--- /dev/null
+++ b/tests/overload/toverl4.nim
@@ -0,0 +1,77 @@
+discard """
+  output: '''true'''
+"""
+
+#bug #592
+
+type
+  ElementKind = enum inner, leaf
+  TElement[TKey, TData] = object
+    case kind: ElementKind
+    of inner:
+      key: TKey
+      left, right: ref TElement[Tkey, TData]
+    of leaf:
+      data: TData
+  PElement[TKey, TData] = ref TElement[TKey, TData]
+
+proc newElement[Tkey, TData](other: PElement[TKey, TData]): PElement[Tkey, TData] =
+  case other.kind:
+  of inner:
+    PElement[TKey, TData](kind: ElementKind.inner, key: other.key, left: other.left, right: other.right)
+  of leaf:
+    PElement[TKey, TData](kind: ElementKind.leaf, data: other.data)
+
+proc newElement[TKey, TData](key: TKey, left: PElement[TKey, TData] = nil, right: PElement[TKey, TData] = nil) : PElement[TKey, TData] =
+  PElement[TKey, TData](kind: ElementKind.inner, key: key, left: left, right: right)
+
+proc newElement[Tkey, TData](key: Tkey, data: TData) : PElement[Tkey, TData] =
+  PElement[TKey, TData](kind: ElementKind.leaf, data: data)
+
+proc find*[TKey, TData](root: PElement[TKey, TData], key: TKey): TData {.raises: [EInvalidKey].} =
+  if root.left == nil:
+    raise newException(EInvalidKey, "key does not exist: " & key)
+
+  var tmp_element = addr(root)
+
+  while tmp_element.kind == inner and tmp_element.right != nil:
+    tmp_element = if tmp_element.key > key:
+                    addr(tmp_element.left)
+                  else:
+                    addr(tmp_element.right)
+
+  if tmp_element.key == key:
+    return tmp_element.left.data
+  else:
+    raise newException(EInvalidKey, "key does not exist: " & key)
+
+proc add*[TKey, TData](root: var PElement[TKey, TData], key: TKey, data: TData) : bool =
+  if root.left == nil:
+    root.key = key
+    root.left = newElement[TKey, TData](key, data)
+    return true
+
+  var tmp_element = addr(root)
+
+  while tmp_element.kind == ElementKind.inner and tmp_element.right != nil:
+    tmp_element = if tmp_element.key > key:
+                    addr(tmp_element.left)
+                  else:
+                    addr(tmp_element.right)
+
+  if tmp_element.key == key:
+    return false
+
+  var old_element = newElement[TKey, TData](tmp_element[])
+  var new_element = newElement[TKey, TData](key, data)
+
+  tmp_element[] = if tmp_element.key < key:
+                    newElement(key, old_element, new_element)
+                  else:
+                    newElement(tmp_element.key, new_element, old_element)
+
+  return true
+
+var tree = PElement[int, int](kind: ElementKind.inner, key: 0, left: nil, right: nil)
+let result = add(tree, 1, 1)
+echo(result)
\ No newline at end of file
diff --git a/tests/parallel/tdeepcopy.nim b/tests/parallel/tdeepcopy.nim
new file mode 100644
index 000000000..84e2edf3f
--- /dev/null
+++ b/tests/parallel/tdeepcopy.nim
@@ -0,0 +1,18 @@
+discard """
+  output: '''13 abc'''
+"""
+
+type
+  PBinaryTree = ref object
+    le, ri: PBinaryTree
+    value: int
+
+
+proc main =
+  var x: PBinaryTree
+  deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13))))
+  var y: string
+  deepCopy y, "abc"
+  echo x.ri.le.value, " ", y
+
+main()
diff --git a/tests/range/tmatrix3.nim b/tests/range/tmatrix3.nim
index 900404524..80d38d63d 100644
--- a/tests/range/tmatrix3.nim
+++ b/tests/range/tmatrix3.nim
@@ -1,6 +1,6 @@
 discard """
-  output: '''0.0000000000000000e+00
-0.0000000000000000e+00
+  output: '''0.0
+0.0
 0
 0
 0
diff --git a/tests/system/toString.nim b/tests/system/toString.nim
index 17dcb3cb4..52e7a4b92 100644
--- a/tests/system/toString.nim
+++ b/tests/system/toString.nim
@@ -1,11 +1,9 @@
 discard """
   output:'''@[23, 45]
-@[, foo, bar]
-[, foo, bar]
-[23, 45]'''
+@[, foo, bar]'''
 """
 
 echo($(@[23, 45]))
 echo($(@["", "foo", "bar"]))
-echo($(["", "foo", "bar"]))
-echo($([23, 45]))
+#echo($(["", "foo", "bar"]))
+#echo($([23, 45]))
diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim
index 6e72f4b5e..184f07c51 100644
--- a/tests/testament/specs.nim
+++ b/tests/testament/specs.nim
@@ -53,7 +53,7 @@ const
   targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"]
   targetToCmd*: array[TTarget, string] = ["c", "cpp", "objc", "js"]
 
-when not defined(parseCfgBool):
+when not declared(parseCfgBool):
   # candidate for the stdlib:
   proc parseCfgBool(s: string): bool =
     case normalize(s)
diff --git a/tests/threads/tthreadanalysis.nim b/tests/threads/tthreadanalysis.nim
index 383680d81..37369b79c 100644
--- a/tests/threads/tthreadanalysis.nim
+++ b/tests/threads/tthreadanalysis.nim
@@ -1,7 +1,7 @@
 discard """
   outputsub: "101"
-  msg: "Warning: write to foreign heap"
-  line: 37
+  errormsg: "'threadFunc' is not GC-safe"
+  line: 39
   cmd: "nimrod $target --hints:on --threads:on $options $file"
 """
 
diff --git a/tests/threads/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim
index f3a36e036..e0629ed08 100644
--- a/tests/threads/tthreadheapviolation1.nim
+++ b/tests/threads/tthreadheapviolation1.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 12
-  errormsg: "write to foreign heap"
+  line: 11
+  errormsg: "'horrible' is not GC-safe"
   cmd: "nimrod $target --hints:on --threads:on $options $file"
 """
 
diff --git a/tests/vm/twrongarray.nim b/tests/vm/twrongarray.nim
new file mode 100644
index 000000000..c1514d0e9
--- /dev/null
+++ b/tests/vm/twrongarray.nim
@@ -0,0 +1,17 @@
+discard """
+  errormsg: "cannot evaluate at compile time: size"
+  line: 16
+"""
+
+#bug #1343
+
+when false:
+  proc one(dummy: int, size: int) =
+    var x: array[size, int] # compile error: constant expression expected
+
+  proc three(size: int) =
+    var x: array[size * 1, int] # compile error: cannot evaluate at compile time: size
+
+proc two(dummy: int, size: int) =
+  var x: array[size * 1, int] # compiles, but shouldn't?
+  #assert(x.len == size) # just for fun
diff --git a/tests/vm/twrongconst.nim b/tests/vm/twrongconst.nim
index 5c0c80f9f..68ab2757c 100644
--- a/tests/vm/twrongconst.nim
+++ b/tests/vm/twrongconst.nim
@@ -4,6 +4,6 @@ discard """
 """
 
 var x: array[100, char]
-template Foo : expr = x[42]
+template foo : expr = x[42]
 
 const myConst = foo
diff --git a/todo.txt b/todo.txt
index bd8f7f89e..d8085226d 100644
--- a/todo.txt
+++ b/todo.txt
@@ -2,21 +2,25 @@ version 0.9.6
 =============
 
 - scopes are still broken for generic instantiation!
-- start experimental branch
-- overloading of '='; general lift mechanism
+- implicit deref for parameter matching
 
 Concurrency
 -----------
 
-- 'gcsafe' inferrence needs to be fixed
+- 'deepCopy' needs to be instantiated for
+  generics *when the type is constructed*
+- test 'deepCopy'
+- overloading of '='; general lift mechanism
+
 - the disjoint checker needs to deal with 'a = spawn f(); g = spawn f()'
-- implement 'deepCopy' builtin
 - implement 'foo[1..4] = spawn(f[4..7])'
-- support for exception propagation
-- Minor: The copying of the 'ref Promise' into the thead local storage only
+- document the new 'spawn' and 'parallel' statements
+
+Low priority:
+- support for exception propagation? (hard to implement)
+- the copying of the 'ref Promise' into the thead local storage only
   happens to work due to the write barrier's implementation
 - implement lock levels --> first without the more complex race avoidance
-- document the new 'spawn' and 'parallel' statements
 
 
 Misc
@@ -27,8 +31,6 @@ Misc
 - fix the tuple unpacking in lambda bug
 - make tuple unpacking work in a non-var/let context
 - special rule for ``[]=``
-- ``=`` should be overloadable; requires specialization for ``=``; general
-  lift mechanism in the compiler is already implemented for 'fields'
 - built-in 'getImpl'
 - type API for macros; make 'spawn' a macro
 - markAndSweepGC should expose an API for fibers
@@ -57,13 +59,9 @@ version 0.9.x
 - implement 'bits' pragmas
 - we need a magic thisModule symbol
 - provide --nilChecks:on|off
-- fix closures/lambdalifting
 - ensure (ref T)(a, b) works as a type conversion and type constructor
 - optimize 'genericReset'; 'newException' leads to code bloat
 - stack-less GC
-- implicit deref for parameter matching
-
-- VM: optimize opcAsgnStr
 
 
 version 0.9.X
diff --git a/tools/niminst/EnvVarUpdate.nsh b/tools/niminst/EnvVarUpdate.nsh
new file mode 100644
index 000000000..4340b8f3c
--- /dev/null
+++ b/tools/niminst/EnvVarUpdate.nsh
@@ -0,0 +1,346 @@
+/**
+ *  EnvVarUpdate.nsh
+ *    : Environmental Variables: append, prepend, and remove entries
+ *
+ *     WARNING: If you use StrFunc.nsh header then include it before this file
+ *              with all required definitions. This is to avoid conflicts
+ *
+ *  Usage:
+ *    ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString"
+ *
+ *  Credits:
+ *  Version 1.0 
+ *  * Cal Turney (turnec2)
+ *  * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this
+ *    function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar,
+ *    WriteEnvStr, and un.DeleteEnvStr
+ *  * Diego Pedroso (deguix) for StrTok
+ *  * Kevin English (kenglish_hi) for StrContains
+ *  * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry  
+ *    (dandaman32) for StrReplace
+ *
+ *  Version 1.1 (compatibility with StrFunc.nsh)
+ *  * techtonik
+ *
+ *  http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries
+ *
+ */
+
+
+!ifndef ENVVARUPDATE_FUNCTION
+!define ENVVARUPDATE_FUNCTION
+!verbose push
+!verbose 3
+!include "LogicLib.nsh"
+!include "WinMessages.NSH"
+!include "StrFunc.nsh"
+
+; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------
+!macro _IncludeStrFunction StrFuncName
+  !ifndef ${StrFuncName}_INCLUDED
+    ${${StrFuncName}}
+  !endif
+  !ifndef Un${StrFuncName}_INCLUDED
+    ${Un${StrFuncName}}
+  !endif
+  !define un.${StrFuncName} "${Un${StrFuncName}}"
+!macroend
+
+!insertmacro _IncludeStrFunction StrTok
+!insertmacro _IncludeStrFunction StrStr
+!insertmacro _IncludeStrFunction StrRep
+
+; ---------------------------------- Macro Definitions ----------------------------------------
+!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
+  Push "${EnvVarName}"
+  Push "${Action}"
+  Push "${RegLoc}"
+  Push "${PathString}"
+    Call EnvVarUpdate
+  Pop "${ResultVar}"
+!macroend
+!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"'
+ 
+!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
+  Push "${EnvVarName}"
+  Push "${Action}"
+  Push "${RegLoc}"
+  Push "${PathString}"
+    Call un.EnvVarUpdate
+  Pop "${ResultVar}"
+!macroend
+!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'
+; ---------------------------------- Macro Definitions end-------------------------------------
+ 
+;----------------------------------- EnvVarUpdate start----------------------------------------
+!define hklm_all_users     'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
+!define hkcu_current_user  'HKCU "Environment"'
+ 
+!macro EnvVarUpdate UN
+ 
+Function ${UN}EnvVarUpdate
+ 
+  Push $0
+  Exch 4
+  Exch $1
+  Exch 3
+  Exch $2
+  Exch 2
+  Exch $3
+  Exch
+  Exch $4
+  Push $5
+  Push $6
+  Push $7
+  Push $8
+  Push $9
+  Push $R0
+ 
+  /* After this point:
+  -------------------------
+     $0 = ResultVar     (returned)
+     $1 = EnvVarName    (input)
+     $2 = Action        (input)
+     $3 = RegLoc        (input)
+     $4 = PathString    (input)
+     $5 = Orig EnvVar   (read from registry)
+     $6 = Len of $0     (temp)
+     $7 = tempstr1      (temp)
+     $8 = Entry counter (temp)
+     $9 = tempstr2      (temp)
+     $R0 = tempChar     (temp)  */
+ 
+  ; Step 1:  Read contents of EnvVarName from RegLoc
+  ;
+  ; Check for empty EnvVarName
+  ${If} $1 == ""
+    SetErrors
+    DetailPrint "ERROR: EnvVarName is blank"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Check for valid Action
+  ${If}    $2 != "A"
+  ${AndIf} $2 != "P"
+  ${AndIf} $2 != "R"
+    SetErrors
+    DetailPrint "ERROR: Invalid Action - must be A, P, or R"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ${If} $3 == HKLM
+    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5
+  ${ElseIf} $3 == HKCU
+    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5
+  ${Else}
+    SetErrors
+    DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Check for empty PathString
+  ${If} $4 == ""
+    SetErrors
+    DetailPrint "ERROR: PathString is blank"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  Push $6
+  Push $7
+  Push $8
+  StrLen $7 $4  
+  StrLen $6 $5
+  IntOp $8 $6 + $7
+  ${If} $5 == ""
+  ${OrIf} $8 >= ${NSIS_MAX_STRLEN}
+    SetErrors
+    DetailPrint "Current $1 length ($6) too long to modify in NSIS; set manually if needed"
+    Pop $8
+    Pop $7
+    Pop $6
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+  Pop $8
+  Pop $7
+  Pop $6
+
+  ; Make sure we've got some work to do
+  ${If} $5 == ""
+  ${AndIf} $2 == "R"
+    SetErrors
+    DetailPrint "$1 is empty - Nothing to remove"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Step 2: Scrub EnvVar
+  ;
+  StrCpy $0 $5                             ; Copy the contents to $0
+  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or
+  ; after the last one are not removed here but instead in Step 3)
+  ${If} $0 != ""                           ; If EnvVar is not empty ...
+    ${Do}
+      ${${UN}StrStr} $7 $0 " ;"
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 " ;" ";"         ; Remove '<space>;'
+    ${Loop}
+    ${Do}
+      ${${UN}StrStr} $7 $0 "; "
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 "; " ";"         ; Remove ';<space>'
+    ${Loop}
+    ${Do}
+      ${${UN}StrStr} $7 $0 ";;" 
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 ";;" ";"
+    ${Loop}
+ 
+    ; Remove a leading or trailing semicolon from EnvVar
+    StrCpy  $7  $0 1 0
+    ${If} $7 == ";"
+      StrCpy $0  $0 "" 1                   ; Change ';<EnvVar>' to '<EnvVar>'
+    ${EndIf}
+    StrLen $6 $0
+    IntOp $6 $6 - 1
+    StrCpy $7  $0 1 $6
+    ${If} $7 == ";"
+     StrCpy $0  $0 $6                      ; Change ';<EnvVar>' to '<EnvVar>'
+    ${EndIf}
+    ; DetailPrint "Scrubbed $1: [$0]"      ; Uncomment to debug
+  ${EndIf}
+ 
+  /* Step 3. Remove all instances of the target path/string (even if "A" or "P")
+     $6 = bool flag (1 = found and removed PathString)
+     $7 = a string (e.g. path) delimited by semicolon(s)
+     $8 = entry counter starting at 0
+     $9 = copy of $0
+     $R0 = tempChar      */
+ 
+  ${If} $5 != ""                           ; If EnvVar is not empty ...
+    StrCpy $9 $0
+    StrCpy $0 ""
+    StrCpy $8 0
+    StrCpy $6 0
+ 
+    ${Do}
+      ${${UN}StrTok} $7 $9 ";" $8 "0"      ; $7 = next entry, $8 = entry counter
+ 
+      ${If} $7 == ""                       ; If we've run out of entries,
+        ${ExitDo}                          ;    were done
+      ${EndIf}                             ;
+ 
+      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)
+      ${Do}
+        StrCpy $R0  $7 1
+        ${If} $R0 != " "
+          ${ExitDo}
+        ${EndIf}
+        StrCpy $7   $7 "" 1                ;  Remove leading space
+      ${Loop}
+      ${Do}
+        StrCpy $R0  $7 1 -1
+        ${If} $R0 != " "
+          ${ExitDo}
+        ${EndIf}
+        StrCpy $7   $7 -1                  ;  Remove trailing space
+      ${Loop}
+      ${If} $7 == $4                       ; If string matches, remove it by not appending it
+        StrCpy $6 1                        ; Set 'found' flag
+      ${ElseIf} $7 != $4                   ; If string does NOT match
+      ${AndIf}  $0 == ""                   ;    and the 1st string being added to $0,
+        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon
+      ${ElseIf} $7 != $4                   ; If string does NOT match
+      ${AndIf}  $0 != ""                   ;    and this is NOT the 1st string to be added to $0,
+        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon
+      ${EndIf}                             ;
+ 
+      IntOp $8 $8 + 1                      ; Bump counter
+    ${Loop}                                ; Check for duplicates until we run out of paths
+  ${EndIf}
+ 
+  ; Step 4:  Perform the requested Action
+  ;
+  ${If} $2 != "R"                          ; If Append or Prepend
+    ${If} $6 == 1                          ; And if we found the target
+      DetailPrint "Target is already present in $1. It will be removed and"
+    ${EndIf}
+    ${If} $0 == ""                         ; If EnvVar is (now) empty
+      StrCpy $0 $4                         ;   just copy PathString to EnvVar
+      ${If} $6 == 0                        ; If found flag is either 0
+      ${OrIf} $6 == ""                     ; or blank (if EnvVarName is empty)
+        DetailPrint "$1 was empty and has been updated with the target"
+      ${EndIf}
+    ${ElseIf} $2 == "A"                    ;  If Append (and EnvVar is not empty),
+      StrCpy $0 $0;$4                      ;     append PathString
+      ${If} $6 == 1
+        DetailPrint "appended to $1"
+      ${Else}
+        DetailPrint "Target was appended to $1"
+      ${EndIf}
+    ${Else}                                ;  If Prepend (and EnvVar is not empty),
+      StrCpy $0 $4;$0                      ;     prepend PathString
+      ${If} $6 == 1
+        DetailPrint "prepended to $1"
+      ${Else}
+        DetailPrint "Target was prepended to $1"
+      ${EndIf}
+    ${EndIf}
+  ${Else}                                  ; If Action = Remove
+    ${If} $6 == 1                          ;   and we found the target
+      DetailPrint "Target was found and removed from $1"
+    ${Else}
+      DetailPrint "Target was NOT found in $1 (nothing to remove)"
+    ${EndIf}
+    ${If} $0 == ""
+      DetailPrint "$1 is now empty"
+    ${EndIf}
+  ${EndIf}
+ 
+  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change
+  ;
+  ClearErrors
+  ${If} $3  == HKLM
+    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section
+  ${ElseIf} $3 == HKCU
+    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section
+  ${EndIf}
+ 
+  IfErrors 0 +4
+    MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"
+    DetailPrint "Could not write updated $1 to $3"
+    Goto EnvVarUpdate_Restore_Vars
+ 
+  ; "Export" our change
+  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+ 
+  EnvVarUpdate_Restore_Vars:
+  ;
+  ; Restore the user's variables and return ResultVar
+  Pop $R0
+  Pop $9
+  Pop $8
+  Pop $7
+  Pop $6
+  Pop $5
+  Pop $4
+  Pop $3
+  Pop $2
+  Pop $1
+  Push $0  ; Push my $0 (ResultVar)
+  Exch
+  Pop $0   ; Restore his $0
+ 
+FunctionEnd
+ 
+!macroend   ; EnvVarUpdate UN
+!insertmacro EnvVarUpdate ""
+!insertmacro EnvVarUpdate "un."
+;----------------------------------- EnvVarUpdate end----------------------------------------
+ 
+!verbose pop
+!endif
diff --git a/tools/niminst/inno.tmpl b/tools/niminst/inno.tmpl
index b9d04755e..3460c22a2 100644
--- a/tools/niminst/inno.tmpl
+++ b/tools/niminst/inno.tmpl
@@ -44,9 +44,9 @@ Name: modifypath; Description: &Add $c.displayName to your system path (if not i
 [Code]
 function GiveMeAPath(const DefaultPathName: string): string;
 begin
-  if IsAdminLoggedOn then Result := ExpandConstant('{pf}')
-  else Result := ExpandConstant('{userdocs}');
-  Result := Result + '\' + DefaultPathName;
+  if IsAdminLoggedOn then result := ExpandConstant('{pf}')
+  else result := ExpandConstant('{userdocs}');
+  result := result + '\' + DefaultPathName;
 end;
 
   #if c.binPaths.len > 0:
diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index bf8a7a84f..53de52f0a 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -31,6 +31,7 @@ type
     actionNone,   # action not yet known
     actionCSource # action: create C sources
     actionInno,   # action: create Inno Setup installer
+    actionNsis,   # action: create NSIS installer
     actionScripts # action: create install and deinstall scripts
     actionZip,    # action: create zip file
     actionDeb     # action: prepare deb package
@@ -50,10 +51,10 @@ type
   TConfigData = object of TObject
     actions: set[TAction]
     cat: array[TFileCategory, seq[string]]
-    binPaths, authors, oses, cpus: seq[string]
+    binPaths, authors, oses, cpus, downloads: seq[string]
     cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
     platforms: array[1..maxOS, array[1..maxCPU, bool]]
-    ccompiler, linker, innosetup: tuple[path, flags: string]
+    ccompiler, linker, innosetup, nsisSetup: tuple[path, flags: string]
     name, displayName, version, description, license, infile, outdir: string
     libpath: string
     innoSetupFlag, installScript, uninstallScript: bool
@@ -75,9 +76,11 @@ proc initConfigData(c: var TConfigData) =
   c.authors = @[]
   c.oses = @[]
   c.cpus = @[]
+  c.downloads = @[]
   c.ccompiler = ("", "")
   c.linker = ("", "")
   c.innosetup = ("", "")
+  c.nsisSetup = ("", "")
   c.name = ""
   c.displayName = ""
   c.version = ""
@@ -117,6 +120,7 @@ proc skipRoot(f: string): string =
   if result.len == 0: result = f
 
 include "inno.tmpl"
+include "nsis.tmpl"
 include "buildsh.tmpl"
 include "buildbat.tmpl"
 include "install.tmpl"
@@ -125,10 +129,10 @@ include "deinstall.tmpl"
 # ------------------------- configuration file -------------------------------
 
 const
-  Version = "0.9"
+  Version = "1.0"
   Usage = "niminst - Nimrod Installation Generator Version " & Version & """
 
-  (c) 2013 Andreas Rumpf
+  (c) 2014 Andreas Rumpf
 Usage:
   niminst [options] command[;command2...] ini-file[.ini] [compile_options]
 Command:
@@ -136,6 +140,7 @@ Command:
   scripts             build install and deinstall scripts
   zip                 build the ZIP file
   inno                build the Inno Setup installer
+  nsis                build the NSIS Setup installer
   deb                 create files for debhelper
 Options:
   -o, --output:dir    set the output directory
@@ -162,6 +167,7 @@ proc parseCmdLine(c: var TConfigData) =
           of "scripts": incl(c.actions, actionScripts)
           of "zip": incl(c.actions, actionZip)
           of "inno": incl(c.actions, actionInno)
+          of "nsis": incl(c.actions, actionNsis)
           of "deb": incl(c.actions, actionDeb)
           else: quit(Usage)
       else:
@@ -190,7 +196,7 @@ proc walkDirRecursively(s: var seq[string], root: string) =
     case k
     of pcFile, pcLinkToFile: add(s, unixToNativePath(f))
     of pcDir: walkDirRecursively(s, f)
-    of pcLinkToDir: nil
+    of pcLinkToDir: discard
 
 proc addFiles(s: var seq[string], patterns: seq[string]) =
   for p in items(patterns):
@@ -288,7 +294,7 @@ proc parseIniFile(c: var TConfigData) =
             else: quit(errorStr(p, "expected: console or gui"))
           of "license": c.license = unixToNativePath(k.value)
           else: quit(errorStr(p, "unknown variable: " & k.key))
-        of "var": nil
+        of "var": discard
         of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin])
         of "config": filesOnly(p, k.key, v, c.cat[fcConfig])
         of "data": filesOnly(p, k.key, v, c.cat[fcData])
@@ -304,6 +310,7 @@ proc parseIniFile(c: var TConfigData) =
           of "files": addFiles(c.cat[fcWindows], split(v, {';'}))
           of "binpath": c.binPaths = split(v, {';'})
           of "innosetup": c.innoSetupFlag = yesno(p, v)
+          of "download": c.downloads.add(v)
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "unix":
           case normalize(k.key)
@@ -313,6 +320,7 @@ proc parseIniFile(c: var TConfigData) =
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin])
         of "innosetup": pathFlags(p, k.key, v, c.innosetup)
+        of "nsis": pathFlags(p, k.key, v, c.nsisSetup)
         of "ccompiler": pathFlags(p, k.key, v, c.ccompiler)
         of "linker": pathFlags(p, k.key, v, c.linker)
         of "deb":
@@ -479,14 +487,14 @@ proc srcdist(c: var TConfigData) =
 
 # --------------------- generate inno setup -----------------------------------
 proc setupDist(c: var TConfigData) =
-  var scrpt = generateInnoSetup(c)
-  var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
+  let scrpt = generateInnoSetup(c)
+  let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
   writeFile(n, scrpt, "\13\10")
   when defined(windows):
     if c.innosetup.path.len == 0:
       c.innosetup.path = "iscc.exe"
-    var outcmd = if c.outdir.len == 0: "build" else: c.outdir
-    var cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
+    let outcmd = if c.outdir.len == 0: "build" else: c.outdir
+    let cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
                                  c.innosetup.flags, outcmd, n]
     echo(cmd)
     if execShellCmd(cmd) == 0:
@@ -494,6 +502,23 @@ proc setupDist(c: var TConfigData) =
     else:
       quit("External program failed")
 
+# --------------------- generate NSIS setup -----------------------------------
+proc setupDist2(c: var TConfigData) =
+  let scrpt = generateNsisSetup(c)
+  let n = "build" / "install_$#_$#.nsi" % [toLower(c.name), c.version]
+  writeFile(n, scrpt, "\13\10")
+  when defined(windows):
+    if c.nsisSetup.path.len == 0:
+      c.nsisSetup.path = "makensis.exe"
+    let outcmd = if c.outdir.len == 0: "build" else: c.outdir
+    let cmd = "$# $# /O$# $#" % [quoteShell(c.nsisSetup.path),
+                                 c.nsisSetup.flags, outcmd, n]
+    echo(cmd)
+    if execShellCmd(cmd) == 0:
+      removeFile(n)
+    else:
+      quit("External program failed")
+
 # ------------------ generate ZIP file ---------------------------------------
 when haveZipLib:
   proc zipDist(c: var TConfigData) =
@@ -503,17 +528,17 @@ when haveZipLib:
     else: n = c.outdir / n
     var z: TZipArchive
     if open(z, n, fmWrite):
-      addFile(z, proj / buildBatFile32, buildBatFile32)
-      addFile(z, proj / buildBatFile64, buildBatFile64)
-      addFile(z, proj / buildShFile, buildShFile)
+      addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
+      addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
+      addFile(z, proj / buildShFile, "build" / buildShFile)
       addFile(z, proj / installShFile, installShFile)
       addFile(z, proj / deinstallShFile, deinstallShFile)
       for f in walkFiles(c.libpath / "lib/*.h"):
-        addFile(z, proj / "build" / extractFilename(f), f)
+        addFile(z, proj / "c_code" / extractFilename(f), f)
       for osA in 1..c.oses.len:
         for cpuA in 1..c.cpus.len:
           var dir = buildDir(osA, cpuA)
-          for k, f in walkDir(dir):
+          for k, f in walkDir("build" / dir):
             if k == pcFile: addFile(z, proj / dir / extractFilename(f), f)
 
       for cat in items({fcConfig..fcOther, fcUnix}):
@@ -576,6 +601,8 @@ parseCmdLine(c)
 parseIniFile(c)
 if actionInno in c.actions:
   setupDist(c)
+if actionNsis in c.actions:
+  setupDist2(c)
 if actionCSource in c.actions:
   srcdist(c)
 if actionScripts in c.actions:
diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl
new file mode 100644
index 000000000..40e171d41
--- /dev/null
+++ b/tools/niminst/nsis.tmpl
@@ -0,0 +1,258 @@
+#! stdtmpl(subsChar='?') | standard
+#proc generateNsisSetup(c: TConfigData): string = 
+#  result = "; NSIS script generated by niminst\n" &
+#           "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"
+
+;--------------------------------
+; Included headers
+  ; Modern User Interface 2.0 Header
+  !include "MUI2.nsh"
+
+  ; File Functions Header, used to get the current drive root.
+  !include "FileFunc.nsh"
+
+  ; *Patched* Environment Variable Manipulation Header, used to add
+  ; tools to the user's PATH environment variable.
+  !include "EnvVarUpdate.nsh"
+
+;--------------------------------
+; Global variables and defines
+  !define PRODUCT_NAME "?c.displayName"
+  !define PRODUCT_VERSION "?c.version"
+  !define PRODUCT_PUBLISHER "?c.authors"
+  !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe"
+  !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+  !define PRODUCT_UNINST_ROOT_KEY "HKCU"
+  !define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
+
+
+;--------------------------------
+; General Setup Information
+
+  ; Name and output file
+  Name "?{c.name} ?{c.version}"
+  OutFile "?{c.name}_?{c.version}.exe"
+
+  ; Default installation folder
+  ; This is changed later (in .onInit) to the root directory, if possible.
+  InstallDir "$LOCALAPPDATA\?{c.name}"
+  
+  ; Get installation folder from registry if available
+  InstallDirRegKey HKCU "Software\c.name\c.version" ""
+
+  ; Request user level application privileges.
+  RequestExecutionLevel user
+
+  ; Allow installation to the root drive directory.
+  AllowRootDirInstall true
+
+  ; Maximum compression!
+  SetCompressor /SOLID /FINAL lzma
+
+  ; Installer and Uninstaller Icons
+  ; Icon "nimrod.ico"
+  ; UninstallIcon "nimrod.ico"
+
+  ; Set installation details to be shown by default
+  ShowInstDetails show
+  ShowUnInstDetails show
+
+;--------------------------------
+; Interface Settings
+
+  ; Warn the user if aborting during installation/uninstallation
+  !define MUI_ABORTWARNING
+  !define MUI_UNABORTWARNING
+
+  ; Don't show a description for sections
+  !define MUI_COMPONENTSPAGE_NODESC
+
+;--------------------------------
+; Pages
+
+  ; Setup the installer pages
+  !insertmacro MUI_PAGE_WELCOME
+  !insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}"
+  !insertmacro MUI_PAGE_COMPONENTS
+  !insertmacro MUI_PAGE_DIRECTORY
+
+  ; Setup the start menu entry page
+  var ICONS_GROUP
+  !define MUI_STARTMENUPAGE_DEFAULTFOLDER "?{c.displayName}"
+  !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
+  !define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
+  !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
+  !insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
+
+  !insertmacro MUI_PAGE_INSTFILES
+  !insertmacro MUI_PAGE_FINISH
+  
+  ; Setup the uninstaller pages
+  !insertmacro MUI_UNPAGE_CONFIRM
+  !insertmacro MUI_UNPAGE_INSTFILES
+  
+;--------------------------------
+;Languages
+ 
+  !insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Installer Sections
+
+  ; The core section. This is comprised of a base Nim installation,
+  ; such as what would be retrieved via git, and an already bootstrapped
+  ; Nim binary.
+  Section "Core Files" CoreSection
+    ; This is a mandotory section
+    SectionIn RO 
+
+    ; Output files to the base installation directory
+    SetOutPath "$INSTDIR"
+
+    ; Only overwrite newer files
+    SetOverwrite ifnewer
+
+    ; Write all the files to the output directory.
+    #for i in low(TFileCategory)..fcWindows:
+    #  for f in items(c.cat[i]):
+         SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}"
+         File "?{expandFilename(f).toWin}"
+    #  end for
+    #end for
+
+    ; Write out the uninstaller
+    WriteUninstaller "$INSTDIR\uninstaller.exe"
+  SectionEnd
+
+  Section "-Add Registry Keys" RegistrySection
+    ; Write application registry keys
+    WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+    ; Reset the output path
+    SetOutPath "$INSTDIR"
+  SectionEnd
+
+  ; Section for adding the shortcuts related to files and applications
+  Section "-Setup Shortcuts" ShortcutsSection
+    !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+      CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
+
+      #if c.app == appConsole:
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
+        CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
+      #else:
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
+        CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
+      #end if
+
+      ; Write the shortcut to the uninstaller
+      CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstaller.exe"
+    !insertmacro MUI_STARTMENU_WRITE_END
+  SectionEnd
+
+  ; Section for adding tools to the PATH variable
+  Section "Setup Path Environment" PathSection
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw"
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw\bin"
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\bin"
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\babel"
+  SectionEnd
+
+  ; The downloadable sections. These sections are automatically generated by
+  ; niminst and the template filters.
+  #var i = 0 
+  #for download in c.downloads:
+  #  inc i
+  #  let d = download.split('|')
+  #  if d.len != 5 and d.len != 6:
+  #    quit("download string needs 5..6 parts: " & download)
+  #  end if
+  #  let sectionName = d[0]
+  #  let dir = d[1]
+  #  let zipName = d[2]
+  #  let size = d[3]
+  #  let url = d[4]
+  Section /o "?sectionName" ?{i}Section
+    ; Add the section size to the total size.
+    AddSize ?size
+
+    ; Download the file, and if successful, extract it to the given directory
+    ; otherwise,
+    retry:
+    NSISdl::download "?url" "$TEMP\?zipName"
+    Pop $0
+    ${If} $0 == "success"
+      ZipDLL::extractall "$TEMP\?zipName" "$INSTDIR\?dir"
+      Delete "$TEMP\?zipName"
+    ${ElseIf} $0 == "cancel"
+      MessageBox MB_ICONQUESTION|MB_YESNO|MB_TOPMOST \
+                 "Download of component '?sectionName' cancelled. Continue installation process??" \
+                 IDYES ignore
+      abort
+    ${Else}
+      MessageBox MB_ICONSTOP|MB_ABORTRETRYIGNORE|MB_TOPMOST "Error: $0" \
+                 IDRETRY retry IDIGNORE ignore
+      abort
+    ${EndIf}
+
+    ; Shortcuts
+    #  if d.len >= 6:
+    #    let startMenuEntry = d[5]
+    #    let e = splitFile(startMenuEntry).name.capitalize
+      !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
+      !insertmacro MUI_STARTMENU_WRITE_END
+    #  end if
+    
+    ignore:
+  SectionEnd
+  #end
+
+;--------------------------------
+; Section Descriptions
+  ; Series of strings describing each section
+  ; LangString DESC_CoreSection ${LANG_ENGLISH} "Core Nim files"
+
+  ; The macros to actually insert the descriptions into the sections.
+  ; Each description above should have a corresponding MUI_DESCRIPTION_TEXT
+  ; macro linking the section to the description.
+  ; !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+  ;   !insertmacro MUI_DESCRIPTION_TEXT ${CoreSection} $(DESC_CoreSection)
+  ; !insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+
+;--------------------------------
+; Uninstaller Sections
+
+  Section "Uninstall"
+    ; Remove previously created shortcuts
+    !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
+    Delete "$DESKTOP\?{c.displayName}.lnk"
+
+    ; Remove installed application files
+    RMDir /r "$SMPROGRAMS\$ICONS_GROUP"
+    RMDir /r "$INSTDIR"
+
+    ; Remove the previously created registry key
+    DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+    DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}"
+    SetAutoClose true
+
+    ; Remove entries from the PATH environment variable
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw"
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw\bin"
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\bin"
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\babel"
+  SectionEnd
+
+;--------------------------------
+; Function hooks
+
+  Function .onInit
+    ${GetRoot} "$EXEDIR" $R0
+    strCpy $INSTDIR "$R0\?{c.name}"
+  FunctionEnd
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index 9a83a5cca..5233bac45 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -21,6 +21,7 @@ type
     nimrodArgs: string
     gitCommit: string
     quotations: TTable[string, tuple[quote, author: string]]
+    numProcessors: int # Set by parallelBuild:n, only works for values > 0.
   TRssItem = object
     year, month, day, title: string
 
@@ -42,10 +43,12 @@ proc initConfigData(c: var TConfigData) =
   c.ticker = ""
   c.vars = newStringTable(modeStyleInsensitive)
   c.gitCommit = "master"
+  c.numProcessors = countProcessors()
   # Attempts to obtain the git current commit.
-  let (output, code) = execCmdEx("git log -n 1 --format=%H")
-  if code == 0 and output.strip.len == 40:
-    c.gitCommit = output.strip
+  when false:
+    let (output, code) = execCmdEx("git log -n 1 --format=%H")
+    if code == 0 and output.strip.len == 40:
+      c.gitCommit = output.strip
   c.quotations = initTable[string, tuple[quote, author: string]]()
 
 include "website.tmpl"
@@ -121,6 +124,12 @@ proc parseCmdLine(c: var TConfigData) =
         stdout.write(Version & "\n")
         quit(0)
       of "o", "output": c.outdir = val
+      of "parallelbuild":
+        try:
+          let num = parseInt(val)
+          if num != 0: c.numProcessors = num
+        except EInvalidValue:
+          quit("invalid numeric value for --parallelBuild")
       of "var":
         var idx = val.find('=')
         if idx < 0: quit("invalid command line")
@@ -187,6 +196,12 @@ proc parseIniFile(c: var TConfigData) =
           of "srcdoc": addFiles(c.srcdoc, "lib", ".nim", split(v, {';'}))
           of "srcdoc2": addFiles(c.srcdoc2, "lib", ".nim", split(v, {';'}))
           of "webdoc": addFiles(c.webdoc, "lib", ".nim", split(v, {';'}))
+          of "parallelbuild":
+            try:
+              let num = parseInt(v)
+              if num != 0: c.numProcessors = num
+            except EInvalidValue:
+              quit("invalid numeric value for --parallelBuild in config")
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "quotations":
           let vSplit = v.split('-')
@@ -215,6 +230,20 @@ proc exec(cmd: string) =
   echo(cmd)
   if os.execShellCmd(cmd) != 0: quit("external program failed")
 
+proc sexec(cmds: openarray[string]) =
+  ## Serial queue wrapper around exec.
+  for cmd in cmds: exec(cmd)
+
+proc mexec(cmds: openarray[string], processors: int) =
+  ## Multiprocessor version of exec
+  if processors < 2:
+    sexec(cmds)
+    return
+
+  if execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}) != 0:
+    echo "external program failed, retrying serial work queue for logs!"
+    sexec(cmds)
+
 proc buildDocSamples(c: var TConfigData, destPath: string) =
   ## Special case documentation sample proc.
   ##
@@ -229,18 +258,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
 
 proc buildDoc(c: var TConfigData, destPath: string) =
   # call nim for the documentation:
+  var
+    commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
+    i = 0
   for d in items(c.doc):
-    exec("nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
   for d in items(c.srcdoc):
-    exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
   for d in items(c.srcdoc2):
-    exec("nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
+    commands[i] = "nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(d).name, "html"), d]
+    i.inc
+
+  mexec(commands, c.numProcessors)
   exec("nimrod buildIndex -o:$1/theindex.html $1" % [destPath])
 
 proc buildPdfDoc(c: var TConfigData, destPath: string) =
@@ -253,8 +290,10 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
       exec("pdflatex " & changeFileExt(d, "tex"))
       exec("pdflatex " & changeFileExt(d, "tex"))
       # delete all the crappy temporary files:
-      var pdf = splitFile(d).name & ".pdf"
-      moveFile(dest=destPath / pdf, source=pdf)
+      let pdf = splitFile(d).name & ".pdf"
+      let dest = destPath / pdf
+      removeFile(dest)
+      moveFile(dest=dest, source=pdf)
       removeFile(changeFileExt(pdf, "aux"))
       if existsFile(changeFileExt(pdf, "toc")):
         removeFile(changeFileExt(pdf, "toc"))
@@ -264,10 +303,12 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
 
 proc buildAddDoc(c: var TConfigData, destPath: string) =
   # build additional documentation (without the index):
-  for d in items(c.webdoc):
-    exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" %
+  var commands = newSeq[string](c.webdoc.len)
+  for i, doc in pairs(c.webdoc):
+    commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" %
       [c.nimrodArgs, c.gitCommit,
-      destPath / changeFileExt(splitFile(d).name, "html"), d])
+      destPath / changeFileExt(splitFile(doc).name, "html"), doc]
+  mexec(commands, c.numProcessors)
 
 proc parseNewsTitles(inputFilename: string): seq[TRssItem] =
   # parses the file for titles and returns them as TRssItem blocks.
@@ -394,4 +435,7 @@ var c: TConfigData
 initConfigData(c)
 parseCmdLine(c)
 parseIniFile(c)
-main(c)
+when false:
+  buildPdfDoc(c, "doc")
+else:
+  main(c)
diff --git a/web/download.txt b/web/download.txt
index 557788217..dc53cbeb4 100644
--- a/web/download.txt
+++ b/web/download.txt
@@ -1,127 +1,41 @@
-You can download the latest version of the Nimrod compiler here. You can
-use the binaries provided or build from source.
-
-Binaries
-========
-
-All installers and archives contain the html documentation and tools
-(nimgrep, c2nim and babel).
+You can download the latest version of the Nimrod compiler here.
 
 **Note:** The Nimrod compiler requires a C compiler to compile software. On
 Windows we recommend that you use
 `Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
 and clang on Mac OS X.
 
-Installers
-----------
-
-The "full" version includes a full mingw distribution which includes a C
-compiler. The "slim" version lacks this.
-
-* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.exe>`_
-
-  .. raw:: html
-    <p style="font-size: 8pt; margin-top: 0;">
-    SHA256: dca7c63d0c1861d2d7c51b2e7a29fa98371750a10ab282d5df9de22a07719c24
-    </p>
-
-* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.exe>`_
-
-  .. raw:: html
-      <p style="font-size: 8pt; margin-top: 0;">
-      SHA256: c0fcd1201bd20fad1e14b9d2cc2529494057068de1dd01f871cf129f088a8242
-      </p>
-
-* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.exe>`_
-
-  .. raw:: html
-    <p style="font-size: 8pt; margin-top: 0;">
-    SHA256: af9d478c2f3361e0f238fcb07fa8e7ae5821938c0f9063c6670e925c9ae9d16e
-    </p>
-
-* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.exe>`_
-
-  .. raw:: html
-      <p style="font-size: 8pt; margin-top: 0;">
-      SHA256: 90c380721a46be2b9b8d5437187f701940aefc2e1fb9722dbc543f5c5a3bb85e
-      </p>
 
-Archives
---------
-
-Windows
-~~~~~~~
-
-The "full" version includes a full mingw distribution which includes a C
-compiler. The "slim" version lacks this.
-
-* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.zip>`_
-
-  .. raw:: html
-    <p style="font-size: 8pt; margin-top: 0;">
-    SHA256: 8ee18faaa3a3d5df482c7abd6aa7ea87a350d7328b80ce1e2d486b59a7a93956
-    </p>
-
-* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.zip>`_
-
-  .. raw:: html
-      <p style="font-size: 8pt; margin-top: 0;">
-      SHA256: 7024fb8ad8f98c0bd4949ae36ed11b52b4e401754bbd62a11199d6dc8628d857 
-      </p>
-
-* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.zip>`_
-
-  .. raw:: html
-    <p style="font-size: 8pt; margin-top: 0;">
-    SHA256: cb33cacc1a84fec771323d24cb6d9795f4803882466a9f417b424990aa49e18a
-    </p>
-
-* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.zip>`_
+Binaries
+========
 
-  .. raw:: html
-      <p style="font-size: 8pt; margin-top: 0;">
-      SHA256: fcf877e4bd1ebfa214749af6e4811cd8539af19f1d7b23017e4bd7f6cbfb3eba
-      </p>
+Unfortunately for now we only provide builds for Windows.
 
-Linux
-~~~~~
+* 32 bit: `nimrod_0.9.6.exe <download/nimrod_0.9.6.exe>`_
+* 64 bit: `nimrod_0.9.6_x64.exe <download/nimrod_0.9.6_x64.exe>`_
 
-* Linux (i386, 32bit): `<download/nimrod_0.9.4_linux_i386.tar.gz>`_
 
-  .. raw:: html
-      <p style="font-size: 8pt; margin-top: 0;">
-      SHA256: 79DD337A77AC4313A75F2C5EED8252F00BBBDEB1E0C3504660D4A52EA63DBA92
-      </p>
-* Linux (amd64, 64bit): `<download/nimrod_0.9.4_linux_amd64.tar.gz>`_
+Installation based on generated C code
+======================================
 
-  .. raw:: html
-    <p style="font-size: 8pt; margin-top: 0;">
-    SHA256: 6F6CB3C727BA8059B7605C02942AE7910C20C2A3DC6A8A600D90D50FE61F0D8C
-    </p>
-* Linux (ppc64, 64bit): `<download/nimrod_0.9.4_linux_ppc64.tar.gz>`_
+This installation method is the preferred way for Linux, Mac OS X, and other Unix
+like systems. Binary packages may be provided later.
 
-  .. raw:: html
-      <p style="font-size: 8pt; margin-top: 0;">
-      SHA256: 5DAC2D9F7F545929E04540E6E2594C68FC3126A3B2F7B1FA7DBA5E295B4A7D31
-      </p>
 
-Mac OS X
-~~~~~~~~
+Download `nimrod_0.9.6.zip <download/nimrod_0.9.6.zip>`_, extract it and follow
+these instructions:
 
-* Mac OS X (amd64, 64bit): `<download/nimrod_0.9.4_macosx_amd64.zip>`_
+* sh build.sh
+* Add ``$your_install_dir/bin`` to your PATH.
 
-  .. raw:: html
-      <p style="font-size: 8pt; margin-top: 0;">
-      SHA256: E6F3A8E434DF3E89686F043954C6DFC09ABEBC0FC09D3B9A6B35C2B3102F7C3C
-      </p>
+There are other ways to install Nimrod (like using the ``install.sh`` script),
+but these tend to cause more problems.
 
-If a binary for your platform is not available then you must build from source.
-Bleeding edge binaries are available from the `Nimrod build farm <http://build.nimrod-lang.org/>`_.
 
-Source
-======
+Installation from github
+========================
 
-Starting with 0.9.4 we now advise people to build directly from the
+It is also possible to build directly from the
 github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
 
   git clone -b master git://github.com/Araq/Nimrod.git
@@ -135,4 +49,3 @@ github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
 The ``master`` branch always contains the latest stable version of the compiler.
 If you want bleeding edge then switch to the ``devel`` branch and follow
 the same instructions outlined above.
-
diff --git a/web/news.txt b/web/news.txt
index 62a923dcd..3d962172f 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -2,33 +2,68 @@
 News
 ====
 
-..
-  2014-06-29 Version 0.9.6 released
-  =================================
-
-  Changes affecting backwards compatibility
-  -----------------------------------------
-
-  - ``spawn`` now uses an elaborate self-adapting thread pool and as such
-    has been moved into its own module. So to use it, you now have to import
-    ``threadpool``.
-  - The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is
-    now considered for implicit early binding.
-  - ``c2nim`` moved into its own repository and is now a Babel package.
-  - ``pas2nim`` moved into its own repository and is now a Babel package.
-  - ``system.$`` for floating point types now produces a human friendly string
-    representation.
-  - ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
-    of the new ``TUri`` type in the ``uri`` module.
-
-  Library Additions
-  -----------------
-
-  - Added module ``cpuinfo``.
-  - Added module ``threadpool``.
-  - ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
-  - Added ``algorithm.reversed``
-  - Added ``uri.combine`` and ``uri.parseUri``.
+2014-10-19 Nimrod version 0.9.6 released
+========================================
+
+**Note: 0.9.6 is the last release of Nimrod. The language is being renamed to
+Nim. Nim slightly breaks compatibility.**
+
+This is a maintenance release. The upcoming 0.10.0 release has
+the new features and exciting developments.
+
+
+Changes affecting backwards compatibility
+-----------------------------------------
+
+- ``spawn`` now uses an elaborate self-adapting thread pool and as such
+  has been moved into its own module. So to use it, you now have to import
+  ``threadpool``.
+- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is
+  now considered for implicit early binding.
+- ``c2nim`` moved into its own repository and is now a Babel package.
+- ``pas2nim`` moved into its own repository and is now a Babel package.
+- ``system.$`` for floating point types now produces a human friendly string
+  representation.
+- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
+  of the new ``TUri`` type in the ``uri`` module.
+- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
+  instead. The destructor's name has to be ``destroy`` now.
+- ``lambda`` is not a keyword anymore.
+- **system.defined has been split into system.defined and system.declared**.
+  You have to use ``--symbol`` to declare new conditional symbols that can be
+  set via ``--define``.
+- ``--threadanalysis:on`` is now the default. To make your program compile
+  you can disable it but this is only a temporary solution as this option
+  will disappear soon!
+
+
+Compiler improvements
+---------------------
+
+- Multi method dispatching performance has been improved by a factor of 10x for
+  pathological cases.
+
+
+Language Additions
+------------------
+
+- This version introduces the ``deprecated`` pragma statement that is used
+  to handle the upcoming massive amount of symbol renames.
+- ``spawn`` can now wrap proc that has a return value. It then returns a data
+  flow variable of the wrapped return type.
+
+
+Library Additions
+-----------------
+
+- Added module ``cpuinfo``.
+- Added module ``threadpool``.
+- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
+- Added ``algorithm.reversed``
+- Added ``uri.combine`` and ``uri.parseUri``.
+- Some sockets procedures now support a ``SafeDisconn`` flag which causes 
+  them to handle disconnection errors and not raise them.
+
 
 2014-04-21 Version 0.9.4 released
 =================================
diff --git a/web/nimrod.ini b/web/nimrod.ini
index 544446b11..fc8a5730f 100644
--- a/web/nimrod.ini
+++ b/web/nimrod.ini
@@ -26,9 +26,10 @@ file: ticker.txt
 [Quotations]
 # Page: quote - Person
 # Bad things will happen if you use multiple dashes here.
-index: """The most important thing in the programming language is the name. 
-A language will not succeed without a good name. I have recently invented a 
-very good name and now I am looking for a suitable language. - D. E. Knuth"""
+index: """Is it so bad, then, to be misunderstood? Pythagoras was misunderstood,
+and Socrates, and Jesus, and Luther, and Copernicus, and Galileo, and Newton,
+and every pure and wise spirit that ever took flesh. To be great is to be
+misunderstood. - Ralph Waldo Emerson"""
 documentation: """Incorrect documentation is often worse than no documentation. 
 - Bertrand Meyer"""
 download: """There are two major products that come out of Berkeley: LSD and
@@ -41,7 +42,7 @@ doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt"
 pdf: "manual;lib;tut1;tut2;nimrodc;niminst;gc"
 srcdoc2: "system.nim;impure/graphics;wrappers/sdl"
 srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned"
-srcdoc2: "impure/re;pure/sockets"
+srcdoc2: "impure/re;pure/sockets;pure/typetraits"
 srcdoc: "system/threads.nim;system/channels.nim;js/dom"
 srcdoc2: "pure/os;pure/strutils;pure/math;pure/matchers;pure/algorithm"
 srcdoc2: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib"
@@ -54,10 +55,10 @@ srcdoc2: "pure/httpserver;pure/httpclient;pure/smtp;impure/ssl;pure/fsmonitor"
 srcdoc2: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser"
 srcdoc2: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors;pure/mimetypes"
 srcdoc2: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
-srcdoc2: "impure/rdstdin;wrappers/zmq;wrappers/sphinx"
+srcdoc2: "impure/rdstdin;wrappers/sphinx"
 srcdoc2: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
 srcdoc2: "pure/collections/intsets;pure/collections/queues;pure/encodings"
-srcdoc2: "pure/events;pure/collections/sequtils;pure/irc;pure/cookies"
+srcdoc2: "pure/events;pure/collections/sequtils;pure/cookies"
 srcdoc2: "pure/ftpclient;pure/memfiles;pure/subexes;pure/collections/critbits"
 srcdoc2: "pure/asyncio;pure/actors;core/locks;pure/oids;pure/endians;pure/uri"
 srcdoc2: "pure/nimprof;pure/unittest;packages/docutils/highlite"
diff --git a/web/question.txt b/web/question.txt
index 89e242e35..be90cc67a 100644
--- a/web/question.txt
+++ b/web/question.txt
@@ -28,6 +28,14 @@ one of the even fewer that produces native binaries that require no
 runtime or interpreter.
 
 
+What have been the major influences in the language's design?
+-------------------------------------------------------------
+
+The language borrows heavily from: Modula 3, Delphi, Ada, C++, Python, Lisp,
+Oberon. As far as possible the list is sorted by the impact of influence.
+
+
+
 What is Nimrod's take on concurrency?
 -------------------------------------
 
@@ -89,8 +97,8 @@ Why is it named ``proc``?
 
 *Procedure* used to be the common term as opposed to a *function* which is a
 mathematical entity that has no side effects. It was planned to have ``func``
-as syntactic sugar for ``proc {.noSideEffect.}`` but the more fine-grained
-effect system makes that unimportant.
+as syntactic sugar for ``proc {.noSideEffect.}`` but with the more fine-grained
+effect system it is not yet clear what ``func`` should be a shortcut for.
 
 
 Compilation
@@ -117,15 +125,16 @@ Change the value of the ``cc`` variable to one of the following:
 ==============  ============================================
 Abbreviation    C/C++ Compiler
 ==============  ============================================
-``dmc``         Digital Mars C++
 ``vcc``         Microsoft's Visual C++
 ``gcc``         Gnu C
-``tcc``         Tiny C
 ``llvm_gcc``    LLVM-GCC compiler
 ``icc``         Intel C++ compiler
+``clang``       Clang compiler
 ``ucc``         Generic UNIX C compiler
 ==============  ============================================
 
+Other C compilers are not officially supported, but might work too.
+
 If your C compiler is not in the above list, try using the
 *generic UNIX C compiler* (``ucc``). If the C compiler needs
 different command line arguments try the ``--passc`` and ``--passl`` switches.
diff --git a/web/ticker.txt b/web/ticker.txt
index f06b00572..98ad25905 100644
--- a/web/ticker.txt
+++ b/web/ticker.txt
@@ -1,3 +1,8 @@
+<a class="news" href="news.html#Z2014-10-19-version-0-9-6-released">
+  <h3>Oct 19, 2014</h3>
+  <p>Nimrod version 0.9.6 has been released!</p>
+</a>
+
 <a class="news" href="news.html#Z2014-04-21-version-0-9-4-released">
   <h3>Apr 21, 2014</h3>
   <p>Nimrod version 0.9.4 has been released!</p>