summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim2
-rw-r--r--compiler/ccgtypes.nim2
-rw-r--r--compiler/cgendata.nim3
-rw-r--r--compiler/guards.nim42
-rw-r--r--compiler/lookups.nim1
-rw-r--r--compiler/nimrod.nimrod.cfg2
-rw-r--r--compiler/sem.nim3
-rw-r--r--compiler/sempass2.nim33
-rw-r--r--compiler/semtypinst.nim3
-rw-r--r--compiler/transf.nim1
-rw-r--r--examples/htmltitle.nim8
-rw-r--r--koch.nim28
-rw-r--r--lib/pure/asyncio.nim10
-rw-r--r--lib/pure/nimprof.nim4
-rw-r--r--lib/pure/os.nim5
-rw-r--r--lib/pure/osproc.nim5
-rw-r--r--lib/wrappers/zip/zlib.nim1
-rw-r--r--tests/ccgbugs/tcgbug.nim13
-rw-r--r--tests/collections/tsets.nim (renamed from tests/stdlib/tsets.nim)0
-rw-r--r--tests/effects/teffects6.nim2
-rw-r--r--tests/exprs/tifexpr_typeinference.nim20
-rw-r--r--tests/notnil/tnotnil3.nim35
-rw-r--r--tests/template/ttempl5.nim13
-rw-r--r--tests/testament/htmlgen.nim44
-rw-r--r--todo.txt1
-rw-r--r--tools/nimweb.nim12
26 files changed, 224 insertions, 69 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 01f23850b..27f7f4ba5 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -593,7 +593,7 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
 
 proc genDeref(p: BProc, e: PNode, d: var TLoc) =
   var a: TLoc
-  if mapType(e.sons[0].typ) == ctArray:
+  if mapType(e.sons[0].typ) in {ctArray, ctPtrToArray}:
     # XXX the amount of hacks for C's arrays is incredible, maybe we should
     # simply wrap them in a struct? --> Losing auto vectorization then?
     expr(p, e.sons[0], d)
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index c92c15fa9..673e888fe 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -185,7 +185,7 @@ proc mapType(typ: PType): TCTypeKind =
   of tyPtr, tyVar, tyRef:
     var base = skipTypes(typ.sons[0], typedescInst)
     case base.kind
-    of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
+    of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctPtrToArray
     else: result = ctPtr
   of tyPointer: result = ctPtr
   of tySequence: result = ctNimSeq
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 9cd2c0d87..0e1148343 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -41,7 +41,8 @@ type
     ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
     ctFloat, ctFloat32, ctFloat64, ctFloat128,
     ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
-    ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString
+    ctArray, ctPtrToArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc,
+    ctCString
   TCFileSections* = array[TCFileSection, PRope] # represents a generated C file
   TCProcSection* = enum       # the sections a generated C proc consists of
     cpsLocals,                # section of local variables for C proc
diff --git a/compiler/guards.nim b/compiler/guards.nim
index 607bb074a..fe868054f 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -9,7 +9,7 @@
 
 ## This module implements the 'implies' relation for guards.
 
-import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer
+import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents
 
 const
   someEq = {mEqI, mEqI64, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
@@ -69,9 +69,23 @@ proc isLetLocation(m: PNode, isApprox: bool): bool =
 
 proc interestingCaseExpr*(m: PNode): bool = isLetLocation(m, true)
 
-proc swapArgs(fact: PNode, newOp: string, m: TMagic): PNode =
+proc getMagicOp(name: string, m: TMagic): PSym =
+  result = newSym(skProc, getIdent(name), nil, unknownLineInfo())
+  result.magic = m
+
+let
+  opLe = getMagicOp("<=", mLeI)
+  opLt = getMagicOp("<", mLtI)
+  opAnd = getMagicOp("and", mAnd)
+  opOr = getMagicOp("or", mOr)
+  opNot = getMagicOp("not", mNot)
+  opIsNil = getMagicOp("isnil", mIsNil)
+  opContains = getMagicOp("contains", mInSet)
+  opEq = getMagicOp("==", mEqI)
+
+proc swapArgs(fact: PNode, newOp: PSym): PNode =
   result = newNodeI(nkCall, fact.info, 3)
-  result.sons[0] = newSymNode(getSysMagic(newOp, m))
+  result.sons[0] = newSymNode(newOp)
   result.sons[1] = fact.sons[2]
   result.sons[2] = fact.sons[1]
 
@@ -82,9 +96,9 @@ proc neg(n: PNode): PNode =
     result = n.sons[1]
   of someLt:
     # not (a < b)  ==  a >= b  ==  b <= a
-    result = swapArgs(n, "<=", mLeI)
+    result = swapArgs(n, opLe)
   of someLe:
-    result = swapArgs(n, "<", mLtI)
+    result = swapArgs(n, opLt)
   of mInSet:
     if n.sons[1].kind != nkCurly: return nil
     let t = n.sons[2].typ.skipTypes(abstractInst)
@@ -110,7 +124,7 @@ proc neg(n: PNode): PNode =
       b = n.sons[2].neg
     if a != nil and b != nil:
       result = newNodeI(nkCall, n.info, 3)
-      result.sons[0] = newSymNode(getSysMagic("and", mAnd))
+      result.sons[0] = newSymNode(opAnd)
       result.sons[1] = a
       result.sons[2] = b
     elif a != nil:
@@ -120,12 +134,12 @@ proc neg(n: PNode): PNode =
   else:
     # leave  not (a == 4)  as it is
     result = newNodeI(nkCall, n.info, 2)
-    result.sons[0] = newSymNode(getSysMagic("not", mNot))
+    result.sons[0] = newSymNode(opNot)
     result.sons[1] = n
 
 proc buildIsNil(arg: PNode): PNode =
   result = newNodeI(nkCall, arg.info, 2)
-  result.sons[0] = newSymNode(getSysMagic("isNil", mIsNil))
+  result.sons[0] = newSymNode(opIsNil)
   result.sons[1] = arg
 
 proc usefulFact(n: PNode): PNode =
@@ -154,7 +168,7 @@ proc usefulFact(n: PNode): PNode =
       b = usefulFact(n.sons[2])
     if a != nil and b != nil:
       result = newNodeI(nkCall, n.info, 3)
-      result.sons[0] = newSymNode(getSysMagic("and", mAnd))
+      result.sons[0] = newSymNode(opAnd)
       result.sons[1] = a
       result.sons[2] = b
     elif a != nil:
@@ -177,7 +191,7 @@ proc usefulFact(n: PNode): PNode =
       b = usefulFact(n.sons[2]).neg
     if a != nil and b != nil:
       result = newNodeI(nkCall, n.info, 3)
-      result.sons[0] = newSymNode(getSysMagic("and", mAnd))
+      result.sons[0] = newSymNode(opAnd)
       result.sons[1] = a
       result.sons[2] = b
       result = result.neg
@@ -520,7 +534,7 @@ proc buildOf(it, loc: PNode): PNode =
   s.typ = settype(loc)
   for i in 0..it.len-2: s.sons[i] = it.sons[i]
   result = newNodeI(nkCall, it.info, 3)
-  result.sons[0] = newSymNode(getSysMagic("contains", mInSet))
+  result.sons[0] = newSymNode(opContains)
   result.sons[1] = s
   result.sons[2] = loc
 
@@ -532,20 +546,20 @@ proc buildElse(n: PNode): PNode =
     for j in 0..branch.len-2:
       s.add(branch.sons[j])
   result = newNodeI(nkCall, n.info, 3)
-  result.sons[0] = newSymNode(getSysMagic("contains", mInSet))
+  result.sons[0] = newSymNode(opContains)
   result.sons[1] = s
   result.sons[2] = n.sons[0]
 
 proc addDiscriminantFact*(m: var TModel, n: PNode) =
   var fact = newNodeI(nkCall, n.info, 3)
-  fact.sons[0] = newSymNode(getSysMagic("==", mEqI))
+  fact.sons[0] = newSymNode(opEq)
   fact.sons[1] = n.sons[0]
   fact.sons[2] = n.sons[1]
   m.add fact
 
 proc addAsgnFact*(m: var TModel, key, value: PNode) =
   var fact = newNodeI(nkCall, key.info, 3)
-  fact.sons[0] = newSymNode(getSysMagic("==", mEqI))
+  fact.sons[0] = newSymNode(opEq)
   fact.sons[1] = key
   fact.sons[2] = value
   m.add fact
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index c31eb3121..93a7b7c72 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -32,6 +32,7 @@ proc considerAcc*(n: PNode): PIdent =
         of nkSym: id.add(x.sym.name.s)
         else: globalError(n.info, errIdentifierExpected, renderTree(n))
       result = getIdent(id)
+  of nkOpenSymChoice, nkClosedSymChoice: result = n.sons[0].sym.name
   else:
     globalError(n.info, errIdentifierExpected, renderTree(n))
  
diff --git a/compiler/nimrod.nimrod.cfg b/compiler/nimrod.nimrod.cfg
index 657c47b28..cc27d9f36 100644
--- a/compiler/nimrod.nimrod.cfg
+++ b/compiler/nimrod.nimrod.cfg
@@ -17,4 +17,6 @@ import:testability
   cincludes: "$lib/wrappers/libffi/common"
 @end
 
+define:useStdoutAsStdmsg
+
 cs:partial
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 845d4ae71..140687721 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -120,7 +120,8 @@ proc commonType*(x, y: PType): PType =
     if a.kind == tyObject and b.kind == tyObject:
       result = commonSuperclass(a, b)
       # this will trigger an error later:
-      if result.isNil: return x
+      if result.isNil or result == a: return x
+      if result == b: return y
       if k != tyNone:
         let r = result
         result = newType(k, r.owner)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index fb266ae3a..fedf19c79 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -84,10 +84,10 @@ proc initVar(a: PEffects, n: PNode) =
 proc initVarViaNew(a: PEffects, n: PNode) =
   if n.kind != nkSym: return
   let s = n.sym
-  if {tfNeedsInit, tfNotNil} * s.typ.flags == {tfNotNil}:
+  if {tfNeedsInit, tfNotNil} * s.typ.flags <= {tfNotNil}:
     # 'x' is not nil, but that doesn't mean it's not nil children
     # are initialized:
-    initVarViaNew(a, n)
+    initVar(a, n)
 
 proc useVar(a: PEffects, n: PNode) =
   let s = n.sym
@@ -466,8 +466,7 @@ proc track(tracked: PEffects, n: PNode) =
         mergeEffects(tracked, effectList.sons[exceptionEffects], n)
         mergeTags(tracked, effectList.sons[tagEffects], n)
     for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i))
-    if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, 
-                                           mNewSeq, mShallowCopy}:
+    if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
       # may not look like an assignment, but it is:
       initVarViaNew(tracked, n.sons[1])
     for i in 0 .. <safeLen(n):
@@ -581,22 +580,26 @@ proc setEffectsForProcType*(t: PType, n: PNode) =
     if not isNil(tagsSpec):
       effects.sons[tagEffects] = tagsSpec
 
+proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
+  newSeq(effects.sons, effectListLen)
+  effects.sons[exceptionEffects] = newNodeI(nkArgList, s.info)
+  effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
+  
+  t.exc = effects.sons[exceptionEffects]
+  t.tags = effects.sons[tagEffects]
+  t.owner = s
+  t.init = @[]
+  t.guards = @[]
+  
 proc trackProc*(s: PSym, body: PNode) =
   var effects = s.typ.n.sons[0]
   internalAssert effects.kind == nkEffectList
   # effects already computed?
   if sfForward in s.flags: return
   if effects.len == effectListLen: return
-  newSeq(effects.sons, effectListLen)
-  effects.sons[exceptionEffects] = newNodeI(nkArgList, body.info)
-  effects.sons[tagEffects] = newNodeI(nkArgList, body.info)
   
   var t: TEffects
-  t.exc = effects.sons[exceptionEffects]
-  t.tags = effects.sons[tagEffects]
-  t.owner = s
-  t.init = @[]
-  t.guards = @[]
+  initEffects(effects, s, t)
   track(t, body)
   
   if not isEmptyType(s.typ.sons[0]) and tfNeedsInit in s.typ.sons[0].flags and
@@ -619,3 +622,9 @@ proc trackProc*(s: PSym, body: PNode) =
     # after the check, use the formal spec:
     effects.sons[tagEffects] = tagsSpec
     
+proc trackTopLevelStmt*(module: PSym; n: PNode) =
+  var effects = newNode(nkEffectList, n.info)
+  var t: TEffects
+  initEffects(effects, module, t)
+
+  track(t, n)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index a07d91241..73b618f46 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -153,6 +153,9 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
     discard
   of nkSym:
     result.sym = replaceTypeVarsS(cl, n.sym)
+    if result.sym.typ.kind == tyEmpty:
+      # don't add the 'void' field
+      result = newNode(nkRecList, n.info)
   of nkRecWhen:
     var branch: PNode = nil              # the branch to take
     for i in countup(0, sonsLen(n) - 1):
diff --git a/compiler/transf.nim b/compiler/transf.nim
index deb821eff..0911950d0 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -754,6 +754,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode =
     result = processTransf(c, n, module)
     result = liftLambdasForTopLevel(module, result)
     incl(result.flags, nfTransf)
+    when useEffectSystem: trackTopLevelStmt(module, result)
 
 proc transformExpr*(module: PSym, n: PNode): PNode =
   if nfTransf in n.flags:
diff --git a/examples/htmltitle.nim b/examples/htmltitle.nim
index f3c672382..a3280bb13 100644
--- a/examples/htmltitle.nim
+++ b/examples/htmltitle.nim
@@ -4,10 +4,10 @@
 
 import os, streams, parsexml, strutils
 
-if paramCount() < 1: 
+if paramCount() < 1:
   quit("Usage: htmltitle filename[.html]")
 
-var filename = addFileExt(ParamStr(1), "html")
+var filename = addFileExt(paramStr(1), "html")
 var s = newFileStream(filename, fmRead)
 if s == nil: quit("cannot open the file " & filename)
 var x: TXmlParser
@@ -23,13 +23,13 @@ while true:
         title.add(x.charData)
         x.next()
       if x.kind == xmlElementEnd and cmpIgnoreCase(x.elementName, "title") == 0:
-        Echo("Title: " & title)
+        echo("Title: " & title)
         quit(0) # Success!
       else:
         echo(x.errorMsgExpected("/title"))
   
   of xmlEof: break # end of file reached
-  else: nil # ignore other events
+  else: discard # ignore other events
 
 x.close()
 quit("Could not determine title!")
diff --git a/koch.nim b/koch.nim
index 4d2b3bfb7..dcb66ae3e 100644
--- a/koch.nim
+++ b/koch.nim
@@ -58,6 +58,15 @@ Boot options:
 
 proc exe(f: string): string = return addFileExt(f, ExeExt)
 
+proc findNim(): string =
+  var nimrod = "nimrod".exe
+  result = "bin" / nimrod
+  if existsFile(result): return
+  for dir in split(getEnv("PATH"), PathSep):
+    if existsFile(dir / nimrod): return dir / nimrod
+  # assume there is a symlink to the exe or something:
+  return nimrod
+
 proc exec(cmd: string) =
   echo(cmd)
   if execShellCmd(cmd) != 0: quit("FAILURE")
@@ -70,15 +79,15 @@ const
   compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
 
 proc csource(args: string) = 
-  exec("nimrod cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" %
-       [args, NimrodVersion, compileNimInst])
+  exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" %
+       [args, NimrodVersion, compileNimInst, findNim()])
 
 proc zip(args: string) = 
-  exec("nimrod cc -r $2 --var:version=$1 zip compiler/nimrod.ini" %
-       [NimrodVersion, compileNimInst])
+  exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" %
+       [NimrodVersion, compileNimInst, findNim()])
   
 proc buildTool(toolname, args: string) = 
-  exec("nimrod cc $# $#" % [args, toolname])
+  exec("$# cc $# $#" % [findNim(), args, toolname])
   copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
 
 proc inno(args: string) =
@@ -90,13 +99,14 @@ proc inno(args: string) =
        NimrodVersion)
 
 proc install(args: string) = 
-  exec("nimrod cc -r $# --var:version=$# scripts compiler/nimrod.ini" %
-       [compileNimInst, NimrodVersion])
+  exec("$# cc -r $# --var:version=$# scripts compiler/nimrod.ini" %
+       [findNim(), compileNimInst, NimrodVersion])
   exec("sh ./install.sh $#" % args)
 
 proc web(args: string) =
-  exec(("nimrod cc -r tools/nimweb.nim web/nimrod --putenv:nimrodversion=$#" &
-        " --path:$#") % [NimrodVersion, getCurrentDir()])
+  exec(("$# cc -r tools/nimweb.nim web/nimrod --putenv:nimrodversion=$#" &
+        " --path:$#") % [findNim(), NimrodVersion,
+                         getCurrentDir().quoteIfContainsWhite])
 
 # -------------- boot ---------------------------------------------------------
 
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index 96afc6f4f..ab09dc860 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -167,7 +167,7 @@ proc asyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
   result = newAsyncSocket()
   result.socket = socket(domain, typ, protocol, buffered)
   result.proto = protocol
-  if result.socket == InvalidSocket: OSError(OSLastError())
+  if result.socket == invalidSocket: osError(osLastError())
   result.socket.setBlocking(false)
 
 proc toAsyncSocket*(sock: TSocket, state: TInfo = SockConnected): PAsyncSocket =
@@ -357,7 +357,7 @@ proc acceptAddr*(server: PAsyncSocket, client: var PAsyncSocket,
     client.sslNeedAccept = false
     client.info = SockConnected
 
-  if c == InvalidSocket: SocketError(server.socket)
+  if c == invalidSocket: socketError(server.socket)
   c.setBlocking(false) # TODO: Needs to be tested.
   
   # deleg.open is set in ``toDelegate``.
@@ -481,7 +481,7 @@ proc recvLine*(s: PAsyncSocket, line: var TaintedString): bool {.deprecated.} =
   of RecvDisconnected:
     result = true
   of RecvFail:
-    s.SocketError(async = true)
+    s.socketError(async = true)
     result = false
 {.pop.}
 
@@ -615,11 +615,11 @@ proc poll*(d: PDispatcher, timeout: int = 500): bool =
     if d.hasDataBuffered(d.deleVal):
       hasDataBufferedCount.inc()
       d.handleRead(d.deleVal)
-  if hasDataBufferedCount > 0: return True
+  if hasDataBufferedCount > 0: return true
   
   if readDg.len() == 0 and writeDg.len() == 0:
     ## TODO: Perhaps this shouldn't return if errorDg has something?
-    return False
+    return false
   
   if select(readDg, writeDg, errorDg, timeout) != 0:
     for i in 0..len(d.delegates)-1:
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index 02f0366cd..3d0cc2154 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -67,7 +67,7 @@ when withThreads:
 
 proc hookAux(st: TStackTrace, costs: int) =
   # this is quite performance sensitive!
-  when withThreads: Acquire profilingLock
+  when withThreads: acquire profilingLock
   inc totalCalls
   var last = high(st)
   while last > 0 and isNil(st[last]): dec last
@@ -106,7 +106,7 @@ proc hookAux(st: TStackTrace, costs: int) =
       h = ((5 * h) + 1) and high(profileData)
       inc chain
     maxChainLen = max(maxChainLen, chain)
-  when withThreads: Release profilingLock
+  when withThreads: release profilingLock
 
 when defined(memProfiler):
   const
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index bb70f28b6..89bb92f9a 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1037,7 +1037,10 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
   ## the process has finished. To execute a program without having a
   ## shell involved, use the `execProcess` proc of the `osproc`
   ## module.
-  result = c_system(command) shr 8
+  when defined(linux):
+    result = c_system(command) shr 8
+  else:
+    result = c_system(command)
 
 # Environment handling cannot be put into RTL, because the ``envPairs``
 # iterator depends on ``environment``.
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 6df85bbc6..9a43c0a7d 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -791,7 +791,10 @@ elif not defined(useNimRtl):
   proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
 
   proc execCmd(command: string): int =
-    result = csystem(command) shr 8
+    when defined(linux):
+      result = csystem(command) shr 8
+    else:
+      result = csystem(command)
 
   proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) =
     FD_ZERO(fd)
diff --git a/lib/wrappers/zip/zlib.nim b/lib/wrappers/zip/zlib.nim
index c4c6ac071..cd3a765c1 100644
--- a/lib/wrappers/zip/zlib.nim
+++ b/lib/wrappers/zip/zlib.nim
@@ -134,6 +134,7 @@ proc gzerror*(thefile: gzFile, errnum: var int32): pbytef{.cdecl, dynlib: libz,
     importc: "gzerror".}
 proc adler32*(adler: uLong, buf: pbytef, length: uInt): uLong{.cdecl, 
     dynlib: libz, importc: "adler32".}
+  ## **Warning**: Adler-32 requires at least a few hundred bytes to get rolling.
 proc crc32*(crc: uLong, buf: pbytef, length: uInt): uLong{.cdecl, dynlib: libz, 
     importc: "crc32".}
 proc deflateInitu*(strm: var TZStream, level: int32, version: cstring, 
diff --git a/tests/ccgbugs/tcgbug.nim b/tests/ccgbugs/tcgbug.nim
index 417b909ae..535424a27 100644
--- a/tests/ccgbugs/tcgbug.nim
+++ b/tests/ccgbugs/tcgbug.nim
@@ -19,5 +19,18 @@ var
 new(a)
 q(a)
 
+# bug #914
+var x = newWideCString("Hello")
+
 echo "success"
 
+
+# bug #833
+
+type
+  PFuture*[T] = ref object
+    value*: T
+    finished*: bool
+    cb: proc (future: PFuture[T]) {.closure.}
+
+var k = PFuture[void]()
diff --git a/tests/stdlib/tsets.nim b/tests/collections/tsets.nim
index 656c5b3f2..656c5b3f2 100644
--- a/tests/stdlib/tsets.nim
+++ b/tests/collections/tsets.nim
diff --git a/tests/effects/teffects6.nim b/tests/effects/teffects6.nim
index 54200f2c3..47c85c160 100644
--- a/tests/effects/teffects6.nim
+++ b/tests/effects/teffects6.nim
@@ -4,7 +4,7 @@ type
   PMenuItem = ref object
 
 proc createMenuItem*(menu: PMenu, label: string, 
-                     action: proc (i: PMenuItem, p: pointer) {.cdecl.}) = nil
+                    action: proc (i: PMenuItem, p: pointer) {.cdecl.}) = discard
 
 var s: PMenu
 createMenuItem(s, "Go to definition...",
diff --git a/tests/exprs/tifexpr_typeinference.nim b/tests/exprs/tifexpr_typeinference.nim
new file mode 100644
index 000000000..3ae95c571
--- /dev/null
+++ b/tests/exprs/tifexpr_typeinference.nim
@@ -0,0 +1,20 @@
+#bug #712
+
+import tables
+
+proc test(): TTable[string, string] =
+  discard
+
+proc test2(): TTable[string, string] =
+  discard
+
+var x = 5
+let blah =
+  case x
+  of 5:
+    test2()
+  of 2:
+    test()
+  else: test()
+
+echo blah.len
diff --git a/tests/notnil/tnotnil3.nim b/tests/notnil/tnotnil3.nim
new file mode 100644
index 000000000..b7c7a811d
--- /dev/null
+++ b/tests/notnil/tnotnil3.nim
@@ -0,0 +1,35 @@
+discard """
+  errormsg: "cannot prove 'variable' is not nil"
+  line: 31
+"""
+
+# bug #584
+# Testprogram for 'not nil' check
+
+const testWithResult = true
+
+type
+  A = object
+  B = object
+  C = object
+    a: ref A
+    b: ref B
+
+
+proc testNotNil(c: ref C not nil) =
+  discard
+
+
+when testWithResult:
+  proc testNotNilOnResult(): ref C =
+    new(result)
+    #result.testNotNil() # Here 'not nil' can't be proved
+
+
+var variable: ref C
+new(variable)
+variable.testNotNil() # Here 'not nil' is proved
+
+when testWithResult:
+  discard testNotNilOnResult()
+
diff --git a/tests/template/ttempl5.nim b/tests/template/ttempl5.nim
index 85692e97b..1f2378780 100644
--- a/tests/template/ttempl5.nim
+++ b/tests/template/ttempl5.nim
@@ -3,3 +3,16 @@ import mtempl5
 
 echo templ()
 
+#bug #892
+
+proc parse_to_close(value: string, index: int, open='(', close=')'): int =
+    discard
+
+# Call parse_to_close
+template get_next_ident: stmt =
+    discard "{something}".parse_to_close(0, open = '{', close = '}')
+
+get_next_ident()
+
+
+#identifier expected, but found '(open|open|open)'
diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim
index eb674a171..74d8811b8 100644
--- a/tests/testament/htmlgen.nim
+++ b/tests/testament/htmlgen.nim
@@ -9,7 +9,7 @@
 
 ## HTML generator for the tester.
 
-import db_sqlite, cgi, backend, strutils
+import db_sqlite, cgi, backend, strutils, json
 
 const
   TableHeader = """<table border="1">
@@ -114,8 +114,6 @@ proc getCommit(db: TDbConn, c: int): string =
   for thisCommit in db.rows(sql"select id from [Commit] order by id desc"):
     if commit == 0: result = thisCommit[0]
     inc commit
-  if result.isNil:
-    quit "cannot determine commit " & $c
 
 proc generateHtml*(filename: string, commit: int) =
   const selRow = """select name, category, target, action, 
@@ -161,20 +159,48 @@ proc generateHtml*(filename: string, commit: int) =
   close(outfile)
 
 proc generateJson*(filename: string, commit: int) =
-  const selRow = """select count(*),
+  const
+    selRow = """select count(*),
                            sum(result = 'reSuccess'), 
                            sum(result = 'reIgnored')
-                    from TestResult
-                    where [commit] = ? and machine = ?
-                    order by category"""
+                from TestResult
+                where [commit] = ? and machine = ?
+                order by category"""
+    selDiff = """select A.category || '/' || A.target || '/' || A.name,
+                        A.result,
+                        B.result
+                from TestResult A
+                inner join TestResult B
+                on A.name = B.name and A.category = B.category
+                where A.[commit] = ? and B.[commit] = ? and A.machine = ?
+                   and A.result != B.result"""
   var db = open(connection="testament.db", user="testament", password="",
                 database="testament")
   let lastCommit = db.getCommit(commit)
+  if lastCommit.isNil:
+    quit "cannot determine commit " & $commit
+
+  let previousCommit = db.getCommit(commit-1)
 
   var outfile = open(filename, fmWrite)
 
-  let data = db.getRow(sql(selRow), lastCommit, $backend.getMachine(db))
+  let machine = $backend.getMachine(db)
+  let data = db.getRow(sql(selRow), lastCommit, machine)
+
+  outfile.writeln("""{"total": $#, "passed": $#, "skipped": $#""" % data)
+
+  if not previousCommit.isNil:
+    let diff = newJArray()
+
+    for row in db.rows(sql(selDiff), previousCommit, lastCommit, machine):
+      var obj = newJObject()
+      obj["name"] = %row[0]
+      obj["old"] = %row[1]
+      obj["new"] = %row[2]
+      diff.add obj
+    outfile.writeln(""", "diff": """)
+    outfile.writeln(diff.pretty)
 
-  outfile.writeln("""{"total": $#, "passed": $#, "skipped": $#}""" % data)
+  outfile.writeln "}"
   close(db)
   close(outfile)
diff --git a/todo.txt b/todo.txt
index 44aa39791..2e6eb708b 100644
--- a/todo.txt
+++ b/todo.txt
@@ -4,7 +4,6 @@ version 0.9.4
 - fix GC issues
 - fix macros\tstringinterp.nim
 - test and fix showoff
-- fix closure iterators
 
 
 Bugs
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index 56d6bcadb..ff343bd2a 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -130,7 +130,7 @@ proc walkDirRecursively(s: var seq[string], root, ext: string) =
       if cmpIgnoreCase(ext, splitFile(f).ext) == 0:
         add(s, f)
     of pcDir: walkDirRecursively(s, f, ext)
-    of pcLinkToDir: nil
+    of pcLinkToDir: discard
 
 proc addFiles(s: var seq[string], dir, ext: string, patterns: seq[string]) =
   for p in items(patterns):
@@ -153,7 +153,7 @@ proc parseIniFile(c: var TConfigData) =
       of cfgSectionStart:
         section = normalize(k.section)
         case section
-        of "project", "links", "tabs", "ticker", "documentation", "var": nil
+        of "project", "links", "tabs", "ticker", "documentation", "var": discard
         else: echo("[Warning] Skipping unknown section: " & section)
 
       of cfgKeyValuePair:
@@ -168,7 +168,7 @@ proc parseIniFile(c: var TConfigData) =
           of "logo": c.logo = v
           of "authors": c.authors = v
           else: quit(errorStr(p, "unknown variable: " & k.key))
-        of "var": nil
+        of "var": discard
         of "links":
           let valID = v.split(';')
           add(c.links, (k.key.replace('_', ' '), valID[1], valID[0]))
@@ -186,7 +186,7 @@ proc parseIniFile(c: var TConfigData) =
           let vSplit = v.split('-')
           doAssert vSplit.len == 2
           c.quotations[k.key.normalize] = (vSplit[0], vSplit[1])
-        else: nil
+        else: discard
 
       of cfgOption: quit(errorStr(p, "syntax error"))
       of cfgError: quit(errorStr(p, k.msg))
@@ -211,9 +211,9 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
   ## it didn't make much sense to integrate into the existing generic
   ## documentation builders.
   const src = "doc"/"docgen_sample.nim"
-  Exec("nimrod doc $# -o:$# $#" %
+  exec("nimrod doc $# -o:$# $#" %
     [c.nimrodArgs, destPath / "docgen_sample.html", src])
-  Exec("nimrod doc2 $# -o:$# $#" %
+  exec("nimrod doc2 $# -o:$# $#" %
     [c.nimrodArgs, destPath / "docgen_sample2.html", src])
 
 proc buildDoc(c: var TConfigData, destPath: string) =