summary refs log tree commit diff stats
path: root/compiler/rodwrite.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rodwrite.nim')
-rw-r--r--compiler/rodwrite.nim653
1 files changed, 0 insertions, 653 deletions
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
deleted file mode 100644
index 968cb9e7f..000000000
--- a/compiler/rodwrite.nim
+++ /dev/null
@@ -1,653 +0,0 @@
-#
-#
-#           The Nim Compiler
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This module is responsible for writing of rod files. Note that writing of
-# rod files is a pass, reading of rod files is not! This is why reading and
-# writing of rod files is split into two different modules.
-
-import
-  intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
-  condsyms, ropes, idents, std / sha1, rodread, passes, idgen,
-  rodutils, modulepaths, lineinfos
-
-from modulegraphs import ModuleGraph
-
-type
-  TRodWriter = object of TPassContext
-    module: PSym
-    hash: SecureHash
-    options: TOptions
-    defines: string
-    inclDeps: string
-    modDeps: string
-    interf: string
-    compilerProcs: string
-    index, imports: TIndex
-    converters, methods: string
-    init: string
-    data: string
-    sstack: TSymSeq          # a stack of symbols to process
-    tstack: TTypeSeq         # a stack of types to process
-    files: TStringSeq
-    origFile: string
-    cache: IdentCache
-    config: ConfigRef
-
-  PRodWriter = ref TRodWriter
-
-proc getDefines(conf: ConfigRef): string =
-  result = ""
-  for d in definedSymbolNames(conf.symbols):
-    if result.len != 0: add(result, " ")
-    add(result, d)
-
-proc fileIdx(w: PRodWriter, filename: string): int =
-  for i in countup(0, high(w.files)):
-    if w.files[i] == filename:
-      return i
-  result = len(w.files)
-  setLen(w.files, result + 1)
-  w.files[result] = filename
-
-template filename*(w: PRodWriter): string =
-  toFilename(w.config, FileIndex w.module.position)
-
-proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache;
-                  config: ConfigRef): PRodWriter =
-  new(result)
-  result.config = config
-  result.sstack = @[]
-  result.tstack = @[]
-  initIiTable(result.index.tab)
-  initIiTable(result.imports.tab)
-  result.index.r = ""
-  result.imports.r = ""
-  result.hash = hash
-  result.module = module
-  result.defines = getDefines(config)
-  result.options = config.options
-  result.files = @[]
-  result.inclDeps = ""
-  result.modDeps = ""
-  result.interf = newStringOfCap(2_000)
-  result.compilerProcs = ""
-  result.converters = ""
-  result.methods = ""
-  result.init = ""
-  result.origFile = toFullPath(config, module.info)
-  result.data = newStringOfCap(12_000)
-  result.cache = cache
-
-proc addModDep(w: PRodWriter, dep: string; info: TLineInfo) =
-  if w.modDeps.len != 0: add(w.modDeps, ' ')
-  let resolved = findModule(w.config, dep, toFullPath(w.config, info))
-  encodeVInt(fileIdx(w, resolved), w.modDeps)
-
-const
-  rodNL = "\x0A"
-
-proc addInclDep(w: PRodWriter, dep: string; info: TLineInfo) =
-  let resolved = findModule(w.config, dep, toFullPath(w.config, info))
-  encodeVInt(fileIdx(w, resolved), w.inclDeps)
-  add(w.inclDeps, " ")
-  encodeStr($secureHashFile(resolved), w.inclDeps)
-  add(w.inclDeps, rodNL)
-
-proc pushType(w: PRodWriter, t: PType) =
-  # check so that the stack does not grow too large:
-  if iiTableGet(w.index.tab, t.id) == InvalidKey:
-    w.tstack.add(t)
-
-proc pushSym(w: PRodWriter, s: PSym) =
-  # check so that the stack does not grow too large:
-  if iiTableGet(w.index.tab, s.id) == InvalidKey:
-    when false:
-      if s.kind == skMethod:
-        echo "encoding ", s.id, " ", s.name.s
-        writeStackTrace()
-    w.sstack.add(s)
-
-proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
-                result: var string) =
-  if n == nil:
-    # nil nodes have to be stored too:
-    result.add("()")
-    return
-  result.add('(')
-  encodeVInt(ord(n.kind), result)
-  # we do not write comments for now
-  # Line information takes easily 20% or more of the filesize! Therefore we
-  # omit line information if it is the same as the father's line information:
-  if fInfo.fileIndex != n.info.fileIndex:
-    result.add('?')
-    encodeVInt(n.info.col, result)
-    result.add(',')
-    encodeVInt(int n.info.line, result)
-    result.add(',')
-    encodeVInt(fileIdx(w, toFullPath(w.config, n.info)), result)
-  elif fInfo.line != n.info.line:
-    result.add('?')
-    encodeVInt(n.info.col, result)
-    result.add(',')
-    encodeVInt(int n.info.line, result)
-  elif fInfo.col != n.info.col:
-    result.add('?')
-    encodeVInt(n.info.col, result)
-  # No need to output the file index, as this is the serialization of one
-  # file.
-  var f = n.flags * PersistentNodeFlags
-  if f != {}:
-    result.add('$')
-    encodeVInt(cast[int32](f), result)
-  if n.typ != nil:
-    result.add('^')
-    encodeVInt(n.typ.id, result)
-    pushType(w, n.typ)
-  case n.kind
-  of nkCharLit..nkUInt64Lit:
-    if n.intVal != 0:
-      result.add('!')
-      encodeVBiggestInt(n.intVal, result)
-  of nkFloatLit..nkFloat64Lit:
-    if n.floatVal != 0.0:
-      result.add('!')
-      encodeStr($n.floatVal, result)
-  of nkStrLit..nkTripleStrLit:
-    if n.strVal != "":
-      result.add('!')
-      encodeStr(n.strVal, result)
-  of nkIdent:
-    result.add('!')
-    encodeStr(n.ident.s, result)
-  of nkSym:
-    result.add('!')
-    encodeVInt(n.sym.id, result)
-    pushSym(w, n.sym)
-  else:
-    for i in countup(0, sonsLen(n) - 1):
-      encodeNode(w, n.info, n.sons[i], result)
-  add(result, ')')
-
-proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
-  var oldLen = result.len
-  result.add('<')
-  if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
-  if loc.storage != low(loc.storage):
-    add(result, '*')
-    encodeVInt(ord(loc.storage), result)
-  if loc.flags != {}:
-    add(result, '$')
-    encodeVInt(cast[int32](loc.flags), result)
-  if loc.lode != nil:
-    add(result, '^')
-    encodeNode(w, unknownLineInfo(), loc.lode, result)
-    #encodeVInt(cast[int32](loc.t.id), result)
-    #pushType(w, loc.t)
-  if loc.r != nil:
-    add(result, '!')
-    encodeStr($loc.r, result)
-  if oldLen + 1 == result.len:
-    # no data was necessary, so remove the '<' again:
-    setLen(result, oldLen)
-  else:
-    add(result, '>')
-
-proc encodeType(w: PRodWriter, t: PType, result: var string) =
-  if t == nil:
-    # nil nodes have to be stored too:
-    result.add("[]")
-    return
-  # we need no surrounding [] here because the type is in a line of its own
-  if t.kind == tyForward: internalError(w.config, "encodeType: tyForward")
-  # for the new rodfile viewer we use a preceding [ so that the data section
-  # can easily be disambiguated:
-  add(result, '[')
-  encodeVInt(ord(t.kind), result)
-  add(result, '+')
-  encodeVInt(t.id, result)
-  if t.n != nil:
-    encodeNode(w, unknownLineInfo(), t.n, result)
-  if t.flags != {}:
-    add(result, '$')
-    encodeVInt(cast[int32](t.flags), result)
-  if t.callConv != low(t.callConv):
-    add(result, '?')
-    encodeVInt(ord(t.callConv), result)
-  if t.owner != nil:
-    add(result, '*')
-    encodeVInt(t.owner.id, result)
-    pushSym(w, t.owner)
-  if t.sym != nil:
-    add(result, '&')
-    encodeVInt(t.sym.id, result)
-    pushSym(w, t.sym)
-  if t.size != - 1:
-    add(result, '/')
-    encodeVBiggestInt(t.size, result)
-  if t.align != 2:
-    add(result, '=')
-    encodeVInt(t.align, result)
-  if t.lockLevel.ord != UnspecifiedLockLevel.ord:
-    add(result, '\14')
-    encodeVInt(t.lockLevel.int16, result)
-  if t.destructor != nil and t.destructor.id != 0:
-    add(result, '\15')
-    encodeVInt(t.destructor.id, result)
-    pushSym(w, t.destructor)
-  if t.deepCopy != nil:
-    add(result, '\16')
-    encodeVInt(t.deepcopy.id, result)
-    pushSym(w, t.deepcopy)
-  if t.assignment != nil:
-    add(result, '\17')
-    encodeVInt(t.assignment.id, result)
-    pushSym(w, t.assignment)
-  if t.sink != nil:
-    add(result, '\18')
-    encodeVInt(t.sink.id, result)
-    pushSym(w, t.sink)
-  for i, s in items(t.methods):
-    add(result, '\19')
-    encodeVInt(i, result)
-    add(result, '\20')
-    encodeVInt(s.id, result)
-    pushSym(w, s)
-  encodeLoc(w, t.loc, result)
-  for i in countup(0, sonsLen(t) - 1):
-    if t.sons[i] == nil:
-      add(result, "^()")
-    else:
-      add(result, '^')
-      encodeVInt(t.sons[i].id, result)
-      pushType(w, t.sons[i])
-
-proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) =
-  add(result, '|')
-  encodeVInt(ord(lib.kind), result)
-  add(result, '|')
-  encodeStr($lib.name, result)
-  add(result, '|')
-  encodeNode(w, info, lib.path, result)
-
-proc encodeInstantiations(w: PRodWriter; s: seq[PInstantiation];
-                          result: var string) =
-  for t in s:
-    result.add('\15')
-    encodeVInt(t.sym.id, result)
-    pushSym(w, t.sym)
-    for tt in t.concreteTypes:
-      result.add('\17')
-      encodeVInt(tt.id, result)
-      pushType(w, tt)
-    result.add('\20')
-    encodeVInt(t.compilesId, result)
-
-proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
-  if s == nil:
-    # nil nodes have to be stored too:
-    result.add("{}")
-    return
-  # we need no surrounding {} here because the symbol is in a line of its own
-  encodeVInt(ord(s.kind), result)
-  result.add('+')
-  encodeVInt(s.id, result)
-  result.add('&')
-  encodeStr(s.name.s, result)
-  if s.typ != nil:
-    result.add('^')
-    encodeVInt(s.typ.id, result)
-    pushType(w, s.typ)
-  result.add('?')
-  if s.info.col != -1'i16: encodeVInt(s.info.col, result)
-  result.add(',')
-  if s.info.line != 0'u16: encodeVInt(int s.info.line, result)
-  result.add(',')
-  encodeVInt(fileIdx(w, toFullPath(w.config, s.info)), result)
-  if s.owner != nil:
-    result.add('*')
-    encodeVInt(s.owner.id, result)
-    pushSym(w, s.owner)
-  if s.flags != {}:
-    result.add('$')
-    encodeVInt(cast[int32](s.flags), result)
-  if s.magic != mNone:
-    result.add('@')
-    encodeVInt(ord(s.magic), result)
-  if s.options != w.options:
-    result.add('!')
-    encodeVInt(cast[int32](s.options), result)
-  if s.position != 0:
-    result.add('%')
-    encodeVInt(s.position, result)
-  if s.offset != - 1:
-    result.add('`')
-    encodeVInt(s.offset, result)
-  encodeLoc(w, s.loc, result)
-  if s.annex != nil: encodeLib(w, s.annex, s.info, result)
-  if s.constraint != nil:
-    add(result, '#')
-    encodeNode(w, unknownLineInfo(), s.constraint, result)
-  case s.kind
-  of skType, skGenericParam:
-    for t in s.typeInstCache:
-      result.add('\14')
-      encodeVInt(t.id, result)
-      pushType(w, t)
-  of routineKinds:
-    encodeInstantiations(w, s.procInstCache, result)
-    if s.gcUnsafetyReason != nil:
-      result.add('\16')
-      encodeVInt(s.gcUnsafetyReason.id, result)
-      pushSym(w, s.gcUnsafetyReason)
-  of skModule, skPackage:
-    encodeInstantiations(w, s.usedGenerics, result)
-    # we don't serialize:
-    #tab*: TStrTable         # interface table for modules
-  of skLet, skVar, skField, skForVar:
-    if s.guard != nil:
-      result.add('\18')
-      encodeVInt(s.guard.id, result)
-      pushSym(w, s.guard)
-    if s.bitsize != 0:
-      result.add('\19')
-      encodeVInt(s.bitsize, result)
-  else: discard
-  # lazy loading will soon reload the ast lazily, so the ast needs to be
-  # the last entry of a symbol:
-  if s.ast != nil:
-    # we used to attempt to save space here by only storing a dummy AST if
-    # it is not necessary, but Nim's heavy compile-time evaluation features
-    # make that unfeasible nowadays:
-    encodeNode(w, s.info, s.ast, result)
-
-proc addToIndex(w: var TIndex, key, val: int) =
-  if key - w.lastIdxKey == 1:
-    # we do not store a key-diff of 1 to safe space
-    encodeVInt(val - w.lastIdxVal, w.r)
-  else:
-    encodeVInt(key - w.lastIdxKey, w.r)
-    add(w.r, ' ')
-    encodeVInt(val - w.lastIdxVal, w.r)
-  add(w.r, rodNL)
-  w.lastIdxKey = key
-  w.lastIdxVal = val
-  iiTablePut(w.tab, key, val)
-
-const debugWrittenIds = false
-
-when debugWrittenIds:
-  var debugWritten = initIntSet()
-
-proc symStack(w: PRodWriter): int =
-  var i = 0
-  while i < len(w.sstack):
-    var s = w.sstack[i]
-    if sfForward in s.flags:
-      w.sstack[result] = s
-      inc result
-    elif iiTableGet(w.index.tab, s.id) == InvalidKey:
-      var m = getModule(s)
-      #if m == nil and s.kind != skPackage and sfGenSym notin s.flags:
-      #  internalError("symStack: module nil: " & s.name.s & " " & $s.kind & " ID " & $s.id)
-      if m == nil or s.kind == skPackage or {sfFromGeneric, sfGenSym} * s.flags != {} or m.id == w.module.id:
-        # put definition in here
-        var L = w.data.len
-        addToIndex(w.index, s.id, L)
-        when debugWrittenIds: incl(debugWritten, s.id)
-        encodeSym(w, s, w.data)
-        add(w.data, rodNL)
-        # put into interface section if appropriate:
-        if {sfExported, sfFromGeneric} * s.flags == {sfExported} and
-            s.kind in ExportableSymKinds:
-          encodeStr(s.name.s, w.interf)
-          add(w.interf, ' ')
-          encodeVInt(s.id, w.interf)
-          add(w.interf, rodNL)
-        if sfCompilerProc in s.flags:
-          encodeStr(s.name.s, w.compilerProcs)
-          add(w.compilerProcs, ' ')
-          encodeVInt(s.id, w.compilerProcs)
-          add(w.compilerProcs, rodNL)
-        if s.kind == skConverter or (s.ast != nil and hasPattern(s)):
-          if w.converters.len != 0: add(w.converters, ' ')
-          encodeVInt(s.id, w.converters)
-        if s.kind == skMethod and sfDispatcher notin s.flags:
-          if w.methods.len != 0: add(w.methods, ' ')
-          encodeVInt(s.id, w.methods)
-      elif iiTableGet(w.imports.tab, s.id) == InvalidKey:
-        addToIndex(w.imports, s.id, m.id)
-        when debugWrittenIds:
-          if not contains(debugWritten, s.id):
-            echo(w.filename)
-            debug(s)
-            debug(s.owner)
-            debug(m)
-            internalError("Symbol referred to but never written")
-    inc(i)
-  setLen(w.sstack, result)
-
-proc typeStack(w: PRodWriter): int =
-  var i = 0
-  while i < len(w.tstack):
-    var t = w.tstack[i]
-    if t.kind == tyForward:
-      w.tstack[result] = t
-      inc result
-    elif iiTableGet(w.index.tab, t.id) == InvalidKey:
-      var L = w.data.len
-      addToIndex(w.index, t.id, L)
-      encodeType(w, t, w.data)
-      add(w.data, rodNL)
-    inc(i)
-  setLen(w.tstack, result)
-
-proc processStacks(w: PRodWriter, finalPass: bool) =
-  var oldS = 0
-  var oldT = 0
-  while true:
-    var slen = symStack(w)
-    var tlen = typeStack(w)
-    if slen == oldS and tlen == oldT: break
-    oldS = slen
-    oldT = tlen
-  if finalPass and (oldS != 0 or oldT != 0):
-    internalError(w.config, "could not serialize some forwarded symbols/types")
-
-proc rawAddInterfaceSym(w: PRodWriter, s: PSym) =
-  pushSym(w, s)
-  processStacks(w, false)
-
-proc addInterfaceSym(w: PRodWriter, s: PSym) =
-  if w == nil: return
-  if s.kind in ExportableSymKinds and
-      {sfExported, sfCompilerProc} * s.flags != {}:
-    rawAddInterfaceSym(w, s)
-
-proc addStmt(w: PRodWriter, n: PNode) =
-  encodeVInt(w.data.len, w.init)
-  add(w.init, rodNL)
-  encodeNode(w, unknownLineInfo(), n, w.data)
-  add(w.data, rodNL)
-  processStacks(w, false)
-
-proc writeRod(w: PRodWriter) =
-  processStacks(w, true)
-  var f: File
-  if not open(f, completeGeneratedFilePath(w.config, changeFileExt(
-                      withPackageName(w.config, w.filename), RodExt)),
-              fmWrite):
-    #echo "couldn't write rod file for: ", w.filename
-    return
-  # write header:
-  f.write("NIM:")
-  f.write(RodFileVersion)
-  f.write(rodNL)
-  var id = "ID:"
-  encodeVInt(w.module.id, id)
-  f.write(id)
-  f.write(rodNL)
-
-  var orig = "ORIGFILE:"
-  encodeStr(w.origFile, orig)
-  f.write(orig)
-  f.write(rodNL)
-
-  var hash = "HASH:"
-  encodeStr($w.hash, hash)
-  f.write(hash)
-  f.write(rodNL)
-
-  var options = "OPTIONS:"
-  encodeVInt(cast[int32](w.options), options)
-  f.write(options)
-  f.write(rodNL)
-
-  var goptions = "GOPTIONS:"
-  encodeVInt(cast[int32](w.config.globalOptions), goptions)
-  f.write(goptions)
-  f.write(rodNL)
-
-  var cmd = "CMD:"
-  encodeVInt(cast[int32](w.config.cmd), cmd)
-  f.write(cmd)
-  f.write(rodNL)
-
-  f.write("DEFINES:")
-  f.write(w.defines)
-  f.write(rodNL)
-
-  var files = "FILES(" & rodNL
-  for i in countup(0, high(w.files)):
-    encodeStr(w.files[i], files)
-    files.add(rodNL)
-  f.write(files)
-  f.write(')' & rodNL)
-
-  f.write("INCLUDES(" & rodNL)
-  f.write(w.inclDeps)
-  f.write(')' & rodNL)
-
-  f.write("DEPS:")
-  f.write(w.modDeps)
-  f.write(rodNL)
-
-  f.write("INTERF(" & rodNL)
-  f.write(w.interf)
-  f.write(')' & rodNL)
-
-  f.write("COMPILERPROCS(" & rodNL)
-  f.write(w.compilerProcs)
-  f.write(')' & rodNL)
-
-  f.write("INDEX(" & rodNL)
-  f.write(w.index.r)
-  f.write(')' & rodNL)
-
-  f.write("IMPORTS(" & rodNL)
-  f.write(w.imports.r)
-  f.write(')' & rodNL)
-
-  f.write("CONVERTERS:")
-  f.write(w.converters)
-  f.write(rodNL)
-
-  f.write("METHODS:")
-  f.write(w.methods)
-  f.write(rodNL)
-
-  f.write("INIT(" & rodNL)
-  f.write(w.init)
-  f.write(')' & rodNL)
-
-  f.write("DATA(" & rodNL)
-  f.write(w.data)
-  f.write(')' & rodNL)
-  # write trailing zero which is necessary because we use memory mapped files
-  # for reading:
-  f.write("\0")
-  f.close()
-
-  #echo "interf: ", w.interf.len
-  #echo "index:  ", w.index.r.len
-  #echo "init:   ", w.init.len
-  #echo "data:   ", w.data.len
-
-proc process(c: PPassContext, n: PNode): PNode =
-  result = n
-  if c == nil: return
-  var w = PRodWriter(c)
-  case n.kind
-  of nkStmtList:
-    for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i])
-    #var s = n.sons[namePos].sym
-    #addInterfaceSym(w, s)
-  of nkProcDef, nkFuncDef, nkIteratorDef, nkConverterDef,
-      nkTemplateDef, nkMacroDef:
-    let s = n.sons[namePos].sym
-    if s == nil: internalError(w.config, n.info, "rodwrite.process")
-    if n.sons[bodyPos] == nil:
-      internalError(w.config, n.info, "rodwrite.process: body is nil")
-    if n.sons[bodyPos].kind != nkEmpty or s.magic != mNone or
-        sfForward notin s.flags:
-      addInterfaceSym(w, s)
-  of nkMethodDef:
-    let s = n.sons[namePos].sym
-    if s == nil: internalError(w.config, n.info, "rodwrite.process")
-    if n.sons[bodyPos] == nil:
-      internalError(w.config, n.info, "rodwrite.process: body is nil")
-    if n.sons[bodyPos].kind != nkEmpty or s.magic != mNone or
-        sfForward notin s.flags:
-      pushSym(w, s)
-      processStacks(w, false)
-
-  of nkVarSection, nkLetSection, nkConstSection:
-    for i in countup(0, sonsLen(n) - 1):
-      var a = n.sons[i]
-      if a.kind == nkCommentStmt: continue
-      addInterfaceSym(w, a.sons[0].sym)
-  of nkTypeSection:
-    for i in countup(0, sonsLen(n) - 1):
-      var a = n.sons[i]
-      if a.kind == nkCommentStmt: continue
-      if a.sons[0].kind != nkSym: internalError(w.config, a.info, "rodwrite.process")
-      var s = a.sons[0].sym
-      addInterfaceSym(w, s)
-      # this takes care of enum fields too
-      # Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum
-      # type aliasing! Otherwise the same enum symbol would be included
-      # several times!
-  of nkImportStmt:
-    for i in countup(0, sonsLen(n) - 1):
-      addModDep(w, getModuleName(w.config, n.sons[i]), n.info)
-    addStmt(w, n)
-  of nkFromStmt, nkImportExceptStmt:
-    addModDep(w, getModuleName(w.config, n.sons[0]), n.info)
-    addStmt(w, n)
-  of nkIncludeStmt:
-    for i in countup(0, sonsLen(n) - 1):
-      addInclDep(w, getModuleName(w.config, n.sons[i]), n.info)
-  of nkPragma:
-    addStmt(w, n)
-  else:
-    discard
-
-proc myOpen(g: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
-  if module.id < 0: internalError(g.config, "rodwrite: module ID not set")
-  var w = newRodWriter(rodread.getHash(g.config, FileIndex module.position), module, cache, g.config)
-  rawAddInterfaceSym(w, module)
-  result = w
-
-proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
-  result = process(c, n)
-  var w = PRodWriter(c)
-  writeRod(w)
-  idgen.saveMaxIds(graph.config, graph.config.projectPath / graph.config.projectName)
-
-const rodwritePass* = makePass(open = myOpen, close = myClose, process = process)
-