summary refs log tree commit diff stats
path: root/rod/rodread.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/rodread.nim')
-rwxr-xr-xrod/rodread.nim856
1 files changed, 0 insertions, 856 deletions
diff --git a/rod/rodread.nim b/rod/rodread.nim
deleted file mode 100755
index 36cb29185..000000000
--- a/rod/rodread.nim
+++ /dev/null
@@ -1,856 +0,0 @@
-#
-#
-#           The Nimrod Compiler
-#        (c) Copyright 2011 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This module is responsible for loading of rod files.
-#
-#  Reading and writing binary files are really hard to debug. Therefore we use
-#  a special text format. ROD-files are more efficient to process because
-#  symbols are only loaded on demand.
-#  It consists of:
-#
-#  - a header:
-#    NIM:$fileversion\n
-#  - the module's id (even if the module changed, its ID will not!):
-#    ID:Ax3\n
-#  - CRC value of this module:
-#    CRC:CRC-val\n
-#  - a section containing the compiler options and defines this
-#    module has been compiled with:
-#    OPTIONS:options\n
-#    DEFINES:defines\n
-#  - FILES(
-#    myfile.inc
-#    lib/mymodA
-#    )
-#  - a include file dependency section:
-#    INCLUDES(
-#    <fileidx> <CRC of myfile.inc>\n # fileidx is the LINE in the file section!
-#    )
-#  - a module dependency section:
-#    DEPS: <fileidx> <fileidx>\n
-#  - an interface section:
-#    INTERF(
-#    identifier1 id\n # id is the symbol's id
-#    identifier2 id\n
-#    )
-#  - a compiler proc section:
-#    COMPILERPROCS(
-#    identifier1 id\n # id is the symbol's id    
-#    )
-#  - an index consisting of (ID, linenumber)-pairs:
-#    INDEX(
-#    id-diff idx-diff\n
-#    id-diff idx-diff\n
-#    )
-#  - an import index consisting of (ID, moduleID)-pairs:
-#    IMPORTS(
-#    id-diff moduleID-diff\n
-#    id-diff moduleID-diff\n
-#    )
-#  - a list of all exported type converters because they are needed for correct
-#    semantic checking:
-#    CONVERTERS:id id\n   # position of the symbol in the DATA section
-#  - an AST section that contains the module's AST:
-#    INIT(
-#    idx\n  # position of the node in the DATA section
-#    idx\n
-#    )
-#  - a data section, where each type, symbol or AST is stored.
-#    DATA(
-#    type
-#    (node)
-#    sym
-#    )
-#
-#  We now also do index compression, because an index always needs to be read.
-#
-
-import 
-  os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms, 
-  ropes, idents, crc
-
-type 
-  TReasonForRecompile* = enum 
-    rrEmpty,                  # used by moddeps module
-    rrNone,                   # no need to recompile
-    rrRodDoesNotExist,        # rod file does not exist
-    rrRodInvalid,             # rod file is invalid
-    rrCrcChange,              # file has been edited since last recompilation
-    rrDefines,                # defines have changed
-    rrOptions,                # options have changed
-    rrInclDeps,               # an include has changed
-    rrModDeps                 # a module this module depends on has been changed
-
-const 
-  reasonToFrmt*: array[TReasonForRecompile, string] = ["", 
-    "no need to recompile: $1", "symbol file for $1 does not exist", 
-    "symbol file for $1 has the wrong version", 
-    "file edited since last compilation: $1", 
-    "list of conditional symbols changed for: $1", 
-    "list of options changed for: $1", "an include file edited: $1", 
-    "a module $1 depends on has changed"]
-
-type 
-  TIndex*{.final.} = object   # an index with compression
-    lastIdxKey*, lastIdxVal*: int
-    tab*: TIITable
-    r*: PRope                 # writers use this
-    offset*: int              # readers use this
-  
-  TRodReader* = object of TObject
-    pos*: int                 # position; used for parsing
-    s*: string                # the whole file in memory
-    options*: TOptions
-    reason*: TReasonForRecompile
-    modDeps*: TStringSeq
-    files*: TStringSeq
-    dataIdx*: int             # offset of start of data section
-    convertersIdx*: int       # offset of start of converters section
-    initIdx*, interfIdx*, compilerProcsIdx*, cgenIdx*: int
-    filename*: string
-    index*, imports*: TIndex
-    readerIndex*: int
-    line*: int                # only used for debugging, but is always in the code
-    moduleID*: int
-    syms*: TIdTable           # already processed symbols
-  
-  PRodReader* = ref TRodReader
-
-const 
-  FileVersion* = "1012"       # modify this if the rod-format changes!
-
-var rodCompilerprocs*: TStrTable
-
-proc handleSymbolFile*(module: PSym, filename: string): PRodReader
-  # global because this is needed by magicsys
-proc GetCRC*(filename: string): TCrc32
-proc loadInitSection*(r: PRodReader): PNode
-proc loadStub*(s: PSym)
-proc encodeInt*(x: BiggestInt): PRope
-proc encode*(s: string): PRope
-# implementation
-
-var gTypeTable: TIdTable
-
-proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym
-  # `info` is only used for debugging purposes
-proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType
-proc decode(r: PRodReader): string
-proc decodeInt(r: PRodReader): int
-proc decodeBInt(r: PRodReader): biggestInt
-
-proc encode(s: string): PRope = 
-  var res = ""
-  for i in countup(0, len(s) - 1): 
-    case s[i]
-    of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(res, s[i])
-    else: add(res, '\\' & toHex(ord(s[i]), 2))
-  result = toRope(res)
-
-proc encodeIntAux(str: var string, x: BiggestInt) = 
-  const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
-  var d: char
-  var v = x
-  var rem: biggestInt = v mod 190
-  if (rem < 0): 
-    add(str, '-')
-    v = - (v div 190)
-    rem = - rem
-  else: 
-    v = v div 190
-  var idx = int(rem)
-  if idx < 62: d = chars[idx + 0]
-  else: d = chr(idx - 62 + 128)
-  if (v != 0): encodeIntAux(str, v)
-  add(str, d)
-
-proc encodeInt(x: BiggestInt): PRope = 
-  var res = ""
-  encodeIntAux(res, x)
-  result = toRope(res)
-
-proc decodeLineInfo(r: PRodReader, info: var TLineInfo) = 
-  if r.s[r.pos] == '?': 
-    inc(r.pos)
-    if r.s[r.pos] == ',': info.col = int16(- 1)
-    else: info.col = int16(decodeInt(r))
-    if r.s[r.pos] == ',': 
-      inc(r.pos)
-      if r.s[r.pos] == ',': info.line = int16(- 1)
-      else: info.line = int16(decodeInt(r))
-      if r.s[r.pos] == ',': 
-        inc(r.pos)
-        info = newLineInfo(r.files[decodeInt(r)], info.line, info.col)
-
-proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode = 
-  result = nil
-  if r.s[r.pos] == '(': 
-    inc(r.pos)
-    if r.s[r.pos] == ')': 
-      inc(r.pos)
-      return                  # nil node
-    result = newNodeI(TNodeKind(decodeInt(r)), fInfo)
-    decodeLineInfo(r, result.info)
-    if r.s[r.pos] == '$': 
-      inc(r.pos)
-      result.flags = cast[TNodeFlags](int32(decodeInt(r)))
-    if r.s[r.pos] == '^': 
-      inc(r.pos)
-      var id = decodeInt(r)
-      result.typ = rrGetType(r, id, result.info)
-    case result.kind
-    of nkCharLit..nkInt64Lit: 
-      if r.s[r.pos] == '!': 
-        inc(r.pos)
-        result.intVal = decodeBInt(r)
-    of nkFloatLit..nkFloat64Lit: 
-      if r.s[r.pos] == '!': 
-        inc(r.pos)
-        var fl = decode(r)
-        result.floatVal = parseFloat(fl)
-    of nkStrLit..nkTripleStrLit: 
-      if r.s[r.pos] == '!': 
-        inc(r.pos)
-        result.strVal = decode(r)
-      else: 
-        result.strVal = ""    # BUGFIX
-    of nkIdent: 
-      if r.s[r.pos] == '!': 
-        inc(r.pos)
-        var fl = decode(r)
-        result.ident = getIdent(fl)
-      else: 
-        internalError(result.info, "decodeNode: nkIdent")
-    of nkSym: 
-      if r.s[r.pos] == '!': 
-        inc(r.pos)
-        var id = decodeInt(r)
-        result.sym = rrGetSym(r, id, result.info)
-      else: 
-        internalError(result.info, "decodeNode: nkSym")
-    else: 
-      while r.s[r.pos] != ')': addSon(result, decodeNode(r, result.info))
-    if r.s[r.pos] == ')': inc(r.pos)
-    else: internalError(result.info, "decodeNode")
-  else: 
-    InternalError(result.info, "decodeNode " & r.s[r.pos])
-  
-proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) = 
-  if r.s[r.pos] == '<': 
-    inc(r.pos)
-    if r.s[r.pos] in {'0'..'9', 'a'..'z', 'A'..'Z'}: 
-      loc.k = TLocKind(decodeInt(r))
-    else: 
-      loc.k = low(loc.k)
-    if r.s[r.pos] == '*': 
-      inc(r.pos)
-      loc.s = TStorageLoc(decodeInt(r))
-    else: 
-      loc.s = low(loc.s)
-    if r.s[r.pos] == '$': 
-      inc(r.pos)
-      loc.flags = cast[TLocFlags](int32(decodeInt(r)))
-    else: 
-      loc.flags = {}
-    if r.s[r.pos] == '^': 
-      inc(r.pos)
-      loc.t = rrGetType(r, decodeInt(r), info)
-    else: 
-      loc.t = nil
-    if r.s[r.pos] == '!': 
-      inc(r.pos)
-      loc.r = toRope(decode(r))
-    else: 
-      loc.r = nil
-    if r.s[r.pos] == '?': 
-      inc(r.pos)
-      loc.a = decodeInt(r)
-    else: 
-      loc.a = 0
-    if r.s[r.pos] == '>': inc(r.pos)
-    else: InternalError(info, "decodeLoc " & r.s[r.pos])
-  
-proc decodeType(r: PRodReader, info: TLineInfo): PType = 
-  result = nil
-  if r.s[r.pos] == '[': 
-    inc(r.pos)
-    if r.s[r.pos] == ']': 
-      inc(r.pos)
-      return                  # nil type
-  new(result)
-  result.kind = TTypeKind(decodeInt(r))
-  if r.s[r.pos] == '+': 
-    inc(r.pos)
-    result.id = decodeInt(r)
-    setId(result.id)
-    if debugIds: registerID(result)
-  else: 
-    InternalError(info, "decodeType: no id")
-  # here this also avoids endless recursion for recursive type
-  IdTablePut(gTypeTable, result, result) 
-  if r.s[r.pos] == '(': result.n = decodeNode(r, UnknownLineInfo())
-  if r.s[r.pos] == '$': 
-    inc(r.pos)
-    result.flags = cast[TTypeFlags](int32(decodeInt(r)))
-  if r.s[r.pos] == '?': 
-    inc(r.pos)
-    result.callConv = TCallingConvention(decodeInt(r))
-  if r.s[r.pos] == '*': 
-    inc(r.pos)
-    result.owner = rrGetSym(r, decodeInt(r), info)
-  if r.s[r.pos] == '&': 
-    inc(r.pos)
-    result.sym = rrGetSym(r, decodeInt(r), info)
-  if r.s[r.pos] == '/': 
-    inc(r.pos)
-    result.size = decodeInt(r)
-  else: 
-    result.size = - 1
-  if r.s[r.pos] == '=': 
-    inc(r.pos)
-    result.align = decodeInt(r)
-  else: 
-    result.align = 2
-  if r.s[r.pos] == '@': 
-    inc(r.pos)
-    result.containerID = decodeInt(r)
-  decodeLoc(r, result.loc, info)
-  while r.s[r.pos] == '^': 
-    inc(r.pos)
-    if r.s[r.pos] == '(': 
-      inc(r.pos)
-      if r.s[r.pos] == ')': inc(r.pos)
-      else: InternalError(info, "decodeType ^(" & r.s[r.pos])
-      addSon(result, nil)
-    else: 
-      var d = decodeInt(r)
-      addSon(result, rrGetType(r, d, info))
-
-proc decodeLib(r: PRodReader, info: TLineInfo): PLib = 
-  result = nil
-  if r.s[r.pos] == '|': 
-    new(result)
-    inc(r.pos)
-    result.kind = TLibKind(decodeInt(r))
-    if r.s[r.pos] != '|': InternalError("decodeLib: 1")
-    inc(r.pos)
-    result.name = toRope(decode(r))
-    if r.s[r.pos] != '|': InternalError("decodeLib: 2")
-    inc(r.pos)
-    result.path = decodeNode(r, info)
-
-proc decodeSym(r: PRodReader, info: TLineInfo): PSym = 
-  var 
-    id: int
-    ident: PIdent
-  result = nil
-  if r.s[r.pos] == '{': 
-    inc(r.pos)
-    if r.s[r.pos] == '}': 
-      inc(r.pos)
-      return                  # nil sym
-  var k = TSymKind(decodeInt(r))
-  if r.s[r.pos] == '+': 
-    inc(r.pos)
-    id = decodeInt(r)
-    setId(id)
-  else: 
-    InternalError(info, "decodeSym: no id")
-  if r.s[r.pos] == '&': 
-    inc(r.pos)
-    ident = getIdent(decode(r))
-  else: 
-    InternalError(info, "decodeSym: no ident")
-  result = PSym(IdTableGet(r.syms, id))
-  if result == nil: 
-    new(result)
-    result.id = id
-    IdTablePut(r.syms, result, result)
-    if debugIds: registerID(result)
-  elif (result.id != id): 
-    InternalError(info, "decodeSym: wrong id")
-  result.kind = k
-  result.name = ident         # read the rest of the symbol description:
-  if r.s[r.pos] == '^': 
-    inc(r.pos)
-    result.typ = rrGetType(r, decodeInt(r), info)
-  decodeLineInfo(r, result.info)
-  if r.s[r.pos] == '*': 
-    inc(r.pos)
-    result.owner = rrGetSym(r, decodeInt(r), result.info)
-  if r.s[r.pos] == '$': 
-    inc(r.pos)
-    result.flags = cast[TSymFlags](int32(decodeInt(r)))
-  if r.s[r.pos] == '@': 
-    inc(r.pos)
-    result.magic = TMagic(decodeInt(r))
-  if r.s[r.pos] == '(': result.ast = decodeNode(r, result.info)
-  if r.s[r.pos] == '!': 
-    inc(r.pos)
-    result.options = cast[TOptions](int32(decodeInt(r)))
-  else: 
-    result.options = r.options
-  if r.s[r.pos] == '%': 
-    inc(r.pos)
-    result.position = decodeInt(r)
-  else: 
-    result.position = 0       
-    # BUGFIX: this may have been misused as reader index!
-  if r.s[r.pos] == '`': 
-    inc(r.pos)
-    result.offset = decodeInt(r)
-  else: 
-    result.offset = - 1
-  decodeLoc(r, result.loc, result.info)
-  result.annex = decodeLib(r, info)
-
-proc decodeInt(r: PRodReader): int = 
-  # base 190 numbers
-  var i = r.pos
-  var sign = - 1
-  assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
-  if r.s[i] == '-': 
-    inc(i)
-    sign = 1
-  result = 0
-  while true: 
-    case r.s[i]
-    of '0'..'9': result = result * 190 - (ord(r.s[i]) - ord('0'))
-    of 'a'..'z': result = result * 190 - (ord(r.s[i]) - ord('a') + 10)
-    of 'A'..'Z': result = result * 190 - (ord(r.s[i]) - ord('A') + 36)
-    of '\x80'..'\xFF': result = result * 190 - (ord(r.s[i]) - 128 + 62)
-    else: break 
-    inc(i)
-  result = result * sign
-  r.pos = i
-
-proc decodeBInt(r: PRodReader): biggestInt = 
-  var i = r.pos
-  var sign: biggestInt = - 1
-  assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
-  if r.s[i] == '-': 
-    inc(i)
-    sign = 1
-  result = 0
-  while true: 
-    case r.s[i]
-    of '0'..'9': result = result * 190 - (ord(r.s[i]) - ord('0'))
-    of 'a'..'z': result = result * 190 - (ord(r.s[i]) - ord('a') + 10)
-    of 'A'..'Z': result = result * 190 - (ord(r.s[i]) - ord('A') + 36)
-    of '\x80'..'\xFF': result = result * 190 - (ord(r.s[i]) - 128 + 62)
-    else: break 
-    inc(i)
-  result = result * sign
-  r.pos = i
-
-proc hexChar(c: char, xi: var int) = 
-  case c
-  of '0'..'9': xi = (xi shl 4) or (ord(c) - ord('0'))
-  of 'a'..'f': xi = (xi shl 4) or (ord(c) - ord('a') + 10)
-  of 'A'..'F': xi = (xi shl 4) or (ord(c) - ord('A') + 10)
-  else: nil
-
-proc decode(r: PRodReader): string = 
-  var i = r.pos
-  result = ""
-  while true: 
-    case r.s[i]
-    of '\\': 
-      inc(i, 3)
-      var xi = 0
-      hexChar(r.s[i-2], xi)
-      hexChar(r.s[i-1], xi)
-      add(result, chr(xi))
-    of 'a'..'z', 'A'..'Z', '0'..'9', '_': 
-      add(result, r.s[i])
-      inc(i)
-    else: break 
-  r.pos = i
-
-proc skipSection(r: PRodReader) = 
-  if r.s[r.pos] == ':': 
-    while r.s[r.pos] > '\x0A': inc(r.pos)
-  elif r.s[r.pos] == '(': 
-    var c = 0                 # count () pairs
-    inc(r.pos)
-    while true: 
-      case r.s[r.pos]
-      of '\x0A': inc(r.line)
-      of '(': inc(c)
-      of ')': 
-        if c == 0: 
-          inc(r.pos)
-          break 
-        elif c > 0: 
-          dec(c)
-      of '\0': break          # end of file
-      else: nil
-      inc(r.pos)
-  else: 
-    InternalError("skipSection " & $r.line)
-  
-proc rdWord(r: PRodReader): string = 
-  result = ""
-  while r.s[r.pos] in {'A'..'Z', '_', 'a'..'z', '0'..'9'}: 
-    add(result, r.s[r.pos])
-    inc(r.pos)
-
-proc newStub(r: PRodReader, name: string, id: int): PSym = 
-  new(result)
-  result.kind = skStub
-  result.id = id
-  result.name = getIdent(name)
-  result.position = r.readerIndex
-  setID(id)                   #MessageOut(result.name.s);
-  if debugIds: registerID(result)
-  
-proc processInterf(r: PRodReader, module: PSym) = 
-  if r.interfIdx == 0: InternalError("processInterf")
-  r.pos = r.interfIdx
-  while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
-    var w = decode(r)
-    inc(r.pos)
-    var key = decodeInt(r)
-    inc(r.pos)                # #10
-    var s = newStub(r, w, key)
-    s.owner = module
-    StrTableAdd(module.tab, s)
-    IdTablePut(r.syms, s, s)
-
-proc processCompilerProcs(r: PRodReader, module: PSym) = 
-  if r.compilerProcsIdx == 0: InternalError("processCompilerProcs")
-  r.pos = r.compilerProcsIdx
-  while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
-    var w = decode(r)
-    inc(r.pos)
-    var key = decodeInt(r)
-    inc(r.pos)                # #10
-    var s = PSym(IdTableGet(r.syms, key))
-    if s == nil: 
-      s = newStub(r, w, key)
-      s.owner = module
-      IdTablePut(r.syms, s, s)
-    StrTableAdd(rodCompilerProcs, s)
-
-proc processIndex(r: PRodReader, idx: var TIndex) = 
-  var key, val, tmp: int
-  inc(r.pos, 2)               # skip "(\10"
-  inc(r.line)
-  while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
-    tmp = decodeInt(r)
-    if r.s[r.pos] == ' ': 
-      inc(r.pos)
-      key = idx.lastIdxKey + tmp
-      val = decodeInt(r) + idx.lastIdxVal
-    else: 
-      key = idx.lastIdxKey + 1
-      val = tmp + idx.lastIdxVal
-    IITablePut(idx.tab, key, val)
-    idx.lastIdxKey = key
-    idx.lastIdxVal = val
-    setID(key)                # ensure that this id will not be used
-    if r.s[r.pos] == '\x0A': 
-      inc(r.pos)
-      inc(r.line)
-  if r.s[r.pos] == ')': inc(r.pos)
-  
-proc processRodFile(r: PRodReader, crc: TCrc32) = 
-  var 
-    w: string
-    d, L, inclCrc: int
-  while r.s[r.pos] != '\0': 
-    var section = rdWord(r)
-    if r.reason != rrNone: 
-      break                   # no need to process this file further
-    case section 
-    of "CRC": 
-      inc(r.pos)              # skip ':'
-      if int(crc) != decodeInt(r): r.reason = rrCrcChange
-    of "ID": 
-      inc(r.pos)              # skip ':'
-      r.moduleID = decodeInt(r)
-      setID(r.moduleID)
-    of "OPTIONS": 
-      inc(r.pos)              # skip ':'
-      r.options = cast[TOptions](int32(decodeInt(r)))
-      if options.gOptions != r.options: r.reason = rrOptions
-    of "DEFINES": 
-      inc(r.pos)              # skip ':'
-      d = 0
-      while r.s[r.pos] > '\x0A': 
-        w = decode(r)
-        inc(d)
-        if not condsyms.isDefined(getIdent(w)): 
-          r.reason = rrDefines #MessageOut('not defined, but should: ' + w);
-        if r.s[r.pos] == ' ': inc(r.pos)
-      if (d != countDefinedSymbols()): r.reason = rrDefines
-    of "FILES": 
-      inc(r.pos, 2)           # skip "(\10"
-      inc(r.line)
-      L = 0
-      while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
-        setlen(r.files, L + 1)
-        r.files[L] = decode(r)
-        inc(r.pos)            # skip #10
-        inc(r.line)
-        inc(L)
-      if r.s[r.pos] == ')': inc(r.pos)
-    of "INCLUDES": 
-      inc(r.pos, 2)           # skip "(\10"
-      inc(r.line)
-      while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
-        w = r.files[decodeInt(r)]
-        inc(r.pos)            # skip ' '
-        inclCrc = decodeInt(r)
-        if r.reason == rrNone: 
-          if not ExistsFile(w) or (inclCrc != int(crcFromFile(w))): 
-            r.reason = rrInclDeps
-        if r.s[r.pos] == '\x0A': 
-          inc(r.pos)
-          inc(r.line)
-      if r.s[r.pos] == ')': inc(r.pos)
-    of "DEPS": 
-      inc(r.pos)              # skip ':'
-      L = 0
-      while (r.s[r.pos] > '\x0A'): 
-        setlen(r.modDeps, L + 1)
-        r.modDeps[L] = r.files[decodeInt(r)]
-        inc(L)
-        if r.s[r.pos] == ' ': inc(r.pos)
-    of "INTERF": 
-      r.interfIdx = r.pos + 2
-      skipSection(r)
-    of "COMPILERPROCS": 
-      r.compilerProcsIdx = r.pos + 2
-      skipSection(r)
-    of "INDEX": 
-      processIndex(r, r.index)
-    of "IMPORTS": 
-      processIndex(r, r.imports)
-    of "CONVERTERS": 
-      r.convertersIdx = r.pos + 1
-      skipSection(r)
-    of "DATA": 
-      r.dataIdx = r.pos + 2 # "(\10"
-      # We do not read the DATA section here! We read the needed objects on
-      # demand.
-      skipSection(r)
-    of "INIT": 
-      r.initIdx = r.pos + 2   # "(\10"
-      skipSection(r)
-    of "CGEN": 
-      r.cgenIdx = r.pos + 2
-      skipSection(r)
-    else: 
-      MsgWriteln("skipping section: " & $r.pos)
-      skipSection(r)
-    if r.s[r.pos] == '\x0A': 
-      inc(r.pos)
-      inc(r.line)
-
-proc newRodReader(modfilename: string, crc: TCrc32, 
-                  readerIndex: int): PRodReader = 
-  new(result)
-  result.files = @[]
-  result.modDeps = @[]
-  var r = result
-  r.reason = rrNone
-  r.pos = 0
-  r.line = 1
-  r.readerIndex = readerIndex
-  r.filename = modfilename
-  InitIdTable(r.syms)
-  r.s = readFile(modfilename)
-  if startsWith(r.s, "NIM:"): 
-    initIITable(r.index.tab)
-    initIITable(r.imports.tab) # looks like a ROD file
-    inc(r.pos, 4)
-    var version = ""
-    while not (r.s[r.pos] in {'\0', '\x0A'}): 
-      add(version, r.s[r.pos])
-      inc(r.pos)
-    if r.s[r.pos] == '\x0A': inc(r.pos)
-    if version == FileVersion: 
-      # since ROD files are only for caching, no backwarts compatibility is
-      # needed
-      processRodFile(r, crc)
-    else: 
-      result = nil
-  else: 
-    result = nil
-  
-proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType = 
-  result = PType(IdTableGet(gTypeTable, id))
-  if result == nil: 
-    # load the type:
-    var oldPos = r.pos
-    var d = IITableGet(r.index.tab, id)
-    if d == invalidKey: InternalError(info, "rrGetType")
-    r.pos = d + r.dataIdx
-    result = decodeType(r, info)
-    r.pos = oldPos
-
-type 
-  TFileModuleRec{.final.} = object 
-    filename*: string
-    reason*: TReasonForRecompile
-    rd*: PRodReader
-    crc*: TCrc32
-
-  TFileModuleMap = seq[TFileModuleRec]
-
-var gMods: TFileModuleMap = @[]
-
-proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym = 
-  # all compiled modules
-  if rd.dataIdx == 0: InternalError(info, "dataIdx == 0")
-  var oldPos = rd.pos
-  rd.pos = offset + rd.dataIdx
-  result = decodeSym(rd, info)
-  rd.pos = oldPos
-
-proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym = 
-  result = PSym(IdTableGet(r.syms, id))
-  if result == nil: 
-    # load the symbol:
-    var d = IITableGet(r.index.tab, id)
-    if d == invalidKey: 
-      var moduleID = IiTableGet(r.imports.tab, id)
-      if moduleID < 0: 
-        InternalError(info, 
-                      "missing from both indexes: +" & ropeToStr(encodeInt(id))) 
-      # find the reader with the correct moduleID:
-      for i in countup(0, high(gMods)): 
-        var rd = gMods[i].rd
-        if (rd != nil): 
-          if (rd.moduleID == moduleID): 
-            d = IITableGet(rd.index.tab, id)
-            if d != invalidKey: 
-              result = decodeSymSafePos(rd, d, info)
-              break 
-            else: 
-              InternalError(info, "rrGetSym: no reader found: +" &
-                  ropeToStr(encodeInt(id)))
-          else: 
-            #if IiTableGet(rd.index.tab, id) <> invalidKey then
-            # XXX expensive check!
-            #InternalError(info,
-            #'id found in other module: +' + ropeToStr(encodeInt(id)))
-    else: 
-      # own symbol:
-      result = decodeSymSafePos(r, d, info)
-  if (result != nil) and (result.kind == skStub): loadStub(result)
-  
-proc loadInitSection(r: PRodReader): PNode = 
-  if (r.initIdx == 0) or (r.dataIdx == 0): InternalError("loadInitSection")
-  var oldPos = r.pos
-  r.pos = r.initIdx
-  result = newNode(nkStmtList)
-  while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
-    var d = decodeInt(r)
-    inc(r.pos)                # #10
-    var p = r.pos
-    r.pos = d + r.dataIdx
-    addSon(result, decodeNode(r, UnknownLineInfo()))
-    r.pos = p
-  r.pos = oldPos
-
-proc loadConverters(r: PRodReader) = 
-  # We have to ensure that no exported converter is a stub anymore.
-  if (r.convertersIdx == 0) or (r.dataIdx == 0): 
-    InternalError("importConverters")
-  r.pos = r.convertersIdx
-  while (r.s[r.pos] > '\x0A'): 
-    var d = decodeInt(r)
-    discard rrGetSym(r, d, UnknownLineInfo())
-    if r.s[r.pos] == ' ': inc(r.pos)
-  
-proc getModuleIdx(filename: string): int = 
-  for i in countup(0, high(gMods)): 
-    if sameFile(gMods[i].filename, filename): return i
-  result = len(gMods)
-  setlen(gMods, result + 1)
-
-proc checkDep(filename: string): TReasonForRecompile = 
-  var idx = getModuleIdx(filename)
-  if gMods[idx].reason != rrEmpty: 
-    # reason has already been computed for this module:
-    return gMods[idx].reason
-  var crc: TCrc32 = crcFromFile(filename)
-  gMods[idx].reason = rrNone  # we need to set it here to avoid cycles
-  gMods[idx].filename = filename
-  gMods[idx].crc = crc
-  result = rrNone
-  var r: PRodReader = nil
-  var rodfile = toGeneratedFile(filename, RodExt)
-  if ExistsFile(rodfile): 
-    r = newRodReader(rodfile, crc, idx)
-    if r == nil: 
-      result = rrRodInvalid
-    else: 
-      result = r.reason
-      if result == rrNone: 
-        # check modules it depends on
-        # NOTE: we need to process the entire module graph so that no ID will
-        # be used twice! However, compilation speed does not suffer much from
-        # this, since results are cached.
-        var res = checkDep(options.libpath / addFileExt("system", nimExt))
-        if res != rrNone: result = rrModDeps
-        for i in countup(0, high(r.modDeps)): 
-          res = checkDep(r.modDeps[i])
-          if res != rrNone: 
-            result = rrModDeps 
-            # we cannot break here, because of side-effects of `checkDep`
-  else: 
-    result = rrRodDoesNotExist
-  if (result != rrNone) and (gVerbosity > 0): 
-    MsgWriteln(`%`(reasonToFrmt[result], [filename]))
-  if (result != rrNone) or (optForceFullMake in gGlobalOptions): 
-    # recompilation is necessary:
-    r = nil
-  gMods[idx].rd = r
-  gMods[idx].reason = result  # now we know better
-  
-proc handleSymbolFile(module: PSym, filename: string): PRodReader = 
-  if not (optSymbolFiles in gGlobalOptions): 
-    module.id = getID()
-    return nil
-  discard checkDep(filename)
-  var idx = getModuleIdx(filename)
-  if gMods[idx].reason == rrEmpty: InternalError("handleSymbolFile")
-  result = gMods[idx].rd
-  if result != nil: 
-    module.id = result.moduleID
-    IdTablePut(result.syms, module, module)
-    processInterf(result, module)
-    processCompilerProcs(result, module)
-    loadConverters(result)
-  else: 
-    module.id = getID()
-  
-proc GetCRC(filename: string): TCrc32 = 
-  var idx = getModuleIdx(filename)
-  result = gMods[idx].crc
-
-proc loadStub(s: PSym) = 
-  if s.kind != skStub: 
-    InternalError("loadStub") #MessageOut('loading stub: ' + s.name.s);
-  var rd = gMods[s.position].rd
-  var theId = s.id                # used for later check
-  var d = IITableGet(rd.index.tab, s.id)
-  if d == invalidKey: InternalError("loadStub: invalid key")
-  var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
-  if rs != s: 
-    InternalError(rs.info, "loadStub: wrong symbol")
-  elif rs.id != theId: 
-    InternalError(rs.info, "loadStub: wrong ID") 
-  #MessageOut('loaded stub: ' + s.name.s);
-  
-InitIdTable(gTypeTable)
-InitStrTable(rodCompilerProcs)