summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2018-05-10 13:12:42 +0200
committerAndreas Rumpf <rumpf_a@web.de>2018-05-10 13:12:42 +0200
commit0d56dd4677b8f6b080844db8655b41c10bee68c1 (patch)
tree962e23fec560371bcf2c0b9c367143d2d5ef783d
parent61e57cfa137544ebbb915ce2ed5da9afae4375ef (diff)
downloadNim-0d56dd4677b8f6b080844db8655b41c10bee68c1.tar.gz
big refactoring: magicsys compiles again
-rw-r--r--compiler/filter_tmpl.nim23
-rw-r--r--compiler/filters.nim43
-rw-r--r--compiler/magicsys.nim179
-rw-r--r--compiler/modulegraphs.nim9
-rw-r--r--compiler/msgs.nim4
-rw-r--r--compiler/options.nim6
-rw-r--r--compiler/renderer.nim18
-rw-r--r--compiler/rodread.nim118
-rw-r--r--compiler/syntaxes.nim34
-rw-r--r--compiler/types.nim69
10 files changed, 264 insertions, 239 deletions
diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim
index 545bea950..9bdc41016 100644
--- a/compiler/filter_tmpl.nim
+++ b/compiler/filter_tmpl.nim
@@ -27,7 +27,7 @@ type
     emit, conc, toStr: string
     curly, bracket, par: int
     pendingExprLine: bool
-
+    config: ConfigRef
 
 const
   PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '.', '_'}
@@ -90,7 +90,7 @@ proc parseLine(p: var TTmplParser) =
         dec(p.indent, 2)
       else:
         p.info.col = int16(j)
-        localError(p.info, errXNotAllowedHere, "end")
+        localError(p.config, p.info, "'end' does not close a control flow construct")
       llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, "#end")
     of "if", "when", "try", "while", "for", "block", "case", "proc", "iterator",
@@ -175,7 +175,7 @@ proc parseLine(p: var TTmplParser) =
                 llStreamWrite(p.outp, p.x[j])
                 inc(j)
             if curly > 0:
-              localError(p.info, errXExpected, "}")
+              localError(p.config, p.info, "expected closing '}'")
               break
             llStreamWrite(p.outp, ')')
             llStreamWrite(p.outp, p.conc)
@@ -197,22 +197,23 @@ proc parseLine(p: var TTmplParser) =
               inc(j)
             else:
               p.info.col = int16(j)
-              localError(p.info, errInvalidExpression, "$")
+              localError(p.config, p.info, "invalid expression")
         else:
           llStreamWrite(p.outp, p.x[j])
           inc(j)
     llStreamWrite(p.outp, "\\n\"")
 
-proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode): PLLStream =
+proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode; conf: ConfigRef): PLLStream =
   var p: TTmplParser
-  p.info = newLineInfo(filename, 0, 0)
+  p.config = conf
+  p.info = newLineInfo(conf, filename, 0, 0)
   p.outp = llStreamOpen("")
   p.inp = stdin
-  p.subsChar = charArg(call, "subschar", 1, '$')
-  p.nimDirective = charArg(call, "metachar", 2, '#')
-  p.emit = strArg(call, "emit", 3, "result.add")
-  p.conc = strArg(call, "conc", 4, " & ")
-  p.toStr = strArg(call, "tostring", 5, "$")
+  p.subsChar = charArg(conf, call, "subschar", 1, '$')
+  p.nimDirective = charArg(conf, call, "metachar", 2, '#')
+  p.emit = strArg(conf, call, "emit", 3, "result.add")
+  p.conc = strArg(conf, call, "conc", 4, " & ")
+  p.toStr = strArg(conf, call, "tostring", 5, "$")
   p.x = newStringOfCap(120)
   # do not process the first line which contains the directive:
   if llStreamReadLine(p.inp, p.x):
diff --git a/compiler/filters.nim b/compiler/filters.nim
index 37df628ed..3ebbad678 100644
--- a/compiler/filters.nim
+++ b/compiler/filters.nim
@@ -13,43 +13,44 @@ import
   llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
   renderer
 
-proc invalidPragma(n: PNode) =
-  localError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
+proc invalidPragma(conf: ConfigRef; n: PNode) =
+  localError(conf, n.info,
+      "'$1' not allowed here" % renderTree(n, {renderNoComments}))
 
-proc getArg(n: PNode, name: string, pos: int): PNode =
+proc getArg(conf: ConfigRef; n: PNode, name: string, pos: int): PNode =
   result = nil
   if n.kind in {nkEmpty..nkNilLit}: return
   for i in countup(1, sonsLen(n) - 1):
     if n.sons[i].kind == nkExprEqExpr:
-      if n.sons[i].sons[0].kind != nkIdent: invalidPragma(n)
+      if n.sons[i].sons[0].kind != nkIdent: invalidPragma(conf, n)
       if cmpIgnoreStyle(n.sons[i].sons[0].ident.s, name) == 0:
         return n.sons[i].sons[1]
     elif i == pos:
       return n.sons[i]
 
-proc charArg*(n: PNode, name: string, pos: int, default: char): char =
-  var x = getArg(n, name, pos)
+proc charArg*(conf: ConfigRef; n: PNode, name: string, pos: int, default: char): char =
+  var x = getArg(conf, n, name, pos)
   if x == nil: result = default
   elif x.kind == nkCharLit: result = chr(int(x.intVal))
-  else: invalidPragma(n)
+  else: invalidPragma(conf, n)
 
-proc strArg*(n: PNode, name: string, pos: int, default: string): string =
-  var x = getArg(n, name, pos)
+proc strArg*(conf: ConfigRef; n: PNode, name: string, pos: int, default: string): string =
+  var x = getArg(conf, n, name, pos)
   if x == nil: result = default
   elif x.kind in {nkStrLit..nkTripleStrLit}: result = x.strVal
-  else: invalidPragma(n)
+  else: invalidPragma(conf, n)
 
-proc boolArg*(n: PNode, name: string, pos: int, default: bool): bool =
-  var x = getArg(n, name, pos)
+proc boolArg*(conf: ConfigRef; n: PNode, name: string, pos: int, default: bool): bool =
+  var x = getArg(conf, n, name, pos)
   if x == nil: result = default
   elif x.kind == nkIdent and cmpIgnoreStyle(x.ident.s, "true") == 0: result = true
   elif x.kind == nkIdent and cmpIgnoreStyle(x.ident.s, "false") == 0: result = false
-  else: invalidPragma(n)
+  else: invalidPragma(conf, n)
 
-proc filterStrip*(stdin: PLLStream, filename: string, call: PNode): PLLStream =
-  var pattern = strArg(call, "startswith", 1, "")
-  var leading = boolArg(call, "leading", 2, true)
-  var trailing = boolArg(call, "trailing", 3, true)
+proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: string, call: PNode): PLLStream =
+  var pattern = strArg(conf, call, "startswith", 1, "")
+  var leading = boolArg(conf, call, "leading", 2, true)
+  var trailing = boolArg(conf, call, "trailing", 3, true)
   result = llStreamOpen("")
   var line = newStringOfCap(80)
   while llStreamReadLine(stdin, line):
@@ -60,10 +61,10 @@ proc filterStrip*(stdin: PLLStream, filename: string, call: PNode): PLLStream =
       llStreamWriteln(result, line)
   llStreamClose(stdin)
 
-proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream =
-  var sub = strArg(call, "sub", 1, "")
-  if len(sub) == 0: invalidPragma(call)
-  var by = strArg(call, "by", 2, "")
+proc filterReplace*(conf: ConfigRef; stdin: PLLStream, filename: string, call: PNode): PLLStream =
+  var sub = strArg(conf, call, "sub", 1, "")
+  if len(sub) == 0: invalidPragma(conf, call)
+  var by = strArg(conf, call, "by", 2, "")
   result = llStreamOpen("")
   var line = newStringOfCap(80)
   while llStreamReadLine(stdin, line):
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index 6a9d69082..75026d5f4 100644
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -10,63 +10,59 @@
 # Built-in types and compilerprocs are registered here.
 
 import
-  ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread
+  ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread,
+  modulegraphs
 
-var systemModule*: PSym
+proc nilOrSysInt*(g: ModuleGraph): PType = g.sysTypes[tyInt]
 
-var
-  gSysTypes: array[TTypeKind, PType]
-  compilerprocs: TStrTable
-  exposed: TStrTable
+proc registerSysType*(g: ModuleGraph; t: PType) =
+  if g.sysTypes[t.kind] == nil: g.sysTypes[t.kind] = t
 
-proc nilOrSysInt*: PType = gSysTypes[tyInt]
-
-proc registerSysType*(t: PType) =
-  if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
-
-proc newSysType(kind: TTypeKind, size: int): PType =
-  result = newType(kind, systemModule)
+proc newSysType(g: ModuleGraph; kind: TTypeKind, size: int): PType =
+  result = newType(kind, g.systemModule)
   result.size = size
   result.align = size.int16
 
-proc getSysSym*(name: string): PSym =
-  result = strTableGet(systemModule.tab, getIdent(name))
+proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym =
+  result = strTableGet(g.systemModule.tab, getIdent(name))
   if result == nil:
-    rawMessage(errSystemNeeds, name)
-    result = newSym(skError, getIdent(name), systemModule, systemModule.info)
-    result.typ = newType(tyError, systemModule)
+    localError(g.config, info, "system module needs: " & name)
+    result = newSym(skError, getIdent(name), g.systemModule, g.systemModule.info)
+    result.typ = newType(tyError, g.systemModule)
   if result.kind == skStub: loadStub(result)
   if result.kind == skAlias: result = result.owner
 
-proc createMagic*(name: string, m: TMagic): PSym =
+proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym =
   result = newSym(skProc, getIdent(name), nil, unknownLineInfo())
   result.magic = m
 
-let
-  opNot* = createMagic("not", mNot)
-  opContains* = createMagic("contains", mInSet)
+when false:
+  let
+    opNot* = createMagic("not", mNot)
+    opContains* = createMagic("contains", mInSet)
 
-proc getSysMagic*(name: string, m: TMagic): PSym =
+proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSym =
   var ti: TIdentIter
   let id = getIdent(name)
-  var r = initIdentIter(ti, systemModule.tab, id)
+  var r = initIdentIter(ti, g.systemModule.tab, id)
   while r != nil:
     if r.kind == skStub: loadStub(r)
     if r.magic == m:
       # prefer the tyInt variant:
       if r.typ.sons[0] != nil and r.typ.sons[0].kind == tyInt: return r
       result = r
-    r = nextIdentIter(ti, systemModule.tab)
+    r = nextIdentIter(ti, g.systemModule.tab)
   if result != nil: return result
-  rawMessage(errSystemNeeds, name)
-  result = newSym(skError, id, systemModule, systemModule.info)
-  result.typ = newType(tyError, systemModule)
+  localError(g.config, info, "system module needs: " & name)
+  result = newSym(skError, id, g.systemModule, g.systemModule.info)
+  result.typ = newType(tyError, g.systemModule)
 
-proc sysTypeFromName*(name: string): PType =
-  result = getSysSym(name).typ
+proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType =
+  result = getSysSym(g, info, name).typ
 
-proc getSysType*(kind: TTypeKind): PType =
-  result = gSysTypes[kind]
+proc getSysType*(g: ModuleGraph; info: TLineInfo; kind: TTypeKind): PType =
+  template sysTypeFromName(s: string): untyped = sysTypeFromName(g, info, s)
+  result = g.sysTypes[kind]
   if result == nil:
     case kind
     of tyInt: result = sysTypeFromName("int")
@@ -88,51 +84,49 @@ proc getSysType*(kind: TTypeKind): PType =
     of tyString: result = sysTypeFromName("string")
     of tyCString: result = sysTypeFromName("cstring")
     of tyPointer: result = sysTypeFromName("pointer")
-    of tyNil: result = newSysType(tyNil, ptrSize)
-    else: internalError("request for typekind: " & $kind)
-    gSysTypes[kind] = result
+    of tyNil: result = newSysType(g, tyNil, ptrSize)
+    else: internalError(g.config, "request for typekind: " & $kind)
+    g.sysTypes[kind] = result
   if result.kind != kind:
-    internalError("wanted: " & $kind & " got: " & $result.kind)
-  if result == nil: internalError("type not found: " & $kind)
+    internalError(g.config, "wanted: " & $kind & " got: " & $result.kind)
+  if result == nil: internalError(g.config, "type not found: " & $kind)
 
-var
-  intTypeCache: array[-5..64, PType]
+proc resetSysTypes*(g: ModuleGraph) =
+  g.systemModule = nil
+  initStrTable(g.compilerprocs)
+  initStrTable(g.exposed)
+  for i in low(g.sysTypes)..high(g.sysTypes):
+    g.sysTypes[i] = nil
 
-proc resetSysTypes* =
-  systemModule = nil
-  initStrTable(compilerprocs)
-  initStrTable(exposed)
-  for i in low(gSysTypes)..high(gSysTypes):
-    gSysTypes[i] = nil
+  for i in low(g.intTypeCache)..high(g.intTypeCache):
+    g.intTypeCache[i] = nil
 
-  for i in low(intTypeCache)..high(intTypeCache):
-    intTypeCache[i] = nil
-
-proc getIntLitType*(literal: PNode): PType =
+proc getIntLitType*(g: ModuleGraph; literal: PNode): PType =
   # we cache some common integer literal types for performance:
   let value = literal.intVal
-  if value >= low(intTypeCache) and value <= high(intTypeCache):
-    result = intTypeCache[value.int]
+  if value >= low(g.intTypeCache) and value <= high(g.intTypeCache):
+    result = g.intTypeCache[value.int]
     if result == nil:
-      let ti = getSysType(tyInt)
+      let ti = getSysType(g, literal.info, tyInt)
       result = copyType(ti, ti.owner, false)
       result.n = literal
-      intTypeCache[value.int] = result
+      g.intTypeCache[value.int] = result
   else:
-    let ti = getSysType(tyInt)
+    let ti = getSysType(g, literal.info, tyInt)
     result = copyType(ti, ti.owner, false)
     result.n = literal
 
-proc getFloatLitType*(literal: PNode): PType =
+proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType =
   # for now we do not cache these:
-  result = newSysType(tyFloat, size=8)
+  result = newSysType(g, tyFloat, size=8)
   result.n = literal
 
 proc skipIntLit*(t: PType): PType {.inline.} =
-  if t.n != nil:
-    if t.kind in {tyInt, tyFloat}:
-      return getSysType(t.kind)
-  result = t
+  if t.n != nil and t.kind in {tyInt, tyFloat}:
+    result = copyType(t, t.owner, false)
+    result.n = nil
+  else:
+    result = t
 
 proc addSonSkipIntLit*(father, son: PType) =
   if isNil(father.sons): father.sons = @[]
@@ -140,60 +134,59 @@ proc addSonSkipIntLit*(father, son: PType) =
   add(father.sons, s)
   propagateToOwner(father, s)
 
-proc setIntLitType*(result: PNode) =
+proc setIntLitType*(g: ModuleGraph; result: PNode) =
   let i = result.intVal
   case platform.intSize
-  of 8: result.typ = getIntLitType(result)
+  of 8: result.typ = getIntLitType(g, result)
   of 4:
     if i >= low(int32) and i <= high(int32):
-      result.typ = getIntLitType(result)
+      result.typ = getIntLitType(g, result)
     else:
-      result.typ = getSysType(tyInt64)
+      result.typ = getSysType(g, result.info, tyInt64)
   of 2:
     if i >= low(int16) and i <= high(int16):
-      result.typ = getIntLitType(result)
+      result.typ = getIntLitType(g, result)
     elif i >= low(int32) and i <= high(int32):
-      result.typ = getSysType(tyInt32)
+      result.typ = getSysType(g, result.info, tyInt32)
     else:
-      result.typ = getSysType(tyInt64)
+      result.typ = getSysType(g, result.info, tyInt64)
   of 1:
     # 8 bit CPUs are insane ...
     if i >= low(int8) and i <= high(int8):
-      result.typ = getIntLitType(result)
+      result.typ = getIntLitType(g, result)
     elif i >= low(int16) and i <= high(int16):
-      result.typ = getSysType(tyInt16)
+      result.typ = getSysType(g, result.info, tyInt16)
     elif i >= low(int32) and i <= high(int32):
-      result.typ = getSysType(tyInt32)
+      result.typ = getSysType(g, result.info, tyInt32)
     else:
-      result.typ = getSysType(tyInt64)
-  else: internalError(result.info, "invalid int size")
+      result.typ = getSysType(g, result.info, tyInt64)
+  else:
+    internalError(g.config, result.info, "invalid int size")
 
-proc getCompilerProc*(name: string): PSym =
+proc getCompilerProc*(g: ModuleGraph; name: string): PSym =
   let ident = getIdent(name)
-  result = strTableGet(compilerprocs, ident)
-  if result == nil:
-    result = strTableGet(rodCompilerprocs, ident)
-    if result != nil:
-      strTableAdd(compilerprocs, result)
-      if result.kind == skStub: loadStub(result)
-      if result.kind == skAlias: result = result.owner
+  result = strTableGet(g.compilerprocs, ident)
+  when false:
+    if result == nil:
+      result = strTableGet(g.rodCompilerprocs, ident)
+      if result != nil:
+        strTableAdd(g.compilerprocs, result)
+        if result.kind == skStub: loadStub(result)
+        if result.kind == skAlias: result = result.owner
 
-proc registerCompilerProc*(s: PSym) =
-  strTableAdd(compilerprocs, s)
+proc registerCompilerProc*(g: ModuleGraph; s: PSym) =
+  strTableAdd(g.compilerprocs, s)
 
-proc registerNimScriptSymbol*(s: PSym) =
+proc registerNimScriptSymbol*(g: ModuleGraph; s: PSym) =
   # Nimscript symbols must be al unique:
-  let conflict = strTableGet(exposed, s.name)
+  let conflict = strTableGet(g.exposed, s.name)
   if conflict == nil:
-    strTableAdd(exposed, s)
+    strTableAdd(g.exposed, s)
   else:
-    localError(s.info, "symbol conflicts with other .exportNims symbol at: " &
-      $conflict.info)
-
-proc getNimScriptSymbol*(name: string): PSym =
-  strTableGet(exposed, getIdent(name))
+    localError(g.config, s.info,
+      "symbol conflicts with other .exportNims symbol at: " & $conflict.info)
 
-proc resetNimScriptSymbols*() = initStrTable(exposed)
+proc getNimScriptSymbol*(g: ModuleGraph; name: string): PSym =
+  strTableGet(g.exposed, getIdent(name))
 
-initStrTable(compilerprocs)
-initStrTable(exposed)
+proc resetNimScriptSymbols*(g: ModuleGraph) = initStrTable(g.exposed)
diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim
index 6c14a46e8..5f741a3b3 100644
--- a/compiler/modulegraphs.nim
+++ b/compiler/modulegraphs.nim
@@ -44,6 +44,11 @@ type
     usageSym*: PSym # for nimsuggest
     owners*: seq[PSym]
     methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]]
+    systemModule*: PSym
+    sysTypes*: array[TTypeKind, PType]
+    compilerprocs*: TStrTable
+    exposed*: TStrTable
+    intTypeCache*: array[-5..64, PType]
 
 proc hash*(x: FileIndex): Hash {.borrow.}
 
@@ -65,6 +70,8 @@ proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph =
     result.config = config
   result.owners = @[]
   result.methods = @[]
+  initStrTable(result.compilerprocs)
+  initStrTable(result.exposed)
 
 proc resetAllModules*(g: ModuleGraph) =
   initStrTable(packageSyms)
@@ -75,6 +82,8 @@ proc resetAllModules*(g: ModuleGraph) =
   usageSym = nil
   owners = @[]
   methods = @[]
+  initStrTable(compilerprocs)
+  initStrTable(exposed)
 
 proc getModule*(g: ModuleGraph; fileIdx: FileIndex): PSym =
   if fileIdx.int32 >= 0 and fileIdx.int32 < modules.len:
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 08be515d1..5b75596b8 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -629,9 +629,9 @@ proc quotedFilename*(i: TLineInfo): Rope =
 ropes.errorHandler = proc (err: RopesError, msg: string, useWarning: bool) =
   case err
   of rInvalidFormatStr:
-    internalError(newConfigRef(), "ropes: invalid format string: " & msg)
+    internalError(newPartialConfigRef(), "ropes: invalid format string: " & msg)
   of rCannotOpenFile:
-    rawMessage(newConfigRef(), if useWarning: warnCannotOpenFile else: errCannotOpenFile, msg)
+    rawMessage(newPartialConfigRef(), if useWarning: warnCannotOpenFile else: errCannotOpenFile, msg)
 
 proc listWarnings*(conf: ConfigRef) =
   msgWriteln("Warnings:")
diff --git a/compiler/options.nim b/compiler/options.nim
index ec87ed805..4c5b6b668 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -141,6 +141,12 @@ proc newConfigRef*(): ConfigRef =
     notes: NotesVerbosity[1], mainPackageNotes: NotesVerbosity[1],
     symbols: newStringTable(modeStyleInsensitive))
 
+proc newPartialConfigRef*(): ConfigRef =
+  ## create a new ConfigRef that is only good enough for error reporting.
+  result = ConfigRef(foreignPackageNotes: {hintProcessing, warnUnknownMagic,
+    hintQuitCalled, hintExecuting},
+    notes: NotesVerbosity[1], mainPackageNotes: NotesVerbosity[1])
+
 proc cppDefine*(c: ConfigRef; define: string) =
   c.cppDefines.incl define
 
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 996168412..a47c77464 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -10,7 +10,7 @@
 # This module implements the renderer of the standard Nim representation.
 
 import
-  lexer, options, idents, strutils, ast, msgs
+  lexer, options, idents, strutils, ast, msgs, configuration
 
 type
   TRenderFlag* = enum
@@ -40,6 +40,7 @@ type
     when defined(nimpretty):
       pendingNewlineCount: int
     fid*: FileIndex
+    config*: ConfigRef
 
 # We render the source code in a two phases: The first
 # determines how long the subtree will likely be, the second
@@ -90,7 +91,7 @@ const
   MaxLineLen = 80
   LineCommentColumn = 30
 
-proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) =
+proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags; config: ConfigRef) =
   g.comStack = @[]
   g.tokens = @[]
   g.indent = 0
@@ -102,6 +103,7 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) =
   g.pendingNL = -1
   g.pendingWhitespace = -1
   g.inGenericParams = false
+  g.config = config
 
 proc addTok(g: var TSrcGen, kind: TTokType, s: string) =
   var length = len(g.tokens)
@@ -377,7 +379,7 @@ proc atom(g: TSrcGen; n: PNode): string =
     if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s
     else: result = "[type node]"
   else:
-    internalError("rnimsyn.atom " & $n.kind)
+    internalError(g.config, "rnimsyn.atom " & $n.kind)
     result = ""
 
 proc lcomma(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
@@ -1422,11 +1424,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     gTypeClassTy(g, n)
   else:
     #nkNone, nkExplicitTypeListCall:
-    internalError(n.info, "rnimsyn.gsub(" & $n.kind & ')')
+    internalError(g.config, n.info, "rnimsyn.gsub(" & $n.kind & ')')
 
 proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string =
   var g: TSrcGen
-  initSrcGen(g, renderFlags)
+  initSrcGen(g, renderFlags, newPartialConfigRef())
   # do not indent the initial statement list so that
   # writeFile("file.nim", repr n)
   # produces working Nim code:
@@ -1444,7 +1446,7 @@ proc renderModule*(n: PNode, infile, outfile: string,
   var
     f: File
     g: TSrcGen
-  initSrcGen(g, renderFlags)
+  initSrcGen(g, renderFlags, newPartialConfigRef())
   g.fid = fid
   for i in countup(0, sonsLen(n) - 1):
     gsub(g, n.sons[i])
@@ -1460,10 +1462,10 @@ proc renderModule*(n: PNode, infile, outfile: string,
     write(f, g.buf)
     close(f)
   else:
-    rawMessage(errCannotOpenFile, outfile)
+    rawMessage(g.config, errGenerated, "cannot open file: " & outfile)
 
 proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
-  initSrcGen(r, renderFlags)
+  initSrcGen(r, renderFlags, newPartialConfigRef())
   gsub(r, n)
 
 proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string) =
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index f55c3279c..9fab37632 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -90,7 +90,8 @@
 
 import
   os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
-  ropes, idents, std / sha1, idgen, types, rodutils, memfiles, tables
+  ropes, idents, std / sha1, idgen, types, rodutils, memfiles, tables,
+  configuration
 
 type
   TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
@@ -143,6 +144,7 @@ type
     origFile: string
     inViewMode: bool
     cache*: IdentCache
+    config: ConfigRef
 
   PRodReader* = ref TRodReader
 
@@ -222,14 +224,14 @@ proc decodeNodeLazyBody(r: PRodReader, fInfo: TLineInfo,
         var fl = decodeStr(r.s, r.pos)
         result.ident = r.cache.getIdent(fl)
       else:
-        internalError(result.info, "decodeNode: nkIdent")
+        internalError(r.config, result.info, "decodeNode: nkIdent")
     of nkSym:
       if r.s[r.pos] == '!':
         inc(r.pos)
         var id = decodeVInt(r.s, r.pos)
         result.sym = rrGetSym(r, id, result.info)
       else:
-        internalError(result.info, "decodeNode: nkSym")
+        internalError(r.config, result.info, "decodeNode: nkSym")
     else:
       var i = 0
       while r.s[r.pos] != ')':
@@ -241,9 +243,9 @@ proc decodeNodeLazyBody(r: PRodReader, fInfo: TLineInfo,
           addSonNilAllowed(result, decodeNodeLazyBody(r, result.info, nil))
         inc i
     if r.s[r.pos] == ')': inc(r.pos)
-    else: internalError(result.info, "decodeNode: ')' missing")
+    else: internalError(r.config, result.info, "decodeNode: ')' missing")
   else:
-    internalError(fInfo, "decodeNode: '(' missing " & $r.pos)
+    internalError(r.config, fInfo, "decodeNode: '(' missing " & $r.pos)
 
 proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
   result = decodeNodeLazyBody(r, fInfo, nil)
@@ -277,7 +279,7 @@ proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
     else:
       loc.r = nil
     if r.s[r.pos] == '>': inc(r.pos)
-    else: internalError(info, "decodeLoc " & r.s[r.pos])
+    else: internalError(r.config, info, "decodeLoc " & r.s[r.pos])
 
 proc decodeType(r: PRodReader, info: TLineInfo): PType =
   result = nil
@@ -294,7 +296,7 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
     setId(result.id)
     if debugIds: registerID(result)
   else:
-    internalError(info, "decodeType: no id")
+    internalError(r.config, 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())
@@ -345,14 +347,14 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
     doAssert r.s[r.pos] == '\20'
     inc(r.pos)
     let y = rrGetSym(r, decodeVInt(r.s, r.pos), info)
-    result.methods.safeAdd((x, y))
+    result.methods.add((x, y))
   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])
+      else: internalError(r.config, info, "decodeType ^(" & r.s[r.pos])
       rawAddSon(result, nil)
     else:
       var d = decodeVInt(r.s, r.pos)
@@ -364,10 +366,10 @@ proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
     new(result)
     inc(r.pos)
     result.kind = TLibKind(decodeVInt(r.s, r.pos))
-    if r.s[r.pos] != '|': internalError("decodeLib: 1")
+    if r.s[r.pos] != '|': internalError(r.config, "decodeLib: 1")
     inc(r.pos)
     result.name = rope(decodeStr(r.s, r.pos))
-    if r.s[r.pos] != '|': internalError("decodeLib: 2")
+    if r.s[r.pos] != '|': internalError(r.config, "decodeLib: 2")
     inc(r.pos)
     result.path = decodeNode(r, info)
 
@@ -385,7 +387,7 @@ proc decodeInstantiations(r: PRodReader; info: TLineInfo;
     if r.s[r.pos] == '\20':
       inc(r.pos)
       ii.compilesId = decodeVInt(r.s, r.pos)
-    s.safeAdd ii
+    s.add ii
 
 proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
   var
@@ -403,12 +405,12 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
     id = decodeVInt(r.s, r.pos)
     setId(id)
   else:
-    internalError(info, "decodeSym: no id")
+    internalError(r.config, info, "decodeSym: no id")
   if r.s[r.pos] == '&':
     inc(r.pos)
     ident = r.cache.getIdent(decodeStr(r.s, r.pos))
   else:
-    internalError(info, "decodeSym: no ident")
+    internalError(r.config, info, "decodeSym: no ident")
   #echo "decoding: {", ident.s
   result = r.syms.getOrDefault(id)
   if result == nil:
@@ -417,7 +419,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
     r.syms[result.id] = result
     if debugIds: registerID(result)
   elif result.id != id:
-    internalError(info, "decodeSym: wrong id")
+    internalError(r.config, info, "decodeSym: wrong id")
   elif result.kind != skStub and not r.inViewMode:
     # we already loaded the symbol
     return
@@ -465,7 +467,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
   of skType, skGenericParam:
     while r.s[r.pos] == '\14':
       inc(r.pos)
-      result.typeInstCache.safeAdd rrGetType(r, decodeVInt(r.s, r.pos), result.info)
+      result.typeInstCache.add rrGetType(r, decodeVInt(r.s, r.pos), result.info)
   of routineKinds:
     decodeInstantiations(r, result.info, result.procInstCache)
     if r.s[r.pos] == '\16':
@@ -512,7 +514,7 @@ proc skipSection(r: PRodReader) =
       else: discard
       inc(r.pos)
   else:
-    internalError("skipSection " & $r.line)
+    internalError(r.config, "skipSection " & $r.line)
 
 proc rdWord(r: PRodReader): string =
   result = ""
@@ -530,7 +532,7 @@ proc newStub(r: PRodReader, name: string, id: int): PSym =
   if debugIds: registerID(result)
 
 proc processInterf(r: PRodReader, module: PSym) =
-  if r.interfIdx == 0: internalError("processInterf")
+  if r.interfIdx == 0: internalError(r.config, "processInterf")
   r.pos = r.interfIdx
   while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
     var w = decodeStr(r.s, r.pos)
@@ -543,7 +545,7 @@ proc processInterf(r: PRodReader, module: PSym) =
     r.syms[s.id] = s
 
 proc processCompilerProcs(r: PRodReader, module: PSym) =
-  if r.compilerProcsIdx == 0: internalError("processCompilerProcs")
+  if r.compilerProcsIdx == 0: internalError(r.config, "processCompilerProcs")
   r.pos = r.compilerProcsIdx
   while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
     var w = decodeStr(r.s, r.pos)
@@ -637,10 +639,10 @@ proc processRodFile(r: PRodReader, hash: SecureHash) =
       while r.s[r.pos] > '\x0A':
         w = decodeStr(r.s, r.pos)
         inc(d)
-        if not condsyms.isDefined(r.cache.getIdent(w)):
+        if not isDefined(r.config, w):
           r.reason = rrDefines #MessageOut('not defined, but should: ' + w);
         if r.s[r.pos] == ' ': inc(r.pos)
-      if d != countDefinedSymbols(): r.reason = rrDefines
+      if d != countDefinedSymbols(r.config.symbols): r.reason = rrDefines
     of "FILES":
       inc(r.pos, 2)           # skip "(\10"
       inc(r.line)
@@ -648,7 +650,7 @@ proc processRodFile(r: PRodReader, hash: SecureHash) =
         let finalPath = decodeStr(r.s, r.pos)
         #let resolvedPath = relativePath.findModule(r.origFile)
         #let finalPath = if resolvedPath.len > 0: resolvedPath else: relativePath
-        r.files.add(finalPath.fileInfoIdx)
+        r.files.add(fileInfoIdx(r.config, finalPath))
         inc(r.pos)            # skip #10
         inc(r.line)
       if r.s[r.pos] == ')': inc(r.pos)
@@ -696,7 +698,7 @@ proc processRodFile(r: PRodReader, hash: SecureHash) =
       r.initIdx = r.pos + 2   # "(\10"
       skipSection(r)
     else:
-      internalError("invalid section: '" & section &
+      internalError(r.config, "invalid section: '" & section &
                     "' at " & $r.line & " in " & r.filename)
       #MsgWriteln("skipping section: " & section &
       #           " at " & $r.line & " in " & r.filename)
@@ -712,9 +714,11 @@ proc startsWith(buf: cstring, token: string, pos = 0): bool =
   result = s == token.len
 
 proc newRodReader(modfilename: string, hash: SecureHash,
-                  readerIndex: int; cache: IdentCache): PRodReader =
+                  readerIndex: int; cache: IdentCache;
+                  config: ConfigRef): PRodReader =
   new(result)
   result.cache = cache
+  result.config = config
   try:
     result.memfile = memfiles.open(modfilename)
   except OSError:
@@ -757,13 +761,13 @@ proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType =
     # load the type:
     var oldPos = r.pos
     var d = iiTableGet(r.index.tab, id)
-    if d == InvalidKey: internalError(info, "rrGetType")
+    if d == InvalidKey: internalError(r.config, info, "rrGetType")
     r.pos = d + r.dataIdx
     result = decodeType(r, info)
     r.pos = oldPos
 
 type
-  TFileModuleRec{.final.} = object
+  TFileModuleRec = object
     filename*: string
     reason*: TReasonForRecompile
     rd*: PRodReader
@@ -776,7 +780,7 @@ var gMods*: TFileModuleMap = @[]
 
 proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym =
   # all compiled modules
-  if rd.dataIdx == 0: internalError(info, "dataIdx == 0")
+  if rd.dataIdx == 0: internalError(rd.config, info, "dataIdx == 0")
   var oldPos = rd.pos
   rd.pos = offset + rd.dataIdx
   result = decodeSym(rd, info)
@@ -811,7 +815,7 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
       if moduleID < 0:
         var x = ""
         encodeVInt(id, x)
-        internalError(info, "missing from both indexes: +" & x)
+        internalError(r.config, info, "missing from both indexes: +" & x)
       var rd = getReader(moduleID)
       doAssert rd != nil
       d = iiTableGet(rd.index.tab, id)
@@ -821,14 +825,14 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
         var x = ""
         encodeVInt(id, x)
         when false: findSomeWhere(id)
-        internalError(info, "rrGetSym: no reader found: +" & x)
+        internalError(r.config, info, "rrGetSym: no reader found: +" & x)
     else:
       # own symbol:
       result = decodeSymSafePos(r, d, info)
   if result != nil and result.kind == skStub: rawLoadStub(result)
 
 proc loadInitSection*(r: PRodReader): PNode =
-  if r.initIdx == 0 or r.dataIdx == 0: internalError("loadInitSection")
+  if r.initIdx == 0 or r.dataIdx == 0: internalError(r.config, "loadInitSection")
   var oldPos = r.pos
   r.pos = r.initIdx
   result = newNode(nkStmtList)
@@ -845,7 +849,7 @@ proc loadConverters(r: PRodReader) =
   # We have to ensure that no exported converter is a stub anymore, and the
   # import mechanism takes care of the rest.
   if r.convertersIdx == 0 or r.dataIdx == 0:
-    internalError("importConverters")
+    internalError(r.config, "importConverters")
   r.pos = r.convertersIdx
   while r.s[r.pos] > '\x0A':
     var d = decodeVInt(r.s, r.pos)
@@ -854,7 +858,7 @@ proc loadConverters(r: PRodReader) =
 
 proc loadMethods(r: PRodReader) =
   if r.methodsIdx == 0 or r.dataIdx == 0:
-    internalError("loadMethods")
+    internalError(r.config, "loadMethods")
   r.pos = r.methodsIdx
   while r.s[r.pos] > '\x0A':
     var d = decodeVInt(r.s, r.pos)
@@ -872,7 +876,7 @@ proc getHash*(fileIdx: FileIndex): SecureHash =
 template growCache*(cache, pos) =
   if cache.len <= pos: cache.setLen(pos+1)
 
-proc checkDep(fileIdx: FileIndex; cache: IdentCache): TReasonForRecompile =
+proc checkDep(fileIdx: FileIndex; cache: IdentCache; conf: ConfigRef): TReasonForRecompile =
   assert fileIdx != InvalidFileIDX
   growCache gMods, fileIdx.int32
   if gMods[fileIdx.int32].reason != rrEmpty:
@@ -882,8 +886,8 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache): TReasonForRecompile =
   var hash = getHash(fileIdx)
   gMods[fileIdx.int32].reason = rrNone  # we need to set it here to avoid cycles
   result = rrNone
-  var rodfile = toGeneratedFile(filename.withPackageName, RodExt)
-  var r = newRodReader(rodfile, hash, fileIdx.int32, cache)
+  var rodfile = toGeneratedFile(conf, filename.withPackageName, RodExt)
+  var r = newRodReader(rodfile, hash, fileIdx.int32, cache, conf)
   if r == nil:
     result = (if existsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
   else:
@@ -894,15 +898,15 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache): TReasonForRecompile =
       # 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(systemFileIdx, cache)
+      var res = checkDep(systemFileIdx, cache, conf)
       if res != rrNone: result = rrModDeps
       for i in countup(0, high(r.modDeps)):
-        res = checkDep(r.modDeps[i], cache)
+        res = checkDep(r.modDeps[i], cache, conf)
         if res != rrNone:
           result = rrModDeps
           # we cannot break here, because of side-effects of `checkDep`
   if result != rrNone:
-    rawMessage(hintProcessing, reasonToFrmt[result] % filename)
+    rawMessage(conf, hintProcessing, reasonToFrmt[result] % filename)
   if result != rrNone or optForceFullMake in gGlobalOptions:
     # recompilation is necessary:
     if r != nil: memfiles.close(r.memfile)
@@ -910,14 +914,14 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache): TReasonForRecompile =
   gMods[fileIdx.int32].rd = r
   gMods[fileIdx.int32].reason = result  # now we know better
 
-proc handleSymbolFile*(module: PSym; cache: IdentCache): PRodReader =
+proc handleSymbolFile*(module: PSym; cache: IdentCache; conf: ConfigRef): PRodReader =
   if gSymbolFiles in {disabledSf, writeOnlySf, v2Sf}:
     module.id = getID()
     return nil
-  idgen.loadMaxIds(options.gProjectPath / options.gProjectName)
+  idgen.loadMaxIds(conf, options.gProjectPath / options.gProjectName)
   let fileIdx = module.fileIdx
-  discard checkDep(fileIdx, cache)
-  if gMods[fileIdx.int32].reason == rrEmpty: internalError("handleSymbolFile")
+  discard checkDep(fileIdx, cache, conf)
+  #if gMods[fileIdx.int32].reason == rrEmpty: internalError("handleSymbolFile")
   result = gMods[fileIdx.int32].rd
   if result != nil:
     module.id = result.moduleID
@@ -930,19 +934,20 @@ proc handleSymbolFile*(module: PSym; cache: IdentCache): PRodReader =
     module.id = getID()
 
 proc rawLoadStub(s: PSym) =
-  if s.kind != skStub: internalError("loadStub")
+  assert s.kind == skStub
+  #if s.kind != skStub: internalError("loadStub")
   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")
+  #if d == InvalidKey: internalError("loadStub: invalid key")
   var rs = decodeSymSafePos(rd, d, unknownLineInfo())
-  if rs != s:
-    #echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2),
-    #     "\ns:  ", toHex(cast[int](s.position), int.sizeof * 2)
-    internalError(rs.info, "loadStub: wrong symbol")
-  elif rs.id != theId:
-    internalError(rs.info, "loadStub: wrong ID")
-  #MessageOut('loaded stub: ' + s.name.s);
+  when false:
+    if rs != s:
+      #echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2),
+      #     "\ns:  ", toHex(cast[int](s.position), int.sizeof * 2)
+      internalError(rs.info, "loadStub: wrong symbol")
+    elif rs.id != theId:
+      internalError(rs.info, "loadStub: wrong ID")
 
 proc loadStub*(s: PSym) =
   ## loads the stub symbol `s`.
@@ -1083,9 +1088,10 @@ proc writeType(f: File; t: PType) =
   f.write("]\n")
 
 proc viewFile(rodfile: string) =
-  var r = newRodReader(rodfile, secureHash(""), 0, newIdentCache())
+  let conf = newConfigRef()
+  var r = newRodReader(rodfile, secureHash(""), 0, newIdentCache(), conf)
   if r == nil:
-    rawMessage(errGenerated, "cannot open file (or maybe wrong version):" &
+    rawMessage(conf, errGenerated, "cannot open file (or maybe wrong version):" &
        rodfile)
     return
   r.inViewMode = true
@@ -1133,9 +1139,9 @@ proc viewFile(rodfile: string) =
       outf.write("FILES(\n")
       while r.s[r.pos] != ')':
         let relativePath = decodeStr(r.s, r.pos)
-        let resolvedPath = relativePath.findModule(r.origFile)
+        let resolvedPath = findModule(conf, relativePath, r.origFile)
         let finalPath = if resolvedPath.len > 0: resolvedPath else: relativePath
-        r.files.add(finalPath.fileInfoIdx)
+        r.files.add(fileInfoIdx(conf, finalPath))
         inc(r.pos)            # skip #10
         inc(r.line)
         outf.writeLine finalPath
@@ -1227,7 +1233,7 @@ proc viewFile(rodfile: string) =
       if r.s[r.pos] == ')': inc r.pos
       outf.write("<not supported by viewer>)\n")
     else:
-      internalError("invalid section: '" & section &
+      internalError(r.config, "invalid section: '" & section &
                     "' at " & $r.line & " in " & r.filename)
       skipSection(r)
     if r.s[r.pos] == '\x0A':
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index 974df50fb..4a6474912 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -11,7 +11,7 @@
 
 import
   strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser,
-  filters, filter_tmpl, renderer
+  filters, filter_tmpl, renderer, configuration
 
 type
   TFilterKind* = enum
@@ -30,12 +30,14 @@ type
     skin*: TParserKind
     parser*: TParser
 
+template config(p: TParsers): ConfigRef = p.parser.lex.config
+
 proc parseAll*(p: var TParsers): PNode =
   case p.skin
   of skinStandard, skinStrongSpaces:
     result = parser.parseAll(p.parser)
   of skinEndX:
-    internalError("parser to implement")
+    internalError(p.config, "parser to implement")
     result = ast.emptyNode
 
 proc parseTopLevelStmt*(p: var TParsers): PNode =
@@ -43,7 +45,7 @@ proc parseTopLevelStmt*(p: var TParsers): PNode =
   of skinStandard, skinStrongSpaces:
     result = parser.parseTopLevelStmt(p.parser)
   of skinEndX:
-    internalError("parser to implement")
+    internalError(p.config, "parser to implement")
     result = ast.emptyNode
 
 proc utf8Bom(s: string): int =
@@ -86,39 +88,39 @@ proc getFilter(ident: PIdent): TFilterKind =
       return i
   result = filtNone
 
-proc getParser(ident: PIdent): TParserKind =
+proc getParser(conf: ConfigRef; n: PNode; ident: PIdent): TParserKind =
   for i in countup(low(TParserKind), high(TParserKind)):
     if cmpIgnoreStyle(ident.s, parserNames[i]) == 0:
       return i
-  rawMessage(errInvalidDirectiveX, ident.s)
+  localError(conf, n.info, "unknown parser: " & ident.s)
 
-proc getCallee(n: PNode): PIdent =
+proc getCallee(conf: ConfigRef; n: PNode): PIdent =
   if n.kind in nkCallKinds and n.sons[0].kind == nkIdent:
     result = n.sons[0].ident
   elif n.kind == nkIdent:
     result = n.ident
   else:
-    rawMessage(errXNotAllowedHere, renderTree(n))
+    localError(conf, n.info, "invalid filter: " & renderTree(n))
 
 proc applyFilter(p: var TParsers, n: PNode, filename: string,
                  stdin: PLLStream): PLLStream =
-  var ident = getCallee(n)
+  var ident = getCallee(p.config, n)
   var f = getFilter(ident)
   case f
   of filtNone:
-    p.skin = getParser(ident)
+    p.skin = getParser(p.config, n, ident)
     result = stdin
   of filtTemplate:
-    result = filterTmpl(stdin, filename, n)
+    result = filterTmpl(stdin, filename, n, p.config)
   of filtStrip:
-    result = filterStrip(stdin, filename, n)
+    result = filterStrip(p.config, stdin, filename, n)
   of filtReplace:
-    result = filterReplace(stdin, filename, n)
+    result = filterReplace(p.config, stdin, filename, n)
   if f != filtNone:
-    if hintCodeBegin in gNotes:
-      rawMessage(hintCodeBegin, [])
+    if hintCodeBegin in p.config.notes:
+      rawMessage(p.config, hintCodeBegin, [])
       msgWriteln(result.s)
-      rawMessage(hintCodeEnd, [])
+      rawMessage(p.config, hintCodeEnd, [])
 
 proc evalPipe(p: var TParsers, n: PNode, filename: string,
               start: PLLStream): PLLStream =
@@ -158,7 +160,7 @@ proc parseFile*(fileIdx: FileIndex; cache: IdentCache; config: ConfigRef): PNode
     f: File
   let filename = fileIdx.toFullPathConsiderDirty
   if not open(f, filename):
-    rawMessage(errCannotOpenFile, filename)
+    rawMessage(config, errGenerated, "cannot open file: " & filename)
     return
   openParsers(p, fileIdx, llStreamOpen(f), cache, config)
   result = parseAll(p)
diff --git a/compiler/types.nim b/compiler/types.nim
index edf4e5b46..a5c053488 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -10,7 +10,7 @@
 # this module contains routines for accessing and iterating over types
 
 import
-  intsets, ast, astalgo, trees, msgs, strutils, platform, renderer
+  intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options
 
 type
   TPreferedDesc* = enum
@@ -92,8 +92,9 @@ proc getOrdValue*(n: PNode): BiggestInt =
   of nkNilLit: result = 0
   of nkHiddenStdConv: result = getOrdValue(n.sons[1])
   else:
-    localError(n.info, errOrdinalTypeExpected)
-    result = 0
+    #localError(n.info, errOrdinalTypeExpected)
+    # XXX check usages of getOrdValue
+    result = high(BiggestInt)
 
 proc isIntLit*(t: PType): bool {.inline.} =
   result = t.kind == tyInt and t.n != nil and t.n.kind == nkIntLit
@@ -105,14 +106,14 @@ proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string =
   result = sym.owner.name.s & '.' & sym.name.s & '('
   var n = sym.typ.n
   for i in countup(1, sonsLen(n) - 1):
-    var p = n.sons[i]
+    let p = n.sons[i]
     if p.kind == nkSym:
       add(result, p.sym.name.s)
       add(result, ": ")
       add(result, typeToString(p.sym.typ, prefer))
       if i != sonsLen(n)-1: add(result, ", ")
     else:
-      internalError("getProcHeader")
+      result.add renderTree(p)
   add(result, ')')
   if n.sons[0].typ != nil:
     result.add(": " & typeToString(n.sons[0].typ, prefer))
@@ -195,10 +196,10 @@ proc searchTypeNodeForAux(n: PNode, p: TTypePredicate,
       of nkOfBranch, nkElse:
         result = searchTypeNodeForAux(lastSon(n.sons[i]), p, marker)
         if result: return
-      else: internalError("searchTypeNodeForAux(record case branch)")
+      else: discard
   of nkSym:
     result = searchTypeForAux(n.sym.typ, p, marker)
-  else: internalError(n.info, "searchTypeNodeForAux()")
+  else: discard
 
 proc searchTypeForAux(t: PType, predicate: TTypePredicate,
                       marker: var IntSet): bool =
@@ -244,7 +245,7 @@ proc analyseObjectWithTypeFieldAux(t: PType,
   if t == nil: return
   case t.kind
   of tyObject:
-    if (t.n != nil):
+    if t.n != nil:
       if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
         return frEmbedded
     for i in countup(0, sonsLen(t) - 1):
@@ -453,16 +454,17 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     if t.sons[0].kind == tyNone: result = "typedesc"
     else: result = "type " & typeToString(t.sons[0])
   of tyStatic:
-    internalAssert t.len > 0
     if prefer == preferGenericArg and t.n != nil:
       result = t.n.renderTree
     else:
-      result = "static[" & typeToString(t.sons[0]) & "]"
+      result = "static[" & (if t.len > 0: typeToString(t.sons[0]) else: "") & "]"
       if t.n != nil: result.add "(" & renderTree(t.n) & ")"
   of tyUserTypeClass:
-    internalAssert t.sym != nil and t.sym.owner != nil
-    if t.isResolvedUserTypeClass: return typeToString(t.lastSon)
-    return t.sym.owner.name.s
+    if t.sym != nil and t.sym.owner != nil:
+      if t.isResolvedUserTypeClass: return typeToString(t.lastSon)
+      return t.sym.owner.name.s
+    else:
+      result = "<invalid tyUserTypeClass>"
   of tyBuiltInTypeClass:
     result = case t.base.kind:
       of tyVar: "var"
@@ -496,7 +498,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
   of tyNot:
     result = "not " & typeToString(t.sons[0])
   of tyExpr:
-    internalAssert t.len == 0
+    #internalAssert t.len == 0
     result = "untyped"
   of tyFromExpr:
     result = renderTree(t.n)
@@ -616,9 +618,9 @@ proc firstOrd*(t: PType): BiggestInt =
     result = firstOrd(lastSon(t))
   of tyOrdinal:
     if t.len > 0: result = firstOrd(lastSon(t))
-    else: internalError("invalid kind for firstOrd(" & $t.kind & ')')
+    else: internalError(newPartialConfigRef(), "invalid kind for firstOrd(" & $t.kind & ')')
   else:
-    internalError("invalid kind for firstOrd(" & $t.kind & ')')
+    internalError(newPartialConfigRef(), "invalid kind for firstOrd(" & $t.kind & ')')
     result = 0
 
 proc lastOrd*(t: PType; fixedUnsigned = false): BiggestInt =
@@ -656,9 +658,9 @@ proc lastOrd*(t: PType; fixedUnsigned = false): BiggestInt =
   of tyProxy: result = 0
   of tyOrdinal:
     if t.len > 0: result = lastOrd(lastSon(t))
-    else: internalError("invalid kind for lastOrd(" & $t.kind & ')')
+    else: internalError(newPartialConfigRef(), "invalid kind for lastOrd(" & $t.kind & ')')
   else:
-    internalError("invalid kind for lastOrd(" & $t.kind & ')')
+    internalError(newPartialConfigRef(), "invalid kind for lastOrd(" & $t.kind & ')')
     result = 0
 
 proc lengthOrd*(t: PType): BiggestInt =
@@ -748,7 +750,7 @@ proc equalParam(a, b: PSym): TParamsEquality =
 
 proc sameConstraints(a, b: PNode): bool =
   if isNil(a) and isNil(b): return true
-  internalAssert a.len == b.len
+  if a.len != b.len: return false
   for i in 1 ..< a.len:
     if not exprStructuralEquivalent(a[i].sym.constraint,
                                     b[i].sym.constraint):
@@ -807,7 +809,8 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
           var y = b.n.sons[i].sym
           result = x.name.id == y.name.id
           if not result: break
-        else: internalError(a.n.info, "sameTuple")
+        else:
+          return false
     elif a.n != b.n and (a.n == nil or b.n == nil) and IgnoreTupleFields notin c.flags:
       result = false
 
@@ -997,7 +1000,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     cycleCheck()
     result = sameTypeAux(a.lastSon, b.lastSon, c)
   of tyNone: result = false
-  of tyUnused, tyOptAsRef: internalError("sameFlags")
+  of tyUnused, tyOptAsRef: result = false
 
 proc sameBackendType*(x, y: PType): bool =
   var c = initSameTypeClosure()
@@ -1191,7 +1194,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     # for now same as error node; we say it's a valid type as it should
     # prevent cascading errors:
     result = nil
-  of tyUnused, tyOptAsRef: internalError("typeAllowedAux")
+  of tyUnused, tyOptAsRef: result = t
 
 proc typeAllowed*(t: PType, kind: TSymKind; flags: TTypeAllowedFlags = {}): PType =
   # returns 'nil' on success and otherwise the part of the type that is
@@ -1280,7 +1283,8 @@ proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt =
         if res < 0: return res
         maxSize = max(maxSize, res)
         maxAlign = max(maxAlign, b)
-      else: internalError("computeRecSizeAux(record case branch)")
+      else:
+        return szIllegalRecursion
     currOffset = align(currOffset, maxAlign) + maxSize
     result = align(result, maxAlign) + maxSize
     a = maxAlign
@@ -1441,7 +1445,8 @@ proc getReturnType*(s: PSym): PType =
 
 proc getSize*(typ: PType): BiggestInt =
   result = computeSize(typ)
-  if result < 0: internalError("getSize: " & $typ.kind)
+  #if result < 0: internalError("getSize: " & $typ.kind)
+  # XXX review all usages of 'getSize'
 
 proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
   case t.kind
@@ -1469,8 +1474,7 @@ proc baseOfDistinct*(t: PType): PType =
     while it.kind in {tyPtr, tyRef}:
       parent = it
       it = it.lastSon
-    if it.kind == tyDistinct:
-      internalAssert parent != nil
+    if it.kind == tyDistinct and parent != nil:
       parent.sons[0] = it.sons[0]
 
 proc safeInheritanceDiff*(a, b: PType): int =
@@ -1502,8 +1506,9 @@ type
 proc compatibleEffects*(formal, actual: PType): EffectsCompat =
   # for proc type compatibility checking:
   assert formal.kind == tyProc and actual.kind == tyProc
-  internalAssert formal.n.sons[0].kind == nkEffectList
-  internalAssert actual.n.sons[0].kind == nkEffectList
+  if formal.n.sons[0].kind != nkEffectList or
+     actual.n.sons[0].kind != nkEffectList:
+    return efTagsUnknown
 
   var spec = formal.n.sons[0]
   if spec.len != 0:
@@ -1628,14 +1633,14 @@ proc skipHiddenSubConv*(n: PNode): PNode =
   else:
     result = n
 
-proc typeMismatch*(info: TLineInfo, formal, actual: PType) =
+proc typeMismatch*(conf: ConfigRef; info: TLineInfo, formal, actual: PType) =
   if formal.kind != tyError and actual.kind != tyError:
     let named = typeToString(formal)
     let desc = typeToString(formal, preferDesc)
     let x = if named == desc: named else: named & " = " & desc
-    var msg = msgKindToString(errTypeMismatch) &
+    var msg = "type mismatch: got <" &
               typeToString(actual) & "> " &
-              msgKindToString(errButExpectedX) % [x]
+              "but expected " & x & "'"
 
     if formal.kind == tyProc and actual.kind == tyProc:
       case compatibleEffects(formal, actual)
@@ -1650,4 +1655,4 @@ proc typeMismatch*(info: TLineInfo, formal, actual: PType) =
         msg.add "\n.tag effect is 'any tag allowed'"
       of efLockLevelsDiffer:
         msg.add "\nlock levels differ"
-    localError(info, errGenerated, msg)
+    localError(conf, info, msg)