summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim1
-rw-r--r--compiler/ccgexprs.nim24
-rw-r--r--compiler/ccgtypes.nim5
-rw-r--r--compiler/cgen.nim1
-rw-r--r--compiler/cgendata.nim1
-rw-r--r--compiler/guards.nim2
-rw-r--r--compiler/llstream.nim3
-rw-r--r--compiler/parser.nim44
-rw-r--r--compiler/sem.nim10
-rw-r--r--compiler/semdata.nim4
-rw-r--r--compiler/seminst.nim8
-rw-r--r--compiler/semstmts.nim10
-rw-r--r--compiler/semtypes.nim5
-rw-r--r--compiler/suggest.nim9
-rw-r--r--compiler/vmdeps.nim2
-rw-r--r--doc/grammar.txt4
-rw-r--r--doc/manual.txt2
-rw-r--r--doc/nimrodc.txt12
-rw-r--r--doc/tut1.txt4
-rw-r--r--doc/tut2.txt2
-rw-r--r--lib/pure/algorithm.nim9
-rw-r--r--lib/pure/asyncdispatch.nim27
-rw-r--r--lib/pure/asynchttpserver.nim7
-rw-r--r--lib/pure/collections/queues.nim2
-rw-r--r--lib/pure/collections/tables.nim17
-rw-r--r--lib/pure/fsmonitor.nim6
-rw-r--r--lib/pure/hashes.nim29
-rw-r--r--lib/pure/json.nim52
-rw-r--r--lib/pure/net.nim2
-rw-r--r--lib/pure/rawsockets.nim1
-rw-r--r--lib/system.nim55
-rw-r--r--lib/system/chcks.nim22
-rw-r--r--tests/misc/tbug1217bracketquotes.nim14
-rw-r--r--tests/notnil/tnotnil4.nim14
-rw-r--r--tests/osproc/ta.nim3
-rw-r--r--tests/osproc/tstdin.nim16
-rw-r--r--tests/testament/caasdriver.nim22
-rw-r--r--tests/testament/categories.nim45
-rw-r--r--todo.txt1
-rw-r--r--web/assets/style.css2
40 files changed, 385 insertions, 114 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 1755dcce9..461854496 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -511,6 +511,7 @@ const
   tfUncheckedArray* = tfVarargs
   tfUnion* = tfNoSideEffect
   tfGcSafe* = tfThread
+  tfObjHasKids* = tfEnumHasHoles
   skError* = skUnknown
   
   # type flags that are essential for type equality:
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 69e382f8d..e6b22819f 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1144,6 +1144,24 @@ proc genNewFinalize(p: BProc, e: PNode) =
   genObjectInit(p, cpsStmts, bt, a, false)
   gcUsage(e)
 
+proc genOfHelper(p: BProc; dest: PType; a: PRope): PRope =
+  # unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we
+  # have to call it here first:
+  let ti = genTypeInfo(p.module, dest)
+  if tfFinal in dest.flags or (p.module.objHasKidsValid and
+                               tfObjHasKids notin dest.flags):
+    result = ropef("$1.m_type == $2", a, ti)
+  else:
+    discard cgsym(p.module, "TNimType")
+    inc p.module.labels
+    let cache = con("Nim_OfCheck_CACHE", p.module.labels.toRope)
+    appf(p.module.s[cfsVars], "static TNimType* $#[2];$n", cache)
+    result = rfmt(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache)
+  when false:
+    # former version:
+    result = rfmt(p.module, "#isObj($1.m_type, $2)",
+                  a, genTypeInfo(p.module, dest))
+
 proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
   var a: TLoc
   initLocExpr(p, x, a)
@@ -1163,11 +1181,9 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     globalError(x.info, errGenerated, 
       "no 'of' operator available for pure objects")
   if nilCheck != nil:
-    r = rfmt(p.module, "(($1) && #isObj($2.m_type, $3))",
-             nilCheck, r, genTypeInfo(p.module, dest))
+    r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
   else:
-    r = rfmt(p.module, "#isObj($1.m_type, $2)",
-             r, genTypeInfo(p.module, dest))
+    r = rfmt(p.module, "($1)", genOfHelper(p, dest, r))
   putIntoDest(p, d, getSysType(tyBool), r)
 
 proc genOf(p: BProc, n: PNode, d: var TLoc) =
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 7a490082f..8e762ce27 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -796,6 +796,11 @@ proc genObjectInfo(m: BModule, typ: PType, name: PRope) =
   var tmp = getNimNode(m)
   genObjectFields(m, typ, typ.n, tmp)
   appf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
+  var t = typ.sons[0]
+  while t != nil:
+    t = t.skipTypes(abstractInst)
+    t.flags.incl tfObjHasKids
+    t = t.sons[0]
 
 proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
   genTypeInfoAuxBase(m, typ, name, toRope("0"))
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 314af7784..a5852c735 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -1384,6 +1384,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
   registerModuleToMain(m.module)
 
   if sfMainModule in m.module.flags: 
+    m.objHasKidsValid = true
     var disp = generateMethodDispatchers()
     for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
     genMainProc(m)
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index e7d818556..12041c55b 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -96,6 +96,7 @@ type
                               # a frame var twice in an init proc
     isHeaderFile*: bool       # C source file is the header file
     includesStringh*: bool    # C source file already includes ``<string.h>``
+    objHasKidsValid*: bool    # whether we can rely on tfObjHasKids
     cfilename*: string        # filename of the module (including path,
                               # without extension)
     typeCache*: TIdTable      # cache the generated types
diff --git a/compiler/guards.nim b/compiler/guards.nim
index 813a30014..4cf06fe02 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -625,7 +625,7 @@ proc factImplies(fact, prop: PNode): TImplication =
     #  == not a or not b == not (a and b)
     let arg = fact.sons[1]
     case arg.getMagic
-    of mIsNil:
+    of mIsNil, mEqRef:
       return ~factImplies(arg, prop)
     of mAnd:
       # not (a and b)  means  not a or not b:
diff --git a/compiler/llstream.nim b/compiler/llstream.nim
index 510880ffd..86bfeaabd 100644
--- a/compiler/llstream.nim
+++ b/compiler/llstream.nim
@@ -82,6 +82,9 @@ when not defined(readLineFromStdin):
   proc readLineFromStdin(prompt: string, line: var string): bool =
     stdout.write(prompt)
     result = readLine(stdin, line)
+    if not result:
+      stdout.write("\n")
+      quit(0)
 
 proc endsWith*(x: string, s: set[char]): bool =
   var i = x.len-1
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 2f9deb6b3..18de1570a 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -147,8 +147,10 @@ proc expectIdent(p: TParser) =
 proc eat(p: var TParser, tokType: TTokType) =
   ## Move the parser to the next token if the current token is of type
   ## `tokType`, otherwise error.
-  if p.tok.tokType == tokType: getTok(p)
-  else: lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType])
+  if p.tok.tokType == tokType:
+    getTok(p)
+  else:
+    lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType])
   
 proc parLineInfo(p: TParser): TLineInfo =
   ## Retrieve the line information associated with the parser's current state.
@@ -285,7 +287,7 @@ proc colcom(p: var TParser, n: PNode) =
   skipComment(p, n)
 
 proc parseSymbol(p: var TParser, allowNil = false): PNode =
-  #| symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`'
+  #| symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
   #|        | IDENT
   case p.tok.tokType
   of tkSymbol: 
@@ -296,31 +298,22 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode =
     getTok(p)
     while true:
       case p.tok.tokType
-      of tkBracketLe: 
-        add(result, newIdentNodeP(getIdent"[]", p))
-        getTok(p)
-        eat(p, tkBracketRi)
-      of tkEquals:
-        add(result, newIdentNodeP(getIdent"=", p))
-        getTok(p)
-      of tkParLe:
-        add(result, newIdentNodeP(getIdent"()", p))
-        getTok(p)
-        eat(p, tkParRi)
-      of tkCurlyLe:
-        add(result, newIdentNodeP(getIdent"{}", p))
-        getTok(p)
-        eat(p, tkCurlyRi)
-      of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDot, tkDotDot:
-        add(result, newIdentNodeP(p.tok.ident, p))
-        getTok(p)
-      of tkIntLit..tkCharLit:
-        add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p))
-        getTok(p)
-      else:
+      of tkAccent:
         if result.len == 0: 
           parMessage(p, errIdentifierExpected, p.tok)
         break
+      of tkOpr, tkDot, tkDotDot, tkEquals, tkParLe..tkParDotRi:
+        var accm = ""
+        while p.tok.tokType in {tkOpr, tkDot, tkDotDot, tkEquals,
+                                tkParLe..tkParDotRi}:
+          accm.add(tokToStr(p.tok))
+          getTok(p)
+        result.add(newIdentNodeP(getIdent(accm), p))
+      of tokKeywordLow..tokKeywordHigh, tkSymbol, tkIntLit..tkCharLit:
+        result.add(newIdentNodeP(getIdent(tokToStr(p.tok)), p))
+        getTok(p)
+      else:
+        parMessage(p, errIdentifierExpected, p.tok)
     eat(p, tkAccent)
   else:
     if allowNil and p.tok.tokType == tkNil:
@@ -993,6 +986,7 @@ proc parseSymbolList(p: var TParser, result: PNode, allowNil = false) =
 
 proc parseTypeDescKAux(p: var TParser, kind: TNodeKind,
                        mode: TPrimaryMode): PNode =
+  #| distinct = 'distinct' optInd typeDesc
   result = newNodeP(kind, p)
   getTok(p)
   optInd(p, result)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 2e3b10a40..e4ef6473f 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -269,11 +269,15 @@ include hlo, seminst, semcall
 
 proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
                        flags: TExprFlags): PNode =
+  ## Semantically check the output of a macro.
+  ## This involves processes such as re-checking the macro output for type
+  ## coherence, making sure that variables declared with 'let' aren't
+  ## reassigned, and binding the unbound identifiers that the macro output
+  ## contains.
   inc(evalTemplateCounter)
   if evalTemplateCounter > 100:
     globalError(s.info, errTemplateInstantiationTooNested)
-  let oldFriend = c.friendModule
-  c.friendModule = s.owner.getModule
+  c.friendModules.add(s.owner.getModule)
 
   result = n
   if s.typ.sons[0] == nil:
@@ -297,7 +301,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
       result = fitNode(c, s.typ.sons[0], result)
       #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
   dec(evalTemplateCounter)
-  c.friendModule = oldFriend
+  discard c.friendModules.pop()
 
 proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
                   flags: TExprFlags = {}): PNode =
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 19181d98e..abecc1b6d 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -52,7 +52,7 @@ type
     importTable*: PScope       # scope for all imported symbols
     topLevelScope*: PScope     # scope for all top-level symbols
     p*: PProcCon               # procedure context
-    friendModule*: PSym        # current friend module; may access private data;
+    friendModules*: seq[PSym]  # friend modules; may access private data;
                                # this is used so that generic instantiations
                                # can access private object fields
     instCounter*: int          # to prevent endless instantiations
@@ -169,7 +169,7 @@ proc newContext(module: PSym): PContext =
   initLinkedList(result.libs)
   append(result.optionStack, newOptionEntry())
   result.module = module
-  result.friendModule = module
+  result.friendModules = @[module]
   result.converters = @[]
   result.patterns = @[]
   result.includedFiles = initIntSet()
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index f7d5fa6f8..b93d7ca15 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -190,6 +190,9 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
 
 proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
                       info: TLineInfo): PSym =
+  ## Generates a new instance of a generic procedure.
+  ## The `pt` parameter is a type-unsafe mapping table used to link generic
+  ## parameters to their concrete types within the generic instance.
   # no need to instantiate generic templates/macros:
   if fn.kind in {skTemplate, skMacro}: return fn
   # generates an instantiated proc
@@ -199,8 +202,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   var n = copyTree(fn.ast)
   # NOTE: for access of private fields within generics from a different module
   # we set the friend module:
-  var oldFriend = c.friendModule
-  c.friendModule = getModule(fn)
+  c.friendModules.add(getModule(fn))
   #let oldScope = c.currentScope
   #c.currentScope = fn.scope
   result = copySym(fn, false)
@@ -236,6 +238,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   closeScope(c)           # close scope for parameters
   popOwner()
   #c.currentScope = oldScope
-  c.friendModule = oldFriend
+  discard c.friendModules.pop()
   dec(c.instCounter)
   if result.kind == skMethod: finishMethod(c, result)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 43c7bf3fe..d17351988 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -66,10 +66,16 @@ proc toCover(t: PType): BiggestInt =
     result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
 
 proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
+  ## Checks that the given symbol is a proper procedure variable, meaning
+  ## that it 
   var smoduleId = getModule(s).id
   if sfProcvar notin s.flags and s.typ.callConv == ccDefault and
-      smoduleId != c.module.id and smoduleId != c.friendModule.id: 
-    localError(n.info, errXCannotBePassedToProcVar, s.name.s)
+      smoduleId != c.module.id:
+    block outer:
+      for module in c.friendModules:
+        if smoduleId == module.id:
+          break outer
+      localError(n.info, errXCannotBePassedToProcVar, s.name.s)
 
 proc semProcvarCheck(c: PContext, n: PNode) =
   let n = n.skipConv
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 3b9e82261..9d38c4619 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -70,9 +70,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       counter = x
     of nkSym: 
       e = n.sons[i].sym
-    of nkIdent: 
+    of nkIdent, nkAccQuoted: 
       e = newSymS(skEnumField, n.sons[i], c)
-    else: illFormedAst(n)
+    else:
+      illFormedAst(n[i])
     e.typ = result
     e.position = int(counter)
     if e.position == 0: hasNull = true
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index fc6ba2f77..db95c480f 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -63,8 +63,11 @@ proc filterSym(s: PSym): bool {.inline.} =
 
 proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
   let fmoduleId = getModule(f).id
-  result = sfExported in f.flags or fmoduleId == c.module.id or
-      fmoduleId == c.friendModule.id
+  result = sfExported in f.flags or fmoduleId == c.module.id
+  for module in c.friendModules:
+    if fmoduleId == module.id:
+      result = true
+      break
 
 proc suggestField(c: PContext, s: PSym, outputs: var int) = 
   if filterSym(s) and fieldVisible(c, s):
@@ -319,7 +322,7 @@ proc suggestSym*(n: PNode, s: PSym) {.inline.} =
     findUsages(n, s)
   if optDef in gGlobalOptions:
     findDefinition(n, s)
-  if isServing:
+  if isServing and not n.isNil:
     addToSourceMap(s, n.info)
 
 proc markUsed(n: PNode, s: PSym) =
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 0e01f5031..9a213d813 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -15,6 +15,8 @@ proc readOutput(p: PProcess): string =
   discard p.waitForExit
   while not output.atEnd:
     result.add(output.readLine)
+    result.add("\n")
+  result.setLen(result.len - "\n".len)
 
 proc opGorge*(cmd, input: string): string =
   var p = startCmd(cmd)
diff --git a/doc/grammar.txt b/doc/grammar.txt
index 63e898e11..47ae095f6 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -24,7 +24,7 @@ ampExpr = plusExpr (OP6 optInd plusExpr)*
 plusExpr = mulExpr (OP7 optInd mulExpr)*
 mulExpr = dollarExpr (OP8 optInd dollarExpr)*
 dollarExpr = primary (OP9 optInd primary)*
-symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`'
+symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
        | IDENT
 indexExpr = expr
 indexExprList = indexExpr ^+ comma
@@ -82,6 +82,7 @@ paramListColon = paramList? (':' optInd typeDesc)?
 doBlock = 'do' paramListArrow pragmas? colcom stmt
 doBlocks = doBlock ^* IND{=}
 procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
+distinct = 'distinct' optInd typeDesc
 expr = (ifExpr
       | whenExpr
       | caseExpr
@@ -166,7 +167,6 @@ object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
 typeClassParam = ('var')? symbol
 typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
               &IND{>} stmt
-distinct = 'distinct' optInd typeDesc
 typeDef = identWithPragma genericParamList? '=' optInd typeDefAux
             indAndComment?
 varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
diff --git a/doc/manual.txt b/doc/manual.txt
index c6f50298c..e96e50999 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -5485,7 +5485,7 @@ the argument is missing, the C name is the Nimrod identifier *exactly as
 spelled*:
 
 .. code-block::
-  proc printf(formatstr: cstring) {.importc: "printf", varargs.}
+  proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
 
 Note that this pragma is somewhat of a misnomer: Other backends will provide
 the same feature under the same name.
diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt
index e4f1c41dc..fea1037da 100644
--- a/doc/nimrodc.txt
+++ b/doc/nimrodc.txt
@@ -87,6 +87,18 @@ Level  Description
        for compiler developers.
 =====  ============================================
 
+
+Compile time symbols
+--------------------
+
+Through the ``-d:x`` or ``--define:x`` switch you can define compile time
+symbols for conditional compilation. The defined switches can be checked in
+source code with the `when statement <manual.html#when-statement>`_ and
+`defined proc <system.html#defined>`_. The typical use of this switch is to
+enable builds in release mode (``-d:release``) where certain safety checks are
+omitted for better performance. Another common use is the ``-d:ssl`` switch to
+activate `SSL sockets <sockets.html>`_.
+
 

 Configuration files

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

diff --git a/doc/tut1.txt b/doc/tut1.txt
index 8c6f140eb..9874f267b 100644
--- a/doc/tut1.txt
+++ b/doc/tut1.txt
@@ -1385,8 +1385,8 @@ Tuples
 A tuple type defines various named *fields* and an *order* of the fields.
 The constructor ``()`` can be used to construct tuples. The order of the
 fields in the constructor must match the order in the tuple's definition.
-Different tuple-types are *equivalent* if they specify the same fields of
-the same type in the same order.
+Different tuple-types are *equivalent* if they specify fields of
+the same type and of the same name in the same order.
 
 The assignment operator for tuples copies each component. The notation
 ``t.field`` is used to access a tuple's field. Another notation is
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 11b485f50..1e23618e0 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -501,7 +501,7 @@ with the file and line where the uncaught exception is being raised, which may
 help you locate the offending code which has changed.
 
 If you want to add the ``{.raises.}`` pragma to existing code, the compiler can
-also help you. You can add the ``{.effect.}`` pragma statement to your proc and
+also help you. You can add the ``{.effects.}`` pragma statement to your proc and
 the compiler will output all inferred effects up to that point (exception
 tracking is part of Nimrod's effect system). Another more roundabout way to
 find out the list of exceptions raised by a proc is to use the Nimrod ``doc2``
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 37fbc948c..86d329763 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -150,6 +150,15 @@ proc sort*[T](a: var openArray[T],
   ##    # overload:
   ##    sort(myStrArray, system.cmp)
   ##
+  ## You can inline adhoc comparison procs with the `do notation
+  ## <manual.html#do-notation>`_. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##
+  ##   people.sort do (x, y: Person) -> int:
+  ##     result = cmp(x.surname, y.surname)
+  ##     if result == 0:
+  ##       result = cmp(x.name, y.name)
   var n = a.len
   var b: seq[T]
   newSeq(b, n div 2)
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index 87ee83ad9..6d9e605f1 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -27,9 +27,11 @@ export TPort
 
 
 # TODO: Discarded void PFutures need to checked for exception.
-# TODO: Exceptions are currently uncatchable due to the limitation that 
-# you cannot have yield in a try stmt. Perhaps I can get the macro to put
-# a user's try except around ``future.read``.
+# TODO: ``except`` statement (without `try`) does not work.
+# TODO: Multiple exception names in a ``except`` don't work.
+# TODO: The effect system (raises: []) has trouble with my try transformation.
+# TODO: Can't await in a 'except' body
+
 
 # -- Futures
 
@@ -922,14 +924,17 @@ proc getName(node: PNimrodNode): string {.compileTime.} =
     return $node[1].ident
   of nnkIdent:
     return $node.ident
+  of nnkEmpty:
+    return "anonymous"
   else:
-    assert false
+    error("Unknown name.")
 
 macro async*(prc: stmt): stmt {.immediate.} =
   ## Macro which processes async procedures into the appropriate
   ## iterators and yield statements.
-
-  expectKind(prc, nnkProcDef)
+  if prc.kind notin {nnkProcDef, nnkLambda}:
+    error("Cannot transform this node kind into an async proc." &
+          " Proc definition or lambda node expected.")
 
   hint("Processing " & prc[0].getName & " as an async proc.")
 
@@ -941,7 +946,9 @@ macro async*(prc: stmt): stmt {.immediate.} =
     if $returnType[0] != "PFuture":
       error("Expected return type of 'PFuture' got '" & $returnType[0] & "'")
 
-  let subtypeIsVoid = returnType.kind == nnkEmpty
+  let subtypeIsVoid = returnType.kind == nnkEmpty or
+        (returnType.kind == nnkBracketExpr and
+         returnType[1].kind == nnkIdent and returnType[1].ident == !"void")
 
   var outerProcBody = newNimNode(nnkStmtList)
 
@@ -990,17 +997,19 @@ macro async*(prc: stmt): stmt {.immediate.} =
 
   # Remove the 'async' pragma.
   for i in 0 .. <result[4].len:
-    if result[4][i].ident == !"async":
+    if result[4][i].kind == nnkIdent and result[4][i].ident == !"async":
       result[4].del(i)
   if subtypeIsVoid:
     # Add discardable pragma.
-    result[4].add(newIdentNode("discardable"))
+    if prc.kind == nnkProcDef: # TODO: This is a workaround for #1287
+      result[4].add(newIdentNode("discardable"))
     if returnType.kind == nnkEmpty:
       # Add PFuture[void]
       result[3][0] = parseExpr("PFuture[void]")
 
   result[6] = outerProcBody
 
+  #echo(treeRepr(result))
   #echo(toStrLit(result))
 
 proc recvLine*(socket: TAsyncFD): PFuture[string] {.async.} =
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 6c2414d99..005c56ebc 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -14,12 +14,13 @@
 import strtabs, asyncnet, asyncdispatch, parseutils, parseurl, strutils
 type
   TRequest* = object
-    client: PAsyncSocket # TODO: Separate this into a Response object?
+    client*: PAsyncSocket # TODO: Separate this into a Response object?
     reqMethod*: string
     headers*: PStringTable
     protocol*: tuple[orig: string, major, minor: int]
     url*: TURL
     hostname*: string ## The hostname of the client that made the request.
+    body*: string # TODO
 
   PAsyncHttpServer* = ref object
     socket: PAsyncSocket
@@ -169,6 +170,10 @@ proc serve*(server: PAsyncHttpServer, port: TPort,
     var fut = await server.socket.acceptAddr()
     processClient(fut.client, fut.address, callback)
 
+proc close*(server: PAsyncHttpServer) =
+  ## Terminates the async http server instance.
+  server.socket.close()
+
 when isMainModule:
   var server = newAsyncHttpServer()
   proc cb(req: TRequest) {.async.} =
diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim
index db1d50569..5481272f0 100644
--- a/lib/pure/collections/queues.nim
+++ b/lib/pure/collections/queues.nim
@@ -59,7 +59,7 @@ proc enqueue*[T](q: var TQueue[T], item: T) =
 
 proc dequeue*[T](q: var TQueue[T]): T =
   ## removes and returns the first element of the queue `q`.
-  assert q.len > 0
+  assert q.count > 0
   dec q.count
   result = q.data[q.rd]
   q.rd = (q.rd + 1) and q.mask
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index 848f4b8ba..ce9df09e1 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -37,7 +37,8 @@
 ##     ## Piggyback on the already available string hash proc.
 ##     ##
 ##     ## Without this proc nothing works!
-##     result = hash(x.firstName & x.lastName)
+##     result = x.firstName.hash !& x.lastName.hash
+##     result = !$result
 ##
 ##   var
 ##     salaries = initTable[Person, int]()
@@ -145,6 +146,14 @@ proc mget*[A, B](t: var TTable[A, B], key: A): var B =
   if index >= 0: result = t.data[index].val
   else: raise newException(EInvalidKey, "key not found: " & $key)
 
+iterator allValues*[A, B](t: TTable[A, B]; key: A): B =
+  ## iterates over any value in the table `t` that belongs to the given `key`.
+  var h: THash = hash(key) and high(t.data)
+  while t.data[h].slot != seEmpty:
+    if t.data[h].key == key and t.data[h].slot == seFilled:
+      yield t.data[h].val
+    h = nextTry(h, high(t.data))
+
 proc hasKey*[A, B](t: TTable[A, B], key: A): bool =
   ## returns true iff `key` is in the table `t`.
   result = rawGet(t, key) >= 0
@@ -313,8 +322,7 @@ proc newTable*[A, B](initialSize=64): PTable[A, B] =
   new(result)
   result[] = initTable[A, B](initialSize)
 
-proc newTable*[A, B](pairs: openArray[tuple[key: A, 
-                    val: B]]): PTable[A, B] =
+proc newTable*[A, B](pairs: openArray[tuple[key: A, val: B]]): PTable[A, B] =
   ## creates a new hash table that contains the given `pairs`.
   new(result)
   result[] = toTable[A, B](pairs)
@@ -841,7 +849,8 @@ when isMainModule:
     ## Piggyback on the already available string hash proc.
     ##
     ## Without this proc nothing works!
-    result = hash(x.firstName & x.lastName)
+    result = x.firstName.hash !& x.lastName.hash
+    result = !$result
 
   var
     salaries = initTable[Person, int]()
diff --git a/lib/pure/fsmonitor.nim b/lib/pure/fsmonitor.nim
index d6584c1a0..b35466771 100644
--- a/lib/pure/fsmonitor.nim
+++ b/lib/pure/fsmonitor.nim
@@ -119,8 +119,8 @@ proc getEvent(m: PFSMonitor, fd: cint): seq[TMonitorEvent] =
     var mev: TMonitorEvent
     mev.wd = event.wd
     if event.len.int != 0:
-      mev.name = newString(event.len.int)
-      copyMem(addr(mev.name[0]), addr event.name, event.len.int-1)
+      let cstr = event.name.addr.cstring
+      mev.name = $cstr
     else:
       mev.name = ""
     
@@ -211,4 +211,4 @@ when isMainModule:
       
   while true:
     if not disp.poll(): break
-  
\ No newline at end of file
+  
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 5784a96c1..740355e55 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -8,7 +8,34 @@
 #
 
 ## This module implements efficient computations of hash values for diverse
-## Nimrod types.
+## Nimrod types. All the procs are based on these two building blocks: the `!&
+## proc <#!&>`_ used to start or mix a hash value, and the `!$ proc <#!$>`_
+## used to *finish* the hash value.  If you want to implement hash procs for
+## your custom types you will end up writing the following kind of skeleton of
+## code:
+##
+## .. code-block:: nimrod
+##  proc hash(x: Something): THash =
+##    ## Computes a THash from `x`.
+##    var h: THash = 0
+##    # Iterate over parts of `x`.
+##    for xAtom in x:
+##      # Mix the atom with the partial hash.
+##      h = h !& xAtom
+##    # Finish the hash.
+##    result = !$h
+##
+## If your custom types contain fields for which there already is a hash proc,
+## like for example objects made up of ``strings``, you can simply hash
+## together the hash value of the individual fields:
+##
+## .. code-block:: nimrod
+##  proc hash(x: Something): THash =
+##    ## Computes a THash from `x`.
+##    var h: THash = 0
+##    h = h &! hash(x.foo)
+##    h = h &! hash(x.bar)
+##    result = !$h
 
 import 
   strutils
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 306a8a2e2..508e564c5 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -619,6 +619,44 @@ proc `%`*(elements: openArray[PJsonNode]): PJsonNode =
   newSeq(result.elems, elements.len)
   for i, p in pairs(elements): result.elems[i] = p
 
+proc `==`* (a,b: PJsonNode): bool =
+  ## Check two nodes for equality
+  if a.kind != b.kind: false
+  else:
+    case a.kind
+    of JString:
+      a.str == b.str
+    of JInt:
+      a.num == b.num
+    of JFloat:
+      a.fnum == b.fnum
+    of JBool:
+      a.bval == b.bval
+    of JNull:
+      true
+    of JArray:
+      a.elems == b.elems
+    of JObject:
+      a.fields == b.fields
+
+proc hash* (n:PJsonNode): THash =
+  ## Compute the hash for a JSON node
+  case n.kind
+  of JArray:
+    result = hash(n.elems)
+  of JObject:
+    result = hash(n.fields)
+  of JInt:
+    result = hash(n.num)
+  of JFloat:
+    result = hash(n.fnum)
+  of JBool:
+    result = hash(n.bval.int)
+  of JString:
+    result = hash(n.str)
+  of JNull:
+    result = hash(0)
+
 proc len*(n: PJsonNode): int = 
   ## If `n` is a `JArray`, it returns the number of elements.
   ## If `n` is a `JObject`, it returns the number of pairs.
@@ -631,7 +669,7 @@ proc len*(n: PJsonNode): int =
 proc `[]`*(node: PJsonNode, name: string): PJsonNode =
   ## Gets a field from a `JObject`, which must not be nil.
   ## If the value at `name` does not exist, returns nil
-  assert(node != nil)
+  assert(not isNil(node))
   assert(node.kind == JObject)
   for key, item in items(node.fields):
     if key == name:
@@ -641,8 +679,8 @@ proc `[]`*(node: PJsonNode, name: string): PJsonNode =
 proc `[]`*(node: PJsonNode, index: int): PJsonNode =
   ## Gets the node at `index` in an Array. Result is undefined if `index`
   ## is out of bounds
+  assert(not isNil(node))
   assert(node.kind == JArray)
-  assert(node != nil)
   return node.elems[index]
 
 proc hasKey*(node: PJsonNode, key: string): bool =
@@ -675,14 +713,12 @@ proc `[]=`*(obj: PJsonNode, key: string, val: PJsonNode) =
       return
   obj.fields.add((key, val))
 
-proc `{}`*(node: PJsonNode, names: varargs[string]): PJsonNode =
+proc `{}`*(node: PJsonNode, key: string): PJsonNode =
   ## Transverses the node and gets the given value. If any of the
   ## names does not exist, returns nil
   result = node
-  for name in names:
-    result = result[name]
-    if isNil(result):
-      return nil
+  if isNil(node): return nil
+  result = result[key]
 
 proc `{}=`*(node: PJsonNode, names: varargs[string], value: PJsonNode) =
   ## Transverses the node and tries to set the value at the given location
@@ -1021,7 +1057,7 @@ when isMainModule:
 
   let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd" }"""
   # nil passthrough
-  assert(testJson{"doesnt_exist", "anything"} == nil)
+  assert(testJson{"doesnt_exist"}{"anything"}.isNil)
   testJson{["c", "d"]} = %true
   assert(testJson["c"]["d"].bval)
 
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 2f1a6fa46..e34c88327 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -11,7 +11,7 @@
 
 {.deadCodeElim: on.}
 import rawsockets, os, strutils, unsigned, parseutils, times
-export TPort
+export TPort, `$`
 
 const useWinVersion = defined(Windows) or defined(nimdoc)
 
diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim
index 07b647b68..94189fd89 100644
--- a/lib/pure/rawsockets.nim
+++ b/lib/pure/rawsockets.nim
@@ -39,7 +39,6 @@ export
   MSG_PEEK
 
 type
-  
   TPort* = distinct uint16  ## port type
   
   TDomain* = enum   ## domain, which specifies the protocol family of the
diff --git a/lib/system.nim b/lib/system.nim
index 6934d29ae..3e5308f90 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -90,6 +90,15 @@ proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
   ##   when not defined(strutils.toUpper):
   ##     # provide our own toUpper proc here, because strutils is
   ##     # missing it.
+  ##
+  ## You can also check external symbols introduced through the compiler's
+  ## `-d:x switch <nimrodc.html#compile-time-symbols>`_ to enable build time
+  ## conditionals:
+  ##
+  ## .. code-block:: Nimrod
+  ##   when not defined(release):
+  ##     # Do here programmer friendly expensive sanity checks.
+  ##   # Put here the normal code
 
 when defined(useNimRtl):
   {.deadCodeElim: on.}
@@ -1769,9 +1778,38 @@ iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a,b: expr] {
   ## in the loop body.
 iterator fieldPairs*[T: tuple|object](x: T): TObject {.
   magic: "FieldPairs", noSideEffect.}
-  ## iterates over every field of `x`. Warning: This really transforms
-  ## the 'for' and unrolls the loop. The current implementation also has a bug
-  ## that affects symbol binding in the loop body.
+  ## Iterates over every field of `x` returning their name and value.
+  ##
+  ## When you iterate over objects with different field types you have to use
+  ## the compile time ``when`` instead of a runtime ``if`` to select the code
+  ## you want to run for each type. To perform the comparison use the `is
+  ## operator <manual.html#is-operator>`_. Example:
+  ##
+  ## .. code-block:: Nimrod
+  ##
+  ##   type
+  ##     Custom = object
+  ##       foo: string
+  ##       bar: bool
+  ##
+  ##   proc `$`(x: Custom): string =
+  ##     result = "Custom:"
+  ##     for name, value in x.fieldPairs:
+  ##       when value is bool:
+  ##         result.add("\n\t" & name & " is " & $value)
+  ##       else:
+  ##         if value.isNil:
+  ##           result.add("\n\t" & name & " (nil)")
+  ##         else:
+  ##           result.add("\n\t" & name & " '" & value & "'")
+  ##
+  ## Another way to do the same without ``when`` is to leave the task of
+  ## picking the appropriate code to a secondary proc which you overload for
+  ## each field type and pass the `value` to.
+  ##
+  ## Warning: This really transforms the 'for' and unrolls the loop. The
+  ## current implementation also has a bug that affects symbol binding in the
+  ## loop body.
 iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[
   a, b: expr] {.
   magic: "FieldPairs", noSideEffect.}
@@ -2785,10 +2823,15 @@ when true:
     THide(raiseAssert)(msg)
 
 template assert*(cond: bool, msg = "") =
-  ## provides a means to implement `programming by contracts`:idx: in Nimrod.
+  ## Raises ``EAssertionFailure`` with `msg` if `cond` is false.
+  ##
+  ## Provides a means to implement `programming by contracts`:idx: in Nimrod.
   ## ``assert`` evaluates expression ``cond`` and if ``cond`` is false, it
-  ## raises an ``EAssertionFailure`` exception. However, the compiler may
-  ## not generate any code at all for ``assert`` if it is advised to do so.
+  ## raises an ``EAssertionFailure`` exception. However, the compiler may not
+  ## generate any code at all for ``assert`` if it is advised to do so through
+  ## the ``-d:release`` or ``--assertions:off`` `command line switches
+  ## <nimrodc.html#command-line-switches>`_.
+  ##
   ## Use ``assert`` for debugging purposes only.
   bind instantiationInfo
   mixin failedAssertImpl
diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index f29e222e8..387b54ef1 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -67,6 +67,28 @@ proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
   if a != b:
     sysFatal(EInvalidObjectAssignment, "invalid object assignment")
 
+type ObjCheckCache = array[0..1, PNimType]
+
+proc isObjSlowPath(obj, subclass: PNimType;
+                   cache: var ObjCheckCache): bool {.noinline.} =
+  # checks if obj is of type subclass:
+  var x = obj.base
+  while x != subclass:
+    if x == nil:
+      cache[0] = obj
+      return false
+    x = x.base
+  cache[1] = obj
+  return true
+
+proc isObjWithCache(obj, subclass: PNimType;
+                    cache: var ObjCheckCache): bool {.compilerProc, inline.} =
+  if obj == subclass: return true
+  if obj.base == subclass: return true
+  if cache[0] == obj: return false
+  if cache[1] == obj: return true
+  return isObjSlowPath(obj, subclass, cache)
+
 proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
   # checks if obj is of type subclass:
   var x = obj
diff --git a/tests/misc/tbug1217bracketquotes.nim b/tests/misc/tbug1217bracketquotes.nim
new file mode 100644
index 000000000..90e67d45b
--- /dev/null
+++ b/tests/misc/tbug1217bracketquotes.nim
@@ -0,0 +1,14 @@
+discard """
+  output: "13{(.{}}{*4&*$**()&*@1235"
+"""
+
+type
+  Test = enum
+    `1`, `3`, `{`, `(.`, `{}}{`, `*4&*$**()&*@`
+
+let `.}` = 1
+let `(}` = 2
+let `[` = 3
+let `]` = 5
+
+echo `1`, `3`, `{`, `(.`, `{}}{`, `*4&*$**()&*@`, `.}`, `(}`, `[`, `]`
diff --git a/tests/notnil/tnotnil4.nim b/tests/notnil/tnotnil4.nim
new file mode 100644
index 000000000..23968ee48
--- /dev/null
+++ b/tests/notnil/tnotnil4.nim
@@ -0,0 +1,14 @@
+discard ""
+type
+   TObj = ref object
+
+proc check(a: TObj not nil) =
+  echo repr(a)
+
+proc doit() =
+   var x : array[0..1, TObj]
+
+   if x[0] != nil:
+      check(x[0])
+
+doit()
\ No newline at end of file
diff --git a/tests/osproc/ta.nim b/tests/osproc/ta.nim
new file mode 100644
index 000000000..6c1495590
--- /dev/null
+++ b/tests/osproc/ta.nim
@@ -0,0 +1,3 @@
+import strutils
+let x = stdin.readLine()
+echo x.parseInt + 5
\ No newline at end of file
diff --git a/tests/osproc/tstdin.nim b/tests/osproc/tstdin.nim
new file mode 100644
index 000000000..2ea939992
--- /dev/null
+++ b/tests/osproc/tstdin.nim
@@ -0,0 +1,16 @@
+discard """
+  file: "tstdin.nim"
+  output: "10"
+"""
+import osproc, os, streams
+
+doAssert fileExists(getCurrentDir() / "tests" / "osproc" / "ta.exe")
+
+var p = startProcess("ta.exe", getCurrentDir() / "tests" / "osproc")
+p.inputStream.write("5\n")
+while true:
+  let line = p.outputStream.readLine()
+  if line != "":
+    echo line
+  else:
+    break
\ No newline at end of file
diff --git a/tests/testament/caasdriver.nim b/tests/testament/caasdriver.nim
index 22c5ed6fa..ddfe88273 100644
--- a/tests/testament/caasdriver.nim
+++ b/tests/testament/caasdriver.nim
@@ -86,6 +86,10 @@ proc doProcCommand(session: var TNimrodSession, command: string): string =
 
 proc doCommand(session: var TNimrodSession, command: string) =
   if session.mode == CaasRun:
+    if not session.nim.running:
+      session.lastOutput = "FAILED TO EXECUTE: " & command & "\n" &
+          "Exit code " & $session.nim.peekExitCode
+      return
     session.lastOutput = doCaasCommand(session,
                                        command & " " & session.filename)
   else:
@@ -102,7 +106,7 @@ proc close(session: var TNimrodSession) {.destructor.} =
   if session.mode == CaasRun:
     session.nim.close
 
-proc doScenario(script: string, output: PStream, mode: TRunMode): bool =
+proc doScenario(script: string, output: PStream, mode: TRunMode, verbose: bool): bool =
   result = true
 
   var f = open(script)
@@ -134,7 +138,7 @@ proc doScenario(script: string, output: PStream, mode: TRunMode): bool =
         continue
       elif line.startsWith(">"):
         s.doCommand(line.substr(1).strip)
-        output.writeln line, "\n", s.lastOutput
+        output.writeln line, "\n", if verbose: s.lastOutput else: ""
       else:
         var expectMatch = true
         var pattern = s.replaceVars(line)
@@ -151,13 +155,14 @@ proc doScenario(script: string, output: PStream, mode: TRunMode): bool =
           output.writeln "FAILURE ", line
           result = false
 
-iterator caasTestsRunner*(filter = ""): tuple[test, output: string,
-                                              status: bool, mode: TRunMode] =
+iterator caasTestsRunner*(filter = "", verbose = false): tuple[test,
+                                              output: string, status: bool,
+                                              mode: TRunMode] =
   for scenario in os.walkFiles(TesterDir / "caas/*.txt"):
     if filter.len > 0 and find(scenario, filter) == -1: continue
     for mode in modes:
       var outStream = newStringStream()
-      let r = doScenario(scenario, outStream, mode)
+      let r = doScenario(scenario, outStream, mode, verbose)
       yield (scenario, outStream.data, r, mode)
 
 when isMainModule:
@@ -175,9 +180,12 @@ when isMainModule:
   if verbose and len(filter) > 0:
     echo "Running only test cases matching filter '$1'" % [filter]
 
-  for test, output, result, mode in caasTestsRunner(filter):
+  for test, output, result, mode in caasTestsRunner(filter, verbose):
     if not result or verbose:
-      echo test, "\n", output, "-> ", $mode, ":", $result, "\n-----"
+      echo "Mode ", $mode, " (", if result: "succeeded)" else: "failed)"
+      echo test
+      echo output
+      echo "---------\n"
     if not result:
       failures += 1
 
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index bb9c90d2a..841eb8159 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -282,26 +282,33 @@ proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) =
     echo("[Warning] - Cannot run babel tests: Babel update failed.")
     return
 
-  for name, url in listPackages(filter):
-    var test = makeTest(name, "", cat)
-    echo(url)
-    let
-      installProcess = startProcess(babelExe, "", ["install", "-y", name])
-      installStatus = waitForExitEx(installProcess)
-    installProcess.close
-    if installStatus != quitSuccess:
-      r.addResult(test, "", "", reInstallFailed)
-      continue
+  let packageFileTest = makeTest("PackageFileParsed", "", cat)
+  try:
+    for name, url in listPackages(filter):
+      var test = makeTest(name, "", cat)
+      echo(url)
+      let
+        installProcess = startProcess(babelExe, "", ["install", "-y", name])
+        installStatus = waitForExitEx(installProcess)
+      installProcess.close
+      if installStatus != quitSuccess:
+        r.addResult(test, "", "", reInstallFailed)
+        continue
+
+      let
+        buildPath = getPackageDir(name)[0.. -3]
+      let
+        buildProcess = startProcess(babelExe, buildPath, ["build"])
+        buildStatus = waitForExitEx(buildProcess)
+      buildProcess.close
+      if buildStatus != quitSuccess:
+        r.addResult(test, "", "", reBuildFailed)
+      r.addResult(test, "", "", reSuccess)
+    r.addResult(packageFileTest, "", "", reSuccess)
+  except EJsonParsingError:
+    echo("[Warning] - Cannot run babel tests: Invalid package file.")
+    r.addResult(packageFileTest, "", "", reBuildFailed)
 
-    let
-      buildPath = getPackageDir(name)[0.. -3]
-    let
-      buildProcess = startProcess(babelExe, buildPath, ["build"])
-      buildStatus = waitForExitEx(buildProcess)
-    buildProcess.close
-    if buildStatus != quitSuccess:
-      r.addResult(test, "", "", reBuildFailed)
-    r.addResult(test, "", "", reSuccess)
 
 # ----------------------------------------------------------------------------
 
diff --git a/todo.txt b/todo.txt
index 11fc2ef81..df18ff7e9 100644
--- a/todo.txt
+++ b/todo.txt
@@ -155,7 +155,6 @@ Not essential for 1.0.0
 - implement the "snoopResult" pragma; no, make a strutils with string append
   semantics instead ...
 - implement "closure tuple consists of a single 'ref'" optimization
-- optimize method dispatchers
 - new feature: ``distinct T with operations``
 - arglist as a type (iterator chaining); variable length type lists for generics
 - implement marker procs for message passing
diff --git a/web/assets/style.css b/web/assets/style.css
index 5cee279fc..91bb4bd8a 100644
--- a/web/assets/style.css
+++ b/web/assets/style.css
@@ -93,7 +93,7 @@ html, body {
         border-left:10px solid #8f9698;
         background:#f3f6f8;
         font-size:15px;
-        font-family:courier;
+        font-family:courier, monospace;
         letter-spacing:0;
         line-height:17px;
       }