summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xrod/ast.nim18
-rwxr-xr-xrod/c2nim/c2nim.nim4
-rwxr-xr-xrod/c2nim/cparse.nim94
-rwxr-xr-xrod/c2nim/cpp.nim16
-rwxr-xr-xrod/depends.nim1
-rwxr-xr-xrod/docgen.nim1
-rwxr-xr-xrod/evals.nim22
-rwxr-xr-xrod/main.nim1
-rwxr-xr-xrod/msgs.nim391
-rwxr-xr-xrod/pas2nim/pasparse.nim138
-rwxr-xr-xrod/passes.nim9
-rwxr-xr-xrod/pnimsyn.nim183
-rwxr-xr-xrod/rnimsyn.nim38
-rwxr-xr-xrod/scanner.nim8
-rwxr-xr-xrod/semtypes.nim4
-rwxr-xr-xrod/syntaxes.nim7
-rwxr-xr-xtodo.txt6
17 files changed, 505 insertions, 436 deletions
diff --git a/rod/ast.nim b/rod/ast.nim
index 50bd00444..7bdfef82c 100755
--- a/rod/ast.nim
+++ b/rod/ast.nim
@@ -577,12 +577,10 @@ proc newSons*(father: PNode, length: int)
 proc newSons*(father: PType, length: int)
 proc addSon*(father, son: PNode)
 proc addSon*(father, son: PType)
-proc addSonIfNotNil*(father, n: PNode)
 proc delSon*(father: PNode, idx: int)
 proc hasSonWith*(n: PNode, kind: TNodeKind): bool
 proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool
 proc replaceSons*(n: PNode, oldKind, newKind: TNodeKind)
-proc sonsNotNil*(n: PNode): bool
 proc copyNode*(src: PNode): PNode
   # does not copy its sons!
 proc copyTree*(src: PNode): PNode
@@ -590,6 +588,10 @@ proc copyTree*(src: PNode): PNode
 
 proc discardSons*(father: PNode)
 
+var emptyNode* = newNode(nkEmpty)
+# There is a single empty node that is shared! Do not overwrite it!
+
+
 const                         # for all kind of hash tables:
   GrowthFactor* = 2           # must be power of 2, > 0
   StartSize* = 8              # must be power of 2, > 0
@@ -868,6 +870,7 @@ proc len*(n: PNode): int {.inline.} =
   else: result = len(n.sons)
   
 proc add*(father, son: PNode) =
+  assert son != nil
   if isNil(father.sons): father.sons = @[]
   add(father.sons, son)  
   
@@ -879,6 +882,7 @@ proc newSons(father: PNode, length: int) =
   setlen(father.sons, len(father.sons) + length)
 
 proc addSon(father, son: PNode) = 
+  assert son != nil
   if isNil(father.sons): father.sons = @[]
   add(father.sons, son)
 
@@ -947,7 +951,7 @@ proc lastSon(n: PType): PType =
 
 proc hasSonWith(n: PNode, kind: TNodeKind): bool = 
   for i in countup(0, sonsLen(n) - 1): 
-    if (n.sons[i] != nil) and (n.sons[i].kind == kind): 
+    if n.sons[i].kind == kind: 
       return true
   result = false
 
@@ -956,9 +960,8 @@ proc hasSubnodeWith(n: PNode, kind: TNodeKind): bool =
   of nkEmpty..nkNilLit: result = n.kind == kind
   else: 
     for i in countup(0, sonsLen(n) - 1): 
-      if n.sons[i] != nil: 
-        if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind): 
-          return true
+      if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind): 
+        return true
     result = false
 
 proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) = 
@@ -971,9 +974,6 @@ proc sonsNotNil(n: PNode): bool =
       return false
   result = true
 
-proc addSonIfNotNil(father, n: PNode) = 
-  if n != nil: addSon(father, n)
-  
 proc getInt*(a: PNode): biggestInt = 
   case a.kind
   of nkIntLit..nkInt64Lit: result = a.intVal
diff --git a/rod/c2nim/c2nim.nim b/rod/c2nim/c2nim.nim
index f1cb05920..f4e185445 100755
--- a/rod/c2nim/c2nim.nim
+++ b/rod/c2nim/c2nim.nim
@@ -1,7 +1,7 @@
 #
 #
 #      c2nim - C to Nimrod source converter
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -15,7 +15,7 @@ const
   Version = NimrodVersion
   Usage = """
 c2nim - C to Nimrod source converter
-  (c) 2010 Andreas Rumpf
+  (c) 2011 Andreas Rumpf
 Usage: c2nim [options] inputfile [options]
 Options: 
   -o, --out:FILE         set output filename
diff --git a/rod/c2nim/cparse.nim b/rod/c2nim/cparse.nim
index 2634e8598..da96de1f4 100755
--- a/rod/c2nim/cparse.nim
+++ b/rod/c2nim/cparse.nim
@@ -197,7 +197,7 @@ proc parLineInfo(p: TParser): TLineInfo =
   result = getLineInfo(p.lex)
 
 proc skipComAux(p: var TParser, n: PNode) =
-  if (n != nil): 
+  if n != nil and n.kind != nkEmpty: 
     if pfSkipComments notin p.options.flags:
       if n.comment == nil: n.comment = p.tok.s
       else: add(n.comment, "\n" & p.tok.s)
@@ -216,8 +216,7 @@ proc getTok(p: var TParser, n: PNode) =
   skipCom(p, n)
 
 proc ExpectIdent(p: TParser) = 
-  if p.tok.xkind != pxSymbol: 
-    parMessage(p, errIdentifierExpected, $(p.tok^))
+  if p.tok.xkind != pxSymbol: parMessage(p, errIdentifierExpected, $(p.tok^))
   
 proc Eat(p: var TParser, xkind: TTokKind, n: PNode) = 
   if p.tok.xkind == xkind: getTok(p, n)
@@ -375,7 +374,7 @@ proc skipTypeIdentExport(p: var TParser, prefix='T'): PNode =
 proc markTypeIdent(p: var TParser, typ: PNode) = 
   if pfTypePrefixes in p.options.flags:
     var prefix = ""
-    if typ == nil: 
+    if typ == nil or typ.kind == nkEmpty: 
       prefix = "T"
     else: 
       var t = typ
@@ -479,11 +478,12 @@ proc newProcPragmas(p: TParser): PNode =
 
 proc addPragmas(father, pragmas: PNode) =
   if sonsLen(pragmas) > 0: addSon(father, pragmas)
-  else: addSon(father, nil)
+  else: addSon(father, ast.emptyNode)
 
 proc addReturnType(params, rettyp: PNode) =
-  if rettyp == nil or rettyp.kind != nkNilLit: addSon(params, rettyp)
-  else: addson(params, nil)
+  if rettyp == nil: addSon(params, ast.emptyNode)
+  elif rettyp.kind != nkNilLit: addSon(params, rettyp)
+  else: addson(params, ast.emptyNode)
 
 proc parseFormalParams(p: var TParser, params, pragmas: PNode)
 
@@ -527,9 +527,6 @@ proc parseTypeSuffix(p: var TParser, typ: PNode): PNode =
     else: break
 
 proc typeDesc(p: var TParser): PNode = 
-  #result = typeAtom(p)
-  #if result != nil:
-  #  result = pointer(p, result)
   result = pointer(p, typeAtom(p))
 
 proc parseField(p: var TParser, kind: TNodeKind): PNode =
@@ -560,7 +557,7 @@ proc parseStructBody(p: var TParser, isUnion: bool,
       var t = pointer(p, baseTyp)
       var i = parseField(p, kind)
       t = parseTypeSuffix(p, t)
-      addSon(def, i, t, nil)
+      addSon(def, i, t, ast.emptyNode)
       if not takeOnlyFirstField(p, isUnion) or sonsLen(result) < 1: 
         addSon(result, def)
       if p.tok.xkind != pxComma: break
@@ -591,7 +588,7 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
 
 proc parseStruct(p: var TParser, isUnion: bool): PNode = 
   result = newNodeP(nkObjectTy, p)
-  addSon(result, nil, nil) # no pragmas, no inheritance 
+  addSon(result, ast.emptyNode, ast.emptyNode) # no pragmas, no inheritance 
   if p.tok.xkind == pxCurlyLe:
     addSon(result, parseStructBody(p, isUnion))
   else: 
@@ -616,7 +613,7 @@ proc parseParam(p: var TParser, params: PNode) =
     getTok(p, x)
     addSon(x, assignmentExpression(p))
   else:
-    addSon(x, nil)
+    addSon(x, ast.emptyNode)
   addSon(params, x)
 
 proc parseFormalParams(p: var TParser, params, pragmas: PNode) = 
@@ -662,15 +659,16 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
   if p.inTypeDef == 0:
     result = newNodeP(nkVarSection, p)
     var def = newNodeP(nkIdentDefs, p)
-    addSon(def, name, procType, nil)
+    addSon(def, name, procType, ast.emptyNode)
     addSon(result, def)    
   else:
     result = newNodeP(nkTypeDef, p)
-    addSon(result, name, nil, procType)
+    addSon(result, name, ast.emptyNode, procType)
+  assert result != nil
   
 proc addTypeDef(section, name, t: PNode) = 
   var def = newNodeI(nkTypeDef, name.info)
-  addSon(def, name, nil, t)
+  addSon(def, name, ast.emptyNode, t)
   addSon(section, def)
   
 proc otherTypeDef(p: var TParser, section, typ: PNode) = 
@@ -705,7 +703,7 @@ proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) =
 
 proc enumFields(p: var TParser): PNode = 
   result = newNodeP(nkEnumTy, p)
-  addSon(result, nil) # enum does not inherit from anything
+  addSon(result, ast.emptyNode) # enum does not inherit from anything
   while true:
     var e = skipIdent(p)
     if p.tok.xkind == pxAsgn: 
@@ -846,7 +844,7 @@ proc addInitializer(p: var TParser, def: PNode) =
     getTok(p, def)
     addSon(def, parseInitializer(p))
   else:
-    addSon(def, nil)  
+    addSon(def, ast.emptyNode)  
 
 proc parseVarDecl(p: var TParser, baseTyp, typ: PNode, 
                   origName: string): PNode =  
@@ -921,22 +919,24 @@ proc declaration(p: var TParser): PNode =
       addSon(pragmas, newIdentNodeP("cdecl", p))
     elif pfStdcall in p.options.flags:
       addSon(pragmas, newIdentNodeP("stdcall", p))
-    addSon(result, exportSym(p, name, origName), nil) # no generics
+    addSon(result, exportSym(p, name, origName), ast.emptyNode) # no generics
     addSon(result, params, pragmas)
     case p.tok.xkind 
     of pxSemicolon: 
       getTok(p)
-      addSon(result, nil) # nobody
+      addSon(result, ast.emptyNode) # nobody
       if p.scopeCounter == 0: DoImport(origName, pragmas, p)
     of pxCurlyLe:
       addSon(result, compoundStatement(p))
     else:
       parMessage(p, errTokenExpected, ";")
-    if sonsLen(result.sons[pragmasPos]) == 0: result.sons[pragmasPos] = nil
+    if sonsLen(result.sons[pragmasPos]) == 0: 
+      result.sons[pragmasPos] = ast.emptyNode
   of pxAsgn, pxSemicolon, pxComma:
     result = parseVarDecl(p, baseTyp, rettyp, origName)
   else:
     parMessage(p, errTokenExpected, ";")
+  assert result != nil
 
 proc createConst(name, typ, val: PNode, p: TParser): PNode =
   result = newNodeP(nkConstDef, p)
@@ -963,7 +963,7 @@ proc enumSpecifier(p: var TParser): PNode =
       else:
         val = newIntNodeP(nkIntLit, i, p)
         inc(i)
-      var c = createConst(name, nil, val, p)
+      var c = createConst(name, ast.emptyNode, val, p)
       addSon(result, c)
       if p.tok.xkind != pxComma: break
       getTok(p, c)
@@ -984,7 +984,7 @@ proc enumSpecifier(p: var TParser): PNode =
       var t = newNodeP(nkTypeDef, p)
       getTok(p, t)
       var e = enumFields(p)
-      addSon(t, exportSym(p, name, origName), nil, e) # nil for generic params
+      addSon(t, exportSym(p, name, origName), ast.emptyNode, e)
       addSon(result, t)
       eat(p, pxCurlyRi, result)
       eat(p, pxSemicolon)
@@ -998,6 +998,7 @@ proc enumSpecifier(p: var TParser): PNode =
   else:
     closeContext(p)
     parMessage(p, errTokenExpected, "{")
+    result = ast.emptyNode
     
 # Expressions
 
@@ -1085,7 +1086,7 @@ proc primaryExpression(p: var TParser): PNode =
   of pxParLe:
     result = castExpression(p)
   else:
-    result = nil
+    result = ast.emptyNode
 
 proc multiplicativeExpression(p: var TParser): PNode = 
   result = castExpression(p)
@@ -1309,7 +1310,7 @@ proc andExpression(p: var TParser): PNode =
     getTok(p, result)
     var a = result 
     var b = equalityExpression(p)
-    result = newBinary("&", a, b, p)
+    result = newBinary("and", a, b, p)
 
 proc exclusiveOrExpression(p: var TParser): PNode = 
   result = andExpression(p)
@@ -1390,10 +1391,12 @@ proc expressionStatement(p: var TParser): PNode =
   # do not skip the comment after a semicolon to make a new nkCommentStmt
   if p.tok.xkind == pxSemicolon: 
     getTok(p)
+    result = ast.emptyNode
   else:
     result = expression(p)
     if p.tok.xkind == pxSemicolon: getTok(p)
     else: parMessage(p, errTokenExpected, ";")
+  assert result != nil
 
 proc parseIf(p: var TParser): PNode = 
   # we parse additional "else if"s too here for better Nimrod code
@@ -1431,7 +1434,7 @@ proc parseDoWhile(p: var TParser): PNode =
   # ``block: stmt``
   result = newNodeP(nkBlockStmt, p)
   getTok(p, result) # skip "do"
-  addSon(result, nil, nestedStatement(p))
+  addSon(result, ast.emptyNode, nestedStatement(p))
   eat(p, "while", result)
   eat(p, pxParLe, result)
   if p.tok.xkind == pxIntLit and p.tok.iNumber == 0: getTok(p, result)
@@ -1465,6 +1468,7 @@ proc declarationOrStatement(p: var TParser): PNode =
     else: 
       backtrackContext(p)
       result = expressionStatement(p)
+  assert result != nil
 
 proc parseTuple(p: var TParser, isUnion: bool): PNode = 
   result = parseStructBody(p, isUnion, nkTupleTy)
@@ -1516,15 +1520,16 @@ proc parseFor(p: var TParser, result: PNode) =
   getTok(p, result)
   eat(p, pxParLe, result)
   var initStmt = declarationOrStatement(p)
-  addSonIfNotNil(result, initStmt)
+  if initStmt.kind != nkEmpty:
+    addSon(result, initStmt)
   var w = newNodeP(nkWhileStmt, p)
   var condition = expressionStatement(p)
-  if condition == nil: condition = newIdentNodeP("true", p)
+  if condition.kind == nkEmpty: condition = newIdentNodeP("true", p)
   addSon(w, condition)
-  var step = if p.tok.xkind != pxParRi: expression(p) else: nil
+  var step = if p.tok.xkind != pxParRi: expression(p) else: ast.emptyNode
   eat(p, pxParRi, step)
   var loopBody = nestedStatement(p)
-  if step != nil:
+  if step.kind != nkEmpty:
     loopBody = buildStmtList(loopBody)
     addSon(loopBody, step)
   addSon(w, loopBody)
@@ -1604,7 +1609,7 @@ proc embedStmts(sl, a: PNode) =
     addStmt(sl, a)
   else:
     for i in 0..sonsLen(a)-1: 
-      if a[i] != nil: addStmt(sl, a[i])
+      if a[i].kind != nkEmpty: addStmt(sl, a[i])
 
 proc compoundStatement(p: var TParser): PNode = 
   result = newNodeP(nkStmtList, p)
@@ -1612,7 +1617,7 @@ proc compoundStatement(p: var TParser): PNode =
   inc(p.scopeCounter)
   while p.tok.xkind notin {pxEof, pxCurlyRi}: 
     var a = statement(p)
-    if a == nil: break
+    if a.kind == nkEmpty: break
     embedStmts(result, a)
   if sonsLen(result) == 0:
     # translate ``{}`` to Nimrod's ``nil`` statement
@@ -1644,12 +1649,12 @@ proc statement(p: var TParser): PNode =
       result = newNodeP(nkContinueStmt, p)
       getTok(p)
       eat(p, pxSemicolon)
-      addSon(result, nil)
+      addSon(result, ast.emptyNode)
     of "break":
       result = newNodeP(nkBreakStmt, p)
       getTok(p)
       eat(p, pxSemicolon)
-      addSon(result, nil)
+      addSon(result, ast.emptyNode)
     of "return":
       result = newNodeP(nkReturnStmt, p)
       getTok(p)
@@ -1662,18 +1667,13 @@ proc statement(p: var TParser): PNode =
       elif p.tok.xkind != pxSemicolon:
         addSon(result, expression(p))
       else:
-        addSon(result, nil)
+        addSon(result, ast.emptyNode)
       eat(p, pxSemicolon)
-    of "enum":
-      result = enumSpecifier(p)
-    of "typedef": 
-      result = parseTypeDef(p)
-    of "struct":
-      result = parseStandaloneStruct(p, isUnion=false)
-    of "union":
-      result = parseStandaloneStruct(p, isUnion=true)    
-    else: 
-      result = declarationOrStatement(p)
+    of "enum": result = enumSpecifier(p)
+    of "typedef": result = parseTypeDef(p)
+    of "struct": result = parseStandaloneStruct(p, isUnion=false)
+    of "union": result = parseStandaloneStruct(p, isUnion=true)    
+    else: result = declarationOrStatement(p)
   of pxCurlyLe:
     result = compoundStatement(p)
   of pxDirective, pxDirectiveParLe:
@@ -1691,12 +1691,12 @@ proc statement(p: var TParser): PNode =
       result = newNodeP(nkNilLit, p)
   else:
     result = expressionStatement(p)
-    #parMessage(p, errStmtExpected)
+  assert result != nil
 
 proc parseUnit(p: var TParser): PNode = 
   result = newNodeP(nkStmtList, p)
   getTok(p) # read first token
   while p.tok.xkind != pxEof: 
     var s = statement(p)
-    if s != nil: embedStmts(result, s)
+    if s.kind != nkEmpty: embedStmts(result, s)
 
diff --git a/rod/c2nim/cpp.nim b/rod/c2nim/cpp.nim
index f59c86044..e7c7e86b0 100755
--- a/rod/c2nim/cpp.nim
+++ b/rod/c2nim/cpp.nim
@@ -45,7 +45,7 @@ proc parseDefine(p: var TParser): PNode =
     eat(p, pxParLe)
     var params = newNodeP(nkFormalParams, p)
     # return type; not known yet:
-    addSon(params, nil)  
+    addSon(params, ast.emptyNode)  
     var identDefs = newNodeP(nkIdentDefs, p)
     while p.tok.xkind != pxParRi: 
       addSon(identDefs, skipIdent(p))
@@ -53,13 +53,13 @@ proc parseDefine(p: var TParser): PNode =
       if p.tok.xkind != pxComma: break
       getTok(p)
     addSon(identDefs, newIdentNodeP("expr", p))
-    addSon(identDefs, nil)
+    addSon(identDefs, ast.emptyNode)
     addSon(params, identDefs)
     eat(p, pxParRi)
     
-    addSon(result, nil) # no generic parameters
+    addSon(result, ast.emptyNode) # no generic parameters
     addSon(result, params)
-    addSon(result, nil) # no pragmas
+    addSon(result, ast.emptyNode) # no pragmas
     var kind = parseDefineBody(p, result)
     params.sons[0] = newIdentNodeP(kind, p)
     eatNewLine(p, result)
@@ -70,7 +70,7 @@ proc parseDefine(p: var TParser): PNode =
       getTok(p) # skip #define
       var c = newNodeP(nkConstDef, p)
       addSon(c, skipIdentExport(p))
-      addSon(c, nil)
+      addSon(c, ast.emptyNode)
       skipStarCom(p, c)
       if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}:
         addSon(c, newIdentNodeP("true", p))
@@ -78,6 +78,7 @@ proc parseDefine(p: var TParser): PNode =
         addSon(c, expression(p))
       addSon(result, c)
       eatNewLine(p, c)
+  assert result != nil
   
 proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) =
   m.body = @[]
@@ -147,7 +148,7 @@ proc parseInclude(p: var TParser): PNode =
       skipLine(p)
   if sonsLen(result) == 0: 
     # we only parsed includes that we chose to ignore:
-    result = nil
+    result = ast.emptyNode
 
 proc definedExprAux(p: var TParser): PNode = 
   result = newNodeP(nkCall, p)
@@ -226,6 +227,7 @@ proc parseIfdef(p: var TParser): PNode =
   case p.tok.s
   of "__cplusplus":
     skipUntilEndif(p)
+    result = ast.emptyNode
   of c2nimSymbol:
     skipLine(p)
     result = parseStmtList(p)
@@ -238,6 +240,7 @@ proc parseIfdef(p: var TParser): PNode =
     parseIfDirAux(p, result)
   
 proc parseIfndef(p: var TParser): PNode = 
+  result = ast.emptyNode
   getTok(p) # skip #ifndef
   ExpectIdent(p)
   if p.tok.s == c2nimSymbol: 
@@ -295,6 +298,7 @@ proc parseMangleDir(p: var TParser) =
   eatNewLine(p, nil)
 
 proc parseDir(p: var TParser): PNode = 
+  result = ast.emptyNode
   assert(p.tok.xkind in {pxDirective, pxDirectiveParLe})
   case p.tok.s
   of "define": result = parseDefine(p)
diff --git a/rod/depends.nim b/rod/depends.nim
index 4c464f5ec..05d176436 100755
--- a/rod/depends.nim
+++ b/rod/depends.nim
@@ -29,7 +29,6 @@ proc addDependencyAux(importing, imported: string) =
   
 proc addDotDependency(c: PPassContext, n: PNode): PNode = 
   result = n
-  if n == nil: return 
   var g = PGen(c)
   case n.kind
   of nkImportStmt: 
diff --git a/rod/docgen.nim b/rod/docgen.nim
index 73566dbb0..cc31da925 100755
--- a/rod/docgen.nim
+++ b/rod/docgen.nim
@@ -771,7 +771,6 @@ proc traceDeps(d: PDoc, n: PNode) =
         "$1", [toRope(getModuleFile(n))])
 
 proc generateDoc(d: PDoc, n: PNode) = 
-  if n == nil: return 
   case n.kind
   of nkCommentStmt: app(d.modDesc, genComment(d, n))
   of nkProcDef: genItem(d, n, n.sons[namePos], skProc)
diff --git a/rod/evals.nim b/rod/evals.nim
index 4f0aeb6c6..b20c20acf 100755
--- a/rod/evals.nim
+++ b/rod/evals.nim
@@ -54,8 +54,6 @@ const
   evalMaxIterations = 10000000 # max iterations of all loops
   evalMaxRecDepth = 100000    # max recursion depth for evaluation
 
-var emptyNode: PNode
-
 proc newStackFrame(): PStackFrame = 
   new(result)
   initIdNodeTable(result.mapping)
@@ -136,7 +134,7 @@ proc evalWhile(c: PEvalContext, n: PNode): PNode =
     result = evalAux(c, n.sons[1], {})
     case result.kind
     of nkBreakStmt: 
-      if result.sons[0] == nil: 
+      if result.sons[0].kind == nkEmpty: 
         result = emptyNode    # consume ``break`` token
         break 
     of nkExceptBranch, nkReturnToken: 
@@ -153,7 +151,7 @@ proc evalBlock(c: PEvalContext, n: PNode): PNode =
   if result.kind == nkBreakStmt: 
     if result.sons[0] != nil: 
       assert(result.sons[0].kind == nkSym)
-      if n.sons[0] != nil: 
+      if n.sons[0].kind != nkempty: 
         assert(n.sons[0].kind == nkSym)
         if result.sons[0].sym.id == n.sons[0].sym.id: result = emptyNode
     else: 
@@ -228,7 +226,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
     assert(a.kind == nkIdentDefs)
     assert(a.sons[0].kind == nkSym)
     var v = a.sons[0].sym
-    if a.sons[2] != nil: 
+    if a.sons[2].kind != nkEmpty: 
       result = evalAux(c, a.sons[2], {})
       if isSpecial(result): return 
     else: 
@@ -507,7 +505,7 @@ proc evalConvCStrToStr(c: PEvalContext, n: PNode): PNode =
   result.typ = n.typ
 
 proc evalRaise(c: PEvalContext, n: PNode): PNode = 
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     result = evalAux(c, n.sons[0], {})
     if isSpecial(result): return 
     var a = result
@@ -519,17 +517,17 @@ proc evalRaise(c: PEvalContext, n: PNode): PNode =
   else: 
     stackTrace(c, n, errExceptionAlreadyHandled)
     result = newNodeIT(nkExceptBranch, n.info, nil)
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
 
 proc evalReturn(c: PEvalContext, n: PNode): PNode = 
-  if n.sons[0] != nil: 
+  if n.sons[0].kind != nkEmpty: 
     result = evalAsgn(c, n.sons[0])
     if isSpecial(result): return 
   result = newNodeIT(nkReturnToken, n.info, nil)
 
 proc evalProc(c: PEvalContext, n: PNode): PNode = 
-  if n.sons[genericParamsPos] == nil: 
-    if (resultPos < sonsLen(n)) and (n.sons[resultPos] != nil): 
+  if n.sons[genericParamsPos].kind == nkEmpty: 
+    if (resultPos < sonsLen(n)) and (n.sons[resultPos].kind != nkEmpty): 
       var v = n.sons[resultPos].sym
       result = getNullValue(v.typ, n.info)
       IdNodeTablePut(c.tos.mapping, v, result)
@@ -740,8 +738,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
     if isSpecial(result): return 
     var k = getOrdValue(b)
     if (k >= 0) and (k < sonsLen(a)) and not (a.kind in {nkEmpty..nkNilLit}): 
-      if result.kind == nkEmpty: a.sons[int(k)] = nil
-      else: a.sons[int(k)] = result
+      a.sons[int(k)] = result
     else: 
       stackTrace(c, n, errIndexOutOfBounds)
     result = emptyNode
@@ -1055,4 +1052,3 @@ proc evalPass(): TPass =
   result.close = myProcess
   result.process = myProcess
 
-emptyNode = newNode(nkEmpty)
diff --git a/rod/main.nim b/rod/main.nim
index 68958acb6..2b391e7dd 100755
--- a/rod/main.nim
+++ b/rod/main.nim
@@ -109,6 +109,7 @@ proc CommandGenDepend(filename: string) =
       changeFileExt(filename, "dot"))
 
 proc CommandCheck(filename: string) = 
+  msgs.gErrorMax = high(int)  # do not stop after first error
   semanticPasses()            # use an empty backend for semantic checking only
   compileProject(filename)
 
diff --git a/rod/msgs.nim b/rod/msgs.nim
index 9e826e127..a3e9c1211 100755
--- a/rod/msgs.nim
+++ b/rod/msgs.nim
@@ -62,7 +62,7 @@ type
     errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue, 
     errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice, 
     errInvalidOrderInArrayConstructor,
-    errInvalidOrderInEnumX, errEnumXHasWholes, errExceptExpected, errInvalidTry, 
+    errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry, 
     errOptionExpected, errXisNoLabel, errNotAllCasesCovered, 
     errUnkownSubstitionVar, errComplexStmtRequiresInd, errXisNotCallable, 
     errNoPragmasAllowedForX, errNoGenericParamsAllowedForX, 
@@ -96,154 +96,245 @@ type
     hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser
 
 const 
-  MsgKindToStr*: array[TMsgKind, string] = ["unknown error", 
-    "illformed AST: $1", "cannot open \'$1\'", "internal error: $1", "$1", 
-    "\'$1\' compiler does not support C++", "string literal expected", 
-    "integer literal expected", "invalid character constant", 
-    "closing \"\"\" expected, but end of file reached", "closing \" expected", 
-    "tabulators are not allowed", "invalid token: $1", "line too long", 
-    "$1 is not a valid number", "number $1 out of valid range", 
-    "\\n not allowed in character literal", 
-    "closing \']\' expected, but end of file reached", "missing final \'", 
-    "identifier expected, but found \'$1\'", 
-    "operator expected, but found \'$1\'", "\'$1\' expected", 
-    "string after \'include\' expected", "recursive dependency: \'$1\'", 
-    "\'on\' or \'off\' expected", "\'none\', \'speed\' or \'size\' expected", 
-    "invalid pragma", "unknown pragma: \'$1\'", "invalid directive: \'$1\'", 
-    "\'pop\' without a \'push\' pragma", "empty asm statement", 
-    "invalid indentation", "exception expected", "exception already handled", 
-    "\'yield\' only allowed in a loop of an iterator", 
-    "invalid number of \'yield\' expresions", 
-    "current routine cannot return an expression", "attempt to redefine \'$1\'", 
-    "statement not allowed after \'return\', \'break\' or \'raise\'", 
-    "statement expected", "\'$1\' is no label", 
-    "invalid command line option: \'$1\'", 
-    "argument for command line option expected: \'$1\'", 
-    "invalid argument for command line option: \'$1\'", 
-    "invalid variable substitution in \'$1\'", "unknown variable: \'$1\'", 
-    "unknown C compiler: \'$1\'", 
-    "\'on\' or \'off\' expected, but \'$1\' found", 
-    "\'none\', \'boehm\' or \'refc\' expected, but \'$1\' found", 
-    "\'none\', \'speed\' or \'size\' expected, but \'$1\' found", 
-    "\'gui\', \'console\' or \'lib\' expected, but \'$1\' found", 
-    "unknown OS: \'$1\'", "unknown CPU: \'$1\'", 
-    "\'c\', \'c++\' or \'yaml\' expected, but \'$1\' found", 
-    "arguments can only be given if the \'--run\' option is selected", 
-    "multiple assignment is not allowed", 
-    "\':\' or \'=\' expected, but found \'$1\'", 
-    "expression expected, but found \'$1\'", "undeclared identifier: \'$1\'", 
-    "ambiguous identifier: \'$1\' -- use a qualifier", "type expected", 
-    "system module needs \'$1\'", "execution of an external program failed", 
-    "overloaded \'$1\' leads to ambiguous calls", "invalid argument for \'$1\'", 
-    "statement has no effect", "\'$1\' expects a type or value", 
-    "\'$1\' expects an array type", 
-    "\'$1\' cannot be instantiated because its body has not been compiled yet", 
-    "expression \'$1\' ambiguous in this context", "constant division by zero", 
-    "ordinal type expected", "ordinal or float type expected", 
-    "over- or underflow", 
-    "cannot evalutate \'$1\' because type is not defined completely", 
-    "\'chr\' expects an int in the range 0..255", 
-    "\'dynlib\' requires \'exportc\'", "undeclared field: \'$1\'", 
-    "attempt to access a nil address", "index out of bounds", 
-    "index types do not match", "\'[]\' operator invalid for this type", 
-    "value out of set bounds", "field initialized twice: \'$1\'", 
-    "field \'$1\' not initialized", "expression \'$1\' cannot be called", 
-    "expression has no type", "expression \'$1\' has no type (or is ambiguous)", 
-    "\'cast\' not allowed in safe mode", "expression cannot be casted to $1", 
-    "\',\' or \')\' expected", "\'{\' or \'(\' expected", 
-    "section (\'type\', \'proc\', etc.) expected", "range expected", 
-    "attempt to redefine \'$1\'", "\'magic\' only allowed in system module", 
-    "power of two expected", "string literal may not be empty", 
-    "calling convention expected", 
-    "a proc can only have one calling convention", 
-    "symbol must be imported if \'lib\' pragma is used", 
-    "expression must be of type \'bool\'", "constant expression expected", 
-    "duplicate case label", "range is empty", 
-    "selector must be of an ordinal type, real or string", 
-    "selector must be of an ordinal type", "ord($1) must not be negative", 
-    "len($1) must be less than 32768", "wrong number of variables", 
-    "only objects can be raised", "\'break\' only allowed in loop construct", 
-    "type \'$1\' has unknown size", 
-    "a constant can only be initialized with a constant expression", 
-    "a constant needs a value", "the result type cannot be on open array", 
-    "computing the type\'s size produced an overflow", "set is too large", 
-    "base type of a set must be an ordinal", 
-    "inheritance only works with non-final objects", 
-    "inheritance only works with an enum", "illegal recursion in type \'$1\'", 
-    "cannot instantiate: \'$1\'", "expression has no address", 
-    "for a \'var\' type a variable needs to be passed", "type mismatch", 
-    "type mismatch: got (", "but expected one of: ", "but expected \'$1\'", 
-    "ambiguous call; both $1 and $2 match for: $3", "wrong number of arguments", 
-    "\'$1\' cannot be passed to a procvar", 
-    "$1 cannot be declared in parameter declaration", 
-    "pragmas are only in the header of a proc allowed", 
-    "implementation of \'$1\' is not allowed", 
-    "implementation of \'$1\' expected", "no symbol to borrow from found", 
-    "value returned by statement has to be discarded", 
-    "statement returns no value that can be discarded", 
-    "conversion from $1 to $2 is invalid", "cannot bind parameter \'$1\' twice", 
-    "invalid order in array constructor",
-    "invalid order in enum \'$1\'", "enum \'$1\' has wholes", 
-    "\'except\' or \'finally\' expected", 
-    "after catch all \'except\' or \'finally\' no section may follow", 
-    "option expected, but found \'$1\'", "\'$1\' is not a label", 
-    "not all cases are covered", "unknown substitution variable: \'$1\'", 
-    "complex statement requires indentation", "\'$1\' is not callable", 
-    "no pragmas allowed for $1", "no generic parameters allowed for $1", 
-    "invalid param kind: \'$1\'", "default argument invalid", 
-    "named parameter has to be an identifier", "no return type for $1 allowed", 
-    "a type conversion needs exactly one argument", "invalid pragma: $1", 
-    "$1 not allowed here", "invalid control flow: $1", "a type has no value", 
-    "invalid type: \'$1\'", "\'^\' needs a pointer or reference type", 
-    "invalid expression", "invalid expression: \'$1\'", 
-    "enum has no value \'$1\'", "named expression expected", 
-    "named expression not allowed here", "\'$1\' expects one type parameter", 
-    "array expects two type parameters", "invalid visibility: \'$1\'", 
-    "initialization not allowed here", "\'$1\' cannot be assigned to", 
-    "iterators can only be defined at the module\'s top level", 
-    "$1 needs a return type", "invalid command: \'$1\'", 
-    "\'$1\' is only allowed at top level", 
-    "'$1' needs a parameter that has an object type",
-    "template/macro instantiation too nested", "instantiation from here", 
-    "invalid index value for tuple subscript", 
-    "command expects a filename argument", "\'$1\' expected", 
-    "invalid section start", "grid table is not implemented", 
-    "general parse error", "new section expected", 
-    "whitespace expected, got \'$1\'", "\'$1\' is no valid index file", 
-    "cannot render reStructuredText element \'$1\'", 
-    "type \'var var\' is not allowed", "\'is\' expects two arguments", 
-    "\'is\' expects object types", "\'$1\' can never be of this subtype", 
-    "interpretation requires too many iterations", 
-    "cannot interpret node kind \'$1\'", "field \'$1\' cannot be found", 
-    "invalid conversion from type \'$1\'", "assertion failed", 
-    "cannot generate code for \'$1\'", "$1 requires one parameter", 
-    "unhandled exception: $1", "macro returned a cyclic abstract syntax tree", 
-    "\'$1\' is no macro or template", "\'$1\' can have side effects", 
-    "iterator within for loop context expected", "$1", 
-    "cannot open \'$1\' [CannotOpenFile]", "octal escape sequences do not exist; leading zero is ignored [OctalEscape]", 
-    "\'$1\' is never read [XIsNeverRead]", 
-    "\'$1\' might not have been initialized [XmightNotBeenInit]", 
-    "cannot write file \'$1\' [CannotWriteMO2]", 
-    "cannot read file \'$1\' [CannotReadMO2]", 
-    "\'$1\' is deprecated [Deprecated]", "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]", 
-    "unknown magic \'$1\' might crash the compiler [UnknownMagic]", 
-    "redefinition of label \'$1\' [RedefinitionOfLabel]", 
-    "unknown substitution \'$1\' [UnknownSubstitutionX]", 
-    "language \'$1\' not supported [LanguageXNotSupported]", 
-    "comment \'$1\' ignored [CommentXIgnored]", 
-    "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]", 
-    "$1 [User]", "operation successful [Success]", 
-    "operation successful ($1 lines compiled; $2 sec total) [SuccessX]", 
-    "line too long [LineTooLong]", 
-    "\'$1\' is declared but not used [XDeclaredButNotUsed]", 
-    "conversion to base object is not needed [ConvToBaseNotNeeded]", 
-    "conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]", 
-    "expression evaluates always to \'$1\' [ExprAlwaysX]", 
-    "quit() called [QuitCalled]", "$1 [Processing]", 
-    "generated code listing: [CodeBegin]", "end of listing [CodeEnd]", 
-    "used config file \'$1\' [Conf]", 
-    "added path: '$1' [Path]",
-    "$1 [User]"]
+  MsgKindToStr*: array[TMsgKind, string] = [
+    errUnknown: "unknown error", 
+    errIllFormedAstX: "illformed AST: $1",
+    errCannotOpenFile: "cannot open \'$1\'", 
+    errInternal: "internal error: $1", 
+    errGenerated: "$1", 
+    errXCompilerDoesNotSupportCpp: "\'$1\' compiler does not support C++", 
+    errStringLiteralExpected: "string literal expected", 
+    errIntLiteralExpected: "integer literal expected", 
+    errInvalidCharacterConstant: "invalid character constant", 
+    errClosingTripleQuoteExpected: "closing \"\"\" expected, but end of file reached", 
+    errClosingQuoteExpected: "closing \" expected", 
+    errTabulatorsAreNotAllowed: "tabulators are not allowed", 
+    errInvalidToken: "invalid token: $1", 
+    errLineTooLong: "line too long", 
+    errInvalidNumber: "$1 is not a valid number", 
+    errNumberOutOfRange: "number $1 out of valid range", 
+    errNnotAllowedInCharacter: "\\n not allowed in character literal", 
+    errClosingBracketExpected: "closing ']' expected, but end of file reached", 
+    errMissingFinalQuote: "missing final \'", 
+    errIdentifierExpected: "identifier expected, but found \'$1\'", 
+    errOperatorExpected: "operator expected, but found \'$1\'", 
+    errTokenExpected: "\'$1\' expected", 
+    errStringAfterIncludeExpected: "string after \'include\' expected", 
+    errRecursiveDependencyX: "recursive dependency: \'$1\'", 
+    errOnOrOffExpected: "\'on\' or \'off\' expected", 
+    errNoneSpeedOrSizeExpected: "\'none\', \'speed\' or \'size\' expected", 
+    errInvalidPragma: "invalid pragma", 
+    errUnknownPragma: "unknown pragma: \'$1\'", 
+    errInvalidDirectiveX: "invalid directive: \'$1\'", 
+    errAtPopWithoutPush: "\'pop\' without a \'push\' pragma", 
+    errEmptyAsm: "empty asm statement", 
+    errInvalidIndentation: "invalid indentation", 
+    errExceptionExpected: "exception expected", 
+    errExceptionAlreadyHandled: "exception already handled", 
+    errYieldNotAllowedHere: "\'yield\' only allowed in a loop of an iterator", 
+    errInvalidNumberOfYieldExpr: "invalid number of \'yield\' expresions", 
+    errCannotReturnExpr: "current routine cannot return an expression", 
+    errAttemptToRedefine: "attempt to redefine \'$1\'", 
+    errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\' or \'raise\'", 
+    errStmtExpected: "statement expected", 
+    errInvalidLabel: "\'$1\' is no label", 
+    errInvalidCmdLineOption: "invalid command line option: \'$1\'", 
+    errCmdLineArgExpected: "argument for command line option expected: \'$1\'", 
+    errCmdLineNoArgExpected: "invalid argument for command line option: \'$1\'", 
+    errInvalidVarSubstitution: "invalid variable substitution in \'$1\'", 
+    errUnknownVar: "unknown variable: \'$1\'", 
+    errUnknownCcompiler: "unknown C compiler: \'$1\'", 
+    errOnOrOffExpectedButXFound: "\'on\' or \'off\' expected, but \'$1\' found", 
+    errNoneBoehmRefcExpectedButXFound: "'none', 'boehm' or 'refc' expected, but '$1' found", 
+    errNoneSpeedOrSizeExpectedButXFound: "'none', 'speed' or 'size' expected, but '$1' found", 
+    errGuiConsoleOrLibExpectedButXFound: "'gui', 'console' or 'lib' expected, but '$1' found", 
+    errUnknownOS: "unknown OS: '$1'", 
+    errUnknownCPU: "unknown CPU: '$1'", 
+    errGenOutExpectedButXFound: "'c', 'c++' or 'yaml' expected, but '$1' found", 
+    errArgsNeedRunOption: "arguments can only be given if the '--run' option is selected", 
+    errInvalidMultipleAsgn: "multiple assignment is not allowed", 
+    errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'", 
+    errExprExpected: "expression expected, but found \'$1\'", 
+    errUndeclaredIdentifier: "undeclared identifier: \'$1\'", 
+    errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier", 
+    errTypeExpected: "type expected", 
+    errSystemNeeds: "system module needs \'$1\'", 
+    errExecutionOfProgramFailed: "execution of an external program failed", 
+    errNotOverloadable: "overloaded \'$1\' leads to ambiguous calls", 
+    errInvalidArgForX: "invalid argument for \'$1\'", 
+    errStmtHasNoEffect: "statement has no effect", 
+    errXExpectsTypeOrValue: "\'$1\' expects a type or value", 
+    errXExpectsArrayType: "\'$1\' expects an array type", 
+    errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet", 
+    errExprXAmbiguous: "expression '$1' ambiguous in this context", 
+    errConstantDivisionByZero: "constant division by zero", 
+    errOrdinalTypeExpected: "ordinal type expected", 
+    errOrdinalOrFloatTypeExpected: "ordinal or float type expected", 
+    errOverOrUnderflow: "over- or underflow", 
+    errCannotEvalXBecauseIncompletelyDefined: "cannot evalutate '$1' because type is not defined completely", 
+    errChrExpectsRange0_255: "\'chr\' expects an int in the range 0..255", 
+    errDynlibRequiresExportc: "\'dynlib\' requires \'exportc\'", 
+    errUndeclaredFieldX: "undeclared field: \'$1\'", 
+    errNilAccess: "attempt to access a nil address",
+    errIndexOutOfBounds: "index out of bounds", 
+    errIndexTypesDoNotMatch: "index types do not match", 
+    errBracketsInvalidForType: "\'[]\' operator invalid for this type", 
+    errValueOutOfSetBounds: "value out of set bounds", 
+    errFieldInitTwice: "field initialized twice: \'$1\'", 
+    errFieldNotInit: "field \'$1\' not initialized", 
+    errExprXCannotBeCalled: "expression \'$1\' cannot be called", 
+    errExprHasNoType: "expression has no type", 
+    errExprXHasNoType: "expression \'$1\' has no type (or is ambiguous)", 
+    errCastNotInSafeMode: "\'cast\' not allowed in safe mode",
+    errExprCannotBeCastedToX: "expression cannot be casted to $1", 
+    errCommaOrParRiExpected: "',' or ')' expected", 
+    errCurlyLeOrParLeExpected: "\'{\' or \'(\' expected", 
+    errSectionExpected: "section (\'type\', \'proc\', etc.) expected", 
+    errRangeExpected: "range expected", 
+    errAttemptToRedefineX: "attempt to redefine \'$1\'", 
+    errMagicOnlyInSystem: "\'magic\' only allowed in system module", 
+    errPowerOfTwoExpected: "power of two expected",
+    errStringMayNotBeEmpty: "string literal may not be empty", 
+    errCallConvExpected: "calling convention expected", 
+    errProcOnlyOneCallConv: "a proc can only have one calling convention", 
+    errSymbolMustBeImported: "symbol must be imported if 'lib' pragma is used", 
+    errExprMustBeBool: "expression must be of type 'bool'", 
+    errConstExprExpected: "constant expression expected", 
+    errDuplicateCaseLabel: "duplicate case label", 
+    errRangeIsEmpty: "range is empty", 
+    errSelectorMustBeOfCertainTypes: "selector must be of an ordinal type, float or string", 
+    errSelectorMustBeOrdinal: "selector must be of an ordinal type", 
+    errOrdXMustNotBeNegative: "ord($1) must not be negative", 
+    errLenXinvalid: "len($1) must be less than 32768",
+    errWrongNumberOfVariables: "wrong number of variables", 
+    errExprCannotBeRaised: "only objects can be raised", 
+    errBreakOnlyInLoop: "'break' only allowed in loop construct", 
+    errTypeXhasUnknownSize: "type \'$1\' has unknown size", 
+    errConstNeedsConstExpr: "a constant can only be initialized with a constant expression", 
+    errConstNeedsValue: "a constant needs a value", 
+    errResultCannotBeOpenArray: "the result type cannot be on open array", 
+    errSizeTooBig: "computing the type\'s size produced an overflow", 
+    errSetTooBig: "set is too large", 
+    errBaseTypeMustBeOrdinal: "base type of a set must be an ordinal", 
+    errInheritanceOnlyWithNonFinalObjects: "inheritance only works with non-final objects", 
+    errInheritanceOnlyWithEnums: "inheritance only works with an enum",
+    errIllegalRecursionInTypeX: "illegal recursion in type \'$1\'", 
+    errCannotInstantiateX: "cannot instantiate: \'$1\'", 
+    errExprHasNoAddress: "expression has no address", 
+    errVarForOutParamNeeded: "for a \'var\' type a variable needs to be passed",
+    errPureTypeMismatch: "type mismatch", 
+    errTypeMismatch: "type mismatch: got (", 
+    errButExpected: "but expected one of: ",
+    errButExpectedX: "but expected \'$1\'", 
+    errAmbiguousCallXYZ: "ambiguous call; both $1 and $2 match for: $3", 
+    errWrongNumberOfArguments: "wrong number of arguments", 
+    errXCannotBePassedToProcVar: "\'$1\' cannot be passed to a procvar", 
+    errXCannotBeInParamDecl: "$1 cannot be declared in parameter declaration", 
+    errPragmaOnlyInHeaderOfProc: "pragmas are only in the header of a proc allowed", 
+    errImplOfXNotAllowed: "implementation of \'$1\' is not allowed", 
+    errImplOfXexpected: "implementation of \'$1\' expected", 
+    errNoSymbolToBorrowFromFound: "no symbol to borrow from found", 
+    errDiscardValue: "value returned by statement has to be discarded", 
+    errInvalidDiscard: "statement returns no value that can be discarded", 
+    errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
+    errCannotBindXTwice: "cannot bind parameter \'$1\' twice", 
+    errInvalidOrderInArrayConstructor: "invalid order in array constructor",
+    errInvalidOrderInEnumX: "invalid order in enum \'$1\'", 
+    errEnumXHasHoles: "enum \'$1\' has holes", 
+    errExceptExpected: "\'except\' or \'finally\' expected", 
+    errInvalidTry: "after catch all \'except\' or \'finally\' no section may follow", 
+    errOptionExpected: "option expected, but found \'$1\'",
+    errXisNoLabel: "\'$1\' is not a label", 
+    errNotAllCasesCovered: "not all cases are covered", 
+    errUnkownSubstitionVar: "unknown substitution variable: \'$1\'", 
+    errComplexStmtRequiresInd: "complex statement requires indentation",
+    errXisNotCallable: "\'$1\' is not callable", 
+    errNoPragmasAllowedForX: "no pragmas allowed for $1", 
+    errNoGenericParamsAllowedForX: "no generic parameters allowed for $1", 
+    errInvalidParamKindX: "invalid param kind: \'$1\'", 
+    errDefaultArgumentInvalid: "default argument invalid", 
+    errNamedParamHasToBeIdent: "named parameter has to be an identifier", 
+    errNoReturnTypeForX: "no return type for $1 allowed", 
+    errConvNeedsOneArg: "a type conversion needs exactly one argument", 
+    errInvalidPragmaX: "invalid pragma: $1", 
+    errXNotAllowedHere: "$1 not allowed here",
+    errInvalidControlFlowX: "invalid control flow: $1",
+    errATypeHasNoValue: "a type has no value", 
+    errXisNoType: "invalid type: \'$1\'",
+    errCircumNeedsPointer: "\'^\' needs a pointer or reference type", 
+    errInvalidExpression: "invalid expression",
+    errInvalidExpressionX: "invalid expression: \'$1\'", 
+    errEnumHasNoValueX: "enum has no value \'$1\'",
+    errNamedExprExpected: "named expression expected", 
+    errNamedExprNotAllowed: "named expression not allowed here", 
+    errXExpectsOneTypeParam: "\'$1\' expects one type parameter", 
+    errArrayExpectsTwoTypeParams: "array expects two type parameters", 
+    errInvalidVisibilityX: "invalid visibility: \'$1\'", 
+    errInitHereNotAllowed: "initialization not allowed here", 
+    errXCannotBeAssignedTo: "\'$1\' cannot be assigned to", 
+    errIteratorNotAllowed: "iterators can only be defined at the module\'s top level", 
+    errXNeedsReturnType: "$1 needs a return type",
+    errInvalidCommandX: "invalid command: \'$1\'", 
+    errXOnlyAtModuleScope: "\'$1\' is only allowed at top level", 
+    errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
+    errTemplateInstantiationTooNested: "template/macro instantiation too nested",
+    errInstantiationFrom: "instantiation from here", 
+    errInvalidIndexValueForTuple: "invalid index value for tuple subscript", 
+    errCommandExpectsFilename: "command expects a filename argument",
+    errXExpected: "\'$1\' expected", 
+    errInvalidSectionStart: "invalid section start",
+    errGridTableNotImplemented: "grid table is not implemented", 
+    errGeneralParseError: "general parse error",
+    errNewSectionExpected: "new section expected", 
+    errWhitespaceExpected: "whitespace expected, got \'$1\'",
+    errXisNoValidIndexFile: "\'$1\' is no valid index file", 
+    errCannotRenderX: "cannot render reStructuredText element \'$1\'", 
+    errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
+    errIsExpectsTwoArguments: "\'is\' expects two arguments", 
+    errIsExpectsObjectTypes: "\'is\' expects object types",
+    errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", 
+    errTooManyIterations: "interpretation requires too many iterations", 
+    errCannotInterpretNodeX: "cannot interpret node kind \'$1\'", 
+    errFieldXNotFound: "field \'$1\' cannot be found", 
+    errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'",
+    errAssertionFailed: "assertion failed", 
+    errCannotGenerateCodeForX: "cannot generate code for \'$1\'", 
+    errXRequiresOneArgument: "$1 requires one parameter", 
+    errUnhandledExceptionX: "unhandled exception: $1", 
+    errCyclicTree: "macro returned a cyclic abstract syntax tree", 
+    errXisNoMacroOrTemplate: "\'$1\' is no macro or template",
+    errXhasSideEffects: "\'$1\' can have side effects", 
+    errIteratorExpected: "iterator within for loop context expected",
+    errUser: "$1", 
+    warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]",
+    warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]", 
+    warnXIsNeverRead: "\'$1\' is never read [XIsNeverRead]", 
+    warnXmightNotBeenInit: "\'$1\' might not have been initialized [XmightNotBeenInit]", 
+    warnCannotWriteMO2: "cannot write file \'$1\' [CannotWriteMO2]", 
+    warnCannotReadMO2: "cannot read file \'$1\' [CannotReadMO2]", 
+    warnDeprecated: "\'$1\' is deprecated [Deprecated]", 
+    warnSmallLshouldNotBeUsed: "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]", 
+    warnUnknownMagic: "unknown magic \'$1\' might crash the compiler [UnknownMagic]", 
+    warnRedefinitionOfLabel: "redefinition of label \'$1\' [RedefinitionOfLabel]", 
+    warnUnknownSubstitutionX: "unknown substitution \'$1\' [UnknownSubstitutionX]", 
+    warnLanguageXNotSupported: "language \'$1\' not supported [LanguageXNotSupported]", 
+    warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]", 
+    warnXisPassedToProcVar: "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]", 
+    warnUser: "$1 [User]", 
+    hintSuccess: "operation successful [Success]", 
+    hintSuccessX: "operation successful ($1 lines compiled; $2 sec total) [SuccessX]", 
+    hintLineTooLong: "line too long [LineTooLong]", 
+    hintXDeclaredButNotUsed: "\'$1\' is declared but not used [XDeclaredButNotUsed]", 
+    hintConvToBaseNotNeeded: "conversion to base object is not needed [ConvToBaseNotNeeded]", 
+    hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]", 
+    hintExprAlwaysX: "expression evaluates always to \'$1\' [ExprAlwaysX]", 
+    hintQuitCalled: "quit() called [QuitCalled]",
+    hintProcessing: "$1 [Processing]", 
+    hintCodeBegin: "generated code listing: [CodeBegin]",
+    hintCodeEnd: "end of listing [CodeEnd]", 
+    hintConf: "used config file \'$1\' [Conf]", 
+    hintPath: "added path: '$1' [Path]",
+    hintUser: "$1 [User]"]
 
 const 
   WarningsToStr*: array[0..14, string] = ["CannotOpenFile", "OctalEscape", 
@@ -353,7 +444,7 @@ proc checkpoint(info: TLineInfo, filename: string, line: int): bool =
       (ChangeFileExt(extractFilename(filenames[info.fileIndex]), "") ==
       filename)
 
-var checkPoints: seq[TLineInfo] = @ []
+var checkPoints: seq[TLineInfo] = @[]
 
 proc addCheckpoint(info: TLineInfo) = 
   var length: int
diff --git a/rod/pas2nim/pasparse.nim b/rod/pas2nim/pasparse.nim
index 427cdc5ef..a84acc100 100755
--- a/rod/pas2nim/pasparse.nim
+++ b/rod/pas2nim/pasparse.nim
@@ -141,7 +141,7 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode
 
 proc parseEmit(p: var TParser, definition: PNode): PNode = 
   getTok(p)                   # skip 'emit'
-  result = nil
+  result = ast.emptyNode
   if p.tok.xkind != pxCurlyDirRi: 
     case p.context
     of conExpr: 
@@ -159,7 +159,7 @@ proc parseEmit(p: var TParser, definition: PNode): PNode =
   eat(p, pxCurlyDirRi)
 
 proc parseCommand(p: var TParser, definition: PNode = nil): PNode = 
-  result = nil
+  result = ast.emptyNode
   getTok(p)
   if p.tok.ident.id == getIdent("discard").id: 
     result = newNodeP(nkDiscardStmt, p)
@@ -170,8 +170,8 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
     getTok(p)
     eat(p, pxCurlyDirRi)
     result = parseExpr(p)
+    if result.kind == nkEmpty: InternalError("emptyNode modified")
     result.kind = nkCurly
-    assert(sonsNotNil(result))
   elif p.tok.ident.id == getIdent("cast").id: 
     getTok(p)
     eat(p, pxCurlyDirRi)
@@ -181,7 +181,7 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
       addSon(result, a.sons[0])
       addSon(result, a.sons[1])
     else: 
-      parMessage(p, errInvalidDirectiveX, $(p.tok))
+      parMessage(p, errInvalidDirectiveX, $p.tok)
       result = a
   elif p.tok.ident.id == getIdent("emit").id: 
     result = parseEmit(p, definition)
@@ -216,12 +216,12 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
     getTok(p)
     eat(p, pxCurlyDirRi)
   else: 
-    parMessage(p, errInvalidDirectiveX, $(p.tok))
+    parMessage(p, errInvalidDirectiveX, $p.tok)
     while true: 
       getTok(p)
-      if (p.tok.xkind == pxCurlyDirRi) or (p.tok.xkind == pxEof): break 
+      if p.tok.xkind == pxCurlyDirRi or p.tok.xkind == pxEof: break 
     eat(p, pxCurlyDirRi)
-    result = nil
+    result = ast.emptyNode
 
 proc getPrecedence(kind: TTokKind): int = 
   case kind
@@ -295,7 +295,7 @@ proc qualifiedIdent(p: var TParser): PNode =
     result = createIdentNodeP(p.tok.ident, p)
   else: 
     parMessage(p, errIdentifierExpected, $p.tok)
-    return nil
+    return ast.emptyNode
   getTok(p)
   skipCom(p, result)
   if p.tok.xkind == pxDot: 
@@ -390,15 +390,15 @@ proc identOrLiteral(p: var TParser): PNode =
   else: 
     parMessage(p, errExprExpected, $(p.tok))
     getTok(p) # we must consume a token here to prevend endless loops!
-    result = nil
-  if result != nil: skipCom(p, result)
+    result = ast.emptyNode
+  if result.kind != nkEmpty: skipCom(p, result)
   
 proc primary(p: var TParser): PNode = 
   # prefix operator?
   if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or
       (p.tok.xkind == pxPlus): 
     result = newNodeP(nkPrefix, p)
-    var a = newIdentNodeP(getIdent($(p.tok)), p)
+    var a = newIdentNodeP(getIdent($p.tok), p)
     addSon(result, a)
     getTok(p)
     skipCom(p, a)
@@ -406,7 +406,7 @@ proc primary(p: var TParser): PNode =
     return 
   elif p.tok.xkind == pxAt: 
     result = newNodeP(nkAddr, p)
-    var a = newIdentNodeP(getIdent($(p.tok)), p)
+    var a = newIdentNodeP(getIdent($p.tok), p)
     getTok(p)
     if p.tok.xkind == pxBracketLe: 
       result = newNodeP(nkPrefix, p)
@@ -433,7 +433,7 @@ proc primary(p: var TParser): PNode =
         addSon(result, createIdentNodeP(p.tok.ident, p))
         getTok(p)
       else: 
-        parMessage(p, errIdentifierExpected, $(p.tok))
+        parMessage(p, errIdentifierExpected, $p.tok)
     of pxHat: 
       var a = result
       result = newNodeP(nkDerefExpr, p)
@@ -490,7 +490,6 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
   
 proc fixExpr(n: PNode): PNode = 
   result = n
-  if n == nil: return 
   case n.kind
   of nkInfix: 
     if n.sons[1].kind == nkBracket: n.sons[1].kind = nkCurly
@@ -559,7 +558,7 @@ proc parseUsesStmt(p: var TParser): PNode =
       skipCom(p, a)
     else: 
       break 
-  if sonsLen(result) == 0: result = nil
+  if sonsLen(result) == 0: result = ast.emptyNode
   
 proc parseIncludeDir(p: var TParser): PNode = 
   result = newNodeP(nkIncludeStmt, p)
@@ -568,7 +567,7 @@ proc parseIncludeDir(p: var TParser): PNode =
   while true: 
     case p.tok.xkind
     of pxSymbol, pxDot, pxDotDot, pxSlash: 
-      filename = filename & $(p.tok)
+      add(filename, $p.tok)
       getTok(p)
     of pxStrLit: 
       filename = p.tok.literal
@@ -577,10 +576,10 @@ proc parseIncludeDir(p: var TParser): PNode =
     of pxCurlyDirRi: 
       break 
     else: 
-      parMessage(p, errIdentifierExpected, $(p.tok))
+      parMessage(p, errIdentifierExpected, $p.tok)
       break 
   addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p))
-  if filename == "config.inc": result = nil
+  if filename == "config.inc": result = ast.emptyNode
   
 proc definedExprAux(p: var TParser): PNode = 
   result = newNodeP(nkCall, p)
@@ -590,7 +589,6 @@ proc definedExprAux(p: var TParser): PNode =
   getTok(p)
 
 proc isHandledDirective(p: TParser): bool = 
-  result = false
   if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: 
     case toLower(p.tok.ident.s)
     of "else", "endif": result = false
@@ -657,7 +655,7 @@ proc parseIfDir(p: var TParser, endMarker: TTokKind): PNode =
   parseIfDirAux(p, result)
 
 proc parseDirective(p: var TParser): PNode = 
-  result = nil
+  result = ast.emptyNode
   if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return 
   var endMarker = succ(p.tok.xkind)
   if p.tok.ident != nil: 
@@ -680,7 +678,7 @@ proc parseRaise(p: var TParser): PNode =
   getTok(p)
   skipCom(p, result)
   if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p))
-  else: addSon(result, nil)
+  else: addSon(result, ast.emptyNode)
   
 proc parseIf(p: var TParser): PNode = 
   result = newNodeP(nkIfStmt, p)
@@ -721,14 +719,14 @@ proc parseRepeat(p: var TParser): PNode =
   skipCom(p, result)
   addSon(result, newIdentNodeP(getIdent("true"), p))
   var s = newNodeP(nkStmtList, p)
-  while (p.tok.xkind != pxEof) and (p.tok.xkind != pxUntil): 
+  while p.tok.xkind != pxEof and p.tok.xkind != pxUntil: 
     addSon(s, parseStmt(p))
   eat(p, pxUntil)
   var a = newNodeP(nkIfStmt, p)
   skipCom(p, a)
   var b = newNodeP(nkElifBranch, p)
   var c = newNodeP(nkBreakStmt, p)
-  addSon(c, nil)
+  addSon(c, ast.emptyNode)
   addSon(b, parseExpr(p))
   skipCom(p, a)
   addSon(b, c)
@@ -809,7 +807,7 @@ proc parseFor(p: var TParser): PNode =
   getTok(p)
   eat(p, pxAsgn)
   var a = parseExpr(p)
-  var b: PNode = nil
+  var b = ast.emptyNode
   var c = newNodeP(nkCall, p)
   if p.tok.xkind == pxTo: 
     addSon(c, newIdentNodeP(getIdent("countup"), p))
@@ -829,9 +827,9 @@ proc parseFor(p: var TParser): PNode =
   addSon(result, parseStmt(p))
 
 proc parseParam(p: var TParser): PNode = 
-  var a, v: PNode
+  var a: PNode
   result = newNodeP(nkIdentDefs, p)
-  v = nil
+  var v = ast.emptyNode
   case p.tok.xkind
   of pxConst: 
     getTok(p)
@@ -848,7 +846,7 @@ proc parseParam(p: var TParser): PNode =
     of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
     of pxColon, pxEof, pxParRi, pxEquals: break 
     else: 
-      parMessage(p, errIdentifierExpected, $(p.tok))
+      parMessage(p, errIdentifierExpected, $p.tok)
       return 
     getTok(p)                 # skip identifier
     skipCom(p, a)
@@ -859,24 +857,24 @@ proc parseParam(p: var TParser): PNode =
   if p.tok.xkind == pxColon: 
     getTok(p)
     skipCom(p, result)
-    if v != nil: addSon(v, parseTypeDesc(p))
+    if v.kind != nkEmpty: addSon(v, parseTypeDesc(p))
     else: v = parseTypeDesc(p)
     addSon(result, v)
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
     if p.tok.xkind != pxEquals: 
-      parMessage(p, errColonOrEqualsExpected, $(p.tok))
+      parMessage(p, errColonOrEqualsExpected, $p.tok)
   if p.tok.xkind == pxEquals: 
     getTok(p)
     skipCom(p, result)
     addSon(result, parseExpr(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   
 proc parseParamList(p: var TParser): PNode = 
   var a: PNode
   result = newNodeP(nkFormalParams, p)
-  addSon(result, nil)         # return type
+  addSon(result, ast.emptyNode)         # return type
   if p.tok.xkind == pxParLe: 
     p.inParamList = true
     getTok(p)
@@ -903,7 +901,7 @@ proc parseParamList(p: var TParser): PNode =
     result.sons[0] = parseTypeDesc(p)
 
 proc parseCallingConvention(p: var TParser): PNode = 
-  result = nil
+  result = ast.emptyNode
   if p.tok.xkind == pxSymbol: 
     case toLower(p.tok.ident.s)
     of "stdcall", "cdecl", "safecall", "syscall", "inline", "fastcall": 
@@ -935,7 +933,7 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
     of "importc": 
       # This is a fake for platform module. There is no ``importc``
       # directive in Pascal.
-      if result == nil: result = newNodeP(nkPragma, p)
+      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
       addSon(result, newIdentNodeP(getIdent("importc"), p))
       noBody = true
       getTok(p)
@@ -943,7 +941,7 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
     of "noconv": 
       # This is a fake for platform module. There is no ``noconv``
       # directive in Pascal.
-      if result == nil: result = newNodeP(nkPragma, p)
+      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
       addSon(result, newIdentNodeP(getIdent("noconv"), p))
       noBody = true
       getTok(p)
@@ -951,17 +949,17 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
     of "procvar": 
       # This is a fake for the Nimrod compiler. There is no ``procvar``
       # directive in Pascal.
-      if result == nil: result = newNodeP(nkPragma, p)
+      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
       addSon(result, newIdentNodeP(getIdent("procvar"), p))
       getTok(p)
       opt(p, pxSemicolon)
     of "varargs": 
-      if result == nil: result = newNodeP(nkPragma, p)
+      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
       addSon(result, newIdentNodeP(getIdent("varargs"), p))
       getTok(p)
       opt(p, pxSemicolon)
     of "external": 
-      if result == nil: result = newNodeP(nkPragma, p)
+      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
       getTok(p)
       noBody = true
       e = newNodeP(nkExprColonExpr, p)
@@ -981,8 +979,8 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
       opt(p, pxSemicolon)
     else: 
       e = parseCallingConvention(p)
-      if e == nil: break 
-      if result == nil: result = newNodeP(nkPragma, p)
+      if e.kind == nkEmpty: break 
+      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
       addSon(result, e.sons[0])
 
 proc parseRoutineType(p: var TParser): PNode = 
@@ -999,7 +997,7 @@ proc parseEnum(p: var TParser): PNode =
   result = newNodeP(nkEnumTy, p)
   getTok(p)
   skipCom(p, result)
-  addSon(result, nil)         # it does not inherit from any enumeration
+  addSon(result, ast.emptyNode) # it does not inherit from any enumeration
   while true: 
     case p.tok.xkind
     of pxEof, pxParRi: break 
@@ -1061,7 +1059,7 @@ proc parseIdentColonEquals(p: var TParser,
     skipCom(p, result)
     addSon(result, parseTypeDesc(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
     if p.tok.xkind != pxEquals: 
       parMessage(p, errColonOrEqualsExpected, $(p.tok))
   if p.tok.xkind == pxEquals: 
@@ -1069,20 +1067,20 @@ proc parseIdentColonEquals(p: var TParser,
     skipCom(p, result)
     addSon(result, parseExpr(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   if p.tok.xkind == pxSemicolon: 
     getTok(p)
     skipCom(p, result)
 
 proc parseRecordCase(p: var TParser): PNode = 
-  var a, b, c: PNode
+  var b, c: PNode
   result = newNodeP(nkRecCase, p)
   getTok(p)
-  a = newNodeP(nkIdentDefs, p)
+  var a = newNodeP(nkIdentDefs, p)
   addSon(a, rawIdent(p))
   eat(p, pxColon)
   addSon(a, parseTypeDesc(p))
-  addSon(a, nil)
+  addSon(a, ast.emptyNode)
   addSon(result, a)
   eat(p, pxOf)
   skipCom(p, result)
@@ -1116,9 +1114,9 @@ proc parseRecordCase(p: var TParser): PNode =
     if b.kind == nkElse: break 
   
 proc parseRecordPart(p: var TParser): PNode = 
-  result = nil
+  result = ast.emptyNode
   while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): 
-    if result == nil: result = newNodeP(nkRecList, p)
+    if result.kind == nkEmpty: result = newNodeP(nkRecList, p)
     case p.tok.xkind
     of pxSymbol: 
       addSon(result, parseIdentColonEquals(p, rawIdent))
@@ -1129,8 +1127,8 @@ proc parseRecordPart(p: var TParser): PNode =
     of pxComment: 
       skipCom(p, lastSon(result))
     else: 
-      parMessage(p, errIdentifierExpected, $(p.tok))
-      break 
+      parMessage(p, errIdentifierExpected, $p.tok)
+      break
 
 proc exSymbol(n: var PNode) = 
   case n.kind
@@ -1146,7 +1144,6 @@ proc exSymbol(n: var PNode) =
   else: internalError(n.info, "exSymbol(): " & $n.kind)
   
 proc fixRecordDef(n: var PNode) = 
-  if n == nil: return 
   case n.kind
   of nkRecCase: 
     fixRecordDef(n.sons[0])
@@ -1157,7 +1154,7 @@ proc fixRecordDef(n: var PNode) =
     for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
   of nkIdentDefs: 
     for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
-  of nkNilLit: nil
+  of nkNilLit, nkEmpty: nil
   else: internalError(n.info, "fixRecordDef(): " & $n.kind)
   
 proc addPragmaToIdent(ident: var PNode, pragma: PNode) = 
@@ -1202,7 +1199,7 @@ proc parseRecordOrObject(p: var TParser, kind: TNodeKind,
                          definition: PNode): PNode = 
   result = newNodeP(kind, p)
   getTok(p)
-  addSon(result, nil)
+  addSon(result, ast.emptyNode)
   if p.tok.xkind == pxParLe: 
     var a = newNodeP(nkOfInherit, p)
     getTok(p)
@@ -1210,7 +1207,7 @@ proc parseRecordOrObject(p: var TParser, kind: TNodeKind,
     addSon(result, a)
     eat(p, pxParRi)
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   parseRecordBody(p, result, definition)
 
 proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode = 
@@ -1234,8 +1231,8 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
         else: addSon(result, a.sons[i])
     else: 
       result = newNodeP(nkObjectTy, p)
-      addSon(result, nil)
-      addSon(result, nil)
+      addSon(result, ast.emptyNode)
+      addSon(result, ast.emptyNode)
       parseRecordBody(p, result, definition)
       if definition != nil: 
         addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p))
@@ -1288,13 +1285,13 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
 proc parseTypeDef(p: var TParser): PNode = 
   result = newNodeP(nkTypeDef, p)
   addSon(result, identVis(p))
-  addSon(result, nil)         # generic params
+  addSon(result, ast.emptyNode)         # generic params
   if p.tok.xkind == pxEquals: 
     getTok(p)
     skipCom(p, result)
     addSon(result, parseTypeDesc(p, result))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   if p.tok.xkind == pxSemicolon: 
     getTok(p)
     skipCom(p, result)
@@ -1314,7 +1311,7 @@ proc parseConstant(p: var TParser): PNode =
     skipCom(p, result)
     addSon(result, parseTypeDesc(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
     if p.tok.xkind != pxEquals: 
       parMessage(p, errColonOrEqualsExpected, $(p.tok))
   if p.tok.xkind == pxEquals: 
@@ -1322,7 +1319,7 @@ proc parseConstant(p: var TParser): PNode =
     skipCom(p, result)
     addSon(result, parseExpr(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   if p.tok.xkind == pxSemicolon: 
     getTok(p)
     skipCom(p, result)
@@ -1349,12 +1346,12 @@ proc parseRoutine(p: var TParser): PNode =
   skipCom(p, result)
   expectIdent(p)
   addSon(result, identVis(p))
-  addSon(result, nil)         # generic parameters
+  addSon(result, ast.emptyNode)         # generic parameters
   addSon(result, parseParamList(p))
   opt(p, pxSemicolon)
   addSon(result, parseRoutineSpecifiers(p, noBody))
   if (p.section == seInterface) or noBody: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   else: 
     var stmts = newNodeP(nkStmtList, p)
     while true: 
@@ -1408,8 +1405,7 @@ proc exSymbols(n: PNode) =
   of nkTypeSection: 
     for i in countup(0, sonsLen(n) - 1): 
       exSymbol(n.sons[i].sons[0])
-      if (n.sons[i].sons[2] != nil) and
-          (n.sons[i].sons[2].kind == nkObjectTy): 
+      if n.sons[i].sons[2].kind == nkObjectTy: 
         fixRecordDef(n.sons[i].sons[2])
   else: nil
 
@@ -1425,13 +1421,15 @@ proc parseBegin(p: var TParser, result: PNode) =
       break 
     of pxSemicolon: getTok(p)
     of pxEof: parMessage(p, errExprExpected)
-    else: addSonIfNotNil(result, parseStmt(p))
+    else: 
+      var a = parseStmt(p)
+      if a.kind != nkEmpty: addSon(result, a)
   if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p))
   
 proc parseStmt(p: var TParser): PNode = 
   var oldcontext = p.context
   p.context = conStmt
-  result = nil
+  result = ast.emptyNode
   case p.tok.xkind
   of pxBegin: 
     result = newNodeP(nkStmtList, p)
@@ -1475,23 +1473,23 @@ proc parseStmt(p: var TParser): PNode =
       result = newNodeP(nkBreakStmt, p)
       getTok(p)
       skipCom(p, result)
-      addSon(result, nil)
+      addSon(result, ast.emptyNode)
     elif p.tok.ident.id == getIdent("continue").id: 
       result = newNodeP(nkContinueStmt, p)
       getTok(p)
       skipCom(p, result)
-      addSon(result, nil)
+      addSon(result, ast.emptyNode)
     elif p.tok.ident.id == getIdent("exit").id: 
       result = newNodeP(nkReturnStmt, p)
       getTok(p)
       skipCom(p, result)
-      addSon(result, nil)
+      addSon(result, ast.emptyNode)
     else: 
       result = parseExprStmt(p)
   of pxDot: getTok(p) # BUGFIX for ``end.`` in main program
   else: result = parseExprStmt(p)
   opt(p, pxSemicolon)
-  if result != nil: skipCom(p, result)
+  if result.kind != nkEmpty: skipCom(p, result)
   p.context = oldcontext
 
 proc parseUnit(p: var TParser): PNode = 
diff --git a/rod/passes.nim b/rod/passes.nim
index e35f4d045..40036cb5a 100755
--- a/rod/passes.nim
+++ b/rod/passes.nim
@@ -104,7 +104,7 @@ proc processTopLevelStmtCached(n: PNode, a: var TPassContextArray) =
     if not isNil(gPasses[i].openCached): m = gPasses[i].process(a[i], m)
   
 proc closePassesCached(a: var TPassContextArray) = 
-  var m: PNode = nil
+  var m = ast.emptyNode
   for i in countup(0, gPassesLen - 1): 
     if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close): 
       m = gPasses[i].close(a[i], m)
@@ -114,7 +114,6 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
                    rd: PRodReader) = 
   var 
     p: TParsers
-    n: PNode
     a: TPassContextArray
     s: PLLStream
   if rd == nil: 
@@ -129,8 +128,8 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
     while true: 
       openParsers(p, filename, s)
       while true: 
-        n = parseTopLevelStmt(p)
-        if n == nil: break 
+        var n = parseTopLevelStmt(p)
+        if n.kind == nkEmpty: break 
         processTopLevelStmt(n, a)
       closeParsers(p)
       if s.kind != llsStdIn: break 
@@ -139,7 +138,7 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
     IDsynchronizationPoint(1000)
   else: 
     openPassesCached(a, module, filename, rd)
-    n = loadInitSection(rd)   #MessageOut('init section' + renderTree(n));
+    var n = loadInitSection(rd)   #MessageOut('init section' + renderTree(n));
     for i in countup(0, sonsLen(n) - 1): processTopLevelStmtCached(n.sons[i], a)
     closePassesCached(a)
 
diff --git a/rod/pnimsyn.nim b/rod/pnimsyn.nim
index 113f47d34..7734d7490 100755
--- a/rod/pnimsyn.nim
+++ b/rod/pnimsyn.nim
@@ -28,8 +28,8 @@ proc ParseAll*(p: var TParser): PNode
 proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
 proc closeParser*(p: var TParser)
 proc parseTopLevelStmt*(p: var TParser): PNode
-  # implements an iterator. Returns the next top-level statement or nil if end
-  # of stream.
+  # implements an iterator. Returns the next top-level statement or
+  # emtyNode if end of stream.
   
 # helpers for the other parsers
 proc getPrecedence*(tok: PToken): int
@@ -94,7 +94,7 @@ proc optInd(p: var TParser, n: PNode) =
   skipInd(p)
 
 proc expectIdentOrKeyw(p: TParser) = 
-  if (p.tok.tokType != tkSymbol) and not isKeyword(p.tok.tokType): 
+  if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType): 
     lexMessage(p.lex^, errIdentifierExpected, tokToStr(p.tok))
   
 proc ExpectIdent(p: TParser) = 
@@ -217,18 +217,17 @@ proc parseSymbol(p: var TParser): PNode =
         addSon(result, newIdentNodeP(id, p))
     else: 
       parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-      result = nil
+      result = ast.emptyNode
     eat(p, tkAccent)
   else: 
     parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-    result = nil
+    result = ast.emptyNode
 
 proc accExpr(p: var TParser): PNode = 
-  var x, y: PNode
   result = newNodeP(nkAccQuoted, p)
   getTok(p)                   # skip `
-  x = nil
-  y = nil
+  var x = ast.emptyNode
+  var y = ast.emptyNode
   case p.tok.tokType
   of tkSymbol, tkOpr, tokKeywordLow..tokKeywordHigh: 
     x = newIdentNodeP(p.tok.ident, p)
@@ -255,9 +254,9 @@ proc optExpr(p: var TParser): PNode =
       (p.tok.tokType != tkDotDot): 
     result = parseExpr(p)
   else: 
-    result = nil
+    result = ast.emptyNode
   
-proc dotdotExpr(p: var TParser, first: PNode = nil): PNode = 
+proc dotdotExpr(p: var TParser, first: PNode): PNode = 
   result = newNodeP(nkRange, p)
   addSon(result, first)
   getTok(p)
@@ -266,20 +265,19 @@ proc dotdotExpr(p: var TParser, first: PNode = nil): PNode =
 
 proc indexExpr(p: var TParser): PNode = 
   # indexExpr ::= '..' [expr] | expr ['=' expr | '..' expr]
-  var a, b: PNode
   if p.tok.tokType == tkDotDot: 
-    result = dotdotExpr(p)
+    result = dotdotExpr(p, ast.emptyNode)
   else: 
-    a = parseExpr(p)
+    var a = parseExpr(p)
     case p.tok.tokType
     of tkEquals: 
       result = newNodeP(nkExprEqExpr, p)
       addSon(result, a)
       getTok(p)
       if p.tok.tokType == tkDotDot: 
-        addSon(result, dotdotExpr(p))
+        addSon(result, dotdotExpr(p, ast.emptyNode))
       else: 
-        b = parseExpr(p)
+        var b = parseExpr(p)
         if p.tok.tokType == tkDotDot: b = dotdotExpr(p, b)
         addSon(result, b)
     of tkDotDot: 
@@ -305,7 +303,8 @@ proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode =
   var a = parseExpr(p)
   if p.tok.tokType == tok: 
     result = newNodeP(kind, p)
-    getTok(p)                 #optInd(p, result);
+    getTok(p)
+    #optInd(p, result)
     addSon(result, a)
     addSon(result, parseExpr(p))
   else: 
@@ -481,14 +480,13 @@ proc identOrLiteral(p: var TParser): PNode =
   else: 
     parMessage(p, errExprExpected, tokToStr(p.tok))
     getTok(p)  # we must consume a token here to prevend endless loops!
-    result = nil
+    result = ast.emptyNode
 
 proc primary(p: var TParser): PNode = 
-  var a: PNode
   # prefix operator?
   if (p.tok.tokType == tkNot) or (p.tok.tokType == tkOpr): 
     result = newNodeP(nkPrefix, p)
-    a = newIdentNodeP(p.tok.ident, p)
+    var a = newIdentNodeP(p.tok.ident, p)
     addSon(result, a)
     getTok(p)
     optInd(p, a)
@@ -504,12 +502,12 @@ proc primary(p: var TParser): PNode =
   while true: 
     case p.tok.tokType
     of tkParLe: 
-      a = result
+      var a = result
       result = newNodeP(nkCall, p)
       addSon(result, a)
       exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
     of tkDot: 
-      a = result
+      var a = result
       result = newNodeP(nkDotExpr, p)
       addSon(result, a)
       getTok(p)               # skip '.'
@@ -517,7 +515,7 @@ proc primary(p: var TParser): PNode =
       addSon(result, parseSymbol(p))
       result = parseGStrLit(p, result)
     of tkHat: 
-      a = result
+      var a = result
       result = newNodeP(nkDerefExpr, p)
       addSon(result, a)
       getTok(p)
@@ -549,30 +547,28 @@ proc lowestExpr(p: var TParser): PNode =
   discard lowestExprAux(p, result, - 1)
 
 proc parseIfExpr(p: var TParser): PNode = 
-  var branch: PNode
   result = newNodeP(nkIfExpr, p)
   while true: 
     getTok(p)                 # skip `if`, `elif`
-    branch = newNodeP(nkElifExpr, p)
+    var branch = newNodeP(nkElifExpr, p)
     addSon(branch, parseExpr(p))
     eat(p, tkColon)
     addSon(branch, parseExpr(p))
     addSon(result, branch)
     if p.tok.tokType != tkElif: break 
-  branch = newNodeP(nkElseExpr, p)
+  var branch = newNodeP(nkElseExpr, p)
   eat(p, tkElse)
   eat(p, tkColon)
   addSon(branch, parseExpr(p))
   addSon(result, branch)
 
 proc parsePragma(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkPragma, p)
   getTok(p)
   optInd(p, result)
   while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
       (p.tok.tokType != tkEof) and (p.tok.tokType != tkSad): 
-    a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
+    var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
     addSon(result, a)
     if p.tok.tokType == tkComma: 
       getTok(p)
@@ -583,8 +579,7 @@ proc parsePragma(p: var TParser): PNode =
   
 proc identVis(p: var TParser): PNode = 
   # identifier with visability
-  var a: PNode
-  a = parseSymbol(p)
+  var a = parseSymbol(p)
   if p.tok.tokType == tkOpr: 
     result = newNodeP(nkPostfix, p)
     addSon(result, newIdentNodeP(p.tok.ident, p))
@@ -594,8 +589,7 @@ proc identVis(p: var TParser): PNode =
     result = a
   
 proc identWithPragma(p: var TParser): PNode = 
-  var a: PNode
-  a = identVis(p)
+  var a = identVis(p)
   if p.tok.tokType == tkCurlyDotLe: 
     result = newNodeP(nkPragmaExpr, p)
     addSon(result, a)
@@ -617,7 +611,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
     of tkSymbol, tkAccent: 
       if withPragma in flags: a = identWithPragma(p)
       else: a = parseSymbol(p)
-      if a == nil: return 
+      if a.kind == nkEmpty: return 
     else: break 
     addSon(result, a)
     if p.tok.tokType != tkComma: break 
@@ -628,7 +622,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
     optInd(p, result)
     addSon(result, parseTypeDesc(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
     if (p.tok.tokType != tkEquals) and not (withBothOptional in flags): 
       parMessage(p, errColonOrEqualsExpected, tokToStr(p.tok))
   if p.tok.tokType == tkEquals: 
@@ -636,16 +630,15 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
     optInd(p, result)
     addSon(result, parseExpr(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   
 proc parseTuple(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkTupleTy, p)
   getTok(p)
   eat(p, tkBracketLe)
   optInd(p, result)
   while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent): 
-    a = parseIdentColonEquals(p, {})
+    var a = parseIdentColonEquals(p, {})
     addSon(result, a)
     if p.tok.tokType != tkComma: break 
     getTok(p)
@@ -656,7 +649,7 @@ proc parseTuple(p: var TParser): PNode =
 proc parseParamList(p: var TParser): PNode = 
   var a: PNode
   result = newNodeP(nkFormalParams, p)
-  addSon(result, nil)         # return type
+  addSon(result, ast.emptyNode) # return type
   if p.tok.tokType == tkParLe: 
     getTok(p)
     optInd(p, result)
@@ -689,11 +682,11 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
   getTok(p)
   params = parseParamList(p)
   if p.tok.tokType == tkCurlyDotLe: pragmas = parsePragma(p)
-  else: pragmas = nil
+  else: pragmas = ast.emptyNode
   if (p.tok.tokType == tkEquals) and isExpr: 
     result = newNodeI(nkLambda, info)
-    addSon(result, nil)       # no name part
-    addSon(result, nil)       # no generic parameters
+    addSon(result, ast.emptyNode)       # no name part
+    addSon(result, ast.emptyNode)       # no generic parameters
     addSon(result, params)
     addSon(result, pragmas)
     getTok(p)
@@ -744,12 +737,11 @@ proc isExprStart(p: TParser): bool =
   else: result = false
   
 proc parseExprStmt(p: var TParser): PNode = 
-  var a, b, e: PNode
-  a = lowestExpr(p)
+  var a = lowestExpr(p)
   if p.tok.tokType == tkEquals: 
     getTok(p)
     optInd(p, result)
-    b = parseExpr(p)
+    var b = parseExpr(p)
     result = newNodeI(nkAsgn, a.info)
     addSon(result, a)
     addSon(result, b)
@@ -759,7 +751,7 @@ proc parseExprStmt(p: var TParser): PNode =
     addSon(result, a)
     while true: 
       if not isExprStart(p): break 
-      e = parseExpr(p)
+      var e = parseExpr(p)
       addSon(result, e)
       if p.tok.tokType != tkComma: break 
       getTok(p)
@@ -778,6 +770,7 @@ proc parseExprStmt(p: var TParser): PNode =
         addSon(result, parseStmt(p))
       while true: 
         if p.tok.tokType == tkSad: getTok(p)
+        var b: PNode
         case p.tok.tokType
         of tkOf: 
           b = newNodeP(nkOfBranch, p)
@@ -871,7 +864,7 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
   getTok(p)
   optInd(p, result)
   case p.tok.tokType
-  of tkEof, tkSad, tkDed: addSon(result, nil)
+  of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode)
   else: addSon(result, parseExpr(p))
   
 proc parseYieldOrDiscard(p: var TParser, kind: TNodeKind): PNode = 
@@ -885,15 +878,14 @@ proc parseBreakOrContinue(p: var TParser, kind: TNodeKind): PNode =
   getTok(p)
   optInd(p, result)
   case p.tok.tokType
-  of tkEof, tkSad, tkDed: addSon(result, nil)
+  of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode)
   else: addSon(result, parseSymbol(p))
   
 proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode = 
-  var branch: PNode
   result = newNodeP(kind, p)
   while true: 
     getTok(p)                 # skip `if`, `when`, `elif`
-    branch = newNodeP(nkElifBranch, p)
+    var branch = newNodeP(nkElifBranch, p)
     optInd(p, branch)
     addSon(branch, parseExpr(p))
     eat(p, tkColon)
@@ -903,7 +895,7 @@ proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
     addSon(result, branch)
     if p.tok.tokType != tkElif: break 
   if p.tok.tokType == tkElse: 
-    branch = newNodeP(nkElse, p)
+    var branch = newNodeP(nkElse, p)
     eat(p, tkElse)
     eat(p, tkColon)
     skipComment(p, branch)
@@ -954,13 +946,12 @@ proc parseCase(p: var TParser): PNode =
     if b.kind == nkElse: break 
   
 proc parseTry(p: var TParser): PNode = 
-  var b: PNode
   result = newNodeP(nkTryStmt, p)
   getTok(p)
   eat(p, tkColon)
   skipComment(p, result)
   addSon(result, parseStmt(p))
-  b = nil
+  var b: PNode = nil
   while true: 
     if p.tok.tokType == tkSad: getTok(p)
     case p.tok.tokType
@@ -979,11 +970,10 @@ proc parseTry(p: var TParser): PNode =
   if b == nil: parMessage(p, errTokenExpected, "except")
   
 proc parseFor(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkForStmt, p)
   getTok(p)
   optInd(p, result)
-  a = parseSymbol(p)
+  var a = parseSymbol(p)
   addSon(result, a)
   while p.tok.tokType == tkComma: 
     getTok(p)
@@ -1001,7 +991,7 @@ proc parseBlock(p: var TParser): PNode =
   getTok(p)
   optInd(p, result)
   case p.tok.tokType
-  of tkEof, tkSad, tkDed, tkColon: addSon(result, nil)
+  of tkEof, tkSad, tkDed, tkColon: addSon(result, ast.emptyNode)
   else: addSon(result, parseSymbol(p))
   eat(p, tkColon)
   skipComment(p, result)
@@ -1012,7 +1002,7 @@ proc parseAsm(p: var TParser): PNode =
   getTok(p)
   optInd(p, result)
   if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
-  else: addSon(result, nil)
+  else: addSon(result, ast.emptyNode)
   case p.tok.tokType
   of tkStrLit: addSon(result, newStrNodeP(nkStrLit, p.tok.literal, p))
   of tkRStrLit: addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p))
@@ -1020,17 +1010,16 @@ proc parseAsm(p: var TParser): PNode =
                             newStrNodeP(nkTripleStrLit, p.tok.literal, p))
   else: 
     parMessage(p, errStringLiteralExpected)
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
     return 
   getTok(p)
 
 proc parseGenericParamList(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkGenericParams, p)
   getTok(p)
   optInd(p, result)
   while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent): 
-    a = parseIdentColonEquals(p, {withBothOptional})
+    var a = parseIdentColonEquals(p, {withBothOptional})
     addSon(result, a)
     if p.tok.tokType != tkComma: break 
     getTok(p)
@@ -1044,16 +1033,16 @@ proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
   optInd(p, result)
   addSon(result, identVis(p))
   if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
-  else: addSon(result, nil)
+  else: addSon(result, ast.emptyNode)
   addSon(result, parseParamList(p))
   if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
-  else: addSon(result, nil)
+  else: addSon(result, ast.emptyNode)
   if p.tok.tokType == tkEquals: 
     getTok(p)
     skipComment(p, result)
     addSon(result, parseStmt(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   indAndComment(p, result)    # XXX: document this in the grammar!
   
 proc newCommentStmt(p: var TParser): PNode = 
@@ -1065,13 +1054,12 @@ type
 
 proc parseSection(p: var TParser, kind: TNodeKind, 
                   defparser: TDefParser): PNode = 
-  var a: PNode
   result = newNodeP(kind, p)
   getTok(p)
   skipComment(p, result)
   case p.tok.tokType
   of tkInd: 
-    pushInd(p.lex^ , p.tok.indent)
+    pushInd(p.lex^, p.tok.indent)
     getTok(p)
     skipComment(p, result)
     while true: 
@@ -1079,7 +1067,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
       of tkSad: 
         getTok(p)
       of tkSymbol, tkAccent: 
-        a = defparser(p)
+        var a = defparser(p)
         skipComment(p, a)
         addSon(result, a)
       of tkDed: 
@@ -1088,13 +1076,13 @@ proc parseSection(p: var TParser, kind: TNodeKind,
       of tkEof: 
         break                 # BUGFIX
       of tkComment: 
-        a = newCommentStmt(p)
+        var a = newCommentStmt(p)
         skipComment(p, a)
         addSon(result, a)
       else: 
         parMessage(p, errIdentifierExpected, tokToStr(p.tok))
         break 
-    popInd(p.lex^ )
+    popInd(p.lex^)
   of tkSymbol, tkAccent, tkParLe: 
     # tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
     addSon(result, defparser(p))
@@ -1108,7 +1096,7 @@ proc parseConstant(p: var TParser): PNode =
     optInd(p, result)
     addSon(result, parseTypeDesc(p))
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   eat(p, tkEquals)
   optInd(p, result)
   addSon(result, parseExpr(p))
@@ -1126,7 +1114,7 @@ proc parseEnum(p: var TParser): PNode =
     addSon(a, parseTypeDesc(p))
     addSon(result, a)
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   optInd(p, result)
   while true: 
     case p.tok.tokType
@@ -1148,11 +1136,10 @@ proc parseEnum(p: var TParser): PNode =
 
 proc parseObjectPart(p: var TParser): PNode
 proc parseObjectWhen(p: var TParser): PNode = 
-  var branch: PNode
   result = newNodeP(nkRecWhen, p)
   while true: 
     getTok(p)                 # skip `when`, `elif`
-    branch = newNodeP(nkElifBranch, p)
+    var branch = newNodeP(nkElifBranch, p)
     optInd(p, branch)
     addSon(branch, parseExpr(p))
     eat(p, tkColon)
@@ -1162,7 +1149,7 @@ proc parseObjectWhen(p: var TParser): PNode =
     addSon(result, branch)
     if p.tok.tokType != tkElif: break 
   if p.tok.tokType == tkElse: 
-    branch = newNodeP(nkElse, p)
+    var branch = newNodeP(nkElse, p)
     eat(p, tkElse)
     eat(p, tkColon)
     skipComment(p, branch)
@@ -1170,18 +1157,18 @@ proc parseObjectWhen(p: var TParser): PNode =
     addSon(result, branch)
 
 proc parseObjectCase(p: var TParser): PNode = 
-  var a, b: PNode
   result = newNodeP(nkRecCase, p)
   getTok(p)
-  a = newNodeP(nkIdentDefs, p)
+  var a = newNodeP(nkIdentDefs, p)
   addSon(a, identWithPragma(p))
   eat(p, tkColon)
   addSon(a, parseTypeDesc(p))
-  addSon(a, nil)
+  addSon(a, ast.emptyNode)
   addSon(result, a)
   skipComment(p, result)
   while true: 
     if p.tok.tokType == tkSad: getTok(p)
+    var b: PNode
     case p.tok.tokType
     of tkOf: 
       b = newNodeP(nkOfBranch, p)
@@ -1200,7 +1187,7 @@ proc parseObjectPart(p: var TParser): PNode =
   case p.tok.tokType
   of tkInd: 
     result = newNodeP(nkRecList, p)
-    pushInd(p.lex^ , p.tok.indent)
+    pushInd(p.lex^, p.tok.indent)
     getTok(p)
     skipComment(p, result)
     while true: 
@@ -1228,21 +1215,20 @@ proc parseObjectPart(p: var TParser): PNode =
   of tkNil: 
     result = newNodeP(nkNilLit, p)
     getTok(p)
-  else: result = nil
+  else: result = ast.emptyNode
   
 proc parseObject(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkObjectTy, p)
   getTok(p)
   if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
-  else: addSon(result, nil)
+  else: addSon(result, ast.emptyNode)
   if p.tok.tokType == tkOf: 
-    a = newNodeP(nkOfInherit, p)
+    var a = newNodeP(nkOfInherit, p)
     getTok(p)
     addSon(a, parseTypeDesc(p))
     addSon(result, a)
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   skipComment(p, result)
   addSon(result, parseObjectPart(p))
 
@@ -1253,14 +1239,14 @@ proc parseDistinct(p: var TParser): PNode =
   addSon(result, parseTypeDesc(p))
 
 proc parseTypeDef(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkTypeDef, p)
   addSon(result, identWithPragma(p))
   if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
-  else: addSon(result, nil)
+  else: addSon(result, ast.emptyNode)
   if p.tok.tokType == tkEquals: 
     getTok(p)
     optInd(p, result)
+    var a: PNode
     case p.tok.tokType
     of tkObject: a = parseObject(p)
     of tkEnum: a = parseEnum(p)
@@ -1268,21 +1254,20 @@ proc parseTypeDef(p: var TParser): PNode =
     else: a = parseTypeDesc(p)
     addSon(result, a)
   else: 
-    addSon(result, nil)
+    addSon(result, ast.emptyNode)
   indAndComment(p, result)    # special extension!
   
 proc parseVarTuple(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkVarTuple, p)
   getTok(p)                   # skip '('
   optInd(p, result)
   while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent): 
-    a = identWithPragma(p)
+    var a = identWithPragma(p)
     addSon(result, a)
     if p.tok.tokType != tkComma: break 
     getTok(p)
     optInd(p, a)
-  addSon(result, nil)         # no type desc
+  addSon(result, ast.emptyNode)         # no type desc
   optPar(p)
   eat(p, tkParRi)
   eat(p, tkEquals)
@@ -1309,8 +1294,8 @@ proc simpleStmt(p: var TParser): PNode =
   of tkComment: result = newCommentStmt(p)
   else: 
     if isExprStart(p): result = parseExprStmt(p)
-    else: result = nil
-  if result != nil: skipComment(p, result)
+    else: result = ast.emptyNode
+  if result.kind != nkEmpty: skipComment(p, result)
   
 proc complexOrSimpleStmt(p: var TParser): PNode = 
   case p.tok.tokType
@@ -1334,10 +1319,9 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
   else: result = simpleStmt(p)
   
 proc parseStmt(p: var TParser): PNode = 
-  var a: PNode
   if p.tok.tokType == tkInd: 
     result = newNodeP(nkStmtList, p)
-    pushInd(p.lex^ , p.tok.indent)
+    pushInd(p.lex^, p.tok.indent)
     getTok(p)
     while true: 
       case p.tok.tokType
@@ -1347,8 +1331,8 @@ proc parseStmt(p: var TParser): PNode =
         getTok(p)
         break 
       else: 
-        a = complexOrSimpleStmt(p)
-        if a == nil: break 
+        var a = complexOrSimpleStmt(p)
+        if a.kind == nkEmpty: break 
         addSon(result, a)
     popInd(p.lex^ )
   else: 
@@ -1357,14 +1341,13 @@ proc parseStmt(p: var TParser): PNode =
     of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkIterator, 
        tkMacro, tkType, tkConst, tkWhen, tkVar: 
       parMessage(p, errComplexStmtRequiresInd)
-      result = nil
+      result = ast.emptyNode
     else: 
       result = simpleStmt(p)
-      if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
+      if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
       if p.tok.tokType == tkSad: getTok(p)
   
 proc parseAll(p: var TParser): PNode = 
-  var a: PNode
   result = newNodeP(nkStmtList, p)
   while true: 
     case p.tok.tokType
@@ -1372,20 +1355,20 @@ proc parseAll(p: var TParser): PNode =
     of tkDed, tkInd: parMessage(p, errInvalidIndentation)
     of tkEof: break 
     else: 
-      a = complexOrSimpleStmt(p)
-      if a == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
+      var a = complexOrSimpleStmt(p)
+      if a.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
       addSon(result, a)
 
 proc parseTopLevelStmt(p: var TParser): PNode = 
-  result = nil
+  result = ast.emptyNode
   while true: 
     case p.tok.tokType
     of tkSad: getTok(p)
     of tkDed, tkInd: 
       parMessage(p, errInvalidIndentation)
-      break 
+      getTok(p)
     of tkEof: break 
     else: 
       result = complexOrSimpleStmt(p)
-      if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
+      if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
       break 
diff --git a/rod/rnimsyn.nim b/rod/rnimsyn.nim
index 9424c4519..43b5f4800 100755
--- a/rod/rnimsyn.nim
+++ b/rod/rnimsyn.nim
@@ -323,13 +323,13 @@ proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int =
   
 proc lsub(n: PNode): int = 
   # computes the length of a tree
-  if n == nil: return 0
   if n.comment != nil: return maxLineLen + 1
   case n.kind
+  of nkEmpty: result = 0
   of nkTripleStrLit: 
     if containsNL(n.strVal): result = maxLineLen + 1
     else: result = len(atom(n))
-  of nkEmpty..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit: 
+  of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit: 
     result = len(atom(n))
   of nkCall, nkBracketExpr, nkConv: result = lsub(n.sons[0]) + lcomma(n, 1) + 2
   of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
@@ -348,8 +348,8 @@ proc lsub(n: PNode): int =
   of nkConstDef, nkIdentDefs: 
     result = lcomma(n, 0, - 3)
     var L = sonsLen(n)
-    if n.sons[L - 2] != nil: result = result + lsub(n.sons[L - 2]) + 2
-    if n.sons[L - 1] != nil: result = result + lsub(n.sons[L - 1]) + 3
+    if n.sons[L - 2].kind != nkEmpty: result = result + lsub(n.sons[L - 2]) + 2
+    if n.sons[L - 1].kind != nkEmpty: result = result + lsub(n.sons[L - 1]) + 3
   of nkVarTuple: result = lcomma(n, 0, - 3) + len("() = ") + lsub(lastSon(n))
   of nkChckRangeF: result = len("chckRangeF") + 2 + lcomma(n)
   of nkChckRange64: result = len("chckRange64") + 2 + lcomma(n)
@@ -401,7 +401,7 @@ proc lsub(n: PNode): int =
   of nkGenericParams: result = lcomma(n) + 2
   of nkFormalParams: 
     result = lcomma(n, 1) + 2
-    if n.sons[0] != nil: result = result + lsub(n.sons[0]) + 2
+    if n.sons[0].kind != nkEmpty: result = result + lsub(n.sons[0]) + 2
   of nkExceptBranch: 
     result = lcomma(n, 0, -2) + lsub(lastSon(n)) + len("except_:_")
   else: result = maxLineLen + 1
@@ -430,7 +430,6 @@ proc gsub(g: var TSrcGen, n: PNode) =
 
 proc hasCom(n: PNode): bool = 
   result = false
-  if n == nil: return 
   if n.comment != nil: return true
   case n.kind
   of nkEmpty..nkNilLit: nil
@@ -496,7 +495,7 @@ proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool =
         break 
 
 proc gstmts(g: var TSrcGen, n: PNode, c: TContext) = 
-  if n == nil: return 
+  if n.kind == nkEmpty: return 
   if (n.kind == nkStmtList) or (n.kind == nkStmtListExpr): 
     indentNL(g)
     for i in countup(0, sonsLen(n) - 1): 
@@ -598,7 +597,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
   gsub(g, n.sons[2])
   gsub(g, n.sons[3])
   if not (renderNoBody in g.flags): 
-    if n.sons[4] != nil: 
+    if n.sons[4].kind != nkEmpty: 
       put(g, tkSpaces, Space)
       putWithSpace(g, tkEquals, "=")
       indentNL(g)
@@ -615,7 +614,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
 proc gblock(g: var TSrcGen, n: PNode) = 
   var c: TContext
   initContext(c)
-  if n.sons[0] != nil:
+  if n.sons[0].kind != nkEmpty:
     putWithSpace(g, tkBlock, "block")
     gsub(g, n.sons[0])
   else:
@@ -656,11 +655,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   var 
     L: int
     a: TContext
-  if n == nil: return 
   if n.comment != nil: pushCom(g, n)
   case n.kind                 # atoms:
   of nkTripleStrLit: putRawStr(g, tkTripleStrLit, n.strVal)
-  of nkEmpty, nkType: put(g, tkInvalid, atom(n))
+  of nkEmpty: nil
+  of nkType: put(g, tkInvalid, atom(n))
   of nkSym, nkIdent: gident(g, n)
   of nkIntLit: put(g, tkIntLit, atom(n))
   of nkInt8Lit: put(g, tkInt8Lit, atom(n))
@@ -765,7 +764,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: 
     gsub(g, n.sons[0])
   of nkLambda: 
-    assert(n.sons[genericParamsPos] == nil)
+    assert(n.sons[genericParamsPos].kind == nkEmpty)
     putWithSpace(g, tkLambda, "lambda")
     gsub(g, n.sons[paramsPos])
     gsub(g, n.sons[pragmasPos])
@@ -775,10 +774,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkConstDef, nkIdentDefs: 
     gcomma(g, n, 0, - 3)
     var L = sonsLen(n)
-    if n.sons[L - 2] != nil: 
+    if n.sons[L - 2].kind != nkEmpty: 
       putWithSpace(g, tkColon, ":")
       gsub(g, n.sons[L - 2])
-    if n.sons[L - 1] != nil: 
+    if n.sons[L - 1].kind != nkEmpty: 
       put(g, tkSpaces, Space)
       putWithSpace(g, tkEquals, "=")
       gsub(g, n.sons[L - 1], c)
@@ -855,7 +854,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     gsub(g, n.sons[0])
     gsub(g, n.sons[1])
     put(g, tkSpaces, Space)
-    if n.sons[2] != nil: 
+    if n.sons[2].kind != nkEmpty: 
       putWithSpace(g, tkEquals, "=")
       gsub(g, n.sons[2])
   of nkObjectTy: 
@@ -1029,7 +1028,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     put(g, tkParLe, "(")
     gcomma(g, n, 1)
     put(g, tkParRi, ")")
-    if n.sons[0] != nil: 
+    if n.sons[0].kind != nkEmpty: 
       putWithSpace(g, tkColon, ":")
       gsub(g, n.sons[0])
   of nkTupleTy: 
@@ -1055,10 +1054,9 @@ proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) =
   for i in countup(0, sonsLen(n) - 1): 
     gsub(g, n.sons[i])
     optNL(g)
-    if n.sons[i] != nil: 
-      case n.sons[i].kind
-      of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
-      else: nil
+    case n.sons[i].kind
+    of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
+    else: nil
   gcoms(g)
   if open(f, filename, fmWrite): 
     write(f, g.buf)
diff --git a/rod/scanner.nim b/rod/scanner.nim
index f40b8769d..1ef688dd3 100755
--- a/rod/scanner.nim
+++ b/rod/scanner.nim
@@ -175,7 +175,6 @@ proc findIdent(L: TLexer, indent: int): bool =
   for i in countdown(len(L.indentStack) - 1, 0): 
     if L.indentStack[i] == indent: 
       return true
-  result = false
 
 proc tokToStr(tok: PToken): string = 
   case tok.tokType
@@ -574,7 +573,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
     of '_': 
       if buf[pos+1] notin SymChars: 
         lexMessage(L, errInvalidToken, "_")
-        return
+        break
     else: break 
     Inc(pos)
   h = h +% h shl 3
@@ -587,11 +586,6 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
     tok.tokType = tkSymbol
   else: 
     tok.tokType = TTokType(tok.ident.id + ord(tkSymbol))
-  when false:
-    if buf[pos] == '\"': 
-      getString(L, tok, true)
-      if tok.tokType == tkRStrLit: tok.tokType = tkCallRStrLit
-      else: tok.tokType = tkCallTripleStrLit
   
 proc getOperator(L: var TLexer, tok: var TToken) = 
   var pos = L.bufpos
diff --git a/rod/semtypes.nim b/rod/semtypes.nim
index 0fb359170..8585c70a4 100755
--- a/rod/semtypes.nim
+++ b/rod/semtypes.nim
@@ -133,7 +133,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
       {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): 
     liMessage(n.info, errOrdinalTypeExpected)
   if enumHasWholes(a.typ): 
-    liMessage(n.info, errEnumXHasWholes, a.typ.sym.name.s)
+    liMessage(n.info, errEnumXHasHoles, a.typ.sym.name.s)
   if not leValue(a, b): liMessage(n.Info, errRangeIsEmpty)
   addSon(result.n, a)
   addSon(result.n, b)
@@ -160,7 +160,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
       if not isOrdinalType(indx): 
         liMessage(n.sons[1].info, errOrdinalTypeExpected)
       if enumHasWholes(indx): 
-        liMessage(n.sons[1].info, errEnumXHasWholes, indx.sym.name.s)
+        liMessage(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
     base = semTypeNode(c, n.sons[2], nil)
     addSon(result, base)
   else: 
diff --git a/rod/syntaxes.nim b/rod/syntaxes.nim
index 9361ad2ff..e7217950c 100755
--- a/rod/syntaxes.nim
+++ b/rod/syntaxes.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.
@@ -59,6 +59,7 @@ proc parseAll(p: var TParsers): PNode =
     result = pbraces.parseAll(p.parser)
   of skinEndX: 
     InternalError("parser to implement") 
+    result = ast.emptyNode
     # skinEndX: result := pendx.parseAll(p.parser);
   
 proc parseTopLevelStmt(p: var TParsers): PNode = 
@@ -69,6 +70,7 @@ proc parseTopLevelStmt(p: var TParsers): PNode =
     result = pbraces.parseTopLevelStmt(p.parser)
   of skinEndX: 
     InternalError("parser to implement") 
+    result = ast.emptyNode
     #skinEndX: result := pendx.parseTopLevelStmt(p.parser);
   
 proc UTF8_BOM(s: string): int = 
@@ -84,6 +86,7 @@ proc containsShebang(s: string, i: int): bool =
     result = s[j] == '/'
 
 proc parsePipe(filename: string, inputStream: PLLStream): PNode = 
+  result = ast.emptyNode
   var s = LLStreamOpen(filename, fmRead)
   if s != nil: 
     var line = LLStreamReadLine(s)
@@ -143,7 +146,7 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string,
 proc evalPipe(p: var TParsers, n: PNode, filename: string, 
               start: PLLStream): PLLStream = 
   result = start
-  if n == nil: return 
+  if n.kind == nkEmpty: return 
   if (n.kind == nkInfix) and (n.sons[0].kind == nkIdent) and
       IdentEq(n.sons[0].ident, "|"): 
     for i in countup(1, 2): 
diff --git a/todo.txt b/todo.txt
index 73f598fd9..476eb01e9 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,3 +1,8 @@
+- ban ``nil`` from the AST. This might also fix bugs concerning macros.
+  TODO: 
+    * semantic checking (keep in mind incremental parsing!)
+    * code generators
+
 - thread support: threadvar on Windows seems broken; 
   add --deadlock_prevention:on|off switch
 - built-in serialization
@@ -68,7 +73,6 @@ Low priority
 - fast assignment optimization for TPeg
 - better error messages for used keywords as identifiers
 - case statement branches should support constant sets
-- ban ``nil`` from the AST. This might also fix bugs concerning macros.
 
 
 Library