summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--].gitignore0
-rwxr-xr-xdoc/astspec.txt8
-rwxr-xr-x[-rw-r--r--]doc/lib.txt0
-rwxr-xr-x[-rw-r--r--]examples/httpserver2.nim0
-rwxr-xr-x[-rw-r--r--]icons/koch.rc0
-rwxr-xr-x[-rw-r--r--]icons/koch.resbin5768 -> 5768 bytes
-rwxr-xr-x[-rw-r--r--]icons/nimrod.rc0
-rwxr-xr-x[-rw-r--r--]icons/nimrod.resbin30830 -> 30830 bytes
-rwxr-xr-x[-rw-r--r--]koch.nim0
-rwxr-xr-x[-rw-r--r--]lib/core/marshal.nim0
-rwxr-xr-x[-rw-r--r--]lib/core/threads.nim0
-rwxr-xr-x[-rw-r--r--]lib/impure/ssl.nim0
-rwxr-xr-x[-rw-r--r--]lib/pure/base64.nim0
-rwxr-xr-x[-rw-r--r--]lib/pure/cookies.nim0
-rwxr-xr-xlib/pure/math.nim8
-rwxr-xr-x[-rw-r--r--]lib/pure/scgi.nim0
-rwxr-xr-x[-rw-r--r--]lib/pure/smtp.nim0
-rwxr-xr-x[-rw-r--r--]lib/wrappers/claro.nim0
-rwxr-xr-x[-rw-r--r--]lib/wrappers/openssl.nim0
-rwxr-xr-x[-rw-r--r--]lib/wrappers/pcre.nim0
-rwxr-xr-xrod/astalgo.nim15
-rwxr-xr-xrod/c2nim/clex.nim4
-rwxr-xr-xrod/ccgexprs.nim4
-rwxr-xr-xrod/ccgstmts.nim31
-rwxr-xr-xrod/cgen.nim10
-rwxr-xr-xrod/cgmeth.nim19
-rwxr-xr-xrod/commands.nim32
-rwxr-xr-xrod/ecmasgen.nim23
-rwxr-xr-xrod/evals.nim10
-rwxr-xr-x[-rw-r--r--]rod/extccomp.nim0
-rwxr-xr-xrod/filters.nim6
-rwxr-xr-xrod/importer.nim8
-rwxr-xr-xrod/lookups.nim61
-rwxr-xr-xrod/main.nim6
-rwxr-xr-xrod/msgs.nim147
-rwxr-xr-x[-rw-r--r--]rod/nimrod.ini0
-rwxr-xr-x[-rw-r--r--]rod/nimrod.nim0
-rwxr-xr-xrod/pas2nim/paslex.nim4
-rwxr-xr-xrod/passaux.nim14
-rwxr-xr-xrod/passes.nim26
-rwxr-xr-xrod/pnimsyn.nim2
-rwxr-xr-xrod/pragmas.nim67
-rwxr-xr-xrod/procfind.nim4
-rwxr-xr-xrod/ptmplsyn.nim9
-rwxr-xr-x[-rw-r--r--]rod/rodutils.nim0
-rwxr-xr-xrod/rst.nim6
-rwxr-xr-xrod/scanner.nim4
-rwxr-xr-xrod/sem.nim47
-rwxr-xr-xrod/semdata.nim31
-rwxr-xr-xrod/semexprs.nim187
-rwxr-xr-xrod/semfold.nim15
-rwxr-xr-xrod/semgnrc.nim21
-rwxr-xr-xrod/seminst.nim35
-rwxr-xr-xrod/semstmts.nim265
-rwxr-xr-xrod/semtempl.nim68
-rwxr-xr-xrod/semtypes.nim155
-rwxr-xr-xrod/sigmatch.nim15
-rwxr-xr-xrod/tccgen.nim2
-rwxr-xr-xrod/transf.nim15
-rwxr-xr-xrod/types.nim2
-rwxr-xr-x[-rw-r--r--]tests/accept/compile/tgenericvariant.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/compile/tnamedparams.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/compile/toop.nim0
-rwxr-xr-xtests/accept/run/spec.csv4
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tarraycons.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tcountup.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/temit.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tenumhole.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/texcsub.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tfloat3.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/titer6.nim0
-rwxr-xr-xtests/accept/run/tmultim2.nim2
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tmultim4.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/tnamedenumfields.nim0
-rwxr-xr-x[-rw-r--r--]tests/accept/run/toprprec.nim0
-rwxr-xr-x[-rw-r--r--]tests/gc/tthreads.nim0
-rwxr-xr-x[-rw-r--r--]tests/reject/tarraycons.nim0
-rwxr-xr-x[-rw-r--r--]tests/reject/tmethod.nim0
-rwxr-xr-x[-rw-r--r--]tests/reject/tnamedparams.nim0
-rwxr-xr-x[-rw-r--r--]tests/reject/twrongtupleaccess.nim0
-rwxr-xr-x[-rw-r--r--]tests/testdata/jsontest2.json0
-rwxr-xr-xtodo.txt5
-rwxr-xr-xweb/news.txt1
-rwxr-xr-x[-rw-r--r--]web/nimrod.ini0
84 files changed, 677 insertions, 721 deletions
diff --git a/.gitignore b/.gitignore
index 20a87aea7..20a87aea7 100644..100755
--- a/.gitignore
+++ b/.gitignore
diff --git a/doc/astspec.txt b/doc/astspec.txt
index 01c1adba3..6b6242614 100755
--- a/doc/astspec.txt
+++ b/doc/astspec.txt
@@ -43,10 +43,8 @@ To specify the AST for the different Nimrod constructs, the notation
 ``nodekind(son1, son2, ...)`` or ``nodekind(value)`` or 
 ``nodekind(field=value)`` is used.
 
-Some child may be missing. Then it is ``nil``. A nil child is equivalent to 
-a node of kind ``nnkEmpty``. This is more or less a (useful) artifact from 
-the implementation. (In the compiler's implementation ``nil`` is of course 
-not the same as ``nnkEmpty``!)
+Some child may be missing. A missing child is a node of kind ``nnkEmpty``; 
+a child can never be nil.
 
 
 Leaf nodes/Atoms
@@ -364,7 +362,7 @@ When statement
 --------------
 
 Like the ``if`` statement, but the root has the kind ``nnkWhenStmt``.
-  
+
 
 Assignment
 ----------
diff --git a/doc/lib.txt b/doc/lib.txt
index cefb1a1fe..cefb1a1fe 100644..100755
--- a/doc/lib.txt
+++ b/doc/lib.txt
diff --git a/examples/httpserver2.nim b/examples/httpserver2.nim
index 0604e6a83..0604e6a83 100644..100755
--- a/examples/httpserver2.nim
+++ b/examples/httpserver2.nim
diff --git a/icons/koch.rc b/icons/koch.rc
index 2e5d884dc..2e5d884dc 100644..100755
--- a/icons/koch.rc
+++ b/icons/koch.rc
diff --git a/icons/koch.res b/icons/koch.res
index 3b38f7da4..3b38f7da4 100644..100755
--- a/icons/koch.res
+++ b/icons/koch.res
Binary files differdiff --git a/icons/nimrod.rc b/icons/nimrod.rc
index 6f36b8145..6f36b8145 100644..100755
--- a/icons/nimrod.rc
+++ b/icons/nimrod.rc
diff --git a/icons/nimrod.res b/icons/nimrod.res
index 6eddd053b..6eddd053b 100644..100755
--- a/icons/nimrod.res
+++ b/icons/nimrod.res
Binary files differdiff --git a/koch.nim b/koch.nim
index 273f0b79f..273f0b79f 100644..100755
--- a/koch.nim
+++ b/koch.nim
diff --git a/lib/core/marshal.nim b/lib/core/marshal.nim
index 1a06e5c37..1a06e5c37 100644..100755
--- a/lib/core/marshal.nim
+++ b/lib/core/marshal.nim
diff --git a/lib/core/threads.nim b/lib/core/threads.nim
index fc120f1a3..fc120f1a3 100644..100755
--- a/lib/core/threads.nim
+++ b/lib/core/threads.nim
diff --git a/lib/impure/ssl.nim b/lib/impure/ssl.nim
index ab53d0538..ab53d0538 100644..100755
--- a/lib/impure/ssl.nim
+++ b/lib/impure/ssl.nim
diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim
index 8c4883c11..8c4883c11 100644..100755
--- a/lib/pure/base64.nim
+++ b/lib/pure/base64.nim
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index eed6c7512..eed6c7512 100644..100755
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index dc6133901..c44d786b1 100755
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -185,11 +185,12 @@ when not defined(ECMAScript):
   proc random(max: int): int = return int(rand()) mod max
 
   proc trunc*(x: float): float {.importc: "trunc", nodecl.}
+  proc floor*(x: float): float {.importc: "floor", nodecl.}
 
 else:  
   proc mathrandom(): float {.importc: "Math.random", nodecl.}
-  proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.}
-  proc random*(max: int): int = return mathfloor(mathrandom() * max)
+  proc floor*(x: float): float {.importc: "Math.floor", nodecl.}
+  proc random*(max: int): int = return floor(mathrandom() * max)
   proc randomize*() = nil
   
   proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
@@ -208,7 +209,7 @@ else:
     elif x < 0.0:
       result = -frexp(-x, exponent)
     else:
-      var ex = mathfloor(log2(x))
+      var ex = floor(log2(x))
       exponent = round(ex)
       result = x / pow(2.0, ex)
 
@@ -227,7 +228,6 @@ else:
     var y = exp(2.0*x)
     return (y-1.0)/(y+1.0)
 
-
 type
   TRunningStat* = object  ## an accumulator for statistical data
     n*: int               ## number of pushed data
diff --git a/lib/pure/scgi.nim b/lib/pure/scgi.nim
index 4893cf603..4893cf603 100644..100755
--- a/lib/pure/scgi.nim
+++ b/lib/pure/scgi.nim
diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim
index 21afdf953..21afdf953 100644..100755
--- a/lib/pure/smtp.nim
+++ b/lib/pure/smtp.nim
diff --git a/lib/wrappers/claro.nim b/lib/wrappers/claro.nim
index feab2a216..feab2a216 100644..100755
--- a/lib/wrappers/claro.nim
+++ b/lib/wrappers/claro.nim
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index 5fc6ddd02..5fc6ddd02 100644..100755
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
diff --git a/lib/wrappers/pcre.nim b/lib/wrappers/pcre.nim
index 7e75035da..7e75035da 100644..100755
--- a/lib/wrappers/pcre.nim
+++ b/lib/wrappers/pcre.nim
diff --git a/rod/astalgo.nim b/rod/astalgo.nim
index a4a6ec06e..3167f814b 100755
--- a/rod/astalgo.nim
+++ b/rod/astalgo.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -44,9 +44,8 @@ proc TableSearch*(t: TTable, key, closure: PObject, comparator: TCmpProc): PObje
 # ----------------------- str table -----------------------------------------
 proc StrTableContains*(t: TStrTable, n: PSym): bool
 proc StrTableAdd*(t: var TStrTable, n: PSym)
-proc StrTableGet*(t: TStrTable, name: PIdent): PSym
-proc StrTableIncl*(t: var TStrTable, n: PSym): bool
-  # returns true if n is already in the string table
+proc StrTableGet*(t: TStrTable, name: PIdent): PSym  
+  
   # the iterator scheme:
 type 
   TTabIter*{.final.} = object # consider all fields here private
@@ -574,8 +573,10 @@ proc StrTableAdd(t: var TStrTable, n: PSym) =
   StrTableRawInsert(t.data, n)
   inc(t.counter)
 
-proc StrTableIncl(t: var TStrTable, n: PSym): bool = 
+proc StrTableIncl*(t: var TStrTable, n: PSym): bool = 
   # returns true if n is already in the string table:
+  # It is essential that `n` is written nevertheless!
+  # This way the newest redefinition is picked by the semantic analyses!
   var 
     h: THash
     it: PSym
@@ -584,6 +585,7 @@ proc StrTableIncl(t: var TStrTable, n: PSym): bool =
     it = t.data[h]
     if it == nil: break 
     if it.name.id == n.name.id: 
+      t.data[h] = n           # overwrite it with newer definition!
       return true             # found it
     h = nextTry(h, high(t.data))
   if mustRehash(len(t.data), t.counter): 
@@ -661,10 +663,9 @@ proc SymTabAdd(tab: var TSymTab, e: PSym) =
   StrTableAdd(tab.stack[tab.tos - 1], e)
 
 proc SymTabAddUniqueAt(tab: var TSymTab, e: PSym, at: Natural): TResult = 
-  if StrTableGet(tab.stack[at], e.name) != nil: 
+  if StrTableIncl(tab.stack[at], e): 
     result = Failure
   else: 
-    StrTableAdd(tab.stack[at], e)
     result = Success
 
 proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult = 
diff --git a/rod/c2nim/clex.nim b/rod/c2nim/clex.nim
index 8136ad998..5a67f9475 100755
--- a/rod/c2nim/clex.nim
+++ b/rod/c2nim/clex.nim
@@ -130,11 +130,11 @@ proc getLineInfo*(L: TLexer): TLineInfo =
   result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
 
 proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = 
-  msgs.liMessage(getLineInfo(L), msg, arg)
+  msgs.GenericMessage(getLineInfo(L), msg, arg)
 
 proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = 
   var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
-  msgs.liMessage(info, msg, arg)
+  msgs.GenericMessage(info, msg, arg)
 
 proc TokKindToStr*(k: TTokKind): string =
   case k
diff --git a/rod/ccgexprs.nim b/rod/ccgexprs.nim
index 634dea886..36603be61 100755
--- a/rod/ccgexprs.nim
+++ b/rod/ccgexprs.nim
@@ -1439,7 +1439,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mEcho: genEcho(p, e)
   of mArrToSeq: genArrToSeq(p, e, d)
   of mNLen..mNError:
-    liMessage(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s)
+    localError(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s)
   else: internalError(e.info, "genMagicExpr: " & $op)
 
 proc genConstExpr(p: BProc, n: PNode): PRope
@@ -1605,7 +1605,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
     var sym = e.sym
     case sym.Kind
     of skMethod:
-      if sym.ast.sons[codePos] == nil:
+      if sym.ast.sons[codePos].kind == nkEmpty:
         # we cannot produce code for the dispatcher yet:
         fillProcLoc(sym)
         genProcPrototype(p.module, sym)
diff --git a/rod/ccgstmts.nim b/rod/ccgstmts.nim
index 2ac87824c..2b649a270 100755
--- a/rod/ccgstmts.nim
+++ b/rod/ccgstmts.nim
@@ -56,22 +56,19 @@ proc genVarTuple(p: BProc, n: PNode) =
     genObjectInit(p, v.typ, v.loc, true)
 
 proc genVarStmt(p: BProc, n: PNode) = 
-  var 
-    v: PSym
-    a: PNode
   for i in countup(0, sonsLen(n) - 1): 
-    a = n.sons[i]
+    var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
     if a.kind == nkIdentDefs: 
       assert(a.sons[0].kind == nkSym)
-      v = a.sons[0].sym
+      var v = a.sons[0].sym
       if sfGlobal in v.flags: 
         assignGlobalVar(p, v)
       else: 
         assignLocalVar(p, v)
         initVariable(p, v)    # XXX: this is not required if a.sons[2] != nil,
                               # unless it is a GC'ed pointer
-      if a.sons[2] != nil: 
+      if a.sons[2].kind != nkEmpty: 
         genLineDir(p, a)
         expr(p, a.sons[2], v.loc)
       genObjectInit(p, v.typ, v.loc, true) # correct position
@@ -79,13 +76,11 @@ proc genVarStmt(p: BProc, n: PNode) =
       genVarTuple(p, a)
   
 proc genConstStmt(p: BProc, t: PNode) = 
-  var c: PSym
   for i in countup(0, sonsLen(t) - 1): 
     if t.sons[i].kind == nkCommentStmt: continue 
     if t.sons[i].kind != nkConstDef: InternalError(t.info, "genConstStmt")
-    c = t.sons[i].sons[0].sym # This can happen for forward consts:
-    if (c.ast != nil) and (c.typ.kind in ConstantDataTypes) and
-        not (lfNoDecl in c.loc.flags): 
+    var c = t.sons[i].sons[0].sym 
+    if c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags): 
       # generate the data:
       fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown)
       if sfImportc in c.flags: 
@@ -134,7 +129,7 @@ proc genIfStmt(p: BProc, n: PNode) =
   
 proc popSafePoints(p: BProc, howMany: int) = 
   var L = p.nestedTryStmts.len
-  # danger of endless recursion! we workaround this here, by a temp stack
+  # danger of endless recursion! we workaround this here by a temp stack
   var stack: seq[PNode]
   newSeq(stack, howMany)
   for i in countup(1, howMany): 
@@ -154,7 +149,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
   p.beforeRetNeeded = true
   popSafePoints(p, min(1, p.nestedTryStmts.len))
   genLineDir(p, t)
-  if (t.sons[0] != nil): genStmts(p, t.sons[0])
+  if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
   appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", [])
   
 proc genWhileStmt(p: BProc, t: PNode) = 
@@ -185,7 +180,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
 proc genBlock(p: BProc, t: PNode, d: var TLoc) = 
   inc(p.labels)
   var idx = len(p.blocks)
-  if t.sons[0] != nil: 
+  if t.sons[0].kind != nkEmpty: 
     # named block?
     assert(t.sons[0].kind == nkSym)
     var sym = t.sons[0].sym
@@ -202,7 +197,7 @@ proc genBlock(p: BProc, t: PNode, d: var TLoc) =
 
 proc genBreakStmt(p: BProc, t: PNode) = 
   var idx = len(p.blocks) - 1
-  if t.sons[0] != nil: 
+  if t.sons[0].kind != nkEmpty: 
     # named break?
     assert(t.sons[0].kind == nkSym)
     var sym = t.sons[0].sym
@@ -220,7 +215,7 @@ proc getRaiseFrmt(p: BProc): string =
     result = "#raiseException((#E_Base*)$1, $2);$n"
 
 proc genRaiseStmt(p: BProc, t: PNode) = 
-  if t.sons[0] != nil: 
+  if t.sons[0].kind != nkEmpty: 
     var a: TLoc
     InitLocExpr(p, t.sons[0], a)
     var e = rdLoc(a)
@@ -668,8 +663,6 @@ proc genStmts(p: BProc, t: PNode) =
   var 
     a: TLoc
     prc: PSym
-  #assert(t <> nil);
-  if inCheckpoint(t.info): MessageOut(renderTree(t))
   case t.kind
   of nkEmpty: 
     nil
@@ -707,7 +700,7 @@ proc genStmts(p: BProc, t: PNode) =
     nil
   of nkPragma: genPragma(p, t)
   of nkProcDef, nkMethodDef, nkConverterDef: 
-    if (t.sons[genericParamsPos] == nil): 
+    if (t.sons[genericParamsPos].kind == nkEmpty): 
       prc = t.sons[namePos].sym
       if (optDeadCodeElim notin gGlobalOptions and
           sfDeadCodeElim notin getModule(prc).flags) or
@@ -715,7 +708,7 @@ proc genStmts(p: BProc, t: PNode) =
           (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
           (prc.kind == skMethod): 
         # we have not only the header: 
-        if (t.sons[codePos] != nil) or (lfDynamicLib in prc.loc.flags): 
+        if (t.sons[codePos].kind != nkEmpty) or (lfDynamicLib in prc.loc.flags): 
           genProc(p.module, prc)
   else: internalError(t.info, "genStmts(" & $t.kind & ')')
   
diff --git a/rod/cgen.nim b/rod/cgen.nim
index 685d912c4..13b96c19b 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -890,12 +890,12 @@ proc myOpen(module: PSym, filename: string): PPassContext =
 proc myOpenCached(module: PSym, filename: string, 
                   rd: PRodReader): PPassContext = 
   if gNimDat == nil: 
-    registerTypeInfoModule()  
-    #MessageOut('cgen.myOpenCached has been called ' + filename);
+    registerTypeInfoModule()
+    #MessageOut('cgen.myOpenCached has been called ' + filename)
   var cfile = changeFileExt(completeCFilePath(filename), cExt)
   var cfilenoext = changeFileExt(cfile, "")
   addFileToLink(cfilenoext)
-  registerModuleToMain(module) 
+  registerModuleToMain(module)
   # XXX: this cannot be right here, initalization has to be appended during
   # the ``myClose`` call
   result = nil
@@ -911,7 +911,7 @@ proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool =
   
 proc myProcess(b: PPassContext, n: PNode): PNode = 
   result = n
-  if b == nil: return 
+  if b == nil or passes.skipCodegen(n): return
   var m = BModule(b)
   m.initProc.options = gOptions
   genStmts(m.initProc, n)
@@ -951,7 +951,7 @@ proc writeModule(m: BModule) =
 
 proc myClose(b: PPassContext, n: PNode): PNode = 
   result = n
-  if b == nil: return 
+  if b == nil or passes.skipCodegen(n): return 
   var m = BModule(b)
   if n != nil: 
     m.initProc.options = gOptions
diff --git a/rod/cgmeth.nim b/rod/cgmeth.nim
index fe1b581f9..f9b12647f 100755
--- a/rod/cgmeth.nim
+++ b/rod/cgmeth.nim
@@ -1,22 +1,17 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# This module implements code generation for multi methods.
+## This module implements code generation for multi methods.
 
 import 
   options, ast, astalgo, msgs, idents, rnimsyn, types, magicsys
 
-proc methodDef*(s: PSym)
-proc methodCall*(n: PNode): PNode
-proc generateMethodDispatchers*(): PNode
-# implementation
-
 proc genConv(n: PNode, d: PType, downcast: bool): PNode = 
   var 
     dest, source: PType
@@ -40,7 +35,7 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
   else: 
     result = n
   
-proc methodCall(n: PNode): PNode = 
+proc methodCall*(n: PNode): PNode = 
   var disp: PSym
   result = n
   disp = lastSon(result.sons[0].sym.ast).sym
@@ -76,7 +71,7 @@ proc sameMethodBucket(a, b: PSym): bool =
       return 
   result = true
 
-proc methodDef(s: PSym) = 
+proc methodDef*(s: PSym) = 
   var 
     L, q: int
     disp: PSym
@@ -86,12 +81,12 @@ proc methodDef(s: PSym) =
       add(gMethods[i], s)     # store a symbol to the dispatcher:
       addSon(s.ast, lastSon(gMethods[i][0].ast))
       return 
-  add(gMethods, @ [s])        # create a new dispatcher:
+  add(gMethods, @[s])        # create a new dispatcher:
   disp = copySym(s)
   disp.typ = copyType(disp.typ, disp.typ.owner, false)
   if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
   disp.ast = copyTree(s.ast)
-  disp.ast.sons[codePos] = nil
+  disp.ast.sons[codePos] = ast.emptyNode
   if s.typ.sons[0] != nil: 
     disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
   addSon(s.ast, newSymNode(disp))
@@ -188,7 +183,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
     addSon(disp, a)
   result.ast.sons[codePos] = disp
 
-proc generateMethodDispatchers(): PNode = 
+proc generateMethodDispatchers*(): PNode = 
   var relevantCols: TIntSet
   result = newNode(nkStmtList)
   for bucket in countup(0, len(gMethods) - 1): 
diff --git a/rod/commands.nim b/rod/commands.nim
index ef7f04eb8..2be58e8c8 100755
--- a/rod/commands.nim
+++ b/rod/commands.nim
@@ -152,7 +152,7 @@ proc writeCommandLineUsage() =
     helpWritten = true
 
 proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) = 
-  liMessage(info, errInvalidCmdLineOption, switch)
+  LocalError(info, errInvalidCmdLineOption, switch)
 
 proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass, 
                  info: TLineInfo) = 
@@ -174,20 +174,20 @@ proc ProcessOnOffSwitch(op: TOptions, arg: string, pass: TCmdlinePass,
   case whichKeyword(arg)
   of wOn: gOptions = gOptions + op
   of wOff: gOptions = gOptions - op
-  else: liMessage(info, errOnOrOffExpectedButXFound, arg)
+  else: LocalError(info, errOnOrOffExpectedButXFound, arg)
   
 proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass, 
                          info: TLineInfo) = 
   case whichKeyword(arg)
   of wOn: gGlobalOptions = gGlobalOptions + op
   of wOff: gGlobalOptions = gGlobalOptions - op
-  else: liMessage(info, errOnOrOffExpectedButXFound, arg)
+  else: LocalError(info, errOnOrOffExpectedButXFound, arg)
   
 proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 
-  if arg == "": liMessage(info, errCmdLineArgExpected, switch)
+  if arg == "": LocalError(info, errCmdLineArgExpected, switch)
   
 proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 
-  if arg != "": liMessage(info, errCmdLineNoArgExpected, switch)
+  if arg != "": LocalError(info, errCmdLineNoArgExpected, switch)
   
 proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass, 
                          info: TLineInfo) = 
@@ -212,7 +212,7 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
   case whichKeyword(copy(arg, i))
   of wOn: incl(gNotes, n)
   of wOff: excl(gNotes, n)
-  else: liMessage(info, errOnOrOffExpectedButXFound, arg)
+  else: LocalError(info, errOnOrOffExpectedButXFound, arg)
 
 proc processCompile(filename: string) = 
   var found = findFile(filename)
@@ -228,13 +228,13 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
     of wBoehm: result = contains(gGlobalOptions, optBoehmGC)
     of wRefc:  result = contains(gGlobalOptions, optRefcGC)
     of wNone:  result = gGlobalOptions * {optBoehmGC, optRefcGC} == {}
-    else: liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
+    else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
   of wOpt: 
     case whichKeyword(arg)
     of wSpeed: result = contains(gOptions, optOptimizeSpeed)
     of wSize: result = contains(gOptions, optOptimizeSize)
     of wNone: result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {}
-    else: liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
+    else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
   else: InvalidCmdLineOption(passCmd1, switch, info)
 
 proc testCompileOption*(switch: string, info: TLineInfo): bool = 
@@ -285,7 +285,7 @@ proc addPathRec(dir: string, info: TLineInfo) =
     if k == pcDir and p[pos] != '.':
       addPathRec(p, info)
       if not contains(options.searchPaths, p): 
-        liMessage(info, hintPath, p)
+        Message(info, hintPath, p)
         lists.PrependStr(options.searchPaths, p)
 
 proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = 
@@ -346,7 +346,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
       excl(gGlobalOptions, optRefcGC)
       excl(gGlobalOptions, optBoehmGC)
       defineSymbol("nogc")
-    else: liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
+    else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
   of wWarnings, wW: ProcessOnOffSwitch({optWarns}, arg, pass, info)
   of wWarning: ProcessSpecificNote(arg, wWarning, pass, info)
   of wHint: ProcessSpecificNote(arg, wHint, pass, info)
@@ -388,7 +388,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     of wNone: 
       excl(gOptions, optOptimizeSpeed)
       excl(gOptions, optOptimizeSize)
-    else: liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
+    else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
   of wApp: 
     expectArg(switch, arg, pass, info)
     case whichKeyword(arg)
@@ -401,7 +401,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
       incl(gGlobalOptions, optGenDynLib)
       excl(gGlobalOptions, optGenGuiApp)
       defineSymbol("library")
-    else: liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg)
+    else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
   of wListDef: 
     expectNoArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: condsyms.listSymbols()
@@ -427,8 +427,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     expectArg(switch, arg, pass, info)
     if (pass == passCmd1): 
       theOS = platform.NameToOS(arg)
-      if theOS == osNone: liMessage(info, errUnknownOS, arg)
-      if theOS != platform.hostOS: 
+      if theOS == osNone: LocalError(info, errUnknownOS, arg)
+      elif theOS != platform.hostOS: 
         setTarget(theOS, targetCPU)
         incl(gGlobalOptions, optCompileOnly)
         condsyms.InitDefines()
@@ -436,8 +436,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     expectArg(switch, arg, pass, info)
     if (pass == passCmd1): 
       cpu = platform.NameToCPU(arg)
-      if cpu == cpuNone: liMessage(info, errUnknownCPU, arg)
-      if cpu != platform.hostCPU: 
+      if cpu == cpuNone: LocalError(info, errUnknownCPU, arg)
+      elif cpu != platform.hostCPU: 
         setTarget(targetOS, cpu)
         incl(gGlobalOptions, optCompileOnly)
         condsyms.InitDefines()
diff --git a/rod/ecmasgen.nim b/rod/ecmasgen.nim
index b86b5dd59..6898b01d1 100755
--- a/rod/ecmasgen.nim
+++ b/rod/ecmasgen.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -547,7 +547,7 @@ proc genRaiseStmt(p: var TProc, n: PNode, r: var TCompRes) =
     a: TCompRes
     typ: PType
   genLineDir(p, n, r)
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     gen(p, n.sons[0], a)
     if a.com != nil: appf(r.com, "$1;$n", [a.com])
     typ = skipTypes(n.sons[0].typ, abstractPtrs)
@@ -610,7 +610,7 @@ proc genBlock(p: var TProc, n: PNode, r: var TCompRes) =
     sym: PSym
   inc(p.unique)
   idx = len(p.blocks)
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     # named block?
     if (n.sons[0].kind != nkSym): InternalError(n.info, "genBlock")
     sym = n.sons[0].sym
@@ -633,7 +633,7 @@ proc genBreakStmt(p: var TProc, n: PNode, r: var TCompRes) =
     sym: PSym
   genLineDir(p, n, r)
   idx = len(p.blocks) - 1
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     # named break?
     assert(n.sons[0].kind == nkSym)
     sym = n.sons[0].sym
@@ -991,7 +991,7 @@ proc genVarInit(p: var TProc, v: PSym, n: PNode, r: var TCompRes) =
   var 
     a: TCompRes
     s: PRope
-  if n == nil: 
+  if n.kind == nkEmpty: 
     appf(r.com, "var $1 = $2;$n", 
          [mangleName(v), createVar(p, v.typ, isIndirect(v))])
   else: 
@@ -1135,7 +1135,7 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
   of mExcl: binaryStmt(p, n, r, "", "delete $1[$2]")
   of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
   of mNLen..mNError: 
-    liMessage(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
+    localError(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
   of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
   of mEcho: genEcho(p, n, r)
   else: 
@@ -1231,7 +1231,7 @@ proc genReturnStmt(p: var TProc, n: PNode, r: var TCompRes) =
   var a: TCompRes
   if p.procDef == nil: InternalError(n.info, "genReturnStmt")
   p.BeforeRetNeeded = true
-  if (n.sons[0] != nil): 
+  if (n.sons[0].kind != nkEmpty): 
     genStmt(p, n.sons[0], a)
     if a.com != nil: appf(r.com, "$1;$n", mergeStmt(a))
   else: 
@@ -1297,7 +1297,7 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
   r.com = nil
   r.res = nil
   case n.kind
-  of nkNilLit: nil
+  of nkNilLit, nkEmpty: nil
   of nkStmtList: 
     for i in countup(0, sonsLen(n) - 1): 
       genStmt(p, n.sons[i], a)
@@ -1324,9 +1324,9 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
      nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: 
     nil
   of nkProcDef, nkMethodDef, nkConverterDef: 
-    if (n.sons[genericParamsPos] == nil): 
+    if (n.sons[genericParamsPos].kind == nkEmpty): 
       var prc = n.sons[namePos].sym
-      if (n.sons[codePos] != nil) and not (lfNoDecl in prc.loc.flags): 
+      if (n.sons[codePos].kind != nkEmpty) and not (lfNoDecl in prc.loc.flags): 
         genProc(p, n, r)
       else: 
         discard mangleName(prc)
@@ -1391,6 +1391,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
   of nkCStringToString: convCStrToStr(p, n, r)
   of nkPassAsOpenArray: gen(p, n.sons[0], r)
   of nkStmtListExpr: genStmtListExpr(p, n, r)
+  of nkEmpty: nil
   else: InternalError(n.info, "gen: unknown node type: " & $n.kind)
   
 var globals: PGlobals
@@ -1416,6 +1417,7 @@ proc genModule(p: var TProc, n: PNode, r: var TCompRes) =
         makeCString(toFilename(p.module.module.info)), r.com])
 
 proc myProcess(b: PPassContext, n: PNode): PNode = 
+  if passes.skipCodegen(n): return n
   var 
     p: TProc
     r: TCompRes
@@ -1428,6 +1430,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
   app(p.globals.code, mergeStmt(r))
 
 proc myClose(b: PPassContext, n: PNode): PNode = 
+  if passes.skipCodegen(n): return n
   result = myProcess(b, n)
   var m = BModule(b)
   if sfMainModule in m.module.flags: 
diff --git a/rod/evals.nim b/rod/evals.nim
index b20c20acf..531ef8fbb 100755
--- a/rod/evals.nim
+++ b/rod/evals.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -84,7 +84,7 @@ proc stackTraceAux(x: PStackFrame) =
 proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") = 
   messageOut("stack trace: (most recent call last)")
   stackTraceAux(c.tos)
-  liMessage(n.info, msg, arg)
+  Fatal(n.info, msg, arg)
 
 proc isSpecial(n: PNode): bool = 
   result = (n.kind == nkExceptBranch) 
@@ -414,7 +414,7 @@ proc evalEcho(c: PEvalContext, n: PNode): PNode =
 proc evalExit(c: PEvalContext, n: PNode): PNode = 
   result = evalAux(c, n.sons[1], {})
   if isSpecial(result): return 
-  liMessage(n.info, hintQuitCalled)
+  Message(n.info, hintQuitCalled)
   quit(int(getOrdValue(result)))
 
 proc evalOr(c: PEvalContext, n: PNode): PNode = 
@@ -915,12 +915,12 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
   of mNHint: 
     result = evalAux(c, n.sons[1], {})
     if isSpecial(result): return 
-    liMessage(n.info, hintUser, getStrValue(result))
+    Message(n.info, hintUser, getStrValue(result))
     result = emptyNode
   of mNWarning: 
     result = evalAux(c, n.sons[1], {})
     if isSpecial(result): return 
-    liMessage(n.info, warnUser, getStrValue(result))
+    Message(n.info, warnUser, getStrValue(result))
     result = emptyNode
   of mNError: 
     result = evalAux(c, n.sons[1], {})
diff --git a/rod/extccomp.nim b/rod/extccomp.nim
index bb29cea33..bb29cea33 100644..100755
--- a/rod/extccomp.nim
+++ b/rod/extccomp.nim
diff --git a/rod/filters.nim b/rod/filters.nim
index 20db697bf..d1c61749d 100755
--- a/rod/filters.nim
+++ b/rod/filters.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -9,7 +9,7 @@
 
 # This module implements Nimrod's simple filters and helpers for filters.
 
-import 
+import
   llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, rnimsyn
 
 proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream
@@ -21,7 +21,7 @@ proc boolArg*(n: PNode, name: string, pos: int, default: bool): bool
 # implementation
 
 proc invalidPragma(n: PNode) = 
-  liMessage(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
+  LocalError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
 
 proc getArg(n: PNode, name: string, pos: int): PNode = 
   result = nil
diff --git a/rod/importer.nim b/rod/importer.nim
index 608bad066..06eebcb4e 100755
--- a/rod/importer.nim
+++ b/rod/importer.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -22,7 +22,7 @@ proc getModuleFile*(n: PNode): string
 proc findModule(info: TLineInfo, modulename: string): string = 
   # returns path to module
   result = options.FindFile(AddFileExt(modulename, nimExt))
-  if result == "": liMessage(info, errCannotOpenFile, modulename)
+  if result == "": Fatal(info, errCannotOpenFile, modulename)
   
 proc getModuleFile(n: PNode): string = 
   case n.kind
@@ -73,7 +73,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
 proc importSymbol(c: PContext, ident: PNode, fromMod: PSym) = 
   if (ident.kind != nkIdent): InternalError(ident.info, "importSymbol")
   var s = StrTableGet(fromMod.tab, ident.ident)
-  if s == nil: liMessage(ident.info, errUndeclaredIdentifier, ident.ident.s)
+  if s == nil: GlobalError(ident.info, errUndeclaredIdentifier, ident.ident.s)
   if s.kind == skStub: loadStub(s)
   if not (s.Kind in ExportableSymKinds): 
     InternalError(ident.info, "importSymbol: 2")  
@@ -106,7 +106,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
     var f = getModuleFile(n.sons[i])
     var m = gImportModule(f)
     if sfDeprecated in m.flags: 
-      liMessage(n.sons[i].info, warnDeprecated, m.name.s) 
+      Message(n.sons[i].info, warnDeprecated, m.name.s) 
     # ``addDecl`` needs to be done before ``importAllSymbols``!
     addDecl(c, m)             # add symbol to symbol table of module
     importAllSymbols(c, m)
diff --git a/rod/lookups.nim b/rod/lookups.nim
index f872224c0..160f9635b 100755
--- a/rod/lookups.nim
+++ b/rod/lookups.nim
@@ -35,24 +35,24 @@ proc CloseScope*(tab: var TSymTab) =
   s = InitTabIter(it, tab.stack[tab.tos - 1])
   while s != nil: 
     if sfForward in s.flags: 
-      liMessage(s.info, errImplOfXexpected, getSymRepr(s))
+      LocalError(s.info, errImplOfXexpected, getSymRepr(s))
     elif ({sfUsed, sfInInterface} * s.flags == {}) and
         (optHints in s.options): # BUGFIX: check options in s!
       if not (s.kind in {skForVar, skParam, skMethod, skUnknown}): 
-        liMessage(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
+        Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
     s = NextIter(it, tab.stack[tab.tos - 1])
   astalgo.rawCloseScope(tab)
 
 proc AddSym*(t: var TStrTable, n: PSym) = 
-  if StrTableIncl(t, n): liMessage(n.info, errAttemptToRedefine, n.name.s)
+  if StrTableIncl(t, n): LocalError(n.info, errAttemptToRedefine, n.name.s)
   
 proc addDecl*(c: PContext, sym: PSym) = 
   if SymTabAddUnique(c.tab, sym) == Failure: 
-    liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
+    LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
   
 proc addDeclAt*(c: PContext, sym: PSym, at: Natural) = 
   if SymTabAddUniqueAt(c.tab, sym, at) == Failure: 
-    liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
+    LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
 
 proc AddInterfaceDeclAux(c: PContext, sym: PSym) = 
   if (sfInInterface in sym.flags): 
@@ -66,12 +66,13 @@ proc addInterfaceDeclAt*(c: PContext, sym: PSym, at: Natural) =
   AddInterfaceDeclAux(c, sym)
   
 proc addOverloadableSymAt*(c: PContext, fn: PSym, at: Natural) = 
-  if not (fn.kind in OverloadableSyms): 
+  if fn.kind notin OverloadableSyms: 
     InternalError(fn.info, "addOverloadableSymAt")
   var check = StrTableGet(c.tab.stack[at], fn.name)
-  if (check != nil) and not (check.Kind in OverloadableSyms): 
-    liMessage(fn.info, errAttemptToRedefine, fn.Name.s)
-  SymTabAddAt(c.tab, fn, at)
+  if check != nil and check.Kind notin OverloadableSyms: 
+    LocalError(fn.info, errAttemptToRedefine, fn.Name.s)
+  else:
+    SymTabAddAt(c.tab, fn, at)
   
 proc addInterfaceDecl*(c: PContext, sym: PSym) = 
   # it adds the symbol to the interface if appropriate
@@ -89,17 +90,13 @@ proc lookUp*(c: PContext, n: PNode): PSym =
   of nkAccQuoted: 
     result = lookup(c, n.sons[0])
   of nkSym: 
-    #
-    #      result := SymtabGet(c.Tab, n.sym.name);
-    #      if result = nil then
-    #        liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s); 
     result = n.sym
   of nkIdent: 
     result = SymtabGet(c.Tab, n.ident)
-    if result == nil: liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
+    if result == nil: GlobalError(n.info, errUndeclaredIdentifier, n.ident.s)
   else: InternalError(n.info, "lookUp")
   if IntSetContains(c.AmbiguousSymbols, result.id): 
-    liMessage(n.info, errUseQualifier, result.name.s)
+    LocalError(n.info, errUseQualifier, result.name.s)
   if result.kind == skStub: loadStub(result)
   
 type 
@@ -111,20 +108,15 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
   of nkIdent: 
     result = SymtabGet(c.Tab, n.ident)
     if result == nil and checkUndeclared in flags: 
-      liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
-    elif checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols, 
-                                                    result.id): 
-      liMessage(n.info, errUseQualifier, n.ident.s)
+      GlobalError(n.info, errUndeclaredIdentifier, n.ident.s)
+    elif checkAmbiguity in flags and result != nil and 
+        IntSetContains(c.AmbiguousSymbols, result.id): 
+      LocalError(n.info, errUseQualifier, n.ident.s)
   of nkSym: 
-    #
-    #      result = SymtabGet(c.Tab, n.sym.name)
-    #      if result == nil:
-    #        liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
-    #      else 
     result = n.sym
     if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols, 
                                                   result.id): 
-      liMessage(n.info, errUseQualifier, n.sym.name.s)
+      LocalError(n.info, errUseQualifier, n.sym.name.s)
   of nkDotExpr: 
     result = nil
     var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
@@ -141,9 +133,10 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
         else: 
           result = StrTableGet(m.tab, ident)
         if result == nil and checkUndeclared in flags: 
-          liMessage(n.sons[1].info, errUndeclaredIdentifier, ident.s)
+          GlobalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
       elif checkUndeclared in flags: 
-        liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
+        GlobalError(n.sons[1].info, errIdentifierExpected, 
+                    renderTree(n.sons[1]))
   of nkAccQuoted: 
     result = QualifiedLookup(c, n.sons[0], flags)
   else: 
@@ -151,7 +144,6 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
   if (result != nil) and (result.kind == skStub): loadStub(result)
   
 proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = 
-  var ident: PIdent
   result = nil
   case n.kind
   of nkIdent: 
@@ -163,18 +155,12 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident)
   of nkSym: 
     result = n.sym
-    o.mode = oimDone 
-    #      o.stackPtr = c.tab.tos
-    #      o.mode = oimNoQualifier
-    #      while result == nil:
-    #        dec(o.stackPtr)
-    #        if o.stackPtr < 0: break
-    #        result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name)
+    o.mode = oimDone
   of nkDotExpr: 
     o.mode = oimOtherModule
     o.m = qualifiedLookUp(c, n.sons[0])
     if (o.m != nil) and (o.m.kind == skModule): 
-      ident = nil
+      var ident: PIdent = nil
       if (n.sons[1].kind == nkIdent): 
         ident = n.sons[1].ident
       elif (n.sons[1].kind == nkAccQuoted) and
@@ -188,7 +174,8 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
         else: 
           result = InitIdentIter(o.it, o.m.tab, ident)
       else: 
-        liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
+        GlobalError(n.sons[1].info, errIdentifierExpected, 
+                    renderTree(n.sons[1]))
   of nkAccQuoted: 
     result = InitOverloadIter(o, c, n.sons[0])
   of nkSymChoice: 
diff --git a/rod/main.nim b/rod/main.nim
index 2b391e7dd..5239227ac 100755
--- a/rod/main.nim
+++ b/rod/main.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -73,7 +73,7 @@ proc importModule(filename: string): PSym =
     # compile the module
     result = compileModule(filename, false, false)
   elif sfSystemModule in result.flags: 
-    liMessage(result.info, errAttemptToRedefine, result.Name.s)
+    LocalError(result.info, errAttemptToRedefine, result.Name.s)
   
 proc CompileModule(filename: string, isMainFile, isSystemFile: bool): PSym = 
   var rd: PRodReader = nil
@@ -177,7 +177,7 @@ proc CommandScan(filename: string) =
   
 proc WantFile(filename: string) = 
   if filename == "": 
-    liMessage(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
+    Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
   
 proc MainCommand(cmd, filename: string) = 
   appendStr(searchPaths, options.libpath)
diff --git a/rod/msgs.nim b/rod/msgs.nim
index a3e9c1211..dd7fea4cc 100755
--- a/rod/msgs.nim
+++ b/rod/msgs.nim
@@ -343,7 +343,6 @@ const
     "RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported", 
     "CommentXIgnored", "XisPassedToProcVar", "User"]
 
-const 
   HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong", 
     "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", 
     "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", 
@@ -371,19 +370,20 @@ type
                                # only 8 bytes.
     line*, col*: int16
     fileIndex*: int32
+    
+  ERecoverableError* = object of EInvalidValue
 
 
-proc UnknownLineInfo*(): TLineInfo
-
-var 
+var
   gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)}
   gErrorCounter*: int = 0     # counts the number of errors
   gHintCounter*: int = 0
   gWarnCounter*: int = 0
   gErrorMax*: int = 1         # stop after gErrorMax errors
 
-const # this format is understood by many text editors: it is the same that
-      # Borland and Freepascal use
+# this format is understood by many text editors: it is the same that
+# Borland and Freepascal use
+const
   PosErrorFormat* = "$1($2, $3) Error: $4"
   PosWarningFormat* = "$1($2, $3) Warning: $4"
   PosHintFormat* = "$1($2, $3) Hint: $4"
@@ -391,47 +391,22 @@ const # this format is understood by many text editors: it is the same that
   RawWarningFormat* = "Warning: $1"
   RawHintFormat* = "Hint: $1"
 
-proc MessageOut*(s: string)
-proc rawMessage*(msg: TMsgKind, arg: string)
-proc rawMessage*(msg: TMsgKind, args: openarray[string])
-proc liMessage*(info: TLineInfo, msg: TMsgKind, arg: string = "")
-proc InternalError*(info: TLineInfo, errMsg: string)
-proc InternalError*(errMsg: string)
-proc newLineInfo*(filename: string, line, col: int): TLineInfo
-proc ToFilename*(info: TLineInfo): string
-proc toColumn*(info: TLineInfo): int
-proc ToLinenumber*(info: TLineInfo): int
-proc MsgKindToString*(kind: TMsgKind): string
-  # checkpoints are used for debugging:
-proc checkpoint*(info: TLineInfo, filename: string, line: int): bool
-proc addCheckpoint*(info: TLineInfo)
-proc addCheckpoint*(filename: string, line: int)
-proc inCheckpoint*(current: TLineInfo): bool
-  # prints the line information if in checkpoint
-proc pushInfoContext*(info: TLineInfo)
-proc popInfoContext*()
-proc includeFilename*(f: string): int
-# implementation
-
-proc UnknownLineInfo(): TLineInfo = 
-  result.line = int16(- 1)
-  result.col = int16(- 1)
-  result.fileIndex = - 1
+proc UnknownLineInfo*(): TLineInfo = 
+  result.line = int16(-1)
+  result.col = int16(-1)
+  result.fileIndex = -1
 
 var 
   filenames: seq[string] = @ []
   msgContext: seq[TLineInfo] = @ []
 
-proc pushInfoContext(info: TLineInfo) = 
-  var length: int
-  length = len(msgContext)
-  setlen(msgContext, length + 1)
-  msgContext[length] = info
-
-proc popInfoContext() = 
+proc pushInfoContext*(info: TLineInfo) = 
+  msgContext.add(info)
+  
+proc popInfoContext*() = 
   setlen(msgContext, len(msgContext) - 1)
 
-proc includeFilename(f: string): int = 
+proc includeFilename*(f: string): int = 
   for i in countdown(high(filenames), low(filenames)): 
     if filenames[i] == f: 
       return i
@@ -439,53 +414,51 @@ proc includeFilename(f: string): int =
   setlen(filenames, result + 1)
   filenames[result] = f
 
-proc checkpoint(info: TLineInfo, filename: string, line: int): bool = 
-  result = (int(info.line) == line) and
-      (ChangeFileExt(extractFilename(filenames[info.fileIndex]), "") ==
-      filename)
-
-var checkPoints: seq[TLineInfo] = @[]
-
-proc addCheckpoint(info: TLineInfo) = 
-  var length: int
-  length = len(checkPoints)
-  setlen(checkPoints, length + 1)
-  checkPoints[length] = info
-
-proc addCheckpoint(filename: string, line: int) = 
-  addCheckpoint(newLineInfo(filename, line, - 1))
-
-proc newLineInfo(filename: string, line, col: int): TLineInfo = 
+proc newLineInfo*(filename: string, line, col: int): TLineInfo = 
   result.fileIndex = includeFilename(filename)
   result.line = int16(line)
   result.col = int16(col)
 
-proc ToFilename(info: TLineInfo): string = 
+proc ToFilename*(info: TLineInfo): string = 
   if info.fileIndex == - 1: result = "???"
   else: result = filenames[info.fileIndex]
   
-proc ToLinenumber(info: TLineInfo): int = 
+proc ToLinenumber*(info: TLineInfo): int = 
   result = info.line
 
-proc toColumn(info: TLineInfo): int = 
+proc toColumn*(info: TLineInfo): int = 
   result = info.col
 
-proc MessageOut(s: string) = 
+proc checkpoint*(info: TLineInfo, filename: string, line: int): bool = 
+  result = (int(info.line) == line) and
+      (ChangeFileExt(extractFilename(filenames[info.fileIndex]), "") ==
+      filename)
+
+var checkPoints: seq[TLineInfo] = @[]
+
+proc addCheckpoint*(info: TLineInfo) = 
+  checkPoints.add(info)
+
+proc addCheckpoint*(filename: string, line: int) = 
+  addCheckpoint(newLineInfo(filename, line, - 1))
+
+proc MessageOut*(s: string) = 
   # change only this proc to put it elsewhere
   Writeln(stdout, s)
  
 proc coordToStr(coord: int): string = 
-  if coord == - 1: result = "???"
-  else: result = $(coord)
+  if coord == -1: result = "???"
+  else: result = $coord
   
-proc MsgKindToString(kind: TMsgKind): string = 
+proc MsgKindToString*(kind: TMsgKind): string = 
   # later versions may provide translated error messages
   result = msgKindToStr[kind]
 
 proc getMessageStr(msg: TMsgKind, arg: string): string = 
   result = `%`(msgKindToString(msg), [arg])
 
-proc inCheckpoint(current: TLineInfo): bool = 
+proc inCheckpoint*(current: TLineInfo): bool = 
+  ## prints the line information if in checkpoint
   result = false
   if not (optCheckpoints in gOptions): 
     return                    # ignore all checkpoints
@@ -496,7 +469,10 @@ proc inCheckpoint(current: TLineInfo): bool =
           coordToStr(current.line), coordToStr(current.col)]))
       return true
 
-proc handleError(msg: TMsgKind) = 
+type
+  TErrorHandling = enum doNothing, doAbort, doRaise
+
+proc handleError(msg: TMsgKind, eh: TErrorHandling) = 
   if msg == errInternal: 
     assert(false)             # we want a stack trace here
   if (msg >= fatalMin) and (msg <= fatalMax): 
@@ -504,9 +480,12 @@ proc handleError(msg: TMsgKind) =
     quit(1)
   if (msg >= errMin) and (msg <= errMax): 
     inc(gErrorCounter)
-    if gErrorCounter >= gErrorMax: 
+    options.gExitcode = 1'i8
+    if gErrorCounter >= gErrorMax or eh == doAbort: 
       if gVerbosity >= 3: assert(false)
       quit(1)                 # one error stops the compiler
+    elif eh == doRaise:
+      raise newException(ERecoverableError, "")
   
 proc sameLineInfo(a, b: TLineInfo): bool = 
   result = (a.line == b.line) and (a.fileIndex == b.fileIndex)
@@ -523,7 +502,7 @@ proc writeContext(lastinfo: TLineInfo) =
                                       getMessageStr(errInstantiationFrom, "")]))
     info = msgContext[i]
 
-proc rawMessage(msg: TMsgKind, args: openarray[string]) = 
+proc rawMessage*(msg: TMsgKind, args: openarray[string]) = 
   var frmt: string
   case msg
   of errMin..errMax: 
@@ -542,12 +521,13 @@ proc rawMessage(msg: TMsgKind, args: openarray[string]) =
   else: 
     assert(false)             # cannot happen
   MessageOut(`%`(frmt, `%`(msgKindToString(msg), args)))
-  handleError(msg)
+  handleError(msg, doAbort)
 
-proc rawMessage(msg: TMsgKind, arg: string) = 
+proc rawMessage*(msg: TMsgKind, arg: string) = 
   rawMessage(msg, [arg])
 
-proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string = "") = 
+proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, 
+               eh: TErrorHandling) = 
   var frmt: string
   case msg
   of errMin..errMax: 
@@ -567,12 +547,29 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string = "") =
     assert(false)             # cannot happen
   MessageOut(`%`(frmt, [toFilename(info), coordToStr(info.line), 
                         coordToStr(info.col), getMessageStr(msg, arg)]))
-  handleError(msg)
+  handleError(msg, doAbort)
+  
+proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") = 
+  liMessage(info, msg, arg, doAbort)
+
+proc GlobalError*(info: TLineInfo, msg: TMsgKind, arg = "") = 
+  liMessage(info, msg, arg, doRaise)
+
+proc LocalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
+  liMessage(info, msg, arg, doNothing)
+
+proc Message*(info: TLineInfo, msg: TMsgKind, arg = "") =
+  liMessage(info, msg, arg, doNothing)
+
+proc GenericMessage*(info: TLineInfo, msg: TMsgKind, arg = "") =
+  ## does the right thing for old code that is written with "abort on first
+  ## error" in mind.
+  liMessage(info, msg, arg, doAbort)
 
-proc InternalError(info: TLineInfo, errMsg: string) = 
+proc InternalError*(info: TLineInfo, errMsg: string) = 
   writeContext(info)
-  liMessage(info, errInternal, errMsg)
+  liMessage(info, errInternal, errMsg, doAbort)
 
-proc InternalError(errMsg: string) = 
+proc InternalError*(errMsg: string) = 
   writeContext(UnknownLineInfo())
   rawMessage(errInternal, errMsg)
diff --git a/rod/nimrod.ini b/rod/nimrod.ini
index d4c6dc3b2..d4c6dc3b2 100644..100755
--- a/rod/nimrod.ini
+++ b/rod/nimrod.ini
diff --git a/rod/nimrod.nim b/rod/nimrod.nim
index 5eac2db43..5eac2db43 100644..100755
--- a/rod/nimrod.nim
+++ b/rod/nimrod.nim
diff --git a/rod/pas2nim/paslex.nim b/rod/pas2nim/paslex.nim
index 193a45001..ed554bdc2 100755
--- a/rod/pas2nim/paslex.nim
+++ b/rod/pas2nim/paslex.nim
@@ -109,11 +109,11 @@ proc getLineInfo*(L: TLexer): TLineInfo =
   result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
 
 proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = 
-  msgs.liMessage(getLineInfo(L), msg, arg)
+  msgs.GenericMessage(getLineInfo(L), msg, arg)
 
 proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = 
   var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
-  msgs.liMessage(info, msg, arg)
+  msgs.GenericMessage(info, msg, arg)
 
 proc TokKindToStr*(k: TTokKind): string =
   case k
diff --git a/rod/passaux.nim b/rod/passaux.nim
index d687dba08..5df37c095 100755
--- a/rod/passaux.nim
+++ b/rod/passaux.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -12,10 +12,6 @@
 import 
   strutils, ast, astalgo, passes, msgs, options
 
-proc verbosePass*(): TPass
-proc cleanupPass*(): TPass
-# implementation
-
 proc verboseOpen(s: PSym, filename: string): PPassContext = 
   #MessageOut('compiling ' + s.name.s);
   result = nil                # we don't need a context
@@ -24,9 +20,9 @@ proc verboseOpen(s: PSym, filename: string): PPassContext =
 proc verboseProcess(context: PPassContext, n: PNode): PNode = 
   result = n
   if context != nil: InternalError("logpass: context is not nil")
-  if gVerbosity == 3: liMessage(n.info, hintProcessing, $(ast.gid))
+  if gVerbosity == 3: Message(n.info, hintProcessing, $ast.gid)
   
-proc verbosePass(): TPass = 
+proc verbosePass*(): TPass = 
   initPass(result)
   result.open = verboseOpen
   result.process = verboseProcess
@@ -43,11 +39,11 @@ proc cleanUp(c: PPassContext, n: PNode): PNode =
     if (n.sons[namePos].kind == nkSym): 
       s = n.sons[namePos].sym
       if not (sfDeadCodeElim in getModule(s).flags) and not astNeeded(s): 
-        s.ast.sons[codePos] = nil # free the memory
+        s.ast.sons[codePos] = ast.emptyNode # free the memory
   else: 
     nil
 
-proc cleanupPass(): TPass = 
+proc cleanupPass*(): TPass = 
   initPass(result)
   result.process = cleanUp
   result.close = cleanUp
diff --git a/rod/passes.nim b/rod/passes.nim
index 40036cb5a..b380cd66f 100755
--- a/rod/passes.nim
+++ b/rod/passes.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -25,9 +25,9 @@ type
     close: proc (p: PPassContext, n: PNode): PNode, 
     process: proc (p: PPassContext, topLevelStmt: PNode): PNode] 
     
-# a  pass is a tuple of procedure vars ``TPass.close`` may produce additional 
+# a pass is a tuple of procedure vars ``TPass.close`` may produce additional 
 # nodes. These are passed to the other close procedures. 
-# This mechanism is needed for the instantiation of generics.
+# This mechanism used to be used for the instantiation of generics.
 
 proc registerPass*(p: TPass)
 proc initPass*(p: var TPass)
@@ -37,11 +37,6 @@ proc initPass*(p: var TPass)
   # whole program optimizations. For now, we avoid it to save a lot of memory.
 proc processModule*(module: PSym, filename: string, stream: PLLStream, 
                     rd: PRodReader)
-proc astNeeded*(s: PSym): bool
-  # The ``rodwrite`` module uses this to determine if the body of a proc
-  # needs to be stored. The passes manager frees s.sons[codePos] when
-  # appropriate to free the procedure body's memory. This is important
-  # to keep memory usage down.
 
 # the semantic checker needs these:
 var 
@@ -50,10 +45,21 @@ var
 
 # implementation
 
-proc astNeeded(s: PSym): bool = 
+proc skipCodegen*(n: PNode): bool {.inline.} = 
+  # can be used by codegen passes to determine whether they should do 
+  # something with `n`. Currently, this ignores `n` and uses the global
+  # error count instead.
+  result = msgs.gErrorCounter > 0
+
+proc astNeeded*(s: PSym): bool = 
+  # The ``rodwrite`` module uses this to determine if the body of a proc
+  # needs to be stored. The passes manager frees s.sons[codePos] when
+  # appropriate to free the procedure body's memory. This is important
+  # to keep memory usage down.
   if (s.kind in {skMethod, skProc}) and
       ({sfCompilerProc, sfCompileTime} * s.flags == {}) and
-      (s.typ.callConv != ccInline) and (s.ast.sons[genericParamsPos] == nil): 
+      (s.typ.callConv != ccInline) and 
+      (s.ast.sons[genericParamsPos].kind == nkEmpty): 
     result = false
   else: 
     result = true
diff --git a/rod/pnimsyn.nim b/rod/pnimsyn.nim
index 7734d7490..fb2b7429e 100755
--- a/rod/pnimsyn.nim
+++ b/rod/pnimsyn.nim
@@ -117,7 +117,7 @@ proc indAndComment(p: var TParser, n: PNode) =
     var info = parLineInfo(p)
     getTok(p)
     if p.tok.tokType == tkComment: skipComment(p, n)
-    else: liMessage(info, errInvalidIndentation)
+    else: LocalError(info, errInvalidIndentation)
   else: 
     skipComment(p, n)
   
diff --git a/rod/pragmas.nim b/rod/pragmas.nim
index d19c8d58e..45543eb74 100755
--- a/rod/pragmas.nim
+++ b/rod/pragmas.nim
@@ -52,7 +52,7 @@ proc pragmaAsm*(c: PContext, n: PNode): char
 # implementation
 
 proc invalidPragma(n: PNode) = 
-  liMessage(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
+  LocalError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
 
 proc pragmaAsm(c: PContext, n: PNode): char = 
   result = '\0'
@@ -82,27 +82,24 @@ proc MakeExternExport(s: PSym, extname: string) =
 
 proc getStrLitNode(c: PContext, n: PNode): PNode =
   if n.kind != nkExprColonExpr: 
-    liMessage(n.info, errStringLiteralExpected)
+    GlobalError(n.info, errStringLiteralExpected)
   else: 
     n.sons[1] = c.semConstExpr(c, n.sons[1])
     case n.sons[1].kind
     of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
-    else: liMessage(n.info, errStringLiteralExpected)
+    else: GlobalError(n.info, errStringLiteralExpected)
 
 proc expectStrLit(c: PContext, n: PNode): string = 
   result = getStrLitNode(c, n).strVal
 
 proc expectIntLit(c: PContext, n: PNode): int = 
   if n.kind != nkExprColonExpr: 
-    liMessage(n.info, errIntLiteralExpected)
-    result = 0
+    LocalError(n.info, errIntLiteralExpected)
   else: 
     n.sons[1] = c.semConstExpr(c, n.sons[1])
     case n.sons[1].kind
     of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal)
-    else: 
-      liMessage(n.info, errIntLiteralExpected)
-      result = 0
+    else: LocalError(n.info, errIntLiteralExpected)
 
 proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string = 
   if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
@@ -112,7 +109,9 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
   var v: string
   #if not (sfSystemModule in c.module.flags) then
   #  liMessage(n.info, errMagicOnlyInSystem);
-  if n.kind != nkExprColonExpr: liMessage(n.info, errStringLiteralExpected)
+  if n.kind != nkExprColonExpr: 
+    LocalError(n.info, errStringLiteralExpected)
+    return
   if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
   else: v = expectStrLit(c, n)
   incl(s.flags, sfImportc) 
@@ -123,7 +122,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
     if copy($m, 1) == v: 
       s.magic = m
       return 
-  liMessage(n.info, warnUnknownMagic, v)
+  Message(n.info, warnUnknownMagic, v)
 
 proc wordToCallConv(sw: TSpecialWord): TCallingConvention = 
   # this assumes that the order of special words and calling conventions is
@@ -135,9 +134,9 @@ proc IsTurnedOn(c: PContext, n: PNode): bool =
     case whichKeyword(n.sons[1].ident)
     of wOn: result = true
     of wOff: result = false
-    else: liMessage(n.info, errOnOrOffExpected)
+    else: LocalError(n.info, errOnOrOffExpected)
   else: 
-    liMessage(n.info, errOnOrOffExpected)
+    LocalError(n.info, errOnOrOffExpected)
 
 proc onOff(c: PContext, n: PNode, op: TOptions) = 
   if IsTurnedOn(c, n): gOptions = gOptions + op
@@ -153,9 +152,9 @@ proc processCallConv(c: PContext, n: PNode) =
     case sw
     of firstCallConv..lastCallConv: 
       POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw)
-    else: liMessage(n.info, errCallConvExpected)
+    else: LocalError(n.info, errCallConvExpected)
   else: 
-    liMessage(n.info, errCallConvExpected)
+    LocalError(n.info, errCallConvExpected)
   
 proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = 
   var it = PLib(c.libs.head)
@@ -168,13 +167,13 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
   Append(c.libs, result)
 
 proc expectDynlibNode(c: PContext, n: PNode): PNode = 
-  if n.kind != nkExprColonExpr: liMessage(n.info, errStringLiteralExpected)
+  if n.kind != nkExprColonExpr: GlobalError(n.info, errStringLiteralExpected)
   else: 
     result = c.semExpr(c, n.sons[1])
     if result.kind == nkSym and result.sym.kind == skConst:
       result = result.sym.ast # look it up
     if result.typ == nil or result.typ.kind != tyString: 
-      liMessage(n.info, errStringLiteralExpected)
+      GlobalError(n.info, errStringLiteralExpected)
     
 proc processDynLib(c: PContext, n: PNode, sym: PSym) = 
   if (sym == nil) or (sym.kind == skModule): 
@@ -208,7 +207,7 @@ proc processNote(c: PContext, n: PNode) =
     case whichKeyword(n.sons[1].ident)
     of wOn: incl(gNotes, nk)
     of wOff: excl(gNotes, nk)
-    else: liMessage(n.info, errOnOrOffExpected)
+    else: LocalError(n.info, errOnOrOffExpected)
   else: 
     invalidPragma(n)
   
@@ -254,8 +253,8 @@ proc processOption(c: PContext, n: PNode) =
         of wNone: 
           excl(gOptions, optOptimizeSpeed)
           excl(gOptions, optOptimizeSize)
-        else: liMessage(n.info, errNoneSpeedOrSizeExpected)
-    else: liMessage(n.info, errOptionExpected)
+        else: LocalError(n.info, errNoneSpeedOrSizeExpected)
+    else: LocalError(n.info, errOptionExpected)
   
 proc processPush(c: PContext, n: PNode, start: int) = 
   var x = newOptionEntry()
@@ -271,7 +270,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
   
 proc processPop(c: PContext, n: PNode) = 
   if c.optionStack.counter <= 1: 
-    liMessage(n.info, errAtPopWithoutPush)
+    LocalError(n.info, errAtPopWithoutPush)
   else: 
     gOptions = POptionEntry(c.optionStack.tail).options 
     #liMessage(n.info, warnUser, ropeToStr(optionsToStr(gOptions)));
@@ -281,14 +280,14 @@ proc processPop(c: PContext, n: PNode) =
 proc processDefine(c: PContext, n: PNode) = 
   if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): 
     DefineSymbol(n.sons[1].ident.s)
-    liMessage(n.info, warnDeprecated, "define")
+    Message(n.info, warnDeprecated, "define")
   else: 
     invalidPragma(n)
   
 proc processUndef(c: PContext, n: PNode) = 
   if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): 
     UndefSymbol(n.sons[1].ident.s)
-    liMessage(n.info, warnDeprecated, "undef")
+    Message(n.info, warnDeprecated, "undef")
   else: 
     invalidPragma(n)
   
@@ -329,7 +328,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
   of nkStrLit, nkRStrLit, nkTripleStrLit: 
     result = copyNode(n)
     var str = n.sons[1].strVal
-    if str == "": liMessage(n.info, errEmptyAsm) 
+    if str == "": GlobalError(n.info, errEmptyAsm) 
     # now parse the string literal and substitute symbols:
     var a = 0
     while true: 
@@ -392,14 +391,16 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
           of wExtern: setExternName(sym, expectStrLit(c, it))
           of wAlign: 
             if sym.typ == nil: invalidPragma(it)
-            sym.typ.align = expectIntLit(c, it)
-            if not IsPowerOfTwo(sym.typ.align) and (sym.typ.align != 0): 
-              liMessage(it.info, errPowerOfTwoExpected)
+            var align = expectIntLit(c, it)
+            if not IsPowerOfTwo(align) and align != 0: 
+              LocalError(it.info, errPowerOfTwoExpected)
+            else: 
+              sym.typ.align = align              
           of wSize: 
             if sym.typ == nil: invalidPragma(it)
             var size = expectIntLit(c, it)
             if not IsPowerOfTwo(size) or size <= 0 or size > 8: 
-              liMessage(it.info, errPowerOfTwoExpected)
+              LocalError(it.info, errPowerOfTwoExpected)
             else:
               sym.typ.size = size
           of wNodecl: 
@@ -477,12 +478,10 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
           of wTypeCheck: 
             noVal(it)
             incl(sym.flags, sfTypeCheck)
-          of wHint: liMessage(it.info, hintUser, expectStrLit(c, it))
-          of wWarning: liMessage(it.info, warnUser, expectStrLit(c, it))
-          of wError: liMessage(it.info, errUser, expectStrLit(c, it))
-          of wFatal: 
-            liMessage(it.info, errUser, expectStrLit(c, it))
-            quit(1)
+          of wHint: Message(it.info, hintUser, expectStrLit(c, it))
+          of wWarning: Message(it.info, warnUser, expectStrLit(c, it))
+          of wError: LocalError(it.info, errUser, expectStrLit(c, it))
+          of wFatal: Fatal(it.info, errUser, expectStrLit(c, it))
           of wDefine: processDefine(c, it)
           of wUndef: processUndef(c, it)
           of wCompile: processCompile(c, it)
@@ -515,7 +514,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
     else: processNote(c, it)
   if (sym != nil) and (sym.kind != skModule): 
     if (lfExportLib in sym.loc.flags) and not (sfExportc in sym.flags): 
-      liMessage(n.info, errDynlibRequiresExportc)
+      LocalError(n.info, errDynlibRequiresExportc)
     var lib = POptionEntry(c.optionstack.tail).dynlib
     if ({lfDynamicLib, lfHeader} * sym.loc.flags == {}) and
         (sfImportc in sym.flags) and (lib != nil): 
diff --git a/rod/procfind.nim b/rod/procfind.nim
index bd5b3841f..2bfa27494 100755
--- a/rod/procfind.nim
+++ b/rod/procfind.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -50,7 +50,7 @@ proc SearchForProc(c: PContext, fn: PSym, tos: int): PSym =
         of paramsEqual: 
           return 
         of paramsIncompatible: 
-          liMessage(fn.info, errNotOverloadable, fn.name.s)
+          LocalError(fn.info, errNotOverloadable, fn.name.s)
           return 
         of paramsNotEqual: 
           nil
diff --git a/rod/ptmplsyn.nim b/rod/ptmplsyn.nim
index 24cce2f0e..f428c6df8 100755
--- a/rod/ptmplsyn.nim
+++ b/rod/ptmplsyn.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -94,7 +94,7 @@ proc parseLine(p: var TTmplParser) =
         dec(p.indent, 2)
       else: 
         p.info.col = int16(j)
-        liMessage(p.info, errXNotAllowedHere, "end")
+        LocalError(p.info, errXNotAllowedHere, "end")
       LLStreamWrite(p.outp, repeatChar(p.indent))
       LLStreamWrite(p.outp, "#end")
     of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator, 
@@ -163,7 +163,8 @@ proc parseLine(p: var TTmplParser) =
             while true: 
               case p.x[j]
               of '\0': 
-                liMessage(p.info, errXExpected, "}")
+                LocalError(p.info, errXExpected, "}")
+                break
               of '{': 
                 inc(j)
                 inc(curly)
@@ -196,7 +197,7 @@ proc parseLine(p: var TTmplParser) =
               inc(j)
             else: 
               p.info.col = int16(j)
-              liMessage(p.info, errInvalidExpression, "$")
+              LocalError(p.info, errInvalidExpression, "$")
         else: 
           LLStreamWrite(p.outp, p.x[j])
           inc(j)
diff --git a/rod/rodutils.nim b/rod/rodutils.nim
index dad5d679f..dad5d679f 100644..100755
--- a/rod/rodutils.nim
+++ b/rod/rodutils.nim
diff --git a/rod/rst.nim b/rod/rst.nim
index 207640b2c..efda9bd9a 100755
--- a/rod/rst.nim
+++ b/rod/rst.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -288,10 +288,10 @@ proc tokInfo(p: TRstParser, tok: TToken): TLineInfo =
   result = newLineInfo(p.filename, p.line + tok.line, p.col + tok.col)
 
 proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) = 
-  liMessage(tokInfo(p, p.tok[p.idx]), msgKind, arg)
+  GenericMessage(tokInfo(p, p.tok[p.idx]), msgKind, arg)
 
 proc rstMessage(p: TRstParser, msgKind: TMsgKind) = 
-  liMessage(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol)
+  GenericMessage(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol)
 
 proc currInd(p: TRstParser): int = 
   result = p.indentStack[high(p.indentStack)]
diff --git a/rod/scanner.nim b/rod/scanner.nim
index 1ef688dd3..2560eb6f9 100755
--- a/rod/scanner.nim
+++ b/rod/scanner.nim
@@ -223,11 +223,11 @@ proc getLineInfo(L: TLexer): TLineInfo =
   result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
 
 proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = 
-  msgs.liMessage(getLineInfo(L), msg, arg)
+  msgs.Message(getLineInfo(L), msg, arg)
 
 proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = 
   var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
-  msgs.liMessage(info, msg, arg)
+  msgs.Message(info, msg, arg)
 
 proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = 
   var pos = L.bufpos              # use registers for pos, buf
diff --git a/rod/sem.nim b/rod/sem.nim
index ac2f21857..1e6ec9080 100755
--- a/rod/sem.nim
+++ b/rod/sem.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -25,7 +25,7 @@ proc considerAcc(n: PNode): PIdent =
   of nkIdent: result = x.ident
   of nkSym: result = x.sym.name
   else: 
-    liMessage(n.info, errIdentifierExpected, renderTree(n))
+    GlobalError(n.info, errIdentifierExpected, renderTree(n))
     result = nil
 
 proc isTopLevel(c: PContext): bool = 
@@ -37,7 +37,7 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
 
 proc markUsed(n: PNode, s: PSym) = 
   incl(s.flags, sfUsed)
-  if sfDeprecated in s.flags: liMessage(n.info, warnDeprecated, s.name.s)
+  if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
   
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym
   # identifier with visability
@@ -65,22 +65,22 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
 proc semConstExpr(c: PContext, n: PNode): PNode = 
   result = semExprWithType(c, n)
   if result == nil: 
-    liMessage(n.info, errConstExprExpected)
+    GlobalError(n.info, errConstExprExpected)
     return 
   result = getConstExpr(c.module, result)
-  if result == nil: liMessage(n.info, errConstExprExpected)
+  if result == nil: GlobalError(n.info, errConstExprExpected)
   
 proc semAndEvalConstExpr(c: PContext, n: PNode): PNode = 
   var e = semExprWithType(c, n)
   if e == nil: 
-    liMessage(n.info, errConstExprExpected)
+    GlobalError(n.info, errConstExprExpected)
     return nil
   result = getConstExpr(c.module, e)
   if result == nil: 
     #writeln(output, renderTree(n));
     result = evalConstExpr(c.module, e)
     if (result == nil) or (result.kind == nkEmpty): 
-      liMessage(n.info, errConstExprExpected)
+      GlobalError(n.info, errConstExprExpected)
   
 proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode = 
   result = n
@@ -91,7 +91,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
     result = semExpr(c, result) # semExprWithType(c, result)
   of tyStmt: result = semStmt(c, result)
   of tyTypeDesc: result.typ = semTypeNode(c, result, nil)
-  else: liMessage(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
+  else: GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
   
 include "semtempl.nim"
 
@@ -99,7 +99,7 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
                   semCheck: bool = true): PNode = 
   inc(evalTemplateCounter)
   if evalTemplateCounter > 100: 
-    liMessage(n.info, errTemplateInstantiationTooNested)
+    GlobalError(n.info, errTemplateInstantiationTooNested)
   markUsed(n, sym)
   var p = newEvalContext(c.module, "", false)
   var s = newStackFrame()
@@ -111,23 +111,23 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
   discard eval(p, sym.ast.sons[codePos])
   result = s.params[0]
   popStackFrame(p)
-  if cyclicTree(result): liMessage(n.info, errCyclicTree)
+  if cyclicTree(result): GlobalError(n.info, errCyclicTree)
   if semCheck: result = semAfterMacroCall(c, result, sym)
   dec(evalTemplateCounter)
 
-include "seminst.nim", "sigmatch.nim"
+include seminst, sigmatch
 
 proc CheckBool(t: PNode) = 
   if (t.Typ == nil) or
       (skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool): 
-    liMessage(t.Info, errExprMustBeBool)
+    LocalError(t.Info, errExprMustBeBool)
   
 proc typeMismatch(n: PNode, formal, actual: PType) = 
-  liMessage(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
+  GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
       typeToString(actual) & ") " &
       `%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
 
-include "semtypes.nim", "semexprs.nim", "semgnrc.nim", "semstmts.nim"
+include semtypes, semexprs, semgnrc, semstmts
 
 proc addCodeForGenerics(c: PContext, n: PNode) = 
   for i in countup(c.lastGenericIdx, sonsLen(c.generics) - 1): 
@@ -166,19 +166,28 @@ proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext
   c.fromCache = true
   result = c
 
-proc myProcess(context: PPassContext, n: PNode): PNode = 
-  result = nil
-  var c = PContext(context)
-  result = semStmt(c, n)      
+proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
+  result = semStmt(c, n)
   # BUGFIX: process newly generated generics here, not at the end!
   if sonsLen(c.generics) > 0: 
     var a = newNodeI(nkStmtList, n.info)
     addCodeForGenerics(c, a)
     if sonsLen(a) > 0: 
       # a generic has been added to `a`:
-      addSonIfNotNil(a, result)
+      if result.kind != nkEmpty: addSon(a, result)
       result = a
 
+proc myProcess(context: PPassContext, n: PNode): PNode = 
+  var c = PContext(context)    
+  # no need for an expensive 'try' if we stop after the first error anyway:
+  if msgs.gErrorMax <= 1:
+    result = SemStmtAndGenerateGenerics(c, n)
+  else:
+    try:
+      result = SemStmtAndGenerateGenerics(c, n)
+    except ERecoverableError:
+      result = ast.emptyNode
+  
 proc myClose(context: PPassContext, n: PNode): PNode = 
   var c = PContext(context)
   closeScope(c.tab)           # close module's scope
diff --git a/rod/semdata.nim b/rod/semdata.nim
index ebad21ad8..5b7425a96 100755
--- a/rod/semdata.nim
+++ b/rod/semdata.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -69,10 +69,6 @@ proc makeVarType*(c: PContext, baseType: PType): PType
 proc newTypeS*(kind: TTypeKind, c: PContext): PType
 proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext)
 proc makeRangeType*(c: PContext, first, last: biggestInt, info: TLineInfo): PType
-proc illFormedAst*(n: PNode)
-proc getSon*(n: PNode, indx: int): PNode
-proc checkSonsLen*(n: PNode, length: int)
-proc checkMinSonsLen*(n: PNode, length: int)
   
 # owner handling:
 proc getCurrOwner*(): PSym
@@ -122,7 +118,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
   append(result.optionStack, newOptionEntry())
   result.module = module
   result.generics = newNode(nkStmtList)
-  result.converters = @ []
+  result.converters = @[]
   result.filename = nimfile
   IntSetInit(result.includedFiles)
   initStrTable(result.userPragmas)
@@ -140,7 +136,7 @@ proc newLib(kind: TLibKind): PLib =
   
 proc addToLib(lib: PLib, sym: PSym) = 
   #ObjectSetIncl(lib.syms, sym);
-  if sym.annex != nil: liMessage(sym.info, errInvalidPragma)
+  if sym.annex != nil: LocalError(sym.info, errInvalidPragma)
   sym.annex = lib
 
 proc makePtrType(c: PContext, baseType: PType): PType = 
@@ -170,20 +166,13 @@ proc makeRangeType(c: PContext, first, last: biggestInt,
   result.n = n
   addSon(result, getSysType(tyInt)) # basetype of range
   
-proc illFormedAst(n: PNode) = 
-  liMessage(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
-
-proc getSon(n: PNode, indx: int): PNode = 
-  if (n != nil) and (indx < sonsLen(n)): 
-    result = n.sons[indx]
-  else: 
-    illFormedAst(n)
-    result = nil
-
-proc checkSonsLen(n: PNode, length: int) = 
-  if (n == nil) or (sonsLen(n) != length): illFormedAst(n)
+proc illFormedAst*(n: PNode) = 
+  GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
+
+proc checkSonsLen*(n: PNode, length: int) = 
+  if sonsLen(n) != length: illFormedAst(n)
   
-proc checkMinSonsLen(n: PNode, length: int) = 
-  if (n == nil) or (sonsLen(n) < length): illFormedAst(n)
+proc checkMinSonsLen*(n: PNode, length: int) = 
+  if sonsLen(n) < length: illFormedAst(n)
   
 initIdTable(gInstTypes)
diff --git a/rod/semexprs.nim b/rod/semexprs.nim
index cdcf09d3e..0478cff82 100755
--- a/rod/semexprs.nim
+++ b/rod/semexprs.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -23,22 +23,24 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
 proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
   result = semExpr(c, n, flags)
-  if result == nil: InternalError("semExprWithType")
-  if (result.typ == nil): 
-    liMessage(n.info, errExprXHasNoType, renderTree(result, {renderNoComments}))
-  if result.typ.kind == tyVar: 
-    var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])
-    addSon(d, result)
-    result = d
-
+  if result.kind == nkEmpty: InternalError("semExprWithType")
+  if result.typ != nil: 
+    if result.typ.kind == tyVar: 
+      var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])
+      addSon(d, result)
+      result = d
+  else:
+    GlobalError(n.info, errExprXHasNoType, 
+                renderTree(result, {renderNoComments}))
+  
 proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = 
   if s.kind == skType and efAllowType notin flags:
-    liMessage(n.info, errATypeHasNoValue)
+    GlobalError(n.info, errATypeHasNoValue)
   case s.kind
   of skProc, skMethod, skIterator, skConverter: 
     if not (sfProcVar in s.flags) and (s.typ.callConv == ccDefault) and
         (getModule(s).id != c.module.id): 
-      liMessage(n.info, errXCannotBePassedToProcVar, s.name.s)
+      LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
     result = symChoice(c, n, s)
   of skConst: 
     #
@@ -79,7 +81,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
 proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) = 
   var diff = inheritanceDiff(castDest, src)
   if diff == high(int): 
-    liMessage(info, errGenerated, `%`(MsgKindToString(errIllegalConvFromXtoY), [
+    GlobalError(info, errGenerated, `%`(MsgKindToString(errIllegalConvFromXtoY), [
         typeToString(src), typeToString(castDest)]))
   
 proc checkConvertible(info: TLineInfo, castDest, src: PType) = 
@@ -88,7 +90,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
   if sameType(castDest, src): 
     # don't annoy conversions that may be needed on another processor:
     if not (castDest.kind in {tyInt..tyFloat128, tyNil}): 
-      liMessage(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
+      Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
     return 
   var d = skipTypes(castDest, abstractVar)
   var s = skipTypes(src, abstractVar)
@@ -96,9 +98,9 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
     d = base(d)
     s = base(s)
   if d == nil: 
-    liMessage(info, errGenerated, `%`(msgKindToString(errIllegalConvFromXtoY), [
+    GlobalError(info, errGenerated, `%`(msgKindToString(errIllegalConvFromXtoY), [
         typeToString(src), typeToString(castDest)]))
-  if (d.Kind == tyObject) and (s.Kind == tyObject): 
+  elif d.Kind == tyObject and s.Kind == tyObject: 
     checkConversionBetweenObjects(info, d, s)
   elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
       (skipTypes(src, abstractVarRange).Kind in IntegralTypes): 
@@ -109,7 +111,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
     of isNone, isGeneric: 
       if not equalOrDistinctOf(castDest, src) and
           not equalOrDistinctOf(src, castDest): 
-        liMessage(info, errGenerated, `%`(
+        GlobalError(info, errGenerated, `%`(
             MsgKindToString(errIllegalConvFromXtoY), 
             [typeToString(src), typeToString(castDest)]))
     else: 
@@ -134,7 +136,7 @@ proc isCastable(dst, src: PType): bool =
         (skipTypes(src, abstractInst).kind in {tyInt..tyFloat128})
   
 proc semConv(c: PContext, n: PNode, s: PSym): PNode = 
-  if sonsLen(n) != 2: liMessage(n.info, errConvNeedsOneArg)
+  if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg)
   result = newNodeI(nkConv, n.info)
   result.typ = semTypeNode(c, n.sons[0], nil)
   addSon(result, copyTree(n.sons[0]))
@@ -147,10 +149,10 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
       if sameType(result.typ, op.sons[i].typ): 
         markUsed(n, op.sons[i].sym)
         return op.sons[i]
-    liMessage(n.info, errUseQualifier, op.sons[0].sym.name.s)
+    localError(n.info, errUseQualifier, op.sons[0].sym.name.s)
 
 proc semCast(c: PContext, n: PNode): PNode = 
-  if optSafeCode in gGlobalOptions: liMessage(n.info, errCastNotInSafeMode)
+  if optSafeCode in gGlobalOptions: localError(n.info, errCastNotInSafeMode)
   incl(c.p.owner.flags, sfSideEffect)
   checkSonsLen(n, 2)
   result = newNodeI(nkCast, n.info)
@@ -158,13 +160,13 @@ proc semCast(c: PContext, n: PNode): PNode =
   addSon(result, copyTree(n.sons[0]))
   addSon(result, semExprWithType(c, n.sons[1]))
   if not isCastable(result.typ, result.sons[1].Typ): 
-    liMessage(result.info, errExprCannotBeCastedToX, typeToString(result.Typ))
+    GlobalError(result.info, errExprCannotBeCastedToX, typeToString(result.Typ))
   
 proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = 
   const 
     opToStr: array[mLow..mHigh, string] = ["low", "high"]
   if sonsLen(n) != 2: 
-    liMessage(n.info, errXExpectsTypeOrValue, opToStr[m])
+    GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m])
   else: 
     n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
     var typ = skipTypes(n.sons[1].typ, abstractVarRange)
@@ -175,11 +177,11 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
       n.typ = n.sons[1].typ.sons[0] # indextype
     of tyInt..tyInt64, tyChar, tyBool, tyEnum: 
       n.typ = n.sons[1].typ
-    else: liMessage(n.info, errInvalidArgForX, opToStr[m])
+    else: GlobalError(n.info, errInvalidArgForX, opToStr[m])
   result = n
 
 proc semSizeof(c: PContext, n: PNode): PNode = 
-  if sonsLen(n) != 2: liMessage(n.info, errXExpectsTypeOrValue, "sizeof")
+  if sonsLen(n) != 2: GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
   else: n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
   n.typ = getSysType(tyInt)
   result = n
@@ -190,20 +192,22 @@ proc semIs(c: PContext, n: PNode): PNode =
     n.sons[2] = semExprWithType(c, n.sons[2], {efAllowType})
     var a = n.sons[1].typ
     var b = n.sons[2].typ
-    if (b.kind != tyObject) or (a.kind != tyObject): 
-      liMessage(n.info, errIsExpectsObjectTypes)
-    while (b != nil) and (b.id != a.id): b = b.sons[0]
-    if b == nil: liMessage(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
+    # a and b can be nil in case of an error:
+    if a != nil and b != nil:
+      if (b.kind != tyObject) or (a.kind != tyObject): 
+        GlobalError(n.info, errIsExpectsObjectTypes)
+      while (b != nil) and (b.id != a.id): b = b.sons[0]
+      if b == nil: 
+        GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
     n.typ = getSysType(tyBool)
   else: 
-    liMessage(n.info, errIsExpectsTwoArguments)
+    GlobalError(n.info, errIsExpectsTwoArguments)
   result = n
 
 proc semOpAux(c: PContext, n: PNode) = 
   for i in countup(1, sonsLen(n) - 1): 
     var a = n.sons[i]
-    if a.kind == nkExprEqExpr: 
-      checkSonsLen(a, 2)
+    if a.kind == nkExprEqExpr and sonsLen(a) == 2: 
       var info = a.sons[0].info
       a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
       a.sons[1] = semExprWithType(c, a.sons[1])
@@ -223,9 +227,6 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
     result = semExpr(c, result)
 
 proc changeType(n: PNode, newType: PType) = 
-  var 
-    f: PSym
-    a, m: PNode
   case n.kind
   of nkCurly, nkBracket: 
     for i in countup(0, sonsLen(n) - 1): changeType(n.sons[i], elemType(newType))
@@ -235,22 +236,21 @@ proc changeType(n: PNode, newType: PType) =
     if newType.n == nil: InternalError(n.info, "changeType: no tuple fields")
     if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr): 
       for i in countup(0, sonsLen(n) - 1): 
-        m = n.sons[i].sons[0]
+        var m = n.sons[i].sons[0]
         if m.kind != nkSym: 
           internalError(m.info, "changeType(): invalid tuple constr")
-        f = getSymFromList(newType.n, m.sym.name)
+        var f = getSymFromList(newType.n, m.sym.name)
         if f == nil: internalError(m.info, "changeType(): invalid identifier")
         changeType(n.sons[i].sons[1], f.typ)
     else: 
       for i in countup(0, sonsLen(n) - 1): 
-        m = n.sons[i]
-        a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
+        var m = n.sons[i]
+        var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
         addSon(a, newSymNode(newType.n.sons[i].sym))
         addSon(a, m)
         changeType(m, newType.sons[i])
         n.sons[i] = a
-  else: 
-    nil
+  else: nil
   n.typ = newType
 
 proc semArrayConstr(c: PContext, n: PNode): PNode = 
@@ -263,7 +263,7 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
     var x = n.sons[0]
     var lastIndex: biggestInt = 0
     var indexType = getSysType(tyInt)
-    if x.kind == nkExprColonExpr: 
+    if x.kind == nkExprColonExpr and sonsLen(x) == 2: 
       var idx = semConstExpr(c, x.sons[0])
       lastIndex = getOrdValue(idx)
       indexType = idx.typ
@@ -273,11 +273,11 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
     var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
     for i in countup(1, sonsLen(n) - 1): 
       x = n.sons[i]
-      if x.kind == nkExprColonExpr:
+      if x.kind == nkExprColonExpr and sonsLen(x) == 2: 
         var idx = semConstExpr(c, x.sons[0])
         idx = fitNode(c, indexType, idx)
         if lastIndex+1 != getOrdValue(idx):
-          liMessage(x.info, errInvalidOrderInArrayConstructor)
+          localError(x.info, errInvalidOrderInArrayConstructor)
         x = x.sons[1]
       
       n.sons[i] = semExprWithType(c, x)
@@ -334,7 +334,6 @@ proc isAssignable(n: PNode): TAssignableResult =
   of nkSym: 
     if (n.sym.kind in {skVar, skTemp}): result = arLValue
   of nkDotExpr: 
-    checkMinSonsLen(n, 1)
     if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}: 
       result = arLValue
     else: 
@@ -342,7 +341,6 @@ proc isAssignable(n: PNode): TAssignableResult =
     if (result == arLValue) and (sfDiscriminant in n.sons[1].sym.flags): 
       result = arDiscriminant
   of nkBracketExpr: 
-    checkMinSonsLen(n, 1)
     if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}: 
       result = arLValue
     else: 
@@ -368,7 +366,7 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
     result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
     addSon(result, n)
     if isAssignable(n) != arLValue: 
-      liMessage(n.info, errVarForOutParamNeeded)
+      localError(n.info, errVarForOutParamNeeded)
 
 proc analyseIfAddressTaken(c: PContext, n: PNode): PNode = 
   result = n
@@ -403,7 +401,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
     for i in countup(1, sonsLen(n) - 1): 
       if i < sonsLen(t) and skipTypes(t.sons[i], abstractInst).kind == tyVar: 
         if isAssignable(n.sons[i]) != arLValue: 
-          liMessage(n.sons[i].info, errVarForOutParamNeeded)
+          LocalError(n.sons[i].info, errVarForOutParamNeeded)
     return
   for i in countup(1, sonsLen(n) - 1): 
     if (i < sonsLen(t)) and
@@ -421,7 +419,7 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
       InternalError("semDirectCallAnalyseEffects")
     var callee = result.sons[0].sym
     if (callee.kind == skIterator) and (callee.id == c.p.owner.id): 
-      liMessage(n.info, errRecursiveDependencyX, callee.name.s)
+      GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
     if not (sfNoSideEffect in callee.flags): 
       if (sfForward in callee.flags) or
           ({sfImportc, sfSideEffect} * callee.flags != {}): 
@@ -456,7 +454,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
         add(msg, typeToString(n.sons[i].typ))
       add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
           typeToString(n.sons[0].typ))
-      liMessage(n.Info, errGenerated, msg)
+      GlobalError(n.Info, errGenerated, msg)
       result = nil
     else: 
       result = m.call
@@ -471,8 +469,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
       n.sons[0] = prc
       result = semDirectCallAnalyseEffects(c, n, flags)
     if result == nil: 
-      liMessage(n.info, errExprXCannotBeCalled, 
-                renderTree(n, {renderNoComments}))
+      GlobalError(n.info, errExprXCannotBeCalled, 
+                  renderTree(n, {renderNoComments}))
   fixAbstractType(c, result)
   analyseIfAddressTakenInCall(c, result)
 
@@ -482,7 +480,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = semDirectCallAnalyseEffects(c, n, flags)
   if result == nil: 
     result = overloadedCallOpr(c, n)
-    if result == nil: liMessage(n.Info, errGenerated, getNotFoundError(c, n))
+    if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n))
   fixAbstractType(c, result)
   analyseIfAddressTakenInCall(c, result)
 
@@ -517,12 +515,12 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
         else: 
           result = StrTableGet(m.tab, ident)
       else: 
-        liMessage(n.sons[1].info, errIdentifierExpected, "")
+        GlobalError(n.sons[1].info, errIdentifierExpected, "")
   of nkAccQuoted: 
     checkSonsLen(n, 1)
     result = lookupForDefined(c, n.sons[0], onlyCurrentScope)
   else: 
-    liMessage(n.info, errIdentifierExpected, renderTree(n))
+    GlobalError(n.info, errIdentifierExpected, renderTree(n))
     result = nil
 
 proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = 
@@ -588,7 +586,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
         else: 
           if check == nil: 
             check = newNodeI(nkCheckedFieldExpr, n.info)
-            addSon(check, nil) # make space for access node
+            addSon(check, ast.emptyNode) # make space for access node
           s = newNodeI(nkCurly, n.info)
           for j in countup(0, sonsLen(it) - 2): addSon(s, copyTree(it.sons[j]))
           inExpr = newNodeI(nkCall, n.info)
@@ -602,7 +600,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
         if result != nil: 
           if check == nil: 
             check = newNodeI(nkCheckedFieldExpr, n.info)
-            addSon(check, nil) # make space for access node
+            addSon(check, ast.emptyNode) # make space for access node
           inExpr = newNodeI(nkCall, n.info)
           addSon(inExpr, newIdentNode(getIdent("in"), n.info))
           addSon(inExpr, copyTree(r.sons[0]))
@@ -653,10 +651,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
       result.typ = ty
       markUsed(n, f)
     else: 
-      liMessage(n.sons[1].info, errEnumHasNoValueX, i.s)
+      GlobalError(n.sons[1].info, errEnumHasNoValueX, i.s)
     return 
   elif not (efAllowType in flags) and isTypeExpr(n.sons[0]): 
-    liMessage(n.sons[0].info, errATypeHasNoValue)
+    GlobalError(n.sons[0].info, errATypeHasNoValue)
     return 
   ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
   var check: PNode = nil
@@ -705,27 +703,27 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
       addSon(result, newIdentNode(i, n.info))
       addSon(result, copyTree(n[0]))
     else: 
-      liMessage(n.Info, errUndeclaredFieldX, i.s)
+      GlobalError(n.Info, errUndeclaredFieldX, i.s)
 
 proc whichSliceOpr(n: PNode): string = 
-  if (n.sons[0] == nil): 
-    if (n.sons[1] == nil): result = "[..]"
+  if n.sons[0].kind == nkEmpty: 
+    if n.sons[1].kind == nkEmpty: result = "[..]"
     else: result = "[..$]"
-  elif (n.sons[1] == nil): 
+  elif n.sons[1].kind == nkEmpty: 
     result = "[$..]"
   else: 
     result = "[$..$]"
 
 proc addSliceOpr(result: var string, n: PNode) = 
-  if n[0] == nil: 
-    if n[1] == nil: result.add("..")
+  if n[0].kind == nkEmpty: 
+    if n[1].kind == nkEmpty: result.add("..")
     else: result.add("..$")
-  elif n[1] == nil: result.add("$..") 
+  elif n[1].kind == nkEmpty: result.add("$..") 
   else: result.add("$..$")
 
 proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
   result = newNodeI(nkCall, n.info)
-  add(result, nil) # fill with the correct node later
+  add(result, ast.emptyNode) # fill with the correct node later
   add(result, n[0])
   var opr = "["
   for i in 1..n.len-1:
@@ -734,8 +732,8 @@ proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
       # we have a slice argument
       checkSonsLen(n[i], 2)
       addSliceOpr(opr, n[i])
-      addSonIfNotNil(result, n[i][0])
-      addSonIfNotNil(result, n[i][1])
+      addSon(result, n[i][0])
+      addSon(result, n[i][1])
     else:
       add(result, n[i])
   if inAsgn: add(opr, "]=")
@@ -757,7 +755,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
     var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
     var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
     if arg != nil: n.sons[1] = arg
-    else: liMessage(n.info, errIndexTypesDoNotMatch)
+    else: GlobalError(n.info, errIndexTypesDoNotMatch)
     result = n
     result.typ = elemType(arr)
   of tyTuple: 
@@ -769,9 +767,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
         {tyInt..tyInt64}: 
       var idx = getOrdValue(n.sons[1])
       if (idx >= 0) and (idx < sonsLen(arr)): n.typ = arr.sons[int(idx)]
-      else: liMessage(n.info, errInvalidIndexValueForTuple)
+      else: GlobalError(n.info, errInvalidIndexValueForTuple)
     else: 
-      liMessage(n.info, errIndexTypesDoNotMatch)
+      GlobalError(n.info, errIndexTypesDoNotMatch)
     result = n
   else: nil
   
@@ -779,21 +777,7 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = semSubscript(c, n, flags)
   if result == nil:
     # overloaded [] operator:
-    when false:
-      result = newNodeI(nkCall, n.info)
-      if n.sons[1].kind == nkRange: 
-        checkSonsLen(n.sons[1], 2)
-        addSon(result, newIdentNode(getIdent(whichSliceOpr(n.sons[1])), n.info))
-        addSon(result, n.sons[0])
-        addSonIfNotNil(result, n.sons[1].sons[0])
-        addSonIfNotNil(result, n.sons[1].sons[1])
-      else: 
-        addSon(result, newIdentNode(getIdent("[]"), n.info))
-        addSon(result, n.sons[0])
-        addSon(result, n.sons[1])
-      result = semExpr(c, result)
-    else:
-      result = semExpr(c, buildOverloadedSubscripts(n, inAsgn=false))
+    result = semExpr(c, buildOverloadedSubscripts(n, inAsgn=false))
 
 proc semIfExpr(c: PContext, n: PNode): PNode = 
   result = n
@@ -839,7 +823,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
         if typ == nil: 
           typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
     if not isOrdinalType(typ): 
-      liMessage(n.info, errOrdinalTypeExpected)
+      GlobalError(n.info, errOrdinalTypeExpected)
       return 
     if lengthOrd(typ) > MaxSetElements: 
       typ = makeRangeType(c, 0, MaxSetElements - 1, n.info)
@@ -871,11 +855,11 @@ proc checkPar(n: PNode): TParKind =
       if result == paTupleFields: 
         if (n.sons[i].kind != nkExprColonExpr) or
             not (n.sons[i].sons[0].kind in {nkSym, nkIdent}): 
-          liMessage(n.sons[i].info, errNamedExprExpected)
+          GlobalError(n.sons[i].info, errNamedExprExpected)
           return paNone
       else: 
         if n.sons[i].kind == nkExprColonExpr: 
-          liMessage(n.sons[i].info, errNamedExprNotAllowed)
+          GlobalError(n.sons[i].info, errNamedExprNotAllowed)
           return paNone
 
 proc semTupleFieldsConstr(c: PContext, n: PNode): PNode = 
@@ -892,7 +876,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
     if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
     else: id = n.sons[i].sons[0].sym.name
     if IntSetContainsOrIncl(ids, id.id): 
-      liMessage(n.sons[i].info, errFieldInitTwice, id.s)
+      localError(n.sons[i].info, errFieldInitTwice, id.s)
     n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
     var f = newSymS(skField, n.sons[i].sons[0], c)
     f.typ = n.sons[i].sons[1].typ
@@ -925,7 +909,7 @@ proc semBlockExpr(c: PContext, n: PNode): PNode =
   Inc(c.p.nestedBlockCounter)
   checkSonsLen(n, 2)
   openScope(c.tab)            # BUGFIX: label is in the scope of block!
-  if n.sons[0] != nil: addDecl(c, newSymS(skLabel, n.sons[0], c))
+  if n.sons[0].kind != nkEmpty: addDecl(c, newSymS(skLabel, n.sons[0], c))
   n.sons[1] = semStmtListExpr(c, n.sons[1])
   n.typ = n.sons[1].typ
   closeScope(c.tab)
@@ -935,7 +919,7 @@ proc isCallExpr(n: PNode): bool =
   result = n.kind in {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
                       nkCallStrLit}
 
-proc semMacroStmt(c: PContext, n: PNode, semCheck: bool = true): PNode = 
+proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode = 
   checkMinSonsLen(n, 2)
   var a: PNode
   if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
@@ -957,23 +941,18 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck: bool = true): PNode =
           addSon(result, n.sons[0].sons[i])
       for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
       result = semTemplateExpr(c, result, s, semCheck)
-    else: liMessage(n.info, errXisNoMacroOrTemplate, s.name.s)
+    else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s)
   else: 
-    liMessage(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments}))
+    GlobalError(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments}))
   
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
   result = n
-  if n == nil: return 
   if nfSem in n.flags: return 
   case n.kind                 # atoms:
   of nkIdent: 
     var s = lookUp(c, n)
     result = semSym(c, n, s, flags)
   of nkSym: 
-    #s := n.sym;
-    #      include(s.flags, sfUsed);
-    #      if (s.kind = skType) and not (efAllowType in flags) then
-    #        liMessage(n.info, errATypeHasNoValue);
     # because of the changed symbol binding, this does not mean that we
     # don't have to check the symbol for semantics here again!
     result = semSym(c, n, n.sym, flags)
@@ -982,7 +961,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkNilLit: 
     result.typ = getSysType(tyNil)
   of nkType: 
-    if not (efAllowType in flags): liMessage(n.info, errATypeHasNoValue)
+    if not (efAllowType in flags): GlobalError(n.info, errATypeHasNoValue)
     n.typ = semTypeNode(c, n, nil)
   of nkIntLit: 
     if result.typ == nil: result.typ = getSysType(tyInt)
@@ -1020,7 +999,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       of skMacro: result = semMacroExpr(c, n, s)
       of skTemplate: result = semTemplateExpr(c, n, s)
       of skType: 
-        if n.kind != nkCall: liMessage(n.info, errXisNotCallable, s.name.s)
+        if n.kind != nkCall: GlobalError(n.info, errXisNotCallable, s.name.s)
         # XXX does this check make any sense?
         result = semConv(c, n, s)
       of skProc, skMethod, skConverter, skIterator: 
@@ -1062,14 +1041,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar})
     case t.kind
     of tyRef, tyPtr: n.typ = t.sons[0]
-    else: liMessage(n.sons[0].info, errCircumNeedsPointer)
+    else: GlobalError(n.sons[0].info, errCircumNeedsPointer)
     result = n
   of nkAddr: 
     result = n
     checkSonsLen(n, 1)
     n.sons[0] = semExprWithType(c, n.sons[0])
     if isAssignable(n.sons[0]) != arLValue: 
-      liMessage(n.info, errExprHasNoAddress)
+      GlobalError(n.info, errExprHasNoAddress)
     n.typ = makePtrType(c, n.sons[0].typ)
   of nkHiddenAddr, nkHiddenDeref: 
     checkSonsLen(n, 1)
@@ -1091,8 +1070,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkCheckedFieldExpr: 
     checkMinSonsLen(n, 2)
   of nkSymChoice: 
-    liMessage(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
+    GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
   else: 
     #InternalError(n.info, nodeKindToStr[n.kind]);
-    liMessage(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments}))
+    GlobalError(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments}))
   incl(result.flags, nfSem)
diff --git a/rod/semfold.nim b/rod/semfold.nim
index a61ad0f8e..234d656f3 100755
--- a/rod/semfold.nim
+++ b/rod/semfold.nim
@@ -334,8 +334,10 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
       of mSizeOf: 
         var a = n.sons[1]
         if computeSize(a.typ) < 0: 
-          liMessage(a.info, errCannotEvalXBecauseIncompletelyDefined, "sizeof")
-        if a.typ.kind in {tyArray, tyObject, tyTuple}: 
+          LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined, 
+                     "sizeof")
+          result = nil
+        elif a.typ.kind in {tyArray, tyObject, tyTuple}: 
           result = nil        
           # XXX: size computation for complex types is still wrong
         else: 
@@ -345,7 +347,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
       of mHigh: 
         if not (skipTypes(n.sons[1].typ, abstractVar).kind in
             {tyOpenArray, tySequence, tyString}): 
-          result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)), n)
+          result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)),
+                               n)
       of mLengthOpenArray:
         var a = n.sons[1]
         if a.kind == nkPassAsOpenArray: a = a.sons[0]
@@ -357,9 +360,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
       else: 
         result = magicCall(m, n)
     except EOverflow: 
-      liMessage(n.info, errOverOrUnderflow)
+      LocalError(n.info, errOverOrUnderflow)
     except EDivByZero: 
-      liMessage(n.info, errConstantDivisionByZero)
+      LocalError(n.info, errConstantDivisionByZero)
   of nkAddr: 
     var a = getConstExpr(m, n.sons[0])
     if a != nil: 
@@ -408,7 +411,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
       result = a              # a <= x and x <= b
       result.typ = n.typ
     else: 
-      liMessage(n.info, errGenerated, `%`(
+      LocalError(n.info, errGenerated, `%`(
           msgKindToString(errIllegalConvFromXtoY), 
           [typeToString(n.sons[0].typ), typeToString(n.typ)]))
   of nkStringToCString, nkCStringToString: 
diff --git a/rod/semgnrc.nim b/rod/semgnrc.nim
index 3ccd415f9..77c200120 100755
--- a/rod/semgnrc.nim
+++ b/rod/semgnrc.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -55,7 +55,7 @@ proc getIdentNode(n: PNode): PNode =
   of nkIdent: result = n
   else: 
     illFormedAst(n)
-    result = nil
+    result = n
 
 #  of nkAccQuoted: 
 #    s = lookUp(c, n)
@@ -67,21 +67,20 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
     L: int
     a: PNode
   result = n
-  if n == nil: return 
   case n.kind
   of nkIdent:
     var s = SymtabGet(c.Tab, n.ident)
     if s == nil:
       # no error if symbol cannot be bound, unless in ``bind`` context:
       if withinBind in flags: 
-        liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
+        localError(n.info, errUndeclaredIdentifier, n.ident.s)
     else:
       if withinBind in flags: result = symChoice(c, n, s)
       else: result = semGenericStmtSymbol(c, n, s)
   of nkDotExpr: 
     var s = QualifiedLookUp(c, n, {})
     if s != nil: result = semGenericStmtSymbol(c, n, s)
-  of nkSym..nkNilLit: 
+  of nkEmpty, nkSym..nkNilLit: 
     nil
   of nkBind: 
     result = semGenericStmt(c, n.sons[0], {withinBind})
@@ -138,7 +137,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
   of nkBlockStmt, nkBlockExpr, nkBlockType: 
     checkSonsLen(n, 2)
     openScope(c.tab)
-    if n.sons[0] != nil: addDecl(c, newSymS(skUnknown, n.sons[0], c))
+    if n.sons[0].kind != nkEmpty: addDecl(c, newSymS(skUnknown, n.sons[0], c))
     n.sons[1] = semGenericStmt(c, n.sons[1])
     closeScope(c.tab)
   of nkTryStmt: 
@@ -193,7 +192,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
       if a.kind == nkCommentStmt: continue 
       if (a.kind != nkTypeDef): IllFormedAst(a)
       checkSonsLen(a, 3)
-      if a.sons[1] != nil: 
+      if a.sons[1].kind != nkEmpty: 
         openScope(c.tab)
         a.sons[1] = semGenericStmt(c, a.sons[1])
         a.sons[2] = semGenericStmt(c, a.sons[2], {withinTypeDesc})
@@ -202,7 +201,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
         a.sons[2] = semGenericStmt(c, a.sons[2], {withinTypeDesc})
   of nkEnumTy: 
     checkMinSonsLen(n, 1)
-    if n.sons[0] != nil: 
+    if n.sons[0].kind != nkEmpty: 
       n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
     for i in countup(1, sonsLen(n) - 1): 
       case n.sons[i].kind
@@ -214,7 +213,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
     nil
   of nkFormalParams: 
     checkMinSonsLen(n, 1)
-    if n.sons[0] != nil: 
+    if n.sons[0].kind != nkEmpty: 
       n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
     for i in countup(1, sonsLen(n) - 1): 
       a = n.sons[i]
@@ -231,8 +230,8 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
     addDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c))
     openScope(c.tab)
     n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos])
-    if n.sons[paramsPos] != nil: 
-      if n.sons[paramsPos].sons[0] != nil: 
+    if n.sons[paramsPos].kind != nkEmpty: 
+      if n.sons[paramsPos].sons[0].kind != nkEmpty: 
         addDecl(c, newSym(skUnknown, getIdent("result"), nil))
       n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos])
     n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos])
diff --git a/rod/seminst.nim b/rod/seminst.nim
index 7954d2e8f..f2acdba60 100755
--- a/rod/seminst.nim
+++ b/rod/seminst.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -48,7 +48,9 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
     if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue 
     var s = newSym(skType, q.name, getCurrOwner())
     var t = PType(IdTableGet(pt, q.typ))
-    if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
+    if t == nil: 
+      LocalError(a.info, errCannotInstantiateX, s.name.s)
+      break
     if (t.kind == tyGenericParam): 
       InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
     s.typ = t
@@ -94,13 +96,14 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   result.ast = n
   pushOwner(result)
   openScope(c.tab)
-  if (n.sons[genericParamsPos] == nil): 
+  if (n.sons[genericParamsPos].kind == nkEmpty): 
     InternalError(n.info, "generateInstance")
   n.sons[namePos] = newSymNode(result)
   pushInfoContext(info)
   instantiateGenericParamList(c, n.sons[genericParamsPos], pt)
-  n.sons[genericParamsPos] = nil # semantic checking for the parameters:
-  if n.sons[paramsPos] != nil: 
+  n.sons[genericParamsPos] = ast.emptyNode
+  # semantic checking for the parameters:
+  if n.sons[paramsPos].kind != nkEmpty: 
     semParamList(c, n.sons[ParamsPos], nil, result)
     addParams(c, result.typ.n)
   else: 
@@ -112,7 +115,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     # add it here, so that recursive generic procs are possible:
     GenericCacheAdd(c, fn, result)
     addDecl(c, result)
-    if n.sons[codePos] != nil: 
+    if n.sons[codePos].kind != nkEmpty: 
       c.p = newProcCon(result)
       if result.kind in {skProc, skMethod, skConverter}: 
         addResult(c, result.typ.sons[0], n.info)
@@ -129,11 +132,11 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
 
 proc checkConstructedType(info: TLineInfo, t: PType) = 
   if (tfAcyclic in t.flags) and (skipTypes(t, abstractInst).kind != tyObject): 
-    liMessage(info, errInvalidPragmaX, "acyclic")
-  if computeSize(t) < 0: 
-    liMessage(info, errIllegalRecursionInTypeX, typeToString(t))
-  if (t.kind == tyVar) and (t.sons[0].kind == tyVar): 
-    liMessage(info, errVarVarTypeNotAllowed)
+    LocalError(info, errInvalidPragmaX, "acyclic")
+  elif computeSize(t) < 0: 
+    LocalError(info, errIllegalRecursionInTypeX, typeToString(t))
+  elif (t.kind == tyVar) and (t.sons[0].kind == tyVar): 
+    LocalError(info, errVarVarTypeNotAllowed)
   
 type 
   TReplTypeVars{.final.} = object 
@@ -162,8 +165,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
           result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
   
 proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = 
-  if s == nil: 
-    return nil
+  if s == nil: return nil
   result = PSym(idTableGet(cl.symMap, s))
   if result == nil: 
     result = copySym(s, false)
@@ -176,7 +178,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
 proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil: 
-    liMessage(t.sym.info, errCannotInstantiateX, typeToString(t))
+    GlobalError(t.sym.info, errCannotInstantiateX, typeToString(t))
   elif result.kind == tyGenericParam: 
     InternalError(cl.info, "substitution with generic parameter")
   
@@ -210,7 +212,8 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
     idTablePut(gInstTypes, header, result)
     newbody = ReplaceTypeVarsT(cl, lastSon(body))
     newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
-    addSon(result, newbody)   #writeln(output, ropeToStr(Typetoyaml(newbody)));
+    addSon(result, newbody)   
+    #writeln(output, ropeToStr(Typetoyaml(newbody)));
     checkConstructedType(cl.info, newbody)
   of tyGenericBody: 
     InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody")
@@ -222,7 +225,7 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
         result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
       result.n = ReplaceTypeVarsN(cl, result.n)
       if result.Kind in GenericTypes: 
-        liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
+        LocalError(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
         #writeln(output, ropeToStr(Typetoyaml(result)))
         #checkConstructedType(cl.info, result)
   
diff --git a/rod/semstmts.nim b/rod/semstmts.nim
index 0faf3e5fc..d2e7322c2 100755
--- a/rod/semstmts.nim
+++ b/rod/semstmts.nim
@@ -12,13 +12,12 @@
 proc semExprNoType(c: PContext, n: PNode): PNode =
   result = semExpr(c, n)
   if result.typ != nil and result.typ.kind != tyStmt:
-    liMessage(n.info, errDiscardValue)
+    localError(n.info, errDiscardValue)
 
 proc semWhen(c: PContext, n: PNode): PNode = 
   result = nil
   for i in countup(0, sonsLen(n) - 1): 
     var it = n.sons[i]
-    if it == nil: illFormedAst(n)
     case it.kind
     of nkElifBranch: 
       checkSonsLen(it, 2)
@@ -43,7 +42,6 @@ proc semIf(c: PContext, n: PNode): PNode =
   result = n
   for i in countup(0, sonsLen(n) - 1): 
     var it = n.sons[i]
-    if it == nil: illFormedAst(n)
     case it.kind
     of nkElifBranch: 
       checkSonsLen(it, 2)
@@ -61,12 +59,12 @@ proc semDiscard(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
   n.sons[0] = semExprWithType(c, n.sons[0])
-  if n.sons[0].typ == nil: liMessage(n.info, errInvalidDiscard)
+  if n.sons[0].typ == nil: localError(n.info, errInvalidDiscard)
   
 proc semBreakOrContinue(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     var s: PSym
     case n.sons[0].kind
     of nkIdent: s = lookUp(c, n.sons[0])
@@ -78,19 +76,20 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
       incl(s.flags, sfUsed)
       n.sons[0] = x
     else: 
-      liMessage(n.info, errInvalidControlFlowX, s.name.s)
+      localError(n.info, errInvalidControlFlowX, s.name.s)
   elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0): 
-    liMessage(n.info, errInvalidControlFlowX, renderTree(n, {renderNoComments}))
+    localError(n.info, errInvalidControlFlowX, 
+               renderTree(n, {renderNoComments}))
   
 proc semBlock(c: PContext, n: PNode): PNode = 
   result = n
   Inc(c.p.nestedBlockCounter)
   checkSonsLen(n, 2)
   openScope(c.tab)            # BUGFIX: label is in the scope of block!
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     var labl = newSymS(skLabel, n.sons[0], c)
     addDecl(c, labl)
-    n.sons[0] = newSymNode(labl) # BUGFIX
+    n.sons[0] = newSymNode(labl)
   n.sons[1] = semStmt(c, n.sons[1])
   closeScope(c.tab)
   Dec(c.p.nestedBlockCounter)
@@ -132,7 +131,9 @@ proc semCase(c: PContext, n: PNode): PNode =
     chckCovered = true
   of tyFloat..tyFloat128, tyString: 
     nil
-  else: liMessage(n.info, errSelectorMustBeOfCertainTypes)
+  else: 
+    LocalError(n.info, errSelectorMustBeOfCertainTypes)
+    return
   for i in countup(1, sonsLen(n) - 1): 
     var x = n.sons[i]
     case x.kind
@@ -153,7 +154,7 @@ proc semCase(c: PContext, n: PNode): PNode =
       x.sons[0] = semStmtScope(c, x.sons[0])
     else: illFormedAst(x)
   if chckCovered and (covered != toCover(n.sons[0].typ)): 
-    liMessage(n.info, errNotAllCasesCovered)
+    localError(n.info, errNotAllCasesCovered)
   closeScope(c.tab)
 
 proc propertyWriteAccess(c: PContext, n, a: PNode): PNode = 
@@ -170,7 +171,7 @@ proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
     fixAbstractType(c, result)
     analyseIfAddressTakenInCall(c, result)
   else:
-    liMessage(n.Info, errUndeclaredFieldX, id.s)
+    globalError(n.Info, errUndeclaredFieldX, id.s)
 
 proc semAsgn(c: PContext, n: PNode): PNode = 
   checkSonsLen(n, 2)
@@ -197,7 +198,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
   var le = a.typ
   if skipTypes(le, {tyGenericInst}).kind != tyVar and IsAssignable(a) == arNone: 
     # Direct assignment to a discriminant is allowed!
-    liMessage(a.info, errXCannotBeAssignedTo, renderTree(a, {renderNoComments}))
+    localError(a.info, errXCannotBeAssignedTo, 
+               renderTree(a, {renderNoComments}))
   else: 
     n.sons[1] = fitNode(c, le, n.sons[1])
     fixAbstractType(c, n)
@@ -210,83 +212,84 @@ proc SemReturn(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
   if not (c.p.owner.kind in {skConverter, skMethod, skProc, skMacro}): 
-    liMessage(n.info, errXNotAllowedHere, "\'return\'")
-  if (n.sons[0] != nil): 
+    globalError(n.info, errXNotAllowedHere, "\'return\'")
+  if n.sons[0].kind != nkEmpty: 
     n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
     restype = c.p.owner.typ.sons[0]
-    if (restype != nil): 
+    if restype != nil: 
       a = newNodeI(nkAsgn, n.sons[0].info)
       n.sons[0] = fitNode(c, restype, n.sons[0])
       # optimize away ``return result``, because it would be transformed
       # to ``result = result; return``:
       if (n.sons[0].kind == nkSym) and (sfResult in n.sons[0].sym.flags): 
-        n.sons[0] = nil
+        n.sons[0] = ast.emptyNode
       else: 
         if (c.p.resultSym == nil): InternalError(n.info, "semReturn")
         addSon(a, semExprWithType(c, newSymNode(c.p.resultSym)))
         addSon(a, n.sons[0])
         n.sons[0] = a
     else: 
-      liMessage(n.info, errCannotReturnExpr)
+      localError(n.info, errCannotReturnExpr)
   
 proc SemYield(c: PContext, n: PNode): PNode = 
   result = n
   checkSonsLen(n, 1)
   if (c.p.owner == nil) or (c.p.owner.kind != skIterator): 
-    liMessage(n.info, errYieldNotAllowedHere)
-  if (n.sons[0] != nil): 
+    GlobalError(n.info, errYieldNotAllowedHere)
+  if n.sons[0].kind != nkEmpty: 
     n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
     var restype = c.p.owner.typ.sons[0]
-    if (restype != nil): 
+    if restype != nil: 
       n.sons[0] = fitNode(c, restype, n.sons[0])
       if (n.sons[0].typ == nil): InternalError(n.info, "semYield")
     else: 
-      liMessage(n.info, errCannotReturnExpr)
+      localError(n.info, errCannotReturnExpr)
   
 proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode = 
   result = fitNode(c, typ, n)
-  if (result.kind in {nkHiddenStdConv, nkHiddenSubConv}): 
+  if result.kind in {nkHiddenStdConv, nkHiddenSubConv}: 
     changeType(result.sons[1], typ)
     result = result.sons[1]
   elif not sameType(result.typ, typ): 
     changeType(result, typ)
   
 proc semVar(c: PContext, n: PNode): PNode = 
-  var 
-    length: int
-    a, b, def: PNode
-    typ, tup: PType
-    v: PSym
+  var b: PNode
   result = copyNode(n)
-  for i in countup(0, sonsLen(n) - 1): 
-    a = n.sons[i]
+  for i in countup(0, sonsLen(n)-1): 
+    var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
     if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
     checkMinSonsLen(a, 3)
-    length = sonsLen(a)
-    if a.sons[length - 2] != nil: typ = semTypeNode(c, a.sons[length - 2], nil)
-    else: typ = nil
-    if a.sons[length - 1] != nil: 
-      def = semExprWithType(c, a.sons[length - 1]) 
+    var length = sonsLen(a)
+    var typ: PType
+    if a.sons[length-2].kind != nkEmpty:
+      typ = semTypeNode(c, a.sons[length-2], nil)
+    else: 
+      typ = nil
+    var def: PNode
+    if a.sons[length-1].kind != nkEmpty: 
+      def = semExprWithType(c, a.sons[length-1])
       # BUGFIX: ``fitNode`` is needed here!
       # check type compability between def.typ and typ:
-      if (typ != nil): def = fitNode(c, typ, def)
+      if typ != nil: def = fitNode(c, typ, def)
       else: typ = def.typ
     else: 
-      def = nil
+      def = ast.emptyNode
     if not typeAllowed(typ, skVar): 
-      liMessage(a.info, errXisNoType, typeToString(typ))
-    tup = skipTypes(typ, {tyGenericInst})
+      GlobalError(a.info, errXisNoType, typeToString(typ))
+    var tup = skipTypes(typ, {tyGenericInst})
     if a.kind == nkVarTuple: 
-      if tup.kind != tyTuple: liMessage(a.info, errXExpected, "tuple")
+      if tup.kind != tyTuple: GlobalError(a.info, errXExpected, "tuple")
       if length - 2 != sonsLen(tup): 
-        liMessage(a.info, errWrongNumberOfVariables)
+        GlobalError(a.info, errWrongNumberOfVariables)
       b = newNodeI(nkVarTuple, a.info)
       newSons(b, length)
-      b.sons[length - 2] = nil # no type desc
+      b.sons[length - 2] = ast.emptyNode # no type desc
       b.sons[length - 1] = def
       addSon(result, b)
     for j in countup(0, length - 3): 
+      var v: PSym
       if (c.p.owner.kind == skModule): 
         v = semIdentWithPragma(c, skVar, a.sons[j], {sfStar, sfMinus})
         incl(v.flags, sfGlobal)
@@ -298,7 +301,7 @@ proc semVar(c: PContext, n: PNode): PNode =
         v.typ = typ
         b = newNodeI(nkIdentDefs, a.info)
         addSon(b, newSymNode(v))
-        addSon(b, nil)        # no type description
+        addSon(b, ast.emptyNode)        # no type description
         addSon(b, copyTree(def))
         addSon(result, b)
       else: 
@@ -306,57 +309,53 @@ proc semVar(c: PContext, n: PNode): PNode =
         b.sons[j] = newSymNode(v)
 
 proc semConst(c: PContext, n: PNode): PNode = 
-  var 
-    a, def, b: PNode
-    v: PSym
-    typ: PType
   result = copyNode(n)
   for i in countup(0, sonsLen(n) - 1): 
-    a = n.sons[i]
+    var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
     if (a.kind != nkConstDef): IllFormedAst(a)
     checkSonsLen(a, 3)
+    var v: PSym
     if (c.p.owner.kind == skModule): 
       v = semIdentWithPragma(c, skConst, a.sons[0], {sfStar, sfMinus})
       incl(v.flags, sfGlobal)
     else: 
       v = semIdentWithPragma(c, skConst, a.sons[0], {})
-    if a.sons[1] != nil: typ = semTypeNode(c, a.sons[1], nil)
-    else: typ = nil
-    def = semAndEvalConstExpr(c, a.sons[2]) 
+    var typ: PType = nil
+    if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
+    var def = semAndEvalConstExpr(c, a.sons[2]) 
     # check type compability between def.typ and typ:
     if (typ != nil): 
       def = fitRemoveHiddenConv(c, typ, def)
     else: 
       typ = def.typ
     if not typeAllowed(typ, skConst): 
-      liMessage(a.info, errXisNoType, typeToString(typ))
+      GlobalError(a.info, errXisNoType, typeToString(typ))
     v.typ = typ
     v.ast = def               # no need to copy
     if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
     addInterfaceDecl(c, v)
-    b = newNodeI(nkConstDef, a.info)
+    var b = newNodeI(nkConstDef, a.info)
     addSon(b, newSymNode(v))
-    addSon(b, nil)            # no type description
+    addSon(b, ast.emptyNode)            # no type description
     addSon(b, copyTree(def))
     addSon(result, b)
 
 proc semFor(c: PContext, n: PNode): PNode = 
   var 
-    length: int
     v, countup: PSym
     iter: PType
     countupNode, call: PNode
   result = n
   checkMinSonsLen(n, 3)
-  length = sonsLen(n)
+  var length = sonsLen(n)
   openScope(c.tab)
   if n.sons[length - 2].kind == nkRange: 
     checkSonsLen(n.sons[length - 2], 2) 
     # convert ``in 3..5`` to ``in countup(3, 5)``
     countupNode = newNodeI(nkCall, n.sons[length - 2].info)
     countUp = StrTableGet(magicsys.systemModule.Tab, getIdent("countup"))
-    if (countUp == nil): liMessage(countupNode.info, errSystemNeeds, "countup")
+    if countUp == nil: GlobalError(countupNode.info, errSystemNeeds, "countup")
     newSons(countupNode, 3)
     countupnode.sons[0] = newSymNode(countup)
     countupNode.sons[1] = n.sons[length - 2].sons[0]
@@ -366,16 +365,16 @@ proc semFor(c: PContext, n: PNode): PNode =
   call = n.sons[length - 2]
   if (call.kind != nkCall) or (call.sons[0].kind != nkSym) or
       (call.sons[0].sym.kind != skIterator): 
-    liMessage(n.sons[length - 2].info, errIteratorExpected)
+    GlobalError(n.sons[length - 2].info, errIteratorExpected)
   iter = skipTypes(n.sons[length - 2].typ, {tyGenericInst})
   if iter.kind != tyTuple: 
-    if length != 3: liMessage(n.info, errWrongNumberOfVariables)
+    if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
     v = newSymS(skForVar, n.sons[0], c)
     v.typ = iter
     n.sons[0] = newSymNode(v)
     addDecl(c, v)
   else: 
-    if length - 2 != sonsLen(iter): liMessage(n.info, errWrongNumberOfVariables)
+    if length-2 != sonsLen(iter): GlobalError(n.info, errWrongNumberOfVariables)
     for i in countup(0, length - 3): 
       v = newSymS(skForVar, n.sons[i], c)
       v.typ = iter.sons[i]
@@ -389,11 +388,11 @@ proc semFor(c: PContext, n: PNode): PNode =
 proc semRaise(c: PContext, n: PNode): PNode = 
   result = n
   checkSonsLen(n, 1)
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     n.sons[0] = semExprWithType(c, n.sons[0])
     var typ = n.sons[0].typ
     if (typ.kind != tyRef) or (typ.sons[0].kind != tyObject): 
-      liMessage(n.info, errExprCannotBeRaised)
+      localError(n.info, errExprCannotBeRaised)
   
 proc semTry(c: PContext, n: PNode): PNode = 
   var check: TIntSet
@@ -409,12 +408,12 @@ proc semTry(c: PContext, n: PNode): PNode =
       for j in countup(0, length - 2): 
         var typ = semTypeNode(c, a.sons[j], nil)
         if typ.kind == tyRef: typ = typ.sons[0]
-        if (typ.kind != tyObject): 
-          liMessage(a.sons[j].info, errExprCannotBeRaised)
+        if typ.kind != tyObject: 
+          GlobalError(a.sons[j].info, errExprCannotBeRaised)
         a.sons[j] = newNodeI(nkType, a.sons[j].info)
         a.sons[j].typ = typ
         if IntSetContainsOrIncl(check, typ.id): 
-          liMessage(a.sons[j].info, errExceptionAlreadyHandled)
+          localError(a.sons[j].info, errExceptionAlreadyHandled)
     elif a.kind != nkFinally: 
       illFormedAst(n) 
     # last child of an nkExcept/nkFinally branch is a statement:
@@ -423,16 +422,16 @@ proc semTry(c: PContext, n: PNode): PNode =
 proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = 
   result = copyNode(n)
   if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
-  for i in countup(0, sonsLen(n) - 1): 
+  for i in countup(0, sonsLen(n)-1): 
     var a = n.sons[i]
     if a.kind != nkIdentDefs: illFormedAst(n)
     var L = sonsLen(a)
-    var def = a.sons[L - 1]
+    var def = a.sons[L-1]
     var typ: PType
-    if a.sons[L - 2] != nil: typ = semTypeNode(c, a.sons[L - 2], nil)
-    elif def != nil: typ = newTypeS(tyExpr, c)
+    if a.sons[L-2].kind != nkEmpty: typ = semTypeNode(c, a.sons[L-2], nil)
+    elif def.kind != nkEmpty: typ = newTypeS(tyExpr, c)
     else: typ = nil
-    for j in countup(0, L - 3): 
+    for j in countup(0, L-3): 
       var s: PSym
       if (typ == nil) or (typ.kind == tyTypeDesc): 
         s = newSymS(skType, a.sons[j], c)
@@ -441,7 +440,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
         # not a type param, but an expression
         s = newSymS(skGenericParam, a.sons[j], c)
         s.typ = typ
-      s.ast = def
+      if def.kind != nkEmpty: s.ast = def
       s.typ.sym = s
       if father != nil: addSon(father, s.typ)
       s.position = i
@@ -451,7 +450,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
 proc addGenericParamListToScope(c: PContext, n: PNode) = 
   if n.kind != nkGenericParams: 
     InternalError(n.info, "addGenericParamListToScope")
-  for i in countup(0, sonsLen(n) - 1): 
+  for i in countup(0, sonsLen(n)-1): 
     var a = n.sons[i]
     if a.kind != nkSym: internalError(a.info, "addGenericParamListToScope")
     addDecl(c, a.sym)
@@ -466,7 +465,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
   for i in countup(0, sonsLen(n) - 1): 
     var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
-    if (a.kind != nkTypeDef): IllFormedAst(a)
+    if a.kind != nkTypeDef: IllFormedAst(a)
     checkSonsLen(a, 3)
     if (c.p.owner.kind == skModule): 
       s = semIdentWithPragma(c, skType, a.sons[0], {sfStar, sfMinus})
@@ -488,10 +487,10 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
     checkSonsLen(a, 3)
     if (a.sons[0].kind != nkSym): IllFormedAst(a)
     s = a.sons[0].sym
-    if (s.magic == mNone) and (a.sons[2] == nil): 
-      liMessage(a.info, errImplOfXexpected, s.name.s)
+    if (s.magic == mNone) and (a.sons[2].kind == nkEmpty): 
+      GlobalError(a.info, errImplOfXexpected, s.name.s)
     if s.magic != mNone: processMagicType(c, s)
-    if a.sons[1] != nil: 
+    if a.sons[1].kind != nkEmpty: 
       # We have a generic type declaration here. In generic types,
       # symbol lookup needs to be done here.
       openScope(c.tab)
@@ -508,7 +507,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
       s.typ.sons[sonsLen(s.typ) - 1] = body #debug(s.typ);
       popOwner()
       closeScope(c.tab)
-    elif a.sons[2] != nil: 
+    elif a.sons[2].kind != nkEmpty: 
       # process the type's body:
       pushOwner(s)
       t = semTypeNode(c, a.sons[2], s.typ)
@@ -523,9 +522,8 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
     if (a.sons[0].kind != nkSym): IllFormedAst(a)
     s = a.sons[0].sym         
     # compute the type's size and check for illegal recursions:
-    if a.sons[1] == nil: 
-      if (a.sons[2] != nil) and
-          (a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}): 
+    if a.sons[1].kind == nkEmpty: 
+      if (a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}): 
         # type aliases are hard:
         #MessageOut('for type ' + typeToString(s.typ));
         t = semTypeNode(c, a.sons[2], nil)
@@ -538,21 +536,23 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
   s.typ = semProcTypeNode(c, n, genericParams, nil)
 
 proc addParams(c: PContext, n: PNode) = 
-  for i in countup(1, sonsLen(n) - 1): 
+  for i in countup(1, sonsLen(n)-1): 
     if (n.sons[i].kind != nkSym): InternalError(n.info, "addParams")
     addDecl(c, n.sons[i].sym)
 
 proc semBorrow(c: PContext, n: PNode, s: PSym) = 
   # search for the correct alias:
   var b = SearchForBorrowProc(c, s, c.tab.tos - 2)
-  if b == nil: 
-    liMessage(n.info, errNoSymbolToBorrowFromFound) # store the alias:
-  n.sons[codePos] = newSymNode(b)
+  if b != nil: 
+    # store the alias:
+    n.sons[codePos] = newSymNode(b)
+  else:
+    LocalError(n.info, errNoSymbolToBorrowFromFound) 
 
 proc sideEffectsCheck(c: PContext, s: PSym) = 
   if {sfNoSideEffect, sfSideEffect} * s.flags ==
       {sfNoSideEffect, sfSideEffect}: 
-    liMessage(s.info, errXhasSideEffects, s.name.s)
+    LocalError(s.info, errXhasSideEffects, s.name.s)
   
 proc addResult(c: PContext, t: PType, info: TLineInfo) = 
   if t != nil: 
@@ -577,26 +577,27 @@ proc semLambda(c: PContext, n: PNode): PNode =
   n.sons[namePos] = newSymNode(s)
   pushOwner(s)
   openScope(c.tab)
-  if (n.sons[genericParamsPos] != nil): 
+  if (n.sons[genericParamsPos].kind != nkEmpty): 
     illFormedAst(n)           # process parameters:
-  if n.sons[paramsPos] != nil: 
+  if n.sons[paramsPos].kind != nkEmpty: 
     semParamList(c, n.sons[ParamsPos], nil, s)
     addParams(c, s.typ.n)
   else: 
     s.typ = newTypeS(tyProc, c)
     addSon(s.typ, nil)
   s.typ.callConv = ccClosure
-  if n.sons[pragmasPos] != nil: pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
+  if n.sons[pragmasPos].kind != nkEmpty:
+    pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
   s.options = gOptions
-  if n.sons[codePos] != nil: 
+  if n.sons[codePos].kind != nkEmpty: 
     if sfImportc in s.flags: 
-      liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
+      LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
     c.p = newProcCon(s)
     addResult(c, s.typ.sons[0], n.info)
     n.sons[codePos] = semStmtScope(c, n.sons[codePos])
     addResultNode(c, n)
   else: 
-    liMessage(n.info, errImplOfXexpected, s.name.s)
+    LocalError(n.info, errImplOfXexpected, s.name.s)
   closeScope(c.tab)           # close scope for parameters
   popOwner()
   c.p = oldP                  # restore
@@ -620,16 +621,16 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   s.ast = n
   pushOwner(s)
   openScope(c.tab)
-  if n.sons[genericParamsPos] != nil: 
+  if n.sons[genericParamsPos].kind != nkEmpty: 
     n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
     gp = n.sons[genericParamsPos]
   else: 
     gp = newNodeI(nkGenericParams, n.info)
   # process parameters:
-  if n.sons[paramsPos] != nil: 
+  if n.sons[paramsPos].kind != nkEmpty:
     semParamList(c, n.sons[ParamsPos], gp, s)
     if sonsLen(gp) > 0: 
-      if n.sons[genericParamsPos] == nil:
+      if n.sons[genericParamsPos].kind == nkEmpty:
         # we have a list of implicit type parameters:
         n.sons[genericParamsPos] = gp
         # check for semantics again:
@@ -651,16 +652,17 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
       addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2)
     else: 
       addInterfaceDeclAt(c, s, c.tab.tos - 2)
-    if n.sons[pragmasPos] != nil: pragma(c, s, n.sons[pragmasPos], validPragmas)
+    if n.sons[pragmasPos].kind != nkEmpty:
+      pragma(c, s, n.sons[pragmasPos], validPragmas)
   else: 
-    if n.sons[pragmasPos] != nil: 
-      liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
+    if n.sons[pragmasPos].kind != nkEmpty: 
+      LocalError(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
     if sfForward notin proto.flags: 
-      liMessage(n.info, errAttemptToRedefineX, proto.name.s)
+      LocalError(n.info, errAttemptToRedefineX, proto.name.s)
     excl(proto.flags, sfForward)
     closeScope(c.tab)         # close scope with wrong parameter symbols
     openScope(c.tab)          # open scope for old (correct) parameter symbols
-    if proto.ast.sons[genericParamsPos] != nil: 
+    if proto.ast.sons[genericParamsPos].kind != nkEmpty: 
       addGenericParamListToScope(c, proto.ast.sons[genericParamsPos])
     addParams(c, proto.typ.n)
     proto.info = s.info       # more accurate line information
@@ -674,27 +676,27 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     popOwner()
     pushOwner(s)
   s.options = gOptions
-  if n.sons[codePos] != nil: 
-    # for DLL generation, it is annoying to check for sfImportc!
+  if n.sons[codePos].kind != nkEmpty: 
+    # for DLL generation it is annoying to check for sfImportc!
     if sfBorrow in s.flags: 
-      liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
-    if (n.sons[genericParamsPos] == nil): 
+      LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
+    if n.sons[genericParamsPos].kind == nkEmpty: 
       c.p = newProcCon(s)
       if (s.typ.sons[0] != nil) and (kind != skIterator): 
         addResult(c, s.typ.sons[0], n.info)
       if sfImportc notin s.flags: 
         # no semantic checking for importc:
         n.sons[codePos] = semStmtScope(c, n.sons[codePos])
-      if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
+      if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n)
     else: 
-      if (s.typ.sons[0] != nil) and (kind != skIterator): 
+      if s.typ.sons[0] != nil and kind != skIterator: 
         addDecl(c, newSym(skUnknown, getIdent("result"), nil))
       n.sons[codePos] = semGenericStmtScope(c, n.sons[codePos])
     if sfImportc in s.flags: 
       # so we just ignore the body after semantic checking for importc:
-      n.sons[codePos] = nil
+      n.sons[codePos] = ast.emptyNode
   else: 
-    if proto != nil: liMessage(n.info, errImplOfXexpected, proto.name.s)
+    if proto != nil: LocalError(n.info, errImplOfXexpected, proto.name.s)
     if {sfImportc, sfBorrow} * s.flags == {}: incl(s.flags, sfForward)
     elif sfBorrow in s.flags: semBorrow(c, n, s)
   sideEffectsCheck(c, s)
@@ -706,14 +708,16 @@ proc semIterator(c: PContext, n: PNode): PNode =
   result = semProcAux(c, n, skIterator, iteratorPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
-  if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "iterator")
-  if n.sons[codePos] == nil: liMessage(n.info, errImplOfXexpected, s.name.s)
+  if t.sons[0] == nil: 
+    LocalError(n.info, errXNeedsReturnType, "iterator")
+  if n.sons[codePos].kind == nkEmpty: 
+    LocalError(n.info, errImplOfXexpected, s.name.s)
   
 proc semProc(c: PContext, n: PNode): PNode = 
   result = semProcAux(c, n, skProc, procPragmas)
 
 proc semMethod(c: PContext, n: PNode): PNode = 
-  if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "method")
+  if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "method")
   result = semProcAux(c, n, skMethod, methodPragmas)
   
   var s = result.sons[namePos].sym
@@ -728,30 +732,31 @@ proc semMethod(c: PContext, n: PNode): PNode =
   # XXX this not really correct way to do it: Perhaps it should be done after
   # generic instantiation. Well it's good enough for now: 
   if not hasObjParam:
-    liMessage(n.info, errXNeedsParamObjectType, "method")
+    LocalError(n.info, errXNeedsParamObjectType, "method")
 
 proc semConverterDef(c: PContext, n: PNode): PNode = 
-  if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "converter")
+  if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "converter")
   checkSonsLen(n, codePos + 1)
-  if n.sons[genericParamsPos] != nil: 
-    liMessage(n.info, errNoGenericParamsAllowedForX, "converter")
+  if n.sons[genericParamsPos].kind != nkEmpty: 
+    LocalError(n.info, errNoGenericParamsAllowedForX, "converter")
   result = semProcAux(c, n, skConverter, converterPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
-  if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "converter")
-  if sonsLen(t) != 2: liMessage(n.info, errXRequiresOneArgument, "converter")
+  if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "converter")
+  if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "converter")
   addConverter(c, s)
 
 proc semMacroDef(c: PContext, n: PNode): PNode = 
   checkSonsLen(n, codePos + 1)
-  if n.sons[genericParamsPos] != nil: 
-    liMessage(n.info, errNoGenericParamsAllowedForX, "macro")
+  if n.sons[genericParamsPos].kind != nkEmpty: 
+    LocalError(n.info, errNoGenericParamsAllowedForX, "macro")
   result = semProcAux(c, n, skMacro, macroPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
-  if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "macro")
-  if sonsLen(t) != 2: liMessage(n.info, errXRequiresOneArgument, "macro")
-  if n.sons[codePos] == nil: liMessage(n.info, errImplOfXexpected, s.name.s)
+  if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
+  if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "macro")
+  if n.sons[codePos].kind == nkEmpty:
+    LocalError(n.info, errImplOfXexpected, s.name.s)
   
 proc evalInclude(c: PContext, n: PNode): PNode = 
   result = newNodeI(nkStmtList, n.info)
@@ -760,7 +765,7 @@ proc evalInclude(c: PContext, n: PNode): PNode =
     var f = getModuleFile(n.sons[i])
     var fileIndex = includeFilename(f)
     if IntSetContainsOrIncl(c.includedFiles, fileIndex): 
-      liMessage(n.info, errRecursiveDependencyX, f)
+      GlobalError(n.info, errRecursiveDependencyX, f)
     addSon(result, semStmt(c, gIncludeFile(f)))
     IntSetExcl(c.includedFiles, fileIndex)
 
@@ -771,7 +776,6 @@ proc SemStmt(c: PContext, n: PNode): PNode =
   const                       # must be last statements in a block:
     LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
   result = n
-  if n == nil: return 
   if nfSem in n.flags: return 
   case n.kind
   of nkAsgn: result = semAsgn(c, n)
@@ -783,12 +787,11 @@ proc SemStmt(c: PContext, n: PNode): PNode =
     var length = sonsLen(n)
     for i in countup(0, length - 1): 
       n.sons[i] = semStmt(c, n.sons[i])
-      if (n.sons[i].kind in LastBlockStmts): 
+      if n.sons[i].kind in LastBlockStmts: 
         for j in countup(i + 1, length - 1): 
           case n.sons[j].kind
-          of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: 
-            nil
-          else: liMessage(n.sons[j].info, errStmtInvalidAfterReturn)
+          of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil
+          else: localError(n.sons[j].info, errStmtInvalidAfterReturn)
   of nkRaiseStmt: result = semRaise(c, n)
   of nkVarSection: result = semVar(c, n)
   of nkConstSection: result = semConst(c, n)
@@ -812,15 +815,15 @@ proc SemStmt(c: PContext, n: PNode): PNode =
   of nkMacroDef: result = semMacroDef(c, n)
   of nkTemplateDef: result = semTemplateDef(c, n)
   of nkImportStmt: 
-    if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "import")
+    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
     result = evalImport(c, n)
   of nkFromStmt: 
-    if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "from")
+    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
     result = evalFrom(c, n)
   of nkIncludeStmt: 
-    if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "include")
+    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
     result = evalInclude(c, n)
-  else: liMessage(n.info, errStmtExpected)
+  else: LocalError(n.info, errStmtExpected)
   if result == nil: InternalError(n.info, "SemStmt: result = nil")
   incl(result.flags, nfSem)
 
diff --git a/rod/semtempl.nim b/rod/semtempl.nim
index cb4288a56..1fbcbe227 100755
--- a/rod/semtempl.nim
+++ b/rod/semtempl.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -9,8 +9,6 @@
 
 proc isExpr(n: PNode): bool = 
   # returns true if ``n`` looks like an expression
-  if n == nil: 
-    return false
   case n.kind
   of nkIdent..nkNilLit: 
     result = true
@@ -23,8 +21,6 @@ proc isExpr(n: PNode): bool =
   
 proc isTypeDesc(n: PNode): bool = 
   # returns true if ``n`` looks like a type desc
-  if n == nil: 
-    return false
   case n.kind
   of nkIdent, nkSym, nkType: 
     result = true
@@ -38,12 +34,9 @@ proc isTypeDesc(n: PNode): bool =
   else: result = false
   
 proc evalTemplateAux(c: PContext, templ, actual: PNode, sym: PSym): PNode = 
-  var p: PSym
-  if templ == nil: 
-    return nil
   case templ.kind
   of nkSym: 
-    p = templ.sym
+    var p = templ.sym
     if (p.kind == skParam) and (p.owner.id == sym.id): 
       result = copyTree(actual.sons[p.position])
     else: 
@@ -63,32 +56,38 @@ proc evalTemplateArgs(c: PContext, n: PNode, s: PSym): PNode =
   var 
     f, a: int
     arg: PNode
-  f = sonsLen(s.typ) # if the template has zero arguments, it can be called without ``()``
-                     # `n` is then a nkSym or something similar
+  f = sonsLen(s.typ) 
+  # if the template has zero arguments, it can be called without ``()``
+  # `n` is then a nkSym or something similar
   case n.kind
   of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: 
     a = sonsLen(n)
   else: a = 0
-  if a > f: liMessage(n.info, errWrongNumberOfArguments)
+  if a > f: LocalError(n.info, errWrongNumberOfArguments)
   result = copyNode(n)
   for i in countup(1, f - 1): 
     if i < a: arg = n.sons[i]
     else: arg = copyTree(s.typ.n.sons[i].sym.ast)
-    if arg == nil: liMessage(n.info, errWrongNumberOfArguments)
-    if not (s.typ.sons[i].kind in {tyTypeDesc, tyStmt, tyExpr}): 
+    if arg == nil or arg.kind == nkEmpty: 
+      LocalError(n.info, errWrongNumberOfArguments)
+    elif not (s.typ.sons[i].kind in {tyTypeDesc, tyStmt, tyExpr}): 
       # concrete type means semantic checking for argument:
+      # XXX This is horrible! Better make semantic checking use some kind
+      # of fixpoint iteration ...
       arg = fitNode(c, s.typ.sons[i], semExprWithType(c, arg))
     addSon(result, arg)
 
 proc evalTemplate(c: PContext, n: PNode, sym: PSym): PNode = 
   var args: PNode
   inc(evalTemplateCounter)
-  if evalTemplateCounter > 100: 
-    liMessage(n.info, errTemplateInstantiationTooNested) 
-  # replace each param by the corresponding node:
-  args = evalTemplateArgs(c, n, sym)
-  result = evalTemplateAux(c, sym.ast.sons[codePos], args, sym)
-  dec(evalTemplateCounter)
+  if evalTemplateCounter <= 100: 
+    # replace each param by the corresponding node:
+    args = evalTemplateArgs(c, n, sym)
+    result = evalTemplateAux(c, sym.ast.sons[codePos], args, sym)
+    dec(evalTemplateCounter)
+  else:
+    GlobalError(n.info, errTemplateInstantiationTooNested)
+    result = n
 
 proc symChoice(c: PContext, n: PNode, s: PSym): PNode = 
   var 
@@ -116,8 +115,6 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
 proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool, 
                            toBind: var TIntSet): PNode = 
   var s: PSym
-  if n == nil: 
-    return nil
   case n.kind
   of nkIdent: 
     if not withinBind and not IntSetContains(toBind, n.ident.id): 
@@ -130,7 +127,7 @@ proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
     else: 
       IntSetIncl(toBind, n.ident.id)
       result = symChoice(c, n, lookup(c, n))
-  of nkSym..nkNilLit:         # atom
+  of nkEmpty, nkSym..nkNilLit:         # atom
     result = n
   of nkBind: 
     result = resolveTemplateParams(c, n.sons[0], true, toBind)
@@ -155,7 +152,8 @@ proc transformToExpr(n: PNode): PNode =
     if realStmt >= 0: result = transformToExpr(n.sons[realStmt])
     else: n.kind = nkStmtListExpr
   of nkBlockStmt: 
-    n.kind = nkBlockExpr      #nkIfStmt: n.kind := nkIfExpr; // this is not correct!
+    n.kind = nkBlockExpr      
+    #nkIfStmt: n.kind := nkIfExpr; // this is not correct!
   else: 
     nil
 
@@ -173,11 +171,12 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   pushOwner(s)
   openScope(c.tab)
   n.sons[namePos] = newSymNode(s) # check that no pragmas exist:
-  if n.sons[pragmasPos] != nil: 
-    liMessage(n.info, errNoPragmasAllowedForX, "template") # check that no generic parameters exist:
-  if n.sons[genericParamsPos] != nil: 
-    liMessage(n.info, errNoGenericParamsAllowedForX, "template")
-  if (n.sons[paramsPos] == nil): 
+  if n.sons[pragmasPos].kind != nkEmpty: 
+    LocalError(n.info, errNoPragmasAllowedForX, "template") 
+  # check that no generic parameters exist:
+  if n.sons[genericParamsPos].kind != nkEmpty: 
+    LocalError(n.info, errNoGenericParamsAllowedForX, "template")
+  if n.sons[paramsPos].kind == nkEmpty: 
     # use ``stmt`` as implicit result type
     s.typ = newTypeS(tyProc, c)
     s.typ.n = newNodeI(nkFormalParams, n.info)
@@ -185,7 +184,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
     addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0]))
   else: 
     semParamList(c, n.sons[ParamsPos], nil, s)
-    if n.sons[paramsPos].sons[0] == nil: 
+    if n.sons[paramsPos].sons[0].kind == nkEmpty: 
       # use ``stmt`` as implicit result type
       s.typ.sons[0] = newTypeS(tyStmt, c)
       s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
@@ -193,12 +192,13 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   IntSetInit(toBind)
   n.sons[codePos] = resolveTemplateParams(c, n.sons[codePos], false, toBind)
   if not (s.typ.sons[0].kind in {tyStmt, tyTypeDesc}): 
-    n.sons[codePos] = transformToExpr(n.sons[codePos]) # only parameters are resolved, no type checking is performed
+    n.sons[codePos] = transformToExpr(n.sons[codePos]) 
+    # only parameters are resolved, no type checking is performed
   closeScope(c.tab)
   popOwner()
   s.ast = n
   result = n
-  if n.sons[codePos] == nil: 
-    liMessage(n.info, errImplOfXexpected, s.name.s) # add identifier of template as a last step to not allow
-                                                    # recursive templates
+  if n.sons[codePos].kind == nkEmpty: 
+    LocalError(n.info, errImplOfXexpected, s.name.s)
+  # add identifier of template as a last step to not allow recursive templates:
   addInterfaceDecl(c, s)
diff --git a/rod/semtypes.nim b/rod/semtypes.nim
index 8585c70a4..08c64384e 100755
--- a/rod/semtypes.nim
+++ b/rod/semtypes.nim
@@ -30,10 +30,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
   result = newOrPrevType(tyEnum, prev, c)
   result.n = newNodeI(nkEnumTy, n.info)
   checkMinSonsLen(n, 1)
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     base = semTypeNode(c, n.sons[0].sons[0], nil)
     if base.kind != tyEnum: 
-      liMessage(n.sons[0].info, errInheritanceOnlyWithEnums)
+      localError(n.sons[0].info, errInheritanceOnlyWithEnums)
     counter = lastOrd(base) + 1
   addSon(result, base)
   for i in countup(1, sonsLen(n) - 1): 
@@ -44,10 +44,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       var strVal: PNode = nil
       case skipTypes(v.typ, abstractInst).kind 
       of tyTuple: 
-        if sonsLen(v) != 2: liMessage(v.info, errWrongNumberOfVariables)
+        if sonsLen(v) != 2: GlobalError(v.info, errWrongNumberOfVariables)
         strVal = v.sons[1] # second tuple part is the string value
         if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}:
-          liMessage(strVal.info, errStringLiteralExpected)
+          GlobalError(strVal.info, errStringLiteralExpected)
         x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
       of tyString, tyCstring:
         strVal = v
@@ -57,7 +57,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       if i != 1: 
         if (x != counter): incl(result.flags, tfEnumHasWholes)
         if x < counter: 
-          liMessage(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
+          GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
       e.ast = strVal # might be nil
       counter = x
     of nkSym: 
@@ -82,10 +82,10 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
     addSon(result, base)
     if base.kind == tyGenericInst: base = lastSon(base)
     if base.kind != tyGenericParam: 
-      if not isOrdinalType(base): liMessage(n.info, errOrdinalTypeExpected)
-      if lengthOrd(base) > MaxSetElements: liMessage(n.info, errSetTooBig)
+      if not isOrdinalType(base): GlobalError(n.info, errOrdinalTypeExpected)
+      if lengthOrd(base) > MaxSetElements: GlobalError(n.info, errSetTooBig)
   else: 
-    liMessage(n.info, errXExpectsOneTypeParam, "set")
+    GlobalError(n.info, errXExpectsOneTypeParam, "set")
   
 proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, 
                   prev: PType): PType = 
@@ -94,7 +94,7 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
     var base = semTypeNode(c, n.sons[1], nil)
     addSon(result, base)
   else: 
-    liMessage(n.info, errXExpectsOneTypeParam, kindStr)
+    GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
   
 proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, 
                prev: PType): PType = 
@@ -103,38 +103,38 @@ proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
     var base = semTypeNode(c, n.sons[0], nil)
     addSon(result, base)
   else: 
-    liMessage(n.info, errXExpectsOneTypeParam, kindStr)
+    GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
   
 proc semVarType(c: PContext, n: PNode, prev: PType): PType = 
   result = newOrPrevType(tyVar, prev, c)
   if sonsLen(n) == 1: 
     var base = semTypeNode(c, n.sons[0], nil)
-    if base.kind == tyVar: liMessage(n.info, errVarVarTypeNotAllowed)
+    if base.kind == tyVar: GlobalError(n.info, errVarVarTypeNotAllowed)
     addSon(result, base)
   else: 
-    liMessage(n.info, errXExpectsOneTypeParam, "var")
+    GlobalError(n.info, errXExpectsOneTypeParam, "var")
   
 proc semDistinct(c: PContext, n: PNode, prev: PType): PType = 
   result = newOrPrevType(tyDistinct, prev, c)
   if sonsLen(n) == 1: addSon(result, semTypeNode(c, n.sons[0], nil))
-  else: liMessage(n.info, errXExpectsOneTypeParam, "distinct")
+  else: GlobalError(n.info, errXExpectsOneTypeParam, "distinct")
   
 proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = 
   if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
   checkSonsLen(n, 2)
   result = newOrPrevType(tyRange, prev, c)
   result.n = newNodeI(nkRange, n.info)
-  if (n.sons[0] == nil) or (n.sons[1] == nil): 
-    liMessage(n.Info, errRangeIsEmpty)
+  if (n.sons[0].kind == nkEmpty) or (n.sons[1].kind == nkEmpty): 
+    GlobalError(n.Info, errRangeIsEmpty)
   var a = semConstExpr(c, n.sons[0])
   var b = semConstExpr(c, n.sons[1])
-  if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch)
+  if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch)
   if not (a.typ.kind in
       {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): 
-    liMessage(n.info, errOrdinalTypeExpected)
+    GlobalError(n.info, errOrdinalTypeExpected)
   if enumHasWholes(a.typ): 
-    liMessage(n.info, errEnumXHasHoles, a.typ.sym.name.s)
-  if not leValue(a, b): liMessage(n.Info, errRangeIsEmpty)
+    GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
+  if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty)
   addSon(result.n, a)
   addSon(result.n, b)
   addSon(result, b.typ)
@@ -143,9 +143,9 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
   result = nil
   if sonsLen(n) == 2: 
     if n.sons[1].kind == nkRange: result = semRangeAux(c, n.sons[1], prev)
-    else: liMessage(n.sons[0].info, errRangeExpected)
+    else: GlobalError(n.sons[0].info, errRangeExpected)
   else: 
-    liMessage(n.info, errXExpectsOneTypeParam, "range")
+    GlobalError(n.info, errXExpectsOneTypeParam, "range")
   
 proc semArray(c: PContext, n: PNode, prev: PType): PType = 
   var indx, base: PType
@@ -158,13 +158,13 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
     if indx.kind == tyGenericInst: indx = lastSon(indx)
     if indx.kind != tyGenericParam: 
       if not isOrdinalType(indx): 
-        liMessage(n.sons[1].info, errOrdinalTypeExpected)
+        GlobalError(n.sons[1].info, errOrdinalTypeExpected)
       if enumHasWholes(indx): 
-        liMessage(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
+        GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
     base = semTypeNode(c, n.sons[2], nil)
     addSon(result, base)
   else: 
-    liMessage(n.info, errArrayExpectsTwoTypeParams)
+    GlobalError(n.info, errArrayExpectsTwoTypeParams)
   
 proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = 
   result = newOrPrevType(tyOrdinal, prev, c)
@@ -172,46 +172,44 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
     var base = semTypeNode(c, n.sons[1], nil)
     if base.kind != tyGenericParam: 
       if not isOrdinalType(base): 
-        liMessage(n.sons[1].info, errOrdinalTypeExpected)
+        GlobalError(n.sons[1].info, errOrdinalTypeExpected)
     addSon(result, base)
   else: 
-    liMessage(n.info, errXExpectsOneTypeParam, "ordinal")
+    GlobalError(n.info, errXExpectsOneTypeParam, "ordinal")
   
 proc semTypeIdent(c: PContext, n: PNode): PSym = 
   result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
   if (result != nil): 
     markUsed(n, result)
-    if result.kind != skType: liMessage(n.info, errTypeExpected)
+    if result.kind != skType: GlobalError(n.info, errTypeExpected)
   else: 
-    liMessage(n.info, errIdentifierExpected)
+    GlobalError(n.info, errIdentifierExpected)
   
 proc semTuple(c: PContext, n: PNode, prev: PType): PType = 
   var 
-    length, counter: int
     typ: PType
     check: TIntSet
-    a: PNode
-    field: PSym
   result = newOrPrevType(tyTuple, prev, c)
   result.n = newNodeI(nkRecList, n.info)
   IntSetInit(check)
-  counter = 0
+  var counter = 0
   for i in countup(0, sonsLen(n) - 1): 
-    a = n.sons[i]
+    var a = n.sons[i]
     if (a.kind != nkIdentDefs): IllFormedAst(a)
     checkMinSonsLen(a, 3)
-    length = sonsLen(a)
-    if a.sons[length - 2] != nil: typ = semTypeNode(c, a.sons[length - 2], nil)
-    else: liMessage(a.info, errTypeExpected)
-    if a.sons[length - 1] != nil: 
-      liMessage(a.sons[length - 1].info, errInitHereNotAllowed)
+    var length = sonsLen(a)
+    if a.sons[length - 2].kind != nkEmpty: 
+      typ = semTypeNode(c, a.sons[length - 2], nil)
+    else: GlobalError(a.info, errTypeExpected)
+    if a.sons[length - 1].kind != nkEmpty: 
+      GlobalError(a.sons[length - 1].info, errInitHereNotAllowed)
     for j in countup(0, length - 3): 
-      field = newSymS(skField, a.sons[j], c)
+      var field = newSymS(skField, a.sons[j], c)
       field.typ = typ
       field.position = counter
       inc(counter)
       if IntSetContainsOrIncl(check, field.name.id): 
-        liMessage(a.sons[j].info, errAttemptToRedefine, field.name.s)
+        GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
       addSon(result.n, newSymNode(field))
       addSon(result, typ)
 
@@ -220,10 +218,11 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     elem: PType
     isConcrete: bool
   if (s.typ == nil) or (s.typ.kind != tyGenericBody): 
-    liMessage(n.info, errCannotInstantiateX, s.name.s)
+    GlobalError(n.info, errCannotInstantiateX, s.name.s)
   result = newOrPrevType(tyGenericInvokation, prev, c)
   if (s.typ.containerID == 0): InternalError(n.info, "semtypes.semGeneric")
-  if sonsLen(n) != sonsLen(s.typ): liMessage(n.info, errWrongNumberOfArguments)
+  if sonsLen(n) != sonsLen(s.typ): 
+    GlobalError(n.info, errWrongNumberOfArguments)
   addSon(result, s.typ)
   isConcrete = true           # iterate over arguments:
   for i in countup(1, sonsLen(n) - 1): 
@@ -231,7 +230,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     if elem.kind == tyGenericParam: isConcrete = false
     addSon(result, elem)
   if isConcrete: 
-    if s.ast == nil: liMessage(n.info, errCannotInstantiateX, s.name.s)
+    if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s)
     result = instGenericContainer(c, n, result)
 
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, 
@@ -246,7 +245,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
       elif (sfMinus in allowed) and (v.id == ord(wMinus)): 
         incl(result.flags, sfMinus)
       else: 
-        liMessage(n.sons[0].info, errInvalidVisibilityX, v.s)
+        GlobalError(n.sons[0].info, errInvalidVisibilityX, v.s)
     else: 
       illFormedAst(n)
   else: 
@@ -271,8 +270,7 @@ proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) =
   for i in countup(1, branchIndex - 1): 
     for j in countup(0, sonsLen(t.sons[i]) - 2): 
       if overlap(t.sons[i].sons[j], ex): 
-        #MessageOut(renderTree(t));
-        liMessage(ex.info, errDuplicateCaseLabel)
+        LocalError(ex.info, errDuplicateCaseLabel)
   
 proc semBranchExpr(c: PContext, t: PNode, ex: var PNode) = 
   ex = semConstExpr(c, ex)
@@ -290,7 +288,7 @@ proc SemCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
       semBranchExpr(c, t, b.sons[1])
       if emptyRange(b.sons[0], b.sons[1]): 
         #MessageOut(renderTree(t));
-        liMessage(b.info, errRangeIsEmpty)
+        GlobalError(b.info, errRangeIsEmpty)
       covered = covered + getOrdValue(b.sons[1]) - getOrdValue(b.sons[0]) + 1
     else: 
       semBranchExpr(c, t, branch.sons[i]) # NOT: `b`, because of var-param!
@@ -314,11 +312,11 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
   incl(a.sons[0].sym.flags, sfDiscriminant)
   covered = 0
   typ = skipTypes(a.sons[0].Typ, abstractVar)
-  if not isOrdinalType(typ): liMessage(n.info, errSelectorMustBeOrdinal)
+  if not isOrdinalType(typ): GlobalError(n.info, errSelectorMustBeOrdinal)
   if firstOrd(typ) < 0: 
-    liMessage(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
+    GlobalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
   if lengthOrd(typ) > 0x00007FFF: 
-    liMessage(n.info, errLenXinvalid, a.sons[0].sym.name.s)
+    GlobalError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
   chckCovered = true
   for i in countup(1, sonsLen(n) - 1): 
     b = copyTree(n.sons[i])
@@ -334,7 +332,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
     addSon(a, b)
   if chckCovered and (covered != lengthOrd(a.sons[0].typ)): 
-    liMessage(a.info, errNotAllCasesCovered)
+    localError(a.info, errNotAllCasesCovered)
   addSon(father, a)
 
 proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int, 
@@ -370,8 +368,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info))
   of nkRecList: 
     # attempt to keep the nesting at a sane level:
-    if father.kind == nkRecList: a = father
-    else: a = copyNode(n)
+    var a = if father.kind == nkRecList: father else: copyNode(n)
     for i in countup(0, sonsLen(n) - 1): 
       semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
     if a != father: addSon(father, a)
@@ -381,11 +378,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     if (father.kind != nkRecList) and (length >= 4): 
       a = newNodeI(nkRecList, n.info)
     else: 
-      a = nil
-    if n.sons[length - 1] != nil: 
-      liMessage(n.sons[length - 1].info, errInitHereNotAllowed)
-    if n.sons[length - 2] == nil: liMessage(n.info, errTypeExpected)
-    typ = semTypeNode(c, n.sons[length - 2], nil)
+      a = ast.emptyNode
+    if n.sons[length - 1].kind != nkEmpty: 
+      localError(n.sons[length - 1].info, errInitHereNotAllowed)
+    if n.sons[length - 2].kind == nkEmpty: 
+      GlobalError(n.info, errTypeExpected)
+    typ = semTypeNode(c, n.sons[length-2], nil)
     for i in countup(0, sonsLen(n) - 3): 
       f = semIdentWithPragma(c, skField, n.sons[i], {sfStar, sfMinus})
       f.typ = typ
@@ -396,10 +394,11 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
         f.flags = f.flags + ({sfImportc, sfExportc} * rectype.flags)
       inc(pos)
       if IntSetContainsOrIncl(check, f.name.id): 
-        liMessage(n.sons[i].info, errAttemptToRedefine, f.name.s)
-      if a == nil: addSon(father, newSymNode(f))
+        localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
+      if a.kind == nkEmpty: addSon(father, newSymNode(f))
       else: addSon(a, newSymNode(f))
-    if a != nil: addSon(father, a)
+    if a.kind != nkEmpty: addSon(father, a)
+  of nkEmpty: nil
   else: illFormedAst(n)
   
 proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int, 
@@ -435,11 +434,11 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
   IntSetInit(check)
   pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
   checkSonsLen(n, 3)
-  if n.sons[1] != nil: 
+  if n.sons[1].kind != nkEmpty: 
     base = semTypeNode(c, n.sons[1].sons[0], nil)
     if base.kind == tyObject: addInheritedFields(c, check, pos, base)
-    else: liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
-  else: 
+    else: localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
+  else:
     base = nil
   if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode")
   result = newOrPrevType(tyObject, prev, c)
@@ -447,7 +446,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
   result.n = newNodeI(nkRecList, n.info)
   semRecordNodeAux(c, n.sons[2], check, pos, result.n, result.sym)
   if (base != nil) and (tfFinal in base.flags): 
-    liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
+    localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
   
 proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode, 
                               cl: var TIntSet): PType = 
@@ -509,11 +508,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
     if a.kind != nkIdentDefs: IllFormedAst(a)
     checkMinSonsLen(a, 3)
     var length = sonsLen(a)
-    if a.sons[length - 2] != nil: 
+    if a.sons[length - 2].kind != nkEmpty: 
       typ = paramType(c, a.sons[length - 2], genericParams, cl)
     else: 
       typ = nil
-    if a.sons[length - 1] != nil: 
+    if a.sons[length - 1].kind != nkEmpty: 
       def = semExprWithType(c, a.sons[length - 1]) 
       # check type compability between def.typ and typ:
       if typ != nil: 
@@ -523,18 +522,18 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
       else: 
         typ = def.typ
     else: 
-      def = nil
+      def = ast.emptyNode
     for j in countup(0, length - 3): 
       var arg = newSymS(skParam, a.sons[j], c)
       arg.typ = typ
       arg.position = counter
       inc(counter)
-      arg.ast = copyTree(def)
+      if def.kind != nkEmpty: arg.ast = copyTree(def)
       if IntSetContainsOrIncl(check, arg.name.id): 
-        liMessage(a.sons[j].info, errAttemptToRedefine, arg.name.s)
+        LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
       addSon(result.n, newSymNode(arg))
       addSon(result, typ)
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     result.sons[0] = paramType(c, n.sons[0], genericParams, cl)
     res.typ = result.sons[0]
 
@@ -554,7 +553,7 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
   Inc(c.p.nestedBlockCounter)
   checkSonsLen(n, 2)
   openScope(c.tab)
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     addDecl(c, newSymS(skLabel, n.sons[0], c))
   result = semStmtListType(c, n.sons[1], prev)
   n.sons[1].typ = result
@@ -567,13 +566,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     s: PSym
     t: PType
   result = nil
-  if n == nil: return 
   case n.kind
+  of nkEmpty: nil
   of nkTypeOfExpr: 
     result = semExprWithType(c, n, {efAllowType}).typ
   of nkPar: 
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
-    else: liMessage(n.info, errTypeExpected)
+    else: GlobalError(n.info, errTypeExpected)
   of nkBracketExpr: 
     checkMinSonsLen(n, 2)
     s = semTypeIdent(c, n.sons[0])
@@ -587,7 +586,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     else: result = semGeneric(c, n, s, prev)
   of nkIdent, nkDotExpr, nkAccQuoted: 
     s = semTypeIdent(c, n)
-    if s.typ == nil: liMessage(n.info, errTypeExpected)
+    if s.typ == nil: GlobalError(n.info, errTypeExpected)
     if prev == nil: 
       result = s.typ
     else: 
@@ -604,7 +603,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         result = prev
       markUsed(n, n.sym)
     else: 
-      liMessage(n.info, errTypeExpected)
+      GlobalError(n.info, errTypeExpected)
   of nkObjectTy: result = semObjectNode(c, n, prev)
   of nkTupleTy: result = semTuple(c, n, prev)
   of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", prev)
@@ -627,7 +626,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkBlockType: 
     result = semBlockType(c, n, prev)
   else: 
-    liMessage(n.info, errTypeExpected) 
+    GlobalError(n.info, errTypeExpected) 
     #internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
   
 proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
@@ -665,5 +664,5 @@ proc processMagicType(c: PContext, m: PSym) =
   of mStmt: setMagicType(m, tyStmt, 0)
   of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
   of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return 
-  else: liMessage(m.info, errTypeExpected)
+  else: GlobalError(m.info, errTypeExpected)
   
diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim
index bcb9198da..cddfc89cb 100755
--- a/rod/sigmatch.nim
+++ b/rod/sigmatch.nim
@@ -443,7 +443,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
   if containsGenericType(f): result.typ = getInstantiatedType(c, arg, m, f)
   else: result.typ = f
   if result.typ == nil: InternalError(arg.info, "implicitConv")
-  addSon(result, nil)
+  addSon(result, ast.emptyNode)
   addSon(result, arg)
 
 proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, 
@@ -578,7 +578,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
       # named param
       # check if m.callee has such a param:
       if n.sons[a].sons[0].kind != nkIdent: 
-        liMessage(n.sons[a].info, errNamedParamHasToBeIdent)
+        LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
         m.state = csNoMatch
         return 
       formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
@@ -588,7 +588,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
         return 
       if IntSetContainsOrIncl(marker, formal.position): 
         # already in namedParams:
-        liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
+        LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
         m.state = csNoMatch
         return 
       m.baseTypeMatch = false
@@ -633,7 +633,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
         formal = m.callee.n.sons[f].sym
         if IntSetContainsOrIncl(marker, formal.position): 
           # already in namedParams:
-          liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
+          LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
           m.state = csNoMatch
           return 
         m.baseTypeMatch = false
@@ -683,12 +683,13 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
   var
     o: TOverloadIter
     x, y, z: TCandidate
-  #liMessage(n.info, warnUser, renderTree(n));
+  #Message(n.info, warnUser, renderTree(n))
   var sym = initOverloadIter(o, c, f)
   result = nil
   if sym == nil: return 
   initCandidate(x, sym, initialBinding)
   initCandidate(y, sym, initialBinding)
+
   while sym != nil: 
     if sym.kind in filter: 
       initCandidate(z, sym, initialBinding)
@@ -711,7 +712,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
       not sameMethodDispatcher(x.calleeSym, y.calleeSym): 
     if x.state != csMatch: 
       InternalError(n.info, "x.state is not csMatch") 
-    liMessage(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
+    LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
       getProcHeader(x.calleeSym), getProcHeader(y.calleeSym), 
       x.calleeSym.Name.s])
   else: 
@@ -719,7 +720,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
     markUsed(n, x.calleeSym)
     if x.calleeSym.ast == nil: 
       internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
-    if x.calleeSym.ast.sons[genericParamsPos] != nil: 
+    if x.calleeSym.ast.sons[genericParamsPos].kind != nkEmpty: 
       # a generic proc!
       x.calleeSym = generateInstance(c, x.calleeSym, x.bindings, n.info)
       x.callee = x.calleeSym.typ
diff --git a/rod/tccgen.nim b/rod/tccgen.nim
index ca7bac193..2fd207aaa 100755
--- a/rod/tccgen.nim
+++ b/rod/tccgen.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/rod/transf.nim b/rod/transf.nim
index 9eddcbe68..fb9c640cd 100755
--- a/rod/transf.nim
+++ b/rod/transf.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -219,12 +219,11 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
         newVar.owner = getCurrOwner(c)
         IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
         defs[j] = newSymNode(newVar).PTransNode
-      assert(it.sons[L-2] == nil)
+      assert(it.sons[L-2].kind == nkEmpty)
       defs[L-1] = transform(c, it.sons[L-1])
       result[i] = defs
 
 proc hasContinue(n: PNode): bool = 
-  if n == nil: return 
   case n.kind
   of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
   of nkContinueStmt: result = true
@@ -271,7 +270,6 @@ proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) =
         transform(c, newTupleAccess(n, i))))
 
 proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode = 
-  if n == nil: return
   case n.kind
   of nkSym: 
     return transformSym(c, n)
@@ -311,8 +309,8 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
 proc addVar(father, v: PNode) = 
   var vpart = newNodeI(nkIdentDefs, v.info)
   addSon(vpart, v)
-  addSon(vpart, nil)
-  addSon(vpart, nil)
+  addSon(vpart, ast.emptyNode)
+  addSon(vpart, ast.emptyNode)
   addSon(father, vpart)
 
 proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode = 
@@ -515,7 +513,6 @@ proc getMagicOp(call: PNode): TMagic =
 proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym, 
                 container: PNode) = 
   # gather used vars for closure generation
-  if n == nil: return 
   case n.kind
   of nkSym: 
     var s = n.sym
@@ -662,7 +659,6 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
     result = transformSons(c, n)
 
 proc transform(c: PTransf, n: PNode): PTransNode = 
-  if n == nil: return
   case n.kind
   of nkSym: 
     return transformSym(c, n)
@@ -678,7 +674,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
   of nkCaseStmt: 
     result = transformCase(c, n)
   of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef: 
-    if n.sons[genericParamsPos] == nil: 
+    if n.sons[genericParamsPos].kind == nkEmpty: 
       n.sons[codePos] = PNode(transform(c, n.sons[codePos]))
       if n.kind == nkMethodDef: methodDef(n.sons[namePos].sym)
     result = PTransNode(n)
@@ -727,6 +723,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     result = PTransNode(cnst) # do not miss an optimization
  
 proc processTransf(context: PPassContext, n: PNode): PNode = 
+  if passes.skipCodegen(n): return n
   var c = PTransf(context)
   pushTransCon(c, newTransCon(getCurrOwner(c)))
   result = PNode(transform(c, n))
diff --git a/rod/types.nim b/rod/types.nim
index d26136aa9..dcabbd3ee 100755
--- a/rod/types.nim
+++ b/rod/types.nim
@@ -119,7 +119,7 @@ proc getOrdValue(n: PNode): biggestInt =
   of nkCharLit..nkInt64Lit: result = n.intVal
   of nkNilLit: result = 0
   else: 
-    liMessage(n.info, errOrdinalTypeExpected)
+    LocalError(n.info, errOrdinalTypeExpected)
     result = 0
 
 proc isCompatibleToCString(a: PType): bool = 
diff --git a/tests/accept/compile/tgenericvariant.nim b/tests/accept/compile/tgenericvariant.nim
index 51d01355a..51d01355a 100644..100755
--- a/tests/accept/compile/tgenericvariant.nim
+++ b/tests/accept/compile/tgenericvariant.nim
diff --git a/tests/accept/compile/tnamedparams.nim b/tests/accept/compile/tnamedparams.nim
index 4b0cd5361..4b0cd5361 100644..100755
--- a/tests/accept/compile/tnamedparams.nim
+++ b/tests/accept/compile/tnamedparams.nim
diff --git a/tests/accept/compile/toop.nim b/tests/accept/compile/toop.nim
index d103c6304..d103c6304 100644..100755
--- a/tests/accept/compile/toop.nim
+++ b/tests/accept/compile/toop.nim
diff --git a/tests/accept/run/spec.csv b/tests/accept/run/spec.csv
index e9c49ea74..5102c85b1 100755
--- a/tests/accept/run/spec.csv
+++ b/tests/accept/run/spec.csv
@@ -22,7 +22,7 @@ tcopy.nim;TEMP=C:\Programs\xyz\bin
 tcountup.nim;0123456789
 tcurrncy.nim;25
 temit.nim;509
-tenumhole;my value A1my value Bconc2valueCabc4abc
+tenumhole.nim;my value A1my value Bconc2valueCabc4abc
 texcsub.nim;caught!
 texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
 tfinally.nim;came here 3
@@ -47,7 +47,7 @@ tmultim1.nim;7
 tmultim2.nim;collide: unit, thing collide: unit, thing collide: thing, unit
 tmultim3.nim;Hi derived!
 tmultim4.nim;hello
-tnamedenumfields;my value A0my value Bconc1valueCabc3abc
+tnamedenumfields.nim;my value A0my value Bconc1valueCabc3abc
 tnestif.nim;i == 2
 tnestprc.nim;10
 toop1.nim;34[]o 5
diff --git a/tests/accept/run/tarraycons.nim b/tests/accept/run/tarraycons.nim
index 12f13ac33..12f13ac33 100644..100755
--- a/tests/accept/run/tarraycons.nim
+++ b/tests/accept/run/tarraycons.nim
diff --git a/tests/accept/run/tcountup.nim b/tests/accept/run/tcountup.nim
index 4d4c9b304..4d4c9b304 100644..100755
--- a/tests/accept/run/tcountup.nim
+++ b/tests/accept/run/tcountup.nim
diff --git a/tests/accept/run/temit.nim b/tests/accept/run/temit.nim
index 81f9b53ae..81f9b53ae 100644..100755
--- a/tests/accept/run/temit.nim
+++ b/tests/accept/run/temit.nim
diff --git a/tests/accept/run/tenumhole.nim b/tests/accept/run/tenumhole.nim
index 75fb74592..75fb74592 100644..100755
--- a/tests/accept/run/tenumhole.nim
+++ b/tests/accept/run/tenumhole.nim
diff --git a/tests/accept/run/texcsub.nim b/tests/accept/run/texcsub.nim
index b35f0fa3f..b35f0fa3f 100644..100755
--- a/tests/accept/run/texcsub.nim
+++ b/tests/accept/run/texcsub.nim
diff --git a/tests/accept/run/tfloat3.nim b/tests/accept/run/tfloat3.nim
index 72acce958..72acce958 100644..100755
--- a/tests/accept/run/tfloat3.nim
+++ b/tests/accept/run/tfloat3.nim
diff --git a/tests/accept/run/titer6.nim b/tests/accept/run/titer6.nim
index 8a1d9cf1b..8a1d9cf1b 100644..100755
--- a/tests/accept/run/titer6.nim
+++ b/tests/accept/run/titer6.nim
diff --git a/tests/accept/run/tmultim2.nim b/tests/accept/run/tmultim2.nim
index bf3b5fd6e..c43c9b6f0 100755
--- a/tests/accept/run/tmultim2.nim
+++ b/tests/accept/run/tmultim2.nim
@@ -22,7 +22,7 @@ proc test(a, b: TThing) {.inline.} =
 var
   a: TThing
   b, c: TUnit
-collide(b, c) # ambiguous unit, thing or thing, unit? -> prefer unit, thing!
+collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing!
 test(b, c)
 collide(a, b)
 #OUT collide: unit, thing collide: unit, thing collide: thing, unit
diff --git a/tests/accept/run/tmultim4.nim b/tests/accept/run/tmultim4.nim
index fbfaf3175..fbfaf3175 100644..100755
--- a/tests/accept/run/tmultim4.nim
+++ b/tests/accept/run/tmultim4.nim
diff --git a/tests/accept/run/tnamedenumfields.nim b/tests/accept/run/tnamedenumfields.nim
index 6012cf1eb..6012cf1eb 100644..100755
--- a/tests/accept/run/tnamedenumfields.nim
+++ b/tests/accept/run/tnamedenumfields.nim
diff --git a/tests/accept/run/toprprec.nim b/tests/accept/run/toprprec.nim
index 4728b2e68..4728b2e68 100644..100755
--- a/tests/accept/run/toprprec.nim
+++ b/tests/accept/run/toprprec.nim
diff --git a/tests/gc/tthreads.nim b/tests/gc/tthreads.nim
index 2ef599e53..2ef599e53 100644..100755
--- a/tests/gc/tthreads.nim
+++ b/tests/gc/tthreads.nim
diff --git a/tests/reject/tarraycons.nim b/tests/reject/tarraycons.nim
index 1809f8735..1809f8735 100644..100755
--- a/tests/reject/tarraycons.nim
+++ b/tests/reject/tarraycons.nim
diff --git a/tests/reject/tmethod.nim b/tests/reject/tmethod.nim
index 101cabf25..101cabf25 100644..100755
--- a/tests/reject/tmethod.nim
+++ b/tests/reject/tmethod.nim
diff --git a/tests/reject/tnamedparams.nim b/tests/reject/tnamedparams.nim
index 6c59518b3..6c59518b3 100644..100755
--- a/tests/reject/tnamedparams.nim
+++ b/tests/reject/tnamedparams.nim
diff --git a/tests/reject/twrongtupleaccess.nim b/tests/reject/twrongtupleaccess.nim
index f706e267c..f706e267c 100644..100755
--- a/tests/reject/twrongtupleaccess.nim
+++ b/tests/reject/twrongtupleaccess.nim
diff --git a/tests/testdata/jsontest2.json b/tests/testdata/jsontest2.json
index 3a2294474..3a2294474 100644..100755
--- a/tests/testdata/jsontest2.json
+++ b/tests/testdata/jsontest2.json
diff --git a/todo.txt b/todo.txt
index 476eb01e9..92bf541f3 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,4 @@
-- ban ``nil`` from the AST. This might also fix bugs concerning macros.
-  TODO: 
-    * semantic checking (keep in mind incremental parsing!)
-    * code generators
+- 'suggest'
 
 - thread support: threadvar on Windows seems broken; 
   add --deadlock_prevention:on|off switch
diff --git a/web/news.txt b/web/news.txt
index 1548fdc0f..68f0fb190 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -61,6 +61,7 @@ Additions
 - Added basic thread support via the ``threads`` core module and 
   the ``--threads:on`` command line switch.
 - Added unary ``<`` for nice looking excluding upper bounds in ranges.
+- Added ``math.floor``.
 
 
 2010-10-20 Version 0.8.10 released
diff --git a/web/nimrod.ini b/web/nimrod.ini
index fc11c00d0..fc11c00d0 100644..100755
--- a/web/nimrod.ini
+++ b/web/nimrod.ini