summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/aliases.nim8
-rw-r--r--compiler/ast.nim25
-rw-r--r--compiler/astalgo.nim90
-rw-r--r--compiler/bitsets.nim6
-rw-r--r--compiler/canonicalizer.nim4
-rw-r--r--compiler/ccgcalls.nim6
-rw-r--r--compiler/ccgexprs.nim50
-rw-r--r--compiler/ccgmerge.nim8
-rw-r--r--compiler/ccgstmts.nim32
-rw-r--r--compiler/ccgthreadvars.nim11
-rw-r--r--compiler/ccgtrav.nim10
-rw-r--r--compiler/ccgtypes.nim38
-rw-r--r--compiler/ccgutils.nim6
-rw-r--r--compiler/cgen.nim90
-rw-r--r--compiler/cgendata.nim10
-rw-r--r--compiler/cgmeth.nim8
-rw-r--r--compiler/commands.nim56
-rw-r--r--compiler/condsyms.nim5
-rw-r--r--compiler/crc.nim4
-rw-r--r--compiler/depends.nim2
-rw-r--r--compiler/docgen.nim14
-rw-r--r--compiler/docgen2.nim4
-rw-r--r--compiler/evalffi.nim4
-rw-r--r--compiler/evaltempl.nim2
-rw-r--r--compiler/extccomp.nim122
-rw-r--r--compiler/filter_tmpl.nim6
-rw-r--r--compiler/filters.nim4
-rw-r--r--compiler/guards.nim18
-rw-r--r--compiler/hlo.nim2
-rw-r--r--compiler/idents.nim4
-rw-r--r--compiler/idgen.nim4
-rw-r--r--compiler/importer.nim10
-rw-r--r--compiler/jsgen.nim13
-rw-r--r--compiler/jstypes.nim2
-rw-r--r--compiler/lambdalifting.nim8
-rw-r--r--compiler/lexer.nim83
-rw-r--r--compiler/lists.nim4
-rw-r--r--compiler/llstream.nim14
-rw-r--r--compiler/lookups.nim2
-rw-r--r--compiler/lowerings.nim14
-rw-r--r--compiler/magicsys.nim14
-rw-r--r--compiler/main.nim62
-rw-r--r--compiler/modules.nim18
-rw-r--r--compiler/msgs.nim30
-rw-r--r--compiler/nim.ini (renamed from compiler/nimrod.ini)28
-rw-r--r--compiler/nim.nim (renamed from compiler/nimrod.nim)10
-rw-r--r--compiler/nim.nimrod.cfg (renamed from compiler/nimrod.nimrod.cfg)5
-rw-r--r--compiler/nimblecmd.nim (renamed from compiler/babelcmd.nim)20
-rw-r--r--compiler/nimconf.nim13
-rw-r--r--compiler/nimeval.nim4
-rw-r--r--compiler/nimfix/prettybase.nim2
-rw-r--r--compiler/nimlexbase.nim4
-rw-r--r--compiler/nimsets.nim4
-rw-r--r--compiler/nversion.nim8
-rw-r--r--compiler/options.nim28
-rw-r--r--compiler/parampatterns.nim2
-rw-r--r--compiler/parser.nim6
-rw-r--r--compiler/passaux.nim2
-rw-r--r--compiler/passes.nim4
-rw-r--r--compiler/patterns.nim2
-rw-r--r--compiler/pbraces.nim2
-rw-r--r--compiler/pragmas.nim30
-rw-r--r--compiler/pretty.nim281
-rw-r--r--compiler/procfind.nim10
-rw-r--r--compiler/readme.txt4
-rw-r--r--compiler/renderer.nim10
-rw-r--r--compiler/rodread.nim23
-rw-r--r--compiler/rodutils.nim2
-rw-r--r--compiler/rodwrite.nim9
-rw-r--r--compiler/ropes.nim14
-rw-r--r--compiler/saturate.nim2
-rw-r--r--compiler/sem.nim15
-rw-r--r--compiler/semasgn.nim197
-rw-r--r--compiler/semcall.nim46
-rw-r--r--compiler/semdata.nim14
-rw-r--r--compiler/semdestruct.nim2
-rw-r--r--compiler/semexprs.nim54
-rw-r--r--compiler/semfold.nim7
-rw-r--r--compiler/semgnrc.nim65
-rw-r--r--compiler/seminst.nim2
-rw-r--r--compiler/semmacrosanity.nim4
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/semparallel.nim12
-rw-r--r--compiler/sempass2.nim248
-rw-r--r--compiler/semstmts.nim51
-rw-r--r--compiler/semtempl.nim22
-rw-r--r--compiler/semtypes.nim49
-rw-r--r--compiler/semtypinst.nim9
-rw-r--r--compiler/service.nim36
-rw-r--r--compiler/sigmatch.nim43
-rw-r--r--compiler/suggest.nim5
-rw-r--r--compiler/syntaxes.nim4
-rw-r--r--compiler/tccgen.nim2
-rw-r--r--compiler/transf.nim6
-rw-r--r--compiler/trees.nim2
-rw-r--r--compiler/treetab.nim2
-rw-r--r--compiler/types.nim114
-rw-r--r--compiler/vm.nim37
-rw-r--r--compiler/vmdef.nim15
-rw-r--r--compiler/vmdeps.nim6
-rw-r--r--compiler/vmgen.nim37
-rw-r--r--compiler/vmhooks.nim45
-rw-r--r--compiler/vmops.nim75
-rw-r--r--compiler/wordrecg.nim2
104 files changed, 1601 insertions, 1085 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim
index a26b94303..3f3d45ff7 100644
--- a/compiler/aliases.nim
+++ b/compiler/aliases.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -16,9 +16,9 @@ type
   TAnalysisResult* = enum
     arNo, arMaybe, arYes
 
-proc isPartOfAux(a, b: PType, marker: var TIntSet): TAnalysisResult
+proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult
 
-proc isPartOfAux(n: PNode, b: PType, marker: var TIntSet): TAnalysisResult =
+proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
   result = arNo
   case n.kind
   of nkRecList: 
@@ -39,7 +39,7 @@ proc isPartOfAux(n: PNode, b: PType, marker: var TIntSet): TAnalysisResult =
     result = isPartOfAux(n.sym.typ, b, marker)
   else: internalError(n.info, "isPartOfAux()")
   
-proc isPartOfAux(a, b: PType, marker: var TIntSet): TAnalysisResult = 
+proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult = 
   result = arNo
   if a == nil or b == nil: return 
   if containsOrIncl(marker, a.id): return 
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 0c828a6d9..db6003b87 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -681,7 +681,6 @@ type
     heapRoot*: PRope          # keeps track of the enclosing heap object that
                               # owns this location (required by GC algorithms
                               # employing heap snapshots or sliding views)
-    a*: int
 
   # ---------------- end of backend information ------------------------------
 
@@ -772,6 +771,7 @@ type
                               # it won't cause problems
   
   TTypeSeq* = seq[PType]
+  TLockLevel* = distinct int16
   TType* {.acyclic.} = object of TIdObj # \
                               # types are identical iff they have the
                               # same id; there may be multiple copies of a type
@@ -798,11 +798,12 @@ type
     deepCopy*: PSym           # overriden 'deepCopy' operation
     size*: BiggestInt         # the size of the type in bytes
                               # -1 means that the size is unkwown
-    align*: int               # the type's alignment requirements
+    align*: int16             # the type's alignment requirements
+    lockLevel*: TLockLevel    # lock level as required for deadlock checking
     loc*: TLoc
 
   TPair*{.final.} = object 
-    key*, val*: PObject
+    key*, val*: RootRef
 
   TPairSeq* = seq[TPair]
   TTable*{.final.} = object   # the same as table[PObject] of PObject
@@ -811,7 +812,7 @@ type
 
   TIdPair*{.final.} = object 
     key*: PIdObj
-    val*: PObject
+    val*: RootRef
 
   TIdPairSeq* = seq[TIdPair]
   TIdTable*{.final.} = object # the same as table[PIdent] of PObject
@@ -838,7 +839,7 @@ type
     counter*: int
     data*: TNodePairSeq
 
-  TObjectSeq* = seq[PObject]
+  TObjectSeq* = seq[RootRef]
   TObjectSet*{.final.} = object 
     counter*: int
     data*: TObjectSeq
@@ -1166,6 +1167,16 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
   result.sons = @[name, pattern, genericParams, params,
                   pragmas, exceptions, body]
 
+const
+  UnspecifiedLockLevel* = TLockLevel(-1'i16)
+  MaxLockLevel* = 1000'i16
+  UnknownLockLevel* = TLockLevel(1001'i16)
+
+proc `$`*(x: TLockLevel): string =
+  if x.ord == UnspecifiedLockLevel.ord: result = "<unspecified>"
+  elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
+  else: result = $int16(x)
+
 proc newType(kind: TTypeKind, owner: PSym): PType = 
   new(result)
   result.kind = kind
@@ -1173,6 +1184,7 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
   result.size = - 1
   result.align = 2            # default alignment
   result.id = getID()
+  result.lockLevel = UnspecifiedLockLevel
   when debugIds:
     registerId(result)
   #if result.id < 2000:
@@ -1184,7 +1196,7 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
   a.flags = a.flags + b.flags
   if a.t == nil: a.t = b.t
   if a.r == nil: a.r = b.r
-  if a.a == 0: a.a = b.a
+  #if a.a == 0: a.a = b.a
   
 proc assignType(dest, src: PType) = 
   dest.kind = src.kind
@@ -1195,6 +1207,7 @@ proc assignType(dest, src: PType) =
   dest.align = src.align
   dest.destructor = src.destructor
   dest.deepCopy = src.deepCopy
+  dest.lockLevel = src.lockLevel
   # this fixes 'type TLock = TSysLock':
   if src.sym != nil:
     if dest.sym != nil:
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index eb7ffc63e..110b0c26e 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -14,7 +14,7 @@
 import 
   ast, hashes, intsets, strutils, options, msgs, ropes, idents, rodutils
 
-proc hashNode*(p: PObject): THash
+proc hashNode*(p: RootRef): THash
 proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope
   # Convert a tree into its YAML representation; this is used by the
   # YAML code generator and it is invaluable for debugging purposes.
@@ -24,21 +24,21 @@ proc symToYaml*(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope
 proc lineInfoToStr*(info: TLineInfo): PRope
   
 # ----------------------- node sets: ---------------------------------------
-proc objectSetContains*(t: TObjectSet, obj: PObject): bool
+proc objectSetContains*(t: TObjectSet, obj: RootRef): bool
   # returns true whether n is in t
-proc objectSetIncl*(t: var TObjectSet, obj: PObject)
+proc objectSetIncl*(t: var TObjectSet, obj: RootRef)
   # include an element n in the table t
-proc objectSetContainsOrIncl*(t: var TObjectSet, obj: PObject): bool
+proc objectSetContainsOrIncl*(t: var TObjectSet, obj: RootRef): bool
   # more are not needed ...
 
 # ----------------------- (key, val)-Hashtables ----------------------------
-proc tablePut*(t: var TTable, key, val: PObject)
-proc tableGet*(t: TTable, key: PObject): PObject
+proc tablePut*(t: var TTable, key, val: RootRef)
+proc tableGet*(t: TTable, key: RootRef): RootRef
 type 
-  TCmpProc* = proc (key, closure: PObject): bool {.nimcall.} # true if found
+  TCmpProc* = proc (key, closure: RootRef): bool {.nimcall.} # true if found
 
-proc tableSearch*(t: TTable, key, closure: PObject, 
-                  comparator: TCmpProc): PObject
+proc tableSearch*(t: TTable, key, closure: RootRef, 
+                  comparator: TCmpProc): RootRef
   # return val as soon as comparator returns true; if this never happens,
   # nil is returned
 
@@ -79,9 +79,9 @@ proc debug*(n: PType) {.deprecated.}
 proc debug*(n: PNode) {.deprecated.}
 
 # --------------------------- ident tables ----------------------------------
-proc idTableGet*(t: TIdTable, key: PIdObj): PObject
-proc idTableGet*(t: TIdTable, key: int): PObject
-proc idTablePut*(t: var TIdTable, key: PIdObj, val: PObject)
+proc idTableGet*(t: TIdTable, key: PIdObj): RootRef
+proc idTableGet*(t: TIdTable, key: int): RootRef
+proc idTablePut*(t: var TIdTable, key: PIdObj, val: RootRef)
 proc idTableHasObjectAsKey*(t: TIdTable, key: PIdObj): bool
   # checks if `t` contains the `key` (compared by the pointer value, not only
   # `key`'s id)
@@ -196,7 +196,7 @@ proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym =
     else: internalError(list.info, "getSymFromList")
   result = nil
 
-proc hashNode(p: PObject): THash = 
+proc hashNode(p: RootRef): THash = 
   result = hash(cast[pointer](p))
 
 proc mustRehash(length, counter: int): bool = 
@@ -245,13 +245,13 @@ proc lineInfoToStr(info: TLineInfo): PRope =
                                   toRope(toLinenumber(info)), 
                                   toRope(toColumn(info))])
 
-proc treeToYamlAux(n: PNode, marker: var TIntSet, 
+proc treeToYamlAux(n: PNode, marker: var IntSet, 
                    indent, maxRecDepth: int): PRope
-proc symToYamlAux(n: PSym, marker: var TIntSet, 
+proc symToYamlAux(n: PSym, marker: var IntSet, 
                   indent, maxRecDepth: int): PRope
-proc typeToYamlAux(n: PType, marker: var TIntSet, 
+proc typeToYamlAux(n: PType, marker: var IntSet, 
                    indent, maxRecDepth: int): PRope
-proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int, 
+proc strTableToYaml(n: TStrTable, marker: var IntSet, indent: int, 
                     maxRecDepth: int): PRope = 
   var istr = spaces(indent + 2)
   result = toRope("[")
@@ -277,13 +277,13 @@ proc ropeConstr(indent: int, c: openArray[PRope]): PRope =
     inc(i, 2)
   appf(result, "$N$1}", [spaces(indent)])
 
-proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int, 
+proc symToYamlAux(n: PSym, marker: var IntSet, indent: int, 
                   maxRecDepth: int): PRope = 
   if n == nil: 
     result = toRope("null")
   elif containsOrIncl(marker, n.id): 
     result = ropef("\"$1 @$2\"", [toRope(n.name.s), toRope(
-        strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
+        strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))])
   else: 
     var ast = treeToYamlAux(n.ast, marker, indent + 2, maxRecDepth - 1)
     result = ropeConstr(indent, [toRope("kind"), 
@@ -298,13 +298,13 @@ proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int,
                                  flagsToStr(n.options), toRope("position"), 
                                  toRope(n.position)])
 
-proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int, 
+proc typeToYamlAux(n: PType, marker: var IntSet, indent: int, 
                    maxRecDepth: int): PRope = 
   if n == nil: 
     result = toRope("null")
   elif containsOrIncl(marker, n.id): 
     result = ropef("\"$1 @$2\"", [toRope($n.kind), toRope(
-        strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
+        strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))])
   else: 
     if sonsLen(n) > 0: 
       result = toRope("[")
@@ -326,7 +326,7 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
                                  toRope("align"), toRope(n.align), 
                                  toRope("sons"), result])
 
-proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int, 
+proc treeToYamlAux(n: PNode, marker: var IntSet, indent: int, 
                    maxRecDepth: int): PRope = 
   if n == nil: 
     result = toRope("null")
@@ -469,7 +469,7 @@ proc nextTry(h, maxHash: THash): THash =
   # generates each int in range(maxHash) exactly once (see any text on
   # random-number generation for proof).
   
-proc objectSetContains(t: TObjectSet, obj: PObject): bool =
+proc objectSetContains(t: TObjectSet, obj: RootRef): bool =
   # returns true whether n is in t
   var h: THash = hashNode(obj) and high(t.data) # start with real hash value
   while t.data[h] != nil:
@@ -478,7 +478,7 @@ proc objectSetContains(t: TObjectSet, obj: PObject): bool =
     h = nextTry(h, high(t.data))
   result = false
 
-proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) =
+proc objectSetRawInsert(data: var TObjectSeq, obj: RootRef) =
   var h: THash = hashNode(obj) and high(data)
   while data[h] != nil:
     assert(data[h] != obj)
@@ -493,12 +493,12 @@ proc objectSetEnlarge(t: var TObjectSet) =
     if t.data[i] != nil: objectSetRawInsert(n, t.data[i])
   swap(t.data, n)
 
-proc objectSetIncl(t: var TObjectSet, obj: PObject) = 
+proc objectSetIncl(t: var TObjectSet, obj: RootRef) = 
   if mustRehash(len(t.data), t.counter): objectSetEnlarge(t)
   objectSetRawInsert(t.data, obj)
   inc(t.counter)
 
-proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool = 
+proc objectSetContainsOrIncl(t: var TObjectSet, obj: RootRef): bool = 
   # returns true if obj is already in the string table:
   var h: THash = hashNode(obj) and high(t.data)
   while true: 
@@ -516,7 +516,7 @@ proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool =
   inc(t.counter)
   result = false
 
-proc tableRawGet(t: TTable, key: PObject): int = 
+proc tableRawGet(t: TTable, key: RootRef): int = 
   var h: THash = hashNode(key) and high(t.data) # start with real hash value
   while t.data[h].key != nil: 
     if t.data[h].key == key: 
@@ -524,8 +524,8 @@ proc tableRawGet(t: TTable, key: PObject): int =
     h = nextTry(h, high(t.data))
   result = -1
 
-proc tableSearch(t: TTable, key, closure: PObject, 
-                 comparator: TCmpProc): PObject = 
+proc tableSearch(t: TTable, key, closure: RootRef, 
+                 comparator: TCmpProc): RootRef = 
   var h: THash = hashNode(key) and high(t.data) # start with real hash value
   while t.data[h].key != nil: 
     if t.data[h].key == key: 
@@ -535,12 +535,12 @@ proc tableSearch(t: TTable, key, closure: PObject,
     h = nextTry(h, high(t.data))
   result = nil
 
-proc tableGet(t: TTable, key: PObject): PObject = 
+proc tableGet(t: TTable, key: RootRef): RootRef = 
   var index = tableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = nil
   
-proc tableRawInsert(data: var TPairSeq, key, val: PObject) = 
+proc tableRawInsert(data: var TPairSeq, key, val: RootRef) = 
   var h: THash = hashNode(key) and high(data)
   while data[h].key != nil: 
     assert(data[h].key != key)
@@ -556,7 +556,7 @@ proc tableEnlarge(t: var TTable) =
     if t.data[i].key != nil: tableRawInsert(n, t.data[i].key, t.data[i].val)
   swap(t.data, n)
 
-proc tablePut(t: var TTable, key, val: PObject) = 
+proc tablePut(t: var TTable, key, val: RootRef) = 
   var index = tableRawGet(t, key)
   if index >= 0: 
     t.data[index].val = val
@@ -626,6 +626,12 @@ proc strTableAdd(t: var TStrTable, n: PSym) =
   strTableRawInsert(t.data, n)
   inc(t.counter)
 
+proc reallySameIdent(a, b: string): bool {.inline.} =
+  when defined(nimfix):
+    result = a[0] == b[0]
+  else:
+    result = true
+
 proc strTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
   # returns true if n is already in the string table:
   # It is essential that `n` is written nevertheless!
@@ -635,7 +641,7 @@ proc strTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
   while true:
     var it = t.data[h]
     if it == nil: break
-    if it.name.id == n.name.id:
+    if it.name.id == n.name.id and reallySameIdent(it.name.s, n.name.s):
       t.data[h] = n           # overwrite it with newer definition!
       return true             # found it
     h = nextTry(h, high(t.data))
@@ -677,7 +683,7 @@ proc nextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
   ti.h = nextTry(h, high(tab.data))
   
 proc nextIdentExcluding*(ti: var TIdentIter, tab: TStrTable, 
-                         excluding: TIntSet): PSym =
+                         excluding: IntSet): PSym =
   var h: THash = ti.h and high(tab.data)
   var start = h
   result = tab.data[h]
@@ -693,7 +699,7 @@ proc nextIdentExcluding*(ti: var TIdentIter, tab: TStrTable,
   if result != nil and contains(excluding, result.id): result = nil
 
 proc firstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
-                          excluding: TIntSet): PSym = 
+                          excluding: IntSet): PSym = 
   ti.h = s.h
   ti.name = s
   if tab.counter == 0: result = nil
@@ -740,22 +746,22 @@ proc idTableHasObjectAsKey(t: TIdTable, key: PIdObj): bool =
   if index >= 0: result = t.data[index].key == key
   else: result = false
   
-proc idTableGet(t: TIdTable, key: PIdObj): PObject = 
+proc idTableGet(t: TIdTable, key: PIdObj): RootRef = 
   var index = idTableRawGet(t, key.id)
   if index >= 0: result = t.data[index].val
   else: result = nil
   
-proc idTableGet(t: TIdTable, key: int): PObject = 
+proc idTableGet(t: TIdTable, key: int): RootRef = 
   var index = idTableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = nil
 
-iterator pairs*(t: TIdTable): tuple[key: int, value: PObject] =
+iterator pairs*(t: TIdTable): tuple[key: int, value: RootRef] =
   for i in 0..high(t.data):
     if t.data[i].key != nil:
       yield (t.data[i].key.id, t.data[i].val)
   
-proc idTableRawInsert(data: var TIdPairSeq, key: PIdObj, val: PObject) = 
+proc idTableRawInsert(data: var TIdPairSeq, key: PIdObj, val: RootRef) = 
   var h: THash
   h = key.id and high(data)
   while data[h].key != nil: 
@@ -765,7 +771,7 @@ proc idTableRawInsert(data: var TIdPairSeq, key: PIdObj, val: PObject) =
   data[h].key = key
   data[h].val = val
 
-proc idTablePut(t: var TIdTable, key: PIdObj, val: PObject) = 
+proc idTablePut(t: var TIdTable, key: PIdObj, val: RootRef) = 
   var 
     index: int
     n: TIdPairSeq
@@ -784,7 +790,7 @@ proc idTablePut(t: var TIdTable, key: PIdObj, val: PObject) =
     idTableRawInsert(t.data, key, val)
     inc(t.counter)
 
-iterator idTablePairs*(t: TIdTable): tuple[key: PIdObj, val: PObject] =
+iterator idTablePairs*(t: TIdTable): tuple[key: PIdObj, val: RootRef] =
   for i in 0 .. high(t.data):
     if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
 
diff --git a/compiler/bitsets.nim b/compiler/bitsets.nim
index 740bdd5ef..a2324f4e2 100644
--- a/compiler/bitsets.nim
+++ b/compiler/bitsets.nim
@@ -1,14 +1,14 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# this unit handles Nimrod sets; it implements bit sets
-# the code here should be reused in the Nimrod standard library
+# this unit handles Nim sets; it implements bit sets
+# the code here should be reused in the Nim standard library
 
 type 
   TBitSet* = seq[int8]        # we use byte here to avoid issues with
diff --git a/compiler/canonicalizer.nim b/compiler/canonicalizer.nim
index 3bc4eb029..14448f0e8 100644
--- a/compiler/canonicalizer.nim
+++ b/compiler/canonicalizer.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -370,7 +370,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
   # 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 Nimrod's heavy compile-time evaluation features
+    # it is not necessary, but Nim's heavy compile-time evaluation features
     # make that unfeasible nowadays:
     encodeNode(w, s.info, s.ast, result)
 
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index adcc95e84..b01a81c5e 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -103,9 +103,9 @@ proc openArrayLoc(p: BProc, n: PNode): PRope =
       result = ropef("$1, $1Len0", [rdLoc(a)])
     of tyString, tySequence:
       if skipTypes(n.typ, abstractInst).kind == tyVar:
-        result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField()])
+        result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField(p)])
       else:
-        result = ropef("$1->data, $1->$2", [a.rdLoc, lenField()])
+        result = ropef("$1->data, $1->$2", [a.rdLoc, lenField(p)])
     of tyArray, tyArrayConstr:
       result = ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))])
     else: internalError("openArrayLoc: " & typeToString(a.t))
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index b5817de05..75f0f3a42 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -15,7 +15,7 @@ proc intLiteral(i: BiggestInt): PRope =
   if (i > low(int32)) and (i <= high(int32)):
     result = toRope(i)
   elif i == low(int32):
-    # Nimrod has the same bug for the same reasons :-)
+    # Nim has the same bug for the same reasons :-)
     result = ~"(-2147483647 -1)"
   elif i > low(int64):
     result = rfmt(nil, "IL64($1)", toRope(i))
@@ -409,7 +409,6 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
     d.k = locData
     d.t = getUniqueType(t)
     d.r = r
-    d.a = -1
 
 proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
   var a: TLoc
@@ -425,7 +424,6 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
     d.k = locExpr
     d.t = getUniqueType(t)
     d.r = r
-    d.a = -1
 
 proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
@@ -723,7 +721,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
         internalError(e.info, "genRecordField")
       field = lookupInRecord(ty.n, f.name)
       if field != nil: break
-      if gCmd != cmdCompileToCpp: app(r, ".Sup")
+      if not p.module.compileToCpp: app(r, ".Sup")
       ty = getUniqueType(ty.sons[0])
     if field == nil: internalError(e.info, "genRecordField 2 ")
     if field.loc.r == nil: internalError(e.info, "genRecordField 3")
@@ -775,7 +773,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
       assert(ty.kind in {tyTuple, tyObject})
       field = lookupInRecord(ty.n, f.name)
       if field != nil: break
-      if gCmd != cmdCompileToCpp: app(r, ".Sup")
+      if not p.module.compileToCpp: app(r, ".Sup")
       ty = getUniqueType(ty.sons[0])
     if field == nil: internalError(e.info, "genCheckedRecordField")
     if field.loc.r == nil:
@@ -842,11 +840,11 @@ proc genSeqElem(p: BProc, e: PNode, d: var TLoc) =
     if ty.kind == tyString:
       linefmt(p, cpsStmts,
            "if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
-           rdLoc(b), rdLoc(a), lenField())
+           rdLoc(b), rdLoc(a), lenField(p))
     else:
       linefmt(p, cpsStmts,
            "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
-           rdLoc(b), rdLoc(a), lenField())
+           rdLoc(b), rdLoc(a), lenField(p))
   if d.k == locNone: d.s = OnHeap
   d.heapRoot = a.r
   if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
@@ -908,7 +906,7 @@ proc gcUsage(n: PNode) =
   if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree)
 
 proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
-  #   <Nimrod code>
+  #   <Nim code>
   #   s = 'Hello ' & name & ', how do you feel?' & 'z'
   #
   #   <generated C code>
@@ -939,7 +937,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
       if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
         inc(L, len(e.sons[i + 1].strVal))
       else:
-        appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
+        appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
       app(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
   linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, toRope(L))
   app(p.s(cpsStmts), appends)
@@ -951,7 +949,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   gcUsage(e)
 
 proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
-  #  <Nimrod code>
+  #  <Nim code>
   #  s &= 'Hello ' & name & ', how do you feel?' & 'z'
   #  // BUG: what if s is on the left side too?
   #  <generated C code>
@@ -979,7 +977,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
       if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
         inc(L, len(e.sons[i + 2].strVal))
       else:
-        appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
+        appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
       app(appends, rfmt(p.module, "#appendString($1, $2);$n",
                         rdLoc(dest), rdLoc(a)))
   linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
@@ -992,7 +990,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   # seq &= x  -->
   #    seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
   #    seq->data[seq->len-1] = x;
-  let seqAppendPattern = if gCmd != cmdCompileToCpp:
+  let seqAppendPattern = if not p.module.compileToCpp:
                            "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
                          else:
                            "$1 = ($2) #incrSeq($1, sizeof($3));$n"
@@ -1005,7 +1003,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
       getTypeDesc(p.module, skipTypes(e.sons[2].typ, abstractVar))])
   keepAlive(p, a)
   initLoc(dest, locExpr, b.t, OnHeap)
-  dest.r = rfmt(nil, "$1->data[$1->$2-1]", rdLoc(a), lenField())
+  dest.r = rfmt(nil, "$1->data[$1->$2-1]", rdLoc(a), lenField(p))
   genAssignment(p, dest, b, {needToCopy, afDestIsNil})
   gcUsage(e)
 
@@ -1099,7 +1097,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     while ty != nil:
       field = lookupInRecord(ty.n, it.sons[0].sym.name)
       if field != nil: break
-      if gCmd != cmdCompileToCpp: app(tmp2.r, ".Sup")
+      if not p.module.compileToCpp: app(tmp2.r, ".Sup")
       ty = getUniqueType(ty.sons[0])
     if field == nil or field.loc.r == nil: internalError(e.info, "genObjConstr")
     if it.len == 3 and optFieldCheck in p.options:
@@ -1200,8 +1198,8 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     if t.kind != tyVar: nilCheck = r
     r = rfmt(nil, "(*$1)", r)
     t = skipTypes(t.lastSon, typedescInst)
-  if gCmd != cmdCompileToCpp:
-    while (t.kind == tyObject) and (t.sons[0] != nil):
+  if not p.module.compileToCpp:
+    while t.kind == tyObject and t.sons[0] != nil:
       app(r, ~".Sup")
       t = skipTypes(t.sons[0], typedescInst)
   if isObjLackingTypeField(t):
@@ -1246,7 +1244,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
       putIntoDest(p, b, e.typ, ropef("$1, $1Len0", [rdLoc(a)]))
     of tyString, tySequence:
       putIntoDest(p, b, e.typ, 
-                  ropef("$1->data, $1->$2", [rdLoc(a), lenField()]))
+                  ropef("$1->data, $1->$2", [rdLoc(a), lenField(p)]))
     of tyArray, tyArrayConstr:
       putIntoDest(p, b, e.typ,
                   ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
@@ -1289,7 +1287,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
     else: unaryExpr(p, e, d, "strlen($1)")
   of tyString, tySequence:
-    if gCmd != cmdCompileToCpp:
+    if not p.module.compileToCpp:
       if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
       else: unaryExpr(p, e, d, "$1->Sup.len")
     else:
@@ -1307,7 +1305,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
   initLocExpr(p, e.sons[1], a)
   initLocExpr(p, e.sons[2], b)
   var t = skipTypes(e.sons[1].typ, abstractVar)
-  let setLenPattern = if gCmd != cmdCompileToCpp:
+  let setLenPattern = if not p.module.compileToCpp:
       "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
     else:
       "$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n"
@@ -1508,7 +1506,6 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
     linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
       getTypeDesc(p.module, srct), getTypeDesc(p.module, destt), lbl)
     tmp.k = locExpr
-    tmp.a = -1
     tmp.t = srct
     tmp.s = OnStack
     tmp.flags = {}
@@ -1564,11 +1561,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
   elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
     initLocExpr(p, e.sons[2], x)
     putIntoDest(p, d, e.typ,
-      rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField()))
+      rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
   elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""):
     initLocExpr(p, e.sons[1], x)
     putIntoDest(p, d, e.typ,
-      rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField()))
+      rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
   else:
     binaryExpr(p, e, d, "#eqStrings($1, $2)")
 
@@ -1827,7 +1824,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
       if t.kind != tyVar: nilCheck = r
       r = ropef("(*$1)", [r])
       t = skipTypes(t.lastSon, abstractInst)
-    if gCmd != cmdCompileToCpp:
+    if not p.module.compileToCpp:
       while t.kind == tyObject and t.sons[0] != nil:
         app(r, ".Sup")
         t = skipTypes(t.sons[0], abstractInst)
@@ -1845,7 +1842,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
                                    [getTypeDesc(p.module, dest), addrLoc(a)]))
 
 proc downConv(p: BProc, n: PNode, d: var TLoc) =
-  if gCmd == cmdCompileToCpp:
+  if p.module.compileToCpp:
     expr(p, n.sons[0], d)     # downcast does C++ for us
   else:
     var dest = skipTypes(n.typ, abstractPtrs)
@@ -2031,7 +2028,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
       initLocExpr(p, n.sons[0], a)
   of nkAsmStmt: genAsmStmt(p, n)
   of nkTryStmt:
-    if gCmd == cmdCompileToCpp: genTryCpp(p, n, d)
+    if p.module.compileToCpp: genTryCpp(p, n, d)
     else: genTry(p, n, d)
   of nkRaiseStmt: genRaiseStmt(p, n)
   of nkTypeSection:
@@ -2043,6 +2040,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
      nkFromStmt, nkTemplateDef, nkMacroDef: 
     discard
   of nkPragma: genPragma(p, n)
+  of nkPragmaBlock: expr(p, n.lastSon, d)
   of nkProcDef, nkMethodDef, nkConverterDef: 
     if (n.sons[genericParamsPos].kind == nkEmpty):
       var prc = n.sons[namePos].sym
diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim
index 2d27257ce..36da68d23 100644
--- a/compiler/ccgmerge.nim
+++ b/compiler/ccgmerge.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -83,7 +83,7 @@ proc writeTypeCache(a: TIdTable, s: var string) =
     inc i
   s.add('}')
 
-proc writeIntSet(a: TIntSet, s: var string) =
+proc writeIntSet(a: IntSet, s: var string) =
   var i = 0
   for x in items(a):
     if i == 10:
@@ -200,7 +200,7 @@ proc readTypeCache(L: var TBaseLexer, result: var TIdTable) =
     idTablePut(result, newFakeType(key), value.toRope)
   inc L.bufpos
 
-proc readIntSet(L: var TBaseLexer, result: var TIntSet) =
+proc readIntSet(L: var TBaseLexer, result: var IntSet) =
   if ^L.bufpos != '{': internalError("ccgmerge: '{' expected")
   inc L.bufpos
   while ^L.bufpos != '}':
@@ -249,7 +249,7 @@ proc readMergeInfo*(cfilename: string, m: BModule) =
       break
 
 type
-  TMergeSections = object {.pure.}
+  TMergeSections = object
     f: TCFileSections
     p: TCProcSections
 
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 037594e89..0898f0b03 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -46,7 +46,6 @@ proc genVarTuple(p: BProc, n: PNode) =
   if useLowering:
     genStmts(p, lowerTupleUnpacking(n, p.prc))
     return
-
   genLineDir(p, n)
   initLocExpr(p, n.sons[L-1], tup)
   var t = tup.t
@@ -294,8 +293,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
   
   var alreadyPoppedCnt = p.inExceptBlock
   for i in countup(1, howManyTrys):
-
-    if gCmd != cmdCompileToCpp:
+    if not p.module.compileToCpp:
       # Pop safe points generated by try
       if alreadyPoppedCnt > 0:
         dec alreadyPoppedCnt
@@ -317,7 +315,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
   for i in countdown(howManyTrys-1, 0): 
     p.nestedTryStmts.add(stack[i])
 
-  if gCmd != cmdCompileToCpp:
+  if not p.module.compileToCpp:
     # Pop exceptions that was handled by the
     # except-blocks we are in
     for i in countdown(howManyExcepts-1, 0):
@@ -448,7 +446,7 @@ proc genBlock(p: BProc, t: PNode, d: var TLoc) =
       assert(t.sons[0].kind == nkSym)
       var sym = t.sons[0].sym
       sym.loc.k = locOther
-      sym.loc.a = p.breakIdx
+      sym.position = p.breakIdx+1
     expr(p, t.sons[1], d)
     endBlock(p)
 
@@ -487,7 +485,7 @@ proc genBreakStmt(p: BProc, t: PNode) =
     assert(t.sons[0].kind == nkSym)
     var sym = t.sons[0].sym
     assert(sym.loc.k == locOther)
-    idx = sym.loc.a
+    idx = sym.position-1
   else:
     # an unnamed 'break' can only break a loop after 'transf' pass:
     while idx >= 0 and not p.blocks[idx].isLoop: dec idx
@@ -501,8 +499,10 @@ proc genBreakStmt(p: BProc, t: PNode) =
   lineF(p, cpsStmts, "goto $1;$n", [label])
 
 proc getRaiseFrmt(p: BProc): string = 
-  if gCmd == cmdCompileToCpp: 
+  if p.module.compileToCpp:
     result = "throw NimException($1, $2);$n"
+  elif getCompilerProc("Exception") != nil:
+    result = "#raiseException((#Exception*)$1, $2);$n"
   else:
     result = "#raiseException((#E_Base*)$1, $2);$n"
 
@@ -520,10 +520,10 @@ proc genRaiseStmt(p: BProc, t: PNode) =
     var typ = skipTypes(t.sons[0].typ, abstractPtrs)
     genLineDir(p, t)
     lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
-  else: 
+  else:
     genLineDir(p, t)
     # reraise the last exception:
-    if gCmd == cmdCompileToCpp:
+    if p.module.compileToCpp:
       line(p, cpsStmts, ~"throw;$n")
     else:
       linefmt(p, cpsStmts, "#reraiseException();$n")
@@ -559,7 +559,7 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
 proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
                        rangeFormat, eqFormat: TFormatStr,
                        until: int, a: TLoc): TLabel =
-  # generate a C-if statement for a Nimrod case statement
+  # generate a C-if statement for a Nim case statement
   var labId = p.labels
   for i in 1..until:
     inc(p.labels)
@@ -747,7 +747,10 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
     i, length, blen: int
   genLineDir(p, t)
   exc = getTempName()
-  discard cgsym(p.module, "E_Base")
+  if getCompilerProc("Exception") != nil:
+    discard cgsym(p.module, "Exception")
+  else:
+    discard cgsym(p.module, "E_Base")
   add(p.nestedTryStmts, t)
   startBlock(p, "try {$n")
   expr(p, t.sons[0], d)
@@ -829,7 +832,10 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   discard lists.includeStr(p.module.headerFiles, "<setjmp.h>")
   genLineDir(p, t)
   var safePoint = getTempName()
-  discard cgsym(p.module, "E_Base")
+  if getCompilerProc("Exception") != nil:
+    discard cgsym(p.module, "Exception")
+  else:
+    discard cgsym(p.module, "E_Base")
   linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
   linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
   if isDefined("nimStdSetjmp"):
diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim
index c00b931ef..c24dd5c41 100644
--- a/compiler/ccgthreadvars.nim
+++ b/compiler/ccgthreadvars.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -57,6 +57,9 @@ proc generateThreadLocalStorage(m: BModule) =
 
 proc generateThreadVarsSize(m: BModule) =
   if nimtv != nil:
-    app(m.s[cfsProcs], 
-      "NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}" & tnl)
-
+    let externc = if gCmd != cmdCompileToCpp and
+                       sfCompileToCpp in m.module.flags: "extern \"C\""
+                  else: ""
+    appf(m.s[cfsProcs],
+      "$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n",
+      [externc.toRope])
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index a5bf9e7a7..8bb820283 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -49,8 +49,8 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
     genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t)
   else: internalError(n.info, "genTraverseProc()")
 
-proc parentObj(accessor: PRope): PRope {.inline.} =
-  if gCmd != cmdCompileToCpp:
+proc parentObj(accessor: PRope; m: BModule): PRope {.inline.} =
+  if not m.compileToCpp:
     result = ropef("$1.Sup", accessor)
   else:
     result = accessor
@@ -71,7 +71,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
     lineF(p, cpsStmts, "}$n")
   of tyObject:
     for i in countup(0, sonsLen(typ) - 1):
-      genTraverseProc(c, accessor.parentObj, typ.sons[i])
+      genTraverseProc(c, accessor.parentObj(c.p.module), typ.sons[i])
     if typ.n != nil: genTraverseProc(c, accessor, typ.n)
   of tyTuple:
     let typ = getUniqueType(typ)
@@ -91,7 +91,7 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) =
   var i: TLoc
   getTemp(p, getSysType(tyInt), i)
   lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n",
-      i.r, accessor, toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len"))
+      i.r, accessor, toRope(if c.p.module.compileToCpp: "len" else: "Sup.len"))
   genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0])
   lineF(p, cpsStmts, "}$n")
   
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index fc6febc6f..fbdea7e66 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -162,7 +162,7 @@ proc mapReturnType(typ: PType): TCTypeKind =
   if skipTypes(typ, typedescInst).kind == tyArray: result = ctPtr
   else: result = mapType(typ)
   
-proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope
+proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope
 proc needsComplexAssignment(typ: PType): bool = 
   result = containsGarbageCollectedRef(typ)
 
@@ -228,7 +228,7 @@ proc fillResult(param: PSym) =
     incl(param.loc.flags, lfIndirect)
     param.loc.s = OnUnknown
 
-proc getParamTypeDesc(m: BModule, t: PType, check: var TIntSet): PRope =
+proc getParamTypeDesc(m: BModule, t: PType, check: var IntSet): PRope =
   when false:
     if t.Kind in {tyRef, tyPtr, tyVar}:
       var b = skipTypes(t.lastson, typedescInst)
@@ -243,7 +243,7 @@ proc paramStorageLoc(param: PSym): TStorageLoc =
     result = OnUnknown
 
 proc genProcParams(m: BModule, t: PType, rettype, params: var PRope, 
-                   check: var TIntSet, declareEnvironment=true) = 
+                   check: var IntSet, declareEnvironment=true) = 
   params = nil
   if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]): 
     rettype = ~"void"
@@ -342,8 +342,8 @@ proc getTypePre(m: BModule, typ: PType): PRope =
 proc structOrUnion(t: PType): PRope =
   (if tfUnion in t.flags: toRope("union") else: toRope("struct"))
 
-proc getForwardStructFormat(): string = 
-  if gCmd == cmdCompileToCpp: result = "$1 $2;$n"
+proc getForwardStructFormat(m: BModule): string = 
+  if m.compileToCpp: result = "$1 $2;$n"
   else: result = "typedef $1 $2 $2;$n"
   
 proc getTypeForward(m: BModule, typ: PType): PRope = 
@@ -355,7 +355,7 @@ proc getTypeForward(m: BModule, typ: PType): PRope =
   of tySequence, tyTuple, tyObject: 
     result = getTypeName(typ)
     if not isImportedType(typ): 
-      appf(m.s[cfsForwardTypes], getForwardStructFormat(),
+      appf(m.s[cfsForwardTypes], getForwardStructFormat(m),
           [structOrUnion(typ), result])
     idTablePut(m.forwTypeCache, typ, result)
   else: internalError("getTypeForward(" & $typ.kind & ')')
@@ -370,7 +370,7 @@ proc mangleRecFieldName(field: PSym, rectype: PType): PRope =
   
 proc genRecordFieldsAux(m: BModule, n: PNode, 
                         accessExpr: PRope, rectype: PType, 
-                        check: var TIntSet): PRope = 
+                        check: var IntSet): PRope = 
   var 
     ae, uname, sname, a: PRope
     k: PNode
@@ -419,19 +419,19 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
       appf(result, "$1 $2;$n", [getTypeDescAux(m, fieldType, check), sname])
   else: internalError(n.info, "genRecordFieldsAux()")
   
-proc getRecordFields(m: BModule, typ: PType, check: var TIntSet): PRope = 
+proc getRecordFields(m: BModule, typ: PType, check: var IntSet): PRope = 
   result = genRecordFieldsAux(m, typ.n, nil, typ, check)
 
 proc getRecordDesc(m: BModule, typ: PType, name: PRope, 
-                   check: var TIntSet): PRope = 
+                   check: var IntSet): PRope = 
   # declare the record:
   var hasField = false
 
   var attribute: PRope =
-    if tfPacked in typ.flags: toRope(CC[ccompiler].packedPragma)
+    if tfPacked in typ.flags: toRope(CC[cCompiler].packedPragma)
     else: nil
 
-  result = ropecg(m, CC[ccompiler].structStmtFmt, 
+  result = ropecg(m, CC[cCompiler].structStmtFmt, 
     [structOrUnion(typ), name, attribute])
 
   if typ.kind == tyObject: 
@@ -442,7 +442,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
       else: 
         appcg(m, result, " {$n#TNimType* m_type;$n", [name, attribute])
         hasField = true
-    elif gCmd == cmdCompileToCpp: 
+    elif m.compileToCpp:
       appcg(m, result, " : public $1 {$n", 
                       [getTypeDescAux(m, typ.sons[0], check)])
       hasField = true
@@ -461,7 +461,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
   app(result, "};" & tnl)
 
 proc getTupleDesc(m: BModule, typ: PType, name: PRope, 
-                  check: var TIntSet): PRope =
+                  check: var IntSet): PRope =
   result = ropef("$1 $2 {$n", [structOrUnion(typ), name])
   var desc: PRope = nil
   for i in countup(0, sonsLen(typ) - 1): 
@@ -474,7 +474,7 @@ proc getTupleDesc(m: BModule, typ: PType, name: PRope,
 proc pushType(m: BModule, typ: PType) = 
   add(m.typeStack, typ)
 
-proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope = 
+proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = 
   # returns only the type's name
   var 
     name, rettype, desc, recdesc: PRope
@@ -538,7 +538,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
     if result == nil: 
       result = getTypeName(t)
       if not isImportedType(t): 
-        appf(m.s[cfsForwardTypes], getForwardStructFormat(),
+        appf(m.s[cfsForwardTypes], getForwardStructFormat(m),
             [structOrUnion(t), result])
       idTablePut(m.forwTypeCache, t, result)
     assert(cacheGetType(m.typeCache, t) == nil)
@@ -550,7 +550,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
           cSeq = "struct $2 {$n" &
                  "  #TGenericSeq Sup;$n"
         appcg(m, m.s[cfsSeqTypes],
-            (if gCmd == cmdCompileToCpp: cppSeq else: cSeq) &
+            (if m.compileToCpp: cppSeq else: cSeq) &
             "  $1 data[SEQ_DECL_SIZE];$n" & 
             "};$n", [getTypeDescAux(m, t.sons[0], check), result])
       else: 
@@ -570,7 +570,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
     if result == nil: 
       result = getTypeName(t)
       if not isImportedType(t): 
-        appf(m.s[cfsForwardTypes], getForwardStructFormat(),
+        appf(m.s[cfsForwardTypes], getForwardStructFormat(m),
            [structOrUnion(t), result])
       idTablePut(m.forwTypeCache, t, result)
     idTablePut(m.typeCache, t, result) # always call for sideeffects:
@@ -898,7 +898,7 @@ include ccgtrav
 
 proc genDeepCopyProc(m: BModule; s: PSym; result: PRope) =
   genProc(m, s)
-  appf(m.s[cfsTypeInit3], "$1.deepcopy = (N_NIMCALL_PTR(void*, void*)) $2;$n",
+  appf(m.s[cfsTypeInit3], "$1.deepcopy =(void* (N_RAW_NIMCALL*)(void*))$2;$n",
      [result, s.loc.r])
 
 proc genTypeInfo(m: BModule, t: PType): PRope =
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 65957584a..7396c0bf8 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -149,7 +149,7 @@ proc getUniqueType*(key: PType): PType =
       idTablePut(gTypeTable[k], key, key)
       result = key
       
-proc tableGetType*(tab: TIdTable, key: PType): PObject = 
+proc tableGetType*(tab: TIdTable, key: PType): RootRef = 
   # returns nil if we need to declare this type
   result = idTableGet(tab, key)
   if (result == nil) and (tab.counter > 0): 
@@ -171,7 +171,7 @@ proc mangle*(name: string): string =
   ## Lowercases the given name and manges any non-alphanumeric characters
   ## so they are represented as `HEX____`. If the name starts with a number,
   ## `N` is prepended
-  result = ""
+  result = newStringOfCap(name.len)
   case name[0]
   of Letters:
     result.add(name[0].toLower)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 359fa3309..afeac8c88 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -55,7 +55,7 @@ proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) =
   result.s = s
   result.t = getUniqueType(typ)
   result.r = nil
-  result.a = - 1
+  #result.a = - 1
   result.flags = {}
 
 proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) = 
@@ -63,7 +63,7 @@ proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) =
   if a.k == locNone: 
     a.k = k
     a.t = getUniqueType(typ)
-    a.a = - 1
+    #a.a = - 1
     a.s = s
     if a.r == nil: a.r = r
   
@@ -139,7 +139,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
     if i - 1 >= start: 
       app(result, substr(frmt, start, i - 1))
 
-const compileTimeRopeFmt = not defined(booting)
+const compileTimeRopeFmt = false
 
 when compileTimeRopeFmt:
   import macros
@@ -186,7 +186,7 @@ when compileTimeRopeFmt:
         while s[i] in IdentChars: inc i
         yield (kind: ffSym, value: substr(s, j, i-1), intValue: 0)
         start = i
-      else: nil
+      else: discard
 
       while i < length:
         if s[i] != '$' and s[i] != '#': inc i
@@ -201,7 +201,7 @@ when compileTimeRopeFmt:
     ## the compilation of nimrod itself or will the macro execution time
     ## offset the gains?
     result = newCall(bindSym"ropeConcat")
-    for frag in fmtStringFragments(fmt.strVal):
+    for frag in fmtStringFragments(fmt):
       case frag.kind
       of ffSym:
         result.add(newCall(bindSym"cgsym", m, newStrLitNode(frag.value)))
@@ -297,6 +297,9 @@ proc accessThreadLocalVar(p: BProc, s: PSym)
 proc emulatedThreadVars(): bool {.inline.}
 proc genProc(m: BModule, prc: PSym)
 
+template compileToCpp(m: BModule): expr =
+  gCmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags
+
 include "ccgtypes.nim"
 
 # ------------------------------ Manager of temporaries ------------------
@@ -326,7 +329,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
     var r = rdLoc(a)
     if not takeAddr: r = ropef("(*$1)", [r])
     var s = skipTypes(t, abstractInst)
-    if gCmd != cmdCompileToCpp:
+    if not p.module.compileToCpp:
       while (s.kind == tyObject) and (s.sons[0] != nil):
         app(r, ".Sup")
         s = skipTypes(s.sons[0], abstractInst)
@@ -407,7 +410,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
     result.r = con("LOC", toRope(p.labels))
     linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
   result.k = locTemp
-  result.a = - 1
+  #result.a = - 1
   result.t = getUniqueType(t)
   result.s = OnStack
   result.flags = {}
@@ -425,7 +428,7 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) =
         [getTypeDesc(p.module, toKeepAlive.t), fid])
     inc(p.gcFrameId)
     result.k = locTemp
-    result.a = -1
+    #result.a = -1
     result.t = toKeepAlive.t
     result.s = OnStack
     result.flags = {}
@@ -506,7 +509,7 @@ proc assignLocalVar(p: BProc, s: PSym) =
     #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
     #  app(decl, " GC_GUARD")
     if sfVolatile in s.flags or (p.nestedTryStmts.len > 0 and
-                                 gCmd != cmdCompileToCpp):
+                                 not p.module.compileToCpp):
       app(decl, " volatile")
     appf(decl, " $1;$n", [s.loc.r])
   else:
@@ -587,8 +590,8 @@ proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
   initLoc(result, locNone, e.typ, OnUnknown)
   expr(p, e, result)
 
-proc lenField: PRope {.inline.} =
-  result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len")
+proc lenField(p: BProc): PRope =
+  result = toRope(if p.module.compileToCpp: "len" else: "Sup.len")
 
 include ccgcalls, "ccgstmts.nim", "ccgexprs.nim"
 
@@ -812,7 +815,12 @@ proc genProcAux(m: BModule, prc: PSym) =
     app(generatedProc, returnStmt)
     app(generatedProc, ~"}$N")
   app(m.s[cfsProcs], generatedProc)
-  
+
+proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} =
+  result = sfCompileToCpp in m.module.flags and
+           sfCompileToCpp notin sym.getModule().flags and
+           gCmd != cmdCompileToCpp
+
 proc genProcPrototype(m: BModule, sym: PSym) = 
   useHeader(m, sym)
   if lfNoDecl in sym.loc.flags: return 
@@ -824,6 +832,8 @@ proc genProcPrototype(m: BModule, sym: PSym) =
       if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
   elif not containsOrIncl(m.declaredProtos, sym.id):
     var header = genProcHeader(m, sym)
+    if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym):
+      header = con("extern \"C\" ", header)
     if sfPure in sym.flags and hasNakedAttribute in CC[cCompiler].props:
       header.app(" __attribute__((naked))")
     app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header))
@@ -915,30 +925,30 @@ proc addIntTypes(result: var PRope) {.inline.} =
   appf(result, "#define NIM_INTBITS $1", [
     platform.CPU[targetCPU].intSize.toRope])
 
-proc getCopyright(cfilenoext: string): PRope =
+proc getCopyright(cfile: string): PRope =
   if optCompileOnly in gGlobalOptions:
-    result = ropeff("/* Generated by Nimrod Compiler v$1 */$N" &
+    result = ropeff("/* Generated by Nim Compiler v$1 */$N" &
         "/*   (c) 2014 Andreas Rumpf */$N" &
         "/* The generated code is subject to the original license. */$N",
-        "; Generated by Nimrod Compiler v$1$N" &
+        "; Generated by Nim Compiler v$1$N" &
         ";   (c) 2012 Andreas Rumpf$N", [toRope(VersionAsString)])
   else:
-    result = ropeff("/* Generated by Nimrod Compiler v$1 */$N" &
+    result = ropeff("/* Generated by Nim Compiler v$1 */$N" &
         "/*   (c) 2014 Andreas Rumpf */$N" &
         "/* The generated code is subject to the original license. */$N" &
         "/* Compiled for: $2, $3, $4 */$N" &
         "/* Command for C compiler:$n   $5 */$N",
-        "; Generated by Nimrod Compiler v$1$N" &
+        "; Generated by Nim Compiler v$1$N" &
         ";   (c) 2014 Andreas Rumpf$N" &
         "; Compiled for: $2, $3, $4$N" &
         "; Command for LLVM compiler:$N   $5$N", [toRope(VersionAsString),
         toRope(platform.OS[targetOS].name),
         toRope(platform.CPU[targetCPU].name),
         toRope(extccomp.CC[extccomp.cCompiler].name),
-        toRope(getCompileCFileCmd(cfilenoext))])
+        toRope(getCompileCFileCmd(cfile))])
 
-proc getFileHeader(cfilenoext: string): PRope =
-  result = getCopyright(cfilenoext)
+proc getFileHeader(cfile: string): PRope =
+  result = getCopyright(cfile)
   addIntTypes(result)
 
 proc genFilenames(m: BModule): PRope =
@@ -1078,9 +1088,9 @@ proc registerModuleToMain(m: PSym) =
   var
     init = m.getInitName
     datInit = m.getDatInitName
-  appff(mainModProcs, "N_NOINLINE(void, $1)(void);$N",
+  appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N",
                       "declare void $1() noinline$N", [init])
-  appff(mainModProcs, "N_NOINLINE(void, $1)(void);$N",
+  appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N",
                       "declare void $1() noinline$N", [datInit])
   if sfSystemModule notin m.flags:
     appff(mainDatInit, "\t$1();$N", "call void ()* $1$n", [datInit])
@@ -1092,7 +1102,7 @@ proc registerModuleToMain(m: PSym) =
     
 proc genInitCode(m: BModule) = 
   var initname = getInitName(m.module)
-  var prc = ropeff("N_NOINLINE(void, $1)(void) {$N", 
+  var prc = ropeff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", 
                    "define void $1() noinline {$n", [initname])
   if m.typeNodes > 0: 
     appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", 
@@ -1135,7 +1145,7 @@ proc genInitCode(m: BModule) =
   app(prc, deinitGCFrame(m.initProc))
   appf(prc, "}$N$N")
 
-  prc.appff("N_NOINLINE(void, $1)(void) {$N",
+  prc.appff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N",
             "define void $1() noinline {$n", [getDatInitName(m.module)])
 
   for i in cfsTypeInit1..cfsDynLibInit:
@@ -1155,8 +1165,8 @@ proc genInitCode(m: BModule) =
         (i.ord - '0'.ord).toRope, el)
       app(m.s[cfsInitProc], ex)
 
-proc genModule(m: BModule, cfilenoext: string): PRope = 
-  result = getFileHeader(cfilenoext)
+proc genModule(m: BModule, cfile: string): PRope = 
+  result = getFileHeader(cfile)
   result.app(genMergeInfo(m))
   
   generateHeaders(m)
@@ -1297,7 +1307,11 @@ proc writeHeader(m: BModule) =
   writeRope(result, m.filename)
 
 proc getCFile(m: BModule): string =
-  result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), cExt)
+  let ext =
+      if m.compileToCpp: ".cpp"
+      elif gCmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m"
+      else: ".c"
+  result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), ext)
 
 proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
   assert optSymbolFiles in gGlobalOptions
@@ -1326,10 +1340,10 @@ proc finishModule(m: BModule) =
   dec(gForwardedProcsCounter, i)
   setLen(m.forwardedProcs, 0)
 
-proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool = 
+proc shouldRecompile(code: PRope, cfile: string): bool = 
   result = true
   if optForceFullMake notin gGlobalOptions:
-    var objFile = toObjFile(cfilenoext)
+    var objFile = toObjFile(cfile)
     if writeRopeIfNotEqual(code, cfile): return 
     if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false
   else: 
@@ -1354,26 +1368,26 @@ proc writeModule(m: BModule, pending: bool) =
       app(m.s[cfsProcHeaders], mainModProcs)
       generateThreadVarsSize(m)
     
-    var code = genModule(m, cfilenoext)
+    var code = genModule(m, cfile)
     when hasTinyCBackend:
       if gCmd == cmdRun:
         tccgen.compileCCode(ropeToStr(code))
         return
 
-    if shouldRecompile(code, cfile, cfilenoext):
-      addFileToCompile(cfilenoext)
+    if shouldRecompile(code, cfile):
+      addFileToCompile(cfile)
   elif pending and mergeRequired(m) and sfMainModule notin m.module.flags:
     mergeFiles(cfile, m)
     genInitCode(m)
     finishTypeDescriptions(m)
-    var code = genModule(m, cfilenoext)
+    var code = genModule(m, cfile)
     writeRope(code, cfile)
-    addFileToCompile(cfilenoext)
+    addFileToCompile(cfile)
   elif not existsFile(toObjFile(cfilenoext)):
     # Consider: first compilation compiles ``system.nim`` and produces
     # ``system.c`` but then compilation fails due to an error. This means
     # that ``system.o`` is missing, so we need to call the C compiler for it:
-    addFileToCompile(cfilenoext)
+    addFileToCompile(cfile)
   
   addFileToLink(cfilenoext)
 
@@ -1385,9 +1399,9 @@ proc updateCachedModule(m: BModule) =
     mergeFiles(cfile, m)
     genInitCode(m)
     finishTypeDescriptions(m)
-    var code = genModule(m, cfilenoext)
+    var code = genModule(m, cfile)
     writeRope(code, cfile)
-    addFileToCompile(cfilenoext)
+    addFileToCompile(cfile)
 
   addFileToLink(cfilenoext)
 
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 12041c55b..508f98074 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -62,7 +62,7 @@ type
     frameLen*: int16
   
   TCProc{.final.} = object    # represents C proc that is currently generated
-    prc*: PSym                # the Nimrod proc that this C proc belongs to
+    prc*: PSym                # the Nim proc that this C proc belongs to
     beforeRetNeeded*: bool    # true iff 'BeforeRet' label for proc is needed
     threadVarAccessed*: bool  # true if the proc already accessed some threadvar
     nestedTryStmts*: seq[PNode]   # in how many nested try statements we are
@@ -101,10 +101,10 @@ type
                               # without extension)
     typeCache*: TIdTable      # cache the generated types
     forwTypeCache*: TIdTable  # cache for forward declarations of types
-    declaredThings*: TIntSet  # things we have declared in this .c file
-    declaredProtos*: TIntSet  # prototypes we have declared in this .c file
+    declaredThings*: IntSet  # things we have declared in this .c file
+    declaredProtos*: IntSet  # prototypes we have declared in this .c file
     headerFiles*: TLinkedList # needed headers to include
-    typeInfoMarker*: TIntSet  # needed for generating type information
+    typeInfoMarker*: IntSet  # needed for generating type information
     initProc*: BProc          # code for init procedure
     postInitProc*: BProc      # code to be executed after the init proc
     preInitProc*: BProc       # code executed before the init proc
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index d881226d4..6c997b983 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -155,7 +155,7 @@ proc relevantCol(methods: TSymSeq, col: int): bool =
       if not sameType(t2, t):
         return true
   
-proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int = 
+proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int = 
   for col in countup(1, sonsLen(a.typ) - 1): 
     if contains(relevantCols, col): 
       var aa = skipTypes(a.typ.sons[col], skipPtrs)
@@ -164,7 +164,7 @@ proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int =
       if (d != high(int)): 
         return d
   
-proc sortBucket(a: var TSymSeq, relevantCols: TIntSet) = 
+proc sortBucket(a: var TSymSeq, relevantCols: IntSet) = 
   # we use shellsort here; fast and simple
   var n = len(a)
   var h = 1
@@ -183,7 +183,7 @@ proc sortBucket(a: var TSymSeq, relevantCols: TIntSet) =
       a[j] = v
     if h == 1: break 
   
-proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
+proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
   var base = lastSon(methods[0].ast).sym
   result = base
   var paramLen = sonsLen(base.typ)
diff --git a/compiler/commands.nim b/compiler/commands.nim
index cea965f5c..f26d1d6c7 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -26,7 +26,7 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
 
 import 
   os, msgs, options, nversion, condsyms, strutils, extccomp, platform, lists, 
-  wordrecg, parseutils, babelcmd, idents
+  wordrecg, parseutils, nimblecmd, idents, parseopt
 
 # but some have deps to imported modules. Yay.
 bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
@@ -43,7 +43,7 @@ type
   TCmdLinePass* = enum 
     passCmd1,                 # first pass over the command line
     passCmd2,                 # second pass over the command line
-    passPP                    # preprocessor called ProcessCommand()
+    passPP                    # preprocessor called processCommand()
 
 proc processCommand*(switch: string, pass: TCmdLinePass)
 proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo)
@@ -51,7 +51,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo)
 # implementation
 
 const
-  HelpMessage = "Nimrod Compiler Version $1 (" & CompileDate & ") [$2: $3]\n" &
+  HelpMessage = "Nim Compiler Version $1 (" & CompileDate & ") [$2: $3]\n" &
       "Copyright (c) 2006-2014 by Andreas Rumpf\n"
 
 const 
@@ -234,7 +234,9 @@ proc processPath(path: string, notRelativeToProj = false): string =
             path 
           else:
             options.gProjectPath / path
-  result = unixToNativePath(p % ["nimrod", getPrefixDir(), "lib", libpath,
+  result = unixToNativePath(p % ["nimrod", getPrefixDir(),
+    "nim", getPrefixDir(),
+    "lib", libpath,
     "home", removeTrailingDirSep(os.getHomeDir()),
     "projectname", options.gProjectName,
     "projectpath", options.gProjectPath])
@@ -280,14 +282,15 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
   of "path", "p": 
     expectArg(switch, arg, pass, info)
     addPath(processPath(arg), info)
-  of "babelpath":
-    if pass in {passCmd2, passPP} and not options.gNoBabelPath:
+  of "nimblepath", "babelpath":
+    # keep the old name for compat
+    if pass in {passCmd2, passPP} and not options.gNoNimblePath:
       expectArg(switch, arg, pass, info)
       let path = processPath(arg, notRelativeToProj=true)
-      babelpath(path, info)
-  of "nobabelpath":
+      nimblePath(path, info)
+  of "nonimblepath", "nobabelpath":
     expectNoArg(switch, arg, pass, info)
-    options.gNoBabelPath = true
+    options.gNoNimblePath = true
   of "excludepath":
     expectArg(switch, arg, pass, info)
     let path = processPath(arg)
@@ -307,8 +310,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
     expectArg(switch, arg, pass, info)
     options.docSeeSrcUrl = arg
   of "mainmodule", "m":
-    expectArg(switch, arg, pass, info)
-    optMainModule = arg
+    discard "allow for backwards compatibility, but don't do anything"
   of "define", "d": 
     expectArg(switch, arg, pass, info)
     defineSymbol(arg)
@@ -574,3 +576,33 @@ proc processCommand(switch: string, pass: TCmdLinePass) =
   var cmd, arg: string
   splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
   processSwitch(cmd, arg, pass, gCmdLineInfo)
+
+
+var
+  arguments* = ""
+    # the arguments to be passed to the program that
+    # should be run
+
+proc processSwitch*(pass: TCmdLinePass; p: OptParser) =
+  # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
+  # we fix this here
+  var bracketLe = strutils.find(p.key, '[')
+  if bracketLe >= 0: 
+    var key = substr(p.key, 0, bracketLe - 1)
+    var val = substr(p.key, bracketLe + 1) & ':' & p.val
+    processSwitch(key, val, pass, gCmdLineInfo)
+  else: 
+    processSwitch(p.key, p.val, pass, gCmdLineInfo)
+
+proc processArgument*(pass: TCmdLinePass; p: OptParser; 
+                      argsCount: var int): bool =
+  if argsCount == 0:
+    options.command = p.key
+  else:
+    if pass == passCmd1: options.commandArgs.add p.key
+    if argsCount == 1:
+      # support UNIX style filenames anywhere for portable build scripts:
+      options.gProjectName = unixToNativePath(p.key)
+      arguments = cmdLineRest(p)
+      result = true
+  inc argsCount
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 6d144ad96..9c07972cf 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -14,7 +14,7 @@ import
 
 # We need to use a PStringTable here as defined symbols are always guaranteed
 # to be style insensitive. Otherwise hell would break lose.
-var gSymbols: PStringTable
+var gSymbols: StringTableRef
 
 proc defineSymbol*(symbol: string) = 
   gSymbols[symbol] = "true"
@@ -41,7 +41,7 @@ proc countDefinedSymbols*(): int =
   for key, val in pairs(gSymbols):
     if val == "true": inc(result)
 
-# For ease of bootstrapping, we keep there here and not in the global config
+# For ease of bootstrapping, we keep them here and not in the global config
 # file for now:
 const
   additionalSymbols = """
@@ -88,6 +88,7 @@ proc initDefines*() =
   defineSymbol("nimrequiresnimframe")
   defineSymbol("nimparsebiggestfloatmagic")
   defineSymbol("nimalias")
+  defineSymbol("nimlocks")
   
   # add platform specific symbols:
   for c in low(CPU)..high(CPU):
diff --git a/compiler/crc.nim b/compiler/crc.nim
index ae1df3ff1..a8b61f2a5 100644
--- a/compiler/crc.nim
+++ b/compiler/crc.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -102,7 +102,7 @@ proc crcFromFile(filename: string): TCrc32 =
   const 
     bufSize = 8000 # don't use 8K for the memory allocator!
   var 
-    bin: TFile
+    bin: File
   result = InitCrc32
   if not open(bin, filename): 
     return                    # not equal if file does not exist
diff --git a/compiler/depends.nim b/compiler/depends.nim
index a43eaf844..115a98f84 100644
--- a/compiler/depends.nim
+++ b/compiler/depends.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 434e2a65b..8bd0bb490 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -23,7 +23,7 @@ type
     id: int                  # for generating IDs
     toc, section: TSections
     indexValFilename: string
-    seenSymbols: PStringTable # avoids duplicate symbol generation for HTML.
+    seenSymbols: StringTableRef # avoids duplicate symbol generation for HTML.
 
   PDoc* = ref TDocumentor ## Alias to type less.
 
@@ -55,7 +55,7 @@ proc parseRst(text, filename: string,
   result = rstParse(text, filename, line, column, hasToc, rstOptions,
                     docgenFindFile, compilerMsgHandler)
 
-proc newDocumentor*(filename: string, config: PStringTable): PDoc =
+proc newDocumentor*(filename: string, config: StringTableRef): PDoc =
   new(result)
   initRstGenerator(result[], (if gCmd != cmdRst2tex: outHtml else: outLatex),
                    options.gConfigVars, filename, {roSupportRawDirective},
@@ -374,11 +374,11 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
     cleanPlainSymbol = renderPlainSymbolName(nameNode)
     complexSymbol = complexName(k, n, cleanPlainSymbol)
     plainSymbolRope = toRope(cleanPlainSymbol)
-    plainSymbolEncRope = toRope(URLEncode(cleanPlainSymbol))
+    plainSymbolEncRope = toRope(encodeUrl(cleanPlainSymbol))
     itemIDRope = toRope(d.id)
     symbolOrId = d.newUniquePlainSymbol(complexSymbol)
     symbolOrIdRope = symbolOrId.toRope
-    symbolOrIdEncRope = URLEncode(symbolOrId).toRope
+    symbolOrIdEncRope = encodeUrl(symbolOrId).toRope
 
   var seeSrcRope: PRope = nil
   let docItemSeeSrc = getConfigVar("doc.item.seesrc")
@@ -413,7 +413,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
   setIndexTerm(d[], symbolOrId, name, linkTitle,
     xmltree.escape(plainDocstring.docstringSummary))
 
-proc genJSONItem(d: PDoc, n, nameNode: PNode, k: TSymKind): PJsonNode =
+proc genJSONItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode =
   if not isVisible(nameNode): return
   var
     name = getName(d, nameNode)
@@ -473,7 +473,7 @@ proc generateDoc*(d: PDoc, n: PNode) =
   of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
   else: discard
 
-proc generateJson(d: PDoc, n: PNode, jArray: PJsonNode = nil): PJsonNode =
+proc generateJson(d: PDoc, n: PNode, jArray: JsonNode = nil): JsonNode =
   case n.kind
   of nkCommentStmt:
     if n.comment != nil and startsWith(n.comment, "##"):
diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim
index d76be8e3c..aa832b6df 100644
--- a/compiler/docgen2.nim
+++ b/compiler/docgen2.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -26,7 +26,7 @@ proc close(p: PPassContext, n: PNode): PNode =
     writeOutput(g.doc, g.module.filename, HtmlExt, useWarning)
     try:
       generateIndex(g.doc)
-    except EIO:
+    except IOError:
       discard
 
 proc processNode(c: PPassContext, n: PNode): PNode = 
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index f798a43ac..d6b3a1aa5 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## This file implements the FFI part of the evaluator for Nimrod code.
+## This file implements the FFI part of the evaluator for Nim code.
 
 import ast, astalgo, ropes, types, options, tables, dynlib, libffi, msgs, os
 
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 78cdbb45f..78cc691c0 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index f0e5dad11..ad9c38904 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -1,14 +1,16 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# module for calling the different external C compilers
-# some things are read in from the configuration file
+# Module providing functions for calling the different external C compilers
+# Uses some hard-wired facts about each C/C++ compiler, plus options read
+# from a configuration file, to provide generalized procedures to compile
+# nim files.
 
 import
   lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, crc
@@ -59,6 +61,7 @@ type
 template compiler(name: expr, settings: stmt): stmt {.immediate.} =
   proc name: TInfoCC {.compileTime.} = settings
 
+# GNU C and C++ Compiler
 compiler gcc:
   result = (
     name: "gcc",
@@ -84,21 +87,24 @@ compiler gcc:
     props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
             hasNakedAttribute})
 
+# LLVM Frontend for GCC/G++
 compiler llvmGcc:
-  result = gcc()
-  
+  result = gcc() # Uses settings from GCC
+
   result.name = "llvm_gcc"
   result.compilerExe = "llvm-gcc"
   result.cppCompiler = "llvm-g++"
   result.buildLib = "llvm-ar rcs $libfile $objfiles"
 
+# Clang (LLVM) C/C++ Compiler
 compiler clang:
-  result = llvmGcc()
+  result = llvmGcc() # Uses settings from llvmGcc
 
   result.name = "clang"
   result.compilerExe = "clang"
   result.cppCompiler = "clang++"
 
+# Microsoft Visual C/C++ Compiler
 compiler vcc:
   result = (
     name: "vcc",
@@ -123,6 +129,7 @@ compiler vcc:
     packedPragma: "#pragma pack(1)",
     props: {hasCpp, hasAssume, hasNakedDeclspec})
 
+# Intel C/C++ Compiler
 compiler icl:
   # Intel compilers try to imitate the native ones (gcc and msvc)
   when defined(windows):
@@ -134,6 +141,7 @@ compiler icl:
   result.compilerExe = "icl"
   result.linkerExe = "icl"
 
+# Local C Compiler
 compiler lcc:
   result = (
     name: "lcc",
@@ -158,6 +166,7 @@ compiler lcc:
     packedPragma: "", # XXX: not supported yet
     props: {})
 
+# Borland C Compiler
 compiler bcc:
   result = (
     name: "bcc",
@@ -182,6 +191,7 @@ compiler bcc:
     packedPragma: "", # XXX: not supported yet
     props: {hasCpp})
 
+# Digital Mars C Compiler
 compiler dmc:
   result = (
     name: "dmc",
@@ -206,6 +216,7 @@ compiler dmc:
     packedPragma: "#pragma pack(1)",
     props: {hasCpp})
 
+# Watcom C Compiler
 compiler wcc:
   result = (
     name: "wcc",
@@ -230,6 +241,7 @@ compiler wcc:
     packedPragma: "", # XXX: not supported yet
     props: {hasCpp})
 
+# Tiny C Compiler
 compiler tcc:
   result = (
     name: "tcc",
@@ -254,6 +266,7 @@ compiler tcc:
     packedPragma: "", # XXX: not supported yet
     props: {hasSwitchRange, hasComputedGoto})
 
+# Pelles C Compiler
 compiler pcc:
   # Pelles C
   result = (
@@ -279,6 +292,7 @@ compiler pcc:
     packedPragma: "", # XXX: not supported yet
     props: {})
 
+# Your C Compiler
 compiler ucc:
   result = (
     name: "ucc",
@@ -323,10 +337,7 @@ const
 
 var
   cCompiler* = ccGcc # the used compiler
-
-  cExt* = ".c" # extension of generated C/C++ files
-               # (can be changed to .cpp later)
-  
+  gMixedMode*: bool  # true if some module triggered C++ codegen
   cIncludes*: seq[string] = @[]   # directories to search for included files
   cLibs*: seq[string] = @[]       # directories to search for lib files
   cLinkedLibs*: seq[string] = @[] # libraries to link
@@ -342,7 +353,9 @@ var
   compileOptions: string = ""
   ccompilerpath: string = ""
 
-proc nameToCC*(name: string): TSystemCC = 
+proc nameToCC*(name: string): TSystemCC =
+  ## Returns the kind of compiler referred to by `name`, or ccNone
+  ## if the name doesn't refer to any known compiler.
   for i in countup(succ(ccNone), high(TSystemCC)): 
     if cmpIgnoreStyle(name, CC[i].name) == 0: 
       return i
@@ -351,17 +364,18 @@ proc nameToCC*(name: string): TSystemCC =
 proc getConfigVar(c: TSystemCC, suffix: string): string =
   # use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given
   # for niminst support
+  let fullSuffix = (if gCmd == cmdCompileToCpp: ".cpp" & suffix else: suffix)
   if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and
       optCompileOnly notin gGlobalOptions:
     let fullCCname = platform.CPU[targetCPU].name & '.' & 
                      platform.OS[targetOS].name & '.' & 
-                     CC[c].name & suffix
+                     CC[c].name & fullSuffix
     result = getConfigVar(fullCCname)
     if result.len == 0:
       # not overriden for this cross compilation setting?
-      result = getConfigVar(CC[c].name & suffix)
+      result = getConfigVar(CC[c].name & fullSuffix)
   else:
-    result = getConfigVar(CC[c].name & suffix)
+    result = getConfigVar(CC[c].name & fullSuffix)
 
 proc setCC*(ccname: string) = 
   cCompiler = nameToCC(ccname)
@@ -387,8 +401,6 @@ proc initVars*() =
   # we need to define the symbol here, because ``CC`` may have never been set!
   for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
   defineSymbol(CC[cCompiler].name)
-  if gCmd == cmdCompileToCpp: cExt = ".cpp"
-  elif gCmd == cmdCompileToOC: cExt = ".m"
   addCompileOption(getConfigVar(cCompiler, ".options.always"))
   addLinkOption(getConfigVar(cCompiler, ".options.linker"))
   if len(ccompilerpath) == 0:
@@ -397,9 +409,9 @@ proc initVars*() =
 proc completeCFilePath*(cfile: string, createSubDir: bool = true): string = 
   result = completeGeneratedFilePath(cfile, createSubDir)
 
-proc toObjFile*(filenameWithoutExt: string): string = 
+proc toObjFile*(filename: string): string = 
   # Object file for compilation
-  result = changeFileExt(filenameWithoutExt, CC[cCompiler].objExt)
+  result = changeFileExt(filename, CC[cCompiler].objExt)
 
 proc addFileToCompile*(filename: string) =
   appendStr(toCompile, filename)
@@ -417,8 +429,12 @@ proc addFileToLink*(filename: string) =
   prependStr(toLink, filename)
   # BUGFIX: was ``appendStr``
 
-proc execExternalProgram*(cmd: string) = 
-  if optListCmd in gGlobalOptions or gVerbosity > 0: msgWriteln(cmd)
+proc execExternalProgram*(cmd: string, prettyCmd = "") =
+  if optListCmd in gGlobalOptions or gVerbosity > 0:
+    if prettyCmd != "":
+      msgWriteln(prettyCmd)
+    else:
+      msgWriteln(cmd)
   if execCmd(cmd) != 0: rawMessage(errExecutionOfProgramFailed, "")
 
 proc generateScript(projectFile: string, script: PRope) = 
@@ -487,7 +503,7 @@ proc getLinkOptions: string =
 
 proc needsExeExt(): bool {.inline.} =
   result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
-                                       (platform.hostOS == osWindows)
+           (platform.hostOS == osWindows)
 
 proc getCompilerExe(compiler: TSystemCC): string =
   result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler
@@ -497,6 +513,7 @@ proc getCompilerExe(compiler: TSystemCC): string =
 
 proc getLinkerExe(compiler: TSystemCC): string =
   result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
+           elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
            else: compiler.getCompilerExe
 
 proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = 
@@ -507,11 +524,11 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
   
   if needsExeExt(): exe = addFileExt(exe, "exe")
   if optGenDynLib in gGlobalOptions and
-      ospNeedsPIC in platform.OS[targetOS].props: 
+      ospNeedsPIC in platform.OS[targetOS].props:
     add(options, ' ' & CC[c].pic)
   
   var includeCmd, compilePattern: string
-  if not noAbsolutePaths(): 
+  if not noAbsolutePaths():
     # compute include paths:
     includeCmd = CC[c].includeCmd & quoteShell(libpath)
 
@@ -519,29 +536,31 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
       includeCmd.add([CC[c].includeCmd, includeDir.quoteShell])
 
     compilePattern = joinPath(ccompilerpath, exe)
-  else: 
+  else:
     includeCmd = ""
     compilePattern = c.getCompilerExe
   
-  var cfile = if noAbsolutePaths(): extractFilename(cfilename) 
+  var cfile = if noAbsolutePaths(): extractFilename(cfilename)
               else: cfilename
-  var objfile = if not isExternal or noAbsolutePaths(): 
-                  toObjFile(cfile) 
-                else: 
+  var objfile = if not isExternal or noAbsolutePaths():
+                  toObjFile(cfile)
+                else:
                   completeCFilePath(toObjFile(cfile))
-  cfile = quoteShell(addFileExt(cfile, cExt))
   objfile = quoteShell(objfile)
   result = quoteShell(compilePattern % [
-    "file", cfile, "objfile", objfile, "options", options, 
-    "include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath])
+    "file", cfile, "objfile", objfile, "options", options,
+    "include", includeCmd, "nimrod", getPrefixDir(),
+    "nim", getPrefixDir(), "lib", libpath])
   add(result, ' ')
   addf(result, CC[c].compileTmpl, [
-    "file", cfile, "objfile", objfile, 
-    "options", options, "include", includeCmd, 
-    "nimrod", quoteShell(getPrefixDir()), 
+    "file", cfile, "objfile", objfile,
+    "options", options, "include", includeCmd,
+    "nimrod", quoteShell(getPrefixDir()),
+    "nim", quoteShell(getPrefixDir()),
     "lib", quoteShell(libpath)])
 
 proc footprint(filename: string): TCrc32 =
+  # note, '><' further modifies a crc value with a string.
   result = crcFromFile(filename) ><
       platform.OS[targetOS].name ><
       platform.CPU[targetCPU].name ><
@@ -551,7 +570,7 @@ proc footprint(filename: string): TCrc32 =
 proc externalFileChanged(filename: string): bool = 
   var crcFile = toGeneratedFile(filename.withPackageName, "crc")
   var currentCrc = int(footprint(filename))
-  var f: TFile
+  var f: File
   if open(f, crcFile, fmRead): 
     var line = newStringOfCap(40)
     if not f.readLine(line): line = "0"
@@ -569,14 +588,16 @@ proc addExternalFileToCompile*(filename: string) =
   if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
     appendStr(externalToCompile, filename)
 
-proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq, 
-                  isExternal: bool) = 
+proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
+                  prettyCmds: var TStringSeq, isExternal: bool) =
   var it = PStrEntry(list.head)
   while it != nil: 
     inc(fileCounter)          # call the C compiler for the .c file:
     var compileCmd = getCompileCFileCmd(it.data, isExternal)
     if optCompileOnly notin gGlobalOptions: 
       add(cmds, compileCmd)
+      let (dir, name, ext) = splitFile(it.data)
+      add(prettyCmds, "CC: " & name)
     if optGenScript in gGlobalOptions: 
       app(script, compileCmd)
       app(script, tnl)
@@ -592,18 +613,24 @@ proc callCCompiler*(projectfile: string) =
   var c = cCompiler
   var script: PRope = nil
   var cmds: TStringSeq = @[]
-  compileCFile(toCompile, script, cmds, false)
-  compileCFile(externalToCompile, script, cmds, true)
+  var prettyCmds: TStringSeq = @[]
+  let prettyCb = proc (idx: int) =
+    echo prettyCmds[idx]
+  compileCFile(toCompile, script, cmds, prettyCmds, false)
+  compileCFile(externalToCompile, script, cmds, prettyCmds, true)
   if optCompileOnly notin gGlobalOptions: 
     if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
     var res = 0
     if gNumberOfProcessors <= 1: 
       for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res)
-    elif optListCmd in gGlobalOptions or gVerbosity > 0: 
-      res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams}, 
+    elif optListCmd in gGlobalOptions or gVerbosity > 1:
+      res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams},
                           gNumberOfProcessors)
-    else: 
-      res = execProcesses(cmds, {poUseShell, poParentStreams}, 
+    elif gVerbosity == 1:
+      res = execProcesses(cmds, {poUseShell, poParentStreams},
+                          gNumberOfProcessors, prettyCb)
+    else:
+      res = execProcesses(cmds, {poUseShell, poParentStreams},
                           gNumberOfProcessors)
     if res != 0:
       if gNumberOfProcessors <= 1:
@@ -625,7 +652,6 @@ proc callCCompiler*(projectfile: string) =
     if optGenStaticLib in gGlobalOptions:
       linkCmd = CC[c].buildLib % ["libfile", (libNameTmpl() % gProjectName),
                                   "objfiles", objfiles]
-      if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
     else:
       var linkerExe = getConfigVar(c, ".linkerexe")
       if len(linkerExe) == 0: linkerExe = c.getLinkerExe
@@ -657,7 +683,11 @@ proc callCCompiler*(projectfile: string) =
           "objfiles", objfiles, "exefile", exefile,
           "nimrod", quoteShell(getPrefixDir()),
           "lib", quoteShell(libpath)])
-      if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
+    if optCompileOnly notin gGlobalOptions:
+      if gVerbosity == 1:
+        execExternalProgram(linkCmd, "[Linking]")
+      else:
+        execExternalProgram(linkCmd)
   else:
     linkCmd = ""
   if optGenScript in gGlobalOptions:
@@ -668,7 +698,7 @@ proc callCCompiler*(projectfile: string) =
 proc genMappingFiles(list: TLinkedList): PRope = 
   var it = PStrEntry(list.head)
   while it != nil: 
-    appf(result, "--file:r\"$1\"$N", [toRope(addFileExt(it.data, cExt))])
+    appf(result, "--file:r\"$1\"$N", [toRope(it.data)])
     it = PStrEntry(it.next)
 
 proc writeMapping*(gSymbolMapping: PRope) = 
diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim
index 0014e9c78..7b975dbaa 100644
--- a/compiler/filter_tmpl.nim
+++ b/compiler/filter_tmpl.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# This module implements Nimrod's standard template filter.
+# This module implements Nim's standard template filter.
 
 import 
   llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, 
@@ -148,7 +148,7 @@ proc parseLine(p: var TTmplParser) =
         inc(j)
       else: 
         if p.x[j] == p.subsChar: 
-          # parse Nimrod expression:
+          # parse Nim expression:
           inc(j)
           case p.x[j]
           of '{': 
diff --git a/compiler/filters.nim b/compiler/filters.nim
index ce0ffd196..783a320a4 100644
--- a/compiler/filters.nim
+++ b/compiler/filters.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# This module implements Nimrod's simple filters and helpers for filters.
+# This module implements Nim's simple filters and helpers for filters.
 
 import
   llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, 
diff --git a/compiler/guards.nim b/compiler/guards.nim
index 431de6156..cd0aaf296 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -838,6 +838,22 @@ proc addAsgnFact*(m: var TModel, key, value: PNode) =
   fact.sons[2] = value
   m.add fact
 
+proc sameSubexprs*(m: TModel; a, b: PNode): bool =
+  # This should be used to check whether two *path expressions* refer to the
+  # same memory location according to 'm'. This is tricky:
+  # lock a[i].guard:
+  #   ...
+  #   access a[i].guarded
+  #
+  # Here a[i] is the same as a[i] iff 'i' and 'a' are not changed via '...'.
+  # However, nil checking requires exactly the same mechanism! But for now
+  # we simply use sameTree and live with the unsoundness of the analysis.
+  var check = newNodeI(nkCall, a.info, 3)
+  check.sons[0] = newSymNode(opEq)
+  check.sons[1] = a
+  check.sons[2] = b
+  result = m.doesImply(check) == impYes
+
 proc addCaseBranchFacts*(m: var TModel, n: PNode, i: int) =
   let branch = n.sons[i]
   if branch.kind == nkOfBranch:
diff --git a/compiler/hlo.nim b/compiler/hlo.nim
index c75d6519f..363d100be 100644
--- a/compiler/hlo.nim
+++ b/compiler/hlo.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/idents.nim b/compiler/idents.nim
index ec903826a..775bffa00 100644
--- a/compiler/idents.nim
+++ b/compiler/idents.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -15,7 +15,7 @@ import
   hashes, strutils
 
 type 
-  TIdObj* = object of TObject
+  TIdObj* = object of RootObj
     id*: int # unique id; use this for comparisons and not the pointers
   
   PIdObj* = ref TIdObj
diff --git a/compiler/idgen.nim b/compiler/idgen.nim
index d932e3d9d..3c5669b54 100644
--- a/compiler/idgen.nim
+++ b/compiler/idgen.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -53,7 +53,7 @@ proc saveMaxIds*(project: string) =
   f.close()
   
 proc loadMaxIds*(project: string) =
-  var f: TFile
+  var f: File
   if open(f, project.toGid, fmRead):
     var line = newStringOfCap(20)
     if f.readLine(line):
diff --git a/compiler/importer.nim b/compiler/importer.nim
index 33ed7e055..fbf3be4f2 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -113,7 +113,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
         e = nextIdentIter(it, fromMod.tab)
     else: rawImportSymbol(c, s)
 
-proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: TIntSet) =
+proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
   var i: TTabIter
   var s = initTabIter(i, fromMod.tab)
   while s != nil:
@@ -126,10 +126,10 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: TIntSet) =
     s = nextIter(i, fromMod.tab)
 
 proc importAllSymbols*(c: PContext, fromMod: PSym) =
-  var exceptSet: TIntSet
+  var exceptSet: IntSet
   importAllSymbolsExcept(c, fromMod, exceptSet)
 
-proc importForwarded(c: PContext, n: PNode, exceptSet: TIntSet) =
+proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
   if n.isNil: return
   case n.kind
   of nkExportStmt:
@@ -166,7 +166,7 @@ proc myImportModule(c: PContext, n: PNode): PSym =
 
 proc evalImport(c: PContext, n: PNode): PNode = 
   result = n
-  var emptySet: TIntSet
+  var emptySet: IntSet
   for i in countup(0, sonsLen(n) - 1): 
     var m = myImportModule(c, n.sons[i])
     if m != nil:
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index dfe498e47..4772aecb5 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -71,8 +71,8 @@ type
   TGlobals = object 
     typeInfo, code: PRope
     forwarded: seq[PSym]
-    generatedSyms: TIntSet
-    typeInfoGenerated: TIntSet
+    generatedSyms: IntSet
+    typeInfoGenerated: IntSet
 
   PGlobals = ref TGlobals
   PProc = ref TProc
@@ -724,7 +724,7 @@ proc genBlock(p: PProc, n: PNode, r: var TCompRes) =
     if (n.sons[0].kind != nkSym): internalError(n.info, "genBlock")
     var sym = n.sons[0].sym
     sym.loc.k = locOther
-    sym.loc.a = idx
+    sym.position = idx+1
   setLen(p.blocks, idx + 1)
   p.blocks[idx].id = - p.unique # negative because it isn't used yet
   let labl = p.unique
@@ -741,7 +741,7 @@ proc genBreakStmt(p: PProc, n: PNode) =
     assert(n.sons[0].kind == nkSym)
     let sym = n.sons[0].sym
     assert(sym.loc.k == locOther)
-    idx = sym.loc.a
+    idx = sym.position-1
   else:
     # an unnamed 'break' can only break a loop after 'transf' pass:
     idx = len(p.blocks) - 1
@@ -1654,6 +1654,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
       r.res = nil
   of nkGotoState, nkState:
     internalError(n.info, "first class iterators not implemented")
+  of nkPragmaBlock: gen(p, n.lastSon, r)
   else: internalError(n.info, "gen: unknown node type: " & $n.kind)
   
 var globals: PGlobals
@@ -1664,7 +1665,7 @@ proc newModule(module: PSym): BModule =
   if globals == nil: globals = newGlobals()
   
 proc genHeader(): PRope =
-  result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" &
+  result = ropef("/* Generated by the Nim Compiler v$1 */$n" &
                  "/*   (c) 2014 Andreas Rumpf */$n$n" & 
                  "$nvar Globals = this;$n" &
                  "var framePtr = null;$n" & 
diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim
index 009fc7935..8b032c3ce 100644
--- a/compiler/jstypes.nim
+++ b/compiler/jstypes.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 62e13b9c4..194396ddd 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -128,7 +128,7 @@ type
     obj: PType
     
   PEnv = ref TEnv
-  TEnv {.final.} = object of TObject
+  TEnv {.final.} = object of RootObj
     attachedNode, replacementNode: PNode
     createdVar: PNode        # if != nil it is a used environment; for closure
                              # iterators this can be 'envParam.env'
@@ -140,12 +140,12 @@ type
     fn: PSym                # function that belongs to this scope;
                             # if up.fn != fn then we cross function boundaries.
                             # This is an important case to consider.
-    vars: TIntSet           # variables belonging to this environment
+    vars: IntSet           # variables belonging to this environment
     
   TOuterContext = object
     fn: PSym # may also be a module!
     head: PEnv
-    capturedVars, processed: TIntSet
+    capturedVars, processed: IntSet
     localsToAccess: TIdNodeTable
     lambdasToEnv: TIdTable # PSym->PEnv mapping
 
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index ea51a1399..cbc87972d 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -21,10 +21,10 @@ import
 
 const 
   MaxLineLength* = 80         # lines longer than this lead to a warning
-  numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'}
-  SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
-  SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
-  OpChars*: TCharSet = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.', 
+  numChars*: set[char] = {'0'..'9', 'a'..'z', 'A'..'Z'}
+  SymChars*: set[char] = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
+  SymStartChars*: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
+  OpChars*: set[char] = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.', 
     '|', '=', '%', '&', '$', '@', '~', ':', '\x80'..'\xFF'}
 
 # don't forget to update the 'highlite' module if these charsets should change
@@ -102,7 +102,7 @@ type
                               # so that it is the correct default value
     base2, base8, base16
 
-  TToken* = object            # a Nimrod token
+  TToken* = object            # a Nim token
     tokType*: TTokType        # the type of the token
     indent*: int              # the indentation; != -1 if the token has been
                               # preceeded with indentation
@@ -148,7 +148,7 @@ proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "")
 proc isKeyword(kind: TTokType): bool = 
   result = (kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
 
-proc isNimrodIdentifier*(s: string): bool =
+proc isNimIdentifier*(s: string): bool =
   if s[0] in SymStartChars:
     var i = 1
     while i < s.len:
@@ -229,7 +229,7 @@ proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
   var info = newLineInfo(L.fileIdx, L.lineNumber, pos - L.lineStart)
   msgs.message(info, msg, arg)
 
-proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = 
+proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: set[char]) = 
   var pos = L.bufpos              # use registers for pos, buf
   var buf = L.buf
   while true: 
@@ -246,7 +246,7 @@ proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
       inc(pos)
   L.bufpos = pos
 
-proc matchTwoChars(L: TLexer, first: char, second: TCharSet): bool = 
+proc matchTwoChars(L: TLexer, first: char, second: set[char]): bool = 
   result = (L.buf[L.bufpos] == first) and (L.buf[L.bufpos + 1] in second)
 
 proc isFloatLiteral(s: string): bool =
@@ -429,9 +429,9 @@ proc getNumber(L: var TLexer): TToken =
       elif result.tokType == tkInt16Lit and
           (result.iNumber < int16.low or result.iNumber > int16.high):
         lexMessage(L, errNumberOutOfRange, result.literal)
-  except EInvalidValue:
+  except ValueError:
     lexMessage(L, errInvalidNumber, result.literal)
-  except EOverflow, EOutOfRange:
+  except OverflowError, RangeError:
     lexMessage(L, errNumberOutOfRange, result.literal)
   L.bufpos = endpos
 
@@ -482,7 +482,7 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
     add(tok.literal, VT)
     inc(L.bufpos)
   of 't', 'T': 
-    add(tok.literal, Tabulator)
+    add(tok.literal, '\t')
     inc(L.bufpos)
   of '\'', '\"': 
     add(tok.literal, L.buf[L.bufpos])
@@ -519,7 +519,7 @@ proc handleCRLF(L: var TLexer, pos: int): int =
       lexMessagePos(L, hintLineTooLong, pos)
 
     if optEmbedOrigSrc in gGlobalOptions:
-      let lineStart = cast[TAddress](L.buf) + L.lineStart
+      let lineStart = cast[ByteAddress](L.buf) + L.lineStart
       let line = newString(cast[cstring](lineStart), col)
       addSourceLine(L.fileIdx, line)
   
@@ -659,28 +659,32 @@ proc getOperator(L: var TLexer, tok: var TToken) =
   if buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
     tok.strongSpaceB = -1
 
-proc scanComment(L: var TLexer, tok: var TToken) = 
+proc scanComment(L: var TLexer, tok: var TToken) =
   var pos = L.bufpos
-  var buf = L.buf 
-  # a comment ends if the next line does not start with the # on the same
-  # column after only whitespace
+  var buf = L.buf
+  when not defined(nimfix):
+    assert buf[pos+1] == '#'
+    if buf[pos+2] == '[':
+      lexMessagePos(L, warnDeprecated, pos, "use '## [' instead; '##['")
   tok.tokType = tkComment
   # iNumber contains the number of '\n' in the token
   tok.iNumber = 0
-  var col = getColNumber(L, pos)
+  when defined(nimfix):
+    var col = getColNumber(L, pos)
   while true:
     var lastBackslash = -1
     while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}:
       if buf[pos] == '\\': lastBackslash = pos+1
       add(tok.literal, buf[pos])
       inc(pos)
-    if lastBackslash > 0:
-      # a backslash is a continuation character if only followed by spaces
-      # plus a newline:
-      while buf[lastBackslash] == ' ': inc(lastBackslash)
-      if buf[lastBackslash] notin {CR, LF, nimlexbase.EndOfFile}:
-        # false positive:
-        lastBackslash = -1
+    when defined(nimfix):
+      if lastBackslash > 0:
+        # a backslash is a continuation character if only followed by spaces
+        # plus a newline:
+        while buf[lastBackslash] == ' ': inc(lastBackslash)
+        if buf[lastBackslash] notin {CR, LF, nimlexbase.EndOfFile}:
+          # false positive:
+          lastBackslash = -1
 
     pos = handleCRLF(L, pos)
     buf = L.buf
@@ -688,9 +692,16 @@ proc scanComment(L: var TLexer, tok: var TToken) =
     while buf[pos] == ' ': 
       inc(pos)
       inc(indent)
-    if buf[pos] == '#' and (col == indent or lastBackslash > 0):
+
+    when defined(nimfix):
+      template doContinue(): expr =
+        buf[pos] == '#' and (col == indent or lastBackslash > 0)
+    else:
+      template doContinue(): expr =
+        buf[pos] == '#' and buf[pos+1] == '#'
+    if doContinue():
       tok.literal.add "\n"
-      col = indent
+      when defined(nimfix): col = indent
       inc tok.iNumber
     else:
       if buf[pos] > ' ': 
@@ -707,7 +718,7 @@ proc skip(L: var TLexer, tok: var TToken) =
     of ' ':
       inc(pos)
       inc(tok.strongSpaceA)
-    of Tabulator:
+    of '\t':
       lexMessagePos(L, errTabulatorsAreNotAllowed, pos)
       inc(pos)
     of CR, LF:
@@ -718,10 +729,24 @@ proc skip(L: var TLexer, tok: var TToken) =
         inc(pos)
         inc(indent)
       tok.strongSpaceA = 0
-      if buf[pos] > ' ':
+      when defined(nimfix):
+        template doBreak(): expr = buf[pos] > ' '
+      else:
+        template doBreak(): expr =
+          buf[pos] > ' ' and (buf[pos] != '#' or buf[pos+1] == '#')
+      if doBreak():
         tok.indent = indent
         L.currLineIndent = indent
         break
+    of '#':
+      when defined(nimfix):
+        break
+      else:
+        # do not skip documentation comment:
+        if buf[pos+1] == '#': break
+        if buf[pos+1] == '[':
+          lexMessagePos(L, warnDeprecated, pos, "use '# [' instead; '#['")
+        while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}: inc(pos)
     else:
       break                   # EndOfFile also leaves the loop
   L.bufpos = pos
diff --git a/compiler/lists.nim b/compiler/lists.nim
index efffe60fe..1b2b91bff 100644
--- a/compiler/lists.nim
+++ b/compiler/lists.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -12,7 +12,7 @@
 import os
 type 
   PListEntry* = ref TListEntry
-  TListEntry* = object of TObject
+  TListEntry* = object of RootObj
     prev*, next*: PListEntry
 
   TStrEntry* = object of TListEntry
diff --git a/compiler/llstream.nim b/compiler/llstream.nim
index 5aefd468a..be469548d 100644
--- a/compiler/llstream.nim
+++ b/compiler/llstream.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -21,9 +21,9 @@ type
     llsString,                # stream encapsulates a string
     llsFile,                  # stream encapsulates a file
     llsStdIn                  # stream encapsulates stdin
-  TLLStream* = object of TObject
+  TLLStream* = object of RootObj
     kind*: TLLStreamKind # accessible for low-level access (lexbase uses this)
-    f*: TFile
+    f*: File
     s*: string
     rd*, wr*: int             # for string streams
     lineOffset*: int          # for fake stdin line numbers
@@ -31,8 +31,8 @@ type
   PLLStream* = ref TLLStream
 
 proc llStreamOpen*(data: string): PLLStream
-proc llStreamOpen*(f: var TFile): PLLStream
-proc llStreamOpen*(filename: string, mode: TFileMode): PLLStream
+proc llStreamOpen*(f: var File): PLLStream
+proc llStreamOpen*(filename: string, mode: FileMode): PLLStream
 proc llStreamOpen*(): PLLStream
 proc llStreamOpenStdIn*(): PLLStream
 proc llStreamClose*(s: PLLStream)
@@ -50,12 +50,12 @@ proc llStreamOpen(data: string): PLLStream =
   result.s = data
   result.kind = llsString
 
-proc llStreamOpen(f: var TFile): PLLStream = 
+proc llStreamOpen(f: var File): PLLStream = 
   new(result)
   result.f = f
   result.kind = llsFile
 
-proc llStreamOpen(filename: string, mode: TFileMode): PLLStream = 
+proc llStreamOpen(filename: string, mode: FileMode): PLLStream = 
   new(result)
   result.kind = llsFile
   if not open(result.f, filename, mode): result = nil
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index d486585ef..fa1837296 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -114,7 +114,7 @@ type
     mode*: TOverloadIterMode
     symChoiceIndex*: int
     scope*: PScope
-    inSymChoice: TIntSet
+    inSymChoice: IntSet
 
 proc getSymRepr*(s: PSym): string = 
   case s.kind
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index e1fb09e44..8e5ffd48a 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -261,7 +261,7 @@ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
     threadLocalBarrier = addLocalVar(varSection2, nil, argsParam.owner, 
                                      barrier.typ, barrier)
     body.add varSection2
-    body.add callCodeGenProc("barrierEnter", threadLocalBarrier.newSymNode)
+    body.add callCodegenProc("barrierEnter", threadLocalBarrier.newSymNode)
   var threadLocalProm: PSym
   if spawnKind == srByVar:
     threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv)
@@ -276,7 +276,7 @@ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
     body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
       "owner", fv.info), threadParam.newSymNode)
 
-  body.add callCodeGenProc("nimArgsPassingDone", threadParam.newSymNode)
+  body.add callCodegenProc("nimArgsPassingDone", threadParam.newSymNode)
   if spawnKind == srByVar:
     body.add newAsgnStmt(genDeref(threadLocalProm.newSymNode), call)
   elif fv != nil:
@@ -289,11 +289,11 @@ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
     if barrier == nil:
       # by now 'fv' is shared and thus might have beeen overwritten! we need
       # to use the thread-local view instead:
-      body.add callCodeGenProc("nimFlowVarSignal", threadLocalProm.newSymNode)
+      body.add callCodegenProc("nimFlowVarSignal", threadLocalProm.newSymNode)
   else:
     body.add call
   if barrier != nil:
-    body.add callCodeGenProc("barrierLeave", threadLocalBarrier.newSymNode)
+    body.add callCodegenProc("barrierLeave", threadLocalBarrier.newSymNode)
 
   var params = newNodeI(nkFormalParams, f.info)
   params.add emptyNode
@@ -543,7 +543,7 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
     # create flowVar:
     result.add newFastAsgnStmt(fvField, callProc(spawnExpr[2]))
     if barrier == nil:
-      result.add callCodeGenProc("nimFlowVarCreateCondVar", fvField)
+      result.add callCodegenProc("nimFlowVarCreateCondVar", fvField)
 
   elif spawnKind == srByVar:
     var field = newSym(skField, getIdent"fv", owner, n.info)
@@ -556,7 +556,7 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
   let wrapper = createWrapperProc(fn, threadParam, argsParam, 
                                   varSection, varInit, call,
                                   barrierAsExpr, fvAsExpr, spawnKind)
-  result.add callCodeGenProc("nimSpawn", wrapper.newSymNode,
+  result.add callCodegenProc("nimSpawn", wrapper.newSymNode,
                              genAddrOf(scratchObj.newSymNode))
 
   if spawnKind == srFlowVar: result.add fvField
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index 475326161..6d4c65268 100644
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -35,7 +35,7 @@ proc registerSysType(t: PType) =
 proc newSysType(kind: TTypeKind, size: int): PType = 
   result = newType(kind, systemModule)
   result.size = size
-  result.align = size
+  result.align = size.int16
 
 proc getSysSym(name: string): PSym = 
   result = strTableGet(systemModule.tab, getIdent(name))
@@ -44,6 +44,7 @@ proc getSysSym(name: string): PSym =
     result = newSym(skError, getIdent(name), systemModule, systemModule.info)
     result.typ = newType(tyError, systemModule)
   if result.kind == skStub: loadStub(result)
+  if result.kind == skAlias: result = result.owner
   
 proc getSysMagic*(name: string, m: TMagic): PSym =
   var ti: TIdentIter
@@ -165,13 +166,14 @@ proc setIntLitType*(result: PNode) =
 proc getCompilerProc(name: string): PSym = 
   var ident = getIdent(name, hashIgnoreStyle(name))
   result = strTableGet(compilerprocs, ident)
-  if result == nil: 
+  if result == nil:
     result = strTableGet(rodCompilerprocs, ident)
-    if result != nil: 
+    if result != nil:
       strTableAdd(compilerprocs, result)
       if result.kind == skStub: loadStub(result)
-  
-proc registerCompilerProc(s: PSym) = 
+      if result.kind == skAlias: result = result.owner
+
+proc registerCompilerProc(s: PSym) =
   strTableAdd(compilerprocs, s)
 
 proc finishSystem(tab: TStrTable) = discard
diff --git a/compiler/main.nim b/compiler/main.nim
index b4af49248..82e55058c 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -15,8 +15,7 @@ import
   wordrecg, sem, semdata, idents, passes, docgen, extccomp,
   cgen, jsgen, json, nversion,
   platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
-  tables, docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists,
-  pretty
+  tables, docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists
 
 from magicsys import systemModule, resetSysTypes
 
@@ -164,19 +163,6 @@ proc commandEval(exp: string) =
   var echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
   evalNim(echoExp.parseString, makeStdinModule())
 
-proc commandPrettyOld =
-  var projectFile = addFileExt(mainCommandArg(), NimExt)
-  var module = parseFile(projectFile.fileInfoIdx)
-  if module != nil:
-    renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt))
-
-proc commandPretty =
-  msgs.gErrorMax = high(int)  # do not stop after first error
-  semanticPasses()
-  registerPass(prettyPass)
-  compileProject()
-  pretty.overwriteFiles()
-
 proc commandScan =
   var f = addFileExt(mainCommandArg(), NimExt)
   var stream = llStreamOpen(f, fmRead)
@@ -217,25 +203,6 @@ proc commandSuggest =
                    else: gProjectMainIdx
     compileProject(projFile)
 
-proc wantMainModule =
-  if gProjectFull.len == 0:
-    if optMainModule.len == 0:
-      fatal(gCmdLineInfo, errCommandExpectsFilename)
-    else:
-      gProjectName = optMainModule
-      gProjectFull = gProjectPath / gProjectName
-
-  gProjectMainIdx = addFileExt(gProjectFull, NimExt).fileInfoIdx
-
-proc requireMainModuleOption =
-  if optMainModule.len == 0:
-    fatal(gCmdLineInfo, errMainModuleMustBeSpecified)
-  else:
-    gProjectName = optMainModule
-    gProjectFull = gProjectPath / gProjectName
-
-  gProjectMainIdx = addFileExt(gProjectFull, NimExt).fileInfoIdx
-
 proc resetMemory =
   resetCompilationLists()
   ccgutils.resetCaches()
@@ -299,30 +266,22 @@ proc mainCommand* =
     # current path is always looked first for modules
     prependStr(searchPaths, gProjectPath)
   setId(100)
-  passes.gIncludeFile = includeModule
-  passes.gImportModule = importModule
   case command.normalize
   of "c", "cc", "compile", "compiletoc":
     # compile means compileToC currently
     gCmd = cmdCompileToC
-    wantMainModule()
     commandCompileToC()
   of "cpp", "compiletocpp":
-    extccomp.cExt = ".cpp"
     gCmd = cmdCompileToCpp
     if cCompiler == ccGcc: setCC("gcc")
-    wantMainModule()
     defineSymbol("cpp")
     commandCompileToC()
   of "objc", "compiletooc":
-    extccomp.cExt = ".m"
     gCmd = cmdCompileToOC
-    wantMainModule()
     defineSymbol("objc")
     commandCompileToC()
   of "run":
     gCmd = cmdRun
-    wantMainModule()
     when hasTinyCBackend:
       extccomp.setCC("tcc")
       commandCompileToC()
@@ -330,41 +289,33 @@ proc mainCommand* =
       rawMessage(errInvalidCommandX, command)
   of "js", "compiletojs":
     gCmd = cmdCompileToJS
-    wantMainModule()
     commandCompileToJS()
   of "compiletollvm":
     gCmd = cmdCompileToLLVM
-    wantMainModule()
     when hasLLVM_Backend:
       CommandCompileToLLVM()
     else:
       rawMessage(errInvalidCommandX, command)
-  of "pretty":
-    gCmd = cmdPretty
-    wantMainModule()
-    commandPretty()
   of "doc":
+    wantMainModule()
     gCmd = cmdDoc
     loadConfigs(DocConfig)
-    wantMainModule()
     commandDoc()
   of "doc2":
     gCmd = cmdDoc
     loadConfigs(DocConfig)
-    wantMainModule()
     defineSymbol("nimdoc")
     commandDoc2()
   of "rst2html":
     gCmd = cmdRst2html
     loadConfigs(DocConfig)
-    wantMainModule()
     commandRst2Html()
   of "rst2tex":
     gCmd = cmdRst2tex
     loadConfigs(DocTexConfig)
-    wantMainModule()
     commandRst2TeX()
   of "jsondoc":
+    wantMainModule()
     gCmd = cmdDoc
     loadConfigs(DocConfig)
     wantMainModule()
@@ -376,12 +327,11 @@ proc mainCommand* =
     commandBuildIndex()
   of "gendepend":
     gCmd = cmdGenDepend
-    wantMainModule()
     commandGenDepend()
   of "dump":
     gCmd = cmdDump
     if getConfigVar("dump.format") == "json":
-      requireMainModuleOption()
+      wantMainModule()
 
       var definedSymbols = newJArray()
       for s in definedSymbolNames(): definedSymbols.elems.add(%s)
@@ -405,7 +355,6 @@ proc mainCommand* =
       for it in iterSearchPath(searchPaths): msgWriteln(it)
   of "check":
     gCmd = cmdCheck
-    wantMainModule()
     commandCheck()
   of "parse":
     gCmd = cmdParse
@@ -429,7 +378,6 @@ proc mainCommand* =
     if gEvalExpr != "":
       commandEval(gEvalExpr)
     else:
-      wantMainModule()
       commandSuggest()
   of "serve":
     isServing = true
diff --git a/compiler/modules.nim b/compiler/modules.nim
index b102224cd..05b795473 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -117,7 +117,7 @@ proc newModule(fileIdx: int32): PSym =
   result.kind = skModule
   let filename = fileIdx.toFullPath
   result.name = getIdent(splitFile(filename).name)
-  if not isNimrodIdentifier(result.name.s):
+  if not isNimIdentifier(result.name.s):
     rawMessage(errInvalidModuleName, result.name.s)
   
   result.info = newLineInfo(fileIdx, 1, 1)
@@ -177,7 +177,7 @@ proc includeModule*(s: PSym, fileIdx: int32): PNode {.procvar.} =
 proc `==^`(a, b: string): bool =
   try:
     result = sameFile(a, b)
-  except EOS:
+  except OSError:
     result = false
 
 proc compileSystemModule* =
@@ -185,8 +185,18 @@ proc compileSystemModule* =
     systemFileIdx = fileInfoIdx(options.libpath/"system.nim")
     discard compileModule(systemFileIdx, {sfSystemModule})
 
-proc compileProject*(projectFile = gProjectMainIdx) =
+proc wantMainModule* =
+  if gProjectFull.len == 0:
+    fatal(gCmdLineInfo, errCommandExpectsFilename)
+  gProjectMainIdx = addFileExt(gProjectFull, NimExt).fileInfoIdx
+
+passes.gIncludeFile = includeModule
+passes.gImportModule = importModule
+
+proc compileProject*(projectFileIdx = -1'i32) =
+  wantMainModule()
   let systemFileIdx = fileInfoIdx(options.libpath / "system.nim")
+  let projectFile = if projectFileIdx < 0: gProjectMainIdx else: projectFileIdx
   if projectFile == systemFileIdx:
     discard compileModule(projectFile, {sfMainModule, sfSystemModule})
   else:
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 730cb9605..51d2836f8 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -119,12 +119,12 @@ type
     warnDifferentHeaps, warnWriteToForeignHeap, warnUnsafeCode,
     warnEachIdentIsTuple, warnShadowIdent, 
     warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
-    warnUninit, warnGcMem, warnUser,
+    warnUninit, warnGcMem, warnLockLevel, warnUser,
     hintSuccess, hintSuccessX,
     hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
     hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
     hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
-    hintConditionAlwaysTrue, hintPattern,
+    hintConditionAlwaysTrue, hintName, hintPattern,
     hintUser
 
 const 
@@ -368,7 +368,7 @@ const
     warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]", 
     warnXIsNeverRead: "\'$1\' is never read [XIsNeverRead]", 
     warnXmightNotBeenInit: "\'$1\' might not have been initialized [XmightNotBeenInit]", 
-    warnDeprecated: "\'$1\' is deprecated [Deprecated]", 
+    warnDeprecated: "$1 is deprecated [Deprecated]", 
     warnConfigDeprecated: "config file '$1' is deprecated [ConfigDeprecated]",
     warnSmallLshouldNotBeUsed: "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]", 
     warnUnknownMagic: "unknown magic \'$1\' might crash the compiler [UnknownMagic]", 
@@ -387,9 +387,10 @@ const
     warnProveField: "cannot prove that field '$1' is accessible [ProveField]",
     warnProveIndex: "cannot prove index '$1' is valid [ProveIndex]",
     warnGcUnsafe: "not GC-safe: '$1' [GcUnsafe]",
-    warnGcUnsafe2: "cannot prove '$1' is GC-safe. This will become a compile time error in the future.",
+    warnGcUnsafe2: "cannot prove '$1' is GC-safe. Does not compile with --threads:on.",
     warnUninit: "'$1' might not have been initialized [Uninit]",
     warnGcMem: "'$1' uses GC'ed memory [GcMem]",
+    warnLockLevel: "$1 [LockLevel]",
     warnUser: "$1 [User]", 
     hintSuccess: "operation successful [Success]", 
     hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#) [SuccessX]", 
@@ -405,11 +406,12 @@ const
     hintConf: "used config file \'$1\' [Conf]", 
     hintPath: "added path: '$1' [Path]",
     hintConditionAlwaysTrue: "condition is always true: '$1' [CondTrue]",
+    hintName: "name should be: '$1' [Name]",
     hintPattern: "$1 [Pattern]",
     hintUser: "$1 [User]"]
 
 const
-  WarningsToStr*: array[0..26, string] = ["CannotOpenFile", "OctalEscape", 
+  WarningsToStr*: array[0..27, string] = ["CannotOpenFile", "OctalEscape", 
     "XIsNeverRead", "XmightNotBeenInit",
     "Deprecated", "ConfigDeprecated",
     "SmallLshouldNotBeUsed", "UnknownMagic", 
@@ -418,12 +420,12 @@ const
     "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
     "UnsafeCode", "EachIdentIsTuple", "ShadowIdent", 
     "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
-    "GcMem", "User"]
+    "GcMem", "LockLevel", "User"]
 
-  HintsToStr*: array[0..15, string] = ["Success", "SuccessX", "LineTooLong", 
+  HintsToStr*: array[0..16, string] = ["Success", "SuccessX", "LineTooLong", 
     "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", 
     "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", 
-    "Path", "CondTrue", "Pattern",
+    "Path", "CondTrue", "Name", "Pattern",
     "User"]
 
 const 
@@ -441,7 +443,7 @@ type
   TNoteKinds* = set[TNoteKind]
 
   TFileInfo*{.final.} = object 
-    fullPath*: string          # This is a canonical full filesystem path
+    fullPath: string           # This is a canonical full filesystem path
     projPath*: string          # This is relative to the project's root
     shortName*: string         # short name of the module
     quotedName*: PRope         # cached quoted short name for codegen
@@ -468,8 +470,8 @@ type
 
   TErrorOutputs* = set[TErrorOutput]
 
-  ERecoverableError* = object of EInvalidValue
-  ESuggestDone* = object of E_Base
+  ERecoverableError* = object of ValueError
+  ESuggestDone* = object of Exception
 
 const
   InvalidFileIDX* = int32(-1)
@@ -567,7 +569,7 @@ var
   gErrorMax*: int = 1         # stop after gErrorMax errors
 
 when useCaas:
-  var stdoutSocket*: TSocket
+  var stdoutSocket*: Socket
 
 proc unknownLineInfo*(): TLineInfo =
   result.line = int16(-1)
@@ -858,7 +860,7 @@ proc sourceLine*(i: TLineInfo): PRope =
     try:
       for line in lines(i.toFullPath):
         addSourceLine i.fileIndex, line.string
-    except EIO:
+    except IOError:
       discard
   internalAssert i.fileIndex < fileInfos.len
   # can happen if the error points to EOF:
diff --git a/compiler/nimrod.ini b/compiler/nim.ini
index 7135b3490..576b6d2bb 100644
--- a/compiler/nimrod.ini
+++ b/compiler/nim.ini
@@ -2,7 +2,7 @@
 ; and project.
 
 [Project]
-Name: "Nimrod"
+Name: "Nim"
 Version: "$version"
 Platforms: """
   windows: i386;amd64
@@ -16,15 +16,15 @@ Platforms: """
 """
 
 Authors: "Andreas Rumpf"
-Description: """This is the Nimrod Compiler. Nimrod is a new statically typed,
+Description: """This is the Nim Compiler. Nim is a new statically typed,
 imperative programming language, that supports procedural, functional, object
 oriented and generic programming styles while remaining simple and efficient.
-A special feature that Nimrod inherited from Lisp is that Nimrod's abstract
+A special feature that Nim inherited from Lisp is that Nim's abstract
 syntax tree (AST) is part of the specification - this allows a powerful macro
 system which can be used to create domain specific languages.
 
-Nimrod is a compiled, garbage-collected systems programming language
-which has an excellent productivity/performance ratio. Nimrod's design
+Nim is a compiled, garbage-collected systems programming language
+which has an excellent productivity/performance ratio. Nim's design
 focuses on the 3E: efficiency, expressiveness, elegance (in the order of
 priority)."""
 
@@ -32,7 +32,7 @@ App: Console
 License: "copying.txt"
 
 [Config]
-Files: "config/nimrod.cfg"
+Files: "config/nim.cfg"
 Files: "config/nimdoc.cfg"
 Files: "config/nimdoc.tex.cfg"
 
@@ -61,8 +61,8 @@ Files: "icons/koch.res"
 Files: "icons/koch_icon.o"
 
 Files: "compiler/readme.txt"
-Files: "compiler/nimrod.ini"
-Files: "compiler/nimrod.cfg"
+Files: "compiler/nim.ini"
+Files: "compiler/nim.nimrod.cfg"
 Files: "compiler/*.nim"
 Files: "doc/*.txt"
 Files: "compiler/nimfix/*.nim"
@@ -113,10 +113,9 @@ Files: "examples/*.tmpl"
 
 
 [Windows]
-Files: "bin/nimrod.exe"
-Files: "bin/nimrod_debug.exe"
+Files: "bin/nim.exe"
+Files: "bin/nim_debug.exe"
 Files: "bin/c2nim.exe"
-Files: "bin/niminst.exe"
 Files: "bin/nimgrep.exe"
 
 Files: "dist/*.dll"
@@ -132,7 +131,7 @@ Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia
 ; for now only NSIS supports optional downloads
 
 [UnixBin]
-Files: "bin/nimrod"
+Files: "bin/nim"
 
 
 [Unix]
@@ -156,6 +155,5 @@ flags = "-w"
 [deb]
 buildDepends: "gcc (>= 4:4.3.2)"
 pkgDepends: "gcc (>= 4:4.3.2)"
-shortDesc: "The Nimrod Compiler"
-licenses: "bin/nimrod,MIT;lib/*,MIT;"
-
+shortDesc: "The Nim Compiler"
+licenses: "bin/nim,MIT;lib/*,MIT;"
diff --git a/compiler/nimrod.nim b/compiler/nim.nim
index 618d98698..a87e0a1ac 100644
--- a/compiler/nimrod.nim
+++ b/compiler/nim.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -40,7 +40,7 @@ proc handleCmdLine() =
     if gProjectName != "":
       try:
         gProjectFull = canonicalizePath(gProjectName)
-      except EOS:
+      except OSError:
         gProjectFull = gProjectName
       var p = splitFile(gProjectFull)
       gProjectPath = p.dir
@@ -58,7 +58,7 @@ proc handleCmdLine() =
     if msgs.gErrorCounter == 0:
       when hasTinyCBackend:
         if gCmd == cmdRun:
-          tccgen.run(service.arguments)
+          tccgen.run(commands.arguments)
       if optRun in gGlobalOptions:
         if gCmd == cmdCompileToJS:
           var ex: string
@@ -67,7 +67,7 @@ proc handleCmdLine() =
           else:
             ex = quoteShell(
               completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
-          execExternalProgram("node " & ex & ' ' & service.arguments)
+          execExternalProgram("node " & ex & ' ' & commands.arguments)
         else:
           var binPath: string
           if options.outFile.len > 0:
@@ -77,7 +77,7 @@ proc handleCmdLine() =
             # Figure out ourselves a valid binary name.
             binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir
           var ex = quoteShell(binPath)
-          execExternalProgram(ex & ' ' & service.arguments)
+          execExternalProgram(ex & ' ' & commands.arguments)
 
 when declared(GC_setMaxPause):
   GC_setMaxPause 2_000
diff --git a/compiler/nimrod.nimrod.cfg b/compiler/nim.nimrod.cfg
index 2c6e6f249..ba7697c4c 100644
--- a/compiler/nimrod.nimrod.cfg
+++ b/compiler/nim.nimrod.cfg
@@ -1,6 +1,4 @@
-# Special configuration file for the Nimrod project
-
-mainModule:"nimrod.nim"
+# Special configuration file for the Nim project
 
 # gc:markAndSweep
 
@@ -21,3 +19,4 @@ define:useStdoutAsStdmsg
 
 cs:partial
 #define:useNodeIds
+symbol:nimfix
diff --git a/compiler/babelcmd.nim b/compiler/nimblecmd.nim
index 7fa233732..049b94aa9 100644
--- a/compiler/babelcmd.nim
+++ b/compiler/nimblecmd.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## Implements some helper procs for Babel (Nimrod's package manager) support.
+## Implements some helper procs for Nimble (Nim's package manager) support.
 
 import parseutils, strutils, strtabs, os, options, msgs, lists
 
@@ -43,7 +43,7 @@ proc `<.`(a, b: string): bool =
     if a[i] == '.': inc i
     if b[j] == '.': inc j
 
-proc addPackage(packages: PStringTable, p: string) =
+proc addPackage(packages: StringTableRef, p: string) =
   let x = versionSplitPos(p)
   let name = p.substr(0, x-1)
   if x < p.len:
@@ -53,12 +53,12 @@ proc addPackage(packages: PStringTable, p: string) =
   else:
     packages[name] = latest
 
-iterator chosen(packages: PStringTable): string =
+iterator chosen(packages: StringTableRef): string =
   for key, val in pairs(packages):
     let res = if val == latest: key else: key & '-' & val
     yield res
 
-proc addBabelPath(p: string, info: TLineInfo) =
+proc addNimblePath(p: string, info: TLineInfo) =
   if not contains(options.searchPaths, p):
     if gVerbosity >= 1: message(info, hintPath, p)
     lists.prependStr(options.lazyPaths, p)
@@ -70,10 +70,10 @@ proc addPathWithNimFiles(p: string, info: TLineInfo) =
         result = true
         break
   if hasNimFile(p):
-    addBabelPath(p, info)
+    addNimblePath(p, info)
   else:
     for kind, p2 in walkDir(p):
-      if hasNimFile(p2): addBabelPath(p2, info)
+      if hasNimFile(p2): addNimblePath(p2, info)
 
 proc addPathRec(dir: string, info: TLineInfo) =
   var packages = newStringTable(modeStyleInsensitive)
@@ -83,8 +83,8 @@ proc addPathRec(dir: string, info: TLineInfo) =
     if k == pcDir and p[pos] != '.':
       addPackage(packages, p)
   for p in packages.chosen:
-    addBabelPath(p, info)
+    addNimblePath(p, info)
 
-proc babelPath*(path: string, info: TLineInfo) =
+proc nimblePath*(path: string, info: TLineInfo) =
   addPathRec(path, info)
-  addBabelPath(path, info)
+  addNimblePath(path, info)
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index 136a0d454..98fe831d3 100644
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -14,7 +14,7 @@ import
   options, idents, wordrecg
 
 # ---------------- configuration file parser -----------------------------
-# we use Nimrod's scanner here to safe space and work
+# we use Nim's scanner here to safe space and work
 
 proc ppGetTok(L: var TLexer, tok: var TToken) = 
   # simple filter
@@ -224,8 +224,8 @@ proc loadConfigs*(cfg: string) =
   if libpath == "": 
     # choose default libpath:
     var prefix = getPrefixDir()
-    if prefix == "/usr": libpath = "/usr/lib/nimrod"
-    elif prefix == "/usr/local": libpath = "/usr/local/lib/nimrod"
+    if prefix == "/usr": libpath = "/usr/lib/nim"
+    elif prefix == "/usr/local": libpath = "/usr/local/lib/nim"
     else: libpath = joinPath(prefix, "lib")
 
   if optSkipConfigFile notin gGlobalOptions:
@@ -244,5 +244,6 @@ proc loadConfigs*(cfg: string) =
     
     if gProjectName.len != 0:
       # new project wide config file:
-      readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg"))
- 
+      let projectConfig = changeFileExt(gProjectFull, "nim.cfg")
+      if fileExists(projectConfig): readConfigFile(projectConfig)
+      else: readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg"))
diff --git a/compiler/nimeval.nim b/compiler/nimeval.nim
index 0ee108d48..5693cbe91 100644
--- a/compiler/nimeval.nim
+++ b/compiler/nimeval.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## exposes the Nimrod VM to clients.
+## exposes the Nim VM to clients.
 
 import
   ast, modules, passes, passaux, condsyms, 
diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim
index 8e0f5db6d..225b78479 100644
--- a/compiler/nimfix/prettybase.nim
+++ b/compiler/nimfix/prettybase.nim
@@ -34,7 +34,7 @@ proc loadFile*(info: TLineInfo) =
     for line in lines(path):
       gSourceFiles[i].lines.add(line)
     # extract line ending of the file:
-    var lex: TBaseLexer
+    var lex: BaseLexer
     open(lex, newFileStream(path, fmRead))
     var pos = lex.bufpos
     while true:
diff --git a/compiler/nimlexbase.nim b/compiler/nimlexbase.nim
index 038573c35..e18e1c22a 100644
--- a/compiler/nimlexbase.nim
+++ b/compiler/nimlexbase.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -37,7 +37,7 @@ const
   NewLines* = {CR, LF}
 
 type 
-  TBaseLexer* = object of TObject
+  TBaseLexer* = object of RootObj
     bufpos*: int
     buf*: cstring
     bufLen*: int              # length of buffer in characters
diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim
index d65618e0a..aa7686d30 100644
--- a/compiler/nimsets.nim
+++ b/compiler/nimsets.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# this unit handles Nimrod sets; it implements symbolic sets
+# this unit handles Nim sets; it implements symbolic sets
 
 import 
   ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer
diff --git a/compiler/nversion.nim b/compiler/nversion.nim
index bd1f79ac6..c29880fe2 100644
--- a/compiler/nversion.nim
+++ b/compiler/nversion.nim
@@ -1,20 +1,20 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# This module contains Nimrod's version. It is the only place where it needs
+# This module contains Nim's version. It is the only place where it needs
 # to be changed.
 
 const 
   MaxSetElements* = 1 shl 16  # (2^16) to support unicode character sets?
   VersionMajor* = 0
-  VersionMinor* = 9
-  VersionPatch* = 6
+  VersionMinor* = 10
+  VersionPatch* = 0
   VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
 
   RodFileVersion* = "1215"       # modify this if the rod-format changes!
diff --git a/compiler/options.nim b/compiler/options.nim
index 02719cacc..838f99f8e 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -68,7 +68,7 @@ type                          # please make sure we have under 32 options
                               # also: generate header file
    
   TGlobalOptions* = set[TGlobalOption]
-  TCommands* = enum           # Nimrod's commands
+  TCommands* = enum           # Nim's commands
                               # **keep binary compatible**
     cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, 
     cmdCompileToJS, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc, 
@@ -114,7 +114,7 @@ var
   gDirtyBufferIdx* = 0'i32    # indicates the fileIdx of the dirty version of
                               # the tracked source X, saved by the CAAS client.
   gDirtyOriginalIdx* = 0'i32  # the original source file of the dirtified buffer.
-  gNoBabelPath* = false
+  gNoNimblePath* = false
 
 proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
 proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
@@ -139,7 +139,7 @@ const
   JsonExt* = "json"
   TexExt* = "tex"
   IniExt* = "ini"
-  DefaultConfig* = "nimrod.cfg"
+  DefaultConfig* = "nim.cfg"
   DocConfig* = "nimdoc.cfg"
   DocTexConfig* = "nimdoc.tex.cfg"
 
@@ -152,7 +152,6 @@ var
   gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
   gProjectFull* = "" # projectPath/projectName
   gProjectMainIdx*: int32 # the canonical path id of the main module
-  optMainModule* = "" # the main module that should be used for idetools commands
   nimcacheDir* = ""
   command* = "" # the main command (e.g. cc, check, scan, etc)
   commandArgs*: seq[string] = @[] # any arguments after the main command
@@ -189,8 +188,8 @@ proc getPrefixDir*(): string =
   result = splitPath(getAppDir()).head
 
 proc canonicalizePath*(path: string): string =
-  result = path.expandFilename
-  when not FileSystemCaseSensitive: result = result.toLower
+  when not FileSystemCaseSensitive: result = path.expandFilename.toLower
+  else: result = path.expandFilename
 
 proc shortenDir*(dir: string): string = 
   ## returns the interesting part of a dir
@@ -238,6 +237,9 @@ proc getPackageName*(path: string): string =
         #echo "from cache ", d, " |", packageCache[d], "|", path.splitFile.name
         return packageCache[d]
       inc parents
+      for file in walkFiles(d / "*.nimble"):
+        result = file.splitFile.name
+        break packageSearch
       for file in walkFiles(d / "*.babel"):
         result = file.splitFile.name
         break packageSearch
@@ -295,7 +297,7 @@ proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
       createDir(subdir)
       when noTimeMachine:
        excludeDirFromTimeMachine(subdir)
-    except EOS: 
+    except OSError: 
       writeln(stdout, "cannot create directory: " & subdir)
       quit(1)
   result = joinPath(subdir, tail)
@@ -335,6 +337,16 @@ proc findFile*(f: string): string {.procvar.} =
 
 proc findModule*(modulename, currentModule: string): string =
   # returns path to module
+  when defined(nimfix):
+    # '.nimfix' modules are preferred over '.nim' modules so that specialized
+    # versions can be kept for 'nimfix'.
+    block:
+      let m = addFileExt(modulename, "nimfix")
+      let currentPath = currentModule.splitFile.dir
+      result = currentPath / m
+      if not existsFile(result):
+        result = findFile(m)
+        if existsFile(result): return result
   let m = addFileExt(modulename, NimExt)
   let currentPath = currentModule.splitFile.dir
   result = currentPath / m
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index bbdba8c22..300abea1e 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 6ff0c2dfc..20c037c00 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# This module implements the parser of the standard Nimrod syntax.
+# This module implements the parser of the standard Nim syntax.
 # The parser strictly reflects the grammar ("doc/grammar.txt"); however
 # it uses several helper routines to keep the parser small. A special
 # efficient algorithm is used for the precedence levels. The parser here can
@@ -84,7 +84,7 @@ proc openParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream,
 
 proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
                  strongSpaces=false) =
-  openParser(p, filename.fileInfoIdx, inputstream, strongSpaces)
+  openParser(p, filename.fileInfoIdx, inputStream, strongSpaces)
 
 proc closeParser(p: var TParser) =
   ## Close a parser, freeing up its resources.
diff --git a/compiler/passaux.nim b/compiler/passaux.nim
index 0ba9f22d0..f754c80e5 100644
--- a/compiler/passaux.nim
+++ b/compiler/passaux.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 66a1a4954..a63e29b35 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -16,7 +16,7 @@ import
   nimsets, syntaxes, times, rodread, idgen
 
 type  
-  TPassContext* = object of TObject # the pass's context
+  TPassContext* = object of RootObj # the pass's context
     fromCache*: bool  # true if created by "openCached"
    
   PPassContext* = ref TPassContext
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index 5e21289b5..3d71aa4d1 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/pbraces.nim b/compiler/pbraces.nim
index ce6e0d9a9..cf4dbffc5 100644
--- a/compiler/pbraces.nim
+++ b/compiler/pbraces.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index d73494c6e..52eb46bf4 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -130,6 +130,7 @@ proc processImportCpp(s: PSym, extname: string) =
   excl(s.flags, sfForward)
   let m = s.getModule()
   incl(m.flags, sfCompileToCpp)
+  extccomp.gMixedMode = true
 
 proc processImportObjC(s: PSym, extname: string) =
   setExternName(s, extname)
@@ -447,6 +448,9 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
           addSon(result, newSymNode(e))
         else: 
           addSon(result, newStrNode(nkStrLit, sub))
+      else:
+        # an empty '``' produces a single '`'
+        addSon(result, newStrNode(nkStrLit, $marker))
       if c < 0: break 
       a = c + 1
   else: illFormedAst(n)
@@ -518,6 +522,28 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
   else:
     invalidPragma(n)
 
+proc pragmaLockStmt(c: PContext; it: PNode) =
+  if it.kind != nkExprColonExpr:
+    invalidPragma(it)
+  else:
+    let n = it[1]
+    if n.kind != nkBracket:
+      localError(n.info, errGenerated, "locks pragma takes a list of expressions")
+    else:
+      for i in 0 .. <n.len:
+        n.sons[i] = c.semExpr(c, n.sons[i])
+
+proc pragmaLocks(c: PContext, it: PNode): TLockLevel =
+  if it.kind != nkExprColonExpr:
+    invalidPragma(it)
+  else:
+    if it[1].kind != nkNilLit:
+      let x = expectIntLit(c, it)
+      if x < 0 or x > MaxLockLevel:
+        localError(it[1].info, "integer must be within 0.." & $MaxLockLevel)
+      else:
+        result = TLockLevel(x)
+
 proc typeBorrow(sym: PSym, n: PNode) =
   if n.kind == nkExprColonExpr:
     let it = n.sons[1]
@@ -807,6 +833,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           if sym == nil: invalidPragma(it)
         of wLine: pragmaLine(c, it)
         of wRaises, wTags: pragmaRaisesOrTags(c, it)
+        of wLocks:
+          if sym == nil: pragmaLockStmt(c, it)
+          elif sym.typ == nil: invalidPragma(it)
+          else: sym.typ.lockLevel = pragmaLocks(c, it)
         of wGuard:
           if sym == nil or sym.kind notin {skVar, skLet, skField}:
             invalidPragma(it)
diff --git a/compiler/pretty.nim b/compiler/pretty.nim
deleted file mode 100644
index 17311f9e6..000000000
--- a/compiler/pretty.nim
+++ /dev/null
@@ -1,281 +0,0 @@
-#
-#
-#           The Nimrod Compiler
-#        (c) Copyright 2014 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This module implements the code "prettifier". This is part of the toolchain
-## to convert Nimrod code into a consistent style.
-
-import 
-  strutils, os, options, ast, astalgo, msgs, ropes, idents, passes,
-  intsets, strtabs, semdata
-  
-const
-  removeTP = false # when true, "nimrod pretty" converts TTyp to Typ.
-
-type
-  TGen = object of TPassContext
-    module*: PSym
-  PGen = ref TGen
-  
-  TSourceFile = object
-    lines: seq[string]
-    dirty: bool
-    fullpath: string
-
-var
-  gSourceFiles: seq[TSourceFile] = @[]
-  gCheckExtern: bool
-  rules: PStringTable
-
-proc loadFile(info: TLineInfo) =
-  let i = info.fileIndex
-  if i >= gSourceFiles.len:
-    gSourceFiles.setLen(i+1)
-  if gSourceFiles[i].lines.isNil:
-    gSourceFiles[i].lines = @[]
-    let path = info.toFullPath
-    gSourceFiles[i].fullpath = path
-    # we want to die here for EIO:
-    for line in lines(path):
-      gSourceFiles[i].lines.add(line)
-
-proc overwriteFiles*() =
-  let overWrite = options.getConfigVar("pretty.overwrite").normalize == "on"
-  let doStrip = options.getConfigVar("pretty.strip").normalize == "on"
-  for i in 0 .. high(gSourceFiles):
-    if not gSourceFiles[i].dirty: continue
-    let newFile = if overWrite: gSourceFiles[i].fullpath
-                  else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim")
-    try:
-      var f = open(newFile, fmWrite)
-      for line in gSourceFiles[i].lines:
-        if doStrip:
-          f.write line.strip(leading = false, trailing = true)
-        else:
-          f.write line
-        f.write("\L")
-      f.close
-    except EIO:
-      rawMessage(errCannotOpenFile, newFile)
-
-proc `=~`(s: string, a: openArray[string]): bool =
-  for x in a:
-    if s.startsWith(x): return true
-
-proc beautifyName(s: string, k: TSymKind): string =
-  # minimal set of rules here for transition:
-  # GC_ is allowed
-
-  let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
-  if allUpper and k in {skConst, skEnumField, skType}: return s
-  result = newStringOfCap(s.len)
-  var i = 0
-  case k
-  of skType, skGenericParam:
-    # Types should start with a capital unless builtins like 'int' etc.:
-    when removeTP:
-      if s[0] == 'T' and s[1] in {'A'..'Z'}:
-        i = 1
-    if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
-             "char", "byte", "bool", "openArray", "seq", "array", "void",
-             "pointer", "float", "csize", "cdouble", "cchar", "cschar",
-             "cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any",
-             "range", "openarray", "varargs", "set", "cfloat"
-             ]:
-      result.add s[i]
-    else:
-      result.add toUpper(s[i])
-  of skConst, skEnumField:
-    # for 'const' we keep how it's spelt; either upper case or lower case:
-    result.add s[0]
-  else:
-    # as a special rule, don't transform 'L' to 'l'
-    if s.len == 1 and s[0] == 'L': result.add 'L'
-    elif '_' in s: result.add(s[i])
-    else: result.add toLower(s[0])
-  inc i
-  while i < s.len:
-    if s[i] == '_':
-      if i > 0 and s[i-1] in {'A'..'Z'}:
-        # don't skip '_' as it's essential for e.g. 'GC_disable'
-        result.add('_')
-        inc i
-        result.add s[i]
-      else:
-        inc i
-        result.add toUpper(s[i])
-    elif allUpper:
-      result.add toLower(s[i])
-    else:
-      result.add s[i]
-    inc i
-
-proc checkStyle*(info: TLineInfo, s: string, k: TSymKind) =
-  let beau = beautifyName(s, k)
-  if s != beau:
-    message(info, errGenerated, "name should be: " & beau)
-
-const
-  Letters = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
-
-proc identLen(line: string, start: int): int =
-  while start+result < line.len and line[start+result] in Letters:
-    inc result
-
-proc differ(line: string, a, b: int, x: string): bool =
-  let y = line[a..b]
-  result = cmpIgnoreStyle(y, x) == 0 and y != x
-  when false:
-    var j = 0
-    for i in a..b:
-      if line[i] != x[j]: return true
-      inc j
-    return false
-
-proc checkDef*(n: PNode; s: PSym) =
-  # operators stay as they are:
-  if s.kind in {skResult, skTemp} or s.name.s[0] notin Letters: return
-  if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
-
-  if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern:
-    checkStyle(n.info, s.name.s, s.kind)
-
-proc checkDef(c: PGen; n: PNode) =
-  if n.kind != nkSym: return
-  checkDef(n, n.sym)
-
-proc checkUse*(info: TLineInfo; s: PSym) =
-  if info.fileIndex < 0: return
-  # we simply convert it to what it looks like in the definition
-  # for consistency
-  
-  # operators stay as they are:
-  if s.kind in {skResult, skTemp} or s.name.s[0] notin Letters: return
-  if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
-  let newName = s.name.s
-  
-  loadFile(info)
-  
-  let line = gSourceFiles[info.fileIndex].lines[info.line-1]
-  var first = min(info.col.int, line.len)
-  if first < 0: return
-  #inc first, skipIgnoreCase(line, "proc ", first)
-  while first > 0 and line[first-1] in Letters: dec first
-  if first < 0: return
-  if line[first] == '`': inc first
-  
-  let last = first+identLen(line, first)-1
-  if differ(line, first, last, newName):
-    # last-first+1 != newName.len or 
-    var x = line.substr(0, first-1) & newName & line.substr(last+1)
-    when removeTP:
-      # the WinAPI module is full of 'TX = X' which after the substitution
-      # becomes 'X = X'. We remove those lines:
-      if x.match(peg"\s* {\ident} \s* '=' \s* y$1 ('#' .*)?"):
-        x = ""
-    
-    system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
-    gSourceFiles[info.fileIndex].dirty = true
-
-when false:
-  var cannotRename = initIntSet()
-
-  proc beautifyName(s: string, k: TSymKind): string =
-    let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
-    result = newStringOfCap(s.len)
-    var i = 0
-    case k
-    of skType, skGenericParam:
-      # skip leading 'T'
-      when removeTP:
-        if s[0] == 'T' and s[1] in {'A'..'Z'}:
-          i = 1
-      if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
-               "char", "byte", "bool", "openArray", "seq", "array", "void",
-               "pointer", "float", "csize", "cdouble", "cchar", "cschar",
-               "cshort", "cu"]:
-        result.add s[i]
-      else:
-        result.add toUpper(s[i])
-    of skConst, skEnumField:
-      # for 'const' we keep how it's spelt; either upper case or lower case:
-      result.add s[0]
-    else:
-      # as a special rule, don't transform 'L' to 'l'
-      if s.len == 1 and s[0] == 'L': result.add 'L'
-      else: result.add toLower(s[0])
-    inc i
-    while i < s.len:
-      if s[i] == '_':
-        inc i
-        result.add toUpper(s[i])
-      elif allUpper:
-        result.add toLower(s[i])
-      else:
-        result.add s[i]
-      inc i
-
-proc check(c: PGen, n: PNode) =
-  case n.kind
-  of nkSym: checkUse(n.info, n.sym)
-  of nkBlockStmt, nkBlockExpr, nkBlockType:
-    checkDef(c, n[0])
-    check(c, n.sons[1])
-  of nkForStmt, nkParForStmt:
-    let L = n.len
-    for i in countup(0, L-3):
-      checkDef(c, n[i])
-    check(c, n[L-2])
-    check(c, n[L-1])
-  of nkProcDef, nkLambdaKinds, nkMethodDef, nkIteratorDef, nkTemplateDef,
-      nkMacroDef, nkConverterDef:
-    checkDef(c, n[namePos])
-    for i in namePos+1 .. <n.len: check(c, n.sons[i])
-  of nkIdentDefs, nkVarTuple:
-    let a = n
-    checkMinSonsLen(a, 3)
-    let L = len(a)
-    for j in countup(0, L-3): checkDef(c, a.sons[j])
-    check(c, a.sons[L-2])
-    check(c, a.sons[L-1])
-  of nkTypeSection, nkConstSection:
-    for i in countup(0, sonsLen(n) - 1): 
-      let a = n.sons[i]
-      if a.kind == nkCommentStmt: continue 
-      checkSonsLen(a, 3)
-      checkDef(c, a.sons[0])
-      check(c, a.sons[1])
-      check(c, a.sons[2])
-  else:
-    for i in 0 .. <n.safeLen: check(c, n.sons[i])
-
-proc processSym(c: PPassContext, n: PNode): PNode = 
-  result = n
-  check(PGen(c), n)
-
-proc myOpen(module: PSym): PPassContext =
-  var g: PGen
-  new(g)
-  g.module = module
-  gCheckExtern = options.getConfigVar("pretty.checkextern").normalize == "on"
-  result = g
-  if rules.isNil:
-    rules = newStringTable(modeStyleInsensitive)
-    when removeTP:
-      # XXX activate when the T/P stuff is deprecated
-      let path = joinPath([getPrefixDir(), "config", "rename.rules.cfg"])
-      for line in lines(path):
-        if line.len > 0:
-          let colon = line.find(':')
-          if colon > 0:
-            rules[line.substr(0, colon-1)] = line.substr(colon+1)
-          else:
-            rules[line] = line
-
-const prettyPass* = makePass(open = myOpen, process = processSym)
-
diff --git a/compiler/procfind.nim b/compiler/procfind.nim
index 9f52cc117..473965a3d 100644
--- a/compiler/procfind.nim
+++ b/compiler/procfind.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -11,7 +11,7 @@
 # This is needed for proper handling of forward declarations.
 
 import
-  ast, astalgo, msgs, semdata, types, trees
+  ast, astalgo, msgs, semdata, types, trees, strutils
 
 proc equalGenericParams(procA, procB: PNode): bool =
   if sonsLen(procA) != sonsLen(procB): return
@@ -68,11 +68,17 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
                  ExactConstraints, IgnoreCC}
 
   var it: TIdentIter
+
   result = initIdentIter(it, scope.symbols, fn.name)
   while result != nil:
     if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags):
       case equalParams(result.typ.n, fn.typ.n)
       of paramsEqual:
+        if (sfExported notin result.flags) and (sfExported in fn.flags):
+          let message = ("public implementation '$1' has non-public " &
+                         "forward declaration in $2") %
+                        [getProcHeader(result), $result.info]
+          localError(fn.info, errGenerated, message)
         return
       of paramsIncompatible:
         localError(fn.info, errNotOverloadable, fn.name.s)
diff --git a/compiler/readme.txt b/compiler/readme.txt
index 3d3cf4b29..c4934e031 100644
--- a/compiler/readme.txt
+++ b/compiler/readme.txt
@@ -1,4 +1,4 @@
-This directory contains the Nimrod compiler written in Nimrod. Note that this
+This directory contains the Nim compiler written in Nim. Note that this
 code has been translated from a bootstrapping version written in Pascal, so
-the code is **not** a poster child of good Nimrod code.
+the code is **not** a poster child of good Nim code.
 
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index c97b2f321..a4469acda 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -1,13 +1,13 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-# This module implements the renderer of the standard Nimrod representation.
+# This module implements the renderer of the standard Nim representation.
 
 import 
   lexer, options, idents, strutils, ast, msgs, lists
@@ -1009,9 +1009,9 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     put(g, tkElse, " else")
     putWithSpace(g, tkColon, ":")
     gsub(g, n.sons[0])
-  of nkTypeOfExpr: 
+  of nkTypeOfExpr:
     putWithSpace(g, tkType, "type")
-    gsub(g, n.sons[0])
+    if n.len > 0: gsub(g, n.sons[0])
   of nkRefTy: 
     if sonsLen(n) > 0:
       putWithSpace(g, tkRef, "ref")
@@ -1306,7 +1306,7 @@ proc renderTree(n: PNode, renderFlags: TRenderFlags = {}): string =
 proc renderModule(n: PNode, filename: string, 
                   renderFlags: TRenderFlags = {}) =
   var
-    f: TFile
+    f: File
     g: TSrcGen
   initSrcGen(g, renderFlags)
   for i in countup(0, sonsLen(n) - 1):
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index 036e6cc3c..3b3538e5d 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -121,7 +121,7 @@ type
     r*: string                # writers use this
     offset*: int              # readers use this
   
-  TRodReader* = object of TObject
+  TRodReader* = object of RootObj
     pos: int                 # position; used for parsing
     s: cstring               # mmap'ed file contents
     options: TOptions
@@ -137,7 +137,7 @@ type
     line: int            # only used for debugging, but is always in the code
     moduleID: int
     syms: TIdTable       # already processed symbols
-    memfile: TMemFile    # unfortunately there is no point in time where we
+    memfile: MemFile     # unfortunately there is no point in time where we
                          # can close this! XXX
     methods*: TSymSeq
     origFile: string
@@ -280,11 +280,6 @@ proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
       loc.r = toRope(decodeStr(r.s, r.pos))
     else: 
       loc.r = nil
-    if r.s[r.pos] == '?': 
-      inc(r.pos)
-      loc.a = decodeVInt(r.s, r.pos)
-    else: 
-      loc.a = 0
     if r.s[r.pos] == '>': inc(r.pos)
     else: internalError(info, "decodeLoc " & r.s[r.pos])
   
@@ -326,7 +321,7 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
     result.size = - 1
   if r.s[r.pos] == '=': 
     inc(r.pos)
-    result.align = decodeVInt(r.s, r.pos)
+    result.align = decodeVInt(r.s, r.pos).int16
   else: 
     result.align = 2
   decodeLoc(r, result.loc, info)
@@ -503,7 +498,7 @@ proc processCompilerProcs(r: PRodReader, module: PSym) =
       idTablePut(r.syms, s, s)
     strTableAdd(rodCompilerprocs, s)
 
-proc processIndex(r: PRodReader; idx: var TIndex; outf: TFile = nil) = 
+proc processIndex(r: PRodReader; idx: var TIndex; outf: File = nil) = 
   var key, val, tmp: int
   inc(r.pos, 2)               # skip "(\10"
   inc(r.line)
@@ -659,7 +654,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
   new(result)
   try:
     result.memfile = memfiles.open(modfilename)
-  except EOS:
+  except OSError:
     return nil
   result.files = @[]
   result.modDeps = @[]
@@ -916,7 +911,7 @@ initIdTable(gTypeTable)
 initStrTable(rodCompilerprocs)
 
 # viewer:
-proc writeNode(f: TFile; n: PNode) =
+proc writeNode(f: File; n: PNode) =
   f.write("(")
   if n != nil:
     f.write($n.kind)
@@ -947,7 +942,7 @@ proc writeNode(f: TFile; n: PNode) =
         writeNode(f, n.sons[i])
   f.write(")")
 
-proc writeSym(f: TFile; s: PSym) =
+proc writeSym(f: File; s: PSym) =
   if s == nil:
     f.write("{}\n")
     return
@@ -985,7 +980,7 @@ proc writeSym(f: TFile; s: PSym) =
     f.writeNode(s.ast)
   f.write("}\n")
 
-proc writeType(f: TFile; t: PType) =
+proc writeType(f: File; t: PType) =
   if t == nil:
     f.write("[]\n")
     return
diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim
index 09b92cd8a..e0ef3c397 100644
--- a/compiler/rodutils.nim
+++ b/compiler/rodutils.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index 4231da2d0..9fed7ac52 100644
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -187,9 +187,6 @@ proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
   if loc.r != nil: 
     add(result, '!')
     encodeStr(ropeToStr(loc.r), result)
-  if loc.a != 0: 
-    add(result, '?')
-    encodeVInt(loc.a, result)
   if oldLen + 1 == result.len:
     # no data was necessary, so remove the '<' again:
     setLen(result, oldLen)
@@ -297,7 +294,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
   # 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 Nimrod's heavy compile-time evaluation features
+    # it is not necessary, but Nim's heavy compile-time evaluation features
     # make that unfeasible nowadays:
     encodeNode(w, s.info, s.ast, result)
     when false:
@@ -422,7 +419,7 @@ proc addStmt(w: PRodWriter, n: PNode) =
 
 proc writeRod(w: PRodWriter) = 
   processStacks(w, true)
-  var f: TFile
+  var f: File
   if not open(f, completeGeneratedFilePath(changeFileExt(
                       w.filename.withPackageName, RodExt)),
               fmWrite):
diff --git a/compiler/ropes.nim b/compiler/ropes.nim
index fcf5dd202..b14081694 100644
--- a/compiler/ropes.nim
+++ b/compiler/ropes.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -12,7 +12,7 @@
 #  Ropes are a data structure that represents a very long string
 #  efficiently; especially concatenation is done in O(1) instead of O(N).
 #  Ropes make use a lazy evaluation: They are essentially concatenation
-#  trees that are only flattened when converting to a native Nimrod
+#  trees that are only flattened when converting to a native Nim
 #  string or when written to disk. The empty string is represented by a
 #  nil pointer.
 #  A little picture makes everything clear:
@@ -64,7 +64,7 @@ type
                        # copy the format strings
                        # though it is not necessary)
   PRope* = ref TRope
-  TRope*{.acyclic.} = object of TObject # the empty rope is represented 
+  TRope*{.acyclic.} = object of RootObj # the empty rope is represented 
                                         # by nil to safe space
     left*, right*: PRope
     length*: int
@@ -216,7 +216,7 @@ proc app(a: var PRope, b: PRope) = a = con(a, b)
 proc app(a: var PRope, b: string) = a = con(a, b)
 proc prepend(a: var PRope, b: PRope) = a = con(b, a)
 
-proc writeRope*(f: TFile, c: PRope) = 
+proc writeRope*(f: File, c: PRope) = 
   var stack = @[c]
   while len(stack) > 0: 
     var it = pop(stack)
@@ -228,7 +228,7 @@ proc writeRope*(f: TFile, c: PRope) =
     write(f, it.data)
 
 proc writeRope*(head: PRope, filename: string, useWarning = false) =
-  var f: TFile
+  var f: File
   if open(f, filename, fmWrite):
     if head != nil: writeRope(f, head)
     close(f)
@@ -299,7 +299,7 @@ proc appf(c: var PRope, frmt: TFormatStr, args: varargs[PRope]) =
 const 
   bufSize = 1024              # 1 KB is reasonable
 
-proc auxRopeEqualsFile(r: PRope, bin: var TFile, buf: pointer): bool = 
+proc auxRopeEqualsFile(r: PRope, bin: var File, buf: pointer): bool = 
   if r.data != nil:
     if r.length > bufSize:
       errorHandler(rTokenTooLong, r.data)
@@ -312,7 +312,7 @@ proc auxRopeEqualsFile(r: PRope, bin: var TFile, buf: pointer): bool =
     if result: result = auxRopeEqualsFile(r.right, bin, buf)
   
 proc ropeEqualsFile(r: PRope, f: string): bool = 
-  var bin: TFile
+  var bin: File
   result = open(bin, f)
   if not result: 
     return                    # not equal if file does not exist
diff --git a/compiler/saturate.nim b/compiler/saturate.nim
index ed197bdd1..f4fe29a20 100644
--- a/compiler/saturate.nim
+++ b/compiler/saturate.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 26a59334c..81846e1b4 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -15,9 +15,12 @@ import
   magicsys, parser, nversion, nimsets, semfold, importer,
   procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
   intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
-  evaltempl, patterns, parampatterns, sempass2, pretty, semmacrosanity,
+  evaltempl, patterns, parampatterns, sempass2, nimfix.pretty, semmacrosanity,
   semparallel, lowerings
 
+when defined(nimfix):
+  import nimfix.prettybase
+
 # implementation
 
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.procvar.}
@@ -37,8 +40,7 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym)
 proc addParams(c: PContext, n: PNode, kind: TSymKind)
 proc maybeAddResult(c: PContext, s: PSym, n: PNode)
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
-proc tryExpr(c: PContext, n: PNode,
-             flags: TExprFlags = {}, bufferErrors = false): PNode
+proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 proc fixImmediateParams(n: PNode): PNode
 proc activate(c: PContext, n: PNode)
 proc semQuoteAst(c: PContext, n: PNode): PNode
@@ -308,6 +310,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
   pushInfoContext(nOrig.info)
 
   markUsed(n.info, sym)
+  styleCheckUse(n.info, sym)
   if sym == c.p.owner:
     globalError(n.info, errRecursiveDependencyX, sym.name.s)
 
@@ -340,7 +343,7 @@ type
   TSemGenericFlags = set[TSemGenericFlag]
 
 proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
-                    ctx: var TIntSet): PNode
+                    ctx: var IntSet): PNode
 
 include semtypes, semtempl, semgnrc, semstmts, semexprs
 
@@ -367,6 +370,8 @@ proc myOpen(module: PSym): PPassContext =
   c.semInferredLambda = semInferredLambda
   c.semGenerateInstance = generateInstance
   c.semTypeNode = semTypeNode
+  c.instDeepCopy = sigmatch.instDeepCopy
+
   pushProcCon(c, module)
   pushOwner(c.module)
   c.importTable = openScope(c)
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
new file mode 100644
index 000000000..483d36bf3
--- /dev/null
+++ b/compiler/semasgn.nim
@@ -0,0 +1,197 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements lifting for assignments and ``deepCopy``.
+
+# included from sem.nim
+
+type
+  TLiftCtx = object
+    c: PContext
+    info: TLineInfo # for construction
+    result: PNode
+    kind: TTypeAttachedOp
+
+type
+  TFieldInstCtx = object  # either 'tup[i]' or 'field' is valid
+    tupleType: PType      # if != nil we're traversing a tuple
+    tupleIndex: int
+    field: PSym
+    replaceByFieldName: bool
+
+proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
+  case n.kind
+  of nkEmpty..pred(nkIdent), succ(nkIdent)..nkNilLit: result = n
+  of nkIdent:
+    result = n
+    var L = sonsLen(forLoop)
+    if c.replaceByFieldName:
+      if n.ident.id == forLoop[0].ident.id:
+        let fieldName = if c.tupleType.isNil: c.field.name.s
+                        elif c.tupleType.n.isNil: "Field" & $c.tupleIndex
+                        else: c.tupleType.n.sons[c.tupleIndex].sym.name.s
+        result = newStrNode(nkStrLit, fieldName)
+        return
+    # other fields:
+    for i in ord(c.replaceByFieldName)..L-3:
+      if n.ident.id == forLoop[i].ident.id:
+        var call = forLoop.sons[L-2]
+        var tupl = call.sons[i+1-ord(c.replaceByFieldName)]
+        if c.field.isNil:
+          result = newNodeI(nkBracketExpr, n.info)
+          result.add(tupl)
+          result.add(newIntNode(nkIntLit, c.tupleIndex))
+        else:
+          result = newNodeI(nkDotExpr, n.info)
+          result.add(tupl)
+          result.add(newSymNode(c.field, n.info))
+        break
+  else:
+    if n.kind == nkContinueStmt:
+      localError(n.info, errGenerated,
+                 "'continue' not supported in a 'fields' loop")
+    result = copyNode(n)
+    newSons(result, sonsLen(n))
+    for i in countup(0, sonsLen(n)-1):
+      result.sons[i] = instFieldLoopBody(c, n.sons[i], forLoop)
+
+proc liftBodyObj(c: TLiftCtx; typ, x, y: PNode) =
+  case typ.kind
+  of nkSym:
+    var fc: TFieldInstCtx  # either 'tup[i]' or 'field' is valid
+    fc.field = typ.sym
+    fc.replaceByFieldName = c.m == mFieldPairs
+    openScope(c.c)
+    inc c.c.inUnrolledContext
+    let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
+    father.add(semStmt(c.c, body))
+    dec c.c.inUnrolledContext
+    closeScope(c.c)
+  of nkNilLit: discard
+  of nkRecCase:
+    let L = forLoop.len
+    let call = forLoop.sons[L-2]
+    if call.len > 2:
+      localError(forLoop.info, errGenerated, 
+                 "parallel 'fields' iterator does not work for 'case' objects")
+      return
+    # iterate over the selector:
+    asgnForObjectFields(c, typ[0], forLoop, father)
+    # we need to generate a case statement:
+    var caseStmt = newNodeI(nkCaseStmt, c.info)
+    # generate selector:
+    var access = newNodeI(nkDotExpr, forLoop.info, 2)
+    access.sons[0] = call.sons[1]
+    access.sons[1] = newSymNode(typ.sons[0].sym, forLoop.info)
+    caseStmt.add(semExprWithType(c.c, access))
+    # copy the branches over, but replace the fields with the for loop body:
+    for i in 1 .. <typ.len:
+      var branch = copyTree(typ[i])
+      let L = branch.len
+      branch.sons[L-1] = newNodeI(nkStmtList, forLoop.info)
+      semForObjectFields(c, typ[i].lastSon, forLoop, branch[L-1])
+      caseStmt.add(branch)
+    father.add(caseStmt)
+  of nkRecList:
+    for t in items(typ): liftBodyObj(c, t, x, y)
+  else:
+    illFormedAst(typ)
+
+proc newAsgnCall(op: PSym; x, y: PNode): PNode =
+  result = newNodeI(nkCall, x.info)
+  result.add(newSymNode(op))
+  result.add x
+  result.add y
+
+proc newAsgnStmt(le, ri: PNode): PNode =
+  result = newNodeI(nkAsgn, le.info, 2)
+  result.sons[0] = le
+  result.sons[1] = ri
+
+proc newDestructorCall(op: PSym; x: PNode): PNode =
+  result = newNodeIT(nkCall, x.info, op.typ.sons[0])
+  result.add(newSymNode(op))
+  result.add x  
+
+proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
+  result = newAsgnStmt(x, newDestructorCall(op, y))
+
+proc considerOverloadedOp(c: TLiftCtx; t: PType; x, y: PNode): bool =
+  let op = t.attachedOps[c.kind]
+  if op != nil:
+    markUsed(c.info, op)
+    styleCheckUse(c.info, op)
+    case c.kind
+    of attachedDestructor:
+      c.result.add newDestructorCall(op, x)
+    of attachedAsgn:
+      c.result.add newAsgnCall(op, x, y)
+    of attachedDeepCopy:
+      c.result.add newDeepCopyCall(op, x, y)
+    result = true
+
+proc defaultOp(c: TLiftCtx; t: PType; x, y: PNode) =
+  if c.kind != attachedDestructor:
+    c.result.add newAsgnStmt(x, y)
+
+proc liftBodyAux(c: TLiftCtx; t: PType; x, y: PNode) =
+  const hasAttachedOp: array[TTypeAttachedOp, TTypeIter] = [
+    (proc (t: PType, closure: PObject): bool =
+       t.attachedOp[attachedDestructor] != nil),
+    (proc (t: PType, closure: PObject): bool =
+       t.attachedOp[attachedAsgn] != nil),
+    (proc (t: PType, closure: PObject): bool =
+       t.attachedOp[attachedDeepCopy] != nil)]
+  case t.kind
+  of tyNone, tyEmpty: discard
+  of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString:
+    defaultOp(c, t, x, y)
+  of tyPtr, tyString:
+    if not considerOverloadedOp(c, t, x, y):
+      defaultOp(c, t, x, y)
+  of tyArrayConstr, tyArray, tySequence:
+    if iterOverType(lastSon(t), hasAttachedOp[c.kind], nil):
+      # generate loop and call the attached Op:
+      
+    else:
+      defaultOp(c, t, x, y)
+  of tyObject:
+    liftBodyObj(c, t.n, x, y)
+  of tyTuple:
+    liftBodyTup(c, t, x, y)
+  of tyRef:
+    # we MUST not check for acyclic here as a DAG might still share nodes:
+    
+  of tyProc:
+    if t.callConv != ccClosure or c.kind != attachedDeepCopy:
+      defaultOp(c, t, x, y)
+    else:
+      # a big problem is that we don't know the enviroment's type here, so we
+      # have to go through some indirection; we delegate this to the codegen:
+      call = newNodeI(nkCall, n.info, 2)
+      call.typ = t
+      call.sons[0] = newSymNode(createMagic("deepCopy", mDeepCopy))
+      call.sons[1] = y
+      c.result.add newAsgnStmt(x, call)
+  of tyVarargs, tyOpenArray:
+    localError(c.info, errGenerated, "cannot copy openArray")
+  of tyFromExpr, tyIter, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
+     tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
+     tyMutable, tyGenericParam, tyGenericBody, tyNil, tyExpr, tyStmt,
+     tyTypeDesc, tyGenericInvokation, tyBigNum, tyConst, tyForward:
+    internalError(c.info, "assignment requested for type: " & typeToString(t))
+  of tyDistinct, tyOrdinal, tyRange,
+     tyGenericInst, tyFieldAccessor, tyStatic, tyVar:
+    liftBodyAux(c, lastSon(t))
+
+proc liftBody(c: PContext; typ: PType; info: TLineInfo): PNode =
+  var a: TLiftCtx
+  a.info = info
+  a.result = newNodeI(nkStmtList, info)
+  liftBodyAux(a, typ)
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 927b23cf2..3971b8ff5 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -39,7 +39,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
                        initialBinding: PNode,
                        filter: TSymKinds,
                        best, alt: var TCandidate,
-                       errors: var seq[string]) =
+                       errors: var CandidateErrors) =
   var o: TOverloadIter
   var sym = initOverloadIter(o, c, headSymbol)
   var symScope = o.lastOverloadScope
@@ -58,10 +58,10 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
       z.calleeSym = sym
       matches(c, n, orig, z)
       if errors != nil:
-        errors.safeAdd(getProcHeader(sym))
+        errors.safeAdd(sym)
         if z.errors != nil:
           for err in z.errors:
-            errors[errors.len - 1].add("\n  " & err)
+            errors.add(err)
       if z.state == csMatch:
         # little hack so that iterators are preferred over everything else:
         if sym.kind in skIterators: inc(z.exactMatches, 200)
@@ -74,7 +74,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
           else: discard
     sym = nextOverloadIter(o, c, headSymbol)
 
-proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) =
+proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
   # Gives a detailed error message; this is separated from semOverloadedCall,
   # as semOverlodedCall is already pretty slow (and we need this information
   # only in case of an error).
@@ -83,18 +83,38 @@ proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) =
     globalError(n.info, errTypeMismatch, "")
   if errors.len == 0:
     localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
+
+  # to avoid confusing errors like: 
+  #   got (SslPtr, SocketHandle)
+  #   but expected one of: 
+  #   openssl.SSL_set_fd(ssl: SslPtr, fd: SocketHandle): cint
+  # we do a pre-analysis. If all types produce the same string, we will add
+  # module information.
+  let proto = describeArgs(c, n, 1, preferName)
+  
+  var prefer = preferName
+  for err in errors:
+    var errProto = ""
+    let n = err.typ.n
+    for i in countup(1, n.len - 1): 
+      var p = n.sons[i]
+      if p.kind == nkSym:
+        add(errProto, typeToString(p.sym.typ, preferName))
+        if i != n.len-1: add(errProto, ", ")
+      # else: ignore internal error as we're already in error handling mode
+    if errProto == proto:
+      prefer = preferModuleInfo
+      break
+  # now use the information stored in 'prefer' to produce a nice error message:
   var result = msgKindToString(errTypeMismatch)
-  add(result, describeArgs(c, n, 1))
+  add(result, describeArgs(c, n, 1, prefer))
   add(result, ')')
-  
   var candidates = ""
   for err in errors:
-    add(candidates, err)
+    add(candidates, err.getProcHeader(prefer))
     add(candidates, "\n")
-
   if candidates != "":
     add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
-
   localError(n.info, errGenerated, result)
 
 proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) =
@@ -114,7 +134,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
   else:
     initialBinding = nil
 
-  var errors: seq[string]
+  var errors: CandidateErrors
   var usedSyms: seq[PNode]
 
   template pickBest(headSymbol: expr) =
@@ -254,6 +274,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
   assert x.state == csMatch
   var finalCallee = x.calleeSym
   markUsed(n.sons[0].info, finalCallee)
+  styleCheckUse(n.sons[0].info, finalCallee)
   if finalCallee.ast == nil:
     internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
   if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
@@ -286,6 +307,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
   initCandidate(c, m, s, n)
   var newInst = generateInstance(c, s, m.bindings, n.info)
   markUsed(n.info, s)
+  styleCheckUse(n.info, s)
   result = newSymNode(newInst, n.info)
 
 proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
@@ -305,7 +327,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     result = explicitGenericSym(c, n, s)
   elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
     # choose the generic proc with the proper number of type parameters.
-    # XXX I think this could be improved by reusing sigmatch.ParamTypesMatch.
+    # XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
     # It's good enough for now.
     result = newNodeI(a.kind, n.info)
     for i in countup(0, len(a)-1): 
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index abecc1b6d..921e87d30 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -57,7 +57,7 @@ type
                                # can access private object fields
     instCounter*: int          # to prevent endless instantiations
    
-    ambiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
+    ambiguousSymbols*: IntSet  # ids of all ambiguous symbols (cannot
                                # store this info in the syms themselves!)
     inTypeClass*: int          # > 0 if we are in a user-defined type class
     inGenericContext*: int     # > 0 if we are in a generic type
@@ -72,8 +72,7 @@ type
     libs*: TLinkedList         # all libs used by this module
     semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
     semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
-    semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {},
-                       bufferErrors = false): PNode {.nimcall.}
+    semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {}): PNode {.nimcall.}
     semTryConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.}
     semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
     semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
@@ -83,15 +82,18 @@ type
     semInferredLambda*: proc(c: PContext, pt: TIdTable, n: PNode): PNode
     semGenerateInstance*: proc (c: PContext, fn: PSym, pt: TIdTable,
                                 info: TLineInfo): PSym
-    includedFiles*: TIntSet    # used to detect recursive include files
+    includedFiles*: IntSet    # used to detect recursive include files
     userPragmas*: TStrTable
     evalContext*: PEvalContext
-    unknownIdents*: TIntSet    # ids of all unknown identifiers to prevent
+    unknownIdents*: IntSet     # ids of all unknown identifiers to prevent
                                # naming it multiple times
     generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
     lastGenericIdx*: int      # used for the generics stack
     hloLoopDetector*: int     # used to prevent endless loops in the HLO
     inParallelStmt*: int
+    instDeepCopy*: proc (c: PContext; dc: PSym; t: PType;
+                         info: TLineInfo): PSym {.nimcall.}
+
    
 proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
   result.genericSym = s
diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim
index 3c30dc1bd..4ce610bf9 100644
--- a/compiler/semdestruct.nim
+++ b/compiler/semdestruct.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 58cef36f9..287a11b33 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -13,6 +13,7 @@
 proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
                      flags: TExprFlags = {}): PNode =
   markUsed(n.info, s)
+  styleCheckUse(n.info, s)
   pushInfoContext(n.info)
   result = evalTemplate(n, s, getCurrOwner())
   if efNoSemCheck notin flags: result = semAfterMacroCall(c, result, s, flags)
@@ -79,6 +80,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   case s.kind
   of skConst:
     markUsed(n.info, s)
+    styleCheckUse(n.info, s)
     case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
     of  tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, 
         tyTuple, tySet, tyUInt..tyUInt64:
@@ -103,6 +105,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   of skTemplate: result = semTemplateExpr(c, n, s, flags)
   of skVar, skLet, skResult, skParam, skForVar:
     markUsed(n.info, s)
+    styleCheckUse(n.info, s)
     # if a proc accesses a global variable, it is not side effect free:
     if sfGlobal in s.flags:
       incl(c.p.owner.flags, sfSideEffect)
@@ -115,6 +118,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     # var len = 0 # but won't be called
     # genericThatUsesLen(x) # marked as taking a closure?
   of skGenericParam:
+    styleCheckUse(n.info, s)
     if s.typ.kind == tyStatic:
       result = newSymNode(s, n.info)
       result.typ = s.typ
@@ -125,12 +129,14 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
       return n
   of skType:
     markUsed(n.info, s)
+    styleCheckUse(n.info, s)
     if s.typ.kind == tyStatic and s.typ.n != nil:
       return s.typ.n
     result = newSymNode(s, n.info)
     result.typ = makeTypeDesc(c, s.typ)
   else:
     markUsed(n.info, s)
+    styleCheckUse(n.info, s)
     result = newSymNode(s, n.info)
 
 type
@@ -259,6 +265,7 @@ proc semConv(c: PContext, n: PNode): PNode =
       let status = checkConvertible(c, result.typ, it.typ)
       if status in {convOK, convNotNeedeed}:
         markUsed(n.info, it.sym)
+        styleCheckUse(n.info, it.sym)
         markIndirect(c, it.sym)
         return it
     localError(n.info, errUseQualifier, op.sons[0].sym.name.s)
@@ -360,6 +367,7 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
       result = newIntNode(nkIntLit, ord(t.kind == tyProc and
                                         t.callConv == ccClosure and 
                                         tfIterator notin t.flags))
+    else: discard
   else:
     var t2 = n[2].typ.skipTypes({tyTypeDesc})
     maybeLiftType(t2, c, n.info)
@@ -981,6 +989,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
   if s != nil:
     markUsed(n.sons[1].info, s)
+    styleCheckUse(n.sons[1].info, s)
     return semSym(c, n, s, flags)
 
   n.sons[0] = semExprWithType(c, n.sons[0], flags+{efDetermineType})
@@ -1004,6 +1013,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
         result.info = n.info
         result.typ = ty
         markUsed(n.info, f)
+        styleCheckUse(n.info, f)
         return
     of tyTypeParamsHolders:
       return readTypeParameter(c, ty, i, n.info)
@@ -1036,12 +1046,13 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
       if fieldVisible(c, f):
         # is the access to a public field or in the same module or in a friend?
         markUsed(n.sons[1].info, f)
+        styleCheckUse(n.sons[1].info, f)
         n.sons[0] = makeDeref(n.sons[0])
         n.sons[1] = newSymNode(f) # we now have the correct field
         n.typ = f.typ
-        if check == nil: 
+        if check == nil:
           result = n
-        else: 
+        else:
           check.sons[0] = n
           check.typ = n.typ
           result = check
@@ -1049,6 +1060,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
     f = getSymFromList(ty.n, i)
     if f != nil:
       markUsed(n.sons[1].info, f)
+      styleCheckUse(n.sons[1].info, f)
       n.sons[0] = makeDeref(n.sons[0])
       n.sons[1] = newSymNode(f)
       n.typ = f.typ
@@ -1465,6 +1477,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
 
   macroCall.sons[0] = newSymNode(expandedSym, macroCall.info)
   markUsed(n.info, expandedSym)
+  styleCheckUse(n.info, expandedSym)
 
   for i in countup(1, macroCall.len-1):
     macroCall.sons[i] = semExprWithType(c, macroCall[i], {})
@@ -1538,8 +1551,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
     newNode(nkCall, n.info, quotes)])
   result = semExpandToAst(c, result)
 
-proc tryExpr(c: PContext, n: PNode,
-             flags: TExprFlags = {}, bufferErrors = false): PNode =
+proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   # watch out, hacks ahead:
   let oldErrorCount = msgs.gErrorCounter
   let oldErrorMax = msgs.gErrorMax
@@ -1553,7 +1565,7 @@ proc tryExpr(c: PContext, n: PNode,
   let oldOwnerLen = len(gOwners)
   let oldGenerics = c.generics
   let oldErrorOutputs = errorOutputs
-  errorOutputs = if bufferErrors: {eInMemory} else: {}
+  #errorOutputs = if bufferErrors: {eInMemory} else: {}
   let oldContextLen = msgs.getInfoContextLen()
   
   let oldInGenericContext = c.inGenericContext
@@ -1821,7 +1833,7 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
     addSonSkipIntLit(typ, n.sons[i].typ)
   result.typ = typ
 
-proc checkInitialized(n: PNode, ids: TIntSet, info: TLineInfo) =
+proc checkInitialized(n: PNode, ids: IntSet, info: TLineInfo) =
   case n.kind
   of nkRecList:
     for i in countup(0, sonsLen(n) - 1):
@@ -1902,6 +1914,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
       addDecl(c, labl)
       n.sons[0] = newSymNode(labl, n.sons[0].info)
     suggestSym(n.sons[0].info, labl)
+    styleCheckDef(labl)
   n.sons[1] = semExpr(c, n.sons[1])
   n.typ = n.sons[1].typ
   if isEmptyType(n.typ): n.kind = nkBlockStmt
@@ -1932,11 +1945,22 @@ proc semExport(c: PContext, n: PNode): PNode =
     if s == nil:
       localError(a.info, errGenerated, "invalid expr for 'export': " &
           renderTree(a))
-    while s != nil:
-      if s.kind in ExportableSymKinds+{skModule}:
-        x.add(newSymNode(s, a.info))
-        strTableAdd(c.module.tab, s)
-      s = nextOverloadIter(o, c, a)
+    elif s.kind == skModule:
+      # forward everything from that module:
+      strTableAdd(c.module.tab, s)
+      x.add(newSymNode(s, a.info))
+      var ti: TTabIter
+      var it = initTabIter(ti, s.tab)
+      while it != nil:
+        if it.kind in ExportableSymKinds+{skModule}:
+          strTableAdd(c.module.tab, it)
+        it = nextIter(ti, s.tab)
+    else:
+      while s != nil:
+        if s.kind in ExportableSymKinds+{skModule}:
+          x.add(newSymNode(s, a.info))
+          strTableAdd(c.module.tab, s)
+        s = nextOverloadIter(o, c, a)
   when false:
     if c.module.ast.isNil:
       c.module.ast = newNodeI(nkStmtList, n.info)
@@ -2021,9 +2045,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     checkMinSonsLen(n, 1)
     let mode = if nfDotField in n.flags: {} else: {checkUndeclared}
     var s = qualifiedLookUp(c, n.sons[0], mode)
-    if s != nil: 
-      if gCmd == cmdPretty and n.sons[0].kind == nkDotExpr:
-        pretty.checkUse(n.sons[0].sons[1].info, s)
+    if s != nil:
+      #if gCmd == cmdPretty and n.sons[0].kind == nkDotExpr:
+      #  pretty.checkUse(n.sons[0].sons[1].info, s)
       case s.kind
       of skMacro:
         if sfImmediate notin s.flags:
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 30e02dcc9..76ac23e0d 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -255,6 +255,7 @@ proc evalIs(n, a: PNode): PNode =
       result = newIntNode(nkIntLit, ord(t.kind == tyProc and
                                         t.callConv == ccClosure and 
                                         tfIterator in t.flags))
+    else: discard
   else:
     # XXX semexprs.isOpImpl is slightly different and requires a context. yay.
     let t2 = n[2].typ
@@ -683,9 +684,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
           result = evalIs(n, a)
       else:
         result = magicCall(m, n)
-    except EOverflow: 
+    except OverflowError: 
       localError(n.info, errOverOrUnderflow)
-    except EDivByZero: 
+    except DivByZeroError: 
       localError(n.info, errConstantDivisionByZero)
   of nkAddr: 
     var a = getConstExpr(m, n.sons[0])
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index a004d1465..6c218fa0c 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -28,7 +28,7 @@ proc getIdentNode(n: PNode): PNode =
   
 proc semGenericStmtScope(c: PContext, n: PNode, 
                          flags: TSemGenericFlags,
-                         ctx: var TIntSet): PNode = 
+                         ctx: var IntSet): PNode = 
   openScope(c)
   result = semGenericStmt(c, n, flags, ctx)
   closeScope(c)
@@ -37,7 +37,7 @@ template macroToExpand(s: expr): expr =
   s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags)
 
 proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
-                          ctx: var TIntSet): PNode =
+                          ctx: var IntSet): PNode =
   incl(s.flags, sfUsed)
   case s.kind
   of skUnknown:
@@ -47,33 +47,40 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
     result = symChoice(c, n, s, scOpen)
   of skTemplate:
     if macroToExpand(s):
+      styleCheckUse(n.info, s)
       let n = fixImmediateParams(n)
       result = semTemplateExpr(c, n, s, {efNoSemCheck})
       result = semGenericStmt(c, result, {}, ctx)
     else:
       result = symChoice(c, n, s, scOpen)
-  of skMacro: 
+  of skMacro:
     if macroToExpand(s):
+      styleCheckUse(n.info, s)
       result = semMacroExpr(c, n, n, s, {efNoSemCheck})
       result = semGenericStmt(c, result, {}, ctx)
     else:
       result = symChoice(c, n, s, scOpen)
   of skGenericParam: 
     result = newSymNodeTypeDesc(s, n.info)
-  of skParam: 
+    styleCheckUse(n.info, s)
+  of skParam:
     result = n
+    styleCheckUse(n.info, s)
   of skType: 
     if (s.typ != nil) and (s.typ.kind != tyGenericParam): 
       result = newSymNodeTypeDesc(s, n.info)
     else: 
       result = n
-  else: result = newSymNode(s, n.info)
+    styleCheckUse(n.info, s)
+  else:
+    result = newSymNode(s, n.info)
+    styleCheckUse(n.info, s)
 
 proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags, 
-            ctx: var TIntSet): PNode =
+            ctx: var IntSet): PNode =
   result = n
   let ident = considerQuotedIdent(n)
-  var s = searchInScopes(c, ident)
+  var s = searchInScopes(c, ident).skipAlias(n)
   if s == nil:
     if ident.id notin ctx and withinMixin notin flags:
       localError(n.info, errUndeclaredIdentifier, ident.s)
@@ -92,7 +99,7 @@ proc newDot(n, b: PNode): PNode =
   result.add(b)
 
 proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, 
-                 ctx: var TIntSet): PNode =
+                 ctx: var IntSet): PNode =
   assert n.kind == nkDotExpr
   let luf = if withinMixin notin flags: {checkUndeclared} else: {}
   
@@ -104,7 +111,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
     result = n
     let n = n[1]
     let ident = considerQuotedIdent(n)
-    var s = searchInScopes(c, ident)
+    var s = searchInScopes(c, ident).skipAlias(n)
     if s != nil and s.kind in routineKinds:
       if withinBind in flags:
         result = newDot(result, symChoice(c, n, s, scClosed))
@@ -117,8 +124,13 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
         else:
           result = newDot(result, sym)
 
+proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) =
+  let s = newSymS(skUnknown, getIdentNode(n), c)
+  addPrelimDecl(c, s)
+  styleCheckDef(n.info, s, kind)
+
 proc semGenericStmt(c: PContext, n: PNode, 
-                    flags: TSemGenericFlags, ctx: var TIntSet): PNode =
+                    flags: TSemGenericFlags, ctx: var IntSet): PNode =
   result = n
   if gCmd == cmdIdeTools: suggestStmt(c, n)
   case n.kind
@@ -161,13 +173,15 @@ proc semGenericStmt(c: PContext, n: PNode,
       case s.kind
       of skMacro:
         if macroToExpand(s):
+          styleCheckUse(fn.info, s)
           result = semMacroExpr(c, n, n, s, {efNoSemCheck})
           result = semGenericStmt(c, result, {}, ctx)
         else:
           n.sons[0] = symChoice(c, n.sons[0], s, scOption)
           result = n
-      of skTemplate: 
+      of skTemplate:
         if macroToExpand(s):
+          styleCheckUse(fn.info, s)
           let n = fixImmediateParams(n)
           result = semTemplateExpr(c, n, s, {efNoSemCheck})
           result = semGenericStmt(c, result, {}, ctx)
@@ -184,14 +198,17 @@ proc semGenericStmt(c: PContext, n: PNode,
         first = 1
       of skGenericParam:
         result.sons[0] = newSymNodeTypeDesc(s, n.sons[0].info)
+        styleCheckUse(fn.info, s)
         first = 1
       of skType: 
         # bad hack for generics:
         if (s.typ != nil) and (s.typ.kind != tyGenericParam): 
           result.sons[0] = newSymNodeTypeDesc(s, n.sons[0].info)
+          styleCheckUse(fn.info, s)
           first = 1
       else:
         result.sons[0] = newSymNode(s, n.sons[0].info)
+        styleCheckUse(fn.info, s)
         first = 1
     # Consider 'when defined(globalsSlot): ThreadVarSetValue(globalsSlot, ...)'
     # in threads.nim: the subtle preprocessing here binds 'globalsSlot' which 
@@ -226,14 +243,14 @@ proc semGenericStmt(c: PContext, n: PNode,
     openScope(c)
     n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
     for i in countup(0, L - 3):
-      addPrelimDecl(c, newSymS(skUnknown, n.sons[i], c))
+      addTempDecl(c, n.sons[i], skForVar)
     n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx)
     closeScope(c)
   of nkBlockStmt, nkBlockExpr, nkBlockType: 
     checkSonsLen(n, 2)
     openScope(c)
     if n.sons[0].kind != nkEmpty: 
-      addPrelimDecl(c, newSymS(skUnknown, n.sons[0], c))
+      addTempDecl(c, n.sons[0], skLabel)
     n.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
     closeScope(c)
   of nkTryStmt: 
@@ -256,7 +273,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
       a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
       for j in countup(0, L-3):
-        addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
+        addTempDecl(c, getIdentNode(a.sons[j]), skVar)
   of nkGenericParams: 
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
@@ -266,23 +283,23 @@ proc semGenericStmt(c: PContext, n: PNode,
       a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx) 
       # do not perform symbol lookup for default expressions 
       for j in countup(0, L-3): 
-        addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
+        addTempDecl(c, getIdentNode(a.sons[j]), skType)
   of nkConstSection: 
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if (a.kind != nkConstDef): illFormedAst(a)
       checkSonsLen(a, 3)
-      addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c))
+      addTempDecl(c, getIdentNode(a.sons[0]), skConst)
       a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, ctx)
       a.sons[2] = semGenericStmt(c, a.sons[2], flags, ctx)
-  of nkTypeSection: 
+  of nkTypeSection:
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if (a.kind != nkTypeDef): illFormedAst(a)
       checkSonsLen(a, 3)
-      addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c))
+      addTempDecl(c, getIdentNode(a.sons[0]), skType)
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
@@ -306,9 +323,9 @@ proc semGenericStmt(c: PContext, n: PNode,
         of nkIdent: a = n.sons[i]
         else: illFormedAst(n)
         addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c))
-  of nkObjectTy, nkTupleTy: 
+  of nkObjectTy, nkTupleTy:
     discard
-  of nkFormalParams: 
+  of nkFormalParams:
     checkMinSonsLen(n, 1)
     if n.sons[0].kind != nkEmpty: 
       n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
@@ -320,17 +337,17 @@ proc semGenericStmt(c: PContext, n: PNode,
       a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
       a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
       for j in countup(0, L-3): 
-        addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
+        addTempDecl(c, getIdentNode(a.sons[j]), skParam)
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, 
      nkIteratorDef, nkLambdaKinds: 
     checkSonsLen(n, bodyPos + 1)
     if n.kind notin nkLambdaKinds:
-      addPrelimDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c))
+      addTempDecl(c, getIdentNode(n.sons[0]), skProc)
     openScope(c)
     n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos], 
                                               flags, ctx)
     if n.sons[paramsPos].kind != nkEmpty: 
-      if n.sons[paramsPos].sons[0].kind != nkEmpty: 
+      if n.sons[paramsPos].sons[0].kind != nkEmpty:
         addPrelimDecl(c, newSym(skUnknown, getIdent("result"), nil, n.info))
       n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos], flags, ctx)
     n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos], flags, ctx)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index b205eb09a..8ac3849b4 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim
index 1bece95c2..c685d602d 100644
--- a/compiler/semmacrosanity.nim
+++ b/compiler/semmacrosanity.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -55,7 +55,7 @@ proc annotateType*(n: PNode, t: PType) =
     else:
       globalError(n.info, "() must have an object or tuple type")
   of nkBracket:
-    if x.kind in {tyArrayConstr, tyArray, tySequence, tyOpenarray}:
+    if x.kind in {tyArrayConstr, tyArray, tySequence, tyOpenArray}:
       n.typ = t
       for m in n: annotateType(m, x.elemType)
     else:
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index d4aeba32a..a72a6ab7d 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim
index 7c489c3b6..c4546f616 100644
--- a/compiler/semparallel.nim
+++ b/compiler/semparallel.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -320,7 +320,7 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
       # since we already ensure sfAddrTaken is not in s.flags, we only need to
       # prevent direct assignments to the monotonic variable:
       let slot = c.getSlot(n[0].sym)
-      slot.blackListed = true
+      slot.blacklisted = true
     invalidateFacts(c.guards, n[0])
     analyseSons(c, n)
     addAsgnFact(c.guards, n[0], n[1])
@@ -335,7 +335,7 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
     localError(n.info, "invalid control flow for 'parallel'")
     # 'break' that leaves the 'parallel' section is not valid either
     # or maybe we should generate a 'try' XXX
-  of nkVarSection:
+  of nkVarSection, nkLetSection:
     for it in n:
       let value = it.lastSon
       if value.kind != nkEmpty:
@@ -396,7 +396,7 @@ proc transformSpawnSons(owner: PSym; n, barrier: PNode): PNode =
 
 proc transformSpawn(owner: PSym; n, barrier: PNode): PNode =
   case n.kind
-  of nkVarSection:
+  of nkVarSection, nkLetSection:
     result = nil
     for it in n:
       let b = it.lastSon
@@ -464,6 +464,6 @@ proc liftParallel*(owner: PSym; n: PNode): PNode =
   result = newNodeI(nkStmtList, n.info)
   generateAliasChecks(a, result)
   result.add varSection
-  result.add callCodeGenProc("openBarrier", barrier)
+  result.add callCodegenProc("openBarrier", barrier)
   result.add transformSpawn(owner, body, barrier)
-  result.add callCodeGenProc("closeBarrier", barrier)
+  result.add callCodegenProc("closeBarrier", barrier)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index da4adcf49..0d8c7c479 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -57,26 +57,114 @@ discard """
     c()
  
  --> we need a stack of scopes for this analysis
-"""
 
-const trackGlobals = false ## we don't need it for now
+  # XXX enhance the algorithm to care about 'dirty' expressions:
+  lock a[i].L:
+    inc i # mark 'i' dirty
+    lock a[j].L:
+      access a[i], a[j]  # --> reject a[i]
+"""
 
 type
   TEffects = object
     exc: PNode  # stack of exceptions
     tags: PNode # list of tags
-    uses: PNode # list of used global variables
     bottom: int
     owner: PSym
     init: seq[int] # list of initialized variables
     guards: TModel # nested guards
     locked: seq[PNode] # locked locations
-    gcUnsafe, isRecursive: bool
+    gcUnsafe, isRecursive, isToplevel: bool
+    maxLockLevel, currLockLevel: TLockLevel
   PEffects = var TEffects
 
+proc `<`(a, b: TLockLevel): bool {.borrow.}
+proc `<=`(a, b: TLockLevel): bool {.borrow.}
+proc `==`(a, b: TLockLevel): bool {.borrow.}
+proc max(a, b: TLockLevel): TLockLevel {.borrow.}
+
 proc isLocalVar(a: PEffects, s: PSym): bool =
   s.kind in {skVar, skResult} and sfGlobal notin s.flags and s.owner == a.owner
 
+proc getLockLevel(t: PType): TLockLevel =
+  var t = t
+  # tyGenericInst(TLock {tyGenericBody}, tyStatic, tyObject):
+  if t.kind == tyGenericInst and t.len == 3: t = t.sons[1]
+  if t.kind == tyStatic and t.n != nil and t.n.kind in {nkCharLit..nkInt64Lit}:
+    result = t.n.intVal.TLockLevel
+
+proc lockLocations(a: PEffects; pragma: PNode) =
+  if pragma.kind != nkExprColonExpr:
+    localError(pragma.info, errGenerated, "locks pragma without argument")
+    return
+  var firstLL = TLockLevel(-1'i16)
+  for x in pragma[1]:
+    let thisLL = getLockLevel(x.typ)
+    if thisLL != 0.TLockLevel:
+      if thisLL < 0.TLockLevel or thisLL > MaxLockLevel.TLockLevel:
+        localError(x.info, "invalid lock level: " & $thisLL)
+      elif firstLL < 0.TLockLevel: firstLL = thisLL
+      elif firstLL != thisLL:
+        localError(x.info, errGenerated,
+          "multi-lock requires the same static lock level for every operand")
+      a.maxLockLevel = max(a.maxLockLevel, firstLL)
+    a.locked.add x
+  if firstLL >= 0.TLockLevel and firstLL != a.currLockLevel:
+    if a.currLockLevel > 0.TLockLevel and a.currLockLevel <= firstLL:
+      localError(pragma.info, errGenerated,
+        "invalid nested locking")
+    a.currLockLevel = firstLL
+
+proc guardGlobal(a: PEffects; n: PNode; guard: PSym) =
+  # check whether the corresponding lock is held:
+  for L in a.locked:
+    if L.kind == nkSym and L.sym == guard: return
+  # we allow accesses nevertheless in top level statements for
+  # easier initialization:
+  #if a.isTopLevel:
+  #  message(n.info, warnUnguardedAccess, renderTree(n))
+  #else:
+  if not a.isTopLevel:
+    localError(n.info, errGenerated, "unguarded access: " & renderTree(n))
+
+# 'guard*' are checks which are concerned with 'guard' annotations
+# (var x{.guard: y.}: int)
+proc guardDotAccess(a: PEffects; n: PNode) =
+  let ri = n.sons[1]
+  if ri.kind != nkSym or ri.sym.kind != skField: return
+  var g = ri.sym.guard
+  if g.isNil or a.isTopLevel: return
+  # fixup guard:
+  if g.kind == skUnknown:
+    var field: PSym = nil
+    var ty = n.sons[0].typ.skipTypes(abstractPtrs)
+    if ty.kind == tyTuple:
+      field = lookupInRecord(ty.n, g.name)
+    else:
+      while ty != nil and ty.kind == tyObject:
+        field = lookupInRecord(ty.n, g.name)
+        if field != nil: break
+        ty = ty.sons[0]
+        if ty == nil: break
+        ty = ty.skipTypes(abstractPtrs)
+    if field == nil:
+      localError(n.info, errGenerated, "invalid guard field: " & g.name.s)
+      return
+    g = field
+    #ri.sym.guard = field
+    # XXX unfortunately this is not correct for generic instantiations!
+  if g.kind == skField:
+    let dot = newNodeI(nkDotExpr, n.info, 2)
+    dot.sons[0] = n.sons[0]
+    dot.sons[1] = newSymNode(g)
+    dot.typ = g.typ
+    for L in a.locked:
+      #if a.guards.sameSubexprs(dot, L): return
+      if guards.sameTree(dot, L): return
+    localError(n.info, errGenerated, "unguarded access: " & renderTree(n))
+  else:
+    guardGlobal(a, n, g)
+
 proc initVar(a: PEffects, n: PNode) =
   if n.kind != nkSym: return
   let s = n.sym
@@ -93,12 +181,9 @@ proc initVarViaNew(a: PEffects, n: PNode) =
     # are initialized:
     initVar(a, n)
 
-when trackGlobals: 
-  proc addUse(a: PEffects, e: PNode) =
-    var aa = a.uses
-    for i in 0 .. <aa.len:
-      if aa[i].sym.id == e.sym.id: return
-    a.uses.add(e)
+proc warnAboutGcUnsafe(n: PNode) =
+  #assert false
+  message(n.info, warnGcUnsafe, renderTree(n))
 
 proc useVar(a: PEffects, n: PNode) =
   let s = n.sym
@@ -110,12 +195,11 @@ proc useVar(a: PEffects, n: PNode) =
         message(n.info, warnUninit, s.name.s)
       # prevent superfluous warnings about the same variable:
       a.init.add s.id
-  if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind == skVar:
-    when trackGlobals:
-      a.addUse(copyNode(n))
+  if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind in {skVar, skLet}:
+    if s.guard != nil: guardGlobal(a, n, s.guard)
     if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and 
         tfGcSafe notin s.typ.flags:
-      if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
+      if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
       a.gcUnsafe = true
 
 type
@@ -130,20 +214,27 @@ proc addToIntersection(inter: var TIntersection, s: int) =
 
 proc throws(tracked, n: PNode) =
   if n.typ == nil or n.typ.kind != tyError: tracked.add n
-  
+
+proc getEbase(): PType =
+  result = if getCompilerProc("Exception") != nil: sysTypeFromName"Exception"
+           else: sysTypeFromName"E_Base"
+
 proc excType(n: PNode): PType =
   # reraise is like raising E_Base:
-  let t = if n.kind == nkEmpty: sysTypeFromName"E_Base" else: n.typ
+  let t = if n.kind == nkEmpty: getEbase() else: n.typ
   result = skipTypes(t, skipPtrs)
 
 proc createRaise(n: PNode): PNode =
   result = newNode(nkType)
-  result.typ = sysTypeFromName"E_Base"
+  result.typ = getEbase()
   if not n.isNil: result.info = n.info
 
 proc createTag(n: PNode): PNode =
   result = newNode(nkType)
-  result.typ = sysTypeFromName"TEffect"
+  if getCompilerProc("RootEffect") != nil:
+    result.typ = sysTypeFromName"RootEffect"
+  else:
+    result.typ = sysTypeFromName"TEffect"
   if not n.isNil: result.info = n.info
 
 proc createAnyGlobal(n: PNode): PNode =
@@ -179,17 +270,11 @@ proc mergeTags(a: PEffects, b, comesFrom: PNode) =
   else:
     for effect in items(b): addTag(a, effect, useLineInfo=comesFrom != nil)
 
-when trackGlobals:
-  proc mergeUses(a: PEffects, b, comesFrom: PNode) =
-    if b.isNil:
-      addUse(a, createAnyGlobal(comesFrom))
-    else:
-      for effect in items(b): addUse(a, effect)
-
 proc listEffects(a: PEffects) =
   for e in items(a.exc):  message(e.info, hintUser, typeToString(e.typ))
   for e in items(a.tags): message(e.info, hintUser, typeToString(e.typ))
-  for e in items(a.uses): message(e.info, hintUser, e.sym.name.s)
+  #if a.maxLockLevel != 0:
+  #  message(e.info, hintUser, "lockLevel: " & a.maxLockLevel)
 
 proc catches(tracked: PEffects, e: PType) =
   let e = skipTypes(e, skipPtrs)
@@ -322,6 +407,25 @@ proc importedFromC(n: PNode): bool =
   # when imported from C, we assume GC-safety.
   result = n.kind == nkSym and sfImportc in n.sym.flags
 
+proc getLockLevel(s: PSym): TLockLevel =
+  result = s.typ.lockLevel
+  if result == UnspecifiedLockLevel:
+    if {sfImportc, sfNoSideEffect} * s.flags != {} or
+       tfNoSideEffect in s.typ.flags:
+      result = 0.TLockLevel
+    else:
+      result = UnknownLockLevel
+      #message(s.info, warnUser, "FOR THIS " & s.name.s)
+
+proc mergeLockLevels(tracked: PEffects, n: PNode, lockLevel: TLockLevel) =
+  if lockLevel >= tracked.currLockLevel:
+    # if in lock section:
+    if tracked.currLockLevel > 0.TLockLevel:
+      localError n.info, errGenerated,
+        "expected lock level < " & $tracked.currLockLevel &
+        " but got lock level " & $lockLevel
+    tracked.maxLockLevel = max(tracked.maxLockLevel, lockLevel)
+
 proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
   let pragma = s.ast.sons[pragmasPos]
   let spec = effectSpec(pragma, wRaises)
@@ -331,8 +435,9 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
   mergeTags(tracked, tagSpec, n)
 
   if notGcSafe(s.typ) and sfImportc notin s.flags:
-    if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
+    if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
     tracked.gcUnsafe = true
+  mergeLockLevels(tracked, n, s.getLockLevel)
 
 proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
   let n = n.skipConv
@@ -352,8 +457,22 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
       message(n.info, errGenerated, "'$1' is provably nil" % n.renderTree)
     of impYes: discard
 
+proc assumeTheWorst(tracked: PEffects; n: PNode; op: PType) =
+  addEffect(tracked, createRaise(n))
+  addTag(tracked, createTag(n))
+  let lockLevel = if op.lockLevel == UnspecifiedLockLevel: UnknownLockLevel
+                  else: op.lockLevel
+  #if lockLevel == UnknownLockLevel:
+  #  message(n.info, warnUser, "had to assume the worst here")
+  mergeLockLevels(tracked, n, lockLevel)
+
+proc isOwnedProcVar(n: PNode; owner: PSym): bool =
+  # XXX prove the soundness of this effect system rule
+  result = n.kind == nkSym and n.sym.kind == skParam and owner == n.sym.owner
+
 proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
-  let op = skipConvAndClosure(n).typ
+  let a = skipConvAndClosure(n)
+  let op = a.typ
   if op != nil and op.kind == tyProc and n.kind != nkNilLit:
     internalAssert op.n.sons[0].kind == nkEffectList
     var effectList = op.n.sons[0]
@@ -365,21 +484,18 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
         # we have no explicit effects but it's a forward declaration and so it's
         # stated there are no additional effects, so simply propagate them:
         propagateEffects(tracked, n, n.sym)
-      else:
+      elif not isOwnedProcVar(a, tracked.owner):
         # we have no explicit effects so assume the worst:
-        addEffect(tracked, createRaise(n))
-        addTag(tracked, createTag(n))
-        when trackGlobals: addUse(tracked, createAnyGlobal(n))
+        assumeTheWorst(tracked, n, op)
       # assume GcUnsafe unless in its type; 'forward' does not matter:
-      if notGcSafe(op):
-        if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
+      if notGcSafe(op) and not isOwnedProcVar(a, tracked.owner):
+        if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
         tracked.gcUnsafe = true
     else:
       mergeEffects(tracked, effectList.sons[exceptionEffects], n)
       mergeTags(tracked, effectList.sons[tagEffects], n)
-      when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n)
       if notGcSafe(op):
-        if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
+        if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
         tracked.gcUnsafe = true
   notNilCheck(tracked, n, paramType)
 
@@ -506,8 +622,12 @@ proc track(tracked: PEffects, n: PNode) =
     # are indistinguishable from normal procs (both have tyProc type) and
     # we can detect them only by checking for attached nkEffectList.
     if op != nil and op.kind == tyProc and op.n.sons[0].kind == nkEffectList:
-      if a.kind == nkSym and a.sym == tracked.owner:
-        tracked.isRecursive = true
+      if a.kind == nkSym:
+        if a.sym == tracked.owner: tracked.isRecursive = true
+        # even for recursive calls we need to check the lock levels (!):
+        mergeLockLevels(tracked, n, a.sym.getLockLevel)
+      else:
+        mergeLockLevels(tracked, n, op.lockLevel)
       var effectList = op.n.sons[0]
       if a.kind == nkSym and a.sym.kind == skMethod:
         propagateEffects(tracked, n, a.sym)
@@ -515,18 +635,14 @@ proc track(tracked: PEffects, n: PNode) =
         if isForwardedProc(a):
           propagateEffects(tracked, n, a.sym)
         elif isIndirectCall(a, tracked.owner):
-          addEffect(tracked, createRaise(n))
-          addTag(tracked, createTag(n))
-          when trackGlobals: addUse(tracked, createAnyGlobal(n))
-          # XXX handle 'gcsafe' properly for callbacks!
+          assumeTheWorst(tracked, n, op)
       else:
         mergeEffects(tracked, effectList.sons[exceptionEffects], n)
         mergeTags(tracked, effectList.sons[tagEffects], n)
-        when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n)
         if notGcSafe(op) and not importedFromC(a):
           # and it's not a recursive call:
           if not (a.kind == nkSym and a.sym == tracked.owner):
-            message(n.info, warnGcUnsafe, renderTree(n))
+            warnAboutGcUnsafe(n)
             tracked.gcUnsafe = true
     for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i))
     if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
@@ -534,6 +650,9 @@ proc track(tracked: PEffects, n: PNode) =
       initVarViaNew(tracked, n.sons[1])
     for i in 0 .. <safeLen(n):
       track(tracked, n.sons[i])
+  of nkDotExpr:
+    guardDotAccess(tracked, n)
+    for i in 0 .. <len(n): track(tracked, n.sons[i])
   of nkCheckedFieldExpr:
     track(tracked, n.sons[0])
     if warnProveField in gNotes: checkFieldAccess(tracked.guards, n)
@@ -547,7 +666,7 @@ proc track(tracked: PEffects, n: PNode) =
     addAsgnFact(tracked.guards, n.sons[0], n.sons[1])
     notNilCheck(tracked, n.sons[1], n.sons[0].typ)
     when false: cstringCheck(tracked, n)
-  of nkVarSection:
+  of nkVarSection, nkLetSection:
     for child in n:
       let last = lastSon(child)
       if child.kind == nkIdentDefs and last.kind != nkEmpty:
@@ -589,6 +708,16 @@ proc track(tracked: PEffects, n: PNode) =
       if sfDiscriminant in x.sons[0].sym.flags:
         addDiscriminantFact(tracked.guards, x)
     setLen(tracked.guards, oldFacts)
+  of nkPragmaBlock:
+    let pragmaList = n.sons[0]
+    let oldLocked = tracked.locked.len
+    let oldLockLevel = tracked.currLockLevel
+    for i in 0 .. <pragmaList.len:
+      if whichPragma(pragmaList.sons[i]) == wLocks:
+        lockLocations(tracked, pragmaList.sons[i])
+    track(tracked, n.lastSon)
+    setLen(tracked.locked, oldLocked)
+    tracked.currLockLevel = oldLockLevel
   of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
       nkMacroDef, nkTemplateDef:
     discard
@@ -639,6 +768,16 @@ proc checkMethodEffects*(disp, branch: PSym) =
   if sfThread in disp.flags and notGcSafe(branch.typ):
     localError(branch.info, "base method is GC-safe, but '$1' is not" % 
                                 branch.name.s)
+  if branch.typ.lockLevel > disp.typ.lockLevel:
+    when true:
+      message(branch.info, warnLockLevel,
+        "base method has lock level $1, but dispatcher has $2" %
+          [$branch.typ.lockLevel, $disp.typ.lockLevel])
+    else:
+      # XXX make this an error after bigbreak has been released:
+      localError(branch.info,
+        "base method has lock level $1, but dispatcher has $2" %
+          [$branch.typ.lockLevel, $disp.typ.lockLevel])
 
 proc setEffectsForProcType*(t: PType, n: PNode) =
   var effects = t.n.sons[0]
@@ -659,14 +798,13 @@ proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
   newSeq(effects.sons, effectListLen)
   effects.sons[exceptionEffects] = newNodeI(nkArgList, s.info)
   effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
-  effects.sons[usesEffects] = newNodeI(nkArgList, s.info)
   
   t.exc = effects.sons[exceptionEffects]
   t.tags = effects.sons[tagEffects]
-  t.uses = effects.sons[usesEffects]
   t.owner = s
   t.init = @[]
   t.guards = @[]
+  t.locked = @[]
   
 proc trackProc*(s: PSym, body: PNode) =
   var effects = s.typ.n.sons[0]
@@ -700,9 +838,17 @@ proc trackProc*(s: PSym, body: PNode) =
 
   if optThreadAnalysis in gGlobalOptions:
     if sfThread in s.flags and t.gcUnsafe:
-      #localError(s.info, warnGcUnsafe2, s.name.s)
-      localError(s.info, "'$1' is not GC-safe" % s.name.s)
+      if optThreads in gGlobalOptions:
+        localError(s.info, "'$1' is not GC-safe" % s.name.s)
+      else:
+        localError(s.info, warnGcUnsafe2, s.name.s)
     if not t.gcUnsafe: s.typ.flags.incl tfGcSafe
+    if s.typ.lockLevel == UnspecifiedLockLevel:
+      s.typ.lockLevel = t.maxLockLevel
+    elif t.maxLockLevel > s.typ.lockLevel:
+      localError(s.info,
+        "declared lock level is $1, but real lock level is $2" %
+          [$s.typ.lockLevel, $t.maxLockLevel])
 
 proc trackTopLevelStmt*(module: PSym; n: PNode) =
   if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef,
@@ -711,5 +857,5 @@ proc trackTopLevelStmt*(module: PSym; n: PNode) =
   var effects = newNode(nkEffectList, n.info)
   var t: TEffects
   initEffects(effects, module, t)
-
+  t.isToplevel = true
   track(t, n)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index d394a2ae5..255507548 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -29,17 +29,18 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
       of nkIdent: s = lookUp(c, n.sons[0])
       of nkSym: s = n.sons[0].sym
       else: illFormedAst(n)
-      if s.kind == skLabel and s.owner.id == c.p.owner.id:
+      if s.kind == skLabel and s.owner.id == c.p.owner.id: 
         var x = newSymNode(s)
         x.info = n.info
         incl(s.flags, sfUsed)
         n.sons[0] = x
         suggestSym(x.info, s)
+        styleCheckUse(x.info, s)
       else:
         localError(n.info, errInvalidControlFlowX, s.name.s)
     else:
       localError(n.info, errGenerated, "'continue' cannot have a label")
-  elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0): 
+  elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0):
     localError(n.info, errInvalidControlFlowX, 
                renderTree(n, {renderNoComments}))
 
@@ -198,11 +199,12 @@ proc semCase(c: PContext, n: PNode): PNode =
   var covered: BiggestInt = 0
   var typ = commonTypeBegin
   var hasElse = false
+  var notOrdinal = false
   case skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc}).kind
   of tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool:
     chckCovered = true
   of tyFloat..tyFloat128, tyString, tyError:
-    discard
+    notOrdinal = true
   else:
     localError(n.info, errSelectorMustBeOfCertainTypes)
     return
@@ -232,6 +234,9 @@ proc semCase(c: PContext, n: PNode): PNode =
       hasElse = true
     else:
       illFormedAst(x)
+  if notOrdinal and not hasElse:
+    message(n.info, warnDeprecated,
+            "use 'else: discard'; non-ordinal case without 'else'")
   if chckCovered:
     if covered == toCover(n.sons[0].typ):
       hasElse = true
@@ -263,7 +268,7 @@ proc semTry(c: PContext, n: PNode): PNode =
     checkMinSonsLen(a, 1)
     var length = sonsLen(a)
     if a.kind == nkExceptBranch:
-      # XXX what does this do? so that ``except [a, b, c]`` is supported?
+      # so that ``except [a, b, c]`` is supported:
       if length == 2 and a.sons[0].kind == nkBracket:
         a.sons[0..0] = a.sons[0].sons
         length = a.sonsLen
@@ -323,6 +328,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
   else:
     result = semIdentWithPragma(c, kind, n, {})
   suggestSym(n.info, result)
+  styleCheckDef(result)
 
 proc checkNilable(v: PSym) =
   if sfGlobal in v.flags and {tfNotNil, tfNeedsInit} * v.typ.flags != {}:
@@ -350,9 +356,14 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
     var def: PNode
     if a.sons[length-1].kind != nkEmpty:
       def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
-      # BUGFIX: ``fitNode`` is needed here!
-      # check type compability between def.typ and typ:
-      if typ != nil: def = fitNode(c, typ, def)
+      if typ != nil:
+        if typ.isMetaType:
+          def = inferWithMetatype(c, typ, def)
+          typ = def.typ
+        else:
+          # BUGFIX: ``fitNode`` is needed here!
+          # check type compability between def.typ and typ        
+          def = fitNode(c, typ, def)
       else:
         typ = skipIntLit(def.typ)
         if typ.kind in {tySequence, tyArray, tySet} and
@@ -441,7 +452,7 @@ proc semConst(c: PContext, n: PNode): PNode =
     if typ == nil:
       localError(a.sons[2].info, errConstExprExpected)
       continue
-    if not typeAllowed(typ, skConst):
+    if not typeAllowed(typ, skConst) and def.kind != nkNilLit:
       localError(a.info, errXisNoType, typeToString(typ))
       continue
     v.typ = typ
@@ -614,6 +625,7 @@ proc addForVarDecl(c: PContext, v: PSym) =
 proc symForVar(c: PContext, n: PNode): PSym =
   let m = if n.kind == nkPragmaExpr: n.sons[0] else: n
   result = newSymG(skForVar, m, c)
+  styleCheckDef(result)
 
 proc semForVars(c: PContext, n: PNode): PNode =
   result = n
@@ -1021,7 +1033,11 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
         sameType(s.typ.sons[1], s.typ.sons[0]):
       # Note: we store the deepCopy in the base of the pointer to mitigate
       # the problem that pointers are structural types:
-      let t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst)
+      var t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst)
+      while true:
+        if t.kind == tyGenericBody: t = t.lastSon
+        elif t.kind == tyGenericInvokation: t = t.sons[0]
+        else: break
       if t.kind in {tyObject, tyDistinct, tyEnum}:
         if t.deepCopy.isNil: t.deepCopy = s
         else: 
@@ -1036,6 +1052,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
   of "=": discard
   else: localError(n.info, errGenerated,
                    "'destroy' or 'deepCopy' expected for 'override'")
+  incl(s.flags, sfUsed)
 
 type
   TProcCompilationSteps = enum
@@ -1292,9 +1309,14 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
   let pragmaList = n.sons[0]
   pragma(c, nil, pragmaList, exprPragmas)
   result = semExpr(c, n.sons[1])
+  n.sons[1] = result
   for i in 0 .. <pragmaList.len:
-    if whichPragma(pragmaList.sons[i]) == wLine:
-      setLine(result, pragmaList.sons[i].info)
+    case whichPragma(pragmaList.sons[i])
+    of wLine: setLine(result, pragmaList.sons[i].info)
+    of wLocks: 
+      result = n
+      result.typ = n.sons[1].typ
+    else: discard
 
 proc semStaticStmt(c: PContext, n: PNode): PNode =
   let a = semStmt(c, n.sons[0])
@@ -1393,6 +1415,11 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
       else: discard
   if result.len == 1:
     result = result.sons[0]
+  when defined(nimfix):
+    if result.kind == nkCommentStmt and not result.comment.isNil and
+        not (result.comment[0] == '#' and result.comment[1] == '#'):
+      # it is an old-style comment statement: we replace it with 'discard ""':
+      prettybase.replaceComment(result.info)
   when false:
     # a statement list (s; e) has the type 'e':
     if result.kind == nkStmtList and result.len > 0:
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index ee8b1ccb8..0a647a65d 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -71,7 +71,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
       addSon(result, newSymNode(a, n.info))
       a = nextOverloadIter(o, c, n)
 
-proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
+proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
   for i in 0 .. < n.len:
     var a = n.sons[i]
     # If 'a' is an overloaded symbol, we used to use the first symbol
@@ -91,7 +91,7 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
       illFormedAst(a)
   result = newNodeI(nkEmpty, n.info)
 
-proc semMixinStmt(c: PContext, n: PNode, toMixin: var TIntSet): PNode =
+proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
   for i in 0 .. < n.len:
     toMixin.incl(considerQuotedIdent(n.sons[i]).id)
   result = newNodeI(nkEmpty, n.info)
@@ -106,7 +106,7 @@ proc replaceIdentBySym(n: var PNode, s: PNode) =
 type
   TemplCtx {.pure, final.} = object
     c: PContext
-    toBind, toMixin, toInject: TIntSet
+    toBind, toMixin, toInject: IntSet
     owner: PSym
 
 proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
@@ -146,6 +146,7 @@ proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
       if s.owner == c.owner and s.kind == skParam:
         incl(s.flags, sfUsed)
         result = newSymNode(s, n.info)
+        styleCheckUse(n.info, s)
   else:
     for i in 0 .. <n.safeLen:
       result.sons[i] = onlyReplaceParams(c, n.sons[i])
@@ -183,12 +184,15 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
     if not isTemplParam(c, ident):
       let local = newGenSym(k, ident, c)
       addPrelimDecl(c.c, local)
+      styleCheckDef(n.info, local)
       replaceIdentBySym(n, newSymNode(local, n.info))
     else:
       replaceIdentBySym(n, ident)
 
 proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode = 
   incl(s.flags, sfUsed)
+  # we do not call styleCheckUse here, as the identifier is not really
+  # resolved here. We will fixup the used identifiers later.
   case s.kind
   of skUnknown: 
     # Introduced in this pass! Leave it as an identifier.
@@ -204,7 +208,8 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
       result = newSymNodeTypeDesc(s, n.info)
     else: 
       result = n
-  else: result = newSymNode(s, n.info)
+  else:
+    result = newSymNode(s, n.info)
 
 proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
   result = n
@@ -214,6 +219,7 @@ proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
       if s.owner == c.owner and (s.kind == skParam or sfGenSym in s.flags):
         incl(s.flags, sfUsed)
         result = newSymNode(s, n.info)
+        styleCheckUse(n.info, s)
   else:
     for i in countup(0, safeLen(n) - 1):
       result.sons[i] = semRoutineInTemplName(c, n.sons[i])
@@ -228,6 +234,7 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
       var s = newGenSym(k, ident, c)
       s.ast = n
       addPrelimDecl(c.c, s)
+      styleCheckDef(n.info, s)
       n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
     else:
       n.sons[namePos] = ident
@@ -261,6 +268,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
       if s.owner == c.owner and s.kind == skParam:
         incl(s.flags, sfUsed)
         result = newSymNode(s, n.info)
+        styleCheckUse(n.info, s)
       elif contains(c.toBind, s.id):
         result = symChoice(c.c, n, s, scClosed)
       elif contains(c.toMixin, s.name.id):
@@ -270,6 +278,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
         # var yz: T
         incl(s.flags, sfUsed)
         result = newSymNode(s, n.info)
+        styleCheckUse(n.info, s)
       else:
         result = semTemplSymbol(c.c, n, s)
   of nkBind:
@@ -322,6 +331,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
       # labels are always 'gensym'ed:
       let s = newGenSym(skLabel, n.sons[0], c)
       addPrelimDecl(c.c, s)
+      styleCheckDef(s)
       n.sons[0] = newSymNode(s, n.sons[0].info)
     n.sons[1] = semTemplBody(c, n.sons[1])
     closeScope(c)
@@ -456,6 +466,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
     incl(s.flags, sfGlobal)
   else:
     s = semIdentVis(c, skTemplate, n.sons[0], {})
+  styleCheckDef(s)
   # check parameter list:
   s.scope = c.currentScope
   pushOwner(s)
@@ -527,6 +538,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
     # semtypes.addParamOrResult). Within the pattern we have to ensure
     # to use the param with the proper type though:
     incl(s.flags, sfUsed)
+    styleCheckUse(n.info, s)
     let x = c.owner.typ.n.sons[s.position+1].sym
     assert x.name == s.name
     result = newSymNode(x, n.info)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 53fe4e266..b3ff6c82a 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -82,6 +82,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       incl(e.flags, sfExported)
       if not isPure: strTableAdd(c.module.tab, e)
     addSon(result.n, newSymNode(e))
+    styleCheckDef(e)
     if sfGenSym notin e.flags and not isPure: addDecl(c, e)
     inc(counter)
   if not hasNull: incl(result.flags, tfNeedsInit)
@@ -92,7 +93,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
     var base = semTypeNode(c, n.sons[1], nil)
     addSonSkipIntLit(result, base)
     if base.kind == tyGenericInst: base = lastSon(base)
-    if base.kind != tyGenericParam: 
+    if base.kind != tyGenericParam:
       if not isOrdinalType(base): 
         localError(n.info, errOrdinalTypeExpected)
       elif lengthOrd(base) > MaxSetElements: 
@@ -279,9 +280,15 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
   if n.kind == nkSym: 
     result = n.sym
   else:
-    result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
+    when defined(nimfix):
+      result = pickSym(c, n, skType)
+      if result.isNil:
+        result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
+    else:
+      result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
     if result != nil:
       markUsed(n.info, result)
+      styleCheckUse(n.info, result)
       if result.kind == skParam and result.typ.kind == tyTypeDesc:
         # This is a typedesc param. is it already bound?
         # it's not bound when it's used multiple times in the
@@ -358,7 +365,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
       else:
         addSon(result.n, newSymNode(field))
         addSonSkipIntLit(result, typ)
-      if gCmd == cmdPretty: checkDef(a.sons[j], field)
+      if gCmd == cmdPretty: styleCheckDef(a.sons[j].info, field)
 
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, 
                  allowed: TSymFlags): PSym = 
@@ -394,7 +401,7 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
     else: discard
   else:
     result = semIdentVis(c, kind, n, allowed)
-  if gCmd == cmdPretty: checkDef(n, result)
+  if gCmd == cmdPretty: styleCheckDef(n.info, result)
   
 proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
   let ex = t[branchIndex][currentEx].skipConv
@@ -461,9 +468,9 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
           swap(branch.sons[L-2], branch.sons[L-1])
     checkForOverlap(c, t, i, branchIndex)
     
-proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
+proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
                       father: PNode, rectype: PType)
-proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
+proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
                    father: PNode, rectype: PType) =
   var a = copyNode(n)
   checkMinSonsLen(n, 2)
@@ -498,7 +505,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     localError(a.info, errNotAllCasesCovered)
   addSon(father, a)
 
-proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int, 
+proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, 
                       father: PNode, rectype: PType) =
   if n == nil: return
   case n.kind
@@ -524,7 +531,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
       else: illFormedAst(n)
       if c.inGenericContext > 0:
         # use a new check intset here for each branch:
-        var newCheck: TIntSet
+        var newCheck: IntSet
         assign(newCheck, check)
         var newPos = pos
         var newf = newNodeI(nkRecList, n.info)
@@ -574,11 +581,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
         localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
       if a.kind == nkEmpty: addSon(father, newSymNode(f))
       else: addSon(a, newSymNode(f))
+      styleCheckDef(f)
     if a.kind != nkEmpty: addSon(father, a)
   of nkEmpty: discard
   else: illFormedAst(n)
   
-proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int, 
+proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int, 
                            n: PNode) =
   case n.kind
   of nkRecCase:
@@ -597,7 +605,7 @@ proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int,
     inc(pos)
   else: internalError(n.info, "addInheritedFieldsAux()")
   
-proc addInheritedFields(c: PContext, check: var TIntSet, pos: var int, 
+proc addInheritedFields(c: PContext, check: var IntSet, pos: var int, 
                         obj: PType) = 
   if (sonsLen(obj) > 0) and (obj.sons[0] != nil): 
     addInheritedFields(c, check, pos, obj.sons[0])
@@ -814,10 +822,10 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     for i in 1 .. <paramType.sonsLen:
       let lifted = liftingWalk(paramType.sons[i])
       if lifted != nil: paramType.sons[i] = lifted
-
-    let expanded = instGenericContainer(c, info, paramType,
-                                        allowMetaTypes = true)
-    result = liftingWalk(expanded, true)
+    when false:
+      let expanded = instGenericContainer(c, info, paramType,
+                                          allowMetaTypes = true)
+      result = liftingWalk(expanded, true)
 
   of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
     result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
@@ -828,6 +836,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   
   of tyGenericParam:
     markUsed(info, paramType.sym)
+    styleCheckUse(info, paramType.sym)
     if tfWildcard in paramType.flags:
       paramType.flags.excl tfWildcard
       paramType.sym.kind = skType
@@ -847,7 +856,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
                      prev: PType, kind: TSymKind): PType =
   var
     res: PNode
-    cl: TIntSet
+    cl: IntSet
   checkMinSonsLen(n, 1)
   result = newOrPrevType(tyProc, prev, c)
   result.callConv = lastOptionEntry(c).defaultCC
@@ -913,7 +922,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       addSon(result.n, newSymNode(arg))
       rawAddSon(result, finalType)
       addParamOrResult(c, arg, kind)
-      if gCmd == cmdPretty: checkDef(a.sons[j], arg)
+      if gCmd == cmdPretty: styleCheckDef(a.sons[j].info, arg)
 
   var r: PType
   if n.sons[0].kind != nkEmpty:
@@ -1188,6 +1197,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         assignType(prev, t)
         result = prev
       markUsed(n.info, n.sym)
+      styleCheckUse(n.info, n.sym)
     else:
       if n.sym.kind != skError: localError(n.info, errTypeExpected)
       result = newOrPrevType(tyError, prev, c)
@@ -1234,7 +1244,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   
 proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
   m.typ.kind = kind
-  m.typ.align = size
+  m.typ.align = size.int16
   m.typ.size = size
   
 proc processMagicType(c: PContext, m: PSym) = 
@@ -1332,6 +1342,9 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
         if def.typ.kind != tyTypeDesc:
           typ = newTypeWithSons(c, tyStatic, @[def.typ])
       else:
+        # the following line fixes ``TV2*[T:SomeNumber=TR] = array[0..1, T]``
+        # from manyloc/named_argument_bug/triengine:
+        def.typ = def.typ.skipTypes({tyTypeDesc})
         if not containsGenericType(def.typ):
           def = fitNode(c, typ, def)
     
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 9f0a4100d..9c15be635 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -216,7 +216,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
     result.typ = replaceTypeVarsT(cl, s.typ)
     result.ast = replaceTypeVarsN(cl, s.ast)
     
-proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType = 
+proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil:
     if cl.allowMetaTypes or tfRetType in t.flags: return
@@ -299,6 +299,11 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
   if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
   rawAddSon(result, newbody)
   checkPartialConstructedType(cl.info, newbody)
+  let dc = newbody.deepCopy
+  if dc != nil and sfFromGeneric notin newbody.deepCopy.flags:
+    # 'deepCopy' needs to be instantiated for
+    # generics *when the type is constructed*:
+    newbody.deepCopy = cl.c.instDeepCopy(cl.c, dc, result, cl.info)
 
 proc eraseVoidParams*(t: PType) =
   if t.sons[0] != nil and t.sons[0].kind == tyEmpty:
diff --git a/compiler/service.nim b/compiler/service.nim
index 22f5c6e33..4a1b296cd 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -25,39 +25,17 @@ var
   lastCaasCmd* = ""
     # in caas mode, the list of defines and options will be given at start-up?
     # it's enough to check that the previous compilation command is the same?
-  arguments* = ""
-    # the arguments to be passed to the program that
-    # should be run
 
 proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
   var p = parseopt.initOptParser(cmd)
   var argsCount = 0
-  while true: 
+  while true:
     parseopt.next(p)
     case p.kind
-    of cmdEnd: break 
-    of cmdLongoption, cmdShortOption: 
-      # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
-      # we fix this here
-      var bracketLe = strutils.find(p.key, '[')
-      if bracketLe >= 0: 
-        var key = substr(p.key, 0, bracketLe - 1)
-        var val = substr(p.key, bracketLe + 1) & ':' & p.val
-        processSwitch(key, val, pass, gCmdLineInfo)
-      else: 
-        processSwitch(p.key, p.val, pass, gCmdLineInfo)
+    of cmdEnd: break
+    of cmdLongoption, cmdShortOption: processSwitch(pass, p)
     of cmdArgument:
-      if argsCount == 0:
-        options.command = p.key
-      else:
-        if pass == passCmd1: options.commandArgs.add p.key
-        if argsCount == 1:
-          # support UNIX style filenames anywhere for portable build scripts:
-          options.gProjectName = unixToNativePath(p.key)
-          arguments = cmdLineRest(p)
-          break
-      inc argsCount
-          
+      if processArgument(pass, p, argsCount): break
   if pass == passCmd2:
     if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run":
       rawMessage(errArgsNeedRunOption, [])
@@ -84,9 +62,9 @@ proc serve*(action: proc (){.nimcall.}) =
   of "tcp", "":
     when useCaas:
       var server = socket()
-      if server == invalidSocket: osError(osLastError())
+      if server == invalidSocket: raiseOSError(osLastError())
       let p = getConfigVar("server.port")
-      let port = if p.len > 0: parseInt(p).TPort else: 6000.TPort
+      let port = if p.len > 0: parseInt(p).Port else: 6000.Port
       server.bindAddr(port, getConfigVar("server.address"))
       var inp = "".TaintedString
       server.listen()
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index e5bf08097..4a3773ed8 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -12,7 +12,8 @@
 
 import 
   intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
-  magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees
+  magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees,
+  nimfix.pretty
 
 when not defined(noDocgen):
   import docgen
@@ -21,6 +22,7 @@ type
   TCandidateState* = enum 
     csEmpty, csMatch, csNoMatch
 
+  CandidateErrors* = seq[PSym]
   TCandidate* {.final.} = object
     c*: PContext
     exactMatches*: int       # also misused to prefer iters over procs
@@ -44,7 +46,7 @@ type
                              # a distrinct type
     typedescMatched: bool
     inheritancePenalty: int  # to prefer closest father object type
-    errors*: seq[string]     # additional clarifications to be displayed to the
+    errors*: CandidateErrors # additional clarifications to be displayed to the
                              # user if overload resolution fails
 
   TTypeRelation* = enum      # order is important!
@@ -201,16 +203,17 @@ proc writeMatches*(c: TCandidate) =
   writeln(stdout, "intconv matches: " & $c.intConvMatches)
   writeln(stdout, "generic matches: " & $c.genericMatches)
 
-proc argTypeToString(arg: PNode): string =
+proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string =
   if arg.kind in nkSymChoices:
-    result = typeToString(arg[0].typ)
+    result = typeToString(arg[0].typ, prefer)
     for i in 1 .. <arg.len:
       result.add(" | ")
-      result.add typeToString(arg[i].typ)
+      result.add typeToString(arg[i].typ, prefer)
   else:
-    result = arg.typ.typeToString
+    result = arg.typ.typeToString(prefer)
 
-proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
+proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
+                   prefer: TPreferedDesc = preferName): string =
   result = ""
   for i in countup(startIdx, n.len - 1):
     var arg = n.sons[i]
@@ -226,7 +229,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
         arg = c.semOperand(c, n.sons[i])
         n.sons[i] = arg
     if arg.typ.kind == tyError: return
-    add(result, argTypeToString(arg))
+    add(result, argTypeToString(arg, prefer))
     if i != sonsLen(n) - 1: add(result, ", ")
 
 proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation
@@ -479,8 +482,8 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
     dummyParam.typ = dummyType
     addDecl(c, dummyParam)
 
-  var checkedBody = c.semTryExpr(c, body.n[3].copyTree, bufferErrors = false)
-  m.errors = bufferedMsgs
+  var checkedBody = c.semTryExpr(c, body.n[3].copyTree)
+  #m.errors = bufferedMsgs
   clearBufferedMsgs()
   if checkedBody == nil: return isNone
 
@@ -1272,6 +1275,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
     else: 
       # only one valid interpretation found:
       markUsed(arg.info, arg.sons[best].sym)
+      styleCheckUse(arg.info, arg.sons[best].sym)
       result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
                                   argOrig)
 
@@ -1319,7 +1323,7 @@ proc incrIndexType(t: PType) =
   inc t.sons[0].n.sons[1].intVal
 
 proc matchesAux(c: PContext, n, nOrig: PNode,
-                m: var TCandidate, marker: var TIntSet) = 
+                m: var TCandidate, marker: var IntSet) = 
   template checkConstraint(n: expr) {.immediate, dirty.} =
     if not formal.constraint.isNil:
       if matchNodeKinds(formal.constraint, n):
@@ -1480,8 +1484,23 @@ proc argtypeMatches*(c: PContext, f, a: PType): bool =
   # instantiate generic converters for that
   result = res != nil
 
+proc instDeepCopy*(c: PContext; dc: PSym; t: PType; info: TLineInfo): PSym {.
+                    procvar.} =
+  var m: TCandidate
+  initCandidate(c, m, dc.typ)
+  var f = dc.typ.sons[1]
+  if f.kind in {tyRef, tyPtr}: f = f.lastSon
+  if typeRel(m, f, t) == isNone:
+    localError(info, errGenerated, "cannot instantiate 'deepCopy'")
+  else:
+    result = c.semGenerateInstance(c, dc, m.bindings, info)
+    assert sfFromGeneric in result.flags
+
 include suggest
 
+when not declared(tests):
+  template tests(s: stmt) {.immediate.} = discard
+
 tests:
   var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
   
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index c2bdfc5c3..c700db323 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -11,7 +11,7 @@
 
 # included from sigmatch.nim
 
-import algorithm, sequtils, pretty
+import algorithm, sequtils
 
 const
   sep = '\t'
@@ -331,7 +331,6 @@ proc markUsed(info: TLineInfo; s: PSym) =
     if sfDeprecated in s.flags: message(info, warnDeprecated, s.name.s)
     if sfError in s.flags: localError(info, errWrongSymbolX, s.name.s)
   suggestSym(info, s)
-  if gCmd == cmdPretty: checkUse(info, s)
 
 proc useSym*(sym: PSym): PNode =
   result = newSymNode(sym)
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index d5062544f..61677a641 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -44,7 +44,7 @@ proc parseTopLevelStmt*(p: var TParsers): PNode
 proc parseFile(fileIdx: int32): PNode =
   var 
     p: TParsers
-    f: TFile
+    f: File
   let filename = fileIdx.toFullPath
   if not open(f, filename):
     rawMessage(errCannotOpenFile, filename)
diff --git a/compiler/tccgen.nim b/compiler/tccgen.nim
index a571d416e..0082dfcbb 100644
--- a/compiler/tccgen.nim
+++ b/compiler/tccgen.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 1ec31d605..6196512ba 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -785,8 +785,8 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
     #  result = lambdalifting.liftIterator(prc, result)
     incl(result.flags, nfTransf)
     when useEffectSystem: trackProc(prc, result)
-    if prc.name.s == "testbody":
-      echo renderTree(result)
+    #if prc.name.s == "testbody":
+    #  echo renderTree(result)
 
 proc transformStmt*(module: PSym, n: PNode): PNode =
   if nfTransf in n.flags:
diff --git a/compiler/trees.nim b/compiler/trees.nim
index 35e9334cc..b1edd21f3 100644
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/treetab.nim b/compiler/treetab.nim
index ecb8fb083..63f3fc6e2 100644
--- a/compiler/treetab.nim
+++ b/compiler/treetab.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2012 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
diff --git a/compiler/types.nim b/compiler/types.nim
index c04413857..87f2e1a59 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -16,21 +16,20 @@ proc firstOrd*(t: PType): BiggestInt
 proc lastOrd*(t: PType): BiggestInt
 proc lengthOrd*(t: PType): BiggestInt
 type 
-  TPreferedDesc* = enum 
-    preferName, preferDesc, preferExported
+  TPreferedDesc* = enum
+    preferName, preferDesc, preferExported, preferModuleInfo
 
-proc typeToString*(typ: PType, prefer: TPreferedDesc = preferName): string
-proc getProcHeader*(sym: PSym): string
+proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
 proc base*(t: PType): PType
   # ------------------- type iterator: ----------------------------------------
 type 
-  TTypeIter* = proc (t: PType, closure: PObject): bool {.nimcall.} # true if iteration should stop
-  TTypeMutator* = proc (t: PType, closure: PObject): PType {.nimcall.} # copy t and mutate it
+  TTypeIter* = proc (t: PType, closure: RootRef): bool {.nimcall.} # true if iteration should stop
+  TTypeMutator* = proc (t: PType, closure: RootRef): PType {.nimcall.} # copy t and mutate it
   TTypePredicate* = proc (t: PType): bool {.nimcall.}
 
-proc iterOverType*(t: PType, iter: TTypeIter, closure: PObject): bool
+proc iterOverType*(t: PType, iter: TTypeIter, closure: RootRef): bool
   # Returns result of `iter`.
-proc mutateType*(t: PType, iter: TTypeMutator, closure: PObject): PType
+proc mutateType*(t: PType, iter: TTypeMutator, closure: RootRef): PType
   # Returns result of `iter`.
 
 type 
@@ -121,7 +120,7 @@ proc isCompatibleToCString(a: PType): bool =
         (a.sons[1].kind == tyChar): 
       result = true
   
-proc getProcHeader(sym: PSym): string = 
+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): 
@@ -129,13 +128,14 @@ proc getProcHeader(sym: PSym): string =
     if p.kind == nkSym: 
       add(result, p.sym.name.s)
       add(result, ": ")
-      add(result, typeToString(p.sym.typ))
+      add(result, typeToString(p.sym.typ, prefer))
       if i != sonsLen(n)-1: add(result, ", ")
     else:
       internalError("getProcHeader")
   add(result, ')')
-  if n.sons[0].typ != nil: result.add(": " & typeToString(n.sons[0].typ))
-  
+  if n.sons[0].typ != nil:
+    result.add(": " & typeToString(n.sons[0].typ, prefer))
+
 proc elemType*(t: PType): PType = 
   assert(t != nil)
   case t.kind
@@ -160,10 +160,10 @@ proc enumHasHoles(t: PType): bool =
   while b.kind in {tyConst, tyMutable, tyRange, tyGenericInst}: b = b.sons[0]
   result = b.kind == tyEnum and tfEnumHasHoles in b.flags
 
-proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter, 
-                     closure: PObject): bool
-proc iterOverNode(marker: var TIntSet, n: PNode, iter: TTypeIter, 
-                  closure: PObject): bool = 
+proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, 
+                     closure: RootRef): bool
+proc iterOverNode(marker: var IntSet, n: PNode, iter: TTypeIter, 
+                  closure: RootRef): bool = 
   if n != nil: 
     case n.kind
     of nkNone..nkNilLit: 
@@ -174,8 +174,8 @@ proc iterOverNode(marker: var TIntSet, n: PNode, iter: TTypeIter,
         result = iterOverNode(marker, n.sons[i], iter, closure)
         if result: return 
   
-proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter, 
-                     closure: PObject): bool = 
+proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, 
+                     closure: RootRef): bool = 
   result = false
   if t == nil: return 
   result = iter(t, closure)
@@ -190,15 +190,15 @@ proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter,
         if result: return 
       if t.n != nil: result = iterOverNode(marker, t.n, iter, closure)
   
-proc iterOverType(t: PType, iter: TTypeIter, closure: PObject): bool = 
+proc iterOverType(t: PType, iter: TTypeIter, closure: RootRef): bool = 
   var marker = initIntSet()
   result = iterOverTypeAux(marker, t, iter, closure)
 
 proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
-                      marker: var TIntSet): bool
+                      marker: var IntSet): bool
 
 proc searchTypeNodeForAux(n: PNode, p: TTypePredicate, 
-                          marker: var TIntSet): bool = 
+                          marker: var IntSet): bool = 
   result = false
   case n.kind
   of nkRecList: 
@@ -220,7 +220,7 @@ proc searchTypeNodeForAux(n: PNode, p: TTypePredicate,
   else: internalError(n.info, "searchTypeNodeForAux()")
   
 proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
-                      marker: var TIntSet): bool = 
+                      marker: var IntSet): bool = 
   # iterates over VALUE types!
   result = false
   if t == nil: return 
@@ -256,7 +256,7 @@ proc isObjectWithTypeFieldPredicate(t: PType): bool =
       tfFinal notin t.flags
 
 proc analyseObjectWithTypeFieldAux(t: PType, 
-                                   marker: var TIntSet): TTypeFieldResult = 
+                                   marker: var IntSet): TTypeFieldResult = 
   var res: TTypeFieldResult
   result = frNone
   if t == nil: return 
@@ -310,8 +310,8 @@ proc containsHiddenPointer(typ: PType): bool =
   # that need to be copied deeply)
   result = searchTypeFor(typ, isHiddenPointer)
 
-proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool
-proc canFormAcycleNode(marker: var TIntSet, n: PNode, startId: int): bool = 
+proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool
+proc canFormAcycleNode(marker: var IntSet, n: PNode, startId: int): bool = 
   result = false
   if n != nil: 
     result = canFormAcycleAux(marker, n.typ, startId)
@@ -324,7 +324,7 @@ proc canFormAcycleNode(marker: var TIntSet, n: PNode, startId: int): bool =
           result = canFormAcycleNode(marker, n.sons[i], startId)
           if result: return 
   
-proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool = 
+proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool = 
   result = false
   if typ == nil: return 
   if tfAcyclic in typ.flags: return 
@@ -353,10 +353,10 @@ proc canFormAcycle(typ: PType): bool =
   var marker = initIntSet()
   result = canFormAcycleAux(marker, typ, typ.id)
 
-proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator, 
-                   closure: PObject): PType
-proc mutateNode(marker: var TIntSet, n: PNode, iter: TTypeMutator, 
-                closure: PObject): PNode = 
+proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, 
+                   closure: RootRef): PType
+proc mutateNode(marker: var IntSet, n: PNode, iter: TTypeMutator, 
+                closure: RootRef): PNode = 
   result = nil
   if n != nil: 
     result = copyNode(n)
@@ -369,8 +369,8 @@ proc mutateNode(marker: var TIntSet, n: PNode, iter: TTypeMutator,
       for i in countup(0, sonsLen(n) - 1): 
         addSon(result, mutateNode(marker, n.sons[i], iter, closure))
   
-proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator, 
-                   closure: PObject): PType = 
+proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, 
+                   closure: RootRef): PType = 
   result = nil
   if t == nil: return 
   result = iter(t, closure)
@@ -380,7 +380,7 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
     if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure)
   assert(result != nil)
 
-proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType =
+proc mutateType(t: PType, iter: TTypeMutator, closure: RootRef): PType =
   var marker = initIntSet()
   result = mutateTypeAux(marker, t, iter, closure)
 
@@ -415,10 +415,14 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
   var t = typ
   result = ""
   if t == nil: return 
-  if prefer == preferName and t.sym != nil and sfAnon notin t.sym.flags:
+  if prefer in {preferName, preferModuleInfo} and t.sym != nil and
+       sfAnon notin t.sym.flags:
     if t.kind == tyInt and isIntLit(t):
       return t.sym.name.s & " literal(" & $t.n.intVal & ")"
-    return t.sym.name.s
+    if prefer == preferName or t.sym.owner.isNil:
+      return t.sym.name.s
+    else:
+      return t.sym.owner.name.s & '.' & t.sym.name.s
   case t.kind
   of tyInt:
     if not isIntLit(t) or prefer == preferExported:
@@ -492,8 +496,9 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     result = "set[" & typeToString(t.sons[0]) & ']'
   of tyOpenArray: 
     result = "openarray[" & typeToString(t.sons[0]) & ']'
-  of tyDistinct: 
-    result = "distinct " & typeToString(t.sons[0], preferName)
+  of tyDistinct:
+    result = "distinct " & typeToString(t.sons[0],
+      if prefer == preferModuleInfo: preferModuleInfo else: preferName)
   of tyTuple: 
     # we iterate over t.sons here, because t.n may be nil
     result = "tuple["
@@ -530,15 +535,16 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       if i < sonsLen(t) - 1: add(result, ", ")
     add(result, ')')
     if t.sons[0] != nil: add(result, ": " & typeToString(t.sons[0]))
-    var prag: string
-    if t.callConv != ccDefault: prag = CallingConvToStr[t.callConv]
-    else: prag = ""
-    if tfNoSideEffect in t.flags: 
+    var prag = if t.callConv == ccDefault: "" else: CallingConvToStr[t.callConv]
+    if tfNoSideEffect in t.flags:
       addSep(prag)
       add(prag, "noSideEffect")
     if tfThread in t.flags:
       addSep(prag)
       add(prag, "gcsafe")
+    if t.lockLevel.ord != UnspecifiedLockLevel.ord:
+      addSep(prag)
+      add(prag, "locks: " & $t.lockLevel)
     if len(prag) != 0: add(result, "{." & prag & ".}")
   of tyVarargs, tyIter:
     result = typeToStr[t.kind] % typeToString(t.sons[0])
@@ -579,8 +585,7 @@ proc firstOrd(t: PType): BiggestInt =
     else: 
       assert(t.n.sons[0].kind == nkSym)
       result = t.n.sons[0].sym.position
-  of tyGenericInst, tyDistinct, tyConst, tyMutable,
-     tyTypeDesc, tyFieldAccessor:
+  of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc, tyFieldAccessor:
     result = firstOrd(lastSon(t))
   of tyOrdinal:
     if t.len > 0: result = firstOrd(lastSon(t))
@@ -969,6 +974,7 @@ proc inheritanceDiff*(a, b: PType): int =
   # | returns: -x iff `a` is the x'th direct superclass of `b`
   # | returns: +x iff `a` is the x'th direct subclass of `b`
   # | returns: `maxint` iff `a` and `b` are not compatible at all
+  if a == b or a.kind == tyError or b.kind == tyError: return 0
   assert a.kind == tyObject
   assert b.kind == tyObject
   var x = a
@@ -1014,10 +1020,10 @@ type
 
   TTypeAllowedFlags = set[TTypeAllowedFlag]
 
-proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
+proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
                     flags: TTypeAllowedFlags = {}): bool
 
-proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind,
+proc typeAllowedNode(marker: var IntSet, n: PNode, kind: TSymKind,
                      flags: TTypeAllowedFlags = {}): bool =
   result = true
   if n != nil: 
@@ -1041,7 +1047,7 @@ proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]],
     a = a.sons[i]
   result = a.kind == last
 
-proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
+proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
                     flags: TTypeAllowedFlags = {}): bool =
   assert(kind in {skVar, skLet, skConst, skParam, skResult})
   # if we have already checked the type, return true, because we stop the
@@ -1207,8 +1213,11 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     else: result = ptrSize
     a = ptrSize
   of tyNil, tyCString, tyString, tySequence, tyPtr, tyRef, tyVar, tyOpenArray,
-     tyBigNum: 
-    result = ptrSize
+     tyBigNum:
+    let base = typ.lastSon
+    if base == typ or (base.kind == tyTuple and base.size==szIllegalRecursion):
+      result = szIllegalRecursion
+    else: result = ptrSize
     a = result
   of tyArray, tyArrayConstr:
     let elemSize = computeSizeAux(typ.sons[1], a)
@@ -1270,7 +1279,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     #internalError("computeSizeAux()")
     result = szUnknownSize
   typ.size = result
-  typ.align = int(a)
+  typ.align = int16(a)
 
 proc computeSize(typ: PType): BiggestInt = 
   var a: BiggestInt = 1
@@ -1285,7 +1294,7 @@ proc getSize(typ: PType): BiggestInt =
   result = computeSize(typ)
   if result < 0: internalError("getSize: " & $typ.kind)
 
-proc containsGenericTypeIter(t: PType, closure: PObject): bool =
+proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
   if t.kind == tyStatic:
     return t.n == nil
 
@@ -1359,7 +1368,8 @@ proc compatibleEffects*(formal, actual: PType): bool =
       if real.len == 0: return false
       result = compatibleEffectsAux(st, real.sons[tagEffects])
       if not result: return
-  result = true
+  result = formal.lockLevel.ord < 0 or
+      actual.lockLevel.ord <= formal.lockLevel.ord
 
 proc isCompileTimeOnly*(t: PType): bool {.inline.} =
   result = t.kind in {tyTypeDesc, tyStatic}
diff --git a/compiler/vm.nim b/compiler/vm.nim
index e40acca6c..e5b357a11 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -133,6 +133,8 @@ proc createStrKeepNode(x: var TFullReg) =
     # cause of bugs like these is that the VM does not properly distinguish
     # between variable defintions (var foo = e) and variable updates (foo = e).
 
+include vmhooks
+
 template createStr(x) =
   x.node = newNode(nkStrLit)
 
@@ -256,8 +258,16 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
         c.currentExceptionB = c.currentExceptionA
         c.currentExceptionA = nil
         # execute the corresponding handler:
+        while c.code[pc2].opcode == opcExcept: inc pc2
         return (pc2, f)
       inc pc2
+      if c.code[pc2].opcode != opcExcept and nextExceptOrFinally >= 0:
+        # we're at the end of the *except list*, but maybe there is another
+        # *except branch*?
+        pc2 = nextExceptOrFinally+1
+        if c.code[pc2].opcode == opcExcept:
+          nextExceptOrFinally = pc2 + c.code[pc2].regBx - wordExcess
+
     if nextExceptOrFinally >= 0:
       pc2 = nextExceptOrFinally
     if c.code[pc2].opcode == opcFinally:
@@ -801,7 +811,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       let bb = regs[rb].node
       let isClosure = bb.kind == nkPar
       let prc = if not isClosure: bb.sym else: bb.sons[0].sym
-      if sfImportc in prc.flags:
+      if prc.offset < -1:
+        # it's a callback:
+        c.callbacks[-prc.offset-2].value(
+          VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs)))
+      elif sfImportc in prc.flags:
         if allowFFI notin c.features:
           globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI")
         # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
@@ -832,9 +846,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         if isClosure:
           newFrame.slots[rc].kind = rkNode
           newFrame.slots[rc].node = regs[rb].node.sons[1]
-        # allocate the temporaries:
-        #for i in rc+ord(isClosure) .. <prc.offset:
-        #  newFrame.slots[i] = newNode(nkEmpty)
         tos = newFrame
         move(regs, newFrame.slots)
         # -1 for the following 'inc pc'
@@ -888,10 +899,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcTry:
       let rbx = instr.regBx - wordExcess
       tos.pushSafePoint(pc + rbx)
+      assert c.code[pc+rbx].opcode in {opcExcept, opcFinally}
     of opcExcept:
       # just skip it; it's followed by a jump;
       # we'll execute in the 'raise' handler
-      discard
+      let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
+      inc pc, rbx
+      assert c.code[pc+1].opcode in {opcExcept, opcFinally}
     of opcFinally:
       # just skip it; it's followed by the code we need to execute anyway
       tos.popSafePoint()
@@ -1033,8 +1047,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       internalError(c.debug[pc], "too implement")
     of opcNarrowS:
       decodeB(rkInt)
-      let min = -(1 shl (rb-1))
-      let max = (1 shl (rb-1))-1
+      let min = -(1.BiggestInt shl (rb-1))
+      let max = (1.BiggestInt shl (rb-1))-1
       if regs[ra].intVal < min or regs[ra].intVal > max:
         stackTrace(c, tos, pc, errGenerated,
           msgKindToString(errUnhandledExceptionX) % "value out of range")
@@ -1132,14 +1146,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcParseExprToAst:
       decodeB(rkNode)
       # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
-      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
                             c.debug[pc].line.int)
       if sonsLen(ast) != 1:
         globalError(c.debug[pc], errExprExpected, "multiple statements")
       regs[ra].node = ast.sons[0]
     of opcParseStmtToAst:
       decodeB(rkNode)
-      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
                             c.debug[pc].line.int)
       regs[ra].node = ast
     of opcCallSite:
@@ -1316,6 +1330,8 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
   assert c.code[start].opcode != opcEof
   result = execute(c, start)
 
+include vmops
+
 # for now we share the 'globals' environment. XXX Coming soon: An API for
 # storing&loading the 'globals' environment to get what a component system
 # requires.
@@ -1325,6 +1341,7 @@ var
 proc setupGlobalCtx(module: PSym) =
   if globalCtx.isNil: globalCtx = newCtx(module)
   else: refresh(globalCtx, module)
+  registerAdditionalOps(globalCtx)
 
 proc myOpen(module: PSym): PPassContext =
   #var c = newEvalContext(module, emRepl)
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index cad48abea..d7cdafb69 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -170,7 +170,12 @@ type
     sym*: PSym
     slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
     maxSlots*: int
-    
+
+  VmArgs* = object
+    ra*, rb*, rc*: Natural
+    slots*: pointer
+  VmCallback* = proc (args: VmArgs) {.closure.}
+  
   PCtx* = ref TCtx
   TCtx* = object of passes.TPassContext # code gen context
     code*: seq[TInstr]
@@ -189,6 +194,7 @@ type
     traceActive*: bool
     loopIterations*: int
     comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces
+    callbacks*: seq[tuple[key: string, value: VmCallback]]
 
   TPosition* = distinct int
 
@@ -198,12 +204,15 @@ proc newCtx*(module: PSym): PCtx =
   PCtx(code: @[], debug: @[],
     globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
     prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations,
-    comesFromHeuristic: unknownLineInfo())
+    comesFromHeuristic: unknownLineInfo(), callbacks: @[])
 
 proc refresh*(c: PCtx, module: PSym) =
   c.module = module
   c.prc = PProc(blocks: @[])
 
+proc registerCallback*(c: PCtx; name: string; callback: VmCallback) =
+  c.callbacks.add((name, callback))
+
 const
   firstABxInstr* = opcTJmp
   largeInstrs* = { # instructions which use 2 int32s instead of 1:
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index fdd8276cc..6673d0bd2 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -9,7 +9,7 @@
 
 import ast, types, msgs, osproc, streams, options
 
-proc readOutput(p: PProcess): string =
+proc readOutput(p: Process): string =
   result = ""
   var output = p.outputStream
   while not output.atEnd:
@@ -33,6 +33,6 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
     # the module dependencies are accurate:
     appendToModule(module, newNode(nkIncludeStmt, info, @[
       newStrNode(nkStrLit, filename)]))
-  except EIO:
+  except IOError:
     localError(info, errCannotOpenFile, file)
     result = ""
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index a4ddc2e15..e0e34306c 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -46,7 +46,6 @@ proc debugInfo(info: TLineInfo): string =
 proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
   # first iteration: compute all necessary labels:
   var jumpTargets = initIntSet()
-  
   let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1)
   for i in start..last:
     let x = c.code[i]
@@ -83,7 +82,7 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
     result.add("\n")
     inc i
 
-proc echoCode*(c: PCtx, start=0; last = -1) {.deprecated.} =
+proc echoCode*(c: PCtx; start=0; last = -1) {.deprecated.} =
   var buf = ""
   codeListing(c, buf, start, last)
   echo buf
@@ -1068,6 +1067,9 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
         c.gABC(n, opcNodeToReg, dest, dest)
     elif c.prc.slots[tmp].kind >= slotTempUnknown:
       gABC(c, n, opcAddrNode, dest, tmp)
+      # XXX this can still be wrong sometimes; hopefully it's only generated
+      # in call contexts, where it is safe
+      #message(n.info, warnUser, "suspicious opcode used")
     else:
       gABC(c, n, opcAddrReg, dest, tmp)
     c.freeTemp(tmp)
@@ -1124,6 +1126,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
   # we need to ensure that we don't evaluate 'x' here:
   # proc foo() = var x ...
   let s = n.sym
+  if {sfCompileTime, sfGlobal} <= s.flags: return
   if s.kind in {skVar, skTemp, skLet, skParam, skResult} and 
       not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
     cannotEval(n)
@@ -1134,6 +1137,9 @@ proc isTemp(c: PCtx; dest: TDest): bool =
 template needsAdditionalCopy(n): expr =
   not c.isTemp(dest) and not fitsRegister(n.typ)
 
+proc skipDeref(n: PNode): PNode =
+  result = if n.kind in {nkDerefExpr, nkHiddenDeref}: n.sons[0] else: n
+
 proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
                        dest, idx, value: TRegister) =
   # opcLdObj et al really means "load address". We sometimes have to create a
@@ -1497,6 +1503,26 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
 
 proc genProc*(c: PCtx; s: PSym): int
 
+proc matches(s: PSym; x: string): bool =
+  let y = x.split('.')
+  var s = s
+  var L = y.len-1
+  while L >= 0:
+    if s == nil or y[L].cmpIgnoreStyle(s.name.s) != 0: return false
+    s = s.owner
+    dec L
+  result = true
+
+proc procIsCallback(c: PCtx; s: PSym): bool =
+  if s.offset < -1: return true
+  var i = -2
+  for key, value in items(c.callbacks):
+    if s.matches(key): 
+      doAssert s.offset == -1
+      s.offset = i
+      return true
+    dec i
+
 proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   case n.kind
   of nkSym:
@@ -1507,7 +1533,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
       genRdVar(c, n, dest, flags)
     of skProc, skConverter, skMacro, skTemplate, skMethod, skIterators:
       # 'skTemplate' is only allowed for 'getAst' support:
-      if sfImportc in s.flags: c.importcSym(n.info, s)
+      if procIsCallback(c, s): discard
+      elif sfImportc in s.flags: c.importcSym(n.info, s)
       genLit(c, n, dest)
     of skConst:
       gen(c, s.ast, dest)
@@ -1569,6 +1596,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
     let L = n.len-1
     for i in 0 .. <L: gen(c, n.sons[i])
     gen(c, n.sons[L], dest, flags)
+  of nkPragmaBlock:
+    gen(c, n.lastSon, dest, flags)
   of nkDiscardStmt:
     unused(n, dest)
     gen(c, n.sons[0])
diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim
new file mode 100644
index 000000000..cce87d433
--- /dev/null
+++ b/compiler/vmhooks.nim
@@ -0,0 +1,45 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+template setX(k, field) {.immediate, dirty.} =
+  var s: seq[TFullReg]
+  move(s, cast[seq[TFullReg]](a.slots))
+  if s[a.ra].kind != k:
+    myreset(s[a.ra])
+    s[a.ra].kind = k
+  s[a.ra].field = v
+
+proc setResult*(a: VmArgs; v: BiggestInt) = setX(rkInt, intVal)
+proc setResult*(a: VmArgs; v: BiggestFloat) = setX(rkFloat, floatVal)
+proc setResult*(a: VmArgs; v: bool) = 
+  let v = v.ord
+  setX(rkInt, intVal)
+
+proc setResult*(a: VmArgs; v: string) =
+  var s: seq[TFullReg]
+  move(s, cast[seq[TFullReg]](a.slots))
+  if s[a.ra].kind != rkNode:
+    myreset(s[a.ra])
+    s[a.ra].kind = rkNode
+  s[a.ra].node = newNode(nkStrLit)
+  s[a.ra].node.strVal = v
+
+template getX(k, field) {.immediate, dirty.} =
+  doAssert i < a.rc-1
+  let s = cast[seq[TFullReg]](a.slots)
+  doAssert s[i+a.rb+1].kind == k
+  result = s[i+a.rb+1].field
+
+proc getInt*(a: VmArgs; i: Natural): BiggestInt = getX(rkInt, intVal)
+proc getFloat*(a: VmArgs; i: Natural): BiggestFloat = getX(rkFloat, floatVal)
+proc getString*(a: VmArgs; i: Natural): string =
+  doAssert i < a.rc-1
+  let s = cast[seq[TFullReg]](a.slots)
+  doAssert s[i+a.rb+1].kind == rkNode
+  result = s[i+a.rb+1].node.strVal
diff --git a/compiler/vmops.nim b/compiler/vmops.nim
new file mode 100644
index 000000000..aa25d208a
--- /dev/null
+++ b/compiler/vmops.nim
@@ -0,0 +1,75 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+# Unforunately this cannot be a module yet:
+#import vmdeps, vm
+from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
+  arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc, 
+  floor, ceil, fmod
+
+from os import getEnv, existsEnv, dirExists, fileExists
+
+template mathop(op) {.immediate, dirty.} =
+  registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`)
+
+template osop(op) {.immediate, dirty.} =
+  registerCallback(c, "stdlib.os." & astToStr(op), `op Wrapper`)
+
+template systemop(op) {.immediate, dirty.} =
+  registerCallback(c, "stdlib.system." & astToStr(op), `op Wrapper`)
+
+template wrap1f(op) {.immediate, dirty.} =
+  proc `op Wrapper`(a: VmArgs) {.nimcall.} =
+    setResult(a, op(getFloat(a, 0)))
+  mathop op
+
+template wrap2f(op) {.immediate, dirty.} =
+  proc `op Wrapper`(a: VmArgs) {.nimcall.} =
+    setResult(a, op(getFloat(a, 0), getFloat(a, 1)))
+  mathop op
+
+template wrap1s(op) {.immediate, dirty.} =
+  proc `op Wrapper`(a: VmArgs) {.nimcall.} =
+    setResult(a, op(getString(a, 0)))
+  osop op
+
+template wrap2svoid(op) {.immediate, dirty.} =
+  proc `op Wrapper`(a: VmArgs) {.nimcall.} =
+    op(getString(a, 0), getString(a, 1))
+  systemop op
+
+proc registerAdditionalOps*(c: PCtx) =
+  wrap1f(sqrt)
+  wrap1f(ln)
+  wrap1f(log10)
+  wrap1f(log2)
+  wrap1f(exp)
+  wrap1f(round)
+  wrap1f(arccos)
+  wrap1f(arcsin)
+  wrap1f(arctan)
+  wrap2f(arctan2)
+  wrap1f(cos)
+  wrap1f(cosh)
+  wrap2f(hypot)
+  wrap1f(sinh)
+  wrap1f(sin)
+  wrap1f(tan)
+  wrap1f(tanh)
+  wrap2f(pow)
+  wrap1f(trunc)
+  wrap1f(floor)
+  wrap1f(ceil)
+  wrap2f(fmod)
+
+  wrap1s(getEnv)
+  wrap1s(existsEnv)
+  wrap1s(dirExists)
+  wrap1s(fileExists)
+  wrap2svoid(writeFile)
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index d81031917..068f59c71 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this