summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim33
-rw-r--r--compiler/astalgo.nim8
-rw-r--r--compiler/canonicalizer.nim6
-rw-r--r--compiler/ccgutils.nim5
-rw-r--r--compiler/evalffi.nim2
-rw-r--r--compiler/extccomp.nim52
-rw-r--r--compiler/guards.nim4
-rw-r--r--compiler/lambdalifting.nim2
-rw-r--r--compiler/lexer.nim25
-rw-r--r--compiler/lookups.nim5
-rw-r--r--compiler/msgs.nim22
-rw-r--r--compiler/parser.nim104
-rw-r--r--compiler/pragmas.nim10
-rw-r--r--compiler/sem.nim25
-rw-r--r--compiler/semcall.nim12
-rw-r--r--compiler/semdata.nim5
-rw-r--r--compiler/semexprs.nim98
-rw-r--r--compiler/seminst.nim82
-rw-r--r--compiler/semstmts.nim22
-rw-r--r--compiler/semtempl.nim12
-rw-r--r--compiler/semtypes.nim197
-rw-r--r--compiler/semtypinst.nim49
-rw-r--r--compiler/sigmatch.nim86
-rw-r--r--compiler/syntaxes.nim21
-rw-r--r--compiler/transf.nim12
-rw-r--r--compiler/types.nim11
-rw-r--r--compiler/vm.nim3
-rw-r--r--compiler/vmgen.nim24
-rw-r--r--doc/manual.txt89
-rw-r--r--lib/impure/db_mysql.nim10
-rw-r--r--lib/nimbase.h3
-rw-r--r--lib/posix/epoll.nim2
-rw-r--r--lib/pure/asyncio2.nim223
-rw-r--r--lib/pure/dynlib.nim2
-rw-r--r--lib/pure/net.nim261
-rw-r--r--lib/pure/os.nim11
-rw-r--r--lib/pure/osproc.nim95
-rw-r--r--lib/pure/parsesql.nim2
-rw-r--r--lib/pure/selectors.nim69
-rw-r--r--lib/pure/sockets2.nim22
-rw-r--r--lib/system.nim54
-rw-r--r--lib/windows/winlean.nim1
-rw-r--r--tests/async/tasyncawait.nim33
-rw-r--r--tests/bind/tinvalidbindtypedesc.nim (renamed from tests/bind/tbindtypedesc.nim)1
-rw-r--r--tests/effects/teffects1.nim2
-rw-r--r--tests/generics/tbadgenericlambda.nim7
-rw-r--r--tests/generics/tgenericlambda.nim7
-rw-r--r--tests/generics/tgenericshardcases.nim18
-rw-r--r--tests/generics/tlateboundstatic.nim16
-rw-r--r--tests/generics/tsigtypeop.nim9
-rw-r--r--tests/iter/tchainediterators.nim38
-rw-r--r--tests/iter/titerable.nim26
-rw-r--r--tests/metatype/tstaticparams.nim37
-rw-r--r--tests/metatype/tusertypeclasses.nim5
-rw-r--r--tests/metatype/udtcmanual.nim2
-rw-r--r--tests/overload/tissue966.nim12
-rw-r--r--tests/parser/tstrongspaces.nim52
-rw-r--r--tests/static/tstaticparammacro.nim52
-rw-r--r--tests/stdlib/tpegs.nim2
-rw-r--r--tests/system/alloc.nim37
-rw-r--r--tests/template/tissue909.nim16
-rw-r--r--tests/template/tissue993.nim21
-rw-r--r--tests/testament/htmlgen.nim18
-rw-r--r--tests/testament/tester.nim8
-rw-r--r--tests/vm/tstaticprintseq.nim36
-rw-r--r--tests/vm/twrongconst.nim7
-rw-r--r--tests/vm/twrongwhen.nim4
-rw-r--r--todo.txt2
-rw-r--r--web/news.txt1
69 files changed, 1714 insertions, 536 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 9c9dfce9a..1dff21503 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -382,6 +382,10 @@ type
       # sons[0]: type of containing object or tuple
       # sons[1]: field type
       # .n: nkDotExpr storing the field name
+    
+static:
+  # remind us when TTypeKind stops to fit in a single 64-bit word
+  assert TTypeKind.high.ord <= 63
 
 const
   tyPureObject* = tyTuple
@@ -394,7 +398,7 @@ const
                     tyUserTypeClass, tyUserTypeClassInst,
                     tyAnd, tyOr, tyNot, tyAnything}
 
-  tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyStatic, tyExpr} + tyTypeClasses
+  tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses
  
 type
   TTypeKinds* = set[TTypeKind]
@@ -428,8 +432,9 @@ type
     tfFromGeneric,    # type is an instantiation of a generic; this is needed
                       # because for instantiations of objects, structural
                       # type equality has to be used
-    tfUnresolved,     # marks unresolved typedesc params: e.g.
+    tfUnresolved,     # marks unresolved typedesc/static params: e.g.
                       # proc foo(T: typedesc, list: seq[T]): var T
+                      # proc foo(L: static[int]): array[L, int]
     tfRetType,        # marks return types in proc (used to detect type classes 
                       # used as return types for return type inference)
     tfCapturesEnv,    # whether proc really captures some environment
@@ -448,6 +453,10 @@ type
     tfHasStatic
     tfGenericTypeParam
     tfImplicitTypeParam
+    tfWildcard        # consider a proc like foo[T, I](x: Type[T, I])
+                      # T and I here can bind to both typedesc and static types
+                      # before this is determined, we'll consider them to be a
+                      # wildcard type.
 
   TTypeFlags* = set[TTypeFlag]
 
@@ -693,7 +702,7 @@ type
   TSym* {.acyclic.} = object of TIdObj
     # proc and type instantiations are cached in the generic symbol
     case kind*: TSymKind
-    of skType:
+    of skType, skGenericParam:
       typeInstCache*: seq[PType]
       typScope*: PScope
     of routineKinds:
@@ -818,6 +827,9 @@ type
     counter*: int
     data*: TObjectSeq
 
+  TImplication* = enum
+    impUnknown, impNo, impYes
+
 # BUGFIX: a module is overloadable so that a proc can have the
 # same name as an imported module. This is necessary because of
 # the poor naming choices in the standard library.
@@ -865,6 +877,7 @@ const
   nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
                   nkCommand, nkCallStrLit, nkHiddenCallConv}
 
+  nkLiterals* = {nkCharLit..nkTripleStrLit}
   nkLambdaKinds* = {nkLambda, nkDo}
   declarativeDefs* = {nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef}
   procDefs* = nkLambdaKinds + declarativeDefs
@@ -957,7 +970,9 @@ var emptyNode* = newNode(nkEmpty)
 # There is a single empty node that is shared! Do not overwrite it!
 
 proc isMetaType*(t: PType): bool =
-  return t.kind in tyMetaTypes or tfHasMeta in t.flags
+  return t.kind in tyMetaTypes or
+         (t.kind == tyStatic and t.n == nil) or
+         tfHasMeta in t.flags
 
 proc linkTo*(t: PType, s: PSym): PType {.discardable.} =
   t.sym = s
@@ -1287,7 +1302,7 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
 proc propagateToOwner*(owner, elem: PType) =
   const HaveTheirOwnEmpty = {tySequence, tySet}
   owner.flags = owner.flags + (elem.flags * {tfHasShared, tfHasMeta,
-                                             tfHasStatic, tfHasGCedMem})
+                                             tfHasGCedMem})
   if tfNotNil in elem.flags:
     if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}:
       owner.flags.incl tfNotNil
@@ -1301,12 +1316,9 @@ proc propagateToOwner*(owner, elem: PType) =
   if tfShared in elem.flags:
     owner.flags.incl tfHasShared
 
-  if elem.kind in tyMetaTypes:
+  if elem.isMetaType:
     owner.flags.incl tfHasMeta
 
-  if elem.kind == tyStatic:
-    owner.flags.incl tfHasStatic
-
   if elem.kind in {tyString, tyRef, tySequence} or
       elem.kind == tyProc and elem.callConv == ccClosure:
     owner.flags.incl tfHasGCedMem
@@ -1494,6 +1506,9 @@ proc hasPattern*(s: PSym): bool {.inline.} =
 iterator items*(n: PNode): PNode =
   for i in 0.. <n.len: yield n.sons[i]
 
+iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
+  for i in 0.. <n.len: yield (i, n.sons[i])
+
 proc isAtom*(n: PNode): bool {.inline.} =
   result = n.kind >= nkNone and n.kind <= nkNilLit
 
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index cce2cc215..36dd7f562 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -50,7 +50,7 @@ proc strTableGet*(t: TStrTable, name: PIdent): PSym
 type 
   TTabIter*{.final.} = object # consider all fields here private
     h*: THash                 # current hash
-  
+
 proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym
 proc nextIter*(ti: var TTabIter, tab: TStrTable): PSym
   # usage:
@@ -157,6 +157,12 @@ proc leValue*(a, b: PNode): bool =
     #InternalError(a.info, "leValue")
     discard
 
+proc weakLeValue*(a, b: PNode): TImplication =
+  if a.kind notin nkLiterals or b.kind notin nkLiterals:
+    result = impUnknown
+  else:
+    result = if leValue(a, b): impYes else: impNo
+
 proc lookupInRecord(n: PNode, field: PIdent): PSym = 
   result = nil
   case n.kind
diff --git a/compiler/canonicalizer.nim b/compiler/canonicalizer.nim
index 07e932b28..3bc4eb029 100644
--- a/compiler/canonicalizer.nim
+++ b/compiler/canonicalizer.nim
@@ -81,7 +81,7 @@ proc hashSym(c: var MD5Context, s: PSym) =
 
 proc hashTree(c: var MD5Context, n: PNode) =
   if n == nil:
-    c &= "noTreeKind"
+    c &= "\255"
     return
   var k = n.kind
   md5Update(c, cast[cstring](addr(k)), 1)
@@ -107,7 +107,7 @@ proc hashTree(c: var MD5Context, n: PNode) =
 proc hashType(c: var MD5Context, t: PType) =
   # modelled after 'typeToString'
   if t == nil: 
-    c &= "noTypeKind"
+    c &= "\254"
     return
 
   var k = t.kind
@@ -168,7 +168,7 @@ proc canonConst(n: PNode): TUid =
   c.hashType(n.typ)
   md5Final(c, MD5Digest(result))
 
-proc canonSym(s: PSym): TUid
+proc canonSym(s: PSym): TUid =
   var c: MD5Context
   md5Init(c)
   c.hashSym(s)
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index da1673ca4..1d8f0158b 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -87,9 +87,10 @@ proc getUniqueType*(key: PType): PType =
       gCanonicalTypes[k] = key
       result = key
   of tyTypeDesc, tyTypeClasses, tyGenericParam,
-     tyFromExpr, tyStatic, tyFieldAccessor:
+     tyFromExpr, tyFieldAccessor:
     internalError("GetUniqueType")
-  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
+  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable,
+     tyConst, tyIter, tyStatic:
     result = getUniqueType(lastSon(key))
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
      tyOpenArray, tyArray, tySet, tyRange, tyTuple,
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index 54be0ccb2..db78da714 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -151,7 +151,7 @@ proc getField(n: PNode; position: int): PSym =
   else: discard
 
 proc packObject(x: PNode, typ: PType, res: pointer) =
-  InternalAssert x.kind in {nkObjConstr, nkPar}
+  internalAssert x.kind in {nkObjConstr, nkPar}
   # compute the field's offsets:
   discard typ.getSize
   for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 12761f1d4..a7ee7f7cc 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -16,7 +16,7 @@ import
 type 
   TSystemCC* = enum 
     ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, 
-    ccTcc, ccPcc, ccUcc, ccIcl, ccGpp
+    ccTcc, ccPcc, ccUcc, ccIcl
   TInfoCCProp* = enum         # properties of the C compiler:
     hasSwitchRange,           # CC allows ranges in switch statements (GNU C)
     hasComputedGoto,          # CC has computed goto (GNU C extension)
@@ -33,11 +33,12 @@ type
     optSpeed: string,    # the options for optimization for speed
     optSize: string,     # the options for optimization for size
     compilerExe: string, # the compiler's executable
+    cppCompiler: string, # name of the C++ compiler's executable (if supported)
     compileTmpl: string, # the compile command template
     buildGui: string,    # command to build a GUI application
     buildDll: string,    # command to build a shared library
     buildLib: string,    # command to build a static library
-    linkerExe: string,   # the linker's executable
+    linkerExe: string,   # the linker's executable (if not matching compiler's)
     linkTmpl: string,    # command to link files to produce an exe
     includeCmd: string,  # command to add an include dir
     linkDirCmd: string,  # command to add a lib dir
@@ -63,11 +64,12 @@ compiler gcc:
     optSpeed: " -O3 -ffast-math ",
     optSize: " -Os -ffast-math ",
     compilerExe: "gcc",
+    cppCompiler: "g++",
     compileTmpl: "-c $options $include -o $objfile $file",
     buildGui: " -mwindows",
     buildDll: " -shared",
     buildLib: "ar rcs $libfile $objfiles",
-    linkerExe: "gcc",
+    linkerExe: "",
     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options",
     includeCmd: " -I",
     linkDirCmd: " -L",
@@ -77,32 +79,21 @@ compiler gcc:
     asmStmtFrmt: "asm($1);$n",
     props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
             hasNakedAttribute})
-    
-compiler gpp:
-  result = gcc()
-  
-  result.name = "gpp"
-  result.compilerExe = "g++"
-  result.linkerExe = "g++"  
-
-  result.buildDll = " -mdll" 
-  # XXX: Hmm, I'm keeping this from the previos version, 
-  # but my gcc doesn't even have such an option (is this mingw?)
 
 compiler llvmGcc:
   result = gcc()
   
   result.name = "llvm_gcc"
   result.compilerExe = "llvm-gcc"
+  result.cppCompiler = "llvm-g++"
   result.buildLib = "llvm-ar rcs $libfile $objfiles"
-  result.linkerExe = "llvm-gcc"
 
 compiler clang:
   result = llvmGcc()
 
   result.name = "clang"
   result.compilerExe = "clang"
-  result.linkerExe = "clang"
+  result.cppCompiler = "clang++"
 
 compiler vcc:
   result = (
@@ -111,6 +102,7 @@ compiler vcc:
     optSpeed: " /Ogityb2 /G7 /arch:SSE2 ",
     optSize: " /O1 /G7 ",
     compilerExe: "cl",
+    cppCompiler: "cl",
     compileTmpl: "/c $options $include /Fo$objfile $file",
     buildGui: " /link /SUBSYSTEM:WINDOWS ",
     buildDll: " /LD",
@@ -131,7 +123,7 @@ compiler icl:
     result = vcc()
   else:
     result = gcc()
-
+    
   result.name = "icl"
   result.compilerExe = "icl"
   result.linkerExe = "icl"
@@ -143,6 +135,7 @@ compiler lcc:
     optSpeed: " -O -p6 ",
     optSize: " -O -p6 ",
     compilerExe: "lcc",
+    cppCompiler: "",
     compileTmpl: "$options $include -Fo$objfile $file",
     buildGui: " -subsystem windows",
     buildDll: " -dll",
@@ -164,6 +157,7 @@ compiler bcc:
     optSpeed: " -O2 -6 ",
     optSize: " -O1 -6 ",
     compilerExe: "bcc32",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o$objfile $file",
     buildGui: " -tW",
     buildDll: " -tWD",
@@ -185,6 +179,7 @@ compiler dmc:
     optSpeed: " -ff -o -6 ",
     optSize: " -ff -o -6 ",
     compilerExe: "dmc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o$objfile $file",
     buildGui: " -L/exet:nt/su:windows",
     buildDll: " -WD",
@@ -206,6 +201,7 @@ compiler wcc:
     optSpeed: " -ox -on -6 -d0 -fp6 -zW ",
     optSize: "",
     compilerExe: "wcl386",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -fo=$objfile $file",
     buildGui: " -bw",
     buildDll: " -bd",
@@ -227,6 +223,7 @@ compiler tcc:
     optSpeed: "",
     optSize: "",
     compilerExe: "tcc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o $objfile $file",
     buildGui: "UNAVAILABLE!",
     buildDll: " -shared",
@@ -249,6 +246,7 @@ compiler pcc:
     optSpeed: " -Ox ",
     optSize: " -Os ",
     compilerExe: "cc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -Fo$objfile $file",
     buildGui: " -SUBSYSTEM:WINDOWS",
     buildDll: " -DLL",
@@ -270,6 +268,7 @@ compiler ucc:
     optSpeed: " -O3 ",
     optSize: " -O1 ",
     compilerExe: "cc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o $objfile $file",
     buildGui: "",
     buildDll: " -shared ",
@@ -297,8 +296,7 @@ const
     tcc(),
     pcc(),
     ucc(),
-    icl(),
-    gpp()]
+    icl()]
 
 const
   hExt* = ".h"
@@ -471,11 +469,21 @@ proc needsExeExt(): bool {.inline.} =
   result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
                                        (platform.hostOS == osWindows)
 
+proc getCompilerExe(compiler: TSystemCC): string =
+  result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler
+           else: CC[compiler].compilerExe
+  if result.len == 0:
+    rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name)
+
+proc getLinkerExe(compiler: TSystemCC): string =
+  result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
+           else: compiler.getCompilerExe
+
 proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = 
   var c = cCompiler
   var options = cFileSpecificOptions(cfilename)
   var exe = getConfigVar(c, ".exe")
-  if exe.len == 0: exe = CC[c].compilerExe
+  if exe.len == 0: exe = c.getCompilerExe
   
   if needsExeExt(): exe = addFileExt(exe, "exe")
   if optGenDynLib in gGlobalOptions and
@@ -493,7 +501,7 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
     compilePattern = joinPath(ccompilerpath, exe)
   else: 
     includeCmd = ""
-    compilePattern = CC[c].compilerExe
+    compilePattern = c.getCompilerExe
   
   var cfile = if noAbsolutePaths(): extractFilename(cfilename) 
               else: cfilename
@@ -600,7 +608,7 @@ proc callCCompiler*(projectfile: string) =
       if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
     else:
       var linkerExe = getConfigVar(c, ".linkerexe")
-      if len(linkerExe) == 0: linkerExe = CC[c].linkerExe
+      if len(linkerExe) == 0: linkerExe = c.getLinkerExe
       if needsExeExt(): linkerExe = addFileExt(linkerExe, "exe")
       if noAbsolutePaths(): linkCmd = quoteShell(linkerExe)
       else: linkCmd = quoteShell(joinPath(ccompilerpath, linkerExe))
diff --git a/compiler/guards.nim b/compiler/guards.nim
index fe868054f..f475f5068 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -274,10 +274,6 @@ proc pred(n: PNode): PNode =
   else:
     result = n
 
-type
-  TImplication* = enum
-    impUnknown, impNo, impYes  
-
 proc impliesEq(fact, eq: PNode): TImplication =
   let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1)
   
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 67cd364dc..4bc8eff86 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -518,7 +518,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
       else:
         internalError(it.info, "transformOuter")
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, 
-     nkClosure:
+     nkClosure, nkTypeSection:
     # don't recurse here:
     # XXX recurse here and setup 'up' pointers
     discard
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 4285a090d..217e33675 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -101,6 +101,7 @@ type
     base10,                   # base10 is listed as the first element,
                               # so that it is the correct default value
     base2, base8, base16
+
   TToken* = object            # a Nimrod token
     tokType*: TTokType        # the type of the token
     indent*: int              # the indentation; != -1 if the token has been
@@ -110,6 +111,8 @@ type
     fNumber*: BiggestFloat    # the parsed floating point literal
     base*: TNumericalBase     # the numerical base; only valid for int
                               # or float literals
+    strongSpaceA*: int8       # leading spaces of an operator
+    strongSpaceB*: int8       # trailing spaces of an operator
     literal*: string          # the parsed (string) literal; and
                               # documentation comments are here too
     line*, col*: int
@@ -119,7 +122,9 @@ type
     indentAhead*: int         # if > 0 an indendation has already been read
                               # this is needed because scanning comments
                               # needs so much look-ahead
-  
+    currLineIndent*: int
+    strongSpaces*: bool
+
 
 var gLinesCompiled*: int  # all lines that have been compiled
 
@@ -184,6 +189,7 @@ proc initToken*(L: var TToken) =
   L.tokType = tkInvalid
   L.iNumber = 0
   L.indent = 0
+  L.strongSpaceA = 0
   L.literal = ""
   L.fNumber = 0.0
   L.base = base10
@@ -193,6 +199,7 @@ proc fillToken(L: var TToken) =
   L.tokType = tkInvalid
   L.iNumber = 0
   L.indent = 0
+  L.strongSpaceA = 0
   setLen(L.literal, 0)
   L.fNumber = 0.0
   L.base = base10
@@ -202,6 +209,7 @@ proc openLexer(lex: var TLexer, fileIdx: int32, inputstream: PLLStream) =
   openBaseLexer(lex, inputstream)
   lex.fileIdx = fileidx
   lex.indentAhead = - 1
+  lex.currLineIndent = 0
   inc(lex.lineNumber, inputstream.lineOffset) 
 
 proc closeLexer(lex: var TLexer) = 
@@ -635,6 +643,14 @@ proc getOperator(L: var TLexer, tok: var TToken) =
     h = h !& ord(c)
     inc(pos)
   endOperator(L, tok, pos, h)
+  # advance pos but don't store it in L.bufpos so the next token (which might
+  # be an operator too) gets the preceeding spaces:
+  tok.strongSpaceB = 0
+  while buf[pos] == ' ':
+    inc pos
+    inc tok.strongSpaceB
+  if buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
+    tok.strongSpaceB = -1
 
 proc scanComment(L: var TLexer, tok: var TToken) = 
   var pos = L.bufpos
@@ -678,10 +694,12 @@ proc scanComment(L: var TLexer, tok: var TToken) =
 proc skip(L: var TLexer, tok: var TToken) =
   var pos = L.bufpos
   var buf = L.buf
+  tok.strongSpaceA = 0
   while true:
     case buf[pos]
     of ' ':
       inc(pos)
+      inc(tok.strongSpaceA)
     of Tabulator:
       lexMessagePos(L, errTabulatorsAreNotAllowed, pos)
       inc(pos)
@@ -692,8 +710,10 @@ proc skip(L: var TLexer, tok: var TToken) =
       while buf[pos] == ' ':
         inc(pos)
         inc(indent)
+      tok.strongSpaceA = 0
       if buf[pos] > ' ':
         tok.indent = indent
+        L.currLineIndent = indent
         break
     else:
       break                   # EndOfFile also leaves the loop
@@ -703,6 +723,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
   fillToken(tok)
   if L.indentAhead >= 0:
     tok.indent = L.indentAhead
+    L.currLineIndent = L.indentAhead
     L.indentAhead = -1
   else:
     tok.indent = -1
@@ -812,5 +833,5 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
         tok.tokType = tkInvalid
         lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
         inc(L.bufpos)
-  
+
 dummyIdent = getIdent("")
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 8239f2a47..60125177c 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -127,7 +127,10 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
     elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options: 
       # BUGFIX: check options in s!
       if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
-        message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
+        # XXX: implicit type params are currently skTypes
+        # maybe they can be made skGenericParam as well.
+        if s.typ != nil and tfImplicitTypeParam notin s.typ.flags:
+          message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
     s = nextIter(it, scope.symbols)
   
 proc wrongRedefinition*(info: TLineInfo, s: string) =
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 66763e7f5..cdafc997b 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -96,8 +96,8 @@ type
     errOnlyACallOpCanBeDelegator, errUsingNoSymbol,
     errMacroBodyDependsOnGenericTypes,
     errDestructorNotGenericEnough,
-    
-    errXExpectsTwoArguments, 
+    errInlineIteratorsAsProcParams,
+    errXExpectsTwoArguments,
     errXExpectsObjectTypes, errXcanNeverBeOfThisSubtype, errTooManyIterations, 
     errCannotInterpretNodeX, errFieldXNotFound, errInvalidConversionFromTypeX, 
     errAssertionFailed, errCannotGenerateCodeForX, errXRequiresOneArgument, 
@@ -106,6 +106,9 @@ type
     errThreadvarCannotInit, errWrongSymbolX, errIllegalCaptureX,
     errXCannotBeClosure, errXMustBeCompileTime,
     errCannotInferTypeOfTheLiteral,
+    errCannotInferReturnType,
+    errGenericLambdaNotAllowed,
+    errCompilerDoesntSupportTarget,
     errUser,
     warnCannotOpenFile, 
     warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit, 
@@ -331,6 +334,8 @@ const
                                        "because the parameter '$1' has a generic type",
     errDestructorNotGenericEnough: "Destructor signarue is too specific. " &
                                    "A destructor must be associated will all instantiations of a generic type",
+    errInlineIteratorsAsProcParams: "inline iterators can be used as parameters only for " &
+                                    "templates, macros and other inline iterators",
     errXExpectsTwoArguments: "\'$1\' expects two arguments", 
     errXExpectsObjectTypes: "\'$1\' expects object types",
     errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", 
@@ -353,6 +358,11 @@ const
     errXCannotBeClosure: "'$1' cannot have 'closure' calling convention",
     errXMustBeCompileTime: "'$1' can only be used in compile-time context",
     errCannotInferTypeOfTheLiteral: "cannot infer the type of the $1",
+    errCannotInferReturnType: "cannot infer the return type of the proc",
+    errGenericLambdaNotAllowed: "A nested proc can have generic parameters only when " &
+                                "it is used as an operand to another routine and the types " &
+                                "of the generic paramers can be infered from the expected signature.",
+    errCompilerDoesntSupportTarget: "The current compiler \'$1\' doesn't support the requested compilation target",
     errUser: "$1", 
     warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]",
     warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]", 
@@ -717,19 +727,19 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
       writeStackTrace()
     quit 1
 
-  if msg >= fatalMin and msg <= fatalMax: 
+  if msg >= fatalMin and msg <= fatalMax:
     quit()
-  if msg >= errMin and msg <= errMax: 
+  if msg >= errMin and msg <= errMax:
     inc(gErrorCounter)
     options.gExitcode = 1'i8
-    if gErrorCounter >= gErrorMax: 
+    if gErrorCounter >= gErrorMax:
       quit()
     elif eh == doAbort and gCmd != cmdIdeTools:
       quit()
     elif eh == doRaise:
       raiseRecoverableError(s)
 
-proc `==`*(a, b: TLineInfo): bool = 
+proc `==`*(a, b: TLineInfo): bool =
   result = a.line == b.line and a.fileIndex == b.fileIndex
 
 proc writeContext(lastinfo: TLineInfo) = 
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 5a5bfb574..060629518 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -38,7 +38,6 @@ type
     inSemiStmtList: int
 
 proc parseAll*(p: var TParser): PNode
-proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
 proc closeParser*(p: var TParser)
 proc parseTopLevelStmt*(p: var TParser): PNode
   # implements an iterator. Returns the next top-level statement or
@@ -50,7 +49,6 @@ proc parseString*(s: string, filename: string = "", line: int = 0): PNode
   # correct error messages referring to the original source.
   
 # helpers for the other parsers
-proc getPrecedence*(tok: TToken): int
 proc isOperator*(tok: TToken): bool
 proc getTok*(p: var TParser)
 proc parMessage*(p: TParser, msg: TMsgKind, arg: string = "")
@@ -77,14 +75,17 @@ proc parseCase(p: var TParser): PNode
 proc getTok(p: var TParser) = 
   rawGetTok(p.lex, p.tok)
 
-proc openParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream) =
+proc openParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream,
+                 strongSpaces=false) =
   initToken(p.tok)
   openLexer(p.lex, fileIdx, inputStream)
   getTok(p)                   # read the first token
   p.firstTok = true
+  p.strongSpaces = strongSpaces
 
-proc openParser*(p: var TParser, filename: string, inputStream: PLLStream) =
-  openParser(p, filename.fileInfoIdx, inputstream)
+proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
+                 strongSpaces=false) =
+  openParser(p, filename.fileInfoIdx, inputstream, strongSpaces)
 
 proc closeParser(p: var TParser) = 
   closeLexer(p.lex)
@@ -193,34 +194,52 @@ proc isSigilLike(tok: TToken): bool {.inline.} =
 proc isLeftAssociative(tok: TToken): bool {.inline.} =
   result = tok.tokType != tkOpr or relevantOprChar(tok.ident) != '^'
 
-proc getPrecedence(tok: TToken): int = 
+proc getPrecedence(tok: TToken, strongSpaces: bool): int =
+  template considerStrongSpaces(x): expr =
+    x + (if strongSpaces: 100 - tok.strongSpaceA.int*10 else: 0)
+
   case tok.tokType
   of tkOpr:
     let L = tok.ident.s.len
     let relevantChar = relevantOprChar(tok.ident)
     
-    template considerAsgn(value: expr) = 
-      result = if tok.ident.s[L-1] == '=': 1 else: value     
+    template considerAsgn(value: expr) =
+      result = if tok.ident.s[L-1] == '=': 1 else: considerStrongSpaces(value)
     
     case relevantChar
     of '$', '^': considerAsgn(10)
     of '*', '%', '/', '\\': considerAsgn(9)
-    of '~': result = 8
+    of '~': result = considerStrongSpaces(8)
     of '+', '-', '|': considerAsgn(8)
     of '&': considerAsgn(7)
-    of '=', '<', '>', '!': result = 5
+    of '=', '<', '>', '!': result = considerStrongSpaces(5)
     of '.': considerAsgn(6)
-    of '?': result = 2
+    of '?': result = considerStrongSpaces(2)
     else: considerAsgn(2)
   of tkDiv, tkMod, tkShl, tkShr: result = 9
   of tkIn, tkNotin, tkIs, tkIsnot, tkNot, tkOf, tkAs: result = 5
-  of tkDotDot: result = 6
+  of tkDotDot: result = considerStrongSpaces(6)
   of tkAnd: result = 4
   of tkOr, tkXor: result = 3
-  else: result = - 10
-  
-proc isOperator(tok: TToken): bool = 
-  result = getPrecedence(tok) >= 0
+  else: result = -10
+
+proc isOperator(tok: TToken): bool =
+  tok.tokType in {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
+                  tkIsnot, tkNot, tkOf, tkAs, tkDotDot, tkAnd, tkOr, tkXor}
+
+proc isUnary(p: TParser): bool =
+  p.strongSpaces and p.tok.tokType in {tkOpr, tkDotDot} and
+    p.tok.strongSpaceB == 0 and
+    p.tok.strongSpaceA > 0
+
+proc checkBinary(p: TParser) {.inline.} =
+  # we don't check '..' here as that's too annoying
+  if p.strongSpaces and p.tok.tokType == tkOpr:
+    if p.tok.strongSpaceB > 0 and p.tok.strongSpaceA != p.tok.strongSpaceB:
+      parMessage(p, errGenerated, "number of spaces around '$#' not consistent"%
+        prettyTok(p.tok))
+    elif p.tok.strongSpaceA notin {0,1,2,4,8}:
+      parMessage(p, errGenerated, "number of spaces must be 0,1,2,4 or 8")
 
 #| module = stmt ^* (';' / IND{=})
 #|
@@ -639,7 +658,7 @@ proc namedParams(p: var TParser, callee: PNode,
   exprColonEqExprListAux(p, endTok, result)
 
 proc parseMacroColon(p: var TParser, x: PNode): PNode
-proc primarySuffix(p: var TParser, r: PNode): PNode =
+proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
   #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
   #|               | doBlocks
   #|               | '.' optInd ('type' | 'addr' | symbol) generalizedLit?
@@ -647,9 +666,11 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
   #|               | '{' optInd indexExprList optPar '}'
   #|               | &( '`'|IDENT|literal|'cast') expr # command syntax
   result = r
-  while p.tok.indent < 0:
+  while p.tok.indent < 0 or
+       (p.tok.tokType == tkDot and p.tok.indent >= baseIndent):
     case p.tok.tokType
     of tkParLe:
+      if p.strongSpaces and p.tok.strongSpaceA > 0: break
       result = namedParams(p, result, nkCall, tkParRi)
       if result.len > 1 and result.sons[1].kind == nkExprColonExpr:
         result.kind = nkObjConstr
@@ -664,8 +685,10 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
       result = dotExpr(p, result)
       result = parseGStrLit(p, result)
     of tkBracketLe:
+      if p.strongSpaces and p.tok.strongSpaceA > 0: break
       result = namedParams(p, result, nkBracketExpr, tkBracketRi)
     of tkCurlyLe:
+      if p.strongSpaces and p.tok.strongSpaceA > 0: break
       result = namedParams(p, result, nkCurlyExpr, tkCurlyRi)
     of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast:
       if p.inPragma == 0:
@@ -691,14 +714,17 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
       break
     
 proc primary(p: var TParser, mode: TPrimaryMode): PNode
+proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode
 
-proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
-  result = primary(p, mode)
+proc parseOperators(p: var TParser, headNode: PNode,
+                    limit: int, mode: TPrimaryMode): PNode =
+  result = headNode
   # expand while operators have priorities higher than 'limit'
-  var opPrec = getPrecedence(p.tok)
+  var opPrec = getPrecedence(p.tok, p.strongSpaces)
   let modeB = if mode == pmTypeDef: pmTypeDesc else: mode
   # the operator itself must not start on a new line:
-  while opPrec >= limit and p.tok.indent < 0:
+  while opPrec >= limit and p.tok.indent < 0 and not isUnary(p):
+    checkBinary(p)
     var leftAssoc = ord(isLeftAssociative(p.tok))
     var a = newNodeP(nkInfix, p)
     var opNode = newIdentNodeP(p.tok.ident, p) # skip operator:
@@ -710,7 +736,11 @@ proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
     addSon(a, result)
     addSon(a, b)
     result = a
-    opPrec = getPrecedence(p.tok)
+    opPrec = getPrecedence(p.tok, p.strongSpaces)
+
+proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
+  result = primary(p, mode)
+  result = parseOperators(p, result, limit, mode)
   
 proc simpleExpr(p: var TParser, mode = pmNormal): PNode =
   result = simpleExprAux(p, -1, mode)
@@ -978,8 +1008,9 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
     optInd(p, a)
     if isSigil: 
       #XXX prefix operators
+      let baseInd = p.lex.currLineIndent
       addSon(result, primary(p, pmSkipSuffix))
-      result = primarySuffix(p, result)
+      result = primarySuffix(p, result, baseInd)
     else:
       addSon(result, primary(p, pmNormal))
     return
@@ -1042,9 +1073,10 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
     optInd(p, result)
     addSon(result, primary(p, pmNormal))
   else:
+    let baseInd = p.lex.currLineIndent
     result = identOrLiteral(p, mode)
     if mode != pmSkipSuffix:
-      result = primarySuffix(p, result)
+      result = primarySuffix(p, result, baseInd)
 
 proc parseTypeDesc(p: var TParser): PNode =
   #| typeDesc = simpleExpr
@@ -1478,7 +1510,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
                   defparser: TDefParser): PNode =
   #| section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
   result = newNodeP(kind, p)
-  getTok(p)
+  if kind != nkTypeSection: getTok(p)
   skipComment(p, result)
   if realInd(p):
     withInd(p):
@@ -1839,7 +1871,16 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
   of tkMacro: result = parseRoutine(p, nkMacroDef)
   of tkTemplate: result = parseRoutine(p, nkTemplateDef)
   of tkConverter: result = parseRoutine(p, nkConverterDef)
-  of tkType: result = parseSection(p, nkTypeSection, parseTypeDef)
+  of tkType:
+    getTok(p)
+    if p.tok.tokType == tkParLe:
+      getTok(p)
+      result = newNodeP(nkTypeOfExpr, p)
+      result.addSon(primary(p, pmTypeDesc))
+      eat(p, tkParRi)
+      result = parseOperators(p, result, -1, pmNormal)
+    else:
+      result = parseSection(p, nkTypeSection, parseTypeDef)
   of tkConst: result = parseSection(p, nkConstSection, parseConstant)
   of tkLet: result = parseSection(p, nkLetSection, parseVariable)
   of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
@@ -1863,7 +1904,7 @@ proc parseStmt(p: var TParser): PNode =
           if p.tok.indent < 0 or p.tok.indent == p.currInd: discard
           else: break
         else:
-          if p.tok.indent > p.currInd:
+          if p.tok.indent > p.currInd and p.tok.tokType != tkDot:
             parMessage(p, errInvalidIndentation)
           break
         if p.tok.tokType in {tkCurlyRi, tkParRi, tkCurlyDotRi, tkBracketRi}:
@@ -1890,7 +1931,8 @@ proc parseStmt(p: var TParser): PNode =
       else:
         result = newNodeP(nkStmtList, p)
         while true:
-          if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)     
+          if p.tok.indent >= 0:
+            parMessage(p, errInvalidIndentation)
           let a = simpleStmt(p)
           if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
           result.add(a)
@@ -1933,7 +1975,9 @@ proc parseString(s: string, filename: string = "", line: int = 0): PNode =
   stream.lineOffset = line
 
   var parser: TParser
-  openParser(parser, filename, stream)
+  # XXX for now the builtin 'parseStmt/Expr' functions do not know about strong
+  # spaces...
+  openParser(parser, filename, stream, false)
 
   result = parser.parseAll
   closeParser(parser)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 076e99924..fba4e7657 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -97,8 +97,6 @@ proc makeExternImport(s: PSym, extname: string) =
   incl(s.flags, sfImportc)
   excl(s.flags, sfForward)
 
-const invalidIdentChars = AllChars - IdentChars
-
 proc validateExternCName(s: PSym, info: TLineInfo) =
   ## Validates that the symbol name in s.loc.r is a valid C identifier.
   ##
@@ -106,16 +104,14 @@ proc validateExternCName(s: PSym, info: TLineInfo) =
   ## starting with a number. If the check fails, a generic error will be
   ## displayed to the user.
   let target = ropeToStr(s.loc.r)
-  if target.len < 1 or (not (target[0] in IdentStartChars)) or
-      (not target.allCharsInSet(IdentChars)):
+  if target.len < 1 or target[0] notin IdentStartChars or
+      not target.allCharsInSet(IdentChars):
     localError(info, errGenerated, "invalid exported symbol")
 
 proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
   setExternName(s, extname)
-  case gCmd
-  of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC:
+  if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC}:
     validateExternCName(s, info)
-  else: discard
   incl(s.flags, sfExportc)
 
 proc processImportCompilerProc(s: PSym, extname: string) =
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 5ee46654e..093fc9452 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -139,6 +139,10 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
     result = n.sym
     internalAssert sfGenSym in result.flags
     internalAssert result.kind == kind
+    # when there is a nested proc inside a template, semtmpl
+    # will assign a wrong owner during the first pass over the
+    # template; we must fix it here: see #909
+    result.owner = getCurrOwner()
   else:
     result = newSym(kind, considerAcc(n), getCurrOwner(), n.info)
 
@@ -194,7 +198,8 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
       result = semExprWithType(c, evaluated)
     else:
       result = evaluated
-      semmacrosanity.annotateType(result, eOrig.typ)
+      let expectedType = eOrig.typ.skipTypes({tyStatic})
+      semmacrosanity.annotateType(result, expectedType)
   else:
     result = semExprWithType(c, evaluated)
     #result = fitNode(c, e.typ, result) inlined with special case:
@@ -214,14 +219,26 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
   result = getConstExpr(c.module, e)
   if result != nil: return
 
+  let oldErrorCount = msgs.gErrorCounter
+  let oldErrorMax = msgs.gErrorMax
+  let oldErrorOutputs = errorOutputs
+
+  errorOutputs = {}
+  msgs.gErrorMax = high(int)
+
   try:
     result = evalConstExpr(c.module, e)
     if result == nil or result.kind == nkEmpty:
-      return nil
+      result = nil
+    else:
+      result = fixupTypeAfterEval(c, result, e)
 
-    result = fixupTypeAfterEval(c, result, e)
   except ERecoverableError:
-    return nil
+    result = nil
+
+  msgs.gErrorCounter = oldErrorCount
+  msgs.gErrorMax = oldErrorMax
+  errorOutputs = oldErrorOutputs
 
 proc semConstExpr(c: PContext, n: PNode): PNode =
   var e = semExprWithType(c, n)
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 2e5def75a..5d480bc98 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -82,7 +82,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) =
     # fail fast:
     globalError(n.info, errTypeMismatch, "")
   var result = msgKindToString(errTypeMismatch)
-  add(result, describeArgs(c, n, 1 + ord(nfDotField in n.flags)))
+  add(result, describeArgs(c, n, 1))
   add(result, ')')
   
   var candidates = ""
@@ -114,7 +114,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
 
   var errors: seq[string]
   var usedSyms: seq[PNode]
- 
+
   template pickBest(headSymbol: expr) =
     pickBestCandidate(c, headSymbol, n, orig, initialBinding,
                       filter, result, alt, errors)
@@ -166,7 +166,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
       n.sons[0..1] = [callOp, n[1], calleeName]
       orig.sons[0..1] = [callOp, orig[1], calleeName]
       pickBest(callOp)
-    
+   
     if overloadsState == csEmpty and result.state == csEmpty:
       localError(n.info, errUndeclaredIdentifier, considerAcc(f).s)
       return
@@ -175,9 +175,15 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
         localError(n.info, errExprXCannotBeCalled,
                    renderTree(n, {renderNoComments}))
       else:
+        if {nfDotField, nfDotSetter} * n.flags != {}:
+          # clean up the inserted ops
+          n.sons.delete(2)
+          n.sons[0] = f
+
         errors = @[]
         pickBest(f)
         notFoundError(c, n, errors)
+
       return
 
   if alt.state == csMatch and cmpCandidates(result, alt) == 0 and
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index d942aa41e..088b93fae 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -42,7 +42,7 @@ type
 
   TExprFlag* = enum 
     efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType,
-    efAllowDestructor, efWantValue
+    efAllowDestructor, efWantValue, efOperand
   TExprFlags* = set[TExprFlag]
 
   PContext* = ref TContext
@@ -236,17 +236,20 @@ proc makeAndType*(c: PContext, t1, t2: PType): PType =
   result.sons = @[t1, t2]
   propagateToOwner(result, t1)
   propagateToOwner(result, t2)
+  result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
 
 proc makeOrType*(c: PContext, t1, t2: PType): PType =
   result = newTypeS(tyOr, c)
   result.sons = @[t1, t2]
   propagateToOwner(result, t1)
   propagateToOwner(result, t2)
+  result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
 
 proc makeNotType*(c: PContext, t1: PType): PType =
   result = newTypeS(tyNot, c)
   result.sons = @[t1]
   propagateToOwner(result, t1)
+  result.flags.incl(t1.flags * {tfHasStatic})
 
 proc newTypeS(kind: TTypeKind, c: PContext): PType =
   result = newType(kind, getCurrOwner())
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 203a51816..7e141cb24 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -21,7 +21,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 
 proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   # same as 'semExprWithType' but doesn't check for proc vars
-  result = semExpr(c, n, flags)
+  result = semExpr(c, n, flags + {efOperand})
   if result.kind == nkEmpty: 
     # do not produce another redundant error message:
     #raiseRecoverableError("")
@@ -117,8 +117,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     elif s.ast != nil:
       result = semExpr(c, s.ast)
     else:
-      internalError(n.info, "no default for")
-      result = emptyNode
+      n.typ = s.typ
+      return n
   of skType:
     markUsed(n, s)
     result = newSymNode(s, n.info)
@@ -325,8 +325,13 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
                                         tfIterator notin t.flags))
   else:
     var t2 = n[2].typ.skipTypes({tyTypeDesc})
+    # XXX: liftParamType started to perform addDecl
+    # we could do that instead in semTypeNode by snooping for added
+    # gnrc. params, then it won't be necessary to open a new scope here
+    openScope(c)
     let lifted = liftParamType(c, skType, newNodeI(nkArgList, n.info),
                                t2, ":anon", n.info)
+    closeScope(c)
     if lifted != nil: t2 = lifted
     var m: TCandidate
     initCandidate(c, m, t2)
@@ -612,7 +617,19 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
       if result.isNil: result = n
       else: return result
     result.typ = semfold.getIntervalType(callee.magic, call)
-    
+  
+  block maybeLabelAsStatic:
+    # XXX: temporary work-around needed for tlateboundstatic.
+    # This is certainly not correct, but it will get the job
+    # done until we have a more robust infrastructure for
+    # implicit statics.
+    if n.len > 1:
+      for i in 1 .. <n.len:
+        if n[i].typ.kind != tyStatic or tfUnresolved notin n[i].typ.flags:
+          break maybeLabelAsStatic
+      n.typ = newTypeWithSons(c, tyStatic, @[n.typ])
+      n.typ.flags.incl tfUnresolved
+
   # optimization pass: not necessary for correctness of the semantic pass
   if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
      {sfForward, sfImportc} * callee.flags == {}:
@@ -885,7 +902,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
   of nkSym: 
     if r.sym.name.id == field.id: result = r.sym
   else: illFormedAst(n)
-  
+
 proc makeDeref(n: PNode): PNode = 
   var t = skipTypes(n.typ, {tyGenericInst})
   result = n
@@ -899,6 +916,24 @@ proc makeDeref(n: PNode): PNode =
     addSon(result, a)
     t = skipTypes(t.sons[0], {tyGenericInst})
 
+const tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass}
+
+proc readTypeParameter(c: PContext, typ: PType,
+                       paramName: PIdent, info: TLineInfo): PNode =
+  let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
+           else: (internalAssert typ.kind == tyCompositeTypeClass; typ.sons[1])
+  
+  let tbody = ty.sons[0]
+  for s in countup(0, tbody.len-2):
+    let tParam = tbody.sons[s]
+    if tParam.sym.name == paramName:
+      let rawTyp = ty.sons[s + 1]
+      if rawTyp.kind == tyStatic:
+        return rawTyp.n
+      else:
+        let foundTyp = makeTypeDesc(c, rawTyp)
+        return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
+
 proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if it's not a built-in field access
   checkSonsLen(n, 2)
@@ -916,7 +951,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   var ty = n.sons[0].typ
   var f: PSym = nil
   result = nil
-  if isTypeExpr(n.sons[0]) or ty.kind == tyTypeDesc and ty.base.kind != tyNone:
+  if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
     if ty.kind == tyTypeDesc: ty = ty.base
     case ty.kind
     of tyEnum:
@@ -925,28 +960,17 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
         f = getSymFromList(ty.n, i)
         if f != nil: break 
         ty = ty.sons[0]         # enum inheritance
-      if f != nil: 
+      if f != nil:
         result = newSymNode(f)
         result.info = n.info
         result.typ = ty
         markUsed(n, f)
         return
-    of tyGenericInst:
-      assert ty.sons[0].kind == tyGenericBody
-      let tbody = ty.sons[0]
-      for s in countup(0, tbody.len-2):
-        let tParam = tbody.sons[s]
-        if tParam.sym.name == i:
-          let rawTyp = ty.sons[s + 1]
-          if rawTyp.kind == tyStatic:
-            return rawTyp.n
-          else:
-            let foundTyp = makeTypeDesc(c, rawTyp)
-            return newSymNode(copySym(tParam.sym).linkTo(foundTyp), n.info)
-      return
+    of tyTypeParamsHolders:
+      return readTypeParameter(c, ty, i, n.info)
     of tyObject, tyTuple:
       if ty.n.kind == nkRecList:
-        for field in ty.n.sons:
+        for field in ty.n:
           if field.sym.name == i:
             n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])
             n.typ.n = copyTree(n)
@@ -958,6 +982,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
     # XXX: This is probably not relevant any more
     # reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
     ty = n.sons[0].typ
+    return nil
     
   ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
   var check: PNode = nil
@@ -990,6 +1015,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
       n.typ = f.typ
       result = n
 
+  # we didn't find any field, let's look for a generic param
+  if result == nil and n.sons[0].typ.kind in tyTypeParamsHolders:
+    result = readTypeParameter(c, n.sons[0].typ, i, n.info)
+
 proc dotTransformation(c: PContext, n: PNode): PNode =
   if isSymChoice(n.sons[1]):
     result = newNodeI(nkDotCall, n.info)
@@ -1119,6 +1148,9 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
       n.sons[0] = x # 'result[]' --> 'result'
       n.sons[1] = takeImplicitAddr(c, ri)
 
+template resultTypeIsInferrable(typ: PType): expr =
+  typ.isMetaType and typ.kind != tyTypeDesc
+
 proc semAsgn(c: PContext, n: PNode): PNode =
   checkSonsLen(n, 2)
   var a = n.sons[0]
@@ -1170,7 +1202,7 @@ proc semAsgn(c: PContext, n: PNode): PNode =
         if lhsIsResult: {efAllowDestructor} else: {})
     if lhsIsResult:
       n.typ = enforceVoidContext
-      if lhs.sym.typ.isMetaType and lhs.sym.typ.kind != tyTypeDesc:
+      if resultTypeIsInferrable(lhs.sym.typ):
         if cmpTypes(c, lhs.typ, rhs.typ) == isGeneric:
           internalAssert c.p.resultSym != nil
           lhs.typ = rhs.typ
@@ -1206,6 +1238,7 @@ proc semReturn(c: PContext, n: PNode): PNode =
 
 proc semProcBody(c: PContext, n: PNode): PNode =
   openScope(c)
+  
   result = semExpr(c, n)
   if c.p.resultSym != nil and not isEmptyType(result.typ):
     # transform ``expr`` to ``result = expr``, but not if the expr is already
@@ -1229,6 +1262,11 @@ proc semProcBody(c: PContext, n: PNode): PNode =
       result = semAsgn(c, a)
   else:
     discardCheck(c, result)
+  
+  if c.p.owner.kind notin {skMacro, skTemplate} and
+     c.p.resultSym != nil and c.p.resultSym.typ.isMetaType:
+    localError(c.p.resultSym.info, errCannotInferReturnType)
+
   closeScope(c)
 
 proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
@@ -1259,12 +1297,21 @@ proc semYield(c: PContext, n: PNode): PNode =
     localError(n.info, errYieldNotAllowedInTryStmt)
   elif n.sons[0].kind != nkEmpty:
     n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility:
-    var restype = c.p.owner.typ.sons[0]
+    var iterType = c.p.owner.typ
+    var restype = iterType.sons[0]
     if restype != nil:
       let adjustedRes = if c.p.owner.kind == skIterator: restype.base
                         else: restype
       n.sons[0] = fitNode(c, adjustedRes, n.sons[0])
       if n.sons[0].typ == nil: internalError(n.info, "semYield")
+      
+      if resultTypeIsInferrable(adjustedRes):
+        let inferred = n.sons[0].typ
+        if c.p.owner.kind == skIterator:
+          iterType.sons[0].sons[0] = inferred
+        else:
+          iterType.sons[0] = inferred
+      
       semYieldVarResult(c, n, adjustedRes)
     else:
       localError(n.info, errCannotReturnExpr)
@@ -1346,7 +1393,7 @@ proc expectString(c: PContext, n: PNode): string =
     localError(n.info, errStringLiteralExpected)
 
 proc getMagicSym(magic: TMagic): PSym =
-  result = newSym(skProc, getIdent($magic), getCurrOwner(), gCodegenLineInfo)
+  result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo)
   result.magic = magic
 
 proc newAnonSym(kind: TSymKind, info: TLineInfo,
@@ -1939,7 +1986,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkBracketExpr:
     checkMinSonsLen(n, 1)
     var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
-    if s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators:
+    if (s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators) or
+        n[0].kind in nkSymChoices:
       # type parameters: partial generic specialization
       n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
       result = explicitGenericInstantiation(c, n, s)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 8faf1d21a..a5149a842 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -15,12 +15,11 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
   if n.kind != nkGenericParams: 
     internalError(n.info, "instantiateGenericParamList; no generic params")
   newSeq(entry.concreteTypes, n.len)
-  for i in countup(0, n.len - 1):
-    var a = n.sons[i]
+  for i, a in n.pairs:
     if a.kind != nkSym: 
       internalError(a.info, "instantiateGenericParamList; no symbol")
     var q = a.sym
-    if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses:
+    if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
       continue
     var s = newSym(skType, q.name, getCurrOwner(), q.info)
     s.flags = s.flags + {sfUsed, sfFromGeneric}
@@ -86,19 +85,21 @@ proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
 
 proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind)
 
+proc addProcDecls(c: PContext, fn: PSym) =
+  # get the proc itself in scope (e.g. for recursion)
+  addDecl(c, fn)
+
+  for i in 1 .. <fn.typ.n.len:
+    var param = fn.typ.n.sons[i].sym
+    param.owner = fn
+    addParamOrResult(c, param, fn.kind)
+  
+  maybeAddResult(c, fn, fn.ast)
+
 proc instantiateBody(c: PContext, n: PNode, result: PSym) =
   if n.sons[bodyPos].kind != nkEmpty:
     inc c.inGenericInst
     # add it here, so that recursive generic procs are possible:
-    addDecl(c, result)
-    pushProcCon(c, result)
-    # add params to scope
-    for i in 1 .. <result.typ.n.len:
-      var param = result.typ.n.sons[i].sym
-      param.owner = result
-      addParamOrResult(c, param, result.kind)
-    # debug result.typ.n
-    maybeAddResult(c, result, n)
     var b = n.sons[bodyPos]
     var symMap: TIdTable
     initIdTable symMap
@@ -108,7 +109,6 @@ proc instantiateBody(c: PContext, n: PNode, result: PSym) =
     n.sons[bodyPos] = transformBody(c.module, b, result)
     #echo "code instantiated ", result.name.s
     excl(result.flags, sfForward)
-    popProcCon(c)
     dec c.inGenericInst
 
 proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
@@ -145,11 +145,56 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
   result = instGenericContainer(c, n.info, header)
 
+proc instantiateProcType(c: PContext, pt: TIdTable,
+                          prc: PSym, info: TLineInfo) =
+  # XXX: Instantiates a generic proc signature, while at the same
+  # time adding the instantiated proc params into the current scope.
+  # This is necessary, because the instantiation process may refer to
+  # these params in situations like this:
+  # proc foo[Container](a: Container, b: a.type.Item): type(b.x)
+  #
+  # Alas, doing this here is probably not enough, because another
+  # proc signature could appear in the params:
+  # proc foo[T](a: proc (x: T, b: type(x.y))
+  #   
+  # The solution would be to move this logic into semtypinst, but
+  # at this point semtypinst have to become part of sem, because it
+  # will need to use openScope, addDecl, etc
+  #
+  addDecl(c, prc)
+  
+  pushInfoContext(info)
+  var cl = initTypeVars(c, pt, info)
+  var result = instCopyType(cl, prc.typ)
+  let originalParams = result.n
+  result.n = originalParams.shallowCopy
+  
+  for i in 1 .. <result.len:
+    result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
+    propagateToOwner(result, result.sons[i])
+    let param = replaceTypeVarsN(cl, originalParams[i])
+    result.n.sons[i] = param
+    if param.kind == nkSym:
+      # XXX: this won't be true for void params
+      # implement pass-through of void params and
+      # the "sort by distance to point" container
+      param.sym.owner = prc
+      addDecl(c, param.sym)
+    
+  result.sons[0] = replaceTypeVarsT(cl, result.sons[0])
+  result.n.sons[0] = originalParams[0].copyTree
+  
+  eraseVoidParams(result)
+  skipIntLiteralParams(result)
+ 
+  prc.typ = result
+  maybeAddResult(c, prc, prc.ast)
+  popInfoContext()
+
 proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
                       info: TLineInfo): PSym =
   # no need to instantiate generic templates/macros:
   if fn.kind in {skTemplate, skMacro}: return fn
- 
   # generates an instantiated proc
   if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
   inc(c.instCounter)
@@ -173,7 +218,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   var entry = TInstantiation.new
   entry.sym = result
   instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
-  result.typ = generateTypeInstance(c, pt, info, fn.typ)
+  pushProcCon(c, result)
+  instantiateProcType(c, pt, result, info)
   n.sons[genericParamsPos] = ast.emptyNode
   var oldPrc = genericCacheGet(fn, entry[])
   if oldPrc == nil:
@@ -183,12 +229,12 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
       pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
     if isNil(n.sons[bodyPos]):
       n.sons[bodyPos] = copyTree(fn.getBody)
-    if fn.kind != skTemplate:
-      instantiateBody(c, n, result)
-      sideEffectsCheck(c, result)
+    instantiateBody(c, n, result)
+    sideEffectsCheck(c, result)
     paramsTypeCheck(c, result.typ)
   else:
     result = oldPrc
+  popProcCon(c)
   popInfoContext()
   closeScope(c)           # close scope for parameters
   popOwner()
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index a11386966..15bfaab10 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -661,10 +661,18 @@ proc semFor(c: PContext, n: PNode): PNode =
   openScope(c)
   n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator})
   var call = n.sons[length-2]
-  if call.kind in nkCallKinds and call.sons[0].typ.callConv == ccClosure:
+  let isCallExpr = call.kind in nkCallKinds
+  if isCallExpr and call.sons[0].sym.magic != mNone:
+    if call.sons[0].sym.magic == mOmpParFor:
+      result = semForVars(c, n)
+      result.kind = nkParForStmt
+    else:
+      result = semForFields(c, n, call.sons[0].sym.magic)
+  elif (isCallExpr and call.sons[0].typ.callConv == ccClosure) or
+      call.typ.kind == tyIter:
     # first class iterator:
     result = semForVars(c, n)
-  elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
+  elif not isCallExpr or call.sons[0].kind != nkSym or
       call.sons[0].sym.kind notin skIterators:
     if length == 3:
       n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
@@ -673,12 +681,6 @@ proc semFor(c: PContext, n: PNode): PNode =
     else:
       localError(n.sons[length-2].info, errIteratorExpected)
     result = semForVars(c, n)
-  elif call.sons[0].sym.magic != mNone:
-    if call.sons[0].sym.magic == mOmpParFor:
-      result = semForVars(c, n)
-      result.kind = nkParForStmt
-    else:
-      result = semForFields(c, n, call.sons[0].sym.magic)
   else:
     result = semForVars(c, n)
   # propagate any enforced VoidContext:
@@ -942,13 +944,15 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
       localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
     #if efDetermineType notin flags:
     # XXX not good enough; see tnamedparamanonproc.nim
-    if n.sons[genericParamsPos].kind == nkEmpty:
+    if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags):
       pushProcCon(c, s)
       addResult(c, s.typ.sons[0], n.info, skProc)
       let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
       n.sons[bodyPos] = transformBody(c.module, semBody, s)
       addResultNode(c, n)
       popProcCon(c)
+    elif efOperand notin flags:
+      localError(n.info, errGenericLambdaNotAllowed)
     sideEffectsCheck(c, s)
   else:
     localError(n.info, errImplOfXexpected, s.name.s)
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 31624a97f..363c5246f 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -155,7 +155,11 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
       of nkPragmaExpr: x = x[0]
       of nkIdent: break
       else: illFormedAst(x)
-    c.toInject.incl(x.ident.id)
+    let ident = getIdentNode(c, x)
+    if not isTemplParam(c, ident):
+      c.toInject.incl(x.ident.id)
+    else:
+      replaceIdentBySym(n, ident)
   else:
     let ident = getIdentNode(c, n)
     if not isTemplParam(c, ident):
@@ -348,7 +352,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   of nkMethodDef:
     result = semRoutineInTemplBody(c, n, skMethod)
   of nkIteratorDef:
-    result = semRoutineInTemplBody(c, n, n[namePos].sym.kind)
+    let kind = if hasPragma(n[pragmasPos], wClosure): skClosureIterator
+               else: skIterator
+    result = semRoutineInTemplBody(c, n, kind)
   of nkTemplateDef:
     result = semRoutineInTemplBody(c, n, skTemplate)
   of nkMacroDef:
@@ -357,6 +363,8 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
     result = semRoutineInTemplBody(c, n, skConverter)
   of nkPragmaExpr:
     result.sons[0] = semTemplBody(c, n.sons[0])
+  of nkPostfix:
+    result.sons[1] = semTemplBody(c, n.sons[1])
   of nkPragma:
     discard
   else:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index a619de7ff..2f1532e6a 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -147,26 +147,38 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
   else:
     result = newConstraint(c, tyDistinct)
   
-proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = 
+proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
   assert isRange(n)
   checkSonsLen(n, 3)
   result = newOrPrevType(tyRange, prev, c)
   result.n = newNodeI(nkRange, n.info)
-  if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): 
+  if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty):
     localError(n.info, errRangeIsEmpty)
-  var a = semConstExpr(c, n[1])
-  var b = semConstExpr(c, n[2])
-  if not sameType(a.typ, b.typ):
+  
+  var range: array[2, PNode]
+  range[0] = semExprWithType(c, n[1], {efDetermineType})
+  range[1] = semExprWithType(c, n[2], {efDetermineType})
+  
+  var rangeT: array[2, PType]
+  for i in 0..1: rangeT[i] = range[i].typ.skipTypes({tyStatic}).skipIntLit
+
+  if not sameType(rangeT[0], rangeT[1]):
     localError(n.info, errPureTypeMismatch)
-  elif a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,
-                         tyFloat..tyFloat128,tyUInt8..tyUInt32}:
+  elif not rangeT[0].isOrdinalType:
     localError(n.info, errOrdinalTypeExpected)
-  elif enumHasHoles(a.typ): 
-    localError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
-  elif not leValue(a, b): localError(n.info, errRangeIsEmpty)
-  addSon(result.n, a)
-  addSon(result.n, b)
-  addSonSkipIntLit(result, b.typ)
+  elif enumHasHoles(rangeT[0]):
+    localError(n.info, errEnumXHasHoles, rangeT[0].sym.name.s)
+  
+  for i in 0..1:
+    if hasGenericArguments(range[i]):
+      result.n.addSon makeStaticExpr(c, range[i])
+    else:
+      result.n.addSon semConstExpr(c, range[i])
+ 
+  if weakLeValue(result.n[0], result.n[1]) == impNo:
+    localError(n.info, errRangeIsEmpty)
+
+  addSonSkipIntLit(result, rangeT[0])
 
 proc semRange(c: PContext, n: PNode, prev: PType): PType =
   result = nil
@@ -191,6 +203,14 @@ proc nMinusOne(n: PNode): PNode =
     newSymNode(getSysMagic("<", mUnaryLt)),
     n])
 
+proc makeRangeWithStaticExpr(c: PContext, n: PNode): PType =
+  let intType = getSysType tyInt
+  result = newTypeS(tyRange, c)
+  result.sons = @[intType]
+  result.n = newNode(nkRange, n.info, @[
+    newIntTypeNode(nkIntLit, 0, intType),
+    makeStaticExpr(c, n.nMinusOne)])
+
 proc semArray(c: PContext, n: PNode, prev: PType): PType = 
   var indx, base: PType
   result = newOrPrevType(tyArray, prev, c)
@@ -200,7 +220,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
     else:
       let e = semExprWithType(c, n.sons[1], {efDetermineType})
       if e.typ.kind == tyFromExpr:
-        indx = e.typ
+        indx = makeRangeWithStaticExpr(c, e.typ.n)
       elif e.kind in {nkIntLit..nkUInt64Lit}:
         indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
       elif e.kind == nkSym and e.typ.kind == tyStatic:
@@ -208,7 +228,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
         internalAssert c.inGenericContext > 0
         if not isOrdinalType(e.typ.lastSon):
           localError(n[1].info, errOrdinalTypeExpected)
-        indx = e.typ
+        indx = makeRangeWithStaticExpr(c, e)
       elif e.kind in nkCallKinds and hasGenericArguments(e):
         if not isOrdinalType(e.typ):
           localError(n[1].info, errOrdinalTypeExpected)
@@ -217,12 +237,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
         # We are going to construct a range type that will be
         # properly filled-out in semtypinst (see how tyStaticExpr
         # is handled there).
-        let intType = getSysType(tyInt)
-        indx = newTypeS(tyRange, c)
-        indx.sons = @[intType]
-        indx.n = newNode(nkRange, n.info, @[
-          newIntTypeNode(nkIntLit, 0, intType),
-          makeStaticExpr(c, e.nMinusOne)])
+        indx = makeRangeWithStaticExpr(c, e)
       else:
         indx = e.typ.skipTypes({tyTypeDesc})
     addSonSkipIntLit(result, indx)
@@ -271,6 +286,18 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
         result = result.typ.sym.copySym
         result.typ = copyType(result.typ, result.typ.owner, true)
         result.typ.flags.incl tfUnresolved
+      
+      if result.kind == skGenericParam:
+        if result.typ.kind == tyGenericParam and result.typ.len == 0 and
+           tfWildcard in result.typ.flags:
+          # collapse the wild-card param to a type
+          result.kind = skType
+          result.typ.flags.excl tfWildcard
+          return
+        else:
+          localError(n.info, errTypeExpected)
+          return errorSym(c, n)
+
       if result.kind != skType: 
         # this implements the wanted ``var v: V, x: V`` feature ...
         var ov: TOverloadIter
@@ -602,15 +629,24 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
     incl(result.flags, tfFinal)
 
 proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
-  if kind == skMacro and param.typ.kind notin {tyTypeDesc, tyStatic}:
-    # within a macro, every param has the type PNimrodNode!
-    # and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
-    let nn = getSysSym"PNimrodNode"
-    var a = copySym(param)
-    a.typ = nn.typ
-    if sfGenSym notin a.flags: addDecl(c, a)
+  template addDecl(x) =
+    if sfGenSym notin x.flags: addDecl(c, x)
+
+  if kind == skMacro:
+    if param.typ.kind == tyTypeDesc:
+      addDecl(param)
+    elif param.typ.kind == tyStatic:
+      var a = copySym(param)
+      a.typ = param.typ.base
+      addDecl(a)
+    else:
+      # within a macro, every param has the type PNimrodNode!
+      let nn = getSysSym"PNimrodNode"
+      var a = copySym(param)
+      a.typ = nn.typ
+      addDecl(a)
   else:
-    if sfGenSym notin param.flags: addDecl(c, param)
+    addDecl(param)
 
 let typedescId = getIdent"typedesc"
 
@@ -644,6 +680,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     s.position = genericParams.len
     genericParams.addSon(newSymNode(s))
     result = typeClass
+    addDecl(c, s)
  
   # XXX: There are codegen errors if this is turned into a nested proc
   template liftingWalk(typ: PType, anonFlag = false): expr =
@@ -667,11 +704,13 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   of tyStatic:
     # proc(a: expr{string}, b: expr{nkLambda})
     # overload on compile time values and AST trees
+    if paramType.n != nil: return # this is a concrete type
+    if tfUnresolved in paramType.flags: return # already lifted
     let base = paramType.base.maybeLift
     if base.isMetaType and procKind == skMacro:
       localError(info, errMacroBodyDependsOnGenericTypes, paramName)
     result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
-    result.flags.incl tfHasStatic
+    result.flags.incl({tfHasStatic, tfUnresolved})
   
   of tyTypeDesc:
     if tfUnresolved notin paramType.flags:
@@ -716,12 +755,21 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
       result.kind = tyUserTypeClassInst
       result.rawAddSon paramType.lastSon
       return addImplicitGeneric(result)
-    
+   
     result = instGenericContainer(c, paramType.sym.info, result,
                                   allowMetaTypes = true)
     result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
     result = addImplicitGeneric(result)
-  
+
+  of tyIter:
+    if paramType.callConv == ccInline:
+      if procKind notin {skTemplate, skMacro, skIterator}:
+        localError(info, errInlineIteratorsAsProcParams)
+      if paramType.len == 1:
+        let lifted = liftingWalk(paramType.base)
+        if lifted != nil: paramType.sons[0] = lifted
+      result = addImplicitGeneric(paramType)
+
   of tyGenericInst:
     if paramType.lastSon.kind == tyUserTypeClass:
       var cp = copyType(paramType, getCurrOwner(), false)
@@ -735,7 +783,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
         result = paramType
         result.lastSon.shouldHaveMeta
 
-    let liftBody = liftingWalk(paramType.lastSon)
+    let liftBody = liftingWalk(paramType.lastSon, true)
     if liftBody != nil:
       result = liftBody
       result.shouldHaveMeta
@@ -747,7 +795,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
 
     let expanded = instGenericContainer(c, info, paramType,
                                         allowMetaTypes = true)
-    result = liftingWalk(expanded)
+    result = liftingWalk(expanded, true)
 
   of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
     result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
@@ -757,12 +805,11 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
       result = addImplicitGeneric(newTypeS(tyAnything, c))
   
   of tyGenericParam:
-    if tfGenericTypeParam in paramType.flags and false:
-      if paramType.sonsLen > 0:
-        result = liftingWalk(paramType.lastSon)
-      else:
-        result = addImplicitGeneric(newTypeS(tyAnything, c))
- 
+    markUsed(genericParams, paramType.sym)
+    if tfWildcard in paramType.flags:
+      paramType.flags.excl tfWildcard
+      paramType.sym.kind = skType
+    
   else: discard
 
   # result = liftingWalk(paramType)
@@ -774,8 +821,8 @@ proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
   else:
     result = semTypeNode(c, n, nil)
 
-proc semProcTypeNode(c: PContext, n, genericParams: PNode, 
-                     prev: PType, kind: TSymKind): PType = 
+proc semProcTypeNode(c: PContext, n, genericParams: PNode,
+                     prev: PType, kind: TSymKind): PType =
   var
     res: PNode
     cl: TIntSet
@@ -840,9 +887,13 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       addParamOrResult(c, arg, kind)
       if gCmd == cmdPretty: checkDef(a.sons[j], arg)
 
-
+  var r: PType
   if n.sons[0].kind != nkEmpty:
-    var r = semTypeNode(c, n.sons[0], nil)
+    r = semTypeNode(c, n.sons[0], nil)
+  elif kind == skIterator:
+    r = newTypeS(tyAnything, c)
+  
+  if r != nil:
     # turn explicit 'void' return type into 'nil' because the rest of the 
     # compiler only checks for 'nil':
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
@@ -852,10 +903,20 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
         if lifted != nil: r = lifted
         r.flags.incl tfRetType
       r = skipIntLit(r)
-      if kind == skIterator: r = newTypeWithSons(c, tyIter, @[r])
+      if kind == skIterator:
+        # see tchainediterators
+        # in cases like iterator foo(it: iterator): type(it)
+        # we don't need to change the return type to iter[T]
+        if not r.isInlineIterator: r = newTypeWithSons(c, tyIter, @[r])
       result.sons[0] = r
       res.typ = r
 
+  if genericParams != nil:
+    for n in genericParams:
+      if tfWildcard in n.sym.typ.flags:
+        n.sym.kind = skType
+        n.sym.typ.flags.excl tfWildcard
+
 proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
   checkMinSonsLen(n, 1)
   var length = sonsLen(n)
@@ -884,6 +945,11 @@ proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
   result = semTypeNode(c, n, nil)
 
 proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = 
+  if s.typ == nil:
+    localError(n.info, "cannot instantiate the '$1' $2" %
+                       [s.name.s, ($s.kind).substr(2).toLower])
+    return newOrPrevType(tyError, prev, c)
+  
   result = newOrPrevType(tyGenericInvokation, prev, c)
   addSonSkipIntLit(result, s.typ)
 
@@ -893,10 +959,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
       rawAddSon(result, typ)
     else: addSonSkipIntLit(result, typ)
 
-  if s.typ == nil:
-    localError(n.info, errCannotInstantiateX, s.name.s)
-    return newOrPrevType(tyError, prev, c)
-  elif s.typ.kind == tyForward:
+  if s.typ.kind == tyForward:
     for i in countup(1, sonsLen(n)-1):
       var elem = semGenericParamInInvokation(c, n.sons[i])
       addToResult(elem)
@@ -906,7 +969,6 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     localError(n.info, errNoGenericParamsAllowedForX, s.name.s)
     return newOrPrevType(tyError, prev, c)
   else:
-
     var m = newCandidate(c, s, n)
     matches(c, n, copyTree(n), m)
     
@@ -923,7 +985,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
       let typ = m.call[i].typ.skipTypes({tyTypeDesc})
       if containsGenericType(typ): isConcrete = false
       addToResult(typ)
-    
+   
     if isConcrete:
       if s.ast == nil:
         localError(n.info, errCannotInstantiateX, s.name.s)
@@ -984,7 +1046,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkTypeOfExpr:
     # for ``type(countup(1,3))``, see ``tests/ttoseq``.
     checkSonsLen(n, 1)
-    result = semExprWithType(c, n.sons[0], {efInTypeof}).typ.skipTypes({tyIter})
+    let typExpr = semExprWithType(c, n.sons[0], {efInTypeof})
+    result = typExpr.typ.skipTypes({tyIter})
   of nkPar: 
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
     else:
@@ -1051,13 +1114,17 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         for i in countup(1, n.len - 1):
           result.rawAddSon(semTypeNode(c, n.sons[i], nil))
     else: result = semGeneric(c, n, s, prev)
-  of nkIdent, nkDotExpr, nkAccQuoted: 
-    if n.kind == nkDotExpr:
-      let head = qualifiedLookUp(c, n[0], {checkAmbiguity, checkUndeclared})
-      if head.kind in {skType}:
-        var toBind = initIntSet()
-        var preprocessed = semGenericStmt(c, n, {}, toBind)
-        return makeTypeFromExpr(c, preprocessed)
+  of nkDotExpr:
+    var typeExpr = semExpr(c, n)
+    if typeExpr.typ.kind != tyTypeDesc:
+      localError(n.info, errTypeExpected)
+      return errorType(c)
+    result = typeExpr.typ.base
+    if result.isMetaType:
+      var toBind = initIntSet()
+      var preprocessed = semGenericStmt(c, n, {}, toBind)
+      return makeTypeFromExpr(c, preprocessed)
+  of nkIdent, nkAccQuoted:
     var s = semTypeIdent(c, n)
     if s.typ == nil: 
       if s.kind != skError: localError(n.info, errTypeExpected)
@@ -1103,8 +1170,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       result = newConstraint(c, tyIter)
     else:
       result = semProcTypeWithScope(c, n, prev, skClosureIterator)
-      result.flags.incl(tfIterator)
-      result.callConv = ccClosure
+      if n.lastSon.kind == nkPragma and hasPragma(n.lastSon, wInline):
+        result.kind = tyIter
+        result.callConv = ccInline
+      else:
+        result.flags.incl(tfIterator)
+        result.callConv = ccClosure
   of nkProcTy:
     if n.sonsLen == 0:
       result = newConstraint(c, tyProc)
@@ -1219,6 +1290,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
     
     if typ == nil:
       typ = newTypeS(tyGenericParam, c)
+      if father == nil: typ.flags.incl tfWildcard
 
     typ.flags.incl tfGenericTypeParam
 
@@ -1229,8 +1301,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
                       # type for each generic param. the index
                       # of the parameter will be stored in the
                       # attached symbol.
-      var s = case finalType.kind
-        of tyStatic:
+      var s = if finalType.kind == tyStatic or tfWildcard in typ.flags:
           newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
         else:
           newSymG(skType, a.sons[j], c).linkTo(finalType)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 22edc6e32..4a8a463f5 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -80,7 +80,7 @@ type
 
 proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType
 proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
-proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode
+proc replaceTypeVarsN*(cl: var TReplTypeVars, n: PNode): PNode
 
 template checkMetaInvariants(cl: TReplTypeVars, t: PType) =
   when false:
@@ -96,8 +96,11 @@ proc replaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
   checkMetaInvariants(cl, result)
 
 proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
+  let t = replaceTypeVarsT(cl, n.typ)
+  if t != nil and t.kind == tyStatic and t.n != nil:
+    return t.n
   result = copyNode(n)
-  result.typ = replaceTypeVarsT(cl, n.typ)
+  result.typ = t
   if result.kind == nkSym: result.sym = replaceTypeVarsS(cl, n.sym)
   let isCall = result.kind in nkCallKinds
   for i in 0 .. <n.safeLen:
@@ -181,7 +184,8 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
   of nkStaticExpr:
     var n = prepareNode(cl, n)
     n = reResolveCallsWithTypedescParams(cl, n)
-    result = cl.c.semExpr(cl.c, n)
+    result = if cl.allowMetaTypes: n
+             else: cl.c.semExpr(cl.c, n)
   else:
     var length = sonsLen(n)
     if length > 0:
@@ -196,10 +200,10 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
     result = copySym(s, false)
     incl(result.flags, sfFromGeneric)
     idTablePut(cl.symMap, s, result)
-    result.typ = replaceTypeVarsT(cl, s.typ)
     result.owner = s.owner
+    result.typ = replaceTypeVarsT(cl, s.typ)
     result.ast = replaceTypeVarsN(cl, s.ast)
-
+    
 proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil:
@@ -209,7 +213,7 @@ proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
   elif result.kind == tyGenericParam and not cl.allowMetaTypes:
     internalError(cl.info, "substitution with generic parameter")
 
-proc instCopyType(cl: var TReplTypeVars, t: PType): PType =
+proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
   # XXX: relying on allowMetaTypes is a kludge
   result = copyType(t, t.owner, cl.allowMetaTypes)
   result.flags.incl tfFromGeneric
@@ -280,7 +284,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
   rawAddSon(result, newbody)
   checkPartialConstructedType(cl.info, newbody)
 
-proc eraseVoidParams(t: PType) =
+proc eraseVoidParams*(t: PType) =
   if t.sons[0] != nil and t.sons[0].kind == tyEmpty:
     t.sons[0] = nil
   
@@ -297,7 +301,7 @@ proc eraseVoidParams(t: PType) =
       setLen t.n.sons, pos
       return
 
-proc skipIntLiteralParams(t: PType) =
+proc skipIntLiteralParams*(t: PType) =
   for i in 0 .. <t.sonsLen:
     let p = t.sons[i]
     if p == nil: continue
@@ -305,6 +309,11 @@ proc skipIntLiteralParams(t: PType) =
     if skipped != p:
       t.sons[i] = skipped
       if i > 0: t.n.sons[i].sym.typ = skipped
+  
+  # when the typeof operator is used on a static input
+  # param, the results gets infected with static as well:
+  if t.sons[0] != nil and t.sons[0].kind == tyStatic:
+    t.sons[0] = t.sons[0].base
 
 proc propagateFieldFlags(t: PType, n: PNode) =
   # This is meant for objects and tuples
@@ -314,16 +323,15 @@ proc propagateFieldFlags(t: PType, n: PNode) =
   of nkSym:
     propagateToOwner(t, n.sym.typ)
   of nkRecList, nkRecCase, nkOfBranch, nkElse:
-    if n.sons != nil:
-      for son in n.sons:
-        propagateFieldFlags(t, son)
+    for son in n:
+      propagateFieldFlags(t, son)
   else: discard
 
 proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
   result = t
   if t == nil: return
 
-  if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses:
+  if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses:
     let lookup = PType(idTableGet(cl.typeMap, t))
     if lookup != nil: return lookup
   
@@ -336,6 +344,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
     result = replaceTypeVarsT(cl, lastSon(t))
 
   of tyFromExpr:
+    if cl.allowMetaTypes: return
     var n = prepareNode(cl, t.n)
     n = cl.c.semConstExpr(cl.c, n)
     if n.typ.kind == tyTypeDesc:
@@ -388,21 +397,11 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
           propagateToOwner(result, result.sons[i])
 
       result.n = replaceTypeVarsN(cl, result.n)
-      
-      # XXX: This is not really needed?
-      # if result.kind in GenericTypes:
-      #   localError(cl.info, errCannotInstantiateX, typeToString(t, preferName))
-
+     
       case result.kind
       of tyArray:
         let idx = result.sons[0]
-        if idx.kind == tyStatic:
-          if idx.n == nil:
-            let lookup = lookupTypeVar(cl, idx)
-            internalAssert lookup != nil
-            idx.n = lookup.n
-
-          result.sons[0] = makeRangeType(cl.c, 0, idx.n.intVal - 1, idx.n.info)
+        internalAssert idx.kind != tyStatic
        
       of tyObject, tyTuple:
         propagateFieldFlags(result, result.n)
@@ -413,7 +412,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
       
       else: discard
 
-proc initTypeVars(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars =
+proc initTypeVars*(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars =
   initIdTable(result.symMap)
   copyIdTable(result.typeMap, pt)
   initIdTable(result.localCache)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index c0898ef26..662268380 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -522,8 +522,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   template bindingRet(res) =
     when res == isGeneric:
-      let bound = aOrig.skipTypes({tyRange}).skipIntLit
-      put(c.bindings, f, bound)
+      if doBind:
+        let bound = aOrig.skipTypes({tyRange}).skipIntLit
+        if doBind: put(c.bindings, f, bound)
     return res
 
   template considerPreviousT(body: stmt) {.immediate.} =
@@ -620,8 +621,10 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         else:
           fRange = prev
       result = typeRel(c, f.sons[1], a.sons[1])
-      if result < isGeneric: result = isNone
-      elif lengthOrd(fRange) != lengthOrd(a): result = isNone
+      if result < isGeneric:
+        result = isNone
+      elif lengthOrd(fRange) != lengthOrd(a):
+        result = isNone
     else: discard
   of tyOpenArray, tyVarargs:
     case a.kind
@@ -867,7 +870,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         # any value" and what we need is "match any type", which can be encoded
         # by a tyTypeDesc params. Unfortunately, this requires more substantial
         # changes in semtypinst and elsewhere.
-        if a.kind == tyTypeDesc:
+        if tfWildcard in a.flags:
+          result = isGeneric
+        elif a.kind == tyTypeDesc:
           if f.sonsLen == 0:
             result = isGeneric
           else:
@@ -883,11 +888,16 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
           result = isGeneric
 
       if result == isGeneric:
-        var concrete = concreteType(c, a)
-        if concrete == nil:
-          result = isNone
+        var concrete = a
+        if tfWildcard in a.flags:
+          a.sym.kind = skType
+          a.flags.excl tfWildcard
         else:
-          if doBind: put(c.bindings, f, concrete)
+          concrete = concreteType(c, a)
+          if concrete == nil:
+            return isNone
+        if doBind:
+          put(c.bindings, f, concrete)
     elif a.kind == tyEmpty:
       result = isGeneric
     elif x.kind == tyGenericParam:
@@ -937,8 +947,19 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   
   of tyProxy:
     result = isEqual
+
+  of tyFromExpr:
+    # fix the expression, so it contains the already instantiated types
+    let instantiated = replaceTypesInBody(c.c, c.bindings, f.n)
+    let reevaluted = c.c.semExpr(c.c, instantiated)
+    if reevaluted.typ.kind != tyTypeDesc:
+      localError(f.n.info, errTypeExpected)
+      result = isNone
+    else:
+      result = typeRel(c, a, reevaluted.typ.base)
   
-  else: internalAssert false
+  else:
+    internalAssert false
   
 proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation = 
   var m: TCandidate
@@ -1014,6 +1035,10 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
       result.typ = getInstantiatedType(c, arg, m, base(f))
     m.baseTypeMatch = true
 
+proc isInlineIterator*(t: PType): bool =
+  result = t.kind == tyIter or
+          (t.kind == tyBuiltInTypeClass and t.base.kind == tyIter)
+
 proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
                         argSemantized, argOrig: PNode): PNode =
   var
@@ -1021,17 +1046,31 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     arg = argSemantized
     argType = argType
     c = m.c
-    
+ 
   if tfHasStatic in fMaybeStatic.flags:
     # XXX: When implicit statics are the default
     # this will be done earlier - we just have to
     # make sure that static types enter here
-    var evaluated = c.semTryConstExpr(c, arg)
-    if evaluated != nil:
-      arg.typ = newTypeS(tyStatic, c)
-      arg.typ.sons = @[evaluated.typ]
-      arg.typ.n = evaluated
-      argType = arg.typ
+    
+    # XXX: weaken tyGenericParam and call it tyGenericPlaceholder
+    # and finally start using tyTypedesc for generic types properly.
+    if argType.kind == tyGenericParam and tfWildcard in argType.flags:
+      argType.assignType(f)
+      # put(m.bindings, f, argType)
+      return argSemantized
+
+    if argType.kind == tyStatic:
+      if m.calleeSym.kind == skType:
+        result = newNodeI(nkType, argOrig.info)
+        result.typ = makeTypeFromExpr(c, arg)
+        return
+    else:
+      var evaluated = c.semTryConstExpr(c, arg)
+      if evaluated != nil:
+        arg.typ = newTypeS(tyStatic, c)
+        arg.typ.sons = @[evaluated.typ]
+        arg.typ.n = evaluated
+        argType = arg.typ
  
   var
     a = if c.inTypeClass > 0: argType.skipTypes({tyTypeDesc, tyFieldAccessor})
@@ -1060,7 +1099,14 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
       return arg.typ.n
     else:
       return argOrig
-  
+
+  if r != isNone and f.isInlineIterator:
+    var inlined = newTypeS(tyStatic, c)
+    inlined.sons = @[argType]
+    inlined.n = argSemantized
+    put(m.bindings, f, inlined)
+    return argSemantized
+
   case r
   of isConvertible:
     inc(m.convMatches)
@@ -1188,7 +1234,9 @@ proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
     # a.typ == nil is valid
     result = a
   elif a.typ.isNil:
-    result = c.semOperand(c, a, {efDetermineType})
+    let flags = if formal.kind == tyIter: {efDetermineType, efWantIterator}
+                else: {efDetermineType}
+    result = c.semOperand(c, a, flags)
   else:
     result = a
 
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index 7c44ec0b4..478c2a837 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -17,14 +17,15 @@ type
   TFilterKind* = enum 
     filtNone, filtTemplate, filtReplace, filtStrip
   TParserKind* = enum 
-    skinStandard, skinBraces, skinEndX
+    skinStandard, skinStrongSpaces, skinBraces, skinEndX
 
 const 
-  parserNames*: array[TParserKind, string] = ["standard", "braces", "endx"]
-  filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace", 
-    "strip"]
+  parserNames*: array[TParserKind, string] = ["standard", "strongspaces",
+                                              "braces", "endx"]
+  filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace",
+                                              "strip"]
 
-type 
+type
   TParsers*{.final.} = object 
     skin*: TParserKind
     parser*: TParser
@@ -54,7 +55,7 @@ proc parseFile(fileIdx: int32): PNode =
 
 proc parseAll(p: var TParsers): PNode = 
   case p.skin
-  of skinStandard: 
+  of skinStandard, skinStrongSpaces:
     result = parser.parseAll(p.parser)
   of skinBraces: 
     result = pbraces.parseAll(p.parser)
@@ -65,7 +66,7 @@ proc parseAll(p: var TParsers): PNode =
   
 proc parseTopLevelStmt(p: var TParsers): PNode = 
   case p.skin
-  of skinStandard: 
+  of skinStandard, skinStrongSpaces:
     result = parser.parseTopLevelStmt(p.parser)
   of skinBraces: 
     result = pbraces.parseTopLevelStmt(p.parser)
@@ -170,7 +171,9 @@ proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) =
   else: s = inputstream
   case p.skin
   of skinStandard, skinBraces, skinEndX:
-    parser.openParser(p.parser, fileIdx, s)
+    parser.openParser(p.parser, fileIdx, s, false)
+  of skinStrongSpaces:
+    parser.openParser(p.parser, fileIdx, s, true)
   
-proc closeParsers(p: var TParsers) = 
+proc closeParsers(p: var TParsers) =
   parser.closeParser(p.parser)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index f4b716c5b..9586398c9 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -425,7 +425,7 @@ proc findWrongOwners(c: PTransf, n: PNode) =
         x.sym.owner.name.s & " " & getCurrOwner(c).name.s)
   else:
     for i in 0 .. <safeLen(n): findWrongOwners(c, n.sons[i])
-  
+
 proc transformFor(c: PTransf, n: PNode): PTransNode = 
   # generate access statements for the parameters (unless they are constant)
   # put mapping from formal parameters to actual parameters
@@ -433,12 +433,13 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
 
   var length = sonsLen(n)
   var call = n.sons[length - 2]
-  if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or 
-      call.sons[0].sym.kind != skIterator:
+  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")
-
+  
   #echo "transforming: ", renderTree(n)
   result = newTransNode(nkStmtList, n.info, 0)
   var loopBody = transformLoopBody(c, n.sons[length-1])
@@ -459,6 +460,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
   for i in countup(1, sonsLen(call) - 1): 
     var arg = transform(c, call.sons[i]).PNode
     var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym 
+    if arg.typ.kind == tyIter: continue
     case putArgInto(arg, formal.typ)
     of paDirectMapping: 
       idNodeTablePut(newC.mapping, formal, arg)
@@ -480,7 +482,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
   dec(c.inlining)
   popInfoContext()
   popTransCon(c)
-  #echo "transformed: ", renderTree(n)
+  # echo "transformed: ", result.PNode.renderTree
   
 proc getMagicOp(call: PNode): TMagic = 
   if call.sons[0].kind == nkSym and
diff --git a/compiler/types.nim b/compiler/types.nim
index 8cf91da8b..89b15c4a8 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1255,15 +1255,18 @@ proc getSize(typ: PType): BiggestInt =
   if result < 0: internalError("getSize: " & $typ.kind)
 
 proc containsGenericTypeIter(t: PType, closure: PObject): bool =
-  if t.kind in GenericTypes + tyTypeClasses + {tyFromExpr}:
-    return true
+  if t.kind == tyStatic:
+    return t.n == nil
 
   if t.kind == tyTypeDesc:
     if t.base.kind == tyNone: return true
     if containsGenericTypeIter(t.base, closure): return true
     return false
-  
-  return t.kind == tyStatic and t.n == nil
+
+  if t.kind in GenericTypes + tyTypeClasses + {tyFromExpr}:
+    return true
+
+  return false
 
 proc containsGenericType*(t: PType): bool = 
   result = iterOverType(t, containsGenericTypeIter, nil)
diff --git a/compiler/vm.nim b/compiler/vm.nim
index f9b143bce..5c8e533f1 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -425,7 +425,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       decodeBC(rkNode)
       let src = regs[rb].node
       if src.kind notin {nkEmpty..nkNilLit}:
-        regs[ra].node = src.sons[rc]
+        let n = src.sons[rc]
+        regs[ra].node = n
       else:
         stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcWrObj:
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index b1a751723..d3eda5db3 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -308,12 +308,20 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
   c.gen(n.sons[2], dest)
   c.patch(L1)
 
-proc nilLiteral(n: PNode): PNode =
-  result = n
+proc canonConst(n: PNode): PNode =
+  if n.kind == nkExprColonExpr:
+    result = n.sons[1]
+  elif n.hasSubnodeWith(nkExprColonExpr):
+    result = n.copyNode
+    newSeq(result.sons, n.len)
+    for i in 0.. <n.len:
+      result.sons[i] = canonConst(n.sons[i])
+  else:
+    result = n
 
 proc rawGenLiteral(c: PCtx; n: PNode): int =
   result = c.constants.len
-  c.constants.add n.nilLiteral
+  c.constants.add n.canonConst
   internalAssert result < 0x7fff
 
 proc sameConstant*(a, b: PNode): bool =
@@ -329,10 +337,10 @@ proc sameConstant*(a, b: PNode): bool =
     of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
     of nkType: result = a.typ == b.typ
     of nkEmpty, nkNilLit: result = true
-    else: 
-      if sonsLen(a) == sonsLen(b): 
-        for i in countup(0, sonsLen(a) - 1): 
-          if not sameConstant(a.sons[i], b.sons[i]): return 
+    else:
+      if sonsLen(a) == sonsLen(b):
+        for i in countup(0, sonsLen(a) - 1):
+          if not sameConstant(a.sons[i], b.sons[i]): return
         result = true
 
 proc genLiteral(c: PCtx; n: PNode): int =
@@ -1561,7 +1569,7 @@ proc genProc(c: PCtx; s: PSym): int =
     c.gABC(body, opcEof, eofInstr.regA)
     c.optimizeJumps(result)
     s.offset = c.prc.maxSlots
-    #if s.name.s == "xmlConstructor":
+    #if s.name.s == "foo":
     #  echo renderTree(body)
     #  c.echoCode(result)
     c.prc = oldPrc
diff --git a/doc/manual.txt b/doc/manual.txt
index 3c1f7b651..ab1badaf3 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -79,8 +79,21 @@ program execution. Unless explicitly classified, an error is a static error.
 
 A `checked runtime error`:idx: is an error that the implementation detects
 and reports at runtime. The method for reporting such errors is via *raising
-exceptions*. However, the implementation provides a means to disable these
-runtime checks. See the section pragmas_ for details.
+exceptions* or *dying with a fatal error*. However, the implementation 
+provides a means to disable these runtime checks. See the section pragmas_
+for details. 
+
+Wether a checked runtime error results in an exception or in a fatal error at
+runtime is implementation specific. Thus the following program is always
+invalid:
+
+.. code-block:: nimrod
+  var a: array[0..1, char]
+  let i = 5
+  try:
+    a[i] = 'N'
+  except EInvalidIndex:
+    echo "invalid index"
 
 An `unchecked runtime error`:idx: is an error that is not guaranteed to be
 detected, and can cause the subsequent behavior of the computation to
@@ -480,8 +493,8 @@ precedence and associativity; this is useful for meta programming.
 Associativity
 -------------
 
-All binary operators are left-associative, except binary operators whose
-relevant char is ``^``.
+Binary operators whose relevant character is ``^`` are right-associative, all
+other binary operators are left-associative.
 
 Precedence
 ----------
@@ -508,7 +521,7 @@ Precedence level    Operators                                      Relevant char
   7               ``+    -``                                       ``+  ~  |``         OP7
   6               ``&``                                            ``&``               OP6
   5               ``..``                                           ``.``               OP5
-  4               ``==  <= < >= > !=  in not_in is isnot not of``  ``= <  > !``        OP4
+  4               ``==  <= < >= > !=  in notin is isnot not of``   ``= <  > !``        OP4
   3               ``and``                                                              OP3
   2               ``or xor``                                                           OP2
   1                                                                ``@  : ?``          OP1
@@ -516,6 +529,46 @@ Precedence level    Operators                                      Relevant char
 ================  ===============================================  ==================  ===============
 
 
+Strong spaces
+-------------
+
+The number of spaces preceeding a non-keyword operator affects precedence
+if the experimental parser directive ``#!strongSpaces`` is used. Indentation
+is not used to determine the number of spaces. If 2 or more operators have the
+same number of preceding spaces the precedence table applies, so ``1 + 3 * 4``
+is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``:
+
+.. code-block:: nimrod
+  #! strongSpaces
+  if foo+4 * 4 == 8 and b&c | 9  ++
+      bar:
+    echo ""
+  # is parsed as
+  if ((foo+4)*4 == 8) and (((b&c) | 9) ++ bar): echo ""
+
+
+Furthermore whether an operator is used a prefix operator is affected by the
+number of spaces: 
+
+.. code-block:: nimrod
+  #! strongSpaces
+  echo $foo
+  # is parsed as
+  echo($foo)
+
+This also affects whether ``[]``, ``{}``, ``()`` are parsed as constructors
+or as accessors:
+
+.. code-block:: nimrod
+  #! strongSpaces
+  echo (1,2)
+  # is parsed as
+  echo((1,2))
+
+
+Grammar
+-------
+
 The grammar's start symbol is ``module``.
 
 .. include:: grammar.txt
@@ -2822,7 +2875,6 @@ as there are components in the tuple. The i'th iteration variable's type is
 the type of the i'th component. In other words, implicit tuple unpacking in a 
 for loop context is supported.
 
-
 Implict items/pairs invocations
 -------------------------------
 
@@ -2847,10 +2899,11 @@ First class iterators
 There are 2 kinds of iterators in Nimrod: *inline* and *closure* iterators.
 An `inline iterator`:idx: is an iterator that's always inlined by the compiler 
 leading to zero overhead for the abstraction, but may result in a heavy
-increase in code size. Inline iterators are second class
-citizens; one cannot pass them around like first class procs.
+increase in code size. Inline iterators are second class citizens;
+They can be passed as parameters only to other inlining code facilities like
+templates, macros and other inline iterators.
 
-In contrast to that, a `closure iterator`:idx: can be passed around:
+In contrast to that, a `closure iterator`:idx: can be passed around more freely:
 
 .. code-block:: nimrod
   iterator count0(): int {.closure.} =
@@ -2873,9 +2926,7 @@ Closure iterators have other restrictions than inline iterators:
 1. ``yield`` in a closure iterator can not occur in a ``try`` statement.
 2. For now, a closure iterator cannot be evaluated at compile time.
 3. ``return`` is allowed in a closure iterator (but rarely useful).
-4. Since closure iterators can be used as a collaborative tasking
-   system, ``void`` is a valid return type for them.
-5. Both inline and closure iterators cannot be recursive.
+4. Both inline and closure iterators cannot be recursive.
 
 Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly
 default to being inline, but that this may change in future versions of the
@@ -2937,6 +2988,14 @@ parameters of an outer factory proc:
   for f in foo():
     echo f
 
+Implicit return type
+--------------------
+
+Since inline interators must always produce values that will be consumed in
+a for loop, the compiler will implicity use the ``auto`` return type if no
+type is given by the user. In contrast, since closure iterators can be used
+as a collaborative tasking system, ``void`` is a valid return type for them.
+
 
 Type sections
 =============
@@ -3441,7 +3500,7 @@ Declarative type classes are written in the following form:
       c.len is ordinal
       items(c) is iterator
       for value in c:
-        value.type is T
+        type(value) is T
 
 The type class will be matched if:
 
@@ -4016,8 +4075,8 @@ Static params can also appear in the signatures of generic types:
     AffineTransform2D[T] = Matrix[3, 3, T]
     AffineTransform3D[T] = Matrix[4, 4, T]
 
-  AffineTransform3D[float]  # OK
-  AffineTransform2D[string] # Error, `string` is not a `Number`
+  var m1: AffineTransform3D[float]  # OK
+  var m2: AffineTransform2D[string] # Error, `string` is not a `Number`
 
 
 typedesc
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
index 74aaa1a59..32cda3e4d 100644
--- a/lib/impure/db_mysql.nim
+++ b/lib/impure/db_mysql.nim
@@ -195,8 +195,14 @@ proc open*(connection, user, password, database: string): TDbConn {.
   ## be established.
   result = mysql.Init(nil)
   if result == nil: dbError("could not open database connection") 
-  if mysql.RealConnect(result, "", user, password, database, 
-                       0'i32, nil, 0) == nil:
+  let
+    colonPos = connection.find(':')
+    host =        if colonPos < 0: connection
+                  else:            substr(connection, 0, colonPos-1)
+    port: int32 = if colonPos < 0: 0'i32
+                  else:            substr(connection, colonPos+1).parseInt.int32
+  if mysql.RealConnect(result, host, user, password, database, 
+                       port, nil, 0) == nil:
     var errmsg = $mysql.error(result)
     db_mysql.Close(result)
     dbError(errmsg)
diff --git a/lib/nimbase.h b/lib/nimbase.h
index 1100e084b..b16b27b2c 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -314,6 +314,9 @@ static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
 #    define INF INFINITY
 #  elif defined(HUGE_VAL)
 #    define INF  HUGE_VAL
+#  elif defined(_MSC_VER)
+#    include <float.h>
+#    define INF (DBL_MAX+DBL_MAX)
 #  else
 #    define INF (1.0 / 0.0)
 #  endif
diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim
index 366521551..57a2f001f 100644
--- a/lib/posix/epoll.nim
+++ b/lib/posix/epoll.nim
@@ -36,7 +36,7 @@ type
   epoll_data* {.importc: "union epoll_data", 
       header: "<sys/epoll.h>", pure, final.} = object # TODO: This is actually a union.
     #thePtr* {.importc: "ptr".}: pointer
-    fd*: cint # \
+    fd* {.importc: "fd".}: cint # \
     #u32*: uint32
     #u64*: uint64
 
diff --git a/lib/pure/asyncio2.nim b/lib/pure/asyncio2.nim
index 12d4cb5a3..eb31eca13 100644
--- a/lib/pure/asyncio2.nim
+++ b/lib/pure/asyncio2.nim
@@ -43,6 +43,14 @@ proc complete*[T](future: PFuture[T], val: T) =
   if future.cb != nil:
     future.cb()
 
+proc complete*(future: PFuture[void]) =
+  ## Completes a void ``future``.
+  assert(not future.finished, "Future already finished, cannot finish twice.")
+  assert(future.error == nil)
+  future.finished = true
+  if future.cb != nil:
+    future.cb()
+
 proc fail*[T](future: PFuture[T], error: ref EBase) =
   ## Completes ``future`` with ``error``.
   assert(not future.finished, "Future already finished, cannot finish twice.")
@@ -76,7 +84,8 @@ proc read*[T](future: PFuture[T]): T =
   ## 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
-    return future.value
+    when T isnot void:
+      return future.value
   else:
     # TODO: Make a custom exception type for this?
     raise newException(EInvalidValue, "Future still in progress.")
@@ -94,7 +103,8 @@ proc failed*[T](future: PFuture[T]): bool =
 # TODO: Get rid of register. Do it implicitly.
 
 when defined(windows) or defined(nimdoc):
-  import winlean
+  import winlean, sets, hashes
+  #from hashes import THash
   type
     TCompletionKey = dword
 
@@ -105,7 +115,7 @@ when defined(windows) or defined(nimdoc):
 
     PDispatcher* = ref object
       ioPort: THandle
-      hasHandles: bool
+      handles: TSet[TSocketHandle]
 
     TCustomOverlapped = object
       Internal*: DWORD
@@ -117,21 +127,31 @@ when defined(windows) or defined(nimdoc):
 
     PCustomOverlapped = ptr TCustomOverlapped
 
+  proc hash(x: TSocketHandle): THash {.borrow.}
+
   proc newDispatcher*(): PDispatcher =
     ## Creates a new Dispatcher instance.
     new result
     result.ioPort = CreateIOCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)
+    result.handles = initSet[TSocketHandle]()
 
   proc register*(p: PDispatcher, sock: TSocketHandle) =
     ## Registers ``sock`` with the dispatcher ``p``.
     if CreateIOCompletionPort(sock.THandle, p.ioPort,
                               cast[TCompletionKey](sock), 1) == 0:
       OSError(OSLastError())
-    p.hasHandles = true
+    p.handles.incl(sock)
+
+  proc verifyPresence(p: PDispatcher, sock: TSocketHandle) =
+    ## Ensures that socket has been registered with the dispatcher.
+    if sock notin p.handles:
+      raise newException(EInvalidValue,
+        "Operation performed on a socket which has not been registered with" &
+        " the dispatcher yet.")
 
   proc poll*(p: PDispatcher, timeout = 500) =
     ## Waits for completion events and processes them.
-    if not p.hasHandles:
+    if p.handles.len == 0:
       raise newException(EInvalidValue, "No handles registered in dispatcher.")
     
     let llTimeout =
@@ -232,13 +252,13 @@ when defined(windows) or defined(nimdoc):
                   RemoteSockaddr, RemoteSockaddrLength)
 
   proc connect*(p: PDispatcher, socket: TSocketHandle, address: string, port: TPort,
-    af = AF_INET): PFuture[int] =
+    af = AF_INET): PFuture[void] =
     ## Connects ``socket`` to server at ``address:port``.
     ##
     ## Returns a ``PFuture`` which will complete when the connection succeeds
     ## or an error occurs.
-
-    var retFuture = newFuture[int]()# TODO: Change to void when that regression is fixed.
+    verifyPresence(p, socket)
+    var retFuture = newFuture[void]()
     # Apparently ``ConnectEx`` expects the socket to be initially bound:
     var saddr: Tsockaddr_in
     saddr.sin_family = int16(toInt(af))
@@ -260,7 +280,7 @@ when defined(windows) or defined(nimdoc):
         proc (sock: TSocketHandle, bytesCount: DWord, errcode: TOSErrorCode) =
           if not retFuture.finished:
             if errcode == TOSErrorCode(-1):
-              retFuture.complete(0)
+              retFuture.complete()
             else:
               retFuture.fail(newException(EOS, osErrorMsg(errcode)))
       )
@@ -270,7 +290,7 @@ when defined(windows) or defined(nimdoc):
       if ret:
         # Request to connect completed immediately.
         success = true
-        retFuture.complete(0)
+        retFuture.complete()
         # We don't deallocate ``ol`` here because even though this completed
         # immediately poll will still be notified about its completion and it will
         # free ``ol``.
@@ -298,7 +318,7 @@ when defined(windows) or defined(nimdoc):
     ## recv operation then the future may complete with only a part of the
     ## requested data read. If socket is disconnected and no data is available
     ## to be read then the future will complete with a value of ``""``.
-
+    verifyPresence(p, socket)
     var retFuture = newFuture[string]()
     
     var dataBuf: TWSABuf
@@ -351,10 +371,11 @@ when defined(windows) or defined(nimdoc):
       # free ``ol``.
     return retFuture
 
-  proc send*(p: PDispatcher, socket: TSocketHandle, data: string): PFuture[int] =
+  proc send*(p: PDispatcher, socket: TSocketHandle, data: string): PFuture[void] =
     ## Sends ``data`` to ``socket``. The returned future will complete once all
     ## data has been sent.
-    var retFuture = newFuture[int]()
+    verifyPresence(p, socket)
+    var retFuture = newFuture[void]()
 
     var dataBuf: TWSABuf
     dataBuf.buf = data
@@ -366,7 +387,7 @@ when defined(windows) or defined(nimdoc):
       proc (sock: TSocketHandle, bytesCount: DWord, errcode: TOSErrorCode) =
         if not retFuture.finished:
           if errcode == TOSErrorCode(-1):
-            retFuture.complete(0)
+            retFuture.complete()
           else:
             retFuture.fail(newException(EOS, osErrorMsg(errcode)))
     )
@@ -379,7 +400,7 @@ when defined(windows) or defined(nimdoc):
         retFuture.fail(newException(EOS, osErrorMsg(err)))
         dealloc(ol)
     else:
-      retFuture.complete(0)
+      retFuture.complete()
       # We don't deallocate ``ol`` here because even though this completed
       # immediately poll will still be notified about its completion and it will
       # free ``ol``.
@@ -390,7 +411,9 @@ when defined(windows) or defined(nimdoc):
     ## 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.
+    verifyPresence(p, socket)
     var retFuture = newFuture[tuple[address: string, client: TSocketHandle]]()
 
     var clientSock = socket()
@@ -416,6 +439,7 @@ when defined(windows) or defined(nimdoc):
                            dwLocalAddressLength, dwRemoteAddressLength,
                            addr LocalSockaddr, addr localLen,
                            addr RemoteSockaddr, addr remoteLen)
+      p.register(clientSock)
       # TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186
       retFuture.complete(
         (address: $inet_ntoa(cast[ptr Tsockaddr_in](remoteSockAddr).sin_addr),
@@ -452,6 +476,18 @@ when defined(windows) or defined(nimdoc):
 
     return retFuture
 
+  proc socket*(disp: PDispatcher, domain: TDomain = AF_INET,
+               typ: TType = SOCK_STREAM,
+               protocol: TProtocol = IPPROTO_TCP): TSocketHandle =
+    ## Creates a new socket and registers it with the dispatcher implicitly.
+    result = socket(domain, typ, protocol)
+    disp.register(result)
+
+  proc close*(disp: PDispatcher, socket: TSocketHandle) =
+    ## Closes a socket and ensures that it is unregistered.
+    socket.close()
+    disp.handles.excl(socket)
+
   initAll()
 else:
   import selectors
@@ -473,62 +509,76 @@ else:
 
   proc update(p: PDispatcher, sock: TSocketHandle, events: set[TEvent]) =
     assert sock in p.selector
-    echo("Update: ", events)
-    if events == {}:
-      discard p.selector.unregister(sock)
-    else:
-      discard p.selector.update(sock, events)
+    discard p.selector.update(sock, events)
+
+  proc register(p: PDispatcher, sock: TSocketHandle) =
+    var data = PData(sock: sock, readCBs: @[], writeCBs: @[])
+    p.selector.register(sock, {}, data.PObject)
+
+  proc socket*(disp: PDispatcher, domain: TDomain = AF_INET,
+               typ: TType = SOCK_STREAM,
+               protocol: TProtocol = IPPROTO_TCP): TSocketHandle =
+    result = socket(domain, typ, protocol)
+    disp.register(result)
   
+  proc close*(disp: PDispatcher, sock: TSocketHandle) =
+    sock.close()
+    disp.selector.unregister(sock)
+
   proc addRead(p: PDispatcher, sock: TSocketHandle, cb: TCallback) =
     if sock notin p.selector:
-      var data = PData(sock: sock, readCBs: @[cb], writeCBs: @[])
-      p.selector.register(sock, {EvRead}, data.PObject)
-    else:
-      p.selector[sock].data.PData.readCBs.add(cb)
-      p.update(sock, p.selector[sock].events + {EvRead})
+      raise newException(EInvalidValue, "File descriptor not registered.")
+    p.selector[sock].data.PData.readCBs.add(cb)
+    p.update(sock, p.selector[sock].events + {EvRead})
   
   proc addWrite(p: PDispatcher, sock: TSocketHandle, cb: TCallback) =
     if sock notin p.selector:
-      var data = PData(sock: sock, readCBs: @[], writeCBs: @[cb])
-      p.selector.register(sock, {EvWrite}, data.PObject)
-    else:
-      p.selector[sock].data.PData.writeCBs.add(cb)
-      p.update(sock, p.selector[sock].events + {EvWrite})
+      raise newException(EInvalidValue, "File descriptor not registered.")
+    p.selector[sock].data.PData.writeCBs.add(cb)
+    p.update(sock, p.selector[sock].events + {EvWrite})
   
   proc poll*(p: PDispatcher, timeout = 500) =
     for info in p.selector.select(timeout):
       let data = PData(info.key.data)
       assert data.sock == info.key.fd
-      echo("R: ", data.readCBs.len, " W: ", data.writeCBs.len, ". ", info.events)
-      
+      #echo("In poll ", data.sock.cint)
       if EvRead in info.events:
-        var newReadCBs: seq[TCallback] = @[]
-        for cb in data.readCBs:
+        # Callback may add items to ``data.readCBs`` which causes issues if
+        # we are iterating over ``data.readCBs`` at the same time. We therefore
+        # make a copy to iterate over.
+        let currentCBs = data.readCBs
+        data.readCBs = @[]
+        for cb in currentCBs:
           if not cb(data.sock):
             # Callback wants to be called again.
-            newReadCBs.add(cb)
-        data.readCBs = newReadCBs
+            data.readCBs.add(cb)
       
       if EvWrite in info.events:
-        var newWriteCBs: seq[TCallback] = @[]
-        for cb in data.writeCBs:
+        let currentCBs = data.writeCBs
+        data.writeCBs = @[]
+        for cb in currentCBs:
           if not cb(data.sock):
             # Callback wants to be called again.
-            newWriteCBs.add(cb)
-        data.writeCBs = newWriteCBs
-  
-      var newEvents: set[TEvent]
-      if data.readCBs.len != 0: newEvents = {EvRead}
-      if data.writeCBs.len != 0: newEvents = newEvents + {EvWrite}
-      p.update(data.sock, newEvents)
+            data.writeCBs.add(cb)
+      
+      if info.key in p.selector:
+        var newEvents: set[TEvent]
+        if data.readCBs.len != 0: newEvents = {EvRead}
+        if data.writeCBs.len != 0: newEvents = newEvents + {EvWrite}
+        if newEvents != info.key.events:
+          echo(info.key.events, " -> ", newEvents)
+          p.update(data.sock, newEvents)
+      else:
+        # FD no longer a part of the selector. Likely been closed
+        # (e.g. socket disconnected).
   
   proc connect*(p: PDispatcher, socket: TSocketHandle, address: string, port: TPort,
-    af = AF_INET): PFuture[int] =
-    var retFuture = newFuture[int]()
+    af = AF_INET): PFuture[void] =
+    var retFuture = newFuture[void]()
     
     proc cb(sock: TSocketHandle): bool =
       # We have connected.
-      retFuture.complete(0)
+      retFuture.complete()
       return true
     
     var aiList = getAddrInfo(address, port, af)
@@ -540,7 +590,7 @@ else:
       if ret == 0:
         # Request to connect completed immediately.
         success = true
-        retFuture.complete(0)
+        retFuture.complete()
         break
       else:
         lastError = osLastError()
@@ -568,6 +618,7 @@ else:
       result = true
       let netSize = size - sizeRead
       let res = recv(sock, addr readBuffer[sizeRead], netSize, flags.cint)
+      #echo("recv cb res: ", res)
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 notin {EINTR, EWOULDBLOCK, EAGAIN}: 
@@ -575,6 +626,7 @@ else:
         else:
           result = false # We still want this callback to be called.
       elif res == 0:
+        #echo("Disconnected recv: ", sizeRead)
         # Disconnected
         if sizeRead == 0:
           retFuture.complete("")
@@ -587,12 +639,13 @@ else:
           result = false # We want to read all the data requested.
         else:
           retFuture.complete(readBuffer)
+      #echo("Recv cb result: ", result)
   
     addRead(p, socket, cb)
     return retFuture
 
-  proc send*(p: PDispatcher, socket: TSocketHandle, data: string): PFuture[int] =
-    var retFuture = newFuture[int]()
+  proc send*(p: PDispatcher, socket: TSocketHandle, data: string): PFuture[void] =
+    var retFuture = newFuture[void]()
     
     var written = 0
     
@@ -612,10 +665,9 @@ else:
         if res != netSize:
           result = false # We still have data to send.
         else:
-          retFuture.complete(0)
+          retFuture.complete()
     addWrite(p, socket, cb)
     return retFuture
-        
 
   proc acceptAddr*(p: PDispatcher, socket: TSocketHandle): 
       PFuture[tuple[address: string, client: TSocketHandle]] =
@@ -634,6 +686,7 @@ else:
         else:
           retFuture.fail(newException(EOS, osErrorMsg(lastError)))
       else:
+        p.register(client)
         retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client))
     addRead(p, socket, cb)
     return retFuture
@@ -745,12 +798,17 @@ macro async*(prc: stmt): stmt {.immediate.} =
 
   hint("Processing " & prc[0].getName & " as an async proc.")
 
+  let returnType = prc[3][0]
+  var subtypeName = ""
   # Verify that the return type is a PFuture[T]
-  if prc[3][0].kind == nnkIdent:
-    error("Expected return type of 'PFuture' got '" & $prc[3][0] & "'")
-  elif prc[3][0].kind == nnkBracketExpr:
-    if $prc[3][0][0] != "PFuture":
-      error("Expected return type of 'PFuture' got '" & $prc[3][0][0] & "'")
+  if returnType.kind == nnkIdent:
+    error("Expected return type of 'PFuture' got '" & $returnType & "'")
+  elif returnType.kind == nnkBracketExpr:
+    if $returnType[0] != "PFuture":
+      error("Expected return type of 'PFuture' got '" & $returnType[0] & "'")
+    subtypeName = $returnType[1].ident
+  elif returnType.kind == nnkEmpty:
+    subtypeName = "void"
   
   # TODO: Why can't I use genSym? I get illegal capture errors for Syms.
   # TODO: It seems genSym is broken. Change all usages back to genSym when fixed
@@ -763,20 +821,24 @@ macro async*(prc: stmt): stmt {.immediate.} =
     newVarStmt(retFutureSym, 
       newCall(
         newNimNode(nnkBracketExpr).add(
-          newIdentNode("newFuture"),
-          prc[3][0][1])))) # Get type from return type of this proc.
-
+          newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
+          newIdentNode(subtypeName))))) # Get type from return type of this proc
+  echo(treeRepr(outerProcBody))
   # -> iterator nameIter(): PFutureBase {.closure.} = 
   # ->   var result: T
   # ->   <proc_body>
   # ->   complete(retFuture, result)
   var iteratorNameSym = newIdentNode($prc[0].getName & "Iter") #genSym(nskIterator, $prc[0].ident & "Iter")
   var procBody = prc[6].processBody(retFutureSym)
-  procBody.insert(0, newNimNode(nnkVarSection).add(
-    newIdentDefs(newIdentNode("result"), prc[3][0][1]))) # -> var result: T
-  procBody.add(
-    newCall(newIdentNode("complete"),
-      retFutureSym, newIdentNode("result"))) # -> complete(retFuture, result)
+  if subtypeName != "void":
+    procBody.insert(0, newNimNode(nnkVarSection).add(
+      newIdentDefs(newIdentNode("result"), returnType[1]))) # -> var result: T
+    procBody.add(
+      newCall(newIdentNode("complete"),
+        retFutureSym, newIdentNode("result"))) # -> complete(retFuture, result)
+  else:
+    # -> complete(retFuture)
+    procBody.add(newCall(newIdentNode("complete"), retFutureSym))
   
   var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")],
                                 procBody, nnkIteratorDef)
@@ -811,6 +873,12 @@ macro async*(prc: stmt): stmt {.immediate.} =
   for i in 0 .. <result[4].len:
     if result[4][i].ident == !"async":
       result[4].del(i)
+  if subtypeName == "void":
+    # Add discardable pragma.
+    result[4].add(newIdentNode("discardable"))
+    if returnType.kind == nnkEmpty:
+      # Add PFuture[void]
+      result[3][0] = parseExpr("PFuture[void]")
 
   result[6] = outerProcBody
 
@@ -833,9 +901,13 @@ proc recvLine*(p: PDispatcher, socket: TSocketHandle): PFuture[string] {.async.}
   result = ""
   var c = ""
   while true:
+    #echo("1")
     c = await p.recv(socket, 1)
+    #echo("Received ", c.len)
     if c.len == 0:
+      #echo("returning")
       return
+    #echo("2")
     if c == "\r":
       c = await p.recv(socket, 1, MSG_PEEK)
       if c.len > 0 and c == "\L":
@@ -845,12 +917,14 @@ proc recvLine*(p: PDispatcher, socket: TSocketHandle): PFuture[string] {.async.}
     elif c == "\L":
       addNLIfEmpty()
       return
+    #echo("3")
     add(result.string, c)
+  #echo("4")
 
 when isMainModule:
   
   var p = newDispatcher()
-  var sock = socket()
+  var sock = p.socket()
   sock.setBlocking false
 
 
@@ -859,6 +933,7 @@ when isMainModule:
     proc main(p: PDispatcher): PFuture[int] {.async.} =
       discard await p.connect(sock, "irc.freenode.net", TPort(6667))
       while true:
+        echo("recvLine")
         var line = await p.recvLine(sock)
         echo("Line is: ", line.repr)
         if line == "":
@@ -882,7 +957,7 @@ when isMainModule:
   else:
     when false:
 
-      var f = p.connect(sock, "irc.freenode.org", TPort(6667))
+      var f = p.connect(sock, "irc.poop.nl", TPort(6667))
       f.callback =
         proc (future: PFuture[int]) =
           echo("Connected in future!")
@@ -898,11 +973,13 @@ when isMainModule:
       sock.bindAddr(TPort(6667))
       sock.listen()
       proc onAccept(future: PFuture[TSocketHandle]) =
-        echo "Accepted"
-        var t = p.send(future.read, "test\c\L")
+        let client = future.read
+        echo "Accepted ", client.cint
+        var t = p.send(client, "test\c\L")
         t.callback =
           proc (future: PFuture[int]) =
-            echo(future.read)
+            echo("Send: ", future.read)
+            client.close()
         
         var f = p.accept(sock)
         f.callback = onAccept
@@ -919,4 +996,4 @@ when isMainModule:
 
   
 
-  
\ No newline at end of file
+  
diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim
index 889912052..54a553173 100644
--- a/lib/pure/dynlib.nim
+++ b/lib/pure/dynlib.nim
@@ -92,7 +92,7 @@ elif defined(windows) or defined(dos):
   proc unloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib))
 
   proc symAddr(lib: TLibHandle, name: cstring): pointer =
-    result = GetProcAddress(cast[THINSTANCE](lib), name)
+    result = getProcAddress(cast[THINSTANCE](lib), name)
 
 else:
   {.error: "no implementation for dynlib".}
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 0ec007009..9ee98cbe6 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -9,7 +9,264 @@
 
 ## This module implements a high-level cross-platform sockets interface.
 
-import sockets2, os
+import sockets2, os, strutils, unsigned
+
+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'u8, 0'u8, 0'u8])
+
+proc IPv4_loopback*(): TIpAddress =
+  ## Returns the IPv4 loopback address (127.0.0.1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [127'u8, 0'u8, 0'u8, 1'u8])
+
+proc IPv4_broadcast*(): TIpAddress =
+  ## Returns the IPv4 broadcast address (255.255.255.255)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv4,
+    address_v4: [255'u8, 255'u8, 255'u8, 255'u8])
+
+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'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8])
+
+proc IPv6_loopback*(): TIpAddress =
+  ## Returns the IPv6 loopback address (::1)
+  result = TIpAddress(
+    family: IpAddressFamily.IPv6,
+    address_v6: [0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,0'u8,1'u8])
+
+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)
+
 
 type
   TSocket* = TSocketHandle
@@ -52,4 +309,4 @@ proc setBlocking*(s: TSocket, blocking: bool) {.tags: [].} =
     else:
       var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK
       if fcntl(s, F_SETFL, mode) == -1:
-        osError(osLastError())
\ No newline at end of file
+        osError(osLastError())
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index bfecc569a..faca17e98 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -260,11 +260,12 @@ proc osError*(errorCode: TOSErrorCode) =
   ##
   ## If the error code is ``0`` or an error message could not be retrieved,
   ## the message ``unknown OS error`` will be used.
-  let msg = osErrorMsg(errorCode)
-  if msg == "":
-    raise newException(EOS, "unknown OS error")
-  else:
-    raise newException(EOS, msg)
+  var e: ref EOS; new(e)
+  e.errorCode = errorCode.int32
+  e.msg = osErrorMsg(errorCode)
+  if e.msg == "":
+    e.msg = "unknown OS error"
+  raise e
 
 {.push stackTrace:off.}
 proc osLastError*(): TOSErrorCode =
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 582b3c960..5d6848565 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -606,7 +606,8 @@ elif not defined(useNimRtl):
     optionPoParentStreams: bool
     optionPoStdErrToStdOut: bool
 
-  proc startProcessAuxSpawn(data: TStartProcessData): TPid {.tags: [FExecIO, FReadEnv].}
+  when not defined(useFork):
+    proc startProcessAuxSpawn(data: TStartProcessData): TPid {.tags: [FExecIO, FReadEnv].}
   proc startProcessAuxFork(data: TStartProcessData): TPid {.tags: [FExecIO, FReadEnv].}
   {.push stacktrace: off, profiler: off.}
   proc startProcessAfterFork(data: ptr TStartProcessData) {.
@@ -664,7 +665,8 @@ elif not defined(useNimRtl):
     data.workingDir = workingDir
 
 
-    when defined(posix_spawn) and not defined(useFork) and not defined(useClone) and not defined(linux):
+    when defined(posix_spawn) and not defined(useFork) and 
+        not defined(useClone) and not defined(linux):
       pid = startProcessAuxSpawn(data)
     else:
       pid = startProcessAuxFork(data)
@@ -694,55 +696,56 @@ elif not defined(useNimRtl):
       discard close(pStdin[readIdx])
       discard close(pStdout[writeIdx])
 
-  proc startProcessAuxSpawn(data: TStartProcessData): TPid =
-    var attr: Tposix_spawnattr
-    var fops: Tposix_spawn_file_actions
-
-    template chck(e: expr) =
-      if e != 0'i32: osError(osLastError())
-
-    chck posix_spawn_file_actions_init(fops)
-    chck posix_spawnattr_init(attr)
-
-    var mask: Tsigset
-    chck sigemptyset(mask)
-    chck posix_spawnattr_setsigmask(attr, mask)
-    chck posix_spawnattr_setpgroup(attr, 0'i32)
-
-    chck posix_spawnattr_setflags(attr, POSIX_SPAWN_USEVFORK or
-                                        POSIX_SPAWN_SETSIGMASK or
-                                        POSIX_SPAWN_SETPGROUP)
-
-    if not data.optionPoParentStreams:
-      chck posix_spawn_file_actions_addclose(fops, data.pStdin[writeIdx])
-      chck posix_spawn_file_actions_adddup2(fops, data.pStdin[readIdx], readIdx)
-      chck posix_spawn_file_actions_addclose(fops, data.pStdout[readIdx])
-      chck posix_spawn_file_actions_adddup2(fops, data.pStdout[writeIdx], writeIdx)
-      chck posix_spawn_file_actions_addclose(fops, data.pStderr[readIdx])
-      if data.optionPoStdErrToStdOut:
-        chck posix_spawn_file_actions_adddup2(fops, data.pStdout[writeIdx], 2)
+  when not defined(useFork):
+    proc startProcessAuxSpawn(data: TStartProcessData): TPid =
+      var attr: Tposix_spawnattr
+      var fops: Tposix_spawn_file_actions
+
+      template chck(e: expr) =
+        if e != 0'i32: osError(osLastError())
+
+      chck posix_spawn_file_actions_init(fops)
+      chck posix_spawnattr_init(attr)
+
+      var mask: Tsigset
+      chck sigemptyset(mask)
+      chck posix_spawnattr_setsigmask(attr, mask)
+      chck posix_spawnattr_setpgroup(attr, 0'i32)
+
+      chck posix_spawnattr_setflags(attr, POSIX_SPAWN_USEVFORK or
+                                          POSIX_SPAWN_SETSIGMASK or
+                                          POSIX_SPAWN_SETPGROUP)
+
+      if not data.optionPoParentStreams:
+        chck posix_spawn_file_actions_addclose(fops, data.pStdin[writeIdx])
+        chck posix_spawn_file_actions_adddup2(fops, data.pStdin[readIdx], readIdx)
+        chck posix_spawn_file_actions_addclose(fops, data.pStdout[readIdx])
+        chck posix_spawn_file_actions_adddup2(fops, data.pStdout[writeIdx], writeIdx)
+        chck posix_spawn_file_actions_addclose(fops, data.pStderr[readIdx])
+        if data.optionPoStdErrToStdOut:
+          chck posix_spawn_file_actions_adddup2(fops, data.pStdout[writeIdx], 2)
+        else:
+          chck posix_spawn_file_actions_adddup2(fops, data.pStderr[writeIdx], 2)
+
+      var res: cint
+      # FIXME: chdir is global to process
+      if data.workingDir.len > 0:
+        setCurrentDir($data.workingDir)
+      var pid: TPid
+
+      if data.optionPoUsePath:
+        res = posix_spawnp(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv)
       else:
-        chck posix_spawn_file_actions_adddup2(fops, data.pStderr[writeIdx], 2)
-
-    var res: cint
-    # FIXME: chdir is global to process
-    if data.workingDir.len > 0:
-      setCurrentDir($data.workingDir)
-    var pid: TPid
-
-    if data.optionPoUsePath:
-      res = posix_spawnp(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv)
-    else:
-      res = posix_spawn(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv)
+        res = posix_spawn(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv)
 
-    discard posix_spawn_file_actions_destroy(fops)
-    discard posix_spawnattr_destroy(attr)
-    chck res
-    return pid
+      discard posix_spawn_file_actions_destroy(fops)
+      discard posix_spawnattr_destroy(attr)
+      chck res
+      return pid
 
   proc startProcessAuxFork(data: TStartProcessData): TPid =
     if pipe(data.pErrorPipe) != 0:
-        osError(osLastError())
+      osError(osLastError())
 
     finally:
       discard close(data.pErrorPipe[readIdx])
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
index 3f9686e1e..bd8836f7c 100644
--- a/lib/pure/parsesql.nim
+++ b/lib/pure/parsesql.nim
@@ -267,7 +267,7 @@ proc getSymbol(c: var TSqlLexer, tok: var TToken) =
   while true: 
     add(tok.literal, buf[pos])
     Inc(pos)
-    if not (buf[pos] in {'a'..'z','A'..'Z','0'..'9','_','$', '\128'..'\255'}):
+    if buf[pos] notin {'a'..'z','A'..'Z','0'..'9','_','$', '\128'..'\255'}:
       break
   c.bufpos = pos
   tok.kind = tkIdentifier
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
index 6482a01a6..085344e3e 100644
--- a/lib/pure/selectors.nim
+++ b/lib/pure/selectors.nim
@@ -15,6 +15,7 @@ when defined(linux): import posix, epoll
 elif defined(windows): import winlean
 
 proc hash*(x: TSocketHandle): THash {.borrow.}
+proc `$`*(x: TSocketHandle): string {.borrow.}
 
 type
   TEvent* = enum
@@ -31,7 +32,7 @@ when defined(linux) or defined(nimdoc):
   type
     PSelector* = ref object
       epollFD: cint
-      events: array[64, ptr epoll_event]
+      events: array[64, epoll_event]
       fds: TTable[TSocketHandle, PSelectorKey]
   
   proc createEventStruct(events: set[TEvent], fd: TSocketHandle): epoll_event =
@@ -39,17 +40,14 @@ when defined(linux) or defined(nimdoc):
       result.events = EPOLLIN
     if EvWrite in events:
       result.events = result.events or EPOLLOUT
+    result.events = result.events or EPOLLRDHUP
     result.data.fd = fd.cint
   
   proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent],
       data: PObject): PSelectorKey {.discardable.} =
     ## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent
     ## ``events``.
-    if s.fds.hasKey(fd):
-      raise newException(EInvalidValue, "File descriptor already exists.")
-    
     var event = createEventStruct(events, fd)
-  
     if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0:
       OSError(OSLastError())
   
@@ -61,22 +59,19 @@ when defined(linux) or defined(nimdoc):
   proc update*(s: PSelector, fd: TSocketHandle,
       events: set[TEvent]): PSelectorKey {.discardable.} =
     ## Updates the events which ``fd`` wants notifications for.
-    if not s.fds.hasKey(fd):
-      raise newException(EInvalidValue, "File descriptor not found.")
-    var event = createEventStruct(events, fd)
-    
-    s.fds[fd].events = events
-    echo("About to update")
-    if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0:
-      OSError(OSLastError())
-    echo("finished updating")
-    result = s.fds[fd]
+    if s.fds[fd].events != events:
+      var event = createEventStruct(events, fd)
+      
+      s.fds[fd].events = events
+      if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0:
+        OSError(OSLastError())
+      result = s.fds[fd]
   
   proc unregister*(s: PSelector, fd: TSocketHandle): PSelectorKey {.discardable.} =
-    if not s.fds.hasKey(fd):
-      raise newException(EInvalidValue, "File descriptor not found.")
     if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
-      OSError(OSLastError())
+      let err = OSLastError()
+      if err.cint notin {ENOENT, EBADF}: # TODO: Why do we sometimes get an EBADF? Is this normal?
+        OSError(err)
     result = s.fds[fd]
     s.fds.del(fd)
 
@@ -84,6 +79,15 @@ when defined(linux) or defined(nimdoc):
     if s.epollFD.close() != 0: OSError(OSLastError())
     dealloc(addr s.events) # TODO: Test this
   
+  proc epollHasFd(s: PSelector, fd: TSocketHandle): bool =
+    result = true
+    var event = createEventStruct(s.fds[fd].events, fd)
+    if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0:
+      let err = osLastError()
+      if err.cint in {ENOENT, EBADF}:
+        return false
+      OSError(OSLastError())
+  
   proc select*(s: PSelector, timeout: int): seq[TReadyInfo] =
     ##
     ## The ``events`` field of the returned ``key`` contains the original events
@@ -91,29 +95,44 @@ when defined(linux) or defined(nimdoc):
     ## of the ``TReadyInfo`` tuple which determines which events are ready
     ## on the ``fd``.
     result = @[]
-    
-    let evNum = epoll_wait(s.epollFD, s.events[0], 64.cint, timeout.cint)
+    let evNum = epoll_wait(s.epollFD, addr s.events[0], 64.cint, timeout.cint)
     if evNum < 0: OSError(OSLastError())
     if evNum == 0: return @[]
     for i in 0 .. <evNum:
+      let fd = s.events[i].data.fd.TSocketHandle
+    
       var evSet: set[TEvent] = {}
       if (s.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead}
       if (s.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite}
-      
-      let selectorKey = s.fds[s.events[i].data.fd.TSocketHandle]
+      let selectorKey = s.fds[fd]
+      assert selectorKey != nil
       result.add((selectorKey, evSet))
+
+      #echo("Epoll: ", result[i].key.fd, " ", result[i].events, " ", result[i].key.events)
   
   proc newSelector*(): PSelector =
     new result
     result.epollFD = epoll_create(64)
-    result.events = cast[array[64, ptr epoll_event]](alloc0(sizeof(epoll_event)*64))
+    result.events = cast[array[64, epoll_event]](alloc0(sizeof(epoll_event)*64))
     result.fds = initTable[TSocketHandle, PSelectorKey]()
     if result.epollFD < 0:
       OSError(OSLastError())
 
   proc contains*(s: PSelector, fd: TSocketHandle): bool =
     ## Determines whether selector contains a file descriptor.
-    return s.fds.hasKey(fd)
+    if s.fds.hasKey(fd):
+      # Ensure the underlying epoll instance still contains this fd.
+      result = epollHasFd(s, fd)
+    else:
+      return false
+
+  proc contains*(s: PSelector, key: PSelectorKey): bool =
+    ## Determines whether selector contains this selector key. More accurate
+    ## than checking if the file descriptor is in the selector because it
+    ## ensures that the keys are equal. File descriptors may not always be
+    ## unique especially when an fd is closed and then a new one is opened,
+    ## the new one may have the same value.
+    return key.fd in s and s.fds[key.fd] == key
 
   proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey =
     ## Retrieves the selector key for ``fd``.
@@ -247,4 +266,4 @@ when isMainModule:
   
   
   
-  
\ No newline at end of file
+  
diff --git a/lib/pure/sockets2.nim b/lib/pure/sockets2.nim
index 3542a0694..290f414b4 100644
--- a/lib/pure/sockets2.nim
+++ b/lib/pure/sockets2.nim
@@ -24,6 +24,10 @@ else:
 export TSocketHandle, TSockaddr_in, TAddrinfo, INADDR_ANY, TSockAddr, TSockLen,
   inet_ntoa, recv, `==`, connect, send, accept
 
+export
+  SO_ERROR,
+  SOL_SOCKET
+
 type
   
   TPort* = distinct uint16  ## port type
@@ -208,6 +212,24 @@ proc htons*(x: int16): int16 =
   ## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
   result = sockets2.ntohs(x)
 
+proc getSockOptInt*(socket: TSocketHandle, level, optname: int): int {.
+  tags: [FReadIO].} = 
+  ## getsockopt for integer options.
+  var res: cint
+  var size = sizeof(res).TSocklen
+  if getsockopt(socket, cint(level), cint(optname), 
+                addr(res), addr(size)) < 0'i32:
+    osError(osLastError())
+  result = int(res)
+
+proc setSockOptInt*(socket: TSocketHandle, level, optname, optval: int) {.
+  tags: [FWriteIO].} =
+  ## setsockopt for integer options.
+  var value = cint(optval)
+  if setsockopt(socket, cint(level), cint(optname), addr(value),  
+                sizeof(value).TSocklen) < 0'i32:
+    osError(osLastError())
+
 when defined(Windows):
   var wsa: TWSADATA
   if WSAStartup(0x0101'i16, addr wsa) != 0: OSError(OSLastError())
diff --git a/lib/system.nim b/lib/system.nim
index 171c7b6b8..41624bb05 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -260,6 +260,7 @@ type
                               ## system raises.
   EIO* = object of ESystem    ## raised if an IO error occured.
   EOS* = object of ESystem    ## raised if an operating system service failed.
+    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
@@ -1164,13 +1165,13 @@ when not defined(nimrodVM):
       ## from it before writing to it is undefined behaviour!
       ## The allocated memory belongs to its allocating thread!
       ## Use `allocShared` to allocate from a shared heap.
-    proc alloc*(T: typedesc, size = 1): ptr T {.inline.} =
+    proc createU*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
       ## allocates a new memory block with at least ``T.sizeof * size``
-      ## bytes. The block has to be freed with ``realloc(block, 0)`` or
-      ## ``dealloc(block)``. The block is not initialized, so reading
+      ## bytes. The block has to be freed with ``resize(block, 0)`` or
+      ## ``free(block)``. The block is not initialized, so reading
       ## from it before writing to it is undefined behaviour!
       ## The allocated memory belongs to its allocating thread!
-      ## Use `allocShared` to allocate from a shared heap.
+      ## Use `createSharedU` to allocate from a shared heap.
       cast[ptr T](alloc(T.sizeof * size))
     proc alloc0*(size: int): pointer {.noconv, rtl, tags: [].}
       ## allocates a new memory block with at least ``size`` bytes. The
@@ -1179,13 +1180,13 @@ when not defined(nimrodVM):
       ## containing zero, so it is somewhat safer than ``alloc``.
       ## The allocated memory belongs to its allocating thread!
       ## Use `allocShared0` to allocate from a shared heap.
-    proc alloc0*(T: typedesc, size = 1): ptr T {.inline.} =
+    proc create*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
       ## allocates a new memory block with at least ``T.sizeof * size``
-      ## bytes. The block has to be freed with ``realloc(block, 0)`` or
-      ## ``dealloc(block)``. The block is initialized with all bytes
-      ## containing zero, so it is somewhat safer than ``alloc``.
+      ## bytes. The block has to be freed with ``resize(block, 0)`` or
+      ## ``free(block)``. The block is initialized with all bytes
+      ## containing zero, so it is somewhat safer than ``createU``.
       ## The allocated memory belongs to its allocating thread!
-      ## Use `allocShared0` to allocate from a shared heap.
+      ## Use `createShared` to allocate from a shared heap.
       cast[ptr T](alloc0(T.sizeof * size))
     proc realloc*(p: pointer, newSize: int): pointer {.noconv, rtl, tags: [].}
       ## grows or shrinks a given memory block. If p is **nil** then a new
@@ -1195,14 +1196,14 @@ when not defined(nimrodVM):
       ## be freed with ``dealloc``.
       ## The allocated memory belongs to its allocating thread!
       ## Use `reallocShared` to reallocate from a shared heap.
-    proc reallocType*[T](p: ptr T, newSize: int): ptr T {.inline.} =
+    proc resize*[T](p: ptr T, newSize: Natural): ptr T {.inline.} =
       ## grows or shrinks a given memory block. If p is **nil** then a new
       ## memory block is returned. In either way the block has at least
       ## ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is not
-      ## **nil** ``realloc`` calls ``dealloc(p)``. In other cases the block
-      ## has to be freed with ``dealloc``. The allocated memory belongs to
+      ## **nil** ``resize`` calls ``free(p)``. In other cases the block
+      ## has to be freed with ``free``. The allocated memory belongs to
       ## its allocating thread!
-      ## Use `reallocShared` to reallocate from a shared heap.
+      ## Use `resizeShared` to reallocate from a shared heap.
       cast[ptr T](realloc(p, T.sizeof * newSize))
     proc dealloc*(p: pointer) {.noconv, rtl, tags: [].}
       ## frees the memory allocated with ``alloc``, ``alloc0`` or
@@ -1212,16 +1213,18 @@ when not defined(nimrodVM):
       ## or other memory may be corrupted. 
       ## The freed memory must belong to its allocating thread!
       ## Use `deallocShared` to deallocate from a shared heap.
+    proc free*[T](p: ptr T) {.inline.} =
+      dealloc(p)
     proc allocShared*(size: int): pointer {.noconv, rtl.}
       ## allocates a new memory block on the shared heap with at
       ## least ``size`` bytes. The block has to be freed with
       ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
       ## is not initialized, so reading from it before writing to it is 
       ## undefined behaviour!
-    proc allocShared*(T: typedesc, size: int): ptr T {.inline.} =
+    proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
       ## allocates a new memory block on the shared heap with at
       ## least ``T.sizeof * size`` bytes. The block has to be freed with
-      ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
+      ## ``resizeShared(block, 0)`` or ``freeShared(block)``. The block
       ## is not initialized, so reading from it before writing to it is 
       ## undefined behaviour!
       cast[ptr T](allocShared(T.sizeof * size))
@@ -1231,25 +1234,25 @@ when not defined(nimrodVM):
       ## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
       ## The block is initialized with all bytes
       ## containing zero, so it is somewhat safer than ``allocShared``.
-    proc allocShared0*(T: typedesc, size: int): ptr T {.inline.} =
+    proc createShared*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
       ## allocates a new memory block on the shared heap with at 
       ## least ``T.sizeof * size`` bytes. The block has to be freed with
-      ## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
+      ## ``resizeShared(block, 0)`` or ``freeShared(block)``.
       ## The block is initialized with all bytes
-      ## containing zero, so it is somewhat safer than ``allocShared``.
-      cast[ptr T](allocShared(T.sizeof * size))
+      ## containing zero, so it is somewhat safer than ``createSharedU``.
+      cast[ptr T](allocShared0(T.sizeof * size))
     proc reallocShared*(p: pointer, newSize: int): pointer {.noconv, rtl.}
       ## grows or shrinks a given memory block on the heap. If p is **nil**
       ## then a new memory block is returned. In either way the block has at
       ## least ``newSize`` bytes. If ``newSize == 0`` and p is not **nil**
       ## ``reallocShared`` calls ``deallocShared(p)``. In other cases the
       ## block has to be freed with ``deallocShared``.
-    proc reallocSharedType*[T](p: ptr T, newSize: int): ptr T {.inline.} =
+    proc resizeShared*[T](p: ptr T, newSize: Natural): ptr T {.inline.} =
       ## grows or shrinks a given memory block on the heap. If p is **nil**
       ## then a new memory block is returned. In either way the block has at
       ## least ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is
-      ## not **nil** ``reallocShared`` calls ``deallocShared(p)``. In other
-      ## cases the block has to be freed with ``deallocShared``.
+      ## not **nil** ``resizeShared`` calls ``freeShared(p)``. In other
+      ## cases the block has to be freed with ``freeShared``.
       cast[ptr T](reallocShared(p, T.sizeof * newSize))
     proc deallocShared*(p: pointer) {.noconv, rtl.}
       ## frees the memory allocated with ``allocShared``, ``allocShared0`` or
@@ -1257,6 +1260,13 @@ when not defined(nimrodVM):
       ## free the memory a leak occurs; if one tries to access freed
       ## memory (or just freeing it twice!) a core dump may happen
       ## or other memory may be corrupted.
+    proc freeShared*[T](p: ptr T) {.inline.} =
+      ## frees the memory allocated with ``createShared``, ``createSharedU`` or
+      ## ``resizeShared``. This procedure is dangerous! If one forgets to
+      ## free the memory a leak occurs; if one tries to access freed
+      ## memory (or just freeing it twice!) a core dump may happen
+      ## or other memory may be corrupted.
+      deallocShared(p)
 
 proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.}
   ## swaps the values `a` and `b`. This is often more efficient than
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 74ef9c9ec..4d87cf4b2 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -456,6 +456,7 @@ var
 
   SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint
   SO_EXCLUSIVEADDRUSE* {.importc, header: "Winsock2.h".}: cint # disallow local address reuse
+  SO_ERROR* {.importc, header: "Winsock2.h".}: cint
 
 proc `==`*(x, y: TSocketHandle): bool {.borrow.}
 
diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim
index bde5bf8c8..91dfb7932 100644
--- a/tests/async/tasyncawait.nim
+++ b/tests/async/tasyncawait.nim
@@ -14,30 +14,31 @@ const
 
 var clientCount = 0
 
-proc sendMessages(disp: PDispatcher, client: TSocketHandle): PFuture[int] {.async.} =
+proc sendMessages(disp: PDispatcher, client: TSocketHandle) {.async.} =
   for i in 0 .. <messagesToSend:
-    discard await disp.send(client, "Message " & $i & "\c\L") 
+    await disp.send(client, "Message " & $i & "\c\L")
 
-proc launchSwarm(disp: PDispatcher, port: TPort): PFuture[int] {.async.} =
+proc launchSwarm(disp: PDispatcher, port: TPort) {.async.} =
   for i in 0 .. <swarmSize:
-    var sock = socket()
+    var sock = disp.socket()
+
     #disp.register(sock)
-    discard await disp.connect(sock, "localhost", port)
+    await disp.connect(sock, "localhost", port)
     when true:
-      discard await sendMessages(disp, sock)
-      sock.close()
+      await sendMessages(disp, sock)
+      disp.close(sock)
     else:
       # Issue #932: https://github.com/Araq/Nimrod/issues/932
       var msgFut = sendMessages(disp, sock)
       msgFut.callback =
         proc () =
-          sock.close()
+          disp.close(sock)
 
-proc readMessages(disp: PDispatcher, client: TSocketHandle): PFuture[int] {.async.} =
+proc readMessages(disp: PDispatcher, client: TSocketHandle) {.async.} =
   while true:
     var line = await disp.recvLine(client)
     if line == "":
-      client.close()
+      disp.close(client)
       clientCount.inc
       break
     else:
@@ -46,16 +47,18 @@ proc readMessages(disp: PDispatcher, client: TSocketHandle): PFuture[int] {.asyn
       else:
         doAssert false
 
-proc createServer(disp: PDispatcher, port: TPort): PFuture[int] {.async.} =
-  var server = socket()
+proc createServer(disp: PDispatcher, port: TPort) {.async.} =
+  var server = disp.socket()
   #disp.register(server)
   server.bindAddr(port)
   server.listen()
   while true:
-    discard readMessages(disp, await disp.accept(server))
+    var client = await disp.accept(server)
+    readMessages(disp, client)
+    # TODO: Test: readMessages(disp, await disp.accept(server))
 
-discard disp.createServer(TPort(10335))
-discard disp.launchSwarm(TPort(10335))
+disp.createServer(TPort(10335))
+disp.launchSwarm(TPort(10335))
 while true:
   disp.poll()
   if clientCount == swarmSize: break
diff --git a/tests/bind/tbindtypedesc.nim b/tests/bind/tinvalidbindtypedesc.nim
index d6fbae537..7d97d2e0d 100644
--- a/tests/bind/tbindtypedesc.nim
+++ b/tests/bind/tinvalidbindtypedesc.nim
@@ -1,6 +1,5 @@
 discard """
   line: 11
-  file: "tbindtypedesc.nim"
   errormsg: "type mismatch: got (typedesc[float], string)"
 """
 
diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim
index b72e8b00c..0014cff46 100644
--- a/tests/effects/teffects1.nim
+++ b/tests/effects/teffects1.nim
@@ -1,5 +1,5 @@
 discard """
-  line: 1855
+  line: 1913
   file: "system.nim"
   errormsg: "can raise an unlisted exception: ref EIO"
 """
diff --git a/tests/generics/tbadgenericlambda.nim b/tests/generics/tbadgenericlambda.nim
new file mode 100644
index 000000000..5e406cacc
--- /dev/null
+++ b/tests/generics/tbadgenericlambda.nim
@@ -0,0 +1,7 @@
+discard """
+  msg: "nested proc can have generic parameters only when"
+  line: 6
+"""
+
+let x = proc (x, y): auto = x + y
+
diff --git a/tests/generics/tgenericlambda.nim b/tests/generics/tgenericlambda.nim
index f7aafe1d9..eb6ada3e5 100644
--- a/tests/generics/tgenericlambda.nim
+++ b/tests/generics/tgenericlambda.nim
@@ -1,5 +1,5 @@
 discard """
-  output: "10\n10\n1\n2\n3"
+  output: "10\n10\n1\n2\n3\n15"
 """
 
 proc test(x: proc (a, b: int): int) =
@@ -16,3 +16,8 @@ proc foreach[T](s: seq[T], body: proc(x: T)) =
 foreach(@[1,2,3]) do (x):
   echo x
 
+proc foo =
+  let x = proc (a, b: int): auto = a + b
+  echo x(5, 10)
+
+foo()
diff --git a/tests/generics/tgenericshardcases.nim b/tests/generics/tgenericshardcases.nim
index 2ef63bc20..e3b805db6 100644
--- a/tests/generics/tgenericshardcases.nim
+++ b/tests/generics/tgenericshardcases.nim
@@ -14,7 +14,8 @@ macro selectType(a, b: typedesc): typedesc =
 type
   Foo[T] = object
     data1: array[T.high, int]
-    data2: array[typeNameLen(T), float] # data3: array[0..T.typeNameLen, selectType(float, int)]
+    data2: array[typeNameLen(T), float]
+    data3: array[0..T.typeNameLen, selectType(float, int)]
 
   MyEnum = enum A, B, C, D
 
@@ -27,10 +28,15 @@ echo high(f1.data2) # (MyEnum.len = 6) - 1 == 5
 echo high(f2.data1) # 127 - 1 == 126
 echo high(f2.data2) # int8.len - 1 == 3
 
-#static:
-# assert high(f1.data1) == ord(D)
-# assert high(f1.data2) == 6 # length of MyEnum
+static:
+  assert high(f1.data1) == ord(C)
+  assert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high
 
-# assert high(f2.data1) == 127
-# assert high(f2.data2) == 4 # length of int8
+  assert high(f2.data1) == 126
+  assert high(f2.data2) == 3 
+
+  assert high(f1.data3) == 6 # length of MyEnum
+  assert high(f2.data3) == 4 # length of int8
+
+  assert f2.data3[0] is float
 
diff --git a/tests/generics/tlateboundstatic.nim b/tests/generics/tlateboundstatic.nim
new file mode 100644
index 000000000..f68f95f8d
--- /dev/null
+++ b/tests/generics/tlateboundstatic.nim
@@ -0,0 +1,16 @@
+discard """
+  msg: "array[0..3, int]"
+"""
+
+type
+  KK[I: static[int]] = object
+   x: array[I, int]
+
+proc foo(a: static[string]): KK[a.len] =
+  result.x[0] = 12
+
+var x = foo "test"
+
+import typetraits
+static: echo x.x.type.name
+
diff --git a/tests/generics/tsigtypeop.nim b/tests/generics/tsigtypeop.nim
new file mode 100644
index 000000000..4c863cba1
--- /dev/null
+++ b/tests/generics/tsigtypeop.nim
@@ -0,0 +1,9 @@
+type
+  Vec3[T] = array[3, T]
+
+proc foo(x: Vec3, y: Vec3.T, z: x.T): x.type.T =
+  return 10
+
+var y: Vec3[int] = [1, 2, 3]
+var z: int = foo(y, 3, 4)
+
diff --git a/tests/iter/tchainediterators.nim b/tests/iter/tchainediterators.nim
new file mode 100644
index 000000000..18d096761
--- /dev/null
+++ b/tests/iter/tchainediterators.nim
@@ -0,0 +1,38 @@
+discard """
+  output: '''16
+32
+48
+64
+128
+192
+'''
+"""
+
+iterator gaz(it: iterator{.inline.}): type(it) =
+  for x in it:
+    yield x*2
+
+iterator baz(it: iterator{.inline.}) =
+  for x in gaz(it):
+    yield x*2
+
+type T1 = auto
+
+iterator bar(it: iterator: T1{.inline.}): T1 =
+  for x in baz(it):
+    yield x*2
+
+iterator foo[T](x: iterator: T{.inline.}): T =
+  for e in bar(x):
+    yield e*2
+
+var s = @[1, 2, 3]
+
+# pass an interator several levels deep:
+for x in s.items.foo:
+  echo x
+
+# use some complex iterator as an input for another one:
+for x in s.items.baz.foo:
+  echo x
+
diff --git a/tests/iter/titerable.nim b/tests/iter/titerable.nim
new file mode 100644
index 000000000..3ec79f68d
--- /dev/null
+++ b/tests/iter/titerable.nim
@@ -0,0 +1,26 @@
+discard """
+  output: '''2
+4
+6
+4
+8
+12
+'''
+"""
+
+iterator map[T, U](s: iterator:T{.inline.}, f: proc(x: T): U): U =
+  for e in s: yield f(e)
+
+template toSeq(s: expr): expr =
+  var res = newSeq[type(s)](0)
+  for e in s: res.add(e)
+  res
+
+var s1 = @[1, 2, 3]
+for x in map(s1.items, proc (a:int): int = a*2):
+  echo x
+
+var s2 = toSeq(map(s1.items, proc (a:int): int = a*4))
+for x in s2:
+  echo x
+
diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim
index b1377443b..6d7c569e0 100644
--- a/tests/metatype/tstaticparams.nim
+++ b/tests/metatype/tstaticparams.nim
@@ -1,6 +1,6 @@
 discard """
   file: "tstaticparams.nim"
-  output: "abracadabra\ntest\n3"
+  output: "abracadabra\ntest\n3\n15\n4\n2"
 """
 
 type 
@@ -11,8 +11,11 @@ type
     data: array[I, T]
 
   TA1[T; I: static[int]] = array[I, T]
-  # TA2[T; I: static[int]] = array[0..I, T]
-  # TA3[T; I: static[int]] = array[I-1, T]
+  TA2[T; I: static[int]] = array[0..I, T]
+  TA3[T; I: static[int]] = array[I-1, T]
+
+  TObj = object
+    x: TA3[int, 3]
 
 proc takeFoo(x: TFoo) =
   echo "abracadabra"
@@ -26,6 +29,30 @@ echo high(y.data)
 
 var
   t1: TA1[float, 1]
-  # t2: TA2[string, 4]
-  # t3: TA3[int, 10]
+  t2: TA2[string, 4]
+  t3: TA3[int, 10]
+  t4: TObj
+
+# example from the manual:
+type
+  Matrix[M,N: static[int]; T] = array[0..(M*N - 1), T]
+    # Note how `Number` is just a type constraint here, while
+    # `static[int]` requires us to supply a compile-time int value
+
+  AffineTransform2D[T] = Matrix[3, 3, T]
+  AffineTransform3D[T] = Matrix[4, 4, T]
+
+var m: AffineTransform3D[float]
+echo high(m)
+
+proc getRows(mtx: Matrix): int =
+  result = mtx.M
+
+echo getRows(m)
+
+# issue 997
+type TTest[T: static[int], U: static[int]] = array[0..T*U, int]
+type TTestSub[N: static[int]] = TTest[1, N]
 
+var z: TTestSub[2]
+echo z.high
diff --git a/tests/metatype/tusertypeclasses.nim b/tests/metatype/tusertypeclasses.nim
index 5b04c490f..a5d575dbf 100644
--- a/tests/metatype/tusertypeclasses.nim
+++ b/tests/metatype/tusertypeclasses.nim
@@ -26,7 +26,7 @@ foo 10
 foo "test"
 foo(@[TObj(x: 10), TObj(x: 20)])
 
-proc intval(x: int) = discard
+proc intval(x: int): int = 10
 
 # check real and virtual fields
 type
@@ -34,7 +34,8 @@ type
     T.x
     y(T)
     intval T.y
-    
+    let z = intval(T.y)
+
 proc y(x: TObj): int = 10
 
 proc testFoo(x: TFoo) = discard
diff --git a/tests/metatype/udtcmanual.nim b/tests/metatype/udtcmanual.nim
index f22bd6ac6..dd44298dc 100644
--- a/tests/metatype/udtcmanual.nim
+++ b/tests/metatype/udtcmanual.nim
@@ -25,7 +25,7 @@ type
     C.len is Ordinal
     items(c) is iterator
     for value in C:
-      value.type is T
+      type(value) is T
 
 proc takesIntContainer(c: Container[int]) =
   for e in c: echo e
diff --git a/tests/overload/tissue966.nim b/tests/overload/tissue966.nim
new file mode 100644
index 000000000..2911348cf
--- /dev/null
+++ b/tests/overload/tissue966.nim
@@ -0,0 +1,12 @@
+discard """
+  errormsg: "type mismatch: got (PTest)"
+"""
+
+type
+  PTest = ref object
+
+proc test(x: PTest, y: int) = nil
+
+var buf: PTest
+buf.test()
+
diff --git a/tests/parser/tstrongspaces.nim b/tests/parser/tstrongspaces.nim
new file mode 100644
index 000000000..91506daf0
--- /dev/null
+++ b/tests/parser/tstrongspaces.nim
@@ -0,0 +1,52 @@
+#! strongSpaces
+
+discard """
+  output: '''35
+77
+(Field0: 1, Field1: 2, Field2: 2)
+ha
+true
+tester args
+all
+all args
+'''
+"""
+
+echo 2+5 * 5
+
+let foo = 77
+echo $foo
+
+echo (1, 2, 2)
+
+template `&`(a, b: int): expr = a and b
+template `|`(a, b: int): expr = a - b
+template `++`(a, b: int): expr = a + b == 8009
+
+when true:
+  let b = 66
+  let c = 90
+  let bar = 8000
+  if foo+4 * 4 == 8 and b&c | 9  ++
+      bar:
+    echo "ho"
+  else:
+    echo "ha"
+
+  let booA = foo+4 * 4  -  b&c | 9  +
+      bar
+  # is parsed as
+  let booB = ((foo+4)*4) - ((b&c) | 9) + bar
+
+  echo booA == booB
+
+
+template `|`(a, b): expr = (if a.len > 0: a else: b)
+
+const
+  tester = "tester"
+  args = "args"
+
+echo tester & " " & args|"all"
+echo "all"  |  tester & " " & args
+echo "all"|tester & " " & args
diff --git a/tests/static/tstaticparammacro.nim b/tests/static/tstaticparammacro.nim
new file mode 100644
index 000000000..7fb9e2014
--- /dev/null
+++ b/tests/static/tstaticparammacro.nim
@@ -0,0 +1,52 @@
+discard """
+  msg: '''letters
+aa
+bb
+numbers
+11
+22
+AST a 
+[(11, 22), (33, 44)]
+AST b 
+(e: [55, 66], f: [77, 88])
+55
+'''
+"""
+
+import macros
+
+type
+  TConfig = tuple
+    letters: seq[string]
+    numbers:seq[int]
+
+const data: Tconfig = (@["aa", "bb"], @[11, 22])
+
+macro mymacro(data: static[TConfig]): stmt =
+  echo "letters"
+  for s in items(data.letters):
+    echo s
+  echo "numbers"
+  for n in items(data.numbers):
+    echo n
+
+mymacro(data)
+
+type
+  Ta = seq[tuple[c:int, d:int]]
+  Tb = tuple[e:seq[int], f:seq[int]]
+
+const
+  a : Ta = @[(11, 22), (33, 44)]
+  b : Tb = (@[55,66], @[77, 88])
+
+macro mA(data: static[Ta]): stmt =
+  echo "AST a \n", repr(data)
+
+macro mB(data: static[Tb]): stmt =
+  echo "AST b \n", repr(data)
+  echo data.e[0]
+
+mA(a)
+mB(b)
+
diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim
index 7775091a1..6e488bab4 100644
--- a/tests/stdlib/tpegs.nim
+++ b/tests/stdlib/tpegs.nim
@@ -72,7 +72,7 @@ type
     rule: TNode                   ## the rule that the symbol refers to
   TNode {.final, shallow.} = object
     case kind: TPegKind
-    of pkEmpty..pkWhitespace: discard
+    of pkEmpty..pkWhitespace: nil
     of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string
     of pkChar, pkGreedyRepChar: ch: char
     of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char]
diff --git a/tests/system/alloc.nim b/tests/system/alloc.nim
index 665b448ac..7abefec2a 100644
--- a/tests/system/alloc.nim
+++ b/tests/system/alloc.nim
@@ -2,44 +2,51 @@ var x: ptr int
 
 x = cast[ptr int](alloc(7))
 assert x != nil
-
-x = alloc(int, 3)
+x = cast[ptr int](x.realloc(2))
 assert x != nil
 x.dealloc()
 
-x = alloc0(int, 4)
+x = createU(int, 3)
+assert x != nil
+x.free()
+
+x = create(int, 4)
 assert cast[ptr array[4, int]](x)[0] == 0
 assert cast[ptr array[4, int]](x)[1] == 0
 assert cast[ptr array[4, int]](x)[2] == 0
 assert cast[ptr array[4, int]](x)[3] == 0
 
-x = cast[ptr int](x.realloc(2))
-assert x != nil
-
-x = x.reallocType(4)
+x = x.resize(4)
 assert x != nil
-x.dealloc()
+x.free()
 
 x = cast[ptr int](allocShared(100))
 assert x != nil
 deallocShared(x)
 
-x = allocShared(int, 3)
+x = createSharedU(int, 3)
 assert x != nil
-x.deallocShared()
+x.freeShared()
 
-x = allocShared0(int, 3)
+x = createShared(int, 3)
 assert x != nil
 assert cast[ptr array[3, int]](x)[0] == 0
 assert cast[ptr array[3, int]](x)[1] == 0
 assert cast[ptr array[3, int]](x)[2] == 0
 
-x = cast[ptr int](reallocShared(x, 2))
 assert x != nil
+x = cast[ptr int](x.resizeShared(2))
+assert x != nil
+x.freeShared()
 
-x = reallocType(x, 12)
+x = create(int, 10)
 assert x != nil
+x = x.resize(12)
+assert x != nil
+x.dealloc()
 
-x = reallocSharedType(x, 1)
+x = createShared(int, 1)
+assert x != nil
+x = x.resizeShared(1)
 assert x != nil
-x.deallocShared()
+x.freeShared()
diff --git a/tests/template/tissue909.nim b/tests/template/tissue909.nim
new file mode 100644
index 000000000..5b57a3558
--- /dev/null
+++ b/tests/template/tissue909.nim
@@ -0,0 +1,16 @@
+import macros
+
+template baz() =
+  proc bar() =
+    var x = 5
+    iterator foo(): int {.closure.} =
+      echo x
+    var y = foo
+    discard y()
+
+macro test(): stmt =
+  result = getAst(baz())
+  echo(treeRepr(result))
+
+test()
+bar()
diff --git a/tests/template/tissue993.nim b/tests/template/tissue993.nim
new file mode 100644
index 000000000..d39f43942
--- /dev/null
+++ b/tests/template/tissue993.nim
@@ -0,0 +1,21 @@
+
+type pnode* = ref object of tobject
+
+template litNode (name, ty): stmt  =
+  type name* = ref object of PNode
+    val*: ty
+litNode PIntNode, int
+
+import json
+
+template withKey*(j: PJsonNode; key: string; varname: expr;
+                  body:stmt): stmt {.immediate.} =
+  if j.hasKey(key):
+    let varname{.inject.}= j[key]
+    block:
+      body
+
+var j = parsejson("{\"zzz\":1}")
+withkey(j, "foo", x):
+  echo(x)
+
diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim
index 74d8811b8..89d56c693 100644
--- a/tests/testament/htmlgen.nim
+++ b/tests/testament/htmlgen.nim
@@ -174,6 +174,10 @@ proc generateJson*(filename: string, commit: int) =
                 on A.name = B.name and A.category = B.category
                 where A.[commit] = ? and B.[commit] = ? and A.machine = ?
                    and A.result != B.result"""
+    selResults = """select 
+                      name, category, target, action, result, expected, given 
+                    from TestResult
+                    where [commit] = ?"""
   var db = open(connection="testament.db", user="testament", password="",
                 database="testament")
   let lastCommit = db.getCommit(commit)
@@ -189,6 +193,20 @@ proc generateJson*(filename: string, commit: int) =
 
   outfile.writeln("""{"total": $#, "passed": $#, "skipped": $#""" % data)
 
+  let results = newJArray()
+  for row in db.rows(sql(selResults), lastCommit):
+    var obj = newJObject()
+    obj["name"] = %row[0]
+    obj["category"] = %row[1]
+    obj["target"] = %row[2]
+    obj["action"] = %row[3]
+    obj["result"] = %row[4]
+    obj["expected"] = %row[5]
+    obj["given"] = %row[6]
+    results.add(obj)
+  outfile.writeln(""", "results": """)
+  outfile.write(results.pretty)
+
   if not previousCommit.isNil:
     let diff = newJArray()
 
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index fac97cf2a..923cd7518 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -11,7 +11,7 @@
 
 import
   parseutils, strutils, pegs, os, osproc, streams, parsecfg, json,
-  marshal, backend, parseopt, specs, htmlgen, browsers
+  marshal, backend, parseopt, specs, htmlgen, browsers, terminal
 
 const
   resultsFile = "testresults.html"
@@ -109,6 +109,12 @@ proc addResult(r: var TResults, test: TTest,
                           expected = expected,
                           given = given)
   r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success)
+  if success notin {reSuccess, reIgnored}:
+    styledEcho styleBright, fgRed, "^^^ [", $success, "]"
+    styledEcho styleDim, "EXPECTED:"
+    echo expected
+    styledEcho styleDim, "GIVEN:"
+    echo given
 
 proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
   if strip(expected.msg) notin strip(given.msg):
diff --git a/tests/vm/tstaticprintseq.nim b/tests/vm/tstaticprintseq.nim
index 99a56d161..4575f3af1 100644
--- a/tests/vm/tstaticprintseq.nim
+++ b/tests/vm/tstaticprintseq.nim
@@ -4,7 +4,17 @@ discard """
 3
 1
 2
-3'''
+3
+1
+2
+3
+1
+2
+3
+aa
+bb
+aa
+bb'''
 """
 
 const s = @[1,2,3]
@@ -19,3 +29,27 @@ static:
   for e in s:
     echo e
 
+macro bar(x: static[seq[int]]): stmt =
+  for e in x:
+    echo e
+
+bar s
+bar(@[1, 2, 3])
+
+type
+  TData = tuple
+    letters: seq[string]
+    numbers: seq[int]
+
+const data: TData = (@["aa", "bb"], @[11, 22])
+
+static:
+  var m = data
+  for x in m.letters:
+    echo x
+
+macro ff(d: static[TData]): stmt =
+  for x in d.letters:
+    echo x
+
+ff(data)
diff --git a/tests/vm/twrongconst.nim b/tests/vm/twrongconst.nim
index e5b8a15bd..5c0c80f9f 100644
--- a/tests/vm/twrongconst.nim
+++ b/tests/vm/twrongconst.nim
@@ -1,10 +1,9 @@
 discard """
-  output: "Error: cannot evaluate at compile time: x"
-  line: 10
+  errormsg: "cannot evaluate at compile time: x"
+  line: 9
 """
 
-var x: array[100, char] 
+var x: array[100, char]
 template Foo : expr = x[42]
 
-
 const myConst = foo
diff --git a/tests/vm/twrongwhen.nim b/tests/vm/twrongwhen.nim
index 085bb6fb6..d67e42883 100644
--- a/tests/vm/twrongwhen.nim
+++ b/tests/vm/twrongwhen.nim
@@ -1,9 +1,9 @@
 discard """
-  output: "Error: cannot evaluate at compile time: x"
+  errormsg: "cannot evaluate at compile time: x"
   line: 7
 """
 
-proc bla(x:int) = 
+proc bla(x:int) =
   when x == 0:
     echo "oops"
   else:
diff --git a/todo.txt b/todo.txt
index a67ff5172..3b085ac91 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,6 @@
 version 0.9.4
 =============
 
-- make testament produce full JSON information
 - fix gensym capture bug
 - vm
   - at least try to get the basic type zoo ops right
@@ -32,7 +31,6 @@ version 0.9.x
 - ensure (ref T)(a, b) works as a type conversion and type constructor
 - optimize 'genericReset'; 'newException' leads to code bloat
 - stack-less GC
-- implement strongSpaces:on
 - make '--implicitStatic:on' the default
 - implicit deref for parameter matching
 
diff --git a/web/news.txt b/web/news.txt
index 0001cece7..83863cdd9 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -82,6 +82,7 @@ News
     - The *command syntax* is supported in a lot more contexts.
     - Anonymous iterators are now supported and iterators can capture variables
       of an outer proc.
+    - The experimental ``strongSpaces`` parsing mode has been implemented.
 
 
     Tools improvements