summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/cgen.nim2
-rw-r--r--compiler/charsets.nim49
-rw-r--r--compiler/commands.nim22
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/nversion.nim7
-rw-r--r--compiler/options.nim2
-rw-r--r--compiler/parsecfg.nim346
-rw-r--r--compiler/pendx.nim18
-rw-r--r--compiler/semtypes.nim13
-rw-r--r--compiler/semtypinst.nim5
-rw-r--r--compiler/syntaxes.nim2
-rw-r--r--compiler/typesrenderer.nim8
-rw-r--r--doc/docs.txt8
-rw-r--r--doc/manual.txt51
-rw-r--r--koch.nim2
-rw-r--r--lib/pure/collections/tables.nim68
-rw-r--r--lib/pure/future.nim2
-rw-r--r--lib/pure/os.nim29
-rw-r--r--lib/system.nim91
-rw-r--r--lib/system/embedded.nim2
-rw-r--r--lib/system/excpt.nim14
-rw-r--r--lib/system/inclrtl.nim6
-rw-r--r--lib/wrappers/sqlite3.nim6
-rw-r--r--tests/ccgbugs/tcgbug.nim3
-rw-r--r--tests/system/tsysspawn.nim29
-rw-r--r--tools/website.tmpl2
-rw-r--r--web/download.txt154
-rw-r--r--web/index.txt10
-rw-r--r--web/news.txt32
-rw-r--r--web/ticker.txt6
30 files changed, 450 insertions, 540 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index f64ebacfb..8d66d7a3b 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -730,7 +730,7 @@ proc retIsNotVoid(s: PSym): bool =
   result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
 
 proc initFrame(p: BProc, procname, filename: PRope): PRope =
-  discard cgsym(p.module, "pushFrame")
+  discard cgsym(p.module, "nimFrame")
   if p.maxFrameLen > 0:
     discard cgsym(p.module, "TVarSlot")
     result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N",
diff --git a/compiler/charsets.nim b/compiler/charsets.nim
deleted file mode 100644
index d3d00b687..000000000
--- a/compiler/charsets.nim
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-#
-#           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-const 
-  CharSize* = SizeOf(Char)
-  Lrz* = ' '
-  Apo* = '\''
-  Tabulator* = '\x09'
-  ESC* = '\x1B'
-  CR* = '\x0D'
-  FF* = '\x0C'
-  LF* = '\x0A'
-  BEL* = '\x07'
-  BACKSPACE* = '\x08'
-  VT* = '\x0B'
-
-when defined(macos): 
-  DirSep == ':'
-  "\n" == CR & ""
-  FirstNLchar == CR
-  PathSep == ';'              # XXX: is this correct?
-else: 
-  when defined(unix): 
-    DirSep == '/'
-    "\n" == LF & ""
-    FirstNLchar == LF
-    PathSep == ':'
-  else: 
-    # windows, dos
-    DirSep == '\\'
-    "\n" == CR + LF
-    FirstNLchar == CR
-    DriveSeparator == ':'
-    PathSep == ';'
-UpLetters == {'A'..'Z', '\xC0'..'\xDE'}
-DownLetters == {'a'..'z', '\xDF'..'\xFF'}
-Numbers == {'0'..'9'}
-Letters == UpLetters + DownLetters
-type 
-  TCharSet* = set[Char]
-  PCharSet* = ref TCharSet
-
-# implementation
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 8339219ed..366019c19 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -50,11 +50,33 @@ proc writeAdvancedUsage(pass: TCmdLinePass) =
                                  CPU[platform.hostCPU].name]) & AdvancedUsage)
     quit(0)
 
+template bootSwitch(name, expr, userString: expr): expr =
+  # Helper to build boot constants, for debugging you can 'echo' the else part.
+  const name = if expr: " " & userString else: ""
+
+bootSwitch(usedAvoidTimeMachine, noTimeMachine, "-d:avoidTimeMachine")
+bootSwitch(usedRelease, defined(release), "-d:release")
+bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
+bootSwitch(usedGnuReadline, defined(useGnuReadline), "-d:useGnuReadline")
+bootSwitch(usedNativeStacktrace,
+  defined(nativeStackTrace) and nativeStackTraceSupported,
+  "-d:nativeStackTrace")
+bootSwitch(usedNoCaas, defined(noCaas), "-d:noCaas")
+bootSwitch(usedFFI, hasFFI, "-d:useFFI")
+bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
+bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
+bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational")
+bootSwitch(usedNoGC, defined(nogc), "--gc:none")
+
+
 proc writeVersionInfo(pass: TCmdLinePass) = 
   if pass == passCmd1:
     msgWriteln(`%`(HelpMessage, [VersionAsString, 
                                  platform.OS[platform.hostOS].name, 
                                  CPU[platform.hostCPU].name]))
+    msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
+      usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &
+      usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedNoGC)
     quit(0)
 
 var
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 4117fc461..17bb5db55 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -49,6 +49,7 @@ proc initDefines*() =
   defineSymbol("nimcomputedgoto")
   defineSymbol("nimunion")
   defineSymbol("nimnewshared")
+  defineSymbol("nimrequiresnimframe")
   
   # add platform specific symbols:
   case targetCPU
diff --git a/compiler/nversion.nim b/compiler/nversion.nim
index db38354ce..3c868ed2a 100644
--- a/compiler/nversion.nim
+++ b/compiler/nversion.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -12,11 +12,10 @@
 
 const 
   MaxSetElements* = 1 shl 16  # (2^16) to support unicode character sets?
-  defaultAsmMarkerSymbol* = '!'
   VersionMajor* = 0
   VersionMinor* = 9
-  VersionPatch* = 3
+  VersionPatch* = 5
   VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
 
-  RodFileVersion* = "1214"       # modify this if the rod-format changes!
+  RodFileVersion* = "1215"       # modify this if the rod-format changes!
 
diff --git a/compiler/options.nim b/compiler/options.nim
index 36d343d1b..58a340d21 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -16,7 +16,7 @@ const
   hasFFI* = defined(useFFI)
   newScopeForIf* = true
   useCaas* = not defined(noCaas)
-  noTimeMachine = defined(avoidTimeMachine) and defined(macosx)
+  noTimeMachine* = defined(avoidTimeMachine) and defined(macosx)
 
 type                          # please make sure we have under 32 options
                               # (improves code efficiency a lot!)
diff --git a/compiler/parsecfg.nim b/compiler/parsecfg.nim
deleted file mode 100644
index e0d1afff1..000000000
--- a/compiler/parsecfg.nim
+++ /dev/null
@@ -1,346 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# A HIGH-PERFORMANCE configuration file parser;
-# the Nimrod version of this file is part of the
-# standard library.
-
-import 
-  llstream, nhashes, strutils, nimlexbase
-
-type 
-  TCfgEventKind* = enum 
-    cfgEof,                   # end of file reached
-    cfgSectionStart,          # a ``[section]`` has been parsed
-    cfgKeyValuePair,          # a ``key=value`` pair has been detected
-    cfgOption,                # a ``--key=value`` command line option
-    cfgError # an error ocurred during parsing; msg contains the
-             # error message
-  TCfgEvent* = object of TObject
-    case kind*: TCfgEventKind
-    of cfgEof: 
-        nil
-
-    of cfgSectionStart: 
-        section*: string
-
-    of cfgKeyValuePair, cfgOption: 
-        key*, value*: string
-
-    of cfgError: 
-        msg*: string
-
-  
-  TTokKind* = enum 
-    tkInvalid, tkEof,         # order is important here!
-    tkSymbol, tkEquals, tkColon, tkBracketLe, tkBracketRi, tkDashDash
-  TToken*{.final.} = object   # a token
-    kind*: TTokKind           # the type of the token
-    literal*: string          # the parsed (string) literal
-  
-  TParserState* = enum 
-    startState, commaState
-  TCfgParser* = object of TBaseLexer
-    tok*: TToken
-    state*: TParserState
-    filename*: string
-
-
-proc Open*(c: var TCfgParser, filename: string, inputStream: PLLStream)
-proc Close*(c: var TCfgParser)
-proc next*(c: var TCfgParser): TCfgEvent
-proc getColumn*(c: TCfgParser): int
-proc getLine*(c: TCfgParser): int
-proc getFilename*(c: TCfgParser): string
-proc errorStr*(c: TCfgParser, msg: string): string
-# implementation
-
-const 
-  SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'} # 
-                                                                           # ----------------------------------------------------------------------------
-
-proc rawGetTok(c: var TCfgParser, tok: var TToken)
-proc open(c: var TCfgParser, filename: string, inputStream: PLLStream) = 
-  openBaseLexer(c, inputStream)
-  c.filename = filename
-  c.state = startState
-  c.tok.kind = tkInvalid
-  c.tok.literal = ""
-  rawGetTok(c, c.tok)
-
-proc close(c: var TCfgParser) = 
-  closeBaseLexer(c)
-
-proc getColumn(c: TCfgParser): int = 
-  result = getColNumber(c, c.bufPos)
-
-proc getLine(c: TCfgParser): int = 
-  result = c.linenumber
-
-proc getFilename(c: TCfgParser): string = 
-  result = c.filename
-
-proc handleHexChar(c: var TCfgParser, xi: var int) = 
-  case c.buf[c.bufpos]
-  of '0'..'9': 
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
-    inc(c.bufpos)
-  of 'a'..'f': 
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
-    inc(c.bufpos)
-  of 'A'..'F': 
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
-    inc(c.bufpos)
-  else: 
-    nil
-
-proc handleDecChars(c: var TCfgParser, xi: var int) = 
-  while c.buf[c.bufpos] in {'0'..'9'}: 
-    xi = (xi * 10) + (ord(c.buf[c.bufpos]) - ord('0'))
-    inc(c.bufpos)
-
-proc getEscapedChar(c: var TCfgParser, tok: var TToken) = 
-  var xi: int
-  inc(c.bufpos)               # skip '\'
-  case c.buf[c.bufpos]
-  of 'n', 'N': 
-    tok.literal = tok.literal & "\n"
-    Inc(c.bufpos)
-  of 'r', 'R', 'c', 'C': 
-    add(tok.literal, CR)
-    Inc(c.bufpos)
-  of 'l', 'L': 
-    add(tok.literal, LF)
-    Inc(c.bufpos)
-  of 'f', 'F': 
-    add(tok.literal, FF)
-    inc(c.bufpos)
-  of 'e', 'E': 
-    add(tok.literal, ESC)
-    Inc(c.bufpos)
-  of 'a', 'A': 
-    add(tok.literal, BEL)
-    Inc(c.bufpos)
-  of 'b', 'B': 
-    add(tok.literal, BACKSPACE)
-    Inc(c.bufpos)
-  of 'v', 'V': 
-    add(tok.literal, VT)
-    Inc(c.bufpos)
-  of 't', 'T': 
-    add(tok.literal, Tabulator)
-    Inc(c.bufpos)
-  of '\'', '\"': 
-    add(tok.literal, c.buf[c.bufpos])
-    Inc(c.bufpos)
-  of '\\': 
-    add(tok.literal, '\\')
-    Inc(c.bufpos)
-  of 'x', 'X': 
-    inc(c.bufpos)
-    xi = 0
-    handleHexChar(c, xi)
-    handleHexChar(c, xi)
-    add(tok.literal, Chr(xi))
-  of '0'..'9': 
-    xi = 0
-    handleDecChars(c, xi)
-    if (xi <= 255): add(tok.literal, Chr(xi))
-    else: tok.kind = tkInvalid
-  else: tok.kind = tkInvalid
-  
-proc HandleCRLF(c: var TCfgParser, pos: int): int = 
-  case c.buf[pos]
-  of CR: result = lexbase.HandleCR(c, pos)
-  of LF: result = lexbase.HandleLF(c, pos)
-  else: result = pos
-  
-proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) = 
-  var 
-    pos: int
-    ch: Char
-    buf: cstring
-  pos = c.bufPos + 1          # skip "
-  buf = c.buf                 # put `buf` in a register
-  tok.kind = tkSymbol
-  if (buf[pos] == '\"') and (buf[pos + 1] == '\"'): 
-    # long string literal:
-    inc(pos, 2)               # skip ""
-                              # skip leading newline:
-    pos = HandleCRLF(c, pos)
-    buf = c.buf
-    while true: 
-      case buf[pos]
-      of '\"': 
-        if (buf[pos + 1] == '\"') and (buf[pos + 2] == '\"'): break 
-        add(tok.literal, '\"')
-        Inc(pos)
-      of CR, LF: 
-        pos = HandleCRLF(c, pos)
-        buf = c.buf
-        tok.literal = tok.literal & "\n"
-      of lexbase.EndOfFile: 
-        tok.kind = tkInvalid
-        break 
-      else: 
-        add(tok.literal, buf[pos])
-        Inc(pos)
-    c.bufpos = pos +
-        3                     # skip the three """
-  else: 
-    # ordinary string literal
-    while true: 
-      ch = buf[pos]
-      if ch == '\"': 
-        inc(pos)              # skip '"'
-        break 
-      if ch in {CR, LF, lexbase.EndOfFile}: 
-        tok.kind = tkInvalid
-        break 
-      if (ch == '\\') and not rawMode: 
-        c.bufPos = pos
-        getEscapedChar(c, tok)
-        pos = c.bufPos
-      else: 
-        add(tok.literal, ch)
-        Inc(pos)
-    c.bufpos = pos
-
-proc getSymbol(c: var TCfgParser, tok: var TToken) = 
-  var 
-    pos: int
-    buf: cstring
-  pos = c.bufpos
-  buf = c.buf
-  while true: 
-    add(tok.literal, buf[pos])
-    Inc(pos)
-    if not (buf[pos] in SymChars): break 
-  c.bufpos = pos
-  tok.kind = tkSymbol
-
-proc skip(c: var TCfgParser) = 
-  var 
-    buf: cstring
-    pos: int
-  pos = c.bufpos
-  buf = c.buf
-  while true: 
-    case buf[pos]
-    of ' ': 
-      Inc(pos)
-    of Tabulator: 
-      inc(pos)
-    of '#', ';': 
-      while not (buf[pos] in {CR, LF, lexbase.EndOfFile}): inc(pos)
-    of CR, LF: 
-      pos = HandleCRLF(c, pos)
-      buf = c.buf
-    else: 
-      break                   # EndOfFile also leaves the loop
-  c.bufpos = pos
-
-proc rawGetTok(c: var TCfgParser, tok: var TToken) = 
-  tok.kind = tkInvalid
-  setlen(tok.literal, 0)
-  skip(c)
-  case c.buf[c.bufpos]
-  of '=': 
-    tok.kind = tkEquals
-    inc(c.bufpos)
-    tok.literal = "="
-  of '-': 
-    inc(c.bufPos)
-    if c.buf[c.bufPos] == '-': inc(c.bufPos)
-    tok.kind = tkDashDash
-    tok.literal = "--"
-  of ':': 
-    tok.kind = tkColon
-    inc(c.bufpos)
-    tok.literal = ":"
-  of 'r', 'R': 
-    if c.buf[c.bufPos + 1] == '\"': 
-      Inc(c.bufPos)
-      getString(c, tok, true)
-    else: 
-      getSymbol(c, tok)
-  of '[': 
-    tok.kind = tkBracketLe
-    inc(c.bufpos)
-    tok.literal = "["
-  of ']': 
-    tok.kind = tkBracketRi
-    Inc(c.bufpos)
-    tok.literal = "]"
-  of '\"': 
-    getString(c, tok, false)
-  of lexbase.EndOfFile: 
-    tok.kind = tkEof
-  else: getSymbol(c, tok)
-  
-proc errorStr(c: TCfgParser, msg: string): string = 
-  result = `%`("$1($2, $3) Error: $4", 
-               [c.filename, $(getLine(c)), $(getColumn(c)), msg])
-
-proc getKeyValPair(c: var TCfgParser, kind: TCfgEventKind): TCfgEvent = 
-  if c.tok.kind == tkSymbol: 
-    result.kind = kind
-    result.key = c.tok.literal
-    result.value = ""
-    rawGetTok(c, c.tok)
-    while c.tok.literal == ".": 
-      add(result.key, '.')
-      rawGetTok(c, c.tok)
-      if c.tok.kind == tkSymbol: 
-        add(result.key, c.tok.literal)
-        rawGetTok(c, c.tok)
-      else: 
-        result.kind = cfgError
-        result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal)
-        break 
-    if c.tok.kind in {tkEquals, tkColon}: 
-      rawGetTok(c, c.tok)
-      if c.tok.kind == tkSymbol: 
-        result.value = c.tok.literal
-      else: 
-        result.kind = cfgError
-        result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal)
-      rawGetTok(c, c.tok)
-  else: 
-    result.kind = cfgError
-    result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal)
-    rawGetTok(c, c.tok)
-
-proc next(c: var TCfgParser): TCfgEvent = 
-  case c.tok.kind
-  of tkEof: 
-    result.kind = cfgEof
-  of tkDashDash: 
-    rawGetTok(c, c.tok)
-    result = getKeyValPair(c, cfgOption)
-  of tkSymbol: 
-    result = getKeyValPair(c, cfgKeyValuePair)
-  of tkBracketLe: 
-    rawGetTok(c, c.tok)
-    if c.tok.kind == tkSymbol: 
-      result.kind = cfgSectionStart
-      result.section = c.tok.literal
-    else: 
-      result.kind = cfgError
-      result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal)
-    rawGetTok(c, c.tok)
-    if c.tok.kind == tkBracketRi: 
-      rawGetTok(c, c.tok)
-    else: 
-      result.kind = cfgError
-      result.msg = errorStr(c, "\']\' expected, but found: " & c.tok.literal)
-  of tkInvalid, tkBracketRi, tkEquals, tkColon: 
-    result.kind = cfgError
-    result.msg = errorStr(c, "invalid token: " & c.tok.literal)
-    rawGetTok(c, c.tok)
diff --git a/compiler/pendx.nim b/compiler/pendx.nim
deleted file mode 100644
index 2942968a0..000000000
--- a/compiler/pendx.nim
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-#
-#           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-import 
-  llstream, lexer, parser, idents, strutils, ast, msgs
-
-proc ParseAll*(p: var TParser): PNode = 
-  result = nil
-
-proc parseTopLevelStmt*(p: var TParser): PNode = 
-  result = nil
-  
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 384bdc8a3..6289ecc85 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -194,10 +194,15 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
     if isRange(n[1]):
       result = semRangeAux(c, n[1], prev)
       let n = result.n
-      if n.sons[0].kind in {nkCharLit..nkUInt64Lit}:
-        if n.sons[0].intVal > 0 or n.sons[1].intVal < 0:
-          incl(result.flags, tfNeedsInit)
-      elif n.sons[0].floatVal > 0.0 or n.sons[1].floatVal < 0.0:
+      if n.sons[0].kind in {nkCharLit..nkUInt64Lit} and n.sons[0].intVal > 0:
+        incl(result.flags, tfNeedsInit)
+      elif n.sons[1].kind in {nkCharLit..nkUInt64Lit} and n.sons[1].intVal < 0:
+        incl(result.flags, tfNeedsInit)
+      elif n.sons[0].kind in {nkFloatLit..nkFloat64Lit} and 
+          n.sons[0].floatVal > 0.0:
+        incl(result.flags, tfNeedsInit)
+      elif n.sons[1].kind in {nkFloatLit..nkFloat64Lit} and 
+          n.sons[1].floatVal < 0.0:
         incl(result.flags, tfNeedsInit)
     else:
       localError(n.sons[0].info, errRangeExpected)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 271a01266..33de40f34 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -352,8 +352,9 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
     result = handleGenericInvokation(cl, t)
 
   of tyGenericBody:
-    internalError(cl.info, "ReplaceTypeVarsT: tyGenericBody" )
-    result = replaceTypeVarsT(cl, lastSon(t))
+    localError(cl.info, errCannotInstantiateX, typeToString(t))
+    result = t
+    #result = replaceTypeVarsT(cl, lastSon(t))
 
   of tyFromExpr:
     if cl.allowMetaTypes: return
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index 478c2a837..d5062544f 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -62,7 +62,6 @@ proc parseAll(p: var TParsers): PNode =
   of skinEndX: 
     internalError("parser to implement") 
     result = ast.emptyNode
-    # skinEndX: result := pendx.parseAll(p.parser);
   
 proc parseTopLevelStmt(p: var TParsers): PNode = 
   case p.skin
@@ -73,7 +72,6 @@ proc parseTopLevelStmt(p: var TParsers): PNode =
   of skinEndX: 
     internalError("parser to implement") 
     result = ast.emptyNode
-    #skinEndX: result := pendx.parseTopLevelStmt(p.parser);
   
 proc utf8Bom(s: string): int = 
   if (s[0] == '\xEF') and (s[1] == '\xBB') and (s[2] == '\xBF'): 
diff --git a/compiler/typesrenderer.nim b/compiler/typesrenderer.nim
index ebb9b7e15..790bd1047 100644
--- a/compiler/typesrenderer.nim
+++ b/compiler/typesrenderer.nim
@@ -69,7 +69,7 @@ proc renderType(n: PNode): string =
     for i in 1 .. <len(n): result.add(renderType(n[i]) & ',')
     result[<len(result)] = ']'
   else: result = ""
-  assert (not result.isNil)
+  assert(not result.isNil)
 
 
 proc renderParamTypes(found: var seq[string], n: PNode) =
@@ -86,13 +86,11 @@ proc renderParamTypes(found: var seq[string], n: PNode) =
     let typePos = len(n) - 2
     assert typePos > 0
     var typeStr = renderType(n[typePos])
-    if typeStr.len < 1:
+    if typeStr.len < 1 and n[typePos+1].kind != nkEmpty:
       # Try with the last node, maybe its a default value.
-      assert n[typePos+1].kind != nkEmpty
       let typ = n[typePos+1].typ
       if not typ.isNil: typeStr = typeToString(typ, preferExported)
-      if typeStr.len < 1:
-        return
+      if typeStr.len < 1: return
     for i in 0 .. <typePos:
       assert n[i].kind == nkIdent
       found.add(typeStr)
diff --git a/doc/docs.txt b/doc/docs.txt
index 2162d6564..8126da86c 100644
--- a/doc/docs.txt
+++ b/doc/docs.txt
@@ -6,19 +6,19 @@ The documentation consists of several documents:
 - | `Tutorial (part II) <tut2.html>`_
   | The Nimrod tutorial part two deals with the advanced language constructs.
 
+- | `Language Manual <manual.html>`_
+  | The Nimrod manual is a draft that will evolve into a proper specification.
+
 - | `Library documentation <lib.html>`_
   | This document describes Nimrod's standard library.
 
-- | `User guide <nimrodc.html>`_
+- | `Compiler user guide <nimrodc.html>`_
   | The user guide lists command line arguments, special features of the
     compiler, etc.
 
 - | `Tools documentation <tools.html>`_
   | Description of some tools that come with the standard distribution.
 
-- | `Manual <manual.html>`_
-  | The Nimrod manual is a draft that will evolve into a proper specification.
-
 - | `GC <gc.html>`_
   | Additional documentation about Nimrod's GC and how to operate it in a
   | realtime setting.
diff --git a/doc/manual.txt b/doc/manual.txt
index d6b9f296e..39e2bad2a 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -3575,6 +3575,8 @@ match anything without discrimination.
 User defined type classes
 -------------------------
 
+**Note**: User defined type classes are still in development.
+
 The user-defined type classes are available in two flavours - declarative and
 imperative. Both are used to specify an arbitrary set of requirements that the
 matched type must satisfy.
@@ -3599,13 +3601,13 @@ b) all statically evaluatable boolean expressions in the body must be true
 
 The identifiers following the `generic` keyword represent instances of the
 currently matched type. These instances can act both as variables of the type,
-when used in contexts, where a value is expected, and as the type itself, when
-used in a contexts, where a type is expected.
+when used in contexts where a value is expected, and as the type itself when
+used in contexts where a type is expected.
 
 Please note that the ``is`` operator allows one to easily verify the precise
 type signatures of the required operations, but since type inference and
 default parameters are still applied in the provided block, it's also possible
-to encode usage protocols that doesn't reveal implementation details.
+to encode usage protocols that do not reveal implementation details.
 
 As a special rule providing further convenience when writing type classes, any
 type value appearing in a callable expression will be treated as a variable of
@@ -4118,6 +4120,8 @@ Special Types
 static[T]
 ---------
 
+**Note**: static[T] is still in development.
+
 As their name suggests, static params must be known at compile-time:
 
 .. code-block:: nimrod
@@ -4255,6 +4259,7 @@ types that will match the typedesc param:
 
 The constraint can be a concrete type or a type class.
 
+
 Special Operators
 =================
 
@@ -5600,10 +5605,8 @@ This is only useful if the program is compiled as a dynamic library via the
 Threads
 =======
 
-Even though Nimrod's `thread`:idx: support and semantics are preliminary, 
-they should be quite usable already. To enable thread support 
-the ``--threads:on`` command line switch needs to be used. The ``system``
-module then contains several threading primitives. 
+To enable thread support the ``--threads:on`` command line switch needs to 
+be used. The ``system`` module then contains several threading primitives. 
 See the `threads <threads.html>`_ and `channels <channels.html>`_ modules 
 for the thread API.
 
@@ -5645,6 +5648,11 @@ contain a ``ref`` or ``closure`` type. This enforces
 the *no heap sharing restriction*. 
 
 Routines that are imported from C are always assumed to be ``gcsafe``.
+To enable the GC-safety checking the ``--threadAnalysis:on`` command line
+switch must be used. This is a temporary workaround to ease the porting effort
+from old code to the new threading model. In the future the thread analysis
+will always be performed.
+
 
 Future directions:
 
@@ -5675,6 +5683,35 @@ in one thread cannot affect any other thread. However, an *unhandled*
 exception in one thread terminates the whole *process*!
 
 
+Spawn
+-----
+
+Nimrod has a builtin thread pool that can be used for CPU intensive tasks. For
+IO intensive tasks the upcoming ``async`` and ``await`` features should be
+used instead. `spawn`:idx: is used to pass a task to the thread pool:
+
+.. code-block:: nimrod
+  proc processLine(line: string) =
+    # do some heavy lifting here:
+    discard
+    
+  for x in lines("myinput.txt"):
+    spawn processLine(x)
+  sync()
+
+Currently the expression that ``spawn`` takes is however quite restricted: 
+
+* It must be a call expresion ``f(a, ...)``.
+* ``f`` must be ``gcsafe``.
+* ``f`` must not have the calling convention ``closure``.
+* ``f``'s parameters may not be of type ``var`` nor may they contain ``ref``.
+  This means you have to use raw ``ptr``'s for data passing reminding the
+  programmer to be careful.
+* For *safe* data exchange between ``f`` and the caller a global ``TChannel``
+  needs to be used. Other means will be provided soon.
+
+
+
 Taint mode
 ==========
 
diff --git a/koch.nim b/koch.nim
index 9d59344f2..79acc7791 100644
--- a/koch.nim
+++ b/koch.nim
@@ -299,7 +299,7 @@ of cmdArgument:
   of "boot": boot(op.cmdLineRest)
   of "clean": clean(op.cmdLineRest)
   of "web": web(op.cmdLineRest)
-  of "csource": csource(op.cmdLineRest)
+  of "csource", "csources": csource(op.cmdLineRest)
   of "zip": zip(op.cmdLineRest)
   of "inno": inno(op.cmdLineRest)
   of "install": install(op.cmdLineRest)
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index cd28f9af0..33e558aee 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -10,6 +10,47 @@
 ## The ``tables`` module implements an efficient hash table that is
 ## a mapping from keys to values.
 ##
+## If you are using simple standard types like ``int`` or ``string`` for the
+## keys of the table you won't have any problems, but as soon as you try to use
+## a more complex object as a key you will be greeted by a strange compiler
+## error::
+##
+##   Error: type mismatch: got (Person)
+##   but expected one of:
+##   hashes.hash(x: openarray[A]): THash
+##   hashes.hash(x: int): THash
+##   hashes.hash(x: float): THash
+##   …
+##
+## What is happening here is that the types used for table keys require to have
+## a ``hash()`` proc which will convert them to a `THash <hashes.html#THash>`_
+## value, and the compiler is listing all the hash functions it knows. After
+## you add such a proc for your custom type everything will work. See this
+## example:
+##
+## .. code-block:: nimrod
+##   type
+##     Person = object
+##       firstName, lastName: string
+##
+##   proc hash(x: Person): THash =
+##     ## Piggyback on the already available string hash proc.
+##     ##
+##     ## Without this proc nothing works!
+##     result = hash(x.firstName & x.lastName)
+##
+##   var
+##     salaries = initTable[Person, int]()
+##     p1, p2: Person
+##
+##   p1.firstName = "Jon"
+##   p1.lastName = "Ross"
+##   salaries[p1] = 30_000
+##
+##   p2.firstName = "소진"
+##   p2.lastName = "박"
+##   salaries[p2] = 45_000
+##
 ## **Note:** The data types declared here have *value semantics*: This means
 ## that ``=`` performs a copy of the hash table.
 
@@ -526,3 +567,30 @@ proc sort*[A](t: var TCountTable[A]) =
         if j < h: break
     if h == 1: break
 
+when isMainModule:
+  type
+    Person = object
+      firstName, lastName: string
+
+  proc hash(x: Person): THash =
+    ## Piggyback on the already available string hash proc.
+    ##
+    ## Without this proc nothing works!
+    result = hash(x.firstName & x.lastName)
+
+  var
+    salaries = initTable[Person, int]()
+    p1, p2: Person
+  p1.firstName = "Jon"
+  p1.lastName = "Ross"
+  salaries[p1] = 30_000
+  p2.firstName = "소진"
+  p2.lastName = "박"
+  salaries[p2] = 45_000
+  var
+    s2 = initOrderedTable[Person, int]()
+    s3 = initCountTable[Person]()
+  s2[p1] = 30_000
+  s2[p2] = 45_000
+  s3[p1] = 30_000
+  s3[p2] = 45_000
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
index 73c20e708..e0e4c4176 100644
--- a/lib/pure/future.nim
+++ b/lib/pure/future.nim
@@ -115,4 +115,4 @@ macro `->`*(p, b: expr): expr {.immediate.} =
   ##   proc pass2(f: proc (x, y: float): float): float =
   ##     f(2, 2)
 
-  createProcType(p, b)
+  result = createProcType(p, b)
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 00a33db75..e2fc62d77 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -1612,6 +1612,20 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
       len = readlink(procPath, result, len)
     setLen(result, len)
 
+when not (defined(windows) or defined(macosx)):
+  proc getApplHeuristic(): string =
+    when defined(paramStr):
+      result = string(paramStr(0))
+      # POSIX guaranties that this contains the executable
+      # as it has been executed by the calling process
+      if len(result) > 0 and result[0] != DirSep: # not an absolute path?
+        # iterate over any path in the $PATH environment variable
+        for p in split(string(getEnv("PATH")), {PathSep}):
+          var x = joinPath(p, result)
+          if existsFile(x): return x
+    else:
+      result = ""
+
 when defined(macosx):
   type
     cuint32* {.importc: "unsigned int", nodecl.} = int
@@ -1648,10 +1662,13 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
       setlen(result, int(len))
   elif defined(linux) or defined(aix):
     result = getApplAux("/proc/self/exe")
+    if result.len == 0: result = getApplHeuristic()
   elif defined(solaris):
     result = getApplAux("/proc/" & $getpid() & "/path/a.out")
+    if result.len == 0: result = getApplHeuristic()
   elif defined(freebsd):
     result = getApplAux("/proc/" & $getpid() & "/file")
+    if result.len == 0: result = getApplHeuristic()
   elif defined(macosx):
     var size: cuint32
     getExecPath1(nil, size)
@@ -1663,15 +1680,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
   else:
     # little heuristic that may work on other POSIX-like systems:
     result = string(getEnv("_"))
-    if len(result) == 0:
-      result = string(paramStr(0))
-      # POSIX guaranties that this contains the executable
-      # as it has been executed by the calling process
-      if len(result) > 0 and result[0] != DirSep: # not an absolute path?
-        # iterate over any path in the $PATH environment variable
-        for p in split(string(getEnv("PATH")), {PathSep}):
-          var x = joinPath(p, result)
-          if existsFile(x): return x
+    if result.len == 0: result = getApplHeuristic()
 
 proc getApplicationFilename*(): string {.rtl, extern: "nos$1", deprecated.} =
   ## Returns the filename of the application's executable.
diff --git a/lib/system.nim b/lib/system.nim
index 273820b82..ecee7dad7 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -193,6 +193,52 @@ when defined(nimNewShared):
     `shared`* {.magic: "Shared".}
     guarded* {.magic: "Guarded".}
 
+# comparison operators:
+proc `==` *[TEnum: enum](x, y: TEnum): bool {.magic: "EqEnum", noSideEffect.}
+proc `==` *(x, y: pointer): bool {.magic: "EqRef", noSideEffect.}
+proc `==` *(x, y: string): bool {.magic: "EqStr", noSideEffect.}
+proc `==` *(x, y: cstring): bool {.magic: "EqCString", noSideEffect.}
+proc `==` *(x, y: char): bool {.magic: "EqCh", noSideEffect.}
+proc `==` *(x, y: bool): bool {.magic: "EqB", noSideEffect.}
+proc `==` *[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.}
+proc `==` *[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
+proc `==` *[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
+proc `==` *[T: proc](x, y: T): bool {.magic: "EqProc", noSideEffect.}
+
+proc `<=` *[TEnum: enum](x, y: TEnum): bool {.magic: "LeEnum", noSideEffect.}
+proc `<=` *(x, y: string): bool {.magic: "LeStr", noSideEffect.}
+proc `<=` *(x, y: char): bool {.magic: "LeCh", noSideEffect.}
+proc `<=` *[T](x, y: set[T]): bool {.magic: "LeSet", noSideEffect.}
+proc `<=` *(x, y: bool): bool {.magic: "LeB", noSideEffect.}
+proc `<=` *[T](x, y: ref T): bool {.magic: "LePtr", noSideEffect.}
+proc `<=` *(x, y: pointer): bool {.magic: "LePtr", noSideEffect.}
+
+proc `<` *[TEnum: enum](x, y: TEnum): bool {.magic: "LtEnum", noSideEffect.}
+proc `<` *(x, y: string): bool {.magic: "LtStr", noSideEffect.}
+proc `<` *(x, y: char): bool {.magic: "LtCh", noSideEffect.}
+proc `<` *[T](x, y: set[T]): bool {.magic: "LtSet", noSideEffect.}
+proc `<` *(x, y: bool): bool {.magic: "LtB", noSideEffect.}
+proc `<` *[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.}
+proc `<` *[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.}
+proc `<` *(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.}
+
+template `!=` * (x, y: expr): expr {.immediate.} =
+  ## unequals operator. This is a shorthand for ``not (x == y)``.
+  not (x == y)
+
+template `>=` * (x, y: expr): expr {.immediate.} =
+  ## "is greater or equals" operator. This is the same as ``y <= x``.
+  y <= x
+
+template `>` * (x, y: expr): expr {.immediate.} =
+  ## "is greater" operator. This is the same as ``y < x``.
+  y < x
+
+const
+  appType* {.magic: "AppType"}: string = ""
+    ## a string that describes the application type. Possible values:
+    ## "console", "gui", "lib".
+
 include "system/inclrtl"
 
 const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
@@ -695,47 +741,6 @@ proc `-+-` *[T](x, y: set[T]): set[T] {.magic: "SymDiffSet", noSideEffect.}
   ## computes the symmetric set difference. This is the same as
   ## ``(A - B) + (B - A)``, but more efficient.
 
-# comparison operators:
-proc `==` *[TEnum: enum](x, y: TEnum): bool {.magic: "EqEnum", noSideEffect.}
-proc `==` *(x, y: pointer): bool {.magic: "EqRef", noSideEffect.}
-proc `==` *(x, y: string): bool {.magic: "EqStr", noSideEffect.}
-proc `==` *(x, y: cstring): bool {.magic: "EqCString", noSideEffect.}
-proc `==` *(x, y: char): bool {.magic: "EqCh", noSideEffect.}
-proc `==` *(x, y: bool): bool {.magic: "EqB", noSideEffect.}
-proc `==` *[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.}
-proc `==` *[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
-proc `==` *[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
-proc `==` *[T: proc](x, y: T): bool {.magic: "EqProc", noSideEffect.}
-
-proc `<=` *[TEnum: enum](x, y: TEnum): bool {.magic: "LeEnum", noSideEffect.}
-proc `<=` *(x, y: string): bool {.magic: "LeStr", noSideEffect.}
-proc `<=` *(x, y: char): bool {.magic: "LeCh", noSideEffect.}
-proc `<=` *[T](x, y: set[T]): bool {.magic: "LeSet", noSideEffect.}
-proc `<=` *(x, y: bool): bool {.magic: "LeB", noSideEffect.}
-proc `<=` *[T](x, y: ref T): bool {.magic: "LePtr", noSideEffect.}
-proc `<=` *(x, y: pointer): bool {.magic: "LePtr", noSideEffect.}
-
-proc `<` *[TEnum: enum](x, y: TEnum): bool {.magic: "LtEnum", noSideEffect.}
-proc `<` *(x, y: string): bool {.magic: "LtStr", noSideEffect.}
-proc `<` *(x, y: char): bool {.magic: "LtCh", noSideEffect.}
-proc `<` *[T](x, y: set[T]): bool {.magic: "LtSet", noSideEffect.}
-proc `<` *(x, y: bool): bool {.magic: "LtB", noSideEffect.}
-proc `<` *[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.}
-proc `<` *[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.}
-proc `<` *(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.}
-
-template `!=` * (x, y: expr): expr {.immediate.} =
-  ## unequals operator. This is a shorthand for ``not (x == y)``.
-  not (x == y)
-
-template `>=` * (x, y: expr): expr {.immediate.} =
-  ## "is greater or equals" operator. This is the same as ``y <= x``.
-  y <= x
-
-template `>` * (x, y: expr): expr {.immediate.} =
-  ## "is greater" operator. This is the same as ``y < x``.
-  y < x
-
 proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
   ## One should overload this proc if one wants to overload the ``in`` operator.
   ## The parameters are in reverse order! ``a in b`` is a template for
@@ -940,10 +945,6 @@ const
     ## a string that describes the host CPU. Possible values:
     ## "i386", "alpha", "powerpc", "sparc", "amd64", "mips", "arm".
   
-  appType* {.magic: "AppType"}: string = ""
-    ## a string that describes the application type. Possible values:
-    ## "console", "gui", "lib".
-  
   seqShallowFlag = low(int)
   
 proc compileOption*(option: string): bool {.
diff --git a/lib/system/embedded.nim b/lib/system/embedded.nim
index 85fe17f8d..661992e81 100644
--- a/lib/system/embedded.nim
+++ b/lib/system/embedded.nim
@@ -15,7 +15,7 @@ proc chckRange(i, a, b: int): int {.inline, compilerproc.}
 proc chckRangeF(x, a, b: float): float {.inline, compilerproc.}
 proc chckNil(p: pointer) {.inline, compilerproc.}
 
-proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = discard
+proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = discard
 proc popFrame {.compilerRtl, inl.} = discard
 
 proc setFrame(s: PFrame) {.compilerRtl, inl.} = discard
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 612a9e729..2dc134eaf 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -44,9 +44,15 @@ var
     # a global variable for the root of all try blocks
   currException {.rtlThreadVar.}: ref E_Base
 
-proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
-  s.prev = framePtr
-  framePtr = s
+when defined(nimRequiresNimFrame):
+  proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
+    s.prev = framePtr
+    framePtr = s
+else:
+  proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
+    # XXX only for backwards compatibility
+    s.prev = framePtr
+    framePtr = s
 
 proc popFrame {.compilerRtl, inl.} =
   framePtr = framePtr.prev
@@ -71,7 +77,7 @@ proc popCurrentException {.compilerRtl, inl.} =
 
 # some platforms have native support for stack traces:
 const
-  nativeStackTraceSupported = (defined(macosx) or defined(linux)) and 
+  nativeStackTraceSupported* = (defined(macosx) or defined(linux)) and
                               not nimrodStackTrace
   hasSomeStackTrace = nimrodStackTrace or 
     defined(nativeStackTrace) and nativeStackTraceSupported
diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim
index 475a09686..5c82db4da 100644
--- a/lib/system/inclrtl.nim
+++ b/lib/system/inclrtl.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -30,9 +30,9 @@ when defined(createNimRtl):
   {.pragma: inl.}
   {.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.}
 elif defined(useNimRtl):
-  when hostOS == "windows": 
+  when defined(windows): 
     const nimrtl* = "nimrtl.dll"
-  elif hostOS == "macosx":
+  elif defined(macosx):
     const nimrtl* = "nimrtl.dylib"
   else: 
     const nimrtl* = "libnimrtl.so"
diff --git a/lib/wrappers/sqlite3.nim b/lib/wrappers/sqlite3.nim
index 586f763ae..7b7f0874e 100644
--- a/lib/wrappers/sqlite3.nim
+++ b/lib/wrappers/sqlite3.nim
@@ -106,15 +106,15 @@ type
   Pstmt* = ptr Tstmt
   Tvalue{.pure, final.} = object 
   Pvalue* = ptr Tvalue
-  PPValue* = ptr Pvalue 
+  PValueArg* = array[0..127, Pvalue]
   
   Tcallback* = proc (para1: pointer, para2: int32, para3, 
                      para4: cstringArray): int32{.cdecl.}
   Tbind_destructor_func* = proc (para1: pointer){.cdecl.}
   Tcreate_function_step_func* = proc (para1: Pcontext, para2: int32, 
-                                      para3: PPValue){.cdecl.}
+                                      para3: PValueArg){.cdecl.}
   Tcreate_function_func_func* = proc (para1: Pcontext, para2: int32, 
-                                      para3: PPValue){.cdecl.}
+                                      para3: PValueArg){.cdecl.}
   Tcreate_function_final_func* = proc (para1: Pcontext){.cdecl.}
   Tresult_func* = proc (para1: pointer){.cdecl.}
   Tcreate_collation_func* = proc (para1: pointer, para2: int32, para3: pointer, 
diff --git a/tests/ccgbugs/tcgbug.nim b/tests/ccgbugs/tcgbug.nim
index 535424a27..3e4755f2f 100644
--- a/tests/ccgbugs/tcgbug.nim
+++ b/tests/ccgbugs/tcgbug.nim
@@ -20,7 +20,8 @@ new(a)
 q(a)
 
 # bug #914
-var x = newWideCString("Hello")
+when defined(windows):
+  var x = newWideCString("Hello")
 
 echo "success"
 
diff --git a/tests/system/tsysspawn.nim b/tests/system/tsysspawn.nim
new file mode 100644
index 000000000..0388918aa
--- /dev/null
+++ b/tests/system/tsysspawn.nim
@@ -0,0 +1,29 @@
+discard """
+  output: '''4
+8'''
+  cmd: "nimrod $target --threads:on $options $file"
+"""
+
+var
+  x, y = 0
+
+proc p1 =
+  for i in 0 .. 1_000_000:
+    discard
+
+  inc x
+
+proc p2 =
+  for i in 0 .. 1_000_000:
+    discard
+
+  inc y, 2
+
+for i in 0.. 3:
+  spawn(p1())
+  spawn(p2())
+
+sync()
+
+echo x
+echo y
diff --git a/tools/website.tmpl b/tools/website.tmpl
index bd68bdb06..1d6242736 100644
--- a/tools/website.tmpl
+++ b/tools/website.tmpl
@@ -71,7 +71,7 @@
     </div>
     <!-- site_foot -->
     <div id="site_foot">
-       <div id="legal">Copyright &copy; 2013 - Andreas Rumpf &amp; Contributors - All rights reserved - <a href="http://reign-studios.com/philipwitte/">Design by Philip Witte</a></div>
+       <div id="legal">Copyright &copy; 2014 - Andreas Rumpf &amp; Contributors - All rights reserved - <a href="http://reign-studios.com/philipwitte/">Design by Philip Witte</a></div>
     </div>
   </div>
   <script>
diff --git a/web/download.txt b/web/download.txt
index f638a43b2..557788217 100644
--- a/web/download.txt
+++ b/web/download.txt
@@ -1,18 +1,138 @@
-Here you can download the latest version of the Nimrod Compiler.
-Please choose your platform:
-* source-based installation: `<download/nimrod_0.9.2.zip>`_
-* installer for Windows XP/Vista/7 (i386, 32bit): `<download/nimrod_0.9.2.exe>`_
-  (includes GCC and everything else you need)
-* minimal installer for Windows XP/Vista/7 (i386, 32bit): `<download/nimrod_gamera_0.9.2.exe>`_
-  ("Gamera edition": includes only a minimal GCC)
-
-The source-based installation has been tested on these systems:
-* Linux: i386, AMD64, PowerPC, ARM
-* BSD: AMD64
-* Mac OS X: i386, AMD64
-* Solaris: AMD64
-
-Other UNIX-based operating systems may work.
-
-.. include:: ../install.txt
+You can download the latest version of the Nimrod compiler here. You can
+use the binaries provided or build from source.
+
+Binaries
+========
+
+All installers and archives contain the html documentation and tools
+(nimgrep, c2nim and babel).
+
+**Note:** The Nimrod compiler requires a C compiler to compile software. On
+Windows we recommend that you use
+`Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
+and clang on Mac OS X.
+
+Installers
+----------
+
+The "full" version includes a full mingw distribution which includes a C
+compiler. The "slim" version lacks this.
+
+* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.exe>`_
+
+  .. raw:: html
+    <p style="font-size: 8pt; margin-top: 0;">
+    SHA256: dca7c63d0c1861d2d7c51b2e7a29fa98371750a10ab282d5df9de22a07719c24
+    </p>
+
+* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.exe>`_
+
+  .. raw:: html
+      <p style="font-size: 8pt; margin-top: 0;">
+      SHA256: c0fcd1201bd20fad1e14b9d2cc2529494057068de1dd01f871cf129f088a8242
+      </p>
+
+* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.exe>`_
+
+  .. raw:: html
+    <p style="font-size: 8pt; margin-top: 0;">
+    SHA256: af9d478c2f3361e0f238fcb07fa8e7ae5821938c0f9063c6670e925c9ae9d16e
+    </p>
+
+* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.exe>`_
+
+  .. raw:: html
+      <p style="font-size: 8pt; margin-top: 0;">
+      SHA256: 90c380721a46be2b9b8d5437187f701940aefc2e1fb9722dbc543f5c5a3bb85e
+      </p>
+
+Archives
+--------
+
+Windows
+~~~~~~~
+
+The "full" version includes a full mingw distribution which includes a C
+compiler. The "slim" version lacks this.
+
+* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.zip>`_
+
+  .. raw:: html
+    <p style="font-size: 8pt; margin-top: 0;">
+    SHA256: 8ee18faaa3a3d5df482c7abd6aa7ea87a350d7328b80ce1e2d486b59a7a93956
+    </p>
+
+* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.zip>`_
+
+  .. raw:: html
+      <p style="font-size: 8pt; margin-top: 0;">
+      SHA256: 7024fb8ad8f98c0bd4949ae36ed11b52b4e401754bbd62a11199d6dc8628d857 
+      </p>
+
+* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.zip>`_
+
+  .. raw:: html
+    <p style="font-size: 8pt; margin-top: 0;">
+    SHA256: cb33cacc1a84fec771323d24cb6d9795f4803882466a9f417b424990aa49e18a
+    </p>
+
+* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.zip>`_
+
+  .. raw:: html
+      <p style="font-size: 8pt; margin-top: 0;">
+      SHA256: fcf877e4bd1ebfa214749af6e4811cd8539af19f1d7b23017e4bd7f6cbfb3eba
+      </p>
+
+Linux
+~~~~~
+
+* Linux (i386, 32bit): `<download/nimrod_0.9.4_linux_i386.tar.gz>`_
+
+  .. raw:: html
+      <p style="font-size: 8pt; margin-top: 0;">
+      SHA256: 79DD337A77AC4313A75F2C5EED8252F00BBBDEB1E0C3504660D4A52EA63DBA92
+      </p>
+* Linux (amd64, 64bit): `<download/nimrod_0.9.4_linux_amd64.tar.gz>`_
+
+  .. raw:: html
+    <p style="font-size: 8pt; margin-top: 0;">
+    SHA256: 6F6CB3C727BA8059B7605C02942AE7910C20C2A3DC6A8A600D90D50FE61F0D8C
+    </p>
+* Linux (ppc64, 64bit): `<download/nimrod_0.9.4_linux_ppc64.tar.gz>`_
+
+  .. raw:: html
+      <p style="font-size: 8pt; margin-top: 0;">
+      SHA256: 5DAC2D9F7F545929E04540E6E2594C68FC3126A3B2F7B1FA7DBA5E295B4A7D31
+      </p>
+
+Mac OS X
+~~~~~~~~
+
+* Mac OS X (amd64, 64bit): `<download/nimrod_0.9.4_macosx_amd64.zip>`_
+
+  .. raw:: html
+      <p style="font-size: 8pt; margin-top: 0;">
+      SHA256: E6F3A8E434DF3E89686F043954C6DFC09ABEBC0FC09D3B9A6B35C2B3102F7C3C
+      </p>
+
+If a binary for your platform is not available then you must build from source.
+Bleeding edge binaries are available from the `Nimrod build farm <http://build.nimrod-lang.org/>`_.
+
+Source
+======
+
+Starting with 0.9.4 we now advise people to build directly from the
+github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
+
+  git clone -b master git://github.com/Araq/Nimrod.git
+  cd Nimrod
+  git clone --depth 1 git://github.com/nimrod-code/csources
+  cd csources && sh build.sh
+  cd ..
+  bin/nimrod c koch
+  ./koch boot -d:release
+
+The ``master`` branch always contains the latest stable version of the compiler.
+If you want bleeding edge then switch to the ``devel`` branch and follow
+the same instructions outlined above.
 
diff --git a/web/index.txt b/web/index.txt
index e504b65c4..c3459d56b 100644
--- a/web/index.txt
+++ b/web/index.txt
@@ -90,7 +90,9 @@ Nimrod plays nice with others
   interfacing.**
 * There are lots of bindings: for example, bindings to GTK2, the Windows API, 
   the POSIX API, OpenGL, SDL, Cairo, Python, Lua, TCL, X11, libzip, PCRE, 
-  libcurl, mySQL and SQLite are included in the standard distribution.
+  libcurl, mySQL and SQLite are included in the standard distribution or
+  can easily be obtained via the
+  `Babel package manager <https://github.com/nimrod-code/babel>`_.
 * A C to Nimrod conversion utility: New bindings to C libraries are easily 
   generated by ``c2nim``.
 
@@ -98,6 +100,6 @@ Nimrod plays nice with others
 Roadmap to 1.0
 ==============
 
-Version 0.9.x
-  * the symbol binding rules for templates will change
-  * a shared memory garbage collected heap will be provided
+Please have a look at
+this `wiki page <https://github.com/Araq/Nimrod/wiki/Feature-Matrix>`_ for
+an up-to-date overview.
diff --git a/web/news.txt b/web/news.txt
index f7a9d05fa..4c41a0a76 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -4,17 +4,25 @@ News
 
 
 
-2014-XX-XX Version 0.9.4 released
+2014-04-21 Version 0.9.4 released
 =================================
 
 The Nimrod development community is proud to announce the release of version
-0.9.4 of the Nimrod compiler and tools.
+0.9.4 of the Nimrod compiler and tools. **Note: This release has to be
+considered beta quality! Lots of new features have been implemented but
+unfortunately some do not fullfill our quality standards yet.**
 
-This release includes about 1300 changes in total including various bug
+Prebuilt binaries and instructions for building from source are available
+on the `download page <download.html>`_.
+
+This release includes about 
+`1400 changes <https://github.com/Araq/Nimrod/compare/v0.9.2...v0.9.4>`_
+in total including various bug
 fixes, new languages features and standard library additions and improvements.
 This release brings with it support for user-defined type classes, a brand
 new VM for executing Nimrod code at compile-time and new symbol binding
 rules for clean templates.
+
 It also introduces support for the brand new
 `Babel package manager <https://github.com/nimrod-code/babel>`_ which
 has itself seen its first release recently. Many of the wrappers that were
@@ -63,6 +71,18 @@ capabilities.
 Note that this feature has been implemented with Nimrod's macro system and so
 ``await`` and ``async`` are no keywords.
 
+Syntactic sugar for anonymous procedures has also been introduced. It too has
+been implemented as a macro. The following shows some simple usage of the new
+syntax:
+ 
+.. code-block::nimrod
+  import future
+  
+  var s = @[1, 2, 3, 4, 5]
+  echo(s.map((x: int) => x * 5))
+
+A list of changes follows, for a comprehensive list of changes take a look
+`here <https://github.com/Araq/Nimrod/compare/v0.9.2...v0.9.4>`_.
 
 Library Additions
 -----------------
@@ -77,6 +97,9 @@ Library Additions
 - Added module ``selectors``.
 - Added module ``asynchttpserver``.
 - Added support for the new asynchronous IO in the ``httpclient`` module.
+- Added a Python-inspired ``future`` module that feature upcoming additions
+  to the ``system`` module.
+
 
 Changes affecting backwards compatibility
 -----------------------------------------
@@ -102,6 +125,8 @@ Changes affecting backwards compatibility
   of sockets given to it.
 - The ``noStackFrame`` pragma has been renamed to ``asmNoStackFrame`` to
   ensure you only use it when you know what you're doing.
+- Many of the wrappers that were present in the standard library have been
+  moved to separate repositories and should now be installed using Babel.
 
 
 Compiler Additions
@@ -146,6 +171,7 @@ Language Additions
   of an outer proc.
 - The experimental ``strongSpaces`` parsing mode has been implemented.
 - You can annotate pointer types with regions for increased type safety.
+- Added support for the builtin ``spawn`` for easy thread pool usage.
 
 
 Tools improvements
diff --git a/web/ticker.txt b/web/ticker.txt
index a4ddddbbe..f06b00572 100644
--- a/web/ticker.txt
+++ b/web/ticker.txt
@@ -1,5 +1,5 @@
-<a class="news" href="news.html#Z2014-XX-XX-version-0-9-4-released">
-  <h3>Apr 20, 2014</h3>
+<a class="news" href="news.html#Z2014-04-21-version-0-9-4-released">
+  <h3>Apr 21, 2014</h3>
   <p>Nimrod version 0.9.4 has been released!</p>
 </a>
 
@@ -46,4 +46,4 @@
 <a class="news" href="news.html#Z2010-03-14-version-0-8-8-released">
   <h3>Mar 14, 2010</h3>
   <p>Nimrod version 0.8.8 has been released!</p>
-</a>
\ No newline at end of file
+</a>