summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-07-15 09:37:45 +0200
committerAraq <rumpf_a@web.de>2014-07-15 09:37:45 +0200
commit6d3b632b47d626f6915dc2cbef8745baf04b8d76 (patch)
treecd2097090977d241065d1415bc9d0845689063f8 /compiler
parent41bb0bf9dcccdfcebdb0f823fea8b2853b89ea4e (diff)
parent5f8ab1653ad38faf395daf1b8a70249f6954b1ba (diff)
downloadNim-6d3b632b47d626f6915dc2cbef8745baf04b8d76.tar.gz
Merge branch 'new_spawn' into devel
Conflicts:
	todo.txt
	web/news.txt
	web/nimrod.ini
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/c2nim/c2nim.nim92
-rw-r--r--compiler/c2nim/clex.nim787
-rw-r--r--compiler/c2nim/cparse.nim2272
-rw-r--r--compiler/c2nim/cpp.nim347
-rw-r--r--compiler/c2nim/nimrod.cfg4
-rw-r--r--compiler/c2nim/tests/enum.h40
-rw-r--r--compiler/c2nim/tests/matrix.h240
-rw-r--r--compiler/c2nim/tests/struct_anonym.h27
-rw-r--r--compiler/c2nim/tests/systest.c622
-rw-r--r--compiler/c2nim/tests/systest2.c17
-rw-r--r--compiler/c2nim/tests/vincent.c33
-rw-r--r--compiler/c2nim/tests/vincent.h3
-rw-r--r--compiler/lambdalifting.nim745
-rw-r--r--compiler/lowerings.nim43
-rw-r--r--compiler/magicsys.nim2
-rw-r--r--compiler/pas2nim/nimrod.cfg4
-rw-r--r--compiler/pas2nim/pas2nim.nim64
-rw-r--r--compiler/pas2nim/paslex.nim570
-rw-r--r--compiler/pas2nim/pasparse.nim1513
20 files changed, 487 insertions, 6941 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 516954b88..9b8218071 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -417,6 +417,7 @@ type
                 # efficiency
     nfTransf,   # node has been transformed
     nfSem       # node has been checked for semantics
+    nfLL        # node has gone through lambda lifting
     nfDotField  # the call can use a dot operator
     nfDotSetter # the call can use a setter dot operarator
     nfExplicitCall # x.y() was used instead of x.y
@@ -1505,7 +1506,7 @@ proc isGenericRoutine*(s: PSym): bool =
 proc skipGenericOwner*(s: PSym): PSym =
   internalAssert s.kind in skProcKinds
   ## Generic instantiations are owned by their originating generic
-  ## symbol. This proc skips such owners and goes straigh to the owner
+  ## symbol. This proc skips such owners and goes straight to the owner
   ## of the generic itself (the module or the enclosing proc).
   result = if sfFromGeneric in s.flags: s.owner.owner
            else: s.owner
diff --git a/compiler/c2nim/c2nim.nim b/compiler/c2nim/c2nim.nim
deleted file mode 100644
index 9b12b9e47..000000000
--- a/compiler/c2nim/c2nim.nim
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-#
-#      c2nim - C to Nimrod source converter
-#        (c) Copyright 2013 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-import
-  strutils, os, times, parseopt, llstream, ast, renderer, options, msgs,
-  clex, cparse
-
-const
-  Version = NimrodVersion
-  Usage = """
-c2nim - C to Nimrod source converter
-  (c) 2013 Andreas Rumpf
-Usage: c2nim [options] inputfile [options]
-Options:
-  -o, --out:FILE         set output filename
-  --cpp                  process C++ input file
-  --dynlib:SYMBOL        import from dynlib: SYMBOL will be used for the import
-  --header:HEADER_FILE   import from a HEADER_FILE (discouraged!)
-  --cdecl                annotate procs with ``{.cdecl.}``
-  --stdcall              annotate procs with ``{.stdcall.}``
-  --ref                  convert typ* to ref typ (default: ptr typ)
-  --prefix:PREFIX        strip prefix for the generated Nimrod identifiers
-                         (multiple --prefix options are supported)
-  --suffix:SUFFIX        strip suffix for the generated Nimrod identifiers
-                         (multiple --suffix options are supported)
-  --skipinclude          do not convert ``#include`` to ``import``
-  --typeprefixes         generate ``T`` and ``P`` type prefixes
-  --skipcomments         do not copy comments
-  --ignoreRValueRefs     translate C++'s ``T&&`` to ``T`` instead ``of var T``
-  --keepBodies           keep C++'s method bodies
-  --spliceHeader         parse and emit header before source file
-  -v, --version          write c2nim's version
-  -h, --help             show this help
-"""
-
-proc parse(infile: string, options: PParserOptions): PNode =
-  var stream = llStreamOpen(infile, fmRead)
-  if stream == nil: rawMessage(errCannotOpenFile, infile)
-  var p: TParser
-  openParser(p, infile, stream, options)
-  result = parseUnit(p)
-  closeParser(p)
-
-proc main(infile, outfile: string, options: PParserOptions, spliceHeader: bool) =
-  var start = getTime()
-  if spliceHeader and infile.splitFile.ext == ".c" and existsFile(infile.changeFileExt(".h")):
-    var header_module = parse(infile.changeFileExt(".h"), options)
-    var source_module = parse(infile, options)
-    for n in source_module:
-      addson(header_module, n)
-    renderModule(header_module, outfile)
-  else:
-    renderModule(parse(infile, options), outfile)
-  rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start), 
-                            formatSize(getTotalMem())])
-
-var
-  infile = ""
-  outfile = ""
-  spliceHeader = false
-  parserOptions = newParserOptions()
-for kind, key, val in getopt():
-  case kind
-  of cmdArgument: infile = key
-  of cmdLongOption, cmdShortOption:
-    case key.toLower
-    of "help", "h":
-      stdout.write(Usage)
-      quit(0)
-    of "version", "v":
-      stdout.write(Version & "\n")
-      quit(0)
-    of "o", "out": outfile = val
-    of "spliceheader": spliceHeader = true
-    else:
-      if not parserOptions.setOption(key, val):
-        stdout.writeln("[Error] unknown option: " & key)
-  of cmdEnd: assert(false)
-if infile.len == 0:
-  # no filename has been given, so we show the help:
-  stdout.write(Usage)
-else:
-  if outfile.len == 0:
-    outfile = changeFileExt(infile, "nim")
-  infile = addFileExt(infile, "h")
-  main(infile, outfile, parserOptions, spliceHeader)
diff --git a/compiler/c2nim/clex.nim b/compiler/c2nim/clex.nim
deleted file mode 100644
index 3934eea63..000000000
--- a/compiler/c2nim/clex.nim
+++ /dev/null
@@ -1,787 +0,0 @@
-#
-#
-#      c2nim - C to Nimrod source converter
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This module implements an Ansi C scanner. This is an adaption from
-# the scanner module. Keywords are not handled here, but in the parser to make
-# it more flexible.
-
-
-import 
-  options, msgs, strutils, platform, nimlexbase, llstream
-
-const 
-  MaxLineLength* = 80         # lines longer than this lead to a warning
-  numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'} 
-  SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'}
-  SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF'}
-
-type
-  TTokKind* = enum 
-    pxInvalid, pxEof,         
-    pxMacroParam,             # fake token: macro parameter (with its index)
-    pxStarComment,            # /* */ comment
-    pxLineComment,            # // comment
-    pxDirective,              # #define, etc.
-    pxDirectiveParLe,         # #define m( with parle (yes, C is that ugly!)
-    pxDirConc,                # ##
-    pxNewLine,                # newline: end of directive
-    pxAmp,                    # &
-    pxAmpAmp,                 # && 
-    pxAmpAsgn,                # &=
-    pxAmpAmpAsgn,             # &&=
-    pxBar,                    # |
-    pxBarBar,                 # ||
-    pxBarAsgn,                # |=
-    pxBarBarAsgn,             # ||=
-    pxNot,                    # !
-    pxPlusPlus,               # ++
-    pxMinusMinus,             # --
-    pxPlus,                   # +
-    pxPlusAsgn,               # +=
-    pxMinus,                  # -
-    pxMinusAsgn,              # -=
-    pxMod,                    # %
-    pxModAsgn,                # %=
-    pxSlash,                  # /
-    pxSlashAsgn,              # /=
-    pxStar,                   # *
-    pxStarAsgn,               # *=
-    pxHat,                    # ^
-    pxHatAsgn,                # ^=
-    pxAsgn,                   # =
-    pxEquals,                 # ==
-    pxDot,                    # .
-    pxDotDotDot,              # ...
-    pxLe,                     # <=
-    pxLt,                     # <
-    pxGe,                     # >=
-    pxGt,                     # >
-    pxNeq,                    # != 
-    pxConditional,            # ?
-    pxShl,                    # <<
-    pxShlAsgn,                # <<=
-    pxShr,                    # >>
-    pxShrAsgn,                # >>=
-    pxTilde,                  # ~
-    pxTildeAsgn,              # ~=
-    pxArrow,                  # ->
-    pxScope,                  # ::
-
-    pxStrLit, 
-    pxCharLit,
-    pxSymbol,                 # a symbol
-    pxIntLit, 
-    pxInt64Lit, # long constant like 0x70fffffff or out of int range
-    pxFloatLit, 
-    pxParLe, pxBracketLe, pxCurlyLe, # this order is important 
-    pxParRi, pxBracketRi, pxCurlyRi, # for macro argument parsing!
-    pxComma, pxSemiColon, pxColon,
-    pxAngleRi                 # '>' but determined to be the end of a
-                              # template's angle bracket
-  TTokKinds* = set[TTokKind]
-
-type
-  TNumericalBase* = enum base10, base2, base8, base16
-  TToken* = object
-    xkind*: TTokKind          # the type of the token
-    s*: string                # parsed symbol, char or string literal
-    iNumber*: BiggestInt      # the parsed integer literal;
-                              # if xkind == pxMacroParam: parameter's position
-    fNumber*: BiggestFloat    # the parsed floating point literal
-    base*: TNumericalBase     # the numerical base; only valid for int
-                              # or float literals
-    next*: ref TToken         # for C we need arbitrary look-ahead :-(
-  
-  TLexer* = object of TBaseLexer
-    fileIdx*: int32
-    inDirective: bool
-  
-proc getTok*(L: var TLexer, tok: var TToken)
-proc printTok*(tok: TToken)
-proc `$`*(tok: TToken): string
-# implementation
-
-var
-  gLinesCompiled*: int
-
-proc fillToken(L: var TToken) = 
-  L.xkind = pxInvalid
-  L.iNumber = 0
-  L.s = ""
-  L.fNumber = 0.0
-  L.base = base10
-  
-proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) = 
-  openBaseLexer(lex, inputstream)
-  lex.fileIdx = filename.fileInfoIdx
-
-proc closeLexer*(lex: var TLexer) = 
-  inc(gLinesCompiled, lex.LineNumber)
-  closeBaseLexer(lex)
-
-proc getColumn*(L: TLexer): int = 
-  result = getColNumber(L, L.bufPos)
-
-proc getLineInfo*(L: TLexer): TLineInfo = 
-  result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos))
-
-proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = 
-  msgs.GlobalError(getLineInfo(L), msg, arg)
-
-proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = 
-  var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart)
-  msgs.GlobalError(info, msg, arg)
-
-proc tokKindToStr*(k: TTokKind): string =
-  case k
-  of pxEof: result = "[EOF]"
-  of pxInvalid: result = "[invalid]"
-  of pxMacroParam: result = "[macro param]"
-  of pxStarComment, pxLineComment: result = "[comment]" 
-  of pxStrLit: result = "[string literal]"
-  of pxCharLit: result = "[char literal]"
-
-  of pxDirective, pxDirectiveParLe: result = "#"             # #define, etc.
-  of pxDirConc: result = "##"
-  of pxNewLine: result = "[NewLine]"
-  of pxAmp: result = "&"                   # &
-  of pxAmpAmp: result = "&&"                # && 
-  of pxAmpAsgn: result = "&="                # &=
-  of pxAmpAmpAsgn: result = "&&="            # &&=
-  of pxBar: result = "|"                   # |
-  of pxBarBar: result = "||"                # ||
-  of pxBarAsgn: result = "|="               # |=
-  of pxBarBarAsgn: result = "||="            # ||=
-  of pxNot: result = "!"                   # !
-  of pxPlusPlus: result = "++"             # ++
-  of pxMinusMinus: result = "--"            # --
-  of pxPlus: result = "+"                  # +
-  of pxPlusAsgn: result = "+="              # +=
-  of pxMinus: result = "-"                 # -
-  of pxMinusAsgn: result = "-="             # -=
-  of pxMod: result = "%"                   # %
-  of pxModAsgn: result = "%="               # %=
-  of pxSlash: result = "/"                 # /
-  of pxSlashAsgn: result = "/="             # /=
-  of pxStar: result = "*"                  # *
-  of pxStarAsgn: result = "*="              # *=
-  of pxHat: result = "^"                   # ^
-  of pxHatAsgn: result = "^="               # ^=
-  of pxAsgn: result = "="                  # =
-  of pxEquals: result = "=="                # ==
-  of pxDot: result = "."                   # .
-  of pxDotDotDot: result = "..."             # ...
-  of pxLe: result = "<="                    # <=
-  of pxLt: result = "<"                    # <
-  of pxGe: result = ">="                    # >=
-  of pxGt: result = ">"                    # >
-  of pxNeq: result = "!="                   # != 
-  of pxConditional: result = "?"
-  of pxShl: result = "<<"
-  of pxShlAsgn: result = "<<="
-  of pxShr: result = ">>"
-  of pxShrAsgn: result = ">>="
-  of pxTilde: result = "~"
-  of pxTildeAsgn: result = "~="
-  of pxArrow: result = "->"
-  of pxScope: result = "::"
-
-  of pxSymbol: result = "[identifier]"
-  of pxIntLit, pxInt64Lit: result = "[integer literal]"
-  of pxFloatLit: result = "[floating point literal]"
-  of pxParLe: result = "("
-  of pxParRi: result = ")"
-  of pxBracketLe: result = "["
-  of pxBracketRi: result = "]"
-  of pxComma: result = ","
-  of pxSemiColon: result = ";"
-  of pxColon: result = ":"
-  of pxCurlyLe: result = "{"
-  of pxCurlyRi: result = "}"
-  of pxAngleRi: result = "> [end of template]"
-
-proc `$`(tok: TToken): string = 
-  case tok.xkind
-  of pxSymbol, pxInvalid, pxStarComment, pxLineComment, pxStrLit: result = tok.s
-  of pxIntLit, pxInt64Lit: result = $tok.iNumber
-  of pxFloatLit: result = $tok.fNumber
-  else: result = tokKindToStr(tok.xkind)
-  
-proc printTok(tok: TToken) = 
-  writeln(stdout, $tok)
-  
-proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = 
-  # matches ([chars]_)*
-  var pos = L.bufpos              # use registers for pos, buf
-  var buf = L.buf
-  while true: 
-    if buf[pos] in chars: 
-      add(tok.s, buf[pos])
-      inc(pos)
-    else: 
-      break 
-    if buf[pos] == '_': 
-      add(tok.s, '_')
-      inc(pos)
-  L.bufPos = pos
-
-proc isFloatLiteral(s: string): bool = 
-  for i in countup(0, len(s)-1): 
-    if s[i] in {'.', 'e', 'E'}: 
-      return true
-
-proc getNumber2(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos + 2 # skip 0b
-  tok.base = base2
-  var xi: BiggestInt = 0
-  var bits = 0
-  while true: 
-    case L.buf[pos]
-    of 'A'..'Z', 'a'..'z':
-      # ignore type suffix:
-      inc(pos)
-    of '2'..'9', '.': 
-      lexMessage(L, errInvalidNumber)
-      inc(pos)
-    of '_': 
-      inc(pos)
-    of '0', '1': 
-      xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0'))
-      inc(pos)
-      inc(bits)
-    else: break 
-  tok.iNumber = xi
-  if (bits > 32): tok.xkind = pxInt64Lit
-  else: tok.xkind = pxIntLit
-  L.bufpos = pos
-
-proc getNumber8(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos + 1 # skip 0
-  tok.base = base8
-  var xi: BiggestInt = 0
-  var bits = 0
-  while true: 
-    case L.buf[pos]
-    of 'A'..'Z', 'a'..'z':
-      # ignore type suffix:
-      inc(pos)
-    of '8'..'9', '.': 
-      lexMessage(L, errInvalidNumber)
-      inc(pos)
-    of '_': 
-      inc(pos)
-    of '0'..'7': 
-      xi = `shl`(xi, 3) or (ord(L.buf[pos]) - ord('0'))
-      inc(pos)
-      inc(bits)
-    else: break 
-  tok.iNumber = xi
-  if (bits > 12): tok.xkind = pxInt64Lit
-  else: tok.xkind = pxIntLit
-  L.bufpos = pos
-
-proc getNumber16(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos + 2          # skip 0x
-  tok.base = base16
-  var xi: BiggestInt = 0
-  var bits = 0
-  while true: 
-    case L.buf[pos]
-    of 'G'..'Z', 'g'..'z': 
-      # ignore type suffix:
-      inc(pos)
-    of '_': inc(pos)
-    of '0'..'9': 
-      xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0'))
-      inc(pos)
-      inc(bits, 4)
-    of 'a'..'f': 
-      xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('a') + 10)
-      inc(pos)
-      inc(bits, 4)
-    of 'A'..'F': 
-      xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10)
-      inc(pos)
-      inc(bits, 4)
-    else: break 
-  tok.iNumber = xi
-  if bits > 32: tok.xkind = pxInt64Lit
-  else: tok.xkind = pxIntLit
-  L.bufpos = pos
-
-proc getFloating(L: var TLexer, tok: var TToken) =
-  matchUnderscoreChars(L, tok, {'0'..'9'})
-  if L.buf[L.bufpos] in {'e', 'E'}:
-    add(tok.s, L.buf[L.bufpos])
-    inc(L.bufpos)
-    if L.buf[L.bufpos] in {'+', '-'}:
-      add(tok.s, L.buf[L.bufpos])
-      inc(L.bufpos)
-    matchUnderscoreChars(L, tok, {'0'..'9'})
-
-proc getNumber(L: var TLexer, tok: var TToken) = 
-  tok.base = base10
-  if L.buf[L.bufpos] == '.':
-    add(tok.s, "0.")
-    inc(L.bufpos)
-    getFloating(L, tok)
-  else:
-    matchUnderscoreChars(L, tok, {'0'..'9'})
-    if L.buf[L.bufpos] == '.':
-      add(tok.s, '.')
-      inc(L.bufpos)
-      getFloating(L, tok)
-  try: 
-    if isFloatLiteral(tok.s): 
-      tok.fnumber = parseFloat(tok.s)
-      tok.xkind = pxFloatLit
-    else: 
-      tok.iNumber = parseInt(tok.s)
-      if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)): 
-        tok.xkind = pxInt64Lit
-      else: 
-        tok.xkind = pxIntLit
-  except EInvalidValue: 
-    lexMessage(L, errInvalidNumber, tok.s)
-  except EOverflow: 
-    lexMessage(L, errNumberOutOfRange, tok.s)
-  # ignore type suffix:
-  while L.buf[L.bufpos] in {'A'..'Z', 'a'..'z'}: inc(L.bufpos)
-  
-proc handleCRLF(L: var TLexer, pos: int): int = 
-  case L.buf[pos]
-  of CR: result = nimlexbase.handleCR(L, pos)
-  of LF: result = nimlexbase.handleLF(L, pos)
-  else: result = pos
-  
-proc escape(L: var TLexer, tok: var TToken, allowEmpty=false) = 
-  inc(L.bufpos) # skip \ 
-  case L.buf[L.bufpos]
-  of 'b', 'B':
-    add(tok.s, '\b')
-    inc(L.bufpos)
-  of 't', 'T':
-    add(tok.s, '\t')
-    inc(L.bufpos)
-  of 'n', 'N':
-    add(tok.s, '\L')
-    inc(L.bufpos)
-  of 'f', 'F':
-    add(tok.s, '\f')
-    inc(L.bufpos)
-  of 'r', 'R':
-    add(tok.s, '\r')
-    inc(L.bufpos)
-  of '\'':
-    add(tok.s, '\'')
-    inc(L.bufpos)
-  of '"':
-    add(tok.s, '"')
-    inc(L.bufpos)
-  of '\\':
-    add(tok.s, '\b')
-    inc(L.bufpos)  
-  of '0'..'7':
-    var xi = ord(L.buf[L.bufpos]) - ord('0')
-    inc(L.bufpos)
-    if L.buf[L.bufpos] in {'0'..'7'}:
-      xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0'))
-      inc(L.bufpos)
-      if L.buf[L.bufpos] in {'0'..'7'}:
-        xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0'))
-        inc(L.bufpos)
-    add(tok.s, chr(xi))
-  of 'x':
-    var xi = 0
-    inc(L.bufpos)
-    while true: 
-      case L.buf[L.bufpos]
-      of '0'..'9': 
-        xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('0'))
-        inc(L.bufpos)
-      of 'a'..'f': 
-        xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('a') + 10)
-        inc(L.bufpos)
-      of 'A'..'F': 
-        xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('A') + 10)
-        inc(L.bufpos)
-      else:
-        break 
-    add(tok.s, chr(xi))
-  elif not allowEmpty:
-    lexMessage(L, errInvalidCharacterConstant)
-  
-proc getCharLit(L: var TLexer, tok: var TToken) = 
-  inc(L.bufpos) # skip '
-  if L.buf[L.bufpos] == '\\':
-    escape(L, tok)
-  else:
-    add(tok.s, L.buf[L.bufpos])
-    inc(L.bufpos)
-  if L.buf[L.bufpos] == '\'':
-    inc(L.bufpos)
-  else:
-    lexMessage(L, errMissingFinalQuote)
-  tok.xkind = pxCharLit
-
-proc getString(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufPos + 1          # skip "
-  var buf = L.buf                 # put `buf` in a register
-  var line = L.linenumber         # save linenumber for better error message
-  while true: 
-    case buf[pos]
-    of '\"': 
-      inc(pos)
-      break
-    of CR: 
-      pos = nimlexbase.HandleCR(L, pos)
-      buf = L.buf
-    of LF: 
-      pos = nimlexbase.HandleLF(L, pos)
-      buf = L.buf
-    of nimlexbase.EndOfFile: 
-      var line2 = L.linenumber
-      L.LineNumber = line
-      lexMessagePos(L, errClosingQuoteExpected, L.lineStart)
-      L.LineNumber = line2
-      break 
-    of '\\': 
-      # we allow an empty \ for line concatenation, but we don't require it
-      # for line concatenation
-      L.bufpos = pos
-      escape(L, tok, allowEmpty=true)
-      pos = L.bufpos
-    else: 
-      add(tok.s, buf[pos])
-      inc(pos)
-  L.bufpos = pos
-  tok.xkind = pxStrLit
-
-proc getSymbol(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos
-  var buf = L.buf
-  while true: 
-    var c = buf[pos]
-    if c notin SymChars: break
-    add(tok.s, c)
-    inc(pos)
-  L.bufpos = pos
-  tok.xkind = pxSymbol
-
-proc scanLineComment(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos
-  var buf = L.buf 
-  # a comment ends if the next line does not start with the // on the same
-  # column after only whitespace
-  tok.xkind = pxLineComment
-  var col = getColNumber(L, pos)
-  while true: 
-    inc(pos, 2)               # skip //
-    add(tok.s, '#')
-    while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}): 
-      add(tok.s, buf[pos])
-      inc(pos)
-    pos = handleCRLF(L, pos)
-    buf = L.buf
-    var indent = 0
-    while buf[pos] == ' ': 
-      inc(pos)
-      inc(indent)
-    if (col == indent) and (buf[pos] == '/') and (buf[pos + 1] == '/'): 
-      add(tok.s, "\n")
-    else: 
-      break 
-  L.bufpos = pos
-
-proc scanStarComment(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos
-  var buf = L.buf
-  tok.s = "#"
-  tok.xkind = pxStarComment
-  while true: 
-    case buf[pos]
-    of CR, LF: 
-      pos = handleCRLF(L, pos)
-      buf = L.buf
-      add(tok.s, "\n#")
-      # skip annoying stars as line prefix: (eg.
-      # /*
-      #  * ugly comment <-- this star
-      #  */
-      while buf[pos] in {' ', '\t'}:
-        add(tok.s, ' ')
-        inc(pos)
-      if buf[pos] == '*' and buf[pos+1] != '/': inc(pos)
-    of '*': 
-      inc(pos)
-      if buf[pos] == '/': 
-        inc(pos)
-        break 
-      else: 
-        add(tok.s, '*')
-    of nimlexbase.EndOfFile: 
-      lexMessage(L, errTokenExpected, "*/")
-    else: 
-      add(tok.s, buf[pos])
-      inc(pos)
-  L.bufpos = pos
-
-proc skip(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos
-  var buf = L.buf
-  while true: 
-    case buf[pos]
-    of '\\': 
-      # Ignore \ line continuation characters when not inDirective
-      inc(pos)
-      if L.inDirective:
-        while buf[pos] in {' ', '\t'}: inc(pos)
-        if buf[pos] in {CR, LF}:
-          pos = handleCRLF(L, pos)
-          buf = L.buf
-    of ' ', Tabulator: 
-      inc(pos)                # newline is special:
-    of CR, LF: 
-      pos = handleCRLF(L, pos)
-      buf = L.buf
-      if L.inDirective:
-        tok.xkind = pxNewLine
-        L.inDirective = false
-    else: 
-      break                   # EndOfFile also leaves the loop
-  L.bufpos = pos
-
-proc getDirective(L: var TLexer, tok: var TToken) = 
-  var pos = L.bufpos + 1
-  var buf = L.buf
-  while buf[pos] in {' ', '\t'}: inc(pos)
-  while buf[pos] in SymChars: 
-    add(tok.s, buf[pos])
-    inc(pos)
-  # a HACK: we need to distinguish 
-  # #define x (...)
-  # from:
-  # #define x(...)
-  # 
-  L.bufpos = pos
-  # look ahead:
-  while buf[pos] in {' ', '\t'}: inc(pos)
-  while buf[pos] in SymChars: inc(pos)
-  if buf[pos] == '(': tok.xkind = pxDirectiveParLe
-  else: tok.xkind = pxDirective
-  L.inDirective = true
-
-proc getTok(L: var TLexer, tok: var TToken) = 
-  tok.xkind = pxInvalid
-  fillToken(tok)
-  skip(L, tok)
-  if tok.xkind == pxNewLine: return
-  var c = L.buf[L.bufpos]
-  if c in SymStartChars: 
-    getSymbol(L, tok)
-  elif c == '0':
-    case L.buf[L.bufpos+1]
-    of 'x', 'X': getNumber16(L, tok)
-    of 'b', 'B': getNumber2(L, tok)
-    of '1'..'7': getNumber8(L, tok)
-    else: getNumber(L, tok)
-  elif c in {'1'..'9'} or (c == '.' and L.buf[L.bufpos+1] in {'0'..'9'}): 
-    getNumber(L, tok)
-  else: 
-    case c
-    of ';': 
-      tok.xkind = pxSemicolon
-      inc(L.bufpos)
-    of '/': 
-      if L.buf[L.bufpos + 1] == '/': 
-        scanLineComment(L, tok)
-      elif L.buf[L.bufpos+1] == '*':
-        inc(L.bufpos, 2)
-        scanStarComment(L, tok)
-      elif L.buf[L.bufpos+1] == '=':
-        inc(L.bufpos, 2)
-        tok.xkind = pxSlashAsgn
-      else: 
-        tok.xkind = pxSlash
-        inc(L.bufpos)
-    of ',': 
-      tok.xkind = pxComma
-      inc(L.bufpos)
-    of '(': 
-      inc(L.bufpos)
-      tok.xkind = pxParLe
-    of '*': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        inc(L.bufpos)
-        tok.xkind = pxStarAsgn
-      else:
-        tok.xkind = pxStar
-    of ')': 
-      inc(L.bufpos)
-      tok.xkind = pxParRi
-    of '[': 
-      inc(L.bufpos)
-      tok.xkind = pxBracketLe
-    of ']': 
-      inc(L.bufpos)
-      tok.xkind = pxBracketRi
-    of '.': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '.' and L.buf[L.bufpos+1] == '.': 
-        tok.xkind = pxDotDotDot
-        inc(L.bufpos, 2)
-      else: 
-        tok.xkind = pxDot
-    of '{': 
-      inc(L.bufpos)
-      tok.xkind = pxCurlyLe
-    of '}': 
-      inc(L.bufpos)
-      tok.xkind = pxCurlyRi
-    of '+': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxPlusAsgn
-        inc(L.bufpos)
-      elif L.buf[L.bufpos] == '+': 
-        tok.xkind = pxPlusPlus
-        inc(L.bufpos)
-      else: 
-        tok.xkind = pxPlus
-    of '-': 
-      inc(L.bufpos)
-      case L.buf[L.bufpos] 
-      of '>':
-        tok.xkind = pxArrow
-        inc(L.bufpos)
-      of '=':
-        tok.xkind = pxMinusAsgn
-        inc(L.bufpos)
-      of '-': 
-        tok.xkind = pxMinusMinus
-        inc(L.bufpos)
-      else: 
-        tok.xkind = pxMinus
-    of '?':
-      inc(L.bufpos)
-      tok.xkind = pxConditional
-    of ':': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == ':':
-        tok.xkind = pxScope
-        inc(L.bufpos)
-      else:
-        tok.xkind = pxColon
-    of '!':
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxNeq
-        inc(L.bufpos)
-      else: 
-        tok.xkind = pxNot
-    of '<': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=': 
-        inc(L.bufpos)
-        tok.xkind = pxLe
-      elif L.buf[L.bufpos] == '<':
-        inc(L.bufpos)
-        if L.buf[L.bufpos] == '=': 
-          inc(L.bufpos)
-          tok.xkind = pxShlAsgn
-        else:
-          tok.xkind = pxShl
-      else: 
-        tok.xkind = pxLt
-    of '>': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=': 
-        inc(L.bufpos)
-        tok.xkind = pxGe
-      elif L.buf[L.bufpos] == '>':
-        inc(L.bufpos)
-        if L.buf[L.bufpos] == '=': 
-          inc(L.bufpos)
-          tok.xkind = pxShrAsgn
-        else:
-          tok.xkind = pxShr
-      else: 
-        tok.xkind = pxGt
-    of '=': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxEquals
-        inc(L.bufpos)
-      else: 
-        tok.xkind = pxAsgn
-    of '&': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxAmpAsgn
-        inc(L.bufpos)
-      elif L.buf[L.bufpos] == '&':
-        inc(L.bufpos)
-        if L.buf[L.bufpos] == '=':
-          inc(L.bufpos)
-          tok.xkind = pxAmpAmpAsgn
-        else:
-          tok.xkind = pxAmpAmp
-      else: 
-        tok.xkind = pxAmp
-    of '|': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxBarAsgn
-        inc(L.bufpos)
-      elif L.buf[L.bufpos] == '|':
-        inc(L.bufpos)
-        if L.buf[L.bufpos] == '=':
-          inc(L.bufpos)
-          tok.xkind = pxBarBarAsgn
-        else:
-          tok.xkind = pxBarBar
-      else: 
-        tok.xkind = pxBar
-    of '^': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxHatAsgn
-        inc(L.bufpos)
-      else: 
-        tok.xkind = pxHat
-    of '%': 
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxModAsgn
-        inc(L.bufpos)
-      else: 
-        tok.xkind = pxMod
-    of '~':
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        tok.xkind = pxTildeAsgn
-        inc(L.bufpos)
-      else: 
-        tok.xkind = pxTilde
-    of '#': 
-      if L.buf[L.bufpos+1] == '#':
-        inc(L.bufpos, 2)
-        tok.xkind = pxDirConc
-      else:
-        getDirective(L, tok)
-    of '"': getString(L, tok)
-    of '\'': getCharLit(L, tok)
-    of nimlexbase.EndOfFile: 
-      tok.xkind = pxEof
-    else: 
-      tok.s = $c
-      tok.xkind = pxInvalid
-      lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
-      inc(L.bufpos)
diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim
deleted file mode 100644
index 2e31af528..000000000
--- a/compiler/c2nim/cparse.nim
+++ /dev/null
@@ -1,2272 +0,0 @@
-#
-#
-#      c2nim - C to Nimrod source converter
-#        (c) Copyright 2013 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements an Ansi C parser.
-## It translates a C source file into a Nimrod AST. Then the renderer can be
-## used to convert the AST to its text representation.
-
-# TODO
-# - document 'cpp' mode
-# - implement handling of '::': function declarations
-# - C++'s "operator" still needs some love
-# - support '#if' in classes
-
-import 
-  os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs,
-  options, strtabs, hashes, algorithm
-
-type 
-  TParserFlag = enum
-    pfRefs,             ## use "ref" instead of "ptr" for C's typ*
-    pfCDecl,            ## annotate procs with cdecl
-    pfStdCall,          ## annotate procs with stdcall
-    pfSkipInclude,      ## skip all ``#include``
-    pfTypePrefixes,     ## all generated types start with 'T' or 'P'
-    pfSkipComments,     ## do not generate comments
-    pfCpp,              ## process C++
-    pfIgnoreRValueRefs, ## transform C++'s 'T&&' to 'T'
-    pfKeepBodies        ## do not skip C++ method bodies
-  
-  TMacro = object
-    name: string
-    params: int           # number of parameters
-    body: seq[ref TToken] # can contain pxMacroParam tokens
-  
-  TParserOptions = object
-    flags: set[TParserFlag]
-    prefixes, suffixes: seq[string]
-    mangleRules: seq[tuple[pattern: TPeg, frmt: string]]
-    privateRules: seq[TPeg]
-    dynlibSym, header: string
-    macros: seq[TMacro]
-    toMangle: PStringTable
-    classes: PStringTable
-  PParserOptions* = ref TParserOptions
-  
-  TParser* = object
-    lex: TLexer
-    tok: ref TToken       # current token
-    options: PParserOptions
-    backtrack: seq[ref TToken]
-    inTypeDef: int
-    scopeCounter: int
-    hasDeadCodeElimPragma: bool
-    currentClass: PNode   # type that needs to be added as 'this' parameter
-  
-  TReplaceTuple* = array[0..1, string]
-
-  ERetryParsing = object of ESynch
-
-
-
-proc addTypeDef(section, name, t: PNode)
-proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode
-proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool,
-                     kind: TNodeKind = nkRecList): PNode
-
-
-
-proc newParserOptions*(): PParserOptions = 
-  new(result)
-  result.prefixes = @[]
-  result.suffixes = @[]
-  result.macros = @[]
-  result.mangleRules = @[]
-  result.privateRules = @[]
-  result.flags = {}
-  result.dynlibSym = ""
-  result.header = ""
-  result.toMangle = newStringTable(modeCaseSensitive)
-  result.classes = newStringTable(modeCaseSensitive)
-
-proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool = 
-  result = true
-  case key.normalize
-  of "ref": incl(parserOptions.flags, pfRefs)
-  of "dynlib": parserOptions.dynlibSym = val
-  of "header": parserOptions.header = val
-  of "cdecl": incl(parserOptions.flags, pfCdecl)
-  of "stdcall": incl(parserOptions.flags, pfStdCall)
-  of "prefix": parserOptions.prefixes.add(val)
-  of "suffix": parserOptions.suffixes.add(val)
-  of "skipinclude": incl(parserOptions.flags, pfSkipInclude)
-  of "typeprefixes": incl(parserOptions.flags, pfTypePrefixes)
-  of "skipcomments": incl(parserOptions.flags, pfSkipComments)
-  of "cpp": incl(parserOptions.flags, pfCpp)
-  of "keepbodies": incl(parserOptions.flags, pfKeepBodies)
-  of "ignorervaluerefs": incl(parserOptions.flags, pfIgnoreRValueRefs)
-  of "class": parserOptions.classes[val] = "true"
-  else: result = false
-
-proc parseUnit*(p: var TParser): PNode
-proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
-                 options = newParserOptions())
-proc closeParser*(p: var TParser)
-
-# implementation
-
-proc openParser(p: var TParser, filename: string, 
-                inputStream: PLLStream, options = newParserOptions()) = 
-  openLexer(p.lex, filename, inputStream)
-  p.options = options
-  p.backtrack = @[]
-  new(p.tok)
-
-proc parMessage(p: TParser, msg: TMsgKind, arg = "") = 
-  #assert false
-  lexMessage(p.lex, msg, arg)
-
-proc closeParser(p: var TParser) = closeLexer(p.lex)
-proc saveContext(p: var TParser) = p.backtrack.add(p.tok)
-proc closeContext(p: var TParser) = discard p.backtrack.pop()
-proc backtrackContext(p: var TParser) = p.tok = p.backtrack.pop()
-
-proc rawGetTok(p: var TParser) = 
-  if p.tok.next != nil:
-    p.tok = p.tok.next
-  elif p.backtrack.len == 0: 
-    p.tok.next = nil
-    getTok(p.lex, p.tok[])
-  else: 
-    # We need the next token and must be able to backtrack. So we need to 
-    # allocate a new token.
-    var t: ref TToken
-    new(t)
-    getTok(p.lex, t[])
-    p.tok.next = t
-    p.tok = t
-
-proc insertAngleRi(currentToken: ref TToken) = 
-  var t: ref TToken
-  new(t)
-  t.xkind = pxAngleRi
-  t.next = currentToken.next
-  currentToken.next = t
-
-proc findMacro(p: TParser): int =
-  for i in 0..high(p.options.macros):
-    if p.tok.s == p.options.macros[i].name: return i
-  return -1
-
-proc rawEat(p: var TParser, xkind: TTokKind) = 
-  if p.tok.xkind == xkind: rawGetTok(p)
-  else: parMessage(p, errTokenExpected, tokKindToStr(xkind))
-
-proc parseMacroArguments(p: var TParser): seq[seq[ref TToken]] = 
-  result = @[]
-  result.add(@[])
-  var i: array[pxParLe..pxCurlyLe, int]
-  var L = 0
-  saveContext(p)
-  while true:
-    var kind = p.tok.xkind
-    case kind
-    of pxEof: rawEat(p, pxParRi)
-    of pxParLe, pxBracketLe, pxCurlyLe: 
-      inc(i[kind])
-      result[L].add(p.tok)
-    of pxParRi:
-      # end of arguments?
-      if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0: break
-      if i[pxParLe] > 0: dec(i[pxParLe])
-      result[L].add(p.tok)
-    of pxBracketRi, pxCurlyRi:
-      kind = pred(kind, 3)
-      if i[kind] > 0: dec(i[kind])
-      result[L].add(p.tok)
-    of pxComma: 
-      if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0:
-        # next argument: comma is not part of the argument
-        result.add(@[])
-        inc(L)
-      else: 
-        # comma does not separate different arguments:
-        result[L].add(p.tok)
-    else:
-      result[L].add(p.tok)
-    rawGetTok(p)
-  closeContext(p)
-
-proc expandMacro(p: var TParser, m: TMacro) = 
-  rawGetTok(p) # skip macro name
-  var arguments: seq[seq[ref TToken]]
-  if m.params > 0:
-    rawEat(p, pxParLe)
-    arguments = parseMacroArguments(p)
-    if arguments.len != m.params: parMessage(p, errWrongNumberOfArguments)
-    rawEat(p, pxParRi)
-  # insert into the token list:
-  if m.body.len > 0:
-    var newList: ref TToken
-    new(newList)
-    var lastTok = newList
-    for tok in items(m.body): 
-      if tok.xkind == pxMacroParam: 
-        for t in items(arguments[int(tok.iNumber)]):
-          #echo "t: ", t^
-          lastTok.next = t
-          lastTok = t
-      else:
-        #echo "tok: ", tok^
-        lastTok.next = tok
-        lastTok = tok
-    lastTok.next = p.tok
-    p.tok = newList.next
-
-proc getTok(p: var TParser) = 
-  rawGetTok(p)
-  if p.tok.xkind == pxSymbol:
-    var idx = findMacro(p)
-    if idx >= 0: 
-      expandMacro(p, p.options.macros[idx])
-
-proc parLineInfo(p: TParser): TLineInfo = 
-  result = getLineInfo(p.lex)
-
-proc skipComAux(p: var TParser, n: PNode) =
-  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)
-  else: 
-    parMessage(p, warnCommentXIgnored, p.tok.s)
-  getTok(p)
-
-proc skipCom(p: var TParser, n: PNode) = 
-  while p.tok.xkind in {pxLineComment, pxStarComment}: skipComAux(p, n)
-
-proc skipStarCom(p: var TParser, n: PNode) = 
-  while p.tok.xkind == pxStarComment: skipComAux(p, n)
-
-proc getTok(p: var TParser, n: PNode) =
-  getTok(p)
-  skipCom(p, n)
-
-proc expectIdent(p: TParser) = 
-  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)
-  else: parMessage(p, errTokenExpected, tokKindToStr(xkind))
-  
-proc eat(p: var TParser, xkind: TTokKind) = 
-  if p.tok.xkind == xkind: getTok(p)
-  else: parMessage(p, errTokenExpected, tokKindToStr(xkind))
-  
-proc eat(p: var TParser, tok: string, n: PNode) = 
-  if p.tok.s == tok: getTok(p, n)
-  else: parMessage(p, errTokenExpected, tok)
-  
-proc opt(p: var TParser, xkind: TTokKind, n: PNode) = 
-  if p.tok.xkind == xkind: getTok(p, n)
-  
-proc addSon(father, a, b: PNode) = 
-  addSon(father, a)
-  addSon(father, b)
-
-proc addSon(father, a, b, c: PNode) = 
-  addSon(father, a)
-  addSon(father, b)
-  addSon(father, c)
-  
-proc newNodeP(kind: TNodeKind, p: TParser): PNode = 
-  result = newNodeI(kind, getLineInfo(p.lex))
-
-proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode = 
-  result = newNodeP(kind, p)
-  result.intVal = intVal
-
-proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, 
-                   p: TParser): PNode = 
-  result = newNodeP(kind, p)
-  result.floatVal = floatVal
-
-proc newStrNodeP(kind: TNodeKind, strVal: string, p: TParser): PNode = 
-  result = newNodeP(kind, p)
-  result.strVal = strVal
-
-proc newIdentNodeP(ident: PIdent, p: TParser): PNode = 
-  result = newNodeP(nkIdent, p)
-  result.ident = ident
-
-proc newIdentNodeP(ident: string, p: TParser): PNode =
-  result = newIdentNodeP(getIdent(ident), p)
-
-proc mangleRules(s: string, p: TParser): string = 
-  block mangle:
-    for pattern, frmt in items(p.options.mangleRules):
-      if s.match(pattern):
-        result = s.replacef(pattern, frmt)
-        break mangle
-    block prefixes:
-      for prefix in items(p.options.prefixes): 
-        if s.startsWith(prefix): 
-          result = s.substr(prefix.len)
-          break prefixes
-      result = s
-    block suffixes:
-      for suffix in items(p.options.suffixes):
-        if result.endsWith(suffix):
-          setLen(result, result.len - suffix.len)
-          break suffixes
-
-proc mangleName(s: string, p: TParser): string = 
-  if p.options.toMangle.hasKey(s): result = p.options.toMangle[s]
-  else: result = mangleRules(s, p)
-
-proc isPrivate(s: string, p: TParser): bool = 
-  for pattern in items(p.options.privateRules): 
-    if s.match(pattern): return true
-
-proc mangledIdent(ident: string, p: TParser): PNode = 
-  result = newNodeP(nkIdent, p)
-  result.ident = getIdent(mangleName(ident, p))
-
-proc newIdentPair(a, b: string, p: TParser): PNode = 
-  result = newNodeP(nkExprColonExpr, p)
-  addSon(result, newIdentNodeP(a, p))
-  addSon(result, newIdentNodeP(b, p))
-
-proc newIdentStrLitPair(a, b: string, p: TParser): PNode =
-  result = newNodeP(nkExprColonExpr, p)
-  addSon(result, newIdentNodeP(a, p))
-  addSon(result, newStrNodeP(nkStrLit, b, p))
-
-proc addImportToPragma(pragmas: PNode, ident: string, p: TParser) =
-  addSon(pragmas, newIdentStrLitPair("importc", ident, p))
-  if p.options.dynlibSym.len > 0:
-    addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p))
-  else:
-    addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
-
-proc exportSym(p: TParser, i: PNode, origName: string): PNode = 
-  assert i.kind == nkIdent
-  if p.scopeCounter == 0 and not isPrivate(origName, p):
-    result = newNodeI(nkPostfix, i.info)
-    addSon(result, newIdentNode(getIdent("*"), i.info), i)
-  else:
-    result = i
-
-proc varIdent(ident: string, p: TParser): PNode = 
-  result = exportSym(p, mangledIdent(ident, p), ident)
-  if p.scopeCounter > 0: return
-  if p.options.dynlibSym.len > 0 or p.options.header.len > 0: 
-    var a = result
-    result = newNodeP(nkPragmaExpr, p)
-    var pragmas = newNodeP(nkPragma, p)
-    addSon(result, a)
-    addSon(result, pragmas)
-    addImportToPragma(pragmas, ident, p)
-
-proc fieldIdent(ident: string, p: TParser): PNode = 
-  result = exportSym(p, mangledIdent(ident, p), ident)
-  if p.scopeCounter > 0: return
-  if p.options.header.len > 0: 
-    var a = result
-    result = newNodeP(nkPragmaExpr, p)
-    var pragmas = newNodeP(nkPragma, p)
-    addSon(result, a)
-    addSon(result, pragmas)
-    addSon(pragmas, newIdentStrLitPair("importc", ident, p))
-
-proc doImport(ident: string, pragmas: PNode, p: TParser) = 
-  if p.options.dynlibSym.len > 0 or p.options.header.len > 0: 
-    addImportToPragma(pragmas, ident, p)
-
-proc doImportCpp(ident: string, pragmas: PNode, p: TParser) = 
-  if p.options.dynlibSym.len > 0 or p.options.header.len > 0:
-    addSon(pragmas, newIdentStrLitPair("importcpp", ident, p))
-    if p.options.dynlibSym.len > 0:
-      addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p))
-    else:
-      addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
-
-proc newBinary(opr: string, a, b: PNode, p: TParser): PNode =
-  result = newNodeP(nkInfix, p)
-  addSon(result, newIdentNodeP(getIdent(opr), p))
-  addSon(result, a)
-  addSon(result, b)
-
-proc skipIdent(p: var TParser): PNode = 
-  expectIdent(p)
-  result = mangledIdent(p.tok.s, p)
-  getTok(p, result)
-
-proc skipIdentExport(p: var TParser): PNode = 
-  expectIdent(p)
-  result = exportSym(p, mangledIdent(p.tok.s, p), p.tok.s)
-  getTok(p, result)
-
-proc skipTypeIdentExport(p: var TParser, prefix='T'): PNode = 
-  expectIdent(p)
-  var n = prefix & mangleName(p.tok.s, p)
-  p.options.toMangle[p.tok.s] = n
-  var i = newNodeP(nkIdent, p)
-  i.ident = getIdent(n)
-  result = exportSym(p, i, p.tok.s)
-  getTok(p, result)
-
-proc markTypeIdent(p: var TParser, typ: PNode) = 
-  if pfTypePrefixes in p.options.flags:
-    var prefix = ""
-    if typ == nil or typ.kind == nkEmpty: 
-      prefix = "T"
-    else: 
-      var t = typ
-      while t != nil and t.kind in {nkVarTy, nkPtrTy, nkRefTy}: 
-        prefix.add('P')
-        t = t.sons[0]
-      if prefix.len == 0: prefix.add('T')
-    expectIdent(p)
-    p.options.toMangle[p.tok.s] = prefix & mangleRules(p.tok.s, p)
-  
-# --------------- parser -----------------------------------------------------
-# We use this parsing rule: If it looks like a declaration, it is one. This
-# avoids to build a symbol table, which can't be done reliably anyway for our
-# purposes.
-
-proc expression(p: var TParser, rbp: int = 0): PNode
-proc constantExpression(p: var TParser): PNode = expression(p, 40)
-proc assignmentExpression(p: var TParser): PNode = expression(p, 30)
-proc compoundStatement(p: var TParser): PNode
-proc statement(p: var TParser): PNode
-
-proc declKeyword(p: TParser, s: string): bool = 
-  # returns true if it is a keyword that introduces a declaration
-  case s
-  of  "extern", "static", "auto", "register", "const", "volatile", "restrict",
-      "inline", "__inline", "__cdecl", "__stdcall", "__syscall", "__fastcall",
-      "__safecall", "void", "struct", "union", "enum", "typedef",
-      "short", "int", "long", "float", "double", "signed", "unsigned", "char": 
-    result = true
-  of "class":
-    result = p.options.flags.contains(pfCpp)
-
-proc stmtKeyword(s: string): bool =
-  case s
-  of  "if", "for", "while", "do", "switch", "break", "continue", "return",
-      "goto":
-    result = true
-
-# ------------------- type desc -----------------------------------------------
-
-proc isIntType(s: string): bool =
-  case s
-  of "short", "int", "long", "float", "double", "signed", "unsigned":
-    result = true
-
-proc skipConst(p: var TParser) = 
-  while p.tok.xkind == pxSymbol and
-      (p.tok.s == "const" or p.tok.s == "volatile" or p.tok.s == "restrict"): 
-    getTok(p, nil)
-
-proc isTemplateAngleBracket(p: var TParser): bool =
-  if pfCpp notin p.options.flags: return false
-  saveContext(p)
-  getTok(p, nil) # skip "<"
-  var i: array[pxParLe..pxCurlyLe, int]
-  var angles = 0
-  while true:
-    let kind = p.tok.xkind
-    case kind
-    of pxEof: break
-    of pxParLe, pxBracketLe, pxCurlyLe: inc(i[kind])
-    of pxGt, pxAngleRi:
-      # end of arguments?
-      if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0 and
-          angles == 0:
-        # mark as end token:
-        p.tok.xkind = pxAngleRi
-        result = true; 
-        break
-      if angles > 0: dec(angles)
-    of pxShr:
-      # >> can end a template too:
-      if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0 and
-          angles == 1:
-        p.tok.xkind = pxAngleRi
-        insertAngleRi(p.tok)
-        result = true
-        break
-      if angles > 1: dec(angles, 2)
-    of pxLt: inc(angles)
-    of pxParRi, pxBracketRi, pxCurlyRi:
-      let kind = pred(kind, 3)
-      if i[kind] > 0: dec(i[kind])
-      else: break
-    of pxSemicolon: break
-    else: discard
-    getTok(p, nil)
-  backtrackContext(p)
-
-proc optAngle(p: var TParser, n: PNode): PNode =
-  if p.tok.xkind == pxLt and isTemplateAngleBracket(p):
-    getTok(p)
-    result = newNodeP(nkBracketExpr, p)
-    result.add(n)
-    while true:
-      let a = assignmentExpression(p)
-      if not a.isNil: result.add(a)
-      if p.tok.xkind != pxComma: break
-      getTok(p)
-    eat(p, pxAngleRi)
-  else:
-    result = n
-
-proc optScope(p: var TParser, n: PNode): PNode =
-  result = n
-  if pfCpp in p.options.flags:
-    while p.tok.xkind == pxScope:
-      let a = result
-      result = newNodeP(nkDotExpr, p)
-      result.add(a)
-      getTok(p, result)
-      expectIdent(p)
-      result.add(mangledIdent(p.tok.s, p))
-      getTok(p, result)
-
-proc typeAtom(p: var TParser): PNode = 
-  skipConst(p)
-  expectIdent(p)
-  case p.tok.s
-  of "void": 
-    result = newNodeP(nkNilLit, p) # little hack
-    getTok(p, nil)
-  of "struct", "union", "enum": 
-    getTok(p, nil)
-    result = skipIdent(p)
-  elif isIntType(p.tok.s):
-    var x = ""
-    #getTok(p, nil)
-    var isUnsigned = false
-    while p.tok.xkind == pxSymbol and (isIntType(p.tok.s) or p.tok.s == "char"):
-      if p.tok.s == "unsigned":
-        isUnsigned = true
-      elif p.tok.s == "signed" or p.tok.s == "int":
-        discard
-      else:
-        add(x, p.tok.s)
-      getTok(p, nil)
-    if x.len == 0: x = "int"
-    let xx = if isUnsigned: "cu" & x else: "c" & x
-    result = mangledIdent(xx, p)
-  else:
-    result = mangledIdent(p.tok.s, p)
-    getTok(p, result)
-    result = optScope(p, result)
-    result = optAngle(p, result)
-    
-proc newPointerTy(p: TParser, typ: PNode): PNode =
-  if pfRefs in p.options.flags: 
-    result = newNodeP(nkRefTy, p)
-  else:
-    result = newNodeP(nkPtrTy, p)
-  result.addSon(typ)
-
-proc pointer(p: var TParser, a: PNode): PNode = 
-  result = a
-  var i = 0
-  skipConst(p)
-  while true:
-    if p.tok.xkind == pxStar:
-      inc(i)
-      getTok(p, result)
-      skipConst(p)
-      result = newPointerTy(p, result)
-    elif p.tok.xkind == pxAmp and pfCpp in p.options.flags:
-      getTok(p, result)
-      skipConst(p)
-      let b = result
-      result = newNodeP(nkVarTy, p)
-      result.add(b)
-    elif p.tok.xkind == pxAmpAmp and pfCpp in p.options.flags:
-      getTok(p, result)
-      skipConst(p)
-      if pfIgnoreRvalueRefs notin p.options.flags:
-        let b = result
-        result = newNodeP(nkVarTy, p)
-        result.add(b)
-    else: break
-  if a.kind == nkIdent and a.ident.s == "char": 
-    if i >= 2: 
-      result = newIdentNodeP("cstringArray", p)
-      for j in 1..i-2: result = newPointerTy(p, result)
-    elif i == 1: result = newIdentNodeP("cstring", p)
-  elif a.kind == nkNilLit and i > 0:
-    result = newIdentNodeP("pointer", p)
-    for j in 1..i-1: result = newPointerTy(p, result)
-
-proc newProcPragmas(p: TParser): PNode =
-  result = newNodeP(nkPragma, p)
-  if pfCDecl in p.options.flags: 
-    addSon(result, newIdentNodeP("cdecl", p))
-  elif pfStdCall in p.options.flags:
-    addSon(result, newIdentNodeP("stdcall", p))
-
-proc addPragmas(father, pragmas: PNode) =
-  if sonsLen(pragmas) > 0: addSon(father, pragmas)
-  else: addSon(father, ast.emptyNode)
-
-proc addReturnType(params, rettyp: PNode) =
-  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)
-
-proc parseTypeSuffix(p: var TParser, typ: PNode): PNode = 
-  result = typ
-  while true:
-    case p.tok.xkind 
-    of pxBracketLe:
-      getTok(p, result)
-      skipConst(p) # POSIX contains: ``int [restrict]``
-      if p.tok.xkind != pxBracketRi:
-        var tmp = result
-        var index = expression(p)
-        # array type:
-        result = newNodeP(nkBracketExpr, p)
-        addSon(result, newIdentNodeP("array", p))
-        #var r = newNodeP(nkRange, p)
-        #addSon(r, newIntNodeP(nkIntLit, 0, p))
-        #addSon(r, newBinary("-", index, newIntNodeP(nkIntLit, 1, p), p))
-        #addSon(result, r)
-        addSon(result, index)
-        addSon(result, tmp)
-      else:
-        # pointer type:
-        var tmp = result
-        if pfRefs in p.options.flags: 
-          result = newNodeP(nkRefTy, p)
-        else:
-          result = newNodeP(nkPtrTy, p)
-        result.addSon(tmp)
-      eat(p, pxBracketRi, result)
-    of pxParLe:
-      # function pointer:
-      var procType = newNodeP(nkProcTy, p)
-      var pragmas = newProcPragmas(p)
-      var params = newNodeP(nkFormalParams, p)
-      addReturnType(params, result)
-      parseFormalParams(p, params, pragmas)
-      addSon(procType, params)
-      addPragmas(procType, pragmas)
-      result = procType
-    else: break
-
-proc typeDesc(p: var TParser): PNode = 
-  result = pointer(p, typeAtom(p))
-
-proc abstractDeclarator(p: var TParser, a: PNode): PNode
-
-proc directAbstractDeclarator(p: var TParser, a: PNode): PNode =
-  if p.tok.xkind == pxParLe:
-    getTok(p, a)
-    if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp}:
-      result = abstractDeclarator(p, a)
-      eat(p, pxParRi, result)
-  return parseTypeSuffix(p, a)
-
-proc abstractDeclarator(p: var TParser, a: PNode): PNode =
-  return directAbstractDeclarator(p, pointer(p, a))
-
-proc typeName(p: var TParser): PNode =
-  return abstractDeclarator(p, typeAtom(p))
-
-proc parseField(p: var TParser, kind: TNodeKind): PNode =
-  if p.tok.xkind == pxParLe: 
-    getTok(p, nil)
-    while p.tok.xkind == pxStar: getTok(p, nil)
-    result = parseField(p, kind)
-    eat(p, pxParRi, result)
-  else: 
-    expectIdent(p)
-    if kind == nkRecList: result = fieldIdent(p.tok.s, p) 
-    else: result = mangledIdent(p.tok.s, p)
-    getTok(p, result)
-
-proc structPragmas(p: TParser, name: PNode, origName: string): PNode = 
-  assert name.kind == nkIdent
-  result = newNodeP(nkPragmaExpr, p)
-  addSon(result, exportSym(p, name, origName))
-  var pragmas = newNodeP(nkPragma, p)
-  #addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
-  if p.options.header.len > 0:
-    addSon(pragmas, newIdentStrLitPair("importc", origName, p),
-                    newIdentStrLitPair("header", p.options.header, p))
-  if pragmas.len > 0: addSon(result, pragmas)
-  else: addSon(result, ast.emptyNode)
-
-proc hashPosition(p: TParser): string =
-  let lineInfo = parLineInfo(p)
-  let fileInfo = fileInfos[lineInfo.fileIndex]
-  result = $hash(fileInfo.shortName & "_" & $lineInfo.line & "_" & $lineInfo.col).uint
-
-proc parseInnerStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode =
-  getTok(p, nil)
-  if p.tok.xkind != pxCurlyLe:
-    parMessage(p, errUser, "Expected '{' but found '" & $(p.tok[]) & "'")
-  
-  let structName =  if isUnion: "INNER_C_UNION_" & p.hashPosition
-                    else: "INNER_C_STRUCT_" & p.hashPosition
-  let typeSection = newNodeP(nkTypeSection, p)
-  let newStruct = newNodeP(nkObjectTy, p)
-  var pragmas = ast.emptyNode
-  if isUnion:
-    pragmas = newNodeP(nkPragma, p)
-    addSon(pragmas, newIdentNodeP("union", p))
-  addSon(newStruct, pragmas, ast.emptyNode) # no inheritance 
-  result = newNodeP(nkIdent, p)
-  result.ident = getIdent(structName)
-  let struct = parseStructBody(p, stmtList, isUnion)
-  let defName = newNodeP(nkIdent, p)
-  defName.ident = getIdent(structName)
-  addSon(newStruct, struct)
-  addTypeDef(typeSection, structPragmas(p, defName, "no_name"), newStruct)
-  addSon(stmtList, typeSection)
-
-proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool,
-                     kind: TNodeKind = nkRecList): PNode =
-  result = newNodeP(kind, p)
-  eat(p, pxCurlyLe, result)
-  while p.tok.xkind notin {pxEof, pxCurlyRi}:
-    skipConst(p)
-    var baseTyp: PNode
-    if p.tok.xkind == pxSymbol and (p.tok.s == "struct" or p.tok.s == "union"):
-      let gotUnion = if p.tok.s == "union": true   else: false
-      saveContext(p)
-      getTok(p, nil)
-      if p.tok.xkind == pxSymbol:
-        backtrackContext(p)
-        baseTyp = typeAtom(p)
-      else:
-        backtrackContext(p)
-        baseTyp = parseInnerStruct(p, stmtList, gotUnion)
-        if p.tok.xkind == pxSemiColon:
-          let def = newNodeP(nkIdentDefs, p)
-          var t = pointer(p, baseTyp)
-          let i = fieldIdent("ano_" & p.hashPosition, p)
-          t = parseTypeSuffix(p, t)
-          addSon(def, i, t, ast.emptyNode)
-          addSon(result, def)
-          getTok(p, nil)
-          continue
-    else:
-      baseTyp = typeAtom(p)
-    
-    while true:
-      var def = newNodeP(nkIdentDefs, p)
-      var t = pointer(p, baseTyp)
-      var i = parseField(p, kind)
-      t = parseTypeSuffix(p, t)
-      addSon(def, i, t, ast.emptyNode)
-      addSon(result, def)
-      if p.tok.xkind != pxComma: break
-      getTok(p, def)
-    eat(p, pxSemicolon, lastSon(result))
-  eat(p, pxCurlyRi, result)
-
-proc enumPragmas(p: TParser, name: PNode): PNode =
-  result = newNodeP(nkPragmaExpr, p)
-  addSon(result, name)
-  var pragmas = newNodeP(nkPragma, p)
-  var e = newNodeP(nkExprColonExpr, p)
-  # HACK: sizeof(cint) should be constructed as AST
-  addSon(e, newIdentNodeP("size", p), newIdentNodeP("sizeof(cint)", p))
-  addSon(pragmas, e)
-  addSon(result, pragmas)
-
-proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode =
-  result = newNodeP(nkObjectTy, p)
-  var pragmas = ast.emptyNode
-  if isUnion:
-    pragmas = newNodeP(nkPragma, p)
-    addSon(pragmas, newIdentNodeP("union", p))
-  addSon(result, pragmas, ast.emptyNode) # no inheritance 
-  if p.tok.xkind == pxCurlyLe:
-    addSon(result, parseStructBody(p, stmtList, isUnion))
-  else: 
-    addSon(result, newNodeP(nkRecList, p))
-
-proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode
-
-proc directDeclarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
-  case p.tok.xkind
-  of pxSymbol:
-    ident[] = skipIdent(p)
-  of pxParLe:
-    getTok(p, a)
-    if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp, pxSymbol}:
-      result = declarator(p, a, ident)
-      eat(p, pxParRi, result)
-  else:
-    discard
-  return parseTypeSuffix(p, a)
-
-proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
-  return directDeclarator(p, pointer(p, a), ident)
-
-# parameter-declaration
-#   declaration-specifiers declarator
-#   declaration-specifiers asbtract-declarator(opt)
-proc parseParam(p: var TParser, params: PNode) = 
-  var typ = typeDesc(p)
-  # support for ``(void)`` parameter list: 
-  if typ.kind == nkNilLit and p.tok.xkind == pxParRi: return
-  var name: PNode
-  typ = declarator(p, typ, addr name)
-  if name == nil:
-    var idx = sonsLen(params)+1
-    name = newIdentNodeP("a" & $idx, p)
-  var x = newNodeP(nkIdentDefs, p)
-  addSon(x, name, typ)
-  if p.tok.xkind == pxAsgn: 
-    # we support default parameters for C++:
-    getTok(p, x)
-    addSon(x, assignmentExpression(p))
-  else:
-    addSon(x, ast.emptyNode)
-  addSon(params, x)
-
-proc parseFormalParams(p: var TParser, params, pragmas: PNode) = 
-  eat(p, pxParLe, params)
-  while p.tok.xkind notin {pxEof, pxParRi}:
-    if p.tok.xkind == pxDotDotDot:  
-      addSon(pragmas, newIdentNodeP("varargs", p))
-      getTok(p, pragmas)
-      break
-    parseParam(p, params)
-    if p.tok.xkind != pxComma: break
-    getTok(p, params)
-  eat(p, pxParRi, params)
-
-proc parseCallConv(p: var TParser, pragmas: PNode) = 
-  while p.tok.xkind == pxSymbol:
-    case p.tok.s
-    of "inline", "__inline": addSon(pragmas, newIdentNodeP("inline", p))
-    of "__cdecl": addSon(pragmas, newIdentNodeP("cdecl", p))
-    of "__stdcall": addSon(pragmas, newIdentNodeP("stdcall", p))
-    of "__syscall": addSon(pragmas, newIdentNodeP("syscall", p))
-    of "__fastcall": addSon(pragmas, newIdentNodeP("fastcall", p))
-    of "__safecall": addSon(pragmas, newIdentNodeP("safecall", p))
-    else: break
-    getTok(p, nil)
-
-proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode = 
-  var procType = newNodeP(nkProcTy, p)
-  var pragmas = newProcPragmas(p)
-  var params = newNodeP(nkFormalParams, p)
-  eat(p, pxParLe, params)
-  addReturnType(params, rettyp)
-  parseCallConv(p, pragmas)
-  if p.tok.xkind == pxStar: getTok(p, params)
-  else: parMessage(p, errTokenExpected, "*")
-  if p.inTypeDef > 0: markTypeIdent(p, nil)
-  var name = skipIdentExport(p)
-  eat(p, pxParRi, name)
-  parseFormalParams(p, params, pragmas)
-  addSon(procType, params)
-  addPragmas(procType, pragmas)
-  
-  if p.inTypeDef == 0:
-    result = newNodeP(nkVarSection, p)
-    var def = newNodeP(nkIdentDefs, p)
-    addSon(def, name, procType, ast.emptyNode)
-    addSon(result, def)    
-  else:
-    result = newNodeP(nkTypeDef, p)
-    addSon(result, name, ast.emptyNode, procType)
-  assert result != nil
-  
-proc addTypeDef(section, name, t: PNode) = 
-  var def = newNodeI(nkTypeDef, name.info)
-  addSon(def, name, ast.emptyNode, t)
-  addSon(section, def)
-  
-proc otherTypeDef(p: var TParser, section, typ: PNode) = 
-  var name: PNode
-  var t = typ
-  if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp}:
-    t = pointer(p, t)
-  if p.tok.xkind == pxParLe: 
-    # function pointer: typedef typ (*name)();
-    var x = parseFunctionPointerDecl(p, t)
-    name = x[0]
-    t = x[2]
-  else: 
-    # typedef typ name;
-    markTypeIdent(p, t)
-    name = skipIdentExport(p)
-  t = parseTypeSuffix(p, t)
-  addTypeDef(section, name, t)
-
-proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) = 
-  while p.tok.xkind == pxComma:
-    getTok(p, nil)
-    var newTyp = pointer(p, typ)
-    markTypeIdent(p, newTyp)
-    var newName = skipIdentExport(p)
-    newTyp = parseTypeSuffix(p, newTyp)
-    addTypeDef(section, newName, newTyp)
-
-proc createConst(name, typ, val: PNode, p: TParser): PNode =
-  result = newNodeP(nkConstDef, p)
-  addSon(result, name, typ, val)
-
-proc exprToNumber(n: PNode not nil): tuple[succ: bool, val: BiggestInt] =
-  result = (false, 0.BiggestInt)
-  case n.kind:
-  of nkPrefix:
-    # Check for negative/positive numbers  -3  or  +6
-    if n.sons.len == 2 and n.sons[0].kind == nkIdent and n.sons[1].kind == nkIntLit:
-      let pre = n.sons[0]
-      let num = n.sons[1]
-      if pre.ident.s == "-": result = (true, - num.intVal)
-      elif pre.ident.s == "+": result = (true, num.intVal)
-  else: discard
-
-proc enumFields(p: var TParser, constList: PNode): PNode = 
-  result = newNodeP(nkEnumTy, p)
-  addSon(result, ast.emptyNode) # enum does not inherit from anything
-  var i: BiggestInt = 0
-  var field: tuple[id: BiggestInt, isNumber: bool, node: PNode]
-  var fields = newSeq[type(field)]()
-  while true:
-    var e = skipIdent(p)
-    if p.tok.xkind == pxAsgn: 
-      getTok(p, e)
-      var c = constantExpression(p)
-      var a = e
-      e = newNodeP(nkEnumFieldDef, p)
-      addSon(e, a, c)
-      skipCom(p, e)
-      if c.kind == nkIntLit:
-        i = c.intVal
-        field.isNumber = true
-      else:
-        var (success, number) = exprToNumber(c)
-        if success:
-          i = number
-          field.isNumber = true
-        else:
-          field.isNumber = false
-    else:
-      inc(i)
-      field.isNumber = true
-    field.id = i
-    field.node = e
-    fields.add(field)
-    if p.tok.xkind != pxComma: break
-    getTok(p, e)
-    # allow trailing comma:
-    if p.tok.xkind == pxCurlyRi: break
-  fields.sort do (x, y: type(field)) -> int:
-    cmp(x.id, y.id)
-  var lastId: BiggestInt
-  var lastIdent: PNode
-  for count, f in fields:
-    if not f.isNumber:
-      addSon(result, f.node)
-    elif f.id == lastId and count > 0:
-      var currentIdent: PNode
-      case f.node.kind:
-      of nkEnumFieldDef:
-        if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent:
-          currentIdent = f.node.sons[0]
-        else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!")
-      of nkIdent: currentIdent = f.node
-      else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!")
-      var constant = createConst( currentIdent, ast.emptyNode, lastIdent, p)
-      constList.addSon(constant)
-    else:
-      addSon(result, f.node)
-      lastId = f.id
-      case f.node.kind:
-      of nkEnumFieldDef:
-        if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent:
-          lastIdent = f.node.sons[0]
-        else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!")
-      of nkIdent: lastIdent = f.node
-      else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!")
-
-proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: bool) = 
-  getTok(p, result)
-  if p.tok.xkind == pxCurlyLe:
-    var t = parseStruct(p, stmtList, isUnion)
-    var origName = p.tok.s
-    markTypeIdent(p, nil)
-    var name = skipIdent(p)
-    addTypeDef(result, structPragmas(p, name, origName), t)
-    parseTrailingDefinedTypes(p, result, name)
-  elif p.tok.xkind == pxSymbol: 
-    # name to be defined or type "struct a", we don't know yet:
-    markTypeIdent(p, nil)
-    var origName = p.tok.s
-    var nameOrType = skipIdent(p)
-    case p.tok.xkind 
-    of pxCurlyLe:
-      var t = parseStruct(p, stmtList, isUnion)
-      if p.tok.xkind == pxSymbol: 
-        # typedef struct tagABC {} abc, *pabc;
-        # --> abc is a better type name than tagABC!
-        markTypeIdent(p, nil)
-        var origName = p.tok.s
-        var name = skipIdent(p)
-        addTypeDef(result, structPragmas(p, name, origName), t)
-        parseTrailingDefinedTypes(p, result, name)
-      else:
-        addTypeDef(result, structPragmas(p, nameOrType, origName), t)
-    of pxSymbol: 
-      # typedef struct a a?
-      if mangleName(p.tok.s, p) == nameOrType.ident.s:
-        # ignore the declaration:
-        getTok(p, nil)
-      else:
-        # typedef struct a b; or typedef struct a b[45];
-        otherTypeDef(p, result, nameOrType)
-    else: 
-      otherTypeDef(p, result, nameOrType)
-  else:
-    expectIdent(p)
-
-proc parseTypedefEnum(p: var TParser, result, constSection: PNode) = 
-  getTok(p, result)
-  if p.tok.xkind == pxCurlyLe:
-    getTok(p, result)
-    var t = enumFields(p, constSection)
-    eat(p, pxCurlyRi, t)
-    var origName = p.tok.s
-    markTypeIdent(p, nil)
-    var name = skipIdent(p)
-    addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t)
-    parseTrailingDefinedTypes(p, result, name)
-  elif p.tok.xkind == pxSymbol: 
-    # name to be defined or type "enum a", we don't know yet:
-    markTypeIdent(p, nil)
-    var origName = p.tok.s
-    var nameOrType = skipIdent(p)
-    case p.tok.xkind 
-    of pxCurlyLe:
-      getTok(p, result)
-      var t = enumFields(p, constSection)
-      eat(p, pxCurlyRi, t)
-      if p.tok.xkind == pxSymbol: 
-        # typedef enum tagABC {} abc, *pabc;
-        # --> abc is a better type name than tagABC!
-        markTypeIdent(p, nil)
-        var origName = p.tok.s
-        var name = skipIdent(p)
-        addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t)
-        parseTrailingDefinedTypes(p, result, name)
-      else:
-        addTypeDef(result, 
-                   enumPragmas(p, exportSym(p, nameOrType, origName)), t)
-    of pxSymbol: 
-      # typedef enum a a?
-      if mangleName(p.tok.s, p) == nameOrType.ident.s:
-        # ignore the declaration:
-        getTok(p, nil)
-      else:
-        # typedef enum a b; or typedef enum a b[45];
-        otherTypeDef(p, result, nameOrType)
-    else: 
-      otherTypeDef(p, result, nameOrType)
-  else:
-    expectIdent(p)
-
-proc parseTypeDef(p: var TParser): PNode =  
-  result = newNodeP(nkStmtList, p)
-  var typeSection = newNodeP(nkTypeSection, p)
-  var afterStatements = newNodeP(nkStmtList, p)
-  while p.tok.xkind == pxSymbol and p.tok.s == "typedef":
-    getTok(p, typeSection)
-    inc(p.inTypeDef)
-    expectIdent(p)
-    case p.tok.s
-    of "struct": parseTypedefStruct(p, typeSection, result, isUnion=false)
-    of "union": parseTypedefStruct(p, typeSection, result, isUnion=true)
-    of "enum":
-      var constSection = newNodeP(nkConstSection, p)
-      parseTypedefEnum(p, typeSection, constSection)
-      addSon(afterStatements, constSection)
-    of "class":
-      if pfCpp in p.options.flags:
-        parseTypedefStruct(p, typeSection, result, isUnion=false)
-      else:
-        var t = typeAtom(p)
-        otherTypeDef(p, typeSection, t)
-    else: 
-      var t = typeAtom(p)
-      otherTypeDef(p, typeSection, t)
-    eat(p, pxSemicolon)
-    dec(p.inTypeDef)
-  
-  addSon(result, typeSection)
-  for s in afterStatements:
-    addSon(result, s)
-  
-proc skipDeclarationSpecifiers(p: var TParser) =
-  while p.tok.xkind == pxSymbol:
-    case p.tok.s
-    of "extern", "static", "auto", "register", "const", "volatile": 
-      getTok(p, nil)
-    else: break
-
-proc parseInitializer(p: var TParser): PNode = 
-  if p.tok.xkind == pxCurlyLe: 
-    result = newNodeP(nkBracket, p)
-    getTok(p, result)
-    while p.tok.xkind notin {pxEof, pxCurlyRi}: 
-      addSon(result, parseInitializer(p))
-      opt(p, pxComma, nil)
-    eat(p, pxCurlyRi, result)
-  else:
-    result = assignmentExpression(p)
-
-proc addInitializer(p: var TParser, def: PNode) = 
-  if p.tok.xkind == pxAsgn:
-    getTok(p, def)
-    addSon(def, parseInitializer(p))
-  else:
-    addSon(def, ast.emptyNode)  
-
-proc parseVarDecl(p: var TParser, baseTyp, typ: PNode, 
-                  origName: string): PNode =  
-  result = newNodeP(nkVarSection, p)
-  var def = newNodeP(nkIdentDefs, p)
-  addSon(def, varIdent(origName, p))
-  addSon(def, parseTypeSuffix(p, typ))
-  addInitializer(p, def)
-  addSon(result, def)
-    
-  while p.tok.xkind == pxComma: 
-    getTok(p, def)
-    var t = pointer(p, baseTyp)
-    expectIdent(p)
-    def = newNodeP(nkIdentDefs, p)
-    addSon(def, varIdent(p.tok.s, p))
-    getTok(p, def)
-    addSon(def, parseTypeSuffix(p, t))
-    addInitializer(p, def)
-    addSon(result, def)
-  eat(p, pxSemicolon)
-
-proc declarationName(p: var TParser): string =
-  expectIdent(p)
-  result = p.tok.s
-  getTok(p) # skip identifier
-  while p.tok.xkind == pxScope and pfCpp in p.options.flags:
-    getTok(p) # skip "::"
-    expectIdent(p)
-    result.add("::")
-    result.add(p.tok.s)
-    getTok(p)
-
-proc declaration(p: var TParser): PNode = 
-  result = newNodeP(nkProcDef, p)
-  var pragmas = newNodeP(nkPragma, p)
-  
-  skipDeclarationSpecifiers(p)
-  parseCallConv(p, pragmas)
-  skipDeclarationSpecifiers(p)
-  expectIdent(p)
-  var baseTyp = typeAtom(p)
-  var rettyp = pointer(p, baseTyp)
-  skipDeclarationSpecifiers(p)
-  parseCallConv(p, pragmas)
-  skipDeclarationSpecifiers(p)
-  
-  if p.tok.xkind == pxParLe: 
-    # Function pointer declaration: This is of course only a heuristic, but the
-    # best we can do here.
-    result = parseFunctionPointerDecl(p, rettyp)
-    eat(p, pxSemicolon)
-    return
-  var origName = declarationName(p)
-  case p.tok.xkind
-  of pxParLe:
-    # really a function!
-    var name = mangledIdent(origName, p)
-    var params = newNodeP(nkFormalParams, p)
-    addReturnType(params, rettyp)
-    parseFormalParams(p, params, pragmas)
-    if pfCpp in p.options.flags and p.tok.xkind == pxSymbol and
-        p.tok.s == "const":
-      addSon(pragmas, newIdentNodeP("noSideEffect", p))
-      getTok(p)
-    if pfCDecl in p.options.flags:
-      addSon(pragmas, newIdentNodeP("cdecl", p))
-    elif pfStdcall in p.options.flags:
-      addSon(pragmas, newIdentNodeP("stdcall", p))
-    # no pattern, no exceptions:
-    addSon(result, exportSym(p, name, origName), ast.emptyNode, ast.emptyNode)
-    addSon(result, params, pragmas, ast.emptyNode) # no exceptions
-    case p.tok.xkind 
-    of pxSemicolon: 
-      getTok(p)
-      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] = ast.emptyNode
-  else:
-    result = parseVarDecl(p, baseTyp, rettyp, origName)
-  assert result != nil
-
-proc enumSpecifier(p: var TParser): PNode =  
-  saveContext(p)
-  getTok(p, nil) # skip "enum"
-  case p.tok.xkind
-  of pxCurlyLe: 
-    closeContext(p)
-    # make a const section out of it:
-    result = newNodeP(nkConstSection, p)
-    getTok(p, result)
-    var i = 0
-    var hasUnknown = false
-    while true:
-      var name = skipIdentExport(p)
-      var val: PNode
-      if p.tok.xkind == pxAsgn: 
-        getTok(p, name)
-        val = constantExpression(p)
-        if val.kind == nkIntLit:  
-          i = int(val.intVal)+1
-          hasUnknown = false
-        else:
-          hasUnknown = true
-      else:
-        if hasUnknown:
-          parMessage(p, warnUser, "computed const value may be wrong: " &
-            name.renderTree)
-        val = newIntNodeP(nkIntLit, i, p)
-        inc(i)
-      var c = createConst(name, ast.emptyNode, val, p)
-      addSon(result, c)
-      if p.tok.xkind != pxComma: break
-      getTok(p, c)
-      # allow trailing comma:
-      if p.tok.xkind == pxCurlyRi: break
-    eat(p, pxCurlyRi, result)
-    eat(p, pxSemicolon)
-  of pxSymbol: 
-    var origName = p.tok.s
-    markTypeIdent(p, nil)
-    result = skipIdent(p)
-    case p.tok.xkind 
-    of pxCurlyLe: 
-      closeContext(p)
-      var name = result
-      # create a type section containing the enum
-      result = newNodeP(nkStmtList, p)
-      var tSection = newNodeP(nkTypeSection, p)
-      var t = newNodeP(nkTypeDef, p)
-      getTok(p, t)
-      var constSection = newNodeP(nkConstSection, p)
-      var e = enumFields(p, constSection)
-      addSon(t, exportSym(p, name, origName), ast.emptyNode, e)
-      addSon(tSection, t)
-      addSon(result, tSection)
-      addSon(result, constSection)
-      eat(p, pxCurlyRi, result)
-      eat(p, pxSemicolon)
-    of pxSemicolon:
-      # just ignore ``enum X;`` for now.
-      closeContext(p)
-      getTok(p, nil)
-    else: 
-      backtrackContext(p)
-      result = declaration(p)
-  else:
-    closeContext(p)
-    parMessage(p, errTokenExpected, "{")
-    result = ast.emptyNode
-    
-# Expressions
-
-proc setBaseFlags(n: PNode, base: TNumericalBase) = 
-  case base
-  of base10: discard
-  of base2: incl(n.flags, nfBase2)
-  of base8: incl(n.flags, nfBase8)
-  of base16: incl(n.flags, nfBase16)
-
-proc startExpression(p : var TParser, tok : TToken) : PNode =
-  #echo "nud ", $tok
-  case tok.xkind:
-  of pxSymbol:
-    if tok.s == "NULL":
-      result = newNodeP(nkNilLit, p)
-    elif tok.s == "sizeof":
-      result = newNodeP(nkCall, p)
-      addSon(result, newIdentNodeP("sizeof", p))
-      saveContext(p)
-      try:
-        addSon(result, expression(p, 139))
-        closeContext(p)
-      except ERetryParsing:
-        backtrackContext(p)
-        eat(p, pxParLe)
-        addSon(result, typeName(p))
-        eat(p, pxParRi)
-    elif (tok.s == "new" or tok.s == "delete") and pfCpp in p.options.flags:
-      var opr = tok.s
-      result = newNodeP(nkCall, p)
-      if p.tok.xkind == pxBracketLe:
-        getTok(p)
-        eat(p, pxBracketRi)
-        opr.add("Array")
-      addSon(result, newIdentNodeP(opr, p))
-      if p.tok.xkind == pxParLe:
-        getTok(p, result)
-        addSon(result, typeDesc(p))
-        eat(p, pxParRi, result)
-      else:
-        addSon(result, expression(p, 139))
-    else:
-      result = mangledIdent(tok.s, p)
-      result = optScope(p, result)
-      result = optAngle(p, result)
-  of pxIntLit: 
-    result = newIntNodeP(nkIntLit, tok.iNumber, p)
-    setBaseFlags(result, tok.base)
-  of pxInt64Lit: 
-    result = newIntNodeP(nkInt64Lit, tok.iNumber, p)
-    setBaseFlags(result, tok.base)
-  of pxFloatLit: 
-    result = newFloatNodeP(nkFloatLit, tok.fNumber, p)
-    setBaseFlags(result, tok.base)
-  of pxStrLit: 
-    result = newStrNodeP(nkStrLit, tok.s, p)
-    while p.tok.xkind == pxStrLit:
-      add(result.strVal, p.tok.s)
-      getTok(p, result)
-  of pxCharLit:
-    result = newIntNodeP(nkCharLit, ord(tok.s[0]), p)
-  of pxParLe:
-    try:
-      saveContext(p)
-      result = newNodeP(nkPar, p)
-      addSon(result, expression(p, 0))
-      if p.tok.xkind != pxParRi:
-        raise newException(ERetryParsing, "expected a ')'")
-      getTok(p, result)
-      if p.tok.xkind in {pxSymbol, pxIntLit, pxFloatLit, pxStrLit, pxCharLit}:
-        raise newException(ERetryParsing, "expected a non literal token")
-      closeContext(p)
-    except ERetryParsing:
-      backtrackContext(p)
-      result = newNodeP(nkCast, p)
-      addSon(result, typeName(p))
-      eat(p, pxParRi, result)
-      addSon(result, expression(p, 139))
-  of pxPlusPlus:
-    result = newNodeP(nkCall, p)
-    addSon(result, newIdentNodeP("inc", p))
-    addSon(result, expression(p, 139))
-  of pxMinusMinus:
-    result = newNodeP(nkCall, p)
-    addSon(result, newIdentNodeP("dec", p))
-    addSon(result, expression(p, 139))
-  of pxAmp:
-    result = newNodeP(nkAddr, p)
-    addSon(result, expression(p, 139))
-  of pxStar:
-    result = newNodeP(nkBracketExpr, p)
-    addSon(result, expression(p, 139))
-  of pxPlus:
-    result = newNodeP(nkPrefix, p)
-    addSon(result, newIdentNodeP("+", p))
-    addSon(result, expression(p, 139))
-  of pxMinus:
-    result = newNodeP(nkPrefix, p)
-    addSon(result, newIdentNodeP("-", p))
-    addSon(result, expression(p, 139))
-  of pxTilde:
-    result = newNodeP(nkPrefix, p)
-    addSon(result, newIdentNodeP("not", p))
-    addSon(result, expression(p, 139))
-  of pxNot:
-    result = newNodeP(nkPrefix, p)
-    addSon(result, newIdentNodeP("not", p))
-    addSon(result, expression(p, 139))
-  else:
-    # probably from a failed sub expression attempt, try a type cast
-    raise newException(ERetryParsing, "did not expect " & $tok)
-
-proc leftBindingPower(p : var TParser, tok : ref TToken) : int =
-  #echo "lbp ", $tok[]
-  case tok.xkind:
-  of pxComma:
-    return 10
-    # throw == 20
-  of pxAsgn, pxPlusAsgn, pxMinusAsgn, pxStarAsgn, pxSlashAsgn, pxModAsgn, 
-     pxShlAsgn, pxShrAsgn, pxAmpAsgn, pxHatAsgn, pxBarAsgn:
-    return 30
-  of pxConditional:
-    return 40
-  of pxBarBar:
-    return 50
-  of pxAmpAmp:
-    return 60
-  of pxBar:
-    return 70
-  of pxHat:
-    return 80
-  of pxAmp:
-    return 90
-  of pxEquals, pxNeq:
-    return 100
-  of pxLt, pxLe, pxGt, pxGe:
-    return 110
-  of pxShl, pxShr:
-    return 120
-  of pxPlus, pxMinus:
-    return 130
-  of pxStar, pxSlash, pxMod:
-    return 140
-    # .* ->* == 150
-  of pxPlusPlus, pxMinusMinus, pxParLe, pxDot, pxArrow, pxBracketLe:
-    return 160
-    # :: == 170
-  else:
-    return 0
-
-proc buildStmtList(a: PNode): PNode
-
-proc leftExpression(p : var TParser, tok : TToken, left : PNode) : PNode =
-  #echo "led ", $tok
-  case tok.xkind:
-  of pxComma: # 10
-    # not supported as an expression, turns into a statement list
-    result = buildStmtList(left)
-    addSon(result, expression(p, 0))
-    # throw == 20
-  of pxAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    addSon(result, left, expression(p, 29))
-  of pxPlusAsgn: # 30
-    result = newNodeP(nkCall, p)
-    addSon(result, newIdentNodeP(getIdent("inc"), p), left, expression(p, 29))
-  of pxMinusAsgn: # 30
-    result = newNodeP(nkCall, p)
-    addSon(result, newIdentNodeP(getIdent("dec"), p), left, expression(p, 29))
-  of pxStarAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("*", copyTree(left), right, p))
-  of pxSlashAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("/", copyTree(left), right, p))
-  of pxModAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("mod", copyTree(left), right, p))
-  of pxShlAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("shl", copyTree(left), right, p))
-  of pxShrAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("shr", copyTree(left), right, p))
-  of pxAmpAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("and", copyTree(left), right, p))
-  of pxHatAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("xor", copyTree(left), right, p))
-  of pxBarAsgn: # 30
-    result = newNodeP(nkAsgn, p)
-    var right = expression(p, 29)
-    addSon(result, left, newBinary("or", copyTree(left), right, p))
-  of pxConditional: # 40
-    var a = expression(p, 0)
-    eat(p, pxColon, a)
-    var b = expression(p, 39)
-    result = newNodeP(nkIfExpr, p)
-    var branch = newNodeP(nkElifExpr, p)
-    addSon(branch, left, a)
-    addSon(result, branch)
-    branch = newNodeP(nkElseExpr, p)
-    addSon(branch, b)
-    addSon(result, branch)
-  of pxBarBar: # 50
-    result = newBinary("or", left, expression(p, 50), p)
-  of pxAmpAmp: # 60
-    result = newBinary("and", left, expression(p, 60), p)
-  of pxBar: # 70
-    result = newBinary("or", left, expression(p, 70), p)
-  of pxHat: # 80
-    result = newBinary("^", left, expression(p, 80), p)
-  of pxAmp: # 90
-    result = newBinary("and", left, expression(p, 90), p)
-  of pxEquals: # 100
-    result = newBinary("==", left, expression(p, 100), p)
-  of pxNeq: # 100
-    result = newBinary("!=", left, expression(p, 100), p)
-  of pxLt: # 110
-    result = newBinary("<", left, expression(p, 110), p)
-  of pxLe: # 110
-    result = newBinary("<=", left, expression(p, 110), p)
-  of pxGt: # 110
-    result = newBinary(">", left, expression(p, 110), p)
-  of pxGe: # 110
-    result = newBinary(">=", left, expression(p, 110), p)
-  of pxShl: # 120
-    result = newBinary("shl", left, expression(p, 120), p)
-  of pxShr: # 120
-    result = newBinary("shr", left, expression(p, 120), p)
-  of pxPlus: # 130
-    result = newNodeP(nkInfix, p)
-    addSon(result, newIdentNodeP("+", p), left)
-    addSon(result, expression(p, 130))
-  of pxMinus: # 130
-    result = newNodeP(nkInfix, p)
-    addSon(result, newIdentNodeP("+", p), left)
-    addSon(result, expression(p, 130))
-  of pxStar: # 140
-    result = newNodeP(nkInfix, p)
-    addSon(result, newIdentNodeP("*", p), left)
-    addSon(result, expression(p, 140))
-  of pxSlash: # 140
-    result = newNodeP(nkInfix, p)
-    addSon(result, newIdentNodeP("div", p), left)
-    addSon(result, expression(p, 140))
-  of pxMod: # 140
-    result = newNodeP(nkInfix, p)
-    addSon(result, newIdentNodeP("mod", p), left)
-    addSon(result, expression(p, 140))
-    # .* ->* == 150
-  of pxPlusPlus: # 160
-    result = newNodeP(nkCall, p)
-    addSon(result, newIdentNodeP("inc", p), left)
-  of pxMinusMinus: # 160
-    result = newNodeP(nkCall, p)
-    addSon(result, newIdentNodeP("dec", p), left)
-  of pxParLe: # 160
-    result = newNodeP(nkCall, p)
-    addSon(result, left)
-    while p.tok.xkind != pxParRi:
-      var a = expression(p, 29)
-      addSon(result, a)
-      while p.tok.xkind == pxComma:
-        getTok(p, a)
-        a = expression(p, 29)
-        addSon(result, a)
-    eat(p, pxParRi, result)
-  of pxDot: # 160
-    result = newNodeP(nkDotExpr, p)
-    addSon(result, left)
-    addSon(result, skipIdent(p))
-  of pxArrow: # 160
-    result = newNodeP(nkDotExpr, p)
-    addSon(result, left)
-    addSon(result, skipIdent(p))
-  of pxBracketLe: # 160
-    result = newNodeP(nkBracketExpr, p)
-    addSon(result, left, expression(p))
-    eat(p, pxBracketRi, result)
-    # :: == 170
-  else:
-    result = left
-
-proc expression*(p : var TParser, rbp : int = 0) : PNode =
-  var tok : TToken
-
-  tok = p.tok[]
-  getTok(p, result)
-
-  result = startExpression(p, tok)
-
-  while rbp < leftBindingPower(p, p.tok):
-    tok = p.tok[]
-    getTok(p, result)
-    result = leftExpression(p, tok, result)
-    
-# Statements
-
-proc buildStmtList(a: PNode): PNode = 
-  if a.kind == nkStmtList: result = a
-  else:
-    result = newNodeI(nkStmtList, a.info)
-    addSon(result, a)
-
-proc nestedStatement(p: var TParser): PNode =
-  # careful: We need to translate:
-  # if (x) if (y) stmt;
-  # into:
-  # if x:
-  #   if x:
-  #     stmt
-  # 
-  # Nimrod requires complex statements to be nested in whitespace!
-  const
-    complexStmt = {nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef,
-      nkTemplateDef, nkIteratorDef, nkIfStmt,
-      nkWhenStmt, nkForStmt, nkWhileStmt, nkCaseStmt, nkVarSection, 
-      nkConstSection, nkTypeSection, nkTryStmt, nkBlockStmt, nkStmtList,
-      nkCommentStmt, nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType}
-  result = statement(p)
-  if result.kind in complexStmt:
-    result = buildStmtList(result)
-
-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
-  result = newNodeP(nkIfStmt, p)
-  while true: 
-    getTok(p) # skip ``if``
-    var branch = newNodeP(nkElifBranch, p)
-    eat(p, pxParLe, branch)
-    addSon(branch, expression(p))
-    eat(p, pxParRi, branch)
-    addSon(branch, nestedStatement(p))
-    addSon(result, branch)
-    skipCom(p, branch)
-    if p.tok.s == "else": 
-      getTok(p, result)
-      if p.tok.s != "if": 
-        # ordinary else part:
-        branch = newNodeP(nkElse, p)
-        addSon(branch, nestedStatement(p))
-        addSon(result, branch)
-        break 
-    else: 
-      break 
-  
-proc parseWhile(p: var TParser): PNode = 
-  result = newNodeP(nkWhileStmt, p)
-  getTok(p, result)
-  eat(p, pxParLe, result)
-  addSon(result, expression(p))
-  eat(p, pxParRi, result)
-  addSon(result, nestedStatement(p))
-
-proc embedStmts(sl, a: PNode)
-
-proc parseDoWhile(p: var TParser): PNode =  
-  # parsing
-  result = newNodeP(nkWhileStmt, p)
-  getTok(p, result)
-  var stm = nestedStatement(p)
-  eat(p, "while", result)
-  eat(p, pxParLe, result)
-  var exp = expression(p)
-  eat(p, pxParRi, result)
-  if p.tok.xkind == pxSemicolon: getTok(p)
-
-  # while true:
-  #   stmt
-  #   if not expr:
-  #     break
-  addSon(result, newIdentNodeP("true", p))
-
-  stm = buildStmtList(stm)
-
-  # get the last exp if it is a stmtlist
-  var cleanedExp = exp
-  if exp.kind == nkStmtList:
-    cleanedExp = exp.sons[exp.len-1]
-    exp.sons = exp.sons[0..exp.len-2]
-    embedStmts(stm, exp)
-
-  var notExp = newNodeP(nkPrefix, p)
-  addSon(notExp, newIdentNodeP("not", p))
-  addSon(notExp, cleanedExp)
-
-  var brkStm = newNodeP(nkBreakStmt, p)
-  addSon(brkStm, ast.emptyNode)
-
-  var ifStm = newNodeP(nkIfStmt, p)
-  var ifBranch = newNodeP(nkElifBranch, p)
-  addSon(ifBranch, notExp)
-  addSon(ifBranch, brkStm)
-  addSon(ifStm, ifBranch)
-
-  embedStmts(stm, ifStm)
-
-  addSon(result, stm)
-
-proc declarationOrStatement(p: var TParser): PNode = 
-  if p.tok.xkind != pxSymbol:
-    result = expressionStatement(p)
-  elif declKeyword(p, p.tok.s): 
-    result = declaration(p)
-  else:
-    # ordinary identifier:
-    saveContext(p)
-    getTok(p) # skip identifier to look ahead
-    case p.tok.xkind
-    of pxSymbol, pxStar, pxLt, pxAmp, pxAmpAmp:
-      # we parse 
-      # a b
-      # a * b
-      # always as declarations! This is of course not correct, but good
-      # enough for most real world C code out there.
-      backtrackContext(p)
-      result = declaration(p)
-    of pxColon: 
-      # it is only a label:
-      closeContext(p)
-      getTok(p)
-      result = statement(p)
-    else: 
-      backtrackContext(p)
-      result = expressionStatement(p)
-  assert result != nil
-
-proc parseTuple(p: var TParser, statements: PNode, isUnion: bool): PNode = 
-  parseStructBody(p, statements, isUnion, nkTupleTy)
-
-proc parseTrailingDefinedIdents(p: var TParser, result, baseTyp: PNode) =
-  var varSection = newNodeP(nkVarSection, p)
-  while p.tok.xkind notin {pxEof, pxSemicolon}:
-    var t = pointer(p, baseTyp)
-    expectIdent(p)
-    var def = newNodeP(nkIdentDefs, p)
-    addSon(def, varIdent(p.tok.s, p))
-    getTok(p, def)
-    addSon(def, parseTypeSuffix(p, t))
-    addInitializer(p, def)
-    addSon(varSection, def)
-    if p.tok.xkind != pxComma: break
-    getTok(p, def)
-  eat(p, pxSemicolon)
-  if sonsLen(varSection) > 0:
-    addSon(result, varSection)
-
-proc parseStandaloneStruct(p: var TParser, isUnion: bool): PNode =
-  result = newNodeP(nkStmtList, p)
-  saveContext(p)
-  getTok(p, result) # skip "struct" or "union"
-  var origName = ""
-  if p.tok.xkind == pxSymbol: 
-    markTypeIdent(p, nil)
-    origName = p.tok.s
-    getTok(p, result)
-  if p.tok.xkind in {pxCurlyLe, pxSemiColon}:
-    if origName.len > 0: 
-      var name = mangledIdent(origName, p)
-      var t = parseStruct(p, result, isUnion)
-      var typeSection = newNodeP(nkTypeSection, p)
-      addTypeDef(typeSection, structPragmas(p, name, origName), t)
-      addSon(result, typeSection)
-      parseTrailingDefinedIdents(p, result, name)
-    else:
-      var t = parseTuple(p, result, isUnion)
-      parseTrailingDefinedIdents(p, result, t)
-  else:
-    backtrackContext(p)
-    result = declaration(p)
-
-proc parseFor(p: var TParser, result: PNode) = 
-  # 'for' '(' expression_statement expression_statement expression? ')'
-  #   statement
-  getTok(p, result)
-  eat(p, pxParLe, result)
-  var initStmt = declarationOrStatement(p)
-  if initStmt.kind != nkEmpty:
-    embedStmts(result, initStmt)
-  var w = newNodeP(nkWhileStmt, p)
-  var condition = expressionStatement(p)
-  if condition.kind == nkEmpty: condition = newIdentNodeP("true", p)
-  addSon(w, condition)
-  var step = if p.tok.xkind != pxParRi: expression(p) else: ast.emptyNode
-  eat(p, pxParRi, step)
-  var loopBody = nestedStatement(p)
-  if step.kind != nkEmpty:
-    loopBody = buildStmtList(loopBody)
-    embedStmts(loopBody, step)
-  addSon(w, loopBody)
-  addSon(result, w)
-  
-proc switchStatement(p: var TParser): PNode = 
-  result = newNodeP(nkStmtList, p)
-  while true:
-    if p.tok.xkind in {pxEof, pxCurlyRi}: break
-    case p.tok.s 
-    of "break":
-      getTok(p, result)
-      eat(p, pxSemicolon, result)
-      break
-    of "return", "continue", "goto": 
-      addSon(result, statement(p))
-      break
-    of "case", "default":
-      break
-    else: discard
-    addSon(result, statement(p))
-  if sonsLen(result) == 0:
-    # translate empty statement list to Nimrod's ``nil`` statement
-    result = newNodeP(nkNilLit, p)
-
-proc rangeExpression(p: var TParser): PNode =
-  # We support GCC's extension: ``case expr...expr:`` 
-  result = constantExpression(p)
-  if p.tok.xkind == pxDotDotDot:
-    getTok(p, result)
-    var a = result
-    var b = constantExpression(p)
-    result = newNodeP(nkRange, p)
-    addSon(result, a)
-    addSon(result, b)
-
-proc parseSwitch(p: var TParser): PNode = 
-  # We cannot support Duff's device or C's crazy switch syntax. We just support
-  # sane usages of switch. ;-)
-  result = newNodeP(nkCaseStmt, p)
-  getTok(p, result)
-  eat(p, pxParLe, result)
-  addSon(result, expression(p))
-  eat(p, pxParRi, result)
-  eat(p, pxCurlyLe, result)
-  var b: PNode
-  while (p.tok.xkind != pxCurlyRi) and (p.tok.xkind != pxEof): 
-    case p.tok.s 
-    of "default": 
-      b = newNodeP(nkElse, p)
-      getTok(p, b)
-      eat(p, pxColon, b)
-    of "case": 
-      b = newNodeP(nkOfBranch, p)
-      while p.tok.xkind == pxSymbol and p.tok.s == "case":
-        getTok(p, b)
-        addSon(b, rangeExpression(p))
-        eat(p, pxColon, b)
-    else:
-      parMessage(p, errXExpected, "case")
-    addSon(b, switchStatement(p))
-    addSon(result, b)
-    if b.kind == nkElse: break 
-  eat(p, pxCurlyRi)
-
-proc addStmt(sl, a: PNode) = 
-  # merge type sections if possible:
-  if a.kind != nkTypeSection or sonsLen(sl) == 0 or
-      lastSon(sl).kind != nkTypeSection:
-    addSon(sl, a)
-  else:
-    var ts = lastSon(sl)
-    for i in 0..sonsLen(a)-1: addSon(ts, a.sons[i])
-
-proc embedStmts(sl, a: PNode) = 
-  if a.kind != nkStmtList:
-    addStmt(sl, a)
-  else:
-    for i in 0..sonsLen(a)-1: 
-      if a[i].kind != nkEmpty: addStmt(sl, a[i])
-
-proc compoundStatement(p: var TParser): PNode = 
-  result = newNodeP(nkStmtList, p)
-  eat(p, pxCurlyLe)
-  inc(p.scopeCounter)
-  while p.tok.xkind notin {pxEof, pxCurlyRi}: 
-    var a = statement(p)
-    if a.kind == nkEmpty: break
-    embedStmts(result, a)
-  if sonsLen(result) == 0:
-    # translate ``{}`` to Nimrod's ``discard`` statement
-    result = newNodeP(nkDiscardStmt, p)
-    result.add(ast.emptyNode)
-  dec(p.scopeCounter)
-  eat(p, pxCurlyRi)
-
-proc skipInheritKeyw(p: var TParser) =
-  if p.tok.xkind == pxSymbol and (p.tok.s == "private" or 
-                                  p.tok.s == "protected" or
-                                  p.tok.s == "public"):
-    getTok(p)
-
-proc parseConstructor(p: var TParser, pragmas: PNode, 
-                      isDestructor=false): PNode =
-  var origName = p.tok.s
-  getTok(p)
-  
-  result = newNodeP(nkProcDef, p)
-  var rettyp = if isDestructor: newNodeP(nkNilLit, p)
-               else: mangledIdent(origName, p)
-  
-  let oname = if isDestructor: "destroy" & origName
-              else: "construct" & origName
-  var name = mangledIdent(oname, p)
-  var params = newNodeP(nkFormalParams, p)
-  addReturnType(params, rettyp)
-  if p.tok.xkind == pxParLe:
-    parseFormalParams(p, params, pragmas)
-  if p.tok.xkind == pxSymbol and p.tok.s == "const":
-    addSon(pragmas, newIdentNodeP("noSideEffect", p))
-  if pfCDecl in p.options.flags:
-    addSon(pragmas, newIdentNodeP("cdecl", p))
-  elif pfStdcall in p.options.flags:
-    addSon(pragmas, newIdentNodeP("stdcall", p))
-  if p.tok.xkind == pxColon:
-    # skip initializer list:
-    while true:
-      getTok(p)
-      discard expression(p)
-      if p.tok.xkind != pxComma: break
-  # no pattern, no exceptions:
-  addSon(result, exportSym(p, name, origName), ast.emptyNode, ast.emptyNode)
-  addSon(result, params, pragmas, ast.emptyNode) # no exceptions
-  addSon(result, ast.emptyNode) # no body
-  case p.tok.xkind 
-  of pxSemicolon: getTok(p)
-  of pxCurlyLe:
-    let body = compoundStatement(p)
-    if pfKeepBodies in p.options.flags:
-      result.sons[bodyPos] = body
-  else:
-    parMessage(p, errTokenExpected, ";")
-  if result.sons[bodyPos].kind == nkEmpty:
-    doImport((if isDestructor: "~" else: "") & origName, pragmas, p)
-  elif isDestructor:
-    addSon(pragmas, newIdentNodeP("destructor", p))
-  if sonsLen(result.sons[pragmasPos]) == 0:
-    result.sons[pragmasPos] = ast.emptyNode
-
-proc parseMethod(p: var TParser, origName: string, rettyp, pragmas: PNode,
-                 isStatic: bool): PNode =
-  result = newNodeP(nkProcDef, p)
-  var params = newNodeP(nkFormalParams, p)
-  addReturnType(params, rettyp)
-  var thisDef = newNodeP(nkIdentDefs, p)
-  if not isStatic:
-    # declare 'this':
-    var t = newNodeP(nkVarTy, p)
-    t.add(p.currentClass)
-    addSon(thisDef, newIdentNodeP("this", p), t, ast.emptyNode)
-    params.add(thisDef)
-  parseFormalParams(p, params, pragmas)
-  if p.tok.xkind == pxSymbol and p.tok.s == "const":
-    addSon(pragmas, newIdentNodeP("noSideEffect", p))
-    getTok(p, result)
-    if not isStatic:
-      # fix the type of the 'this' parameter:
-      thisDef.sons[1] = thisDef.sons[1].sons[0]
-  if pfCDecl in p.options.flags:
-    addSon(pragmas, newIdentNodeP("cdecl", p))
-  elif pfStdcall in p.options.flags:
-    addSon(pragmas, newIdentNodeP("stdcall", p))
-  # no pattern, no exceptions:
-  let methodName = newIdentNodeP(origName, p)
-  addSon(result, exportSym(p, methodName, origName),
-         ast.emptyNode, ast.emptyNode)
-  addSon(result, params, pragmas, ast.emptyNode) # no exceptions
-  addSon(result, ast.emptyNode) # no body
-  case p.tok.xkind
-  of pxSemicolon: getTok(p)
-  of pxCurlyLe:
-    let body = compoundStatement(p)
-    if pfKeepBodies in p.options.flags:
-      result.sons[bodyPos] = body
-  else:
-    parMessage(p, errTokenExpected, ";")
-  if result.sons[bodyPos].kind == nkEmpty:
-    if isStatic: doImport(origName, pragmas, p)
-    else: doImportCpp(origName, pragmas, p)
-  if sonsLen(result.sons[pragmasPos]) == 0:
-    result.sons[pragmasPos] = ast.emptyNode
-
-proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode
-
-proc followedByParLe(p: var TParser): bool =
-  saveContext(p)
-  getTok(p) # skip Identifier
-  result = p.tok.xkind == pxParLe
-  backtrackContext(p)
-
-proc parseOperator(p: var TParser, origName: var string): bool =
-  getTok(p) # skip 'operator' keyword
-  case p.tok.xkind
-  of pxAmp..pxArrow:
-    # ordinary operator symbol:
-    origName.add(tokKindToStr(p.tok.xkind))
-    getTok(p)
-  of pxSymbol:
-    if p.tok.s == "new" or p.tok.s == "delete":
-      origName.add(p.tok.s)
-      getTok(p)
-      if p.tok.xkind == pxBracketLe:
-        getTok(p)
-        eat(p, pxBracketRi)
-        origName.add("[]")
-    else:
-      # type converter
-      let x = typeAtom(p)
-      if x.kind == nkIdent:
-        origName.add(x.ident.s)
-      else:
-        parMessage(p, errGenerated, "operator symbol expected")
-      result = true
-  of pxParLe:
-    getTok(p)
-    eat(p, pxParRi)
-    origName.add("()")
-  of pxBracketLe:
-    getTok(p)
-    eat(p, pxBracketRi)
-    origName.add("[]")
-  else:
-    parMessage(p, errGenerated, "operator symbol expected")
-
-proc parseClass(p: var TParser; isStruct: bool; stmtList: PNode): PNode =
-  result = newNodeP(nkObjectTy, p)
-  addSon(result, ast.emptyNode, ast.emptyNode) # no pragmas, no inheritance 
-  
-  var recList = newNodeP(nkRecList, p)
-  addSon(result, recList)
-  if p.tok.xkind == pxColon:
-    getTok(p, result)
-    skipInheritKeyw(p)
-    var baseTyp = typeAtom(p)
-    var inh = newNodeP(nkOfInherit, p)
-    inh.add(baseTyp)
-    if p.tok.xkind == pxComma:
-      parMessage(p, errGenerated, "multiple inheritance is not supported")
-      while p.tok.xkind == pxComma:
-        getTok(p)
-        skipInheritKeyw(p)
-        discard typeAtom(p)
-    result.sons[0] = inh
-    
-  eat(p, pxCurlyLe, result)
-  var private = not isStruct
-  var pragmas = newNodeP(nkPragma, p)
-  while p.tok.xkind notin {pxEof, pxCurlyRi}:
-    skipCom(p, stmtList)
-    if p.tok.xkind == pxSymbol and (p.tok.s == "private" or 
-                                    p.tok.s == "protected"):
-      getTok(p, result)
-      eat(p, pxColon, result)
-      private = true
-    elif p.tok.xkind == pxSymbol and p.tok.s == "public":
-      getTok(p, result)
-      eat(p, pxColon, result)
-      private = false
-    if p.tok.xkind == pxSymbol and (p.tok.s == "friend" or p.tok.s == "using"):
-      # we skip friend declarations:
-      while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p)
-      eat(p, pxSemicolon)
-    elif p.tok.xkind == pxSymbol and p.tok.s == "enum":
-      let x = enumSpecifier(p)
-      if not private or pfKeepBodies in p.options.flags: stmtList.add(x)
-    elif p.tok.xkind == pxSymbol and p.tok.s == "typedef":
-      let x = parseTypeDef(p)
-      if not private or pfKeepBodies in p.options.flags: stmtList.add(x)
-    elif p.tok.xkind == pxSymbol and(p.tok.s == "struct" or p.tok.s == "class"):
-      let x = parseStandaloneClass(p, isStruct=p.tok.s == "struct")
-      if not private or pfKeepBodies in p.options.flags: stmtList.add(x)
-    elif p.tok.xkind == pxSymbol and p.tok.s == "union":
-      let x = parseStandaloneStruct(p, isUnion=true)
-      if not private or pfKeepBodies in p.options.flags: stmtList.add(x)
-    else:
-      if pragmas.len != 0: pragmas = newNodeP(nkPragma, p)
-      parseCallConv(p, pragmas)
-      var isStatic = false
-      if p.tok.xkind == pxSymbol and p.tok.s == "virtual":
-        getTok(p, stmtList)
-      if p.tok.xkind == pxSymbol and p.tok.s == "explicit":
-        getTok(p, stmtList)
-      if p.tok.xkind == pxSymbol and p.tok.s == "static":
-        getTok(p, stmtList)
-        isStatic = true
-      parseCallConv(p, pragmas)
-      if p.tok.xkind == pxSymbol and p.tok.s == p.currentClass.ident.s and 
-          followedByParLe(p):
-        # constructor
-        let cons = parseConstructor(p, pragmas)
-        if not private or pfKeepBodies in p.options.flags: stmtList.add(cons)
-      elif p.tok.xkind == pxTilde:
-        # destructor
-        getTok(p, stmtList)
-        if p.tok.xkind == pxSymbol and p.tok.s == p.currentClass.ident.s:
-          let des = parseConstructor(p, pragmas, isDestructor=true)
-          if not private or pfKeepBodies in p.options.flags: stmtList.add(des)
-        else:
-          parMessage(p, errGenerated, "invalid destructor")
-      else:
-        # field declaration or method:
-        var baseTyp = typeAtom(p)
-        while true:
-          var def = newNodeP(nkIdentDefs, p)
-          var t = pointer(p, baseTyp)
-          let canBeMethod = p.tok.xkind != pxParLe
-          var origName: string
-          if p.tok.xkind == pxSymbol:
-            origName = p.tok.s
-            if p.tok.s == "operator":
-              var isConverter = parseOperator(p, origName)
-              let meth = parseMethod(p, origName, t, pragmas, isStatic)
-              if not private or pfKeepBodies in p.options.flags:
-                if isConverter: meth.kind = nkConverterDef
-                stmtList.add(meth)
-              break
-          var i = parseField(p, nkRecList)
-          if canBeMethod and p.tok.xkind == pxParLe:
-            let meth = parseMethod(p, origName, t, pragmas, isStatic)
-            if not private or pfKeepBodies in p.options.flags:
-              stmtList.add(meth)
-          else:
-            t = parseTypeSuffix(p, t)
-            addSon(def, i, t, ast.emptyNode)
-            if not isStatic: addSon(recList, def)
-          if p.tok.xkind != pxComma: break
-          getTok(p, def)
-        if p.tok.xkind == pxSemicolon:
-          getTok(p, lastSon(recList))
-  eat(p, pxCurlyRi, result)
-
-proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode =
-  result = newNodeP(nkStmtList, p)
-  saveContext(p)
-  getTok(p, result) # skip "class" or "struct"
-  var origName = ""
-  let oldClass = p.currentClass
-  if p.tok.xkind == pxSymbol: 
-    markTypeIdent(p, nil)
-    origName = p.tok.s
-    getTok(p, result)
-    p.currentClass = mangledIdent(origName, p)
-  else:
-    p.currentClass = nil
-  if p.tok.xkind in {pxCurlyLe, pxSemiColon, pxColon}:
-    if origName.len > 0:
-      p.options.classes[origName] = "true"
-
-      var typeSection = newNodeP(nkTypeSection, p)
-      addSon(result, typeSection)
-      
-      var name = mangledIdent(origName, p)
-      var t = parseClass(p, isStruct, result)
-      addTypeDef(typeSection, structPragmas(p, name, origName), t)
-      parseTrailingDefinedIdents(p, result, name)
-    else:
-      var t = parseTuple(p, result, isUnion=false)
-      parseTrailingDefinedIdents(p, result, t)
-  else:
-    backtrackContext(p)
-    result = declaration(p)
-  p.currentClass = oldClass
-
-proc unwrap(a: PNode): PNode =
-  if a.kind == nkPar:
-    return a.sons[0]
-  return a
-
-include cpp
-
-proc statement(p: var TParser): PNode = 
-  case p.tok.xkind 
-  of pxSymbol: 
-    case p.tok.s
-    of "if": result = parseIf(p)
-    of "switch": result = parseSwitch(p)
-    of "while": result = parseWhile(p)
-    of "do": result = parseDoWhile(p)
-    of "for": 
-      result = newNodeP(nkStmtList, p)
-      parseFor(p, result)
-    of "goto": 
-      # we cannot support "goto"; in hand-written C, "goto" is most often used
-      # to break a block, so we convert it to a break statement with label.
-      result = newNodeP(nkBreakStmt, p)
-      getTok(p)
-      addSon(result, skipIdent(p))
-      eat(p, pxSemicolon)
-    of "continue":
-      result = newNodeP(nkContinueStmt, p)
-      getTok(p)
-      eat(p, pxSemicolon)
-      addSon(result, ast.emptyNode)
-    of "break":
-      result = newNodeP(nkBreakStmt, p)
-      getTok(p)
-      eat(p, pxSemicolon)
-      addSon(result, ast.emptyNode)
-    of "return":
-      result = newNodeP(nkReturnStmt, p)
-      getTok(p)
-      if p.tok.xkind == pxSemicolon:
-        addSon(result, ast.emptyNode)
-      else:
-        addSon(result, unwrap(expression(p)))
-      eat(p, pxSemicolon)
-    of "enum": result = enumSpecifier(p)
-    of "typedef": result = parseTypeDef(p)
-    of "union": result = parseStandaloneStruct(p, isUnion=true)
-    of "struct":
-      if pfCpp in p.options.flags:
-        result = parseStandaloneClass(p, isStruct=true)
-      else:
-        result = parseStandaloneStruct(p, isUnion=false)
-    of "class":
-      if pfCpp in p.options.flags:
-        result = parseStandaloneClass(p, isStruct=false)
-      else:
-        result = declarationOrStatement(p)
-    of "namespace":
-      if pfCpp in p.options.flags:
-        while p.tok.xkind notin {pxEof, pxCurlyLe}: getTok(p)
-        result = compoundStatement(p)
-      else:
-        result = declarationOrStatement(p)
-    of "using":
-      if pfCpp in p.options.flags:
-        while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p)
-        eat(p, pxSemicolon)
-        result = newNodeP(nkNilLit, p)
-      else:
-        result = declarationOrStatement(p)
-    else: result = declarationOrStatement(p)
-  of pxCurlyLe:
-    result = compoundStatement(p)
-  of pxDirective, pxDirectiveParLe:
-    result = parseDir(p)
-  of pxLineComment, pxStarComment:
-    result = newNodeP(nkCommentStmt, p)
-    skipCom(p, result)
-  of pxSemicolon:
-    # empty statement:
-    getTok(p)
-    if p.tok.xkind in {pxLineComment, pxStarComment}:
-      result = newNodeP(nkCommentStmt, p)
-      skipCom(p, result)
-    else:
-      result = newNodeP(nkNilLit, p)
-  else:
-    result = expressionStatement(p)
-  assert result != nil
-
-proc parseUnit(p: var TParser): PNode =
-  try:
-    result = newNodeP(nkStmtList, p)
-    getTok(p) # read first token
-    while p.tok.xkind != pxEof:
-      var s = statement(p)
-      if s.kind != nkEmpty: embedStmts(result, s)
-  except ERetryParsing:
-    parMessage(p, errGenerated, "Uncaught parsing exception raised")
-
diff --git a/compiler/c2nim/cpp.nim b/compiler/c2nim/cpp.nim
deleted file mode 100644
index 84b4c4dfb..000000000
--- a/compiler/c2nim/cpp.nim
+++ /dev/null
@@ -1,347 +0,0 @@
-#
-#
-#      c2nim - C to Nimrod source converter
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# Preprocessor support
-
-const
-  c2nimSymbol = "C2NIM"
-
-proc eatNewLine(p: var TParser, n: PNode) = 
-  if p.tok.xkind == pxLineComment:
-    skipCom(p, n)
-    if p.tok.xkind == pxNewLine: getTok(p)
-  elif p.tok.xkind == pxNewLine: 
-    eat(p, pxNewLine)
-  
-proc skipLine(p: var TParser) = 
-  while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}: getTok(p)
-  eatNewLine(p, nil)
-
-proc parseDefineBody(p: var TParser, tmplDef: PNode): string = 
-  if p.tok.xkind == pxCurlyLe or 
-    (p.tok.xkind == pxSymbol and (
-        declKeyword(p, p.tok.s) or stmtKeyword(p.tok.s))):
-    addSon(tmplDef, statement(p))
-    result = "stmt"
-  elif p.tok.xkind in {pxLineComment, pxNewLine}:
-    addSon(tmplDef, buildStmtList(newNodeP(nkNilLit, p)))
-    result = "stmt"
-  else:
-    addSon(tmplDef, buildStmtList(expression(p)))
-    result = "expr"
-
-proc parseDefine(p: var TParser): PNode = 
-  if p.tok.xkind == pxDirectiveParLe: 
-    # a macro with parameters:
-    result = newNodeP(nkTemplateDef, p)
-    getTok(p)
-    addSon(result, skipIdentExport(p))
-    addSon(result, ast.emptyNode)
-    eat(p, pxParLe)
-    var params = newNodeP(nkFormalParams, p)
-    # return type; not known yet:
-    addSon(params, ast.emptyNode)
-    if p.tok.xkind != pxParRi:
-      var identDefs = newNodeP(nkIdentDefs, p)
-      while p.tok.xkind != pxParRi: 
-        addSon(identDefs, skipIdent(p))
-        skipStarCom(p, nil)
-        if p.tok.xkind != pxComma: break
-        getTok(p)
-      addSon(identDefs, newIdentNodeP("expr", p))
-      addSon(identDefs, ast.emptyNode)
-      addSon(params, identDefs)
-    eat(p, pxParRi)
-    
-    addSon(result, ast.emptyNode) # no generic parameters
-    addSon(result, params)
-    addSon(result, ast.emptyNode) # no pragmas
-    addSon(result, ast.emptyNode)
-    var kind = parseDefineBody(p, result)
-    params.sons[0] = newIdentNodeP(kind, p)
-    eatNewLine(p, result)
-  else:
-    # a macro without parameters:
-    result = newNodeP(nkConstSection, p)
-    while p.tok.xkind == pxDirective and p.tok.s == "define":
-      getTok(p) # skip #define
-      var c = newNodeP(nkConstDef, p)
-      addSon(c, skipIdentExport(p))
-      addSon(c, ast.emptyNode)
-      skipStarCom(p, c)
-      if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}:
-        addSon(c, newIdentNodeP("true", p))
-      else:
-        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 = @[]
-  # A little hack: We safe the context, so that every following token will be 
-  # put into a newly allocated TToken object. Thus we can just save a
-  # reference to the token in the macro's body.
-  saveContext(p)
-  while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}: 
-    case p.tok.xkind 
-    of pxSymbol:
-      # is it a parameter reference?
-      var tok = p.tok
-      for i in 0..high(params):
-        if params[i] == p.tok.s: 
-          new(tok)
-          tok.xkind = pxMacroParam
-          tok.iNumber = i
-          break
-      m.body.add(tok)
-    of pxDirConc: 
-      # just ignore this token: this implements token merging correctly
-      discard
-    else:
-      m.body.add(p.tok)
-    # we do not want macro expansion here:
-    rawGetTok(p)
-  eatNewLine(p, nil)
-  closeContext(p) 
-  # newline token might be overwritten, but this is not
-  # part of the macro body, so it is safe.
-  
-proc parseDef(p: var TParser, m: var TMacro) = 
-  var hasParams = p.tok.xkind == pxDirectiveParLe
-  getTok(p)
-  expectIdent(p)
-  m.name = p.tok.s
-  getTok(p)
-  var params: seq[string] = @[]
-  # parse parameters:
-  if hasParams:
-    eat(p, pxParLe)
-    while p.tok.xkind != pxParRi: 
-      expectIdent(p)
-      params.add(p.tok.s)
-      getTok(p)
-      skipStarCom(p, nil)
-      if p.tok.xkind != pxComma: break
-      getTok(p)
-    eat(p, pxParRi)
-  m.params = params.len
-  parseDefBody(p, m, params)
-  
-proc isDir(p: TParser, dir: string): bool = 
-  result = p.tok.xkind in {pxDirectiveParLe, pxDirective} and p.tok.s == dir
-
-proc parseInclude(p: var TParser): PNode = 
-  result = newNodeP(nkImportStmt, p)
-  while isDir(p, "include"):
-    getTok(p) # skip "include"
-    if p.tok.xkind == pxStrLit and pfSkipInclude notin p.options.flags:
-      var file = newStrNodeP(nkStrLit, changeFileExt(p.tok.s, ""), p)
-      addSon(result, file)
-      getTok(p)
-      skipStarCom(p, file)
-      eatNewLine(p, nil)
-    else:
-      skipLine(p)
-  if sonsLen(result) == 0: 
-    # we only parsed includes that we chose to ignore:
-    result = ast.emptyNode
-
-proc definedExprAux(p: var TParser): PNode = 
-  result = newNodeP(nkCall, p)
-  addSon(result, newIdentNodeP("defined", p))
-  addSon(result, skipIdent(p))
-
-proc parseStmtList(p: var TParser): PNode = 
-  result = newNodeP(nkStmtList, p)
-  while true: 
-    case p.tok.xkind
-    of pxEof: break 
-    of pxDirectiveParLe, pxDirective: 
-      case p.tok.s
-      of "else", "endif", "elif": break
-    else: discard
-    addSon(result, statement(p))
-  
-proc eatEndif(p: var TParser) =
-  if isDir(p, "endif"): 
-    skipLine(p)
-  else: 
-    parMessage(p, errXExpected, "#endif")
-  
-proc parseIfDirAux(p: var TParser, result: PNode) = 
-  addSon(result.sons[0], parseStmtList(p))
-  while isDir(p, "elif"): 
-    var b = newNodeP(nkElifBranch, p)
-    getTok(p)
-    addSon(b, expression(p))
-    eatNewLine(p, nil)
-    addSon(b, parseStmtList(p))
-    addSon(result, b)
-  if isDir(p, "else"): 
-    var s = newNodeP(nkElse, p)
-    skipLine(p)
-    addSon(s, parseStmtList(p))
-    addSon(result, s)
-  eatEndif(p)
-    
-proc skipUntilEndif(p: var TParser) =
-  var nested = 1
-  while p.tok.xkind != pxEof:
-    if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"): 
-      inc(nested)
-    elif isDir(p, "endif"): 
-      dec(nested)
-      if nested <= 0:
-        skipLine(p)
-        return
-    getTok(p)
-  parMessage(p, errXExpected, "#endif")
-  
-type
-  TEndifMarker = enum
-    emElif, emElse, emEndif
-  
-proc skipUntilElifElseEndif(p: var TParser): TEndifMarker =
-  var nested = 1
-  while p.tok.xkind != pxEof:
-    if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"): 
-      inc(nested)
-    elif isDir(p, "elif") and nested <= 1:
-      return emElif
-    elif isDir(p, "else") and nested <= 1:
-      return emElse
-    elif isDir(p, "endif"): 
-      dec(nested)
-      if nested <= 0:
-        return emEndif
-    getTok(p)
-  parMessage(p, errXExpected, "#endif")
-  
-proc parseIfdef(p: var TParser): PNode = 
-  getTok(p) # skip #ifdef
-  expectIdent(p)
-  case p.tok.s
-  of "__cplusplus":
-    skipUntilEndif(p)
-    result = ast.emptyNode
-  of c2nimSymbol:
-    skipLine(p)
-    result = parseStmtList(p)
-    skipUntilEndif(p)
-  else:
-    result = newNodeP(nkWhenStmt, p)
-    addSon(result, newNodeP(nkElifBranch, p))
-    addSon(result.sons[0], definedExprAux(p))
-    eatNewLine(p, nil)
-    parseIfDirAux(p, result)
-  
-proc parseIfndef(p: var TParser): PNode = 
-  result = ast.emptyNode
-  getTok(p) # skip #ifndef
-  expectIdent(p)
-  if p.tok.s == c2nimSymbol: 
-    skipLine(p)
-    case skipUntilElifElseEndif(p)
-    of emElif:
-      result = newNodeP(nkWhenStmt, p)
-      addSon(result, newNodeP(nkElifBranch, p))
-      getTok(p)
-      addSon(result.sons[0], expression(p))
-      eatNewLine(p, nil)
-      parseIfDirAux(p, result)
-    of emElse:
-      skipLine(p)
-      result = parseStmtList(p)
-      eatEndif(p)
-    of emEndif: skipLine(p)
-  else:
-    result = newNodeP(nkWhenStmt, p)
-    addSon(result, newNodeP(nkElifBranch, p))
-    var e = newNodeP(nkCall, p)
-    addSon(e, newIdentNodeP("not", p))
-    addSon(e, definedExprAux(p))
-    eatNewLine(p, nil)
-    addSon(result.sons[0], e)
-    parseIfDirAux(p, result)
-  
-proc parseIfDir(p: var TParser): PNode = 
-  result = newNodeP(nkWhenStmt, p)
-  addSon(result, newNodeP(nkElifBranch, p))
-  getTok(p)
-  addSon(result.sons[0], expression(p))
-  eatNewLine(p, nil)
-  parseIfDirAux(p, result)
-
-proc parsePegLit(p: var TParser): TPeg =
-  var col = getColumn(p.lex) + 2
-  getTok(p)
-  if p.tok.xkind != pxStrLit: expectIdent(p)
-  try:
-    result = parsePeg(
-      pattern = if p.tok.xkind == pxStrLit: p.tok.s else: escapePeg(p.tok.s), 
-      filename = p.lex.fileIdx.toFilename, 
-      line = p.lex.linenumber, 
-      col = col)
-    getTok(p)
-  except EInvalidPeg:
-    parMessage(p, errUser, getCurrentExceptionMsg())
-
-proc parseMangleDir(p: var TParser) = 
-  var pattern = parsePegLit(p)
-  if p.tok.xkind != pxStrLit: expectIdent(p)
-  p.options.mangleRules.add((pattern, p.tok.s))
-  getTok(p)
-  eatNewLine(p, nil)
-
-proc modulePragmas(p: var TParser): PNode = 
-  if p.options.dynlibSym.len > 0 and not p.hasDeadCodeElimPragma:
-    p.hasDeadCodeElimPragma = true
-    result = newNodeP(nkPragma, p)
-    var e = newNodeP(nkExprColonExpr, p)
-    addSon(e, newIdentNodeP("deadCodeElim", p), newIdentNodeP("on", p))
-    addSon(result, e)
-  else:
-    result = ast.emptyNode
-
-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)
-  of "include": result = parseInclude(p)
-  of "ifdef": result = parseIfdef(p)
-  of "ifndef": result = parseIfndef(p)
-  of "if": result = parseIfDir(p)
-  of "cdecl", "stdcall", "ref", "skipinclude", "typeprefixes", "skipcomments": 
-    discard setOption(p.options, p.tok.s)
-    getTok(p)
-    eatNewLine(p, nil)
-  of "dynlib", "header", "prefix", "suffix", "class": 
-    var key = p.tok.s
-    getTok(p)
-    if p.tok.xkind != pxStrLit: expectIdent(p)
-    discard setOption(p.options, key, p.tok.s)
-    getTok(p)
-    eatNewLine(p, nil)
-    result = modulePragmas(p)
-  of "mangle":
-    parseMangleDir(p)
-  of "def":
-    var L = p.options.macros.len
-    setLen(p.options.macros, L+1)
-    parseDef(p, p.options.macros[L])
-  of "private":
-    var pattern = parsePegLit(p)
-    p.options.privateRules.add(pattern)
-    eatNewLine(p, nil)
-  else: 
-    # ignore unimportant/unknown directive ("undef", "pragma", "error")
-    skipLine(p)
-
diff --git a/compiler/c2nim/nimrod.cfg b/compiler/c2nim/nimrod.cfg
deleted file mode 100644
index cfeda63ed..000000000
--- a/compiler/c2nim/nimrod.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-# Use the modules of the compiler
-
-path: "$nimrod/compiler"
-
diff --git a/compiler/c2nim/tests/enum.h b/compiler/c2nim/tests/enum.h
deleted file mode 100644
index 16bc59058..000000000
--- a/compiler/c2nim/tests/enum.h
+++ /dev/null
@@ -1,40 +0,0 @@
-
-enum vehicles
-{
-	car = 0x10,
-	truck,
-	boat = 0x01,
-	ship = 1,
-	speedboat = 1,
-	bicycle = 4,
-	bobycar
-};
-
-enum
-{
-	red = 4,
-	green = 2,
-	blue
-};
-
-typedef enum food
-{
-	bread = 4,
-	toast = 4,
-	bun = 0x04,
-	cucumber = 2,
-	chocolate = 6
-};
-
-typedef enum numbers
-{
-	one = 1,
-	two,
-	nten = - 10,
-	nnine,
-	four = 4,
-	three = + 3,
-	positivenine = + 9,
-	nfour = - 4,
-	negativeten = -10
-};
\ No newline at end of file
diff --git a/compiler/c2nim/tests/matrix.h b/compiler/c2nim/tests/matrix.h
deleted file mode 100644
index 715e9e43b..000000000
--- a/compiler/c2nim/tests/matrix.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/////////////////////////////////////////////////////////////////////////////

-// Name:         wx/matrix.h

-// Purpose:      wxTransformMatrix class. NOT YET USED

-// Author:       Chris Breeze, Julian Smart

-// Modified by:  Klaas Holwerda

-// Created:      01/02/97

-// RCS-ID:       $Id$

-// Copyright:    (c) Julian Smart, Chris Breeze

-// Licence:      wxWindows licence

-/////////////////////////////////////////////////////////////////////////////

-

-#ifndef _WX_MATRIXH__

-#define _WX_MATRIXH__

-

-//! headerfiles="matrix.h wx/object.h"

-#include "wx/object.h"

-#include "wx/math.h"

-

-//! codefiles="matrix.cpp"

-

-// A simple 3x3 matrix. This may be replaced by a more general matrix

-// class some day.

-//

-// Note: this is intended to be used in wxDC at some point to replace

-// the current system of scaling/translation. It is not yet used.

-
-#def WXDLLIMPEXP_CORE
-#header "wxmatrix.h"
-

-//:definition

-//  A 3x3 matrix to do 2D transformations.

-//  It can be used to map data to window coordinates,

-//  and also for manipulating your own data.

-//  For example drawing a picture (composed of several primitives)

-//  at a certain coordinate and angle within another parent picture.

-//  At all times m_isIdentity is set if the matrix itself is an Identity matrix.

-//  It is used where possible to optimize calculations.

-class WXDLLIMPEXP_CORE wxTransformMatrix: public wxObject<string, string<ubyte>>

-{

-public:

-    wxTransformMatrix(void);

-    wxTransformMatrix(const wxTransformMatrix& mat);
-    
-    ~wxTransformMatrix(void);

-

-    //get the value in the matrix at col,row

-    //rows are horizontal (second index of m_matrix member)

-    //columns are vertical (first index of m_matrix member)

-    double GetValue(int col, int row) const;

-

-    //set the value in the matrix at col,row

-    //rows are horizontal (second index of m_matrix member)

-    //columns are vertical (first index of m_matrix member)

-    void SetValue(int col, int row, double value);

-

-    void operator = (const wxTransformMatrix& mat);

-    bool operator == (const wxTransformMatrix& mat) const;

-    bool operator != (const module::gah::wxTransformMatrix& mat) const;

-

-    //multiply every element by t

-    wxTransformMatrix&          operator*=(const double& t);

-    //divide every element by t

-    wxTransformMatrix&          operator/=(const double& t);

-    //add matrix m to this t

-    wxTransformMatrix&          operator+=(const wxTransformMatrix& m);

-    //subtract matrix m from this

-    wxTransformMatrix&          operator-=(const wxTransformMatrix& m);

-    //multiply matrix m with this

-    wxTransformMatrix&          operator*=(const wxTransformMatrix& m);

-

-    // constant operators

-

-    //multiply every element by t  and return result

-    wxTransformMatrix           operator*(const double& t) const;

-    //divide this matrix by t and return result

-    wxTransformMatrix           operator/(const double& t) const;

-    //add matrix m to this and return result

-    wxTransformMatrix           operator+(const wxTransformMatrix& m) const;

-    //subtract matrix m from this and return result

-    wxTransformMatrix           operator-(const wxTransformMatrix& m) const;

-    //multiply this by matrix m and return result

-    wxTransformMatrix           operator*(const wxTransformMatrix& m) const;

-    wxTransformMatrix           operator-() const;

-

-    //rows are horizontal (second index of m_matrix member)

-    //columns are vertical (first index of m_matrix member)

-    double& operator()(int col, int row);

-

-    //rows are horizontal (second index of m_matrix member)

-    //columns are vertical (first index of m_matrix member)

-    double operator()(int col, int row) const;

-

-    // Invert matrix

-    bool Invert(void);

-

-    // Make into identity matrix

-    bool Identity(void);

-

-    // Is the matrix the identity matrix?

-    // Only returns a flag, which is set whenever an operation

-    // is done.

-    inline bool IsIdentity(void) const { return m_isIdentity; }

-

-    // This does an actual check.

-    inline bool IsIdentity1(void) const ;

-

-    //Scale by scale (isotropic scaling i.e. the same in x and y):

-    //!ex:

-    //!code:           | scale  0      0      |

-    //!code: matrix' = |  0     scale  0      | x matrix

-    //!code:           |  0     0      scale  |

-    bool Scale(double scale);

-

-    //Scale with center point and x/y scale

-    //

-    //!ex:

-    //!code:           |  xs    0      xc(1-xs) |

-    //!code: matrix' = |  0    ys      yc(1-ys) | x matrix

-    //!code:           |  0     0      1        |

-    wxTransformMatrix&  Scale(const double &xs, const double &ys,const double &xc, const double &yc);

-

-    // mirror a matrix in x, y

-    //!ex:

-    //!code:           | -1     0      0 |

-    //!code: matrix' = |  0    -1      0 | x matrix

-    //!code:           |  0     0      1 |

-    wxTransformMatrix<float>&  Mirror(bool x=true, bool y=false);

-    // Translate by dx, dy:

-    //!ex:

-    //!code:           | 1  0 dx |

-    //!code: matrix' = | 0  1 dy | x matrix

-    //!code:           | 0  0  1 |

-    bool Translate(double x, double y);

-

-    // Rotate clockwise by the given number of degrees:

-    //!ex:

-    //!code:           |  cos sin 0 |

-    //!code: matrix' = | -sin cos 0 | x matrix

-    //!code:           |   0   0  1 |

-    bool Rotate(double angle);

-

-    //Rotate counter clockwise with point of rotation

-    //

-    //!ex:

-    //!code:           |  cos(r) -sin(r)    x(1-cos(r))+y(sin(r)|

-    //!code: matrix' = |  sin(r)  cos(r)    y(1-cos(r))-x(sin(r)| x matrix

-    //!code:           |   0          0                       1 |

-    wxTransformMatrix&  Rotate(const double &r, const double &x, const double &y);

-

-    // Transform X value from logical to device

-    inline double TransformX(double x) const;

-

-    // Transform Y value from logical to device

-    inline double TransformY(double y) const;

-

-    // Transform a point from logical to device coordinates

-    bool TransformPoint(double x, double y, double& tx, double& ty) const;

-

-    // Transform a point from device to logical coordinates.

-    // Example of use:

-    //   wxTransformMatrix mat = dc.GetTransformation();

-    //   mat.Invert();

-    //   mat.InverseTransformPoint(x, y, x1, y1);

-    // OR (shorthand:)

-    //   dc.LogicalToDevice(x, y, x1, y1);

-    // The latter is slightly less efficient if we're doing several

-    // conversions, since the matrix is inverted several times.

-    // N.B. 'this' matrix is the inverse at this point

-    bool InverseTransformPoint(double x, double y, double& tx, double& ty) const;

-

-    double Get_scaleX();

-    double Get_scaleY();

-    double GetRotation();

-    void   SetRotation(double rotation);

-

-

-public:

-    double  m_matrix[3][3];

-    bool    m_isIdentity;

-};

-

-

-/*

-Chris Breeze reported, that

-some functions of wxTransformMatrix cannot work because it is not

-known if he matrix has been inverted. Be careful when using it.

-*/

-

-// Transform X value from logical to device

-// warning: this function can only be used for this purpose

-// because no rotation is involved when mapping logical to device coordinates

-// mirror and scaling for x and y will be part of the matrix

-// if you have a matrix that is rotated, eg a shape containing a matrix to place

-// it in the logical coordinate system, use TransformPoint

-inline double wxTransformMatrix::TransformX(double x) const

-{

-    //normally like this, but since no rotation is involved (only mirror and scale)

-    //we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero

-    //(x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0]))

-    return (m_isIdentity ? x : (x * m_matrix[0][0] +  m_matrix[2][0]));

-}

-

-// Transform Y value from logical to device

-// warning: this function can only be used for this purpose

-// because no rotation is involved when mapping logical to device coordinates

-// mirror and scaling for x and y will be part of the matrix

-// if you have a matrix that is rotated, eg a shape containing a matrix to place

-// it in the logical coordinate system, use TransformPoint

-inline double wxTransformMatrix::TransformY(double y) const

-{

-    //normally like this, but since no rotation is involved (only mirror and scale)

-    //we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero

-    //(x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1]))

-    return (m_isIdentity ? y : (y * m_matrix[1][1] + m_matrix[2][1]));

-}

-

-

-// Is the matrix the identity matrix?

-// Each operation checks whether the result is still the identity matrix and sets a flag.

-inline bool wxTransformMatrix::IsIdentity1(void) const

-{

-    return

-    ( wxIsSameDouble(m_matrix[0][0], 1.0) &&

-      wxIsSameDouble(m_matrix[1][1], 1.0) &&

-      wxIsSameDouble(m_matrix[2][2], 1.0) &&

-      wxIsSameDouble(m_matrix[1][0], 0.0) &&

-      wxIsSameDouble(m_matrix[2][0], 0.0) &&

-      wxIsSameDouble(m_matrix[0][1], 0.0) &&

-      wxIsSameDouble(m_matrix[2][1], 0.0) &&

-      wxIsSameDouble(m_matrix[0][2], 0.0) &&

-      wxIsSameDouble(m_matrix[1][2], 0.0) );

-}

-

-// Calculates the determinant of a 2 x 2 matrix

-inline double wxCalculateDet(double a11, double a21, double a12, double a22)

-{

-    return a11 * a22 - a12 * a21;

-}
-

-#endif // _WX_MATRIXH__

diff --git a/compiler/c2nim/tests/struct_anonym.h b/compiler/c2nim/tests/struct_anonym.h
deleted file mode 100644
index 859bfc206..000000000
--- a/compiler/c2nim/tests/struct_anonym.h
+++ /dev/null
@@ -1,27 +0,0 @@
-
-struct normal{
-	int a;
-	int b;
-};
-
-typedef struct outerStruct {
-	struct normal a_nomal_one;
-	
-	int a;
-	
-	struct {
-		union {
-			int b;
-		} a_union_in_the_struct;
-		
-		int c;
-	};
-	
-	union {
-		int d;
-		
-		struct {
-			int e;
-		} a_struct_in_the_union;
-	} a_union;
-};
\ No newline at end of file
diff --git a/compiler/c2nim/tests/systest.c b/compiler/c2nim/tests/systest.c
deleted file mode 100644
index 51509e253..000000000
--- a/compiler/c2nim/tests/systest.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/* This file has been written by Blablub.
- *
- * Another comment line.
- */
-
-#ifdef __cplusplus
-#  ifdef __SOME_OTHER_CRAP
-extern "C" {
-#  endif
-#endif
-
-#define interrupts() sei()
-
-enum
-{
-/* 8bit, color or not */
-    CV_LOAD_IMAGE_UNCHANGED  =-1,
-/* 8bit, gray */
-    CV_LOAD_IMAGE_GRAYSCALE  =0,
-/* ?, color */
-    CV_LOAD_IMAGE_COLOR      =1,
-/* any depth, ? */
-    CV_LOAD_IMAGE_ANYDEPTH   =2,
-/* ?, any color */
-    CV_LOAD_IMAGE_ANYCOLOR   =4
-};
-
-typedef void (*callback_t) (int rc);
-typedef const char* (*callback2)(int rc, long L, const char* buffer);
-
-int   aw_callback_set (AW_CALLBACK c, callback_t callback );
-int   aw_instance_callback_set (AW_CALLBACK c, callback_t callback);
-
-unsigned long int wawa;
-
-#define MAX(x, y) ((x) < (y)? (y) : (x))
-
-#define AW_BUILD 85 // AW 5.0
-// Limits
-#define AW_MAX_AVCHANGE_PER_SECOND 10
-
-#private expatDll
-
-#if !defined(expatDll)
-#  if defined(windows)
-#    define expatDll "expat.dll"
-#  elif defined(macosx)
-#    define expatDll "libexpat.dynlib"
-#  else
-#    define expatDll "libexpat.so(.1|)"
-#  endif
-#endif
-
-#mangle "'XML_'{.*}" "$1"
-#private "'XML_ParserStruct'"
-
-#mangle cuint cint
-
-unsigned int uiVar;
-
-#private "@('_'!.)"
-unsigned int myPrivateVar__;
-
-
-struct XML_ParserStruct;
-
-#def XMLCALL __cdecl
-
-typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
-                                                const XML_Char *name,
-                                                XML_Content *model);
-
-
-void* x;
-void* fn(void);
-void (*fn)(void);
-void* (*fn)(void);
-void* (*fn)(void*);
-
-/*
- * Very ugly real world code ahead:
- */
-
-#def JMETHOD(rettype, name, params) rettype (*name) params
-
-typedef struct cjpeg_source_struct * cjpeg_source_ptr;
-
-struct cjpeg_source_struct {
-  JMETHOD(void, start_input, (j_compress_ptr cinfo,
-			      cjpeg_source_ptr sinfo));
-  JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
-				       cjpeg_source_ptr sinfo));
-  JMETHOD(void, finish_input, (j_compress_ptr cinfo,
-			       cjpeg_source_ptr sinfo));
-
-  FILE *input_file;
-
-  JSAMPARRAY buffer;
-  JDIMENSION buffer_height;
-};
-
-// Test standalone structs: 
-
-union myunion {
-  char x, y, *z;
-  myint a, b;  
-} u;
-
-struct mystruct {
-  char x, y, *z;
-  myint a, b;
-}; 
-
-struct mystruct fn(i32 x, i64 y);
-
-struct mystruct {
-  char x, y, *z;
-  myint a, b;
-} *myvar = NULL, **myvar2 = NULL; 
-
-// anonymous struct: 
-
-struct {
-  char x, y, *z;
-  myint a, b;  
-} varX, **varY;
-
-// empty anonymous struct: 
-
-struct {
-
-} varX, **varY;
-
-// Test C2NIM skipping:
-
-#define MASK(x) ((x) & 0xff)
-#define CAST1(x) ((int) &x)
-#define CAST2(x) (typ*) &x
-#define CAST3(x) ((const unsigned char**) &x)
-
-#ifndef C2NIM 
-  #if someNestedCond
-    This is an invalid text that should generate a parser error, if not 
-  #endif
-    skipped correctly.
-#endif
-
-#ifndef C2NIM
-  #if someNestedCond
-    This is an invalid text that should generate a parser error, if not 
-  #endif
-    skipped correctly.
-#else
-typedef char gchar;
-typedef unsigned int gunsignedint;
-typedef unsigned char guchar;
-#endif
-
-#ifdef C2NIM
-# mangle "'those'" "these"
-int those;
-#elif abc
-  #if someNestedCond
-    This is an invalid text that should generate a parser error, if not 
-  #else
-    skipped correctly.
-  #endif
-#else
-  Another crappy input line.
-#endif
-
-point* newPoint(void) {  
-  for (int i = 0; i < 89; ++i) echo("test" " string "  "concatenation");
-  for (; j < 54; j++) {}
-  for (;; j--) ;
-  for (;;) {}
-  mytype * x = y * z;
- 
-  if (**p == ' ') {
-    --p;
-  } else if (**p == '\t') {
-    p += 3;
-  } else { 
-    p = 45 + (mytype*)45;
-    p = 45 + ((mytype*)45);
-    p = 45 + ((mytype)45);
-    // BUG: This does not parse:
-    // p = 45 + (mytype)45;
-  }
-
-  while (x >= 6 && x <= 20) 
-    --x;
-  
-  switch (*p) {
-    case 'A'...'Z':
-    case 'a'...'z':
-      ++p;
-      break;
-    case '0':
-      ++p;
-      break;
-    default:
-      return NULL;
-  }
-}
-
-enum {
-  a1, a2 = 4, a3
-};
-
-typedef enum crazyTAG {
-  x1, x2, x3 = 8, x4, x5
-} myEnum, *pMyEnum;
-
-typedef enum {
-  x1, x2, x3 = 8, x4, x5
-} myEnum, *pMyEnum;
-
-// Test multi-line macro: 
-
-#define MUILTILINE "abc" \ 
-  "xyz" \
-  "def"
-
-#define MULTILINE(x, y) do { \
-  ++y; ++x; \
-} while (0)
-
-#ifdef C2NIM
-#  dynlib iupdll
-#  cdecl
-#  mangle "'GTK_'{.*}" "TGtk$1"
-#  mangle "'PGTK_'{.*}" "PGtk$1"
-#  if defined(windows)
-#    define iupdll "iup.dll"
-#  elif defined(macosx)
-#    define iupdll "libiup.dynlib"
-#  else
-#    define iupdll "libiup.so"
-#  endif
-#endif
-
-typedef struct stupidTAG {
-  mytype a, b;
-} GTK_MyStruct, *PGTK_MyStruct;
-
-typedef struct  {
-  mytype a, b;
-} GTK_MyStruct, *PGTK_MyStruct;
-
-int IupConvertXYToPos(PIhandle ih, int x, int y);
-
-#ifdef DEBUG
-#  define OUT(x) printf("%s\n", x)
-#else
-#  define OUT(x)
-#endif
-
-
-  #ifdef C2NIM
-  #  def EXTERN(x) static x
-  #  def TWO_ARGS(x, y) x* y
-  #endif
-  // parses now!
-  EXTERN(int) f(void);
-  EXTERN(int) g(void);
-
-
-  #def EXPORT
-  // does parse now!
-  EXPORT int f(void);
-  EXPORT int g(void); 
-
-  static TWO_ARGS(int, x) = TWO_ARGS(56, 45);
-
-
-#  define abc 34
-#  define xyz 42
-
-#  define wuseldusel "my string\nconstant"
-
-#undef ignoreThis
-
-char* x;
-
-typedef struct {
-  char x, y, *z;
-} point;
-
-char* __stdcall printf(char* frmt, const char* const** ptrToStrArray,
-             const int* const dummy, ...);
-
-inline char* myinlineProc(char* frmt, const char* const* strArray,
-             const int* const dummy, ...);
-
-// Test void parameter list:
-void myVoidProc(void);
-
-void emptyReturn(void) { return; }
-
-// POSIX stuff:
-
-#ifdef C2NIM
-#prefix posix_
-int c2nimBranch;
-#elif defined(MACOSX)
-int* x, y, z;
-#else
-int dummy;
-#endif
-
-#ifndef C2NIM
-int dontTranslateThis;
-#elif defined(Windows)
-int WindowsTrue = true;
-#endif
-
-int   posix_spawn(pid_t *restrict, const char *restrict,
-          const posix_spawn_file_actions_t *,
-          const posix_spawnattr_t *restrict, char *const [restrict],
-          char *const [restrict]);
-int   posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *,
-          int);
-int   posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *,
-          int, int);
-int   posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict,
-          int, const char *restrict, int, mode_t);
-int   posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *);
-int   posix_spawn_file_actions_init(posix_spawn_file_actions_t *);
-int   posix_spawnattr_destroy(posix_spawnattr_t *);
-int   posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict,
-          sigset_t *restrict);
-int   posix_spawnattr_getflags(const posix_spawnattr_t *restrict,
-          short *restrict);
-int   posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict,
-          pid_t *restrict);
-int   posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict,
-          struct sched_param *restrict);
-int   posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict,
-          int *restrict);
-int   posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict,
-          sigset_t *restrict);
-int   posix_spawnattr_init(posix_spawnattr_t *);
-int   posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict,
-          const sigset_t *restrict);
-int   posix_spawnattr_setflags(posix_spawnattr_t *, short);
-int   posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t);
-
-
-int   posix_spawnattr_setschedparam(posix_spawnattr_t *restrict,
-          const struct sched_param *restrict);
-int   posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int);
-int   posix_spawnattr_setsigmask(posix_spawnattr_t *restrict,
-          const sigset_t *restrict);
-int   posix_spawnp(pid_t *restrict, const char *restrict,
-          const posix_spawn_file_actions_t *,
-          const posix_spawnattr_t *restrict,
-          char *const [restrict], char *const [restrict]);
-
-typedef struct
-{
-  float R, G, B;
-}
-RGBType;
-typedef struct
-{
-  float H, W, B;
-}
-HWBType;
-
-static HWBType *
-RGB_to_HWB (RGBType RGB, HWBType * HWB)
-{
-  HWBType* myArray[20];
-  /*
-   * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is  
-   * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B.  
-   */
-
-  float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f;
-  int i;
-
-  w = MIN3 (R, G, B);
-  v = MAX3 (R, G, B);
-  b &= 1 - v;
-  if (v == w)
-    RETURN_HWB (HWB_UNDEFINED, w, b);
-  f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
-  i = (R == w) ? 3 : ((G == w) ? 5 : 1);
-  RETURN_HWB (i - f / (v - w), w, b);
-
-}
-
-static int
-clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim)
-{
-  double m;                        // gradient of line
-  if (*x0 < mindim)
-    {                                // start of line is left of window 
-      if (*x1 < mindim) // as is the end, so the line never cuts the window 
-        return 0;
-      m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line
-      // adjust x0 to be on the left boundary (ie to be zero), and y0 to match 
-      *y0 -= m * (*x0 - mindim);
-      *x0 = mindim;
-      // now, perhaps, adjust the far end of the line as well
-      if (*x1 > maxdim)
-        {
-          *y1 += m * (maxdim - *x1);
-          *x1 = maxdim;
-        }
-      return 1;
-    }
-  if (*x0 > maxdim)
-    { // start of line is right of window - complement of above 
-      if (*x1 > maxdim) // as is the end, so the line misses the window 
-        return 0;
-      m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line
-      *y0 += m * (maxdim - *x0);        // adjust so point is on the right
-                                        // boundary
-      *x0 = maxdim;
-      // now, perhaps, adjust the end of the line
-      if (*x1 < mindim)
-        {
-          *y1 -= m * (*x1 - mindim);
-          *x1 = mindim;
-        }
-      return 1;
-    }
-  // the final case - the start of the line is inside the window
-  if (*x1 > maxdim)
-    {                                // other end is outside to the right
-      m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line 
-      *y1 += m * (maxdim - *x1);
-      *x1 = maxdim;
-      return 1;
-    }
-  if (*x1 < mindim)
-    {                                // other end is outside to the left 
-      m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of line 
-             *y1 -= m * (*x1 - mindim);
-      *x1 = mindim;
-      return 1;
-    }
-  // only get here if both points are inside the window
-  return 1;
-}
-
-// end of line clipping code
-
-static void
-gdImageBrushApply (gdImagePtr im, int x, int y)
-{
-  int lx, ly;
-  int hy;
-  int hx;
-  int x1, y1, x2, y2;
-  int srcx, srcy;
-  if (!im->brush)
-    {
-      return;
-    }
-  hy = gdImageSY (im->brush) / 2;
-  y1 = y - hy;
-  y2 = y1 + gdImageSY (im->brush);
-  hx = gdImageSX (im->brush) / 2;
-  x1 = x - hx;
-  x2 = x1 + gdImageSX (im->brush);
-  srcy = 0;
-  if (im->trueColor)
-    {
-      if (im->brush->trueColor)
-        {
-          for (ly = y1; (ly < y2); ly++)
-            {
-              srcx = 0;
-              for (lx = x1; (lx < x2); lx++)
-                {
-                  int p;
-                  p = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
-                  // 2.0.9, Thomas Winzig: apply simple full transparency
-                  if (p != gdImageGetTransparent (im->brush))
-                    {
-                      gdImageSetPixel (im, lx, ly, p);
-                    }
-                  srcx++;
-                }
-              srcy++;
-            }
-        }
-      else
-        {
-          // 2.0.12: Brush palette, image truecolor (thanks to Thorben Kundinger
-          // for pointing out the issue)
-          for (ly = y1; (ly < y2); ly++)
-            {
-              srcx = 0;
-              for (lx = x1; (lx < x2); lx++)
-                {
-                  int p, tc;
-                  p = gdImageGetPixel (im->brush, srcx, srcy);
-                  tc = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
-                  // 2.0.9, Thomas Winzig: apply simple full transparency 
-                  if (p != gdImageGetTransparent (im->brush))
-                    {
-                      gdImageSetPixel (im, lx, ly, tc);
-                    }
-                  srcx++;
-                }
-              srcy++;
-            }
-        }
-    }
-  else
-    {
-      for (ly = y1; (ly < y2); ly++)
-        {
-          srcx = 0;
-          for (lx = x1; (lx < x2); lx++)
-            {
-              int p;
-              p = gdImageGetPixel (im->brush, srcx, srcy);
-              // Allow for non-square brushes!
-              if (p != gdImageGetTransparent (im->brush))
-                {
-                  // Truecolor brush. Very slow
-                  // on a palette destination.
-                  if (im->brush->trueColor)
-                    {
-                      gdImageSetPixel (im, lx, ly,
-                                       gdImageColorResolveAlpha(im,
-                                       gdTrueColorGetRed(p),
-                                       gdTrueColorGetGreen(p),
-                                       gdTrueColorGetBlue(p),
-                                       gdTrueColorGetAlpha(p)));
-                    }
-                  else
-                    {
-                      gdImageSetPixel (im, lx, ly, im->brushColorMap[p]);
-                    }
-                }
-              srcx++;
-            }
-          srcy++;
-        }
-    } 
-}
-
-
-void gdImageSetPixel (gdImagePtr im, int x, int y, int color)
-{
-  int p;
-  switch (color)
-    {
-    case gdStyled:
-      if (!im->style)
-        {
-          // Refuse to draw if no style is set.
-          return;
-        }
-      else
-        {
-          p = im->style[im->stylePos++];
-        }
-      if (p != (gdTransparent))
-        {
-          gdImageSetPixel (im, x, y, p);
-        }
-      im->stylePos = im->stylePos % im->styleLength;
-      break;
-    case gdStyledBrushed:
-      if (!im->style)
-        {
-          // Refuse to draw if no style is set.
-          return;
-        }
-      p = im->style[im->stylePos++];
-      if ((p != gdTransparent) && (p != 0))
-        {
-          gdImageSetPixel (im, x, y, gdBrushed);
-        }
-      im->stylePos = im->stylePos % im->styleLength;
-      break;
-    case gdBrushed:
-      gdImageBrushApply (im, x, y);
-      break;
-    case gdTiled:
-      gdImageTileApply (im, x, y);
-      break;
-    case gdAntiAliased:
-      // This shouldn't happen (2.0.26) because we just call
-      // gdImageAALine now, but do something sane.
-      gdImageSetPixel(im, x, y, im->AA_color);
-      break;
-    default:
-      if (gdImageBoundsSafeMacro (im, x, y))
-        {
-          if (im->trueColor)
-            {
-              if (im->alphaBlendingFlag)
-                {
-                  im->tpixels[y][x] = gdAlphaBlend (im->tpixels[y][x], color);
-                }
-              else
-                {
-                  im->tpixels[y][x] = color;
-                }
-            }
-          else
-            {
-              im->pixels[y][x] = color;
-            }
-        }
-      break;
-    }
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-
diff --git a/compiler/c2nim/tests/systest2.c b/compiler/c2nim/tests/systest2.c
deleted file mode 100644
index bf3027cfc..000000000
--- a/compiler/c2nim/tests/systest2.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifdef C2NIM
-#  header "iup.h"
-#  cdecl
-#  mangle "'GTK_'{.*}" "TGtk$1"
-#  mangle "'PGTK_'{.*}" "PGtk$1"
-#endif
-
-typedef struct stupidTAG {
-  mytype a, b;
-} GTK_MyStruct, *PGTK_MyStruct;
-
-typedef struct  {
-  mytype a, b;
-} GTK_MyStruct, *PGTK_MyStruct;
-
-int IupConvertXYToPos(PIhandle ih, int x, int y);
-
diff --git a/compiler/c2nim/tests/vincent.c b/compiler/c2nim/tests/vincent.c
deleted file mode 100644
index 24c6d6425..000000000
--- a/compiler/c2nim/tests/vincent.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-
-int rand(void);
-
-int id2(void) {
-    return (int *)1;
-}
-
-int id(void (*f)(void)) {
-    f();
-    ((void (*)(int))f)(10);
-    return 10;
-    return (20+1);
-    return (int *)id;
-}
-
-int main() {
-    float f = .2,
-          g = 2.,
-          h = 1.0+rand(),
-          i = 1.0e+3;
-    int j, a;
-    for(j = 0, a = 10; j < 0; j++, a++) ;
-    do {
-        printf("howdy");
-    } while(--i, 0);
-    if(1)
-        printf("1"); // error from this comment
-    else
-        printf("2");
-    return '\x00';
-}
diff --git a/compiler/c2nim/tests/vincent.h b/compiler/c2nim/tests/vincent.h
deleted file mode 100644
index b4e761ee1..000000000
--- a/compiler/c2nim/tests/vincent.h
+++ /dev/null
@@ -1,3 +0,0 @@
-struct foo {
-    int x,y,z;
-};
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index c5b9d0f00..ee380b305 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -103,43 +103,50 @@ discard """
 
 """
 
+# Important things to keep in mind:
+# * Don't base the analysis on nkProcDef et al. This doesn't work for
+#   instantiated (formerly generic) procs. The analysis has to look at nkSym.
+#   This also means we need to prevent the same proc is processed multiple
+#   times via the 'processed' set.
+# * Keep in mind that the owner of some temporaries used to be unreliable.
+# * For closure iterators we merge the "real" potential closure with the
+#   local storage requirements for efficiency. This means closure iterators
+#   have slightly different semantics from ordinary closures.
+
+
 const
   upName* = ":up" # field name for the 'up' reference
-  paramName* = ":env"
+  paramName* = ":envP"
   envName* = ":env"
 
 type
-  PInnerContext = ref TInnerContext
   POuterContext = ref TOuterContext
 
+  TIter = object
+    fn, closureParam, state, resultSym: PSym # most are only valid if
+                                             # fn.kind == skClosureIterator
+    obj: PType
+    
   PEnv = ref TEnv
-  TDep = tuple[e: PEnv, field: PSym]
   TEnv {.final.} = object of TObject
-    attachedNode: PNode
+    attachedNode, replacementNode: PNode
     createdVar: PSym        # if != nil it is a used environment
     createdVarComesFromIter: bool
     capturedVars: seq[PSym] # captured variables in this environment
-    deps: seq[TDep]         # dependencies
-    up: PEnv
+    up, next: PEnv          # outer scope and next to keep all in a list
+    upField: PSym        # if != nil the dependency to the outer scope is used
     obj: PType
-  
-  TInnerContext = object
-    fn: PSym
-    closureParam: PSym
-    localsToAccess: TIdNodeTable
+    fn: PSym                # function that belongs to this scope;
+                            # if up.fn != fn then we cross function boundaries.
+                            # This is an important case to consider.
+    vars: TIntSet           # variables belonging to this environment
     
   TOuterContext = object
     fn: PSym # may also be a module!
-    currentEnv: PEnv
-    isIter: bool   # first class iterator?
+    head: PEnv
     capturedVars, processed: TIntSet
-    localsToEnv: TIdTable # PSym->PEnv mapping
     localsToAccess: TIdNodeTable
     lambdasToEnv: TIdTable # PSym->PEnv mapping
-    up: POuterContext
-
-    closureParam, state, resultSym: PSym # only if isIter
-    obj: PType # only if isIter
 
 proc getStateType(iter: PSym): PType =
   var n = newNodeI(nkRange, iter.info)
@@ -147,12 +154,20 @@ proc getStateType(iter: PSym): PType =
   addSon(n, newIntNode(nkIntLit, 0))
   result = newType(tyRange, iter)
   result.n = n
-  rawAddSon(result, getSysType(tyInt))
+  var intType = nilOrSysInt()
+  if intType.isNil: intType = newType(tyInt, iter)
+  rawAddSon(result, intType)
 
 proc createStateField(iter: PSym): PSym =
   result = newSym(skField, getIdent(":state"), iter, iter.info)
   result.typ = getStateType(iter)
 
+proc createEnvObj(owner: PSym): PType =
+  # YYY meh, just add the state field for every closure for now, it's too
+  # hard to figure out if it comes from a closure iterator:
+  result = createObj(owner, owner.info)
+  rawAddField(result, createStateField(owner))
+
 proc newIterResult(iter: PSym): PSym =
   if resultPos < iter.ast.len:
     result = iter.ast.sons[resultPos].sym
@@ -164,6 +179,7 @@ proc newIterResult(iter: PSym): PSym =
     iter.ast.add newSymNode(result)
 
 proc addHiddenParam(routine: PSym, param: PSym) =
+  assert param.kind == skParam
   var params = routine.ast.sons[paramsPos]
   # -1 is correct here as param.position is 0 based but we have at position 0
   # some nkEffect node:
@@ -175,7 +191,7 @@ proc addHiddenParam(routine: PSym, param: PSym) =
 proc getHiddenParam(routine: PSym): PSym =
   let params = routine.ast.sons[paramsPos]
   let hidden = lastSon(params)
-  assert hidden.kind == nkSym
+  internalAssert hidden.kind == nkSym and hidden.sym.kind == skParam
   result = hidden.sym
 
 proc getEnvParam(routine: PSym): PSym =
@@ -184,161 +200,191 @@ proc getEnvParam(routine: PSym): PSym =
   if hidden.kind == nkSym and hidden.sym.name.s == paramName:
     result = hidden.sym
 
-proc initIterContext(c: POuterContext, iter: PSym) =
-  c.fn = iter
-  c.capturedVars = initIntSet()
-
-  var cp = getEnvParam(iter)
-  if cp == nil:
-    c.obj = createObj(iter, iter.info)
-
-    cp = newSym(skParam, getIdent(paramName), iter, iter.info)
-    incl(cp.flags, sfFromGeneric)
-    cp.typ = newType(tyRef, iter)
-    rawAddSon(cp.typ, c.obj)
-    addHiddenParam(iter, cp)
-
-    c.state = createStateField(iter)
-    addField(c.obj, c.state)
-  else:
-    c.obj = cp.typ.sons[0]
-    assert c.obj.kind == tyObject
-    if c.obj.n.len > 0:
-      c.state = c.obj.n[0].sym
+proc initIter(iter: PSym): TIter =
+  result.fn = iter
+  if iter.kind == skClosureIterator:
+    var cp = getEnvParam(iter)
+    if cp == nil:
+      result.obj = createEnvObj(iter)
+
+      cp = newSym(skParam, getIdent(paramName), iter, iter.info)
+      incl(cp.flags, sfFromGeneric)
+      cp.typ = newType(tyRef, iter)
+      rawAddSon(cp.typ, result.obj)
+      addHiddenParam(iter, cp)
     else:
-      c.state = createStateField(iter)
-      addField(c.obj, c.state)
-
-  c.closureParam = cp
-  if iter.typ.sons[0] != nil:
-    c.resultSym = newIterResult(iter)
-    #iter.ast.add(newSymNode(c.resultSym))
-
-proc newOuterContext(fn: PSym, up: POuterContext = nil): POuterContext =
+      result.obj = cp.typ.sons[0]
+      assert result.obj.kind == tyObject
+    internalAssert result.obj.n.len > 0
+    result.state = result.obj.n[0].sym
+    result.closureParam = cp
+    if iter.typ.sons[0] != nil:
+      result.resultSym = newIterResult(iter)
+      #iter.ast.add(newSymNode(c.resultSym))
+
+proc newOuterContext(fn: PSym): POuterContext =
   new(result)
   result.fn = fn
   result.capturedVars = initIntSet()
   result.processed = initIntSet()
   initIdNodeTable(result.localsToAccess)
-  initIdTable(result.localsToEnv)
   initIdTable(result.lambdasToEnv)
-  result.isIter = fn.kind == skClosureIterator
-  if result.isIter: initIterContext(result, fn)
 
-proc newInnerContext(fn: PSym): PInnerContext =
+proc newEnv(o: POuterContext; up: PEnv, n: PNode; owner: PSym): PEnv =
   new(result)
-  result.fn = fn
-  initIdNodeTable(result.localsToAccess)
-
-proc newEnv(outerProc: PSym, up: PEnv, n: PNode): PEnv =
-  new(result)
-  result.deps = @[]
   result.capturedVars = @[]
-  result.obj = createObj(outerProc, outerProc.info)
   result.up = up
   result.attachedNode = n
+  result.fn = owner
+  result.vars = initIntSet()
+  result.next = o.head
+  o.head = result
+  if owner.kind != skModule and (up == nil or up.fn != owner):
+    let param = getEnvParam(owner)
+    if param != nil:
+      result.obj = param.typ.sons[0]
+      assert result.obj.kind == tyObject
+  if result.obj.isNil:
+    result.obj = createEnvObj(owner)
 
 proc addCapturedVar(e: PEnv, v: PSym) =
   for x in e.capturedVars:
     if x == v: return
-  # XXX meh, just add the state field for every closure for now, it's too
-  # hard to figure out if it comes from a closure iterator:
-  if e.obj.n.len == 0: addField(e.obj, createStateField(v.owner))
   e.capturedVars.add(v)
   addField(e.obj, v)
-  
-proc addDep(e, d: PEnv, owner: PSym): PSym =
-  for x, field in items(e.deps):
-    if x == d: return field
-  var pos = sonsLen(e.obj.n)
-  result = newSym(skField, getIdent(upName & $pos), owner, owner.info)
-  result.typ = newType(tyRef, owner)
-  result.position = pos
-  assert d.obj != nil
-  rawAddSon(result.typ, d.obj)
-  addField(e.obj, result)
-  e.deps.add((d, result))
 
 proc newCall(a, b: PSym): PNode =
   result = newNodeI(nkCall, a.info)
   result.add newSymNode(a)
   result.add newSymNode(b)
 
-proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
-  result = s.kind in {skProc, skMethod, skConverter, skClosureIterator} and
-           s.skipGenericOwner == outerProc
+proc isInnerProc(s, outerProc: PSym): bool =
+  if s.kind in {skProc, skMethod, skConverter, skClosureIterator}:
+    var owner = s.skipGenericOwner
+    while true:
+      if owner.isNil: return false
+      if owner == outerProc: return true
+      owner = owner.owner
   #s.typ.callConv == ccClosure
 
-proc addClosureParam(i: PInnerContext, e: PEnv) =
-  var cp = getEnvParam(i.fn)
+proc addClosureParam(fn: PSym; e: PEnv) =
+  var cp = getEnvParam(fn)
   if cp == nil:
-    cp = newSym(skParam, getIdent(paramName), i.fn, i.fn.info)
+    cp = newSym(skParam, getIdent(paramName), fn, fn.info)
     incl(cp.flags, sfFromGeneric)
-    cp.typ = newType(tyRef, i.fn)
+    cp.typ = newType(tyRef, fn)
     rawAddSon(cp.typ, e.obj)
-    addHiddenParam(i.fn, cp)
-  else:
-    e.obj = cp.typ.sons[0]
-    assert e.obj.kind == tyObject
-  i.closureParam = cp
-  #echo "closure param added for ", i.fn.name.s, " ", i.fn.id
-
-proc dummyClosureParam(o: POuterContext, i: PInnerContext) =
-  var e = o.currentEnv
-  if idTableGet(o.lambdasToEnv, i.fn) == nil:
-    idTablePut(o.lambdasToEnv, i.fn, e)
-  if i.closureParam == nil: addClosureParam(i, e)
+    addHiddenParam(fn, cp)
+    #else:
+    #cp.typ.sons[0] = e.obj
+    #assert e.obj.kind == tyObject
 
 proc illegalCapture(s: PSym): bool {.inline.} =
   result = skipTypes(s.typ, abstractInst).kind in 
                    {tyVar, tyOpenArray, tyVarargs} or
       s.kind == skResult
 
-proc captureVar(o: POuterContext, i: PInnerContext, local: PSym, 
-                info: TLineInfo) =
-  # for inlined variables the owner is still wrong, so it can happen that it's
-  # not a captured variable at all ... *sigh* 
-  var it = PEnv(idTableGet(o.localsToEnv, local))
-  if it == nil: return
-  
-  if illegalCapture(local) or o.fn.id != local.owner.id or 
-      i.fn.typ.callConv notin {ccClosure, ccDefault}:
-    # Currently captures are restricted to a single level of nesting:
-    localError(info, errIllegalCaptureX, local.name.s)
-  i.fn.typ.callConv = ccClosure
-  #echo "captureVar ", i.fn.name.s, i.fn.id, " ", local.name.s, local.id
-
-  incl(i.fn.typ.flags, tfCapturesEnv)
-
-  # we need to remember which inner most closure belongs to this lambda:
-  var e = o.currentEnv
-  if idTableGet(o.lambdasToEnv, i.fn) == nil:
-    idTablePut(o.lambdasToEnv, i.fn, e)
-
-  # variable already captured:
-  if idNodeTableGet(i.localsToAccess, local) != nil: return
-  if i.closureParam == nil: addClosureParam(i, e)
-  
-  # check which environment `local` belongs to:
-  var access = newSymNode(i.closureParam)
-  addCapturedVar(it, local)
-  if it == e:
-    # common case: local directly in current environment:
-    discard
-  else:
-    # it's in some upper environment:
-    access = indirectAccess(access, addDep(e, it, i.fn), info)
-  access = indirectAccess(access, local, info)
-  if o.isIter:
-    if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local)
-  else:
-    incl(o.capturedVars, local.id)
-  idNodeTablePut(i.localsToAccess, local, access)
-
 proc interestingVar(s: PSym): bool {.inline.} =
   result = s.kind in {skVar, skLet, skTemp, skForVar, skParam, skResult} and
     sfGlobal notin s.flags
 
+proc nestedAccess(top: PEnv; local: PSym): PNode =
+  # Parts after the transformation are in []:
+  #
+  #  proc main =
+  #    var [:env.]foo = 23
+  #    proc outer(:paramO) =
+  #      [var :envO; createClosure(:envO); :envO.up = paramO]
+  #      proc inner(:paramI) =
+  #        echo [:paramI.up.]foo
+  #      inner([:envO])
+  #    outer([:env])
+  if not interestingVar(local) or top.fn == local.owner:
+    return nil
+  # check it's in fact a captured variable:
+  var it = top
+  while it != nil:
+    if it.vars.contains(local.id): break
+    it = it.up
+  if it == nil: return nil
+  let envParam = top.fn.getEnvParam
+  internalAssert(not envParam.isNil)
+  var access = newSymNode(envParam)
+  it = top.up
+  while it != nil:
+    if it.vars.contains(local.id):
+      access = indirectAccess(access, local, local.info)
+      return access
+    internalAssert it.upField != nil
+    access = indirectAccess(access, it.upField, local.info)
+    it = it.up
+  when false:
+    # Type based expression construction works too, but turned out to hide
+    # other bugs:
+    while true:
+      let obj = access.typ.sons[0]
+      let field = getFieldFromObj(obj, local)
+      if field != nil:
+        return rawIndirectAccess(access, field, local.info)
+      let upField = lookupInRecord(obj.n, getIdent(upName))
+      if upField == nil: break
+      access = rawIndirectAccess(access, upField, local.info)
+  return nil
+
+proc createUpField(obj, fieldType: PType): PSym =
+  let pos = obj.n.len
+  result = newSym(skField, getIdent(upName), obj.owner, obj.owner.info)
+  result.typ = newType(tyRef, obj.owner)
+  result.position = pos
+  rawAddSon(result.typ, fieldType)
+  #rawAddField(obj, result)
+  addField(obj, result)
+
+proc captureVar(o: POuterContext; top: PEnv; local: PSym; 
+                info: TLineInfo): bool =
+  # first check if we should be concerned at all:
+  var it = top
+  while it != nil:
+    if it.vars.contains(local.id): break
+    it = it.up
+  if it == nil: return false
+  # yes, so mark every 'up' pointer as taken:
+  if illegalCapture(local) or top.fn.typ.callConv notin {ccClosure, ccDefault}:
+    localError(info, errIllegalCaptureX, local.name.s)
+  it = top
+  while it != nil:
+    if it.vars.contains(local.id): break
+    # keep in mind that the first element of the chain belong to top.fn itself
+    # and these don't need any upFields
+    if it.upField == nil and it.up != nil and it.fn != top.fn:
+      it.upField = createUpField(it.obj, it.up.obj)
+
+    if it.fn != local.owner:
+      it.fn.typ.callConv = ccClosure
+      incl(it.fn.typ.flags, tfCapturesEnv)
+
+      var u = it.up
+      while u != nil and u.fn == it.fn: u = u.up
+      addClosureParam(it.fn, u)
+
+      if idTableGet(o.lambdasToEnv, it.fn) == nil:
+        if u != nil: idTablePut(o.lambdasToEnv, it.fn, u)
+
+    it = it.up
+  # don't do this: 'top' might not require a closure:
+  #if idTableGet(o.lambdasToEnv, it.fn) == nil:
+  #  idTablePut(o.lambdasToEnv, it.fn, top)
+
+  # mark as captured:
+  #if top.iter != nil:
+  #  if not containsOrIncl(o.capturedVars, local.id):
+  #    #addField(top.iter.obj, local)
+  #    addCapturedVar(it, local)
+  #else:
+  incl(o.capturedVars, local.id)
+  addCapturedVar(it, local)
+  result = true
+
 proc semCaptureSym*(s, owner: PSym) =
   if interestingVar(s) and owner.id != s.owner.id and s.kind != skResult:
     if owner.typ != nil and not isGenericRoutine(owner):
@@ -350,28 +396,20 @@ proc semCaptureSym*(s, owner: PSym) =
     # since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
     # here
 
-proc gatherVars(o: POuterContext, i: PInnerContext, n: PNode) = 
-  # gather used vars for closure generation
-  if n == nil: return
+proc gatherVars(o: POuterContext; e: PEnv; n: PNode): int =
+  # gather used vars for closure generation; returns number of captured vars
+  if n == nil: return 0
   case n.kind
   of nkSym:
     var s = n.sym
-    if interestingVar(s) and i.fn.id != s.owner.id:
-      captureVar(o, i, s, n.info)
-    elif s.kind in {skProc, skMethod, skConverter} and
-            s.skipGenericOwner == o.fn and 
-            tfCapturesEnv in s.typ.flags and s != i.fn:
-      # call to some other inner proc; we need to track the dependencies for
-      # this:
-      let env = PEnv(idTableGet(o.lambdasToEnv, i.fn))
-      if env == nil: internalError(n.info, "no environment computed")
-      if o.currentEnv != env:
-        discard addDep(o.currentEnv, env, i.fn)
-        internalError(n.info, "too complex environment handling required")
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkClosure: discard
+    if interestingVar(s) and e.fn != s.owner:
+      if captureVar(o, e, s, n.info): result = 1
+  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkClosure, nkProcDef, 
+     nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, nkTypeSection:
+    discard
   else:
-    for k in countup(0, sonsLen(n) - 1): 
-      gatherVars(o, i, n.sons[k])
+    for k in countup(0, sonsLen(n) - 1):
+      result += gatherVars(o, e, n.sons[k])
 
 proc generateThunk(prc: PNode, dest: PType): PNode =
   ## Converts 'prc' into '(thunk, nil)' so that it's compatible with
@@ -403,61 +441,112 @@ proc makeClosure(prc, env: PSym, info: TLineInfo): PNode =
   else:
     result.add(newSymNode(env))
 
-proc transformInnerProc(o: POuterContext, i: PInnerContext, n: PNode): PNode =
+proc newClosureCreationVar(e: PEnv): PSym =
+  result = newSym(skVar, getIdent(envName), e.fn, e.attachedNode.info)
+  incl(result.flags, sfShadowed)
+  result.typ = newType(tyRef, e.fn)
+  result.typ.rawAddSon(e.obj)
+
+proc getClosureVar(e: PEnv): PSym =
+  if e.createdVar == nil:
+    result = newClosureCreationVar(e)
+    e.createdVar = result
+  else:
+    result = e.createdVar
+
+proc findEnv(o: POuterContext; s: PSym): PEnv =
+  var env = o.head
+  while env != nil:
+    if env.fn == s: break
+    env = env.next
+  internalAssert env != nil and env.up != nil
+  result = env.up
+  while result.fn == s: result = result.up
+
+proc transformInnerProc(o: POuterContext; e: PEnv, n: PNode): PNode =
   case n.kind
   of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard
   of nkSym:
     let s = n.sym
-    if s == i.fn: 
+    if s == e.fn:
       # recursive calls go through (lambda, hiddenParam):
-      assert i.closureParam != nil, i.fn.name.s
-      result = makeClosure(s, i.closureParam, n.info)
+      result = makeClosure(s, getEnvParam(s), n.info)
     elif isInnerProc(s, o.fn) and s.typ.callConv == ccClosure:
-      # ugh: call to some other inner proc; 
-      assert i.closureParam != nil
-      # XXX this is not correct in general! may also be some 'closure.upval'
-      result = makeClosure(s, i.closureParam, n.info)
+      # ugh: call to some other inner proc;
+      result = makeClosure(s, findEnv(o, s).getClosureVar, n.info)
     else:
       # captured symbol?
-      result = idNodeTableGet(i.localsToAccess, n.sym)
-  of nkLambdaKinds, nkIteratorDef:
-    if n.typ != nil:
-      result = transformInnerProc(o, i, n.sons[namePos])
+      result = nestedAccess(e, n.sym)
+      #result = idNodeTableGet(i.localsToAccess, n.sym)
+    #of nkLambdaKinds, nkIteratorDef:
+    #  if n.typ != nil:
+    #    result = transformInnerProc(o, e, n.sons[namePos])
+    #of nkClosure:
+    #  let x = transformInnerProc(o, e, n.sons[0])
+    #  if x != nil: n.sons[0] = x
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
-      nkClosure:
+     nkLambdaKinds, nkIteratorDef, nkClosure:
     # don't recurse here:
     discard
   else:
     for j in countup(0, sonsLen(n) - 1):
-      let x = transformInnerProc(o, i, n.sons[j])
+      let x = transformInnerProc(o, e, n.sons[j])
       if x != nil: n.sons[j] = x
 
 proc closureCreationPoint(n: PNode): PNode =
-  result = newNodeI(nkStmtList, n.info)
-  result.add(emptyNode)
-  result.add(n)
-
-proc searchForInnerProcs(o: POuterContext, n: PNode) =
+  if n.kind == nkStmtList and n.len >= 1 and n[0].kind == nkEmpty:
+    # we already have a free slot
+    result = n
+  else:
+    result = newNodeI(nkStmtList, n.info)
+    result.add(emptyNode)
+    result.add(n)
+  #result.flags.incl nfLL
+
+proc addParamsToEnv(fn: PSym; env: PEnv) =
+  let params = fn.typ.n
+  for i in 1.. <params.len: 
+    if params.sons[i].kind != nkSym:
+      internalError(params.info, "liftLambdas: strange params")
+    let param = params.sons[i].sym
+    env.vars.incl(param.id)
+  # put the 'result' into the environment so it can be captured:
+  let ast = fn.ast
+  if resultPos < sonsLen(ast) and ast.sons[resultPos].kind == nkSym:
+    env.vars.incl(ast.sons[resultPos].sym.id)
+
+proc searchForInnerProcs(o: POuterContext, n: PNode, env: PEnv) =
   if n == nil: return
   case n.kind
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: 
+  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
     discard
   of nkSym:
-    if isInnerProc(n.sym, o.fn) and not containsOrIncl(o.processed, n.sym.id):
-      var inner = newInnerContext(n.sym)
-      let body = n.sym.getBody
-      gatherVars(o, inner, body)
+    let fn = n.sym
+    if isInnerProc(fn, o.fn) and not containsOrIncl(o.processed, fn.id):
+      let body = fn.getBody
+
+      # handle deeply nested captures:
+      let ex = closureCreationPoint(body)
+      let envB = newEnv(o, env, ex, fn)
+      addParamsToEnv(fn, envB)
+      searchForInnerProcs(o, body, envB)
+      fn.ast.sons[bodyPos] = ex
+      
+      let capturedCounter = gatherVars(o, envB, body)
       # dummy closure param needed?
-      if inner.closureParam == nil and n.sym.typ.callConv == ccClosure:
+      if capturedCounter == 0 and fn.typ.callConv == ccClosure:
         #assert tfCapturesEnv notin n.sym.typ.flags
-        dummyClosureParam(o, inner)
-      # only transform if it really needs a closure:
-      if inner.closureParam != nil:
-        let ti = transformInnerProc(o, inner, body)
-        if ti != nil: n.sym.ast.sons[bodyPos] = ti
+        if idTableGet(o.lambdasToEnv, fn) == nil:
+          idTablePut(o.lambdasToEnv, fn, env)
+        addClosureParam(fn, env)
+
+      elif fn.getEnvParam != nil:
+        # only transform if it really needs a closure:
+        let ti = transformInnerProc(o, envB, body)
+        if ti != nil: fn.ast.sons[bodyPos] = ti
   of nkLambdaKinds, nkIteratorDef:
     if n.typ != nil:
-      searchForInnerProcs(o, n.sons[namePos])
+      searchForInnerProcs(o, n.sons[namePos], env)
   of nkWhileStmt, nkForStmt, nkParForStmt, nkBlockStmt:
     # some nodes open a new scope, so they are candidates for the insertion
     # of closure creation; however for simplicity we merge closures between
@@ -465,14 +554,11 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
     # yield observable changes in semantics. For Zahary we also
     # include ``nkBlock``.
     var body = n.len-1
-    for i in countup(0, body - 1): searchForInnerProcs(o, n.sons[i])
+    for i in countup(0, body - 1): searchForInnerProcs(o, n.sons[i], env)
     # special handling for the loop body:
-    let oldEnv = o.currentEnv
     let ex = closureCreationPoint(n.sons[body])
-    o.currentEnv = newEnv(o.fn, oldEnv, ex)
-    searchForInnerProcs(o, n.sons[body])
+    searchForInnerProcs(o, n.sons[body], newEnv(o, env, ex, env.fn))
     n.sons[body] = ex
-    o.currentEnv = oldEnv
   of nkVarSection, nkLetSection:
     # we need to compute a mapping var->declaredBlock. Note: The definition
     # counts, not the block where it is captured!
@@ -481,26 +567,29 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
       if it.kind == nkCommentStmt: discard
       elif it.kind == nkIdentDefs:
         var L = sonsLen(it)
-        if it.sons[0].kind != nkSym: internalError(it.info, "transformOuter")
-        #echo "set: ", it.sons[0].sym.name.s, " ", o.currentBlock == nil
-        idTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv)
-        searchForInnerProcs(o, it.sons[L-1])
+        if it.sons[0].kind == nkSym:
+          # this can be false for recursive invokations that already
+          # transformed it into 'env.varName':
+          env.vars.incl(it.sons[0].sym.id)
+        searchForInnerProcs(o, it.sons[L-1], env)
       elif it.kind == nkVarTuple:
         var L = sonsLen(it)
         for j in countup(0, L-3):
           #echo "set: ", it.sons[j].sym.name.s, " ", o.currentBlock == nil
-          idTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv)
-        searchForInnerProcs(o, it.sons[L-1])
+          if it.sons[j].kind == nkSym:
+            env.vars.incl(it.sons[j].sym.id)
+        searchForInnerProcs(o, it.sons[L-1], env)
       else:
-        internalError(it.info, "transformOuter")
+        internalError(it.info, "searchForInnerProcs")
+  of nkClosure:
+    searchForInnerProcs(o, n.sons[0], env)
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, 
-     nkClosure, nkTypeSection:
+     nkTypeSection:
     # don't recurse here:
-    # XXX recurse here and setup 'up' pointers
     discard
   else:
     for i in countup(0, sonsLen(n) - 1):
-      searchForInnerProcs(o, n.sons[i])
+      searchForInnerProcs(o, n.sons[i], env)
 
 proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = 
   # Bugfix: unfortunately we cannot use 'nkFastAsgn' here as that would
@@ -512,19 +601,6 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
   result.sons[0] = le
   result.sons[1] = ri
 
-proc newClosureCreationVar(o: POuterContext; e: PEnv): PSym =
-  result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info)
-  incl(result.flags, sfShadowed)
-  result.typ = newType(tyRef, o.fn)
-  result.typ.rawAddSon(e.obj)
-
-proc getClosureVar(o: POuterContext; e: PEnv): PSym =
-  if e.createdVar == nil:
-    result = newClosureCreationVar(o, e)
-    e.createdVar = result
-  else:
-    result = e.createdVar
-
 proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode =
   result = newNodeI(nkStmtList, env.info)
   var v = newNodeI(nkVarSection, env.info)
@@ -548,21 +624,25 @@ proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode =
       idNodeTablePut(o.localsToAccess, local, fieldAccess)
     else:
       result.add(newAsgnStmt(fieldAccess, existing, env.info))
-  # add support for 'up' references:
-  for e, field in items(scope.deps):
-    # add ``env.up = env2``
-    result.add(newAsgnStmt(indirectAccess(env, field, env.info),
-               newSymNode(getClosureVar(o, e)), env.info))
-  
+  if scope.upField != nil:
+    # "up" chain has been used:
+    if scope.up.fn != scope.fn:
+      # crosses function boundary:
+      result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info),
+                 newSymNode(getEnvParam(scope.fn)), env.info))
+    else:
+      result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info),
+                 newSymNode(getClosureVar(scope.up)), env.info))
+
 proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
-  var env = getClosureVar(o, scope)
+  var env = getClosureVar(scope)
   result = rawClosureCreation(o, scope, env)
 
 proc generateIterClosureCreation(o: POuterContext; env: PEnv;
                                  scope: PNode): PSym =
   if env.createdVarComesFromIter or env.createdVar.isNil:
     # we have to create a new closure:
-    result = newClosureCreationVar(o, env)
+    result = newClosureCreationVar(env)
     let cc = rawClosureCreation(o, env, result)
     var insertPoint = scope.sons[0]
     if insertPoint.kind == nkEmpty: scope.sons[0] = cc
@@ -577,21 +657,25 @@ proc generateIterClosureCreation(o: POuterContext; env: PEnv;
 proc interestingIterVar(s: PSym): bool {.inline.} =
   result = s.kind in {skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags
 
-proc transformOuterProc(o: POuterContext, n: PNode): PNode
+proc transformOuterProc(o: POuterContext, n: PNode, it: TIter): PNode
 
-proc transformYield(c: POuterContext, n: PNode): PNode =
-  inc c.state.typ.n.sons[1].intVal
-  let stateNo = c.state.typ.n.sons[1].intVal
+proc transformYield(c: POuterContext, n: PNode, it: TIter): PNode =
+  assert it.state != nil
+  assert it.state.typ != nil
+  assert it.state.typ.n != nil
+  inc it.state.typ.n.sons[1].intVal
+  let stateNo = it.state.typ.n.sons[1].intVal
 
   var stateAsgnStmt = newNodeI(nkAsgn, n.info)
-  stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info))
+  stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam),
+                    it.state, n.info))
   stateAsgnStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt)))
 
   var retStmt = newNodeI(nkReturnStmt, n.info)
   if n.sons[0].kind != nkEmpty:
     var a = newNodeI(nkAsgn, n.sons[0].info)
-    var retVal = transformOuterProc(c, n.sons[0])
-    addSon(a, newSymNode(c.resultSym))
+    var retVal = transformOuterProc(c, n.sons[0], it)
+    addSon(a, newSymNode(it.resultSym))
     addSon(a, if retVal.isNil: n.sons[0] else: retVal)
     retStmt.add(a)
   else:
@@ -605,17 +689,18 @@ proc transformYield(c: POuterContext, n: PNode): PNode =
   result.add(retStmt)
   result.add(stateLabelStmt)
 
-proc transformReturn(c: POuterContext, n: PNode): PNode =
+proc transformReturn(c: POuterContext, n: PNode, it: TIter): PNode =
   result = newNodeI(nkStmtList, n.info)
   var stateAsgnStmt = newNodeI(nkAsgn, n.info)
-  stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info))
+  stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam), it.state,
+                    n.info))
   stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
   result.add(stateAsgnStmt)
   result.add(n)
 
-proc outerProcSons(o: POuterContext, n: PNode) =
+proc outerProcSons(o: POuterContext, n: PNode, it: TIter) =
   for i in countup(0, sonsLen(n) - 1):
-    let x = transformOuterProc(o, n.sons[i])
+    let x = transformOuterProc(o, n.sons[i], it)
     if x != nil: n.sons[i] = x
 
 proc liftIterSym*(n: PNode): PNode =
@@ -631,27 +716,107 @@ proc liftIterSym*(n: PNode): PNode =
   addVar(v, newSymNode(env))
   result.add(v)
   # add 'new' statement:
-  result.add(newCall(getSysSym"internalNew", env))
+  result.add newCall(getSysSym"internalNew", env)
   result.add makeClosure(iter, env, n.info)
 
-proc transformOuterProc(o: POuterContext, n: PNode): PNode =
-  if n == nil: return nil
+template envActive(env): expr =
+  (env.capturedVars.len > 0 or env.upField != nil)
+
+# We have to split up environment creation in 2 steps:
+# 1. Generate it and store it in env.replacementNode
+# 2. Insert replacementNode into its forseen slot.
+# This split is necessary so that assignments belonging to closure
+# creation like 'env.param = param' are not transformed
+# into 'env.param = env.param'.
+proc createEnvironments(o: POuterContext) =
+  var env = o.head
+  while env != nil:
+    if envActive(env):
+      var scope = env.attachedNode
+      assert scope.kind == nkStmtList
+      if scope.sons[0].kind == nkEmpty:
+        # prepare for closure construction:
+        env.replacementNode = generateClosureCreation(o, env)
+    env = env.next
+
+proc finishEnvironments(o: POuterContext) =
+  var env = o.head
+  while env != nil:
+    if env.replacementNode != nil:
+      var scope = env.attachedNode
+      assert scope.kind == nkStmtList
+      if scope.sons[0].kind == nkEmpty:
+        # change the empty node to contain the closure construction:
+        scope.sons[0] = env.replacementNode
+    env = env.next
+
+proc transformOuterProcBody(o: POuterContext, n: PNode; it: TIter): PNode =
+  if nfLL in n.flags:
+    result = nil
+  elif it.fn.kind == skClosureIterator:
+    # unfortunately control flow is still convoluted and we can end up
+    # multiple times here for the very same iterator. We shield against this
+    # with some rather primitive check for now:
+    if n.kind == nkStmtList and n.len > 0:
+      if n.sons[0].kind == nkGotoState: return nil
+      if n.len > 1 and n[1].kind == nkStmtList and n[1].len > 0 and 
+          n[1][0].kind == nkGotoState:
+        return nil
+    result = newNodeI(nkStmtList, it.fn.info)
+    var gs = newNodeI(nkGotoState, it.fn.info)
+    assert it.closureParam != nil
+    assert it.state != nil
+    gs.add(rawIndirectAccess(newSymNode(it.closureParam), it.state, it.fn.info))
+    result.add(gs)
+    var state0 = newNodeI(nkState, it.fn.info)
+    state0.add(newIntNode(nkIntLit, 0))
+    result.add(state0)
+    
+    let newBody = transformOuterProc(o, n, it)
+    if newBody != nil:
+      result.add(newBody)
+    else:
+      result.add(n)
+
+    var stateAsgnStmt = newNodeI(nkAsgn, it.fn.info)
+    stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam),
+                      it.state, it.fn.info))
+    stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
+    result.add(stateAsgnStmt)
+    result.flags.incl nfLL
+  else:
+    result = transformOuterProc(o, n, it)
+    if result != nil: result.flags.incl nfLL
+
+proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
+  if n == nil or nfLL in n.flags: return nil
   case n.kind
   of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard
   of nkSym:
     var local = n.sym
 
-    if o.isIter and interestingIterVar(local) and o.fn.id == local.owner.id:
-      if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local)
-      return indirectAccess(newSymNode(o.closureParam), local, n.info)
+    if isInnerProc(local, o.fn) and o.processed.contains(local.id):
+      o.processed.excl(local.id)
+      let body = local.getBody
+      let newBody = transformOuterProcBody(o, body, initIter(local))
+      if newBody != nil:
+        local.ast.sons[bodyPos] = newBody
+
+    if it.fn.kind == skClosureIterator and interestingIterVar(local) and
+        it.fn == local.owner:
+      # every local goes through the closure:
+      #if not containsOrIncl(o.capturedVars, local.id):
+      #  addField(it.obj, local)
+      addUniqueField(it.obj, local)
+      return indirectAccess(newSymNode(it.closureParam), local, n.info)
 
     var closure = PEnv(idTableGet(o.lambdasToEnv, local))
-
     if local.kind == skClosureIterator:
       # consider: [i1, i2, i1]  Since we merged the iterator's closure
       # with the captured owning variables, we need to generate the
       # closure generation code again:
-      if local == o.fn: message(n.info, errRecursiveDependencyX, local.name.s)
+      if local == o.fn or local == it.fn:
+        message(n.info, errRecursiveDependencyX, local.name.s)
       # XXX why doesn't this work?
       if closure.isNil:
         return liftIterSym(n)
@@ -662,7 +827,6 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
 
     if closure != nil:
       # we need to replace the lambda with '(lambda, env)':
-      
       let a = closure.createdVar
       if a != nil:
         return makeClosure(local, a, n.info)
@@ -678,14 +842,6 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
         return makeClosure(local, x, n.info)
     
     if not contains(o.capturedVars, local.id): return
-    var env = PEnv(idTableGet(o.localsToEnv, local))
-    if env == nil: return
-    var scope = env.attachedNode
-    assert scope.kind == nkStmtList
-    if scope.sons[0].kind == nkEmpty:
-      # change the empty node to contain the closure construction:
-      scope.sons[0] = generateClosureCreation(o, env)
-    
     # change 'local' to 'closure.local', unless it's a 'byCopy' variable:
     # if sfByCopy notin local.flags:
     result = idNodeTableGet(o.localsToAccess, local)
@@ -694,73 +850,56 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
     # to access the local as a local.
   of nkLambdaKinds, nkIteratorDef:
     if n.typ != nil:
-      result = transformOuterProc(o, n.sons[namePos])
-  of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
-      nkClosure:
+      result = transformOuterProc(o, n.sons[namePos], it)
+  of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef:
     # don't recurse here:
     discard
+  of nkClosure:
+    if n.sons[0].kind == nkSym:
+      var local = n.sons[0].sym
+      if isInnerProc(local, o.fn) and o.processed.contains(local.id):
+        o.processed.excl(local.id)
+        let body = local.getBody
+        let newBody = transformOuterProcBody(o, body, initIter(local))
+        if newBody != nil:
+          local.ast.sons[bodyPos] = newBody
   of nkHiddenStdConv, nkHiddenSubConv, nkConv:
-    let x = transformOuterProc(o, n.sons[1])
+    let x = transformOuterProc(o, n.sons[1], it)
     if x != nil: n.sons[1] = x
     result = transformOuterConv(n)
   of nkYieldStmt:
-    if o.isIter: result = transformYield(o, n)
-    else: outerProcSons(o, n)
+    if it.fn.kind == skClosureIterator: result = transformYield(o, n, it)
+    else: outerProcSons(o, n, it)
   of nkReturnStmt:
-    if o.isIter: result = transformReturn(o, n)
-    else: outerProcSons(o, n)
-  else:
-    outerProcSons(o, n)
-
-proc liftIterator(c: POuterContext, body: PNode): PNode =
-  let iter = c.fn
-  result = newNodeI(nkStmtList, iter.info)
-  var gs = newNodeI(nkGotoState, iter.info)
-  gs.add(indirectAccess(newSymNode(c.closureParam), c.state, iter.info))
-  result.add(gs)
-  var state0 = newNodeI(nkState, iter.info)
-  state0.add(newIntNode(nkIntLit, 0))
-  result.add(state0)
-  
-  let newBody = transformOuterProc(c, body)
-  if newBody != nil:
-    result.add(newBody)
+    if it.fn.kind == skClosureIterator: result = transformReturn(o, n, it)
+    else: outerProcSons(o, n, it)
   else:
-    result.add(body)
-
-  var stateAsgnStmt = newNodeI(nkAsgn, iter.info)
-  stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),
-                    c.state,iter.info))
-  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
-  result.add(stateAsgnStmt)
+    outerProcSons(o, n, it)
 
 proc liftLambdas*(fn: PSym, body: PNode): PNode =
   # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
   # the transformation even when compiling to JS ...
-  if body.kind == nkEmpty or gCmd == cmdCompileToJS:
+  if body.kind == nkEmpty or gCmd == cmdCompileToJS or 
+      fn.skipGenericOwner.kind != skModule:
     # ignore forward declaration:
     result = body
   else:
+    #if fn.name.s == "cbOuter":
+    #  echo rendertree(fn.ast, {renderIds})
     var o = newOuterContext(fn)
     let ex = closureCreationPoint(body)
-    o.currentEnv = newEnv(fn, nil, ex)
-    # put all params into the environment so they can be captured:
-    let params = fn.typ.n
-    for i in 1.. <params.len: 
-      if params.sons[i].kind != nkSym:
-        internalError(params.info, "liftLambdas: strange params")
-      let param = params.sons[i].sym
-      idTablePut(o.localsToEnv, param, o.currentEnv)
-    # put the 'result' into the environment so it can be captured:
-    let ast = fn.ast
-    if resultPos < sonsLen(ast) and ast.sons[resultPos].kind == nkSym:
-      idTablePut(o.localsToEnv, ast.sons[resultPos].sym, o.currentEnv)
-    searchForInnerProcs(o, body)
-    if o.isIter:
-      result = liftIterator(o, ex)
+    let env = newEnv(o, nil, ex, fn)
+    addParamsToEnv(fn, env)
+    searchForInnerProcs(o, body, env)
+    createEnvironments(o)
+    if fn.kind == skClosureIterator:
+      result = transformOuterProcBody(o, body, initIter(fn))
     else:
-      discard transformOuterProc(o, body)
+      discard transformOuterProcBody(o, body, initIter(fn))
       result = ex
+    finishEnvironments(o)
+    #if fn.name.s == "cbOuter":
+    #  echo rendertree(result, {renderIds})
 
 proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
   if body.kind == nkEmpty or gCmd == cmdCompileToJS:
@@ -768,9 +907,11 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
   else:
     var o = newOuterContext(module)
     let ex = closureCreationPoint(body)
-    o.currentEnv = newEnv(module, nil, ex)
-    searchForInnerProcs(o, body)
-    discard transformOuterProc(o, body)
+    let env = newEnv(o, nil, ex, module)
+    searchForInnerProcs(o, body, env)
+    createEnvironments(o)
+    discard transformOuterProc(o, body, initIter(module))
+    finishEnvironments(o)
     result = ex
 
 # ------------------- iterator transformation --------------------------------
@@ -846,10 +987,6 @@ proc liftForLoop*(body: PNode): PNode =
 
   loopBody.sons[0] = v2
   var bs = newNodeI(nkBreakState, body.info)
-  #if not env.isNil:
-  #  bs.addSon(indirectAccess(env, 
-  #    newSym(skField, getIdent":state", env, env.info), body.info))
-  #else:
   bs.addSon(call.sons[0])
   loopBody.sons[1] = bs
   loopBody.sons[2] = body[L-1]
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index e2afa4362..5b61a9cae 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -64,6 +64,22 @@ proc createObj*(owner: PSym, info: TLineInfo): PType =
   incl result.flags, tfFinal
   result.n = newNodeI(nkRecList, info)
 
+proc rawAddField*(obj: PType; field: PSym) =
+  assert field.kind == skField
+  field.position = sonsLen(obj.n)
+  addSon(obj.n, newSymNode(field))
+
+proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode = 
+  # returns a[].field as a node
+  assert field.kind == skField
+  var deref = newNodeI(nkHiddenDeref, info)
+  deref.typ = a.typ.skipTypes(abstractInst).sons[0]
+  addSon(deref, a)
+  result = newNodeI(nkDotExpr, info)
+  addSon(result, deref)
+  addSon(result, newSymNode(field))
+  result.typ = field.typ
+
 proc addField*(obj: PType; s: PSym) =
   # because of 'gensym' support, we have to mangle the name with its ID.
   # This is hacky but the clean solution is much more complex than it looks.
@@ -74,6 +90,16 @@ proc addField*(obj: PType; s: PSym) =
   field.position = sonsLen(obj.n)
   addSon(obj.n, newSymNode(field))
 
+proc addUniqueField*(obj: PType; s: PSym) =
+  let fieldName = getIdent(s.name.s & $s.id)
+  if lookupInRecord(obj.n, fieldName) == nil:
+    var field = newSym(skField, fieldName, s.owner, s.info)
+    let t = skipIntLit(s.typ)
+    field.typ = t
+    assert t.kind != tyStmt
+    field.position = sonsLen(obj.n)
+    addSon(obj.n, newSymNode(field))
+
 proc newDotExpr(obj, b: PSym): PNode =
   result = newNodeI(nkDotExpr, obj.info)
   let field = getSymFromList(obj.typ.n, getIdent(b.name.s & $b.id))
@@ -95,13 +121,28 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
     t = t.sons[0]
     if t == nil: break
     t = t.skipTypes(abstractInst)
-  assert field != nil, b
+  #if field == nil:
+  #  debug deref.typ
+  #  echo deref.typ.id
+  internalAssert field != nil
   addSon(deref, a)
   result = newNodeI(nkDotExpr, info)
   addSon(result, deref)
   addSon(result, newSymNode(field))
   result.typ = field.typ
 
+proc getFieldFromObj*(t: PType; v: PSym): PSym =
+  assert v.kind != skField
+  let fieldName = getIdent(v.name.s & $v.id)
+  var t = t
+  while true:
+    assert t.kind == tyObject
+    result = getSymFromList(t.n, fieldName)
+    if result != nil: break
+    t = t.sons[0]
+    if t == nil: break
+    t = t.skipTypes(abstractInst)
+
 proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode = 
   # returns a[].b as a node
   result = indirectAccess(a, b.name.s & $b.id, info)
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index b4f6e043d..475326161 100644
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -27,6 +27,8 @@ var
   gSysTypes: array[TTypeKind, PType]
   compilerprocs: TStrTable
 
+proc nilOrSysInt*: PType = gSysTypes[tyInt]
+
 proc registerSysType(t: PType) = 
   if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
   
diff --git a/compiler/pas2nim/nimrod.cfg b/compiler/pas2nim/nimrod.cfg
deleted file mode 100644
index cfeda63ed..000000000
--- a/compiler/pas2nim/nimrod.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-# Use the modules of the compiler
-
-path: "$nimrod/compiler"
-
diff --git a/compiler/pas2nim/pas2nim.nim b/compiler/pas2nim/pas2nim.nim
deleted file mode 100644
index d10028167..000000000
--- a/compiler/pas2nim/pas2nim.nim
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-#
-#      Pas2nim - Pascal to Nimrod source converter
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-import
-  strutils, os, parseopt, llstream, ast, renderer, options, msgs,
-  paslex, pasparse
-
-const
-  Version = "0.8"
-  Usage = """
-pas2nim - Pascal to Nimrod source converter
-  (c) 2012 Andreas Rumpf
-Usage: pas2nim [options] inputfile [options]
-Options:
-  -o, --out:FILE         set output filename
-  --ref                  convert ^typ to ref typ (default: ptr typ)
-  --boot                 use special translation rules for the Nimrod compiler
-  -v, --version          write pas2nim's version
-  -h, --help             show this help
-"""
-
-proc main(infile, outfile: string, flags: set[TParserFlag]) =
-  var stream = llStreamOpen(infile, fmRead)
-  if stream == nil: rawMessage(errCannotOpenFile, infile)
-  var p: TParser
-  openParser(p, infile, stream, flags)
-  var module = parseUnit(p)
-  closeParser(p)
-  renderModule(module, outfile)
-
-var
-  infile = ""
-  outfile = ""
-  flags: set[TParserFlag] = {}
-for kind, key, val in getopt():
-  case kind
-  of cmdArgument: infile = key
-  of cmdLongOption, cmdShortOption:
-    case key
-    of "help", "h":
-      stdout.write(Usage)
-      quit(0)
-    of "version", "v":
-      stdout.write(Version & "\n")
-      quit(0)
-    of "o", "out": outfile = val
-    of "ref": incl(flags, pfRefs)
-    of "boot": flags = flags + {pfRefs, pfMoreReplacements, pfImportBlackList}
-    else: stdout.writeln("[Error] unknown option: " & key)
-  of cmdEnd: assert(false)
-if infile.len == 0:
-  # no filename has been given, so we show the help:
-  stdout.write(Usage)
-else:
-  if outfile.len == 0:
-    outfile = changeFileExt(infile, "nim")
-  infile = addFileExt(infile, "pas")
-  main(infile, outfile, flags)
diff --git a/compiler/pas2nim/paslex.nim b/compiler/pas2nim/paslex.nim
deleted file mode 100644
index f24b0c420..000000000
--- a/compiler/pas2nim/paslex.nim
+++ /dev/null
@@ -1,570 +0,0 @@
-#
-#
-#      Pas2nim - Pascal to Nimrod source converter
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This module implements a FreePascal scanner. This is an adaption from
-# the scanner module.
-
-import
-  hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream
-
-const
-  MaxLineLength* = 80         # lines longer than this lead to a warning
-  numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'}
-  SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
-  SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
-  OpChars*: TCharSet = {'+', '-', '*', '/', '<', '>', '!', '?', '^', '.', '|',
-    '=', ':', '%', '&', '$', '@', '~', '\x80'..'\xFF'}
-
-# keywords are sorted!
-
-type
-  TTokKind* = enum
-    pxInvalid, pxEof,
-    pxAnd, pxArray, pxAs, pxAsm, pxBegin, pxCase, pxClass, pxConst,
-    pxConstructor, pxDestructor, pxDiv, pxDo, pxDownto, pxElse, pxEnd, pxExcept,
-    pxExports, pxFinalization, pxFinally, pxFor, pxFunction, pxGoto, pxIf,
-    pxImplementation, pxIn, pxInherited, pxInitialization, pxInline,
-    pxInterface, pxIs, pxLabel, pxLibrary, pxMod, pxNil, pxNot, pxObject, pxOf,
-    pxOr, pxOut, pxPacked, pxProcedure, pxProgram, pxProperty, pxRaise,
-    pxRecord, pxRepeat, pxResourcestring, pxSet, pxShl, pxShr, pxThen,
-    pxThreadvar, pxTo, pxTry, pxType, pxUnit, pxUntil, pxUses, pxVar, pxWhile,
-    pxWith, pxXor,
-    pxComment,                # ordinary comment
-    pxCommand,                # {@}
-    pxAmp,                    # {&}
-    pxPer,                    # {%}
-    pxStrLit, pxSymbol,       # a symbol
-    pxIntLit, pxInt64Lit, # long constant like 0x70fffffff or out of int range
-    pxFloatLit, pxParLe, pxParRi, pxBracketLe, pxBracketRi, pxComma,
-    pxSemiColon, pxColon,     # operators
-    pxAsgn, pxEquals, pxDot, pxDotDot, pxHat, pxPlus, pxMinus, pxStar, pxSlash,
-    pxLe, pxLt, pxGe, pxGt, pxNeq, pxAt, pxStarDirLe, pxStarDirRi, pxCurlyDirLe,
-    pxCurlyDirRi
-  TTokKinds* = set[TTokKind]
-
-const
-  Keywords = ["and", "array", "as", "asm", "begin", "case", "class", "const",
-    "constructor", "destructor", "div", "do", "downto", "else", "end", "except",
-    "exports", "finalization", "finally", "for", "function", "goto", "if",
-    "implementation", "in", "inherited", "initialization", "inline",
-    "interface", "is", "label", "library", "mod", "nil", "not", "object", "of",
-    "or", "out", "packed", "procedure", "program", "property", "raise",
-    "record", "repeat", "resourcestring", "set", "shl", "shr", "then",
-    "threadvar", "to", "try", "type", "unit", "until", "uses", "var", "while",
-    "with", "xor"]
-
-  firstKeyword = pxAnd
-  lastKeyword = pxXor
-
-type
-  TNumericalBase* = enum base10, base2, base8, base16
-  TToken* = object
-    xkind*: TTokKind          # the type of the token
-    ident*: PIdent            # the parsed identifier
-    iNumber*: BiggestInt      # the parsed integer literal
-    fNumber*: BiggestFloat    # the parsed floating point literal
-    base*: TNumericalBase     # the numerical base; only valid for int
-                              # or float literals
-    literal*: string          # the parsed (string) literal
-
-  TLexer* = object of TBaseLexer
-    filename*: string
-
-
-proc getTok*(L: var TLexer, tok: var TToken)
-proc printTok*(tok: TToken)
-proc `$`*(tok: TToken): string
-# implementation
-
-var
-  dummyIdent: PIdent
-  gLinesCompiled: int
-
-proc fillToken(L: var TToken) =
-  L.xkind = pxInvalid
-  L.iNumber = 0
-  L.literal = ""
-  L.fNumber = 0.0
-  L.base = base10
-  L.ident = dummyIdent        # this prevents many bugs!
-
-proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) =
-  openBaseLexer(lex, inputstream)
-  lex.filename = filename
-
-proc closeLexer*(lex: var TLexer) =
-  inc(gLinesCompiled, lex.LineNumber)
-  closeBaseLexer(lex)
-
-proc getColumn(L: TLexer): int =
-  result = getColNumber(L, L.bufPos)
-
-proc getLineInfo*(L: TLexer): TLineInfo =
-  result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
-
-proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
-  msgs.globalError(getLineInfo(L), msg, arg)
-
-proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
-  var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
-  msgs.globalError(info, msg, arg)
-
-proc tokKindToStr*(k: TTokKind): string =
-  case k
-  of pxEof: result = "[EOF]"
-  of firstKeyword..lastKeyword:
-    result = Keywords[ord(k)-ord(firstKeyword)]
-  of pxInvalid, pxComment, pxStrLit: result = "string literal"
-  of pxCommand: result = "{@"
-  of pxAmp: result = "{&"
-  of pxPer: result = "{%"
-  of pxSymbol: result = "identifier"
-  of pxIntLit, pxInt64Lit: result = "integer literal"
-  of pxFloatLit: result = "floating point literal"
-  of pxParLe: result = "("
-  of pxParRi: result = ")"
-  of pxBracketLe: result = "["
-  of pxBracketRi: result = "]"
-  of pxComma: result = ","
-  of pxSemiColon: result = ";"
-  of pxColon: result = ":"
-  of pxAsgn: result = ":="
-  of pxEquals: result = "="
-  of pxDot: result = "."
-  of pxDotDot: result = ".."
-  of pxHat: result = "^"
-  of pxPlus: result = "+"
-  of pxMinus: result = "-"
-  of pxStar: result = "*"
-  of pxSlash: result = "/"
-  of pxLe: result = "<="
-  of pxLt: result = "<"
-  of pxGe: result = ">="
-  of pxGt: result = ">"
-  of pxNeq: result = "<>"
-  of pxAt: result = "@"
-  of pxStarDirLe: result = "(*$"
-  of pxStarDirRi: result = "*)"
-  of pxCurlyDirLe: result = "{$"
-  of pxCurlyDirRi: result = "}"
-
-proc `$`(tok: TToken): string =
-  case tok.xkind
-  of pxInvalid, pxComment, pxStrLit: result = tok.literal
-  of pxSymbol: result = tok.ident.s
-  of pxIntLit, pxInt64Lit: result = $tok.iNumber
-  of pxFloatLit: result = $tok.fNumber
-  else: result = tokKindToStr(tok.xkind)
-
-proc printTok(tok: TToken) =
-  writeln(stdout, $tok)
-
-proc setKeyword(L: var TLexer, tok: var TToken) =
-  var x = binaryStrSearch(keywords, toLower(tok.ident.s))
-  if x < 0: tok.xkind = pxSymbol
-  else: tok.xKind = TTokKind(x + ord(firstKeyword))
-
-proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
-  # matches ([chars]_)*
-  var pos = L.bufpos              # use registers for pos, buf
-  var buf = L.buf
-  while true:
-    if buf[pos] in chars:
-      add(tok.literal, buf[pos])
-      inc(pos)
-    else:
-      break
-    if buf[pos] == '_':
-      add(tok.literal, '_')
-      inc(pos)
-  L.bufPos = pos
-
-proc isFloatLiteral(s: string): bool =
-  for i in countup(0, len(s)-1):
-    if s[i] in {'.', 'e', 'E'}:
-      return true
-
-proc getNumber2(L: var TLexer, tok: var TToken) =
-  var pos = L.bufpos + 1 # skip %
-  if not (L.buf[pos] in {'0'..'1'}):
-    # BUGFIX for %date%
-    tok.xkind = pxInvalid
-    add(tok.literal, '%')
-    inc(L.bufpos)
-    return
-  tok.base = base2
-  var xi: BiggestInt = 0
-  var bits = 0
-  while true:
-    case L.buf[pos]
-    of 'A'..'Z', 'a'..'z', '2'..'9', '.':
-      lexMessage(L, errInvalidNumber)
-      inc(pos)
-    of '_':
-      inc(pos)
-    of '0', '1':
-      xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0'))
-      inc(pos)
-      inc(bits)
-    else: break
-  tok.iNumber = xi
-  if (bits > 32): tok.xkind = pxInt64Lit
-  else: tok.xkind = pxIntLit
-  L.bufpos = pos
-
-proc getNumber16(L: var TLexer, tok: var TToken) =
-  var pos = L.bufpos + 1          # skip $
-  tok.base = base16
-  var xi: BiggestInt = 0
-  var bits = 0
-  while true:
-    case L.buf[pos]
-    of 'G'..'Z', 'g'..'z', '.':
-      lexMessage(L, errInvalidNumber)
-      inc(pos)
-    of '_': inc(pos)
-    of '0'..'9':
-      xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0'))
-      inc(pos)
-      inc(bits, 4)
-    of 'a'..'f':
-      xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('a') + 10)
-      inc(pos)
-      inc(bits, 4)
-    of 'A'..'F':
-      xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10)
-      inc(pos)
-      inc(bits, 4)
-    else: break
-  tok.iNumber = xi
-  if (bits > 32):
-    tok.xkind = pxInt64Lit
-  else:
-    tok.xkind = pxIntLit
-  L.bufpos = pos
-
-proc getNumber10(L: var TLexer, tok: var TToken) =
-  tok.base = base10
-  matchUnderscoreChars(L, tok, {'0'..'9'})
-  if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}):
-    add(tok.literal, '.')
-    inc(L.bufpos)
-    matchUnderscoreChars(L, tok, {'e', 'E', '+', '-', '0'..'9'})
-  try:
-    if isFloatLiteral(tok.literal):
-      tok.fnumber = parseFloat(tok.literal)
-      tok.xkind = pxFloatLit
-    else:
-      tok.iNumber = parseInt(tok.literal)
-      if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)):
-        tok.xkind = pxInt64Lit
-      else:
-        tok.xkind = pxIntLit
-  except EInvalidValue:
-    lexMessage(L, errInvalidNumber, tok.literal)
-  except EOverflow:
-    lexMessage(L, errNumberOutOfRange, tok.literal)
-
-proc handleCRLF(L: var TLexer, pos: int): int =
-  case L.buf[pos]
-  of CR: result = nimlexbase.handleCR(L, pos)
-  of LF: result = nimlexbase.handleLF(L, pos)
-  else: result = pos
-
-proc getString(L: var TLexer, tok: var TToken) =
-  var xi: int
-  var pos = L.bufPos
-  var buf = L.buf
-  while true:
-    if buf[pos] == '\'':
-      inc(pos)
-      while true:
-        case buf[pos]
-        of CR, LF, nimlexbase.EndOfFile:
-          lexMessage(L, errClosingQuoteExpected)
-          break
-        of '\'':
-          inc(pos)
-          if buf[pos] == '\'':
-            inc(pos)
-            add(tok.literal, '\'')
-          else:
-            break
-        else:
-          add(tok.literal, buf[pos])
-          inc(pos)
-    elif buf[pos] == '#':
-      inc(pos)
-      xi = 0
-      case buf[pos]
-      of '$':
-        inc(pos)
-        xi = 0
-        while true:
-          case buf[pos]
-          of '0'..'9': xi = (xi shl 4) or (ord(buf[pos]) - ord('0'))
-          of 'a'..'f': xi = (xi shl 4) or (ord(buf[pos]) - ord('a') + 10)
-          of 'A'..'F': xi = (xi shl 4) or (ord(buf[pos]) - ord('A') + 10)
-          else: break
-          inc(pos)
-      of '0'..'9':
-        xi = 0
-        while buf[pos] in {'0'..'9'}:
-          xi = (xi * 10) + (ord(buf[pos]) - ord('0'))
-          inc(pos)
-      else: lexMessage(L, errInvalidCharacterConstant)
-      if (xi <= 255): add(tok.literal, chr(xi))
-      else: lexMessage(L, errInvalidCharacterConstant)
-    else:
-      break
-  tok.xkind = pxStrLit
-  L.bufpos = pos
-
-proc getSymbol(L: var TLexer, tok: var TToken) =
-  var h: THash = 0
-  var pos = L.bufpos
-  var buf = L.buf
-  while true:
-    var c = buf[pos]
-    case c
-    of 'a'..'z', '0'..'9', '\x80'..'\xFF':
-      h = h +% ord(c)
-      h = h +% h shl 10
-      h = h xor (h shr 6)
-    of 'A'..'Z':
-      c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
-      h = h +% ord(c)
-      h = h +% h shl 10
-      h = h xor (h shr 6)
-    of '_': discard
-    else: break
-    inc(pos)
-  h = h +% h shl 3
-  h = h xor (h shr 11)
-  h = h +% h shl 15
-  tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
-  L.bufpos = pos
-  setKeyword(L, tok)
-
-proc scanLineComment(L: var TLexer, tok: var TToken) =
-  var pos = L.bufpos
-  var buf = L.buf
-  # a comment ends if the next line does not start with the // on the same
-  # column after only whitespace
-  tok.xkind = pxComment
-  var col = getColNumber(L, pos)
-  while true:
-    inc(pos, 2)               # skip //
-    add(tok.literal, '#')
-    while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}):
-      add(tok.literal, buf[pos])
-      inc(pos)
-    pos = handleCRLF(L, pos)
-    buf = L.buf
-    var indent = 0
-    while buf[pos] == ' ':
-      inc(pos)
-      inc(indent)
-    if (col == indent) and (buf[pos] == '/') and (buf[pos + 1] == '/'):
-      tok.literal = tok.literal & "\n"
-    else:
-      break
-  L.bufpos = pos
-
-proc scanCurlyComment(L: var TLexer, tok: var TToken) =
-  var pos = L.bufpos
-  var buf = L.buf
-  tok.literal = "#"
-  tok.xkind = pxComment
-  while true:
-    case buf[pos]
-    of CR, LF:
-      pos = handleCRLF(L, pos)
-      buf = L.buf
-      add(tok.literal, "\n#")
-    of '}':
-      inc(pos)
-      break
-    of nimlexbase.EndOfFile: lexMessage(L, errTokenExpected, "}")
-    else:
-      add(tok.literal, buf[pos])
-      inc(pos)
-  L.bufpos = pos
-
-proc scanStarComment(L: var TLexer, tok: var TToken) =
-  var pos = L.bufpos
-  var buf = L.buf
-  tok.literal = "#"
-  tok.xkind = pxComment
-  while true:
-    case buf[pos]
-    of CR, LF:
-      pos = handleCRLF(L, pos)
-      buf = L.buf
-      add(tok.literal, "\n#")
-    of '*':
-      inc(pos)
-      if buf[pos] == ')':
-        inc(pos)
-        break
-      else:
-        add(tok.literal, '*')
-    of nimlexbase.EndOfFile:
-      lexMessage(L, errTokenExpected, "*)")
-    else:
-      add(tok.literal, buf[pos])
-      inc(pos)
-  L.bufpos = pos
-
-proc skip(L: var TLexer, tok: var TToken) =
-  var pos = L.bufpos
-  var buf = L.buf
-  while true:
-    case buf[pos]
-    of ' ', Tabulator:
-      inc(pos)                # newline is special:
-    of CR, LF:
-      pos = handleCRLF(L, pos)
-      buf = L.buf
-    else:
-      break                   # EndOfFile also leaves the loop
-  L.bufpos = pos
-
-proc getTok(L: var TLexer, tok: var TToken) =
-  tok.xkind = pxInvalid
-  fillToken(tok)
-  skip(L, tok)
-  var c = L.buf[L.bufpos]
-  if c in SymStartChars:
-    getSymbol(L, tok)
-  elif c in {'0'..'9'}:
-    getNumber10(L, tok)
-  else:
-    case c
-    of ';':
-      tok.xkind = pxSemicolon
-      inc(L.bufpos)
-    of '/':
-      if L.buf[L.bufpos + 1] == '/':
-        scanLineComment(L, tok)
-      else:
-        tok.xkind = pxSlash
-        inc(L.bufpos)
-    of ',':
-      tok.xkind = pxComma
-      inc(L.bufpos)
-    of '(':
-      inc(L.bufpos)
-      if (L.buf[L.bufPos] == '*'):
-        if (L.buf[L.bufPos + 1] == '$'):
-          inc(L.bufpos, 2)
-          skip(L, tok)
-          getSymbol(L, tok)
-          tok.xkind = pxStarDirLe
-        else:
-          inc(L.bufpos)
-          scanStarComment(L, tok)
-      else:
-        tok.xkind = pxParLe
-    of '*':
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == ')':
-        inc(L.bufpos)
-        tok.xkind = pxStarDirRi
-      else:
-        tok.xkind = pxStar
-    of ')':
-      tok.xkind = pxParRi
-      inc(L.bufpos)
-    of '[':
-      inc(L.bufpos)
-      tok.xkind = pxBracketLe
-    of ']':
-      inc(L.bufpos)
-      tok.xkind = pxBracketRi
-    of '.':
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '.':
-        tok.xkind = pxDotDot
-        inc(L.bufpos)
-      else:
-        tok.xkind = pxDot
-    of '{':
-      inc(L.bufpos)
-      case L.buf[L.bufpos]
-      of '$':
-        inc(L.bufpos)
-        skip(L, tok)
-        getSymbol(L, tok)
-        tok.xkind = pxCurlyDirLe
-      of '&':
-        inc(L.bufpos)
-        tok.xkind = pxAmp
-      of '%':
-        inc(L.bufpos)
-        tok.xkind = pxPer
-      of '@':
-        inc(L.bufpos)
-        tok.xkind = pxCommand
-      else: scanCurlyComment(L, tok)
-    of '+':
-      tok.xkind = pxPlus
-      inc(L.bufpos)
-    of '-':
-      tok.xkind = pxMinus
-      inc(L.bufpos)
-    of ':':
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        inc(L.bufpos)
-        tok.xkind = pxAsgn
-      else:
-        tok.xkind = pxColon
-    of '<':
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '>':
-        inc(L.bufpos)
-        tok.xkind = pxNeq
-      elif L.buf[L.bufpos] == '=':
-        inc(L.bufpos)
-        tok.xkind = pxLe
-      else:
-        tok.xkind = pxLt
-    of '>':
-      inc(L.bufpos)
-      if L.buf[L.bufpos] == '=':
-        inc(L.bufpos)
-        tok.xkind = pxGe
-      else:
-        tok.xkind = pxGt
-    of '=':
-      tok.xkind = pxEquals
-      inc(L.bufpos)
-    of '@':
-      tok.xkind = pxAt
-      inc(L.bufpos)
-    of '^':
-      tok.xkind = pxHat
-      inc(L.bufpos)
-    of '}':
-      tok.xkind = pxCurlyDirRi
-      inc(L.bufpos)
-    of '\'', '#':
-      getString(L, tok)
-    of '$':
-      getNumber16(L, tok)
-    of '%':
-      getNumber2(L, tok)
-    of nimlexbase.EndOfFile:
-      tok.xkind = pxEof
-    else:
-      tok.literal = c & ""
-      tok.xkind = pxInvalid
-      lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
-      inc(L.bufpos)
diff --git a/compiler/pas2nim/pasparse.nim b/compiler/pas2nim/pasparse.nim
deleted file mode 100644
index a6f8363f6..000000000
--- a/compiler/pas2nim/pasparse.nim
+++ /dev/null
@@ -1,1513 +0,0 @@
-#
-#
-#      Pas2nim - Pascal to Nimrod source converter
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This module implements the parser of the Pascal variant Nimrod is written in.
-# It transfers a Pascal module into a Nimrod AST. Then the renderer can be
-# used to convert the AST to its text representation.
-
-import 
-  os, llstream, paslex, idents, strutils, ast, astalgo, msgs, options
-
-type 
-  TSection = enum 
-    seImplementation, seInterface
-  TContext = enum 
-    conExpr, conStmt, conTypeDesc
-  TParserFlag* = enum
-    pfRefs,             ## use "ref" instead of "ptr" for Pascal's ^typ
-    pfMoreReplacements, ## use more than the default replacements
-    pfImportBlackList   ## use import blacklist
-  TParser*{.final.} = object
-    section: TSection
-    inParamList: bool
-    context: TContext     # needed for the @emit command
-    lastVarSection: PNode
-    lex: TLexer
-    tok: TToken
-    repl: TIdTable           # replacements
-    flags: set[TParserFlag]
-  
-  TReplaceTuple* = array[0..1, string]
-
-const 
-  ImportBlackList*: array[1..3, string] = ["nsystem", "sysutils", "charsets"]
-  stdReplacements*: array[1..19, TReplaceTuple] = [["include", "incl"], 
-    ["exclude", "excl"], ["pchar", "cstring"], ["assignfile", "open"], 
-    ["integer", "int"], ["longword", "int32"], ["cardinal", "int"], 
-    ["boolean", "bool"], ["shortint", "int8"], ["smallint", "int16"], 
-    ["longint", "int32"], ["byte", "int8"], ["word", "int16"], 
-    ["single", "float32"], ["double", "float64"], ["real", "float"], 
-    ["length", "len"], ["len", "length"], ["setlength", "setlen"]]
-  nimReplacements*: array[1..35, TReplaceTuple] = [["nimread", "read"], 
-    ["nimwrite", "write"], ["nimclosefile", "close"], ["closefile", "close"], 
-    ["openfile", "open"], ["nsystem", "system"], ["ntime", "times"], 
-    ["nos", "os"], ["nmath", "math"], ["ncopy", "copy"], ["addChar", "add"], 
-    ["halt", "quit"], ["nobject", "TObject"], ["eof", "EndOfFile"], 
-    ["input", "stdin"], ["output", "stdout"], ["addu", "`+%`"], 
-    ["subu", "`-%`"], ["mulu", "`*%`"], ["divu", "`/%`"], ["modu", "`%%`"], 
-    ["ltu", "`<%`"], ["leu", "`<=%`"], ["shlu", "`shl`"], ["shru", "`shr`"], 
-    ["assigned", "not isNil"], ["eintoverflow", "EOverflow"], ["format", "`%`"], 
-    ["snil", "nil"], ["tostringf", "$"], ["ttextfile", "tfile"], 
-    ["tbinaryfile", "tfile"], ["strstart", "0"], ["nl", "\"\\n\""],
-    ["tostring", "$"]]
-
-proc parseUnit*(p: var TParser): PNode
-proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
-                 flags: set[TParserFlag] = {})
-proc closeParser*(p: var TParser)
-proc exSymbol*(n: var PNode)
-proc fixRecordDef*(n: var PNode)
-  # XXX: move these two to an auxiliary module
-
-# implementation
-
-proc openParser(p: var TParser, filename: string, 
-                inputStream: PLLStream, flags: set[TParserFlag] = {}) = 
-  openLexer(p.lex, filename, inputStream)
-  initIdTable(p.repl)
-  for i in countup(low(stdReplacements), high(stdReplacements)): 
-    idTablePut(p.repl, getIdent(stdReplacements[i][0]), 
-               getIdent(stdReplacements[i][1]))
-  if pfMoreReplacements in flags: 
-    for i in countup(low(nimReplacements), high(nimReplacements)): 
-      idTablePut(p.repl, getIdent(nimReplacements[i][0]), 
-                 getIdent(nimReplacements[i][1]))
-  p.flags = flags
-  
-proc closeParser(p: var TParser) = closeLexer(p.lex)
-proc getTok(p: var TParser) = getTok(p.lex, p.tok)
-
-proc parMessage(p: TParser, msg: TMsgKind, arg = "") = 
-  lexMessage(p.lex, msg, arg)
-
-proc parLineInfo(p: TParser): TLineInfo = 
-  result = getLineInfo(p.lex)
-
-proc skipCom(p: var TParser, n: PNode) = 
-  while p.tok.xkind == pxComment: 
-    if (n != nil): 
-      if n.comment == nil: n.comment = p.tok.literal
-      else: add(n.comment, "\n" & p.tok.literal)
-    else: 
-      parMessage(p, warnCommentXIgnored, p.tok.literal)
-    getTok(p)
-
-proc expectIdent(p: TParser) = 
-  if p.tok.xkind != pxSymbol: 
-    lexMessage(p.lex, errIdentifierExpected, $(p.tok))
-  
-proc eat(p: var TParser, xkind: TTokKind) = 
-  if p.tok.xkind == xkind: getTok(p)
-  else: lexMessage(p.lex, errTokenExpected, tokKindToStr(xkind))
-  
-proc opt(p: var TParser, xkind: TTokKind) = 
-  if p.tok.xkind == xkind: getTok(p)
-  
-proc newNodeP(kind: TNodeKind, p: TParser): PNode = 
-  result = newNodeI(kind, getLineInfo(p.lex))
-
-proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode = 
-  result = newNodeP(kind, p)
-  result.intVal = intVal
-
-proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, 
-                   p: TParser): PNode = 
-  result = newNodeP(kind, p)
-  result.floatVal = floatVal
-
-proc newStrNodeP(kind: TNodeKind, strVal: string, p: TParser): PNode = 
-  result = newNodeP(kind, p)
-  result.strVal = strVal
-
-proc newIdentNodeP(ident: PIdent, p: TParser): PNode = 
-  result = newNodeP(nkIdent, p)
-  result.ident = ident
-
-proc createIdentNodeP(ident: PIdent, p: TParser): PNode = 
-  result = newNodeP(nkIdent, p)
-  var x = PIdent(idTableGet(p.repl, ident))
-  if x != nil: result.ident = x
-  else: result.ident = ident
-  
-proc parseExpr(p: var TParser): PNode
-proc parseStmt(p: var TParser): PNode
-proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode
-
-proc parseEmit(p: var TParser, definition: PNode): PNode = 
-  getTok(p)                   # skip 'emit'
-  result = ast.emptyNode
-  if p.tok.xkind != pxCurlyDirRi: 
-    case p.context
-    of conExpr: 
-      result = parseExpr(p)
-    of conStmt: 
-      result = parseStmt(p)
-      if p.tok.xkind != pxCurlyDirRi: 
-        var a = result
-        result = newNodeP(nkStmtList, p)
-        addSon(result, a)
-        while p.tok.xkind != pxCurlyDirRi: 
-          addSon(result, parseStmt(p))
-    of conTypeDesc: 
-      result = parseTypeDesc(p, definition)
-  eat(p, pxCurlyDirRi)
-
-proc parseCommand(p: var TParser, definition: PNode = nil): PNode = 
-  result = ast.emptyNode
-  getTok(p)
-  if p.tok.ident.id == getIdent("discard").id: 
-    result = newNodeP(nkDiscardStmt, p)
-    getTok(p)
-    eat(p, pxCurlyDirRi)
-    addSon(result, parseExpr(p))
-  elif p.tok.ident.id == getIdent("set").id: 
-    getTok(p)
-    eat(p, pxCurlyDirRi)
-    result = parseExpr(p)
-    if result.kind == nkEmpty: internalError("emptyNode modified")
-    result.kind = nkCurly
-  elif p.tok.ident.id == getIdent("cast").id: 
-    getTok(p)
-    eat(p, pxCurlyDirRi)
-    var a = parseExpr(p)
-    if (a.kind == nkCall) and (sonsLen(a) == 2): 
-      result = newNodeP(nkCast, p)
-      addSon(result, a.sons[0])
-      addSon(result, a.sons[1])
-    else: 
-      parMessage(p, errInvalidDirectiveX, $p.tok)
-      result = a
-  elif p.tok.ident.id == getIdent("emit").id: 
-    result = parseEmit(p, definition)
-  elif p.tok.ident.id == getIdent("ignore").id: 
-    getTok(p)
-    eat(p, pxCurlyDirRi)
-    while true: 
-      case p.tok.xkind
-      of pxEof: 
-        parMessage(p, errTokenExpected, "{@emit}")
-      of pxCommand: 
-        getTok(p)
-        if p.tok.ident.id == getIdent("emit").id: 
-          result = parseEmit(p, definition)
-          break 
-        else: 
-          while (p.tok.xkind != pxCurlyDirRi) and (p.tok.xkind != pxEof): 
-            getTok(p)
-          eat(p, pxCurlyDirRi)
-      else: 
-        getTok(p)             # skip token
-  elif p.tok.ident.id == getIdent("ptr").id: 
-    result = newNodeP(nkPtrTy, p)
-    getTok(p)
-    eat(p, pxCurlyDirRi)
-  elif p.tok.ident.id == getIdent("tuple").id: 
-    result = newNodeP(nkTupleTy, p)
-    getTok(p)
-    eat(p, pxCurlyDirRi)
-  elif p.tok.ident.id == getIdent("acyclic").id: 
-    result = newIdentNodeP(p.tok.ident, p)
-    getTok(p)
-    eat(p, pxCurlyDirRi)
-  else: 
-    parMessage(p, errInvalidDirectiveX, $p.tok)
-    while true: 
-      getTok(p)
-      if p.tok.xkind == pxCurlyDirRi or p.tok.xkind == pxEof: break 
-    eat(p, pxCurlyDirRi)
-    result = ast.emptyNode
-
-proc getPrecedence(kind: TTokKind): int = 
-  case kind
-  of pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd: result = 5
-  of pxPlus, pxMinus, pxOr, pxXor: result = 4
-  of pxIn, pxEquals, pxLe, pxLt, pxGe, pxGt, pxNeq, pxIs: result = 3
-  else: result = -1
-  
-proc rangeExpr(p: var TParser): PNode = 
-  var a = parseExpr(p)
-  if p.tok.xkind == pxDotDot: 
-    result = newNodeP(nkRange, p)
-    addSon(result, a)
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, parseExpr(p))
-  else: 
-    result = a
-  
-proc bracketExprList(p: var TParser, first: PNode): PNode = 
-  result = newNodeP(nkBracketExpr, p)
-  addSon(result, first)
-  getTok(p)
-  skipCom(p, result)
-  while true: 
-    if p.tok.xkind == pxBracketRi: 
-      getTok(p)
-      break 
-    if p.tok.xkind == pxEof: 
-      parMessage(p, errTokenExpected, tokKindToStr(pxBracketRi))
-      break 
-    var a = rangeExpr(p)
-    skipCom(p, a)
-    if p.tok.xkind == pxComma: 
-      getTok(p)
-      skipCom(p, a)
-    addSon(result, a)
-
-proc exprColonEqExpr(p: var TParser, kind: TNodeKind, 
-                     tok: TTokKind): PNode = 
-  var a = parseExpr(p)
-  if p.tok.xkind == tok: 
-    result = newNodeP(kind, p)
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, a)
-    addSon(result, parseExpr(p))
-  else: 
-    result = a
-  
-proc exprListAux(p: var TParser, elemKind: TNodeKind, 
-                 endTok, sepTok: TTokKind, result: PNode) = 
-  getTok(p)
-  skipCom(p, result)
-  while true: 
-    if p.tok.xkind == endTok: 
-      getTok(p)
-      break 
-    if p.tok.xkind == pxEof: 
-      parMessage(p, errTokenExpected, tokKindToStr(endTok))
-      break 
-    var a = exprColonEqExpr(p, elemKind, sepTok)
-    skipCom(p, a)
-    if (p.tok.xkind == pxComma) or (p.tok.xkind == pxSemicolon): 
-      getTok(p)
-      skipCom(p, a)
-    addSon(result, a)
-
-proc qualifiedIdent(p: var TParser): PNode = 
-  if p.tok.xkind == pxSymbol: 
-    result = createIdentNodeP(p.tok.ident, p)
-  else: 
-    parMessage(p, errIdentifierExpected, $p.tok)
-    return ast.emptyNode
-  getTok(p)
-  skipCom(p, result)
-  if p.tok.xkind == pxDot: 
-    getTok(p)
-    skipCom(p, result)
-    if p.tok.xkind == pxSymbol: 
-      var a = result
-      result = newNodeI(nkDotExpr, a.info)
-      addSon(result, a)
-      addSon(result, createIdentNodeP(p.tok.ident, p))
-      getTok(p)
-    else: 
-      parMessage(p, errIdentifierExpected, $p.tok)
-  
-proc qualifiedIdentListAux(p: var TParser, endTok: TTokKind, 
-                           result: PNode) = 
-  getTok(p)
-  skipCom(p, result)
-  while true: 
-    if p.tok.xkind == endTok: 
-      getTok(p)
-      break 
-    if p.tok.xkind == pxEof: 
-      parMessage(p, errTokenExpected, tokKindToStr(endTok))
-      break 
-    var a = qualifiedIdent(p)
-    skipCom(p, a)
-    if p.tok.xkind == pxComma: 
-      getTok(p)
-      skipCom(p, a)
-    addSon(result, a)
-
-proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind, 
-                         endTok, sepTok: TTokKind): PNode = 
-  result = newNodeP(kind, p)
-  exprListAux(p, elemKind, endTok, sepTok, result)
-
-proc setBaseFlags(n: PNode, base: TNumericalBase) = 
-  case base
-  of base10: discard
-  of base2: incl(n.flags, nfBase2)
-  of base8: incl(n.flags, nfBase8)
-  of base16: incl(n.flags, nfBase16)
-  
-proc identOrLiteral(p: var TParser): PNode = 
-  case p.tok.xkind
-  of pxSymbol: 
-    result = createIdentNodeP(p.tok.ident, p)
-    getTok(p)
-  of pxIntLit: 
-    result = newIntNodeP(nkIntLit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of pxInt64Lit: 
-    result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of pxFloatLit: 
-    result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of pxStrLit: 
-    if len(p.tok.literal) != 1: result = newStrNodeP(nkStrLit, p.tok.literal, p)
-    else: result = newIntNodeP(nkCharLit, ord(p.tok.literal[0]), p)
-    getTok(p)
-  of pxNil: 
-    result = newNodeP(nkNilLit, p)
-    getTok(p)
-  of pxParLe: 
-    # () constructor
-    result = exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi, pxColon)
-    #if hasSonWith(result, nkExprColonExpr) then
-    #  replaceSons(result, nkExprColonExpr, nkExprEqExpr)
-    if (sonsLen(result) > 1) and not hasSonWith(result, nkExprColonExpr): 
-      result.kind = nkBracket # is an array constructor
-  of pxBracketLe: 
-    # [] constructor
-    result = newNodeP(nkBracket, p)
-    getTok(p)
-    skipCom(p, result)
-    while (p.tok.xkind != pxBracketRi) and (p.tok.xkind != pxEof): 
-      var a = rangeExpr(p)
-      if a.kind == nkRange: 
-        result.kind = nkCurly # it is definitely a set literal
-      opt(p, pxComma)
-      skipCom(p, a)
-      assert(a != nil)
-      addSon(result, a)
-    eat(p, pxBracketRi)
-  of pxCommand: 
-    result = parseCommand(p)
-  else: 
-    parMessage(p, errExprExpected, $(p.tok))
-    getTok(p) # we must consume a token here to prevend endless loops!
-    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)
-    addSon(result, a)
-    getTok(p)
-    skipCom(p, a)
-    addSon(result, primary(p))
-    return 
-  elif p.tok.xkind == pxAt: 
-    result = newNodeP(nkAddr, p)
-    var a = newIdentNodeP(getIdent($p.tok), p)
-    getTok(p)
-    if p.tok.xkind == pxBracketLe: 
-      result = newNodeP(nkPrefix, p)
-      addSon(result, a)
-      addSon(result, identOrLiteral(p))
-    else: 
-      addSon(result, primary(p))
-    return 
-  result = identOrLiteral(p)
-  while true: 
-    case p.tok.xkind
-    of pxParLe: 
-      var a = result
-      result = newNodeP(nkCall, p)
-      addSon(result, a)
-      exprListAux(p, nkExprEqExpr, pxParRi, pxEquals, result)
-    of pxDot: 
-      var a = result
-      result = newNodeP(nkDotExpr, p)
-      addSon(result, a)
-      getTok(p)               # skip '.'
-      skipCom(p, result)
-      if p.tok.xkind == pxSymbol: 
-        addSon(result, createIdentNodeP(p.tok.ident, p))
-        getTok(p)
-      else: 
-        parMessage(p, errIdentifierExpected, $p.tok)
-    of pxHat: 
-      var a = result
-      result = newNodeP(nkBracketExpr, p)
-      addSon(result, a)
-      getTok(p)
-    of pxBracketLe: 
-      result = bracketExprList(p, result)
-    else: break 
-  
-proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind = 
-  var 
-    nextop: TTokKind
-    v2, node, opNode: PNode
-  v = primary(p) # expand while operators have priorities higher than 'limit'
-  var op = p.tok.xkind
-  var opPred = getPrecedence(op)
-  while (opPred > limit): 
-    node = newNodeP(nkInfix, p)
-    opNode = newIdentNodeP(getIdent($(p.tok)), p) # skip operator:
-    getTok(p)
-    case op
-    of pxPlus: 
-      case p.tok.xkind
-      of pxPer: 
-        getTok(p)
-        eat(p, pxCurlyDirRi)
-        opNode.ident = getIdent("+%")
-      of pxAmp: 
-        getTok(p)
-        eat(p, pxCurlyDirRi)
-        opNode.ident = getIdent("&")
-      else: 
-        discard
-    of pxMinus: 
-      if p.tok.xkind == pxPer: 
-        getTok(p)
-        eat(p, pxCurlyDirRi)
-        opNode.ident = getIdent("-%")
-    of pxEquals: 
-      opNode.ident = getIdent("==")
-    of pxNeq: 
-      opNode.ident = getIdent("!=")
-    else: 
-      discard
-    skipCom(p, opNode)        # read sub-expression with higher priority
-    nextop = lowestExprAux(p, v2, opPred)
-    addSon(node, opNode)
-    addSon(node, v)
-    addSon(node, v2)
-    v = node
-    op = nextop
-    opPred = getPrecedence(nextop)
-  result = op                 # return first untreated operator
-  
-proc fixExpr(n: PNode): PNode = 
-  result = n
-  case n.kind
-  of nkInfix: 
-    if n.sons[1].kind == nkBracket: n.sons[1].kind = nkCurly
-    if n.sons[2].kind == nkBracket: n.sons[2].kind = nkCurly
-    if (n.sons[0].kind == nkIdent): 
-      if (n.sons[0].ident.id == getIdent("+").id): 
-        if (n.sons[1].kind == nkCharLit) and (n.sons[2].kind == nkStrLit) and
-            (n.sons[2].strVal == ""): 
-          result = newStrNode(nkStrLit, chr(int(n.sons[1].intVal)) & "")
-          result.info = n.info
-          return              # do not process sons as they don't exist anymore
-        elif (n.sons[1].kind in {nkCharLit, nkStrLit}) or
-            (n.sons[2].kind in {nkCharLit, nkStrLit}): 
-          n.sons[0].ident = getIdent("&") # fix operator
-  else: 
-    discard
-  if not (n.kind in {nkEmpty..nkNilLit}): 
-    for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i])
-  
-proc parseExpr(p: var TParser): PNode = 
-  var oldcontext = p.context
-  p.context = conExpr
-  if p.tok.xkind == pxCommand: 
-    result = parseCommand(p)
-  else: 
-    discard lowestExprAux(p, result, - 1)
-    result = fixExpr(result)
-  p.context = oldcontext
-
-proc parseExprStmt(p: var TParser): PNode = 
-  var info = parLineInfo(p)
-  var a = parseExpr(p)
-  if p.tok.xkind == pxAsgn: 
-    getTok(p)
-    skipCom(p, a)
-    var b = parseExpr(p)
-    result = newNodeI(nkAsgn, info)
-    addSon(result, a)
-    addSon(result, b)
-  else: 
-    result = a
-  
-proc inImportBlackList(ident: PIdent): bool = 
-  for i in countup(low(ImportBlackList), high(ImportBlackList)): 
-    if ident.id == getIdent(ImportBlackList[i]).id: 
-      return true
-
-proc parseUsesStmt(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkImportStmt, p)
-  getTok(p)                   # skip `import`
-  skipCom(p, result)
-  while true: 
-    case p.tok.xkind
-    of pxEof: break 
-    of pxSymbol: a = newIdentNodeP(p.tok.ident, p)
-    else: 
-      parMessage(p, errIdentifierExpected, $(p.tok))
-      break 
-    getTok(p)                 # skip identifier, string
-    skipCom(p, a)
-    if pfImportBlackList notin p.flags or not inImportBlackList(a.ident): 
-      addSon(result, createIdentNodeP(a.ident, p))
-    if p.tok.xkind == pxComma: 
-      getTok(p)
-      skipCom(p, a)
-    else: 
-      break 
-  if sonsLen(result) == 0: result = ast.emptyNode
-  
-proc parseIncludeDir(p: var TParser): PNode = 
-  result = newNodeP(nkIncludeStmt, p)
-  getTok(p)                   # skip `include`
-  var filename = ""
-  while true: 
-    case p.tok.xkind
-    of pxSymbol, pxDot, pxDotDot, pxSlash: 
-      add(filename, $p.tok)
-      getTok(p)
-    of pxStrLit: 
-      filename = p.tok.literal
-      getTok(p)
-      break 
-    of pxCurlyDirRi: 
-      break 
-    else: 
-      parMessage(p, errIdentifierExpected, $p.tok)
-      break 
-  addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p))
-  if filename == "config.inc": result = ast.emptyNode
-  
-proc definedExprAux(p: var TParser): PNode = 
-  result = newNodeP(nkCall, p)
-  addSon(result, newIdentNodeP(getIdent("defined"), p))
-  expectIdent(p)
-  addSon(result, createIdentNodeP(p.tok.ident, p))
-  getTok(p)
-
-proc isHandledDirective(p: TParser): bool = 
-  if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: 
-    case toLower(p.tok.ident.s)
-    of "else", "endif": result = false
-    else: result = true
-  
-proc parseStmtList(p: var TParser): PNode = 
-  result = newNodeP(nkStmtList, p)
-  while true: 
-    case p.tok.xkind
-    of pxEof: 
-      break 
-    of pxCurlyDirLe, pxStarDirLe: 
-      if not isHandledDirective(p): break 
-    else: 
-      discard
-    addSon(result, parseStmt(p))
-  if sonsLen(result) == 1: result = result.sons[0]
-  
-proc parseIfDirAux(p: var TParser, result: PNode) = 
-  addSon(result.sons[0], parseStmtList(p))
-  if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: 
-    var endMarker = succ(p.tok.xkind)
-    if toLower(p.tok.ident.s) == "else": 
-      var s = newNodeP(nkElse, p)
-      while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p)
-      eat(p, endMarker)
-      addSon(s, parseStmtList(p))
-      addSon(result, s)
-    if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: 
-      endMarker = succ(p.tok.xkind)
-      if toLower(p.tok.ident.s) == "endif": 
-        while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p)
-        eat(p, endMarker)
-      else: 
-        parMessage(p, errXExpected, "{$endif}")
-  else: 
-    parMessage(p, errXExpected, "{$endif}")
-  
-proc parseIfdefDir(p: var TParser, endMarker: TTokKind): PNode = 
-  result = newNodeP(nkWhenStmt, p)
-  addSon(result, newNodeP(nkElifBranch, p))
-  getTok(p)
-  addSon(result.sons[0], definedExprAux(p))
-  eat(p, endMarker)
-  parseIfDirAux(p, result)
-
-proc parseIfndefDir(p: var TParser, endMarker: TTokKind): PNode = 
-  result = newNodeP(nkWhenStmt, p)
-  addSon(result, newNodeP(nkElifBranch, p))
-  getTok(p)
-  var e = newNodeP(nkCall, p)
-  addSon(e, newIdentNodeP(getIdent("not"), p))
-  addSon(e, definedExprAux(p))
-  eat(p, endMarker)
-  addSon(result.sons[0], e)
-  parseIfDirAux(p, result)
-
-proc parseIfDir(p: var TParser, endMarker: TTokKind): PNode = 
-  result = newNodeP(nkWhenStmt, p)
-  addSon(result, newNodeP(nkElifBranch, p))
-  getTok(p)
-  addSon(result.sons[0], parseExpr(p))
-  eat(p, endMarker)
-  parseIfDirAux(p, result)
-
-proc parseDirective(p: var TParser): PNode = 
-  result = ast.emptyNode
-  if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return 
-  var endMarker = succ(p.tok.xkind)
-  if p.tok.ident != nil: 
-    case toLower(p.tok.ident.s)
-    of "include": 
-      result = parseIncludeDir(p)
-      eat(p, endMarker)
-    of "if": result = parseIfDir(p, endMarker)
-    of "ifdef": result = parseIfdefDir(p, endMarker)
-    of "ifndef": result = parseIfndefDir(p, endMarker)
-    else: 
-      # skip unknown compiler directive
-      while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p)
-      eat(p, endMarker)
-  else: 
-    eat(p, endMarker)
-  
-proc parseRaise(p: var TParser): PNode = 
-  result = newNodeP(nkRaiseStmt, p)
-  getTok(p)
-  skipCom(p, result)
-  if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p))
-  else: addSon(result, ast.emptyNode)
-  
-proc parseIf(p: var TParser): PNode = 
-  result = newNodeP(nkIfStmt, p)
-  while true: 
-    getTok(p)                 # skip ``if``
-    var branch = newNodeP(nkElifBranch, p)
-    skipCom(p, branch)
-    addSon(branch, parseExpr(p))
-    eat(p, pxThen)
-    skipCom(p, branch)
-    addSon(branch, parseStmt(p))
-    skipCom(p, branch)
-    addSon(result, branch)
-    if p.tok.xkind == pxElse: 
-      getTok(p)
-      if p.tok.xkind != pxIf: 
-        # ordinary else part:
-        branch = newNodeP(nkElse, p)
-        skipCom(p, result)    # BUGFIX
-        addSon(branch, parseStmt(p))
-        addSon(result, branch)
-        break 
-    else: 
-      break 
-  
-proc parseWhile(p: var TParser): PNode = 
-  result = newNodeP(nkWhileStmt, p)
-  getTok(p)
-  skipCom(p, result)
-  addSon(result, parseExpr(p))
-  eat(p, pxDo)
-  skipCom(p, result)
-  addSon(result, parseStmt(p))
-
-proc parseRepeat(p: var TParser): PNode = 
-  result = newNodeP(nkWhileStmt, p)
-  getTok(p)
-  skipCom(p, result)
-  addSon(result, newIdentNodeP(getIdent("true"), p))
-  var s = newNodeP(nkStmtList, p)
-  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, ast.emptyNode)
-  addSon(b, parseExpr(p))
-  skipCom(p, a)
-  addSon(b, c)
-  addSon(a, b)
-  if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id: 
-    discard
-  else: 
-    addSon(s, a)
-  addSon(result, s)
-
-proc parseCase(p: var TParser): PNode = 
-  var b: PNode
-  result = newNodeP(nkCaseStmt, p)
-  getTok(p)
-  addSon(result, parseExpr(p))
-  eat(p, pxOf)
-  skipCom(p, result)
-  while (p.tok.xkind != pxEnd) and (p.tok.xkind != pxEof): 
-    if p.tok.xkind == pxElse: 
-      b = newNodeP(nkElse, p)
-      getTok(p)
-    else: 
-      b = newNodeP(nkOfBranch, p)
-      while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): 
-        addSon(b, rangeExpr(p))
-        opt(p, pxComma)
-        skipCom(p, b)
-      eat(p, pxColon)
-    skipCom(p, b)
-    addSon(b, parseStmt(p))
-    addSon(result, b)
-    if b.kind == nkElse: break 
-  eat(p, pxEnd)
-
-proc parseTry(p: var TParser): PNode = 
-  result = newNodeP(nkTryStmt, p)
-  getTok(p)
-  skipCom(p, result)
-  var b = newNodeP(nkStmtList, p)
-  while not (p.tok.xkind in {pxFinally, pxExcept, pxEof, pxEnd}): 
-    addSon(b, parseStmt(p))
-  addSon(result, b)
-  if p.tok.xkind == pxExcept: 
-    getTok(p)
-    while p.tok.ident.id == getIdent("on").id: 
-      b = newNodeP(nkExceptBranch, p)
-      getTok(p)
-      var e = qualifiedIdent(p)
-      if p.tok.xkind == pxColon: 
-        getTok(p)
-        e = qualifiedIdent(p)
-      addSon(b, e)
-      eat(p, pxDo)
-      addSon(b, parseStmt(p))
-      addSon(result, b)
-      if p.tok.xkind == pxCommand: discard parseCommand(p)
-    if p.tok.xkind == pxElse: 
-      b = newNodeP(nkExceptBranch, p)
-      getTok(p)
-      addSon(b, parseStmt(p))
-      addSon(result, b)
-  if p.tok.xkind == pxFinally: 
-    b = newNodeP(nkFinally, p)
-    getTok(p)
-    var e = newNodeP(nkStmtList, p)
-    while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): 
-      addSon(e, parseStmt(p))
-    if sonsLen(e) == 0: addSon(e, newNodeP(nkNilLit, p))
-    addSon(result, e)
-  eat(p, pxEnd)
-
-proc parseFor(p: var TParser): PNode = 
-  result = newNodeP(nkForStmt, p)
-  getTok(p)
-  skipCom(p, result)
-  expectIdent(p)
-  addSon(result, createIdentNodeP(p.tok.ident, p))
-  getTok(p)
-  eat(p, pxAsgn)
-  var a = parseExpr(p)
-  var b = ast.emptyNode
-  var c = newNodeP(nkCall, p)
-  if p.tok.xkind == pxTo: 
-    addSon(c, newIdentNodeP(getIdent("countup"), p))
-    getTok(p)
-    b = parseExpr(p)
-  elif p.tok.xkind == pxDownto: 
-    addSon(c, newIdentNodeP(getIdent("countdown"), p))
-    getTok(p)
-    b = parseExpr(p)
-  else: 
-    parMessage(p, errTokenExpected, tokKindToStr(pxTo))
-  addSon(c, a)
-  addSon(c, b)
-  eat(p, pxDo)
-  skipCom(p, result)
-  addSon(result, c)
-  addSon(result, parseStmt(p))
-
-proc parseParam(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkIdentDefs, p)
-  var v = ast.emptyNode
-  case p.tok.xkind
-  of pxConst: 
-    getTok(p)
-  of pxVar: 
-    getTok(p)
-    v = newNodeP(nkVarTy, p)
-  of pxOut: 
-    getTok(p)
-    v = newNodeP(nkVarTy, p)
-  else: 
-    discard
-  while true: 
-    case p.tok.xkind
-    of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
-    of pxColon, pxEof, pxParRi, pxEquals: break 
-    else: 
-      parMessage(p, errIdentifierExpected, $p.tok)
-      return 
-    getTok(p)                 # skip identifier
-    skipCom(p, a)
-    if p.tok.xkind == pxComma: 
-      getTok(p)
-      skipCom(p, a)
-    addSon(result, a)
-  if p.tok.xkind == pxColon: 
-    getTok(p)
-    skipCom(p, result)
-    if v.kind != nkEmpty: addSon(v, parseTypeDesc(p))
-    else: v = parseTypeDesc(p)
-    addSon(result, v)
-  else: 
-    addSon(result, ast.emptyNode)
-    if p.tok.xkind != pxEquals: 
-      parMessage(p, errColonOrEqualsExpected, $p.tok)
-  if p.tok.xkind == pxEquals: 
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, parseExpr(p))
-  else: 
-    addSon(result, ast.emptyNode)
-  
-proc parseParamList(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkFormalParams, p)
-  addSon(result, ast.emptyNode)         # return type
-  if p.tok.xkind == pxParLe: 
-    p.inParamList = true
-    getTok(p)
-    skipCom(p, result)
-    while true: 
-      case p.tok.xkind
-      of pxSymbol, pxConst, pxVar, pxOut: 
-        a = parseParam(p)
-      of pxParRi: 
-        getTok(p)
-        break 
-      else: 
-        parMessage(p, errTokenExpected, ")")
-        break 
-      skipCom(p, a)
-      if p.tok.xkind == pxSemicolon: 
-        getTok(p)
-        skipCom(p, a)
-      addSon(result, a)
-    p.inParamList = false
-  if p.tok.xkind == pxColon: 
-    getTok(p)
-    skipCom(p, result)
-    result.sons[0] = parseTypeDesc(p)
-
-proc parseCallingConvention(p: var TParser): PNode = 
-  result = ast.emptyNode
-  if p.tok.xkind == pxSymbol: 
-    case toLower(p.tok.ident.s)
-    of "stdcall", "cdecl", "safecall", "syscall", "inline", "fastcall": 
-      result = newNodeP(nkPragma, p)
-      addSon(result, newIdentNodeP(p.tok.ident, p))
-      getTok(p)
-      opt(p, pxSemicolon)
-    of "register": 
-      result = newNodeP(nkPragma, p)
-      addSon(result, newIdentNodeP(getIdent("fastcall"), p))
-      getTok(p)
-      opt(p, pxSemicolon)
-    else: 
-      discard
-
-proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode = 
-  var e: PNode
-  result = parseCallingConvention(p)
-  noBody = false
-  while p.tok.xkind == pxSymbol: 
-    case toLower(p.tok.ident.s)
-    of "assembler", "overload", "far": 
-      getTok(p)
-      opt(p, pxSemicolon)
-    of "forward": 
-      noBody = true
-      getTok(p)
-      opt(p, pxSemicolon)
-    of "importc": 
-      # This is a fake for platform module. There is no ``importc``
-      # directive in Pascal.
-      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
-      addSon(result, newIdentNodeP(getIdent("importc"), p))
-      noBody = true
-      getTok(p)
-      opt(p, pxSemicolon)
-    of "noconv": 
-      # This is a fake for platform module. There is no ``noconv``
-      # directive in Pascal.
-      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
-      addSon(result, newIdentNodeP(getIdent("noconv"), p))
-      noBody = true
-      getTok(p)
-      opt(p, pxSemicolon)
-    of "procvar": 
-      # This is a fake for the Nimrod compiler. There is no ``procvar``
-      # directive in Pascal.
-      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
-      addSon(result, newIdentNodeP(getIdent("procvar"), p))
-      getTok(p)
-      opt(p, pxSemicolon)
-    of "varargs": 
-      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
-      addSon(result, newIdentNodeP(getIdent("varargs"), p))
-      getTok(p)
-      opt(p, pxSemicolon)
-    of "external": 
-      if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
-      getTok(p)
-      noBody = true
-      e = newNodeP(nkExprColonExpr, p)
-      addSon(e, newIdentNodeP(getIdent("dynlib"), p))
-      addSon(e, parseExpr(p))
-      addSon(result, e)
-      opt(p, pxSemicolon)
-      if (p.tok.xkind == pxSymbol) and
-          (p.tok.ident.id == getIdent("name").id): 
-        e = newNodeP(nkExprColonExpr, p)
-        getTok(p)
-        addSon(e, newIdentNodeP(getIdent("importc"), p))
-        addSon(e, parseExpr(p))
-        addSon(result, e)
-      else: 
-        addSon(result, newIdentNodeP(getIdent("importc"), p))
-      opt(p, pxSemicolon)
-    else: 
-      e = parseCallingConvention(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 = 
-  result = newNodeP(nkProcTy, p)
-  getTok(p)
-  skipCom(p, result)
-  addSon(result, parseParamList(p))
-  opt(p, pxSemicolon)
-  addSon(result, parseCallingConvention(p))
-  skipCom(p, result)
-
-proc parseEnum(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkEnumTy, p)
-  getTok(p)
-  skipCom(p, result)
-  addSon(result, ast.emptyNode) # it does not inherit from any enumeration
-  while true: 
-    case p.tok.xkind
-    of pxEof, pxParRi: break 
-    of pxSymbol: a = newIdentNodeP(p.tok.ident, p)
-    else: 
-      parMessage(p, errIdentifierExpected, $(p.tok))
-      break 
-    getTok(p)                 # skip identifier
-    skipCom(p, a)
-    if (p.tok.xkind == pxEquals) or (p.tok.xkind == pxAsgn): 
-      getTok(p)
-      skipCom(p, a)
-      var b = a
-      a = newNodeP(nkEnumFieldDef, p)
-      addSon(a, b)
-      addSon(a, parseExpr(p))
-    if p.tok.xkind == pxComma: 
-      getTok(p)
-      skipCom(p, a)
-    addSon(result, a)
-  eat(p, pxParRi)
-
-proc identVis(p: var TParser): PNode = 
-  # identifier with visability
-  var a = createIdentNodeP(p.tok.ident, p)
-  if p.section == seInterface: 
-    result = newNodeP(nkPostfix, p)
-    addSon(result, newIdentNodeP(getIdent("*"), p))
-    addSon(result, a)
-  else: 
-    result = a
-  getTok(p)
-
-type 
-  TSymbolParser = proc (p: var TParser): PNode {.nimcall.}
-
-proc rawIdent(p: var TParser): PNode = 
-  result = createIdentNodeP(p.tok.ident, p)
-  getTok(p)
-
-proc parseIdentColonEquals(p: var TParser, 
-                           identParser: TSymbolParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkIdentDefs, p)
-  while true: 
-    case p.tok.xkind
-    of pxSymbol: a = identParser(p)
-    of pxColon, pxEof, pxParRi, pxEquals: break 
-    else: 
-      parMessage(p, errIdentifierExpected, $(p.tok))
-      return 
-    skipCom(p, a)
-    if p.tok.xkind == pxComma: 
-      getTok(p)
-      skipCom(p, a)
-    addSon(result, a)
-  if p.tok.xkind == pxColon: 
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, parseTypeDesc(p))
-  else: 
-    addSon(result, ast.emptyNode)
-    if p.tok.xkind != pxEquals: 
-      parMessage(p, errColonOrEqualsExpected, $(p.tok))
-  if p.tok.xkind == pxEquals: 
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, parseExpr(p))
-  else: 
-    addSon(result, ast.emptyNode)
-  if p.tok.xkind == pxSemicolon: 
-    getTok(p)
-    skipCom(p, result)
-
-proc parseRecordCase(p: var TParser): PNode = 
-  var b, c: PNode
-  result = newNodeP(nkRecCase, p)
-  getTok(p)
-  var a = newNodeP(nkIdentDefs, p)
-  addSon(a, rawIdent(p))
-  eat(p, pxColon)
-  addSon(a, parseTypeDesc(p))
-  addSon(a, ast.emptyNode)
-  addSon(result, a)
-  eat(p, pxOf)
-  skipCom(p, result)
-  while true: 
-    case p.tok.xkind
-    of pxEof, pxEnd: 
-      break 
-    of pxElse: 
-      b = newNodeP(nkElse, p)
-      getTok(p)
-    else: 
-      b = newNodeP(nkOfBranch, p)
-      while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): 
-        addSon(b, rangeExpr(p))
-        opt(p, pxComma)
-        skipCom(p, b)
-      eat(p, pxColon)
-    skipCom(p, b)
-    c = newNodeP(nkRecList, p)
-    eat(p, pxParLe)
-    while (p.tok.xkind != pxParRi) and (p.tok.xkind != pxEof): 
-      addSon(c, parseIdentColonEquals(p, rawIdent))
-      opt(p, pxSemicolon)
-      skipCom(p, lastSon(c))
-    eat(p, pxParRi)
-    opt(p, pxSemicolon)
-    if sonsLen(c) > 0: skipCom(p, lastSon(c))
-    else: addSon(c, newNodeP(nkNilLit, p))
-    addSon(b, c)
-    addSon(result, b)
-    if b.kind == nkElse: break 
-  
-proc parseRecordPart(p: var TParser): PNode = 
-  result = ast.emptyNode
-  while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): 
-    if result.kind == nkEmpty: result = newNodeP(nkRecList, p)
-    case p.tok.xkind
-    of pxSymbol: 
-      addSon(result, parseIdentColonEquals(p, rawIdent))
-      opt(p, pxSemicolon)
-      skipCom(p, lastSon(result))
-    of pxCase: 
-      addSon(result, parseRecordCase(p))
-    of pxComment: 
-      skipCom(p, lastSon(result))
-    else: 
-      parMessage(p, errIdentifierExpected, $p.tok)
-      break
-
-proc exSymbol(n: var PNode) = 
-  case n.kind
-  of nkPostfix: 
-    discard
-  of nkPragmaExpr: 
-    exSymbol(n.sons[0])
-  of nkIdent, nkAccQuoted: 
-    var a = newNodeI(nkPostFix, n.info)
-    addSon(a, newIdentNode(getIdent("*"), n.info))
-    addSon(a, n)
-    n = a
-  else: internalError(n.info, "exSymbol(): " & $n.kind)
-  
-proc fixRecordDef(n: var PNode) = 
-  case n.kind
-  of nkRecCase: 
-    fixRecordDef(n.sons[0])
-    for i in countup(1, sonsLen(n) - 1): 
-      var length = sonsLen(n.sons[i])
-      fixRecordDef(n.sons[i].sons[length - 1])
-  of nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch, nkObjectTy: 
-    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, nkEmpty: discard
-  else: internalError(n.info, "fixRecordDef(): " & $n.kind)
-  
-proc addPragmaToIdent(ident: var PNode, pragma: PNode) = 
-  var pragmasNode: PNode
-  if ident.kind != nkPragmaExpr: 
-    pragmasNode = newNodeI(nkPragma, ident.info)
-    var e = newNodeI(nkPragmaExpr, ident.info)
-    addSon(e, ident)
-    addSon(e, pragmasNode)
-    ident = e
-  else: 
-    pragmasNode = ident.sons[1]
-    if pragmasNode.kind != nkPragma: 
-      internalError(ident.info, "addPragmaToIdent")
-  addSon(pragmasNode, pragma)
-
-proc parseRecordBody(p: var TParser, result, definition: PNode) = 
-  skipCom(p, result)
-  var a = parseRecordPart(p)
-  if result.kind != nkTupleTy: fixRecordDef(a)
-  addSon(result, a)
-  eat(p, pxEnd)
-  case p.tok.xkind
-  of pxSymbol: 
-    if p.tok.ident.id == getIdent("acyclic").id: 
-      if definition != nil: 
-        addPragmaToIdent(definition.sons[0], newIdentNodeP(p.tok.ident, p))
-      else: 
-        internalError(result.info, "anonymous record is not supported")
-      getTok(p)
-    else: 
-      internalError(result.info, "parseRecordBody")
-  of pxCommand: 
-    if definition != nil: addPragmaToIdent(definition.sons[0], parseCommand(p))
-    else: internalError(result.info, "anonymous record is not supported")
-  else: 
-    discard
-  opt(p, pxSemicolon)
-  skipCom(p, result)
-
-proc parseRecordOrObject(p: var TParser, kind: TNodeKind, 
-                         definition: PNode): PNode = 
-  result = newNodeP(kind, p)
-  getTok(p)
-  addSon(result, ast.emptyNode)
-  if p.tok.xkind == pxParLe: 
-    var a = newNodeP(nkOfInherit, p)
-    getTok(p)
-    addSon(a, parseTypeDesc(p))
-    addSon(result, a)
-    eat(p, pxParRi)
-  else: 
-    addSon(result, ast.emptyNode)
-  parseRecordBody(p, result, definition)
-
-proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode = 
-  var oldcontext = p.context
-  p.context = conTypeDesc
-  if p.tok.xkind == pxPacked: getTok(p)
-  case p.tok.xkind
-  of pxCommand: 
-    result = parseCommand(p, definition)
-  of pxProcedure, pxFunction: 
-    result = parseRoutineType(p)
-  of pxRecord: 
-    getTok(p)
-    if p.tok.xkind == pxCommand: 
-      result = parseCommand(p)
-      if result.kind != nkTupleTy: internalError(result.info, "parseTypeDesc")
-      parseRecordBody(p, result, definition)
-      var a = lastSon(result)     # embed nkRecList directly into nkTupleTy
-      for i in countup(0, sonsLen(a) - 1): 
-        if i == 0: result.sons[sonsLen(result) - 1] = a.sons[0]
-        else: addSon(result, a.sons[i])
-    else: 
-      result = newNodeP(nkObjectTy, p)
-      addSon(result, ast.emptyNode)
-      addSon(result, ast.emptyNode)
-      parseRecordBody(p, result, definition)
-      if definition != nil: 
-        addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p))
-      else: 
-        internalError(result.info, "anonymous record is not supported")
-  of pxObject: result = parseRecordOrObject(p, nkObjectTy, definition)
-  of pxParLe: result = parseEnum(p)
-  of pxArray: 
-    result = newNodeP(nkBracketExpr, p)
-    getTok(p)
-    if p.tok.xkind == pxBracketLe: 
-      addSon(result, newIdentNodeP(getIdent("array"), p))
-      getTok(p)
-      addSon(result, rangeExpr(p))
-      eat(p, pxBracketRi)
-    else: 
-      if p.inParamList: addSon(result, newIdentNodeP(getIdent("openarray"), p))
-      else: addSon(result, newIdentNodeP(getIdent("seq"), p))
-    eat(p, pxOf)
-    addSon(result, parseTypeDesc(p))
-  of pxSet: 
-    result = newNodeP(nkBracketExpr, p)
-    getTok(p)
-    eat(p, pxOf)
-    addSon(result, newIdentNodeP(getIdent("set"), p))
-    addSon(result, parseTypeDesc(p))
-  of pxHat: 
-    getTok(p)
-    if p.tok.xkind == pxCommand: result = parseCommand(p)
-    elif pfRefs in p.flags: result = newNodeP(nkRefTy, p)
-    else: result = newNodeP(nkPtrTy, p)
-    addSon(result, parseTypeDesc(p))
-  of pxType: 
-    getTok(p)
-    result = parseTypeDesc(p)
-  else: 
-    var a = primary(p)
-    if p.tok.xkind == pxDotDot: 
-      result = newNodeP(nkBracketExpr, p)
-      var r = newNodeP(nkRange, p)
-      addSon(result, newIdentNodeP(getIdent("range"), p))
-      getTok(p)
-      addSon(r, a)
-      addSon(r, parseExpr(p))
-      addSon(result, r)
-    else: 
-      result = a
-  p.context = oldcontext
-
-proc parseTypeDef(p: var TParser): PNode = 
-  result = newNodeP(nkTypeDef, p)
-  addSon(result, identVis(p))
-  addSon(result, ast.emptyNode)         # generic params
-  if p.tok.xkind == pxEquals: 
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, parseTypeDesc(p, result))
-  else: 
-    addSon(result, ast.emptyNode)
-  if p.tok.xkind == pxSemicolon: 
-    getTok(p)
-    skipCom(p, result)
-
-proc parseTypeSection(p: var TParser): PNode = 
-  result = newNodeP(nkTypeSection, p)
-  getTok(p)
-  skipCom(p, result)
-  while p.tok.xkind == pxSymbol: 
-    addSon(result, parseTypeDef(p))
-
-proc parseConstant(p: var TParser): PNode = 
-  result = newNodeP(nkConstDef, p)
-  addSon(result, identVis(p))
-  if p.tok.xkind == pxColon: 
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, parseTypeDesc(p))
-  else: 
-    addSon(result, ast.emptyNode)
-    if p.tok.xkind != pxEquals: 
-      parMessage(p, errColonOrEqualsExpected, $(p.tok))
-  if p.tok.xkind == pxEquals: 
-    getTok(p)
-    skipCom(p, result)
-    addSon(result, parseExpr(p))
-  else: 
-    addSon(result, ast.emptyNode)
-  if p.tok.xkind == pxSemicolon: 
-    getTok(p)
-    skipCom(p, result)
-
-proc parseConstSection(p: var TParser): PNode = 
-  result = newNodeP(nkConstSection, p)
-  getTok(p)
-  skipCom(p, result)
-  while p.tok.xkind == pxSymbol: 
-    addSon(result, parseConstant(p))
-
-proc parseVar(p: var TParser): PNode = 
-  result = newNodeP(nkVarSection, p)
-  getTok(p)
-  skipCom(p, result)
-  while p.tok.xkind == pxSymbol:
-    addSon(result, parseIdentColonEquals(p, identVis))
-  p.lastVarSection = result
-
-proc parseRoutine(p: var TParser): PNode = 
-  var noBody: bool
-  result = newNodeP(nkProcDef, p)
-  getTok(p)
-  skipCom(p, result)
-  expectIdent(p)
-  addSon(result, identVis(p))
-  # patterns, generic parameters:
-  addSon(result, ast.emptyNode)
-  addSon(result, ast.emptyNode)   
-  addSon(result, parseParamList(p))
-  opt(p, pxSemicolon)
-  addSon(result, parseRoutineSpecifiers(p, noBody))
-  addSon(result, ast.emptyNode)
-  if (p.section == seInterface) or noBody: 
-    addSon(result, ast.emptyNode)
-  else: 
-    var stmts = newNodeP(nkStmtList, p)
-    while true: 
-      case p.tok.xkind
-      of pxVar: addSon(stmts, parseVar(p))
-      of pxConst: addSon(stmts, parseConstSection(p))
-      of pxType: addSon(stmts, parseTypeSection(p))
-      of pxComment: skipCom(p, result)
-      of pxBegin: break 
-      else: 
-        parMessage(p, errTokenExpected, "begin")
-        break 
-    var a = parseStmt(p)
-    for i in countup(0, sonsLen(a) - 1): addSon(stmts, a.sons[i])
-    addSon(result, stmts)
-
-proc fixExit(p: var TParser, n: PNode): bool = 
-  if (p.tok.ident.id == getIdent("exit").id): 
-    var length = sonsLen(n)
-    if (length <= 0): return 
-    var a = n.sons[length-1]
-    if (a.kind == nkAsgn) and (a.sons[0].kind == nkIdent) and
-        (a.sons[0].ident.id == getIdent("result").id): 
-      delSon(a, 0)
-      a.kind = nkReturnStmt
-      result = true
-      getTok(p)
-      opt(p, pxSemicolon)
-      skipCom(p, a)
-
-proc fixVarSection(p: var TParser, counter: PNode) = 
-  if p.lastVarSection == nil: return 
-  assert(counter.kind == nkIdent)
-  for i in countup(0, sonsLen(p.lastVarSection) - 1): 
-    var v = p.lastVarSection.sons[i]
-    for j in countup(0, sonsLen(v) - 3): 
-      if v.sons[j].ident.id == counter.ident.id: 
-        delSon(v, j)
-        if sonsLen(v) <= 2: 
-          delSon(p.lastVarSection, i)
-        return 
-
-proc exSymbols(n: PNode) = 
-  case n.kind
-  of nkEmpty..nkNilLit: discard
-  of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos])
-  of nkWhenStmt, nkStmtList: 
-    for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i])
-  of nkVarSection, nkConstSection: 
-    for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0])
-  of nkTypeSection: 
-    for i in countup(0, sonsLen(n) - 1): 
-      exSymbol(n.sons[i].sons[0])
-      if n.sons[i].sons[2].kind == nkObjectTy: 
-        fixRecordDef(n.sons[i].sons[2])
-  else: discard
-
-proc parseBegin(p: var TParser, result: PNode) = 
-  getTok(p)
-  while true: 
-    case p.tok.xkind
-    of pxComment: addSon(result, parseStmt(p))
-    of pxSymbol: 
-      if not fixExit(p, result): addSon(result, parseStmt(p))
-    of pxEnd: 
-      getTok(p)
-      break 
-    of pxSemicolon: getTok(p)
-    of pxEof: parMessage(p, errExprExpected)
-    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 = ast.emptyNode
-  case p.tok.xkind
-  of pxBegin: 
-    result = newNodeP(nkStmtList, p)
-    parseBegin(p, result)
-  of pxCommand: result = parseCommand(p)
-  of pxCurlyDirLe, pxStarDirLe: 
-    if isHandledDirective(p): result = parseDirective(p)
-  of pxIf: result = parseIf(p)
-  of pxWhile: result = parseWhile(p)
-  of pxRepeat: result = parseRepeat(p)
-  of pxCase: result = parseCase(p)
-  of pxTry: result = parseTry(p)
-  of pxProcedure, pxFunction: result = parseRoutine(p)
-  of pxType: result = parseTypeSection(p)
-  of pxConst: result = parseConstSection(p)
-  of pxVar: result = parseVar(p)
-  of pxFor: 
-    result = parseFor(p)
-    fixVarSection(p, result.sons[0])
-  of pxRaise: result = parseRaise(p)
-  of pxUses: result = parseUsesStmt(p)
-  of pxProgram, pxUnit, pxLibrary: 
-    # skip the pointless header
-    while not (p.tok.xkind in {pxSemicolon, pxEof}): getTok(p)
-    getTok(p)
-  of pxInitialization: getTok(p) # just skip the token
-  of pxImplementation: 
-    p.section = seImplementation
-    result = newNodeP(nkCommentStmt, p)
-    result.comment = "# implementation"
-    getTok(p)
-  of pxInterface: 
-    p.section = seInterface
-    getTok(p)
-  of pxComment: 
-    result = newNodeP(nkCommentStmt, p)
-    skipCom(p, result)
-  of pxSemicolon: getTok(p)
-  of pxSymbol: 
-    if p.tok.ident.id == getIdent("break").id: 
-      result = newNodeP(nkBreakStmt, p)
-      getTok(p)
-      skipCom(p, result)
-      addSon(result, ast.emptyNode)
-    elif p.tok.ident.id == getIdent("continue").id: 
-      result = newNodeP(nkContinueStmt, p)
-      getTok(p)
-      skipCom(p, result)
-      addSon(result, ast.emptyNode)
-    elif p.tok.ident.id == getIdent("exit").id: 
-      result = newNodeP(nkReturnStmt, p)
-      getTok(p)
-      skipCom(p, result)
-      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.kind != nkEmpty: skipCom(p, result)
-  p.context = oldcontext
-
-proc parseUnit(p: var TParser): PNode = 
-  result = newNodeP(nkStmtList, p)
-  getTok(p)                   # read first token
-  while true: 
-    case p.tok.xkind
-    of pxEof, pxEnd: break 
-    of pxBegin: parseBegin(p, result)
-    of pxCurlyDirLe, pxStarDirLe: 
-      if isHandledDirective(p): addSon(result, parseDirective(p))
-      else: parMessage(p, errXNotAllowedHere, p.tok.ident.s)
-    else: addSon(result, parseStmt(p))
-  opt(p, pxEnd)
-  opt(p, pxDot)
-  if p.tok.xkind != pxEof: 
-    addSon(result, parseStmt(p)) # comments after final 'end.'
-