summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/aliases.nim14
-rw-r--r--compiler/ast.nim242
-rw-r--r--compiler/astalgo.nim328
-rw-r--r--compiler/babelcmd.nim10
-rw-r--r--compiler/bitsets.nim40
-rw-r--r--compiler/c2nim/c2nim.nim24
-rw-r--r--compiler/c2nim/clex.nim100
-rw-r--r--compiler/c2nim/cparse.nim826
-rw-r--r--compiler/c2nim/cpp.nim16
-rw-r--r--compiler/c2nim/tests/vincent.c33
-rw-r--r--compiler/c2nim/tests/vincent.h3
-rw-r--r--compiler/canonicalizer.nim416
-rw-r--r--compiler/ccgcalls.nim14
-rw-r--r--compiler/ccgexprs.nim301
-rw-r--r--compiler/ccgmerge.nim60
-rw-r--r--compiler/ccgstmts.nim178
-rw-r--r--compiler/ccgthreadvars.nim6
-rw-r--r--compiler/ccgtrav.nim8
-rw-r--r--compiler/ccgtypes.nim159
-rw-r--r--compiler/ccgutils.nim53
-rw-r--r--compiler/cgen.nim306
-rw-r--r--compiler/cgendata.nim28
-rw-r--r--compiler/cgmeth.nim28
-rw-r--r--compiler/commands.nim207
-rw-r--r--compiler/condsyms.nim77
-rw-r--r--compiler/crc.nim14
-rw-r--r--compiler/depends.nim4
-rw-r--r--compiler/docgen.nim226
-rw-r--r--compiler/docgen2.nim4
-rw-r--r--compiler/evalffi.nim146
-rw-r--r--compiler/evals.nim17
-rw-r--r--compiler/evaltempl.nim59
-rw-r--r--compiler/extccomp.nim190
-rw-r--r--compiler/filter_tmpl.nim112
-rw-r--r--compiler/filters.nim30
-rw-r--r--compiler/guards.nim58
-rw-r--r--compiler/hlo.nim11
-rw-r--r--compiler/idents.nim2
-rw-r--r--compiler/idgen.nim16
-rw-r--r--compiler/importer.nim48
-rw-r--r--compiler/jsgen.nim226
-rw-r--r--compiler/jstypes.nim10
-rw-r--r--compiler/lambdalifting.nim601
-rw-r--r--compiler/lexer.nim258
-rw-r--r--compiler/lists.nim40
-rw-r--r--compiler/llstream.nim97
-rw-r--r--compiler/lookups.nim131
-rw-r--r--compiler/lowerings.nim52
-rw-r--r--compiler/magicsys.nim33
-rw-r--r--compiler/main.nim163
-rw-r--r--compiler/modules.nim37
-rw-r--r--compiler/msgs.nim169
-rw-r--r--compiler/nimconf.nim32
-rw-r--r--compiler/nimeval.nim8
-rw-r--r--compiler/nimlexbase.nim45
-rw-r--r--compiler/nimrod.nim16
-rw-r--r--compiler/nimrod.nimrod.cfg8
-rw-r--r--compiler/nimsets.nim38
-rw-r--r--compiler/options.nim85
-rw-r--r--compiler/parampatterns.nim14
-rw-r--r--compiler/parser.nim396
-rw-r--r--compiler/pas2nim/pas2nim.nim2
-rw-r--r--compiler/pas2nim/paslex.nim76
-rw-r--r--compiler/pas2nim/pasparse.nim76
-rw-r--r--compiler/passaux.nim8
-rw-r--r--compiler/passes.nim8
-rw-r--r--compiler/patterns.nim16
-rw-r--r--compiler/pbraces.nim2
-rw-r--r--compiler/platform.nim20
-rw-r--r--compiler/pragmas.nim338
-rw-r--r--compiler/pretty.nim178
-rw-r--r--compiler/procfind.nim54
-rw-r--r--compiler/renderer.nim190
-rw-r--r--compiler/rodread.nim160
-rw-r--r--compiler/rodutils.nim6
-rw-r--r--compiler/rodwrite.nim54
-rw-r--r--compiler/ropes.nim66
-rw-r--r--compiler/saturate.nim12
-rw-r--r--compiler/sem.nim223
-rw-r--r--compiler/semcall.nim126
-rw-r--r--compiler/semdata.nim114
-rw-r--r--compiler/semdestruct.nim158
-rw-r--r--compiler/semexprs.nim648
-rw-r--r--compiler/semfold.nim135
-rw-r--r--compiler/semgnrc.nim56
-rw-r--r--compiler/seminst.nim251
-rw-r--r--compiler/semmacrosanity.nim89
-rw-r--r--compiler/semmagic.nim39
-rw-r--r--compiler/sempass2.nim71
-rw-r--r--compiler/semstmts.nim449
-rw-r--r--compiler/semtempl.nim176
-rw-r--r--compiler/semthreads.nim42
-rw-r--r--compiler/semtypes.nim707
-rw-r--r--compiler/semtypinst.nim373
-rw-r--r--compiler/service.nim12
-rw-r--r--compiler/sigmatch.nim834
-rw-r--r--compiler/suggest.nim55
-rw-r--r--compiler/syntaxes.nim81
-rw-r--r--compiler/transf.nim129
-rw-r--r--compiler/trees.nim40
-rw-r--r--compiler/treetab.nim36
-rw-r--r--compiler/types.nim489
-rw-r--r--compiler/typesrenderer.nim113
-rw-r--r--compiler/vm.nim1305
-rw-r--r--compiler/vmdef.nim65
-rw-r--r--compiler/vmdeps.nim61
-rw-r--r--compiler/vmgen.nim822
-rw-r--r--compiler/wordrecg.nim24
108 files changed, 9730 insertions, 6132 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim
index 7accb8ce3..a26b94303 100644
--- a/compiler/aliases.nim
+++ b/compiler/aliases.nim
@@ -42,7 +42,7 @@ proc isPartOfAux(n: PNode, b: PType, marker: var TIntSet): TAnalysisResult =
 proc isPartOfAux(a, b: PType, marker: var TIntSet): TAnalysisResult = 
   result = arNo
   if a == nil or b == nil: return 
-  if ContainsOrIncl(marker, a.id): return 
+  if containsOrIncl(marker, a.id): return 
   if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
   case a.kind
   of tyObject: 
@@ -54,11 +54,11 @@ proc isPartOfAux(a, b: PType, marker: var TIntSet): TAnalysisResult =
     for i in countup(0, sonsLen(a) - 1): 
       result = isPartOfAux(a.sons[i], b, marker)
       if result == arYes: return 
-  else: nil
+  else: discard
 
 proc isPartOf(a, b: PType): TAnalysisResult = 
   ## checks iff 'a' can be part of 'b'. Iterates over VALUE types!
-  var marker = InitIntSet()
+  var marker = initIntSet()
   # watch out: parameters reversed because I'm too lazy to change the code...
   result = isPartOfAux(b, a, marker)
 
@@ -115,7 +115,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
           var x = if a[1].kind == nkHiddenStdConv: a[1][1] else: a[1]
           var y = if b[1].kind == nkHiddenStdConv: b[1][1] else: b[1]
           
-          if SameValue(x, y): result = arYes
+          if sameValue(x, y): result = arYes
           else: result = arNo
         # else: maybe and no are accurate
       else:
@@ -140,7 +140,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
       result = isPartOf(a[1], b[1])
     of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
       result = isPartOf(a[0], b[0])
-    else: nil
+    else: discard
     # Calls return a new location, so a default of ``arNo`` is fine.
   else:
     # go down recursively; this is quite demanding:
@@ -177,6 +177,6 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
         if isPartOf(a.typ, b.typ) != arNo:
           result = isPartOf(a[0], b)
           if result == arNo: result = arMaybe
-      else: nil
-    else: nil
+      else: discard
+    else: discard
 
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 0790df0c4..0652bd3e7 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -62,7 +62,7 @@ type
     nkTripleStrLit,       # a triple string literal """
     nkNilLit,             # the nil literal
                           # end of atoms
-    nkMetaNode,           # difficult to explain; represents itself
+    nkMetaNode_Obsolete,  # difficult to explain; represents itself
                           # (used for macros)
     nkDotCall,            # used to temporarily flag a nkCall node; 
                           # this is used
@@ -188,10 +188,15 @@ type
     nkStmtListType,       # a statement list ending in a type; for macros
     nkBlockType,          # a statement block ending in a type; for macros
                           # types as syntactic trees:
+
+    nkWith,               # distinct with `foo`
+    nkWithout,            # distinct without `foo`
+    
     nkTypeOfExpr,         # type(1+2)
     nkObjectTy,           # object body
     nkTupleTy,            # tuple body
     nkTypeClassTy,        # user-defined type class
+    nkStaticTy,           # ``static[T]``
     nkRecList,            # list of object parts
     nkRecCase,            # case section of object
     nkRecWhen,            # when section of object
@@ -335,20 +340,70 @@ type
     tyConst, tyMutable, tyVarargs, 
     tyIter, # unused
     tyProxy # used as errornous type (for idetools)
-    tyTypeClass
-    tyAnd
-    tyOr
-    tyNot
-    tyAnything
-    tyParametricTypeClass # structured similarly to tyGenericInst
-                          # lastSon is the body of the type class
+    
+    tyBuiltInTypeClass #\
+      # Type such as the catch-all object, tuple, seq, etc
+    
+    tyUserTypeClass #\
+      # the body of a user-defined type class
+
+    tyUserTypeClassInst #\
+      # Instance of a parametric user-defined type class.
+      # Structured similarly to tyGenericInst.
+      # tyGenericInst represents concrete types, while
+      # this is still a "generic param" that will bind types
+      # and resolves them during sigmatch and instantiation.
+    
+    tyCompositeTypeClass #\
+      # Type such as seq[Number]
+      # The notes for tyUserTypeClassInst apply here as well 
+      # sons[0]: the original expression used by the user.
+      # sons[1]: fully expanded and instantiated meta type
+      # (potentially following aliases)
+    
+    tyAnd, tyOr, tyNot #\
+      # boolean type classes such as `string|int`,`not seq`,
+      # `Sortable and Enumable`, etc
+    
+    tyAnything #\
+      # a type class matching any type
+    
+    tyStatic #\
+      # a value known at compile type (the underlying type is .base)
+    
+    tyFromExpr #\
+      # This is a type representing an expression that depends
+      # on generic parameters (the exprsesion is stored in t.n)
+      # It will be converted to a real type only during generic
+      # instantiation and prior to this it has the potential to
+      # be any type.
+
+    tyFieldAccessor #\
+      # Expressions such as Type.field (valid in contexts such
+      # as the `is` operator and magics like `high` and `low`).
+      # Could be lifted to a single argument proc returning the
+      # field value.
+      # sons[0]: type of containing object or tuple
+      # sons[1]: field type
+      # .n: nkDotExpr storing the field name
+    
+static:
+  # remind us when TTypeKind stops to fit in a single 64-bit word
+  assert TTypeKind.high.ord <= 63
 
 const
   tyPureObject* = tyTuple
   GcTypeKinds* = {tyRef, tySequence, tyString}
   tyError* = tyProxy # as an errornous node should match everything
-  tyTypeClasses* = {tyTypeClass, tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
 
+  tyUnknownTypes* = {tyError, tyFromExpr}
+
+  tyTypeClasses* = {tyBuiltInTypeClass, tyCompositeTypeClass,
+                    tyUserTypeClass, tyUserTypeClassInst,
+                    tyAnd, tyOr, tyNot, tyAnything}
+
+  tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses
+ 
 type
   TTypeKinds* = set[TTypeKind]
 
@@ -362,11 +417,14 @@ type
                 # efficiency
     nfTransf,   # node has been transformed
     nfSem       # node has been checked for semantics
-    nfDelegate  # the call can use a delegator
+    nfDotField  # the call can use a dot operator
+    nfDotSetter # the call can use a setter dot operarator
+    nfExplicitCall # x.y() was used instead of x.y
     nfExprCall  # this is an attempt to call a regular expression
-
+    nfIsRef     # this node is a 'ref' node; used for the VM
+ 
   TNodeFlags* = set[TNodeFlag]
-  TTypeFlag* = enum   # keep below 32 for efficiency reasons (now: 23)
+  TTypeFlag* = enum   # keep below 32 for efficiency reasons (now: 28)
     tfVarargs,        # procedure has C styled varargs
     tfNoSideEffect,   # procedure type does not allow side effects
     tfFinal,          # is the object final?
@@ -378,13 +436,13 @@ type
     tfFromGeneric,    # type is an instantiation of a generic; this is needed
                       # because for instantiations of objects, structural
                       # type equality has to be used
-    tfUnresolved,     # marks unresolved typedesc params: e.g.
+    tfUnresolved,     # marks unresolved typedesc/static params: e.g.
                       # proc foo(T: typedesc, list: seq[T]): var T
+                      # proc foo(L: static[int]): array[L, int]
+                      # can be attached to ranges to indicate that the range
+                      # depends on unresolved static params.
     tfRetType,        # marks return types in proc (used to detect type classes 
                       # used as return types for return type inference)
-    tfAll,            # type class requires all constraints to be met (default)
-    tfAny,            # type class requires any constraint to be met
-    tfNot,            # type class with a negative check
     tfCapturesEnv,    # whether proc really captures some environment
     tfByCopy,         # pass object/tuple by copy (C backend)
     tfByRef,          # pass object/tuple by reference (C backend)
@@ -395,8 +453,19 @@ type
     tfNeedsInit,      # type constains a "not nil" constraint somewhere or some
                       # other type so that it requires inititalization
     tfHasShared,      # type constains a "shared" constraint modifier somewhere
-    tfHasMeta,        # type has "typedesc" or "expr" somewhere; or uses '|'
+    tfHasMeta,        # type contains "wildcard" sub-types such as generic params
+                      # or other type classes
     tfHasGCedMem,     # type contains GC'ed memory
+    tfPacked
+    tfHasStatic
+    tfGenericTypeParam
+    tfImplicitTypeParam
+    tfWildcard        # consider a proc like foo[T, I](x: Type[T, I])
+                      # T and I here can bind to both typedesc and static types
+                      # before this is determined, we'll consider them to be a
+                      # wildcard type.
+    tfGuarded         # guarded pointer
+    tfBorrowDot       # distinct type borrows '.'
 
   TTypeFlags* = set[TTypeFlag]
 
@@ -418,7 +487,8 @@ type
     skResult,             # special 'result' variable
     skProc,               # a proc
     skMethod,             # a method
-    skIterator,           # an iterator
+    skIterator,           # an inline iterator
+    skClosureIterator,    # a resumable closure iterator
     skConverter,          # a type converter
     skMacro,              # a macro
     skTemplate,           # a template; currently also misused for user-defined
@@ -430,12 +500,15 @@ type
     skStub,               # symbol is a stub and not yet loaded from the ROD
                           # file (it is loaded on demand, which may
                           # mean: never)
+    skPackage             # symbol is a package (used for canonicalization)
   TSymKinds* = set[TSymKind]
 
 const
-  routineKinds* = {skProc, skMethod, skIterator, skConverter,
-    skMacro, skTemplate}
+  routineKinds* = {skProc, skMethod, skIterator, skClosureIterator,
+                   skConverter, skMacro, skTemplate}
   tfIncompleteStruct* = tfVarargs
+  tfUncheckedArray* = tfVarargs
+  tfUnion* = tfNoSideEffect
   skError* = skUnknown
   
   # type flags that are essential for type equality:
@@ -545,11 +618,11 @@ type
     typ*: PType
     info*: TLineInfo
     flags*: TNodeFlags
-    case Kind*: TNodeKind
+    case kind*: TNodeKind
     of nkCharLit..nkUInt64Lit:
-      intVal*: biggestInt
+      intVal*: BiggestInt
     of nkFloatLit..nkFloat128Lit:
-      floatVal*: biggestFloat
+      floatVal*: BiggestFloat
     of nkStrLit..nkTripleStrLit:
       strVal*: string
     of nkSym: 
@@ -638,7 +711,7 @@ type
   TSym* {.acyclic.} = object of TIdObj
     # proc and type instantiations are cached in the generic symbol
     case kind*: TSymKind
-    of skType:
+    of skType, skGenericParam:
       typeInstCache*: seq[PType]
       typScope*: PScope
     of routineKinds:
@@ -763,19 +836,24 @@ type
     counter*: int
     data*: TObjectSeq
 
+  TImplication* = enum
+    impUnknown, impNo, impYes
+
 # BUGFIX: a module is overloadable so that a proc can have the
 # same name as an imported module. This is necessary because of
 # the poor naming choices in the standard library.
 
 const 
-  OverloadableSyms* = {skProc, skMethod, skIterator, skConverter,
-    skModule, skTemplate, skMacro}
+  OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator,
+    skConverter, skModule, skTemplate, skMacro}
 
   GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody, 
     tyGenericParam}
+  
   StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray, 
     tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray,
     tyVarargs}
+  
   ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in::
                                  # var x = expr
     tyBool, tyChar, tyEnum, tyArray, tyObject, 
@@ -789,10 +867,12 @@ const
                                     tyTuple, tySequence}
   NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
     tyProc, tyString, tyError}
-  ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator, 
+  ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType,
+    skIterator, skClosureIterator,
     skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
   PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
-                                      nfAllConst, nfDelegate}
+                                      nfDotSetter, nfDotField,
+                                      nfAllConst,nfIsRef}
   namePos* = 0
   patternPos* = 1    # empty except for term rewriting macros
   genericParamsPos* = 2
@@ -806,6 +886,7 @@ const
   nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
                   nkCommand, nkCallStrLit, nkHiddenCallConv}
 
+  nkLiterals* = {nkCharLit..nkTripleStrLit}
   nkLambdaKinds* = {nkLambda, nkDo}
   declarativeDefs* = {nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef}
   procDefs* = nkLambdaKinds + declarativeDefs
@@ -814,14 +895,17 @@ const
   nkStrKinds* = {nkStrLit..nkTripleStrLit}
 
   skLocalVars* = {skVar, skLet, skForVar, skParam, skResult}
-  skProcKinds* = {skProc, skTemplate, skMacro, skIterator, skMethod, skConverter}
+  skProcKinds* = {skProc, skTemplate, skMacro, skIterator, skClosureIterator,
+                  skMethod, skConverter}
+
+  skIterators* = {skIterator, skClosureIterator}
 
   lfFullExternalName* = lfParamCopy # \
     # only used when 'gCmd == cmdPretty': Indicates that the symbol has been
     # imported via 'importc: "fullname"' and no format string.
 
 # creator procs:
-proc newSym*(symKind: TSymKind, Name: PIdent, owner: PSym,
+proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
              info: TLineInfo): PSym
 proc newType*(kind: TTypeKind, owner: PSym): PType
 proc newNode*(kind: TNodeKind): PNode
@@ -894,6 +978,11 @@ template `{}=`*(n: PNode, i: int, s: PNode): stmt =
 var emptyNode* = newNode(nkEmpty)
 # There is a single empty node that is shared! Do not overwrite it!
 
+proc isMetaType*(t: PType): bool =
+  return t.kind in tyMetaTypes or
+         (t.kind == tyStatic and t.n == nil) or
+         tfHasMeta in t.flags
+
 proc linkTo*(t: PType, s: PSym): PType {.discardable.} =
   t.sym = s
   s.typ = t
@@ -910,7 +999,7 @@ template fileIdx*(c: PSym): int32 =
 
 template filename*(c: PSym): string =
   # XXX: this should be used only on module symbols
-  c.position.int32.toFileName
+  c.position.int32.toFilename
 
 proc appendToModule*(m: PSym, n: PNode) =
   ## The compiler will use this internally to add nodes that will be
@@ -929,7 +1018,7 @@ const                         # for all kind of hash tables:
 proc copyStrTable(dest: var TStrTable, src: TStrTable) = 
   dest.counter = src.counter
   if isNil(src.data): return 
-  setlen(dest.data, len(src.data))
+  setLen(dest.data, len(src.data))
   for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
   
 proc copyIdTable(dest: var TIdTable, src: TIdTable) = 
@@ -941,20 +1030,20 @@ proc copyIdTable(dest: var TIdTable, src: TIdTable) =
 proc copyTable(dest: var TTable, src: TTable) = 
   dest.counter = src.counter
   if isNil(src.data): return 
-  setlen(dest.data, len(src.data))
+  setLen(dest.data, len(src.data))
   for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
   
 proc copyObjectSet(dest: var TObjectSet, src: TObjectSet) = 
   dest.counter = src.counter
   if isNil(src.data): return 
-  setlen(dest.data, len(src.data))
+  setLen(dest.data, len(src.data))
   for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
   
 proc discardSons(father: PNode) = 
   father.sons = nil
 
 when defined(useNodeIds):
-  const nodeIdToDebug = 612777 # 612794
+  const nodeIdToDebug* = 482228 # 612794
   #612840 # 612905 # 614635 # 614637 # 614641
   # 423408
   #429107 # 430443 # 441048 # 441090 # 441153
@@ -990,6 +1079,10 @@ proc newStrNode(kind: TNodeKind, strVal: string): PNode =
   result = newNode(kind)
   result.strVal = strVal
 
+proc withInfo*(n: PNode, info: TLineInfo): PNode =
+  n.info = info
+  return n
+
 proc newIdentNode(ident: PIdent, info: TLineInfo): PNode = 
   result = newNode(nkIdent)
   result.ident = ident
@@ -1051,10 +1144,6 @@ proc newNodeIT(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
   result.info = info
   result.typ = typ
 
-proc newMetaNodeIT*(tree: PNode, info: TLineInfo, typ: PType): PNode =
-  result = newNodeIT(nkMetaNode, info, typ)
-  result.add(tree)
-
 var emptyParams = newNode(nkFormalParams)
 emptyParams.addSon(emptyNode)
 
@@ -1067,7 +1156,7 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
                   pragmas, exceptions, body]
 
 
-proc NewType(kind: TTypeKind, owner: PSym): PType = 
+proc newType(kind: TTypeKind, owner: PSym): PType = 
   new(result)
   result.kind = kind
   result.owner = owner
@@ -1075,7 +1164,7 @@ proc NewType(kind: TTypeKind, owner: PSym): PType =
   result.align = 2            # default alignment
   result.id = getID()
   when debugIds:
-    RegisterId(result)
+    registerId(result)
   #if result.id < 2000 then
   #  MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
   
@@ -1107,12 +1196,12 @@ proc assignType(dest, src: PType) =
   for i in countup(0, sonsLen(src) - 1): dest.sons[i] = src.sons[i]
   
 proc copyType(t: PType, owner: PSym, keepId: bool): PType = 
-  result = newType(t.Kind, owner)
+  result = newType(t.kind, owner)
   assignType(result, t)
   if keepId: 
     result.id = t.id
   else: 
-    when debugIds: RegisterId(result)
+    when debugIds: registerId(result)
   result.sym = t.sym          # backend-info should not be copied
   
 proc copySym(s: PSym, keepId: bool = false): PSym = 
@@ -1123,7 +1212,7 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
     result.id = s.id
   else: 
     result.id = getID()
-    when debugIds: RegisterId(result)
+    when debugIds: registerId(result)
   result.flags = s.flags
   result.magic = s.magic
   if s.kind == skModule:
@@ -1147,12 +1236,12 @@ proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym =
   # XXX once usedGenerics is used, ensure module aliases keep working!
   assert s.usedGenerics == nil
   
-proc newSym(symKind: TSymKind, Name: PIdent, owner: PSym,
+proc newSym(symKind: TSymKind, name: PIdent, owner: PSym,
             info: TLineInfo): PSym = 
   # generates a symbol and initializes the hash field too
   new(result)
-  result.Name = Name
-  result.Kind = symKind
+  result.name = name
+  result.kind = symKind
   result.flags = {}
   result.info = info
   result.options = gOptions
@@ -1160,36 +1249,36 @@ proc newSym(symKind: TSymKind, Name: PIdent, owner: PSym,
   result.offset = - 1
   result.id = getID()
   when debugIds: 
-    RegisterId(result)
+    registerId(result)
   #if result.id < 2000:
   #  MessageOut(name.s & " has id: " & toString(result.id))
   
 proc initStrTable(x: var TStrTable) = 
   x.counter = 0
-  newSeq(x.data, startSize)
+  newSeq(x.data, StartSize)
 
 proc newStrTable*: TStrTable =
   initStrTable(result)
 
 proc initTable(x: var TTable) = 
   x.counter = 0
-  newSeq(x.data, startSize)
+  newSeq(x.data, StartSize)
 
 proc initIdTable(x: var TIdTable) = 
   x.counter = 0
-  newSeq(x.data, startSize)
+  newSeq(x.data, StartSize)
 
 proc initObjectSet(x: var TObjectSet) = 
   x.counter = 0
-  newSeq(x.data, startSize)
+  newSeq(x.data, StartSize)
 
 proc initIdNodeTable(x: var TIdNodeTable) = 
   x.counter = 0
-  newSeq(x.data, startSize)
+  newSeq(x.data, StartSize)
 
 proc initNodeTable(x: var TNodeTable) = 
   x.counter = 0
-  newSeq(x.data, startSize)
+  newSeq(x.data, StartSize)
 
 proc sonsLen(n: PType): int = 
   if isNil(n.sons): result = 0
@@ -1203,7 +1292,7 @@ proc newSons(father: PType, length: int) =
   if isNil(father.sons): 
     newSeq(father.sons, length)
   else:
-    setlen(father.sons, length)
+    setLen(father.sons, length)
 
 proc sonsLen(n: PNode): int = 
   if isNil(n.sons): result = 0
@@ -1213,7 +1302,11 @@ proc newSons(father: PNode, length: int) =
   if isNil(father.sons): 
     newSeq(father.sons, length)
   else:
-    setlen(father.sons, length)
+    setLen(father.sons, length)
+
+proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
+  result = t
+  while result.kind in kinds: result = lastSon(result)
 
 proc propagateToOwner*(owner, elem: PType) =
   const HaveTheirOwnEmpty = {tySequence, tySet}
@@ -1226,15 +1319,16 @@ proc propagateToOwner*(owner, elem: PType) =
       owner.flags.incl tfNeedsInit
   
   if tfNeedsInit in elem.flags:
-    if owner.kind in HaveTheirOwnEmpty: nil
+    if owner.kind in HaveTheirOwnEmpty: discard
     else: owner.flags.incl tfNeedsInit
     
   if tfShared in elem.flags:
     owner.flags.incl tfHasShared
-  
-  if elem.kind in {tyExpr, tyTypeDesc}:
+
+  if elem.isMetaType:
     owner.flags.incl tfHasMeta
-  elif elem.kind in {tyString, tyRef, tySequence} or
+
+  if elem.kind in {tyString, tyRef, tySequence} or
       elem.kind == tyProc and elem.callConv == ccClosure:
     owner.flags.incl tfHasGCedMem
 
@@ -1256,7 +1350,7 @@ proc delSon(father: PNode, idx: int) =
   if isNil(father.sons): return 
   var length = sonsLen(father)
   for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1]
-  setlen(father.sons, length - 1)
+  setLen(father.sons, length - 1)
 
 proc copyNode(src: PNode): PNode = 
   # does not copy its sons!
@@ -1269,13 +1363,13 @@ proc copyNode(src: PNode): PNode =
   when defined(useNodeIds):
     if result.id == nodeIdToDebug:
       echo "COMES FROM ", src.id
-  case src.Kind
+  case src.kind
   of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
   of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
   of nkSym: result.sym = src.sym
   of nkIdent: result.ident = src.ident
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
-  else: nil
+  else: discard
 
 proc shallowCopy*(src: PNode): PNode = 
   # does not copy its sons, but provides space for them:
@@ -1287,7 +1381,7 @@ proc shallowCopy*(src: PNode): PNode =
   when defined(useNodeIds):
     if result.id == nodeIdToDebug:
       echo "COMES FROM ", src.id
-  case src.Kind
+  case src.kind
   of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
   of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
   of nkSym: result.sym = src.sym
@@ -1306,7 +1400,7 @@ proc copyTree(src: PNode): PNode =
   when defined(useNodeIds):
     if result.id == nodeIdToDebug:
       echo "COMES FROM ", src.id
-  case src.Kind
+  case src.kind
   of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
   of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
   of nkSym: result.sym = src.sym
@@ -1364,14 +1458,14 @@ proc sonsNotNil(n: PNode): bool =
       return false
   result = true
 
-proc getInt*(a: PNode): biggestInt = 
+proc getInt*(a: PNode): BiggestInt = 
   case a.kind
   of nkIntLit..nkUInt64Lit: result = a.intVal
   else: 
     internalError(a.info, "getInt")
     result = 0
 
-proc getFloat*(a: PNode): biggestFloat = 
+proc getFloat*(a: PNode): BiggestFloat = 
   case a.kind
   of nkFloatLit..nkFloat128Lit: result = a.floatVal
   else: 
@@ -1398,19 +1492,22 @@ proc isGenericRoutine*(s: PSym): bool =
   of skProcKinds:
     result = sfFromGeneric in s.flags or
              (s.ast != nil and s.ast[genericParamsPos].kind != nkEmpty)
-  else: nil
+  else: discard
 
 proc skipGenericOwner*(s: PSym): PSym =
-  InternalAssert s.kind in skProcKinds
+  internalAssert s.kind in skProcKinds
   ## Generic instantiations are owned by their originating generic
   ## symbol. This proc skips such owners and goes straigh to the owner
   ## of the generic itself (the module or the enclosing proc).
   result = if sfFromGeneric in s.flags: s.owner.owner
            else: s.owner
 
+proc originatingModule*(s: PSym): PSym =
+  result = s.owner
+  while result.kind != skModule: result = result.owner
+
 proc isRoutine*(s: PSym): bool {.inline.} =
-  result = s.kind in {skProc, skTemplate, skMacro, skIterator, skMethod,
-                      skConverter}
+  result = s.kind in skProcKinds
 
 proc hasPattern*(s: PSym): bool {.inline.} =
   result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty
@@ -1418,6 +1515,9 @@ proc hasPattern*(s: PSym): bool {.inline.} =
 iterator items*(n: PNode): PNode =
   for i in 0.. <n.len: yield n.sons[i]
 
+iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
+  for i in 0.. <n.len: yield (i, n.sons[i])
+
 proc isAtom*(n: PNode): bool {.inline.} =
   result = n.kind >= nkNone and n.kind <= nkNilLit
 
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 6c48dd00f..36dd7f562 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -24,35 +24,35 @@ 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: PObject): bool
   # returns true whether n is in t
-proc ObjectSetIncl*(t: var TObjectSet, obj: PObject)
+proc objectSetIncl*(t: var TObjectSet, obj: PObject)
   # include an element n in the table t
-proc ObjectSetContainsOrIncl*(t: var TObjectSet, obj: PObject): bool
+proc objectSetContainsOrIncl*(t: var TObjectSet, obj: PObject): 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: PObject)
+proc tableGet*(t: TTable, key: PObject): PObject
 type 
   TCmpProc* = proc (key, closure: PObject): bool {.nimcall.} # true if found
 
-proc TableSearch*(t: TTable, key, closure: PObject, 
+proc tableSearch*(t: TTable, key, closure: PObject, 
                   comparator: TCmpProc): PObject
   # return val as soon as comparator returns true; if this never happens,
   # nil is returned
 
 # ----------------------- str table -----------------------------------------
-proc StrTableContains*(t: TStrTable, n: PSym): bool
-proc StrTableAdd*(t: var TStrTable, n: PSym)
-proc StrTableGet*(t: TStrTable, name: PIdent): PSym  
+proc strTableContains*(t: TStrTable, n: PSym): bool
+proc strTableAdd*(t: var TStrTable, n: PSym)
+proc strTableGet*(t: TStrTable, name: PIdent): PSym  
   
 type 
   TTabIter*{.final.} = object # consider all fields here private
     h*: THash                 # current hash
-  
-proc InitTabIter*(ti: var TTabIter, tab: TStrTable): PSym
-proc NextIter*(ti: var TTabIter, tab: TStrTable): PSym
+
+proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym
+proc nextIter*(ti: var TTabIter, tab: TStrTable): PSym
   # usage:
   # var 
   #   i: TTabIter
@@ -69,8 +69,8 @@ type
     name*: PIdent
 
 
-proc InitIdentIter*(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym
-proc NextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym
+proc initIdentIter*(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym
+proc nextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym
 
 # these are for debugging only: They are not really deprecated, but I want
 # the warning so that release versions do not contain debugging statements:
@@ -79,15 +79,14 @@ 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 IdTableHasObjectAsKey*(t: TIdTable, key: PIdObj): bool
+proc idTableGet*(t: TIdTable, key: PIdObj): PObject
+proc idTableGet*(t: TIdTable, key: int): PObject
+proc idTablePut*(t: var TIdTable, key: PIdObj, val: PObject)
+proc idTableHasObjectAsKey*(t: TIdTable, key: PIdObj): bool
   # checks if `t` contains the `key` (compared by the pointer value, not only
   # `key`'s id)
-proc IdNodeTableGet*(t: TIdNodeTable, key: PIdObj): PNode
-proc IdNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode)
-proc writeIdNodeTable*(t: TIdNodeTable)
+proc idNodeTableGet*(t: TIdNodeTable, key: PIdObj): PNode
+proc idNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode)
 
 # ---------------------------------------------------------------------------
 
@@ -111,9 +110,9 @@ type
     data*: TIIPairSeq
 
 
-proc initIITable*(x: var TIITable)
-proc IITableGet*(t: TIITable, key: int): int
-proc IITablePut*(t: var TIITable, key, val: int)
+proc initIiTable*(x: var TIITable)
+proc iiTableGet*(t: TIITable, key: int): int
+proc iiTablePut*(t: var TIITable, key, val: int)
 
 # implementation
 
@@ -129,7 +128,7 @@ proc skipConvTakeType*(n: PNode): PNode =
   result = n.skipConv
   result.typ = n.typ
 
-proc SameValue*(a, b: PNode): bool = 
+proc sameValue*(a, b: PNode): bool = 
   result = false
   case a.kind
   of nkCharLit..nkInt64Lit: 
@@ -141,7 +140,7 @@ proc SameValue*(a, b: PNode): bool =
   else:
     # don't raise an internal error for 'nimrod check':
     #InternalError(a.info, "SameValue")
-    nil
+    discard
 
 proc leValue*(a, b: PNode): bool = 
   # a <= b?
@@ -156,7 +155,13 @@ proc leValue*(a, b: PNode): bool =
   else: 
     # don't raise an internal error for 'nimrod check':
     #InternalError(a.info, "leValue")
-    nil
+    discard
+
+proc weakLeValue*(a, b: PNode): TImplication =
+  if a.kind notin nkLiterals or b.kind notin nkLiterals:
+    result = impUnknown
+  else:
+    result = if leValue(a, b): impYes else: impNo
 
 proc lookupInRecord(n: PNode, field: PIdent): PSym = 
   result = nil
@@ -166,7 +171,7 @@ proc lookupInRecord(n: PNode, field: PIdent): PSym =
       result = lookupInRecord(n.sons[i], field)
       if result != nil: return 
   of nkRecCase: 
-    if (n.sons[0].kind != nkSym): InternalError(n.info, "lookupInRecord")
+    if (n.sons[0].kind != nkSym): internalError(n.info, "lookupInRecord")
     result = lookupInRecord(n.sons[0], field)
     if result != nil: return 
     for i in countup(1, sonsLen(n) - 1): 
@@ -182,14 +187,14 @@ proc lookupInRecord(n: PNode, field: PIdent): PSym =
 proc getModule(s: PSym): PSym = 
   result = s
   assert((result.kind == skModule) or (result.owner != result))
-  while (result != nil) and (result.kind != skModule): result = result.owner
+  while result != nil and result.kind != skModule: result = result.owner
   
 proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym = 
   for i in countup(start, sonsLen(list) - 1): 
     if list.sons[i].kind == nkSym:
       result = list.sons[i].sym
       if result.name.id == ident.id: return 
-    else: InternalError(list.info, "getSymFromList")
+    else: internalError(list.info, "getSymFromList")
   result = nil
 
 proc hashNode(p: PObject): THash = 
@@ -203,7 +208,7 @@ proc spaces(x: int): PRope =
   # returns x spaces
   result = toRope(repeatChar(x))
 
-proc toYamlChar(c: Char): string = 
+proc toYamlChar(c: char): string = 
   case c
   of '\0'..'\x1F', '\x80'..'\xFF': result = "\\u" & strutils.toHex(ord(c), 4)
   of '\'', '\"', '\\': result = '\\' & c
@@ -216,7 +221,7 @@ proc makeYamlString*(s: string): PRope =
   const MaxLineLength = 64
   result = nil
   var res = "\""
-  for i in countup(0, len(s) - 1): 
+  for i in countup(0, if s.isNil: -1 else: (len(s)-1)): 
     if (i + 1) mod MaxLineLength == 0: 
       add(res, '\"')
       add(res, "\n")
@@ -262,7 +267,7 @@ proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int,
   app(result, "]")
   assert(mycount == n.counter)
 
-proc ropeConstr(indent: int, c: openarray[PRope]): PRope = 
+proc ropeConstr(indent: int, c: openArray[PRope]): PRope = 
   # array of (name, value) pairs
   var istr = spaces(indent + 2)
   result = toRope("{")
@@ -277,7 +282,7 @@ proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int,
                   maxRecDepth: int): PRope = 
   if n == nil: 
     result = toRope("null")
-  elif ContainsOrIncl(marker, n.id): 
+  elif containsOrIncl(marker, n.id): 
     result = ropef("\"$1 @$2\"", [toRope(n.name.s), toRope(
         strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
   else: 
@@ -298,7 +303,7 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
                    maxRecDepth: int): PRope = 
   if n == nil: 
     result = toRope("null")
-  elif ContainsOrIncl(marker, n.id): 
+  elif containsOrIncl(marker, n.id): 
     result = ropef("\"$1 @$2\"", [toRope($n.kind), toRope(
         strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
   else: 
@@ -315,7 +320,7 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
                                  makeYamlString($n.kind), 
                                  toRope("sym"), symToYamlAux(n.sym, marker, 
         indent + 2, maxRecDepth - 1), toRope("n"), treeToYamlAux(n.n, marker, 
-        indent + 2, maxRecDepth - 1), toRope("flags"), FlagsToStr(n.flags), 
+        indent + 2, maxRecDepth - 1), toRope("flags"), flagsToStr(n.flags), 
                                  toRope("callconv"), 
                                  makeYamlString(CallingConvToStr[n.callConv]), 
                                  toRope("size"), toRope(n.size), 
@@ -336,9 +341,12 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
         appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)])
       of nkFloatLit, nkFloat32Lit, nkFloat64Lit: 
         appf(result, ",$N$1\"floatVal\": $2", 
-            [istr, toRope(n.floatVal.ToStrMaxPrecision)])
+            [istr, toRope(n.floatVal.toStrMaxPrecision)])
       of nkStrLit..nkTripleStrLit: 
-        appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
+        if n.strVal.isNil:
+          appf(result, ",$N$1\"strVal\": null", [istr])
+        else:
+          appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
       of nkSym: 
         appf(result, ",$N$1\"sym\": $2", 
              [istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)])
@@ -360,15 +368,15 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
     appf(result, "$N$1}", [spaces(indent)])
 
 proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope = 
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = treeToYamlAux(n, marker, indent, maxRecDepth)
 
 proc typeToYaml(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope = 
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = typeToYamlAux(n, marker, indent, maxRecDepth)
 
 proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope = 
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = symToYamlAux(n, marker, indent, maxRecDepth)
 
 proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope
@@ -406,9 +414,12 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
         appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)])
       of nkFloatLit, nkFloat32Lit, nkFloat64Lit: 
         appf(result, ",$N$1\"floatVal\": $2", 
-            [istr, toRope(n.floatVal.ToStrMaxPrecision)])
+            [istr, toRope(n.floatVal.toStrMaxPrecision)])
       of nkStrLit..nkTripleStrLit: 
-        appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
+        if n.strVal.isNil:
+          appf(result, ",$N$1\"strVal\": null", [istr])
+        else:
+          appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
       of nkSym: 
         appf(result, ",$N$1\"sym\": $2_$3", 
             [istr, toRope(n.sym.name.s), toRope(n.sym.id)])
@@ -433,6 +444,8 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
 proc debug(n: PSym) =
   if n == nil:
     writeln(stdout, "null")
+  elif n.kind == skUnknown:
+    writeln(stdout, "skUnknown")
   else:
     #writeln(stdout, ropeToStr(symToYaml(n, 0, 1)))
     writeln(stdout, ropeToStr(ropef("$1_$2: $3, $4", [
@@ -454,18 +467,18 @@ 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: PObject): 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: 
-    if (t.data[h] == obj): 
+  while t.data[h] != nil:
+    if t.data[h] == obj:
       return true
     h = nextTry(h, high(t.data))
   result = false
 
-proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) = 
-  var h: THash = HashNode(obj) and high(data)
-  while data[h] != nil: 
+proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) =
+  var h: THash = hashNode(obj) and high(data)
+  while data[h] != nil:
     assert(data[h] != obj)
     h = nextTry(h, high(data))
   assert(data[h] == nil)
@@ -473,8 +486,8 @@ proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) =
 
 proc objectSetEnlarge(t: var TObjectSet) = 
   var n: TObjectSeq
-  newSeq(n, len(t.data) * growthFactor)
-  for i in countup(0, high(t.data)): 
+  newSeq(n, len(t.data) * GrowthFactor)
+  for i in countup(0, high(t.data)):
     if t.data[i] != nil: objectSetRawInsert(n, t.data[i])
   swap(t.data, n)
 
@@ -485,7 +498,7 @@ proc objectSetIncl(t: var TObjectSet, obj: PObject) =
 
 proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool = 
   # returns true if obj is already in the string table:
-  var h: THash = HashNode(obj) and high(t.data)
+  var h: THash = hashNode(obj) and high(t.data)
   while true: 
     var it = t.data[h]
     if it == nil: break 
@@ -501,7 +514,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: PObject): 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: 
@@ -509,7 +522,7 @@ proc TableRawGet(t: TTable, key: PObject): int =
     h = nextTry(h, high(t.data))
   result = -1
 
-proc TableSearch(t: TTable, key, closure: PObject, 
+proc tableSearch(t: TTable, key, closure: PObject, 
                  comparator: TCmpProc): PObject = 
   var h: THash = hashNode(key) and high(t.data) # start with real hash value
   while t.data[h].key != nil: 
@@ -520,13 +533,13 @@ proc TableSearch(t: TTable, key, closure: PObject,
     h = nextTry(h, high(t.data))
   result = nil
 
-proc TableGet(t: TTable, key: PObject): PObject = 
-  var index = TableRawGet(t, key)
+proc tableGet(t: TTable, key: PObject): PObject = 
+  var index = tableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = nil
   
-proc TableRawInsert(data: var TPairSeq, key, val: PObject) = 
-  var h: THash = HashNode(key) and high(data)
+proc tableRawInsert(data: var TPairSeq, key, val: PObject) = 
+  var h: THash = hashNode(key) and high(data)
   while data[h].key != nil: 
     assert(data[h].key != key)
     h = nextTry(h, high(data))
@@ -534,23 +547,23 @@ proc TableRawInsert(data: var TPairSeq, key, val: PObject) =
   data[h].key = key
   data[h].val = val
 
-proc TableEnlarge(t: var TTable) = 
+proc tableEnlarge(t: var TTable) = 
   var n: TPairSeq
-  newSeq(n, len(t.data) * growthFactor)
+  newSeq(n, len(t.data) * GrowthFactor)
   for i in countup(0, high(t.data)): 
-    if t.data[i].key != nil: TableRawInsert(n, t.data[i].key, t.data[i].val)
+    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) = 
-  var index = TableRawGet(t, key)
+proc tablePut(t: var TTable, key, val: PObject) = 
+  var index = tableRawGet(t, key)
   if index >= 0: 
     t.data[index].val = val
   else: 
-    if mustRehash(len(t.data), t.counter): TableEnlarge(t)
-    TableRawInsert(t.data, key, val)
+    if mustRehash(len(t.data), t.counter): tableEnlarge(t)
+    tableRawInsert(t.data, key, val)
     inc(t.counter)
 
-proc StrTableContains(t: TStrTable, n: PSym): bool = 
+proc strTableContains(t: TStrTable, n: PSym): bool = 
   var h: THash = n.name.h and high(t.data) # start with real hash value
   while t.data[h] != nil: 
     if (t.data[h] == n): 
@@ -558,18 +571,35 @@ proc StrTableContains(t: TStrTable, n: PSym): bool =
     h = nextTry(h, high(t.data))
   result = false
 
-proc StrTableRawInsert(data: var TSymSeq, n: PSym) = 
+proc strTableRawInsert(data: var TSymSeq, n: PSym) = 
   var h: THash = n.name.h and high(data)
-  while data[h] != nil: 
-    if data[h] == n:
-      # allowed for 'export' feature:
-      #InternalError(n.info, "StrTableRawInsert: " & n.name.s)
-      return
-    h = nextTry(h, high(data))
-  assert(data[h] == nil)
-  data[h] = n
-
-proc SymTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) =
+  if sfImmediate notin n.flags:
+    # fast path:
+    while data[h] != nil:
+      if data[h] == n:
+        # allowed for 'export' feature:
+        #InternalError(n.info, "StrTableRawInsert: " & n.name.s)
+        return
+      h = nextTry(h, high(data))
+    assert(data[h] == nil)
+    data[h] = n
+  else:
+    # slow path; we have to ensure immediate symbols are preferred for
+    # symbol lookups.
+    # consider the chain: foo (immediate), foo, bar, bar (immediate)
+    # then bar (immediate) gets replaced with foo (immediate) and the non
+    # immediate foo is picked! Thus we need to replace it with the first
+    # slot that has in fact the same identifier stored in it!
+    var favPos = -1
+    while data[h] != nil:
+      if data[h] == n: return
+      if favPos < 0 and data[h].name.id == n.name.id: favPos = h
+      h = nextTry(h, high(data))
+    assert(data[h] == nil)
+    data[h] = n
+    if favPos >= 0: swap data[h], data[favPos]
+
+proc symTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) =
   assert prevSym.name.h == newSym.name.h
   var h: THash = prevSym.name.h and high(data)
   while data[h] != nil:
@@ -579,22 +609,22 @@ proc SymTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) =
     h = nextTry(h, high(data))
   assert false
  
-proc SymTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) =
-  SymTabReplaceRaw(t.data, prevSym, newSym)
+proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) =
+  symTabReplaceRaw(t.data, prevSym, newSym)
 
-proc StrTableEnlarge(t: var TStrTable) = 
+proc strTableEnlarge(t: var TStrTable) = 
   var n: TSymSeq
-  newSeq(n, len(t.data) * growthFactor)
+  newSeq(n, len(t.data) * GrowthFactor)
   for i in countup(0, high(t.data)): 
-    if t.data[i] != nil: StrTableRawInsert(n, t.data[i])
+    if t.data[i] != nil: strTableRawInsert(n, t.data[i])
   swap(t.data, n)
 
-proc StrTableAdd(t: var TStrTable, n: PSym) = 
-  if mustRehash(len(t.data), t.counter): StrTableEnlarge(t)
-  StrTableRawInsert(t.data, n)
+proc strTableAdd(t: var TStrTable, n: PSym) = 
+  if mustRehash(len(t.data), t.counter): strTableEnlarge(t)
+  strTableRawInsert(t.data, n)
   inc(t.counter)
 
-proc StrTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
+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!
   # This way the newest redefinition is picked by the semantic analyses!
@@ -608,15 +638,15 @@ proc StrTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
       return true             # found it
     h = nextTry(h, high(t.data))
   if mustRehash(len(t.data), t.counter):
-    StrTableEnlarge(t)
-    StrTableRawInsert(t.data, n)
+    strTableEnlarge(t)
+    strTableRawInsert(t.data, n)
   else:
     assert(t.data[h] == nil)
     t.data[h] = n
   inc(t.counter)
   result = false
 
-proc StrTableGet(t: TStrTable, name: PIdent): PSym = 
+proc strTableGet(t: TStrTable, name: PIdent): PSym = 
   var h: THash = name.h and high(t.data)
   while true: 
     result = t.data[h]
@@ -624,19 +654,19 @@ proc StrTableGet(t: TStrTable, name: PIdent): PSym =
     if result.name.id == name.id: break 
     h = nextTry(h, high(t.data))
 
-proc InitIdentIter(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym = 
+proc initIdentIter(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym = 
   ti.h = s.h
   ti.name = s
-  if tab.Counter == 0: result = nil
-  else: result = NextIdentIter(ti, tab)
+  if tab.counter == 0: result = nil
+  else: result = nextIdentIter(ti, tab)
   
-proc NextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym = 
+proc nextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym = 
   var h, start: THash
   h = ti.h and high(tab.data)
   start = h
   result = tab.data[h]
   while result != nil: 
-    if result.Name.id == ti.name.id: break 
+    if result.name.id == ti.name.id: break 
     h = nextTry(h, high(tab.data))
     if h == start: 
       result = nil
@@ -644,13 +674,13 @@ proc NextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
     result = tab.data[h]
   ti.h = nextTry(h, high(tab.data))
   
-proc NextIdentExcluding*(ti: var TIdentIter, tab: TStrTable, 
+proc nextIdentExcluding*(ti: var TIdentIter, tab: TStrTable, 
                          excluding: TIntSet): PSym =
   var h: THash = ti.h and high(tab.data)
   var start = h
   result = tab.data[h]
   while result != nil: 
-    if result.Name.id == ti.name.id and not Contains(excluding, result.id): 
+    if result.name.id == ti.name.id and not contains(excluding, result.id): 
       break
     h = nextTry(h, high(tab.data))
     if h == start: 
@@ -658,35 +688,35 @@ proc NextIdentExcluding*(ti: var TIdentIter, tab: TStrTable,
       break 
     result = tab.data[h]
   ti.h = nextTry(h, high(tab.data))
-  if result != nil and Contains(excluding, result.id): result = nil
+  if result != nil and contains(excluding, result.id): result = nil
 
-proc FirstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
+proc firstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
                           excluding: TIntSet): PSym = 
   ti.h = s.h
   ti.name = s
-  if tab.Counter == 0: result = nil
-  else: result = NextIdentExcluding(ti, tab, excluding)
+  if tab.counter == 0: result = nil
+  else: result = nextIdentExcluding(ti, tab, excluding)
 
-proc InitTabIter(ti: var TTabIter, tab: TStrTable): PSym = 
+proc initTabIter(ti: var TTabIter, tab: TStrTable): PSym = 
   ti.h = 0                    # we start by zero ...
   if tab.counter == 0: 
     result = nil              # FIX 1: removed endless loop
   else: 
-    result = NextIter(ti, tab)
+    result = nextIter(ti, tab)
   
-proc NextIter(ti: var TTabIter, tab: TStrTable): PSym = 
+proc nextIter(ti: var TTabIter, tab: TStrTable): PSym = 
   result = nil
   while (ti.h <= high(tab.data)): 
     result = tab.data[ti.h]
-    Inc(ti.h)                 # ... and increment by one always
+    inc(ti.h)                 # ... and increment by one always
     if result != nil: break 
 
 iterator items*(tab: TStrTable): PSym = 
   var it: TTabIter
-  var s = InitTabIter(it, tab)
+  var s = initTabIter(it, tab)
   while s != nil: 
     yield s
-    s = NextIter(it, tab)
+    s = nextIter(it, tab)
 
 proc hasEmptySlot(data: TIdPairSeq): bool = 
   for h in countup(0, high(data)): 
@@ -694,27 +724,27 @@ proc hasEmptySlot(data: TIdPairSeq): bool =
       return true
   result = false
 
-proc IdTableRawGet(t: TIdTable, key: int): int = 
+proc idTableRawGet(t: TIdTable, key: int): int = 
   var h: THash
   h = key and high(t.data)    # start with real hash value
   while t.data[h].key != nil: 
-    if (t.data[h].key.id == key): 
+    if t.data[h].key.id == key:
       return h
     h = nextTry(h, high(t.data))
   result = - 1
 
-proc IdTableHasObjectAsKey(t: TIdTable, key: PIdObj): bool = 
-  var index = IdTableRawGet(t, key.id)
+proc idTableHasObjectAsKey(t: TIdTable, key: PIdObj): bool = 
+  var index = idTableRawGet(t, key.id)
   if index >= 0: result = t.data[index].key == key
   else: result = false
   
-proc IdTableGet(t: TIdTable, key: PIdObj): PObject = 
-  var index = IdTableRawGet(t, key.id)
+proc idTableGet(t: TIdTable, key: PIdObj): PObject = 
+  var index = idTableRawGet(t, key.id)
   if index >= 0: result = t.data[index].val
   else: result = nil
   
-proc IdTableGet(t: TIdTable, key: int): PObject = 
-  var index = IdTableRawGet(t, key)
+proc idTableGet(t: TIdTable, key: int): PObject = 
+  var index = idTableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = nil
 
@@ -723,7 +753,7 @@ iterator pairs*(t: TIdTable): tuple[key: int, value: PObject] =
     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: PObject) = 
   var h: THash
   h = key.id and high(data)
   while data[h].key != nil: 
@@ -733,33 +763,30 @@ 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: PObject) = 
   var 
     index: int
     n: TIdPairSeq
-  index = IdTableRawGet(t, key.id)
+  index = idTableRawGet(t, key.id)
   if index >= 0: 
     assert(t.data[index].key != nil)
     t.data[index].val = val
   else: 
     if mustRehash(len(t.data), t.counter): 
-      newSeq(n, len(t.data) * growthFactor)
+      newSeq(n, len(t.data) * GrowthFactor)
       for i in countup(0, high(t.data)): 
         if t.data[i].key != nil: 
-          IdTableRawInsert(n, t.data[i].key, t.data[i].val)
+          idTableRawInsert(n, t.data[i].key, t.data[i].val)
       assert(hasEmptySlot(n))
       swap(t.data, n)
-    IdTableRawInsert(t.data, key, val)
+    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: PObject] =
   for i in 0 .. high(t.data):
     if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
 
-proc writeIdNodeTable(t: TIdNodeTable) = 
-  nil
-
-proc IdNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int = 
+proc idNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int = 
   var h: THash
   h = key.id and high(t.data) # start with real hash value
   while t.data[h].key != nil:
@@ -768,17 +795,17 @@ proc IdNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int =
     h = nextTry(h, high(t.data))
   result = - 1
 
-proc IdNodeTableGet(t: TIdNodeTable, key: PIdObj): PNode = 
+proc idNodeTableGet(t: TIdNodeTable, key: PIdObj): PNode = 
   var index: int
-  index = IdNodeTableRawGet(t, key)
+  index = idNodeTableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = nil
 
-proc IdNodeTableGetLazy*(t: TIdNodeTable, key: PIdObj): PNode =
+proc idNodeTableGetLazy*(t: TIdNodeTable, key: PIdObj): PNode =
   if not isNil(t.data):
-    result = IdNodeTableGet(t, key)
+    result = idNodeTableGet(t, key)
   
-proc IdNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) = 
+proc idNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) = 
   var h: THash
   h = key.id and high(data)
   while data[h].key != nil: 
@@ -788,25 +815,25 @@ proc IdNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) =
   data[h].key = key
   data[h].val = val
 
-proc IdNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) = 
-  var index = IdNodeTableRawGet(t, key)
+proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) = 
+  var index = idNodeTableRawGet(t, key)
   if index >= 0: 
     assert(t.data[index].key != nil)
     t.data[index].val = val
   else: 
     if mustRehash(len(t.data), t.counter): 
       var n: TIdNodePairSeq
-      newSeq(n, len(t.data) * growthFactor)
+      newSeq(n, len(t.data) * GrowthFactor)
       for i in countup(0, high(t.data)): 
         if t.data[i].key != nil: 
-          IdNodeTableRawInsert(n, t.data[i].key, t.data[i].val)
+          idNodeTableRawInsert(n, t.data[i].key, t.data[i].val)
       swap(t.data, n)
-    IdNodeTableRawInsert(t.data, key, val)
+    idNodeTableRawInsert(t.data, key, val)
     inc(t.counter)
 
-proc IdNodeTablePutLazy*(t: var TIdNodeTable, key: PIdObj, val: PNode) =
+proc idNodeTablePutLazy*(t: var TIdNodeTable, key: PIdObj, val: PNode) =
   if isNil(t.data): initIdNodeTable(t)
-  IdNodeTablePut(t, key, val)
+  idNodeTablePut(t, key, val)
 
 iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] =
   for i in 0 .. high(t.data):
@@ -814,24 +841,23 @@ iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] =
 
 proc initIITable(x: var TIITable) = 
   x.counter = 0
-  newSeq(x.data, startSize)
-  for i in countup(0, startSize - 1): x.data[i].key = InvalidKey
+  newSeq(x.data, StartSize)
+  for i in countup(0, StartSize - 1): x.data[i].key = InvalidKey
   
-proc IITableRawGet(t: TIITable, key: int): int = 
+proc iiTableRawGet(t: TIITable, key: int): int = 
   var h: THash
   h = key and high(t.data)    # start with real hash value
   while t.data[h].key != InvalidKey: 
-    if (t.data[h].key == key): 
-      return h
+    if t.data[h].key == key: return h
     h = nextTry(h, high(t.data))
-  result = - 1
+  result = -1
 
-proc IITableGet(t: TIITable, key: int): int = 
-  var index = IITableRawGet(t, key)
+proc iiTableGet(t: TIITable, key: int): int = 
+  var index = iiTableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = InvalidKey
   
-proc IITableRawInsert(data: var TIIPairSeq, key, val: int) = 
+proc iiTableRawInsert(data: var TIIPairSeq, key, val: int) = 
   var h: THash
   h = key and high(data)
   while data[h].key != InvalidKey: 
@@ -841,19 +867,19 @@ proc IITableRawInsert(data: var TIIPairSeq, key, val: int) =
   data[h].key = key
   data[h].val = val
 
-proc IITablePut(t: var TIITable, key, val: int) = 
-  var index = IITableRawGet(t, key)
+proc iiTablePut(t: var TIITable, key, val: int) = 
+  var index = iiTableRawGet(t, key)
   if index >= 0: 
     assert(t.data[index].key != InvalidKey)
     t.data[index].val = val
   else: 
     if mustRehash(len(t.data), t.counter): 
       var n: TIIPairSeq
-      newSeq(n, len(t.data) * growthFactor)
+      newSeq(n, len(t.data) * GrowthFactor)
       for i in countup(0, high(n)): n[i].key = InvalidKey
       for i in countup(0, high(t.data)): 
         if t.data[i].key != InvalidKey: 
-          IITableRawInsert(n, t.data[i].key, t.data[i].val)
+          iiTableRawInsert(n, t.data[i].key, t.data[i].val)
       swap(t.data, n)
-    IITableRawInsert(t.data, key, val)
+    iiTableRawInsert(t.data, key, val)
     inc(t.counter)
diff --git a/compiler/babelcmd.nim b/compiler/babelcmd.nim
index b67a26040..7fa233732 100644
--- a/compiler/babelcmd.nim
+++ b/compiler/babelcmd.nim
@@ -13,7 +13,7 @@ import parseutils, strutils, strtabs, os, options, msgs, lists
 
 proc addPath*(path: string, info: TLineInfo) = 
   if not contains(options.searchPaths, path): 
-    lists.PrependStr(options.searchPaths, path)
+    lists.prependStr(options.searchPaths, path)
 
 proc versionSplitPos(s: string): int =
   result = s.len-2
@@ -45,9 +45,9 @@ proc `<.`(a, b: string): bool =
 
 proc addPackage(packages: PStringTable, p: string) =
   let x = versionSplitPos(p)
-  let name = p.subStr(0, x-1)
+  let name = p.substr(0, x-1)
   if x < p.len:
-    let version = p.subStr(x+1)
+    let version = p.substr(x+1)
     if packages[name] <. version:
       packages[name] = version
   else:
@@ -60,8 +60,8 @@ iterator chosen(packages: PStringTable): string =
 
 proc addBabelPath(p: string, info: TLineInfo) =
   if not contains(options.searchPaths, p):
-    if gVerbosity >= 1: Message(info, hintPath, p)
-    lists.PrependStr(options.lazyPaths, p)
+    if gVerbosity >= 1: message(info, hintPath, p)
+    lists.prependStr(options.lazyPaths, p)
 
 proc addPathWithNimFiles(p: string, info: TLineInfo) =
   proc hasNimFile(dir: string): bool =
diff --git a/compiler/bitsets.nim b/compiler/bitsets.nim
index dfb23b06d..740bdd5ef 100644
--- a/compiler/bitsets.nim
+++ b/compiler/bitsets.nim
@@ -18,53 +18,53 @@ type
 const 
   ElemSize* = sizeof(int8) * 8
 
-proc BitSetInit*(b: var TBitSet, length: int)
-proc BitSetUnion*(x: var TBitSet, y: TBitSet)
-proc BitSetDiff*(x: var TBitSet, y: TBitSet)
-proc BitSetSymDiff*(x: var TBitSet, y: TBitSet)
-proc BitSetIntersect*(x: var TBitSet, y: TBitSet)
-proc BitSetIncl*(x: var TBitSet, elem: BiggestInt)
-proc BitSetExcl*(x: var TBitSet, elem: BiggestInt)
-proc BitSetIn*(x: TBitSet, e: BiggestInt): bool
-proc BitSetEquals*(x, y: TBitSet): bool
-proc BitSetContains*(x, y: TBitSet): bool
+proc bitSetInit*(b: var TBitSet, length: int)
+proc bitSetUnion*(x: var TBitSet, y: TBitSet)
+proc bitSetDiff*(x: var TBitSet, y: TBitSet)
+proc bitSetSymDiff*(x: var TBitSet, y: TBitSet)
+proc bitSetIntersect*(x: var TBitSet, y: TBitSet)
+proc bitSetIncl*(x: var TBitSet, elem: BiggestInt)
+proc bitSetExcl*(x: var TBitSet, elem: BiggestInt)
+proc bitSetIn*(x: TBitSet, e: BiggestInt): bool
+proc bitSetEquals*(x, y: TBitSet): bool
+proc bitSetContains*(x, y: TBitSet): bool
 # implementation
 
-proc BitSetIn(x: TBitSet, e: BiggestInt): bool = 
+proc bitSetIn(x: TBitSet, e: BiggestInt): bool = 
   result = (x[int(e div ElemSize)] and toU8(int(1 shl (e mod ElemSize)))) !=
       toU8(0)
 
-proc BitSetIncl(x: var TBitSet, elem: BiggestInt) = 
+proc bitSetIncl(x: var TBitSet, elem: BiggestInt) = 
   assert(elem >= 0)
   x[int(elem div ElemSize)] = x[int(elem div ElemSize)] or
       toU8(int(1 shl (elem mod ElemSize)))
 
-proc BitSetExcl(x: var TBitSet, elem: BiggestInt) = 
+proc bitSetExcl(x: var TBitSet, elem: BiggestInt) = 
   x[int(elem div ElemSize)] = x[int(elem div ElemSize)] and
       not toU8(int(1 shl (elem mod ElemSize)))
 
-proc BitSetInit(b: var TBitSet, length: int) = 
+proc bitSetInit(b: var TBitSet, length: int) = 
   newSeq(b, length)
 
-proc BitSetUnion(x: var TBitSet, y: TBitSet) = 
+proc bitSetUnion(x: var TBitSet, y: TBitSet) = 
   for i in countup(0, high(x)): x[i] = x[i] or y[i]
   
-proc BitSetDiff(x: var TBitSet, y: TBitSet) = 
+proc bitSetDiff(x: var TBitSet, y: TBitSet) = 
   for i in countup(0, high(x)): x[i] = x[i] and not y[i]
   
-proc BitSetSymDiff(x: var TBitSet, y: TBitSet) = 
+proc bitSetSymDiff(x: var TBitSet, y: TBitSet) = 
   for i in countup(0, high(x)): x[i] = x[i] xor y[i]
   
-proc BitSetIntersect(x: var TBitSet, y: TBitSet) = 
+proc bitSetIntersect(x: var TBitSet, y: TBitSet) = 
   for i in countup(0, high(x)): x[i] = x[i] and y[i]
   
-proc BitSetEquals(x, y: TBitSet): bool = 
+proc bitSetEquals(x, y: TBitSet): bool = 
   for i in countup(0, high(x)): 
     if x[i] != y[i]: 
       return false
   result = true
 
-proc BitSetContains(x, y: TBitSet): bool = 
+proc bitSetContains(x, y: TBitSet): bool = 
   for i in countup(0, high(x)): 
     if (x[i] and not y[i]) != int8(0): 
       return false
diff --git a/compiler/c2nim/c2nim.nim b/compiler/c2nim/c2nim.nim
index df1e42f23..9b12b9e47 100644
--- a/compiler/c2nim/c2nim.nim
+++ b/compiler/c2nim/c2nim.nim
@@ -34,25 +34,36 @@ Options:
   --skipcomments         do not copy comments
   --ignoreRValueRefs     translate C++'s ``T&&`` to ``T`` instead ``of var T``
   --keepBodies           keep C++'s method bodies
+  --spliceHeader         parse and emit header before source file
   -v, --version          write c2nim's version
   -h, --help             show this help
 """
 
-proc main(infile, outfile: string, options: PParserOptions) =
-  var start = getTime()
-  var stream = LLStreamOpen(infile, fmRead)
+proc parse(infile: string, options: PParserOptions): PNode =
+  var stream = llStreamOpen(infile, fmRead)
   if stream == nil: rawMessage(errCannotOpenFile, infile)
   var p: TParser
   openParser(p, infile, stream, options)
-  var module = parseUnit(p)
+  result = parseUnit(p)
   closeParser(p)
-  renderModule(module, outfile)
+
+proc main(infile, outfile: string, options: PParserOptions, spliceHeader: bool) =
+  var start = getTime()
+  if spliceHeader and infile.splitFile.ext == ".c" and existsFile(infile.changeFileExt(".h")):
+    var header_module = parse(infile.changeFileExt(".h"), options)
+    var source_module = parse(infile, options)
+    for n in source_module:
+      addson(header_module, n)
+    renderModule(header_module, outfile)
+  else:
+    renderModule(parse(infile, options), outfile)
   rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start), 
                             formatSize(getTotalMem())])
 
 var
   infile = ""
   outfile = ""
+  spliceHeader = false
   parserOptions = newParserOptions()
 for kind, key, val in getopt():
   case kind
@@ -66,6 +77,7 @@ for kind, key, val in getopt():
       stdout.write(Version & "\n")
       quit(0)
     of "o", "out": outfile = val
+    of "spliceheader": spliceHeader = true
     else:
       if not parserOptions.setOption(key, val):
         stdout.writeln("[Error] unknown option: " & key)
@@ -77,4 +89,4 @@ else:
   if outfile.len == 0:
     outfile = changeFileExt(infile, "nim")
   infile = addFileExt(infile, "h")
-  main(infile, outfile, parserOptions)
+  main(infile, outfile, parserOptions, spliceHeader)
diff --git a/compiler/c2nim/clex.nim b/compiler/c2nim/clex.nim
index f949b97cb..3934eea63 100644
--- a/compiler/c2nim/clex.nim
+++ b/compiler/c2nim/clex.nim
@@ -103,7 +103,7 @@ type
     inDirective: bool
   
 proc getTok*(L: var TLexer, tok: var TToken)
-proc PrintTok*(tok: TToken)
+proc printTok*(tok: TToken)
 proc `$`*(tok: TToken): string
 # implementation
 
@@ -138,7 +138,7 @@ proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
   var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart)
   msgs.GlobalError(info, msg, arg)
 
-proc TokKindToStr*(k: TTokKind): string =
+proc tokKindToStr*(k: TTokKind): string =
   case k
   of pxEof: result = "[EOF]"
   of pxInvalid: result = "[invalid]"
@@ -211,9 +211,9 @@ proc `$`(tok: TToken): string =
   of pxSymbol, pxInvalid, pxStarComment, pxLineComment, pxStrLit: result = tok.s
   of pxIntLit, pxInt64Lit: result = $tok.iNumber
   of pxFloatLit: result = $tok.fNumber
-  else: result = TokKindToStr(tok.xkind)
+  else: result = tokKindToStr(tok.xkind)
   
-proc PrintTok(tok: TToken) = 
+proc printTok(tok: TToken) = 
   writeln(stdout, $tok)
   
 proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = 
@@ -223,12 +223,12 @@ proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
   while true: 
     if buf[pos] in chars: 
       add(tok.s, buf[pos])
-      Inc(pos)
+      inc(pos)
     else: 
       break 
     if buf[pos] == '_': 
       add(tok.s, '_')
-      Inc(pos)
+      inc(pos)
   L.bufPos = pos
 
 proc isFloatLiteral(s: string): bool = 
@@ -239,7 +239,7 @@ proc isFloatLiteral(s: string): bool =
 proc getNumber2(L: var TLexer, tok: var TToken) = 
   var pos = L.bufpos + 2 # skip 0b
   tok.base = base2
-  var xi: biggestInt = 0
+  var xi: BiggestInt = 0
   var bits = 0
   while true: 
     case L.buf[pos]
@@ -264,7 +264,7 @@ proc getNumber2(L: var TLexer, tok: var TToken) =
 proc getNumber8(L: var TLexer, tok: var TToken) = 
   var pos = L.bufpos + 1 # skip 0
   tok.base = base8
-  var xi: biggestInt = 0
+  var xi: BiggestInt = 0
   var bits = 0
   while true: 
     case L.buf[pos]
@@ -289,7 +289,7 @@ proc getNumber8(L: var TLexer, tok: var TToken) =
 proc getNumber16(L: var TLexer, tok: var TToken) = 
   var pos = L.bufpos + 2          # skip 0x
   tok.base = base16
-  var xi: biggestInt = 0
+  var xi: BiggestInt = 0
   var bits = 0
   while true: 
     case L.buf[pos]
@@ -315,19 +315,34 @@ proc getNumber16(L: var TLexer, tok: var TToken) =
   else: tok.xkind = pxIntLit
   L.bufpos = pos
 
+proc getFloating(L: var TLexer, tok: var TToken) =
+  matchUnderscoreChars(L, tok, {'0'..'9'})
+  if L.buf[L.bufpos] in {'e', 'E'}:
+    add(tok.s, L.buf[L.bufpos])
+    inc(L.bufpos)
+    if L.buf[L.bufpos] in {'+', '-'}:
+      add(tok.s, L.buf[L.bufpos])
+      inc(L.bufpos)
+    matchUnderscoreChars(L, tok, {'0'..'9'})
+
 proc getNumber(L: var TLexer, tok: var TToken) = 
   tok.base = base10
-  matchUnderscoreChars(L, tok, {'0'..'9'})
-  if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}): 
-    add(tok.s, '.')
+  if L.buf[L.bufpos] == '.':
+    add(tok.s, "0.")
     inc(L.bufpos)
-    matchUnderscoreChars(L, tok, {'e', 'E', '+', '-', '0'..'9'})
+    getFloating(L, tok)
+  else:
+    matchUnderscoreChars(L, tok, {'0'..'9'})
+    if L.buf[L.bufpos] == '.':
+      add(tok.s, '.')
+      inc(L.bufpos)
+      getFloating(L, tok)
   try: 
     if isFloatLiteral(tok.s): 
       tok.fnumber = parseFloat(tok.s)
       tok.xkind = pxFloatLit
     else: 
-      tok.iNumber = ParseInt(tok.s)
+      tok.iNumber = parseInt(tok.s)
       if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)): 
         tok.xkind = pxInt64Lit
       else: 
@@ -339,10 +354,10 @@ proc getNumber(L: var TLexer, tok: var TToken) =
   # ignore type suffix:
   while L.buf[L.bufpos] in {'A'..'Z', 'a'..'z'}: inc(L.bufpos)
   
-proc HandleCRLF(L: var TLexer, pos: int): int = 
+proc handleCRLF(L: var TLexer, pos: int): int = 
   case L.buf[pos]
-  of CR: result = nimlexbase.HandleCR(L, pos)
-  of LF: result = nimlexbase.HandleLF(L, pos)
+  of CR: result = nimlexbase.handleCR(L, pos)
+  of LF: result = nimlexbase.handleLF(L, pos)
   else: result = pos
   
 proc escape(L: var TLexer, tok: var TToken, allowEmpty=false) = 
@@ -382,6 +397,23 @@ proc escape(L: var TLexer, tok: var TToken, allowEmpty=false) =
         xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0'))
         inc(L.bufpos)
     add(tok.s, chr(xi))
+  of 'x':
+    var xi = 0
+    inc(L.bufpos)
+    while true: 
+      case L.buf[L.bufpos]
+      of '0'..'9': 
+        xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('0'))
+        inc(L.bufpos)
+      of 'a'..'f': 
+        xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('a') + 10)
+        inc(L.bufpos)
+      of 'A'..'F': 
+        xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('A') + 10)
+        inc(L.bufpos)
+      else:
+        break 
+    add(tok.s, chr(xi))
   elif not allowEmpty:
     lexMessage(L, errInvalidCharacterConstant)
   
@@ -405,7 +437,7 @@ proc getString(L: var TLexer, tok: var TToken) =
   while true: 
     case buf[pos]
     of '\"': 
-      Inc(pos)
+      inc(pos)
       break
     of CR: 
       pos = nimlexbase.HandleCR(L, pos)
@@ -427,7 +459,7 @@ proc getString(L: var TLexer, tok: var TToken) =
       pos = L.bufpos
     else: 
       add(tok.s, buf[pos])
-      Inc(pos)
+      inc(pos)
   L.bufpos = pos
   tok.xkind = pxStrLit
 
@@ -438,7 +470,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
     var c = buf[pos]
     if c notin SymChars: break
     add(tok.s, c)
-    Inc(pos)
+    inc(pos)
   L.bufpos = pos
   tok.xkind = pxSymbol
 
@@ -475,7 +507,7 @@ proc scanStarComment(L: var TLexer, tok: var TToken) =
   while true: 
     case buf[pos]
     of CR, LF: 
-      pos = HandleCRLF(L, pos)
+      pos = handleCRLF(L, pos)
       buf = L.buf
       add(tok.s, "\n#")
       # skip annoying stars as line prefix: (eg.
@@ -511,12 +543,12 @@ proc skip(L: var TLexer, tok: var TToken) =
       if L.inDirective:
         while buf[pos] in {' ', '\t'}: inc(pos)
         if buf[pos] in {CR, LF}:
-          pos = HandleCRLF(L, pos)
+          pos = handleCRLF(L, pos)
           buf = L.buf
     of ' ', Tabulator: 
-      Inc(pos)                # newline is special:
+      inc(pos)                # newline is special:
     of CR, LF: 
-      pos = HandleCRLF(L, pos)
+      pos = handleCRLF(L, pos)
       buf = L.buf
       if L.inDirective:
         tok.xkind = pxNewLine
@@ -559,13 +591,13 @@ proc getTok(L: var TLexer, tok: var TToken) =
     of 'b', 'B': getNumber2(L, tok)
     of '1'..'7': getNumber8(L, tok)
     else: getNumber(L, tok)
-  elif c in {'1'..'9'}: 
+  elif c in {'1'..'9'} or (c == '.' and L.buf[L.bufpos+1] in {'0'..'9'}): 
     getNumber(L, tok)
   else: 
     case c
     of ';': 
       tok.xkind = pxSemicolon
-      Inc(L.bufpos)
+      inc(L.bufpos)
     of '/': 
       if L.buf[L.bufpos + 1] == '/': 
         scanLineComment(L, tok)
@@ -580,9 +612,9 @@ proc getTok(L: var TLexer, tok: var TToken) =
         inc(L.bufpos)
     of ',': 
       tok.xkind = pxComma
-      Inc(L.bufpos)
+      inc(L.bufpos)
     of '(': 
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxParLe
     of '*': 
       inc(L.bufpos)
@@ -592,13 +624,13 @@ proc getTok(L: var TLexer, tok: var TToken) =
       else:
         tok.xkind = pxStar
     of ')': 
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxParRi
     of '[': 
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxBracketLe
     of ']': 
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxBracketRi
     of '.': 
       inc(L.bufpos)
@@ -608,10 +640,10 @@ proc getTok(L: var TLexer, tok: var TToken) =
       else: 
         tok.xkind = pxDot
     of '{': 
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxCurlyLe
     of '}': 
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxCurlyRi
     of '+': 
       inc(L.bufpos)
@@ -752,4 +784,4 @@ proc getTok(L: var TLexer, tok: var TToken) =
       tok.s = $c
       tok.xkind = pxInvalid
       lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
-      Inc(L.bufpos)
+      inc(L.bufpos)
diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim
index 44be556db..52d50ca39 100644
--- a/compiler/c2nim/cparse.nim
+++ b/compiler/c2nim/cparse.nim
@@ -61,6 +61,8 @@ type
   
   TReplaceTuple* = array[0..1, string]
 
+  ERetryParsing = object of ESynch
+
 proc newParserOptions*(): PParserOptions = 
   new(result)
   result.prefixes = @[]
@@ -93,16 +95,16 @@ proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool =
   of "class": parserOptions.classes[val] = "true"
   else: result = false
 
-proc ParseUnit*(p: var TParser): PNode
+proc parseUnit*(p: var TParser): PNode
 proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
                  options = newParserOptions())
 proc closeParser*(p: var TParser)
 
 # implementation
 
-proc OpenParser(p: var TParser, filename: string, 
+proc openParser(p: var TParser, filename: string, 
                 inputStream: PLLStream, options = newParserOptions()) = 
-  OpenLexer(p.lex, filename, inputStream)
+  openLexer(p.lex, filename, inputStream)
   p.options = options
   p.backtrack = @[]
   new(p.tok)
@@ -111,7 +113,7 @@ proc parMessage(p: TParser, msg: TMsgKind, arg = "") =
   #assert false
   lexMessage(p.lex, msg, arg)
 
-proc CloseParser(p: var TParser) = CloseLexer(p.lex)
+proc closeParser(p: var TParser) = closeLexer(p.lex)
 proc saveContext(p: var TParser) = p.backtrack.add(p.tok)
 proc closeContext(p: var TParser) = discard p.backtrack.pop()
 proc backtrackContext(p: var TParser) = p.tok = p.backtrack.pop()
@@ -145,7 +147,7 @@ proc findMacro(p: TParser): int =
 
 proc rawEat(p: var TParser, xkind: TTokKind) = 
   if p.tok.xkind == xkind: rawGetTok(p)
-  else: parMessage(p, errTokenExpected, TokKindToStr(xkind))
+  else: parMessage(p, errTokenExpected, tokKindToStr(xkind))
 
 proc parseMacroArguments(p: var TParser): seq[seq[ref TToken]] = 
   result = @[]
@@ -228,7 +230,7 @@ proc skipComAux(p: var TParser, n: PNode) =
   getTok(p)
 
 proc skipCom(p: var TParser, n: PNode) = 
-  while p.tok.xkind in {pxLineComment, pxStarComment}: skipcomAux(p, n)
+  while p.tok.xkind in {pxLineComment, pxStarComment}: skipComAux(p, n)
 
 proc skipStarCom(p: var TParser, n: PNode) = 
   while p.tok.xkind == pxStarComment: skipComAux(p, n)
@@ -242,11 +244,11 @@ proc expectIdent(p: TParser) =
   
 proc eat(p: var TParser, xkind: TTokKind, n: PNode) = 
   if p.tok.xkind == xkind: getTok(p, n)
-  else: parMessage(p, errTokenExpected, TokKindToStr(xkind))
+  else: parMessage(p, errTokenExpected, tokKindToStr(xkind))
   
 proc eat(p: var TParser, xkind: TTokKind) = 
   if p.tok.xkind == xkind: getTok(p)
-  else: parMessage(p, errTokenExpected, TokKindToStr(xkind))
+  else: parMessage(p, errTokenExpected, tokKindToStr(xkind))
   
 proc eat(p: var TParser, tok: string, n: PNode) = 
   if p.tok.s == tok: getTok(p, n)
@@ -420,9 +422,9 @@ proc markTypeIdent(p: var TParser, typ: PNode) =
 # avoids to build a symbol table, which can't be done reliably anyway for our
 # purposes.
 
-proc expression(p: var TParser): PNode
-proc constantExpression(p: var TParser): PNode
-proc assignmentExpression(p: var TParser): PNode
+proc expression(p: var TParser, rbp: int = 0): PNode
+proc constantExpression(p: var TParser): PNode = expression(p, 40)
+proc assignmentExpression(p: var TParser): PNode = expression(p, 30)
 proc compoundStatement(p: var TParser): PNode
 proc statement(p: var TParser): PNode
 
@@ -538,7 +540,7 @@ proc typeAtom(p: var TParser): PNode =
       if p.tok.s == "unsigned":
         isUnsigned = true
       elif p.tok.s == "signed" or p.tok.s == "int":
-        nil
+        discard
       else:
         add(x, p.tok.s)
       getTok(p, nil)
@@ -605,7 +607,7 @@ proc addPragmas(father, pragmas: PNode) =
 proc addReturnType(params, rettyp: PNode) =
   if rettyp == nil: addSon(params, ast.emptyNode)
   elif rettyp.kind != nkNilLit: addSon(params, rettyp)
-  else: addson(params, ast.emptyNode)
+  else: addSon(params, ast.emptyNode)
 
 proc parseFormalParams(p: var TParser, params, pragmas: PNode)
 
@@ -622,10 +624,11 @@ proc parseTypeSuffix(p: var TParser, typ: PNode): PNode =
         # array type:
         result = newNodeP(nkBracketExpr, p)
         addSon(result, newIdentNodeP("array", p))
-        var r = newNodeP(nkRange, p)
-        addSon(r, newIntNodeP(nkIntLit, 0, p))
-        addSon(r, newBinary("-", index, newIntNodeP(nkIntLit, 1, p), p))
-        addSon(result, r)
+        #var r = newNodeP(nkRange, p)
+        #addSon(r, newIntNodeP(nkIntLit, 0, p))
+        #addSon(r, newBinary("-", index, newIntNodeP(nkIntLit, 1, p), p))
+        #addSon(result, r)
+        addSon(result, index)
         addSon(result, tmp)
       else:
         # pointer type:
@@ -651,6 +654,22 @@ proc parseTypeSuffix(p: var TParser, typ: PNode): PNode =
 proc typeDesc(p: var TParser): PNode = 
   result = pointer(p, typeAtom(p))
 
+proc abstractDeclarator(p: var TParser, a: PNode): PNode
+
+proc directAbstractDeclarator(p: var TParser, a: PNode): PNode =
+  if p.tok.xkind == pxParLe:
+    getTok(p, a)
+    if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp}:
+      result = abstractDeclarator(p, a)
+      eat(p, pxParRi, result)
+  return parseTypeSuffix(p, a)
+
+proc abstractDeclarator(p: var TParser, a: PNode): PNode =
+  return directAbstractDeclarator(p, pointer(p, a))
+
+proc typeName(p: var TParser): PNode =
+  return abstractDeclarator(p, typeAtom(p))
+
 proc parseField(p: var TParser, kind: TNodeKind): PNode =
   if p.tok.xkind == pxParLe: 
     getTok(p, nil)
@@ -663,11 +682,6 @@ proc parseField(p: var TParser, kind: TNodeKind): PNode =
     else: result = mangledIdent(p.tok.s, p)
     getTok(p, result)
 
-proc takeOnlyFirstField(p: TParser, isUnion: bool): bool =
-  # if we generate an interface to a header file, *all* fields can be 
-  # generated:
-  result = isUnion and p.options.header.len == 0
-
 proc parseStructBody(p: var TParser, isUnion: bool,
                      kind: TNodeKind = nkRecList): PNode =
   result = newNodeP(kind, p)
@@ -680,8 +694,7 @@ proc parseStructBody(p: var TParser, isUnion: bool,
       var i = parseField(p, kind)
       t = parseTypeSuffix(p, t)
       addSon(def, i, t, ast.emptyNode)
-      if not takeOnlyFirstField(p, isUnion) or sonsLen(result) < 1: 
-        addSon(result, def)
+      addSon(result, def)
       if p.tok.xkind != pxComma: break
       getTok(p, def)
     eat(p, pxSemicolon, lastSon(result))
@@ -690,44 +703,67 @@ proc parseStructBody(p: var TParser, isUnion: bool,
 proc structPragmas(p: TParser, name: PNode, origName: string): PNode = 
   assert name.kind == nkIdent
   result = newNodeP(nkPragmaExpr, p)
-  addson(result, exportSym(p, name, origName))
-  var pragmas = newNodep(nkPragma, p)
-  addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
+  addSon(result, exportSym(p, name, origName))
+  var pragmas = newNodeP(nkPragma, p)
+  #addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
   if p.options.header.len > 0:
     addSon(pragmas, newIdentStrLitPair("importc", origName, p),
                     newIdentStrLitPair("header", p.options.header, p))
-  addSon(result, pragmas)
+  if pragmas.len > 0: addSon(result, pragmas)
+  else: addSon(result, ast.emptyNode)
 
 proc enumPragmas(p: TParser, name: PNode): PNode =
   result = newNodeP(nkPragmaExpr, p)
-  addson(result, name)
-  var pragmas = newNodep(nkPragma, p)
+  addSon(result, name)
+  var pragmas = newNodeP(nkPragma, p)
   var e = newNodeP(nkExprColonExpr, p)
   # HACK: sizeof(cint) should be constructed as AST
   addSon(e, newIdentNodeP("size", p), newIdentNodeP("sizeof(cint)", p))
   addSon(pragmas, e)
   addSon(result, pragmas)
 
-proc parseStruct(p: var TParser, isUnion: bool): PNode = 
+proc parseStruct(p: var TParser, isUnion: bool): PNode =
   result = newNodeP(nkObjectTy, p)
-  addSon(result, ast.emptyNode, ast.emptyNode) # no pragmas, no inheritance 
+  var pragmas = ast.emptyNode
+  if isUnion:
+    pragmas = newNodeP(nkPragma, p)
+    addSon(pragmas, newIdentNodeP("union", p))
+  addSon(result, pragmas, ast.emptyNode) # no inheritance 
   if p.tok.xkind == pxCurlyLe:
     addSon(result, parseStructBody(p, isUnion))
   else: 
     addSon(result, newNodeP(nkRecList, p))
 
+proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode
+
+proc directDeclarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
+  case p.tok.xkind
+  of pxSymbol:
+    ident[] = skipIdent(p)
+  of pxParLe:
+    getTok(p, a)
+    if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp, pxSymbol}:
+      result = declarator(p, a, ident)
+      eat(p, pxParRi, result)
+  else:
+    discard
+  return parseTypeSuffix(p, a)
+
+proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
+  return directDeclarator(p, pointer(p, a), ident)
+
+# parameter-declaration
+#   declaration-specifiers declarator
+#   declaration-specifiers asbtract-declarator(opt)
 proc parseParam(p: var TParser, params: PNode) = 
   var typ = typeDesc(p)
   # support for ``(void)`` parameter list: 
   if typ.kind == nkNilLit and p.tok.xkind == pxParRi: return
   var name: PNode
-  if p.tok.xkind == pxSymbol: 
-    name = skipIdent(p)
-  else:
-    # generate a name for the formal parameter:
+  typ = declarator(p, typ, addr name)
+  if name == nil:
     var idx = sonsLen(params)+1
     name = newIdentNodeP("a" & $idx, p)
-  typ = parseTypeSuffix(p, typ)
   var x = newNodeP(nkIdentDefs, p)
   addSon(x, name, typ)
   if p.tok.xkind == pxAsgn: 
@@ -1045,7 +1081,7 @@ proc declaration(p: var TParser): PNode =
     of pxSemicolon: 
       getTok(p)
       addSon(result, ast.emptyNode) # nobody
-      if p.scopeCounter == 0: DoImport(origName, pragmas, p)
+      if p.scopeCounter == 0: doImport(origName, pragmas, p)
     of pxCurlyLe:
       addSon(result, compoundStatement(p))
     else:
@@ -1129,229 +1165,32 @@ proc enumSpecifier(p: var TParser): PNode =
 
 proc setBaseFlags(n: PNode, base: TNumericalBase) = 
   case base
-  of base10: nil
+  of base10: discard
   of base2: incl(n.flags, nfBase2)
   of base8: incl(n.flags, nfBase8)
   of base16: incl(n.flags, nfBase16)
 
-proc unaryExpression(p: var TParser): PNode
-
-proc isDefinitelyAType(p: var TParser): bool = 
-  var starFound = false
-  var words = 0
-  while true:
-    case p.tok.xkind 
-    of pxSymbol:
-      if declKeyword(p, p.tok.s): return true
-      elif starFound: return false
-      else: inc(words)
-    of pxStar, pxAmp, pxAmpAmp:
-      starFound = true
-    of pxParRi: return words == 0 or words > 1 or starFound
-    else: return false
-    getTok(p, nil)
-
-proc castExpression(p: var TParser): PNode = 
-  if p.tok.xkind == pxParLe: 
-    saveContext(p)
-    result = newNodeP(nkCast, p)
-    getTok(p, result)
-    var t = isDefinitelyAType(p)
-    backtrackContext(p)
-    if t:
-      eat(p, pxParLe, result)
-      var a = typeDesc(p)
-      eat(p, pxParRi, result)
-      addSon(result, a)
-      addSon(result, castExpression(p))
-    else: 
-      # else it is just an expression in ():
-      result = newNodeP(nkPar, p)
-      eat(p, pxParLe, result)
-      addSon(result, expression(p))
-      if p.tok.xkind != pxParRi:  
-        # ugh, it is a cast, even though it does not look like one:
-        result.kind = nkCast
-        addSon(result, castExpression(p))
-      eat(p, pxParRi, result)
-      #result = unaryExpression(p)
-  else:
-    result = unaryExpression(p)
-  
-proc primaryExpression(p: var TParser): PNode = 
-  case p.tok.xkind
-  of pxSymbol: 
-    if p.tok.s == "NULL": 
-      result = newNodeP(nkNilLit, p)
-    else: 
-      result = mangledIdent(p.tok.s, p)
-    getTok(p, result)
-    result = optScope(p, result)
-  of pxIntLit: 
-    result = newIntNodeP(nkIntLit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p, result)
-  of pxInt64Lit: 
-    result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p, result)
-  of pxFloatLit: 
-    result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p, result)
-  of pxStrLit: 
-    # Ansi C allows implicit string literal concatenations:
-    result = newStrNodeP(nkStrLit, p.tok.s, p)
-    getTok(p, result)
-    while p.tok.xkind == pxStrLit:
-      add(result.strVal, p.tok.s)
-      getTok(p, result)
-  of pxCharLit:
-    result = newIntNodeP(nkCharLit, ord(p.tok.s[0]), p)
-    getTok(p, result)
-  of pxParLe:
-    result = castExpression(p)
-  else:
-    result = ast.emptyNode
-
-proc multiplicativeExpression(p: var TParser): PNode = 
-  result = castExpression(p)
-  while true:
-    case p.tok.xkind
-    of pxStar:
-      var a = result
-      result = newNodeP(nkInfix, p)
-      addSon(result, newIdentNodeP("*", p), a)
-      getTok(p, result)
-      var b = castExpression(p)
-      addSon(result, b)
-    of pxSlash:
-      var a = result
-      result = newNodeP(nkInfix, p)
-      addSon(result, newIdentNodeP("div", p), a)
-      getTok(p, result)
-      var b = castExpression(p)
-      addSon(result, b)
-    of pxMod:
-      var a = result
-      result = newNodeP(nkInfix, p)
-      addSon(result, newIdentNodeP("mod", p), a)
-      getTok(p, result)
-      var b = castExpression(p)
-      addSon(result, b)
-    else: break 
-
-proc additiveExpression(p: var TParser): PNode = 
-  result = multiplicativeExpression(p)
-  while true:
-    case p.tok.xkind
-    of pxPlus:
-      var a = result
-      result = newNodeP(nkInfix, p)
-      addSon(result, newIdentNodeP("+", p), a)
-      getTok(p, result)
-      var b = multiplicativeExpression(p)
-      addSon(result, b)
-    of pxMinus:
-      var a = result
-      result = newNodeP(nkInfix, p)
-      addSon(result, newIdentNodeP("-", p), a)
-      getTok(p, result)
-      var b = multiplicativeExpression(p)
-      addSon(result, b)
-    else: break 
-  
-proc incdec(p: var TParser, opr: string): PNode = 
-  result = newNodeP(nkCall, p)
-  addSon(result, newIdentNodeP(opr, p))
-  gettok(p, result)
-  addSon(result, unaryExpression(p))
-
-proc unaryOp(p: var TParser, kind: TNodeKind): PNode = 
-  result = newNodeP(kind, p)
-  getTok(p, result)
-  addSon(result, castExpression(p))
-
-proc prefixCall(p: var TParser, opr: string): PNode = 
-  result = newNodeP(nkPrefix, p)
-  addSon(result, newIdentNodeP(opr, p))
-  gettok(p, result)
-  addSon(result, castExpression(p))
-
-proc postfixExpression(p: var TParser): PNode = 
-  result = primaryExpression(p)
-  while true:
-    case p.tok.xkind
-    of pxBracketLe:
-      var a = result
-      result = newNodeP(nkBracketExpr, p)
-      addSon(result, a)
-      getTok(p, result)
-      var b = expression(p)
-      addSon(result, b)
-      eat(p, pxBracketRi, result)
-    of pxParLe:
-      var a = result
-      result = newNodeP(nkCall, p)
-      addSon(result, a)
-      getTok(p, result)
-      if p.tok.xkind != pxParRi:
-        a = assignmentExpression(p)
-        addSon(result, a)
-        while p.tok.xkind == pxComma:
-          getTok(p, a)
-          a = assignmentExpression(p)
-          addSon(result, a)
-      eat(p, pxParRi, result)
-    of pxDot, pxArrow:
-      var a = result
-      result = newNodeP(nkDotExpr, p)
-      addSon(result, a)
-      getTok(p, result)
-      addSon(result, skipIdent(p))
-    of pxPlusPlus:
-      var a = result
-      result = newNodeP(nkCall, p)
-      addSon(result, newIdentNodeP("inc", p))
-      gettok(p, result)
-      addSon(result, a)
-    of pxMinusMinus:
-      var a = result
-      result = newNodeP(nkCall, p)
-      addSon(result, newIdentNodeP("dec", p))
-      gettok(p, result)
-      addSon(result, a)
-    of pxLt:
-      if isTemplateAngleBracket(p):
-        result = optAngle(p, result)
-      else: break
-    else: break
-
-proc unaryExpression(p: var TParser): PNode =
-  case p.tok.xkind
-  of pxPlusPlus: result = incdec(p, "inc")
-  of pxMinusMinus: result = incdec(p, "dec")
-  of pxAmp: result = unaryOp(p, nkAddr)
-  of pxStar: result = unaryOp(p, nkBracketExpr)
-  of pxPlus: result = prefixCall(p, "+")
-  of pxMinus: result = prefixCall(p, "-")
-  of pxTilde: result = prefixCall(p, "not")
-  of pxNot: result = prefixCall(p, "not")
+proc startExpression(p : var TParser, tok : TToken) : PNode =
+  #echo "nud ", $tok
+  case tok.xkind:
   of pxSymbol:
-    if p.tok.s == "sizeof": 
+    if tok.s == "NULL":
+      result = newNodeP(nkNilLit, p)
+    elif tok.s == "sizeof":
       result = newNodeP(nkCall, p)
       addSon(result, newIdentNodeP("sizeof", p))
-      getTok(p, result)
-      if p.tok.xkind == pxParLe:
-        getTok(p, result)
-        addSon(result, typeDesc(p))
-        eat(p, pxParRi, result)
-      else:
-        addSon(result, unaryExpression(p))
-    elif p.tok.s == "new" or p.tok.s == "delete" and pfCpp in p.options.flags:
-      var opr = p.tok.s
+      saveContext(p)
+      try:
+        addSon(result, expression(p, 139))
+        closeContext(p)
+      except ERetryParsing:
+        backtrackContext(p)
+        eat(p, pxParLe)
+        addSon(result, typeName(p))
+        eat(p, pxParRi)
+    elif (tok.s == "new" or tok.s == "delete") and pfCpp in p.options.flags:
+      var opr = tok.s
       result = newNodeP(nkCall, p)
-      getTok(p, result)
       if p.tok.xkind == pxBracketLe:
         getTok(p)
         eat(p, pxBracketRi)
@@ -1362,148 +1201,270 @@ proc unaryExpression(p: var TParser): PNode =
         addSon(result, typeDesc(p))
         eat(p, pxParRi, result)
       else:
-        addSon(result, unaryExpression(p))
+        addSon(result, expression(p, 139))
     else:
-      result = postfixExpression(p)
-  else: result = postfixExpression(p)
-
-proc expression(p: var TParser): PNode = 
-  # we cannot support C's ``,`` operator
-  result = assignmentExpression(p)
-  if p.tok.xkind == pxComma:
-    getTok(p, result)
-    parMessage(p, errOperatorExpected, ",")
-    
-proc conditionalExpression(p: var TParser): PNode
-
-proc constantExpression(p: var TParser): PNode = 
-  result = conditionalExpression(p)
-
-proc lvalue(p: var TParser): PNode = 
-  result = unaryExpression(p)
-
-proc asgnExpr(p: var TParser, opr: string, a: PNode): PNode = 
-  closeContext(p)
-  getTok(p, a)
-  var b = assignmentExpression(p)
-  result = newNodeP(nkAsgn, p)
-  addSon(result, a, newBinary(opr, copyTree(a), b, p))
-  
-proc incdec(p: var TParser, opr: string, a: PNode): PNode =
-  closeContext(p)
-  getTok(p, a)
-  var b = assignmentExpression(p)
-  result = newNodeP(nkCall, p)
-  addSon(result, newIdentNodeP(getIdent(opr), p), a, b)
-  
-proc assignmentExpression(p: var TParser): PNode = 
-  saveContext(p)
-  var a = lvalue(p)
-  case p.tok.xkind 
-  of pxAsgn:
-    closeContext(p)
-    getTok(p, a)
-    var b = assignmentExpression(p)
+      result = mangledIdent(tok.s, p)
+      result = optScope(p, result)
+      result = optAngle(p, result)
+  of pxIntLit: 
+    result = newIntNodeP(nkIntLit, tok.iNumber, p)
+    setBaseFlags(result, tok.base)
+  of pxInt64Lit: 
+    result = newIntNodeP(nkInt64Lit, tok.iNumber, p)
+    setBaseFlags(result, tok.base)
+  of pxFloatLit: 
+    result = newFloatNodeP(nkFloatLit, tok.fNumber, p)
+    setBaseFlags(result, tok.base)
+  of pxStrLit: 
+    result = newStrNodeP(nkStrLit, tok.s, p)
+    while p.tok.xkind == pxStrLit:
+      add(result.strVal, p.tok.s)
+      getTok(p, result)
+  of pxCharLit:
+    result = newIntNodeP(nkCharLit, ord(tok.s[0]), p)
+  of pxParLe:
+    try:
+      saveContext(p)
+      result = newNodeP(nkPar, p)
+      addSon(result, expression(p, 0))
+      if p.tok.xkind != pxParRi:
+        raise newException(ERetryParsing, "expected a ')'")
+      getTok(p, result)
+      if p.tok.xkind in {pxSymbol, pxIntLit, pxFloatLit, pxStrLit, pxCharLit}:
+        raise newException(ERetryParsing, "expected a non literal token")
+      closeContext(p)
+    except ERetryParsing:
+      backtrackContext(p)
+      result = newNodeP(nkCast, p)
+      addSon(result, typeName(p))
+      eat(p, pxParRi, result)
+      addSon(result, expression(p, 139))
+  of pxPlusPlus:
+    result = newNodeP(nkCall, p)
+    addSon(result, newIdentNodeP("inc", p))
+    addSon(result, expression(p, 139))
+  of pxMinusMinus:
+    result = newNodeP(nkCall, p)
+    addSon(result, newIdentNodeP("dec", p))
+    addSon(result, expression(p, 139))
+  of pxAmp:
+    result = newNodeP(nkAddr, p)
+    addSon(result, expression(p, 139))
+  of pxStar:
+    result = newNodeP(nkBracketExpr, p)
+    addSon(result, expression(p, 139))
+  of pxPlus:
+    result = newNodeP(nkPrefix, p)
+    addSon(result, newIdentNodeP("+", p))
+    addSon(result, expression(p, 139))
+  of pxMinus:
+    result = newNodeP(nkPrefix, p)
+    addSon(result, newIdentNodeP("-", p))
+    addSon(result, expression(p, 139))
+  of pxTilde:
+    result = newNodeP(nkPrefix, p)
+    addSon(result, newIdentNodeP("not", p))
+    addSon(result, expression(p, 139))
+  of pxNot:
+    result = newNodeP(nkPrefix, p)
+    addSon(result, newIdentNodeP("not", p))
+    addSon(result, expression(p, 139))
+  else:
+    # probably from a failed sub expression attempt, try a type cast
+    raise newException(ERetryParsing, "did not expect " & $tok)
+
+proc leftBindingPower(p : var TParser, tok : ref TToken) : int =
+  #echo "lbp ", $tok[]
+  case tok.xkind:
+  of pxComma:
+    return 10
+    # throw == 20
+  of pxAsgn, pxPlusAsgn, pxMinusAsgn, pxStarAsgn, pxSlashAsgn, pxModAsgn, 
+     pxShlAsgn, pxShrAsgn, pxAmpAsgn, pxHatAsgn, pxBarAsgn:
+    return 30
+  of pxConditional:
+    return 40
+  of pxBarBar:
+    return 50
+  of pxAmpAmp:
+    return 60
+  of pxBar:
+    return 70
+  of pxHat:
+    return 80
+  of pxAmp:
+    return 90
+  of pxEquals, pxNeq:
+    return 100
+  of pxLt, pxLe, pxGt, pxGe:
+    return 110
+  of pxShl, pxShr:
+    return 120
+  of pxPlus, pxMinus:
+    return 130
+  of pxStar, pxSlash, pxMod:
+    return 140
+    # .* ->* == 150
+  of pxPlusPlus, pxMinusMinus, pxParLe, pxDot, pxArrow, pxBracketLe:
+    return 160
+    # :: == 170
+  else:
+    return 0
+
+proc buildStmtList(a: PNode): PNode
+
+proc leftExpression(p : var TParser, tok : TToken, left : PNode) : PNode =
+  #echo "led ", $tok
+  case tok.xkind:
+  of pxComma: # 10
+    # not supported as an expression, turns into a statement list
+    result = buildStmtList(left)
+    addSon(result, expression(p, 0))
+    # throw == 20
+  of pxAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    addSon(result, left, expression(p, 29))
+  of pxPlusAsgn: # 30
+    result = newNodeP(nkCall, p)
+    addSon(result, newIdentNodeP(getIdent("inc"), p), left, expression(p, 29))
+  of pxMinusAsgn: # 30
+    result = newNodeP(nkCall, p)
+    addSon(result, newIdentNodeP(getIdent("dec"), p), left, expression(p, 29))
+  of pxStarAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("*", copyTree(left), right, p))
+  of pxSlashAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("/", copyTree(left), right, p))
+  of pxModAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("mod", copyTree(left), right, p))
+  of pxShlAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("shl", copyTree(left), right, p))
+  of pxShrAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("shr", copyTree(left), right, p))
+  of pxAmpAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("and", copyTree(left), right, p))
+  of pxHatAsgn: # 30
+    result = newNodeP(nkAsgn, p)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("xor", copyTree(left), right, p))
+  of pxBarAsgn: # 30
     result = newNodeP(nkAsgn, p)
-    addSon(result, a, b)
-  of pxPlusAsgn: result = incDec(p, "inc", a)    
-  of pxMinusAsgn: result = incDec(p, "dec", a)
-  of pxStarAsgn: result = asgnExpr(p, "*", a)
-  of pxSlashAsgn: result = asgnExpr(p, "/", a)
-  of pxModAsgn: result = asgnExpr(p, "mod", a)
-  of pxShlAsgn: result = asgnExpr(p, "shl", a)
-  of pxShrAsgn: result = asgnExpr(p, "shr", a)
-  of pxAmpAsgn: result = asgnExpr(p, "and", a)
-  of pxHatAsgn: result = asgnExpr(p, "xor", a)
-  of pxBarAsgn: result = asgnExpr(p, "or", a)
+    var right = expression(p, 29)
+    addSon(result, left, newBinary("or", copyTree(left), right, p))
+  of pxConditional: # 40
+    var a = expression(p, 0)
+    eat(p, pxColon, a)
+    var b = expression(p, 39)
+    result = newNodeP(nkIfExpr, p)
+    var branch = newNodeP(nkElifExpr, p)
+    addSon(branch, left, a)
+    addSon(result, branch)
+    branch = newNodeP(nkElseExpr, p)
+    addSon(branch, b)
+    addSon(result, branch)
+  of pxBarBar: # 50
+    result = newBinary("or", left, expression(p, 50), p)
+  of pxAmpAmp: # 60
+    result = newBinary("and", left, expression(p, 60), p)
+  of pxBar: # 70
+    result = newBinary("or", left, expression(p, 70), p)
+  of pxHat: # 80
+    result = newBinary("^", left, expression(p, 80), p)
+  of pxAmp: # 90
+    result = newBinary("and", left, expression(p, 90), p)
+  of pxEquals: # 100
+    result = newBinary("==", left, expression(p, 100), p)
+  of pxNeq: # 100
+    result = newBinary("!=", left, expression(p, 100), p)
+  of pxLt: # 110
+    result = newBinary("<", left, expression(p, 110), p)
+  of pxLe: # 110
+    result = newBinary("<=", left, expression(p, 110), p)
+  of pxGt: # 110
+    result = newBinary(">", left, expression(p, 110), p)
+  of pxGe: # 110
+    result = newBinary(">=", left, expression(p, 110), p)
+  of pxShl: # 120
+    result = newBinary("shl", left, expression(p, 120), p)
+  of pxShr: # 120
+    result = newBinary("shr", left, expression(p, 120), p)
+  of pxPlus: # 130
+    result = newNodeP(nkInfix, p)
+    addSon(result, newIdentNodeP("+", p), left)
+    addSon(result, expression(p, 130))
+  of pxMinus: # 130
+    result = newNodeP(nkInfix, p)
+    addSon(result, newIdentNodeP("+", p), left)
+    addSon(result, expression(p, 130))
+  of pxStar: # 140
+    result = newNodeP(nkInfix, p)
+    addSon(result, newIdentNodeP("*", p), left)
+    addSon(result, expression(p, 140))
+  of pxSlash: # 140
+    result = newNodeP(nkInfix, p)
+    addSon(result, newIdentNodeP("div", p), left)
+    addSon(result, expression(p, 140))
+  of pxMod: # 140
+    result = newNodeP(nkInfix, p)
+    addSon(result, newIdentNodeP("mod", p), left)
+    addSon(result, expression(p, 140))
+    # .* ->* == 150
+  of pxPlusPlus: # 160
+    result = newNodeP(nkCall, p)
+    addSon(result, newIdentNodeP("inc", p), left)
+  of pxMinusMinus: # 160
+    result = newNodeP(nkCall, p)
+    addSon(result, newIdentNodeP("dec", p), left)
+  of pxParLe: # 160
+    result = newNodeP(nkCall, p)
+    addSon(result, left)
+    while p.tok.xkind != pxParRi:
+      var a = expression(p, 29)
+      addSon(result, a)
+      while p.tok.xkind == pxComma:
+        getTok(p, a)
+        a = expression(p, 29)
+        addSon(result, a)
+    eat(p, pxParRi, result)
+  of pxDot: # 160
+    result = newNodeP(nkDotExpr, p)
+    addSon(result, left)
+    addSon(result, skipIdent(p))
+  of pxArrow: # 160
+    result = newNodeP(nkDotExpr, p)
+    addSon(result, left)
+    addSon(result, skipIdent(p))
+  of pxBracketLe: # 160
+    result = newNodeP(nkBracketExpr, p)
+    addSon(result, left, expression(p))
+    eat(p, pxBracketRi, result)
+    # :: == 170
   else:
-    backtrackContext(p)
-    result = conditionalExpression(p)
-  
-proc shiftExpression(p: var TParser): PNode = 
-  result = additiveExpression(p)
-  while p.tok.xkind in {pxShl, pxShr}:
-    var op = if p.tok.xkind == pxShl: "shl" else: "shr"
-    getTok(p, result)
-    var a = result 
-    var b = additiveExpression(p)
-    result = newBinary(op, a, b, p)
-
-proc relationalExpression(p: var TParser): PNode = 
-  result = shiftExpression(p)
-  # Nimrod uses ``<`` and ``<=``, etc. too:
-  while p.tok.xkind in {pxLt, pxLe, pxGt, pxGe}:
-    var op = TokKindToStr(p.tok.xkind)
-    getTok(p, result)
-    var a = result 
-    var b = shiftExpression(p)
-    result = newBinary(op, a, b, p)
-
-proc equalityExpression(p: var TParser): PNode =
-  result = relationalExpression(p)
-  # Nimrod uses ``==`` and ``!=`` too:
-  while p.tok.xkind in {pxEquals, pxNeq}:
-    var op = TokKindToStr(p.tok.xkind)
-    getTok(p, result)
-    var a = result 
-    var b = relationalExpression(p)
-    result = newBinary(op, a, b, p)
+    result = left
 
-proc andExpression(p: var TParser): PNode =
-  result = equalityExpression(p)
-  while p.tok.xkind == pxAmp:
-    getTok(p, result)
-    var a = result 
-    var b = equalityExpression(p)
-    result = newBinary("and", a, b, p)
+proc expression*(p : var TParser, rbp : int = 0) : PNode =
+  var tok : TToken
 
-proc exclusiveOrExpression(p: var TParser): PNode = 
-  result = andExpression(p)
-  while p.tok.xkind == pxHat:
-    getTok(p, result)
-    var a = result 
-    var b = andExpression(p)
-    result = newBinary("^", a, b, p)
+  tok = p.tok[]
+  getTok(p, result)
 
-proc inclusiveOrExpression(p: var TParser): PNode = 
-  result = exclusiveOrExpression(p)
-  while p.tok.xkind == pxBar:
-    getTok(p, result)
-    var a = result 
-    var b = exclusiveOrExpression(p)
-    result = newBinary("or", a, b, p)
-  
-proc logicalAndExpression(p: var TParser): PNode = 
-  result = inclusiveOrExpression(p)
-  while p.tok.xkind == pxAmpAmp:
-    getTok(p, result)
-    var a = result
-    var b = inclusiveOrExpression(p)
-    result = newBinary("and", a, b, p)
+  result = startExpression(p, tok)
 
-proc logicalOrExpression(p: var TParser): PNode = 
-  result = logicalAndExpression(p)
-  while p.tok.xkind == pxBarBar:
+  while rbp < leftBindingPower(p, p.tok):
+    tok = p.tok[]
     getTok(p, result)
-    var a = result
-    var b = logicalAndExpression(p)
-    result = newBinary("or", a, b, p)
-  
-proc conditionalExpression(p: var TParser): PNode =  
-  result = logicalOrExpression(p)
-  if p.tok.xkind == pxConditional: 
-    getTok(p, result) # skip '?'
-    var a = result
-    var b = expression(p)
-    eat(p, pxColon, b)
-    var c = conditionalExpression(p)
-    result = newNodeP(nkIfExpr, p)
-    var branch = newNodeP(nkElifExpr, p)
-    addSon(branch, a, b)
-    addSon(result, branch)
-    branch = newNodeP(nkElseExpr, p)
-    addSon(branch, c)
-    addSon(result, branch)
+    result = leftExpression(p, tok, result)
     
 # Statements
 
@@ -1549,12 +1510,12 @@ proc parseIf(p: var TParser): PNode =
   while true: 
     getTok(p) # skip ``if``
     var branch = newNodeP(nkElifBranch, p)
-    skipCom(p, branch)
     eat(p, pxParLe, branch)
     addSon(branch, expression(p))
     eat(p, pxParRi, branch)
     addSon(branch, nestedStatement(p))
     addSon(result, branch)
+    skipCom(p, branch)
     if p.tok.s == "else": 
       getTok(p, result)
       if p.tok.s != "if": 
@@ -1574,19 +1535,51 @@ proc parseWhile(p: var TParser): PNode =
   eat(p, pxParRi, result)
   addSon(result, nestedStatement(p))
 
+proc embedStmts(sl, a: PNode)
+
 proc parseDoWhile(p: var TParser): PNode =  
-  # we only support ``do stmt while (0)`` as an idiom for 
-  # ``block: stmt``
-  result = newNodeP(nkBlockStmt, p)
-  getTok(p, result) # skip "do"
-  addSon(result, ast.emptyNode, nestedStatement(p))
+  # parsing
+  result = newNodeP(nkWhileStmt, p)
+  getTok(p, result)
+  var stm = nestedStatement(p)
   eat(p, "while", result)
   eat(p, pxParLe, result)
-  if p.tok.xkind == pxIntLit and p.tok.iNumber == 0: getTok(p, result)
-  else: parMessage(p, errTokenExpected, "0")
+  var exp = expression(p)
   eat(p, pxParRi, result)
   if p.tok.xkind == pxSemicolon: getTok(p)
 
+  # while true:
+  #   stmt
+  #   if not expr:
+  #     break
+  addSon(result, newIdentNodeP("true", p))
+
+  stm = buildStmtList(stm)
+
+  # get the last exp if it is a stmtlist
+  var cleanedExp = exp
+  if exp.kind == nkStmtList:
+    cleanedExp = exp.sons[exp.len-1]
+    exp.sons = exp.sons[0..exp.len-2]
+    embedStmts(stm, exp)
+
+  var notExp = newNodeP(nkPrefix, p)
+  addSon(notExp, newIdentNodeP("not", p))
+  addSon(notExp, cleanedExp)
+
+  var brkStm = newNodeP(nkBreakStmt, p)
+  addSon(brkStm, ast.emptyNode)
+
+  var ifStm = newNodeP(nkIfStmt, p)
+  var ifBranch = newNodeP(nkElifBranch, p)
+  addSon(ifBranch, notExp)
+  addSon(ifBranch, brkStm)
+  addSon(ifStm, ifBranch)
+
+  embedStmts(stm, ifStm)
+
+  addSon(result, stm)
+
 proc declarationOrStatement(p: var TParser): PNode = 
   if p.tok.xkind != pxSymbol:
     result = expressionStatement(p)
@@ -1666,7 +1659,7 @@ proc parseFor(p: var TParser, result: PNode) =
   eat(p, pxParLe, result)
   var initStmt = declarationOrStatement(p)
   if initStmt.kind != nkEmpty:
-    addSon(result, initStmt)
+    embedStmts(result, initStmt)
   var w = newNodeP(nkWhileStmt, p)
   var condition = expressionStatement(p)
   if condition.kind == nkEmpty: condition = newIdentNodeP("true", p)
@@ -1676,7 +1669,7 @@ proc parseFor(p: var TParser, result: PNode) =
   var loopBody = nestedStatement(p)
   if step.kind != nkEmpty:
     loopBody = buildStmtList(loopBody)
-    addSon(loopBody, step)
+    embedStmts(loopBody, step)
   addSon(w, loopBody)
   addSon(result, w)
   
@@ -1694,7 +1687,7 @@ proc switchStatement(p: var TParser): PNode =
       break
     of "case", "default":
       break
-    else: nil
+    else: discard
     addSon(result, statement(p))
   if sonsLen(result) == 0:
     # translate empty statement list to Nimrod's ``nil`` statement
@@ -1818,7 +1811,7 @@ proc parseConstructor(p: var TParser, pragmas: PNode,
   else:
     parMessage(p, errTokenExpected, ";")
   if result.sons[bodyPos].kind == nkEmpty:
-    DoImport((if isDestructor: "~" else: "") & origName, pragmas, p)
+    doImport((if isDestructor: "~" else: "") & origName, pragmas, p)
   elif isDestructor:
     addSon(pragmas, newIdentNodeP("destructor", p))
   if sonsLen(result.sons[pragmasPos]) == 0:
@@ -1862,8 +1855,8 @@ proc parseMethod(p: var TParser, origName: string, rettyp, pragmas: PNode,
   else:
     parMessage(p, errTokenExpected, ";")
   if result.sons[bodyPos].kind == nkEmpty:
-    if isStatic: DoImport(origName, pragmas, p)
-    else: DoImportCpp(origName, pragmas, p)
+    if isStatic: doImport(origName, pragmas, p)
+    else: doImportCpp(origName, pragmas, p)
   if sonsLen(result.sons[pragmasPos]) == 0:
     result.sons[pragmasPos] = ast.emptyNode
 
@@ -1880,7 +1873,7 @@ proc parseOperator(p: var TParser, origName: var string): bool =
   case p.tok.xkind
   of pxAmp..pxArrow:
     # ordinary operator symbol:
-    origName.add(TokKindToStr(p.tok.xkind))
+    origName.add(tokKindToStr(p.tok.xkind))
     getTok(p)
   of pxSymbol:
     if p.tok.s == "new" or p.tok.s == "delete":
@@ -2048,6 +2041,10 @@ proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode =
     result = declaration(p)
   p.currentClass = oldClass
 
+proc unwrap(a: PNode): PNode =
+  if a.kind == nkPar:
+    return a.sons[0]
+  return a
 
 include cpp
 
@@ -2082,16 +2079,10 @@ proc statement(p: var TParser): PNode =
     of "return":
       result = newNodeP(nkReturnStmt, p)
       getTok(p)
-      # special case for ``return (expr)`` because I hate the redundant
-      # parenthesis ;-)
-      if p.tok.xkind == pxParLe:
-        getTok(p, result)
-        addSon(result, expression(p))
-        eat(p, pxParRi, result)
-      elif p.tok.xkind != pxSemicolon:
-        addSon(result, expression(p))
-      else:
+      if p.tok.xkind == pxSemicolon:
         addSon(result, ast.emptyNode)
+      else:
+        addSon(result, unwrap(expression(p)))
       eat(p, pxSemicolon)
     of "enum": result = enumSpecifier(p)
     of "typedef": result = parseTypeDef(p)
@@ -2140,9 +2131,12 @@ proc statement(p: var TParser): PNode =
   assert result != nil
 
 proc parseUnit(p: var TParser): PNode =
-  result = newNodeP(nkStmtList, p)
-  getTok(p) # read first token
-  while p.tok.xkind != pxEof:
-    var s = statement(p)
-    if s.kind != nkEmpty: embedStmts(result, s)
+  try:
+    result = newNodeP(nkStmtList, p)
+    getTok(p) # read first token
+    while p.tok.xkind != pxEof:
+      var s = statement(p)
+      if s.kind != nkEmpty: embedStmts(result, s)
+  except ERetryParsing:
+    parMessage(p, errGenerated, "Uncaught parsing exception raised")
 
diff --git a/compiler/c2nim/cpp.nim b/compiler/c2nim/cpp.nim
index 2ce64e59b..84b4c4dfb 100644
--- a/compiler/c2nim/cpp.nim
+++ b/compiler/c2nim/cpp.nim
@@ -103,7 +103,7 @@ proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) =
       m.body.add(tok)
     of pxDirConc: 
       # just ignore this token: this implements token merging correctly
-      nil
+      discard
     else:
       m.body.add(p.tok)
     # we do not want macro expansion here:
@@ -166,7 +166,7 @@ proc parseStmtList(p: var TParser): PNode =
     of pxDirectiveParLe, pxDirective: 
       case p.tok.s
       of "else", "endif", "elif": break
-    else: nil
+    else: discard
     addSon(result, statement(p))
   
 proc eatEndif(p: var TParser) =
@@ -226,7 +226,7 @@ proc skipUntilElifElseEndif(p: var TParser): TEndifMarker =
   
 proc parseIfdef(p: var TParser): PNode = 
   getTok(p) # skip #ifdef
-  ExpectIdent(p)
+  expectIdent(p)
   case p.tok.s
   of "__cplusplus":
     skipUntilEndif(p)
@@ -245,7 +245,7 @@ proc parseIfdef(p: var TParser): PNode =
 proc parseIfndef(p: var TParser): PNode = 
   result = ast.emptyNode
   getTok(p) # skip #ifndef
-  ExpectIdent(p)
+  expectIdent(p)
   if p.tok.s == c2nimSymbol: 
     skipLine(p)
     case skipUntilElifElseEndif(p)
@@ -282,11 +282,11 @@ proc parseIfDir(p: var TParser): PNode =
 proc parsePegLit(p: var TParser): TPeg =
   var col = getColumn(p.lex) + 2
   getTok(p)
-  if p.tok.xkind != pxStrLit: ExpectIdent(p)
+  if p.tok.xkind != pxStrLit: expectIdent(p)
   try:
     result = parsePeg(
       pattern = if p.tok.xkind == pxStrLit: p.tok.s else: escapePeg(p.tok.s), 
-      filename = p.lex.fileIdx.ToFilename, 
+      filename = p.lex.fileIdx.toFilename, 
       line = p.lex.linenumber, 
       col = col)
     getTok(p)
@@ -295,7 +295,7 @@ proc parsePegLit(p: var TParser): TPeg =
 
 proc parseMangleDir(p: var TParser) = 
   var pattern = parsePegLit(p)
-  if p.tok.xkind != pxStrLit: ExpectIdent(p)
+  if p.tok.xkind != pxStrLit: expectIdent(p)
   p.options.mangleRules.add((pattern, p.tok.s))
   getTok(p)
   eatNewLine(p, nil)
@@ -326,7 +326,7 @@ proc parseDir(p: var TParser): PNode =
   of "dynlib", "header", "prefix", "suffix", "class": 
     var key = p.tok.s
     getTok(p)
-    if p.tok.xkind != pxStrLit: ExpectIdent(p)
+    if p.tok.xkind != pxStrLit: expectIdent(p)
     discard setOption(p.options, key, p.tok.s)
     getTok(p)
     eatNewLine(p, nil)
diff --git a/compiler/c2nim/tests/vincent.c b/compiler/c2nim/tests/vincent.c
new file mode 100644
index 000000000..24c6d6425
--- /dev/null
+++ b/compiler/c2nim/tests/vincent.c
@@ -0,0 +1,33 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+int rand(void);
+
+int id2(void) {
+    return (int *)1;
+}
+
+int id(void (*f)(void)) {
+    f();
+    ((void (*)(int))f)(10);
+    return 10;
+    return (20+1);
+    return (int *)id;
+}
+
+int main() {
+    float f = .2,
+          g = 2.,
+          h = 1.0+rand(),
+          i = 1.0e+3;
+    int j, a;
+    for(j = 0, a = 10; j < 0; j++, a++) ;
+    do {
+        printf("howdy");
+    } while(--i, 0);
+    if(1)
+        printf("1"); // error from this comment
+    else
+        printf("2");
+    return '\x00';
+}
diff --git a/compiler/c2nim/tests/vincent.h b/compiler/c2nim/tests/vincent.h
new file mode 100644
index 000000000..b4e761ee1
--- /dev/null
+++ b/compiler/c2nim/tests/vincent.h
@@ -0,0 +1,3 @@
+struct foo {
+    int x,y,z;
+};
diff --git a/compiler/canonicalizer.nim b/compiler/canonicalizer.nim
new file mode 100644
index 000000000..3bc4eb029
--- /dev/null
+++ b/compiler/canonicalizer.nim
@@ -0,0 +1,416 @@
+#
+#
+#           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 canonalization for the various caching mechanisms.
+
+import strutils, db_sqlite, md5
+
+var db: TDbConn
+
+# We *hash* the relevant information into 128 bit hashes. This should be good
+# enough to prevent any collisions.
+
+type
+  TUid = distinct MD5Digest
+
+# For name mangling we encode these hashes via a variant of base64 (called
+# 'base64a') and prepend the *primary* identifier to ease the debugging pain.
+# So a signature like:
+#
+#   proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt)
+#
+# is mangled into:
+#   gABI_MTdmOWY5MTQ1MDcyNGQ3ZA
+#
+# This is a good compromise between correctness and brevity. ;-)
+
+const

+  cb64 = [
+    "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
+    "O", "P", "Q", "R", "S", "T" "U", "V", "W", "X", "Y", "Z", 
+    "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", 
+    "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", 
+    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+    "_A", "_B"]

+

+proc toBase64a(s: cstring, len: int): string =

+  ## encodes `s` into base64 representation. After `lineLen` characters, a 

+  ## `newline` is added.

+  result = newStringOfCap(((len + 2) div 3) * 4)

+  var i = 0

+  while i < s.len - 2:

+    let a = ord(s[i])

+    let b = ord(s[i+1])

+    let c = ord(s[i+2])

+    result.add cb64[a shr 2]

+    result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]

+    result.add cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)]

+    result.add cb64[c and 0x3F]

+    inc(i, 3)

+  if i < s.len-1:

+    let a = ord(s[i])

+    let b = ord(s[i+1])

+    result.add cb64[a shr 2]

+    result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]

+    result.add cb64[((b and 0x0F) shl 2)]

+  elif i < s.len:

+    let a = ord(s[i])

+    result.add cb64[a shr 2]

+    result.add cb64[(a and 3) shl 4]

+
+proc toBase64a(u: TUid): string = toBase64a(cast[cstring](u), sizeof(u))
+
+proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
+
+proc hashSym(c: var MD5Context, s: PSym) =
+  if sfAnon in s.flags or s.kind == skGenericParam:
+    c &= ":anon"
+  else:
+    var it = s.owner
+    while it != nil: 
+      hashSym(c, it)
+      c &= "."
+      it = s.owner
+    c &= s.name.s
+
+proc hashTree(c: var MD5Context, n: PNode) =
+  if n == nil:
+    c &= "\255"
+    return
+  var k = n.kind
+  md5Update(c, cast[cstring](addr(k)), 1)
+  # we really must not hash line information. 'n.typ' is debatable but
+  # shouldn't be necessary for now and avoids potential infinite recursions.
+  case n.kind
+  of nkEmpty, nkNilLit, nkType: discard
+  of nkIdent:
+    c &= n.ident.s
+  of nkSym:
+    hashSym(c, n.sym)
+  of nkCharLit..nkUInt64Lit:
+    var v = n.intVal
+    md5Update(c, cast[cstring](addr(v)), sizeof(v))
+  of nkFloatLit..nkFloat64Lit:
+    var v = n.floatVal
+    md5Update(c, cast[cstring](addr(v)), sizeof(v))
+  of nkStrLit..nkTripleStrLit:
+    c &= n.strVal
+  else:
+    for i in 0.. <n.len: hashTree(c, n.sons[i])
+
+proc hashType(c: var MD5Context, t: PType) =
+  # modelled after 'typeToString'
+  if t == nil: 
+    c &= "\254"
+    return
+
+  var k = t.kind
+  md5Update(c, cast[cstring](addr(k)), 1)
+  
+  if t.sym != nil and sfAnon notin t.sym.flags:
+    # t.n for literals, but not for e.g. objects!
+    if t.kind in {tyFloat, tyInt}: c.hashNode(t.n)
+    c.hashSym(t.sym)
+    
+  case t.kind
+  of tyGenericBody, tyGenericInst, tyGenericInvokation:
+    for i in countup(0, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)):
+      c.hashType t.sons[i]
+  of tyUserTypeClass:
+    internalAssert t.sym != nil and t.sym.owner != nil
+    c &= t.sym.owner.name.s
+  of tyUserTypeClassInst:
+    let body = t.base
+    c.hashSym body.sym
+    for i in countup(1, sonsLen(t) - 2):
+      c.hashType t.sons[i]
+  of tyFromExpr, tyFieldAccessor:
+    c.hashTree(t.n)
+  of tyArrayConstr:
+    c.hashTree(t.sons[0].n)
+    c.hashType(t.sons[1])
+  of tyTuple: 
+    if t.n != nil:
+      assert(sonsLen(t.n) == sonsLen(t))
+      for i in countup(0, sonsLen(t.n) - 1): 
+        assert(t.n.sons[i].kind == nkSym)
+        c &= t.n.sons[i].sym.name.s
+        c &= ":"
+        c.hashType(t.sons[i])
+        c &= ","
+    else:
+      for i in countup(0, sonsLen(t) - 1): c.hashType t.sons[i]
+  of tyRange:
+    c.hashTree(t.n)
+    c.hashType(t.sons[0])
+  of tyProc:
+    c &= (if tfIterator in t.flags: "iterator " else: "proc ")
+    for i in 0.. <t.len: c.hashType(t.sons[i])
+    md5Update(c, cast[cstring](addr(t.callConv)), 1)
+
+    if tfNoSideEffect in t.flags: c &= ".noSideEffect"
+    if tfThread in t.flags: c &= ".thread"
+  else:
+    for i in 0.. <t.len: c.hashType(t.sons[i])
+  if tfShared in t.flags: c &= "shared"
+  if tfNotNil in t.flags: c &= "not nil"
+
+proc canonConst(n: PNode): TUid =
+  var c: MD5Context
+  md5Init(c)
+  c.hashTree(n)
+  c.hashType(n.typ)
+  md5Final(c, MD5Digest(result))
+
+proc canonSym(s: PSym): TUid =
+  var c: MD5Context
+  md5Init(c)
+  c.hashSym(s)
+  md5Final(c, MD5Digest(result))
+
+proc pushType(w: PRodWriter, t: PType) =
+  # check so that the stack does not grow too large:
+  if iiTableGet(w.index.tab, t.id) == InvalidKey:
+    w.tstack.add(t)
+
+proc pushSym(w: PRodWriter, s: PSym) =
+  # check so that the stack does not grow too large:
+  if iiTableGet(w.index.tab, s.id) == InvalidKey:
+    w.sstack.add(s)
+
+proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode, 
+                result: var string) = 
+  if n == nil: 
+    # nil nodes have to be stored too:
+    result.add("()")
+    return
+  result.add('(')
+  encodeVInt(ord(n.kind), result) 
+  # we do not write comments for now
+  # Line information takes easily 20% or more of the filesize! Therefore we
+  # omit line information if it is the same as the father's line information:
+  if fInfo.fileIndex != n.info.fileIndex: 
+    result.add('?')
+    encodeVInt(n.info.col, result)
+    result.add(',')
+    encodeVInt(n.info.line, result)
+    result.add(',')
+    encodeVInt(fileIdx(w, toFilename(n.info)), result)
+  elif fInfo.line != n.info.line:
+    result.add('?')
+    encodeVInt(n.info.col, result)
+    result.add(',')
+    encodeVInt(n.info.line, result)
+  elif fInfo.col != n.info.col:
+    result.add('?')
+    encodeVInt(n.info.col, result)
+  var f = n.flags * PersistentNodeFlags
+  if f != {}: 
+    result.add('$')
+    encodeVInt(cast[int32](f), result)
+  if n.typ != nil:
+    result.add('^')
+    encodeVInt(n.typ.id, result)
+    pushType(w, n.typ)
+  case n.kind
+  of nkCharLit..nkInt64Lit: 
+    if n.intVal != 0:
+      result.add('!')
+      encodeVBiggestInt(n.intVal, result)
+  of nkFloatLit..nkFloat64Lit: 
+    if n.floatVal != 0.0: 
+      result.add('!')
+      encodeStr($n.floatVal, result)
+  of nkStrLit..nkTripleStrLit:
+    if n.strVal != "": 
+      result.add('!')
+      encodeStr(n.strVal, result)
+  of nkIdent:
+    result.add('!')
+    encodeStr(n.ident.s, result)
+  of nkSym:
+    result.add('!')
+    encodeVInt(n.sym.id, result)
+    pushSym(w, n.sym)
+  else:
+    for i in countup(0, sonsLen(n) - 1): 
+      encodeNode(w, n.info, n.sons[i], result)
+  add(result, ')')
+
+proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) = 
+  var oldLen = result.len
+  result.add('<')
+  if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
+  if loc.s != low(loc.s): 
+    add(result, '*')
+    encodeVInt(ord(loc.s), result)
+  if loc.flags != {}: 
+    add(result, '$')
+    encodeVInt(cast[int32](loc.flags), result)
+  if loc.t != nil:
+    add(result, '^')
+    encodeVInt(cast[int32](loc.t.id), result)
+    pushType(w, loc.t)
+  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)
+  else:
+    add(result, '>')
+  
+proc encodeType(w: PRodWriter, t: PType, result: var string) = 
+  if t == nil: 
+    # nil nodes have to be stored too:
+    result.add("[]")
+    return
+  # we need no surrounding [] here because the type is in a line of its own
+  if t.kind == tyForward: internalError("encodeType: tyForward")
+  # for the new rodfile viewer we use a preceeding [ so that the data section
+  # can easily be disambiguated:
+  add(result, '[')
+  encodeVInt(ord(t.kind), result)
+  add(result, '+')
+  encodeVInt(t.id, result)
+  if t.n != nil: 
+    encodeNode(w, unknownLineInfo(), t.n, result)
+  if t.flags != {}: 
+    add(result, '$')
+    encodeVInt(cast[int32](t.flags), result)
+  if t.callConv != low(t.callConv): 
+    add(result, '?')
+    encodeVInt(ord(t.callConv), result)
+  if t.owner != nil: 
+    add(result, '*')
+    encodeVInt(t.owner.id, result)
+    pushSym(w, t.owner)
+  if t.sym != nil: 
+    add(result, '&')
+    encodeVInt(t.sym.id, result)
+    pushSym(w, t.sym)
+  if t.size != - 1: 
+    add(result, '/')
+    encodeVBiggestInt(t.size, result)
+  if t.align != 2: 
+    add(result, '=')
+    encodeVInt(t.align, result)
+  encodeLoc(w, t.loc, result)
+  for i in countup(0, sonsLen(t) - 1): 
+    if t.sons[i] == nil: 
+      add(result, "^()")
+    else: 
+      add(result, '^') 
+      encodeVInt(t.sons[i].id, result)
+      pushType(w, t.sons[i])
+
+proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) = 
+  add(result, '|')
+  encodeVInt(ord(lib.kind), result)
+  add(result, '|')
+  encodeStr(ropeToStr(lib.name), result)
+  add(result, '|')
+  encodeNode(w, info, lib.path, result)
+
+proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
+  if s == nil:
+    # nil nodes have to be stored too:
+    result.add("{}")
+    return
+  # we need no surrounding {} here because the symbol is in a line of its own
+  encodeVInt(ord(s.kind), result)
+  result.add('+')
+  encodeVInt(s.id, result)
+  result.add('&')
+  encodeStr(s.name.s, result)
+  if s.typ != nil:
+    result.add('^')
+    encodeVInt(s.typ.id, result)
+    pushType(w, s.typ)
+  result.add('?')
+  if s.info.col != -1'i16: encodeVInt(s.info.col, result)
+  result.add(',')
+  if s.info.line != -1'i16: encodeVInt(s.info.line, result)
+  result.add(',')
+  encodeVInt(fileIdx(w, toFilename(s.info)), result)
+  if s.owner != nil:
+    result.add('*')
+    encodeVInt(s.owner.id, result)
+    pushSym(w, s.owner)
+  if s.flags != {}:
+    result.add('$')
+    encodeVInt(cast[int32](s.flags), result)
+  if s.magic != mNone:
+    result.add('@')
+    encodeVInt(ord(s.magic), result)
+  if s.options != w.options: 
+    result.add('!')
+    encodeVInt(cast[int32](s.options), result)
+  if s.position != 0: 
+    result.add('%')
+    encodeVInt(s.position, result)
+  if s.offset != - 1:
+    result.add('`')
+    encodeVInt(s.offset, result)
+  encodeLoc(w, s.loc, result)
+  if s.annex != nil: encodeLib(w, s.annex, s.info, result)
+  if s.constraint != nil:
+    add(result, '#')
+    encodeNode(w, unknownLineInfo(), s.constraint, result)
+  # lazy loading will soon reload the ast lazily, so the ast needs to be
+  # the last entry of a symbol:
+  if s.ast != nil:
+    # we used to attempt to save space here by only storing a dummy AST if
+    # it is not necessary, but Nimrod's heavy compile-time evaluation features
+    # make that unfeasible nowadays:
+    encodeNode(w, s.info, s.ast, result)
+
+
+proc createDb() =
+  db.exec(sql"""
+    create table if not exists Module(
+      id integer primary key,
+      name varchar(256) not null,
+      fullpath varchar(256) not null,
+      interfHash varchar(256) not null,
+      fullHash varchar(256) not null,
+      
+      created timestamp not null default (DATETIME('now')),
+    );""")
+
+  db.exec(sql"""
+    create table if not exists Symbol(
+      id integer primary key,
+      module integer not null,
+      name varchar(max) not null,
+      data varchar(max) not null,
+      created timestamp not null default (DATETIME('now')),
+
+      foreign key (module) references module(id)
+    );""")
+    
+  db.exec(sql"""
+    create table if not exists Type(
+      id integer primary key,
+      module integer not null,
+      name varchar(max) not null,
+      data varchar(max) not null,
+      created timestamp not null default (DATETIME('now')),
+
+      foreign key (module) references module(id)
+    );""")
+
+
+  #db.exec(sql"""
+  #  --create unique index if not exists TsstNameIx on TestResult(name);
+  #  """, [])
+
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index 07fba95a3..84c5bf419 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -73,7 +73,7 @@ proc isInCurrentFrame(p: BProc, n: PNode): bool =
     result = false
   of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
     result = isInCurrentFrame(p, n.sons[0])
-  else: nil
+  else: discard
 
 proc openArrayLoc(p: BProc, n: PNode): PRope =
   var a: TLoc
@@ -88,7 +88,7 @@ proc openArrayLoc(p: BProc, n: PNode): PRope =
       result = ropef("$1->data, $1->$2", [a.rdLoc, lenField()])
   of tyArray, tyArrayConstr:
     result = ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))])
-  else: InternalError("openArrayLoc: " & typeToString(a.t))
+  else: internalError("openArrayLoc: " & typeToString(a.t))
 
 proc genArgStringToCString(p: BProc, 
                            n: PNode): PRope {.inline.} =
@@ -146,7 +146,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
   proc addComma(r: PRope): PRope =
     result = if r == nil: r else: con(r, ~", ")
 
-  const CallPattern = "$1.ClEnv? $1.ClPrc($3$1.ClEnv) : (($4)($1.ClPrc))($2)"
+  const PatProc = "$1.ClEnv? $1.ClPrc($3$1.ClEnv):(($4)($1.ClPrc))($2)"
+  const PatIter = "$1.ClPrc($3$1.ClEnv)" # we know the env exists
   var op: TLoc
   initLocExpr(p, ri.sons[0], op)
   var pl: PRope
@@ -164,9 +165,10 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
     if i < length - 1: app(pl, ~", ")
   
   template genCallPattern {.dirty.} =
-    lineF(p, cpsStmts, CallPattern & ";$n", op.r, pl, pl.addComma, rawProc)
+    lineF(p, cpsStmts, callPattern & ";$n", op.r, pl, pl.addComma, rawProc)
 
   let rawProc = getRawProcType(p, typ)
+  let callPattern = if tfIterator in typ.flags: PatIter else: PatProc
   if typ.sons[0] != nil:
     if isInvalidReturnType(typ.sons[0]):
       if sonsLen(ri) > 1: app(pl, ~", ")
@@ -190,7 +192,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
       assert(d.t != nil)        # generate an assignment to d:
       var list: TLoc
       initLoc(list, locCall, d.t, OnUnknown)
-      list.r = ropef(CallPattern, op.r, pl, pl.addComma, rawProc)
+      list.r = ropef(callPattern, op.r, pl, pl.addComma, rawProc)
       genAssignment(p, d, list, {}) # no need for deep copying
   else:
     genCallPattern()
@@ -243,7 +245,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
   for i in countup(3, length-1):
     assert(sonsLen(typ) == sonsLen(typ.n))
     if i >= sonsLen(typ):
-      InternalError(ri.info, "varargs for objective C method?")
+      internalError(ri.info, "varargs for objective C method?")
     assert(typ.n.sons[i].kind == nkSym)
     var param = typ.n.sons[i].sym
     app(pl, ~" ")
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index daa0c8d88..e346e1b53 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -11,7 +11,7 @@
 
 # -------------------------- constant expressions ------------------------
 
-proc intLiteral(i: biggestInt): PRope =
+proc intLiteral(i: BiggestInt): PRope =
   if (i > low(int32)) and (i <= high(int32)):
     result = toRope(i)
   elif i == low(int32):
@@ -22,7 +22,7 @@ proc intLiteral(i: biggestInt): PRope =
   else:
     result = ~"(IL64(-9223372036854775807) - IL64(1))"
 
-proc int32Literal(i: Int): PRope =
+proc int32Literal(i: int): PRope =
   if i == int(low(int32)):
     result = ~"(-2147483647 -1)"
   else:
@@ -39,7 +39,7 @@ proc getStrLit(m: BModule, s: string): PRope =
   discard cgsym(m, "TGenericSeq")
   result = con("TMP", toRope(backendId()))
   appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
-       [result, makeCString(s), ToRope(len(s))])
+       [result, makeCString(s), toRope(len(s))])
 
 proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
   if ty == nil: internalError(n.info, "genLiteral: ty is nil")
@@ -62,7 +62,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
   of nkNilLit:
     let t = skipTypes(ty, abstractVarRange)
     if t.kind == tyProc and t.callConv == ccClosure:
-      var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId)
+      var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
       result = con("TMP", toRope(id))
       if id == gBackendId:
         # not found in cache:
@@ -74,7 +74,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
       result = toRope("NIM_NIL")
   of nkStrLit..nkTripleStrLit:
     if skipTypes(ty, abstractVarRange).kind == tyString:
-      var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId)
+      var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
       if id == gBackendId:
         # string literal not found in the cache:
         result = ropecg(p.module, "((#NimStringDesc*) &$1)", 
@@ -84,9 +84,9 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
     else:
       result = makeCString(n.strVal)
   of nkFloatLit..nkFloat64Lit:
-    result = toRope(n.floatVal.ToStrMaxPrecision)
+    result = toRope(n.floatVal.toStrMaxPrecision)
   else:
-    InternalError(n.info, "genLiteral(" & $n.kind & ')')
+    internalError(n.info, "genLiteral(" & $n.kind & ')')
     result = nil
 
 proc genLiteral(p: BProc, n: PNode): PRope =
@@ -96,7 +96,7 @@ proc bitSetToWord(s: TBitSet, size: int): BiggestInt =
   result = 0
   when true:
     for j in countup(0, size - 1):
-      if j < len(s): result = result or `shl`(Ze64(s[j]), j * 8)
+      if j < len(s): result = result or `shl`(ze64(s[j]), j * 8)
   else:
     # not needed, too complex thinking:
     if CPU[platform.hostCPU].endian == CPU[targetCPU].endian:
@@ -117,7 +117,7 @@ proc genRawSetData(cs: TBitSet, size: int): PRope =
         else: frmt = "0x$1, "
       else:
         frmt = "0x$1}$n"
-      appf(result, frmt, [toRope(toHex(Ze64(cs[i]), 2))])
+      appf(result, frmt, [toRope(toHex(ze64(cs[i]), 2))])
   else:
     result = intLiteral(bitSetToWord(cs, size))
     #  result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
@@ -127,7 +127,7 @@ proc genSetNode(p: BProc, n: PNode): PRope =
   var size = int(getSize(n.typ))
   toBitSet(n, cs)
   if size > 8:
-    var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId)
+    var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
     result = con("TMP", toRope(id))
     if id == gBackendId:
       # not found in cache:
@@ -155,7 +155,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
     of tyVar: result = OnUnknown
     of tyPtr: result = OnStack
     of tyRef: result = OnHeap
-    else: InternalError(n.info, "getStorageLoc")
+    else: internalError(n.info, "getStorageLoc")
   of nkBracketExpr, nkDotExpr, nkObjDownConv, nkObjUpConv:
     result = getStorageLoc(n.sons[0])
   else: result = OnUnknown
@@ -202,7 +202,7 @@ proc asgnComplexity(n: PNode): int =
     of nkRecList:
       for t in items(n):
         result += asgnComplexity(t)
-    else: nil
+    else: discard
 
 proc optAsgnLoc(a: TLoc, t: PType, field: PRope): TLoc =
   result.k = locField
@@ -242,7 +242,7 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
                      optAsgnLoc(src, field.typ, field.loc.r), newflags)
   of nkRecList:
     for child in items(t): genOptAsgnObject(p, dest, src, newflags, child)
-  else: nil
+  else: discard
 
 proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # Consider: 
@@ -357,7 +357,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
      tyInt..tyUInt64, tyRange, tyVar:
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
-  else: InternalError("genAssignment(" & $ty.kind & ')')
+  else: internalError("genAssignment: " & $ty.kind)
 
 proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
   if d.k == locNone: getTemp(p, typ, d)
@@ -403,62 +403,62 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
 
 proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
-  if d.k != locNone: InternalError(e.info, "binaryStmt")
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  if d.k != locNone: internalError(e.info, "binaryStmt")
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   lineCg(p, cpsStmts, frmt, rdLoc(a), rdLoc(b))
 
 proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
-  if d.k != locNone: InternalError(e.info, "unaryStmt")
-  InitLocExpr(p, e.sons[1], a)
+  if d.k != locNone: internalError(e.info, "unaryStmt")
+  initLocExpr(p, e.sons[1], a)
   lineCg(p, cpsStmts, frmt, [rdLoc(a)])
 
 proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
-  if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  if (d.k != locNone): internalError(e.info, "binaryStmtChar")
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   lineCg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
 
 proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
   assert(e.sons[1].typ != nil)
   assert(e.sons[2].typ != nil)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a), rdLoc(b)]))
 
 proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
   assert(e.sons[1].typ != nil)
   assert(e.sons[2].typ != nil)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [a.rdCharLoc, b.rdCharLoc]))
 
 proc unaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
-  InitLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[1], a)
   putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a)]))
 
 proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
-  InitLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[1], a)
   putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a)]))
 
 proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   const
-    prc: array[mAddi..mModi64, string] = ["addInt", "subInt", "mulInt",
+    prc: array[mAddI..mModI64, string] = ["addInt", "subInt", "mulInt",
       "divInt", "modInt", "addInt64", "subInt64", "mulInt64", "divInt64",
       "modInt64"]
-    opr: array[mAddi..mModi64, string] = ["+", "-", "*", "/", "%", "+", "-",
+    opr: array[mAddI..mModI64, string] = ["+", "-", "*", "/", "%", "+", "-",
       "*", "/", "%"]
   var a, b: TLoc
   assert(e.sons[1].typ != nil)
   assert(e.sons[2].typ != nil)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   var t = skipTypes(e.typ, abstractRange)
   if optOverflowCheck notin p.options:
     putIntoDest(p, d, e.typ, ropef("(NI$4)($2 $1 $3)", [toRope(opr[m]),
@@ -466,7 +466,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   else:
     var storage: PRope
     var size = getSize(t)
-    if size < platform.IntSize:
+    if size < platform.intSize:
       storage = toRope("NI") 
     else:
       storage = getTypeDesc(p.module, t)
@@ -474,7 +474,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
     linefmt(p, cpsLocals, "$1 $2;$n", storage, tmp)
     lineCg(p, cpsStmts, "$1 = #$2($3, $4);$n",
                          tmp, toRope(prc[m]), rdLoc(a), rdLoc(b))
-    if size < platform.IntSize or t.kind in {tyRange, tyEnum, tySet}:
+    if size < platform.intSize or t.kind in {tyRange, tyEnum, tySet}:
       linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
               tmp, intLiteral(firstOrd(t)), intLiteral(lastOrd(t)))
     putIntoDest(p, d, e.typ, ropef("(NI$1)($2)", [toRope(getSize(t)*8), tmp]))
@@ -490,7 +490,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
     a: TLoc
     t: PType
   assert(e.sons[1].typ != nil)
-  InitLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[1], a)
   t = skipTypes(e.typ, abstractRange)
   if optOverflowCheck in p.options:
     linefmt(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
@@ -556,11 +556,11 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       "($1 != $2)"]           # Xor
   var
     a, b: TLoc
-    s: biggestInt
+    s: BiggestInt
   assert(e.sons[1].typ != nil)
   assert(e.sons[2].typ != nil)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   # BUGFIX: cannot use result-type here, as it may be a boolean
   s = max(getSize(a.t), getSize(b.t)) * 8
   putIntoDest(p, d, e.typ,
@@ -571,8 +571,8 @@ proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
   var a, b: TLoc
   assert(e.sons[1].typ != nil)
   assert(e.sons[2].typ != nil)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   if a.t.callConv == ccClosure:
     putIntoDest(p, d, e.typ, 
       ropef("($1.ClPrc == $2.ClPrc && $1.ClEnv == $2.ClEnv)", [
@@ -615,7 +615,7 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     a: TLoc
     t: PType
   assert(e.sons[1].typ != nil)
-  InitLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[1], a)
   t = skipTypes(e.typ, abstractRange)
   putIntoDest(p, d, e.typ,
               ropef(unArithTab[op], [rdLoc(a), toRope(getSize(t) * 8),
@@ -623,7 +623,7 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
 
 proc genDeref(p: BProc, e: PNode, d: var TLoc) =
   var a: TLoc
-  if mapType(e.sons[0].typ) == ctArray:
+  if mapType(e.sons[0].typ) in {ctArray, ctPtrToArray}:
     # XXX the amount of hacks for C's arrays is incredible, maybe we should
     # simply wrap them in a struct? --> Losing auto vectorization then?
     expr(p, e.sons[0], d)
@@ -636,21 +636,21 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
       d.s = OnUnknown
     of tyPtr:
       d.s = OnUnknown         # BUGFIX!
-    else: InternalError(e.info, "genDeref " & $a.t.kind)
+    else: internalError(e.info, "genDeref " & $a.t.kind)
     putIntoDest(p, d, a.t.sons[0], ropef("(*$1)", [rdLoc(a)]))
 
 proc genAddr(p: BProc, e: PNode, d: var TLoc) =
   # careful  'addr(myptrToArray)' needs to get the ampersand:
   if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
     var a: TLoc
-    InitLocExpr(p, e.sons[0], a)
+    initLocExpr(p, e.sons[0], a)
     putIntoDest(p, d, e.typ, con("&", a.r))
     #Message(e.info, warnUser, "HERE NEW &")
   elif mapType(e.sons[0].typ) == ctArray:
     expr(p, e.sons[0], d)
   else:
     var a: TLoc
-    InitLocExpr(p, e.sons[0], a)
+    initLocExpr(p, e.sons[0], a)
     putIntoDest(p, d, e.typ, addrLoc(a))
 
 template inheritLocation(d: var TLoc, a: TLoc) =
@@ -660,7 +660,7 @@ template inheritLocation(d: var TLoc, a: TLoc) =
   
 proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
   initLocExpr(p, e.sons[0], a)
-  if e.sons[1].kind != nkSym: InternalError(e.info, "genRecordFieldAux")
+  if e.sons[1].kind != nkSym: internalError(e.info, "genRecordFieldAux")
   d.inheritLocation(a)
   discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
   result = a.t
@@ -694,13 +694,13 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
     var field: PSym = nil
     while ty != nil:
       if ty.kind notin {tyTuple, tyObject}:
-        InternalError(e.info, "genRecordField")
+        internalError(e.info, "genRecordField")
       field = lookupInRecord(ty.n, f.name)
       if field != nil: break
       if gCmd != cmdCompileToCpp: 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")
+      ty = getUniqueType(ty.sons[0])
+    if field == nil: internalError(e.info, "genRecordField 2 ")
+    if field.loc.r == nil: internalError(e.info, "genRecordField 3")
     appf(r, ".$1", [field.loc.r])
     putIntoDest(p, d, field.typ, r)
 
@@ -716,11 +716,11 @@ proc genFieldCheck(p: BProc, e: PNode, obj: PRope, field: PSym) =
     if op.magic == mNot: it = it.sons[1]
     assert(it.sons[2].kind == nkSym)
     initLoc(test, locNone, it.typ, OnStack)
-    InitLocExpr(p, it.sons[1], u)
+    initLocExpr(p, it.sons[1], u)
     initLoc(v, locExpr, it.sons[2].typ, OnUnknown)
     v.r = ropef("$1.$2", [obj, it.sons[2].sym.loc.r])
     genInExprAux(p, it, u, v, test)
-    let id = NodeTableTestOrSet(p.module.dataCache,
+    let id = nodeTableTestOrSet(p.module.dataCache,
                                newStrNode(nkStrLit, field.name.s), gBackendId)
     let strLit = if id == gBackendId: getStrLit(p.module, field.name.s)
                  else: con("TMP", toRope(id))
@@ -750,9 +750,9 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
       if field != nil: break
       if gCmd != cmdCompileToCpp: app(r, ".Sup")
       ty = getUniqueType(ty.sons[0])
-    if field == nil: InternalError(e.info, "genCheckedRecordField")
+    if field == nil: internalError(e.info, "genCheckedRecordField")
     if field.loc.r == nil:
-      InternalError(e.info, "genCheckedRecordField") # generate the checks:
+      internalError(e.info, "genCheckedRecordField") # generate the checks:
     genFieldCheck(p, e, r, field)
     app(r, rfmt(nil, ".$1", field.loc.r))
     putIntoDest(p, d, field.typ, r)
@@ -766,7 +766,7 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
   var ty = skipTypes(skipTypes(a.t, abstractVarRange), abstractPtrs)
   var first = intLiteral(firstOrd(ty))
   # emit range check:
-  if (optBoundsCheck in p.options):
+  if optBoundsCheck in p.options and tfUncheckedArray notin ty.flags:
     if not isConstExpr(e.sons[1]):
       # semantic pass has already checked for const index expressions
       if firstOrd(ty) == 0:
@@ -804,13 +804,13 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) =
   putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
               rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)))
 
-proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
+proc genSeqElem(p: BProc, e: PNode, d: var TLoc) =
   var a, b: TLoc
   initLocExpr(p, e.sons[0], a)
   initLocExpr(p, e.sons[1], b)
   var ty = skipTypes(a.t, abstractVarRange)
   if ty.kind in {tyRef, tyPtr}:
-    ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
+    ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check:
   if optBoundsCheck in p.options:
     if ty.kind == tyString:
       linefmt(p, cpsStmts,
@@ -868,7 +868,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
 proc genEcho(p: BProc, n: PNode) =
   # this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
   # is threadsafe.
-  discard lists.IncludeStr(p.module.headerFiles, "<stdio.h>")
+  discard lists.includeStr(p.module.headerFiles, "<stdio.h>")
   var args: PRope = nil
   var a: TLoc
   for i in countup(1, n.len-1):
@@ -877,6 +877,9 @@ proc genEcho(p: BProc, n: PNode) =
   linefmt(p, cpsStmts, "printf($1$2);$n",
           makeCString(repeatStr(n.len-1, "%s") & tnl), args)
 
+proc gcUsage(n: PNode) =
+  if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree)
+
 proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   #   <Nimrod code>
   #   s = 'Hello ' & name & ', how do you feel?' & 'z'
@@ -902,12 +905,12 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   for i in countup(0, sonsLen(e) - 2):
     # compute the length expression:
     initLocExpr(p, e.sons[i + 1], a)
-    if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
-      Inc(L)
+    if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
+      inc(L)
       app(appends, rfmt(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a)))
     else:
       if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
-        Inc(L, len(e.sons[i + 1].strVal))
+        inc(L, len(e.sons[i + 1].strVal))
       else:
         appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
       app(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
@@ -918,6 +921,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
     keepAlive(p, tmp)
   else:
     genAssignment(p, d, tmp, {needToKeepAlive}) # no need for deep copying
+  gcUsage(e)
 
 proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
   #  <Nimrod code>
@@ -940,13 +944,13 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
   for i in countup(0, sonsLen(e) - 3):
     # compute the length expression:
     initLocExpr(p, e.sons[i + 2], a)
-    if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
-      Inc(L)
+    if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
+      inc(L)
       app(appends, rfmt(p.module, "#appendChar($1, $2);$n",
                         rdLoc(dest), rdLoc(a)))
     else:
       if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
-        Inc(L, len(e.sons[i + 2].strVal))
+        inc(L, len(e.sons[i + 2].strVal))
       else:
         appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
       app(appends, rfmt(p.module, "#appendString($1, $2);$n",
@@ -955,6 +959,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
           rdLoc(dest), lens, toRope(L))
   keepAlive(p, dest)
   app(p.s(cpsStmts), appends)
+  gcUsage(e)
 
 proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
   # seq &= x  -->
@@ -965,20 +970,21 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
                          else:
                            "$1 = ($2) #incrSeq($1, sizeof($3));$n"
   var a, b, dest: TLoc
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   lineCg(p, cpsStmts, seqAppendPattern, [
       rdLoc(a),
       getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
-      getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
+      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())
   genAssignment(p, dest, b, {needToCopy, afDestIsNil})
+  gcUsage(e)
 
 proc genReset(p: BProc, n: PNode) = 
   var a: TLoc
-  InitLocExpr(p, n.sons[1], a)
+  initLocExpr(p, n.sons[1], a)
   linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
           addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange)))
 
@@ -989,8 +995,8 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: PRope) =
   initLoc(b, locExpr, a.t, OnHeap)
   if sizeExpr.isNil:
     sizeExpr = ropef("sizeof($1)",
-        getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange)))
-  let args = [getTypeDesc(p.module, reftype),
+        getTypeDesc(p.module, skipTypes(refType.sons[0], abstractRange)))
+  let args = [getTypeDesc(p.module, refType),
               genTypeInfo(p.module, refType),
               sizeExpr]
   if a.s == OnHeap and usesNativeGC():
@@ -1009,19 +1015,20 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: PRope) =
 
 proc genNew(p: BProc, e: PNode) =
   var a: TLoc
-  InitLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[1], a)
   # 'genNew' also handles 'unsafeNew':
   if e.len == 3:
     var se: TLoc
-    InitLocExpr(p, e.sons[2], se)
+    initLocExpr(p, e.sons[2], se)
     rawGenNew(p, a, se.rdLoc)
   else:
     rawGenNew(p, a, nil)
+  gcUsage(e)
 
 proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
   let seqtype = skipTypes(dest.t, abstractVarRange)
   let args = [getTypeDesc(p.module, seqtype),
-              genTypeInfo(p.module, seqType), length]
+              genTypeInfo(p.module, seqtype), length]
   var call: TLoc
   initLoc(call, locExpr, dest.t, OnHeap)
   if dest.s == OnHeap and usesNativeGC():
@@ -1037,9 +1044,10 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
   
 proc genNewSeq(p: BProc, e: PNode) =
   var a, b: TLoc
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   genNewSeqAux(p, a, b.rdLoc)
+  gcUsage(e)
   
 proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
   var tmp: TLoc
@@ -1051,6 +1059,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     rawGenNew(p, tmp, nil)
     t = t.sons[0].skipTypes(abstractInst)
     r = ropef("(*$1)", r)
+    gcUsage(e)
   discard getTypeDesc(p.module, t)
   for i in 1 .. <e.len:
     let it = e.sons[i]
@@ -1062,15 +1071,15 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
       field = lookupInRecord(ty.n, it.sons[0].sym.name)
       if field != nil: break
       if gCmd != cmdCompileToCpp: app(tmp2.r, ".Sup")
-      ty = GetUniqueType(ty.sons[0])
-    if field == nil or field.loc.r == nil: InternalError(e.info, "genObjConstr")
+      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:
       genFieldCheck(p, it.sons[2], r, field)
     app(tmp2.r, ".")
     app(tmp2.r, field.loc.r)
     tmp2.k = locTemp
     tmp2.t = field.loc.t
-    tmp2.s = onHeap
+    tmp2.s = if isRef: OnHeap else: OnStack
     tmp2.heapRoot = tmp.r
     expr(p, it.sons[1], tmp2)
   if d.k == locNone:
@@ -1089,6 +1098,7 @@ proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
     arr.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
     arr.s = OnHeap            # we know that sequences are on the heap
     expr(p, t.sons[i], arr)
+  gcUsage(t)
 
 proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
   var elem, a, arr: TLoc
@@ -1118,17 +1128,18 @@ proc genNewFinalize(p: BProc, e: PNode) =
     ti: PRope
     oldModule: BModule
   refType = skipTypes(e.sons[1].typ, abstractVarRange)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], f)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], f)
   initLoc(b, locExpr, a.t, OnHeap)
   ti = genTypeInfo(p.module, refType)
   appf(p.module.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
   b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
       getTypeDesc(p.module, refType),
-      ti, getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
+      ti, getTypeDesc(p.module, skipTypes(refType.sons[0], abstractRange))])
   genAssignment(p, a, b, {needToKeepAlive})  # set the object type:
   bt = skipTypes(refType.sons[0], abstractRange)
   genObjectInit(p, cpsStmts, bt, a, false)
+  gcUsage(e)
 
 proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
   var a: TLoc
@@ -1140,13 +1151,13 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
   while t.kind in {tyVar, tyPtr, tyRef}:
     if t.kind != tyVar: nilCheck = r
     r = rfmt(nil, "(*$1)", r)
-    t = skipTypes(t.sons[0], typedescInst)
+    t = skipTypes(t.lastSon, typedescInst)
   if gCmd != cmdCompileToCpp:
     while (t.kind == tyObject) and (t.sons[0] != nil):
       app(r, ~".Sup")
       t = skipTypes(t.sons[0], typedescInst)
   if isObjLackingTypeField(t):
-    GlobalError(x.info, errGenerated, 
+    globalError(x.info, errGenerated, 
       "no 'of' operator available for pure objects")
   if nilCheck != nil:
     r = rfmt(p.module, "(($1) && #isObj($2.m_type, $3))",
@@ -1162,7 +1173,7 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) =
 proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   # XXX we don't generate keep alive info for now here
   var a: TLoc
-  InitLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[1], a)
   var t = skipTypes(e.sons[1].typ, abstractVarRange)
   case t.kind
   of tyInt..tyInt64, tyUInt..tyUInt64:
@@ -1194,7 +1205,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
     of tyArray, tyArrayConstr:
       putIntoDest(p, b, e.typ,
                   ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
-    else: InternalError(e.sons[0].info, "genRepr()")
+    else: internalError(e.sons[0].info, "genRepr()")
     putIntoDest(p, d, e.typ, 
         ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
         genTypeInfo(p.module, elemType(t))]))
@@ -1206,6 +1217,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   else:
     putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
                                    [addrLoc(a), genTypeInfo(p.module, t)]))
+  gcUsage(e)
 
 proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
   var t = skipTypes(e.sons[1].typ, abstractVarRange)
@@ -1213,20 +1225,21 @@ proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
 
 proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
-  InitLocExpr(p, n.sons[1], a)
+  initLocExpr(p, n.sons[1], a)
   a.r = ropecg(p.module, frmt, [rdLoc(a)])
   if d.k == locNone: getTemp(p, n.typ, d)
   genAssignment(p, d, a, {needToKeepAlive})
+  gcUsage(n)
 
 proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   var a = e.sons[1]
   if a.kind == nkHiddenAddr: a = a.sons[0]
-  var typ = skipTypes(a.Typ, abstractVar)
+  var typ = skipTypes(a.typ, abstractVar)
   case typ.kind
   of tyOpenArray, tyVarargs:
     if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
     else: unaryExpr(p, e, d, "$1Len0")
-  of tyCstring:
+  of tyCString:
     if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
     else: unaryExpr(p, e, d, "strlen($1)")
   of tyString, tySequence:
@@ -1238,15 +1251,15 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       else: unaryExpr(p, e, d, "$1->len")
   of tyArray, tyArrayConstr:
     # YYY: length(sideeffect) is optimized away incorrectly?
-    if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(Typ)))
+    if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(typ)))
     else: putIntoDest(p, d, e.typ, toRope(lengthOrd(typ)))
-  else: InternalError(e.info, "genArrayLen()")
+  else: internalError(e.info, "genArrayLen()")
 
 proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
   var a, b: TLoc
   assert(d.k == locNone)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  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:
       "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
@@ -1257,10 +1270,12 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
       rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
       getTypeDesc(p.module, t.sons[0])])
   keepAlive(p, a)
+  gcUsage(e)
 
 proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
   binaryStmt(p, e, d, "$1 = #setLengthStr($1, $2);$n")
-  keepAlive(P, d)
+  keepAlive(p, d)
+  gcUsage(e)
 
 proc genSwap(p: BProc, e: PNode, d: var TLoc) =
   # swap(a, b) -->
@@ -1269,8 +1284,8 @@ proc genSwap(p: BProc, e: PNode, d: var TLoc) =
   # b = temp
   var a, b, tmp: TLoc
   getTemp(p, skipTypes(e.sons[1].typ, abstractVar), tmp)
-  InitLocExpr(p, e.sons[1], a) # eval a
-  InitLocExpr(p, e.sons[2], b) # eval b
+  initLocExpr(p, e.sons[1], a) # eval a
+  initLocExpr(p, e.sons[2], b) # eval b
   genAssignment(p, tmp, a, {})
   genAssignment(p, a, b, {})
   genAssignment(p, b, tmp, {})
@@ -1286,10 +1301,10 @@ proc rdSetElemLoc(a: TLoc, setType: PType): PRope =
 proc fewCmps(s: PNode): bool =
   # this function estimates whether it is better to emit code
   # for constructing the set or generating a bunch of comparisons directly
-  if s.kind != nkCurly: InternalError(s.info, "fewCmps")
+  if s.kind != nkCurly: internalError(s.info, "fewCmps")
   if (getSize(s.typ) <= platform.intSize) and (nfAllConst in s.flags):
     result = false            # it is better to emit the set generation code
-  elif elemType(s.typ).Kind in {tyInt, tyInt16..tyInt64}:
+  elif elemType(s.typ).kind in {tyInt, tyInt16..tyInt64}:
     result = true             # better not emit the set if int is basetype!
   else:
     result = sonsLen(s) <= 8  # 8 seems to be a good value
@@ -1308,13 +1323,13 @@ proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
 proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a, b: TLoc
   assert(d.k == locNone)
-  InitLocExpr(p, e.sons[1], a)
-  InitLocExpr(p, e.sons[2], b)
+  initLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[2], b)
   lineF(p, cpsStmts, frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
 
 proc genInOp(p: BProc, e: PNode, d: var TLoc) =
   var a, b, x, y: TLoc
-  if (e.sons[1].Kind == nkCurly) and fewCmps(e.sons[1]):
+  if (e.sons[1].kind == nkCurly) and fewCmps(e.sons[1]):
     # a set constructor but not a constant set:
     # do not emit the set, but generate a bunch of comparisons; and if we do
     # so, we skip the unnecessary range check: This is a semantical extension
@@ -1328,13 +1343,13 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
     b.r = toRope("(")
     var length = sonsLen(e.sons[1])
     for i in countup(0, length - 1):
-      if e.sons[1].sons[i].Kind == nkRange:
-        InitLocExpr(p, e.sons[1].sons[i].sons[0], x)
-        InitLocExpr(p, e.sons[1].sons[i].sons[1], y)
+      if e.sons[1].sons[i].kind == nkRange:
+        initLocExpr(p, e.sons[1].sons[i].sons[0], x)
+        initLocExpr(p, e.sons[1].sons[i].sons[1], y)
         appf(b.r, "$1 >= $2 && $1 <= $3",
              [rdCharLoc(a), rdCharLoc(x), rdCharLoc(y)])
       else:
-        InitLocExpr(p, e.sons[1].sons[i], x)
+        initLocExpr(p, e.sons[1].sons[i], x)
         appf(b.r, "$1 == $2", [rdCharLoc(a), rdCharLoc(x)])
       if i < length - 1: app(b.r, " || ")
     app(b.r, ")")
@@ -1342,8 +1357,8 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
   else:
     assert(e.sons[1].typ != nil)
     assert(e.sons[2].typ != nil)
-    InitLocExpr(p, e.sons[1], a)
-    InitLocExpr(p, e.sons[2], b)
+    initLocExpr(p, e.sons[1], a)
+    initLocExpr(p, e.sons[2], b)
     genInExprAux(p, e, a, b, d)
 
 proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
@@ -1356,7 +1371,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
         "if ($3) $3 = (memcmp($4, $5, $2) != 0);$n",
       "&", "|", "& ~", "^"]
   var a, b, i: TLoc
-  var setType = skipTypes(e.sons[1].Typ, abstractVar)
+  var setType = skipTypes(e.sons[1].typ, abstractVar)
   var size = int(getSize(setType))
   case size
   of 1, 2, 4, 8:
@@ -1391,7 +1406,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       getTemp(p, getSysType(tyInt), i) # our counter
       initLocExpr(p, e.sons[1], a)
       initLocExpr(p, e.sons[2], b)
-      if d.k == locNone: getTemp(p, a.t, d)
+      if d.k == locNone: getTemp(p, getSysType(tyBool), d)
       lineF(p, cpsStmts, lookupOpr[op],
            [rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
     of mEqSet:
@@ -1421,7 +1436,7 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
   # we use whatever C gives us. Except if we have a value-type, we need to go
   # through its address:
   var a: TLoc
-  InitLocExpr(p, e.sons[1], a)
+  initLocExpr(p, e.sons[1], a)
   let etyp = skipTypes(e.typ, abstractRange)
   if etyp.kind in ValueTypes and lfIndirect notin a.flags:
     putIntoDest(p, d, e.typ, ropef("(*($1*) ($2))",
@@ -1463,13 +1478,13 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
   var dest = skipTypes(n.typ, abstractVar)
   # range checks for unsigned turned out to be buggy and annoying:
   if optRangeCheck notin p.options or dest.kind in {tyUInt..tyUInt64}:
-    InitLocExpr(p, n.sons[0], a)
+    initLocExpr(p, n.sons[0], a)
     putIntoDest(p, d, n.typ, ropef("(($1) ($2))",
         [getTypeDesc(p.module, dest), rdCharLoc(a)]))
   else:
-    InitLocExpr(p, n.sons[0], a)
+    initLocExpr(p, n.sons[0], a)
     if leValue(n.sons[2], n.sons[1]):
-      InternalError(n.info, "range check will always fail; empty range")
+      internalError(n.info, "range check will always fail; empty range")
     putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
         getTypeDesc(p.module, dest), rdCharLoc(a),
         genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
@@ -1492,6 +1507,7 @@ proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
   initLocExpr(p, n.sons[0], a)
   putIntoDest(p, d, skipTypes(n.typ, abstractVar),
               ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]))
+  gcUsage(n)
 
 proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
   var x: TLoc
@@ -1511,17 +1527,17 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
     binaryExpr(p, e, d, "#eqStrings($1, $2)")
 
 proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
-  if {optNanCheck, optInfCheck} * p.options != {}:
+  if {optNaNCheck, optInfCheck} * p.options != {}:
     const opr: array[mAddF64..mDivF64, string] = ["+", "-", "*", "/"]
     var a, b: TLoc
     assert(e.sons[1].typ != nil)
     assert(e.sons[2].typ != nil)
-    InitLocExpr(p, e.sons[1], a)
-    InitLocExpr(p, e.sons[2], b)
+    initLocExpr(p, e.sons[1], a)
+    initLocExpr(p, e.sons[2], b)
     putIntoDest(p, d, e.typ, rfmt(nil, "(($4)($2) $1 ($4)($3))",
                                   toRope(opr[m]), rdLoc(a), rdLoc(b),
                                   getSimpleTypeDesc(p.module, e[1].typ)))
-    if optNanCheck in p.options:
+    if optNaNCheck in p.options:
       linefmt(p, cpsStmts, "#nanCheck($1);$n", rdLoc(d))
     if optInfCheck in p.options:
       linefmt(p, cpsStmts, "#infCheck($1);$n", rdLoc(d))
@@ -1537,30 +1553,30 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mAddF64..mDivF64: binaryFloatArith(p, e, d, op)
   of mShrI..mXor: binaryArith(p, e, d, op)
   of mEqProc: genEqProc(p, e, d)
-  of mAddi..mModi64: binaryArithOverflow(p, e, d, op)
+  of mAddI..mModI64: binaryArithOverflow(p, e, d, op)
   of mRepr: genRepr(p, e, d)
   of mGetTypeInfo: genGetTypeInfo(p, e, d)
   of mSwap: genSwap(p, e, d)
   of mUnaryLt: 
-    if not (optOverflowCheck in p.Options): unaryExpr(p, e, d, "$1 - 1")
+    if not (optOverflowCheck in p.options): unaryExpr(p, e, d, "$1 - 1")
     else: unaryExpr(p, e, d, "#subInt($1, 1)")
   of mPred:
     # XXX: range checking?
-    if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 - $2")
+    if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 - $2")
     else: binaryExpr(p, e, d, "#subInt($1, $2)")
   of mSucc:
     # XXX: range checking?
-    if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 + $2")
+    if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 + $2")
     else: binaryExpr(p, e, d, "#addInt($1, $2)")
   of mInc:
-    if not (optOverflowCheck in p.Options):
+    if not (optOverflowCheck in p.options):
       binaryStmt(p, e, d, "$1 += $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
       binaryStmt(p, e, d, "$1 = #addInt64($1, $2);$n")
     else:
       binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n")
   of ast.mDec:
-    if not (optOverflowCheck in p.Options):
+    if not (optOverflowCheck in p.options):
       binaryStmt(p, e, d, "$1 -= $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
       binaryStmt(p, e, d, "$1 = #subInt64($1, $2);$n")
@@ -1623,7 +1639,7 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
   if (nfAllConst in n.flags) and (d.k == locNone) and (sonsLen(n) > 0):
     var t = getUniqueType(n.typ)
     discard getTypeDesc(p.module, t) # so that any fields are initialized
-    var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId)
+    var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
     fillLoc(d, locData, t, con("TMP", toRope(id)), OnHeap)
     if id == gBackendId:
       # expression not found in the cache:
@@ -1699,14 +1715,14 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
                       [rdLoc(d), mangleRecFieldName(t.n.sons[i].sym, t)])
         expr(p, it, rec)
 
-proc IsConstClosure(n: PNode): bool {.inline.} =
+proc isConstClosure(n: PNode): bool {.inline.} =
   result = n.sons[0].kind == nkSym and isRoutine(n.sons[0].sym) and
       n.sons[1].kind == nkNilLit
       
 proc genClosure(p: BProc, n: PNode, d: var TLoc) =
   assert n.kind == nkClosure
   
-  if IsConstClosure(n):
+  if isConstClosure(n):
     inc(p.labels)
     var tmp = con("LOC", toRope(p.labels))
     appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
@@ -1751,7 +1767,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
     while t.kind in {tyVar, tyPtr, tyRef}:
       if t.kind != tyVar: nilCheck = r
       r = ropef("(*$1)", [r])
-      t = skipTypes(t.sons[0], abstractInst)
+      t = skipTypes(t.lastSon, abstractInst)
     if gCmd != cmdCompileToCpp:
       while t.kind == tyObject and t.sons[0] != nil:
         app(r, ".Sup")
@@ -1790,7 +1806,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
 proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
   var t = getUniqueType(n.typ)
   discard getTypeDesc(p.module, t) # so that any fields are initialized
-  var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId)
+  var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
   var tmp = con("TMP", toRope(id))
   
   if id == gBackendId:
@@ -1808,7 +1824,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
   case n.kind
   of nkSym:
     var sym = n.sym
-    case sym.Kind
+    case sym.kind
     of skMethod:
       if sym.getBody.kind == nkEmpty or sfDispatcher in sym.flags:
         # we cannot produce code for the dispatcher yet:
@@ -1817,10 +1833,10 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
       else:
         genProc(p.module, sym)
       putLocIntoDest(p, d, sym.loc)
-    of skProc, skConverter, skIterator:
+    of skProc, skConverter, skIterators:
       genProc(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(n.info, "expr: proc not init " & sym.name.s)
+        internalError(n.info, "expr: proc not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
     of skConst:
       if sfFakeConst in sym.flags:
@@ -1835,9 +1851,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
     of skVar, skForVar, skResult, skLet:
       if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(n.info, "expr: var not init " & sym.name.s)
+        internalError(n.info, "expr: var not init " & sym.name.s)
       if sfThread in sym.flags:
-        AccessThreadLocalVar(p, sym)
+        accessThreadLocalVar(p, sym)
         if emulatedThreadVars(): 
           putIntoDest(p, d, sym.loc.t, con("NimTV->", sym.loc.r))
         else:
@@ -1846,13 +1862,13 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         putLocIntoDest(p, d, sym.loc)
     of skTemp:
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(n.info, "expr: temp not init " & sym.name.s)
+        internalError(n.info, "expr: temp not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
     of skParam:
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(n.info, "expr: param not init " & sym.name.s)
+        internalError(n.info, "expr: param not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
-    else: InternalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
+    else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
   of nkNilLit:
     if not isEmptyType(n.typ):
       putIntoDest(p, d, n.typ, genLiteral(p, n))
@@ -1901,14 +1917,14 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
   of nkHiddenAddr, nkAddr: genAddr(p, n, d)
   of nkBracketExpr:
     var ty = skipTypes(n.sons[0].typ, abstractVarRange)
-    if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.sons[0], abstractVarRange)
+    if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
     case ty.kind
     of tyArray, tyArrayConstr: genArrayElem(p, n, d)
     of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, d)
     of tySequence, tyString: genSeqElem(p, n, d)
     of tyCString: genCStringElem(p, n, d)
     of tyTuple: genTupleElem(p, n, d)
-    else: InternalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
+    else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
   of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d)
   of nkDotExpr: genRecordField(p, n, d)
   of nkCheckedFieldExpr: genCheckedRecordField(p, n, d)
@@ -1928,12 +1944,11 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
     var sym = n.sons[namePos].sym
     genProc(p.module, sym)
     if sym.loc.r == nil or sym.loc.t == nil:
-      InternalError(n.info, "expr: proc not init " & sym.name.s)
+      internalError(n.info, "expr: proc not init " & sym.name.s)
     putLocIntoDest(p, d, sym.loc)
   of nkClosure: genClosure(p, n, d)
-  of nkMetaNode: expr(p, n.sons[0], d)
 
-  of nkEmpty:  nil
+  of nkEmpty: discard
   of nkWhileStmt: genWhileStmt(p, n)
   of nkVarSection, nkLetSection: genVarStmt(p, n)
   of nkConstSection: genConstStmt(p, n)
@@ -1963,7 +1978,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
   of nkCommentStmt, nkIteratorDef, nkIncludeStmt, 
      nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, 
      nkFromStmt, nkTemplateDef, nkMacroDef: 
-    nil
+    discard
   of nkPragma: genPragma(p, n)
   of nkProcDef, nkMethodDef, nkConverterDef: 
     if (n.sons[genericParamsPos].kind == nkEmpty):
@@ -1984,7 +1999,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
   of nkState: genState(p, n)
   of nkGotoState: genGotoState(p, n)
   of nkBreakState: genBreakState(p, n)
-  else: InternalError(n.info, "expr(" & $n.kind & "); unknown node kind")
+  else: internalError(n.info, "expr(" & $n.kind & "); unknown node kind")
 
 proc genNamedConstExpr(p: BProc, n: PNode): PRope =
   if n.kind == nkExprColonExpr: result = genConstExpr(p, n.sons[1])
@@ -2022,7 +2037,7 @@ proc genConstSeq(p: BProc, n: PNode, t: PType): PRope =
   result = ropef("(($1)&$2)", [getTypeDesc(p.module, t), result])
 
 proc genConstExpr(p: BProc, n: PNode): PRope =
-  case n.Kind
+  case n.kind
   of nkHiddenStdConv, nkHiddenSubConv:
     result = genConstExpr(p, n.sons[1])
   of nkCurly:
diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim
index c6c294b97..2d27257ce 100644
--- a/compiler/ccgmerge.nim
+++ b/compiler/ccgmerge.nim
@@ -108,7 +108,7 @@ proc genMergeInfo*(m: BModule): PRope =
   s.add("labels:")
   encodeVInt(m.labels, s)
   s.add(" hasframe:")
-  encodeVInt(ord(m.FrameDeclared), s)
+  encodeVInt(ord(m.frameDeclared), s)
   s.add(tnl)
   s.add("*/")
   result = s.toRope
@@ -119,8 +119,8 @@ proc skipWhite(L: var TBaseLexer) =
   var pos = L.bufpos
   while true:
     case ^pos
-    of CR: pos = nimlexbase.HandleCR(L, pos)
-    of LF: pos = nimlexbase.HandleLF(L, pos)
+    of CR: pos = nimlexbase.handleCR(L, pos)
+    of LF: pos = nimlexbase.handleLF(L, pos)
     of ' ': inc pos
     else: break
   L.bufpos = pos
@@ -129,8 +129,8 @@ proc skipUntilCmd(L: var TBaseLexer) =
   var pos = L.bufpos
   while true:
     case ^pos
-    of CR: pos = nimlexbase.HandleCR(L, pos)
-    of LF: pos = nimlexbase.HandleLF(L, pos)
+    of CR: pos = nimlexbase.handleCR(L, pos)
+    of LF: pos = nimlexbase.handleLF(L, pos)
     of '\0': break
     of '/': 
       if ^(pos+1) == '*' and ^(pos+2) == '\t':
@@ -145,33 +145,6 @@ proc atEndMark(buf: cstring, pos: int): bool =
   while s < NimMergeEndMark.len and buf[pos+s] == NimMergeEndMark[s]: inc s
   result = s == NimMergeEndMark.len
 
-when false:
-  proc readVerbatimSection(L: var TBaseLexer): PRope = 
-    var pos = L.bufpos
-    var buf = L.buf
-    result = newMutableRope(30_000)
-    while true:
-      case buf[pos]
-      of CR:
-        pos = nimlexbase.HandleCR(L, pos)
-        buf = L.buf
-        result.data.add(tnl)
-      of LF:
-        pos = nimlexbase.HandleLF(L, pos)
-        buf = L.buf
-        result.data.add(tnl)
-      of '\0':
-        InternalError("ccgmerge: expected: " & NimMergeEndMark)
-        break
-      else: 
-        if atEndMark(buf, pos):
-          inc pos, NimMergeEndMark.len
-          break
-        result.data.add(buf[pos])
-        inc pos
-    L.bufpos = pos
-    freezeMutableRope(result)
-
 proc readVerbatimSection(L: var TBaseLexer): PRope = 
   var pos = L.bufpos
   var buf = L.buf
@@ -179,15 +152,15 @@ proc readVerbatimSection(L: var TBaseLexer): PRope =
   while true:
     case buf[pos]
     of CR:
-      pos = nimlexbase.HandleCR(L, pos)
+      pos = nimlexbase.handleCR(L, pos)
       buf = L.buf
       r.add(tnl)
     of LF:
-      pos = nimlexbase.HandleLF(L, pos)
+      pos = nimlexbase.handleLF(L, pos)
       buf = L.buf
       r.add(tnl)
     of '\0':
-      InternalError("ccgmerge: expected: " & NimMergeEndMark)
+      internalError("ccgmerge: expected: " & NimMergeEndMark)
       break
     else: 
       if atEndMark(buf, pos):
@@ -208,7 +181,7 @@ proc readKey(L: var TBaseLexer, result: var string) =
   if buf[pos] != ':': internalError("ccgmerge: ':' expected")
   L.bufpos = pos + 1 # skip ':'
 
-proc NewFakeType(id: int): PType = 
+proc newFakeType(id: int): PType = 
   new(result)
   result.id = id
 
@@ -224,7 +197,7 @@ proc readTypeCache(L: var TBaseLexer, result: var TIdTable) =
     # XXX little hack: we create a "fake" type object with the correct Id
     # better would be to adapt the data structure to not even store the
     # object as key, but only the Id
-    IdTablePut(result, newFakeType(key), value.toRope)
+    idTablePut(result, newFakeType(key), value.toRope)
   inc L.bufpos
 
 proc readIntSet(L: var TBaseLexer, result: var TIntSet) =
@@ -249,14 +222,14 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) =
     of "declared":  readIntSet(L, m.declaredThings)
     of "typeInfo":  readIntSet(L, m.typeInfoMarker)
     of "labels":    m.labels = decodeVInt(L.buf, L.bufpos)
-    of "hasframe":  m.FrameDeclared = decodeVInt(L.buf, L.bufpos) != 0
-    else: InternalError("ccgmerge: unkown key: " & k)
+    of "hasframe":  m.frameDeclared = decodeVInt(L.buf, L.bufpos) != 0
+    else: internalError("ccgmerge: unkown key: " & k)
 
 when not defined(nimhygiene):
   {.pragma: inject.}
   
 template withCFile(cfilename: string, body: stmt) {.immediate.} = 
-  var s = LLStreamOpen(cfilename, fmRead)
+  var s = llStreamOpen(cfilename, fmRead)
   if s == nil: return
   var L {.inject.}: TBaseLexer
   openBaseLexer(L, s)
@@ -285,7 +258,7 @@ proc readMergeSections(cfilename: string, m: var TMergeSections) =
   withCFile(cfilename):
     readKey(L, k)
     if k == "NIM_merge_INFO":   
-      nil
+      discard
     elif ^L.bufpos == '*' and ^(L.bufpos+1) == '/':
       inc(L.bufpos, 2)
       # read back into section
@@ -300,9 +273,9 @@ proc readMergeSections(cfilename: string, m: var TMergeSections) =
         if sectionB >= 0 and sectionB <= high(TCProcSection).int:
           m.p[TCProcSection(sectionB)] = verbatim
         else:
-          InternalError("ccgmerge: unknown section: " & k)
+          internalError("ccgmerge: unknown section: " & k)
     else:
-      InternalError("ccgmerge: '*/' expected")
+      internalError("ccgmerge: '*/' expected")
 
 proc mergeRequired*(m: BModule): bool =
   for i in cfsHeaders..cfsProcs:
@@ -323,4 +296,3 @@ proc mergeFiles*(cfilename: string, m: BModule) =
     m.s[i] = con(old.f[i], m.s[i])
   for i in low(TCProcSection)..high(TCProcSection):
     m.initProc.s(i) = con(old.p[i], m.initProc.s(i))
-
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index ac4bbb79f..311149cb3 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -16,7 +16,7 @@ const
     # above X strings a hash-switch for strings is generated
 
 proc registerGcRoot(p: BProc, v: PSym) =
-  if gSelectedGc in {gcMarkAndSweep, gcGenerational} and
+  if gSelectedGC in {gcMarkAndSweep, gcGenerational} and
       containsGarbageCollectedRef(v.loc.t):
     # we register a specialized marked proc here; this has the advantage
     # that it works out of the box for thread local storage then :-)
@@ -26,7 +26,7 @@ proc registerGcRoot(p: BProc, v: PSym) =
 
 proc genVarTuple(p: BProc, n: PNode) = 
   var tup, field: TLoc
-  if n.kind != nkVarTuple: InternalError(n.info, "genVarTuple")
+  if n.kind != nkVarTuple: internalError(n.info, "genVarTuple")
   var L = sonsLen(n)
   genLineDir(p, n)
   initLocExpr(p, n.sons[L-1], tup)
@@ -45,7 +45,7 @@ proc genVarTuple(p: BProc, n: PNode) =
     if t.kind == tyTuple: 
       field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
     else: 
-      if t.n.sons[i].kind != nkSym: InternalError(n.info, "genVarTuple")
+      if t.n.sons[i].kind != nkSym: internalError(n.info, "genVarTuple")
       field.r = ropef("$1.$2", 
                       [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
     putLocIntoDest(p, v.loc, field)
@@ -62,9 +62,10 @@ proc startBlock(p: BProc, start: TFormatStr = "{$n",
   lineCg(p, cpsStmts, start, args)
   inc(p.labels)
   result = len(p.blocks)
-  setlen(p.blocks, result + 1)
+  setLen(p.blocks, result + 1)
   p.blocks[result].id = p.labels
   p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
+  p.blocks[result].nestedExceptStmts = p.inExceptBlock.int16
 
 proc assignLabel(b: var TBlock): PRope {.inline.} =
   b.label = con("LA", b.id.toRope)
@@ -81,7 +82,7 @@ proc endBlock(p: BProc, blockEnd: PRope) =
   let topBlock = p.blocks.len-1
   # the block is merged into the parent block
   app(p.blocks[topBlock-1].sections[cpsStmts], p.blocks[topBlock].blockBody)
-  setlen(p.blocks, topBlock)
+  setLen(p.blocks, topBlock)
   # this is done after the block is popped so $n is
   # properly indented when pretty printing is enabled
   line(p, cpsStmts, blockEnd)
@@ -126,7 +127,7 @@ proc genGotoState(p: BProc, n: PNode) =
   var a: TLoc
   initLocExpr(p, n.sons[0], a)
   lineF(p, cpsStmts, "switch ($1) {$n", [rdLoc(a)])
-  p.BeforeRetNeeded = true
+  p.beforeRetNeeded = true
   lineF(p, cpsStmts, "case -1: goto BeforeRet;$n", [])
   for i in 0 .. lastOrd(n.sons[0].typ):
     lineF(p, cpsStmts, "case $1: goto STATE$1;$n", [toRope(i)])
@@ -137,7 +138,7 @@ proc genBreakState(p: BProc, n: PNode) =
   if n.sons[0].kind == nkClosure:
     # XXX this produces quite inefficient code!
     initLocExpr(p, n.sons[0].sons[1], a)
-    lineF(p, cpsStmts, "if (($1->Field0) < 0) break;$n", [rdLoc(a)])
+    lineF(p, cpsStmts, "if (((NI*) $1)[0] < 0) break;$n", [rdLoc(a)])
   else:
     initLocExpr(p, n.sons[0], a)
     # the environment is guaranteed to contain the 'state' field at offset 0:
@@ -200,7 +201,7 @@ proc genConstStmt(p: BProc, t: PNode) =
   for i in countup(0, sonsLen(t) - 1): 
     var it = t.sons[i]
     if it.kind == nkCommentStmt: continue 
-    if it.kind != nkConstDef: InternalError(t.info, "genConstStmt")
+    if it.kind != nkConstDef: internalError(t.info, "genConstStmt")
     var c = it.sons[0].sym 
     if c.typ.containsCompileTimeOnly: continue
     if sfFakeConst in c.flags:
@@ -232,71 +233,91 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
   #  Lend:
   var
     a: TLoc
-    Lelse: TLabel
+    lelse: TLabel
   if not isEmptyType(n.typ) and d.k == locNone:
     getTemp(p, n.typ, d)
   genLineDir(p, n)
-  let Lend = getLabel(p)
+  let lend = getLabel(p)
   for i in countup(0, sonsLen(n) - 1): 
     let it = n.sons[i]
     if it.len == 2: 
       when newScopeForIf: startBlock(p)
       initLocExpr(p, it.sons[0], a)
-      Lelse = getLabel(p)
+      lelse = getLabel(p)
       inc(p.labels)
       lineFF(p, cpsStmts, "if (!$1) goto $2;$n",
             "br i1 $1, label %LOC$3, label %$2$nLOC$3: $n",
-            [rdLoc(a), Lelse, toRope(p.labels)])
+            [rdLoc(a), lelse, toRope(p.labels)])
       when not newScopeForIf: startBlock(p)
       expr(p, it.sons[1], d)
       endBlock(p)
       if sonsLen(n) > 1:
-        lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [Lend])
-      fixLabel(p, Lelse)
+        lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [lend])
+      fixLabel(p, lelse)
     elif it.len == 1:
       startBlock(p)
       expr(p, it.sons[0], d)
       endBlock(p)
     else: internalError(n.info, "genIf()")
-  if sonsLen(n) > 1: fixLabel(p, Lend)
+  if sonsLen(n) > 1: fixLabel(p, lend)
+
+
+proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = 
+  # Called by return and break stmts.
+  # Deals with issues faced when jumping out of try/except/finally stmts,
 
-proc blockLeaveActions(p: BProc, howMany: int) = 
-  var L = p.nestedTryStmts.len
-  # danger of endless recursion! we workaround this here by a temp stack
   var stack: seq[PNode]
-  newSeq(stack, howMany)
-  for i in countup(1, howMany): 
-    stack[i-1] = p.nestedTryStmts[L-i]
-  setLen(p.nestedTryStmts, L-howMany)
+  newSeq(stack, 0)
   
   var alreadyPoppedCnt = p.inExceptBlock
-  for tryStmt in items(stack):
+  for i in countup(1, howManyTrys):
+
     if gCmd != cmdCompileToCpp:
+      # Pop safe points generated by try
       if alreadyPoppedCnt > 0:
         dec alreadyPoppedCnt
       else:
         linefmt(p, cpsStmts, "#popSafePoint();$n")
+
+    # Pop this try-stmt of the list of nested trys
+    # so we don't infinite recurse on it in the next step.
+    var tryStmt = p.nestedTryStmts.pop
+    stack.add(tryStmt)
+
+    # Find finally-stmt for this try-stmt
+    # and generate a copy of its sons
     var finallyStmt = lastSon(tryStmt)
     if finallyStmt.kind == nkFinally: 
       genStmts(p, finallyStmt.sons[0])
+
   # push old elements again:
-  for i in countdown(howMany-1, 0): 
+  for i in countdown(howManyTrys-1, 0): 
     p.nestedTryStmts.add(stack[i])
+
   if gCmd != cmdCompileToCpp:
-    for i in countdown(p.inExceptBlock-1, 0):
+    # Pop exceptions that was handled by the
+    # except-blocks we are in
+    for i in countdown(howManyExcepts-1, 0):
       linefmt(p, cpsStmts, "#popCurrentException();$n")
 
 proc genReturnStmt(p: BProc, t: PNode) =
   p.beforeRetNeeded = true
   genLineDir(p, t)
   if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
-  blockLeaveActions(p, min(1, p.nestedTryStmts.len))
+  blockLeaveActions(p, 
+    howManyTrys    = p.nestedTryStmts.len,
+    howManyExcepts = p.inExceptBlock)
+  if (p.finallySafePoints.len > 0):
+    # If we're in a finally block, and we came here by exception
+    # consume it before we return.
+    var safePoint = p.finallySafePoints[p.finallySafePoints.len-1]
+    linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint)    
   lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", [])
 
 proc genComputedGoto(p: BProc; n: PNode) =
   # first pass: Generate array of computed labels:
   var casePos = -1
-  var arraySize: Int
+  var arraySize: int
   for i in 0 .. <n.len:
     let it = n.sons[i]
     if it.kind == nkCaseStmt:
@@ -322,8 +343,20 @@ proc genComputedGoto(p: BProc; n: PNode) =
     gotoArray.appf("&&TMP$#, ", (id+i).toRope)
   gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope)
   line(p, cpsLocals, gotoArray)
+
+  let topBlock = p.blocks.len-1
+  let oldBody = p.blocks[topBlock].sections[cpsStmts]
+  p.blocks[topBlock].sections[cpsStmts] = nil
   
+  for j in casePos+1 .. <n.len: genStmts(p, n.sons[j])
+  let tailB = p.blocks[topBlock].sections[cpsStmts]
+
+  p.blocks[topBlock].sections[cpsStmts] = nil
   for j in 0 .. casePos-1: genStmts(p, n.sons[j])
+  let tailA = p.blocks[topBlock].sections[cpsStmts]
+
+  p.blocks[topBlock].sections[cpsStmts] = oldBody.con(tailA)
+
   let caseStmt = n.sons[casePos]
   var a: TLoc
   initLocExpr(p, caseStmt.sons[0], a)
@@ -340,8 +373,11 @@ proc genComputedGoto(p: BProc; n: PNode) =
       let val = getOrdValue(it.sons[j])
       lineF(p, cpsStmts, "TMP$#:$n", intLiteral(val+id+1))
     genStmts(p, it.lastSon)
-    for j in casePos+1 .. <n.len: genStmts(p, n.sons[j])
-    for j in 0 .. casePos-1: genStmts(p, n.sons[j])
+    #for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) # tailB
+    #for j in 0 .. casePos-1: genStmts(p, n.sons[j])  # tailA
+    app(p.s(cpsStmts), tailB)
+    app(p.s(cpsStmts), tailA)
+
     var a: TLoc
     initLocExpr(p, caseStmt.sons[0], a)
     lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc)
@@ -352,7 +388,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
   # significantly worse code
   var 
     a: TLoc
-    Labl: TLabel
+    labl: TLabel
   assert(sonsLen(t) == 2)
   inc(p.withinLoop)
   genLineDir(p, t)
@@ -366,7 +402,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
       lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
     var loopBody = t.sons[1]
     if loopBody.stmtsContainPragma(wComputedGoto) and
-        hasComputedGoto in CC[ccompiler].props:
+        hasComputedGoto in CC[cCompiler].props:
       # for closure support weird loop bodies are generated:
       if loopBody.len == 2 and loopBody.sons[0].kind == nkEmpty:
         loopBody = loopBody.sons[1]
@@ -401,7 +437,7 @@ proc genParForStmt(p: BProc, t: PNode) =
   preserveBreakIdx:
     let forLoopVar = t.sons[0].sym
     var rangeA, rangeB: TLoc
-    assignLocalVar(P, forLoopVar)
+    assignLocalVar(p, forLoopVar)
     #initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
     #discard mangleName(forLoopVar)
     let call = t.sons[1]
@@ -433,9 +469,11 @@ proc genBreakStmt(p: BProc, t: PNode) =
     # an unnamed 'break' can only break a loop after 'transf' pass:
     while idx >= 0 and not p.blocks[idx].isLoop: dec idx
     if idx < 0 or not p.blocks[idx].isLoop:
-      InternalError(t.info, "no loop to break")
+      internalError(t.info, "no loop to break")
   let label = assignLabel(p.blocks[idx])
-  blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
+  blockLeaveActions(p, 
+    p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
+    p.inExceptBlock - p.blocks[idx].nestedExceptStmts)
   genLineDir(p, t)
   lineF(p, cpsStmts, "goto $1;$n", [label])
 
@@ -454,7 +492,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
       genSimpleBlock(p, finallyBlock.sons[0])
   if t.sons[0].kind != nkEmpty: 
     var a: TLoc
-    InitLocExpr(p, t.sons[0], a)
+    initLocExpr(p, t.sons[0], a)
     var e = rdLoc(a)
     var typ = skipTypes(t.sons[0].typ, abstractPtrs)
     genLineDir(p, t)
@@ -484,16 +522,16 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
 
 proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc, 
                        labId, until: int): TLabel = 
-  var Lend = getLabel(p)
+  var lend = getLabel(p)
   for i in 1..until:
     lineF(p, cpsStmts, "LA$1: ;$n", [toRope(labId + i)])
     if t.sons[i].kind == nkOfBranch:
       var length = sonsLen(t.sons[i])
       exprBlock(p, t.sons[i].sons[length - 1], d)
-      lineF(p, cpsStmts, "goto $1;$n", [Lend])
+      lineF(p, cpsStmts, "goto $1;$n", [lend])
     else:
       exprBlock(p, t.sons[i].sons[0], d)
-  result = Lend
+  result = lend
 
 proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
                        rangeFormat, eqFormat: TFormatStr,
@@ -520,8 +558,8 @@ proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
                     rangeFormat, eqFormat: TFormatStr) = 
   var a: TLoc
   initLocExpr(p, t.sons[0], a)
-  var Lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a)
-  fixLabel(p, Lend)
+  var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a)
+  fixLabel(p, lend)
 
 proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel, 
                          branches: var openArray[PRope]) = 
@@ -565,25 +603,25 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
     if t.sons[sonsLen(t)-1].kind != nkOfBranch: 
       lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)]) 
     # third pass: generate statements
-    var Lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1)
-    fixLabel(p, Lend)
+    var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1)
+    fixLabel(p, lend)
   else:
     genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n")
   
 proc branchHasTooBigRange(b: PNode): bool = 
   for i in countup(0, sonsLen(b)-2): 
     # last son is block
-    if (b.sons[i].Kind == nkRange) and
+    if (b.sons[i].kind == nkRange) and
         b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit: 
       return true
 
-proc IfSwitchSplitPoint(p: BProc, n: PNode): int =
+proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
   for i in 1..n.len-1:
     var branch = n[i]
     var stmtBlock = lastSon(branch)
     if stmtBlock.stmtsContainPragma(wLinearScanEnd):
       result = i
-    elif hasSwitchRange notin CC[ccompiler].props: 
+    elif hasSwitchRange notin CC[cCompiler].props: 
       if branch.kind == nkOfBranch and branchHasTooBigRange(branch): 
         result = i
 
@@ -591,7 +629,7 @@ proc genCaseRange(p: BProc, branch: PNode) =
   var length = branch.len
   for j in 0 .. length-2: 
     if branch[j].kind == nkRange: 
-      if hasSwitchRange in CC[ccompiler].props: 
+      if hasSwitchRange in CC[cCompiler].props: 
         lineF(p, cpsStmts, "case $1 ... $2:$n", [
             genLiteral(p, branch[j][0]), 
             genLiteral(p, branch[j][1])])
@@ -599,18 +637,18 @@ proc genCaseRange(p: BProc, branch: PNode) =
         var v = copyNode(branch[j][0])
         while v.intVal <= branch[j][1].intVal: 
           lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, v)])
-          Inc(v.intVal)
+          inc(v.intVal)
     else:
       lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, branch[j])])
 
 proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
   # analyse 'case' statement:
-  var splitPoint = IfSwitchSplitPoint(p, n)
+  var splitPoint = ifSwitchSplitPoint(p, n)
   
   # generate if part (might be empty):
   var a: TLoc
   initLocExpr(p, n.sons[0], a)
-  var Lend = if splitPoint > 0: genIfForCaseUntil(p, n, d,
+  var lend = if splitPoint > 0: genIfForCaseUntil(p, n, d,
                     rangeFormat = "if ($1 >= $2 && $1 <= $3) goto $4;$n",
                     eqFormat = "if ($1 == $2) goto $3;$n", 
                     splitPoint, a) else: nil
@@ -629,10 +667,10 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
         hasDefault = true
       exprBlock(p, branch.lastSon, d)
       lineF(p, cpsStmts, "break;$n")
-    if (hasAssume in CC[ccompiler].props) and not hasDefault: 
+    if (hasAssume in CC[cCompiler].props) and not hasDefault: 
       lineF(p, cpsStmts, "default: __assume(0);$n")
     lineF(p, cpsStmts, "}$n")
-  if Lend != nil: fixLabel(p, Lend)
+  if lend != nil: fixLabel(p, lend)
   
 proc genCase(p: BProc, t: PNode, d: var TLoc) = 
   genLineDir(p, t)
@@ -691,7 +729,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
   expr(p, t.sons[0], d)
   length = sonsLen(t)
   endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
-  if optStackTrace in p.Options:
+  if optStackTrace in p.options:
     linefmt(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
   inc p.inExceptBlock
   i = 1
@@ -764,7 +802,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   #
   if not isEmptyType(t.typ) and d.k == locNone:
     getTemp(p, t.typ, d)
-  discard lists.IncludeStr(p.module.headerFiles, "<setjmp.h>")
+  discard lists.includeStr(p.module.headerFiles, "<setjmp.h>")
   genLineDir(p, t)
   var safePoint = getTempName()
   discard cgsym(p.module, "E_Base")
@@ -779,7 +817,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   endBlock(p)
   startBlock(p, "else {$n")
   linefmt(p, cpsStmts, "#popSafePoint();$n")
-  if optStackTrace in p.Options:
+  if optStackTrace in p.options:
     linefmt(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
   inc p.inExceptBlock
   var i = 1
@@ -812,18 +850,20 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   discard pop(p.nestedTryStmts)
   endBlock(p) # end of else block
   if i < length and t.sons[i].kind == nkFinally:
+    p.finallySafePoints.add(safePoint)
     exprBlock(p, t.sons[i].sons[0], d)
+    discard pop(p.finallySafePoints)
   linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint)
 
 proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
   var res = ""
   for i in countup(0, sonsLen(t) - 1):
-    case t.sons[i].Kind
+    case t.sons[i].kind
     of nkStrLit..nkTripleStrLit:
       res.add(t.sons[i].strVal)
     of nkSym:
       var sym = t.sons[i].sym
-      if sym.kind in {skProc, skIterator, skMethod}: 
+      if sym.kind in {skProc, skIterator, skClosureIterator, skMethod}:
         var a: TLoc
         initLocExpr(p, t.sons[i], a)
         res.add(rdLoc(a).ropeToStr)
@@ -835,9 +875,9 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
           r = mangleName(sym)
           sym.loc.r = r       # but be consequent!
         res.add(r.ropeToStr)
-    else: InternalError(t.sons[i].info, "genAsmOrEmitStmt()")
+    else: internalError(t.sons[i].info, "genAsmOrEmitStmt()")
   
-  if isAsmStmt and hasGnuAsm in CC[ccompiler].props:
+  if isAsmStmt and hasGnuAsm in CC[cCompiler].props:
     for x in splitLines(res):
       var j = 0
       while x[j] in {' ', '\t'}: inc(j)
@@ -858,9 +898,9 @@ proc genAsmStmt(p: BProc, t: PNode) =
   var s = genAsmOrEmitStmt(p, t, isAsmStmt=true)
   if p.prc == nil:
     # top level asm statement?
-    appf(p.module.s[cfsProcHeaders], CC[ccompiler].asmStmtFrmt, [s])
+    appf(p.module.s[cfsProcHeaders], CC[cCompiler].asmStmtFrmt, [s])
   else:
-    lineF(p, cpsStmts, CC[ccompiler].asmStmtFrmt, [s])
+    lineF(p, cpsStmts, CC[cCompiler].asmStmtFrmt, [s])
 
 proc genEmit(p: BProc, t: PNode) = 
   genLineDir(p, t)
@@ -877,7 +917,7 @@ var
 
 proc genBreakPoint(p: BProc, t: PNode) = 
   var name: string
-  if optEndb in p.Options:
+  if optEndb in p.options:
     if t.kind == nkExprColonExpr: 
       assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit})
       name = normalize(t.sons[1].strVal)
@@ -891,7 +931,7 @@ proc genBreakPoint(p: BProc, t: PNode) =
         makeCString(name)])
 
 proc genWatchpoint(p: BProc, n: PNode) =
-  if optEndb notin p.Options: return
+  if optEndb notin p.options: return
   var a: TLoc
   initLocExpr(p, n.sons[1], a)
   let typ = skipTypes(n.sons[1].typ, abstractVarRange)
@@ -905,7 +945,7 @@ proc genPragma(p: BProc, n: PNode) =
     case whichPragma(it)
     of wEmit: genEmit(p, it)
     of wBreakpoint: genBreakPoint(p, it)
-    of wWatchpoint: genWatchpoint(p, it)
+    of wWatchPoint: genWatchpoint(p, it)
     of wInjectStmt: 
       var p = newProc(nil, p.module)
       p.options = p.options - {optLineTrace, optStackTrace}
@@ -913,7 +953,7 @@ proc genPragma(p: BProc, n: PNode) =
       p.module.injectStmt = p.s(cpsStmts)
     else: discard
 
-proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool = 
+proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool = 
   if optFieldCheck in p.options:
     var le = asgn.sons[0]
     if le.kind == nkCheckedFieldExpr:
@@ -929,7 +969,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
   assert t.kind == tyObject
   discard genTypeInfo(p.module, t)
   var L = lengthOrd(field.typ)
-  if not ContainsOrIncl(p.module.declaredThings, field.id):
+  if not containsOrIncl(p.module.declaredThings, field.id):
     appcg(p.module, cfsVars, "extern $1", 
           discriminatorTableDecl(p.module, t, field))
   lineCg(p, cpsStmts,
@@ -942,7 +982,7 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
   var dotExpr = e.sons[0]
   var d: PSym
   if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr.sons[0]
-  InitLocExpr(p, e.sons[0], a)
+  initLocExpr(p, e.sons[0], a)
   getTemp(p, a.t, tmp)
   expr(p, e.sons[1], tmp)
   genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, dotExpr.sons[1].sym)
@@ -950,9 +990,9 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
   
 proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = 
   genLineDir(p, e)
-  if not FieldDiscriminantCheckNeeded(p, e):
+  if not fieldDiscriminantCheckNeeded(p, e):
     var a: TLoc
-    InitLocExpr(p, e.sons[0], a)
+    initLocExpr(p, e.sons[0], a)
     if fastAsgn: incl(a.flags, lfNoDeepCopy)
     assert(a.t != nil)
     loadInto(p, e.sons[0], e.sons[1], a)
@@ -962,4 +1002,4 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
 proc genStmts(p: BProc, t: PNode) = 
   var a: TLoc
   expr(p, t, a)
-  InternalAssert a.k in {locNone, locTemp, locLocalVar}
+  internalAssert a.k in {locNone, locTemp, locLocalVar}
diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim
index d312ea027..c00b931ef 100644
--- a/compiler/ccgthreadvars.nim
+++ b/compiler/ccgthreadvars.nim
@@ -16,8 +16,8 @@ proc emulatedThreadVars(): bool =
   result = {optThreads, optTlsEmulation} <= gGlobalOptions
 
 proc accessThreadLocalVar(p: BProc, s: PSym) =
-  if emulatedThreadVars() and not p.ThreadVarAccessed:
-    p.ThreadVarAccessed = true
+  if emulatedThreadVars() and not p.threadVarAccessed:
+    p.threadVarAccessed = true
     p.module.usesThreadVars = true
     appf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV;$n")
     app(p.procSec(cpsInit),
@@ -55,7 +55,7 @@ proc generateThreadLocalStorage(m: BModule) =
     for t in items(nimtvDeps): discard getTypeDesc(m, t)
     appf(m.s[cfsSeqTypes], "typedef struct {$1} NimThreadVars;$n", [nimtv])
 
-proc GenerateThreadVarsSize(m: BModule) =
+proc generateThreadVarsSize(m: BModule) =
   if nimtv != nil:
     app(m.s[cfsProcs], 
       "NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}" & tnl)
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index 9534eae91..26f474659 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -28,7 +28,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
     for i in countup(0, sonsLen(n) - 1):
       genTraverseProc(c, accessor, n.sons[i])
   of nkRecCase:
-    if (n.sons[0].kind != nkSym): InternalError(n.info, "genTraverseProc")
+    if (n.sons[0].kind != nkSym): internalError(n.info, "genTraverseProc")
     var p = c.p
     let disc = n.sons[0].sym
     lineF(p, cpsStmts, "switch ($1.$2) {$n", accessor, disc.loc.r)
@@ -74,7 +74,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
       genTraverseProc(c, accessor.parentObj, typ.sons[i])
     if typ.n != nil: genTraverseProc(c, accessor, typ.n)
   of tyTuple:
-    let typ = GetUniqueType(typ)
+    let typ = getUniqueType(typ)
     for i in countup(0, sonsLen(typ) - 1):
       genTraverseProc(c, rfmt(nil, "$1.Field$2", accessor, i.toRope), typ.sons[i])
   of tyRef, tyString, tySequence:
@@ -83,7 +83,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
     if typ.callConv == ccClosure:
       lineCg(p, cpsStmts, c.visitorFrmt, rfmt(nil, "$1.ClEnv", accessor))
   else:
-    nil
+    discard
 
 proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) =
   var p = c.p
@@ -111,7 +111,7 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
   lineF(p, cpsInit, "a = ($1)p;$n", t)
   
   c.p = p
-  assert typ.kind != tyTypedesc
+  assert typ.kind != tyTypeDesc
   if typ.kind == tySequence:
     genTraverseProcSeq(c, "a".toRope, typ)
   else:
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 4548ac641..f51e66897 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -25,7 +25,7 @@ proc mangleField(name: string): string =
     of 'A'..'Z': 
       add(result, chr(ord(name[i]) - ord('A') + ord('a')))
     of '_': 
-      nil
+      discard
     of 'a'..'z', '0'..'9': 
       add(result, name[i])
     else: 
@@ -48,7 +48,7 @@ proc mangle(name: string): string =
     of 'A'..'Z': 
       add(result, chr(ord(name[i]) - ord('A') + ord('a')))
     of '_': 
-      nil
+      discard
     of 'a'..'z', '0'..'9': 
       add(result, name[i])
     else: 
@@ -69,14 +69,14 @@ proc mangleName(s: PSym): PRope =
   if result == nil: 
     if gCmd == cmdCompileToLLVM: 
       case s.kind
-      of skProc, skMethod, skConverter, skConst, skIterator: 
+      of skProc, skMethod, skConverter, skConst, skIterators:
         result = ~"@"
       of skVar, skForVar, skResult, skLet: 
         if sfGlobal in s.flags: result = ~"@"
         else: result = ~"%"
       of skTemp, skParam, skType, skEnumField, skModule: 
         result = ~"%"
-      else: InternalError(s.info, "mangleName")
+      else: internalError(s.info, "mangleName")
     when oKeepVariableNames:
       let keepOrigName = s.kind in skLocalVars - {skForVar} and 
         {sfFromGeneric, sfGlobal, sfShadowed, sfGenSym} * s.flags == {} and
@@ -150,7 +150,7 @@ proc getTypeName(typ: PType): PRope =
       typ.loc.r = if gCmd != cmdCompileToLLVM: con(typ.typeName, typ.id.toRope)
                   else: con([~"%", typ.typeName, typ.id.toRope])
     result = typ.loc.r
-  if result == nil: InternalError("getTypeName: " & $typ.kind)
+  if result == nil: internalError("getTypeName: " & $typ.kind)
   
 proc mapSetType(typ: PType): TCTypeKind =
   case int(getSize(typ))
@@ -183,9 +183,9 @@ proc mapType(typ: PType): TCTypeKind =
       else: internalError("mapType")
   of tyRange: result = mapType(typ.sons[0])
   of tyPtr, tyVar, tyRef:
-    var base = skipTypes(typ.sons[0], typedescInst)
+    var base = skipTypes(typ.lastSon, typedescInst)
     case base.kind
-    of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
+    of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctPtrToArray
     else: result = ctPtr
   of tyPointer: result = ctPtr
   of tySequence: result = ctNimSeq
@@ -194,7 +194,7 @@ proc mapType(typ: PType): TCTypeKind =
   of tyCString: result = ctCString
   of tyInt..tyUInt64:
     result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt))
-  else: InternalError("mapType")
+  else: internalError("mapType")
   
 proc mapReturnType(typ: PType): TCTypeKind = 
   if skipTypes(typ, typedescInst).kind == tyArray: result = ctPtr
@@ -229,11 +229,11 @@ const
     "stdcall $1", "ccc $1", "safecall $1", "syscall $1", "$1 alwaysinline", 
     "$1 noinline", "fastcc $1", "ccc $1", "$1"]
 
-proc CacheGetType(tab: TIdTable, key: PType): PRope = 
+proc cacheGetType(tab: TIdTable, key: PType): PRope = 
   # returns nil if we need to declare this type
   # since types are now unique via the ``GetUniqueType`` mechanism, this slow
   # linear search is not necessary anymore:
-  result = PRope(IdTableGet(tab, key))
+  result = PRope(idTableGet(tab, key))
 
 proc getTempName(): PRope = 
   result = rfmt(nil, "TMP$1", toRope(backendId()))
@@ -246,7 +246,7 @@ proc ccgIntroducedPtr(s: PSym): bool =
   assert skResult != s.kind
   if tfByRef in pt.flags: return true
   elif tfByCopy in pt.flags: return false
-  case pt.Kind
+  case pt.kind
   of tyObject:
     if (optByRef in s.options) or (getSize(pt) > platform.floatSize * 2): 
       result = true           # requested anyway
@@ -262,14 +262,14 @@ proc ccgIntroducedPtr(s: PSym): bool =
 proc fillResult(param: PSym) = 
   fillLoc(param.loc, locParam, param.typ, ~"Result",
           OnStack)
-  if (mapReturnType(param.typ) != ctArray) and IsInvalidReturnType(param.typ): 
+  if (mapReturnType(param.typ) != ctArray) and isInvalidReturnType(param.typ): 
     incl(param.loc.flags, lfIndirect)
     param.loc.s = OnUnknown
 
 proc getParamTypeDesc(m: BModule, t: PType, check: var TIntSet): PRope =
   when false:
     if t.Kind in {tyRef, tyPtr, tyVar}:
-      var b = skipTypes(t.sons[0], typedescInst)
+      var b = skipTypes(t.lastson, typedescInst)
       if b.kind == tySet and mapSetType(b) == ctArray:
         return getTypeDescAux(m, b, check)
   result = getTypeDescAux(m, t, check)
@@ -288,7 +288,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
   else: 
     rettype = getTypeDescAux(m, t.sons[0], check)
   for i in countup(1, sonsLen(t.n) - 1): 
-    if t.n.sons[i].kind != nkSym: InternalError(t.n.info, "genProcParams")
+    if t.n.sons[i].kind != nkSym: internalError(t.n.info, "genProcParams")
     var param = t.n.sons[i].sym
     if isCompileTimeOnly(param.typ): continue
     if params != nil: app(params, ~", ")
@@ -305,7 +305,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
     var arr = param.typ
     if arr.kind == tyVar: arr = arr.sons[0]
     var j = 0
-    while arr.Kind in {tyOpenArray, tyVarargs}:
+    while arr.kind in {tyOpenArray, tyVarargs}:
       # this fixes the 'sort' bug:
       if param.typ.kind == tyVar: param.loc.s = OnUnknown
       # need to pass hidden parameter:
@@ -344,7 +344,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
       "NI", "NI8", "NI16", "NI32", "NI64",
       "NF", "NF32", "NF64", "NF128",
       "NU", "NU8", "NU16", "NU32", "NU64",]
-  case typ.Kind
+  case typ.kind
   of tyPointer: 
     result = typeNameOrLiteral(typ, "void*")
   of tyEnum: 
@@ -362,12 +362,12 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
   of tyString: 
     discard cgsym(m, "NimStringDesc")
     result = typeNameOrLiteral(typ, "NimStringDesc*")
-  of tyCstring: result = typeNameOrLiteral(typ, "NCSTRING")
+  of tyCString: result = typeNameOrLiteral(typ, "NCSTRING")
   of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
   of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR")
   of tyNil: result = typeNameOrLiteral(typ, "0")
   of tyInt..tyUInt64: 
-    result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind])
+    result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.kind])
   of tyRange: result = getSimpleTypeDesc(m, typ.sons[0])
   else: result = nil
   
@@ -375,14 +375,17 @@ proc getTypePre(m: BModule, typ: PType): PRope =
   if typ == nil: result = toRope("void")
   else: 
     result = getSimpleTypeDesc(m, typ)
-    if result == nil: result = CacheGetType(m.typeCache, typ)
-  
+    if result == nil: result = cacheGetType(m.typeCache, typ)
+
+proc structOrUnion(t: PType): PRope =
+  (if tfUnion in t.flags: toRope("union") else: toRope("struct"))
+
 proc getForwardStructFormat(): string = 
-  if gCmd == cmdCompileToCpp: result = "struct $1;$n"
-  else: result = "typedef struct $1 $1;$n"
+  if gCmd == cmdCompileToCpp: result = "$1 $2;$n"
+  else: result = "typedef $1 $2 $2;$n"
   
 proc getTypeForward(m: BModule, typ: PType): PRope = 
-  result = CacheGetType(m.forwTypeCache, typ)
+  result = cacheGetType(m.forwTypeCache, typ)
   if result != nil: return 
   result = getTypePre(m, typ)
   if result != nil: return 
@@ -390,9 +393,10 @@ proc getTypeForward(m: BModule, typ: PType): PRope =
   of tySequence, tyTuple, tyObject: 
     result = getTypeName(typ)
     if not isImportedType(typ): 
-      appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
-    IdTablePut(m.forwTypeCache, typ, result)
-  else: InternalError("getTypeForward(" & $typ.kind & ')')
+      appf(m.s[cfsForwardTypes], getForwardStructFormat(),
+          [structOrUnion(typ), result])
+    idTablePut(m.forwTypeCache, typ, result)
+  else: internalError("getTypeForward(" & $typ.kind & ')')
   
 proc mangleRecFieldName(field: PSym, rectype: PType): PRope = 
   if (rectype.sym != nil) and
@@ -400,7 +404,7 @@ proc mangleRecFieldName(field: PSym, rectype: PType): PRope =
     result = field.loc.r
   else:
     result = toRope(mangleField(field.name.s))
-  if result == nil: InternalError(field.info, "mangleRecFieldName")
+  if result == nil: internalError(field.info, "mangleRecFieldName")
   
 proc genRecordFieldsAux(m: BModule, n: PNode, 
                         accessExpr: PRope, rectype: PType, 
@@ -415,7 +419,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
     for i in countup(0, sonsLen(n) - 1): 
       app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check))
   of nkRecCase: 
-    if (n.sons[0].kind != nkSym): InternalError(n.info, "genRecordFieldsAux")
+    if (n.sons[0].kind != nkSym): internalError(n.info, "genRecordFieldsAux")
     app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
     uname = toRope(mangle(n.sons[0].sym.name.s) & 'U')
     if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, uname])
@@ -445,7 +449,12 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
     if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, sname])
     else: ae = sname
     fillLoc(field.loc, locField, field.typ, ae, OnUnknown)
-    appf(result, "$1 $2;$n", [getTypeDescAux(m, field.loc.t, check), sname])
+    let fieldType = field.loc.t
+    if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags:
+      appf(result, "$1 $2[SEQ_DECL_SIZE];$n",
+          [getTypeDescAux(m, fieldType.elemType, check), sname])
+    else:
+      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 = 
@@ -455,23 +464,33 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
                    check: var TIntSet): PRope = 
   # declare the record:
   var hasField = false
+
+  var attribute: PRope =
+    if tfPacked in typ.flags: toRope(CC[ccompiler].packedPragma)
+    else: nil
+
+  result = ropecg(m, CC[ccompiler].structStmtFmt, 
+    [structOrUnion(typ), name, attribute])
+
   if typ.kind == tyObject: 
+
     if typ.sons[0] == nil: 
       if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags: 
-        result = ropecg(m, "struct $1 {$n", [name])
+        appcg(m, result, " {$n", [])
       else: 
-        result = ropecg(m, "struct $1 {$n#TNimType* m_type;$n", [name])
+        appcg(m, result, " {$n#TNimType* m_type;$n", [name, attribute])
         hasField = true
     elif gCmd == cmdCompileToCpp: 
-      result = ropecg(m, "struct $1 : public $2 {$n", 
-                      [name, getTypeDescAux(m, typ.sons[0], check)])
+      appcg(m, result, " : public $1 {$n", 
+                      [getTypeDescAux(m, typ.sons[0], check)])
       hasField = true
     else: 
-      result = ropecg(m, "struct $1 {$n  $2 Sup;$n", 
-                      [name, getTypeDescAux(m, typ.sons[0], check)])
+      appcg(m, result, " {$n  $1 Sup;$n", 
+                      [getTypeDescAux(m, typ.sons[0], check)])
       hasField = true
   else: 
-    result = ropef("struct $1 {$n", [name])
+    appf(result, " {$n", [name])
+
   var desc = getRecordFields(m, typ, check)
   if (desc == nil) and not hasField: 
     appf(result, "char dummy;$n", [])
@@ -480,8 +499,8 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
   app(result, "};" & tnl)
 
 proc getTupleDesc(m: BModule, typ: PType, name: PRope, 
-                  check: var TIntSet): PRope = 
-  result = ropef("struct $1 {$n", [name])
+                  check: var TIntSet): PRope =
+  result = ropef("$1 $2 {$n", [structOrUnion(typ), name])
   var desc: PRope = nil
   for i in countup(0, sonsLen(typ) - 1): 
     appf(desc, "$1 Field$2;$n", 
@@ -497,49 +516,49 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
   # returns only the type's name
   var 
     name, rettype, desc, recdesc: PRope
-    n: biggestInt
+    n: BiggestInt
     t, et: PType
   t = getUniqueType(typ)
-  if t == nil: InternalError("getTypeDescAux: t == nil")
+  if t == nil: internalError("getTypeDescAux: t == nil")
   if t.sym != nil: useHeader(m, t.sym)
   result = getTypePre(m, t)
   if result != nil: return 
-  if ContainsOrIncl(check, t.id): 
-    InternalError("cannot generate C type for: " & typeToString(typ)) 
+  if containsOrIncl(check, t.id): 
+    internalError("cannot generate C type for: " & typeToString(typ)) 
     # XXX: this BUG is hard to fix -> we need to introduce helper structs,
     # but determining when this needs to be done is hard. We should split
     # C type generation into an analysis and a code generation phase somehow.
-  case t.Kind
+  case t.kind
   of tyRef, tyPtr, tyVar: 
-    et = getUniqueType(t.sons[0])
+    et = getUniqueType(t.lastSon)
     if et.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: 
       # this is correct! sets have no proper base type, so we treat
       # ``var set[char]`` in `getParamTypeDesc`
       et = getUniqueType(elemType(et))
-    case et.Kind
+    case et.kind
     of tyObject, tyTuple: 
       # no restriction! We have a forward declaration for structs
       name = getTypeForward(m, et)
       result = con(name, "*")
-      IdTablePut(m.typeCache, t, result)
+      idTablePut(m.typeCache, t, result)
       pushType(m, et)
     of tySequence: 
       # no restriction! We have a forward declaration for structs
       name = getTypeForward(m, et)
       result = con(name, "**")
-      IdTablePut(m.typeCache, t, result)
+      idTablePut(m.typeCache, t, result)
       pushType(m, et)
     else: 
       # else we have a strong dependency  :-(
       result = con(getTypeDescAux(m, et, check), "*")
-      IdTablePut(m.typeCache, t, result)
+      idTablePut(m.typeCache, t, result)
   of tyOpenArray, tyVarargs: 
     et = getUniqueType(t.sons[0])
     result = con(getTypeDescAux(m, et, check), "*")
-    IdTablePut(m.typeCache, t, result)
+    idTablePut(m.typeCache, t, result)
   of tyProc: 
     result = getTypeName(t)
-    IdTablePut(m.typeCache, t, result)
+    idTablePut(m.typeCache, t, result)
     genProcParams(m, t, rettype, desc, check)
     if not isImportedType(t): 
       if t.callConv != ccClosure: # procedure vars may need a closure!
@@ -553,14 +572,15 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
   of tySequence: 
     # we cannot use getTypeForward here because then t would be associated
     # with the name of the struct, not with the pointer to the struct:
-    result = CacheGetType(m.forwTypeCache, t)
+    result = cacheGetType(m.forwTypeCache, t)
     if result == nil: 
       result = getTypeName(t)
       if not isImportedType(t): 
-        appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
-      IdTablePut(m.forwTypeCache, t, result)
-    assert(CacheGetType(m.typeCache, t) == nil)
-    IdTablePut(m.typeCache, t, con(result, "*"))
+        appf(m.s[cfsForwardTypes], getForwardStructFormat(),
+            [structOrUnion(t), result])
+      idTablePut(m.forwTypeCache, t, result)
+    assert(cacheGetType(m.typeCache, t) == nil)
+    idTablePut(m.typeCache, t, con(result, "*"))
     if not isImportedType(t): 
       if skipTypes(t.sons[0], typedescInst).kind != tyEmpty: 
         const
@@ -579,18 +599,19 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
     if n <= 0: 
       n = 1                   # make an array of at least one element
     result = getTypeName(t)
-    IdTablePut(m.typeCache, t, result)
+    idTablePut(m.typeCache, t, result)
     if not isImportedType(t): 
       appf(m.s[cfsTypes], "typedef $1 $2[$3];$n", 
-           [getTypeDescAux(m, t.sons[1], check), result, ToRope(n)])
+           [getTypeDescAux(m, t.sons[1], check), result, toRope(n)])
   of tyObject, tyTuple: 
-    result = CacheGetType(m.forwTypeCache, t)
+    result = cacheGetType(m.forwTypeCache, t)
     if result == nil: 
       result = getTypeName(t)
       if not isImportedType(t): 
-        appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
-      IdTablePut(m.forwTypeCache, t, result)
-    IdTablePut(m.typeCache, t, result) # always call for sideeffects:
+        appf(m.s[cfsForwardTypes], getForwardStructFormat(),
+           [structOrUnion(t), result])
+      idTablePut(m.forwTypeCache, t, result)
+    idTablePut(m.typeCache, t, result) # always call for sideeffects:
     if t.kind != tyTuple: recdesc = getRecordDesc(m, t, result, check)
     else: recdesc = getTupleDesc(m, t, result, check)
     if not isImportedType(t): app(m.s[cfsTypes], recdesc)
@@ -602,7 +623,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
     of 8: result = toRope("NU64")
     else: 
       result = getTypeName(t)
-      IdTablePut(m.typeCache, t, result)
+      idTablePut(m.typeCache, t, result)
       if not isImportedType(t): 
         appf(m.s[cfsTypes], "typedef NU8 $1[$2];$n", 
              [result, toRope(getSize(t))])
@@ -610,7 +631,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
       tyIter, tyTypeDesc:
     result = getTypeDescAux(m, lastSon(t), check)
   else:
-    InternalError("getTypeDescAux(" & $t.kind & ')')
+    internalError("getTypeDescAux(" & $t.kind & ')')
     result = nil
   # fixes bug #145:
   excl(check, t.id)
@@ -737,10 +758,10 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope =
   var objtype = objtype
   while lookupInRecord(objtype.n, d.name) == nil:
     objtype = objtype.sons[0]
-  if objType.sym == nil: 
-    InternalError(d.info, "anonymous obj with discriminator")
+  if objtype.sym == nil: 
+    internalError(d.info, "anonymous obj with discriminator")
   result = ropef("NimDT_$1_$2", [
-    toRope(objType.sym.name.s.mangle), toRope(d.name.s.mangle)])
+    toRope(objtype.sym.name.s.mangle), toRope(d.name.s.mangle)])
 
 proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope = 
   discard cgsym(m, "TNimNode")
@@ -911,7 +932,7 @@ include ccgtrav
 proc genTypeInfo(m: BModule, t: PType): PRope = 
   var t = getUniqueType(t)
   result = ropef("NTI$1", [toRope(t.id)])
-  if ContainsOrIncl(m.typeInfoMarker, t.id):
+  if containsOrIncl(m.typeInfoMarker, t.id):
     return con("(&".toRope, result, ")".toRope)
   let owner = t.skipTypes(typedescPtrs).owner.getModule
   if owner != m.module:
@@ -948,8 +969,8 @@ proc genTypeInfo(m: BModule, t: PType): PRope =
     # BUGFIX: use consistently RTTI without proper field names; otherwise
     # results are not deterministic!
     genTupleInfo(m, t, result)
-  else: InternalError("genTypeInfo(" & $t.kind & ')')
+  else: internalError("genTypeInfo(" & $t.kind & ')')
   result = con("(&".toRope, result, ")".toRope)
 
 proc genTypeSection(m: BModule, n: PNode) = 
-  nil
+  discard
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 310f7204a..1d8f0158b 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -22,19 +22,19 @@ proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
   of nkPragma:
     for i in 0 .. < n.len: 
       if whichPragma(n[i]) == w: return n[i]
-  else: nil
+  else: discard
 
 proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool =
   result = getPragmaStmt(n, w) != nil
 
-proc hashString*(s: string): biggestInt = 
+proc hashString*(s: string): BiggestInt = 
   # has to be the same algorithm as system.hashString!
   if CPU[targetCPU].bit == 64: 
     # we have to use the same bitwidth
     # as the target CPU
     var b = 0'i64
     for i in countup(0, len(s) - 1): 
-      b = b +% Ord(s[i])
+      b = b +% ord(s[i])
       b = b +% `shl`(b, 10)
       b = b xor `shr`(b, 6)
     b = b +% `shl`(b, 3)
@@ -44,7 +44,7 @@ proc hashString*(s: string): biggestInt =
   else: 
     var a = 0'i32
     for i in countup(0, len(s) - 1): 
-      a = a +% Ord(s[i]).int32
+      a = a +% ord(s[i]).int32
       a = a +% `shl`(a, 10'i32)
       a = a xor `shr`(a, 6'i32)
     a = a +% `shl`(a, 3'i32)
@@ -57,7 +57,7 @@ var
   gCanonicalTypes: array[TTypeKind, PType]
 
 proc initTypeTables() = 
-  for i in countup(low(TTypeKind), high(TTypeKind)): InitIdTable(gTypeTable[i])
+  for i in countup(low(TTypeKind), high(TTypeKind)): initIdTable(gTypeTable[i])
 
 proc resetCaches* =
   ## XXX: fix that more properly
@@ -70,7 +70,7 @@ when false:
     for i in countup(low(TTypeKind), high(TTypeKind)): 
       echo i, " ", gTypeTable[i].counter
   
-proc GetUniqueType*(key: PType): PType = 
+proc getUniqueType*(key: PType): PType = 
   # this is a hotspot in the compiler!
   if key == nil: return 
   var k = key.kind
@@ -86,12 +86,12 @@ proc GetUniqueType*(key: PType): PType =
     if result == nil:
       gCanonicalTypes[k] = key
       result = key
-  of tyTypeDesc, tyTypeClasses:
-    InternalError("value expected, but got a type")
-  of tyGenericParam:
-    InternalError("GetUniqueType")
-  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
-    result = GetUniqueType(lastSon(key))
+  of tyTypeDesc, tyTypeClasses, tyGenericParam,
+     tyFromExpr, tyFieldAccessor:
+    internalError("GetUniqueType")
+  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable,
+     tyConst, tyIter, tyStatic:
+    result = getUniqueType(lastSon(key))
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
      tyOpenArray, tyArray, tySet, tyRange, tyTuple,
      tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
@@ -102,51 +102,50 @@ proc GetUniqueType*(key: PType): PType =
 
     # we have to do a slow linear search because types may need
     # to be compared by their structure:
-    if IdTableHasObjectAsKey(gTypeTable[k], key): return key 
+    if idTableHasObjectAsKey(gTypeTable[k], key): return key 
     for h in countup(0, high(gTypeTable[k].data)): 
       var t = PType(gTypeTable[k].data[h].key)
       if t != nil and sameBackendType(t, key): 
         return t
-    IdTablePut(gTypeTable[k], key, key)
+    idTablePut(gTypeTable[k], key, key)
     result = key
   of tyObject:
     if tfFromGeneric notin key.flags:
       # fast case; lookup per id suffices:
-      result = PType(IdTableGet(gTypeTable[k], key))
+      result = PType(idTableGet(gTypeTable[k], key))
       if result == nil: 
-        IdTablePut(gTypeTable[k], key, key)
+        idTablePut(gTypeTable[k], key, key)
         result = key
     else:
       # ugly slow case: need to compare by structure
-      if IdTableHasObjectAsKey(gTypeTable[k], key): return key
+      if idTableHasObjectAsKey(gTypeTable[k], key): return key
       for h in countup(0, high(gTypeTable[k].data)): 
         var t = PType(gTypeTable[k].data[h].key)
         if t != nil and sameType(t, key): 
           return t
-      IdTablePut(gTypeTable[k], key, key)
+      idTablePut(gTypeTable[k], key, key)
       result = key
   of tyEnum:
-    result = PType(IdTableGet(gTypeTable[k], key))
+    result = PType(idTableGet(gTypeTable[k], key))
     if result == nil: 
-      IdTablePut(gTypeTable[k], key, key)
+      idTablePut(gTypeTable[k], key, key)
       result = key
   of tyProc:
-    # tyVar is not 100% correct, but would speeds things up a little:
     if key.callConv != ccClosure:
       result = key
     else:
       # ugh, we need the canon here:
-      if IdTableHasObjectAsKey(gTypeTable[k], key): return key 
+      if idTableHasObjectAsKey(gTypeTable[k], key): return key 
       for h in countup(0, high(gTypeTable[k].data)): 
         var t = PType(gTypeTable[k].data[h].key)
         if t != nil and sameBackendType(t, key): 
           return t
-      IdTablePut(gTypeTable[k], key, key)
+      idTablePut(gTypeTable[k], key, key)
       result = key
       
-proc TableGetType*(tab: TIdTable, key: PType): PObject = 
+proc tableGetType*(tab: TIdTable, key: PType): PObject = 
   # returns nil if we need to declare this type
-  result = IdTableGet(tab, key)
+  result = idTableGet(tab, key)
   if (result == nil) and (tab.counter > 0): 
     # we have to do a slow linear search because types may need
     # to be compared by their structure:
@@ -169,7 +168,7 @@ proc makeLLVMString*(s: string): PRope =
   for i in countup(0, len(s) - 1): 
     if (i + 1) mod MaxLineLength == 0: 
       app(result, toRope(res))
-      setlen(res, 0)
+      setLen(res, 0)
     case s[i]
     of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\': 
       add(res, '\\')
@@ -178,4 +177,4 @@ proc makeLLVMString*(s: string): PRope =
   add(res, "\\00\"")
   app(result, toRope(res))
 
-InitTypeTables()
+initTypeTables()
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 6ccef5fde..683aed069 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -52,7 +52,7 @@ proc emitLazily(s: PSym): bool {.inline.} =
 proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) = 
   result.k = k
   result.s = s
-  result.t = GetUniqueType(typ)
+  result.t = getUniqueType(typ)
   result.r = nil
   result.a = - 1
   result.flags = {}
@@ -75,12 +75,12 @@ proc isSimpleConst(typ: PType): bool =
 proc useStringh(m: BModule) =
   if not m.includesStringh:
     m.includesStringh = true
-    discard lists.IncludeStr(m.headerFiles, "<string.h>")
+    discard lists.includeStr(m.headerFiles, "<string.h>")
 
 proc useHeader(m: BModule, sym: PSym) = 
-  if lfHeader in sym.loc.Flags: 
+  if lfHeader in sym.loc.flags: 
     assert(sym.annex != nil)
-    discard lists.IncludeStr(m.headerFiles, getStr(sym.annex.path))
+    discard lists.includeStr(m.headerFiles, getStr(sym.annex.path))
 
 proc cgsym(m: BModule, name: string): PRope
 
@@ -103,7 +103,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
       of '0'..'9': 
         var j = 0
         while true: 
-          j = (j * 10) + Ord(frmt[i]) - ord('0')
+          j = (j * 10) + ord(frmt[i]) - ord('0')
           inc(i)
           if i >= length or not (frmt[i] in {'0'..'9'}): break 
         num = j
@@ -116,7 +116,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
       of 'N': 
         app(result, rnl)
         inc(i)
-      else: InternalError("ropes: invalid format string $" & frmt[i])
+      else: internalError("ropes: invalid format string $" & frmt[i])
     elif frmt[i] == '#' and frmt[i+1] in IdentStartChars:
       inc(i)
       var j = i
@@ -128,7 +128,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
       inc(i, 2)
       var j = 0
       while frmt[i] in Digits: 
-        j = (j * 10) + Ord(frmt[i]) - ord('0')
+        j = (j * 10) + ord(frmt[i]) - ord('0')
         inc(i)
       app(result, cgsym(m, args[j-1].ropeToStr))
     var start = i
@@ -194,7 +194,7 @@ when compileTimeRopeFmt:
       if i - 1 >= start:
         yield (kind: ffLit, value: substr(s, start, i-1), intValue: 0)
 
-  macro rfmt(m: BModule, fmt: expr[string], args: varargs[PRope]): expr =
+  macro rfmt(m: BModule, fmt: static[string], args: varargs[PRope]): expr =
     ## Experimental optimized rope-formatting operator
     ## The run-time code it produces will be very fast, but will it speed up
     ## the compilation of nimrod itself or will the macro execution time
@@ -209,7 +209,7 @@ when compileTimeRopeFmt:
       of ffParam:
         result.add(args[frag.intValue])
 else:
-  template rfmt(m: BModule, fmt: expr[string], args: varargs[PRope]): expr =
+  template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr =
     ropecg(m, fmt, args)
 
 proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, 
@@ -279,11 +279,11 @@ proc genLineDir(p: BProc, t: PNode) =
   if optEmbedOrigSrc in gGlobalOptions:
     app(p.s(cpsStmts), con(~"//", t.info.sourceLine, rnl))
   genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
-  if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
+  if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and
       (p.prc == nil or sfPure notin p.prc.flags):
     linefmt(p, cpsStmts, "#endb($1, $2);$n",
             line.toRope, makeCString(toFilename(t.info)))
-  elif ({optLineTrace, optStackTrace} * p.Options ==
+  elif ({optLineTrace, optStackTrace} * p.options ==
       {optLineTrace, optStackTrace}) and
       (p.prc == nil or sfPure notin p.prc.flags):
     linefmt(p, cpsStmts, "nimln($1, $2);$n",
@@ -319,7 +319,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
                    takeAddr: bool) =
   case analyseObjectWithTypeField(t)
   of frNone:
-    nil
+    discard
   of frHeader:
     var r = rdLoc(a)
     if not takeAddr: r = ropef("(*$1)", [r])
@@ -351,7 +351,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
   if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
     if containsGcRef:
       var nilLoc: TLoc
-      initLoc(nilLoc, locTemp, loc.t, onStack)
+      initLoc(nilLoc, locTemp, loc.t, OnStack)
       nilLoc.r = toRope("NIM_NIL")
       genRefAssign(p, loc, nilLoc, {afSrcIsNil})
     else:
@@ -513,7 +513,7 @@ proc assignLocalVar(p: BProc, s: PSym) =
 
 include ccgthreadvars
 
-proc VarInDynamicLib(m: BModule, sym: PSym)
+proc varInDynamicLib(m: BModule, sym: PSym)
 proc mangleDynLibProc(sym: PSym): PRope
 
 proc assignGlobalVar(p: BProc, s: PSym) = 
@@ -522,8 +522,8 @@ proc assignGlobalVar(p: BProc, s: PSym) =
   
   if lfDynamicLib in s.loc.flags:
     var q = findPendingModule(p.module, s)
-    if q != nil and not ContainsOrIncl(q.declaredThings, s.id): 
-      VarInDynamicLib(q, s)
+    if q != nil and not containsOrIncl(q.declaredThings, s.id): 
+      varInDynamicLib(q, s)
     else:
       s.loc.r = mangleDynLibProc(s)
     return
@@ -578,7 +578,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc)
 proc genProcPrototype(m: BModule, sym: PSym)
 proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
 proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
-proc intLiteral(i: biggestInt): PRope
+proc intLiteral(i: BiggestInt): PRope
 proc genLiteral(p: BProc, n: PNode): PRope
 
 proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
@@ -610,7 +610,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
       var s: TStringSeq = @[]
       libCandidates(lib.path.strVal, s)
       if gVerbosity >= 2:
-        MsgWriteln("Dependency: " & lib.path.strVal)
+        msgWriteln("Dependency: " & lib.path.strVal)
       var loadlib: PRope = nil
       for i in countup(0, high(s)): 
         inc(m.labels)
@@ -632,7 +632,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
            "if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n", 
            [tmp, rdLoc(dest)])
       
-  if lib.name == nil: InternalError("loadDynamicLib")
+  if lib.name == nil: internalError("loadDynamicLib")
   
 proc mangleDynLibProc(sym: PSym): PRope =
   if sfCompilerProc in sym.flags: 
@@ -641,7 +641,7 @@ proc mangleDynLibProc(sym: PSym): PRope =
   else:
     result = ropef("Dl_$1", [toRope(sym.id)])
   
-proc SymInDynamicLib(m: BModule, sym: PSym) = 
+proc symInDynamicLib(m: BModule, sym: PSym) = 
   var lib = sym.annex
   let isCall = isGetProcAddr(lib)
   var extname = sym.loc.r
@@ -665,14 +665,14 @@ proc SymInDynamicLib(m: BModule, sym: PSym) =
         params, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))])
     var last = lastSon(n)
     if last.kind == nkHiddenStdConv: last = last.sons[1]
-    InternalAssert(last.kind == nkStrLit)
+    internalAssert(last.kind == nkStrLit)
     let idx = last.strVal
     if idx.len == 0:
       app(m.initProc.s(cpsStmts), load)
     elif idx.len == 1 and idx[0] in {'0'..'9'}:
       app(m.extensionLoaders[idx[0]], load)
     else:
-      InternalError(sym.info, "wrong index: " & idx)
+      internalError(sym.info, "wrong index: " & idx)
   else:
     appcg(m, m.s[cfsDynLibInit], 
         "\t$1 = ($2) #nimGetProcAddr($3, $4);$n", 
@@ -682,7 +682,7 @@ proc SymInDynamicLib(m: BModule, sym: PSym) =
       "$1 = linkonce global $2 zeroinitializer$n", 
       [sym.loc.r, getTypeDesc(m, sym.loc.t)])
 
-proc VarInDynamicLib(m: BModule, sym: PSym) = 
+proc varInDynamicLib(m: BModule, sym: PSym) = 
   var lib = sym.annex
   var extname = sym.loc.r
   loadDynamicLib(m, lib)
@@ -697,7 +697,7 @@ proc VarInDynamicLib(m: BModule, sym: PSym) =
   appf(m.s[cfsVars], "$2* $1;$n",
       [sym.loc.r, getTypeDesc(m, sym.loc.t)])
 
-proc SymInDynamicLibPartial(m: BModule, sym: PSym) =
+proc symInDynamicLibPartial(m: BModule, sym: PSym) =
   sym.loc.r = mangleDynLibProc(sym)
   sym.typ.sym = nil           # generate a new name
 
@@ -705,10 +705,10 @@ proc cgsym(m: BModule, name: string): PRope =
   var sym = magicsys.getCompilerProc(name)
   if sym != nil: 
     case sym.kind
-    of skProc, skMethod, skConverter, skIterator: genProc(m, sym)
+    of skProc, skMethod, skConverter, skIterators: genProc(m, sym)
     of skVar, skResult, skLet: genVarPrototype(m, sym)
     of skType: discard getTypeDesc(m, sym.typ)
-    else: InternalError("cgsym: " & name)
+    else: internalError("cgsym: " & name)
   else:
     # we used to exclude the system module from this check, but for DLL
     # generation support this sloppyness leads to hard to detect bugs, so
@@ -724,7 +724,7 @@ proc generateHeaders(m: BModule) =
       appf(m.s[cfsHeaders], "$N#include \"$1\"$N", [toRope(it.data)])
     else: 
       appf(m.s[cfsHeaders], "$N#include $1$N", [toRope(it.data)])
-    it = PStrEntry(it.Next)
+    it = PStrEntry(it.next)
 
 proc retIsNotVoid(s: PSym): bool = 
   result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
@@ -747,7 +747,7 @@ proc closureSetup(p: BProc, prc: PSym) =
   # prc.ast[paramsPos].last contains the type we're after:
   var ls = lastSon(prc.ast[paramsPos])
   if ls.kind != nkSym:
-    InternalError(prc.info, "closure generation failed")
+    internalError(prc.info, "closure generation failed")
   var env = ls.sym
   #echo "created environment: ", env.id, " for ", prc.name.s
   assignLocalVar(p, env)
@@ -761,6 +761,8 @@ proc genProcAux(m: BModule, prc: PSym) =
   var returnStmt: PRope = nil
   assert(prc.ast != nil)
   if sfPure notin prc.flags and prc.typ.sons[0] != nil:
+    if resultPos >= prc.ast.len:
+      internalError(prc.info, "proc has no result symbol")
     var res = prc.ast.sons[resultPos].sym # get result symbol
     if not isInvalidReturnType(prc.typ.sons[0]):
       if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
@@ -784,7 +786,7 @@ proc genProcAux(m: BModule, prc: PSym) =
   genStmts(p, prc.getBody) # modifies p.locals, p.init, etc.
   var generatedProc: PRope
   if sfPure in prc.flags:
-    if hasNakedDeclspec in extccomp.CC[extccomp.ccompiler].props:
+    if hasNakedDeclspec in extccomp.CC[extccomp.cCompiler].props:
       header = con("__declspec(naked) ", header)
     generatedProc = rfmt(nil, "$N$1 {$n$2$3$4}$N$N",
                          header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts))
@@ -793,7 +795,7 @@ proc genProcAux(m: BModule, prc: PSym) =
     app(generatedProc, initGCFrame(p))
     if optStackTrace in prc.options: 
       app(generatedProc, p.s(cpsLocals))
-      var procname = CStringLit(p, generatedProc, prc.name.s)
+      var procname = cstringLit(p, generatedProc, prc.name.s)
       app(generatedProc, initFrame(p, procname, prc.info.quotedFilename))
     else: 
       app(generatedProc, p.s(cpsLocals))
@@ -811,16 +813,16 @@ proc genProcAux(m: BModule, prc: PSym) =
   
 proc genProcPrototype(m: BModule, sym: PSym) = 
   useHeader(m, sym)
-  if lfNoDecl in sym.loc.Flags: return 
-  if lfDynamicLib in sym.loc.Flags:
+  if lfNoDecl in sym.loc.flags: return 
+  if lfDynamicLib in sym.loc.flags:
     if getModule(sym).id != m.module.id and
-        not ContainsOrIncl(m.declaredThings, sym.id): 
+        not containsOrIncl(m.declaredThings, sym.id): 
       app(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n",
                         getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)))
       if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
-  elif not ContainsOrIncl(m.declaredProtos, sym.id):
+  elif not containsOrIncl(m.declaredProtos, sym.id):
     var header = genProcHeader(m, sym)
-    if sfPure in sym.flags and hasNakedAttribute in CC[ccompiler].props:
+    if sfPure in sym.flags and hasNakedAttribute in CC[cCompiler].props:
       header.app(" __attribute__((naked))")
     app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header))
 
@@ -832,21 +834,21 @@ proc genProcNoForward(m: BModule, prc: PSym) =
     discard cgsym(m, prc.name.s)
     return  
   genProcPrototype(m, prc)
-  if lfNoDecl in prc.loc.Flags: nil
+  if lfNoDecl in prc.loc.flags: discard
   elif prc.typ.callConv == ccInline:
     # We add inline procs to the calling module to enable C based inlining.
     # This also means that a check with ``q.declaredThings`` is wrong, we need
     # a check for ``m.declaredThings``.
-    if not ContainsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
+    if not containsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
   elif lfDynamicLib in prc.loc.flags:
     var q = findPendingModule(m, prc)
-    if q != nil and not ContainsOrIncl(q.declaredThings, prc.id): 
-      SymInDynamicLib(q, prc)
+    if q != nil and not containsOrIncl(q.declaredThings, prc.id): 
+      symInDynamicLib(q, prc)
     else:
-      SymInDynamicLibPartial(m, prc)
+      symInDynamicLibPartial(m, prc)
   elif sfImportc notin prc.flags:
     var q = findPendingModule(m, prc)
-    if q != nil and not ContainsOrIncl(q.declaredThings, prc.id): 
+    if q != nil and not containsOrIncl(q.declaredThings, prc.id): 
       genProcAux(q, prc)
 
 proc requestConstImpl(p: BProc, sym: PSym) =
@@ -854,15 +856,15 @@ proc requestConstImpl(p: BProc, sym: PSym) =
   useHeader(m, sym)
   if sym.loc.k == locNone:
     fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown)
-  if lfNoDecl in sym.loc.Flags: return
+  if lfNoDecl in sym.loc.flags: return
   # declare implementation:
   var q = findPendingModule(m, sym)
-  if q != nil and not ContainsOrIncl(q.declaredThings, sym.id):
+  if q != nil and not containsOrIncl(q.declaredThings, sym.id):
     assert q.initProc.module == q
     appf(q.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
         [getTypeDesc(q, sym.typ), sym.loc.r, genConstExpr(q.initProc, sym.ast)])
   # declare header:
-  if q != m and not ContainsOrIncl(m.declaredThings, sym.id):
+  if q != m and not containsOrIncl(m.declaredThings, sym.id):
     assert(sym.loc.r != nil)
     let headerDecl = ropef("extern NIM_CONST $1 $2;$n",
         [getTypeDesc(m, sym.loc.t), sym.loc.r])
@@ -879,17 +881,17 @@ proc genProc(m: BModule, prc: PSym) =
   else:
     genProcNoForward(m, prc)
     if {sfExportc, sfCompilerProc} * prc.flags == {sfExportc} and
-        generatedHeader != nil and lfNoDecl notin prc.loc.Flags:
+        generatedHeader != nil and lfNoDecl notin prc.loc.flags:
       genProcPrototype(generatedHeader, prc)
       if prc.typ.callConv == ccInline:
-        if not ContainsOrIncl(generatedHeader.declaredThings, prc.id): 
+        if not containsOrIncl(generatedHeader.declaredThings, prc.id): 
           genProcAux(generatedHeader, prc)
 
 proc genVarPrototypeAux(m: BModule, sym: PSym) = 
   assert(sfGlobal in sym.flags)
   useHeader(m, sym)
   fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap)
-  if (lfNoDecl in sym.loc.Flags) or ContainsOrIncl(m.declaredThings, sym.id): 
+  if (lfNoDecl in sym.loc.flags) or containsOrIncl(m.declaredThings, sym.id): 
     return 
   if sym.owner.id != m.module.id: 
     # else we already have the symbol generated!
@@ -911,29 +913,29 @@ proc addIntTypes(result: var PRope) {.inline.} =
   appf(result, "#define NIM_INTBITS $1", [
     platform.CPU[targetCPU].intSize.toRope])
 
-proc getCopyright(cfilenoext: string): PRope = 
-  if optCompileOnly in gGlobalOptions: 
-    result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
-        "/*   (c) 2012 Andreas Rumpf */$n" &
-        "/* The generated code is subject to the original license. */$n",
-        "; Generated by Nimrod Compiler v$1$n" &
-        ";   (c) 2012 Andreas Rumpf$n", [toRope(versionAsString)])
-  else: 
-    result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
-        "/*   (c) 2012 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" &
-        ";   (c) 2012 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), 
+proc getCopyright(cfilenoext: string): PRope =
+  if optCompileOnly in gGlobalOptions:
+    result = ropeff("/* Generated by Nimrod 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" &
+        ";   (c) 2012 Andreas Rumpf$N", [toRope(VersionAsString)])
+  else:
+    result = ropeff("/* Generated by Nimrod 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" &
+        ";   (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))])
 
-proc getFileHeader(cfilenoext: string): PRope = 
+proc getFileHeader(cfilenoext: string): PRope =
   result = getCopyright(cfilenoext)
   addIntTypes(result)
 
@@ -941,46 +943,72 @@ proc genFilenames(m: BModule): PRope =
   discard cgsym(m, "dbgRegisterFilename")
   result = nil
   for i in 0.. <fileInfos.len:
-    result.appf("dbgRegisterFilename($1);$n", fileInfos[i].projPath.makeCString)
+    result.appf("dbgRegisterFilename($1);$N", fileInfos[i].projPath.makeCString)
 
-proc genMainProc(m: BModule) = 
+proc genMainProc(m: BModule) =
   const 
-    CommonMainBody =
-        "\tsystemDatInit();$n" &
-        "\tsystemInit();$n" &
+    PreMainBody =
+      "\tsystemDatInit();$N" &
+      "\tsystemInit();$N" &
+      "$1" &
+      "$2" &
+      "$3" &
+      "$4"
+
+    MainProcs =
+      "\tNimMain();$N"
+    
+    MainProcsWithResult =
+      MainProcs & "\treturn nim_program_result;$N"
+
+    NimMainBody =
+      "N_CDECL(void, NimMain)(void) {$N" &
+        "\tPreMain();$N" &
         "$1" &
-        "$2" &
-        "$3" &
-        "$4"
-    PosixNimMain = 
-        "int cmdCount;$n" & 
-        "char** cmdLine;$n" & 
-        "char** gEnv;$n" &
-        "N_CDECL(void, NimMain)(void) {$n" &
-        CommonMainBody & "}$n"
-    PosixCMain = "int main(int argc, char** args, char** env) {$n" &
-        "\tcmdLine = args;$n" & "\tcmdCount = argc;$n" & "\tgEnv = env;$n" &
-        "\tNimMain();$n" & "\treturn nim_program_result;$n" & "}$n"
-    StandaloneCMain = "int main(void) {$n" &
-        "\tNimMain();$n" & 
-        "\treturn 0;$n" & "}$n"
-    WinNimMain = "N_CDECL(void, NimMain)(void) {$n" &
-        CommonMainBody & "}$n"
-    WinCMain = "N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $n" &
-        "                        HINSTANCE hPrevInstance, $n" &
-        "                        LPSTR lpCmdLine, int nCmdShow) {$n" &
-        "\tNimMain();$n" & "\treturn nim_program_result;$n" & "}$n"
-    WinNimDllMain = "N_LIB_EXPORT N_CDECL(void, NimMain)(void) {$n" &
-        CommonMainBody & "}$n"
-    WinCDllMain = 
-        "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n" &
-        "                    LPVOID lpvReserved) {$n" &
-          "\tif(fwdreason == DLL_PROCESS_ATTACH) NimMain();$n" &
-        "\treturn 1;$n" & "}$n"
+      "}$N$N"
+
+    PosixNimMain =
+      "int cmdCount;$N" &
+      "char** cmdLine;$N" &
+      "char** gEnv;$N" &
+      NimMainBody
+  
+    PosixCMain =
+      "int main(int argc, char** args, char** env) {$N" &
+        "\tcmdLine = args;$N" &
+        "\tcmdCount = argc;$N" &
+        "\tgEnv = env;$N" &
+        MainProcsWithResult &
+      "}$N$N"
+  
+    StandaloneCMain =
+      "int main(void) {$N" &
+        MainProcs &
+        "\treturn 0;$N" &
+      "}$N$N"
+    
+    WinNimMain = NimMainBody
+    
+    WinCMain = "N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $N" &
+      "                        HINSTANCE hPrevInstance, $N" &
+      "                        LPSTR lpCmdLine, int nCmdShow) {$N" &
+      MainProcsWithResult & "}$N$N"
+  
+    WinNimDllMain = "N_LIB_EXPORT " & NimMainBody
+
+    WinCDllMain =
+      "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $N" &
+      "                    LPVOID lpvReserved) {$N" &
+      "\tif(fwdreason == DLL_PROCESS_ATTACH) {$N" & MainProcs & "}$N" &
+      "\treturn 1;$N}$N$N"
+
     PosixNimDllMain = WinNimDllMain
-    PosixCDllMain = 
-        "void NIM_POSIX_INIT NimMainInit(void) {$n" &
-        "\tNimMain();$n}$n"
+    
+    PosixCDllMain =
+      "void NIM_POSIX_INIT NimMainInit(void) {$N" &
+        MainProcs &
+      "}$N$N"
+
   var nimMain, otherMain: TFormatStr
   if platform.targetOS == osWindows and
       gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}: 
@@ -990,10 +1018,10 @@ proc genMainProc(m: BModule) =
     else: 
       nimMain = WinNimDllMain
       otherMain = WinCDllMain
-    discard lists.IncludeStr(m.headerFiles, "<windows.h>")
+    discard lists.includeStr(m.headerFiles, "<windows.h>")
   elif optGenDynLib in gGlobalOptions:
-    nimMain = posixNimDllMain
-    otherMain = posixCDllMain
+    nimMain = PosixNimDllMain
+    otherMain = PosixCDllMain
   elif platform.targetOS == osStandalone:
     nimMain = PosixNimMain
     otherMain = StandaloneCMain
@@ -1006,16 +1034,20 @@ proc genMainProc(m: BModule) =
   
   let initStackBottomCall = if emulatedThreadVars() or
                               platform.targetOS == osStandalone: "".toRope
-                            else: ropecg(m, "\t#initStackBottom();$n")
+                            else: ropecg(m, "\t#initStackBottom();$N")
   inc(m.labels)
-  appcg(m, m.s[cfsProcs], nimMain, [mainDatInit, initStackBottomCall,
-        gBreakpoints, mainModInit, toRope(m.labels)])
+  appcg(m, m.s[cfsProcs], "void PreMain() {$N" & PreMainBody & "}$N$N", [
+    mainDatInit, initStackBottomCall, gBreakpoints, otherModsInit])
+
+  appcg(m, m.s[cfsProcs], nimMain, [mainModInit, toRope(m.labels)])
   if optNoMain notin gGlobalOptions:
     appcg(m, m.s[cfsProcs], otherMain, [])
 
 proc getSomeInitName(m: PSym, suffix: string): PRope =
+  assert m.kind == skModule
+  assert m.owner.kind == skPackage
   if {sfSystemModule, sfMainModule} * m.flags == {}:
-    result = m.info.toFullPath.getPackageName.mangle.toRope
+    result = m.owner.name.s.mangle.toRope
   result.app m.name.s
   result.app suffix
   
@@ -1030,13 +1062,17 @@ proc registerModuleToMain(m: PSym) =
                       "declare void $1() noinline$N", [init])
   appff(mainModProcs, "N_NOINLINE(void, $1)(void);$N",
                       "declare void $1() noinline$N", [datInit])
-  if not (sfSystemModule in m.flags):
-    appff(mainModInit, "\t$1();$n", "call void ()* $1$n", [init])
-    appff(mainDatInit, "\t$1();$n", "call void ()* $1$n", [datInit])
-  
+  if sfSystemModule notin m.flags:
+    appff(mainDatInit, "\t$1();$N", "call void ()* $1$n", [datInit])
+    let initCall = ropeff("\t$1();$N", "call void ()* $1$n", [init])
+    if sfMainModule in m.flags:
+      app(mainModInit, initCall)
+    else:
+      app(otherModsInit, initCall)
+    
 proc genInitCode(m: BModule) = 
   var initname = getInitName(m.module)
-  var prc = ropeff("N_NOINLINE(void, $1)(void) {$n", 
+  var prc = ropeff("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", 
@@ -1053,12 +1089,12 @@ proc genInitCode(m: BModule) =
   app(prc, m.postInitProc.s(cpsLocals))
   app(prc, genSectionEnd(cpsLocals))
 
-  if optStackTrace in m.initProc.options and not m.FrameDeclared:
+  if optStackTrace in m.initProc.options and not m.frameDeclared:
     # BUT: the generated init code might depend on a current frame, so
     # declare it nevertheless:
-    m.FrameDeclared = true
-    if not m.PreventStackTrace:
-      var procname = CStringLit(m.initProc, prc, m.module.name.s)
+    m.frameDeclared = true
+    if not m.preventStackTrace:
+      var procname = cstringLit(m.initProc, prc, m.module.name.s)
       app(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename))
     else:
       app(prc, ~"\tTFrame F; F.len = 0;$N")
@@ -1074,12 +1110,12 @@ proc genInitCode(m: BModule) =
   app(prc, m.initProc.s(cpsStmts))
   app(prc, m.postInitProc.s(cpsStmts))
   app(prc, genSectionEnd(cpsStmts))
-  if optStackTrace in m.initProc.options and not m.PreventStackTrace:
+  if optStackTrace in m.initProc.options and not m.preventStackTrace:
     app(prc, deinitFrame(m.initProc))
   app(prc, deinitGCFrame(m.initProc))
   appf(prc, "}$N$N")
 
-  prc.appff("N_NOINLINE(void, $1)(void) {$n",
+  prc.appff("N_NOINLINE(void, $1)(void) {$N",
             "define void $1() noinline {$n", [getDatInitName(m.module)])
 
   for i in cfsTypeInit1..cfsDynLibInit:
@@ -1127,7 +1163,7 @@ proc initProcOptions(m: BModule): TOptions =
 
 proc rawNewModule(module: PSym, filename: string): BModule =
   new(result)
-  InitLinkedList(result.headerFiles)
+  initLinkedList(result.headerFiles)
   result.declaredThings = initIntSet()
   result.declaredProtos = initIntSet()
   result.cfilename = filename
@@ -1148,7 +1184,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
   # no line tracing for the init sections of the system module so that we
   # don't generate a TFrame which can confuse the stack botton initialization:
   if sfSystemModule in module.flags:
-    result.PreventStackTrace = true
+    result.preventStackTrace = true
     excl(result.preInitProc.options, optStackTrace)
     excl(result.postInitProc.options, optStackTrace)
 
@@ -1156,10 +1192,10 @@ proc nullify[T](arr: var T) =
   for i in low(arr)..high(arr):
     arr[i] = nil
 
-proc resetModule*(m: var BModule) =
+proc resetModule*(m: BModule) =
   # between two compilations in CAAS mode, we can throw
   # away all the data that was written to disk
-  InitLinkedList(m.headerFiles)
+  initLinkedList(m.headerFiles)
   m.declaredProtos = initIntSet()
   initIdTable(m.forwTypeCache)
   m.initProc = newProc(nil, m)
@@ -1171,7 +1207,7 @@ proc resetModule*(m: var BModule) =
   m.forwardedProcs = @[]
   m.typeNodesName = getTempName()
   m.nimTypesName = getTempName()
-  m.PreventStackTrace = sfSystemModule in m.module.flags
+  m.preventStackTrace = sfSystemModule in m.module.flags
   nullify m.s
   m.usesThreadVars = false
   m.typeNodes = 0
@@ -1202,7 +1238,7 @@ proc rawNewModule(module: PSym): BModule =
 
 proc newModule(module: PSym): BModule =
   # we should create only one cgen module for each module sym
-  InternalAssert getCgenModule(module) == nil
+  internalAssert getCgenModule(module) == nil
 
   result = rawNewModule(module)
   growCache gModules, module.position
@@ -1210,7 +1246,7 @@ proc newModule(module: PSym): BModule =
 
   if (optDeadCodeElim in gGlobalOptions): 
     if (sfDeadCodeElim in module.flags): 
-      InternalError("added pending module twice: " & module.filename)
+      internalError("added pending module twice: " & module.filename)
 
 proc myOpen(module: PSym): PPassContext = 
   result = newModule(module)
@@ -1263,19 +1299,19 @@ proc finishModule(m: BModule) =
     # a ``for`` loop here
     var prc = m.forwardedProcs[i]
     if sfForward in prc.flags: 
-      InternalError(prc.info, "still forwarded: " & prc.name.s)
+      internalError(prc.info, "still forwarded: " & prc.name.s)
     genProcNoForward(m, prc)
     inc(i)
   assert(gForwardedProcsCounter >= i)
   dec(gForwardedProcsCounter, i)
-  setlen(m.forwardedProcs, 0)
+  setLen(m.forwardedProcs, 0)
 
 proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool = 
   result = true
   if optForceFullMake notin gGlobalOptions:
     var objFile = toObjFile(cfilenoext)
     if writeRopeIfNotEqual(code, cfile): return 
-    if ExistsFile(objFile) and os.FileNewer(objFile, cfile): result = false
+    if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false
   else: 
     writeRope(code, cfile)
 
@@ -1296,7 +1332,7 @@ proc writeModule(m: BModule, pending: bool) =
     if sfMainModule in m.module.flags: 
       # generate main file:
       app(m.s[cfsProcHeaders], mainModProcs)
-      GenerateThreadVarsSize(m)
+      generateThreadVarsSize(m)
     
     var code = genModule(m, cfilenoext)
     when hasTinyCBackend:
@@ -1313,7 +1349,7 @@ proc writeModule(m: BModule, pending: bool) =
     var code = genModule(m, cfilenoext)
     writeRope(code, cfile)
     addFileToCompile(cfilenoext)
-  elif not ExistsFile(toObjFile(cfilenoext)):
+  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:
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index a803c0ba1..e7d818556 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -41,7 +41,8 @@ type
     ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
     ctFloat, ctFloat32, ctFloat64, ctFloat128,
     ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
-    ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString
+    ctArray, ctPtrToArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc,
+    ctCString
   TCFileSections* = array[TCFileSection, PRope] # represents a generated C file
   TCProcSection* = enum       # the sections a generated C proc consists of
     cpsLocals,                # section of local variables for C proc
@@ -57,17 +58,20 @@ type
     sections*: TCProcSections # the code beloging
     isLoop*: bool             # whether block is a loop
     nestedTryStmts*: int16    # how many try statements is it nested into
+    nestedExceptStmts*: int16 # how many except statements is it nested into
     frameLen*: int16
   
   TCProc{.final.} = object    # represents C proc that is currently generated
     prc*: PSym                # the Nimrod 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
-                                # (the vars must be volatile then)
+    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
+                                  # (the vars must be volatile then)
     inExceptBlock*: int       # are we currently inside an except block?
                               # leaving such scopes by raise or by return must
                               # execute any applicable finally blocks
+    finallySafePoints*: seq[PRope]  # For correctly cleaning up exceptions when
+                                    # using return in finally statements
     labels*: Natural          # for generating unique labels in the C proc
     blocks*: seq[TBlock]      # nested blocks
     breakIdx*: int            # the block that will be exited
@@ -78,7 +82,7 @@ type
     maxFrameLen*: int         # max length of frame descriptor
     module*: BModule          # used to prevent excessive parameter passing
     withinLoop*: int          # > 0 if we are within a loop
-    gcFrameId*: natural       # for the GC stack marking
+    gcFrameId*: Natural       # for the GC stack marking
     gcFrameType*: PRope       # the struct {} we put the GC markers into
   
   TTypeSeq* = seq[PType]
@@ -86,9 +90,9 @@ type
     module*: PSym
     filename*: string
     s*: TCFileSections        # sections of the C file
-    PreventStackTrace*: bool  # true if stack traces need to be prevented
+    preventStackTrace*: bool  # true if stack traces need to be prevented
     usesThreadVars*: bool     # true if the module uses a thread var
-    FrameDeclared*: bool      # hack for ROD support so that we don't declare
+    frameDeclared*: bool      # hack for ROD support so that we don't declare
                               # a frame var twice in an init proc
     isHeaderFile*: bool       # C source file is the header file
     includesStringh*: bool    # C source file already includes ``<string.h>``
@@ -108,13 +112,14 @@ type
     forwardedProcs*: TSymSeq  # keep forwarded procs here
     typeNodes*, nimTypes*: int # used for type info generation
     typeNodesName*, nimTypesName*: PRope # used for type info generation
-    labels*: natural          # for generating unique module-scope names
+    labels*: Natural          # for generating unique module-scope names
     extensionLoaders*: array['0'..'9', PRope] # special procs for the
                                               # OpenGL wrapper
     injectStmt*: PRope
 
 var
-  mainModProcs*, mainModInit*, mainDatInit*: PRope # parts of the main module
+  mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: PRope
+    # varuious parts of the main module
   gMapping*: PRope             # the generated mapping file (if requested)
   gModules*: seq[BModule] = @[] # list of all compiled modules
   gForwardedProcsCounter*: int = 0
@@ -139,8 +144,9 @@ proc newProc*(prc: PSym, module: BModule): BProc =
   else: result.options = gOptions
   newSeq(result.blocks, 1)
   result.nestedTryStmts = @[]
+  result.finallySafePoints = @[]
 
-iterator cgenModules*: var BModule =
+iterator cgenModules*: BModule =
   for i in 0..high(gModules):
     # ultimately, we are iterating over the file ids here.
     # some "files" won't have an associated cgen module (like stdin)
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index 33bb94b38..948541302 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -18,16 +18,16 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
   var source = skipTypes(n.typ, abstractPtrs)
   if (source.kind == tyObject) and (dest.kind == tyObject): 
     var diff = inheritanceDiff(dest, source)
-    if diff == high(int): InternalError(n.info, "cgmeth.genConv")
+    if diff == high(int): internalError(n.info, "cgmeth.genConv")
     if diff < 0: 
       result = newNodeIT(nkObjUpConv, n.info, d)
       addSon(result, n)
-      if downCast: InternalError(n.info, "cgmeth.genConv: no upcast allowed")
+      if downcast: internalError(n.info, "cgmeth.genConv: no upcast allowed")
     elif diff > 0: 
       result = newNodeIT(nkObjDownConv, n.info, d)
       addSon(result, n)
-      if not downCast: 
-        InternalError(n.info, "cgmeth.genConv: no downcast allowed")
+      if not downcast: 
+        internalError(n.info, "cgmeth.genConv: no downcast allowed")
     else: 
       result = n
   else: 
@@ -59,14 +59,14 @@ proc sameMethodBucket(a, b: PSym): bool =
       aa = skipTypes(aa, {tyGenericInst})
       bb = skipTypes(bb, {tyGenericInst})
       if (aa.kind == bb.kind) and (aa.kind in {tyVar, tyPtr, tyRef}): 
-        aa = aa.sons[0]
-        bb = bb.sons[0]
+        aa = aa.lastSon
+        bb = bb.lastSon
       else: 
         break 
     if sameType(aa, bb) or
         (aa.kind == tyObject) and (bb.kind == tyObject) and
         (inheritanceDiff(bb, aa) < 0):
-      nil
+      discard
     else:
       return
   result = true
@@ -112,12 +112,12 @@ proc relevantCol(methods: TSymSeq, col: int): bool =
   if t.kind == tyObject:
     for i in countup(1, high(methods)):
       let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
-      if not SameType(t2, t):
+      if not sameType(t2, t):
         return true
   
 proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int = 
   for col in countup(1, sonsLen(a.typ) - 1): 
-    if Contains(relevantCols, col): 
+    if contains(relevantCols, col): 
       var aa = skipTypes(a.typ.sons[col], skipPtrs)
       var bb = skipTypes(b.typ.sons[col], skipPtrs)
       var d = inheritanceDiff(aa, bb)
@@ -126,14 +126,14 @@ proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int =
   
 proc sortBucket(a: var TSymSeq, relevantCols: TIntSet) = 
   # we use shellsort here; fast and simple
-  var N = len(a)
+  var n = len(a)
   var h = 1
   while true: 
     h = 3 * h + 1
-    if h > N: break 
+    if h > n: break 
   while true: 
     h = h div 3
-    for i in countup(h, N - 1): 
+    for i in countup(h, n - 1): 
       var v = a[i]
       var j = i
       while cmpSignatures(a[j - h], v, relevantCols) >= 0: 
@@ -154,7 +154,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
     var curr = methods[meth]      # generate condition:
     var cond: PNode = nil
     for col in countup(1, paramLen - 1):
-      if Contains(relevantCols, col):
+      if contains(relevantCols, col):
         var isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
         addSon(isn, newSymNode(iss))
         addSon(isn, newSymNode(base.typ.n.sons[col].sym))
@@ -195,7 +195,7 @@ proc generateMethodDispatchers*(): PNode =
   for bucket in countup(0, len(gMethods) - 1): 
     var relevantCols = initIntSet()
     for col in countup(1, sonsLen(gMethods[bucket][0].typ) - 1): 
-      if relevantCol(gMethods[bucket], col): Incl(relevantCols, col)
+      if relevantCol(gMethods[bucket], col): incl(relevantCols, col)
     sortBucket(gMethods[bucket], relevantCols)
     addSon(result, newSymNode(genDispatcher(gMethods[bucket], relevantCols)))
 
diff --git a/compiler/commands.nim b/compiler/commands.nim
index fa7841275..8339219ed 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -21,40 +21,40 @@ type
     passCmd2,                 # second pass over the command line
     passPP                    # preprocessor called ProcessCommand()
 
-proc ProcessCommand*(switch: string, pass: TCmdLinePass)
-proc processSwitch*(switch, arg: string, pass: TCmdlinePass, info: TLineInfo)
+proc processCommand*(switch: string, pass: TCmdLinePass)
+proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo)
 
 # implementation
 
 const
-  HelpMessage = "Nimrod Compiler Version $1 (" & compileDate & ") [$2: $3]\n" &
-      "Copyright (c) 2004-2013 by Andreas Rumpf\n"
+  HelpMessage = "Nimrod Compiler Version $1 (" & CompileDate & ") [$2: $3]\n" &
+      "Copyright (c) 2006-2014 by Andreas Rumpf\n"
 
 const 
   Usage = slurp"doc/basicopt.txt".replace("//", "")
   AdvancedUsage = slurp"doc/advopt.txt".replace("//", "")
 
 proc getCommandLineDesc(): string = 
-  result = (HelpMessage % [VersionAsString, platform.os[platform.hostOS].name, 
-                           cpu[platform.hostCPU].name]) & Usage
+  result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name, 
+                           CPU[platform.hostCPU].name]) & Usage
 
-proc HelpOnError(pass: TCmdLinePass) = 
+proc helpOnError(pass: TCmdLinePass) = 
   if pass == passCmd1:
-    MsgWriteln(getCommandLineDesc())
+    msgWriteln(getCommandLineDesc())
     quit(0)
 
 proc writeAdvancedUsage(pass: TCmdLinePass) = 
   if pass == passCmd1:
-    MsgWriteln(`%`(HelpMessage, [VersionAsString, 
-                                 platform.os[platform.hostOS].name, 
-                                 cpu[platform.hostCPU].name]) & AdvancedUsage)
+    msgWriteln(`%`(HelpMessage, [VersionAsString, 
+                                 platform.OS[platform.hostOS].name, 
+                                 CPU[platform.hostCPU].name]) & AdvancedUsage)
     quit(0)
 
 proc writeVersionInfo(pass: TCmdLinePass) = 
   if pass == passCmd1:
-    MsgWriteln(`%`(HelpMessage, [VersionAsString, 
-                                 platform.os[platform.hostOS].name, 
-                                 cpu[platform.hostCPU].name]))
+    msgWriteln(`%`(HelpMessage, [VersionAsString, 
+                                 platform.OS[platform.hostOS].name, 
+                                 CPU[platform.hostCPU].name]))
     quit(0)
 
 var
@@ -62,16 +62,16 @@ var
 
 proc writeCommandLineUsage() = 
   if not helpWritten: 
-    MsgWriteln(getCommandLineDesc())
+    msgWriteln(getCommandLineDesc())
     helpWritten = true
 
 proc addPrefix(switch: string): string =
   if len(switch) == 1: result = "-" & switch
   else: result = "--" & switch
 
-proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) = 
-  if switch == " ": LocalError(info, errInvalidCmdLineOption, "-")
-  else: LocalError(info, errInvalidCmdLineOption, addPrefix(switch))
+proc invalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) = 
+  if switch == " ": localError(info, errInvalidCmdLineOption, "-")
+  else: localError(info, errInvalidCmdLineOption, addPrefix(switch))
 
 proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass, 
                  info: TLineInfo) = 
@@ -86,29 +86,29 @@ proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
     inc(i)
   if i >= len(switch): arg = ""
   elif switch[i] in {':', '=', '['}: arg = substr(switch, i + 1)
-  else: InvalidCmdLineOption(pass, switch, info)
+  else: invalidCmdLineOption(pass, switch, info)
   
-proc ProcessOnOffSwitch(op: TOptions, arg: string, pass: TCmdlinePass, 
+proc processOnOffSwitch(op: TOptions, arg: string, pass: TCmdLinePass, 
                         info: TLineInfo) = 
   case whichKeyword(arg)
   of wOn: gOptions = gOptions + op
   of wOff: gOptions = gOptions - op
-  else: LocalError(info, errOnOrOffExpectedButXFound, arg)
+  else: localError(info, errOnOrOffExpectedButXFound, arg)
   
-proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass, 
+proc processOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdLinePass, 
                          info: TLineInfo) = 
   case whichKeyword(arg)
   of wOn: gGlobalOptions = gGlobalOptions + op
   of wOff: gGlobalOptions = gGlobalOptions - op
-  else: LocalError(info, errOnOrOffExpectedButXFound, arg)
+  else: localError(info, errOnOrOffExpectedButXFound, arg)
   
-proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 
-  if arg == "": LocalError(info, errCmdLineArgExpected, addPrefix(switch))
+proc expectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 
+  if arg == "": localError(info, errCmdLineArgExpected, addPrefix(switch))
   
-proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 
-  if arg != "": LocalError(info, errCmdLineNoArgExpected, addPrefix(switch))
+proc expectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 
+  if arg != "": localError(info, errCmdLineNoArgExpected, addPrefix(switch))
   
-proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass, 
+proc processSpecificNote(arg: string, state: TSpecialWord, pass: TCmdLinePass, 
                          info: TLineInfo) = 
   var id = ""  # arg = "X]:on|off"
   var i = 0
@@ -117,21 +117,21 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
     add(id, arg[i])
     inc(i)
   if i < len(arg) and (arg[i] == ']'): inc(i)
-  else: InvalidCmdLineOption(pass, arg, info)
+  else: invalidCmdLineOption(pass, arg, info)
   if i < len(arg) and (arg[i] in {':', '='}): inc(i)
-  else: InvalidCmdLineOption(pass, arg, info)
+  else: invalidCmdLineOption(pass, arg, info)
   if state == wHint: 
     var x = findStr(msgs.HintsToStr, id)
     if x >= 0: n = TNoteKind(x + ord(hintMin))
-    else: InvalidCmdLineOption(pass, arg, info)
+    else: invalidCmdLineOption(pass, arg, info)
   else: 
     var x = findStr(msgs.WarningsToStr, id)
     if x >= 0: n = TNoteKind(x + ord(warnMin))
-    else: InvalidCmdLineOption(pass, arg, info)
+    else: invalidCmdLineOption(pass, arg, info)
   case whichKeyword(substr(arg, i))
   of wOn: incl(gNotes, n)
   of wOff: excl(gNotes, n)
-  else: LocalError(info, errOnOrOffExpectedButXFound, arg)
+  else: localError(info, errOnOrOffExpectedButXFound, arg)
 
 proc processCompile(filename: string) = 
   var found = findFile(filename)
@@ -150,14 +150,14 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
     of "markandsweep": result = gSelectedGC == gcMarkAndSweep
     of "generational": result = gSelectedGC == gcGenerational
     of "none":         result = gSelectedGC == gcNone
-    else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
+    else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
   of "opt":
     case arg.normalize
     of "speed": result = contains(gOptions, optOptimizeSpeed)
     of "size": result = contains(gOptions, optOptimizeSize)
     of "none": result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {}
-    else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
-  else: InvalidCmdLineOption(passCmd1, switch, info)
+    else: localError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
+  else: invalidCmdLineOption(passCmd1, switch, info)
 
 proc testCompileOption*(switch: string, info: TLineInfo): bool = 
   case switch.normalize
@@ -173,11 +173,11 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of "linetrace": result = contains(gOptions, optLineTrace)
   of "debugger": result = contains(gOptions, optEndb)
   of "profiler": result = contains(gOptions, optProfiler)
-  of "checks", "x": result = gOptions * checksOptions == checksOptions
+  of "checks", "x": result = gOptions * ChecksOptions == ChecksOptions
   of "floatchecks":
-    result = gOptions * {optNanCheck, optInfCheck} == {optNanCheck, optInfCheck}
+    result = gOptions * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
   of "infchecks": result = contains(gOptions, optInfCheck)
-  of "nanchecks": result = contains(gOptions, optNanCheck)
+  of "nanchecks": result = contains(gOptions, optNaNCheck)
   of "objchecks": result = contains(gOptions, optObjCheck)
   of "fieldchecks": result = contains(gOptions, optFieldCheck)
   of "rangechecks": result = contains(gOptions, optRangeCheck)
@@ -194,7 +194,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation)
   of "implicitstatic": result = contains(gOptions, optImplicitStatic)
   of "patterns": result = contains(gOptions, optPatterns)
-  else: InvalidCmdLineOption(passCmd1, switch, info)
+  else: invalidCmdLineOption(passCmd1, switch, info)
   
 proc processPath(path: string, notRelativeToProj = false): string =
   let p = if notRelativeToProj or os.isAbsolute(path) or
@@ -202,20 +202,20 @@ proc processPath(path: string, notRelativeToProj = false): string =
             path 
           else:
             options.gProjectPath / path
-  result = UnixToNativePath(p % ["nimrod", getPrefixDir(), "lib", libpath,
+  result = unixToNativePath(p % ["nimrod", getPrefixDir(), "lib", libpath,
     "home", removeTrailingDirSep(os.getHomeDir()),
     "projectname", options.gProjectName,
     "projectpath", options.gProjectPath])
 
 proc trackDirty(arg: string, info: TLineInfo) =
   var a = arg.split(',')
-  if a.len != 4: LocalError(info, errTokenExpected,
+  if a.len != 4: localError(info, errTokenExpected,
                             "DIRTY_BUFFER,ORIGINAL_FILE,LINE,COLUMN")
   var line, column: int
   if parseUtils.parseInt(a[2], line) <= 0:
-    LocalError(info, errInvalidNumber, a[1])
+    localError(info, errInvalidNumber, a[1])
   if parseUtils.parseInt(a[3], column) <= 0:
-    LocalError(info, errInvalidNumber, a[2])
+    localError(info, errInvalidNumber, a[2])
   
   gDirtyBufferIdx = a[0].fileInfoIdx
   gDirtyOriginalIdx = a[1].fileInfoIdx
@@ -225,21 +225,21 @@ proc trackDirty(arg: string, info: TLineInfo) =
 
 proc track(arg: string, info: TLineInfo) = 
   var a = arg.split(',')
-  if a.len != 3: LocalError(info, errTokenExpected, "FILE,LINE,COLUMN")
+  if a.len != 3: localError(info, errTokenExpected, "FILE,LINE,COLUMN")
   var line, column: int
   if parseUtils.parseInt(a[1], line) <= 0:
-    LocalError(info, errInvalidNumber, a[1])
+    localError(info, errInvalidNumber, a[1])
   if parseUtils.parseInt(a[2], column) <= 0:
-    LocalError(info, errInvalidNumber, a[2])
+    localError(info, errInvalidNumber, a[2])
   optTrackPos = newLineInfo(a[0], line, column)
   msgs.addCheckpoint(optTrackPos)
 
-proc dynlibOverride(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
+proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
   if pass in {passCmd2, passPP}:
     expectArg(switch, arg, pass, info)
     options.inclDynlibOverride(arg)
 
-proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = 
+proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = 
   var 
     theOS: TSystemOS
     cpu: TSystemCPU
@@ -259,23 +259,26 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of "excludepath":
     expectArg(switch, arg, pass, info)
     let path = processPath(arg)
-    lists.ExcludeStr(options.searchPaths, path)
-    lists.ExcludeStr(options.lazyPaths, path)
+    lists.excludeStr(options.searchPaths, path)
+    lists.excludeStr(options.lazyPaths, path)
   of "nimcache":
     expectArg(switch, arg, pass, info)
     options.nimcacheDir = processPath(arg)
   of "out", "o": 
     expectArg(switch, arg, pass, info)
     options.outFile = arg
+  of "docseesrcurl":
+    expectArg(switch, arg, pass, info)
+    options.docSeeSrcUrl = arg
   of "mainmodule", "m":
     expectArg(switch, arg, pass, info)
     optMainModule = arg
   of "define", "d": 
     expectArg(switch, arg, pass, info)
-    DefineSymbol(arg)
+    defineSymbol(arg)
   of "undef", "u": 
     expectArg(switch, arg, pass, info)
-    UndefSymbol(arg)
+    undefSymbol(arg)
   of "compile": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: processCompile(arg)
@@ -308,7 +311,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     case arg.normalize
     of "boehm": 
       gSelectedGC = gcBoehm
-      DefineSymbol("boehmgc")
+      defineSymbol("boehmgc")
     of "refc":
       gSelectedGC = gcRefc
     of "v2":
@@ -322,42 +325,42 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     of "none":
       gSelectedGC = gcNone
       defineSymbol("nogc")
-    else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
-  of "warnings", "w": ProcessOnOffSwitch({optWarns}, arg, pass, info)
-  of "warning": ProcessSpecificNote(arg, wWarning, pass, info)
-  of "hint": ProcessSpecificNote(arg, wHint, pass, info)
-  of "hints": ProcessOnOffSwitch({optHints}, arg, pass, info)
-  of "threadanalysis": ProcessOnOffSwitchG({optThreadAnalysis}, arg, pass, info)
-  of "stacktrace": ProcessOnOffSwitch({optStackTrace}, arg, pass, info)
-  of "linetrace": ProcessOnOffSwitch({optLineTrace}, arg, pass, info)
+    else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
+  of "warnings", "w": processOnOffSwitch({optWarns}, arg, pass, info)
+  of "warning": processSpecificNote(arg, wWarning, pass, info)
+  of "hint": processSpecificNote(arg, wHint, pass, info)
+  of "hints": processOnOffSwitch({optHints}, arg, pass, info)
+  of "threadanalysis": processOnOffSwitchG({optThreadAnalysis}, arg, pass, info)
+  of "stacktrace": processOnOffSwitch({optStackTrace}, arg, pass, info)
+  of "linetrace": processOnOffSwitch({optLineTrace}, arg, pass, info)
   of "debugger": 
-    ProcessOnOffSwitch({optEndb}, arg, pass, info)
-    if optEndb in gOptions: DefineSymbol("endb")
-    else: UndefSymbol("endb")
+    processOnOffSwitch({optEndb}, arg, pass, info)
+    if optEndb in gOptions: defineSymbol("endb")
+    else: undefSymbol("endb")
   of "profiler": 
-    ProcessOnOffSwitch({optProfiler}, arg, pass, info)
-    if optProfiler in gOptions: DefineSymbol("profiler")
-    else: UndefSymbol("profiler")
-  of "checks", "x": ProcessOnOffSwitch(checksOptions, arg, pass, info)
+    processOnOffSwitch({optProfiler}, arg, pass, info)
+    if optProfiler in gOptions: defineSymbol("profiler")
+    else: undefSymbol("profiler")
+  of "checks", "x": processOnOffSwitch(ChecksOptions, arg, pass, info)
   of "floatchecks":
-    ProcessOnOffSwitch({optNanCheck, optInfCheck}, arg, pass, info)
-  of "infchecks": ProcessOnOffSwitch({optInfCheck}, arg, pass, info)
-  of "nanchecks": ProcessOnOffSwitch({optNanCheck}, arg, pass, info)
-  of "objchecks": ProcessOnOffSwitch({optObjCheck}, arg, pass, info)
-  of "fieldchecks": ProcessOnOffSwitch({optFieldCheck}, arg, pass, info)
-  of "rangechecks": ProcessOnOffSwitch({optRangeCheck}, arg, pass, info)
-  of "boundchecks": ProcessOnOffSwitch({optBoundsCheck}, arg, pass, info)
-  of "overflowchecks": ProcessOnOffSwitch({optOverflowCheck}, arg, pass, info)
-  of "linedir": ProcessOnOffSwitch({optLineDir}, arg, pass, info)
-  of "assertions", "a": ProcessOnOffSwitch({optAssert}, arg, pass, info)
-  of "deadcodeelim": ProcessOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
-  of "threads": ProcessOnOffSwitchG({optThreads}, arg, pass, info)
-  of "tlsemulation": ProcessOnOffSwitchG({optTlsEmulation}, arg, pass, info)
-  of "taintmode": ProcessOnOffSwitchG({optTaintMode}, arg, pass, info)
+    processOnOffSwitch({optNaNCheck, optInfCheck}, arg, pass, info)
+  of "infchecks": processOnOffSwitch({optInfCheck}, arg, pass, info)
+  of "nanchecks": processOnOffSwitch({optNaNCheck}, arg, pass, info)
+  of "objchecks": processOnOffSwitch({optObjCheck}, arg, pass, info)
+  of "fieldchecks": processOnOffSwitch({optFieldCheck}, arg, pass, info)
+  of "rangechecks": processOnOffSwitch({optRangeCheck}, arg, pass, info)
+  of "boundchecks": processOnOffSwitch({optBoundsCheck}, arg, pass, info)
+  of "overflowchecks": processOnOffSwitch({optOverflowCheck}, arg, pass, info)
+  of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info)
+  of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info)
+  of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
+  of "threads": processOnOffSwitchG({optThreads}, arg, pass, info)
+  of "tlsemulation": processOnOffSwitchG({optTlsEmulation}, arg, pass, info)
+  of "taintmode": processOnOffSwitchG({optTaintMode}, arg, pass, info)
   of "implicitstatic":
-    ProcessOnOffSwitch({optImplicitStatic}, arg, pass, info)
+    processOnOffSwitch({optImplicitStatic}, arg, pass, info)
   of "patterns":
-    ProcessOnOffSwitch({optPatterns}, arg, pass, info)
+    processOnOffSwitch({optPatterns}, arg, pass, info)
   of "opt":
     expectArg(switch, arg, pass, info)
     case arg.normalize
@@ -370,7 +373,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     of "none":
       excl(gOptions, optOptimizeSpeed)
       excl(gOptions, optOptimizeSize)
-    else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
+    else: localError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
   of "app": 
     expectArg(switch, arg, pass, info)
     case arg.normalize
@@ -392,7 +395,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
       excl(gGlobalOptions, optGenGuiApp)
       defineSymbol("library")
       defineSymbol("staticlib")
-    else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
+    else: localError(info, errGuiConsoleOrLibExpectedButXFound, arg)
   of "passc", "t": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: extccomp.addCompileOption(arg)
@@ -401,18 +404,18 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     if pass in {passCmd2, passPP}: extccomp.addLinkOption(arg)
   of "cincludes":
     expectArg(switch, arg, pass, info)
-    if pass in {passCmd2, passPP}: cIncludes.add arg
+    if pass in {passCmd2, passPP}: cIncludes.add arg.processPath
   of "clibdir":
     expectArg(switch, arg, pass, info)
-    if pass in {passCmd2, passPP}: cLibs.add arg
+    if pass in {passCmd2, passPP}: cLibs.add arg.processPath
   of "clib":
     expectArg(switch, arg, pass, info)
-    if pass in {passCmd2, passPP}: cLinkedLibs.add arg
+    if pass in {passCmd2, passPP}: cLinkedLibs.add arg.processPath
   of "header":
     headerFile = arg
     incl(gGlobalOptions, optGenIndex)
   of "index":
-    ProcessOnOffSwitchG({optGenIndex}, arg, pass, info)
+    processOnOffSwitchG({optGenIndex}, arg, pass, info)
   of "import":
     expectArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: implicitImports.add arg
@@ -428,19 +431,19 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of "os": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd1, passPP}: 
-      theOS = platform.NameToOS(arg)
-      if theOS == osNone: LocalError(info, errUnknownOS, arg)
+      theOS = platform.nameToOS(arg)
+      if theOS == osNone: localError(info, errUnknownOS, arg)
       elif theOS != platform.hostOS: 
         setTarget(theOS, targetCPU)
-        condsyms.InitDefines()
+        condsyms.initDefines()
   of "cpu": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd1, passPP}: 
-      cpu = platform.NameToCPU(arg)
-      if cpu == cpuNone: LocalError(info, errUnknownCPU, arg)
+      cpu = platform.nameToCPU(arg)
+      if cpu == cpuNone: localError(info, errUnknownCPU, arg)
       elif cpu != platform.hostCPU: 
         setTarget(targetOS, cpu)
-        condsyms.InitDefines()
+        condsyms.initDefines()
   of "run", "r": 
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optRun)
@@ -460,7 +463,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     expectNoArg(switch, arg, pass, info)
     helpOnError(pass)
   of "symbolfiles": 
-    ProcessOnOffSwitchG({optSymbolFiles}, arg, pass, info)
+    processOnOffSwitchG({optSymbolFiles}, arg, pass, info)
   of "skipcfg": 
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optSkipConfigFile)
@@ -520,13 +523,13 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
     case arg
     of "partial": idents.firstCharIsCS = true
     of "none": idents.firstCharIsCS = false
-    else: LocalError(info, errGenerated,
+    else: localError(info, errGenerated,
       "'partial' or 'none' expected, but found " & arg)
   else:
     if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
-    else: InvalidCmdLineOption(pass, switch, info)
+    else: invalidCmdLineOption(pass, switch, info)
   
-proc ProcessCommand(switch: string, pass: TCmdLinePass) =
+proc processCommand(switch: string, pass: TCmdLinePass) =
   var cmd, arg: string
   splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
   processSwitch(cmd, arg, pass, gCmdLineInfo)
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 21095072b..ddf2075b4 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -16,10 +16,10 @@ import
 # to be style insensitive. Otherwise hell would break lose.
 var gSymbols: PStringTable
 
-proc DefineSymbol*(symbol: string) = 
+proc defineSymbol*(symbol: string) = 
   gSymbols[symbol] = "true"
 
-proc UndefSymbol*(symbol: string) = 
+proc undefSymbol*(symbol: string) = 
   gSymbols[symbol] = "false"
 
 proc isDefined*(symbol: string): bool = 
@@ -37,52 +37,53 @@ proc countDefinedSymbols*(): int =
   for key, val in pairs(gSymbols):
     if val == "true": inc(result)
 
-proc InitDefines*() = 
+proc initDefines*() = 
   gSymbols = newStringTable(modeStyleInsensitive)
-  DefineSymbol("nimrod") # 'nimrod' is always defined
+  defineSymbol("nimrod") # 'nimrod' is always defined
   # for bootstrapping purposes and old code:
-  DefineSymbol("nimhygiene")
-  DefineSymbol("niminheritable")
-  DefineSymbol("nimmixin")
-  DefineSymbol("nimeffects")
-  DefineSymbol("nimbabel")
-  DefineSymbol("nimcomputedgoto")
+  defineSymbol("nimhygiene")
+  defineSymbol("niminheritable")
+  defineSymbol("nimmixin")
+  defineSymbol("nimeffects")
+  defineSymbol("nimbabel")
+  defineSymbol("nimcomputedgoto")
+  defineSymbol("nimunion")
   
   # add platform specific symbols:
   case targetCPU
-  of cpuI386: DefineSymbol("x86")
-  of cpuIa64: DefineSymbol("itanium")
-  of cpuAmd64: DefineSymbol("x8664")
+  of cpuI386: defineSymbol("x86")
+  of cpuIa64: defineSymbol("itanium")
+  of cpuAmd64: defineSymbol("x8664")
   else: discard
   case targetOS
-  of osDOS: 
-    DefineSymbol("msdos")
+  of osDos: 
+    defineSymbol("msdos")
   of osWindows: 
-    DefineSymbol("mswindows")
-    DefineSymbol("win32")
-  of osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX, osAtari, osAix, 
+    defineSymbol("mswindows")
+    defineSymbol("win32")
+  of osLinux, osMorphos, osSkyos, osIrix, osPalmos, osQnx, osAtari, osAix, 
      osHaiku:
     # these are all 'unix-like'
-    DefineSymbol("unix")
-    DefineSymbol("posix")
+    defineSymbol("unix")
+    defineSymbol("posix")
   of osSolaris: 
-    DefineSymbol("sunos")
-    DefineSymbol("unix")
-    DefineSymbol("posix")
-  of osNetBSD, osFreeBSD, osOpenBSD: 
-    DefineSymbol("unix")
-    DefineSymbol("bsd")
-    DefineSymbol("posix")
-  of osMacOS: 
-    DefineSymbol("macintosh")
-  of osMacOSX: 
-    DefineSymbol("macintosh")
-    DefineSymbol("unix")
-    DefineSymbol("posix")
+    defineSymbol("sunos")
+    defineSymbol("unix")
+    defineSymbol("posix")
+  of osNetbsd, osFreebsd, osOpenbsd: 
+    defineSymbol("unix")
+    defineSymbol("bsd")
+    defineSymbol("posix")
+  of osMacos: 
+    defineSymbol("macintosh")
+  of osMacosx: 
+    defineSymbol("macintosh")
+    defineSymbol("unix")
+    defineSymbol("posix")
   else: discard
-  DefineSymbol("cpu" & $cpu[targetCPU].bit)
-  DefineSymbol(normalize(endianToStr[cpu[targetCPU].endian]))
-  DefineSymbol(cpu[targetCPU].name)
-  DefineSymbol(platform.os[targetOS].name)
+  defineSymbol("cpu" & $CPU[targetCPU].bit)
+  defineSymbol(normalize(EndianToStr[CPU[targetCPU].endian]))
+  defineSymbol(CPU[targetCPU].name)
+  defineSymbol(platform.OS[targetOS].name)
   if platform.OS[targetOS].props.contains(ospLacksThreadVars):
-    DefineSymbol("emulatedthreadvars")
+    defineSymbol("emulatedthreadvars")
diff --git a/compiler/crc.nim b/compiler/crc.nim
index a3b181e20..ae1df3ff1 100644
--- a/compiler/crc.nim
+++ b/compiler/crc.nim
@@ -18,8 +18,8 @@ const
   InitAdler32* = int32(1)
 
 proc updateCrc32*(val: int8, crc: TCrc32): TCrc32 {.inline.}
-proc updateCrc32*(val: Char, crc: TCrc32): TCrc32 {.inline.}
-proc crcFromBuf*(buf: Pointer, length: int): TCrc32
+proc updateCrc32*(val: char, crc: TCrc32): TCrc32 {.inline.}
+proc crcFromBuf*(buf: pointer, length: int): TCrc32
 proc strCrc32*(s: string): TCrc32
 proc crcFromFile*(filename: string): TCrc32
 proc updateAdler32*(adler: int32, buf: pointer, length: int): int32
@@ -75,10 +75,10 @@ const
     755167117]
 
 proc updateCrc32(val: int8, crc: TCrc32): TCrc32 = 
-  result = TCrc32(crc32Table[(int(crc) xor (int(val) and 0x000000FF)) and
+  result = TCrc32(crc32table[(int(crc) xor (int(val) and 0x000000FF)) and
       0x000000FF]) xor (crc shr TCrc32(8))
 
-proc updateCrc32(val: Char, crc: TCrc32): TCrc32 = 
+proc updateCrc32(val: char, crc: TCrc32): TCrc32 = 
   result = updateCrc32(toU8(ord(val)), crc)
 
 proc strCrc32(s: string): TCrc32 = 
@@ -93,7 +93,7 @@ type
   TByteArray = array[0..10000000, int8]
   PByteArray = ref TByteArray
 
-proc crcFromBuf(buf: Pointer, length: int): TCrc32 = 
+proc crcFromBuf(buf: pointer, length: int): TCrc32 = 
   var p = cast[PByteArray](buf)
   result = InitCrc32
   for i in countup(0, length - 1): result = updateCrc32(p[i], result)
@@ -102,11 +102,11 @@ proc crcFromFile(filename: string): TCrc32 =
   const 
     bufSize = 8000 # don't use 8K for the memory allocator!
   var 
-    bin: tfile
+    bin: TFile
   result = InitCrc32
   if not open(bin, filename): 
     return                    # not equal if file does not exist
-  var buf = alloc(BufSize)
+  var buf = alloc(bufSize)
   var p = cast[PByteArray](buf)
   while true: 
     var readBytes = readBuffer(bin, buf, bufSize)
diff --git a/compiler/depends.nim b/compiler/depends.nim
index 1468cbdb9..a43eaf844 100644
--- a/compiler/depends.nim
+++ b/compiler/depends.nim
@@ -39,11 +39,11 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
   of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: 
     for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i])
   else: 
-    nil
+    discard
 
 proc generateDot(project: string) = 
   writeRope(ropef("digraph $1 {$n$2}$n", [
-      toRope(changeFileExt(extractFileName(project), "")), gDotGraph]), 
+      toRope(changeFileExt(extractFilename(project), "")), gDotGraph]), 
             changeFileExt(project, "dot"))
 
 proc myOpen(module: PSym): PPassContext =
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index d44018a2b..6948c4979 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -14,7 +14,7 @@
 import
   ast, strutils, strtabs, options, msgs, os, ropes, idents,
   wordrecg, syntaxes, renderer, lexer, rstast, rst, rstgen, times, highlite,
-  importer, sempass2, json
+  importer, sempass2, json, xmltree, cgi, typesrenderer
 
 type
   TSections = array[TSymKind, PRope]
@@ -23,8 +23,9 @@ type
     id: int                  # for generating IDs
     toc, section: TSections
     indexValFilename: string
+    seenSymbols: PStringTable # avoids duplicate symbol generation for HTML.
 
-  PDoc* = ref TDocumentor
+  PDoc* = ref TDocumentor ## Alias to type less.
 
 proc compilerMsgHandler(filename: string, line, col: int,
                         msgKind: rst.TMsgKind, arg: string) {.procvar.} =
@@ -40,33 +41,40 @@ proc compilerMsgHandler(filename: string, line, col: int,
   of mwRedefinitionOfLabel: k = warnRedefinitionOfLabel
   of mwUnknownSubstitution: k = warnUnknownSubstitutionX
   of mwUnsupportedLanguage: k = warnLanguageXNotSupported
-  GlobalError(newLineInfo(filename, line, col), k, arg)
+  globalError(newLineInfo(filename, line, col), k, arg)
+
+proc docgenFindFile(s: string): string {.procvar.} =
+  result = options.findFile(s)
+  if result.len == 0:
+    result = getCurrentDir() / s
+    if not existsFile(result): result = ""
 
 proc parseRst(text, filename: string,
               line, column: int, hasToc: var bool,
               rstOptions: TRstParseOptions): PRstNode =
   result = rstParse(text, filename, line, column, hasToc, rstOptions,
-                    options.FindFile, compilerMsgHandler)
+                    docgenFindFile, compilerMsgHandler)
 
 proc newDocumentor*(filename: string, config: PStringTable): PDoc =
   new(result)
-  initRstGenerator(result[], (if gCmd != cmdRst2Tex: outHtml else: outLatex),
+  initRstGenerator(result[], (if gCmd != cmdRst2tex: outHtml else: outLatex),
                    options.gConfigVars, filename, {roSupportRawDirective},
-                   options.FindFile, compilerMsgHandler)
+                   docgenFindFile, compilerMsgHandler)
+  result.seenSymbols = newStringTable(modeCaseInsensitive)
   result.id = 100
 
-proc dispA(dest: var PRope, xml, tex: string, args: openarray[PRope]) =
-  if gCmd != cmdRst2Tex: appf(dest, xml, args)
+proc dispA(dest: var PRope, xml, tex: string, args: openArray[PRope]) =
+  if gCmd != cmdRst2tex: appf(dest, xml, args)
   else: appf(dest, tex, args)
 
-proc getVarIdx(varnames: openarray[string], id: string): int =
+proc getVarIdx(varnames: openArray[string], id: string): int =
   for i in countup(0, high(varnames)):
     if cmpIgnoreStyle(varnames[i], id) == 0:
       return i
   result = -1
 
-proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openarray[string],
-                         varvalues: openarray[PRope]): PRope =
+proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string],
+                         varvalues: openArray[PRope]): PRope =
   var i = 0
   var L = len(frmt)
   result = nil
@@ -85,7 +93,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openarray[string],
       of '0'..'9':
         var j = 0
         while true:
-          j = (j * 10) + Ord(frmt[i]) - ord('0')
+          j = (j * 10) + ord(frmt[i]) - ord('0')
           inc(i)
           if (i > L + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
         if j > high(varvalues) + 1: internalError("ropeFormatNamedVars")
@@ -112,7 +120,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openarray[string],
         var idx = getVarIdx(varnames, id)
         if idx >= 0: app(result, varvalues[idx])
         else: rawMessage(errUnkownSubstitionVar, id)
-      else: InternalError("ropeFormatNamedVars")
+      else: internalError("ropeFormatNamedVars")
     var start = i
     while i < L:
       if frmt[i] != '$': inc(i)
@@ -124,7 +132,7 @@ proc genComment(d: PDoc, n: PNode): string =
   var dummyHasToc: bool
   if n.comment != nil and startsWith(n.comment, "##"):
     renderRstToOut(d[], parseRst(n.comment, toFilename(n.info),
-                               toLineNumber(n.info), toColumn(n.info),
+                               toLinenumber(n.info), toColumn(n.info),
                                dummyHasToc, d.options + {roSkipPounds}), result)
 
 proc genRecComment(d: PDoc, n: PNode): PRope =
@@ -138,6 +146,23 @@ proc genRecComment(d: PDoc, n: PNode): PRope =
   else:
     n.comment = nil
 
+proc getPlainDocstring(n: PNode): string =
+  ## Gets the plain text docstring of a node non destructively.
+  ##
+  ## You need to call this before genRecComment, whose side effects are removal
+  ## of comments from the tree. The proc will recursively scan and return all
+  ## the concatenated ``##`` comments of the node.
+  result = ""
+  if n == nil: return
+  if n.comment != nil and startsWith(n.comment, "##"):
+    result = n.comment
+  if result.len < 1:
+    if n.kind notin {nkEmpty..nkNilLit}:
+      for i in countup(0, len(n)-1):
+        result = getPlainDocstring(n.sons[i])
+        if result.len > 0: return
+
+
 proc findDocComment(n: PNode): PNode =
   if n == nil: return nil
   if not isNil(n.comment) and startsWith(n.comment, "##"): return n
@@ -152,7 +177,7 @@ proc extractDocComment*(s: PSym, d: PDoc = nil): string =
     if not d.isNil:
       var dummyHasToc: bool
       renderRstToOut(d[], parseRst(n.comment, toFilename(n.info),
-                                   toLineNumber(n.info), toColumn(n.info),
+                                   toLinenumber(n.info), toColumn(n.info),
                                    dummyHasToc, d.options + {roSkipPounds}),
                      result)
     else:
@@ -199,14 +224,111 @@ proc getRstName(n: PNode): PRstNode =
     internalError(n.info, "getRstName()")
     result = nil
 
+proc newUniquePlainSymbol(d: PDoc, original: string): string =
+  ## Returns a new unique plain symbol made up from the original.
+  ##
+  ## When a collision is found in the seenSymbols table, new numerical variants
+  ## with underscore + number will be generated.
+  if not d.seenSymbols.hasKey(original):
+    result = original
+    d.seenSymbols[original] = ""
+    return
+
+  # Iterate over possible numeric variants of the original name.
+  var count = 2
+
+  while true:
+    result = original & "_" & $count
+    if not d.seenSymbols.hasKey(result):
+      d.seenSymbols[result] = ""
+      break
+    count += 1
+
+
+proc complexName(k: TSymKind, n: PNode, baseName: string): string =
+  ## Builds a complex unique href name for the node.
+  ##
+  ## Pass as ``baseName`` the plain symbol obtained from the nodeName. The
+  ## format of the returned symbol will be ``baseName(.callable type)?,(param
+  ## type)?(,param type)*``. The callable type part will be added only if the
+  ## node is not a proc, as those are the common ones. The suffix will be a dot
+  ## and a single letter representing the type of the callable. The parameter
+  ## types will be added with a preceeding dash. Return types won't be added.
+  ##
+  ## If you modify the output of this proc, please update the anchor generation
+  ## section of ``doc/docgen.txt``.
+  result = baseName
+  case k:
+  of skProc: result.add(defaultParamSeparator)
+  of skMacro: result.add(".m" & defaultParamSeparator)
+  of skMethod: result.add(".e" & defaultParamSeparator)
+  of skIterator: result.add(".i" & defaultParamSeparator)
+  of skTemplate: result.add(".t" & defaultParamSeparator)
+  of skConverter: result.add(".c" & defaultParamSeparator)
+  else: discard
+
+  if len(n) > paramsPos and n[paramsPos].kind == nkFormalParams:
+    result.add(renderParamTypes(n[paramsPos]))
+
+
+proc isCallable(n: PNode): bool =
+  ## Returns true if `n` contains a callable node.
+  case n.kind
+  of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef,
+    nkConverterDef: result = true
+  else:
+    result = false
+
+
+proc docstringSummary(rstText: string): string =
+  ## Returns just the first line or a brief chunk of text from a rst string.
+  ##
+  ## Most docstrings will contain a one liner summary, so stripping at the
+  ## first newline is usually fine. If after that the content is still too big,
+  ## it is stripped at the first comma, colon or dot, usual english sentence
+  ## separators.
+  ##
+  ## No guarantees are made on the size of the output, but it should be small.
+  ## Also, we hope to not break the rst, but maybe we do. If there is any
+  ## trimming done, an ellipsis unicode char is added.
+  const maxDocstringChars = 100
+  assert (rstText.len < 2 or (rstText[0] == '#' and rstText[1] == '#'))
+  result = rstText.substr(2).strip
+  var pos = result.find('\L')
+  if pos > 0:
+    result.delete(pos, result.len - 1)
+    result.add("…")
+  if pos < maxDocstringChars:
+    return
+  # Try to keep trimming at other natural boundaries.
+  pos = result.find({'.', ',', ':'})
+  let last = result.len - 1
+  if pos > 0 and pos < last:
+    result.delete(pos, last)
+    result.add("…")
+
+
 proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
   if not isVisible(nameNode): return
-  var name = toRope(getName(d, nameNode))
+  let
+    name = getName(d, nameNode)
+    nameRope = name.toRope
+    plainDocstring = getPlainDocstring(n) # call here before genRecComment!
   var result: PRope = nil
-  var literal = ""
+  var literal, plainName = ""
   var kind = tkEof
   var comm = genRecComment(d, n)  # call this here for the side-effect!
   var r: TSrcGen
+  # Obtain the plain rendered string for hyperlink titles.
+  initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments,
+    renderNoPragmas, renderNoProcDefs})
+  while true:
+    getNextTok(r, kind, literal)
+    if kind == tkEof:
+      break
+    plainName.add(literal)
+
+  # Render the HTML hyperlink.
   initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments})
   while true:
     getNextTok(r, kind, literal)
@@ -247,13 +369,47 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
       dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
             [toRope(esc(d.target, literal))])
   inc(d.id)
+  let
+    plainNameRope = toRope(xmltree.escape(plainName.strip))
+    cleanPlainSymbol = renderPlainSymbolName(nameNode)
+    complexSymbol = complexName(k, n, cleanPlainSymbol)
+    plainSymbolRope = toRope(cleanPlainSymbol)
+    plainSymbolEncRope = toRope(URLEncode(cleanPlainSymbol))
+    itemIDRope = toRope(d.id)
+    symbolOrId = d.newUniquePlainSymbol(complexSymbol)
+    symbolOrIdRope = symbolOrId.toRope
+    symbolOrIdEncRope = URLEncode(symbolOrId).toRope
+
+  var seeSrcRope: PRope = nil
+  let docItemSeeSrc = getConfigVar("doc.item.seesrc")
+  if docItemSeeSrc.len > 0 and options.docSeeSrcUrl.len > 0:
+    let urlRope = ropeFormatNamedVars(options.docSeeSrcUrl,
+      ["path", "line"], [n.info.toFilename.toRope, toRope($n.info.line)])
+    dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
+        ["path", "line", "url"], [n.info.toFilename.toRope,
+        toRope($n.info.line), urlRope])])
+
   app(d.section[k], ropeFormatNamedVars(getConfigVar("doc.item"),
-                                        ["name", "header", "desc", "itemID"],
-                                        [name, result, comm, toRope(d.id)]))
+    ["name", "header", "desc", "itemID", "header_plain", "itemSym",
+      "itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "seeSrc"],
+    [nameRope, result, comm, itemIDRope, plainNameRope, plainSymbolRope,
+      symbolOrIdRope, plainSymbolEncRope, symbolOrIdEncRope, seeSrcRope]))
   app(d.toc[k], ropeFormatNamedVars(getConfigVar("doc.item.toc"),
-                                    ["name", "header", "desc", "itemID"], [
-      toRope(getName(d, nameNode, d.splitAfter)), result, comm, toRope(d.id)]))
-  setIndexTerm(d[], $d.id, getName(d, nameNode))
+    ["name", "header", "desc", "itemID", "header_plain", "itemSym",
+      "itemSymOrID", "itemSymEnc", "itemSymOrIDEnc"],
+    [toRope(getName(d, nameNode, d.splitAfter)), result, comm,
+      itemIDRope, plainNameRope, plainSymbolRope, symbolOrIdRope,
+      plainSymbolEncRope, symbolOrIdEncRope]))
+
+  # Ironically for types the complexSymbol is *cleaner* than the plainName
+  # because it doesn't include object fields or documentation comments. So we
+  # use the plain one for callable elements, and the complex for the rest.
+  var linkTitle = changeFileExt(extractFilename(d.filename), "") & " : "
+  if n.isCallable: linkTitle.add(xmltree.escape(plainName.strip))
+  else: linkTitle.add(xmltree.escape(complexSymbol.strip))
+
+  setIndexTerm(d[], symbolOrId, name, linkTitle,
+    xmltree.escape(plainDocstring.docstringSummary))
 
 proc genJSONItem(d: PDoc, n, nameNode: PNode, k: TSymKind): PJsonNode =
   if not isVisible(nameNode): return
@@ -272,7 +428,7 @@ proc genJSONItem(d: PDoc, n, nameNode: PNode, k: TSymKind): PJsonNode =
     result["code"] = %r.buf
 
 proc checkForFalse(n: PNode): bool =
-  result = n.kind == nkIdent and IdentEq(n.ident, "false")
+  result = n.kind == nkIdent and identEq(n.ident, "false")
 
 proc traceDeps(d: PDoc, n: PNode) =
   const k = skModule
@@ -313,7 +469,7 @@ proc generateDoc*(d: PDoc, n: PNode) =
   of nkImportStmt:
     for i in 0 .. sonsLen(n)-1: traceDeps(d, n.sons[i])
   of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
-  else: nil
+  else: discard
 
 proc generateJson(d: PDoc, n: PNode, jArray: PJsonNode = nil): PJsonNode =
   case n.kind
@@ -355,12 +511,12 @@ proc generateJson(d: PDoc, n: PNode, jArray: PJsonNode = nil): PJsonNode =
     # generate documentation for the first branch only:
     if not checkForFalse(n.sons[0].sons[0]) and jArray != nil:
       discard generateJson(d, lastSon(n.sons[0]), jArray)
-  else: nil
+  else: discard
 
 proc genSection(d: PDoc, kind: TSymKind) =
   const sectionNames: array[skModule..skTemplate, string] = [
     "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Methods",
-    "Iterators", "Converters", "Macros", "Templates"
+    "Iterators", "Iterators", "Converters", "Macros", "Templates"
   ]
   if d.section[kind] == nil: return
   var title = sectionNames[kind].toRope
@@ -408,7 +564,7 @@ proc genOutFile(d: PDoc): PRope =
 proc generateIndex*(d: PDoc) =
   if optGenIndex in gGlobalOptions:
     writeIndexFile(d[], splitFile(options.outFile).dir /
-                        splitFile(d.filename).name & indexExt)
+                        splitFile(d.filename).name & IndexExt)
 
 proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
   var content = genOutFile(d)
@@ -417,7 +573,7 @@ proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
   else:
     writeRope(content, getOutFile(filename, outExt), useWarning)
 
-proc CommandDoc*() =
+proc commandDoc*() =
   var ast = parseFile(gProjectMainIdx)
   if ast == nil: return
   var d = newDocumentor(gProjectFull, options.gConfigVars)
@@ -426,7 +582,7 @@ proc CommandDoc*() =
   writeOutput(d, gProjectFull, HtmlExt)
   generateIndex(d)
 
-proc CommandRstAux(filename, outExt: string) =
+proc commandRstAux(filename, outExt: string) =
   var filen = addFileExt(filename, "txt")
   var d = newDocumentor(filen, options.gConfigVars)
   var rst = parseRst(readFile(filen), filen, 0, 1, d.hasToc,
@@ -439,14 +595,14 @@ proc CommandRstAux(filename, outExt: string) =
   writeOutput(d, filename, outExt)
   generateIndex(d)
 
-proc CommandRst2Html*() =
-  CommandRstAux(gProjectFull, HtmlExt)
+proc commandRst2Html*() =
+  commandRstAux(gProjectFull, HtmlExt)
 
-proc CommandRst2TeX*() =
+proc commandRst2TeX*() =
   splitter = "\\-"
-  CommandRstAux(gProjectFull, TexExt)
+  commandRstAux(gProjectFull, TexExt)
 
-proc CommandJSON*() =
+proc commandJSON*() =
   var ast = parseFile(gProjectMainIdx)
   if ast == nil: return
   var d = newDocumentor(gProjectFull, options.gConfigVars)
@@ -460,7 +616,7 @@ proc CommandJSON*() =
     echo getOutFile(gProjectFull, JsonExt)
     writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false)
 
-proc CommandBuildIndex*() =
+proc commandBuildIndex*() =
   var content = mergeIndexes(gProjectFull).toRope
 
   let code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title",
diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim
index d48f53d15..d76be8e3c 100644
--- a/compiler/docgen2.nim
+++ b/compiler/docgen2.nim
@@ -27,7 +27,7 @@ proc close(p: PPassContext, n: PNode): PNode =
     try:
       generateIndex(g.doc)
     except EIO:
-      nil
+      discard
 
 proc processNode(c: PPassContext, n: PNode): PNode = 
   result = n
@@ -46,4 +46,4 @@ proc myOpen(module: PSym): PPassContext =
 const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
 
 proc finishDoc2Pass*(project: string) = 
-  nil
+  discard
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index 21a131996..f798a43ac 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -9,7 +9,7 @@
 
 ## This file implements the FFI part of the evaluator for Nimrod code.
 
-import ast, astalgo, ropes, types, options, tables, dynlib, libffi, msgs
+import ast, astalgo, ropes, types, options, tables, dynlib, libffi, msgs, os
 
 when defined(windows):
   const libcDll = "msvcrt.dll"
@@ -20,7 +20,11 @@ type
   TDllCache = tables.TTable[string, TLibHandle]
 var
   gDllCache = initTable[string, TLibHandle]()
-  gExeHandle = LoadLib()
+
+when defined(windows):
+  var gExeHandle = loadLib(os.getAppFilename())
+else:
+  var gExeHandle = loadLib()
 
 proc getDll(cache: var TDllCache; dll: string; info: TLineInfo): pointer =
   result = cache[dll]
@@ -28,15 +32,17 @@ proc getDll(cache: var TDllCache; dll: string; info: TLineInfo): pointer =
     var libs: seq[string] = @[]
     libCandidates(dll, libs)
     for c in libs:
-      result = LoadLib(c)
+      result = loadLib(c)
       if not result.isNil: break
     if result.isNil:
-      GlobalError(info, "cannot load: " & dll)
+      globalError(info, "cannot load: " & dll)
     cache[dll] = result
 
 const
   nkPtrLit = nkIntLit # hopefully we can get rid of this hack soon
 
+var myerrno {.importc: "errno", header: "<errno.h>".}: cint ## error variable
+
 proc importcSymbol*(sym: PSym): PNode =
   let name = ropeToStr(sym.loc.r)
   
@@ -47,10 +53,11 @@ proc importcSymbol*(sym: PSym): PNode =
   of "stdin":  result.intVal = cast[TAddress](system.stdin)
   of "stdout": result.intVal = cast[TAddress](system.stdout)
   of "stderr": result.intVal = cast[TAddress](system.stderr)
+  of "vmErrnoWrapper": result.intVal = cast[TAddress](myerrno)
   else:
     let lib = sym.annex
     if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
-      GlobalError(sym.info, "dynlib needs to be a string lit for the REPL")
+      globalError(sym.info, "dynlib needs to be a string lit for the REPL")
     var theAddr: pointer
     if lib.isNil and not gExehandle.isNil:
       # first try this exe itself:
@@ -58,10 +65,12 @@ proc importcSymbol*(sym: PSym): PNode =
       # then try libc:
       if theAddr.isNil:
         let dllhandle = gDllCache.getDll(libcDll, sym.info)
-        theAddr = dllhandle.checkedSymAddr(name)
-    else:
-      let dllhandle = gDllCache.getDll(lib.path.strVal, sym.info)
-      theAddr = dllhandle.checkedSymAddr(name)
+        theAddr = dllhandle.symAddr(name)
+    elif not lib.isNil:
+      let dllhandle = gDllCache.getDll(if lib.kind == libHeader: libcDll 
+                                       else: lib.path.strVal, sym.info)
+      theAddr = dllhandle.symAddr(name)
+    if theAddr.isNil: globalError(sym.info, "cannot import: " & sym.name.s)
     result.intVal = cast[TAddress](theAddr)
 
 proc mapType(t: ast.PType): ptr libffi.TType =
@@ -78,7 +87,7 @@ proc mapType(t: ast.PType): ptr libffi.TType =
   of tyFloat, tyFloat64: result = addr libffi.type_double
   of tyFloat32: result = addr libffi.type_float
   of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
-     tyStmt, tyTypeDesc, tyProc, tyArray, tyArrayConstr, tyNil:
+     tyStmt, tyTypeDesc, tyProc, tyArray, tyArrayConstr, tyStatic, tyNil:
     result = addr libffi.type_pointer
   of tyDistinct:
     result = mapType(t.sons[0])
@@ -93,7 +102,7 @@ proc mapCallConv(cc: TCallingConvention, info: TLineInfo): TABI =
   of ccStdCall: result = when defined(windows): STDCALL else: DEFAULT_ABI
   of ccCDecl: result = DEFAULT_ABI
   else:
-    GlobalError(info, "cannot map calling convention to FFI")
+    globalError(info, "cannot map calling convention to FFI")
 
 template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[]
 template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v
@@ -107,7 +116,7 @@ proc packSize(v: PNode, typ: PType): int =
     if v.kind in {nkNilLit, nkPtrLit}:
       result = sizeof(pointer)
     else:
-      result = sizeof(pointer) + packSize(v.sons[0], typ.sons[0])
+      result = sizeof(pointer) + packSize(v.sons[0], typ.lastSon)
   of tyDistinct, tyGenericInst:
     result = packSize(v, typ.sons[0])
   of tyArray, tyArrayConstr:
@@ -139,10 +148,10 @@ proc getField(n: PNode; position: int): PSym =
       else: internalError(n.info, "getField(record case branch)")
   of nkSym:
     if n.sym.position == position: result = n.sym
-  else: nil
+  else: discard
 
 proc packObject(x: PNode, typ: PType, res: pointer) =
-  InternalAssert x.kind in {nkObjConstr, nkPar}
+  internalAssert x.kind in {nkObjConstr, nkPar}
   # compute the field's offsets:
   discard typ.getSize
   for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
@@ -155,7 +164,7 @@ proc packObject(x: PNode, typ: PType, res: pointer) =
       let field = getField(typ.n, i)
       pack(it, field.typ, res +! field.offset)
     else:
-      GlobalError(x.info, "cannot pack unnamed tuple")
+      globalError(x.info, "cannot pack unnamed tuple")
 
 const maxPackDepth = 20
 var packRecCheck = 0
@@ -184,7 +193,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     of 4: awr(int32, v.intVal.int32)
     of 8: awr(int64, v.intVal.int64)
     else:
-      GlobalError(v.info, "cannot map value to FFI (tyEnum, tySet)")
+      globalError(v.info, "cannot map value to FFI (tyEnum, tySet)")
   of tyFloat: awr(float, v.floatVal)
   of tyFloat32: awr(float32, v.floatVal)
   of tyFloat64: awr(float64, v.floatVal)
@@ -192,25 +201,25 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyPointer, tyProc,  tyCString, tyString:
     if v.kind == nkNilLit:
       # nothing to do since the memory is 0 initialized anyway
-      nil
+      discard
     elif v.kind == nkPtrLit:
       awr(pointer, cast[pointer](v.intVal))
     elif v.kind in {nkStrLit..nkTripleStrLit}:
       awr(cstring, cstring(v.strVal))
     else:
-      GlobalError(v.info, "cannot map pointer/proc value to FFI")
+      globalError(v.info, "cannot map pointer/proc value to FFI")
   of tyPtr, tyRef, tyVar:
     if v.kind == nkNilLit:
       # nothing to do since the memory is 0 initialized anyway
-      nil
+      discard
     elif v.kind == nkPtrLit:
       awr(pointer, cast[pointer](v.intVal))
     else:
       if packRecCheck > maxPackDepth:
         packRecCheck = 0
-        GlobalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
+        globalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
       inc packRecCheck
-      pack(v.sons[0], typ.sons[0], res +! sizeof(pointer))
+      pack(v.sons[0], typ.lastSon, res +! sizeof(pointer))
       dec packRecCheck
       awr(pointer, res +! sizeof(pointer))
   of tyArray, tyArrayConstr:
@@ -220,11 +229,11 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyObject, tyTuple:
     packObject(v, typ, res)
   of tyNil:
-    nil
+    discard
   of tyDistinct, tyGenericInst:
     pack(v, typ.sons[0], res)
   else:
-    GlobalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
+    globalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
 
 proc unpack(x: pointer, typ: PType, n: PNode): PNode
 
@@ -234,14 +243,14 @@ proc unpackObjectAdd(x: pointer, n, result: PNode) =
     for i in countup(0, sonsLen(n) - 1):
       unpackObjectAdd(x, n.sons[i], result)
   of nkRecCase:
-    GlobalError(result.info, "case objects cannot be unpacked")
+    globalError(result.info, "case objects cannot be unpacked")
   of nkSym:
     var pair = newNodeI(nkExprColonExpr, result.info, 2)
     pair.sons[0] = n
     pair.sons[1] = unpack(x +! n.sym.offset, n.sym.typ, nil)
     #echo "offset: ", n.sym.name.s, " ", n.sym.offset
     result.add pair
-  else: nil
+  else: discard
 
 proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
   # compute the field's offsets:
@@ -253,14 +262,14 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
     result = newNode(nkPar)
     result.typ = typ
     if typ.n.isNil:
-      InternalError("cannot unpack unnamed tuple")
+      internalError("cannot unpack unnamed tuple")
     unpackObjectAdd(x, typ.n, result)
   else:
     result = n
     if result.kind notin {nkObjConstr, nkPar}:
-      GlobalError(n.info, "cannot map value from FFI")
+      globalError(n.info, "cannot map value from FFI")
     if typ.n.isNil:
-      GlobalError(n.info, "cannot unpack unnamed tuple")
+      globalError(n.info, "cannot unpack unnamed tuple")
     for i in countup(ord(n.kind == nkObjConstr), sonsLen(n) - 1):
       var it = n.sons[i]
       if it.kind == nkExprColonExpr:
@@ -279,7 +288,7 @@ proc unpackArray(x: pointer, typ: PType, n: PNode): PNode =
   else:
     result = n
     if result.kind != nkBracket:
-      GlobalError(n.info, "cannot map value from FFI")
+      globalError(n.info, "cannot map value from FFI")
   let baseSize = typ.sons[1].getSize
   for i in 0 .. < result.len:
     result.sons[i] = unpack(x +! i * baseSize, typ.sons[1], result.sons[i])
@@ -303,7 +312,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
         #echo "expected ", k, " but got ", result.kind
         #debug result
         return newNodeI(nkExceptBranch, n.info)
-        #GlobalError(n.info, "cannot map value from FFI")
+        #globalError(n.info, "cannot map value from FFI")
     result.field = v
 
   template setNil() =
@@ -328,19 +337,19 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
   of tyInt16: awi(nkInt16Lit, rd(int16, x))
   of tyInt32: awi(nkInt32Lit, rd(int32, x))
   of tyInt64: awi(nkInt64Lit, rd(int64, x))
-  of tyUInt: awi(nkUIntLit, rd(uint, x).biggestInt)
-  of tyUInt8: awi(nkUInt8Lit, rd(uint8, x).biggestInt)
-  of tyUInt16: awi(nkUInt16Lit, rd(uint16, x).biggestInt)
-  of tyUInt32: awi(nkUInt32Lit, rd(uint32, x).biggestInt)
-  of tyUInt64: awi(nkUInt64Lit, rd(uint64, x).biggestInt)
+  of tyUInt: awi(nkUIntLit, rd(uint, x).BiggestInt)
+  of tyUInt8: awi(nkUInt8Lit, rd(uint8, x).BiggestInt)
+  of tyUInt16: awi(nkUInt16Lit, rd(uint16, x).BiggestInt)
+  of tyUInt32: awi(nkUInt32Lit, rd(uint32, x).BiggestInt)
+  of tyUInt64: awi(nkUInt64Lit, rd(uint64, x).BiggestInt)
   of tyEnum:
     case typ.getSize
-    of 1: awi(nkIntLit, rd(uint8, x).biggestInt)
-    of 2: awi(nkIntLit, rd(uint16, x).biggestInt)
-    of 4: awi(nkIntLit, rd(int32, x).biggestInt)
-    of 8: awi(nkIntLit, rd(int64, x).biggestInt)
+    of 1: awi(nkIntLit, rd(uint8, x).BiggestInt)
+    of 2: awi(nkIntLit, rd(uint16, x).BiggestInt)
+    of 4: awi(nkIntLit, rd(int32, x).BiggestInt)
+    of 8: awi(nkIntLit, rd(int64, x).BiggestInt)
     else:
-      GlobalError(n.info, "cannot map value from FFI (tyEnum, tySet)")
+      globalError(n.info, "cannot map value from FFI (tyEnum, tySet)")
   of tyFloat: awf(nkFloatLit, rd(float, x))
   of tyFloat32: awf(nkFloat32Lit, rd(float32, x))
   of tyFloat64: awf(nkFloat64Lit, rd(float64, x))
@@ -362,10 +371,10 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
       awi(nkPtrLit, cast[TAddress](p))
     elif n != nil and n.len == 1:
       internalAssert n.kind == nkRefTy
-      n.sons[0] = unpack(p, typ.sons[0], n.sons[0])
+      n.sons[0] = unpack(p, typ.lastSon, n.sons[0])
       result = n
     else:
-      GlobalError(n.info, "cannot map value from FFI " & typeToString(typ))
+      globalError(n.info, "cannot map value from FFI " & typeToString(typ))
   of tyObject, tyTuple:
     result = unpackObject(x, typ, n)
   of tyArray, tyArrayConstr:
@@ -382,7 +391,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
     result = unpack(x, typ.sons[0], n)
   else:
     # XXX what to do with 'array' here?
-    GlobalError(n.info, "cannot map value from FFI " & typeToString(typ))
+    globalError(n.info, "cannot map value from FFI " & typeToString(typ))
 
 proc fficast*(x: PNode, destTyp: PType): PNode =
   if x.kind == nkPtrLit and x.typ.kind in {tyPtr, tyRef, tyVar, tyPointer, 
@@ -405,7 +414,7 @@ proc fficast*(x: PNode, destTyp: PType): PNode =
     dealloc a
 
 proc callForeignFunction*(call: PNode): PNode =
-  InternalAssert call.sons[0].kind == nkPtrLit
+  internalAssert call.sons[0].kind == nkPtrLit
   
   var cif: TCif
   var sig: TParamList
@@ -413,12 +422,12 @@ proc callForeignFunction*(call: PNode): PNode =
   for i in 1..call.len-1:
     sig[i-1] = mapType(call.sons[i].typ)
     if sig[i-1].isNil:
-      GlobalError(call.info, "cannot map FFI type")
+      globalError(call.info, "cannot map FFI type")
   
   let typ = call.sons[0].typ
   if prep_cif(cif, mapCallConv(typ.callConv, call.info), cuint(call.len-1),
               mapType(typ.sons[0]), sig) != OK:
-    GlobalError(call.info, "error in FFI call")
+    globalError(call.info, "error in FFI call")
   
   var args: TArgList
   let fn = cast[pointer](call.sons[0].intVal)
@@ -441,3 +450,46 @@ proc callForeignFunction*(call: PNode): PNode =
   for i in 1 .. call.len-1:
     call.sons[i] = unpack(args[i-1], typ.sons[i], call[i])
     dealloc args[i-1]
+
+proc callForeignFunction*(fn: PNode, fntyp: PType,
+                          args: var TNodeSeq, start, len: int,
+                          info: TLineInfo): PNode =
+  internalAssert fn.kind == nkPtrLit
+  
+  var cif: TCif
+  var sig: TParamList
+  for i in 0..len-1:
+    var aTyp = args[i+start].typ
+    if aTyp.isNil:
+      internalAssert i+1 < fntyp.len
+      aTyp = fntyp.sons[i+1]
+      args[i+start].typ = aTyp
+    sig[i] = mapType(aTyp)
+    if sig[i].isNil: globalError(info, "cannot map FFI type")
+  
+  if prep_cif(cif, mapCallConv(fntyp.callConv, info), cuint(len),
+              mapType(fntyp.sons[0]), sig) != OK:
+    globalError(info, "error in FFI call")
+  
+  var cargs: TArgList
+  let fn = cast[pointer](fn.intVal)
+  for i in 0 .. len-1:
+    let t = args[i+start].typ
+    cargs[i] = alloc0(packSize(args[i+start], t))
+    pack(args[i+start], t, cargs[i])
+  let retVal = if isEmptyType(fntyp.sons[0]): pointer(nil)
+               else: alloc(fntyp.sons[0].getSize.int)
+
+  libffi.call(cif, fn, retVal, cargs)
+  
+  if retVal.isNil: 
+    result = emptyNode
+  else:
+    result = unpack(retVal, fntyp.sons[0], nil)
+    result.info = info
+
+  if retVal != nil: dealloc retVal
+  for i in 0 .. len-1:
+    let t = args[i+start].typ
+    args[i+start] = unpack(cargs[i], t, args[i+start])
+    dealloc cargs[i]
diff --git a/compiler/evals.nim b/compiler/evals.nim
index b4ea973e8..151adf690 100644
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -91,6 +91,7 @@ proc evalMacroCall*(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode
 proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
 
 proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode =
+  if defined(debug) and gVerbosity >= 3: writeStackTrace()
   result = newNodeI(nkExceptBranch, info)
   # creating a nkExceptBranch without sons 
   # means that it could not be evaluated
@@ -263,8 +264,8 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
     result = newNodeIT(nkUIntLit, info, t)
   of tyFloat..tyFloat128: 
     result = newNodeIt(nkFloatLit, info, t)
-  of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr, 
-     tyStmt, tyTypeDesc, tyProc:
+  of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
+     tyStmt, tyTypeDesc, tyStatic, tyProc:
     result = newNodeIT(nkNilLit, info, t)
   of tyObject: 
     result = newNodeIT(nkPar, info, t)
@@ -358,7 +359,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
 
 proc aliasNeeded(n: PNode, flags: TEvalFlags): bool = 
   result = efLValue in flags or n.typ == nil or 
-    n.typ.kind in {tyExpr, tyStmt, tyTypeDesc}
+    n.typ.kind in {tyExpr, tyStatic, tyStmt, tyTypeDesc}
 
 proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode =
   # We need to return a node to the actual value,
@@ -905,17 +906,15 @@ proc evalParseStmt(c: PEvalContext, n: PNode): PNode =
   result = parseString(code.getStrValue, code.info.toFilename,
                        code.info.line.int)
   #result.typ = newType(tyStmt, c.module)
- 
-proc evalTypeTrait*(trait, operand: PNode, context: PSym): PNode =
-  InternalAssert operand.kind == nkSym
 
-  let typ = operand.sym.typ.skipTypes({tyTypeDesc})
+proc evalTypeTrait*(trait, operand: PNode, context: PSym): PNode =
+  let typ = operand.typ.skipTypes({tyTypeDesc})
   case trait.sym.name.s.normalize
   of "name":
     result = newStrNode(nkStrLit, typ.typeToString(preferName))
     result.typ = newType(tyString, context)
     result.info = trait.info
-  of "arity":    
+  of "arity":
     result = newIntNode(nkIntLit, typ.n.len-1)
     result.typ = newType(tyInt, context)
     result.info = trait.info
@@ -1329,7 +1328,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
   if gNestedEvals <= 0: stackTrace(c, n.info, errTooManyIterations)
   case n.kind
   of nkSym: result = evalSym(c, n, flags)
-  of nkType..nkNilLit:
+  of nkType..nkNilLit, nkTypeOfExpr:
     # nkStrLit is VERY common in the traces, so we should avoid
     # the 'copyNode' here.
     result = n #.copyNode
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 05be0e9d3..78cdbb45f 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -16,9 +16,14 @@ import
 type
   TemplCtx {.pure, final.} = object
     owner, genSymOwner: PSym
+    instLines: bool   # use the instantiation lines numbers
     mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
                       # new symbol
 
+proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
+  result = copyNode(a)
+  if ctx.instLines: result.info = b.info
+
 proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
   case templ.kind
   of nkSym:
@@ -31,49 +36,23 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
         else:
           result.add copyTree(x)
       else:
-        InternalAssert sfGenSym in s.flags
-        var x = PSym(IdTableGet(c.mapping, s))
+        internalAssert sfGenSym in s.flags
+        var x = PSym(idTableGet(c.mapping, s))
         if x == nil:
           x = copySym(s, false)
           x.owner = c.genSymOwner
-          IdTablePut(c.mapping, s, x)
-        result.add newSymNode(x, templ.info)
+          idTablePut(c.mapping, s, x)
+        result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
     else:
-      result.add copyNode(templ)
+      result.add copyNode(c, templ, actual)
   of nkNone..nkIdent, nkType..nkNilLit: # atom
-    result.add copyNode(templ)
+    result.add copyNode(c, templ, actual)
   else:
-    var res = copyNode(templ)
+    var res = copyNode(c, templ, actual)
     for i in countup(0, sonsLen(templ) - 1): 
       evalTemplateAux(templ.sons[i], actual, c, res)
     result.add res
 
-when false:
-  proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx): PNode =
-    case templ.kind
-    of nkSym:
-      var s = templ.sym
-      if s.owner.id == c.owner.id:
-        if s.kind == skParam:
-          result = copyTree(actual.sons[s.position])
-        else:
-          InternalAssert sfGenSym in s.flags
-          var x = PSym(IdTableGet(c.mapping, s))
-          if x == nil:
-            x = copySym(s, false)
-            x.owner = c.genSymOwner
-            IdTablePut(c.mapping, s, x)
-          result = newSymNode(x, templ.info)
-      else:
-        result = copyNode(templ)
-    of nkNone..nkIdent, nkType..nkNilLit: # atom
-      result = copyNode(templ)
-    else:
-      result = copyNode(templ)
-      newSons(result, sonsLen(templ))
-      for i in countup(0, sonsLen(templ) - 1): 
-        result.sons[i] = evalTemplateAux(templ.sons[i], actual, c)
-
 proc evalTemplateArgs(n: PNode, s: PSym): PNode =
   # if the template has zero arguments, it can be called without ``()``
   # `n` is then a nkSym or something similar
@@ -83,13 +62,13 @@ proc evalTemplateArgs(n: PNode, s: PSym): PNode =
     a = sonsLen(n)
   else: a = 0
   var f = s.typ.sonsLen
-  if a > f: GlobalError(n.info, errWrongNumberOfArguments)
+  if a > f: globalError(n.info, errWrongNumberOfArguments)
 
   result = newNodeI(nkArgList, n.info)
   for i in countup(1, f - 1):
     var arg = if i < a: n.sons[i] else: copyTree(s.typ.n.sons[i].sym.ast)
     if arg == nil or arg.kind == nkEmpty:
-      LocalError(n.info, errWrongNumberOfArguments)
+      localError(n.info, errWrongNumberOfArguments)
     addSon(result, arg)
 
 var evalTemplateCounter* = 0
@@ -98,7 +77,7 @@ var evalTemplateCounter* = 0
 proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode =
   inc(evalTemplateCounter)
   if evalTemplateCounter > 100:
-    GlobalError(n.info, errTemplateInstantiationTooNested)
+    globalError(n.info, errTemplateInstantiationTooNested)
     result = n
 
   # replace each param by the corresponding node:
@@ -114,11 +93,13 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode =
     evalTemplateAux(body, args, ctx, result)
     if result.len == 1: result = result.sons[0]
     else:
-      GlobalError(result.info, errIllFormedAstX,
+      globalError(result.info, errIllFormedAstX,
                   renderTree(result, {renderNoComments}))
   else:
     result = copyNode(body)
-    #evalTemplateAux(body, args, ctx, result)
+    ctx.instLines = body.kind notin {nkStmtList, nkStmtListExpr,
+                                     nkBlockStmt, nkBlockExpr}
+    if ctx.instLines: result.info = n.info
     for i in countup(0, safeLen(body) - 1):
       evalTemplateAux(body.sons[i], args, ctx, result)
   
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index bbbbbfb8e..f0e5dad11 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -16,7 +16,7 @@ import
 type 
   TSystemCC* = enum 
     ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, 
-    ccTcc, ccPcc, ccUcc, ccIcl, ccGpp
+    ccTcc, ccPcc, ccUcc, ccIcl
   TInfoCCProp* = enum         # properties of the C compiler:
     hasSwitchRange,           # CC allows ranges in switch statements (GNU C)
     hasComputedGoto,          # CC has computed goto (GNU C extension)
@@ -33,11 +33,12 @@ type
     optSpeed: string,    # the options for optimization for speed
     optSize: string,     # the options for optimization for size
     compilerExe: string, # the compiler's executable
+    cppCompiler: string, # name of the C++ compiler's executable (if supported)
     compileTmpl: string, # the compile command template
     buildGui: string,    # command to build a GUI application
     buildDll: string,    # command to build a shared library
     buildLib: string,    # command to build a static library
-    linkerExe: string,   # the linker's executable
+    linkerExe: string,   # the linker's executable (if not matching compiler's)
     linkTmpl: string,    # command to link files to produce an exe
     includeCmd: string,  # command to add an include dir
     linkDirCmd: string,  # command to add a lib dir
@@ -46,6 +47,8 @@ type
     pic: string,         # command for position independent code
                          # used on some platforms
     asmStmtFrmt: string, # format of ASM statement
+    structStmtFmt: string, # Format for struct statement
+    packedPragma: string,  # Attribute/pragma to make struct packed (1-byte aligned)
     props: TInfoCCProps] # properties of the C compiler
 
 
@@ -63,11 +66,12 @@ compiler gcc:
     optSpeed: " -O3 -ffast-math ",
     optSize: " -Os -ffast-math ",
     compilerExe: "gcc",
+    cppCompiler: "g++",
     compileTmpl: "-c $options $include -o $objfile $file",
     buildGui: " -mwindows",
     buildDll: " -shared",
     buildLib: "ar rcs $libfile $objfiles",
-    linkerExe: "gcc",
+    linkerExe: "",
     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options",
     includeCmd: " -I",
     linkDirCmd: " -L",
@@ -75,34 +79,25 @@ compiler gcc:
     debug: "",
     pic: "-fPIC",
     asmStmtFrmt: "asm($1);$n",
+    structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
+    packedPragma: "__attribute__((__packed__))",
     props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
             hasNakedAttribute})
-    
-compiler gpp:
-  result = gcc()
-  
-  result.name = "gpp"
-  result.compilerExe = "g++"
-  result.linkerExe = "g++"  
-
-  result.buildDll = " -mdll" 
-  # XXX: Hmm, I'm keeping this from the previos version, 
-  # but my gcc doesn't even have such an option (is this mingw?)
 
 compiler llvmGcc:
   result = gcc()
   
   result.name = "llvm_gcc"
   result.compilerExe = "llvm-gcc"
+  result.cppCompiler = "llvm-g++"
   result.buildLib = "llvm-ar rcs $libfile $objfiles"
-  result.linkerExe = "llvm-gcc"
 
 compiler clang:
   result = llvmGcc()
 
   result.name = "clang"
   result.compilerExe = "clang"
-  result.linkerExe = "clang"
+  result.cppCompiler = "clang++"
 
 compiler vcc:
   result = (
@@ -111,6 +106,7 @@ compiler vcc:
     optSpeed: " /Ogityb2 /G7 /arch:SSE2 ",
     optSize: " /O1 /G7 ",
     compilerExe: "cl",
+    cppCompiler: "cl",
     compileTmpl: "/c $options $include /Fo$objfile $file",
     buildGui: " /link /SUBSYSTEM:WINDOWS ",
     buildDll: " /LD",
@@ -123,6 +119,8 @@ compiler vcc:
     debug: " /GZ /Zi ",
     pic: "",
     asmStmtFrmt: "__asm{$n$1$n}$n",
+    structStmtFmt: "$3$n$1 $2",
+    packedPragma: "#pragma pack(1)",
     props: {hasCpp, hasAssume, hasNakedDeclspec})
 
 compiler icl:
@@ -131,7 +129,7 @@ compiler icl:
     result = vcc()
   else:
     result = gcc()
-
+    
   result.name = "icl"
   result.compilerExe = "icl"
   result.linkerExe = "icl"
@@ -143,6 +141,7 @@ compiler lcc:
     optSpeed: " -O -p6 ",
     optSize: " -O -p6 ",
     compilerExe: "lcc",
+    cppCompiler: "",
     compileTmpl: "$options $include -Fo$objfile $file",
     buildGui: " -subsystem windows",
     buildDll: " -dll",
@@ -155,6 +154,8 @@ compiler lcc:
     debug: " -g5 ",
     pic: "",
     asmStmtFrmt: "_asm{$n$1$n}$n",
+    structStmtFmt: "$1 $2",
+    packedPragma: "", # XXX: not supported yet
     props: {})
 
 compiler bcc:
@@ -164,6 +165,7 @@ compiler bcc:
     optSpeed: " -O2 -6 ",
     optSize: " -O1 -6 ",
     compilerExe: "bcc32",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o$objfile $file",
     buildGui: " -tW",
     buildDll: " -tWD",
@@ -176,6 +178,8 @@ compiler bcc:
     debug: "",
     pic: "",
     asmStmtFrmt: "__asm{$n$1$n}$n",
+    structStmtFmt: "$1 $2",
+    packedPragma: "", # XXX: not supported yet
     props: {hasCpp})
 
 compiler dmc:
@@ -185,6 +189,7 @@ compiler dmc:
     optSpeed: " -ff -o -6 ",
     optSize: " -ff -o -6 ",
     compilerExe: "dmc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o$objfile $file",
     buildGui: " -L/exet:nt/su:windows",
     buildDll: " -WD",
@@ -197,6 +202,8 @@ compiler dmc:
     debug: " -g ",
     pic: "",
     asmStmtFrmt: "__asm{$n$1$n}$n",
+    structStmtFmt: "$3$n$1 $2",
+    packedPragma: "#pragma pack(1)",
     props: {hasCpp})
 
 compiler wcc:
@@ -206,6 +213,7 @@ compiler wcc:
     optSpeed: " -ox -on -6 -d0 -fp6 -zW ",
     optSize: "",
     compilerExe: "wcl386",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -fo=$objfile $file",
     buildGui: " -bw",
     buildDll: " -bd",
@@ -218,6 +226,8 @@ compiler wcc:
     debug: " -d2 ",
     pic: "",
     asmStmtFrmt: "__asm{$n$1$n}$n",
+    structStmtFmt: "$1 $2",
+    packedPragma: "", # XXX: not supported yet
     props: {hasCpp})
 
 compiler tcc:
@@ -227,6 +237,7 @@ compiler tcc:
     optSpeed: "",
     optSize: "",
     compilerExe: "tcc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o $objfile $file",
     buildGui: "UNAVAILABLE!",
     buildDll: " -shared",
@@ -239,6 +250,8 @@ compiler tcc:
     debug: " -g ",
     pic: "",
     asmStmtFrmt: "__asm{$n$1$n}$n",
+    structStmtFmt: "$1 $2",
+    packedPragma: "", # XXX: not supported yet
     props: {hasSwitchRange, hasComputedGoto})
 
 compiler pcc:
@@ -249,6 +262,7 @@ compiler pcc:
     optSpeed: " -Ox ",
     optSize: " -Os ",
     compilerExe: "cc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -Fo$objfile $file",
     buildGui: " -SUBSYSTEM:WINDOWS",
     buildDll: " -DLL",
@@ -261,6 +275,8 @@ compiler pcc:
     debug: " -Zi ",
     pic: "",
     asmStmtFrmt: "__asm{$n$1$n}$n",
+    structStmtFmt: "$1 $2",
+    packedPragma: "", # XXX: not supported yet
     props: {})
 
 compiler ucc:
@@ -270,6 +286,7 @@ compiler ucc:
     optSpeed: " -O3 ",
     optSize: " -O1 ",
     compilerExe: "cc",
+    cppCompiler: "",
     compileTmpl: "-c $options $include -o $objfile $file",
     buildGui: "",
     buildDll: " -shared ",
@@ -282,6 +299,8 @@ compiler ucc:
     debug: "",
     pic: "",
     asmStmtFrmt: "__asm{$n$1$n}$n",
+    structStmtFmt: "$1 $2",
+    packedPragma: "", # XXX: not supported yet
     props: {})
 
 const 
@@ -297,8 +316,7 @@ const
     tcc(),
     pcc(),
     ucc(),
-    icl(),
-    gpp()]
+    icl()]
 
 const
   hExt* = ".h"
@@ -324,7 +342,7 @@ var
   compileOptions: string = ""
   ccompilerpath: string = ""
 
-proc NameToCC*(name: string): TSystemCC = 
+proc nameToCC*(name: string): TSystemCC = 
   for i in countup(succ(ccNone), high(TSystemCC)): 
     if cmpIgnoreStyle(name, CC[i].name) == 0: 
       return i
@@ -335,8 +353,8 @@ proc getConfigVar(c: TSystemCC, suffix: string): string =
   # for niminst support
   if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and
       optCompileOnly notin gGlobalOptions:
-    let fullCCname = platform.cpu[targetCPU].name & '.' & 
-                     platform.os[targetOS].name & '.' & 
+    let fullCCname = platform.CPU[targetCPU].name & '.' & 
+                     platform.OS[targetOS].name & '.' & 
                      CC[c].name & suffix
     result = getConfigVar(fullCCname)
     if result.len == 0:
@@ -346,13 +364,13 @@ proc getConfigVar(c: TSystemCC, suffix: string): string =
     result = getConfigVar(CC[c].name & suffix)
 
 proc setCC*(ccname: string) = 
-  ccompiler = nameToCC(ccname)
-  if ccompiler == ccNone: rawMessage(errUnknownCcompiler, ccname)
-  compileOptions = getConfigVar(ccompiler, ".options.always")
-  linkOptions = getConfigVar(ccompiler, ".options.linker")
-  ccompilerpath = getConfigVar(ccompiler, ".path")
+  cCompiler = nameToCC(ccname)
+  if cCompiler == ccNone: rawMessage(errUnknownCcompiler, ccname)
+  compileOptions = getConfigVar(cCompiler, ".options.always")
+  linkOptions = getConfigVar(cCompiler, ".options.linker")
+  ccompilerpath = getConfigVar(cCompiler, ".path")
   for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
-  defineSymbol(CC[ccompiler].name)
+  defineSymbol(CC[cCompiler].name)
 
 proc addOpt(dest: var string, src: string) = 
   if len(dest) == 0 or dest[len(dest)-1] != ' ': add(dest, " ")
@@ -368,20 +386,20 @@ proc addCompileOption*(option: string) =
 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)
+  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:
-    ccompilerpath = getConfigVar(ccompiler, ".path")
+  addCompileOption(getConfigVar(cCompiler, ".options.always"))
+  addLinkOption(getConfigVar(cCompiler, ".options.linker"))
+  if len(ccompilerpath) == 0:
+    ccompilerpath = getConfigVar(cCompiler, ".path")
 
 proc completeCFilePath*(cfile: string, createSubDir: bool = true): string = 
   result = completeGeneratedFilePath(cfile, createSubDir)
 
 proc toObjFile*(filenameWithoutExt: string): string = 
   # Object file for compilation
-  result = changeFileExt(filenameWithoutExt, cc[ccompiler].objExt)
+  result = changeFileExt(filenameWithoutExt, CC[cCompiler].objExt)
 
 proc addFileToCompile*(filename: string) =
   appendStr(toCompile, filename)
@@ -400,28 +418,28 @@ proc addFileToLink*(filename: string) =
   # BUGFIX: was ``appendStr``
 
 proc execExternalProgram*(cmd: string) = 
-  if optListCmd in gGlobalOptions or gVerbosity > 0: MsgWriteln(cmd)
+  if optListCmd in gGlobalOptions or gVerbosity > 0: msgWriteln(cmd)
   if execCmd(cmd) != 0: rawMessage(errExecutionOfProgramFailed, "")
 
 proc generateScript(projectFile: string, script: PRope) = 
   let (dir, name, ext) = splitFile(projectFile)
-  WriteRope(script, dir / addFileExt("compile_" & name, 
-                                     platform.os[targetOS].scriptExt))
+  writeRope(script, dir / addFileExt("compile_" & name, 
+                                     platform.OS[targetOS].scriptExt))
 
 proc getOptSpeed(c: TSystemCC): string = 
   result = getConfigVar(c, ".options.speed")
   if result == "":
-    result = cc[c].optSpeed   # use default settings from this file
+    result = CC[c].optSpeed   # use default settings from this file
 
 proc getDebug(c: TSystemCC): string = 
   result = getConfigVar(c, ".options.debug")
   if result == "":
-    result = cc[c].debug      # use default settings from this file
+    result = CC[c].debug      # use default settings from this file
 
 proc getOptSize(c: TSystemCC): string = 
   result = getConfigVar(c, ".options.size")
   if result == "":
-    result = cc[c].optSize    # use default settings from this file
+    result = CC[c].optSize    # use default settings from this file
 
 proc noAbsolutePaths: bool {.inline.} =
   # We used to check current OS != specified OS, but this makes no sense
@@ -436,78 +454,88 @@ const
 
 var fileCounter: int
 
-proc add(s: var string, many: openarray[string]) =
+proc add(s: var string, many: openArray[string]) =
   s.add many.join
 
-proc CFileSpecificOptions(cfilename: string): string =
+proc cFileSpecificOptions(cfilename: string): string =
   result = compileOptions
   var trunk = splitFile(cfilename).name
   if optCDebug in gGlobalOptions: 
     var key = trunk & ".debug"
     if existsConfigVar(key): addOpt(result, getConfigVar(key))
-    else: addOpt(result, getDebug(ccompiler))
+    else: addOpt(result, getDebug(cCompiler))
   if optOptimizeSpeed in gOptions:
     var key = trunk & ".speed"
     if existsConfigVar(key): addOpt(result, getConfigVar(key))
-    else: addOpt(result, getOptSpeed(ccompiler))
+    else: addOpt(result, getOptSpeed(cCompiler))
   elif optOptimizeSize in gOptions:
     var key = trunk & ".size"
     if existsConfigVar(key): addOpt(result, getConfigVar(key))
-    else: addOpt(result, getOptSize(ccompiler))
+    else: addOpt(result, getOptSize(cCompiler))
   var key = trunk & ".always"
   if existsConfigVar(key): addOpt(result, getConfigVar(key))
 
 proc getCompileOptions: string =
-  result = CFileSpecificOptions("__dummy__")
+  result = cFileSpecificOptions("__dummy__")
 
 proc getLinkOptions: string =
   result = linkOptions
   for linkedLib in items(cLinkedLibs):
-    result.add(cc[ccompiler].linkLibCmd % linkedLib.quoteShell)
+    result.add(CC[cCompiler].linkLibCmd % linkedLib.quoteShell)
   for libDir in items(cLibs):
-    result.add([cc[ccompiler].linkDirCmd, libDir.quoteShell])
+    result.add([CC[cCompiler].linkDirCmd, libDir.quoteShell])
 
 proc needsExeExt(): bool {.inline.} =
   result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
                                        (platform.hostOS == osWindows)
 
+proc getCompilerExe(compiler: TSystemCC): string =
+  result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler
+           else: CC[compiler].compilerExe
+  if result.len == 0:
+    rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name)
+
+proc getLinkerExe(compiler: TSystemCC): string =
+  result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
+           else: compiler.getCompilerExe
+
 proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = 
-  var c = ccompiler
-  var options = CFileSpecificOptions(cfilename)
+  var c = cCompiler
+  var options = cFileSpecificOptions(cfilename)
   var exe = getConfigVar(c, ".exe")
-  if exe.len == 0: exe = cc[c].compilerExe
+  if exe.len == 0: exe = c.getCompilerExe
   
   if needsExeExt(): exe = addFileExt(exe, "exe")
   if optGenDynLib in gGlobalOptions and
       ospNeedsPIC in platform.OS[targetOS].props: 
-    add(options, ' ' & cc[c].pic)
+    add(options, ' ' & CC[c].pic)
   
   var includeCmd, compilePattern: string
   if not noAbsolutePaths(): 
     # compute include paths:
-    includeCmd = cc[c].includeCmd & quoteShell(libpath)
+    includeCmd = CC[c].includeCmd & quoteShell(libpath)
 
     for includeDir in items(cIncludes):
-      includeCmd.add([cc[c].includeCmd, includeDir.quoteShell])
+      includeCmd.add([CC[c].includeCmd, includeDir.quoteShell])
 
-    compilePattern = JoinPath(ccompilerpath, exe)
+    compilePattern = joinPath(ccompilerpath, exe)
   else: 
     includeCmd = ""
-    compilePattern = cc[c].compilerExe
+    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: 
                   completeCFilePath(toObjFile(cfile))
-  cfile = quoteShell(AddFileExt(cfile, cExt))
+  cfile = quoteShell(addFileExt(cfile, cExt))
   objfile = quoteShell(objfile)
   result = quoteShell(compilePattern % [
     "file", cfile, "objfile", objfile, "options", options, 
     "include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath])
   add(result, ' ')
-  addf(result, cc[c].compileTmpl, [
+  addf(result, CC[c].compileTmpl, [
     "file", cfile, "objfile", objfile, 
     "options", options, "include", includeCmd, 
     "nimrod", quoteShell(getPrefixDir()), 
@@ -517,7 +545,7 @@ proc footprint(filename: string): TCrc32 =
   result = crcFromFile(filename) ><
       platform.OS[targetOS].name ><
       platform.CPU[targetCPU].name ><
-      extccomp.CC[extccomp.ccompiler].name ><
+      extccomp.CC[extccomp.cCompiler].name ><
       getCompileCFileCmd(filename, true)
 
 proc externalFileChanged(filename: string): bool = 
@@ -541,7 +569,7 @@ proc addExternalFileToCompile*(filename: string) =
   if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
     appendStr(externalToCompile, filename)
 
-proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq, 
+proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq, 
                   isExternal: bool) = 
   var it = PStrEntry(list.head)
   while it != nil: 
@@ -554,18 +582,18 @@ proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
       app(script, tnl)
     it = PStrEntry(it.next)
 
-proc CallCCompiler*(projectfile: string) =
+proc callCCompiler*(projectfile: string) =
   var 
     linkCmd, buildgui, builddll: string
   if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}: 
     return # speed up that call if only compiling and no script shall be
            # generated
   fileCounter = 0
-  var c = ccompiler
+  var c = cCompiler
   var script: PRope = nil
   var cmds: TStringSeq = @[]
-  CompileCFile(toCompile, script, cmds, false)
-  CompileCFile(externalToCompile, script, cmds, true)
+  compileCFile(toCompile, script, cmds, false)
+  compileCFile(externalToCompile, script, cmds, true)
   if optCompileOnly notin gGlobalOptions: 
     if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
     var res = 0
@@ -591,40 +619,40 @@ proc CallCCompiler*(projectfile: string) =
       let objFile = if noAbsolutePaths(): it.data.extractFilename else: it.data
       add(objfiles, ' ')
       add(objfiles, quoteShell(
-          addFileExt(objFile, cc[ccompiler].objExt)))
+          addFileExt(objFile, CC[cCompiler].objExt)))
       it = PStrEntry(it.next)
 
     if optGenStaticLib in gGlobalOptions:
-      linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl() % gProjectName),
+      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 = cc[c].linkerExe
+      if len(linkerExe) == 0: linkerExe = c.getLinkerExe
       if needsExeExt(): linkerExe = addFileExt(linkerExe, "exe")
       if noAbsolutePaths(): linkCmd = quoteShell(linkerExe)
-      else: linkCmd = quoteShell(JoinPath(ccompilerpath, linkerExe))
-      if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui
-      else: buildGui = ""
+      else: linkCmd = quoteShell(joinPath(ccompilerpath, linkerExe))
+      if optGenGuiApp in gGlobalOptions: buildgui = CC[c].buildGui
+      else: buildgui = ""
       var exefile: string
       if optGenDynLib in gGlobalOptions:
-        exefile = platform.os[targetOS].dllFrmt % splitFile(projectFile).name
-        buildDll = cc[c].buildDll
+        exefile = platform.OS[targetOS].dllFrmt % splitFile(projectfile).name
+        builddll = CC[c].buildDll
       else:
-        exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt
-        buildDll = ""
+        exefile = splitFile(projectfile).name & platform.OS[targetOS].exeExt
+        builddll = ""
       if options.outFile.len > 0: 
         exefile = options.outFile.expandTilde
       if not noAbsolutePaths():
-        if not exeFile.isAbsolute():
-          exefile = joinPath(splitFile(projectFile).dir, exefile)
+        if not exefile.isAbsolute():
+          exefile = joinPath(splitFile(projectfile).dir, exefile)
       exefile = quoteShell(exefile)
       let linkOptions = getLinkOptions()
       linkCmd = quoteShell(linkCmd % ["builddll", builddll,
           "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
           "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
       linkCmd.add ' '
-      addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll,
+      addf(linkCmd, CC[c].linkTmpl, ["builddll", builddll,
           "buildgui", buildgui, "options", linkOptions,
           "objfiles", objfiles, "exefile", exefile,
           "nimrod", quoteShell(getPrefixDir()),
@@ -635,12 +663,12 @@ proc CallCCompiler*(projectfile: string) =
   if optGenScript in gGlobalOptions:
     app(script, linkCmd)
     app(script, tnl)
-    generateScript(projectFile, script)
+    generateScript(projectfile, script)
 
 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(addFileExt(it.data, cExt))])
     it = PStrEntry(it.next)
 
 proc writeMapping*(gSymbolMapping: PRope) = 
@@ -658,5 +686,5 @@ proc writeMapping*(gSymbolMapping: PRope) =
   app(code, strutils.escape(libpath))
   
   appf(code, "\n[Symbols]$n$1", [gSymbolMapping])
-  WriteRope(code, joinPath(gProjectPath, "mapping.txt"))
+  writeRope(code, joinPath(gProjectPath, "mapping.txt"))
   
diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim
index d16639d08..0014e9c78 100644
--- a/compiler/filter_tmpl.nim
+++ b/compiler/filter_tmpl.nim
@@ -27,7 +27,7 @@ type
     indent, emitPar: int
     x: string                # the current input line
     outp: PLLStream          # the ouput will be parsed by pnimsyn
-    subsChar, NimDirective: Char
+    subsChar, nimDirective: char
     emit, conc, toStr: string
     curly, bracket, par: int
     pendingExprLine: bool
@@ -37,11 +37,11 @@ const
   PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '.', '_'}
 
 proc newLine(p: var TTmplParser) = 
-  LLStreamWrite(p.outp, repeatChar(p.emitPar, ')'))
+  llStreamWrite(p.outp, repeatChar(p.emitPar, ')'))
   p.emitPar = 0
-  if p.info.line > int16(1): LLStreamWrite(p.outp, "\n")
+  if p.info.line > int16(1): llStreamWrite(p.outp, "\n")
   if p.pendingExprLine:
-    LLStreamWrite(p.outp, repeatChar(2))
+    llStreamWrite(p.outp, repeatChar(2))
     p.pendingExprLine = false
   
 proc scanPar(p: var TTmplParser, d: int) = 
@@ -55,7 +55,7 @@ proc scanPar(p: var TTmplParser, d: int) =
     of ']': dec(p.bracket)
     of '{': inc(p.curly)
     of '}': dec(p.curly)
-    else: nil
+    else: discard
     inc(i)
 
 proc withInExpr(p: TTmplParser): bool {.inline.} = 
@@ -67,9 +67,9 @@ proc parseLine(p: var TTmplParser) =
     keyw: string
   j = 0
   while p.x[j] == ' ': inc(j)
-  if (p.x[0] == p.NimDirective) and (p.x[0 + 1] == '!'): 
+  if (p.x[0] == p.nimDirective) and (p.x[0 + 1] == '!'): 
     newLine(p)
-  elif (p.x[j] == p.NimDirective): 
+  elif (p.x[j] == p.nimDirective): 
     newLine(p)
     inc(j)
     while p.x[j] == ' ': inc(j)
@@ -87,26 +87,26 @@ proc parseLine(p: var TTmplParser) =
         dec(p.indent, 2)
       else: 
         p.info.col = int16(j)
-        LocalError(p.info, errXNotAllowedHere, "end")
-      LLStreamWrite(p.outp, repeatChar(p.indent))
-      LLStreamWrite(p.outp, "#end")
+        localError(p.info, errXNotAllowedHere, "end")
+      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, "#end")
     of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator, 
        wConverter, wMacro, wTemplate, wMethod: 
-      LLStreamWrite(p.outp, repeatChar(p.indent))
-      LLStreamWrite(p.outp, substr(p.x, d))
+      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, substr(p.x, d))
       inc(p.indent, 2)
     of wElif, wOf, wElse, wExcept, wFinally: 
-      LLStreamWrite(p.outp, repeatChar(p.indent - 2))
-      LLStreamWrite(p.outp, substr(p.x, d))
+      llStreamWrite(p.outp, repeatChar(p.indent - 2))
+      llStreamWrite(p.outp, substr(p.x, d))
     of wLet, wVar, wConst, wType:
-      LLStreamWrite(p.outp, repeatChar(p.indent))
-      LLStreamWrite(p.outp, substr(p.x, d))
+      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, substr(p.x, d))
       if not p.x.contains({':', '='}):
         # no inline element --> treat as block:
         inc(p.indent, 2)
     else:
-      LLStreamWrite(p.outp, repeatChar(p.indent))
-      LLStreamWrite(p.outp, substr(p.x, d))
+      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, substr(p.x, d))
     p.state = psDirective
   else: 
     # data line
@@ -118,15 +118,15 @@ proc parseLine(p: var TTmplParser) =
     case p.state
     of psTempl: 
       # next line of string literal:
-      LLStreamWrite(p.outp, p.conc)
-      LLStreamWrite(p.outp, "\n")
-      LLStreamWrite(p.outp, repeatChar(p.indent + 2))
-      LLStreamWrite(p.outp, "\"")
+      llStreamWrite(p.outp, p.conc)
+      llStreamWrite(p.outp, "\n")
+      llStreamWrite(p.outp, repeatChar(p.indent + 2))
+      llStreamWrite(p.outp, "\"")
     of psDirective: 
       newLine(p)
-      LLStreamWrite(p.outp, repeatChar(p.indent))
-      LLStreamWrite(p.outp, p.emit)
-      LLStreamWrite(p.outp, "(\"")
+      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, p.emit)
+      llStreamWrite(p.outp, "(\"")
       inc(p.emitPar)
     p.state = psTempl
     while true: 
@@ -134,17 +134,17 @@ proc parseLine(p: var TTmplParser) =
       of '\0': 
         break 
       of '\x01'..'\x1F', '\x80'..'\xFF': 
-        LLStreamWrite(p.outp, "\\x")
-        LLStreamWrite(p.outp, toHex(ord(p.x[j]), 2))
+        llStreamWrite(p.outp, "\\x")
+        llStreamWrite(p.outp, toHex(ord(p.x[j]), 2))
         inc(j)
       of '\\': 
-        LLStreamWrite(p.outp, "\\\\")
+        llStreamWrite(p.outp, "\\\\")
         inc(j)
       of '\'': 
-        LLStreamWrite(p.outp, "\\\'")
+        llStreamWrite(p.outp, "\\\'")
         inc(j)
       of '\"': 
-        LLStreamWrite(p.outp, "\\\"")
+        llStreamWrite(p.outp, "\\\"")
         inc(j)
       else: 
         if p.x[j] == p.subsChar: 
@@ -153,59 +153,59 @@ proc parseLine(p: var TTmplParser) =
           case p.x[j]
           of '{': 
             p.info.col = int16(j)
-            LLStreamWrite(p.outp, '\"')
-            LLStreamWrite(p.outp, p.conc)
-            LLStreamWrite(p.outp, p.toStr)
-            LLStreamWrite(p.outp, '(')
+            llStreamWrite(p.outp, '\"')
+            llStreamWrite(p.outp, p.conc)
+            llStreamWrite(p.outp, p.toStr)
+            llStreamWrite(p.outp, '(')
             inc(j)
             curly = 0
             while true: 
               case p.x[j]
               of '\0': 
-                LocalError(p.info, errXExpected, "}")
+                localError(p.info, errXExpected, "}")
                 break
               of '{': 
                 inc(j)
                 inc(curly)
-                LLStreamWrite(p.outp, '{')
+                llStreamWrite(p.outp, '{')
               of '}': 
                 inc(j)
                 if curly == 0: break 
                 if curly > 0: dec(curly)
-                LLStreamWrite(p.outp, '}')
+                llStreamWrite(p.outp, '}')
               else: 
-                LLStreamWrite(p.outp, p.x[j])
+                llStreamWrite(p.outp, p.x[j])
                 inc(j)
-            LLStreamWrite(p.outp, ')')
-            LLStreamWrite(p.outp, p.conc)
-            LLStreamWrite(p.outp, '\"')
+            llStreamWrite(p.outp, ')')
+            llStreamWrite(p.outp, p.conc)
+            llStreamWrite(p.outp, '\"')
           of 'a'..'z', 'A'..'Z', '\x80'..'\xFF': 
-            LLStreamWrite(p.outp, '\"')
-            LLStreamWrite(p.outp, p.conc)
-            LLStreamWrite(p.outp, p.toStr)
-            LLStreamWrite(p.outp, '(')
+            llStreamWrite(p.outp, '\"')
+            llStreamWrite(p.outp, p.conc)
+            llStreamWrite(p.outp, p.toStr)
+            llStreamWrite(p.outp, '(')
             while p.x[j] in PatternChars: 
-              LLStreamWrite(p.outp, p.x[j])
+              llStreamWrite(p.outp, p.x[j])
               inc(j)
-            LLStreamWrite(p.outp, ')')
-            LLStreamWrite(p.outp, p.conc)
-            LLStreamWrite(p.outp, '\"')
+            llStreamWrite(p.outp, ')')
+            llStreamWrite(p.outp, p.conc)
+            llStreamWrite(p.outp, '\"')
           else: 
             if p.x[j] == p.subsChar: 
-              LLStreamWrite(p.outp, p.subsChar)
+              llStreamWrite(p.outp, p.subsChar)
               inc(j)
             else: 
               p.info.col = int16(j)
-              LocalError(p.info, errInvalidExpression, "$")
+              localError(p.info, errInvalidExpression, "$")
         else: 
-          LLStreamWrite(p.outp, p.x[j])
+          llStreamWrite(p.outp, p.x[j])
           inc(j)
-    LLStreamWrite(p.outp, "\\n\"")
+    llStreamWrite(p.outp, "\\n\"")
 
 proc filterTmpl(stdin: PLLStream, filename: string, call: PNode): PLLStream = 
   var p: TTmplParser
   p.info = newLineInfo(filename, 0, 0)
-  p.outp = LLStreamOpen("")
+  p.outp = llStreamOpen("")
   p.inp = stdin
   p.subsChar = charArg(call, "subschar", 1, '$')
   p.nimDirective = charArg(call, "metachar", 2, '#')
@@ -213,9 +213,9 @@ proc filterTmpl(stdin: PLLStream, filename: string, call: PNode): PLLStream =
   p.conc = strArg(call, "conc", 4, " & ")
   p.toStr = strArg(call, "tostring", 5, "$")
   p.x = newStringOfCap(120)
-  while LLStreamReadLine(p.inp, p.x):
+  while llStreamReadLine(p.inp, p.x):
     p.info.line = p.info.line + int16(1)
     parseLine(p)
   newLine(p)
   result = p.outp
-  LLStreamClose(p.inp)
+  llStreamClose(p.inp)
diff --git a/compiler/filters.nim b/compiler/filters.nim
index 19da11bca..ce0ffd196 100644
--- a/compiler/filters.nim
+++ b/compiler/filters.nim
@@ -16,13 +16,13 @@ import
 proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream
 proc filterStrip*(stdin: PLLStream, filename: string, call: PNode): PLLStream
   # helpers to retrieve arguments:
-proc charArg*(n: PNode, name: string, pos: int, default: Char): Char
+proc charArg*(n: PNode, name: string, pos: int, default: char): char
 proc strArg*(n: PNode, name: string, pos: int, default: string): string
 proc boolArg*(n: PNode, name: string, pos: int, default: bool): bool
 # implementation
 
 proc invalidPragma(n: PNode) = 
-  LocalError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
+  localError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
 
 proc getArg(n: PNode, name: string, pos: int): PNode = 
   result = nil
@@ -30,12 +30,12 @@ proc getArg(n: PNode, name: string, pos: int): PNode =
   for i in countup(1, sonsLen(n) - 1): 
     if n.sons[i].kind == nkExprEqExpr: 
       if n.sons[i].sons[0].kind != nkIdent: invalidPragma(n)
-      if IdentEq(n.sons[i].sons[0].ident, name): 
+      if identEq(n.sons[i].sons[0].ident, name): 
         return n.sons[i].sons[1]
     elif i == pos: 
       return n.sons[i]
   
-proc charArg(n: PNode, name: string, pos: int, default: Char): Char = 
+proc charArg(n: PNode, name: string, pos: int, default: char): char = 
   var x = getArg(n, name, pos)
   if x == nil: result = default
   elif x.kind == nkCharLit: result = chr(int(x.intVal))
@@ -50,30 +50,30 @@ proc strArg(n: PNode, name: string, pos: int, default: string): string =
 proc boolArg(n: PNode, name: string, pos: int, default: bool): bool = 
   var x = getArg(n, name, pos)
   if x == nil: result = default
-  elif (x.kind == nkIdent) and IdentEq(x.ident, "true"): result = true
-  elif (x.kind == nkIdent) and IdentEq(x.ident, "false"): result = false
+  elif (x.kind == nkIdent) and identEq(x.ident, "true"): result = true
+  elif (x.kind == nkIdent) and identEq(x.ident, "false"): result = false
   else: invalidPragma(n)
   
 proc filterStrip(stdin: PLLStream, filename: string, call: PNode): PLLStream = 
   var pattern = strArg(call, "startswith", 1, "")
   var leading = boolArg(call, "leading", 2, true)
   var trailing = boolArg(call, "trailing", 3, true)
-  result = LLStreamOpen("")
+  result = llStreamOpen("")
   var line = newStringOfCap(80)
-  while LLStreamReadLine(stdin, line):
+  while llStreamReadLine(stdin, line):
     var stripped = strip(line, leading, trailing)
     if (len(pattern) == 0) or startsWith(stripped, pattern): 
-      LLStreamWriteln(result, stripped)
+      llStreamWriteln(result, stripped)
     else: 
-      LLStreamWriteln(result, line)
-  LLStreamClose(stdin)
+      llStreamWriteln(result, line)
+  llStreamClose(stdin)
 
 proc filterReplace(stdin: PLLStream, filename: string, call: PNode): PLLStream = 
   var sub = strArg(call, "sub", 1, "")
   if len(sub) == 0: invalidPragma(call)
   var by = strArg(call, "by", 2, "")
-  result = LLStreamOpen("")
+  result = llStreamOpen("")
   var line = newStringOfCap(80)
-  while LLStreamReadLine(stdin, line):
-    LLStreamWriteln(result, replace(line, sub, by))
-  LLStreamClose(stdin)
+  while llStreamReadLine(stdin, line):
+    llStreamWriteln(result, replace(line, sub, by))
+  llStreamClose(stdin)
diff --git a/compiler/guards.nim b/compiler/guards.nim
index 8d271fa6d..f475f5068 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -9,7 +9,7 @@
 
 ## This module implements the 'implies' relation for guards.
 
-import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer
+import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents
 
 const
   someEq = {mEqI, mEqI64, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
@@ -69,9 +69,23 @@ proc isLetLocation(m: PNode, isApprox: bool): bool =
 
 proc interestingCaseExpr*(m: PNode): bool = isLetLocation(m, true)
 
-proc swapArgs(fact: PNode, newOp: string, m: TMagic): PNode =
+proc getMagicOp(name: string, m: TMagic): PSym =
+  result = newSym(skProc, getIdent(name), nil, unknownLineInfo())
+  result.magic = m
+
+let
+  opLe = getMagicOp("<=", mLeI)
+  opLt = getMagicOp("<", mLtI)
+  opAnd = getMagicOp("and", mAnd)
+  opOr = getMagicOp("or", mOr)
+  opNot = getMagicOp("not", mNot)
+  opIsNil = getMagicOp("isnil", mIsNil)
+  opContains = getMagicOp("contains", mInSet)
+  opEq = getMagicOp("==", mEqI)
+
+proc swapArgs(fact: PNode, newOp: PSym): PNode =
   result = newNodeI(nkCall, fact.info, 3)
-  result.sons[0] = newSymNode(getSysMagic(newOp, m))
+  result.sons[0] = newSymNode(newOp)
   result.sons[1] = fact.sons[2]
   result.sons[2] = fact.sons[1]
 
@@ -82,9 +96,9 @@ proc neg(n: PNode): PNode =
     result = n.sons[1]
   of someLt:
     # not (a < b)  ==  a >= b  ==  b <= a
-    result = swapArgs(n, "<=", mLeI)
+    result = swapArgs(n, opLe)
   of someLe:
-    result = swapArgs(n, "<", mLtI)
+    result = swapArgs(n, opLt)
   of mInSet:
     if n.sons[1].kind != nkCurly: return nil
     let t = n.sons[2].typ.skipTypes(abstractInst)
@@ -110,7 +124,7 @@ proc neg(n: PNode): PNode =
       b = n.sons[2].neg
     if a != nil and b != nil:
       result = newNodeI(nkCall, n.info, 3)
-      result.sons[0] = newSymNode(getSysMagic("and", mAnd))
+      result.sons[0] = newSymNode(opAnd)
       result.sons[1] = a
       result.sons[2] = b
     elif a != nil:
@@ -120,12 +134,12 @@ proc neg(n: PNode): PNode =
   else:
     # leave  not (a == 4)  as it is
     result = newNodeI(nkCall, n.info, 2)
-    result.sons[0] = newSymNode(getSysMagic("not", mNot))
+    result.sons[0] = newSymNode(opNot)
     result.sons[1] = n
 
 proc buildIsNil(arg: PNode): PNode =
   result = newNodeI(nkCall, arg.info, 2)
-  result.sons[0] = newSymNode(getSysMagic("isNil", mIsNil))
+  result.sons[0] = newSymNode(opIsNil)
   result.sons[1] = arg
 
 proc usefulFact(n: PNode): PNode =
@@ -154,7 +168,7 @@ proc usefulFact(n: PNode): PNode =
       b = usefulFact(n.sons[2])
     if a != nil and b != nil:
       result = newNodeI(nkCall, n.info, 3)
-      result.sons[0] = newSymNode(getSysMagic("and", mAnd))
+      result.sons[0] = newSymNode(opAnd)
       result.sons[1] = a
       result.sons[2] = b
     elif a != nil:
@@ -177,7 +191,7 @@ proc usefulFact(n: PNode): PNode =
       b = usefulFact(n.sons[2]).neg
     if a != nil and b != nil:
       result = newNodeI(nkCall, n.info, 3)
-      result.sons[0] = newSymNode(getSysMagic("and", mAnd))
+      result.sons[0] = newSymNode(opAnd)
       result.sons[1] = a
       result.sons[2] = b
       result = result.neg
@@ -251,19 +265,15 @@ proc invalidateFacts*(m: var TModel, n: PNode) =
 
 proc valuesUnequal(a, b: PNode): bool =
   if a.isValue and b.isValue:
-    result = not SameValue(a, b)
+    result = not sameValue(a, b)
 
 proc pred(n: PNode): PNode =
-  if n.kind in {nkCharLit..nkUInt64Lit} and n.intVal != low(biggestInt):
+  if n.kind in {nkCharLit..nkUInt64Lit} and n.intVal != low(BiggestInt):
     result = copyNode(n)
     dec result.intVal
   else:
     result = n
 
-type
-  TImplication* = enum
-    impUnknown, impNo, impYes  
-
 proc impliesEq(fact, eq: PNode): TImplication =
   let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1)
   
@@ -366,7 +376,7 @@ proc impliesIsNil(fact, eq: PNode): TImplication =
   else: discard
 
 proc impliesGe(fact, x, c: PNode): TImplication =
-  InternalAssert isLocation(x)
+  internalAssert isLocation(x)
   case fact.sons[0].sym.magic
   of someEq:
     if sameTree(fact.sons[1], x):
@@ -439,7 +449,7 @@ proc impliesLe(fact, x, c: PNode): TImplication =
         if leValue(c, fact.sons[1].pred): result = impNo
 
   of mNot, mOr, mAnd: internalError(x.info, "impliesLe")
-  else: nil
+  else: discard
 
 proc impliesLt(fact, x, c: PNode): TImplication =
   # x < 3  same as x <= 2:
@@ -484,7 +494,7 @@ proc factImplies(fact, prop: PNode): TImplication =
       if a == b: return ~a
       return impUnknown
     else:
-      InternalError(fact.info, "invalid fact")
+      internalError(fact.info, "invalid fact")
   of mAnd:
     result = factImplies(fact.sons[1], prop)
     if result != impUnknown: return result
@@ -520,7 +530,7 @@ proc buildOf(it, loc: PNode): PNode =
   s.typ = settype(loc)
   for i in 0..it.len-2: s.sons[i] = it.sons[i]
   result = newNodeI(nkCall, it.info, 3)
-  result.sons[0] = newSymNode(getSysMagic("contains", mInSet))
+  result.sons[0] = newSymNode(opContains)
   result.sons[1] = s
   result.sons[2] = loc
 
@@ -532,20 +542,20 @@ proc buildElse(n: PNode): PNode =
     for j in 0..branch.len-2:
       s.add(branch.sons[j])
   result = newNodeI(nkCall, n.info, 3)
-  result.sons[0] = newSymNode(getSysMagic("contains", mInSet))
+  result.sons[0] = newSymNode(opContains)
   result.sons[1] = s
   result.sons[2] = n.sons[0]
 
 proc addDiscriminantFact*(m: var TModel, n: PNode) =
   var fact = newNodeI(nkCall, n.info, 3)
-  fact.sons[0] = newSymNode(getSysMagic("==", mEqI))
+  fact.sons[0] = newSymNode(opEq)
   fact.sons[1] = n.sons[0]
   fact.sons[2] = n.sons[1]
   m.add fact
 
 proc addAsgnFact*(m: var TModel, key, value: PNode) =
   var fact = newNodeI(nkCall, key.info, 3)
-  fact.sons[0] = newSymNode(getSysMagic("==", mEqI))
+  fact.sons[0] = newSymNode(opEq)
   fact.sons[1] = key
   fact.sons[2] = value
   m.add fact
@@ -575,4 +585,4 @@ proc checkFieldAccess*(m: TModel, n: PNode) =
   for i in 1..n.len-1:
     let check = buildProperFieldCheck(n.sons[0], n.sons[i])
     if m.doesImply(check) != impYes:
-      Message(n.info, warnProveField, renderTree(n.sons[0])); break
+      message(n.info, warnProveField, renderTree(n.sons[0])); break
diff --git a/compiler/hlo.nim b/compiler/hlo.nim
index 1492ed76f..c75d6519f 100644
--- a/compiler/hlo.nim
+++ b/compiler/hlo.nim
@@ -12,7 +12,7 @@
 proc hlo(c: PContext, n: PNode): PNode
 
 proc evalPattern(c: PContext, n, orig: PNode): PNode =
-  InternalAssert n.kind == nkCall and n.sons[0].kind == nkSym
+  internalAssert n.kind == nkCall and n.sons[0].kind == nkSym
   # we need to ensure that the resulting AST is semchecked. However, it's
   # aweful to semcheck before macro invocation, so we don't and treat
   # templates and macros as immediate in this context.
@@ -28,7 +28,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
   else:
     result = semDirectOp(c, n, {})
   if optHints in gOptions and hintPattern in gNotes:
-    Message(orig.info, hintPattern, rule & " --> '" & 
+    message(orig.info, hintPattern, rule & " --> '" & 
       renderTree(result, {renderNoComments}) & "'")
 
 proc applyPatterns(c: PContext, n: PNode): PNode =
@@ -45,7 +45,7 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
         # better be safe than sorry, so check evalTemplateCounter too:
         inc(evalTemplateCounter)
         if evalTemplateCounter > 100:
-          GlobalError(n.info, errTemplateInstantiationTooNested)
+          globalError(n.info, errTemplateInstantiationTooNested)
         # deactivate this pattern:
         c.patterns[i] = nil
         if x.kind == nkStmtList:
@@ -68,7 +68,8 @@ proc hlo(c: PContext, n: PNode): PNode =
     result = n
   else:
     if n.kind in {nkFastAsgn, nkAsgn, nkIdentDefs, nkVarTuple} and
-        n.sons[0].kind == nkSym and sfGlobal in n.sons[0].sym.flags:
+        n.sons[0].kind == nkSym and 
+        {sfGlobal, sfPure} * n.sons[0].sym.flags == {sfGlobal, sfPure}:
       # do not optimize 'var g {.global} = re(...)' again!
       return n
     result = applyPatterns(c, n)
@@ -81,7 +82,7 @@ proc hlo(c: PContext, n: PNode): PNode =
     else:
       # perform type checking, so that the replacement still fits:
       if isEmptyType(n.typ) and isEmptyType(result.typ):
-        nil
+        discard
       else:
         result = fitNode(c, n.typ, result)
       # optimization has been applied so check again:
diff --git a/compiler/idents.nim b/compiler/idents.nim
index 1e6f9d2fd..ec903826a 100644
--- a/compiler/idents.nim
+++ b/compiler/idents.nim
@@ -102,7 +102,7 @@ proc getIdent*(identifier: string): PIdent =
 proc getIdent*(identifier: string, h: THash): PIdent = 
   result = getIdent(cstring(identifier), len(identifier), h)
 
-proc IdentEq*(id: PIdent, name: string): bool = 
+proc identEq*(id: PIdent, name: string): bool = 
   result = id.id == getIdent(name).id
 
 var idAnon* = getIdent":anonymous"
diff --git a/compiler/idgen.nim b/compiler/idgen.nim
index fbf450c90..d932e3d9d 100644
--- a/compiler/idgen.nim
+++ b/compiler/idgen.nim
@@ -19,12 +19,12 @@ const
 when debugIds:
   import intsets
   
-  var usedIds = InitIntSet()
+  var usedIds = initIntSet()
 
 proc registerID*(id: PIdObj) = 
-  when debugIDs: 
-    if id.id == -1 or ContainsOrIncl(usedIds, id.id): 
-      InternalError("ID already used: " & $id.id)
+  when debugIds: 
+    if id.id == -1 or containsOrIncl(usedIds, id.id): 
+      internalError("ID already used: " & $id.id)
 
 proc getID*(): int {.inline.} = 
   result = gFrontEndId
@@ -37,8 +37,8 @@ proc backendId*(): int {.inline.} =
 proc setId*(id: int) {.inline.} = 
   gFrontEndId = max(gFrontEndId, id + 1)
 
-proc IDsynchronizationPoint*(idRange: int) = 
-  gFrontEndId = (gFrontEndId div IdRange + 1) * IdRange + 1
+proc idSynchronizationPoint*(idRange: int) = 
+  gFrontEndId = (gFrontEndId div idRange + 1) * idRange + 1
 
 proc toGid(f: string): string =
   # we used to use ``f.addFileExt("gid")`` (aka ``$project.gid``), but this
@@ -49,7 +49,7 @@ proc toGid(f: string): string =
 proc saveMaxIds*(project: string) =
   var f = open(project.toGid, fmWrite)
   f.writeln($gFrontEndId)
-  f.writeln($gBackEndId)
+  f.writeln($gBackendId)
   f.close()
   
 proc loadMaxIds*(project: string) =
@@ -61,5 +61,5 @@ proc loadMaxIds*(project: string) =
       if f.readLine(line):
         var backEndId = parseInt(line)
         gFrontEndId = max(gFrontEndId, frontEndId)
-        gBackEndId = max(gBackEndId, backEndId)
+        gBackendId = max(gBackendId, backEndId)
     f.close()
diff --git a/compiler/importer.nim b/compiler/importer.nim
index 8b854bcc6..7a73f2bbf 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -22,7 +22,7 @@ proc getModuleName*(n: PNode): string =
   # The proc won't perform any checks that the path is actually valid
   case n.kind
   of nkStrLit, nkRStrLit, nkTripleStrLit:
-    result = UnixToNativePath(n.strVal)
+    result = unixToNativePath(n.strVal)
   of nkIdent:
     result = n.ident.s
   of nkSym:
@@ -50,7 +50,7 @@ proc checkModuleName*(n: PNode): int32 =
   let modulename = n.getModuleName
   let fullPath = findModule(modulename, n.info.toFullPath)
   if fullPath.len == 0:
-    LocalError(n.info, errCannotOpenFile, modulename)
+    localError(n.info, errCannotOpenFile, modulename)
     result = InvalidFileIDX
   else:
     result = fullPath.fileInfoIdx
@@ -59,32 +59,32 @@ proc rawImportSymbol(c: PContext, s: PSym) =
   # This does not handle stubs, because otherwise loading on demand would be
   # pointless in practice. So importing stubs is fine here!
   # check if we have already a symbol of the same name:
-  var check = StrTableGet(c.importTable.symbols, s.name)
+  var check = strTableGet(c.importTable.symbols, s.name)
   if check != nil and check.id != s.id:
     if s.kind notin OverloadableSyms:
       # s and check need to be qualified:
-      Incl(c.AmbiguousSymbols, s.id)
-      Incl(c.AmbiguousSymbols, check.id)
+      incl(c.ambiguousSymbols, s.id)
+      incl(c.ambiguousSymbols, check.id)
   # thanks to 'export' feature, it could be we import the same symbol from
   # multiple sources, so we need to call 'StrTableAdd' here:
-  StrTableAdd(c.importTable.symbols, s)
+  strTableAdd(c.importTable.symbols, s)
   if s.kind == skType:
     var etyp = s.typ
     if etyp.kind in {tyBool, tyEnum} and sfPure notin s.flags:
       for j in countup(0, sonsLen(etyp.n) - 1):
         var e = etyp.n.sons[j].sym
-        if e.Kind != skEnumField: 
-          InternalError(s.info, "rawImportSymbol") 
+        if e.kind != skEnumField: 
+          internalError(s.info, "rawImportSymbol") 
           # BUGFIX: because of aliases for enums the symbol may already
           # have been put into the symbol table
           # BUGFIX: but only iff they are the same symbols!
         var it: TIdentIter 
-        check = InitIdentIter(it, c.importTable.symbols, e.name)
+        check = initIdentIter(it, c.importTable.symbols, e.name)
         while check != nil:
           if check.id == e.id:
             e = nil
             break
-          check = NextIdentIter(it, c.importTable.symbols)
+          check = nextIdentIter(it, c.importTable.symbols)
         if e != nil:
           rawImportSymbol(c, e)
   else:
@@ -94,36 +94,36 @@ proc rawImportSymbol(c: PContext, s: PSym) =
 
 proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = 
   let ident = lookups.considerAcc(n)
-  let s = StrTableGet(fromMod.tab, ident)
+  let s = strTableGet(fromMod.tab, ident)
   if s == nil:
-    LocalError(n.info, errUndeclaredIdentifier, ident.s)
+    localError(n.info, errUndeclaredIdentifier, ident.s)
   else:
     if s.kind == skStub: loadStub(s)
-    if s.Kind notin ExportableSymKinds:
-      InternalError(n.info, "importSymbol: 2")
+    if s.kind notin ExportableSymKinds:
+      internalError(n.info, "importSymbol: 2")
     # for an enumeration we have to add all identifiers
-    case s.Kind
-    of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter:
+    case s.kind
+    of skProcKinds:
       # for a overloadable syms add all overloaded routines
       var it: TIdentIter
-      var e = InitIdentIter(it, fromMod.tab, s.name)
+      var e = initIdentIter(it, fromMod.tab, s.name)
       while e != nil:
-        if e.name.id != s.Name.id: InternalError(n.info, "importSymbol: 3")
+        if e.name.id != s.name.id: internalError(n.info, "importSymbol: 3")
         rawImportSymbol(c, e)
-        e = NextIdentIter(it, fromMod.tab)
+        e = nextIdentIter(it, fromMod.tab)
     else: rawImportSymbol(c, s)
 
 proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: TIntSet) =
   var i: TTabIter
-  var s = InitTabIter(i, fromMod.tab)
+  var s = initTabIter(i, fromMod.tab)
   while s != nil:
     if s.kind != skModule:
       if s.kind != skEnumField:
-        if s.Kind notin ExportableSymKinds:
-          InternalError(s.info, "importAllSymbols: " & $s.kind)
+        if s.kind notin ExportableSymKinds:
+          internalError(s.info, "importAllSymbols: " & $s.kind)
         if exceptSet.empty or s.name.id notin exceptSet:
           rawImportSymbol(c, s)
-    s = NextIter(i, fromMod.tab)
+    s = nextIter(i, fromMod.tab)
 
 proc importAllSymbols*(c: PContext, fromMod: PSym) =
   var exceptSet: TIntSet
@@ -160,7 +160,7 @@ proc myImportModule(c: PContext, n: PNode): PSym =
   if f != InvalidFileIDX:
     result = importModuleAs(n, gImportModule(c.module, f))
     if sfDeprecated in result.flags:
-      Message(n.info, warnDeprecated, result.name.s)
+      message(n.info, warnDeprecated, result.name.s)
 
 proc evalImport(c: PContext, n: PNode): PNode = 
   result = n
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index a3c88824d..a34d8f123 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -64,7 +64,7 @@ type
     options: TOptions
     module: BModule
     g: PGlobals
-    BeforeRetNeeded: bool
+    beforeRetNeeded: bool
     target: TTarget # duplicated here for faster dispatching
     unique: int    # for temp identifier generation
     blocks: seq[TBlock]
@@ -111,7 +111,7 @@ proc mapType(typ: PType): TJSTypeKind =
   let t = skipTypes(typ, abstractInst)
   case t.kind
   of tyVar, tyRef, tyPtr: 
-    if skipTypes(t.sons[0], abstractInst).kind in mappedToObject: 
+    if skipTypes(t.lastSon, abstractInst).kind in MappedToObject: 
       result = etyObject
     else: 
       result = etyBaseIndex
@@ -129,8 +129,9 @@ proc mapType(typ: PType): TJSTypeKind =
      tyVarargs:
     result = etyObject
   of tyNil: result = etyNull
-  of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, tyNone, 
-     tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc, tyTypeClasses: 
+  of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation,
+     tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
+     tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses:
     result = etyNone
   of tyProc: result = etyProc
   of tyCString: result = etyString
@@ -142,7 +143,7 @@ proc mangle(name: string): string =
     of 'A'..'Z': 
       add(result, chr(ord(name[i]) - ord('A') + ord('a')))
     of '_': 
-      nil
+      discard
     of 'a'..'z', '0'..'9': 
       add(result, name[i])
     else: add(result, 'X' & toHex(ord(name[i]), 2))
@@ -175,7 +176,7 @@ proc useMagic(p: PProc, name: string) =
     # we used to exclude the system module from this check, but for DLL
     # generation support this sloppyness leads to hard to detect bugs, so
     # we're picky here for the system module too:
-    if p.prc != nil: GlobalError(p.prc.info, errSystemNeeds, name)
+    if p.prc != nil: globalError(p.prc.info, errSystemNeeds, name)
     else: rawMessage(errSystemNeeds, name)
 
 proc isSimpleExpr(n: PNode): bool =
@@ -240,7 +241,7 @@ proc genOr(p: PProc, a, b: PNode, r: var TCompRes) =
 
 type
   TMagicFrmt = array[0..3, string]
-  TMagicOps = array[mAddi..mStrToStr, TMagicFrmt]
+  TMagicOps = array[mAddI..mStrToStr, TMagicFrmt]
 
 const # magic checked op; magic unchecked op; checked op; unchecked op
   jsOps: TMagicOps = [
@@ -274,11 +275,11 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI64
     ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
     ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
-    ["AddU", "AddU", "AddU($1, $2)", "AddU($1, $2)"], # AddU
-    ["SubU", "SubU", "SubU($1, $2)", "SubU($1, $2)"], # SubU
-    ["MulU", "MulU", "MulU($1, $2)", "MulU($1, $2)"], # MulU
-    ["DivU", "DivU", "DivU($1, $2)", "DivU($1, $2)"], # DivU
-    ["ModU", "ModU", "ModU($1, $2)", "ModU($1, $2)"], # ModU
+    ["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU
+    ["subU", "subU", "subU($1, $2)", "subU($1, $2)"], # subU
+    ["mulU", "mulU", "mulU($1, $2)", "mulU($1, $2)"], # mulU
+    ["divU", "divU", "divU($1, $2)", "divU($1, $2)"], # divU
+    ["modU", "modU", "modU($1, $2)", "modU($1, $2)"], # modU
     ["", "", "($1 == $2)", "($1 == $2)"], # EqI
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
     ["", "", "($1 < $2)", "($1 < $2)"], # LtI
@@ -288,10 +289,10 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["", "", "($1 == $2)", "($1 == $2)"], # EqF64
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
     ["", "", "($1 < $2)", "($1 < $2)"], # LtF64
-    ["LeU", "LeU", "LeU($1, $2)", "LeU($1, $2)"], # LeU
-    ["LtU", "LtU", "LtU($1, $2)", "LtU($1, $2)"], # LtU
-    ["LeU64", "LeU64", "LeU64($1, $2)", "LeU64($1, $2)"], # LeU64
-    ["LtU64", "LtU64", "LtU64($1, $2)", "LtU64($1, $2)"], # LtU64
+    ["leU", "leU", "leU($1, $2)", "leU($1, $2)"], # leU
+    ["ltU", "ltU", "ltU($1, $2)", "ltU($1, $2)"], # ltU
+    ["leU64", "leU64", "leU64($1, $2)", "leU64($1, $2)"], # leU64
+    ["ltU64", "ltU64", "ltU64($1, $2)", "ltU64($1, $2)"], # ltU64
     ["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
     ["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
@@ -308,10 +309,10 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["", "", "($1 == $2)", "($1 == $2)"], # EqCString
     ["", "", "($1 != $2)", "($1 != $2)"], # Xor
     ["", "", "($1 == $2)", "($1 == $2)"], # EqProc
-    ["NegInt", "", "NegInt($1)", "-($1)"], # UnaryMinusI
-    ["NegInt64", "", "NegInt64($1)", "-($1)"], # UnaryMinusI64
-    ["AbsInt", "", "AbsInt($1)", "Math.abs($1)"], # AbsI
-    ["AbsInt64", "", "AbsInt64($1)", "Math.abs($1)"], # AbsI64
+    ["negInt", "", "negInt($1)", "-($1)"], # UnaryMinusI
+    ["negInt64", "", "negInt64($1)", "-($1)"], # UnaryMinusI64
+    ["absInt", "", "absInt($1)", "Math.abs($1)"], # AbsI
+    ["absInt64", "", "absInt64($1)", "Math.abs($1)"], # AbsI64
     ["", "", "!($1)", "!($1)"], # Not
     ["", "", "+($1)", "+($1)"], # UnaryPlusI
     ["", "", "~($1)", "~($1)"], # BitnotI
@@ -326,9 +327,9 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["Ze16ToI64", "Ze16ToI64", "Ze16ToI64($1)", "Ze16ToI64($1)"], # mZe16ToI64
     ["Ze32ToI64", "Ze32ToI64", "Ze32ToI64($1)", "Ze32ToI64($1)"], # mZe32ToI64
     ["ZeIToI64", "ZeIToI64", "ZeIToI64($1)", "ZeIToI64($1)"], # mZeIToI64
-    ["ToU8", "ToU8", "ToU8($1)", "ToU8($1)"], # ToU8
-    ["ToU16", "ToU16", "ToU16($1)", "ToU16($1)"], # ToU16
-    ["ToU32", "ToU32", "ToU32($1)", "ToU32($1)"], # ToU32
+    ["toU8", "toU8", "toU8($1)", "toU8($1)"], # toU8
+    ["toU16", "toU16", "toU16($1)", "toU16($1)"], # toU16
+    ["toU32", "toU32", "toU32($1)", "toU32($1)"], # toU32
     ["", "", "$1", "$1"],     # ToFloat
     ["", "", "$1", "$1"],     # ToBiggestFloat
     ["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt
@@ -374,11 +375,11 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI64
     ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
     ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
-    ["AddU", "AddU", "AddU($1, $2)", "AddU($1, $2)"], # AddU
-    ["SubU", "SubU", "SubU($1, $2)", "SubU($1, $2)"], # SubU
-    ["MulU", "MulU", "MulU($1, $2)", "MulU($1, $2)"], # MulU
-    ["DivU", "DivU", "DivU($1, $2)", "DivU($1, $2)"], # DivU
-    ["ModU", "ModU", "ModU($1, $2)", "ModU($1, $2)"], # ModU
+    ["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU
+    ["subU", "subU", "subU($1, $2)", "subU($1, $2)"], # subU
+    ["mulU", "mulU", "mulU($1, $2)", "mulU($1, $2)"], # mulU
+    ["divU", "divU", "divU($1, $2)", "divU($1, $2)"], # divU
+    ["modU", "modU", "modU($1, $2)", "modU($1, $2)"], # modU
     ["", "", "($1 == $2)", "($1 == $2)"], # EqI
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
     ["", "", "($1 < $2)", "($1 < $2)"], # LtI
@@ -388,10 +389,10 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["", "", "($1 == $2)", "($1 == $2)"], # EqF64
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
     ["", "", "($1 < $2)", "($1 < $2)"], # LtF64
-    ["LeU", "LeU", "LeU($1, $2)", "LeU($1, $2)"], # LeU
-    ["LtU", "LtU", "LtU($1, $2)", "LtU($1, $2)"], # LtU
-    ["LeU64", "LeU64", "LeU64($1, $2)", "LeU64($1, $2)"], # LeU64
-    ["LtU64", "LtU64", "LtU64($1, $2)", "LtU64($1, $2)"], # LtU64
+    ["leU", "leU", "leU($1, $2)", "leU($1, $2)"], # leU
+    ["ltU", "ltU", "ltU($1, $2)", "ltU($1, $2)"], # ltU
+    ["leU64", "leU64", "leU64($1, $2)", "leU64($1, $2)"], # leU64
+    ["ltU64", "ltU64", "ltU64($1, $2)", "ltU64($1, $2)"], # ltU64
     ["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
     ["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
@@ -408,10 +409,10 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["", "", "($1 == $2)", "($1 == $2)"], # EqCString
     ["", "", "($1 != $2)", "($1 != $2)"], # Xor
     ["", "", "($1 == $2)", "($1 == $2)"], # EqProc
-    ["NegInt", "", "NegInt($1)", "-($1)"], # UnaryMinusI
-    ["NegInt64", "", "NegInt64($1)", "-($1)"], # UnaryMinusI64
-    ["AbsInt", "", "AbsInt($1)", "Math.abs($1)"], # AbsI
-    ["AbsInt64", "", "AbsInt64($1)", "Math.abs($1)"], # AbsI64
+    ["negInt", "", "negInt($1)", "-($1)"], # UnaryMinusI
+    ["negInt64", "", "negInt64($1)", "-($1)"], # UnaryMinusI64
+    ["absInt", "", "absInt($1)", "Math.abs($1)"], # AbsI
+    ["absInt64", "", "absInt64($1)", "Math.abs($1)"], # AbsI64
     ["", "", "not ($1)", "not ($1)"], # Not
     ["", "", "+($1)", "+($1)"], # UnaryPlusI
     ["", "", "~($1)", "~($1)"], # BitnotI
@@ -426,9 +427,9 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["Ze16ToI64", "Ze16ToI64", "Ze16ToI64($1)", "Ze16ToI64($1)"], # mZe16ToI64
     ["Ze32ToI64", "Ze32ToI64", "Ze32ToI64($1)", "Ze32ToI64($1)"], # mZe32ToI64
     ["ZeIToI64", "ZeIToI64", "ZeIToI64($1)", "ZeIToI64($1)"], # mZeIToI64
-    ["ToU8", "ToU8", "ToU8($1)", "ToU8($1)"], # ToU8
-    ["ToU16", "ToU16", "ToU16($1)", "ToU16($1)"], # ToU16
-    ["ToU32", "ToU32", "ToU32($1)", "ToU32($1)"], # ToU32
+    ["toU8", "toU8", "toU8($1)", "toU8($1)"], # toU8
+    ["toU16", "toU16", "toU16($1)", "toU16($1)"], # toU16
+    ["toU32", "toU32", "toU32($1)", "toU32($1)"], # toU32
     ["", "", "$1", "$1"],     # ToFloat
     ["", "", "$1", "$1"],     # ToBiggestFloat
     ["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt
@@ -485,14 +486,14 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
 
 proc genLineDir(p: PProc, n: PNode) =
   let line = toLinenumber(n.info)
-  if optLineDir in p.Options:
+  if optLineDir in p.options:
     appf(p.body, "// line $2 \"$1\"$n" | "-- line $2 \"$1\"$n",
          [toRope(toFilename(n.info)), toRope(line)])
-  if {optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb} and
+  if {optStackTrace, optEndb} * p.options == {optStackTrace, optEndb} and
       ((p.prc == nil) or sfPure notin p.prc.flags):
     useMagic(p, "endb")
     appf(p.body, "endb($1);$n", [toRope(line)])
-  elif ({optLineTrace, optStackTrace} * p.Options ==
+  elif ({optLineTrace, optStackTrace} * p.options ==
       {optLineTrace, optStackTrace}) and
       ((p.prc == nil) or not (sfPure in p.prc.flags)): 
     appf(p.body, "F.line = $1;$n", [toRope(line)])
@@ -504,7 +505,7 @@ proc genWhileStmt(p: PProc, n: PNode) =
   genLineDir(p, n)
   inc(p.unique)
   var length = len(p.blocks)
-  setlen(p.blocks, length + 1)
+  setLen(p.blocks, length + 1)
   p.blocks[length].id = -p.unique
   p.blocks[length].isLoop = true
   let labl = p.unique.toRope
@@ -514,7 +515,7 @@ proc genWhileStmt(p: PProc, n: PNode) =
        [cond.res, labl])
   genStmt(p, n.sons[1])
   appf(p.body, "}$n" | "end ::L$#::$n", [labl])
-  setlen(p.blocks, length)
+  setLen(p.blocks, length)
 
 proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) =
   if src.kind != resNone:
@@ -555,7 +556,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
        "var $1 = {prev: excHandler, exc: null};$nexcHandler = $1;$n" | 
        "local $1 = pcall(", 
        [safePoint])
-  if optStackTrace in p.Options: app(p.body, "framePtr = F;" & tnl)
+  if optStackTrace in p.options: app(p.body, "framePtr = F;" & tnl)
   appf(p.body, "try {$n" | "function()$n")
   var length = sonsLen(n)
   var a: TCompRes
@@ -579,7 +580,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
       useMagic(p, "isObj")
       for j in countup(0, blen - 2): 
         if n.sons[i].sons[j].kind != nkType: 
-          InternalError(n.info, "genTryStmt")
+          internalError(n.info, "genTryStmt")
         if orExpr != nil: app(orExpr, "||" | " or ")
         appf(orExpr, "isObj($1.exc.m_type, $2)", 
              [safePoint, genTypeInfo(p, n.sons[i].sons[j].typ)])
@@ -641,13 +642,13 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
           while v.intVal <= e.sons[1].intVal: 
             gen(p, v, cond)
             appf(p.body, "case $1: ", [cond.rdLoc])
-            Inc(v.intVal)
+            inc(v.intVal)
         else:
           if stringSwitch: 
             case e.kind
             of nkStrLit..nkTripleStrLit: appf(p.body, "case $1: ", 
                 [makeJSString(e.strVal)])
-            else: InternalError(e.info, "jsgen.genCaseStmt: 2")
+            else: internalError(e.info, "jsgen.genCaseStmt: 2")
           else: 
             gen(p, e, cond)
             appf(p.body, "case $1: ", [cond.rdLoc])
@@ -694,7 +695,7 @@ proc genCaseLua(p: PProc, n: PNode, r: var TCompRes) =
             case e.kind
             of nkStrLit..nkTripleStrLit: appf(p.body, "eqStr($1, $2)",
                 [tmp, makeJSString(e.strVal)])
-            else: InternalError(e.info, "jsgen.genCaseStmt: 2")
+            else: internalError(e.info, "jsgen.genCaseStmt: 2")
           else:
             gen(p, e, cond)
             appf(p.body, "$1 == $2", [tmp, cond.rdLoc])
@@ -713,17 +714,17 @@ proc genBlock(p: PProc, n: PNode, r: var TCompRes) =
   let idx = len(p.blocks)
   if n.sons[0].kind != nkEmpty: 
     # named block?
-    if (n.sons[0].kind != nkSym): InternalError(n.info, "genBlock")
+    if (n.sons[0].kind != nkSym): internalError(n.info, "genBlock")
     var sym = n.sons[0].sym
     sym.loc.k = locOther
     sym.loc.a = idx
-  setlen(p.blocks, idx + 1)
+  setLen(p.blocks, idx + 1)
   p.blocks[idx].id = - p.unique # negative because it isn't used yet
   let labl = p.unique
   appf(p.body, "L$1: do {$n" | "", labl.toRope)
   gen(p, n.sons[1], r)
   appf(p.body, "} while(false);$n" | "$n::L$#::$n", labl.toRope)
-  setlen(p.blocks, idx)
+  setLen(p.blocks, idx)
 
 proc genBreakStmt(p: PProc, n: PNode) = 
   var idx: int
@@ -739,7 +740,7 @@ proc genBreakStmt(p: PProc, n: PNode) =
     idx = len(p.blocks) - 1
     while idx >= 0 and not p.blocks[idx].isLoop: dec idx
     if idx < 0 or not p.blocks[idx].isLoop:
-      InternalError(n.info, "no loop to break")
+      internalError(n.info, "no loop to break")
   p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
   appf(p.body, "break L$1;$n" | "goto ::L$1::;$n", [toRope(p.blocks[idx].id)])
 
@@ -747,10 +748,10 @@ proc genAsmStmt(p: PProc, n: PNode) =
   genLineDir(p, n)
   assert(n.kind == nkAsmStmt)
   for i in countup(0, sonsLen(n) - 1): 
-    case n.sons[i].Kind
+    case n.sons[i].kind
     of nkStrLit..nkTripleStrLit: app(p.body, n.sons[i].strVal)
     of nkSym: app(p.body, mangleName(n.sons[i].sym))
-    else: InternalError(n.sons[i].info, "jsgen: genAsmStmt()")
+    else: internalError(n.sons[i].info, "jsgen: genAsmStmt()")
   
 proc genIf(p: PProc, n: PNode, r: var TCompRes) = 
   var cond, stmt: TCompRes
@@ -811,8 +812,8 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
     if needsNoCopy(y) or noCopyNeeded:
       appf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
     else:
-      useMagic(p, "NimCopy")
-      appf(p.body, "$1 = NimCopy($2, $3);$n",
+      useMagic(p, "nimCopy")
+      appf(p.body, "$1 = nimCopy($2, $3);$n",
            [a.res, b.res, genTypeInfo(p, y.typ)])
   of etyBaseIndex: 
     if a.typ != etyBaseIndex or b.typ != etyBaseIndex: 
@@ -851,7 +852,7 @@ proc getFieldPosition(f: PNode): int =
   case f.kind
   of nkIntLit..nkUInt64Lit: result = int(f.intVal)
   of nkSym: result = f.sym.position
-  else: InternalError(f.info, "genFieldPosition")
+  else: internalError(f.info, "genFieldPosition")
 
 proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) = 
   var a: TCompRes
@@ -861,11 +862,11 @@ proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) =
   if skipTypes(b.sons[0].typ, abstractVarRange).kind == tyTuple:
     r.res = makeJSString("Field" & $getFieldPosition(b.sons[1]))
   else:
-    if b.sons[1].kind != nkSym: InternalError(b.sons[1].info, "genFieldAddr")
+    if b.sons[1].kind != nkSym: internalError(b.sons[1].info, "genFieldAddr")
     var f = b.sons[1].sym
     if f.loc.r == nil: f.loc.r = mangleName(f)
     r.res = makeJSString(ropeToStr(f.loc.r))
-  InternalAssert a.typ != etyBaseIndex
+  internalAssert a.typ != etyBaseIndex
   r.address = a.res
   r.kind = resExpr
 
@@ -875,7 +876,7 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) =
   if skipTypes(n.sons[0].typ, abstractVarRange).kind == tyTuple:
     r.res = ropef("$1.Field$2", [r.res, getFieldPosition(n.sons[1]).toRope])
   else:
-    if n.sons[1].kind != nkSym: InternalError(n.sons[1].info, "genFieldAddr")
+    if n.sons[1].kind != nkSym: internalError(n.sons[1].info, "genFieldAddr")
     var f = n.sons[1].sym
     if f.loc.r == nil: f.loc.r = mangleName(f)
     r.res = ropef("$1.$2", [r.res, f.loc.r])
@@ -890,14 +891,14 @@ proc genCheckedFieldAccess(p: PProc, n: PNode, r: var TCompRes) =
 proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = 
   var 
     a, b: TCompRes
-    first: biggestInt
+    first: BiggestInt
   r.typ = etyBaseIndex
   gen(p, n.sons[0], a)
   gen(p, n.sons[1], b)
-  InternalAssert a.typ != etyBaseIndex and b.typ != etyBaseIndex
+  internalAssert a.typ != etyBaseIndex and b.typ != etyBaseIndex
   r.address = a.res
   var typ = skipTypes(n.sons[0].typ, abstractPtrs)
-  if typ.kind in {tyArray, tyArrayConstr}: first = FirstOrd(typ.sons[0])
+  if typ.kind in {tyArray, tyArrayConstr}: first = firstOrd(typ.sons[0])
   else: first = 0
   if optBoundsCheck in p.options and not isConstExpr(n.sons[1]): 
     useMagic(p, "chckIndx")
@@ -911,16 +912,16 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
 
 proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) = 
   var ty = skipTypes(n.sons[0].typ, abstractVarRange)
-  if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.sons[0], abstractVarRange)
+  if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
   case ty.kind
   of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString,
      tyVarargs:
     genArrayAddr(p, n, r)
   of tyTuple: 
     genFieldAddr(p, n, r)
-  else: InternalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
+  else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
   r.typ = etyNone
-  if r.res == nil: InternalError(n.info, "genArrayAccess")
+  if r.res == nil: internalError(n.info, "genArrayAccess")
   r.res = ropef("$1[$2]", [r.address, r.res])
   r.address = nil
   r.kind = resExpr
@@ -929,7 +930,7 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
   case n.sons[0].kind
   of nkSym:
     let s = n.sons[0].sym
-    if s.loc.r == nil: InternalError(n.info, "genAddr: 3")
+    if s.loc.r == nil: internalError(n.info, "genAddr: 3")
     case s.kind
     of skVar, skLet, skResult:
       r.kind = resExpr
@@ -948,30 +949,30 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
         r.address = s.loc.r
         r.res = toRope("0")
       else:
-        InternalError(n.info, "genAddr: 4")
-    else: InternalError(n.info, "genAddr: 2")
+        internalError(n.info, "genAddr: 4")
+    else: internalError(n.info, "genAddr: 2")
   of nkCheckedFieldExpr:
     genCheckedFieldAddr(p, n, r)
   of nkDotExpr:
     genFieldAddr(p, n, r)
   of nkBracketExpr:
     var ty = skipTypes(n.sons[0].typ, abstractVarRange)
-    if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.sons[0], abstractVarRange)
+    if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
     case ty.kind
     of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString,
        tyVarargs:
       genArrayAddr(p, n, r)
     of tyTuple: 
       genFieldAddr(p, n, r)
-    else: InternalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
-  else: InternalError(n.info, "genAddr")
+    else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
+  else: internalError(n.info, "genAddr")
   
 proc genSym(p: PProc, n: PNode, r: var TCompRes) = 
   var s = n.sym
   case s.kind
   of skVar, skLet, skParam, skTemp, skResult:
     if s.loc.r == nil:
-      InternalError(n.info, "symbol has no generated name: " & s.name.s)
+      internalError(n.info, "symbol has no generated name: " & s.name.s)
     var k = mapType(s.typ)
     if k == etyBaseIndex:
       r.typ = etyBaseIndex
@@ -988,17 +989,17 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
   of skConst:
     genConstant(p, s)
     if s.loc.r == nil:
-      InternalError(n.info, "symbol has no generated name: " & s.name.s)
+      internalError(n.info, "symbol has no generated name: " & s.name.s)
     r.res = s.loc.r
   of skProc, skConverter, skMethod:
     discard mangleName(s)
     r.res = s.loc.r
     if lfNoDecl in s.loc.flags or s.magic != mNone or
        {sfImportc, sfInfixCall} * s.flags != {}:
-      nil
+      discard
     elif s.kind == skMethod and s.getBody.kind == nkEmpty:
       # we cannot produce code for the dispatcher yet:
-      nil
+      discard
     elif sfForward in s.flags:
       p.g.forwarded.add(s)
     elif not p.g.generatedSyms.containsOrIncl(s.id):
@@ -1010,7 +1011,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
       else: app(p.g.code, newp)
   else:
     if s.loc.r == nil:
-      InternalError(n.info, "symbol has no generated name: " & s.name.s)
+      internalError(n.info, "symbol has no generated name: " & s.name.s)
     r.res = s.loc.r
   r.kind = resVal
   
@@ -1020,7 +1021,7 @@ proc genDeref(p: PProc, n: PNode, r: var TCompRes) =
   else:
     var a: TCompRes
     gen(p, n.sons[0], a)
-    if a.typ != etyBaseIndex: InternalError(n.info, "genDeref")
+    if a.typ != etyBaseIndex: internalError(n.info, "genDeref")
     r.res = ropef("$1[$2]", [a.address, a.res])
 
 proc genArg(p: PProc, n: PNode, r: var TCompRes) =
@@ -1051,7 +1052,7 @@ proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) =
   gen(p, n.sons[1], r)
   if r.typ == etyBaseIndex:
     if r.address == nil:
-      GlobalError(n.info, "cannot invoke with infix syntax")
+      globalError(n.info, "cannot invoke with infix syntax")
     r.res = ropef("$1[$2]", [r.address, r.res])
     r.address = nil
     r.typ = etyNone
@@ -1093,7 +1094,7 @@ proc createRecordVarAux(p: PProc, rec: PNode, c: var int): PRope =
     app(result, ": ")
     app(result, createVar(p, rec.sym.typ, false))
     inc(c)
-  else: InternalError(rec.info, "createRecordVarAux")
+  else: internalError(rec.info, "createRecordVarAux")
   
 proc createVar(p: PProc, typ: PType, indirect: bool): PRope = 
   var t = skipTypes(typ, abstractInst)
@@ -1112,8 +1113,8 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope =
     var length = int(lengthOrd(t))
     var e = elemType(t)
     if length > 32: 
-      useMagic(p, "ArrayConstr")
-      result = ropef("ArrayConstr($1, $2, $3)", [toRope(length), 
+      useMagic(p, "arrayConstr")
+      result = ropef("arrayConstr($1, $2, $3)", [toRope(length), 
           createVar(p, e, false), genTypeInfo(p, e)])
     else: 
       result = toRope("[")
@@ -1125,7 +1126,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope =
       app(result, "]")
   of tyTuple: 
     result = toRope("{")
-    for i in 0.. <t.sonslen:
+    for i in 0.. <t.sonsLen:
       if i > 0: app(result, ", ")
       appf(result, "Field$1: $2" | "Field$# = $#", i.toRope, 
            createVar(p, t.sons[i], false))
@@ -1153,7 +1154,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope =
 
 proc isIndirect(v: PSym): bool = 
   result = (sfAddrTaken in v.flags) and (mapType(v.typ) != etyObject) and
-    v.kind notin {skProc, skConverter, skMethod, skIterator}
+    v.kind notin {skProc, skConverter, skMethod, skIterator, skClosureIterator}
 
 proc genVarInit(p: PProc, v: PSym, n: PNode) = 
   var 
@@ -1170,10 +1171,10 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
       if needsNoCopy(n): 
         s = a.res
       else: 
-        useMagic(p, "NimCopy")
-        s = ropef("NimCopy($1, $2)", [a.res, genTypeInfo(p, n.typ)])
+        useMagic(p, "nimCopy")
+        s = ropef("nimCopy($1, $2)", [a.res, genTypeInfo(p, n.typ)])
     of etyBaseIndex: 
-      if (a.typ != etyBaseIndex): InternalError(n.info, "genVarInit")
+      if (a.typ != etyBaseIndex): internalError(n.info, "genVarInit")
       if {sfAddrTaken, sfGlobal} * v.flags != {}: 
         appf(p.body, "var $1 = [$2, $3];$n" | "local $1 = {$2, $3};$n", 
             [v.loc.r, a.address, a.res])
@@ -1227,7 +1228,7 @@ proc genOrd(p: PProc, n: PNode, r: var TCompRes) =
   case skipTypes(n.sons[1].typ, abstractVar).kind
   of tyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r)
   of tyBool: unaryExpr(p, n, r, "", "($1 ? 1:0)" | "toBool($#)")
-  else: InternalError(n.info, "genOrd")
+  else: internalError(n.info, "genOrd")
   
 proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) =
   var a: TCompRes
@@ -1293,20 +1294,20 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
   case op
   of mOr: genOr(p, n.sons[1], n.sons[2], r)
   of mAnd: genAnd(p, n.sons[1], n.sons[2], r)
-  of mAddi..mStrToStr: arith(p, n, r, op)
+  of mAddI..mStrToStr: arith(p, n, r, op)
   of mRepr: genRepr(p, n, r)
   of mSwap: genSwap(p, n)
   of mUnaryLt:
     # XXX: range checking?
-    if not (optOverflowCheck in p.Options): unaryExpr(p, n, r, "", "$1 - 1")
+    if not (optOverflowCheck in p.options): unaryExpr(p, n, r, "", "$1 - 1")
     else: unaryExpr(p, n, r, "subInt", "subInt($1, 1)")
   of mPred:
     # XXX: range checking?
-    if not (optOverflowCheck in p.Options): binaryExpr(p, n, r, "", "$1 - $2")
+    if not (optOverflowCheck in p.options): binaryExpr(p, n, r, "", "$1 - $2")
     else: binaryExpr(p, n, r, "subInt", "subInt($1, $2)")
   of mSucc:
     # XXX: range checking?
-    if not (optOverflowCheck in p.Options): binaryExpr(p, n, r, "", "$1 - $2")
+    if not (optOverflowCheck in p.options): binaryExpr(p, n, r, "", "$1 - $2")
     else: binaryExpr(p, n, r, "addInt", "addInt($1, $2)")
   of mAppendStrCh: binaryExpr(p, n, r, "addChar", "addChar($1, $2)")
   of mAppendStrStr:
@@ -1335,10 +1336,10 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
     else:
       unaryExpr(p, n, r, "", "($1.length-1)")
   of mInc:
-    if not (optOverflowCheck in p.Options): binaryExpr(p, n, r, "", "$1 += $2")
+    if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
     else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)")
   of ast.mDec:
-    if not (optOverflowCheck in p.Options): binaryExpr(p, n, r, "", "$1 -= $2")
+    if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
     else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
   of mSetLengthStr: binaryExpr(p, n, r, "", "$1.length = ($2)-1")
   of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2")
@@ -1416,7 +1417,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
   for i in countup(1, sonsLen(n) - 1):
     if i > 0: app(r.res, ", ")
     var it = n.sons[i]
-    InternalAssert it.kind == nkExprColonExpr
+    internalAssert it.kind == nkExprColonExpr
     gen(p, it.sons[1], a)
     var f = it.sons[0].sym
     if f.loc.r == nil: f.loc.r = mangleName(f)
@@ -1451,7 +1452,7 @@ proc convStrToCStr(p: PProc, n: PNode, r: var TCompRes) =
     gen(p, n.sons[0].sons[0], r)
   else:
     gen(p, n.sons[0], r)
-    if r.res == nil: InternalError(n.info, "convStrToCStr")
+    if r.res == nil: internalError(n.info, "convStrToCStr")
     useMagic(p, "toJSStr")
     r.res = ropef("toJSStr($1)", [r.res])
     r.kind = resExpr
@@ -1463,14 +1464,14 @@ proc convCStrToStr(p: PProc, n: PNode, r: var TCompRes) =
     gen(p, n.sons[0].sons[0], r)
   else: 
     gen(p, n.sons[0], r)
-    if r.res == nil: InternalError(n.info, "convCStrToStr")
+    if r.res == nil: internalError(n.info, "convCStrToStr")
     useMagic(p, "cstrToNimstr")
     r.res = ropef("cstrToNimstr($1)", [r.res])
     r.kind = resExpr
 
 proc genReturnStmt(p: PProc, n: PNode) = 
-  if p.procDef == nil: InternalError(n.info, "genReturnStmt")
-  p.BeforeRetNeeded = true
+  if p.procDef == nil: internalError(n.info, "genReturnStmt")
+  p.beforeRetNeeded = true
   if (n.sons[0].kind != nkEmpty): 
     genStmt(p, n.sons[0])
   else:
@@ -1543,7 +1544,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
     r.res = toRope(n.intVal)
   of nkNilLit:
     if isEmptyType(n.typ):
-      nil
+      discard
     elif mapType(n.typ) == etyBaseIndex:
       r.typ = etyBaseIndex
       r.address = toRope"null" | toRope"nil"
@@ -1564,7 +1565,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
     elif f == 0.5 * f: 
       if f > 0.0: r.res = toRope"Infinity"
       else: r.res = toRope"-Infinity"
-    else: r.res = toRope(f.ToStrMaxPrecision)
+    else: r.res = toRope(f.toStrMaxPrecision)
   of nkCallKinds:
     if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone): 
       genMagic(p, n, r)
@@ -1591,15 +1592,14 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
   of nkChckRange: genRangeChck(p, n, r, "chckRange")
   of nkStringToCString: convStrToCStr(p, n, r)
   of nkCStringToString: convCStrToStr(p, n, r)
-  of nkEmpty: nil
+  of nkEmpty: discard
   of nkLambdaKinds: 
     let s = n.sons[namePos].sym
     discard mangleName(s)
     r.res = s.loc.r
-    if lfNoDecl in s.loc.flags or s.magic != mNone: nil
+    if lfNoDecl in s.loc.flags or s.magic != mNone: discard
     elif not p.g.generatedSyms.containsOrIncl(s.id):
       app(p.locals, genProc(p, s))
-  of nkMetaNode: gen(p, n.sons[0], r)
   of nkType: r.res = genTypeInfo(p, n.typ)
   of nkStmtList, nkStmtListExpr:
     # this shows the distinction is nice for backends and should be kept
@@ -1613,7 +1613,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
   of nkIfStmt, nkIfExpr: genIf(p, n, r)
   of nkWhileStmt: genWhileStmt(p, n)
   of nkVarSection, nkLetSection: genVarStmt(p, n)
-  of nkConstSection: nil
+  of nkConstSection: discard
   of nkForStmt, nkParForStmt: 
     internalError(n.info, "for statement not eliminated")
   of nkCaseStmt: 
@@ -1632,7 +1632,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
   of nkRaiseStmt: genRaiseStmt(p, n)
   of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt, 
      nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, 
-     nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: nil
+     nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: discard
   of nkProcDef, nkMethodDef, nkConverterDef:
     var s = n.sons[namePos].sym
     if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
@@ -1640,7 +1640,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
       r.res = nil
   of nkGotoState, nkState:
     internalError(n.info, "first class iterators not implemented")
-  else: InternalError(n.info, "gen: unknown node type: " & $n.kind)
+  else: internalError(n.info, "gen: unknown node type: " & $n.kind)
   
 var globals: PGlobals
 
@@ -1651,11 +1651,11 @@ proc newModule(module: PSym): BModule =
   
 proc genHeader(): PRope =
   result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" &
-                 "/*   (c) 2013 Andreas Rumpf */$n$n" & 
+                 "/*   (c) 2014 Andreas Rumpf */$n$n" & 
                  "$nvar Globals = this;$n" &
                  "var framePtr = null;$n" & 
                  "var excHandler = null;$n", 
-                 [toRope(versionAsString)])
+                 [toRope(VersionAsString)])
 
 proc genModule(p: PProc, n: PNode) = 
   if optStackTrace in p.options:
@@ -1671,7 +1671,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
   if passes.skipCodegen(n): return n
   result = n
   var m = BModule(b)
-  if m.module == nil: InternalError(n.info, "myProcess")
+  if m.module == nil: internalError(n.info, "myProcess")
   var p = newProc(globals, m, nil, m.module.options)
   genModule(p, n)
   app(p.g.code, p.locals)
@@ -1702,7 +1702,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
     discard writeRopeIfNotEqual(con(genHeader(), code), outfile)
 
 proc myOpenCached(s: PSym, rd: PRodReader): PPassContext = 
-  InternalError("symbol files are not possible with the JS code generator")
+  internalError("symbol files are not possible with the JS code generator")
   result = nil
 
 proc myOpen(s: PSym): PPassContext = 
diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim
index 0be1e99dc..009fc7935 100644
--- a/compiler/jstypes.nim
+++ b/compiler/jstypes.nim
@@ -37,7 +37,7 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): PRope =
                    [mangleName(field), s, makeJSString(field.name.s)])
   of nkRecCase: 
     length = sonsLen(n)
-    if (n.sons[0].kind != nkSym): InternalError(n.info, "genObjectFields")
+    if (n.sons[0].kind != nkSym): internalError(n.info, "genObjectFields")
     field = n.sons[0].sym
     s = genTypeInfo(p, field.typ)
     for i in countup(1, length - 1): 
@@ -98,7 +98,7 @@ proc genEnumInfo(p: PProc, typ: PType, name: PRope) =
   let length = sonsLen(typ.n)
   var s: PRope = nil
   for i in countup(0, length - 1): 
-    if (typ.n.sons[i].kind != nkSym): InternalError(typ.n.info, "genEnumInfo")
+    if (typ.n.sons[i].kind != nkSym): internalError(typ.n.info, "genEnumInfo")
     let field = typ.n.sons[i].sym
     if i > 0: app(s, ", " & tnl)
     let extName = if field.ast == nil: field.name.s else: field.ast.strVal
@@ -119,7 +119,7 @@ proc genTypeInfo(p: PProc, typ: PType): PRope =
   var t = typ
   if t.kind == tyGenericInst: t = lastSon(t)
   result = ropef("NTI$1", [toRope(t.id)])
-  if ContainsOrIncl(p.g.TypeInfoGenerated, t.id): return 
+  if containsOrIncl(p.g.typeInfoGenerated, t.id): return 
   case t.kind
   of tyDistinct: 
     result = genTypeInfo(p, typ.sons[0])
@@ -134,7 +134,7 @@ proc genTypeInfo(p: PProc, typ: PType): PRope =
               [result, toRope(ord(t.kind))])
     prepend(p.g.typeInfo, s)
     appf(p.g.typeInfo, "$1.base = $2;$n", 
-         [result, genTypeInfo(p, typ.sons[0])])
+         [result, genTypeInfo(p, typ.lastSon)])
   of tyArrayConstr, tyArray: 
     var s = ropef(
       "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n",
@@ -145,4 +145,4 @@ proc genTypeInfo(p: PProc, typ: PType): PRope =
   of tyEnum: genEnumInfo(p, t, result)
   of tyObject: genObjectInfo(p, t, result)
   of tyTuple: genTupleInfo(p, t, result)
-  else: InternalError("genTypeInfo(" & $t.kind & ')')
+  else: internalError("genTypeInfo(" & $t.kind & ')')
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 96eb3a5f4..440468ac4 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -11,7 +11,7 @@
 
 import 
   intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, 
-  idents, renderer, types, magicsys, rodread
+  idents, renderer, types, magicsys, rodread, lowerings
 
 discard """
   The basic approach is that captured vars need to be put on the heap and
@@ -116,26 +116,119 @@ type
   TDep = tuple[e: PEnv, field: PSym]
   TEnv {.final.} = object of TObject
     attachedNode: PNode
-    closure: PSym   # if != nil it is a used environment
+    createdVar: PSym        # if != nil it is a used environment
+    createdVarComesFromIter: bool
     capturedVars: seq[PSym] # captured variables in this environment
-    deps: seq[TDep] # dependencies
+    deps: seq[TDep]         # dependencies
     up: PEnv
-    tup: PType
+    obj: PType
   
-  TInnerContext {.final.} = object
+  TInnerContext = object
     fn: PSym
     closureParam: PSym
     localsToAccess: TIdNodeTable
     
-  TOuterContext {.final.} = object
+  TOuterContext = object
     fn: PSym # may also be a module!
     currentEnv: PEnv
+    isIter: bool   # first class iterator?
     capturedVars, processed: TIntSet
     localsToEnv: TIdTable # PSym->PEnv mapping
     localsToAccess: TIdNodeTable
     lambdasToEnv: TIdTable # PSym->PEnv mapping
     up: POuterContext
 
+    closureParam, state, resultSym: PSym # only if isIter
+    obj: PType # only if isIter
+
+proc createObj(owner: PSym, info: TLineInfo): PType =
+  result = newType(tyObject, owner)
+  rawAddSon(result, nil)
+  incl result.flags, tfFinal
+  result.n = newNodeI(nkRecList, info)
+
+proc getStateType(iter: PSym): PType =
+  var n = newNodeI(nkRange, iter.info)
+  addSon(n, newIntNode(nkIntLit, -1))
+  addSon(n, newIntNode(nkIntLit, 0))
+  result = newType(tyRange, iter)
+  result.n = n
+  rawAddSon(result, getSysType(tyInt))
+
+proc createStateField(iter: PSym): PSym =
+  result = newSym(skField, getIdent(":state"), iter, iter.info)
+  result.typ = getStateType(iter)
+
+proc newIterResult(iter: PSym): PSym =
+  if resultPos < iter.ast.len:
+    result = iter.ast.sons[resultPos].sym
+  else:
+    # XXX a bit hacky:
+    result = newSym(skResult, getIdent":result", iter, iter.info)
+    result.typ = iter.typ.sons[0]
+    incl(result.flags, sfUsed)
+    iter.ast.add newSymNode(result)
+
+proc addHiddenParam(routine: PSym, param: PSym) =
+  var params = routine.ast.sons[paramsPos]
+  # -1 is correct here as param.position is 0 based but we have at position 0
+  # some nkEffect node:
+  param.position = params.len-1
+  addSon(params, newSymNode(param))
+  incl(routine.typ.flags, tfCapturesEnv)
+  #echo "produced environment: ", param.id, " for ", routine.name.s
+
+proc getHiddenParam(routine: PSym): PSym =
+  let params = routine.ast.sons[paramsPos]
+  let hidden = lastSon(params)
+  assert hidden.kind == nkSym
+  result = hidden.sym
+
+proc getEnvParam(routine: PSym): PSym =
+  let params = routine.ast.sons[paramsPos]
+  let hidden = lastSon(params)
+  if hidden.kind == nkSym and hidden.sym.name.s == paramName:
+    result = hidden.sym
+    
+proc addField(obj: PType; s: PSym) =
+  # because of 'gensym' support, we have to mangle the name with its ID.
+  # This is hacky but the clean solution is much more complex than it looks.
+  var field = newSym(skField, getIdent(s.name.s & $s.id), s.owner, s.info)
+  let t = skipIntLit(s.typ)
+  field.typ = t
+  field.position = sonsLen(obj.n)
+  addSon(obj.n, newSymNode(field))
+
+proc initIterContext(c: POuterContext, iter: PSym) =
+  c.fn = iter
+  c.capturedVars = initIntSet()
+
+  var cp = getEnvParam(iter)
+  if cp == nil:
+    c.obj = createObj(iter, iter.info)
+
+    cp = newSym(skParam, getIdent(paramName), iter, iter.info)
+    incl(cp.flags, sfFromGeneric)
+    cp.typ = newType(tyRef, iter)
+    rawAddSon(cp.typ, c.obj)
+    addHiddenParam(iter, cp)
+
+    c.state = createStateField(iter)
+    addField(c.obj, c.state)
+  else:
+    c.obj = cp.typ.sons[0]
+    assert c.obj.kind == tyObject
+    if c.obj.n.len > 0:
+      c.state = c.obj.n[0].sym
+    else:
+      c.state = createStateField(iter)
+      addField(c.obj, c.state)
+
+  c.closureParam = cp
+  if iter.typ.sons[0] != nil:
+    c.resultSym = newIterResult(iter)
+    #iter.ast.add(newSymNode(c.resultSym))
+
 proc newOuterContext(fn: PSym, up: POuterContext = nil): POuterContext =
   new(result)
   result.fn = fn
@@ -144,52 +237,49 @@ proc newOuterContext(fn: PSym, up: POuterContext = nil): POuterContext =
   initIdNodeTable(result.localsToAccess)
   initIdTable(result.localsToEnv)
   initIdTable(result.lambdasToEnv)
-  
+  result.isIter = fn.kind == skClosureIterator
+  if result.isIter: initIterContext(result, fn)
+
 proc newInnerContext(fn: PSym): PInnerContext =
   new(result)
   result.fn = fn
   initIdNodeTable(result.localsToAccess)
-  
+
 proc newEnv(outerProc: PSym, up: PEnv, n: PNode): PEnv =
   new(result)
   result.deps = @[]
   result.capturedVars = @[]
-  result.tup = newType(tyTuple, outerProc)
-  result.tup.n = newNodeI(nkRecList, outerProc.info)
+  result.obj = createObj(outerProc, outerProc.info)
   result.up = up
   result.attachedNode = n
 
-proc addField(tup: PType, s: PSym) =
-  var field = newSym(skField, s.name, s.owner, s.info)
-  let t = skipIntLit(s.typ)
-  field.typ = t
-  field.position = sonsLen(tup)
-  addSon(tup.n, newSymNode(field))
-  rawAddSon(tup, t)
-  
 proc addCapturedVar(e: PEnv, v: PSym) =
   for x in e.capturedVars:
     if x == v: return
+  # XXX meh, just add the state field for every closure for now, it's too
+  # hard to figure out if it comes from a closure iterator:
+  if e.obj.n.len == 0: addField(e.obj, createStateField(v.owner))
   e.capturedVars.add(v)
-  addField(e.tup, v)
+  addField(e.obj, v)
   
 proc addDep(e, d: PEnv, owner: PSym): PSym =
   for x, field in items(e.deps):
     if x == d: return field
-  var pos = sonsLen(e.tup)
+  var pos = sonsLen(e.obj.n)
   result = newSym(skField, getIdent(upName & $pos), owner, owner.info)
   result.typ = newType(tyRef, owner)
   result.position = pos
-  assert d.tup != nil
-  rawAddSon(result.typ, d.tup)
-  addField(e.tup, result)
+  assert d.obj != nil
+  rawAddSon(result.typ, d.obj)
+  addField(e.obj, result)
   e.deps.add((d, result))
   
 proc indirectAccess(a: PNode, b: PSym, info: TLineInfo): PNode = 
   # returns a[].b as a node
   var deref = newNodeI(nkHiddenDeref, info)
   deref.typ = a.typ.sons[0]
-  let field = getSymFromList(deref.typ.n, b.name)
+  assert deref.typ.kind == tyObject
+  let field = getSymFromList(deref.typ.n, getIdent(b.name.s & $b.id))
   assert field != nil, b.name.s
   addSon(deref, a)
   result = newNodeI(nkDotExpr, info)
@@ -205,37 +295,29 @@ proc newCall(a, b: PSym): PNode =
   result.add newSymNode(a)
   result.add newSymNode(b)
 
-proc addHiddenParam(routine: PSym, param: PSym) =
-  var params = routine.ast.sons[paramsPos]
-  param.position = params.len
-  addSon(params, newSymNode(param))
-  incl(routine.typ.flags, tfCapturesEnv)
-  #echo "produced environment: ", param.id, " for ", routine.name.s
-
-proc getHiddenParam(routine: PSym): PSym =
-  let params = routine.ast.sons[paramsPos]
-  let hidden = lastSon(params)
-  assert hidden.kind == nkSym
-  result = hidden.sym
-
 proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
-  result = s.kind in {skProc, skMethod, skConverter} and 
+  result = s.kind in {skProc, skMethod, skConverter, skClosureIterator} and
            s.skipGenericOwner == outerProc
   #s.typ.callConv == ccClosure
 
 proc addClosureParam(i: PInnerContext, e: PEnv) =
-  var cp = newSym(skParam, getIdent(paramname), i.fn, i.fn.info)
-  incl(cp.flags, sfFromGeneric)
-  cp.typ = newType(tyRef, i.fn)
-  rawAddSon(cp.typ, e.tup)
+  var cp = getEnvParam(i.fn)
+  if cp == nil:
+    cp = newSym(skParam, getIdent(paramName), i.fn, i.fn.info)
+    incl(cp.flags, sfFromGeneric)
+    cp.typ = newType(tyRef, i.fn)
+    rawAddSon(cp.typ, e.obj)
+    addHiddenParam(i.fn, cp)
+  else:
+    e.obj = cp.typ.sons[0]
+    assert e.obj.kind == tyObject
   i.closureParam = cp
-  addHiddenParam(i.fn, i.closureParam)
   #echo "closure param added for ", i.fn.name.s, " ", i.fn.id
 
 proc dummyClosureParam(o: POuterContext, i: PInnerContext) =
   var e = o.currentEnv
-  if IdTableGet(o.lambdasToEnv, i.fn) == nil:
-    IdTablePut(o.lambdasToEnv, i.fn, e)
+  if idTableGet(o.lambdasToEnv, i.fn) == nil:
+    idTablePut(o.lambdasToEnv, i.fn, e)
   if i.closureParam == nil: addClosureParam(i, e)
 
 proc illegalCapture(s: PSym): bool {.inline.} =
@@ -247,13 +329,13 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
                 info: TLineInfo) =
   # for inlined variables the owner is still wrong, so it can happen that it's
   # not a captured variable at all ... *sigh* 
-  var it = PEnv(IdTableGet(o.localsToEnv, local))
+  var it = PEnv(idTableGet(o.localsToEnv, local))
   if it == nil: return
   
   if illegalCapture(local) or o.fn.id != local.owner.id or 
       i.fn.typ.callConv notin {ccClosure, ccDefault}:
     # Currently captures are restricted to a single level of nesting:
-    LocalError(info, errIllegalCaptureX, local.name.s)
+    localError(info, errIllegalCaptureX, local.name.s)
   i.fn.typ.callConv = ccClosure
   #echo "captureVar ", i.fn.name.s, i.fn.id, " ", local.name.s, local.id
 
@@ -261,11 +343,11 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
 
   # we need to remember which inner most closure belongs to this lambda:
   var e = o.currentEnv
-  if IdTableGet(o.lambdasToEnv, i.fn) == nil:
-    IdTablePut(o.lambdasToEnv, i.fn, e)
+  if idTableGet(o.lambdasToEnv, i.fn) == nil:
+    idTablePut(o.lambdasToEnv, i.fn, e)
 
   # variable already captured:
-  if IdNodeTableGet(i.localsToAccess, local) != nil: return
+  if idNodeTableGet(i.localsToAccess, local) != nil: return
   if i.closureParam == nil: addClosureParam(i, e)
   
   # check which environment `local` belongs to:
@@ -273,13 +355,16 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
   addCapturedVar(it, local)
   if it == e:
     # common case: local directly in current environment:
-    nil
+    discard
   else:
     # it's in some upper environment:
     access = indirectAccess(access, addDep(e, it, i.fn), info)
   access = indirectAccess(access, local, info)
-  incl(o.capturedVars, local.id)
-  IdNodeTablePut(i.localsToAccess, local, access)
+  if o.isIter:
+    if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local)
+  else:
+    incl(o.capturedVars, local.id)
+  idNodeTablePut(i.localsToAccess, local, access)
 
 proc interestingVar(s: PSym): bool {.inline.} =
   result = s.kind in {skVar, skLet, skTemp, skForVar, skParam, skResult} and
@@ -304,15 +389,17 @@ proc gatherVars(o: POuterContext, i: PInnerContext, n: PNode) =
     var s = n.sym
     if interestingVar(s) and i.fn.id != s.owner.id:
       captureVar(o, i, s, n.info)
-    elif isInnerProc(s, o.fn) and tfCapturesEnv in s.typ.flags and s != i.fn:
+    elif s.kind in {skProc, skMethod, skConverter} and
+            s.skipGenericOwner == o.fn and 
+            tfCapturesEnv in s.typ.flags and s != i.fn:
       # call to some other inner proc; we need to track the dependencies for
       # this:
-      let env = PEnv(IdTableGet(o.lambdasToEnv, i.fn))
-      if env == nil: InternalError(n.info, "no environment computed")
+      let env = PEnv(idTableGet(o.lambdasToEnv, i.fn))
+      if env == nil: internalError(n.info, "no environment computed")
       if o.currentEnv != env:
         discard addDep(o.currentEnv, env, i.fn)
-        InternalError(n.info, "too complex environment handling required")
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: nil
+        internalError(n.info, "too complex environment handling required")
+  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkClosure: discard
   else:
     for k in countup(0, sonsLen(n) - 1): 
       gatherVars(o, i, n.sons[k])
@@ -349,7 +436,7 @@ proc makeClosure(prc, env: PSym, info: TLineInfo): PNode =
 
 proc transformInnerProc(o: POuterContext, i: PInnerContext, n: PNode): PNode =
   case n.kind
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: nil
+  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard
   of nkSym:
     let s = n.sym
     if s == i.fn: 
@@ -363,13 +450,14 @@ proc transformInnerProc(o: POuterContext, i: PInnerContext, n: PNode): PNode =
       result = makeClosure(s, i.closureParam, n.info)
     else:
       # captured symbol?
-      result = IdNodeTableGet(i.localsToAccess, n.sym)
-  of nkLambdaKinds:
-    result = transformInnerProc(o, i, n.sons[namePos])
+      result = idNodeTableGet(i.localsToAccess, n.sym)
+  of nkLambdaKinds, nkIteratorDef:
+    if n.typ != nil:
+      result = transformInnerProc(o, i, n.sons[namePos])
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
-     nkIteratorDef:
+      nkClosure:
     # don't recurse here:
-    nil
+    discard
   else:
     for j in countup(0, sonsLen(n) - 1):
       let x = transformInnerProc(o, i, n.sons[j])
@@ -384,7 +472,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
   if n == nil: return
   case n.kind
   of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: 
-    nil
+    discard
   of nkSym:
     if isInnerProc(n.sym, o.fn) and not containsOrIncl(o.processed, n.sym.id):
       var inner = newInnerContext(n.sym)
@@ -398,8 +486,9 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
       if inner.closureParam != nil:
         let ti = transformInnerProc(o, inner, body)
         if ti != nil: n.sym.ast.sons[bodyPos] = ti
-  of nkLambdaKinds:
-    searchForInnerProcs(o, n.sons[namePos])
+  of nkLambdaKinds, nkIteratorDef:
+    if n.typ != nil:
+      searchForInnerProcs(o, n.sons[namePos])
   of nkWhileStmt, nkForStmt, nkParForStmt, nkBlockStmt:
     # some nodes open a new scope, so they are candidates for the insertion
     # of closure creation; however for simplicity we merge closures between
@@ -420,26 +509,26 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
     # counts, not the block where it is captured!
     for i in countup(0, sonsLen(n) - 1):
       var it = n.sons[i]
-      if it.kind == nkCommentStmt: nil
+      if it.kind == nkCommentStmt: discard
       elif it.kind == nkIdentDefs:
         var L = sonsLen(it)
-        if it.sons[0].kind != nkSym: InternalError(it.info, "transformOuter")
+        if it.sons[0].kind != nkSym: internalError(it.info, "transformOuter")
         #echo "set: ", it.sons[0].sym.name.s, " ", o.currentBlock == nil
-        IdTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv)
+        idTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv)
         searchForInnerProcs(o, it.sons[L-1])
       elif it.kind == nkVarTuple:
         var L = sonsLen(it)
         for j in countup(0, L-3):
           #echo "set: ", it.sons[j].sym.name.s, " ", o.currentBlock == nil
-          IdTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv)
+          idTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv)
         searchForInnerProcs(o, it.sons[L-1])
       else:
-        InternalError(it.info, "transformOuter")
+        internalError(it.info, "transformOuter")
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, 
-     nkIteratorDef:
+     nkClosure, nkTypeSection:
     # don't recurse here:
     # XXX recurse here and setup 'up' pointers
-    nil
+    discard
   else:
     for i in countup(0, sonsLen(n) - 1):
       searchForInnerProcs(o, n.sons[i])
@@ -454,26 +543,20 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
   result.sons[0] = le
   result.sons[1] = ri
 
-proc addVar*(father, v: PNode) = 
-  var vpart = newNodeI(nkIdentDefs, v.info)
-  addSon(vpart, v)
-  addSon(vpart, ast.emptyNode)
-  addSon(vpart, ast.emptyNode)
-  addSon(father, vpart)
-
-proc getClosureVar(o: POuterContext, e: PEnv): PSym =
-  if e.closure == nil:
-    result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info)
-    incl(result.flags, sfShadowed)
-    result.typ = newType(tyRef, o.fn)
-    result.typ.rawAddSon(e.tup)
-    e.closure = result
-  else:
-    result = e.closure
+proc newClosureCreationVar(o: POuterContext; e: PEnv): PSym =
+  result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info)
+  incl(result.flags, sfShadowed)
+  result.typ = newType(tyRef, o.fn)
+  result.typ.rawAddSon(e.obj)
 
-proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
-  var env = getClosureVar(o, scope)
+proc getClosureVar(o: POuterContext; e: PEnv): PSym =
+  if e.createdVar == nil:
+    result = newClosureCreationVar(o, e)
+    e.createdVar = result
+  else:
+    result = e.createdVar
 
+proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode =
   result = newNodeI(nkStmtList, env.info)
   var v = newNodeI(nkVarSection, env.info)
   addVar(v, newSymNode(env))
@@ -488,23 +571,130 @@ proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
       # maybe later: (sfByCopy in local.flags)
       # add ``env.param = param``
       result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
-    IdNodeTablePut(o.localsToAccess, local, fieldAccess)
+    # it can happen that we already captured 'local' in some other environment
+    # then we capture by copy for now. This is not entirely correct but better
+    # than nothing:
+    let existing = idNodeTableGet(o.localsToAccess, local)
+    if existing.isNil:
+      idNodeTablePut(o.localsToAccess, local, fieldAccess)
+    else:
+      result.add(newAsgnStmt(fieldAccess, existing, env.info))
   # add support for 'up' references:
   for e, field in items(scope.deps):
     # add ``env.up = env2``
     result.add(newAsgnStmt(indirectAccess(env, field, env.info),
                newSymNode(getClosureVar(o, e)), env.info))
+  
+proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
+  var env = getClosureVar(o, scope)
+  result = rawClosureCreation(o, scope, env)
+
+proc generateIterClosureCreation(o: POuterContext; env: PEnv;
+                                 scope: PNode): PSym =
+  if env.createdVarComesFromIter or env.createdVar.isNil:
+    # we have to create a new closure:
+    result = newClosureCreationVar(o, env)
+    let cc = rawClosureCreation(o, env, result)
+    var insertPoint = scope.sons[0]
+    if insertPoint.kind == nkEmpty: scope.sons[0] = cc
+    else:
+      assert cc.kind == nkStmtList and insertPoint.kind == nkStmtList
+      for x in cc: insertPoint.add(x)
+    if env.createdVar == nil: env.createdVar = result
+  else:
+    result = env.createdVar
+  env.createdVarComesFromIter = true
+
+proc interestingIterVar(s: PSym): bool {.inline.} =
+  result = s.kind in {skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags
+
+proc transformOuterProc(o: POuterContext, n: PNode): PNode
+
+proc transformYield(c: POuterContext, n: PNode): PNode =
+  inc c.state.typ.n.sons[1].intVal
+  let stateNo = c.state.typ.n.sons[1].intVal
+
+  var stateAsgnStmt = newNodeI(nkAsgn, n.info)
+  stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info))
+  stateAsgnStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt)))
+
+  var retStmt = newNodeI(nkReturnStmt, n.info)
+  if n.sons[0].kind != nkEmpty:
+    var a = newNodeI(nkAsgn, n.sons[0].info)
+    var retVal = transformOuterProc(c, n.sons[0])
+    addSon(a, newSymNode(c.resultSym))
+    addSon(a, if retVal.isNil: n.sons[0] else: retVal)
+    retStmt.add(a)
+  else:
+    retStmt.add(emptyNode)
+  
+  var stateLabelStmt = newNodeI(nkState, n.info)
+  stateLabelStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt)))
+  
+  result = newNodeI(nkStmtList, n.info)
+  result.add(stateAsgnStmt)
+  result.add(retStmt)
+  result.add(stateLabelStmt)
+
+proc transformReturn(c: POuterContext, n: PNode): PNode =
+  result = newNodeI(nkStmtList, n.info)
+  var stateAsgnStmt = newNodeI(nkAsgn, n.info)
+  stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info))
+  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
+  result.add(stateAsgnStmt)
+  result.add(n)
+
+proc outerProcSons(o: POuterContext, n: PNode) =
+  for i in countup(0, sonsLen(n) - 1):
+    let x = transformOuterProc(o, n.sons[i])
+    if x != nil: n.sons[i] = x
+
+proc liftIterSym*(n: PNode): PNode =
+  # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env)) 
+  let iter = n.sym
+  assert iter.kind == skClosureIterator
+
+  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
+  
+  var env = copySym(getHiddenParam(iter))
+  env.kind = skLet
+  var v = newNodeI(nkVarSection, n.info)
+  addVar(v, newSymNode(env))
+  result.add(v)
+  # add 'new' statement:
+  result.add(newCall(getSysSym"internalNew", env))
+  result.add makeClosure(iter, env, n.info)
 
 proc transformOuterProc(o: POuterContext, n: PNode): PNode =
   if n == nil: return nil
   case n.kind
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: nil
+  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard
   of nkSym:
     var local = n.sym
-    var closure = PEnv(IdTableGet(o.lambdasToEnv, local))
+
+    if o.isIter and interestingIterVar(local) and o.fn.id == local.owner.id:
+      if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local)
+      return indirectAccess(newSymNode(o.closureParam), local, n.info)
+
+    var closure = PEnv(idTableGet(o.lambdasToEnv, local))
+
+    if local.kind == skClosureIterator:
+      # consider: [i1, i2, i1]  Since we merged the iterator's closure
+      # with the captured owning variables, we need to generate the
+      # closure generation code again:
+      if local == o.fn: message(n.info, errRecursiveDependencyX, local.name.s)
+      # XXX why doesn't this work?
+      if closure.isNil:
+        return liftIterSym(n)
+      else:
+        let createdVar = generateIterClosureCreation(o, closure,
+                                                     closure.attachedNode)
+        return makeClosure(local, createdVar, n.info)
+
     if closure != nil:
-      # we need to replace the lambda with '(lambda, env)': 
-      let a = closure.closure
+      # we need to replace the lambda with '(lambda, env)':
+      
+      let a = closure.createdVar
       if a != nil:
         return makeClosure(local, a, n.info)
       else:
@@ -514,12 +704,12 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
         if scope.sons[0].kind == nkEmpty:
           # change the empty node to contain the closure construction:
           scope.sons[0] = generateClosureCreation(o, closure)
-        let x = closure.closure
+        let x = closure.createdVar
         assert x != nil
         return makeClosure(local, x, n.info)
     
     if not contains(o.capturedVars, local.id): return
-    var env = PEnv(IdTableGet(o.localsToEnv, local))
+    var env = PEnv(idTableGet(o.localsToEnv, local))
     if env == nil: return
     var scope = env.attachedNode
     assert scope.kind == nkStmtList
@@ -529,26 +719,55 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
     
     # change 'local' to 'closure.local', unless it's a 'byCopy' variable:
     # if sfByCopy notin local.flags:
-    result = IdNodeTableGet(o.localsToAccess, local)
+    result = idNodeTableGet(o.localsToAccess, local)
     assert result != nil, "cannot find: " & local.name.s
     # else it is captured by copy and this means that 'outer' should continue
     # to access the local as a local.
-  of nkLambdaKinds:
-    result = transformOuterProc(o, n.sons[namePos])
-  of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, 
-     nkIteratorDef: 
+  of nkLambdaKinds, nkIteratorDef:
+    if n.typ != nil:
+      result = transformOuterProc(o, n.sons[namePos])
+  of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
+      nkClosure:
     # don't recurse here:
-    nil
+    discard
   of nkHiddenStdConv, nkHiddenSubConv, nkConv:
     let x = transformOuterProc(o, n.sons[1])
     if x != nil: n.sons[1] = x
     result = transformOuterConv(n)
+  of nkYieldStmt:
+    if o.isIter: result = transformYield(o, n)
+    else: outerProcSons(o, n)
+  of nkReturnStmt:
+    if o.isIter: result = transformReturn(o, n)
+    else: outerProcSons(o, n)
   else:
-    for i in countup(0, sonsLen(n) - 1):
-      let x = transformOuterProc(o, n.sons[i])
-      if x != nil: n.sons[i] = x
+    outerProcSons(o, n)
+
+proc liftIterator(c: POuterContext, body: PNode): PNode =
+  let iter = c.fn
+  result = newNodeI(nkStmtList, iter.info)
+  var gs = newNodeI(nkGotoState, iter.info)
+  gs.add(indirectAccess(newSymNode(c.closureParam), c.state, iter.info))
+  result.add(gs)
+  var state0 = newNodeI(nkState, iter.info)
+  state0.add(newIntNode(nkIntLit, 0))
+  result.add(state0)
+  
+  let newBody = transformOuterProc(c, body)
+  if newBody != nil:
+    result.add(newBody)
+  else:
+    result.add(body)
+
+  var stateAsgnStmt = newNodeI(nkAsgn, iter.info)
+  stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),
+                    c.state,iter.info))
+  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
+  result.add(stateAsgnStmt)
 
 proc liftLambdas*(fn: PSym, body: PNode): PNode =
+  # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
+  # the transformation even when compiling to JS ...
   if body.kind == nkEmpty or gCmd == cmdCompileToJS:
     # ignore forward declaration:
     result = body
@@ -560,16 +779,19 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
     let params = fn.typ.n
     for i in 1.. <params.len: 
       if params.sons[i].kind != nkSym:
-        InternalError(params.info, "liftLambdas: strange params")
+        internalError(params.info, "liftLambdas: strange params")
       let param = params.sons[i].sym
-      IdTablePut(o.localsToEnv, param, o.currentEnv)
+      idTablePut(o.localsToEnv, param, o.currentEnv)
     # put the 'result' into the environment so it can be captured:
     let ast = fn.ast
     if resultPos < sonsLen(ast) and ast.sons[resultPos].kind == nkSym:
-      IdTablePut(o.localsToEnv, ast.sons[resultPos].sym, o.currentEnv)
+      idTablePut(o.localsToEnv, ast.sons[resultPos].sym, o.currentEnv)
     searchForInnerProcs(o, body)
-    discard transformOuterProc(o, body)
-    result = ex
+    if o.isIter:
+      result = liftIterator(o, ex)
+    else:
+      discard transformOuterProc(o, body)
+      result = ex
 
 proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
   if body.kind == nkEmpty or gCmd == cmdCompileToJS:
@@ -584,147 +806,6 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
 
 # ------------------- iterator transformation --------------------------------
 
-discard """
-  iterator chain[S, T](a, b: *S->T, args: *S): T =
-    for x in a(args): yield x
-    for x in b(args): yield x
-
-  let c = chain(f, g)
-  for x in c: echo x
-  
-  # translated to:
-  let c = chain( (f, newClosure(f)), (g, newClosure(g)), newClosure(chain))
-"""
-
-type
-  TIterContext {.final, pure.} = object
-    iter, closureParam, state, resultSym: PSym
-    capturedVars: TIntSet
-    tup: PType
-
-proc newIterResult(iter: PSym): PSym =
-  result = iter.ast.sons[resultPos].sym
-  when false:
-    result = newSym(skResult, getIdent":result", iter, iter.info)
-    result.typ = iter.typ.sons[0]
-    incl(result.flags, sfUsed)
-
-proc interestingIterVar(s: PSym): bool {.inline.} =
-  result = s.kind in {skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags
-
-proc transfIterBody(c: var TIterContext, n: PNode): PNode =
-  # gather used vars for closure generation
-  if n == nil: return nil
-  case n.kind
-  of nkSym:
-    var s = n.sym
-    if interestingIterVar(s) and c.iter.id == s.owner.id:
-      if not containsOrIncl(c.capturedVars, s.id): addField(c.tup, s)
-      result = indirectAccess(newSymNode(c.closureParam), s, n.info)
-  of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: nil
-  of nkYieldStmt:
-    inc c.state.typ.n.sons[1].intVal
-    let stateNo = c.state.typ.n.sons[1].intVal
-
-    var stateAsgnStmt = newNodeI(nkAsgn, n.info)
-    stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info))
-    stateAsgnStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt)))
-
-    var retStmt = newNodeI(nkReturnStmt, n.info)
-    if n.sons[0].kind != nkEmpty:
-      var a = newNodeI(nkAsgn, n.sons[0].info)
-      var retVal = transfIterBody(c, n.sons[0])
-      addSon(a, newSymNode(c.resultSym))
-      addSon(a, if retVal.isNil: n.sons[0] else: retVal)
-      retStmt.add(a)
-    else:
-      retStmt.add(emptyNode)
-    
-    var stateLabelStmt = newNodeI(nkState, n.info)
-    stateLabelStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt)))
-    
-    result = newNodeI(nkStmtList, n.info)
-    result.add(stateAsgnStmt)
-    result.add(retStmt)
-    result.add(stateLabelStmt)
-  of nkReturnStmt:
-    result = newNodeI(nkStmtList, n.info)
-    var stateAsgnStmt = newNodeI(nkAsgn, n.info)
-    stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info))
-    stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
-    result.add(stateAsgnStmt)
-    result.add(n)
-  else:
-    for i in countup(0, sonsLen(n)-1):
-      let x = transfIterBody(c, n.sons[i])
-      if x != nil: n.sons[i] = x
-
-proc getStateType(iter: PSym): PType =
-  var n = newNodeI(nkRange, iter.info)
-  addSon(n, newIntNode(nkIntLit, -1))
-  addSon(n, newIntNode(nkIntLit, 0))
-  result = newType(tyRange, iter)
-  result.n = n
-  rawAddSon(result, getSysType(tyInt))
-
-proc liftIterator*(iter: PSym, body: PNode): PNode =
-  var c: TIterContext
-  c.iter = iter
-  c.capturedVars = initIntSet()
-
-  c.tup = newType(tyTuple, iter)
-  c.tup.n = newNodeI(nkRecList, iter.info)
-
-  var cp = newSym(skParam, getIdent(paramname), iter, iter.info)
-  incl(cp.flags, sfFromGeneric)
-  cp.typ = newType(tyRef, iter)
-  rawAddSon(cp.typ, c.tup)
-  c.closureParam = cp
-  addHiddenParam(iter, cp)
-
-  c.state = newSym(skField, getIdent(":state"), iter, iter.info)
-  c.state.typ = getStateType(iter)
-  addField(c.tup, c.state)
-
-  if iter.typ.sons[0] != nil:
-    c.resultSym = newIterResult(iter)
-    iter.ast.add(newSymNode(c.resultSym))
-
-  result = newNodeI(nkStmtList, iter.info)
-  var gs = newNodeI(nkGotoState, iter.info)
-  gs.add(indirectAccess(newSymNode(c.closureParam), c.state, iter.info))
-  result.add(gs)
-  var state0 = newNodeI(nkState, iter.info)
-  state0.add(newIntNode(nkIntLit, 0))
-  result.add(state0)
-  
-  let newBody = transfIterBody(c, body)
-  if newBody != nil:
-    result.add(newBody)
-  else:
-    result.add(body)
-
-  var stateAsgnStmt = newNodeI(nkAsgn, iter.info)
-  stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),
-                    c.state,iter.info))
-  stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
-  result.add(stateAsgnStmt)
-
-proc liftIterSym*(n: PNode): PNode =
-  # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env)) 
-  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
-  let iter = n.sym
-  assert iter.kind == skIterator
-  var env = copySym(getHiddenParam(iter))
-  env.kind = skLet
-
-  var v = newNodeI(nkVarSection, n.info)
-  addVar(v, newSymNode(env))
-  result.add(v)
-  # add 'new' statement:
-  result.add(newCall(getSysSym"internalNew", env))
-  result.add makeClosure(iter, env, n.info)
-
 proc liftForLoop*(body: PNode): PNode =
   # problem ahead: the iterator could be invoked indirectly, but then
   # we don't know what environment to create here: 
@@ -754,17 +835,17 @@ proc liftForLoop*(body: PNode): PNode =
         ...
     """
   var L = body.len
-  InternalAssert body.kind == nkForStmt and body[L-2].kind in nkCallKinds
+  internalAssert body.kind == nkForStmt and body[L-2].kind in nkCallKinds
   var call = body[L-2]
 
   result = newNodeI(nkStmtList, body.info)
   
   # static binding?
   var env: PSym
-  if call[0].kind == nkSym and call[0].sym.kind == skIterator:
-    # createClose()
+  if call[0].kind == nkSym and call[0].sym.kind == skClosureIterator:
+    # createClosure()
     let iter = call[0].sym
-    assert iter.kind == skIterator
+    assert iter.kind == skClosureIterator
     env = copySym(getHiddenParam(iter))
 
     var v = newNodeI(nkVarSection, body.info)
@@ -789,7 +870,7 @@ proc liftForLoop*(body: PNode): PNode =
     addSon(vpart, body[i])
 
   addSon(vpart, ast.emptyNode) # no explicit type
-  if not env.isnil:
+  if not env.isNil:
     call.sons[0] = makeClosure(call.sons[0].sym, env, body.info)
   addSon(vpart, call)
   addSon(v2, vpart)
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 82bfa0ad4..217e33675 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -41,11 +41,12 @@ type
     tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkInterface, 
     tkIs, tkIsnot, tkIterator,
     tkLambda, tkLet,
-    tkMacro, tkMethod, tkMixin, tkUsing, tkMod, tkNil, tkNot, tkNotin, 
+    tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin, 
     tkObject, tkOf, tkOr, tkOut, 
     tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShared, tkShl, tkShr, tkStatic,
     tkTemplate, 
-    tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
+    tkTry, tkTuple, tkType, tkUsing, 
+    tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
     tkYield, # end of keywords
     tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit,
     tkUIntLit, tkUInt8Lit, tkUInt16Lit, tkUInt32Lit, tkUInt64Lit,
@@ -75,12 +76,13 @@ const
     "finally", "for", "from", "generic", "if", 
     "import", "in", "include", "interface", "is", "isnot", "iterator",
     "lambda", "let", 
-    "macro", "method", "mixin", "using", "mod", 
+    "macro", "method", "mixin", "mod", 
     "nil", "not", "notin", "object", "of", "or", 
     "out", "proc", "ptr", "raise", "ref", "return", 
     "shared", "shl", "shr", "static",
     "template", 
-    "try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
+    "try", "tuple", "type", "using",
+    "var", "when", "while", "with", "without", "xor",
     "yield",
     "tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
     "tkUIntLit", "tkUInt8Lit", "tkUInt16Lit", "tkUInt32Lit", "tkUInt64Lit",
@@ -99,6 +101,7 @@ type
     base10,                   # base10 is listed as the first element,
                               # so that it is the correct default value
     base2, base8, base16
+
   TToken* = object            # a Nimrod token
     tokType*: TTokType        # the type of the token
     indent*: int              # the indentation; != -1 if the token has been
@@ -108,6 +111,8 @@ type
     fNumber*: BiggestFloat    # the parsed floating point literal
     base*: TNumericalBase     # the numerical base; only valid for int
                               # or float literals
+    strongSpaceA*: int8       # leading spaces of an operator
+    strongSpaceB*: int8       # trailing spaces of an operator
     literal*: string          # the parsed (string) literal; and
                               # documentation comments are here too
     line*, col*: int
@@ -117,7 +122,9 @@ type
     indentAhead*: int         # if > 0 an indendation has already been read
                               # this is needed because scanning comments
                               # needs so much look-ahead
-  
+    currLineIndent*: int
+    strongSpaces*: bool
+
 
 var gLinesCompiled*: int  # all lines that have been compiled
 
@@ -130,11 +137,11 @@ proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
   newLineInfo(L.fileIdx, tok.line, tok.col)
 
 proc closeLexer*(lex: var TLexer)
-proc PrintTok*(tok: TToken)
+proc printTok*(tok: TToken)
 proc tokToStr*(tok: TToken): string
 
 proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) =
-  OpenLexer(lex, filename.fileInfoIdx, inputStream)
+  openLexer(lex, filename.fileInfoIdx, inputstream)
 
 proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "")
 
@@ -158,19 +165,20 @@ proc tokToStr*(tok: TToken): string =
   of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
   of tkInvalid, tkStrLit..tkCharLit, tkComment: result = tok.literal
   of tkParLe..tkColon, tkEof, tkAccent: 
-    result = tokTypeToStr[tok.tokType]
+    result = TokTypeToStr[tok.tokType]
   else:
     if tok.ident != nil:
       result = tok.ident.s
     else: 
-      InternalError("tokToStr")
+      internalError("tokToStr")
       result = ""
   
 proc prettyTok*(tok: TToken): string =
-  if IsKeyword(tok.tokType): result = "keyword " & tok.ident.s
+  if isKeyword(tok.tokType): result = "keyword " & tok.ident.s
   else: result = tokToStr(tok)
   
-proc PrintTok*(tok: TToken) = 
+proc printTok*(tok: TToken) = 
+  write(stdout, tok.line, ":", tok.col, "\t")
   write(stdout, TokTypeToStr[tok.tokType])
   write(stdout, " ")
   writeln(stdout, tokToStr(tok))
@@ -178,18 +186,20 @@ proc PrintTok*(tok: TToken) =
 var dummyIdent: PIdent
 
 proc initToken*(L: var TToken) = 
-  L.TokType = tkInvalid
+  L.tokType = tkInvalid
   L.iNumber = 0
-  L.Indent = 0
+  L.indent = 0
+  L.strongSpaceA = 0
   L.literal = ""
   L.fNumber = 0.0
   L.base = base10
   L.ident = dummyIdent
 
 proc fillToken(L: var TToken) = 
-  L.TokType = tkInvalid
+  L.tokType = tkInvalid
   L.iNumber = 0
-  L.Indent = 0
+  L.indent = 0
+  L.strongSpaceA = 0
   setLen(L.literal, 0)
   L.fNumber = 0.0
   L.base = base10
@@ -197,26 +207,27 @@ proc fillToken(L: var TToken) =
   
 proc openLexer(lex: var TLexer, fileIdx: int32, inputstream: PLLStream) = 
   openBaseLexer(lex, inputstream)
-  lex.fileIdx = fileIdx
+  lex.fileIdx = fileidx
   lex.indentAhead = - 1
-  inc(lex.Linenumber, inputstream.lineOffset) 
+  lex.currLineIndent = 0
+  inc(lex.lineNumber, inputstream.lineOffset) 
 
 proc closeLexer(lex: var TLexer) = 
-  inc(gLinesCompiled, lex.LineNumber)
+  inc(gLinesCompiled, lex.lineNumber)
   closeBaseLexer(lex)
 
 proc getColumn(L: TLexer): int = 
-  result = getColNumber(L, L.bufPos)
+  result = getColNumber(L, L.bufpos)
 
 proc getLineInfo(L: TLexer): TLineInfo = 
-  result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos))
+  result = newLineInfo(L.fileIdx, L.lineNumber, getColNumber(L, L.bufpos))
 
 proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = 
-  msgs.Message(getLineInfo(L), msg, arg)
+  msgs.message(getLineInfo(L), msg, arg)
 
 proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = 
-  var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart)
-  msgs.Message(info, msg, 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) = 
   var pos = L.bufpos              # use registers for pos, buf
@@ -224,7 +235,7 @@ proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
   while true: 
     if buf[pos] in chars: 
       add(tok.literal, buf[pos])
-      Inc(pos)
+      inc(pos)
     else: 
       break 
     if buf[pos] == '_': 
@@ -232,11 +243,11 @@ proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
         lexMessage(L, errInvalidToken, "_")
         break
       add(tok.literal, '_')
-      Inc(pos)
-  L.bufPos = pos
+      inc(pos)
+  L.bufpos = pos
 
-proc matchTwoChars(L: TLexer, first: Char, second: TCharSet): bool = 
-  result = (L.buf[L.bufpos] == first) and (L.buf[L.bufpos + 1] in Second)
+proc matchTwoChars(L: TLexer, first: char, second: TCharSet): bool = 
+  result = (L.buf[L.bufpos] == first) and (L.buf[L.bufpos + 1] in second)
 
 proc isFloatLiteral(s: string): bool =
   for i in countup(0, len(s) - 1):
@@ -244,10 +255,10 @@ proc isFloatLiteral(s: string): bool =
       return true
   result = false
 
-proc GetNumber(L: var TLexer): TToken = 
+proc getNumber(L: var TLexer): TToken = 
   var 
     pos, endpos: int
-    xi: biggestInt
+    xi: BiggestInt
   # get the base:
   result.tokType = tkIntLit   # int literal until we know better
   result.literal = ""
@@ -388,25 +399,25 @@ proc GetNumber(L: var TLexer): TToken =
             xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10)
             inc(pos)
           else: break 
-      else: InternalError(getLineInfo(L), "getNumber")
+      else: internalError(getLineInfo(L), "getNumber")
       case result.tokType
       of tkIntLit, tkInt64Lit: result.iNumber = xi
-      of tkInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
-      of tkInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
-      of tkInt32Lit: result.iNumber = biggestInt(toU32(xi))
+      of tkInt8Lit: result.iNumber = BiggestInt(int8(toU8(int(xi))))
+      of tkInt16Lit: result.iNumber = BiggestInt(toU16(int(xi)))
+      of tkInt32Lit: result.iNumber = BiggestInt(toU32(xi))
       of tkUIntLit, tkUInt64Lit: result.iNumber = xi
-      of tkUInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
-      of tkUInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
-      of tkUInt32Lit: result.iNumber = biggestInt(toU32(xi))
+      of tkUInt8Lit: result.iNumber = BiggestInt(int8(toU8(int(xi))))
+      of tkUInt16Lit: result.iNumber = BiggestInt(toU16(int(xi)))
+      of tkUInt32Lit: result.iNumber = BiggestInt(toU32(xi))
       of tkFloat32Lit: 
         result.fNumber = (cast[PFloat32](addr(xi)))[] 
         # note: this code is endian neutral!
         # XXX: Test this on big endian machine!
       of tkFloat64Lit: result.fNumber = (cast[PFloat64](addr(xi)))[] 
-      else: InternalError(getLineInfo(L), "getNumber")
+      else: internalError(getLineInfo(L), "getNumber")
     elif isFloatLiteral(result.literal) or (result.tokType == tkFloat32Lit) or
         (result.tokType == tkFloat64Lit): 
-      result.fnumber = parseFloat(result.literal)
+      result.fNumber = parseFloat(result.literal)
       if result.tokType == tkIntLit: result.tokType = tkFloatLit
     else:
       result.iNumber = parseBiggestInt(result.literal)
@@ -432,7 +443,7 @@ proc handleHexChar(L: var TLexer, xi: var int) =
   of 'A'..'F': 
     xi = (xi shl 4) or (ord(L.buf[L.bufpos]) - ord('A') + 10)
     inc(L.bufpos)
-  else: nil
+  else: discard
 
 proc handleDecChars(L: var TLexer, xi: var int) = 
   while L.buf[L.bufpos] in {'0'..'9'}: 
@@ -443,51 +454,51 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
   inc(L.bufpos)               # skip '\'
   case L.buf[L.bufpos]
   of 'n', 'N': 
-    if tok.toktype == tkCharLit: lexMessage(L, errNnotAllowedInCharacter)
+    if tok.tokType == tkCharLit: lexMessage(L, errNnotAllowedInCharacter)
     add(tok.literal, tnl)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 'r', 'R', 'c', 'C': 
     add(tok.literal, CR)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 'l', 'L': 
     add(tok.literal, LF)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 'f', 'F': 
     add(tok.literal, FF)
     inc(L.bufpos)
   of 'e', 'E': 
     add(tok.literal, ESC)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 'a', 'A': 
     add(tok.literal, BEL)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 'b', 'B': 
     add(tok.literal, BACKSPACE)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 'v', 'V': 
     add(tok.literal, VT)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 't', 'T': 
     add(tok.literal, Tabulator)
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of '\'', '\"': 
     add(tok.literal, L.buf[L.bufpos])
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of '\\': 
     add(tok.literal, '\\')
-    Inc(L.bufpos)
+    inc(L.bufpos)
   of 'x', 'X': 
     inc(L.bufpos)
     var xi = 0
     handleHexChar(L, xi)
     handleHexChar(L, xi)
-    add(tok.literal, Chr(xi))
+    add(tok.literal, chr(xi))
   of '0'..'9': 
     if matchTwoChars(L, '0', {'0'..'9'}): 
       lexMessage(L, warnOctalEscape)
     var xi = 0
     handleDecChars(L, xi)
-    if (xi <= 255): add(tok.literal, Chr(xi))
+    if (xi <= 255): add(tok.literal, chr(xi))
     else: lexMessage(L, errInvalidCharacterConstant)
   else: lexMessage(L, errInvalidCharacterConstant)
 
@@ -497,7 +508,7 @@ proc newString(s: cstring, len: int): string =
   for i in 0 .. <len:
     result[i] = s[i]
 
-proc HandleCRLF(L: var TLexer, pos: int): int =
+proc handleCRLF(L: var TLexer, pos: int): int =
   template registerLine =
     let col = L.getColNumber(pos)
     
@@ -512,21 +523,21 @@ proc HandleCRLF(L: var TLexer, pos: int): int =
   case L.buf[pos]
   of CR:
     registerLine()
-    result = nimlexbase.HandleCR(L, pos)
+    result = nimlexbase.handleCR(L, pos)
   of LF:
     registerLine()
-    result = nimlexbase.HandleLF(L, pos)
+    result = nimlexbase.handleLF(L, pos)
   else: result = pos
   
 proc getString(L: var TLexer, tok: var TToken, rawMode: bool) = 
-  var pos = L.bufPos + 1          # skip "
+  var pos = L.bufpos + 1          # skip "
   var buf = L.buf                 # put `buf` in a register
-  var line = L.linenumber         # save linenumber for better error message
+  var line = L.lineNumber         # save linenumber for better error message
   if buf[pos] == '\"' and buf[pos+1] == '\"': 
     tok.tokType = tkTripleStrLit # long string literal:
     inc(pos, 2)               # skip ""
     # skip leading newline:
-    pos = HandleCRLF(L, pos)
+    pos = handleCRLF(L, pos)
     buf = L.buf
     while true: 
       case buf[pos]
@@ -536,20 +547,20 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
           L.bufpos = pos + 3 # skip the three """
           break 
         add(tok.literal, '\"')
-        Inc(pos)
+        inc(pos)
       of CR, LF: 
-        pos = HandleCRLF(L, pos)
+        pos = handleCRLF(L, pos)
         buf = L.buf
         add(tok.literal, tnl)
       of nimlexbase.EndOfFile: 
-        var line2 = L.linenumber
-        L.LineNumber = line
+        var line2 = L.lineNumber
+        L.lineNumber = line
         lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart)
-        L.LineNumber = line2
+        L.lineNumber = line2
         break 
       else: 
         add(tok.literal, buf[pos])
-        Inc(pos)
+        inc(pos)
   else: 
     # ordinary string literal
     if rawMode: tok.tokType = tkRStrLit
@@ -567,23 +578,23 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
         lexMessage(L, errClosingQuoteExpected)
         break 
       elif (c == '\\') and not rawMode: 
-        L.bufPos = pos
+        L.bufpos = pos
         getEscapedChar(L, tok)
-        pos = L.bufPos
+        pos = L.bufpos
       else: 
         add(tok.literal, c)
-        Inc(pos)
+        inc(pos)
     L.bufpos = pos
 
 proc getCharacter(L: var TLexer, tok: var TToken) = 
-  Inc(L.bufpos)               # skip '
+  inc(L.bufpos)               # skip '
   var c = L.buf[L.bufpos]
   case c
-  of '\0'..Pred(' '), '\'': lexMessage(L, errInvalidCharacterConstant)
+  of '\0'..pred(' '), '\'': lexMessage(L, errInvalidCharacterConstant)
   of '\\': getEscapedChar(L, tok)
   else: 
     tok.literal = $c
-    Inc(L.bufpos)
+    inc(L.bufpos)
   if L.buf[L.bufpos] != '\'': lexMessage(L, errMissingFinalQuote)
   inc(L.bufpos)               # skip '
   
@@ -604,7 +615,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
         lexMessage(L, errInvalidToken, "_")
         break
     else: break 
-    Inc(pos)
+    inc(pos)
   h = !$h
   tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
   L.bufpos = pos
@@ -629,9 +640,17 @@ proc getOperator(L: var TLexer, tok: var TToken) =
   while true: 
     var c = buf[pos]
     if c notin OpChars: break
-    h = h !& Ord(c)
-    Inc(pos)
+    h = h !& ord(c)
+    inc(pos)
   endOperator(L, tok, pos, h)
+  # advance pos but don't store it in L.bufpos so the next token (which might
+  # be an operator too) gets the preceeding spaces:
+  tok.strongSpaceB = 0
+  while buf[pos] == ' ':
+    inc pos
+    inc tok.strongSpaceB
+  if buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
+    tok.strongSpaceB = -1
 
 proc scanComment(L: var TLexer, tok: var TToken) = 
   var pos = L.bufpos
@@ -675,22 +694,26 @@ proc scanComment(L: var TLexer, tok: var TToken) =
 proc skip(L: var TLexer, tok: var TToken) =
   var pos = L.bufpos
   var buf = L.buf
+  tok.strongSpaceA = 0
   while true:
     case buf[pos]
     of ' ':
-      Inc(pos)
+      inc(pos)
+      inc(tok.strongSpaceA)
     of Tabulator:
       lexMessagePos(L, errTabulatorsAreNotAllowed, pos)
       inc(pos)
     of CR, LF:
-      pos = HandleCRLF(L, pos)
+      pos = handleCRLF(L, pos)
       buf = L.buf
       var indent = 0
       while buf[pos] == ' ':
-        Inc(pos)
-        Inc(indent)
+        inc(pos)
+        inc(indent)
+      tok.strongSpaceA = 0
       if buf[pos] > ' ':
         tok.indent = indent
+        L.currLineIndent = indent
         break
     else:
       break                   # EndOfFile also leaves the loop
@@ -700,12 +723,13 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
   fillToken(tok)
   if L.indentAhead >= 0:
     tok.indent = L.indentAhead
+    L.currLineIndent = L.indentAhead
     L.indentAhead = -1
   else:
     tok.indent = -1
   skip(L, tok)
   var c = L.buf[L.bufpos]
-  tok.line = L.linenumber
+  tok.line = L.lineNumber
   tok.col = getColNumber(L, L.bufpos)
   if c in SymStartChars - {'r', 'R', 'l'}:
     getSymbol(L, tok)
@@ -722,8 +746,8 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
       else:
         getOperator(L, tok)
     of ',':
-      tok.toktype = tkComma
-      Inc(L.bufpos)
+      tok.tokType = tkComma
+      inc(L.bufpos)
     of 'l': 
       # if we parsed exactly one character and its a small L (l), this
       # is treated as a warning because it may be confused with the number 1
@@ -731,59 +755,59 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
         lexMessage(L, warnSmallLshouldNotBeUsed)
       getSymbol(L, tok)
     of 'r', 'R':
-      if L.buf[L.bufPos + 1] == '\"': 
-        Inc(L.bufPos)
+      if L.buf[L.bufpos + 1] == '\"': 
+        inc(L.bufpos)
         getString(L, tok, true)
       else: 
         getSymbol(L, tok)
     of '(': 
-      Inc(L.bufpos)
-      if L.buf[L.bufPos] == '.' and L.buf[L.bufPos+1] != '.': 
-        tok.toktype = tkParDotLe
-        Inc(L.bufpos)
+      inc(L.bufpos)
+      if L.buf[L.bufpos] == '.' and L.buf[L.bufpos+1] != '.': 
+        tok.tokType = tkParDotLe
+        inc(L.bufpos)
       else: 
-        tok.toktype = tkParLe
+        tok.tokType = tkParLe
     of ')': 
-      tok.toktype = tkParRi
-      Inc(L.bufpos)
+      tok.tokType = tkParRi
+      inc(L.bufpos)
     of '[': 
-      Inc(L.bufpos)
-      if L.buf[L.bufPos] == '.' and L.buf[L.bufPos+1] != '.':
-        tok.toktype = tkBracketDotLe
-        Inc(L.bufpos)
+      inc(L.bufpos)
+      if L.buf[L.bufpos] == '.' and L.buf[L.bufpos+1] != '.':
+        tok.tokType = tkBracketDotLe
+        inc(L.bufpos)
       else:
-        tok.toktype = tkBracketLe
+        tok.tokType = tkBracketLe
     of ']':
-      tok.toktype = tkBracketRi
-      Inc(L.bufpos)
+      tok.tokType = tkBracketRi
+      inc(L.bufpos)
     of '.':
-      if L.buf[L.bufPos+1] == ']': 
+      if L.buf[L.bufpos+1] == ']': 
         tok.tokType = tkBracketDotRi
-        Inc(L.bufpos, 2)
-      elif L.buf[L.bufPos+1] == '}': 
+        inc(L.bufpos, 2)
+      elif L.buf[L.bufpos+1] == '}': 
         tok.tokType = tkCurlyDotRi
-        Inc(L.bufpos, 2)
-      elif L.buf[L.bufPos+1] == ')': 
+        inc(L.bufpos, 2)
+      elif L.buf[L.bufpos+1] == ')': 
         tok.tokType = tkParDotRi
-        Inc(L.bufpos, 2)
+        inc(L.bufpos, 2)
       else: 
         getOperator(L, tok)
     of '{': 
-      Inc(L.bufpos)
-      if L.buf[L.bufPos] == '.' and L.buf[L.bufPos+1] != '.':
-        tok.toktype = tkCurlyDotLe
-        Inc(L.bufpos)
+      inc(L.bufpos)
+      if L.buf[L.bufpos] == '.' and L.buf[L.bufpos+1] != '.':
+        tok.tokType = tkCurlyDotLe
+        inc(L.bufpos)
       else: 
-        tok.toktype = tkCurlyLe
+        tok.tokType = tkCurlyLe
     of '}': 
-      tok.toktype = tkCurlyRi
-      Inc(L.bufpos)
+      tok.tokType = tkCurlyRi
+      inc(L.bufpos)
     of ';': 
-      tok.toktype = tkSemiColon
-      Inc(L.bufpos)
+      tok.tokType = tkSemiColon
+      inc(L.bufpos)
     of '`': 
       tok.tokType = tkAccent
-      Inc(L.bufpos)
+      inc(L.bufpos)
     of '\"': 
       # check for extended raw string literal:
       var rawMode = L.bufpos > 0 and L.buf[L.bufpos-1] in SymChars
@@ -802,12 +826,12 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
       if c in OpChars: 
         getOperator(L, tok)
       elif c == nimlexbase.EndOfFile:
-        tok.toktype = tkEof
+        tok.tokType = tkEof
         tok.indent = 0
       else:
         tok.literal = $c
         tok.tokType = tkInvalid
         lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
-        Inc(L.bufpos)
-  
+        inc(L.bufpos)
+
 dummyIdent = getIdent("")
diff --git a/compiler/lists.nim b/compiler/lists.nim
index 22b1a183a..dd4f5d6be 100644
--- a/compiler/lists.nim
+++ b/compiler/lists.nim
@@ -20,17 +20,17 @@ type
   PStrEntry* = ref TStrEntry
   TLinkedList* = object       # for the "find" operation:
     head*, tail*: PListEntry
-    Counter*: int
+    counter*: int
 
-  TCompareProc* = proc (entry: PListEntry, closure: Pointer): bool {.nimcall.}
+  TCompareProc* = proc (entry: PListEntry, closure: pointer): bool {.nimcall.}
 
-proc InitLinkedList*(list: var TLinkedList) = 
-  list.Counter = 0
+proc initLinkedList*(list: var TLinkedList) = 
+  list.counter = 0
   list.head = nil
   list.tail = nil
 
-proc Append*(list: var TLinkedList, entry: PListEntry) = 
-  Inc(list.counter)
+proc append*(list: var TLinkedList, entry: PListEntry) = 
+  inc(list.counter)
   entry.next = nil
   entry.prev = list.tail
   if list.tail != nil: 
@@ -39,7 +39,7 @@ proc Append*(list: var TLinkedList, entry: PListEntry) =
   list.tail = entry
   if list.head == nil: list.head = entry
   
-proc Contains*(list: TLinkedList, data: string): bool = 
+proc contains*(list: TLinkedList, data: string): bool = 
   var it = list.head
   while it != nil: 
     if PStrEntry(it).data == data: 
@@ -50,15 +50,15 @@ proc newStrEntry(data: string): PStrEntry =
   new(result)
   result.data = data
 
-proc AppendStr*(list: var TLinkedList, data: string) = 
+proc appendStr*(list: var TLinkedList, data: string) = 
   append(list, newStrEntry(data))
 
-proc IncludeStr*(list: var TLinkedList, data: string): bool = 
-  if Contains(list, data): return true
-  AppendStr(list, data)       # else: add to list
+proc includeStr*(list: var TLinkedList, data: string): bool = 
+  if contains(list, data): return true
+  appendStr(list, data)       # else: add to list
 
-proc Prepend*(list: var TLinkedList, entry: PListEntry) = 
-  Inc(list.counter)
+proc prepend*(list: var TLinkedList, entry: PListEntry) = 
+  inc(list.counter)
   entry.prev = nil
   entry.next = list.head
   if list.head != nil: 
@@ -67,22 +67,22 @@ proc Prepend*(list: var TLinkedList, entry: PListEntry) =
   list.head = entry
   if list.tail == nil: list.tail = entry
 
-proc PrependStr*(list: var TLinkedList, data: string) = 
+proc prependStr*(list: var TLinkedList, data: string) = 
   prepend(list, newStrEntry(data))
 
-proc InsertBefore*(list: var TLinkedList, pos, entry: PListEntry) = 
+proc insertBefore*(list: var TLinkedList, pos, entry: PListEntry) = 
   assert(pos != nil)
   if pos == list.head: 
     prepend(list, entry)
   else: 
-    Inc(list.counter)
+    inc(list.counter)
     entry.next = pos
     entry.prev = pos.prev
     if pos.prev != nil: pos.prev.next = entry
     pos.prev = entry
  
-proc Remove*(list: var TLinkedList, entry: PListEntry) = 
-  Dec(list.counter)
+proc remove*(list: var TLinkedList, entry: PListEntry) = 
+  dec(list.counter)
   if entry == list.tail: 
     list.tail = entry.prev
   if entry == list.head: 
@@ -103,14 +103,14 @@ proc bringToFront*(list: var TLinkedList, entry: PListEntry) =
     entry.next = list.head
     list.head = entry
 
-proc ExcludeStr*(list: var TLinkedList, data: string) =
+proc excludeStr*(list: var TLinkedList, data: string) =
   var it = list.head
   while it != nil:
     let nxt = it.next
     if PStrEntry(it).data == data: remove(list, it)
     it = nxt
 
-proc Find*(list: TLinkedList, fn: TCompareProc, closure: Pointer): PListEntry = 
+proc find*(list: TLinkedList, fn: TCompareProc, closure: pointer): PListEntry = 
   result = list.head
   while result != nil:
     if fn(result, closure): return 
diff --git a/compiler/llstream.nim b/compiler/llstream.nim
index 8ccf24b99..510880ffd 100644
--- a/compiler/llstream.nim
+++ b/compiler/llstream.nim
@@ -23,63 +23,63 @@ type
     llsStdIn                  # stream encapsulates stdin
   TLLStream* = object of TObject
     kind*: TLLStreamKind # accessible for low-level access (lexbase uses this)
-    f*: tfile
+    f*: TFile
     s*: string
     rd*, wr*: int             # for string streams
     lineOffset*: int          # for fake stdin line numbers
   
   PLLStream* = ref TLLStream
 
-proc LLStreamOpen*(data: string): PLLStream
-proc LLStreamOpen*(f: var tfile): PLLStream
-proc LLStreamOpen*(filename: string, mode: TFileMode): PLLStream
-proc LLStreamOpen*(): PLLStream
-proc LLStreamOpenStdIn*(): PLLStream
-proc LLStreamClose*(s: PLLStream)
-proc LLStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int
-proc LLStreamReadLine*(s: PLLStream, line: var string): bool
-proc LLStreamReadAll*(s: PLLStream): string
-proc LLStreamWrite*(s: PLLStream, data: string)
-proc LLStreamWrite*(s: PLLStream, data: Char)
-proc LLStreamWrite*(s: PLLStream, buf: pointer, buflen: int)
-proc LLStreamWriteln*(s: PLLStream, data: string)
+proc llStreamOpen*(data: string): PLLStream
+proc llStreamOpen*(f: var TFile): PLLStream
+proc llStreamOpen*(filename: string, mode: TFileMode): PLLStream
+proc llStreamOpen*(): PLLStream
+proc llStreamOpenStdIn*(): PLLStream
+proc llStreamClose*(s: PLLStream)
+proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int
+proc llStreamReadLine*(s: PLLStream, line: var string): bool
+proc llStreamReadAll*(s: PLLStream): string
+proc llStreamWrite*(s: PLLStream, data: string)
+proc llStreamWrite*(s: PLLStream, data: char)
+proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int)
+proc llStreamWriteln*(s: PLLStream, data: string)
 # implementation
 
-proc LLStreamOpen(data: string): PLLStream = 
+proc llStreamOpen(data: string): PLLStream = 
   new(result)
   result.s = data
   result.kind = llsString
 
-proc LLStreamOpen(f: var tfile): PLLStream = 
+proc llStreamOpen(f: var TFile): PLLStream = 
   new(result)
   result.f = f
   result.kind = llsFile
 
-proc LLStreamOpen(filename: string, mode: TFileMode): PLLStream = 
+proc llStreamOpen(filename: string, mode: TFileMode): PLLStream = 
   new(result)
   result.kind = llsFile
   if not open(result.f, filename, mode): result = nil
   
-proc LLStreamOpen(): PLLStream = 
+proc llStreamOpen(): PLLStream = 
   new(result)
   result.kind = llsNone
 
-proc LLStreamOpenStdIn(): PLLStream = 
+proc llStreamOpenStdIn(): PLLStream = 
   new(result)
   result.kind = llsStdIn
   result.s = ""
   result.lineOffset = -1
 
-proc LLStreamClose(s: PLLStream) = 
+proc llStreamClose(s: PLLStream) = 
   case s.kind
   of llsNone, llsString, llsStdIn: 
-    nil
+    discard
   of llsFile: 
     close(s.f)
 
-when not defined(ReadLineFromStdin): 
+when not defined(readLineFromStdin): 
   # fallback implementation:
-  proc ReadLineFromStdin(prompt: string, line: var string): bool =
+  proc readLineFromStdin(prompt: string, line: var string): bool =
     stdout.write(prompt)
     result = readLine(stdin, line)
 
@@ -99,7 +99,7 @@ proc endsWithOpr*(x: string): bool =
   result = x.endsWith(LineContinuationOprs)
 
 proc continueLine(line: string, inTripleString: bool): bool {.inline.} =
-  result = inTriplestring or
+  result = inTripleString or
       line[0] == ' ' or
       line.endsWith(LineContinuationOprs+AdditionalLineContinuationOprs)
 
@@ -111,12 +111,12 @@ proc countTriples(s: string): int =
       inc i, 2
     inc i
 
-proc LLreadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
+proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
   s.s = ""
   s.rd = 0
   var line = newStringOfCap(120)
   var triples = 0
-  while ReadLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line): 
+  while readLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line): 
     add(s.s, line)
     add(s.s, "\n")
     inc triples, countTriples(line)
@@ -127,7 +127,7 @@ proc LLreadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
     copyMem(buf, addr(s.s[s.rd]), result)
     inc(s.rd, result)
 
-proc LLStreamRead(s: PLLStream, buf: pointer, bufLen: int): int = 
+proc llStreamRead(s: PLLStream, buf: pointer, bufLen: int): int = 
   case s.kind
   of llsNone: 
     result = 0
@@ -139,9 +139,9 @@ proc LLStreamRead(s: PLLStream, buf: pointer, bufLen: int): int =
   of llsFile: 
     result = readBuffer(s.f, buf, bufLen)
   of llsStdIn: 
-    result = LLreadFromStdin(s, buf, bufLen)
+    result = llReadFromStdin(s, buf, bufLen)
   
-proc LLStreamReadLine(s: PLLStream, line: var string): bool =
+proc llStreamReadLine(s: PLLStream, line: var string): bool =
   setLen(line, 0)
   case s.kind
   of llsNone:
@@ -165,25 +165,25 @@ proc LLStreamReadLine(s: PLLStream, line: var string): bool =
   of llsStdIn:
     result = readLine(stdin, line)
     
-proc LLStreamWrite(s: PLLStream, data: string) = 
+proc llStreamWrite(s: PLLStream, data: string) = 
   case s.kind
   of llsNone, llsStdIn: 
-    nil
+    discard
   of llsString: 
     add(s.s, data)
     inc(s.wr, len(data))
   of llsFile: 
     write(s.f, data)
   
-proc LLStreamWriteln(s: PLLStream, data: string) = 
-  LLStreamWrite(s, data)
-  LLStreamWrite(s, "\n")
+proc llStreamWriteln(s: PLLStream, data: string) = 
+  llStreamWrite(s, data)
+  llStreamWrite(s, "\n")
 
-proc LLStreamWrite(s: PLLStream, data: Char) = 
+proc llStreamWrite(s: PLLStream, data: char) = 
   var c: char
   case s.kind
   of llsNone, llsStdIn: 
-    nil
+    discard
   of llsString: 
     add(s.s, data)
     inc(s.wr)
@@ -191,22 +191,21 @@ proc LLStreamWrite(s: PLLStream, data: Char) =
     c = data
     discard writeBuffer(s.f, addr(c), sizeof(c))
 
-proc LLStreamWrite(s: PLLStream, buf: pointer, buflen: int) = 
+proc llStreamWrite(s: PLLStream, buf: pointer, buflen: int) = 
   case s.kind
   of llsNone, llsStdIn: 
-    nil
+    discard
   of llsString: 
-    if bufLen > 0: 
-      setlen(s.s, len(s.s) + bufLen)
-      copyMem(addr(s.s[0 + s.wr]), buf, bufLen)
-      inc(s.wr, bufLen)
+    if buflen > 0: 
+      setLen(s.s, len(s.s) + buflen)
+      copyMem(addr(s.s[0 + s.wr]), buf, buflen)
+      inc(s.wr, buflen)
   of llsFile: 
-    discard writeBuffer(s.f, buf, bufLen)
+    discard writeBuffer(s.f, buf, buflen)
   
-proc LLStreamReadAll(s: PLLStream): string = 
+proc llStreamReadAll(s: PLLStream): string = 
   const 
     bufSize = 2048
-  var bytes, i: int
   case s.kind
   of llsNone, llsStdIn: 
     result = ""
@@ -216,10 +215,10 @@ proc LLStreamReadAll(s: PLLStream): string =
     s.rd = len(s.s)
   of llsFile: 
     result = newString(bufSize)
-    bytes = readBuffer(s.f, addr(result[0]), bufSize)
-    i = bytes
+    var bytes = readBuffer(s.f, addr(result[0]), bufSize)
+    var i = bytes
     while bytes == bufSize: 
-      setlen(result, i + bufSize)
+      setLen(result, i + bufSize)
       bytes = readBuffer(s.f, addr(result[i + 0]), bufSize)
       inc(i, bytes)
-    setlen(result, i)
+    setLen(result, i)
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index e1ec9e14b..60125177c 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -21,7 +21,7 @@ proc considerAcc*(n: PNode): PIdent =
   of nkSym: result = n.sym.name
   of nkAccQuoted:
     case n.len
-    of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n))
+    of 0: globalError(n.info, errIdentifierExpected, renderTree(n))
     of 1: result = considerAcc(n.sons[0])
     else:
       var id = ""
@@ -30,16 +30,17 @@ proc considerAcc*(n: PNode): PIdent =
         case x.kind
         of nkIdent: id.add(x.ident.s)
         of nkSym: id.add(x.sym.name.s)
-        else: GlobalError(n.info, errIdentifierExpected, renderTree(n))
+        else: globalError(n.info, errIdentifierExpected, renderTree(n))
       result = getIdent(id)
+  of nkOpenSymChoice, nkClosedSymChoice: result = n.sons[0].sym.name
   else:
-    GlobalError(n.info, errIdentifierExpected, renderTree(n))
+    globalError(n.info, errIdentifierExpected, renderTree(n))
  
 template addSym*(scope: PScope, s: PSym) =
-  StrTableAdd(scope.symbols, s)
+  strTableAdd(scope.symbols, s)
 
 proc addUniqueSym*(scope: PScope, s: PSym): TResult =
-  if StrTableIncl(scope.symbols, s):
+  if strTableIncl(scope.symbols, s):
     result = Failure
   else:
     result = Success
@@ -64,17 +65,17 @@ iterator walkScopes*(scope: PScope): PScope =
     current = current.parent
 
 proc localSearchInScope*(c: PContext, s: PIdent): PSym =
-  result = StrTableGet(c.currentScope.symbols, s)
+  result = strTableGet(c.currentScope.symbols, s)
 
 proc searchInScopes*(c: PContext, s: PIdent): PSym =
   for scope in walkScopes(c.currentScope):
-    result = StrTableGet(scope.symbols, s)
+    result = strTableGet(scope.symbols, s)
     if result != nil: return
   result = nil
 
 proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym =
   for scope in walkScopes(c.currentScope):
-    result = StrTableGet(scope.symbols, s)
+    result = strTableGet(scope.symbols, s)
     if result != nil and result.kind in filter: return
   result = nil
 
@@ -91,7 +92,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
   result.typ = errorType(c)
   incl(result.flags, sfDiscardable)
   # pretend it's imported from some unknown module to prevent cascading errors:
-  if gCmd != cmdInteractive:
+  if gCmd != cmdInteractive and c.inCompilesContext == 0:
     c.importTable.addSym(result)
 
 type 
@@ -108,71 +109,74 @@ type
 
 proc getSymRepr*(s: PSym): string = 
   case s.kind
-  of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s)
+  of skProc, skMethod, skConverter, skIterators: result = getProcHeader(s)
   else: result = s.name.s
 
 proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
   # check if all symbols have been used and defined:
   var it: TTabIter
-  var s = InitTabIter(it, scope.symbols)
+  var s = initTabIter(it, scope.symbols)
   var missingImpls = 0
   while s != nil:
     if sfForward in s.flags:
       # too many 'implementation of X' errors are annoying
       # and slow 'suggest' down:
       if missingImpls == 0:
-        LocalError(s.info, errImplOfXexpected, getSymRepr(s))
+        localError(s.info, errImplOfXexpected, getSymRepr(s))
       inc missingImpls
     elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options: 
       # BUGFIX: check options in s!
       if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
-        Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
-    s = NextIter(it, scope.symbols)
+        # XXX: implicit type params are currently skTypes
+        # maybe they can be made skGenericParam as well.
+        if s.typ != nil and tfImplicitTypeParam notin s.typ.flags:
+          message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
+    s = nextIter(it, scope.symbols)
   
-proc WrongRedefinition*(info: TLineInfo, s: string) =
+proc wrongRedefinition*(info: TLineInfo, s: string) =
   if gCmd != cmdInteractive:
     localError(info, errAttemptToRedefine, s)
   
 proc addDecl*(c: PContext, sym: PSym) =
   if c.currentScope.addUniqueSym(sym) == Failure:
-    WrongRedefinition(sym.info, sym.Name.s)
+    wrongRedefinition(sym.info, sym.name.s)
 
 proc addPrelimDecl*(c: PContext, sym: PSym) =
   discard c.currentScope.addUniqueSym(sym)
 
 proc addDeclAt*(scope: PScope, sym: PSym) =
   if scope.addUniqueSym(sym) == Failure:
-    WrongRedefinition(sym.info, sym.Name.s)
+    wrongRedefinition(sym.info, sym.name.s)
 
-proc AddInterfaceDeclAux(c: PContext, sym: PSym) = 
+proc addInterfaceDeclAux(c: PContext, sym: PSym) = 
   if sfExported in sym.flags:
     # add to interface:
-    if c.module != nil: StrTableAdd(c.module.tab, sym)
-    else: InternalError(sym.info, "AddInterfaceDeclAux")
+    if c.module != nil: strTableAdd(c.module.tab, sym)
+    else: internalError(sym.info, "AddInterfaceDeclAux")
 
 proc addInterfaceDeclAt*(c: PContext, scope: PScope, sym: PSym) =
   addDeclAt(scope, sym)
-  AddInterfaceDeclAux(c, sym)
+  addInterfaceDeclAux(c, sym)
 
 proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
   if fn.kind notin OverloadableSyms: 
-    InternalError(fn.info, "addOverloadableSymAt")
+    internalError(fn.info, "addOverloadableSymAt")
     return
-  var check = StrTableGet(scope.symbols, fn.name)
-  if check != nil and check.Kind notin OverloadableSyms: 
-    WrongRedefinition(fn.info, fn.Name.s)
+  var check = strTableGet(scope.symbols, fn.name)
+  if check != nil and check.kind notin OverloadableSyms: 
+    wrongRedefinition(fn.info, fn.name.s)
   else:
     scope.addSym(fn)
   
 proc addInterfaceDecl*(c: PContext, sym: PSym) = 
   # it adds the symbol to the interface if appropriate
   addDecl(c, sym)
-  AddInterfaceDeclAux(c, sym)
+  addInterfaceDeclAux(c, sym)
 
 proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
   # it adds the symbol to the interface if appropriate
   addOverloadableSymAt(scope, sym)
-  AddInterfaceDeclAux(c, sym)
+  addInterfaceDeclAux(c, sym)
 
 proc lookUp*(c: PContext, n: PNode): PSym = 
   # Looks up a symbol. Generates an error in case of nil.
@@ -180,7 +184,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
   of nkIdent:
     result = searchInScopes(c, n.ident)
     if result == nil: 
-      LocalError(n.info, errUndeclaredIdentifier, n.ident.s)
+      localError(n.info, errUndeclaredIdentifier, n.ident.s)
       result = errorSym(c, n)
   of nkSym:
     result = n.sym
@@ -188,34 +192,34 @@ proc lookUp*(c: PContext, n: PNode): PSym =
     var ident = considerAcc(n)
     result = searchInScopes(c, ident)
     if result == nil:
-      LocalError(n.info, errUndeclaredIdentifier, ident.s)
+      localError(n.info, errUndeclaredIdentifier, ident.s)
       result = errorSym(c, n)
   else:
-    InternalError(n.info, "lookUp")
+    internalError(n.info, "lookUp")
     return
-  if Contains(c.AmbiguousSymbols, result.id): 
-    LocalError(n.info, errUseQualifier, result.name.s)
+  if contains(c.ambiguousSymbols, result.id): 
+    localError(n.info, errUseQualifier, result.name.s)
   if result.kind == skStub: loadStub(result)
   
 type 
   TLookupFlag* = enum 
     checkAmbiguity, checkUndeclared
 
-proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = 
+proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = 
   case n.kind
   of nkIdent, nkAccQuoted:
     var ident = considerAcc(n)
     result = searchInScopes(c, ident)
     if result == nil and checkUndeclared in flags: 
-      LocalError(n.info, errUndeclaredIdentifier, ident.s)
+      localError(n.info, errUndeclaredIdentifier, ident.s)
       result = errorSym(c, n)
     elif checkAmbiguity in flags and result != nil and 
-        Contains(c.AmbiguousSymbols, result.id): 
-      LocalError(n.info, errUseQualifier, ident.s)
+        contains(c.ambiguousSymbols, result.id): 
+      localError(n.info, errUseQualifier, ident.s)
   of nkSym:
     result = n.sym
-    if checkAmbiguity in flags and Contains(c.AmbiguousSymbols, result.id): 
-      LocalError(n.info, errUseQualifier, n.sym.name.s)
+    if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id): 
+      localError(n.info, errUseQualifier, n.sym.name.s)
   of nkDotExpr: 
     result = nil
     var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
@@ -227,28 +231,31 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
         ident = considerAcc(n.sons[1])
       if ident != nil: 
         if m == c.module: 
-          result = StrTableGet(c.topLevelScope.symbols, ident)
+          result = strTableGet(c.topLevelScope.symbols, ident)
         else: 
-          result = StrTableGet(m.tab, ident)
+          result = strTableGet(m.tab, ident)
         if result == nil and checkUndeclared in flags: 
-          LocalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
+          localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
           result = errorSym(c, n.sons[1])
-      elif checkUndeclared in flags:
-        LocalError(n.sons[1].info, errIdentifierExpected, 
+      elif n.sons[1].kind == nkSym:
+        result = n.sons[1].sym
+      elif checkUndeclared in flags and
+           n.sons[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
+        localError(n.sons[1].info, errIdentifierExpected,
                    renderTree(n.sons[1]))
         result = errorSym(c, n.sons[1])
   else:
     result = nil
   if result != nil and result.kind == skStub: loadStub(result)
   
-proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
+proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
   case n.kind
   of nkIdent, nkAccQuoted:
     var ident = considerAcc(n)
     o.scope = c.currentScope
     o.mode = oimNoQualifier
     while true:
-      result = InitIdentIter(o.it, o.scope.symbols, ident)
+      result = initIdentIter(o.it, o.scope.symbols, ident)
       if result != nil:
         break
       else:
@@ -269,12 +276,12 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       if ident != nil: 
         if o.m == c.module: 
           # a module may access its private members:
-          result = InitIdentIter(o.it, c.topLevelScope.symbols, ident)
+          result = initIdentIter(o.it, c.topLevelScope.symbols, ident)
           o.mode = oimSelfModule
         else: 
-          result = InitIdentIter(o.it, o.m.tab, ident)
+          result = initIdentIter(o.it, o.m.tab, ident)
       else: 
-        LocalError(n.sons[1].info, errIdentifierExpected, 
+        localError(n.sons[1].info, errIdentifierExpected, 
                    renderTree(n.sons[1]))
         result = errorSym(c, n.sons[1])
   of nkClosedSymChoice, nkOpenSymChoice:
@@ -282,8 +289,8 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
     result = n.sons[0].sym
     o.symChoiceIndex = 1
     o.inSymChoice = initIntSet()
-    Incl(o.inSymChoice, result.id)
-  else: nil
+    incl(o.inSymChoice, result.id)
+  else: discard
   if result != nil and result.kind == skStub: loadStub(result)
 
 proc lastOverloadScope*(o: TOverloadIter): int =
@@ -303,7 +310,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       while result == nil:
         o.scope = o.scope.parent
         if o.scope == nil: break
-        result = InitIdentIter(o.it, o.scope.symbols, o.it.name)
+        result = initIdentIter(o.it, o.scope.symbols, o.it.name)
         # BUGFIX: o.it.name <-> n.ident
     else: 
       result = nil
@@ -314,26 +321,38 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
   of oimSymChoice: 
     if o.symChoiceIndex < sonsLen(n):
       result = n.sons[o.symChoiceIndex].sym
-      Incl(o.inSymChoice, result.id)
+      incl(o.inSymChoice, result.id)
       inc o.symChoiceIndex
     elif n.kind == nkOpenSymChoice:
       # try 'local' symbols too for Koenig's lookup:
       o.mode = oimSymChoiceLocalLookup
       o.scope = c.currentScope
-      result = FirstIdentExcluding(o.it, o.scope.symbols,
+      result = firstIdentExcluding(o.it, o.scope.symbols,
                                    n.sons[0].sym.name, o.inSymChoice)
       while result == nil:
         o.scope = o.scope.parent
         if o.scope == nil: break
-        result = FirstIdentExcluding(o.it, o.scope.symbols,
+        result = firstIdentExcluding(o.it, o.scope.symbols,
                                      n.sons[0].sym.name, o.inSymChoice)
   of oimSymChoiceLocalLookup:
     result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice)
     while result == nil:
       o.scope = o.scope.parent
       if o.scope == nil: break
-      result = FirstIdentExcluding(o.it, o.scope.symbols,
+      result = firstIdentExcluding(o.it, o.scope.symbols,
                                    n.sons[0].sym.name, o.inSymChoice)
   
   if result != nil and result.kind == skStub: loadStub(result)
-  
+
+when false:
+  proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode,
+                                       flags = {checkUndeclared}): PSym =
+    var o: TOverloadIter
+    result = initOverloadIter(o, c, n)
+    var a = result
+    while a != nil:
+      if sfImmediate in a.flags: return a
+      a = nextOverloadIter(o, c, n)
+    if result == nil and checkUndeclared in flags: 
+      localError(n.info, errUndeclaredIdentifier, n.considerAcc.s)
+      result = errorSym(c, n)
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
new file mode 100644
index 000000000..2cf641d93
--- /dev/null
+++ b/compiler/lowerings.nim
@@ -0,0 +1,52 @@
+#
+#
+#           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 common simple lowerings.
+
+const
+  genPrefix* = ":tmp"         # prefix for generated names
+
+import ast, types, idents, magicsys
+
+proc newTupleAccess*(tup: PNode, i: int): PNode =
+  result = newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(
+                     abstractInst).sons[i])
+  addSon(result, copyTree(tup))
+  var lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
+  lit.intVal = i
+  addSon(result, lit)
+
+proc addVar*(father, v: PNode) = 
+  var vpart = newNodeI(nkIdentDefs, v.info, 3)
+  vpart.sons[0] = v
+  vpart.sons[1] = ast.emptyNode
+  vpart.sons[2] = ast.emptyNode
+  addSon(father, vpart)
+
+proc newAsgnStmt(le, ri: PNode): PNode =
+  result = newNodeI(nkAsgn, le.info, 2)
+  result.sons[0] = le
+  result.sons[1] = ri
+
+proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
+  assert n.kind == nkVarTuple
+  let value = n.lastSon
+  result = newNodeI(nkStmtList, n.info)
+
+  var temp = newSym(skTemp, getIdent(genPrefix), owner, value.info)
+  temp.typ = skipTypes(value.typ, abstractInst)
+  incl(temp.flags, sfFromGeneric)
+
+  var v = newNodeI(nkVarSection, value.info)
+  v.addVar(newSymNode(temp))
+  result.add(v)
+  
+  result.add newAsgnStmt(newSymNode(temp), value)
+  for i in 0 .. n.len-3:
+    result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i))
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index 0c0b87222..b4f6e043d 100644
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -12,14 +12,14 @@
 import 
   ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread
 
-var SystemModule*: PSym
+var systemModule*: PSym
 
 proc registerSysType*(t: PType)
   # magic symbols in the system module:
 proc getSysType*(kind: TTypeKind): PType
 proc getCompilerProc*(name: string): PSym
 proc registerCompilerProc*(s: PSym)
-proc FinishSystem*(tab: TStrTable)
+proc finishSystem*(tab: TStrTable)
 proc getSysSym*(name: string): PSym
 # implementation
 
@@ -36,7 +36,7 @@ proc newSysType(kind: TTypeKind, size: int): PType =
   result.align = size
 
 proc getSysSym(name: string): PSym = 
-  result = StrTableGet(systemModule.tab, getIdent(name))
+  result = strTableGet(systemModule.tab, getIdent(name))
   if result == nil: 
     rawMessage(errSystemNeeds, name)
     result = newSym(skError, getIdent(name), systemModule, systemModule.info)
@@ -46,11 +46,11 @@ proc getSysSym(name: string): PSym =
 proc getSysMagic*(name: string, m: TMagic): PSym =
   var ti: TIdentIter
   let id = getIdent(name)
-  result = InitIdentIter(ti, systemModule.tab, id)
+  result = initIdentIter(ti, systemModule.tab, id)
   while result != nil:
     if result.kind == skStub: loadStub(result)
     if result.magic == m: return result
-    result = NextIdentIter(ti, systemModule.tab)
+    result = nextIdentIter(ti, systemModule.tab)
   rawMessage(errSystemNeeds, name)
   result = newSym(skError, id, systemModule, systemModule.info)
   result.typ = newType(tyError, systemModule)
@@ -79,14 +79,14 @@ proc getSysType(kind: TTypeKind): PType =
     of tyBool: result = sysTypeFromName("bool")
     of tyChar: result = sysTypeFromName("char")
     of tyString: result = sysTypeFromName("string")
-    of tyCstring: result = sysTypeFromName("cstring")
+    of tyCString: result = sysTypeFromName("cstring")
     of tyPointer: result = sysTypeFromName("pointer")
     of tyNil: result = newSysType(tyNil, ptrSize)
-    else: InternalError("request for typekind: " & $kind)
+    else: internalError("request for typekind: " & $kind)
     gSysTypes[kind] = result
   if result.kind != kind: 
-    InternalError("wanted: " & $kind & " got: " & $result.kind)
-  if result == nil: InternalError("type not found: " & $kind)
+    internalError("wanted: " & $kind & " got: " & $result.kind)
+  if result == nil: internalError("type not found: " & $kind)
 
 var
   intTypeCache: array[-5..64, PType]
@@ -126,7 +126,7 @@ proc skipIntLit*(t: PType): PType {.inline.} =
       return getSysType(t.kind)
   result = t
 
-proc AddSonSkipIntLit*(father, son: PType) =
+proc addSonSkipIntLit*(father, son: PType) =
   if isNil(father.sons): father.sons = @[]
   let s = son.skipIntLit
   add(father.sons, s)
@@ -134,7 +134,7 @@ proc AddSonSkipIntLit*(father, son: PType) =
 
 proc setIntLitType*(result: PNode) =
   let i = result.intVal
-  case platform.IntSize
+  case platform.intSize
   of 8: result.typ = getIntLitType(result)
   of 4:
     if i >= low(int32) and i <= high(int32):
@@ -158,13 +158,13 @@ proc setIntLitType*(result: PNode) =
       result.typ = getSysType(tyInt32)
     else:
       result.typ = getSysType(tyInt64)
-  else: InternalError(result.info, "invalid int size")
+  else: internalError(result.info, "invalid int size")
 
 proc getCompilerProc(name: string): PSym = 
   var ident = getIdent(name, hashIgnoreStyle(name))
-  result = StrTableGet(compilerprocs, ident)
+  result = strTableGet(compilerprocs, ident)
   if result == nil: 
-    result = StrTableGet(rodCompilerProcs, ident)
+    result = strTableGet(rodCompilerprocs, ident)
     if result != nil: 
       strTableAdd(compilerprocs, result)
       if result.kind == skStub: loadStub(result)
@@ -172,7 +172,6 @@ proc getCompilerProc(name: string): PSym =
 proc registerCompilerProc(s: PSym) = 
   strTableAdd(compilerprocs, s)
 
-proc FinishSystem(tab: TStrTable) = nil
-  
-initStrTable(compilerprocs)
+proc finishSystem(tab: TStrTable) = discard
 
+initStrTable(compilerprocs)
diff --git a/compiler/main.nim b/compiler/main.nim
index 9ffe99454..f6d11d960 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -14,16 +14,16 @@ import
   os, condsyms, rodread, rodwrite, times,
   wordrecg, sem, semdata, idents, passes, docgen, extccomp,
   cgen, jsgen, json, nversion,
-  platform, nimconf, importer, passaux, depends, evals, types, idgen,
+  platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
   tables, docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists,
   pretty
 
-from magicsys import SystemModule, resetSysTypes
+from magicsys import systemModule, resetSysTypes
 
 const
-  has_LLVM_Backend = false
+  hasLLVM_Backend = false
 
-when has_LLVM_Backend:
+when hasLLVM_Backend:
   import llvmgen
 
 proc rodPass =
@@ -37,22 +37,22 @@ proc semanticPasses =
   registerPass verbosePass
   registerPass semPass
 
-proc CommandGenDepend =
+proc commandGenDepend =
   semanticPasses()
-  registerPass(genDependPass)
+  registerPass(gendependPass)
   registerPass(cleanupPass)
   compileProject()
   generateDot(gProjectFull)
   execExternalProgram("dot -Tpng -o" & changeFileExt(gProjectFull, "png") &
       ' ' & changeFileExt(gProjectFull, "dot"))
 
-proc CommandCheck =
+proc commandCheck =
   msgs.gErrorMax = high(int)  # do not stop after first error
   semanticPasses()            # use an empty backend for semantic checking only
   rodPass()
   compileProject()
 
-proc CommandDoc2 =
+proc commandDoc2 =
   msgs.gErrorMax = high(int)  # do not stop after first error
   semanticPasses()
   registerPass(docgen2Pass)
@@ -60,7 +60,7 @@ proc CommandDoc2 =
   compileProject()
   finishDoc2Pass(gProjectName)
 
-proc CommandCompileToC =
+proc commandCompileToC =
   semanticPasses()
   registerPass(cgenPass)
   rodPass()
@@ -73,7 +73,7 @@ proc CommandCompileToC =
   compileProject()
   cgenWriteModules()
   if gCmd != cmdRun:
-    extccomp.CallCCompiler(changeFileExt(gProjectFull, ""))
+    extccomp.callCCompiler(changeFileExt(gProjectFull, ""))
 
   if isServing:
     # caas will keep track only of the compilation commands
@@ -111,45 +111,45 @@ proc CommandCompileToC =
     ccgutils.resetCaches()
     GC_fullCollect()
 
-when has_LLVM_Backend:
-  proc CommandCompileToLLVM =
+when hasLLVM_Backend:
+  proc commandCompileToLLVM =
     semanticPasses()
     registerPass(llvmgen.llvmgenPass())
     rodPass()
     #registerPass(cleanupPass())
     compileProject()
 
-proc CommandCompileToJS =
+proc commandCompileToJS =
   #incl(gGlobalOptions, optSafeCode)
   setTarget(osJS, cpuJS)
   #initDefines()
-  DefineSymbol("nimrod") # 'nimrod' is always defined
-  DefineSymbol("ecmascript") # For backward compatibility
-  DefineSymbol("js")
+  defineSymbol("nimrod") # 'nimrod' is always defined
+  defineSymbol("ecmascript") # For backward compatibility
+  defineSymbol("js")
   semanticPasses()
-  registerPass(jsgenPass)
+  registerPass(JSgenPass)
   compileProject()
 
-proc InteractivePasses =
+proc interactivePasses =
   #incl(gGlobalOptions, optSafeCode)
   #setTarget(osNimrodVM, cpuNimrodVM)
   initDefines()
-  DefineSymbol("nimrodvm")
-  when hasFFI: DefineSymbol("nimffi")
+  defineSymbol("nimrodvm")
+  when hasFFI: defineSymbol("nimffi")
   registerPass(verbosePass)
   registerPass(semPass)
   registerPass(evalPass)
 
-proc CommandInteractive =
+proc commandInteractive =
   msgs.gErrorMax = high(int)  # do not stop after first error
-  InteractivePasses()
+  interactivePasses()
   compileSystemModule()
   if commandArgs.len > 0:
-    discard CompileModule(fileInfoIdx(gProjectFull), {})
+    discard compileModule(fileInfoIdx(gProjectFull), {})
   else:
     var m = makeStdinModule()
     incl(m.flags, sfMainModule)
-    processModule(m, LLStreamOpenStdIn(), nil)
+    processModule(m, llStreamOpenStdIn(), nil)
 
 const evalPasses = [verbosePass, semPass, evalPass]
 
@@ -157,28 +157,28 @@ proc evalNim(nodes: PNode, module: PSym) =
   carryPasses(nodes, module, evalPasses)
 
 proc commandEval(exp: string) =
-  if SystemModule == nil:
-    InteractivePasses()
+  if systemModule == nil:
+    interactivePasses()
     compileSystemModule()
   var echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
   evalNim(echoExp.parseString, makeStdinModule())
 
-proc CommandPrettyOld =
+proc commandPrettyOld =
   var projectFile = addFileExt(mainCommandArg(), NimExt)
   var module = parseFile(projectFile.fileInfoIdx)
   if module != nil:
     renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt))
 
-proc CommandPretty =
+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)
+proc commandScan =
+  var f = addFileExt(mainCommandArg(), NimExt)
+  var stream = llStreamOpen(f, fmRead)
   if stream != nil:
     var
       L: TLexer
@@ -187,20 +187,20 @@ proc CommandScan =
     openLexer(L, f, stream)
     while true:
       rawGetTok(L, tok)
-      PrintTok(tok)
+      printTok(tok)
       if tok.tokType == tkEof: break
-    CloseLexer(L)
+    closeLexer(L)
   else:
     rawMessage(errCannotOpenFile, f)
 
-proc CommandSuggest =
+proc commandSuggest =
   if isServing:
     # XXX: hacky work-around ahead
     # Currently, it's possible to issue a idetools command, before
     # issuing the first compile command. This will leave the compiler
     # cache in a state where "no recompilation is necessary", but the
     # cgen pass was never executed at all.
-    CommandCompileToC()
+    commandCompileToC()
     if gDirtyBufferIdx != 0:
       discard compileModule(gDirtyBufferIdx, {sfDirty})
       resetModule(gDirtyBufferIdx)
@@ -219,21 +219,21 @@ proc CommandSuggest =
 proc wantMainModule =
   if gProjectFull.len == 0:
     if optMainModule.len == 0:
-      Fatal(gCmdLineInfo, errCommandExpectsFilename)
+      fatal(gCmdLineInfo, errCommandExpectsFilename)
     else:
       gProjectName = optMainModule
       gProjectFull = gProjectPath / gProjectName
 
-  gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
+  gProjectMainIdx = addFileExt(gProjectFull, NimExt).fileInfoIdx
 
 proc requireMainModuleOption =
   if optMainModule.len == 0:
-    Fatal(gCmdLineInfo, errMainModuleMustBeSpecified)
+    fatal(gCmdLineInfo, errMainModuleMustBeSpecified)
   else:
     gProjectName = optMainModule
     gProjectFull = gProjectPath / gProjectName
 
-  gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
+  gProjectMainIdx = addFileExt(gProjectFull, NimExt).fileInfoIdx
 
 proc resetMemory =
   resetCompilationLists()
@@ -286,7 +286,7 @@ const
   SimiluateCaasMemReset = false
   PrintRopeCacheStats = false
 
-proc MainCommand* =
+proc mainCommand* =
   when SimiluateCaasMemReset:
     gGlobalOptions.incl(optCaasEnabled)
 
@@ -297,7 +297,7 @@ proc MainCommand* =
   if gProjectFull.len != 0:
     # current path is always looked first for modules
     prependStr(searchPaths, gProjectPath)
-  setID(100)
+  setId(100)
   passes.gIncludeFile = includeModule
   passes.gImportModule = importModule
   case command.normalize
@@ -305,88 +305,88 @@ proc MainCommand* =
     # compile means compileToC currently
     gCmd = cmdCompileToC
     wantMainModule()
-    CommandCompileToC()
+    commandCompileToC()
   of "cpp", "compiletocpp":
     extccomp.cExt = ".cpp"
     gCmd = cmdCompileToCpp
     if cCompiler == ccGcc: setCC("gpp")
     wantMainModule()
-    DefineSymbol("cpp")
-    CommandCompileToC()
+    defineSymbol("cpp")
+    commandCompileToC()
   of "objc", "compiletooc":
     extccomp.cExt = ".m"
     gCmd = cmdCompileToOC
     wantMainModule()
-    DefineSymbol("objc")
-    CommandCompileToC()
+    defineSymbol("objc")
+    commandCompileToC()
   of "run":
     gCmd = cmdRun
     wantMainModule()
     when hasTinyCBackend:
       extccomp.setCC("tcc")
-      CommandCompileToC()
+      commandCompileToC()
     else:
       rawMessage(errInvalidCommandX, command)
   of "js", "compiletojs":
     gCmd = cmdCompileToJS
     wantMainModule()
-    CommandCompileToJS()
+    commandCompileToJS()
   of "compiletollvm":
     gCmd = cmdCompileToLLVM
     wantMainModule()
-    when has_LLVM_Backend:
+    when hasLLVM_Backend:
       CommandCompileToLLVM()
     else:
       rawMessage(errInvalidCommandX, command)
   of "pretty":
     gCmd = cmdPretty
     wantMainModule()
-    CommandPretty()
+    commandPretty()
   of "doc":
     gCmd = cmdDoc
-    LoadConfigs(DocConfig)
+    loadConfigs(DocConfig)
     wantMainModule()
-    CommandDoc()
+    commandDoc()
   of "doc2":
     gCmd = cmdDoc
-    LoadConfigs(DocConfig)
+    loadConfigs(DocConfig)
     wantMainModule()
-    DefineSymbol("nimdoc")
-    CommandDoc2()
+    defineSymbol("nimdoc")
+    commandDoc2()
   of "rst2html":
     gCmd = cmdRst2html
-    LoadConfigs(DocConfig)
+    loadConfigs(DocConfig)
     wantMainModule()
-    CommandRst2Html()
+    commandRst2Html()
   of "rst2tex":
     gCmd = cmdRst2tex
-    LoadConfigs(DocTexConfig)
+    loadConfigs(DocTexConfig)
     wantMainModule()
-    CommandRst2TeX()
+    commandRst2TeX()
   of "jsondoc":
     gCmd = cmdDoc
-    LoadConfigs(DocConfig)
+    loadConfigs(DocConfig)
     wantMainModule()
-    DefineSymbol("nimdoc")
-    CommandJSON()
+    defineSymbol("nimdoc")
+    commandJSON()
   of "buildindex":
     gCmd = cmdDoc
-    LoadConfigs(DocConfig)
-    CommandBuildIndex()
+    loadConfigs(DocConfig)
+    commandBuildIndex()
   of "gendepend":
     gCmd = cmdGenDepend
     wantMainModule()
-    CommandGenDepend()
+    commandGenDepend()
   of "dump":
-    gcmd = cmdDump
-    if getconfigvar("dump.format") == "json":
+    gCmd = cmdDump
+    if getConfigVar("dump.format") == "json":
       requireMainModuleOption()
 
       var definedSymbols = newJArray()
       for s in definedSymbolNames(): definedSymbols.elems.add(%s)
 
       var libpaths = newJArray()
-      for dir in itersearchpath(searchpaths): libpaths.elems.add(%dir)
+      for dir in iterSearchPath(searchPaths): libpaths.elems.add(%dir)
 
       var dumpdata = % [
         (key: "version", val: %VersionAsString),
@@ -395,17 +395,17 @@ proc MainCommand* =
         (key: "lib_paths", val: libpaths)
       ]
 
-      outWriteLn($dumpdata)
+      outWriteln($dumpdata)
     else:
-      outWriteLn("-- list of currently defined symbols --")
-      for s in definedSymbolNames(): outWriteLn(s)
-      outWriteLn("-- end of list --")
+      outWriteln("-- list of currently defined symbols --")
+      for s in definedSymbolNames(): outWriteln(s)
+      outWriteln("-- end of list --")
 
-      for it in iterSearchPath(searchpaths): msgWriteLn(it)
+      for it in iterSearchPath(searchPaths): msgWriteln(it)
   of "check":
     gCmd = cmdCheck
     wantMainModule()
-    CommandCheck()
+    commandCheck()
   of "parse":
     gCmd = cmdParse
     wantMainModule()
@@ -413,11 +413,11 @@ proc MainCommand* =
   of "scan":
     gCmd = cmdScan
     wantMainModule()
-    CommandScan()
-    MsgWriteln("Beware: Indentation tokens depend on the parser\'s state!")
+    commandScan()
+    msgWriteln("Beware: Indentation tokens depend on the parser\'s state!")
   of "i":
     gCmd = cmdInteractive
-    CommandInteractive()
+    commandInteractive()
   of "e":
     # XXX: temporary command for easier testing
     commandEval(mainCommandArg())
@@ -429,12 +429,12 @@ proc MainCommand* =
       commandEval(gEvalExpr)
     else:
       wantMainModule()
-      CommandSuggest()
+      commandSuggest()
   of "serve":
     isServing = true
     gGlobalOptions.incl(optCaasEnabled)
     msgs.gErrorMax = high(int)  # do not stop after first error
-    serve(MainCommand)
+    serve(mainCommand)
   else:
     rawMessage(errInvalidCommandX, command)
 
@@ -450,7 +450,8 @@ proc MainCommand* =
     echo "  tries : ", gCacheTries
     echo "  misses: ", gCacheMisses
     echo "  int tries: ", gCacheIntTries
-    echo "  efficiency: ", formatFloat(1-(gCacheMisses.float/gCacheTries.float), ffDecimal, 3)
+    echo "  efficiency: ", formatFloat(1-(gCacheMisses.float/gCacheTries.float),
+                                       ffDecimal, 3)
 
   when SimiluateCaasMemReset:
     resetMemory()
diff --git a/compiler/modules.nim b/compiler/modules.nim
index ef6af3d69..fb1940741 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -20,7 +20,7 @@ type
   TModuleInMemory* = object
     compiledAt*: float
     crc*: TCrc32
-    deps*: seq[int32] ## XXX: slurped files are not currently tracked
+    deps*: seq[int32] ## XXX: slurped files are currently not tracked
     needsRecompile*: TNeedRecompile
     crcStatus*: TCrcStatus
 
@@ -41,7 +41,7 @@ template crc(x: PSym): expr =
   gMemCacheData[x.position].crc
 
 proc crcChanged(fileIdx: int32): bool =
-  InternalAssert fileIdx >= 0 and fileIdx < gMemCacheData.len
+  internalAssert fileIdx >= 0 and fileIdx < gMemCacheData.len
   
   template updateStatus =
     gMemCacheData[fileIdx].crcStatus = if result: crcHasChanged
@@ -68,7 +68,7 @@ proc doCRC(fileIdx: int32) =
     # echo "FIRST CRC: ", fileIdx.ToFilename
     gMemCacheData[fileIdx].crc = crcFromFile(fileIdx.toFilename)
 
-proc addDep(x: Psym, dep: int32) =
+proc addDep(x: PSym, dep: int32) =
   growCache gMemCacheData, dep
   gMemCacheData[x.position].deps.safeAdd(dep)
 
@@ -83,7 +83,7 @@ proc resetAllModules* =
   for i in 0..gCompiledModules.high:
     if gCompiledModules[i] != nil:
       resetModule(i.int32)
-
+  resetPackageCache()
   # for m in cgenModules(): echo "CGEN MODULE FOUND"
 
 proc checkDepMem(fileIdx: int32): TNeedRecompile =
@@ -120,8 +120,9 @@ proc newModule(fileIdx: int32): PSym =
   if not isNimrodIdentifier(result.name.s):
     rawMessage(errInvalidModuleName, result.name.s)
   
-  result.owner = result       # a module belongs to itself
   result.info = newLineInfo(fileIdx, 1, 1)
+  result.owner = newSym(skPackage, getIdent(getPackageName(filename)), nil,
+                        result.info)
   result.position = fileIdx
   
   growCache gMemCacheData, fileIdx
@@ -130,7 +131,7 @@ proc newModule(fileIdx: int32): PSym =
   
   incl(result.flags, sfUsed)
   initStrTable(result.tab)
-  StrTableAdd(result.tab, result) # a module knows itself
+  strTableAdd(result.tab, result) # a module knows itself
 
 proc compileModule*(fileIdx: int32, flags: TSymFlags): PSym =
   result = getModule(fileIdx)
@@ -144,7 +145,7 @@ proc compileModule*(fileIdx: int32, flags: TSymFlags): PSym =
     if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
       rd = handleSymbolFile(result)
       if result.id < 0: 
-        InternalError("handleSymbolFile should have set the module\'s ID")
+        internalError("handleSymbolFile should have set the module\'s ID")
         return
     else:
       result.id = getID()
@@ -155,7 +156,7 @@ proc compileModule*(fileIdx: int32, flags: TSymFlags): PSym =
       doCRC fileIdx
   else:
     if checkDepMem(fileIdx) == Yes:
-      result = CompileModule(fileIdx, flags)
+      result = compileModule(fileIdx, flags)
     else:
       result = gCompiledModules[fileIdx]
 
@@ -164,14 +165,14 @@ proc importModule*(s: PSym, fileIdx: int32): PSym {.procvar.} =
   result = compileModule(fileIdx, {})
   if optCaasEnabled in gGlobalOptions: addDep(s, fileIdx)
   if sfSystemModule in result.flags:
-    LocalError(result.info, errAttemptToRedefine, result.Name.s)
+    localError(result.info, errAttemptToRedefine, result.name.s)
 
 proc includeModule*(s: PSym, fileIdx: int32): PNode {.procvar.} =
   result = syntaxes.parseFile(fileIdx)
   if optCaasEnabled in gGlobalOptions:
     growCache gMemCacheData, fileIdx
     addDep(s, fileIdx)
-    doCrc(fileIdx)
+    doCRC(fileIdx)
 
 proc `==^`(a, b: string): bool =
   try:
@@ -180,17 +181,17 @@ proc `==^`(a, b: string): bool =
     result = false
 
 proc compileSystemModule* =
-  if magicsys.SystemModule == nil:
-    SystemFileIdx = fileInfoIdx(options.libpath/"system.nim")
-    discard CompileModule(SystemFileIdx, {sfSystemModule})
+  if magicsys.systemModule == nil:
+    systemFileIdx = fileInfoIdx(options.libpath/"system.nim")
+    discard compileModule(systemFileIdx, {sfSystemModule})
 
-proc CompileProject*(projectFile = gProjectMainIdx) =
+proc compileProject*(projectFile = gProjectMainIdx) =
   let systemFileIdx = fileInfoIdx(options.libpath / "system.nim")
-  if projectFile == SystemFileIdx:
-    discard CompileModule(projectFile, {sfMainModule, sfSystemModule})
+  if projectFile == systemFileIdx:
+    discard compileModule(projectFile, {sfMainModule, sfSystemModule})
   else:
     compileSystemModule()
-    discard CompileModule(projectFile, {sfMainModule})
+    discard compileModule(projectFile, {sfMainModule})
 
 var stdinModule: PSym
 proc makeStdinModule*(): PSym =
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 895ba71f3..a63fbca7f 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -67,7 +67,7 @@ type
     errAmbiguousCallXYZ, errWrongNumberOfArguments, 
     errXCannotBePassedToProcVar, 
     errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed, 
-    errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue, 
+    errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValueX, 
     errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice, 
     errInvalidOrderInArrayConstructor,
     errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry, 
@@ -88,13 +88,16 @@ type
     errTemplateInstantiationTooNested, errInstantiationFrom, 
     errInvalidIndexValueForTuple, errCommandExpectsFilename,
     errMainModuleMustBeSpecified,
-    errXExpected, 
+    errXExpected,
+    errTIsNotAConcreteType,
     errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError, 
     errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile, 
     errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
     errOnlyACallOpCanBeDelegator, errUsingNoSymbol,
-    
-    errXExpectsTwoArguments, 
+    errMacroBodyDependsOnGenericTypes,
+    errDestructorNotGenericEnough,
+    errInlineIteratorsAsProcParams,
+    errXExpectsTwoArguments,
     errXExpectsObjectTypes, errXcanNeverBeOfThisSubtype, errTooManyIterations, 
     errCannotInterpretNodeX, errFieldXNotFound, errInvalidConversionFromTypeX, 
     errAssertionFailed, errCannotGenerateCodeForX, errXRequiresOneArgument, 
@@ -102,6 +105,10 @@ type
     errXhasSideEffects, errIteratorExpected, errLetNeedsInit,
     errThreadvarCannotInit, errWrongSymbolX, errIllegalCaptureX,
     errXCannotBeClosure, errXMustBeCompileTime,
+    errCannotInferTypeOfTheLiteral,
+    errCannotInferReturnType,
+    errGenericLambdaNotAllowed,
+    errCompilerDoesntSupportTarget,
     errUser,
     warnCannotOpenFile, 
     warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit, 
@@ -112,7 +119,7 @@ type
     warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitClosure,
     warnEachIdentIsTuple, warnShadowIdent, 
     warnProveInit, warnProveField, warnProveIndex,
-    warnUninit, warnUser,
+    warnUninit, warnGcMem, warnUser,
     hintSuccess, hintSuccessX,
     hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
     hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
@@ -195,7 +202,7 @@ const
     errXExpectsArrayType: "\'$1\' expects an array type", 
     errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet", 
     errExprXAmbiguous: "expression '$1' ambiguous in this context", 
-    errConstantDivisionByZero: "constant division by zero", 
+    errConstantDivisionByZero: "division by zero", 
     errOrdinalTypeExpected: "ordinal type expected", 
     errOrdinalOrFloatTypeExpected: "ordinal or float type expected", 
     errOverOrUnderflow: "over- or underflow", 
@@ -262,7 +269,7 @@ const
     errImplOfXNotAllowed: "implementation of \'$1\' is not allowed", 
     errImplOfXexpected: "implementation of \'$1\' expected", 
     errNoSymbolToBorrowFromFound: "no symbol to borrow from found", 
-    errDiscardValue: "value returned by statement has to be discarded", 
+    errDiscardValueX: "value of type '$1' has to be discarded", 
     errInvalidDiscard: "statement returns no value that can be discarded", 
     errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
     errCannotBindXTwice: "cannot bind parameter \'$1\' twice", 
@@ -311,6 +318,7 @@ const
     errCommandExpectsFilename: "command expects a filename argument",
     errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
     errXExpected: "\'$1\' expected", 
+    errTIsNotAConcreteType: "\'$1\' is not a concrete type.",
     errInvalidSectionStart: "invalid section start",
     errGridTableNotImplemented: "grid table is not implemented", 
     errGeneralParseError: "general parse error",
@@ -322,6 +330,12 @@ const
     errInstantiateXExplicitely: "instantiate '$1' explicitely",
     errOnlyACallOpCanBeDelegator: "only a call operator can be a delegator",
     errUsingNoSymbol: "'$1' is not a variable, constant or a proc name",
+    errMacroBodyDependsOnGenericTypes: "the macro body cannot be compiled, " &
+                                       "because the parameter '$1' has a generic type",
+    errDestructorNotGenericEnough: "Destructor signarue is too specific. " &
+                                   "A destructor must be associated will all instantiations of a generic type",
+    errInlineIteratorsAsProcParams: "inline iterators can be used as parameters only for " &
+                                    "templates, macros and other inline iterators",
     errXExpectsTwoArguments: "\'$1\' expects two arguments", 
     errXExpectsObjectTypes: "\'$1\' expects object types",
     errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", 
@@ -343,6 +357,12 @@ const
     errIllegalCaptureX: "illegal capture '$1'",
     errXCannotBeClosure: "'$1' cannot have 'closure' calling convention",
     errXMustBeCompileTime: "'$1' can only be used in compile-time context",
+    errCannotInferTypeOfTheLiteral: "cannot infer the type of the $1",
+    errCannotInferReturnType: "cannot infer the return type of the proc",
+    errGenericLambdaNotAllowed: "A nested proc can have generic parameters only when " &
+                                "it is used as an operand to another routine and the types " &
+                                "of the generic paramers can be infered from the expected signature.",
+    errCompilerDoesntSupportTarget: "The current compiler \'$1\' doesn't support the requested compilation target",
     errUser: "$1", 
     warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]",
     warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]", 
@@ -367,6 +387,7 @@ const
     warnProveField: "cannot prove that field '$1' is accessible [ProveField]",
     warnProveIndex: "cannot prove index '$1' is valid [ProveIndex]",
     warnUninit: "'$1' might not have been initialized [Uninit]",
+    warnGcMem: "'$1' uses GC'ed memory [GcMem]",
     warnUser: "$1 [User]", 
     hintSuccess: "operation successful [Success]", 
     hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#) [SuccessX]", 
@@ -386,7 +407,7 @@ const
     hintUser: "$1 [User]"]
 
 const
-  WarningsToStr*: array[0..23, string] = ["CannotOpenFile", "OctalEscape", 
+  WarningsToStr*: array[0..24, string] = ["CannotOpenFile", "OctalEscape", 
     "XIsNeverRead", "XmightNotBeenInit",
     "Deprecated", "ConfigDeprecated",
     "SmallLshouldNotBeUsed", "UnknownMagic", 
@@ -394,7 +415,7 @@ const
     "CommentXIgnored", "NilStmt",
     "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
     "ImplicitClosure", "EachIdentIsTuple", "ShadowIdent", 
-    "ProveInit", "ProveField", "ProveIndex", "Uninit", "User"]
+    "ProveInit", "ProveField", "ProveIndex", "Uninit", "GcMem", "User"]
 
   HintsToStr*: array[0..15, string] = ["Success", "SuccessX", "LineTooLong", 
     "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", 
@@ -445,7 +466,7 @@ type
   TErrorOutputs* = set[TErrorOutput]
 
   ERecoverableError* = object of EInvalidValue
-  ESuggestDone* = object of EBase
+  ESuggestDone* = object of E_Base
 
 const
   InvalidFileIDX* = int32(-1)
@@ -453,9 +474,9 @@ const
 var
   filenameToIndexTbl = initTable[string, int32]()
   fileInfos*: seq[TFileInfo] = @[]
-  SystemFileIdx*: int32
+  systemFileIdx*: int32
 
-proc toCChar*(c: Char): string = 
+proc toCChar*(c: char): string = 
   case c
   of '\0'..'\x1F', '\x80'..'\xFF': result = '\\' & toOctal(c)
   of '\'', '\"', '\\': result = '\\' & c
@@ -474,7 +495,7 @@ proc makeCString*(s: string): PRope =
       add(res, '\"')
       add(res, tnl)
       app(result, toRope(res)) # reset:
-      setlen(res, 1)
+      setLen(res, 1)
       res[0] = '\"'
     add(res, toCChar(s[i]))
   add(res, '\"')
@@ -545,14 +566,14 @@ var
 when useCaas:
   var stdoutSocket*: TSocket
 
-proc UnknownLineInfo*(): TLineInfo =
+proc unknownLineInfo*(): TLineInfo =
   result.line = int16(-1)
   result.col = int16(-1)
   result.fileIndex = -1
 
 var 
   msgContext: seq[TLineInfo] = @[]
-  lastError = UnknownLineInfo()
+  lastError = unknownLineInfo()
   bufferedMsgs*: seq[string]
 
   errorOutputs* = {eStdOut, eStdErr}
@@ -560,20 +581,20 @@ var
 proc clearBufferedMsgs* =
   bufferedMsgs = nil
 
-proc SuggestWriteln*(s: string) =
+proc suggestWriteln*(s: string) =
   if eStdOut in errorOutputs:
     when useCaas:
-      if isNil(stdoutSocket): Writeln(stdout, s)
+      if isNil(stdoutSocket): writeln(stdout, s)
       else:
-        Writeln(stdout, s)
+        writeln(stdout, s)
         stdoutSocket.send(s & "\c\L")
     else:
-      Writeln(stdout, s)
+      writeln(stdout, s)
   
   if eInMemory in errorOutputs:
     bufferedMsgs.safeAdd(s)
 
-proc SuggestQuit*() =
+proc suggestQuit*() =
   if not isServing:
     quit(0)
   elif isWorkingWithDirtyBuffer:
@@ -601,12 +622,12 @@ proc pushInfoContext*(info: TLineInfo) =
   msgContext.add(info)
   
 proc popInfoContext*() = 
-  setlen(msgContext, len(msgContext) - 1)
+  setLen(msgContext, len(msgContext) - 1)
 
 proc getInfoContext*(index: int): TLineInfo =
   let L = msgContext.len
   let i = if index < 0: L + index else: index
-  if i >=% L: result = UnknownLineInfo()
+  if i >=% L: result = unknownLineInfo()
   else: result = msgContext[i]
 
 proc toFilename*(fileIdx: int32): string =
@@ -643,6 +664,8 @@ proc toFileLine*(info: TLineInfo): string {.inline.} =
 proc toFileLineCol*(info: TLineInfo): string {.inline.} =
   result = info.toFilename & "(" & $info.line & "," & $info.col & ")"
 
+template `$`*(info: TLineInfo): expr = toFileLineCol(info)
+
 proc `??`* (info: TLineInfo, filename: string): bool =
   # only for debugging purposes
   result = filename in info.toFilename
@@ -656,18 +679,18 @@ proc addCheckpoint*(info: TLineInfo) =
 proc addCheckpoint*(filename: string, line: int) = 
   addCheckpoint(newLineInfo(filename, line, - 1))
 
-proc OutWriteln*(s: string) = 
+proc outWriteln*(s: string) = 
   ## Writes to stdout. Always.
-  if eStdOut in errorOutputs: Writeln(stdout, s)
+  if eStdOut in errorOutputs: writeln(stdout, s)
  
-proc MsgWriteln*(s: string) = 
+proc msgWriteln*(s: string) = 
   ## Writes to stdout. If --stdout option is given, writes to stderr instead.
   if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
 
   if optStdout in gGlobalOptions:
-    if eStdErr in errorOutputs: Writeln(stderr, s)
+    if eStdErr in errorOutputs: writeln(stderr, s)
   else:
-    if eStdOut in errorOutputs: Writeln(stdout, s)
+    if eStdOut in errorOutputs: writeln(stdout, s)
   
   if eInMemory in errorOutputs: bufferedMsgs.safeAdd(s)
 
@@ -675,9 +698,9 @@ proc coordToStr(coord: int): string =
   if coord == -1: result = "???"
   else: result = $coord
   
-proc MsgKindToString*(kind: TMsgKind): string = 
+proc msgKindToString*(kind: TMsgKind): string = 
   # later versions may provide translated error messages
-  result = msgKindToStr[kind]
+  result = MsgKindToStr[kind]
 
 proc getMessageStr(msg: TMsgKind, arg: string): string = 
   result = msgKindToString(msg) % [arg]
@@ -699,58 +722,55 @@ type
   TErrorHandling = enum doNothing, doAbort, doRaise
 
 proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
-  template maybeTrace =
-    if defined(debug) or gVerbosity >= 3:
+  template quit =
+    if defined(debug) or gVerbosity >= 3 or msg == errInternal:
       writeStackTrace()
+    quit 1
 
-  if msg == errInternal:
-    writeStackTrace() # we always want a stack trace here
-  if msg >= fatalMin and msg <= fatalMax: 
-    maybeTrace()
-    quit(1)
-  if msg >= errMin and msg <= errMax: 
-    maybeTrace()
+  if msg >= fatalMin and msg <= fatalMax:
+    quit()
+  if msg >= errMin and msg <= errMax:
     inc(gErrorCounter)
     options.gExitcode = 1'i8
-    if gErrorCounter >= gErrorMax: 
-      quit(1)
+    if gErrorCounter >= gErrorMax:
+      quit()
     elif eh == doAbort and gCmd != cmdIdeTools:
-      quit(1)
+      quit()
     elif eh == doRaise:
       raiseRecoverableError(s)
 
-proc `==`*(a, b: TLineInfo): bool = 
+proc `==`*(a, b: TLineInfo): bool =
   result = a.line == b.line and a.fileIndex == b.fileIndex
 
 proc writeContext(lastinfo: TLineInfo) = 
-  var info = lastInfo
+  var info = lastinfo
   for i in countup(0, len(msgContext) - 1): 
-    if msgContext[i] != lastInfo and msgContext[i] != info: 
-      MsgWriteln(posContextFormat % [toMsgFilename(msgContext[i]), 
+    if msgContext[i] != lastinfo and msgContext[i] != info: 
+      msgWriteln(PosContextFormat % [toMsgFilename(msgContext[i]), 
                                      coordToStr(msgContext[i].line), 
                                      coordToStr(msgContext[i].col), 
                                      getMessageStr(errInstantiationFrom, "")])
     info = msgContext[i]
 
-proc rawMessage*(msg: TMsgKind, args: openarray[string]) = 
+proc rawMessage*(msg: TMsgKind, args: openArray[string]) = 
   var frmt: string
   case msg
   of errMin..errMax: 
     writeContext(unknownLineInfo())
-    frmt = rawErrorFormat
+    frmt = RawErrorFormat
   of warnMin..warnMax: 
     if optWarns notin gOptions: return 
     if msg notin gNotes: return 
     writeContext(unknownLineInfo())
-    frmt = rawWarningFormat
+    frmt = RawWarningFormat
     inc(gWarnCounter)
   of hintMin..hintMax: 
     if optHints notin gOptions: return 
     if msg notin gNotes: return 
-    frmt = rawHintFormat
+    frmt = RawHintFormat
     inc(gHintCounter)
   let s = `%`(frmt, `%`(msgKindToString(msg), args))
-  MsgWriteln(s)
+  msgWriteln(s)
   handleError(msg, doAbort, s)
 
 proc rawMessage*(msg: TMsgKind, arg: string) = 
@@ -758,8 +778,8 @@ proc rawMessage*(msg: TMsgKind, arg: string) =
 
 proc writeSurroundingSrc(info: TLineInfo) =
   const indent = "  "
-  MsgWriteln(indent & info.sourceLine.ropeToStr)
-  MsgWriteln(indent & repeatChar(info.col, ' ') & '^')
+  msgWriteln(indent & info.sourceLine.ropeToStr)
+  msgWriteln(indent & repeatChar(info.col, ' ') & '^')
 
 proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, 
                eh: TErrorHandling) =
@@ -768,7 +788,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
   case msg
   of errMin..errMax:
     writeContext(info)
-    frmt = posErrorFormat
+    frmt = PosErrorFormat
     # we try to filter error messages so that not two error message
     # in the same file and line are produced:
     #ignoreMsg = lastError == info and eh != doAbort
@@ -776,54 +796,54 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
   of warnMin..warnMax:
     ignoreMsg = optWarns notin gOptions or msg notin gNotes
     if not ignoreMsg: writeContext(info)
-    frmt = posWarningFormat
+    frmt = PosWarningFormat
     inc(gWarnCounter)
   of hintMin..hintMax: 
     ignoreMsg = optHints notin gOptions or msg notin gNotes
-    frmt = posHintFormat
+    frmt = PosHintFormat
     inc(gHintCounter)
   let s = frmt % [toMsgFilename(info), coordToStr(info.line),
                   coordToStr(info.col), getMessageStr(msg, arg)]
   if not ignoreMsg:
-    MsgWriteln(s)
+    msgWriteln(s)
     if optPrintSurroundingSrc and msg in errMin..errMax:
       info.writeSurroundingSrc
   handleError(msg, eh, s)
   
-proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") = 
+proc fatal*(info: TLineInfo, msg: TMsgKind, arg = "") = 
   liMessage(info, msg, arg, doAbort)
 
-proc GlobalError*(info: TLineInfo, msg: TMsgKind, arg = "") = 
+proc globalError*(info: TLineInfo, msg: TMsgKind, arg = "") = 
   liMessage(info, msg, arg, doRaise)
 
-proc GlobalError*(info: TLineInfo, arg: string) =
+proc globalError*(info: TLineInfo, arg: string) =
   liMessage(info, errGenerated, arg, doRaise)
 
-proc LocalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
+proc localError*(info: TLineInfo, msg: TMsgKind, arg = "") =
   liMessage(info, msg, arg, doNothing)
 
-proc LocalError*(info: TLineInfo, arg: string) =
+proc localError*(info: TLineInfo, arg: string) =
   liMessage(info, errGenerated, arg, doNothing)
 
-proc Message*(info: TLineInfo, msg: TMsgKind, arg = "") =
+proc message*(info: TLineInfo, msg: TMsgKind, arg = "") =
   liMessage(info, msg, arg, doNothing)
 
-proc InternalError*(info: TLineInfo, errMsg: string) = 
+proc internalError*(info: TLineInfo, errMsg: string) = 
   if gCmd == cmdIdeTools: return
   writeContext(info)
   liMessage(info, errInternal, errMsg, doAbort)
 
-proc InternalError*(errMsg: string) = 
+proc internalError*(errMsg: string) = 
   if gCmd == cmdIdeTools: return
-  writeContext(UnknownLineInfo())
+  writeContext(unknownLineInfo())
   rawMessage(errInternal, errMsg)
 
-template AssertNotNil*(e: expr): expr =
-  if e == nil: InternalError($InstantiationInfo())
+template assertNotNil*(e: expr): expr =
+  if e == nil: internalError($instantiationInfo())
   e
 
-template InternalAssert*(e: bool): stmt =
-  if not e: InternalError($InstantiationInfo())
+template internalAssert*(e: bool): stmt =
+  if not e: internalError($instantiationInfo())
 
 proc addSourceLine*(fileIdx: int32, line: string) =
   fileInfos[fileIdx].lines.add line.toRope
@@ -837,23 +857,22 @@ proc sourceLine*(i: TLineInfo): PRope =
         addSourceLine i.fileIndex, line.string
     except EIO:
       discard
-  InternalAssert i.fileIndex < fileInfos.len
+  internalAssert i.fileIndex < fileInfos.len
   # can happen if the error points to EOF:
   if i.line > fileInfos[i.fileIndex].lines.len: return nil
 
   result = fileInfos[i.fileIndex].lines[i.line-1]
 
 proc quotedFilename*(i: TLineInfo): PRope =
-  InternalAssert i.fileIndex >= 0
+  internalAssert i.fileIndex >= 0
   result = fileInfos[i.fileIndex].quotedName
 
-ropes.ErrorHandler = proc (err: TRopesError, msg: string, useWarning: bool) =
+ropes.errorHandler = proc (err: TRopesError, msg: string, useWarning: bool) =
   case err
   of rInvalidFormatStr:
     internalError("ropes: invalid format string: " & msg)
   of rTokenTooLong:
     internalError("ropes: token too long: " & msg)
   of rCannotOpenFile:
-    rawMessage(if useWarning: warnCannotOpenFile else: errCannotOpenFile,
-               msg)
- 
+    rawMessage(if useWarning: warnCannotOpenFile else: errCannotOpenFile, msg)
+
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index 7ec566a01..136a0d454 100644
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -49,7 +49,7 @@ proc parseExpr(L: var TLexer, tok: var TToken): bool =
     var b = parseAndExpr(L, tok)
     result = result or b
 
-proc EvalppIf(L: var TLexer, tok: var TToken): bool = 
+proc evalppIf(L: var TLexer, tok: var TToken): bool = 
   ppGetTok(L, tok)            # skip 'if' or 'elif'
   result = parseExpr(L, tok)
   if tok.tokType == tkColon: ppGetTok(L, tok)
@@ -60,7 +60,7 @@ var condStack: seq[bool] = @[]
 proc doEnd(L: var TLexer, tok: var TToken) = 
   if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if")
   ppGetTok(L, tok)            # skip 'end'
-  setlen(condStack, high(condStack))
+  setLen(condStack, high(condStack))
 
 type 
   TJumpDest = enum 
@@ -75,18 +75,18 @@ proc doElse(L: var TLexer, tok: var TToken) =
   
 proc doElif(L: var TLexer, tok: var TToken) = 
   if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if")
-  var res = EvalppIf(L, tok)
+  var res = evalppIf(L, tok)
   if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif)
   else: condStack[high(condStack)] = true
   
 proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) = 
   var nestedIfs = 0
-  while True: 
+  while true: 
     if (tok.ident != nil) and (tok.ident.s == "@"): 
       ppGetTok(L, tok)
       case whichKeyword(tok.ident)
       of wIf: 
-        Inc(nestedIfs)
+        inc(nestedIfs)
       of wElse: 
         if (dest == jdElseEndif) and (nestedIfs == 0): 
           doElse(L, tok)
@@ -99,21 +99,21 @@ proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) =
         if nestedIfs == 0: 
           doEnd(L, tok)
           break 
-        if nestedIfs > 0: Dec(nestedIfs)
+        if nestedIfs > 0: dec(nestedIfs)
       else: 
-        nil
+        discard
       ppGetTok(L, tok)
-    elif tok.tokType == tkEof: 
+    elif tok.tokType == tkEof:
       lexMessage(L, errTokenExpected, "@end")
-    else: 
+    else:
       ppGetTok(L, tok)
   
 proc parseDirective(L: var TLexer, tok: var TToken) = 
   ppGetTok(L, tok)            # skip @
   case whichKeyword(tok.ident)
   of wIf:
-    setlen(condStack, len(condStack) + 1)
-    var res = EvalppIf(L, tok)
+    setLen(condStack, len(condStack) + 1)
+    var res = evalppIf(L, tok)
     condStack[high(condStack)] = res
     if not res: jumpToDirective(L, tok, jdElseEndif)
   of wElif: doElif(L, tok)
@@ -121,7 +121,7 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
   of wEnd: doEnd(L, tok)
   of wWrite: 
     ppGetTok(L, tok)
-    msgs.MsgWriteln(tokToStr(tok))
+    msgs.msgWriteln(tokToStr(tok))
     ppGetTok(L, tok)
   else:
     case tok.ident.s.normalize
@@ -135,13 +135,13 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
       ppGetTok(L, tok)
       var key = tokToStr(tok)
       ppGetTok(L, tok)
-      os.putEnv(key, tokToStr(tok) & os.getenv(key))
+      os.putEnv(key, tokToStr(tok) & os.getEnv(key))
       ppGetTok(L, tok)
     of "appendenv":
       ppGetTok(L, tok)
       var key = tokToStr(tok)
       ppGetTok(L, tok)
-      os.putEnv(key, os.getenv(key) & tokToStr(tok))
+      os.putEnv(key, os.getEnv(key) & tokToStr(tok))
       ppGetTok(L, tok)
     else: lexMessage(L, errInvalidDirectiveX, tokToStr(tok))
   
@@ -196,7 +196,7 @@ proc readConfigFile(filename: string) =
     L: TLexer
     tok: TToken
     stream: PLLStream
-  stream = LLStreamOpen(filename, fmRead)
+  stream = llStreamOpen(filename, fmRead)
   if stream != nil:
     initToken(tok)
     openLexer(L, filename, stream)
@@ -219,7 +219,7 @@ proc getSystemConfigPath(filename: string): string =
     if not existsFile(result): result = joinPath([p, "etc", filename])
     if not existsFile(result): result = "/etc/" & filename
 
-proc LoadConfigs*(cfg: string) =
+proc loadConfigs*(cfg: string) =
   # set default value (can be overwritten):
   if libpath == "": 
     # choose default libpath:
diff --git a/compiler/nimeval.nim b/compiler/nimeval.nim
index a239d4ef2..0ee108d48 100644
--- a/compiler/nimeval.nim
+++ b/compiler/nimeval.nim
@@ -17,11 +17,11 @@ proc execute*(program: string) =
   passes.gIncludeFile = includeModule
   passes.gImportModule = importModule
   initDefines()
-  LoadConfigs(DefaultConfig)
+  loadConfigs(DefaultConfig)
 
   initDefines()
-  DefineSymbol("nimrodvm")
-  when hasFFI: DefineSymbol("nimffi")
+  defineSymbol("nimrodvm")
+  when hasFFI: defineSymbol("nimffi")
   registerPass(verbosePass)
   registerPass(semPass)
   registerPass(vmPass)
@@ -30,4 +30,4 @@ proc execute*(program: string) =
   compileSystemModule()
   var m = makeStdinModule()
   incl(m.flags, sfMainModule)
-  processModule(m, LLStreamOpen(program), nil)
+  processModule(m, llStreamOpen(program), nil)
diff --git a/compiler/nimlexbase.nim b/compiler/nimlexbase.nim
index 6d45a825a..038573c35 100644
--- a/compiler/nimlexbase.nim
+++ b/compiler/nimlexbase.nim
@@ -42,7 +42,7 @@ type
     buf*: cstring
     bufLen*: int              # length of buffer in characters
     stream*: PLLStream        # we read from this stream
-    LineNumber*: int          # the current line number
+    lineNumber*: int          # the current line number
                               # private data:
     sentinel*: int
     lineStart*: int           # index of last line start in buffer
@@ -54,11 +54,11 @@ proc openBaseLexer*(L: var TBaseLexer, inputstream: PLLStream,
 proc closeBaseLexer*(L: var TBaseLexer)
 proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string
 proc getColNumber*(L: TBaseLexer, pos: int): int
-proc HandleCR*(L: var TBaseLexer, pos: int): int
+proc handleCR*(L: var TBaseLexer, pos: int): int
   # Call this if you scanned over CR in the buffer; it returns the
   # position to continue the scanning from. `pos` must be the position
   # of the CR.
-proc HandleLF*(L: var TBaseLexer, pos: int): int
+proc handleLF*(L: var TBaseLexer, pos: int): int
   # Call this if you scanned over LF in the buffer; it returns the the
   # position to continue the scanning from. `pos` must be the position
   # of the LF.
@@ -69,9 +69,9 @@ const
 
 proc closeBaseLexer(L: var TBaseLexer) = 
   dealloc(L.buf)
-  LLStreamClose(L.stream)
+  llStreamClose(L.stream)
 
-proc FillBuffer(L: var TBaseLexer) = 
+proc fillBuffer(L: var TBaseLexer) = 
   var 
     charsRead, toCopy, s: int # all are in characters,
                               # not bytes (in case this
@@ -80,12 +80,12 @@ proc FillBuffer(L: var TBaseLexer) =
   # we know here that pos == L.sentinel, but not if this proc
   # is called the first time by initBaseLexer()
   assert(L.sentinel < L.bufLen)
-  toCopy = L.BufLen - L.sentinel - 1
+  toCopy = L.bufLen - L.sentinel - 1
   assert(toCopy >= 0)
   if toCopy > 0: 
-    MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) 
+    moveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) 
     # "moveMem" handles overlapping regions
-  charsRead = LLStreamRead(L.stream, addr(L.buf[toCopy]), 
+  charsRead = llStreamRead(L.stream, addr(L.buf[toCopy]), 
                            (L.sentinel + 1) * chrSize) div chrSize
   s = toCopy + charsRead
   if charsRead < L.sentinel + 1: 
@@ -96,7 +96,7 @@ proc FillBuffer(L: var TBaseLexer) =
     dec(s)                    # BUGFIX (valgrind)
     while true: 
       assert(s < L.bufLen)
-      while (s >= 0) and not (L.buf[s] in NewLines): Dec(s)
+      while (s >= 0) and not (L.buf[s] in NewLines): dec(s)
       if s >= 0: 
         # we found an appropriate character for a sentinel:
         L.sentinel = s
@@ -104,11 +104,11 @@ proc FillBuffer(L: var TBaseLexer) =
       else: 
         # rather than to give up here because the line is too long,
         # double the buffer's size and try again:
-        oldBufLen = L.BufLen
-        L.bufLen = L.BufLen * 2
+        oldBufLen = L.bufLen
+        L.bufLen = L.bufLen * 2
         L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize))
-        assert(L.bufLen - oldBuflen == oldBufLen)
-        charsRead = LLStreamRead(L.stream, addr(L.buf[oldBufLen]), 
+        assert(L.bufLen - oldBufLen == oldBufLen)
+        charsRead = llStreamRead(L.stream, addr(L.buf[oldBufLen]), 
                                  oldBufLen * chrSize) div chrSize
         if charsRead < oldBufLen: 
           L.buf[oldBufLen + charsRead] = EndOfFile
@@ -126,20 +126,20 @@ proc fillBaseLexer(L: var TBaseLexer, pos: int): int =
     result = 0
   L.lineStart = result
 
-proc HandleCR(L: var TBaseLexer, pos: int): int = 
+proc handleCR(L: var TBaseLexer, pos: int): int = 
   assert(L.buf[pos] == CR)
-  inc(L.linenumber)
+  inc(L.lineNumber)
   result = fillBaseLexer(L, pos)
   if L.buf[result] == LF: 
     result = fillBaseLexer(L, result)
 
-proc HandleLF(L: var TBaseLexer, pos: int): int = 
+proc handleLF(L: var TBaseLexer, pos: int): int = 
   assert(L.buf[pos] == LF)
-  inc(L.linenumber)
+  inc(L.lineNumber)
   result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
   
-proc skip_UTF_8_BOM(L: var TBaseLexer) = 
-  if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'): 
+proc skipUTF8BOM(L: var TBaseLexer) = 
+  if L.buf[0] == '\xEF' and L.buf[1] == '\xBB' and L.buf[2] == '\xBF':
     inc(L.bufpos, 3)
     inc(L.lineStart, 3)
 
@@ -150,10 +150,10 @@ proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen = 8192) =
   L.buf = cast[cstring](alloc(bufLen * chrSize))
   L.sentinel = bufLen - 1
   L.lineStart = 0
-  L.linenumber = 1            # lines start at 1
+  L.lineNumber = 1            # lines start at 1
   L.stream = inputstream
   fillBuffer(L)
-  skip_UTF_8_BOM(L)
+  skipUTF8BOM(L)
 
 proc getColNumber(L: TBaseLexer, pos: int): int = 
   result = abs(pos - L.lineStart)
@@ -166,5 +166,4 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
     inc(i)
   result.add("\n")
   if marker: 
-    result.add(RepeatChar(getColNumber(L, L.bufpos)) & '^' & "\n")
-  
+    result.add(repeatChar(getColNumber(L, L.bufpos)) & '^' & "\n")
diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim
index 2bc94e3f8..38d440ade 100644
--- a/compiler/nimrod.nim
+++ b/compiler/nimrod.nim
@@ -31,12 +31,12 @@ proc prependCurDir(f: string): string =
   else:
     result = f
 
-proc HandleCmdLine() =
+proc handleCmdLine() =
   if paramCount() == 0:
     writeCommandLineUsage()
   else:
     # Process command line arguments:
-    ProcessCmdLine(passCmd1, "")
+    processCmdLine(passCmd1, "")
     if gProjectName != "":
       try:
         gProjectFull = canonicalizePath(gProjectName)
@@ -47,12 +47,12 @@ proc HandleCmdLine() =
       gProjectName = p.name
     else:
       gProjectPath = getCurrentDir()
-    LoadConfigs(DefaultConfig) # load all config files
+    loadConfigs(DefaultConfig) # load all config files
     # now process command line arguments again, because some options in the
     # command line can overwite the config file's settings
     extccomp.initVars()
-    ProcessCmdLine(passCmd2, "")
-    MainCommand()
+    processCmdLine(passCmd2, "")
+    mainCommand()
     if gVerbosity >= 2: echo(GC_getStatistics())
     #echo(GC_getStatistics())
     if msgs.gErrorCounter == 0:
@@ -71,7 +71,7 @@ proc HandleCmdLine() =
             binPath = options.outFile.prependCurDir
           else:
             # Figure out ourselves a valid binary name.
-            binPath = changeFileExt(gProjectFull, exeExt).prependCurDir
+            binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir
           var ex = quoteShell(binPath)
           execExternalProgram(ex & ' ' & service.arguments)
 
@@ -81,8 +81,8 @@ when defined(GC_setMaxPause):
 when compileOption("gc", "v2") or compileOption("gc", "refc"):
   # the new correct mark&sweet collector is too slow :-/
   GC_disableMarkAndSweep()
-condsyms.InitDefines()
+condsyms.initDefines()
 
 when not defined(selftest):
-  HandleCmdLine()
+  handleCmdLine()
   quit(int8(msgs.gErrorCounter > 0))
diff --git a/compiler/nimrod.nimrod.cfg b/compiler/nimrod.nimrod.cfg
index 9fa1b8cba..2c6e6f249 100644
--- a/compiler/nimrod.nimrod.cfg
+++ b/compiler/nimrod.nimrod.cfg
@@ -13,3 +13,11 @@ path:"$lib/packages/docutils"
 define:booting
 import:testability
 
+@if windows:
+  cincludes: "$lib/wrappers/libffi/common"
+@end
+
+define:useStdoutAsStdmsg
+
+cs:partial
+#define:useNodeIds
diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim
index 34f79e14b..d65618e0a 100644
--- a/compiler/nimsets.nim
+++ b/compiler/nimsets.nim
@@ -18,7 +18,7 @@ proc overlap*(a, b: PNode): bool
 proc inSet*(s: PNode, elem: PNode): bool
 proc someInSet*(s: PNode, a, b: PNode): bool
 proc emptyRange*(a, b: PNode): bool
-proc SetHasRange*(s: PNode): bool
+proc setHasRange*(s: PNode): bool
   # returns true if set contains a range (needed by the code generator)
   # these are used for constant folding:
 proc unionSets*(a, b: PNode): PNode
@@ -32,7 +32,7 @@ proc cardSet*(s: PNode): BiggestInt
 
 proc inSet(s: PNode, elem: PNode): bool = 
   if s.kind != nkCurly: 
-    InternalError(s.info, "inSet")
+    internalError(s.info, "inSet")
     return false
   for i in countup(0, sonsLen(s) - 1): 
     if s.sons[i].kind == nkRange: 
@@ -58,10 +58,10 @@ proc overlap(a, b: PNode): bool =
     else:
       result = sameValue(a, b)
 
-proc SomeInSet(s: PNode, a, b: PNode): bool = 
+proc someInSet(s: PNode, a, b: PNode): bool = 
   # checks if some element of a..b is in the set s
   if s.kind != nkCurly:
-    InternalError(s.info, "SomeInSet")
+    internalError(s.info, "SomeInSet")
     return false
   for i in countup(0, sonsLen(s) - 1): 
     if s.sons[i].kind == nkRange: 
@@ -82,12 +82,12 @@ proc toBitSet(s: PNode, b: var TBitSet) =
     if s.sons[i].kind == nkRange: 
       j = getOrdValue(s.sons[i].sons[0])
       while j <= getOrdValue(s.sons[i].sons[1]): 
-        BitSetIncl(b, j - first)
+        bitSetIncl(b, j - first)
         inc(j)
     else: 
-      BitSetIncl(b, getOrdValue(s.sons[i]) - first)
+      bitSetIncl(b, getOrdValue(s.sons[i]) - first)
   
-proc ToTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode = 
+proc toTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode = 
   var 
     a, b, e, first: BiggestInt # a, b are interval borders
     elemType: PType
@@ -98,14 +98,14 @@ proc ToTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
   result.typ = settype
   result.info = info
   e = 0
-  while e < len(s) * elemSize: 
+  while e < len(s) * ElemSize: 
     if bitSetIn(s, e): 
       a = e
       b = e
       while true: 
-        Inc(b)
-        if (b >= len(s) * elemSize) or not bitSetIn(s, b): break 
-      Dec(b)
+        inc(b)
+        if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break 
+      dec(b)
       if a == b: 
         addSon(result, newIntTypeNode(nkIntLit, a + first, elemType))
       else: 
@@ -115,7 +115,7 @@ proc ToTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
         addSon(n, newIntTypeNode(nkIntLit, b + first, elemType))
         addSon(result, n)
       e = b
-    Inc(e)
+    inc(e)
 
 template nodeSetOp(a, b: PNode, op: expr) {.dirty.} = 
   var x, y: TBitSet
@@ -124,10 +124,10 @@ template nodeSetOp(a, b: PNode, op: expr) {.dirty.} =
   op(x, y)
   result = toTreeSet(x, a.typ, a.info)
 
-proc unionSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetUnion)
-proc diffSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetDiff)
-proc intersectSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetIntersect)
-proc symdiffSets(a, b: PNode): PNode = nodeSetOp(a, b, BitSetSymDiff)
+proc unionSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetUnion)
+proc diffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetDiff)
+proc intersectSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
+proc symdiffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
 
 proc containsSets(a, b: PNode): bool = 
   var x, y: TBitSet
@@ -156,11 +156,11 @@ proc cardSet(s: PNode): BiggestInt =
       result = result + getOrdValue(s.sons[i].sons[1]) -
           getOrdValue(s.sons[i].sons[0]) + 1
     else: 
-      Inc(result)
+      inc(result)
   
-proc SetHasRange(s: PNode): bool = 
+proc setHasRange(s: PNode): bool = 
   if s.kind != nkCurly:
-    InternalError(s.info, "SetHasRange")
+    internalError(s.info, "SetHasRange")
     return false
   for i in countup(0, sonsLen(s) - 1): 
     if s.sons[i].kind == nkRange: 
diff --git a/compiler/options.nim b/compiler/options.nim
index c62744485..fa8b77ead 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -100,6 +100,8 @@ var
   gSelectedGC* = gcRefc       # the selected GC
   searchPaths*, lazyPaths*: TLinkedList
   outFile*: string = ""
+  docSeeSrcUrl*: string = ""  # if empty, no seeSrc will be generated. \
+  # The string uses the formatting variables `path` and `line`.
   headerFile*: string = ""
   gVerbosity* = 1             # how verbose the compiler is
   gNumberOfProcessors*: int   # number of processors
@@ -143,7 +145,7 @@ const
 # additional configuration variables:
 var
   gConfigVars* = newStringTable(modeStyleInsensitive)
-  gDllOverrides = newStringtable(modeCaseInsensitive)
+  gDllOverrides = newStringTable(modeCaseInsensitive)
   libpath* = ""
   gProjectName* = "" # holds a name like 'nimrod'
   gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
@@ -159,8 +161,6 @@ var
 
 const oKeepVariableNames* = true
 
-const oUseLateInstantiation* = false
-
 proc mainCommandArg*: string =
   ## This is intended for commands like check or parse
   ## which will work on the main project file unless
@@ -185,7 +185,7 @@ proc getOutFile*(filename, ext: string): string =
   
 proc getPrefixDir*(): string = 
   ## gets the application directory
-  result = SplitPath(getAppDir()).head
+  result = splitPath(getAppDir()).head
 
 proc canonicalizePath*(path: string): string =
   result = path.expandFilename
@@ -193,16 +193,16 @@ proc canonicalizePath*(path: string): string =
 
 proc shortenDir*(dir: string): string = 
   ## returns the interesting part of a dir
-  var prefix = getPrefixDir() & dirSep
+  var prefix = getPrefixDir() & DirSep
   if startsWith(dir, prefix): 
     return substr(dir, len(prefix))
-  prefix = gProjectPath & dirSep
+  prefix = gProjectPath & DirSep
   if startsWith(dir, prefix):
     return substr(dir, len(prefix))
   result = dir
 
 proc removeTrailingDirSep*(path: string): string = 
-  if (len(path) > 0) and (path[len(path) - 1] == dirSep): 
+  if (len(path) > 0) and (path[len(path) - 1] == DirSep): 
     result = substr(path, 0, len(path) - 2)
   else: 
     result = path
@@ -211,21 +211,42 @@ proc getGeneratedPath: string =
   result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
                                                          genSubDir
 
+template newPackageCache(): expr =
+  newStringTable(when FileSystemCaseSensitive:
+                   modeCaseInsensitive
+                 else:
+                   modeCaseSensitive)
+
+var packageCache = newPackageCache()
+
+proc resetPackageCache*() = packageCache = newPackageCache()
+
+iterator myParentDirs(p: string): string =
+  # XXX os's parentDirs is stupid (multiple yields) and triggers an old bug...
+  var current = p
+  while true:
+    current = current.parentDir
+    if current.len == 0: break
+    yield current
+
 proc getPackageName*(path: string): string =
-  var q = 1
-  var b = 0
-  if path[len(path)-1] in {dirsep, altsep}: q = 2
-  for i in countdown(len(path)-q, 0):
-    if path[i] in {dirsep, altsep}:
-      if b == 0: b = i
-      else:
-        let x = path.substr(i+1, b-1)
-        case x.normalize
-        of "lib", "src", "source", "package", "pckg", "library", "private":
-          b = i
-        else:
-          return x.replace('.', '_')
-  result = ""
+  var parents = 0
+  block packageSearch:
+    for d in myParentDirs(path):
+      if packageCache.hasKey(d):
+        #echo "from cache ", d, " |", packageCache[d], "|", path.splitFile.name
+        return packageCache[d]
+      inc parents
+      for file in walkFiles(d / "*.babel"):
+        result = file.splitFile.name
+        break packageSearch
+  # we also store if we didn't find anything:
+  if result.isNil: result = ""
+  for d in myParentDirs(path):
+    #echo "set cache ", d, " |", result, "|", parents
+    packageCache[d] = result
+    dec parents
+    if parents <= 0: break
 
 proc withPackageName*(path: string): string =
   let x = path.getPackageName
@@ -255,15 +276,15 @@ proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
   result = joinPath(subdir, tail)
   #echo "completeGeneratedFilePath(", f, ") = ", result
 
-iterator iterSearchPath*(SearchPaths: TLinkedList): string = 
-  var it = PStrEntry(SearchPaths.head)
+iterator iterSearchPath*(searchPaths: TLinkedList): string = 
+  var it = PStrEntry(searchPaths.head)
   while it != nil:
     yield it.data
-    it = PStrEntry(it.Next)
+    it = PStrEntry(it.next)
 
 proc rawFindFile(f: string): string =
-  for it in iterSearchPath(SearchPaths):
-    result = JoinPath(it, f)
+  for it in iterSearchPath(searchPaths):
+    result = joinPath(it, f)
     if existsFile(result):
       return result.canonicalizePath
   result = ""
@@ -271,14 +292,14 @@ proc rawFindFile(f: string): string =
 proc rawFindFile2(f: string): string =
   var it = PStrEntry(lazyPaths.head)
   while it != nil:
-    result = JoinPath(it.data, f)
+    result = joinPath(it.data, f)
     if existsFile(result):
       bringToFront(lazyPaths, it)
       return result.canonicalizePath
-    it = PStrEntry(it.Next)
+    it = PStrEntry(it.next)
   result = ""
 
-proc FindFile*(f: string): string {.procvar.} = 
+proc findFile*(f: string): string {.procvar.} = 
   result = f.rawFindFile
   if result.len == 0:
     result = f.toLower.rawFindFile
@@ -289,11 +310,11 @@ proc FindFile*(f: string): string {.procvar.} =
 
 proc findModule*(modulename, currentModule: string): string =
   # returns path to module
-  let m = addFileExt(modulename, nimExt)
+  let m = addFileExt(modulename, NimExt)
   let currentPath = currentModule.splitFile.dir
   result = currentPath / m
   if not existsFile(result):
-    result = FindFile(m)
+    result = findFile(m)
 
 proc libCandidates*(s: string, dest: var seq[string]) = 
   var le = strutils.find(s, '(')
@@ -320,7 +341,7 @@ proc inclDynlibOverride*(lib: string) =
 proc isDynlibOverride*(lib: string): bool =
   result = gDllOverrides.hasKey(lib.canonDynlibName)
 
-proc binaryStrSearch*(x: openarray[string], y: string): int = 
+proc binaryStrSearch*(x: openArray[string], y: string): int = 
   var a = 0
   var b = len(x) - 1
   while a <= b: 
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index 283f83906..e94068776 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -42,7 +42,7 @@ const
   MaxStackSize* = 64 ## max required stack size by the VM
 
 proc patternError(n: PNode) = 
-  LocalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
+  localError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
 
 proc add(code: var TPatternCode, op: TOpcode) {.inline.} =
   add(code, chr(ord(op)))
@@ -97,14 +97,14 @@ proc compileConstraints(p: PNode, result: var TPatternCode) =
     of "nosideeffect": result.add(ppNoSideEffect)
     else:
       # check all symkinds:
-      InternalAssert int(high(TSymKind)) < 255
+      internalAssert int(high(TSymKind)) < 255
       for i in low(TSymKind)..high(TSymKind):
         if cmpIgnoreStyle(($i).substr(2), spec) == 0:
           result.add(ppSymKind)
           result.add(chr(i.ord))
           return
       # check all nodekinds:
-      InternalAssert int(high(TNodeKind)) < 255
+      internalAssert int(high(TNodeKind)) < 255
       for i in low(TNodeKind)..high(TNodeKind):
         if cmpIgnoreStyle($i, spec) == 0:
           result.add(ppNodeKind)
@@ -124,8 +124,8 @@ proc semNodeKindConstraints*(p: PNode): PNode =
   if p.len >= 2:
     for i in 1.. <p.len:
       compileConstraints(p.sons[i], result.strVal)
-    if result.strVal.len > maxStackSize-1:
-      InternalError(p.info, "parameter pattern too complex")
+    if result.strVal.len > MaxStackSize-1:
+      internalError(p.info, "parameter pattern too complex")
   else:
     patternError(p)
   result.strVal.add(ppEof)
@@ -216,12 +216,12 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
   of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr: 
     result = isAssignable(owner, n.sons[0])
   else:
-    nil
+    discard
 
 proc matchNodeKinds*(p, n: PNode): bool =
   # matches the parameter constraint 'p' against the concrete AST 'n'. 
   # Efficiency matters here.
-  var stack {.noinit.}: array[0..maxStackSize, bool]
+  var stack {.noinit.}: array[0..MaxStackSize, bool]
   # empty patterns are true:
   stack[0] = true
   var sp = 1
diff --git a/compiler/parser.nim b/compiler/parser.nim
index fd51b04ec..07f5c9de9 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -18,10 +18,10 @@
 # In fact the grammar is generated from this file:
 when isMainModule:
   import pegs
-  var outp = open("compiler/grammar.txt", fmWrite)
+  var outp = open("doc/grammar.txt", fmWrite)
   for line in lines("compiler/parser.nim"):
     if line =~ peg" \s* '#| ' {.*}":
-      outp.writeln matches[0]
+      outp.write matches[0], "\L"
   outp.close
 
 import
@@ -31,12 +31,13 @@ type
   TParser*{.final.} = object  # a TParser object represents a module that
                               # is being parsed
     currInd: int              # current indentation
-    firstTok: bool
+    firstTok, strongSpaces: bool
     lex*: TLexer              # the lexer that is used for parsing
     tok*: TToken              # the current token
+    inPragma: int
+    inSemiStmtList: int
 
-proc ParseAll*(p: var TParser): PNode
-proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
+proc parseAll*(p: var TParser): PNode
 proc closeParser*(p: var TParser)
 proc parseTopLevelStmt*(p: var TParser): PNode
   # implements an iterator. Returns the next top-level statement or
@@ -48,7 +49,6 @@ proc parseString*(s: string, filename: string = "", line: int = 0): PNode
   # correct error messages referring to the original source.
   
 # helpers for the other parsers
-proc getPrecedence*(tok: TToken): int
 proc isOperator*(tok: TToken): bool
 proc getTok*(p: var TParser)
 proc parMessage*(p: TParser, msg: TMsgKind, arg: string = "")
@@ -59,15 +59,15 @@ proc newFloatNodeP*(kind: TNodeKind, floatVal: BiggestFloat, p: TParser): PNode
 proc newStrNodeP*(kind: TNodeKind, strVal: string, p: TParser): PNode
 proc newIdentNodeP*(ident: PIdent, p: TParser): PNode
 proc expectIdentOrKeyw*(p: TParser)
-proc ExpectIdent*(p: TParser)
+proc expectIdent*(p: TParser)
 proc parLineInfo*(p: TParser): TLineInfo
-proc Eat*(p: var TParser, TokType: TTokType)
+proc eat*(p: var TParser, tokType: TTokType)
 proc skipInd*(p: var TParser)
 proc optPar*(p: var TParser)
 proc optInd*(p: var TParser, n: PNode)
 proc indAndComment*(p: var TParser, n: PNode)
 proc setBaseFlags*(n: PNode, base: TNumericalBase)
-proc parseSymbol*(p: var TParser): PNode
+proc parseSymbol*(p: var TParser, allowNil = false): PNode
 proc parseTry(p: var TParser): PNode
 proc parseCase(p: var TParser): PNode
 # implementation
@@ -75,17 +75,20 @@ proc parseCase(p: var TParser): PNode
 proc getTok(p: var TParser) = 
   rawGetTok(p.lex, p.tok)
 
-proc OpenParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream) =
+proc openParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream,
+                 strongSpaces=false) =
   initToken(p.tok)
-  OpenLexer(p.lex, fileIdx, inputstream)
+  openLexer(p.lex, fileIdx, inputStream)
   getTok(p)                   # read the first token
   p.firstTok = true
+  p.strongSpaces = strongSpaces
 
-proc OpenParser*(p: var TParser, filename: string, inputStream: PLLStream) =
-  openParser(p, filename.fileInfoIdx, inputStream)
+proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
+                 strongSpaces=false) =
+  openParser(p, filename.fileInfoIdx, inputstream, strongSpaces)
 
-proc CloseParser(p: var TParser) = 
-  CloseLexer(p.lex)
+proc closeParser(p: var TParser) = 
+  closeLexer(p.lex)
 
 proc parMessage(p: TParser, msg: TMsgKind, arg: string = "") = 
   lexMessage(p.lex, msg, arg)
@@ -135,12 +138,12 @@ proc expectIdentOrKeyw(p: TParser) =
   if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
     lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok))
   
-proc ExpectIdent(p: TParser) =
+proc expectIdent(p: TParser) =
   if p.tok.tokType != tkSymbol:
     lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok))
   
-proc Eat(p: var TParser, TokType: TTokType) =
-  if p.tok.TokType == TokType: getTok(p)
+proc eat(p: var TParser, tokType: TTokType) =
+  if p.tok.tokType == tokType: getTok(p)
   else: lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType])
   
 proc parLineInfo(p: TParser): TLineInfo =
@@ -185,40 +188,58 @@ proc relevantOprChar(ident: PIdent): char {.inline.} =
   if result == '\\' and L > 1:
     result = ident.s[1]
 
-proc IsSigilLike(tok: TToken): bool {.inline.} =
+proc isSigilLike(tok: TToken): bool {.inline.} =
   result = tok.tokType == tkOpr and relevantOprChar(tok.ident) == '@'
 
-proc IsLeftAssociative(tok: TToken): bool {.inline.} =
+proc isLeftAssociative(tok: TToken): bool {.inline.} =
   result = tok.tokType != tkOpr or relevantOprChar(tok.ident) != '^'
 
-proc getPrecedence(tok: TToken): int = 
+proc getPrecedence(tok: TToken, strongSpaces: bool): int =
+  template considerStrongSpaces(x): expr =
+    x + (if strongSpaces: 100 - tok.strongSpaceA.int*10 else: 0)
+
   case tok.tokType
   of tkOpr:
     let L = tok.ident.s.len
     let relevantChar = relevantOprChar(tok.ident)
     
-    template considerAsgn(value: expr) = 
-      result = if tok.ident.s[L-1] == '=': 1 else: value     
+    template considerAsgn(value: expr) =
+      result = if tok.ident.s[L-1] == '=': 1 else: considerStrongSpaces(value)
     
     case relevantChar
     of '$', '^': considerAsgn(10)
     of '*', '%', '/', '\\': considerAsgn(9)
-    of '~': result = 8
+    of '~': result = considerStrongSpaces(8)
     of '+', '-', '|': considerAsgn(8)
     of '&': considerAsgn(7)
-    of '=', '<', '>', '!': result = 5
+    of '=', '<', '>', '!': result = considerStrongSpaces(5)
     of '.': considerAsgn(6)
-    of '?': result = 2
+    of '?': result = considerStrongSpaces(2)
     else: considerAsgn(2)
   of tkDiv, tkMod, tkShl, tkShr: result = 9
-  of tkIn, tkNotIn, tkIs, tkIsNot, tkNot, tkOf, tkAs: result = 5
-  of tkDotDot: result = 6
+  of tkIn, tkNotin, tkIs, tkIsnot, tkNot, tkOf, tkAs: result = 5
+  of tkDotDot: result = considerStrongSpaces(6)
   of tkAnd: result = 4
   of tkOr, tkXor: result = 3
-  else: result = - 10
-  
-proc isOperator(tok: TToken): bool = 
-  result = getPrecedence(tok) >= 0
+  else: result = -10
+
+proc isOperator(tok: TToken): bool =
+  tok.tokType in {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
+                  tkIsnot, tkNot, tkOf, tkAs, tkDotDot, tkAnd, tkOr, tkXor}
+
+proc isUnary(p: TParser): bool =
+  p.strongSpaces and p.tok.tokType in {tkOpr, tkDotDot} and
+    p.tok.strongSpaceB == 0 and
+    p.tok.strongSpaceA > 0
+
+proc checkBinary(p: TParser) {.inline.} =
+  # we don't check '..' here as that's too annoying
+  if p.strongSpaces and p.tok.tokType == tkOpr:
+    if p.tok.strongSpaceB > 0 and p.tok.strongSpaceA != p.tok.strongSpaceB:
+      parMessage(p, errGenerated, "number of spaces around '$#' not consistent"%
+        prettyTok(p.tok))
+    elif p.tok.strongSpaceA notin {0,1,2,4,8}:
+      parMessage(p, errGenerated, "number of spaces must be 0,1,2,4 or 8")
 
 #| module = stmt ^* (';' / IND{=})
 #|
@@ -252,7 +273,7 @@ proc colcom(p: var TParser, n: PNode) =
   eat(p, tkColon)
   skipComment(p, n)
 
-proc parseSymbol(p: var TParser): PNode =
+proc parseSymbol(p: var TParser, allowNil = false): PNode =
   #| symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`'
   #|        | IDENT
   case p.tok.tokType
@@ -279,7 +300,7 @@ proc parseSymbol(p: var TParser): PNode =
         add(result, newIdentNodeP(getIdent"{}", p))
         getTok(p)
         eat(p, tkCurlyRi)
-      of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot:
+      of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDot, tkDotDot:
         add(result, newIdentNodeP(p.tok.ident, p))
         getTok(p)
       of tkIntLit..tkCharLit:
@@ -291,9 +312,13 @@ proc parseSymbol(p: var TParser): PNode =
         break
     eat(p, tkAccent)
   else:
-    parMessage(p, errIdentifierExpected, p.tok)
-    getTok(p) # BUGFIX: We must consume a token here to prevent endless loops!
-    result = ast.emptyNode
+    if allowNil and p.tok.tokType == tkNil:
+      result = newNodeP(nkNilLit, p)
+      getTok(p)
+    else:
+      parMessage(p, errIdentifierExpected, p.tok)
+      getTok(p) # BUGFIX: We must consume a token here to prevent endless loops!
+      result = ast.emptyNode
 
 proc indexExpr(p: var TParser): PNode = 
   #| indexExpr = expr
@@ -427,7 +452,7 @@ proc parseCast(p: var TParser): PNode =
 
 proc setBaseFlags(n: PNode, base: TNumericalBase) = 
   case base
-  of base10: nil
+  of base10: discard
   of base2: incl(n.flags, nfBase2)
   of base8: incl(n.flags, nfBase8)
   of base16: incl(n.flags, nfBase16)
@@ -454,11 +479,13 @@ proc complexOrSimpleStmt(p: var TParser): PNode
 proc simpleExpr(p: var TParser, mode = pmNormal): PNode
 
 proc semiStmtList(p: var TParser, result: PNode) =
+  inc p.inSemiStmtList
   result.add(complexOrSimpleStmt(p))
-  while p.tok.tokType == tkSemicolon:
+  while p.tok.tokType == tkSemiColon:
     getTok(p)
     optInd(p, result)
     result.add(complexOrSimpleStmt(p))
+  dec p.inSemiStmtList
   result.kind = nkStmtListExpr
 
 proc parsePar(p: var TParser): PNode =
@@ -482,7 +509,7 @@ proc parsePar(p: var TParser): PNode =
     # XXX 'bind' used to be an expression, so we exclude it here;
     # tests/reject/tbind2 fails otherwise.
     semiStmtList(p, result)
-  elif p.tok.tokType == tkSemicolon:
+  elif p.tok.tokType == tkSemiColon:
     # '(;' enforces 'stmt' context:
     getTok(p)
     optInd(p, result)
@@ -498,7 +525,9 @@ proc parsePar(p: var TParser): PNode =
       asgn.sons[0] = a
       asgn.sons[1] = b
       result.add(asgn)
-    elif p.tok.tokType == tkSemicolon:
+      if p.tok.tokType == tkSemiColon:
+        semiStmtList(p, result)
+    elif p.tok.tokType == tkSemiColon:
       # stmt context:
       result.add(a)
       semiStmtList(p, result)
@@ -518,14 +547,14 @@ proc parsePar(p: var TParser): PNode =
   eat(p, tkParRi)
 
 proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode = 
+  #| literal = | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
+  #|           | UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
+  #|           | FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
+  #|           | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
+  #|           | CHAR_LIT
+  #|           | NIL
   #| generalizedLit = GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
-  #| identOrLiteral = generalizedLit | symbol 
-  #|                | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
-  #|                | UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
-  #|                | FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
-  #|                | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
-  #|                | CHAR_LIT
-  #|                | NIL
+  #| identOrLiteral = generalizedLit | symbol | literal
   #|                | par | arrayConstr | setOrTableConstr
   #|                | castExpr
   #| tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
@@ -634,16 +663,20 @@ proc namedParams(p: var TParser, callee: PNode,
   addSon(result, a)
   exprColonEqExprListAux(p, endTok, result)
 
-proc primarySuffix(p: var TParser, r: PNode): PNode =
+proc parseMacroColon(p: var TParser, x: PNode): PNode
+proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
   #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
   #|               | doBlocks
   #|               | '.' optInd ('type' | 'addr' | symbol) generalizedLit?
   #|               | '[' optInd indexExprList optPar ']'
   #|               | '{' optInd indexExprList optPar '}'
+  #|               | &( '`'|IDENT|literal|'cast') expr # command syntax
   result = r
-  while p.tok.indent < 0:
+  while p.tok.indent < 0 or
+       (p.tok.tokType == tkDot and p.tok.indent >= baseIndent):
     case p.tok.tokType
     of tkParLe:
+      if p.strongSpaces and p.tok.strongSpaceA > 0: break
       result = namedParams(p, result, nkCall, tkParRi)
       if result.len > 1 and result.sons[1].kind == nkExprColonExpr:
         result.kind = nkObjConstr
@@ -658,21 +691,47 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
       result = dotExpr(p, result)
       result = parseGStrLit(p, result)
     of tkBracketLe:
+      if p.strongSpaces and p.tok.strongSpaceA > 0: break
       result = namedParams(p, result, nkBracketExpr, tkBracketRi)
     of tkCurlyLe:
+      if p.strongSpaces and p.tok.strongSpaceA > 0: break
       result = namedParams(p, result, nkCurlyExpr, tkCurlyRi)
-    else: break
-
+    of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast:
+      if p.inPragma == 0:
+        # actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
+        # solution, but pragmas.nim can't handle that
+        let a = result
+        result = newNodeP(nkCommand, p)
+        addSon(result, a)
+        addSon result, parseExpr(p)
+        when false:
+          while p.tok.tokType != tkEof:
+            let a = parseExpr(p)
+            addSon(result, a)
+            if p.tok.tokType != tkComma: break
+            getTok(p)
+            optInd(p, a)
+          if p.tok.tokType == tkDo:
+            parseDoBlocks(p, result)
+          else:
+            result = parseMacroColon(p, result)
+      break
+    else:
+      break
+    
 proc primary(p: var TParser, mode: TPrimaryMode): PNode
+proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode
 
-proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
-  result = primary(p, mode)
+proc parseOperators(p: var TParser, headNode: PNode,
+                    limit: int, mode: TPrimaryMode): PNode =
+  result = headNode
   # expand while operators have priorities higher than 'limit'
-  var opPrec = getPrecedence(p.tok)
+  var opPrec = getPrecedence(p.tok, p.strongSpaces)
   let modeB = if mode == pmTypeDef: pmTypeDesc else: mode
   # the operator itself must not start on a new line:
-  while opPrec >= limit and p.tok.indent < 0:
-    var leftAssoc = ord(IsLeftAssociative(p.tok))
+  while opPrec >= limit and p.tok.indent < 0 and not isUnary(p):
+    checkBinary(p)
+    var leftAssoc = ord(isLeftAssociative(p.tok))
     var a = newNodeP(nkInfix, p)
     var opNode = newIdentNodeP(p.tok.ident, p) # skip operator:
     getTok(p)
@@ -683,7 +742,11 @@ proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
     addSon(a, result)
     addSon(a, b)
     result = a
-    opPrec = getPrecedence(p.tok)
+    opPrec = getPrecedence(p.tok, p.strongSpaces)
+
+proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
+  result = primary(p, mode)
+  result = parseOperators(p, result, limit, mode)
   
 proc simpleExpr(p: var TParser, mode = pmNormal): PNode =
   result = simpleExprAux(p, -1, mode)
@@ -713,6 +776,7 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
 proc parsePragma(p: var TParser): PNode =
   #| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
   result = newNodeP(nkPragma, p)
+  inc p.inPragma
   getTok(p)
   optInd(p, result)
   while p.tok.tokType notin {tkCurlyDotRi, tkCurlyRi, tkEof}:
@@ -724,6 +788,7 @@ proc parsePragma(p: var TParser): PNode =
   optPar(p)
   if p.tok.tokType in {tkCurlyDotRi, tkCurlyRi}: getTok(p)
   else: parMessage(p, errTokenExpected, ".}")
+  dec p.inPragma
   
 proc identVis(p: var TParser): PNode = 
   #| identVis = symbol opr?  # postfix position
@@ -798,7 +863,7 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
     while p.tok.tokType in {tkSymbol, tkAccent}:
       var a = parseIdentColonEquals(p, {})
       addSon(result, a)
-      if p.tok.tokType notin {tkComma, tkSemicolon}: break
+      if p.tok.tokType notin {tkComma, tkSemiColon}: break
       getTok(p)
       skipComment(p, a)
     optPar(p)
@@ -840,13 +905,13 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
         parMessage(p, errTokenExpected, ")")
         break 
       addSon(result, a)
-      if p.tok.tokType notin {tkComma, tkSemicolon}: break 
+      if p.tok.tokType notin {tkComma, tkSemiColon}: break 
       getTok(p)
       skipComment(p, a)
     optPar(p)
     eat(p, tkParRi)
   let hasRet = if retColon: p.tok.tokType == tkColon
-               else: p.tok.tokType == tkOpr and IdentEq(p.tok.ident, "->")
+               else: p.tok.tokType == tkOpr and identEq(p.tok.ident, "->")
   if hasRet and p.tok.indent < 0:
     getTok(p)
     optInd(p, result)
@@ -905,14 +970,30 @@ proc isExprStart(p: TParser): bool =
      tkTuple, tkObject, tkType, tkWhen, tkCase, tkShared:
     result = true
   else: result = false
-  
-proc parseTypeDescKAux(p: var TParser, kind: TNodeKind, 
-                       mode: TPrimaryMode): PNode = 
+
+proc parseSymbolList(p: var TParser, result: PNode, allowNil = false) =
+  while true:
+    var s = parseSymbol(p, allowNil)
+    if s.kind == nkEmpty: break
+    addSon(result, s)
+    if p.tok.tokType != tkComma: break
+    getTok(p)
+    optInd(p, s)
+
+proc parseTypeDescKAux(p: var TParser, kind: TNodeKind,
+                       mode: TPrimaryMode): PNode =
   result = newNodeP(kind, p)
   getTok(p)
   optInd(p, result)
   if not isOperator(p.tok) and isExprStart(p):
     addSon(result, primary(p, mode))
+  if kind == nkDistinctTy and p.tok.tokType in {tkWith, tkWithout}:
+    let nodeKind = if p.tok.tokType == tkWith: nkWith
+                   else: nkWithout
+    getTok(p)
+    let list = newNodeP(nodeKind, p)
+    result.addSon list
+    parseSymbolList(p, list, allowNil = true)
 
 proc parseExpr(p: var TParser): PNode = 
   #| expr = (ifExpr
@@ -929,7 +1010,6 @@ proc parseExpr(p: var TParser): PNode =
 
 proc parseEnum(p: var TParser): PNode
 proc parseObject(p: var TParser): PNode
-proc parseDistinct(p: var TParser): PNode
 proc parseTypeClass(p: var TParser): PNode
 
 proc primary(p: var TParser, mode: TPrimaryMode): PNode = 
@@ -941,7 +1021,7 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
   #|         / 'static' primary
   #|         / 'bind' primary
   if isOperator(p.tok):
-    let isSigil = IsSigilLike(p.tok)
+    let isSigil = isSigilLike(p.tok)
     result = newNodeP(nkPrefix, p)
     var a = newIdentNodeP(p.tok.ident, p)
     addSon(result, a)
@@ -949,8 +1029,9 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
     optInd(p, a)
     if isSigil: 
       #XXX prefix operators
+      let baseInd = p.lex.currLineIndent
       addSon(result, primary(p, pmSkipSuffix))
-      result = primarySuffix(p, result)
+      result = primarySuffix(p, result, baseInd)
     else:
       addSon(result, primary(p, pmNormal))
     return
@@ -965,14 +1046,19 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
   of tkTuple: result = parseTuple(p, mode == pmTypeDef)
   of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})
   of tkIterator:
-    if mode in {pmTypeDesc, pmTypeDef}:
-      result = parseProcExpr(p, false)
-      result.kind = nkIteratorTy
+    when false:
+      if mode in {pmTypeDesc, pmTypeDef}:
+        result = parseProcExpr(p, false)
+        result.kind = nkIteratorTy
+      else:
+        # no anon iterators for now:
+        parMessage(p, errExprExpected, p.tok)
+        getTok(p)  # we must consume a token here to prevend endless loops!
+        result = ast.emptyNode
     else:
-      # no anon iterators for now:
-      parMessage(p, errExprExpected, p.tok)
-      getTok(p)  # we must consume a token here to prevend endless loops!
-      result = ast.emptyNode
+      result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})
+      if result.kind == nkLambda: result.kind = nkIteratorDef
+      else: result.kind = nkIteratorTy
   of tkEnum:
     if mode == pmTypeDef:
       result = parseEnum(p)
@@ -995,18 +1081,23 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
     getTokNoInd(p)
     addSon(result, primary(p, pmNormal))
   of tkStatic:
-    result = newNodeP(nkStaticExpr, p)
+    let info = parLineInfo(p)
     getTokNoInd(p)
-    addSon(result, primary(p, pmNormal))
+    let next = primary(p, pmNormal)
+    if next.kind == nkBracket and next.sonsLen == 1:
+      result = newNode(nkStaticTy, info, @[next.sons[0]])
+    else:
+      result = newNode(nkStaticExpr, info, @[next])
   of tkBind:
     result = newNodeP(nkBind, p)
     getTok(p)
     optInd(p, result)
     addSon(result, primary(p, pmNormal))
   else:
+    let baseInd = p.lex.currLineIndent
     result = identOrLiteral(p, mode)
     if mode != pmSkipSuffix:
-      result = primarySuffix(p, result)
+      result = primarySuffix(p, result, baseInd)
 
 proc parseTypeDesc(p: var TParser): PNode =
   #| typeDesc = simpleExpr
@@ -1014,6 +1105,7 @@ proc parseTypeDesc(p: var TParser): PNode =
 
 proc parseTypeDefAux(p: var TParser): PNode = 
   #| typeDefAux = simpleExpr
+  #|            | 'generic' typeClass
   result = simpleExpr(p, pmTypeDef)
 
 proc makeCall(n: PNode): PNode =
@@ -1023,17 +1115,54 @@ proc makeCall(n: PNode): PNode =
     result = newNodeI(nkCall, n.info)
     result.add n
 
+proc parseMacroColon(p: var TParser, x: PNode): PNode =
+  #| macroColon = ':' stmt? ( IND{=} 'of' exprList ':' stmt 
+  #|                        | IND{=} 'elif' expr ':' stmt
+  #|                        | IND{=} 'except' exprList ':' stmt
+  #|                        | IND{=} 'else' ':' stmt )*
+  result = x
+  if p.tok.tokType == tkColon and p.tok.indent < 0:
+    result = makeCall(result)
+    getTok(p)
+    skipComment(p, result)
+    if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept}:
+      let body = parseStmt(p)
+      addSon(result, newProcNode(nkDo, body.info, body))
+    while sameInd(p):
+      var b: PNode
+      case p.tok.tokType
+      of tkOf:
+        b = newNodeP(nkOfBranch, p)
+        exprList(p, tkColon, b)
+      of tkElif: 
+        b = newNodeP(nkElifBranch, p)
+        getTok(p)
+        optInd(p, b)
+        addSon(b, parseExpr(p))
+        eat(p, tkColon)
+      of tkExcept: 
+        b = newNodeP(nkExceptBranch, p)
+        exprList(p, tkColon, b)
+        skipComment(p, b)
+      of tkElse: 
+        b = newNodeP(nkElse, p)
+        getTok(p)
+        eat(p, tkColon)
+      else: break 
+      addSon(b, parseStmt(p))
+      addSon(result, b)
+      if b.kind == nkElse: break
+
 proc parseExprStmt(p: var TParser): PNode = 
   #| exprStmt = simpleExpr
   #|          (( '=' optInd expr )
   #|          / ( expr ^+ comma
   #|              doBlocks
-  #|               / ':' stmt? ( IND{=} 'of' exprList ':' stmt 
-  #|                           | IND{=} 'elif' expr ':' stmt
-  #|                           | IND{=} 'except' exprList ':' stmt
-  #|                           | IND{=} 'else' ':' stmt )*
+  #|               / macroColon
   #|            ))?
+  inc p.inPragma
   var a = simpleExpr(p)
+  dec p.inPragma
   if p.tok.tokType == tkEquals: 
     getTok(p)
     optInd(p, result)
@@ -1056,37 +1185,7 @@ proc parseExprStmt(p: var TParser): PNode =
       result = makeCall(result)
       parseDoBlocks(p, result)
       return result
-    if p.tok.tokType == tkColon and p.tok.indent < 0:
-      result = makeCall(result)
-      getTok(p)
-      skipComment(p, result)
-      if p.tok.TokType notin {tkOf, tkElif, tkElse, tkExcept}:
-        let body = parseStmt(p)
-        addSon(result, newProcNode(nkDo, body.info, body))
-      while sameInd(p):
-        var b: PNode
-        case p.tok.tokType
-        of tkOf:
-          b = newNodeP(nkOfBranch, p)
-          exprList(p, tkColon, b)
-        of tkElif: 
-          b = newNodeP(nkElifBranch, p)
-          getTok(p)
-          optInd(p, b)
-          addSon(b, parseExpr(p))
-          eat(p, tkColon)
-        of tkExcept: 
-          b = newNodeP(nkExceptBranch, p)
-          exprList(p, tkColon, b)
-          skipComment(p, b)
-        of tkElse: 
-          b = newNodeP(nkElse, p)
-          getTok(p)
-          eat(p, tkColon)
-        else: break 
-        addSon(b, parseStmt(p))
-        addSon(result, b)
-        if b.kind == nkElse: break
+    result = parseMacroColon(p, result)
 
 proc parseModuleName(p: var TParser, kind: TNodeKind): PNode =
   result = parseExpr(p)
@@ -1169,8 +1268,7 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
   if p.tok.tokType == tkComment:
     skipComment(p, result)
     addSon(result, ast.emptyNode)
-  elif p.tok.indent >= 0 and p.tok.indent <= p.currInd or
-      p.tok.tokType == tkEof:
+  elif p.tok.indent >= 0 and p.tok.indent <= p.currInd or not isExprStart(p):
     # NL terminates:
     addSon(result, ast.emptyNode)
   else:
@@ -1378,7 +1476,7 @@ proc parseGenericParamList(p: var TParser): PNode =
   while p.tok.tokType in {tkSymbol, tkAccent}: 
     var a = parseGenericParam(p)
     addSon(result, a)
-    if p.tok.tokType notin {tkComma, tkSemicolon}: break 
+    if p.tok.tokType notin {tkComma, tkSemiColon}: break 
     getTok(p)
     skipComment(p, a)
   optPar(p)
@@ -1433,7 +1531,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
                   defparser: TDefParser): PNode =
   #| section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
   result = newNodeP(kind, p)
-  getTok(p)
+  if kind != nkTypeSection: getTok(p)
   skipComment(p, result)
   if realInd(p):
     withInd(p):
@@ -1633,12 +1731,15 @@ proc parseTypeClassParam(p: var TParser): PNode =
     result = p.parseSymbol
 
 proc parseTypeClass(p: var TParser): PNode =
+  #| typeClassParam = ('var')? symbol
+  #| typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
+  #|               &IND{>} stmt
   result = newNodeP(nkTypeClassTy, p)
   getTok(p)
   var args = newNode(nkArgList)
   addSon(result, args)
   addSon(args, p.parseTypeClassParam)
-  while p.tok.TokType == tkComma:
+  while p.tok.tokType == tkComma:
     getTok(p)
     addSon(args, p.parseTypeClassParam)
   if p.tok.tokType == tkCurlyDotLe and p.validInd:
@@ -1663,13 +1764,6 @@ proc parseTypeClass(p: var TParser): PNode =
   else:
     addSon(result, parseStmt(p))
 
-proc parseDistinct(p: var TParser): PNode = 
-  #| distinct = 'distinct' optInd typeDesc
-  result = newNodeP(nkDistinctTy, p)
-  getTok(p)
-  optInd(p, result)
-  addSon(result, parseTypeDesc(p))
-
 proc parseTypeDef(p: var TParser): PNode = 
   #| typeDef = identWithPragma genericParamList? '=' optInd typeDefAux
   #|             indAndComment?
@@ -1791,7 +1885,16 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
   of tkMacro: result = parseRoutine(p, nkMacroDef)
   of tkTemplate: result = parseRoutine(p, nkTemplateDef)
   of tkConverter: result = parseRoutine(p, nkConverterDef)
-  of tkType: result = parseSection(p, nkTypeSection, parseTypeDef)
+  of tkType:
+    getTok(p)
+    if p.tok.tokType == tkParLe:
+      getTok(p)
+      result = newNodeP(nkTypeOfExpr, p)
+      result.addSon(primary(p, pmTypeDesc))
+      eat(p, tkParRi)
+      result = parseOperators(p, result, -1, pmNormal)
+    else:
+      result = parseSection(p, nkTypeSection, parseTypeDef)
   of tkConst: result = parseSection(p, nkConstSection, parseConstant)
   of tkLet: result = parseSection(p, nkLetSection, parseVariable)
   of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
@@ -1809,16 +1912,16 @@ proc parseStmt(p: var TParser): PNode =
     withInd(p):
       while true:
         if p.tok.indent == p.currInd:
-          nil
-        elif p.tok.tokType == tkSemicolon:
+          discard
+        elif p.tok.tokType == tkSemiColon:
           getTok(p)
           if p.tok.indent < 0 or p.tok.indent == p.currInd: discard
           else: break
         else:
-          if p.tok.indent > p.currInd:
+          if p.tok.indent > p.currInd and p.tok.tokType != tkDot:
             parMessage(p, errInvalidIndentation)
           break
-        if p.tok.toktype in {tkCurlyRi, tkParRi, tkCurlyDotRi, tkBracketRi}:
+        if p.tok.tokType in {tkCurlyRi, tkParRi, tkCurlyDotRi, tkBracketRi}:
           # XXX this ensures tnamedparamanonproc still compiles;
           # deprecate this syntax later
           break
@@ -1836,14 +1939,19 @@ proc parseStmt(p: var TParser): PNode =
       parMessage(p, errComplexStmtRequiresInd)
       result = ast.emptyNode
     else:
-      result = newNodeP(nkStmtList, p)
-      while true:
-        if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)     
-        let a = simpleStmt(p)
-        if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
-        result.add(a)
-        if p.tok.tokType != tkSemicolon: break
-        getTok(p)
+      if p.inSemiStmtList > 0:
+        result = simpleStmt(p)
+        if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
+      else:
+        result = newNodeP(nkStmtList, p)
+        while true:
+          if p.tok.indent >= 0:
+            parMessage(p, errInvalidIndentation)
+          let a = simpleStmt(p)
+          if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
+          result.add(a)
+          if p.tok.tokType != tkSemiColon: break
+          getTok(p)
   
 proc parseAll(p: var TParser): PNode = 
   result = newNodeP(nkStmtList, p)
@@ -1862,11 +1970,11 @@ proc parseTopLevelStmt(p: var TParser): PNode =
   result = ast.emptyNode
   while true:
     if p.tok.indent != 0: 
-      if p.firstTok and p.tok.indent < 0: nil
+      if p.firstTok and p.tok.indent < 0: discard
       else: parMessage(p, errInvalidIndentation)
     p.firstTok = false
     case p.tok.tokType
-    of tkSemicolon:
+    of tkSemiColon:
       getTok(p)
       if p.tok.indent <= 0: discard
       else: parMessage(p, errInvalidIndentation)
@@ -1877,11 +1985,13 @@ proc parseTopLevelStmt(p: var TParser): PNode =
       break
 
 proc parseString(s: string, filename: string = "", line: int = 0): PNode =
-  var stream = LLStreamOpen(s)
+  var stream = llStreamOpen(s)
   stream.lineOffset = line
 
   var parser: TParser
-  OpenParser(parser, filename, stream)
+  # XXX for now the builtin 'parseStmt/Expr' functions do not know about strong
+  # spaces...
+  openParser(parser, filename, stream, false)
 
   result = parser.parseAll
-  CloseParser(parser)
+  closeParser(parser)
diff --git a/compiler/pas2nim/pas2nim.nim b/compiler/pas2nim/pas2nim.nim
index ce5eb5c1a..d10028167 100644
--- a/compiler/pas2nim/pas2nim.nim
+++ b/compiler/pas2nim/pas2nim.nim
@@ -26,7 +26,7 @@ Options:
 """
 
 proc main(infile, outfile: string, flags: set[TParserFlag]) =
-  var stream = LLStreamOpen(infile, fmRead)
+  var stream = llStreamOpen(infile, fmRead)
   if stream == nil: rawMessage(errCannotOpenFile, infile)
   var p: TParser
   openParser(p, infile, stream, flags)
diff --git a/compiler/pas2nim/paslex.nim b/compiler/pas2nim/paslex.nim
index 94e664832..f24b0c420 100644
--- a/compiler/pas2nim/paslex.nim
+++ b/compiler/pas2nim/paslex.nim
@@ -78,7 +78,7 @@ type
 
 
 proc getTok*(L: var TLexer, tok: var TToken)
-proc PrintTok*(tok: TToken)
+proc printTok*(tok: TToken)
 proc `$`*(tok: TToken): string
 # implementation
 
@@ -109,17 +109,17 @@ proc getLineInfo*(L: TLexer): TLineInfo =
   result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
 
 proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
-  msgs.GlobalError(getLineInfo(L), msg, arg)
+  msgs.globalError(getLineInfo(L), msg, arg)
 
 proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
   var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
-  msgs.GlobalError(info, msg, arg)
+  msgs.globalError(info, msg, arg)
 
-proc TokKindToStr*(k: TTokKind): string =
+proc tokKindToStr*(k: TTokKind): string =
   case k
   of pxEof: result = "[EOF]"
   of firstKeyword..lastKeyword:
-    result = keywords[ord(k)-ord(firstKeyword)]
+    result = Keywords[ord(k)-ord(firstKeyword)]
   of pxInvalid, pxComment, pxStrLit: result = "string literal"
   of pxCommand: result = "{@"
   of pxAmp: result = "{&"
@@ -160,9 +160,9 @@ proc `$`(tok: TToken): string =
   of pxSymbol: result = tok.ident.s
   of pxIntLit, pxInt64Lit: result = $tok.iNumber
   of pxFloatLit: result = $tok.fNumber
-  else: result = TokKindToStr(tok.xkind)
+  else: result = tokKindToStr(tok.xkind)
 
-proc PrintTok(tok: TToken) =
+proc printTok(tok: TToken) =
   writeln(stdout, $tok)
 
 proc setKeyword(L: var TLexer, tok: var TToken) =
@@ -177,12 +177,12 @@ proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
   while true:
     if buf[pos] in chars:
       add(tok.literal, buf[pos])
-      Inc(pos)
+      inc(pos)
     else:
       break
     if buf[pos] == '_':
       add(tok.literal, '_')
-      Inc(pos)
+      inc(pos)
   L.bufPos = pos
 
 proc isFloatLiteral(s: string): bool =
@@ -199,7 +199,7 @@ proc getNumber2(L: var TLexer, tok: var TToken) =
     inc(L.bufpos)
     return
   tok.base = base2
-  var xi: biggestInt = 0
+  var xi: BiggestInt = 0
   var bits = 0
   while true:
     case L.buf[pos]
@@ -221,7 +221,7 @@ proc getNumber2(L: var TLexer, tok: var TToken) =
 proc getNumber16(L: var TLexer, tok: var TToken) =
   var pos = L.bufpos + 1          # skip $
   tok.base = base16
-  var xi: biggestInt = 0
+  var xi: BiggestInt = 0
   var bits = 0
   while true:
     case L.buf[pos]
@@ -261,7 +261,7 @@ proc getNumber10(L: var TLexer, tok: var TToken) =
       tok.fnumber = parseFloat(tok.literal)
       tok.xkind = pxFloatLit
     else:
-      tok.iNumber = ParseInt(tok.literal)
+      tok.iNumber = parseInt(tok.literal)
       if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)):
         tok.xkind = pxInt64Lit
       else:
@@ -271,10 +271,10 @@ proc getNumber10(L: var TLexer, tok: var TToken) =
   except EOverflow:
     lexMessage(L, errNumberOutOfRange, tok.literal)
 
-proc HandleCRLF(L: var TLexer, pos: int): int =
+proc handleCRLF(L: var TLexer, pos: int): int =
   case L.buf[pos]
-  of CR: result = nimlexbase.HandleCR(L, pos)
-  of LF: result = nimlexbase.HandleLF(L, pos)
+  of CR: result = nimlexbase.handleCR(L, pos)
+  of LF: result = nimlexbase.handleLF(L, pos)
   else: result = pos
 
 proc getString(L: var TLexer, tok: var TToken) =
@@ -319,7 +319,7 @@ proc getString(L: var TLexer, tok: var TToken) =
           xi = (xi * 10) + (ord(buf[pos]) - ord('0'))
           inc(pos)
       else: lexMessage(L, errInvalidCharacterConstant)
-      if (xi <= 255): add(tok.literal, Chr(xi))
+      if (xi <= 255): add(tok.literal, chr(xi))
       else: lexMessage(L, errInvalidCharacterConstant)
     else:
       break
@@ -334,17 +334,17 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
     var c = buf[pos]
     case c
     of 'a'..'z', '0'..'9', '\x80'..'\xFF':
-      h = h +% Ord(c)
+      h = h +% ord(c)
       h = h +% h shl 10
       h = h xor (h shr 6)
     of 'A'..'Z':
       c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
-      h = h +% Ord(c)
+      h = h +% ord(c)
       h = h +% h shl 10
       h = h xor (h shr 6)
-    of '_': nil
+    of '_': discard
     else: break
-    Inc(pos)
+    inc(pos)
   h = h +% h shl 3
   h = h xor (h shr 11)
   h = h +% h shl 15
@@ -385,7 +385,7 @@ proc scanCurlyComment(L: var TLexer, tok: var TToken) =
   while true:
     case buf[pos]
     of CR, LF:
-      pos = HandleCRLF(L, pos)
+      pos = handleCRLF(L, pos)
       buf = L.buf
       add(tok.literal, "\n#")
     of '}':
@@ -405,7 +405,7 @@ proc scanStarComment(L: var TLexer, tok: var TToken) =
   while true:
     case buf[pos]
     of CR, LF:
-      pos = HandleCRLF(L, pos)
+      pos = handleCRLF(L, pos)
       buf = L.buf
       add(tok.literal, "\n#")
     of '*':
@@ -428,9 +428,9 @@ proc skip(L: var TLexer, tok: var TToken) =
   while true:
     case buf[pos]
     of ' ', Tabulator:
-      Inc(pos)                # newline is special:
+      inc(pos)                # newline is special:
     of CR, LF:
-      pos = HandleCRLF(L, pos)
+      pos = handleCRLF(L, pos)
       buf = L.buf
     else:
       break                   # EndOfFile also leaves the loop
@@ -449,7 +449,7 @@ proc getTok(L: var TLexer, tok: var TToken) =
     case c
     of ';':
       tok.xkind = pxSemicolon
-      Inc(L.bufpos)
+      inc(L.bufpos)
     of '/':
       if L.buf[L.bufpos + 1] == '/':
         scanLineComment(L, tok)
@@ -458,12 +458,12 @@ proc getTok(L: var TLexer, tok: var TToken) =
         inc(L.bufpos)
     of ',':
       tok.xkind = pxComma
-      Inc(L.bufpos)
+      inc(L.bufpos)
     of '(':
-      Inc(L.bufpos)
+      inc(L.bufpos)
       if (L.buf[L.bufPos] == '*'):
         if (L.buf[L.bufPos + 1] == '$'):
-          Inc(L.bufpos, 2)
+          inc(L.bufpos, 2)
           skip(L, tok)
           getSymbol(L, tok)
           tok.xkind = pxStarDirLe
@@ -481,12 +481,12 @@ proc getTok(L: var TLexer, tok: var TToken) =
         tok.xkind = pxStar
     of ')':
       tok.xkind = pxParRi
-      Inc(L.bufpos)
+      inc(L.bufpos)
     of '[':
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxBracketLe
     of ']':
-      Inc(L.bufpos)
+      inc(L.bufpos)
       tok.xkind = pxBracketRi
     of '.':
       inc(L.bufpos)
@@ -496,21 +496,21 @@ proc getTok(L: var TLexer, tok: var TToken) =
       else:
         tok.xkind = pxDot
     of '{':
-      Inc(L.bufpos)
+      inc(L.bufpos)
       case L.buf[L.bufpos]
       of '$':
-        Inc(L.bufpos)
+        inc(L.bufpos)
         skip(L, tok)
         getSymbol(L, tok)
         tok.xkind = pxCurlyDirLe
       of '&':
-        Inc(L.bufpos)
+        inc(L.bufpos)
         tok.xkind = pxAmp
       of '%':
-        Inc(L.bufpos)
+        inc(L.bufpos)
         tok.xkind = pxPer
       of '@':
-        Inc(L.bufpos)
+        inc(L.bufpos)
         tok.xkind = pxCommand
       else: scanCurlyComment(L, tok)
     of '+':
@@ -554,7 +554,7 @@ proc getTok(L: var TLexer, tok: var TToken) =
       inc(L.bufpos)
     of '}':
       tok.xkind = pxCurlyDirRi
-      Inc(L.bufpos)
+      inc(L.bufpos)
     of '\'', '#':
       getString(L, tok)
     of '$':
@@ -567,4 +567,4 @@ proc getTok(L: var TLexer, tok: var TToken) =
       tok.literal = c & ""
       tok.xkind = pxInvalid
       lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
-      Inc(L.bufpos)
+      inc(L.bufpos)
diff --git a/compiler/pas2nim/pasparse.nim b/compiler/pas2nim/pasparse.nim
index 61d57dec3..a6f8363f6 100644
--- a/compiler/pas2nim/pasparse.nim
+++ b/compiler/pas2nim/pasparse.nim
@@ -57,7 +57,7 @@ const
     ["tbinaryfile", "tfile"], ["strstart", "0"], ["nl", "\"\\n\""],
     ["tostring", "$"]]
 
-proc ParseUnit*(p: var TParser): PNode
+proc parseUnit*(p: var TParser): PNode
 proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
                  flags: set[TParserFlag] = {})
 proc closeParser*(p: var TParser)
@@ -67,20 +67,20 @@ proc fixRecordDef*(n: var PNode)
 
 # implementation
 
-proc OpenParser(p: var TParser, filename: string, 
+proc openParser(p: var TParser, filename: string, 
                 inputStream: PLLStream, flags: set[TParserFlag] = {}) = 
-  OpenLexer(p.lex, filename, inputStream)
+  openLexer(p.lex, filename, inputStream)
   initIdTable(p.repl)
   for i in countup(low(stdReplacements), high(stdReplacements)): 
-    IdTablePut(p.repl, getIdent(stdReplacements[i][0]), 
+    idTablePut(p.repl, getIdent(stdReplacements[i][0]), 
                getIdent(stdReplacements[i][1]))
   if pfMoreReplacements in flags: 
     for i in countup(low(nimReplacements), high(nimReplacements)): 
-      IdTablePut(p.repl, getIdent(nimReplacements[i][0]), 
+      idTablePut(p.repl, getIdent(nimReplacements[i][0]), 
                  getIdent(nimReplacements[i][1]))
   p.flags = flags
   
-proc CloseParser(p: var TParser) = CloseLexer(p.lex)
+proc closeParser(p: var TParser) = closeLexer(p.lex)
 proc getTok(p: var TParser) = getTok(p.lex, p.tok)
 
 proc parMessage(p: TParser, msg: TMsgKind, arg = "") = 
@@ -98,15 +98,15 @@ proc skipCom(p: var TParser, n: PNode) =
       parMessage(p, warnCommentXIgnored, p.tok.literal)
     getTok(p)
 
-proc ExpectIdent(p: TParser) = 
+proc expectIdent(p: TParser) = 
   if p.tok.xkind != pxSymbol: 
     lexMessage(p.lex, errIdentifierExpected, $(p.tok))
   
-proc Eat(p: var TParser, xkind: TTokKind) = 
+proc eat(p: var TParser, xkind: TTokKind) = 
   if p.tok.xkind == xkind: getTok(p)
-  else: lexMessage(p.lex, errTokenExpected, TokKindToStr(xkind))
+  else: lexMessage(p.lex, errTokenExpected, tokKindToStr(xkind))
   
-proc Opt(p: var TParser, xkind: TTokKind) = 
+proc opt(p: var TParser, xkind: TTokKind) = 
   if p.tok.xkind == xkind: getTok(p)
   
 proc newNodeP(kind: TNodeKind, p: TParser): PNode = 
@@ -131,7 +131,7 @@ proc newIdentNodeP(ident: PIdent, p: TParser): PNode =
 
 proc createIdentNodeP(ident: PIdent, p: TParser): PNode = 
   result = newNodeP(nkIdent, p)
-  var x = PIdent(IdTableGet(p.repl, ident))
+  var x = PIdent(idTableGet(p.repl, ident))
   if x != nil: result.ident = x
   else: result.ident = ident
   
@@ -170,7 +170,7 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
     getTok(p)
     eat(p, pxCurlyDirRi)
     result = parseExpr(p)
-    if result.kind == nkEmpty: InternalError("emptyNode modified")
+    if result.kind == nkEmpty: internalError("emptyNode modified")
     result.kind = nkCurly
   elif p.tok.ident.id == getIdent("cast").id: 
     getTok(p)
@@ -251,7 +251,7 @@ proc bracketExprList(p: var TParser, first: PNode): PNode =
       getTok(p)
       break 
     if p.tok.xkind == pxEof: 
-      parMessage(p, errTokenExpected, TokKindToStr(pxBracketRi))
+      parMessage(p, errTokenExpected, tokKindToStr(pxBracketRi))
       break 
     var a = rangeExpr(p)
     skipCom(p, a)
@@ -281,7 +281,7 @@ proc exprListAux(p: var TParser, elemKind: TNodeKind,
       getTok(p)
       break 
     if p.tok.xkind == pxEof: 
-      parMessage(p, errTokenExpected, TokKindToStr(endtok))
+      parMessage(p, errTokenExpected, tokKindToStr(endTok))
       break 
     var a = exprColonEqExpr(p, elemKind, sepTok)
     skipCom(p, a)
@@ -319,7 +319,7 @@ proc qualifiedIdentListAux(p: var TParser, endTok: TTokKind,
       getTok(p)
       break 
     if p.tok.xkind == pxEof: 
-      parMessage(p, errTokenExpected, TokKindToStr(endtok))
+      parMessage(p, errTokenExpected, tokKindToStr(endTok))
       break 
     var a = qualifiedIdent(p)
     skipCom(p, a)
@@ -335,7 +335,7 @@ proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind,
 
 proc setBaseFlags(n: PNode, base: TNumericalBase) = 
   case base
-  of base10: nil
+  of base10: discard
   of base2: incl(n.flags, nfBase2)
   of base8: incl(n.flags, nfBase8)
   of base16: incl(n.flags, nfBase16)
@@ -466,7 +466,7 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
         eat(p, pxCurlyDirRi)
         opNode.ident = getIdent("&")
       else: 
-        nil
+        discard
     of pxMinus: 
       if p.tok.xkind == pxPer: 
         getTok(p)
@@ -477,7 +477,7 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
     of pxNeq: 
       opNode.ident = getIdent("!=")
     else: 
-      nil
+      discard
     skipCom(p, opNode)        # read sub-expression with higher priority
     nextop = lowestExprAux(p, v2, opPred)
     addSon(node, opNode)
@@ -505,7 +505,7 @@ proc fixExpr(n: PNode): PNode =
             (n.sons[2].kind in {nkCharLit, nkStrLit}): 
           n.sons[0].ident = getIdent("&") # fix operator
   else: 
-    nil
+    discard
   if not (n.kind in {nkEmpty..nkNilLit}): 
     for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i])
   
@@ -584,7 +584,7 @@ proc parseIncludeDir(p: var TParser): PNode =
 proc definedExprAux(p: var TParser): PNode = 
   result = newNodeP(nkCall, p)
   addSon(result, newIdentNodeP(getIdent("defined"), p))
-  ExpectIdent(p)
+  expectIdent(p)
   addSon(result, createIdentNodeP(p.tok.ident, p))
   getTok(p)
 
@@ -603,7 +603,7 @@ proc parseStmtList(p: var TParser): PNode =
     of pxCurlyDirLe, pxStarDirLe: 
       if not isHandledDirective(p): break 
     else: 
-      nil
+      discard
     addSon(result, parseStmt(p))
   if sonsLen(result) == 1: result = result.sons[0]
   
@@ -732,7 +732,7 @@ proc parseRepeat(p: var TParser): PNode =
   addSon(b, c)
   addSon(a, b)
   if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id: 
-    nil
+    discard
   else: 
     addSon(s, a)
   addSon(result, s)
@@ -753,7 +753,7 @@ proc parseCase(p: var TParser): PNode =
       while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): 
         addSon(b, rangeExpr(p))
         opt(p, pxComma)
-        skipcom(p, b)
+        skipCom(p, b)
       eat(p, pxColon)
     skipCom(p, b)
     addSon(b, parseStmt(p))
@@ -818,7 +818,7 @@ proc parseFor(p: var TParser): PNode =
     getTok(p)
     b = parseExpr(p)
   else: 
-    parMessage(p, errTokenExpected, TokKindToStr(pxTo))
+    parMessage(p, errTokenExpected, tokKindToStr(pxTo))
   addSon(c, a)
   addSon(c, b)
   eat(p, pxDo)
@@ -840,7 +840,7 @@ proc parseParam(p: var TParser): PNode =
     getTok(p)
     v = newNodeP(nkVarTy, p)
   else: 
-    nil
+    discard
   while true: 
     case p.tok.xkind
     of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
@@ -915,7 +915,7 @@ proc parseCallingConvention(p: var TParser): PNode =
       getTok(p)
       opt(p, pxSemicolon)
     else: 
-      nil
+      discard
 
 proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode = 
   var e: PNode
@@ -1096,7 +1096,7 @@ proc parseRecordCase(p: var TParser): PNode =
       while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): 
         addSon(b, rangeExpr(p))
         opt(p, pxComma)
-        skipcom(p, b)
+        skipCom(p, b)
       eat(p, pxColon)
     skipCom(p, b)
     c = newNodeP(nkRecList, p)
@@ -1133,7 +1133,7 @@ proc parseRecordPart(p: var TParser): PNode =
 proc exSymbol(n: var PNode) = 
   case n.kind
   of nkPostfix: 
-    nil
+    discard
   of nkPragmaExpr: 
     exSymbol(n.sons[0])
   of nkIdent, nkAccQuoted: 
@@ -1154,7 +1154,7 @@ proc fixRecordDef(n: var PNode) =
     for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
   of nkIdentDefs: 
     for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
-  of nkNilLit, nkEmpty: nil
+  of nkNilLit, nkEmpty: discard
   else: internalError(n.info, "fixRecordDef(): " & $n.kind)
   
 proc addPragmaToIdent(ident: var PNode, pragma: PNode) = 
@@ -1168,7 +1168,7 @@ proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
   else: 
     pragmasNode = ident.sons[1]
     if pragmasNode.kind != nkPragma: 
-      InternalError(ident.info, "addPragmaToIdent")
+      internalError(ident.info, "addPragmaToIdent")
   addSon(pragmasNode, pragma)
 
 proc parseRecordBody(p: var TParser, result, definition: PNode) = 
@@ -1183,15 +1183,15 @@ proc parseRecordBody(p: var TParser, result, definition: PNode) =
       if definition != nil: 
         addPragmaToIdent(definition.sons[0], newIdentNodeP(p.tok.ident, p))
       else: 
-        InternalError(result.info, "anonymous record is not supported")
+        internalError(result.info, "anonymous record is not supported")
       getTok(p)
     else: 
-      InternalError(result.info, "parseRecordBody")
+      internalError(result.info, "parseRecordBody")
   of pxCommand: 
     if definition != nil: addPragmaToIdent(definition.sons[0], parseCommand(p))
-    else: InternalError(result.info, "anonymous record is not supported")
+    else: internalError(result.info, "anonymous record is not supported")
   else: 
-    nil
+    discard
   opt(p, pxSemicolon)
   skipCom(p, result)
 
@@ -1223,7 +1223,7 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
     getTok(p)
     if p.tok.xkind == pxCommand: 
       result = parseCommand(p)
-      if result.kind != nkTupleTy: InternalError(result.info, "parseTypeDesc")
+      if result.kind != nkTupleTy: internalError(result.info, "parseTypeDesc")
       parseRecordBody(p, result, definition)
       var a = lastSon(result)     # embed nkRecList directly into nkTupleTy
       for i in countup(0, sonsLen(a) - 1): 
@@ -1237,7 +1237,7 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
       if definition != nil: 
         addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p))
       else: 
-        InternalError(result.info, "anonymous record is not supported")
+        internalError(result.info, "anonymous record is not supported")
   of pxObject: result = parseRecordOrObject(p, nkObjectTy, definition)
   of pxParLe: result = parseEnum(p)
   of pxArray: 
@@ -1399,7 +1399,7 @@ proc fixVarSection(p: var TParser, counter: PNode) =
 
 proc exSymbols(n: PNode) = 
   case n.kind
-  of nkEmpty..nkNilLit: nil
+  of nkEmpty..nkNilLit: discard
   of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos])
   of nkWhenStmt, nkStmtList: 
     for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i])
@@ -1410,7 +1410,7 @@ proc exSymbols(n: PNode) =
       exSymbol(n.sons[i].sons[0])
       if n.sons[i].sons[2].kind == nkObjectTy: 
         fixRecordDef(n.sons[i].sons[2])
-  else: nil
+  else: discard
 
 proc parseBegin(p: var TParser, result: PNode) = 
   getTok(p)
diff --git a/compiler/passaux.nim b/compiler/passaux.nim
index 4a85c994c..0ba9f22d0 100644
--- a/compiler/passaux.nim
+++ b/compiler/passaux.nim
@@ -19,12 +19,12 @@ proc verboseOpen(s: PSym): PPassContext =
   
 proc verboseProcess(context: PPassContext, n: PNode): PNode = 
   result = n
-  if context != nil: InternalError("logpass: context is not nil")
+  if context != nil: internalError("logpass: context is not nil")
   if gVerbosity == 3: 
     # system.nim deactivates all hints, for verbosity:3 we want the processing
     # messages nonetheless, so we activate them again unconditionally:
     incl(msgs.gNotes, hintProcessing)
-    Message(n.info, hintProcessing, $idgen.gBackendId)
+    message(n.info, hintProcessing, $idgen.gBackendId)
   
 const verbosePass* = makePass(open = verboseOpen, process = verboseProcess)
 
@@ -34,14 +34,14 @@ proc cleanUp(c: PPassContext, n: PNode): PNode =
   if optDeadCodeElim in gGlobalOptions or n == nil: return 
   case n.kind
   of nkStmtList: 
-    for i in countup(0, sonsLen(n) - 1): discard cleanup(c, n.sons[i])
+    for i in countup(0, sonsLen(n) - 1): discard cleanUp(c, n.sons[i])
   of nkProcDef, nkMethodDef: 
     if n.sons[namePos].kind == nkSym: 
       var s = n.sons[namePos].sym
       if sfDeadCodeElim notin getModule(s).flags and not astNeeded(s): 
         s.ast.sons[bodyPos] = ast.emptyNode # free the memory
   else: 
-    nil
+    discard
 
 const cleanupPass* = makePass(process = cleanUp, close = cleanUp)
 
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 8d228fe9a..3dc31e7ac 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -30,8 +30,8 @@ type
   TPass* = tuple[open: TPassOpen, openCached: TPassOpenCached,
                  process: TPassProcess, close: TPassClose]
 
-  TPassData* = tuple[input: PNode, closeOutput: Pnode]
-  TPasses* = openarray[TPass]
+  TPassData* = tuple[input: PNode, closeOutput: PNode]
+  TPasses* = openArray[TPass]
 
 # a pass is a tuple of procedure vars ``TPass.close`` may produce additional 
 # nodes. These are passed to the other close procedures. 
@@ -169,7 +169,7 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
     openPasses(a, module)
     if stream == nil: 
       let filename = fileIdx.toFullPath
-      s = LLStreamOpen(filename, fmRead)
+      s = llStreamOpen(filename, fmRead)
       if s == nil: 
         rawMessage(errCannotOpenFile, filename)
         return
@@ -195,7 +195,7 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
       if s.kind != llsStdIn: break 
     closePasses(a)
     # id synchronization point for more consistent code generation:
-    IDsynchronizationPoint(1000)
+    idSynchronizationPoint(1000)
   else:
     openPassesCached(a, module, rd)
     var n = loadInitSection(rd)
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index b7792100f..d262790ab 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -40,7 +40,7 @@ proc canonKind(n: PNode): TNodeKind =
   of nkCallKinds: result = nkCall
   of nkStrLit..nkTripleStrLit: result = nkStrLit
   of nkFastAsgn: result = nkAsgn
-  else: nil
+  else: discard
 
 proc sameKinds(a, b: PNode): bool {.inline.} =
   result = a.kind == b.kind or a.canonKind == b.canonKind
@@ -87,22 +87,22 @@ proc matchChoice(c: PPatternContext, p, n: PNode): bool =
     if matches(c, p.sons[i], n): return true
 
 proc bindOrCheck(c: PPatternContext, param: PSym, n: PNode): bool =
-  var pp = GetLazy(c, param)
+  var pp = getLazy(c, param)
   if pp != nil:
     # check if we got the same pattern (already unified):
     result = sameTrees(pp, n) #matches(c, pp, n)
   elif n.kind == nkArgList or checkTypes(c, param, n):
-    PutLazy(c, param, n)
+    putLazy(c, param, n)
     result = true
 
 proc gather(c: PPatternContext, param: PSym, n: PNode) =
-  var pp = GetLazy(c, param)
+  var pp = getLazy(c, param)
   if pp != nil and pp.kind == nkArgList:
     pp.add(n)
   else:
     pp = newNodeI(nkArgList, n.info, 1)
     pp.sons[0] = n
-    PutLazy(c, param, pp)
+    putLazy(c, param, pp)
 
 proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
   # match ``op * param`` or ``op *| param``
@@ -148,7 +148,7 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
     of "*": result = matchNested(c, p, n, rpn=false)
     of "**": result = matchNested(c, p, n, rpn=true)
     of "~": result = not matches(c, p.sons[1], n)
-    else: InternalError(p.info, "invalid pattern")
+    else: internalError(p.info, "invalid pattern")
     # template {add(a, `&` * b)}(a: string{noalias}, b: varargs[string]) = 
     #   add(a, b)
   elif p.kind == nkCurlyExpr:
@@ -256,7 +256,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
     args = newNodeI(nkArgList, n.info)
   for i in 1 .. < params.len:
     let param = params.sons[i].sym
-    let x = GetLazy(ctx, param)
+    let x = getLazy(ctx, param)
     # couldn't bind parameter:
     if isNil(x): return nil
     result.add(x)
@@ -267,7 +267,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
       var rs = result.sons[i]
       let param = params.sons[i].sym
       case whichAlias(param)
-      of aqNone: nil
+      of aqNone: discard
       of aqShouldAlias:
         # it suffices that it aliases for sure with *some* other param:
         var ok = false
diff --git a/compiler/pbraces.nim b/compiler/pbraces.nim
index a944fe0ab..ce6e0d9a9 100644
--- a/compiler/pbraces.nim
+++ b/compiler/pbraces.nim
@@ -10,7 +10,7 @@
 import 
   llstream, lexer, parser, idents, strutils, ast, msgs
 
-proc ParseAll*(p: var TParser): PNode = 
+proc parseAll*(p: var TParser): PNode = 
   result = nil
 
 proc parseTopLevelStmt*(p: var TParser): PNode = 
diff --git a/compiler/platform.nim b/compiler/platform.nim
index 59091b690..2e78d4fc5 100644
--- a/compiler/platform.nim
+++ b/compiler/platform.nim
@@ -185,13 +185,13 @@ var
   targetCPU*, hostCPU*: TSystemCPU
   targetOS*, hostOS*: TSystemOS
 
-proc NameToOS*(name: string): TSystemOS
-proc NameToCPU*(name: string): TSystemCPU
+proc nameToOS*(name: string): TSystemOS
+proc nameToCPU*(name: string): TSystemCPU
 
 var 
-  IntSize*: int
+  intSize*: int
   floatSize*: int
-  PtrSize*: int
+  ptrSize*: int
   tnl*: string                # target newline
 
 proc setTarget*(o: TSystemOS, c: TSystemCPU) = 
@@ -200,18 +200,18 @@ proc setTarget*(o: TSystemOS, c: TSystemCPU) =
   #echo "new Target: OS: ", o, " CPU: ", c
   targetCPU = c
   targetOS = o
-  intSize = cpu[c].intSize div 8
-  floatSize = cpu[c].floatSize div 8
-  ptrSize = cpu[c].bit div 8
-  tnl = os[o].newLine
+  intSize = CPU[c].intSize div 8
+  floatSize = CPU[c].floatSize div 8
+  ptrSize = CPU[c].bit div 8
+  tnl = OS[o].newLine
 
-proc NameToOS(name: string): TSystemOS = 
+proc nameToOS(name: string): TSystemOS = 
   for i in countup(succ(osNone), high(TSystemOS)): 
     if cmpIgnoreStyle(name, OS[i].name) == 0: 
       return i
   result = osNone
 
-proc NameToCPU(name: string): TSystemCPU = 
+proc nameToCPU(name: string): TSystemCPU = 
   for i in countup(succ(cpuNone), high(TSystemCPU)): 
     if cmpIgnoreStyle(name, CPU[i].name) == 0: 
       return i
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 6f1e7af25..14d155539 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -20,49 +20,50 @@ const
 
 const
   procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
-    wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, 
-    wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
+    wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
+    wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
     wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
-    wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
-    wGenSym, wInject, wRaises, wTags, wOperator, wDelegator}
+    wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
+    wGensym, wInject, wRaises, wTags, wOperator, wDelegator}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas
-  templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty,
+  templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
     wDelegator}
   macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
-    wNodecl, wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
-    wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wDelegator}
-  iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect, 
+    wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
+    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator}
+  iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, 
     wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
-    wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wRaises,
+    wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
     wTags, wOperator}
   exprPragmas* = {wLine}
   stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
     wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
     wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
-    wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop,
-    wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
-    wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
+    wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
+    wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
+    wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
     wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
     wInjectStmt}
   lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, 
-    wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, 
-    wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame,
+    wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, 
+    wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
     wRaises, wTags}
   typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, 
-    wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern, wShallow, 
-    wImportcpp, wImportobjc, wError, wIncompleteStruct, wByCopy, wByRef,
-    wInheritable, wGenSym, wInject, wRequiresInit}
+    wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
+    wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
+    wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
+    wBorrow}
   fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, 
-    wImportcpp, wImportobjc, wError}
+    wImportCpp, wImportObjC, wError}
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, 
-    wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern,
-    wImportcpp, wImportobjc, wError, wNoInit, wCompileTime, wGlobal,
-    wGenSym, wInject, wCodegenDecl}
+    wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
+    wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
+    wGensym, wInject, wCodegenDecl}
   constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
-    wExtern, wImportcpp, wImportobjc, wError, wGenSym, wInject}
+    wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
   letPragmas* = varPragmas
-  procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideEffect,
+  procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
                       wThread, wRaises, wTags}
   allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
 
@@ -70,7 +71,7 @@ proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
 # implementation
 
 proc invalidPragma(n: PNode) = 
-  LocalError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
+  localError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
 
 proc pragmaAsm*(c: PContext, n: PNode): char = 
   result = '\0'
@@ -92,13 +93,27 @@ proc setExternName(s: PSym, extname: string) =
     # note that '{.importc.}' is transformed into '{.importc: "$1".}'
     s.loc.flags.incl(lfFullExternalName)
 
-proc MakeExternImport(s: PSym, extname: string) = 
+proc makeExternImport(s: PSym, extname: string) = 
   setExternName(s, extname)
   incl(s.flags, sfImportc)
   excl(s.flags, sfForward)
 
-proc MakeExternExport(s: PSym, extname: string) = 
+proc validateExternCName(s: PSym, info: TLineInfo) =
+  ## Validates that the symbol name in s.loc.r is a valid C identifier.
+  ##
+  ## Valid identifiers are those alphanumeric including the underscore not
+  ## starting with a number. If the check fails, a generic error will be
+  ## displayed to the user.
+  let target = ropeToStr(s.loc.r)
+  if target.len < 1 or target[0] notin IdentStartChars or
+      not target.allCharsInSet(IdentChars):
+    localError(info, errGenerated, "invalid exported symbol")
+
+proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
   setExternName(s, extname)
+  # XXX to fix make it work with nimrtl.
+  #if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC}:
+  #  validateExternCName(s, info)
   incl(s.flags, sfExportc)
 
 proc processImportCompilerProc(s: PSym, extname: string) =
@@ -125,7 +140,7 @@ proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
 
 proc getStrLitNode(c: PContext, n: PNode): PNode =
   if n.kind != nkExprColonExpr: 
-    LocalError(n.info, errStringLiteralExpected)
+    localError(n.info, errStringLiteralExpected)
     # error correction:
     result = newEmptyStrNode(n)
   else:
@@ -133,7 +148,7 @@ proc getStrLitNode(c: PContext, n: PNode): PNode =
     case n.sons[1].kind
     of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
     else: 
-      LocalError(n.info, errStringLiteralExpected)
+      localError(n.info, errStringLiteralExpected)
       # error correction:
       result = newEmptyStrNode(n)
 
@@ -142,12 +157,12 @@ proc expectStrLit(c: PContext, n: PNode): string =
 
 proc expectIntLit(c: PContext, n: PNode): int = 
   if n.kind != nkExprColonExpr: 
-    LocalError(n.info, errIntLiteralExpected)
+    localError(n.info, errIntLiteralExpected)
   else: 
     n.sons[1] = c.semConstExpr(c, n.sons[1])
     case n.sons[1].kind
     of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal)
-    else: LocalError(n.info, errIntLiteralExpected)
+    else: localError(n.info, errIntLiteralExpected)
 
 proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string = 
   if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
@@ -160,7 +175,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
   #if sfSystemModule notin c.module.flags:
   #  liMessage(n.info, errMagicOnlyInSystem)
   if n.kind != nkExprColonExpr: 
-    LocalError(n.info, errStringLiteralExpected)
+    localError(n.info, errStringLiteralExpected)
     return
   var v: string
   if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
@@ -169,57 +184,57 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
     if substr($m, 1) == v: 
       s.magic = m
       break
-  if s.magic == mNone: Message(n.info, warnUnknownMagic, v)
+  if s.magic == mNone: message(n.info, warnUnknownMagic, v)
 
 proc wordToCallConv(sw: TSpecialWord): TCallingConvention = 
   # this assumes that the order of special words and calling conventions is
   # the same
   result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall))
 
-proc IsTurnedOn(c: PContext, n: PNode): bool = 
+proc isTurnedOn(c: PContext, n: PNode): bool = 
   if n.kind == nkExprColonExpr:
     let x = c.semConstBoolExpr(c, n.sons[1])
     n.sons[1] = x
     if x.kind == nkIntLit: return x.intVal != 0
-  LocalError(n.info, errOnOrOffExpected)
+  localError(n.info, errOnOrOffExpected)
 
 proc onOff(c: PContext, n: PNode, op: TOptions) = 
-  if IsTurnedOn(c, n): gOptions = gOptions + op
+  if isTurnedOn(c, n): gOptions = gOptions + op
   else: gOptions = gOptions - op
   
 proc pragmaDeadCodeElim(c: PContext, n: PNode) = 
-  if IsTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
+  if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
   else: excl(c.module.flags, sfDeadCodeElim)
 
 proc pragmaNoForward(c: PContext, n: PNode) =
-  if IsTurnedOn(c, n): incl(c.module.flags, sfNoForward)
+  if isTurnedOn(c, n): incl(c.module.flags, sfNoForward)
   else: excl(c.module.flags, sfNoForward)
 
 proc processCallConv(c: PContext, n: PNode) = 
   if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): 
     var sw = whichKeyword(n.sons[1].ident)
     case sw
-    of firstCallConv..lastCallConv: 
+    of FirstCallConv..LastCallConv: 
       POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw)
-    else: LocalError(n.info, errCallConvExpected)
+    else: localError(n.info, errCallConvExpected)
   else: 
-    LocalError(n.info, errCallConvExpected)
+    localError(n.info, errCallConvExpected)
   
 proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = 
   var it = PLib(c.libs.head)
   while it != nil: 
     if it.kind == kind: 
-      if trees.ExprStructuralEquivalent(it.path, path): return it
+      if trees.exprStructuralEquivalent(it.path, path): return it
     it = PLib(it.next)
   result = newLib(kind)
   result.path = path
-  Append(c.libs, result)
+  append(c.libs, result)
   if path.kind in {nkStrLit..nkTripleStrLit}:
-    result.isOverriden = options.isDynLibOverride(path.strVal)
+    result.isOverriden = options.isDynlibOverride(path.strVal)
 
 proc expectDynlibNode(c: PContext, n: PNode): PNode =
   if n.kind != nkExprColonExpr:
-    LocalError(n.info, errStringLiteralExpected)
+    localError(n.info, errStringLiteralExpected)
     # error correction:
     result = newEmptyStrNode(n)
   else:
@@ -229,7 +244,7 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
     if result.kind == nkSym and result.sym.kind == skConst:
       result = result.sym.ast # look it up
     if result.typ == nil or result.typ.kind notin {tyPointer, tyString, tyProc}:
-      LocalError(n.info, errStringLiteralExpected)
+      localError(n.info, errStringLiteralExpected)
       result = newEmptyStrNode(n)
     
 proc processDynLib(c: PContext, n: PNode, sym: PSym) = 
@@ -247,7 +262,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
     # since we'll be loading the dynlib symbols dynamically, we must use
     # a calling convention that doesn't introduce custom name mangling
     # cdecl is the default - the user can override this explicitly
-    if sym.kind in RoutineKinds and sym.typ != nil and 
+    if sym.kind in routineKinds and sym.typ != nil and 
         sym.typ.callConv == ccDefault:
       sym.typ.callConv = ccCDecl
 
@@ -265,7 +280,7 @@ proc processNote(c: PContext, n: PNode) =
     of wWarning:
       var x = findStr(msgs.WarningsToStr, n.sons[0].sons[1].ident.s)
       if x >= 0: nk = TNoteKind(x + ord(warnMin))
-      else: InvalidPragma(n); return
+      else: invalidPragma(n); return
     else:
       invalidPragma(n)
       return
@@ -284,27 +299,27 @@ proc processOption(c: PContext, n: PNode): bool =
   else:
     var sw = whichKeyword(n.sons[0].ident)
     case sw
-    of wChecks: OnOff(c, n, checksOptions)
-    of wObjChecks: OnOff(c, n, {optObjCheck})
-    of wFieldchecks: OnOff(c, n, {optFieldCheck})
-    of wRangechecks: OnOff(c, n, {optRangeCheck})
-    of wBoundchecks: OnOff(c, n, {optBoundsCheck})
-    of wOverflowchecks: OnOff(c, n, {optOverflowCheck})
-    of wNilchecks: OnOff(c, n, {optNilCheck})
-    of wFloatChecks: OnOff(c, n, {optNanCheck, optInfCheck})
-    of wNaNchecks: OnOff(c, n, {optNanCheck})
-    of wInfChecks: OnOff(c, n, {optInfCheck})
-    of wAssertions: OnOff(c, n, {optAssert})
-    of wWarnings: OnOff(c, n, {optWarns})
-    of wHints: OnOff(c, n, {optHints})
-    of wCallConv: processCallConv(c, n)   
-    of wLinedir: OnOff(c, n, {optLineDir})
-    of wStacktrace: OnOff(c, n, {optStackTrace})
-    of wLinetrace: OnOff(c, n, {optLineTrace})
-    of wDebugger: OnOff(c, n, {optEndb})
-    of wProfiler: OnOff(c, n, {optProfiler})
-    of wByRef: OnOff(c, n, {optByRef})
-    of wDynLib: processDynLib(c, n, nil) 
+    of wChecks: onOff(c, n, ChecksOptions)
+    of wObjChecks: onOff(c, n, {optObjCheck})
+    of wFieldChecks: onOff(c, n, {optFieldCheck})
+    of wRangechecks: onOff(c, n, {optRangeCheck})
+    of wBoundchecks: onOff(c, n, {optBoundsCheck})
+    of wOverflowchecks: onOff(c, n, {optOverflowCheck})
+    of wNilchecks: onOff(c, n, {optNilCheck})
+    of wFloatchecks: onOff(c, n, {optNaNCheck, optInfCheck})
+    of wNanChecks: onOff(c, n, {optNaNCheck})
+    of wInfChecks: onOff(c, n, {optInfCheck})
+    of wAssertions: onOff(c, n, {optAssert})
+    of wWarnings: onOff(c, n, {optWarns})
+    of wHints: onOff(c, n, {optHints})
+    of wCallconv: processCallConv(c, n)   
+    of wLinedir: onOff(c, n, {optLineDir})
+    of wStacktrace: onOff(c, n, {optStackTrace})
+    of wLinetrace: onOff(c, n, {optLineTrace})
+    of wDebugger: onOff(c, n, {optEndb})
+    of wProfiler: onOff(c, n, {optProfiler})
+    of wByRef: onOff(c, n, {optByRef})
+    of wDynlib: processDynLib(c, n, nil) 
     of wOptimization: 
       if n.sons[1].kind != nkIdent: 
         invalidPragma(n)
@@ -319,14 +334,14 @@ proc processOption(c: PContext, n: PNode): bool =
         of "none": 
           excl(gOptions, optOptimizeSpeed)
           excl(gOptions, optOptimizeSize)
-        else: LocalError(n.info, errNoneSpeedOrSizeExpected)
-    of wImplicitStatic: OnOff(c, n, {optImplicitStatic})
-    of wPatterns: OnOff(c, n, {optPatterns})
+        else: localError(n.info, errNoneSpeedOrSizeExpected)
+    of wImplicitStatic: onOff(c, n, {optImplicitStatic})
+    of wPatterns: onOff(c, n, {optPatterns})
     else: result = true
   
 proc processPush(c: PContext, n: PNode, start: int) = 
   if n.sons[start-1].kind == nkExprColonExpr:
-    LocalError(n.info, errGenerated, "':' after 'push' not supported")
+    localError(n.info, errGenerated, "':' after 'push' not supported")
   var x = newOptionEntry()
   var y = POptionEntry(c.optionStack.tail)
   x.options = gOptions
@@ -344,7 +359,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
   
 proc processPop(c: PContext, n: PNode) = 
   if c.optionStack.counter <= 1: 
-    LocalError(n.info, errAtPopWithoutPush)
+    localError(n.info, errAtPopWithoutPush)
   else: 
     gOptions = POptionEntry(c.optionStack.tail).options 
     gNotes = POptionEntry(c.optionStack.tail).notes
@@ -352,15 +367,15 @@ proc processPop(c: PContext, n: PNode) =
 
 proc processDefine(c: PContext, n: PNode) = 
   if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): 
-    DefineSymbol(n.sons[1].ident.s)
-    Message(n.info, warnDeprecated, "define")
+    defineSymbol(n.sons[1].ident.s)
+    message(n.info, warnDeprecated, "define")
   else: 
     invalidPragma(n)
   
 proc processUndef(c: PContext, n: PNode) = 
   if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): 
-    UndefSymbol(n.sons[1].ident.s)
-    Message(n.info, warnDeprecated, "undef")
+    undefSymbol(n.sons[1].ident.s)
+    message(n.info, warnDeprecated, "undef")
   else: 
     invalidPragma(n)
   
@@ -372,13 +387,13 @@ proc processCompile(c: PContext, n: PNode) =
   var s = expectStrLit(c, n)
   var found = findFile(s)
   if found == "": found = s
-  var trunc = ChangeFileExt(found, "")
+  var trunc = changeFileExt(found, "")
   extccomp.addExternalFileToCompile(found)
   extccomp.addFileToLink(completeCFilePath(trunc, false))
 
 proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) = 
   var f = expectStrLit(c, n)
-  if splitFile(f).ext == "": f = addFileExt(f, cc[ccompiler].objExt)
+  if splitFile(f).ext == "": f = addFileExt(f, CC[cCompiler].objExt)
   var found = findFile(f)
   if found == "": found = f # use the default
   case feature
@@ -387,16 +402,16 @@ proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
     extccomp.addFileToLink(libpath / completeCFilePath(found, false))
   else: internalError(n.info, "processCommonLink")
   
-proc PragmaBreakpoint(c: PContext, n: PNode) = 
+proc pragmaBreakpoint(c: PContext, n: PNode) = 
   discard getOptionalStr(c, n, "")
 
-proc PragmaCheckpoint(c: PContext, n: PNode) = 
+proc pragmaCheckpoint(c: PContext, n: PNode) = 
   # checkpoints can be used to debug the compiler; they are not documented
   var info = n.info
   inc(info.line)              # next line is affected!
   msgs.addCheckpoint(info)
 
-proc PragmaWatchpoint(c: PContext, n: PNode) =
+proc pragmaWatchpoint(c: PContext, n: PNode) =
   if n.kind == nkExprColonExpr:
     n.sons[1] = c.semExpr(c, n.sons[1])
   else:
@@ -408,7 +423,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
     result = newNode(if n.kind == nkAsmStmt: nkAsmStmt else: nkArgList, n.info)
     var str = n.sons[1].strVal
     if str == "":
-      LocalError(n.info, errEmptyAsm)
+      localError(n.info, errEmptyAsm)
       return
     # now parse the string literal and substitute symbols:
     var a = 0
@@ -431,14 +446,14 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
       a = c + 1
   else: illFormedAst(n)
   
-proc PragmaEmit(c: PContext, n: PNode) = 
+proc pragmaEmit(c: PContext, n: PNode) = 
   discard getStrLitNode(c, n)
   n.sons[1] = semAsmOrEmit(c, n, '`')
 
 proc noVal(n: PNode) = 
   if n.kind == nkExprColonExpr: invalidPragma(n)
 
-proc PragmaUnroll(c: PContext, n: PNode) = 
+proc pragmaUnroll(c: PContext, n: PNode) = 
   if c.p.nestedLoopCounter <= 0: 
     invalidPragma(n)
   elif n.kind == nkExprColonExpr:
@@ -448,7 +463,7 @@ proc PragmaUnroll(c: PContext, n: PNode) =
     else: 
       invalidPragma(n)
 
-proc PragmaLine(c: PContext, n: PNode) =
+proc pragmaLine(c: PContext, n: PNode) =
   if n.kind == nkExprColonExpr:
     n.sons[1] = c.semConstExpr(c, n.sons[1])
     let a = n.sons[1]
@@ -458,14 +473,14 @@ proc PragmaLine(c: PContext, n: PNode) =
       if x.kind == nkExprColonExpr: x = x.sons[1]
       if y.kind == nkExprColonExpr: y = y.sons[1]
       if x.kind != nkStrLit: 
-        LocalError(n.info, errStringLiteralExpected)
+        localError(n.info, errStringLiteralExpected)
       elif y.kind != nkIntLit: 
-        LocalError(n.info, errIntLiteralExpected)
+        localError(n.info, errIntLiteralExpected)
       else:
         n.info.fileIndex = msgs.fileInfoIdx(x.strVal)
         n.info.line = int16(y.intVal)
     else:
-      LocalError(n.info, errXExpected, "tuple")
+      localError(n.info, errXExpected, "tuple")
   else:
     # sensible default:
     n.info = getInfoContext(-1)
@@ -476,11 +491,11 @@ proc processPragma(c: PContext, n: PNode, i: int) =
   elif it.sons[0].kind != nkIdent: invalidPragma(n)
   elif it.sons[1].kind != nkIdent: invalidPragma(n)
   
-  var userPragma = NewSym(skTemplate, it.sons[1].ident, nil, it.info)
+  var userPragma = newSym(skTemplate, it.sons[1].ident, nil, it.info)
   var body = newNodeI(nkPragma, n.info)
   for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j])
   userPragma.ast = body
-  StrTableAdd(c.userPragmas, userPragma)
+  strTableAdd(c.userPragmas, userPragma)
 
 proc pragmaRaisesOrTags(c: PContext, n: PNode) =
   proc processExc(c: PContext, x: PNode) =
@@ -498,24 +513,31 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
   else:
     invalidPragma(n)
 
+proc typeBorrow(sym: PSym, n: PNode) =
+  if n.kind == nkExprColonExpr:
+    let it = n.sons[1]
+    if it.kind != nkAccQuoted:
+      localError(n.info, "a type can only borrow `.` for now")
+  incl(sym.typ.flags, tfBorrowDot)
+
 proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
                   validPragmas: TSpecialWords): bool =
   var it = n.sons[i]
   var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
   if key.kind == nkIdent: 
-    var userPragma = StrTableGet(c.userPragmas, key.ident)
+    var userPragma = strTableGet(c.userPragmas, key.ident)
     if userPragma != nil: 
-      inc c.InstCounter
-      if c.InstCounter > 100: 
-        GlobalError(it.info, errRecursiveDependencyX, userPragma.name.s)
+      inc c.instCounter
+      if c.instCounter > 100: 
+        globalError(it.info, errRecursiveDependencyX, userPragma.name.s)
       pragma(c, sym, userPragma.ast, validPragmas)
-      dec c.InstCounter
+      dec c.instCounter
     else:
       var k = whichKeyword(key.ident)
       if k in validPragmas: 
         case k
         of wExportc: 
-          makeExternExport(sym, getOptionalStr(c, it, "$1"))
+          makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
           incl(sym.flags, sfUsed) # avoid wrong hints
         of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
         of wImportCompilerProc:
@@ -534,23 +556,25 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wAlign:
           if sym.typ == nil: invalidPragma(it)
           var align = expectIntLit(c, it)
-          if not IsPowerOfTwo(align) and align != 0: 
-            LocalError(it.info, errPowerOfTwoExpected)
+          if not isPowerOfTwo(align) and align != 0: 
+            localError(it.info, errPowerOfTwoExpected)
           else: 
             sym.typ.align = align              
         of wSize: 
           if sym.typ == nil: invalidPragma(it)
           var size = expectIntLit(c, it)
-          if not IsPowerOfTwo(size) or size <= 0 or size > 8: 
-            LocalError(it.info, errPowerOfTwoExpected)
+          if not isPowerOfTwo(size) or size <= 0 or size > 8: 
+            localError(it.info, errPowerOfTwoExpected)
           else:
             sym.typ.size = size
         of wNodecl: 
           noVal(it)
-          incl(sym.loc.Flags, lfNoDecl)
-        of wPure, wNoStackFrame:
+          incl(sym.loc.flags, lfNoDecl)
+        of wPure, wAsmNoStackFrame:
           noVal(it)
-          if sym != nil: incl(sym.flags, sfPure)
+          if sym != nil:
+            if k == wPure and sym.kind in routineKinds: invalidPragma(it)
+            else: incl(sym.flags, sfPure)
         of wVolatile: 
           noVal(it)
           incl(sym.flags, sfVolatile)
@@ -566,20 +590,20 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wCompileTime: 
           noVal(it)
           incl(sym.flags, sfCompileTime)
-          incl(sym.loc.Flags, lfNoDecl)
+          incl(sym.loc.flags, lfNoDecl)
         of wGlobal:
           noVal(it)
           incl(sym.flags, sfGlobal)
           incl(sym.flags, sfPure)
         of wMerge: 
-          noval(it)
+          noVal(it)
           incl(sym.flags, sfMerge)
         of wHeader: 
           var lib = getLib(c, libHeader, getStrLitNode(c, it))
           addToLib(lib, sym)
           incl(sym.flags, sfImportc)
           incl(sym.loc.flags, lfHeader)
-          incl(sym.loc.Flags, lfNoDecl) 
+          incl(sym.loc.flags, lfNoDecl) 
           # implies nodecl, because otherwise header would not make sense
           if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
         of wDestructor:
@@ -591,23 +615,23 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           noVal(it)
           incl(sym.flags, sfNoSideEffect)
           if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
-        of wSideEffect: 
+        of wSideeffect: 
           noVal(it)
           incl(sym.flags, sfSideEffect)
-        of wNoReturn: 
+        of wNoreturn: 
           noVal(it)
           incl(sym.flags, sfNoReturn)
-        of wDynLib: 
+        of wDynlib: 
           processDynLib(c, it, sym)
-        of wCompilerProc: 
+        of wCompilerproc: 
           noVal(it)           # compilerproc may not get a string!
-          makeExternExport(sym, "$1")
+          makeExternExport(sym, "$1", it.info)
           incl(sym.flags, sfCompilerProc)
           incl(sym.flags, sfUsed) # suppress all those stupid warnings
           registerCompilerProc(sym)
-        of wProcvar: 
+        of wProcVar: 
           noVal(it)
-          incl(sym.flags, sfProcVar)
+          incl(sym.flags, sfProcvar)
         of wDeprecated: 
           noVal(it)
           if sym != nil: incl(sym.flags, sfDeprecated)
@@ -616,9 +640,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           noVal(it)
           if sym.typ == nil: invalidPragma(it)
           else: incl(sym.typ.flags, tfVarargs)
-        of wBorrow: 
-          noVal(it)
-          incl(sym.flags, sfBorrow)
+        of wBorrow:
+          if sym.kind == skType:
+            typeBorrow(sym, it)
+          else:
+            noVal(it)
+            incl(sym.flags, sfBorrow)
         of wFinal: 
           noVal(it)
           if sym.typ == nil: invalidPragma(it)
@@ -638,10 +665,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wThread:
           noVal(it)
           incl(sym.flags, sfThread)
-          incl(sym.flags, sfProcVar)
+          incl(sym.flags, sfProcvar)
           if sym.typ != nil: incl(sym.typ.flags, tfThread)
-        of wHint: Message(it.info, hintUser, expectStrLit(c, it))
-        of wWarning: Message(it.info, warnUser, expectStrLit(c, it))
+        of wPacked:
+          noVal(it)
+          if sym.typ == nil: invalidPragma(it)
+          else: incl(sym.typ.flags, tfPacked)
+        of wHint: message(it.info, hintUser, expectStrLit(c, it))
+        of wWarning: message(it.info, warnUser, expectStrLit(c, it))
         of wError: 
           if sym != nil and sym.isRoutine:
             # This is subtle but correct: the error *statement* is only
@@ -651,17 +682,17 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
             noVal(it)
             incl(sym.flags, sfError)
           else:
-            LocalError(it.info, errUser, expectStrLit(c, it))
-        of wFatal: Fatal(it.info, errUser, expectStrLit(c, it))
+            localError(it.info, errUser, expectStrLit(c, it))
+        of wFatal: fatal(it.info, errUser, expectStrLit(c, it))
         of wDefine: processDefine(c, it)
         of wUndef: processUndef(c, it)
         of wCompile: processCompile(c, it)
         of wLink: processCommonLink(c, it, linkNormal)
-        of wLinkSys: processCommonLink(c, it, linkSys)
-        of wPassL: extccomp.addLinkOption(expectStrLit(c, it))
-        of wPassC: extccomp.addCompileOption(expectStrLit(c, it))
-        of wBreakpoint: PragmaBreakpoint(c, it)
-        of wWatchpoint: PragmaWatchpoint(c, it)
+        of wLinksys: processCommonLink(c, it, linkSys)
+        of wPassl: extccomp.addLinkOption(expectStrLit(c, it))
+        of wPassc: extccomp.addCompileOption(expectStrLit(c, it))
+        of wBreakpoint: pragmaBreakpoint(c, it)
+        of wWatchPoint: pragmaWatchpoint(c, it)
         of wPush: 
           processPush(c, n, i + 1)
           result = true 
@@ -679,18 +710,18 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, 
            wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, 
            wLinedir, wStacktrace, wLinetrace, wOptimization,
-           wCallConv, 
-           wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks,
+           wCallconv, 
+           wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks,
            wPatterns:
           if processOption(c, it):
             # calling conventions (boring...):
-            LocalError(it.info, errOptionExpected)
-        of firstCallConv..lastCallConv: 
+            localError(it.info, errOptionExpected)
+        of FirstCallConv..LastCallConv: 
           assert(sym != nil)
           if sym.typ == nil: invalidPragma(it)
           else: sym.typ.callConv = wordToCallConv(k)
-        of wEmit: PragmaEmit(c, it)
-        of wUnroll: PragmaUnroll(c, it)
+        of wEmit: pragmaEmit(c, it)
+        of wUnroll: pragmaUnroll(c, it)
         of wLinearScanEnd, wComputedGoto: noVal(it)
         of wEffects:
           # is later processed in effect analysis:
@@ -699,6 +730,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           noVal(it)
           if sym.typ == nil: invalidPragma(it)
           else: incl(sym.typ.flags, tfIncompleteStruct)
+        of wUnchecked:
+          noVal(it)
+          if sym.typ == nil: invalidPragma(it)
+          else: incl(sym.typ.flags, tfUncheckedArray)
+        of wUnion:
+          noVal(it)
+          if sym.typ == nil: invalidPragma(it)
+          else: incl(sym.typ.flags, tfUnion)
         of wRequiresInit:
           noVal(it)
           if sym.typ == nil: invalidPragma(it)
@@ -706,19 +745,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wByRef:
           noVal(it)
           if sym == nil or sym.typ == nil:
-            if processOption(c, it): LocalError(it.info, errOptionExpected)
+            if processOption(c, it): localError(it.info, errOptionExpected)
           else:
             incl(sym.typ.flags, tfByRef)
         of wByCopy:
           noVal(it)
           if sym.kind != skType or sym.typ == nil: invalidPragma(it)
           else: incl(sym.typ.flags, tfByCopy)
-        of wInject, wGenSym:
+        of wInject, wGensym:
           # We check for errors, but do nothing with these pragmas otherwise
           # as they are handled directly in 'evalTemplate'.
           noVal(it)
           if sym == nil: invalidPragma(it)
-        of wLine: PragmaLine(c, it)
+        of wLine: pragmaLine(c, it)
         of wRaises, wTags: pragmaRaisesOrTags(c, it)
         of wOperator:
           if sym == nil: invalidPragma(it)
@@ -732,29 +771,40 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
       else: invalidPragma(it)
   else: processNote(c, it)
 
-proc implictPragmas*(c: PContext, sym: PSym, n: PNode,
-                     validPragmas: TSpecialWords) =
+proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
+                      validPragmas: TSpecialWords) =
   if sym != nil and sym.kind != skModule:
-    var it = POptionEntry(c.optionstack.head)
+    var it = POptionEntry(c.optionStack.head)
     while it != nil:
       let o = it.otherPragmas
       if not o.isNil:
         for i in countup(0, sonsLen(o) - 1):
           if singlePragma(c, sym, o, i, validPragmas):
-            InternalError(n.info, "implicitPragmas")
+            internalError(n.info, "implicitPragmas")
       it = it.next.POptionEntry
 
-    if lfExportLib in sym.loc.flags and sfExportc notin sym.flags: 
-      LocalError(n.info, errDynlibRequiresExportc)
-    var lib = POptionEntry(c.optionstack.tail).dynlib
+    if lfExportLib in sym.loc.flags and sfExportc notin sym.flags:
+      localError(n.info, errDynlibRequiresExportc)
+    var lib = POptionEntry(c.optionStack.tail).dynlib
     if {lfDynamicLib, lfHeader} * sym.loc.flags == {} and
         sfImportc in sym.flags and lib != nil:
       incl(sym.loc.flags, lfDynamicLib)
       addToLib(lib, sym)
       if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
 
+proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
+  if n == nil or n.sons == nil:
+    return false
+
+  for p in n.sons:
+    var key = if p.kind == nkExprColonExpr: p[0] else: p
+    if key.kind == nkIdent and whichKeyword(key.ident) == pragma:
+      return true
+  
+  return false
+
 proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
   if n == nil: return
   for i in countup(0, sonsLen(n) - 1):
     if singlePragma(c, sym, n, i, validPragmas): break
-  implictPragmas(c, sym, n, validPragmas)
+  implicitPragmas(c, sym, n, validPragmas)
diff --git a/compiler/pretty.nim b/compiler/pretty.nim
index 5036a16a3..3a5bfe197 100644
--- a/compiler/pretty.nim
+++ b/compiler/pretty.nim
@@ -12,12 +12,12 @@
 
 import 
   strutils, os, options, ast, astalgo, msgs, ropes, idents, passes,
-  intsets, strtabs
+  intsets, strtabs, semdata
   
 const
   removeTP = false # when true, "nimrod pretty" converts TTyp to Typ.
 
-type 
+type
   TGen = object of TPassContext
     module*: PSym
   PGen = ref TGen
@@ -29,6 +29,7 @@ type
 
 var
   gSourceFiles: seq[TSourceFile] = @[]
+  gCheckExtern: bool
   rules: PStringTable
 
 proc loadFile(info: TLineInfo) =
@@ -44,13 +45,20 @@ proc loadFile(info: TLineInfo) =
       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 = gSourceFiles[i].fullpath.changeFileExt(".pretty.nim")
+    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:
-        f.writeln(line)
+        if doStrip:
+          f.write line.strip(leading = false, trailing = true)
+        else:
+          f.write line
+        f.write("\L")
       f.close
     except EIO:
       rawMessage(errCannotOpenFile, newFile)
@@ -60,18 +68,25 @@ proc `=~`(s: string, a: openArray[string]): bool =
     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:
-    # skip leading 'T'
+    # 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"]:
+             "cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any",
+             "range", "openarray", "varargs", "set", "cfloat"
+             ]:
       result.add s[i]
     else:
       result.add toUpper(s[i])
@@ -81,13 +96,19 @@ proc beautifyName(s: string, k: TSymKind): string =
   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
-  let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
   while i < s.len:
     if s[i] == '_':
-      inc i
-      result.add toUpper(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:
@@ -97,8 +118,7 @@ proc beautifyName(s: string, k: TSymKind): string =
 proc checkStyle*(info: TLineInfo, s: string, k: TSymKind) =
   let beau = beautifyName(s, k)
   if s != beau:
-    Message(info, errGenerated, 
-      "name does not adhere to naming convention; should be: " & beau)
+    message(info, errGenerated, "name should be: " & beau)
 
 const
   Letters = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
@@ -117,13 +137,90 @@ proc differ(line: string, a, b: int, x: string): bool =
       inc j
     return false
 
-var cannotRename = initIntSet()
+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
 
-proc processSym(c: PPassContext, n: PNode): PNode = 
-  result = n
-  var g = PGen(c)
-  case n.kind
-  of nkSym:
+  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*(n: PNode, s: PSym) =
+  if n.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(n.info)
+  
+  let line = gSourceFiles[n.info.fileIndex].lines[n.info.line-1]
+  var first = min(n.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[n.info.fileIndex].lines[n.info.line-1], x)
+    gSourceFiles[n.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 checkUse(c: PGen; n: PNode) =
     if n.info.fileIndex < 0: return
     let s = n.sym
     # operators stay as they are:
@@ -138,10 +235,11 @@ proc processSym(c: PPassContext, n: PNode): PNode =
     loadFile(n.info)
     
     let line = gSourceFiles[n.info.fileIndex].lines[n.info.line-1]
-    var first = n.info.col.int
+    var first = min(n.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
     
     if {sfImportc, sfExportc} * s.flags != {}:
@@ -149,8 +247,8 @@ proc processSym(c: PPassContext, n: PNode): PNode =
       # name:
       if newName != s.name.s and newName != s.loc.r.ropeToStr and
           lfFullExternalName notin s.loc.flags:
-        Message(n.info, errGenerated, 
-          "cannot rename $# to $# due to external name" % [s.name.s, newName])
+        #Message(n.info, errGenerated, 
+        #  "cannot rename $# to $# due to external name" % [s.name.s, newName])
         cannotRename.incl(s.id)
         return
     let last = first+identLen(line, first)-1
@@ -165,14 +263,50 @@ proc processSym(c: PPassContext, n: PNode): PNode =
       
       system.shallowCopy(gSourceFiles[n.info.fileIndex].lines[n.info.line-1], x)
       gSourceFiles[n.info.fileIndex].dirty = true
+
+proc check(c: PGen, n: PNode) =
+  case n.kind
+  of nkSym: checkUse(n, 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:
-      discard processSym(c, n.sons[i])
+    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)
diff --git a/compiler/procfind.nim b/compiler/procfind.nim
index aefccd140..0354d585d 100644
--- a/compiler/procfind.nim
+++ b/compiler/procfind.nim
@@ -17,52 +17,76 @@ proc equalGenericParams(procA, procB: PNode): bool =
   if sonsLen(procA) != sonsLen(procB): return
   for i in countup(0, sonsLen(procA) - 1):
     if procA.sons[i].kind != nkSym:
-      InternalError(procA.info, "equalGenericParams")
+      internalError(procA.info, "equalGenericParams")
       return
     if procB.sons[i].kind != nkSym:
-      InternalError(procB.info, "equalGenericParams")
+      internalError(procB.info, "equalGenericParams")
       return
     let a = procA.sons[i].sym
     let b = procB.sons[i].sym
     if a.name.id != b.name.id or
-        not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return
+        not sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}): return
     if a.ast != nil and b.ast != nil:
-      if not ExprStructuralEquivalent(a.ast, b.ast): return
+      if not exprStructuralEquivalent(a.ast, b.ast): return
   result = true
 
-proc SearchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
+proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
   # Searchs for a forward declaration or a "twin" symbol of fn
   # in the symbol table. If the parameter lists are exactly
   # the same the sym in the symbol table is returned, else nil.
   var it: TIdentIter
-  result = initIdentIter(it, scope.symbols, fn.Name)
+  result = initIdentIter(it, scope.symbols, fn.name)
   if isGenericRoutine(fn):
     # we simply check the AST; this is imprecise but nearly the best what
     # can be done; this doesn't work either though as type constraints are
     # not kept in the AST ..
     while result != nil:
-      if result.Kind == fn.kind and isGenericRoutine(result):
+      if result.kind == fn.kind and isGenericRoutine(result):
         let genR = result.ast.sons[genericParamsPos]
         let genF = fn.ast.sons[genericParamsPos]
-        if ExprStructuralEquivalent(genR, genF) and
-           ExprStructuralEquivalent(result.ast.sons[paramsPos],
+        if exprStructuralEquivalent(genR, genF) and
+           exprStructuralEquivalent(result.ast.sons[paramsPos],
                                     fn.ast.sons[paramsPos]) and
            equalGenericParams(genR, genF):
             return
-      result = NextIdentIter(it, scope.symbols)
+      result = nextIdentIter(it, scope.symbols)
   else:
     while result != nil:
-      if result.Kind == fn.kind and not isGenericRoutine(result):
+      if result.kind == fn.kind and not isGenericRoutine(result):
         case equalParams(result.typ.n, fn.typ.n)
         of paramsEqual:
           return
         of paramsIncompatible:
-          LocalError(fn.info, errNotOverloadable, fn.name.s)
+          localError(fn.info, errNotOverloadable, fn.name.s)
           return
         of paramsNotEqual:
-          nil
-      result = NextIdentIter(it, scope.symbols)
+          discard
+      result = nextIdentIter(it, scope.symbols)
 
+proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
+  const flags = {ExactGenericParams, ExactTypeDescValues,
+                 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): return
+
+    result = nextIdentIter(it, scope.symbols)
+  
+  return nil
+
+proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
+  result = searchForProcNew(c, scope, fn)
+  when false:
+    let old = searchForProcOld(c, scope, fn)
+    if old != result:
+      echo "Mismatch in searchForProc: ", fn.info
+      debug fn.typ
+      debug if result != nil: result.typ else: nil
+      debug if old != nil: old.typ else: nil
+ 
 when false:
   proc paramsFitBorrow(child, parent: PNode): bool = 
     var length = sonsLen(child)
@@ -77,7 +101,7 @@ when false:
                           dcEqOrDistinctOf): return
       result = true
 
-  proc SearchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
+  proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
     # Searchs for the fn in the symbol table. If the parameter lists are suitable
     # for borrowing the sym in the symbol table is returned, else nil.
     var it: TIdentIter
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 61babed66..fa119eba9 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -15,7 +15,7 @@ import
 type 
   TRenderFlag* = enum 
     renderNone, renderNoBody, renderNoComments, renderDocComments, 
-    renderNoPragmas, renderIds
+    renderNoPragmas, renderIds, renderNoProcDefs
   TRenderFlags* = set[TRenderFlag]
   TRenderTok*{.final.} = object 
     kind*: TTokType
@@ -51,10 +51,17 @@ proc isKeyword*(s: string): bool =
       (i.id <= ord(tokKeywordHigh) - ord(tkSymbol)): 
     result = true
 
-proc renderDefinitionName*(s: PSym): string =
+proc renderDefinitionName*(s: PSym, noQuotes = false): string =
+  ## Returns the definition name of the symbol.
+  ##
+  ## If noQuotes is false the symbol may be returned in backticks. This will
+  ## happen if the name happens to be a keyword or the first character is not
+  ## part of the SymStartChars set.
   let x = s.name.s
-  if x[0] in SymStartChars and not renderer.isKeyword(x): result = x
-  else: result = '`' & x & '`'
+  if noQuotes or (x[0] in SymStartChars and not renderer.isKeyword(x)):
+    result = x
+  else:
+    result = '`' & x & '`'
 
 const 
   IndentWidth = 2
@@ -62,7 +69,7 @@ const
   MaxLineLen = 80
   LineCommentColumn = 30
 
-proc InitSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) = 
+proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) = 
   g.comStack = @[]
   g.tokens = @[]
   g.indent = 0
@@ -76,7 +83,7 @@ proc InitSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) =
 
 proc addTok(g: var TSrcGen, kind: TTokType, s: string) = 
   var length = len(g.tokens)
-  setlen(g.tokens, length + 1)
+  setLen(g.tokens, length + 1)
   g.tokens[length].kind = kind
   g.tokens[length].length = int16(len(s))
   add(g.buf, s)
@@ -104,16 +111,16 @@ proc optNL(g: var TSrcGen) =
   optNL(g, g.indent)
 
 proc indentNL(g: var TSrcGen) = 
-  inc(g.indent, indentWidth)
+  inc(g.indent, IndentWidth)
   g.pendingNL = g.indent
   g.lineLen = g.indent
 
-proc Dedent(g: var TSrcGen) = 
-  dec(g.indent, indentWidth)
+proc dedent(g: var TSrcGen) = 
+  dec(g.indent, IndentWidth)
   assert(g.indent >= 0)
-  if g.pendingNL > indentWidth: 
-    Dec(g.pendingNL, indentWidth)
-    Dec(g.lineLen, indentWidth)
+  if g.pendingNL > IndentWidth: 
+    dec(g.pendingNL, IndentWidth)
+    dec(g.lineLen, IndentWidth)
 
 proc put(g: var TSrcGen, kind: TTokType, s: string) = 
   addPendingNL(g)
@@ -127,7 +134,7 @@ proc putLong(g: var TSrcGen, kind: TTokType, s: string, lineLen: int) =
   addTok(g, kind, s)
   g.lineLen = lineLen
 
-proc toNimChar(c: Char): string = 
+proc toNimChar(c: char): string = 
   case c
   of '\0': result = "\\0"
   of '\x01'..'\x1F', '\x80'..'\xFF': result = "\\x" & strutils.toHex(ord(c), 2)
@@ -236,19 +243,19 @@ proc containsNL(s: string): bool =
     of '\x0D', '\x0A': 
       return true
     else: 
-      nil
+      discard
   result = false
 
 proc pushCom(g: var TSrcGen, n: PNode) = 
   var length = len(g.comStack)
-  setlen(g.comStack, length + 1)
+  setLen(g.comStack, length + 1)
   g.comStack[length] = n
 
 proc popAllComs(g: var TSrcGen) = 
-  setlen(g.comStack, 0)
+  setLen(g.comStack, 0)
 
 proc popCom(g: var TSrcGen) = 
-  setlen(g.comStack, len(g.comStack) - 1)
+  setLen(g.comStack, len(g.comStack) - 1)
 
 const 
   Space = " "
@@ -269,7 +276,7 @@ proc gcom(g: var TSrcGen, n: PNode) =
     if (g.pendingNL < 0) and (len(g.buf) > 0) and
         (g.lineLen < LineCommentColumn): 
       var ml = maxLineLength(n.comment)
-      if ml + LineCommentColumn <= maxLineLen: 
+      if ml + LineCommentColumn <= MaxLineLen: 
         put(g, tkSpaces, repeatChar(LineCommentColumn - g.lineLen))
     putComment(g, n.comment)  #assert(g.comStack[high(g.comStack)] = n);
   
@@ -278,7 +285,7 @@ proc gcoms(g: var TSrcGen) =
   popAllComs(g)
 
 proc lsub(n: PNode): int
-proc litAux(n: PNode, x: biggestInt, size: int): string =
+proc litAux(n: PNode, x: BiggestInt, size: int): string =
   proc skip(t: PType): PType = 
     result = t
     while result.kind in {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
@@ -295,7 +302,7 @@ proc litAux(n: PNode, x: biggestInt, size: int): string =
   elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
   else: result = $x
 
-proc ulitAux(n: PNode, x: biggestInt, size: int): string = 
+proc ulitAux(n: PNode, x: BiggestInt, size: int): string = 
   if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8)
   elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3)
   elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
@@ -341,7 +348,7 @@ proc atom(n: PNode): string =
     if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s
     else: result = "[type node]"
   else: 
-    InternalError("rnimsyn.atom " & $n.kind)
+    internalError("rnimsyn.atom " & $n.kind)
     result = ""
   
 proc lcomma(n: PNode, start: int = 0, theEnd: int = - 1): int = 
@@ -361,11 +368,11 @@ proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int =
 proc lsub(n: PNode): int = 
   # computes the length of a tree
   if isNil(n): return 0
-  if n.comment != nil: return maxLineLen + 1
+  if n.comment != nil: return MaxLineLen + 1
   case n.kind
   of nkEmpty: result = 0
   of nkTripleStrLit: 
-    if containsNL(n.strVal): result = maxLineLen + 1
+    if containsNL(n.strVal): result = MaxLineLen + 1
     else: result = len(atom(n))
   of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit: 
     result = len(atom(n))
@@ -424,8 +431,13 @@ proc lsub(n: PNode): int =
   of nkRefTy: result = (if n.len > 0: lsub(n.sons[0])+1 else: 0) + len("ref")
   of nkPtrTy: result = (if n.len > 0: lsub(n.sons[0])+1 else: 0) + len("ptr")
   of nkVarTy: result = (if n.len > 0: lsub(n.sons[0])+1 else: 0) + len("var")
-  of nkDistinctTy: result = (if n.len > 0: lsub(n.sons[0])+1 else: 0) +
-                                                               len("Distinct")
+  of nkDistinctTy:
+    result = len("distinct") + (if n.len > 0: lsub(n.sons[0])+1 else: 0)
+    if n.len > 1:
+      result += (if n[1].kind == nkWith: len("_with_") else: len("_without_"))
+      result += lcomma(n[1])
+  of nkStaticTy: result = (if n.len > 0: lsub(n.sons[0]) else: 0) +
+                                                         len("static[]")
   of nkTypeDef: result = lsons(n) + 3
   of nkOfInherit: result = lsub(n.sons[0]) + len("of_")
   of nkProcTy: result = lsons(n) + len("proc_")
@@ -438,7 +450,7 @@ proc lsub(n: PNode): int =
       result = len("enum")
   of nkEnumFieldDef: result = lsons(n) + 3
   of nkVarSection, nkLetSection: 
-    if sonsLen(n) > 1: result = maxLineLen + 1
+    if sonsLen(n) > 1: result = MaxLineLen + 1
     else: result = lsons(n) + len("var_")
   of nkReturnStmt: result = lsub(n.sons[0]) + len("return_")
   of nkRaiseStmt: result = lsub(n.sons[0]) + len("raise_")
@@ -459,10 +471,10 @@ proc lsub(n: PNode): int =
     if n.sons[0].kind != nkEmpty: result = result + lsub(n.sons[0]) + 2
   of nkExceptBranch: 
     result = lcomma(n, 0, -2) + lsub(lastSon(n)) + len("except_:_")
-  else: result = maxLineLen + 1
+  else: result = MaxLineLen + 1
   
 proc fits(g: TSrcGen, x: int): bool = 
-  result = x + g.lineLen <= maxLineLen
+  result = x + g.lineLen <= MaxLineLen
 
 type 
   TSubFlag = enum 
@@ -487,7 +499,7 @@ proc hasCom(n: PNode): bool =
   result = false
   if n.comment != nil: return true
   case n.kind
-  of nkEmpty..nkNilLit: nil
+  of nkEmpty..nkNilLit: discard
   else: 
     for i in countup(0, sonsLen(n) - 1): 
       if hasCom(n.sons[i]): return true
@@ -501,7 +513,7 @@ proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
   for i in countup(start, sonsLen(n) + theEnd):
     var c = i < sonsLen(n) + theEnd
     var sublen = lsub(n.sons[i]) + ord(c)
-    if not fits(g, sublen) and (ind + sublen < maxLineLen): optNL(g, ind)
+    if not fits(g, sublen) and (ind + sublen < MaxLineLen): optNL(g, ind)
     let oldLen = g.tokens.len
     gsub(g, n.sons[i])
     if c:
@@ -515,21 +527,21 @@ proc gcomma(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
             theEnd: int = - 1) = 
   var ind: int
   if rfInConstExpr in c.flags: 
-    ind = g.indent + indentWidth
+    ind = g.indent + IndentWidth
   else: 
     ind = g.lineLen
-    if ind > maxLineLen div 2: ind = g.indent + longIndentWid
+    if ind > MaxLineLen div 2: ind = g.indent + longIndentWid
   gcommaAux(g, n, ind, start, theEnd)
 
 proc gcomma(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) = 
   var ind = g.lineLen
-  if ind > maxLineLen div 2: ind = g.indent + longIndentWid
+  if ind > MaxLineLen div 2: ind = g.indent + longIndentWid
   gcommaAux(g, n, ind, start, theEnd)
 
 proc gsemicolon(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) = 
   var ind = g.lineLen
-  if ind > maxLineLen div 2: ind = g.indent + longIndentWid
-  gcommaAux(g, n, ind, start, theEnd, tkSemicolon)
+  if ind > MaxLineLen div 2: ind = g.indent + longIndentWid
+  gcommaAux(g, n, ind, start, theEnd, tkSemiColon)
 
 proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0, 
            theEnd: int = - 1) = 
@@ -552,20 +564,23 @@ proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool =
   if not result: 
     # check further
     for i in countup(start, sonsLen(n) + theEnd): 
-      if (lsub(n.sons[i]) > maxLineLen): 
+      if (lsub(n.sons[i]) > MaxLineLen): 
         result = true
         break 
 
-proc gstmts(g: var TSrcGen, n: PNode, c: TContext) = 
-  if n.kind == nkEmpty: return 
-  if (n.kind == nkStmtList) or (n.kind == nkStmtListExpr): 
-    indentNL(g)
-    for i in countup(0, sonsLen(n) - 1): 
+proc gstmts(g: var TSrcGen, n: PNode, c: TContext, doIndent=true) =
+  if n.kind == nkEmpty: return
+  if n.kind in {nkStmtList, nkStmtListExpr, nkStmtListType}:
+    if doIndent: indentNL(g)
+    for i in countup(0, sonsLen(n) - 1):
       optNL(g)
-      gsub(g, n.sons[i])
+      if n.sons[i].kind in {nkStmtList, nkStmtListExpr, nkStmtListType}:
+        gstmts(g, n.sons[i], c, doIndent=false)
+      else:
+        gsub(g, n.sons[i])
       gcoms(g)
-    dedent(g)
-  else: 
+    if doIndent: dedent(g)
+  else:
     if rfLongMode in c.flags: indentNL(g)
     gsub(g, n)
     gcoms(g)
@@ -577,7 +592,7 @@ proc gif(g: var TSrcGen, n: PNode) =
   gsub(g, n.sons[0].sons[0])
   initContext(c)
   putWithSpace(g, tkColon, ":")
-  if longMode(n) or (lsub(n.sons[0].sons[1]) + g.lineLen > maxLineLen): 
+  if longMode(n) or (lsub(n.sons[0].sons[1]) + g.lineLen > MaxLineLen): 
     incl(c.flags, rfLongMode)
   gcoms(g)                    # a good place for comments
   gstmts(g, n.sons[0].sons[1], c)
@@ -592,7 +607,7 @@ proc gwhile(g: var TSrcGen, n: PNode) =
   gsub(g, n.sons[0])
   putWithSpace(g, tkColon, ":")
   initContext(c)
-  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen): 
+  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): 
     incl(c.flags, rfLongMode)
   gcoms(g)                    # a good place for comments
   gstmts(g, n.sons[1], c)
@@ -601,7 +616,7 @@ proc gpattern(g: var TSrcGen, n: PNode) =
   var c: TContext
   put(g, tkCurlyLe, "{")
   initContext(c)
-  if longMode(n) or (lsub(n.sons[0]) + g.lineLen > maxLineLen):
+  if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen):
     incl(c.flags, rfLongMode)
   gcoms(g)                    # a good place for comments
   gstmts(g, n.sons[0], c)
@@ -612,7 +627,7 @@ proc gpragmaBlock(g: var TSrcGen, n: PNode) =
   gsub(g, n.sons[0])
   putWithSpace(g, tkColon, ":")
   initContext(c)
-  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen):
+  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen):
     incl(c.flags, rfLongMode)
   gcoms(g)                    # a good place for comments
   gstmts(g, n.sons[1], c)
@@ -622,7 +637,7 @@ proc gtry(g: var TSrcGen, n: PNode) =
   put(g, tkTry, "try")
   putWithSpace(g, tkColon, ":")
   initContext(c)
-  if longMode(n) or (lsub(n.sons[0]) + g.lineLen > maxLineLen): 
+  if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen): 
     incl(c.flags, rfLongMode)
   gcoms(g)                    # a good place for comments
   gstmts(g, n.sons[0], c)
@@ -635,7 +650,7 @@ proc gfor(g: var TSrcGen, n: PNode) =
   initContext(c)
   if longMode(n) or
       (lsub(n.sons[length - 1]) + lsub(n.sons[length - 2]) + 6 + g.lineLen >
-      maxLineLen): 
+      MaxLineLen): 
     incl(c.flags, rfLongMode)
   gcomma(g, n, c, 0, - 3)
   put(g, tkSpaces, Space)
@@ -650,7 +665,7 @@ proc gmacro(g: var TSrcGen, n: PNode) =
   initContext(c)
   gsub(g, n.sons[0])
   putWithSpace(g, tkColon, ":")
-  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen): 
+  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): 
     incl(c.flags, rfLongMode)
   gcoms(g)
   gsons(g, n, c, 1)
@@ -701,6 +716,19 @@ proc gproc(g: var TSrcGen, n: PNode) =
       gcoms(g)
       dedent(g)
 
+proc gTypeClassTy(g: var TSrcGen, n: PNode) =
+  var c: TContext
+  initContext(c)
+  putWithSpace(g, tkGeneric, "generic")
+  gsons(g, n[0], c) # arglist
+  gsub(g, n[1]) # pragmas
+  gsub(g, n[2]) # of
+  gcoms(g)
+  indentNL(g)
+  gcoms(g)
+  gstmts(g, n[3], c)
+  dedent(g)
+
 proc gblock(g: var TSrcGen, n: PNode) = 
   var c: TContext
   initContext(c)
@@ -710,7 +738,7 @@ proc gblock(g: var TSrcGen, n: PNode) =
   else:
     put(g, tkBlock, "block")
   putWithSpace(g, tkColon, ":")
-  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen): 
+  if longMode(n) or (lsub(n.sons[1]) + g.lineLen > MaxLineLen): 
     incl(c.flags, rfLongMode)
   gcoms(g)
   # XXX I don't get why this is needed here! gstmts should already handle this!
@@ -723,7 +751,7 @@ proc gstaticStmt(g: var TSrcGen, n: PNode) =
   putWithSpace(g, tkStatic, "static")
   putWithSpace(g, tkColon, ":")
   initContext(c)
-  if longMode(n) or (lsub(n.sons[0]) + g.lineLen > maxLineLen): 
+  if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen): 
     incl(c.flags, rfLongMode)
   gcoms(g)                    # a good place for comments
   gstmts(g, n.sons[0], c)
@@ -769,7 +797,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   if n.comment != nil: pushCom(g, n)
   case n.kind                 # atoms:
   of nkTripleStrLit: putRawStr(g, tkTripleStrLit, n.strVal)
-  of nkEmpty: nil
+  of nkEmpty: discard
   of nkType: put(g, tkInvalid, atom(n))
   of nkSym, nkIdent: gident(g, n)
   of nkIntLit: put(g, tkIntLit, atom(n))
@@ -817,7 +845,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     put(g, tkParRi, ")")
   of nkStaticExpr:
     put(g, tkStatic, "static")
-    put(g, tkSpaces, space)
+    put(g, tkSpaces, Space)
     gsub(g, n.sons[0])
   of nkBracketExpr: 
     gsub(g, n.sons[0])
@@ -834,7 +862,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     gcomma(g, n, 1)
   of nkCommand: 
     gsub(g, n.sons[0])
-    put(g, tkSpaces, space)
+    put(g, tkSpaces, Space)
     gcomma(g, n, 1)
   of nkExprEqExpr, nkAsgn, nkFastAsgn: 
     gsub(g, n.sons[0])
@@ -941,7 +969,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkPrefix: 
     gsub(g, n.sons[0])
     if n.len > 1:
-      put(g, tkSpaces, space)
+      put(g, tkSpaces, Space)
       if n.sons[1].kind == nkInfix:
         put(g, tkParLe, "(")
         gsub(g, n.sons[1])
@@ -1002,9 +1030,15 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     else:
       put(g, tkVar, "var")
   of nkDistinctTy: 
-    if sonsLen(n) > 0:
+    if n.len > 0:
       putWithSpace(g, tkDistinct, "distinct")
       gsub(g, n.sons[0])
+      if n.len > 1:
+        if n[1].kind == nkWith:
+          putWithSpace(g, tkWith, " with")
+        else:
+          putWithSpace(g, tkWithout, " without")
+        gcomma(g, n[1])
     else:
       put(g, tkDistinct, "distinct")
   of nkTypeDef: 
@@ -1054,6 +1088,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
       gsub(g, n.sons[0])
     else:
       put(g, tkShared, "shared")
+  of nkStaticTy:
+    put(g, tkStatic, "static")
+    put(g, tkBracketLe, "[")
+    if n.len > 0:
+      gsub(g, n.sons[0])
+    put(g, tkBracketRi, "]")    
   of nkEnumTy:
     if sonsLen(n) > 0:
       putWithSpace(g, tkEnum, "enum")
@@ -1070,7 +1110,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     put(g, tkSpaces, Space)
     putWithSpace(g, tkEquals, "=")
     gsub(g, n.sons[1])
-  of nkStmtList, nkStmtListExpr: gstmts(g, n, emptyContext)
+  of nkStmtList, nkStmtListExpr, nkStmtListType: gstmts(g, n, emptyContext)
   of nkIfStmt: 
     putWithSpace(g, tkIf, "if")
     gif(g, n)
@@ -1086,22 +1126,22 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkStaticStmt: gstaticStmt(g, n)
   of nkAsmStmt: gasm(g, n)
   of nkProcDef: 
-    putWithSpace(g, tkProc, "proc")
+    if renderNoProcDefs notin g.flags: putWithSpace(g, tkProc, "proc")
     gproc(g, n)
   of nkConverterDef:
-    putWithSpace(g, tkConverter, "converter")
+    if renderNoProcDefs notin g.flags: putWithSpace(g, tkConverter, "converter")
     gproc(g, n)
   of nkMethodDef: 
-    putWithSpace(g, tkMethod, "method")
+    if renderNoProcDefs notin g.flags: putWithSpace(g, tkMethod, "method")
     gproc(g, n)
   of nkIteratorDef: 
-    putWithSpace(g, tkIterator, "iterator")
+    if renderNoProcDefs notin g.flags: putWithSpace(g, tkIterator, "iterator")
     gproc(g, n)
   of nkMacroDef: 
-    putWithSpace(g, tkMacro, "macro")
+    if renderNoProcDefs notin g.flags: putWithSpace(g, tkMacro, "macro")
     gproc(g, n)
   of nkTemplateDef: 
-    putWithSpace(g, tkTemplate, "template")
+    if renderNoProcDefs notin g.flags: putWithSpace(g, tkTemplate, "template")
     gproc(g, n)
   of nkTypeSection: 
     gsection(g, n, emptyContext, tkType, "type")
@@ -1247,9 +1287,20 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
       put(g, tkBracketLe, "[")
       gcomma(g, n)
       put(g, tkBracketRi, "]")
+  of nkMetaNode_Obsolete:
+    put(g, tkParLe, "(META|")
+    gsub(g, n.sons[0])
+    put(g, tkParRi, ")")
+  of nkGotoState, nkState:
+    var c: TContext
+    initContext c
+    putWithSpace g, tkSymbol, if n.kind == nkState: "state" else: "goto"
+    gsons(g, n, c)
+  of nkTypeClassTy:
+    gTypeClassTy(g, n)
   else: 
-    #nkNone, nkMetaNode, nkExplicitTypeListCall: 
-    InternalError(n.info, "rnimsyn.gsub(" & $n.kind & ')')
+    #nkNone, nkExplicitTypeListCall: 
+    internalError(n.info, "rnimsyn.gsub(" & $n.kind & ')')
 
 proc renderTree(n: PNode, renderFlags: TRenderFlags = {}): string = 
   var g: TSrcGen
@@ -1260,7 +1311,7 @@ proc renderTree(n: PNode, renderFlags: TRenderFlags = {}): string =
 proc renderModule(n: PNode, filename: string, 
                   renderFlags: TRenderFlags = {}) =
   var
-    f: tfile
+    f: TFile
     g: TSrcGen
   initSrcGen(g, renderFlags)
   for i in countup(0, sonsLen(n) - 1):
@@ -1269,7 +1320,7 @@ proc renderModule(n: PNode, filename: string,
     case n.sons[i].kind
     of nkTypeSection, nkConstSection, nkVarSection, nkLetSection,
        nkCommentStmt: putNL(g)
-    else: nil
+    else: discard
   gcoms(g)
   if optStdout in gGlobalOptions:
     write(stdout, g.buf)
@@ -1292,4 +1343,3 @@ proc getNextTok(r: var TSrcGen, kind: var TTokType, literal: var string) =
     inc(r.idx)
   else: 
     kind = tkEof
-  
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index 6e6b83260..036e6cc3c 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -184,7 +184,7 @@ proc skipNode(r: PRodReader) =
       if par == 0: break
       dec par
     of '(': inc par
-    else: nil
+    else: discard
     inc pos
   r.pos = pos+1 # skip ')'
 
@@ -248,7 +248,7 @@ proc decodeNodeLazyBody(r: PRodReader, fInfo: TLineInfo,
     if r.s[r.pos] == ')': inc(r.pos)
     else: internalError(result.info, "decodeNode: ')' missing")
   else:
-    InternalError(fInfo, "decodeNode: '(' missing " & $r.pos)
+    internalError(fInfo, "decodeNode: '(' missing " & $r.pos)
 
 proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
   result = decodeNodeLazyBody(r, fInfo, nil)
@@ -286,7 +286,7 @@ proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
     else: 
       loc.a = 0
     if r.s[r.pos] == '>': inc(r.pos)
-    else: InternalError(info, "decodeLoc " & r.s[r.pos])
+    else: internalError(info, "decodeLoc " & r.s[r.pos])
   
 proc decodeType(r: PRodReader, info: TLineInfo): PType = 
   result = nil
@@ -303,10 +303,10 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
     setId(result.id)
     if debugIds: registerID(result)
   else: 
-    InternalError(info, "decodeType: no id")
+    internalError(info, "decodeType: no id")
   # here this also avoids endless recursion for recursive type
-  IdTablePut(gTypeTable, result, result) 
-  if r.s[r.pos] == '(': result.n = decodeNode(r, UnknownLineInfo())
+  idTablePut(gTypeTable, result, result) 
+  if r.s[r.pos] == '(': result.n = decodeNode(r, unknownLineInfo())
   if r.s[r.pos] == '$': 
     inc(r.pos)
     result.flags = cast[TTypeFlags](int32(decodeVInt(r.s, r.pos)))
@@ -335,7 +335,7 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
     if r.s[r.pos] == '(': 
       inc(r.pos)
       if r.s[r.pos] == ')': inc(r.pos)
-      else: InternalError(info, "decodeType ^(" & r.s[r.pos])
+      else: internalError(info, "decodeType ^(" & r.s[r.pos])
       rawAddSon(result, nil)
     else: 
       var d = decodeVInt(r.s, r.pos)
@@ -347,10 +347,10 @@ proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
     new(result)
     inc(r.pos)
     result.kind = TLibKind(decodeVInt(r.s, r.pos))
-    if r.s[r.pos] != '|': InternalError("decodeLib: 1")
+    if r.s[r.pos] != '|': internalError("decodeLib: 1")
     inc(r.pos)
     result.name = toRope(decodeStr(r.s, r.pos))
-    if r.s[r.pos] != '|': InternalError("decodeLib: 2")
+    if r.s[r.pos] != '|': internalError("decodeLib: 2")
     inc(r.pos)
     result.path = decodeNode(r, info)
 
@@ -370,21 +370,21 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
     id = decodeVInt(r.s, r.pos)
     setId(id)
   else:
-    InternalError(info, "decodeSym: no id")
+    internalError(info, "decodeSym: no id")
   if r.s[r.pos] == '&': 
     inc(r.pos)
     ident = getIdent(decodeStr(r.s, r.pos))
   else:
-    InternalError(info, "decodeSym: no ident")
+    internalError(info, "decodeSym: no ident")
   #echo "decoding: {", ident.s
-  result = PSym(IdTableGet(r.syms, id))
+  result = PSym(idTableGet(r.syms, id))
   if result == nil: 
     new(result)
     result.id = id
-    IdTablePut(r.syms, result, result)
+    idTablePut(r.syms, result, result)
     if debugIds: registerID(result)
   elif result.id != id:
-    InternalError(info, "decodeSym: wrong id")
+    internalError(info, "decodeSym: wrong id")
   elif result.kind != skStub and not r.inViewMode:
     # we already loaded the symbol
     return
@@ -427,7 +427,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
   result.annex = decodeLib(r, info)
   if r.s[r.pos] == '#':
     inc(r.pos)
-    result.constraint = decodeNode(r, UnknownLineInfo())
+    result.constraint = decodeNode(r, unknownLineInfo())
   if r.s[r.pos] == '(':
     if result.kind in routineKinds:
       result.ast = decodeNodeLazyBody(r, result.info, result)
@@ -455,10 +455,10 @@ proc skipSection(r: PRodReader) =
         elif c > 0: 
           dec(c)
       of '\0': break          # end of file
-      else: nil
+      else: discard
       inc(r.pos)
   else: 
-    InternalError("skipSection " & $r.line)
+    internalError("skipSection " & $r.line)
   
 proc rdWord(r: PRodReader): string = 
   result = ""
@@ -472,11 +472,11 @@ proc newStub(r: PRodReader, name: string, id: int): PSym =
   result.id = id
   result.name = getIdent(name)
   result.position = r.readerIndex
-  setID(id)                   #MessageOut(result.name.s);
+  setId(id)                   #MessageOut(result.name.s);
   if debugIds: registerID(result)
   
 proc processInterf(r: PRodReader, module: PSym) = 
-  if r.interfIdx == 0: InternalError("processInterf")
+  if r.interfIdx == 0: internalError("processInterf")
   r.pos = r.interfIdx
   while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
     var w = decodeStr(r.s, r.pos)
@@ -485,23 +485,23 @@ proc processInterf(r: PRodReader, module: PSym) =
     inc(r.pos)                # #10
     var s = newStub(r, w, key)
     s.owner = module
-    StrTableAdd(module.tab, s)
-    IdTablePut(r.syms, s, s)
+    strTableAdd(module.tab, s)
+    idTablePut(r.syms, s, s)
 
 proc processCompilerProcs(r: PRodReader, module: PSym) = 
-  if r.compilerProcsIdx == 0: InternalError("processCompilerProcs")
+  if r.compilerProcsIdx == 0: internalError("processCompilerProcs")
   r.pos = r.compilerProcsIdx
   while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): 
     var w = decodeStr(r.s, r.pos)
     inc(r.pos)
     var key = decodeVInt(r.s, r.pos)
     inc(r.pos)                # #10
-    var s = PSym(IdTableGet(r.syms, key))
+    var s = PSym(idTableGet(r.syms, key))
     if s == nil: 
       s = newStub(r, w, key)
       s.owner = module
-      IdTablePut(r.syms, s, s)
-    StrTableAdd(rodCompilerProcs, s)
+      idTablePut(r.syms, s, s)
+    strTableAdd(rodCompilerprocs, s)
 
 proc processIndex(r: PRodReader; idx: var TIndex; outf: TFile = nil) = 
   var key, val, tmp: int
@@ -516,11 +516,11 @@ proc processIndex(r: PRodReader; idx: var TIndex; outf: TFile = nil) =
     else:
       key = idx.lastIdxKey + 1
       val = tmp + idx.lastIdxVal
-    IITablePut(idx.tab, key, val)
+    iiTablePut(idx.tab, key, val)
     if not outf.isNil: outf.write(key, " ", val, "\n")
     idx.lastIdxKey = key
     idx.lastIdxVal = val
-    setID(key)                # ensure that this id will not be used
+    setId(key)                # ensure that this id will not be used
     if r.s[r.pos] == '\x0A': 
       inc(r.pos)
       inc(r.line)
@@ -539,7 +539,7 @@ proc cmdChangeTriggersRecompilation(old, new: TCommands): bool =
   of cmdNone, cmdDoc, cmdInterpret, cmdPretty, cmdGenDepend, cmdDump,
       cmdCheck, cmdParse, cmdScan, cmdIdeTools, cmdDef, 
       cmdRst2html, cmdRst2tex, cmdInteractive, cmdRun:
-    nil
+    discard
   # else: trigger recompilation:
   result = true
   
@@ -558,7 +558,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
     of "ID": 
       inc(r.pos)              # skip ':'
       r.moduleID = decodeVInt(r.s, r.pos)
-      setID(r.moduleID)
+      setId(r.moduleID)
     of "ORIGFILE":
       inc(r.pos)
       r.origFile = decodeStr(r.s, r.pos)
@@ -603,7 +603,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
         inc(r.pos)            # skip ' '
         inclCrc = decodeVInt(r.s, r.pos)
         if r.reason == rrNone: 
-          if not ExistsFile(w) or (inclCrc != int(crcFromFile(w))): 
+          if not existsFile(w) or (inclCrc != int(crcFromFile(w))): 
             r.reason = rrInclDeps
         if r.s[r.pos] == '\x0A': 
           inc(r.pos)
@@ -639,7 +639,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
       r.initIdx = r.pos + 2   # "(\10"
       skipSection(r)
     else:
-      InternalError("invalid section: '" & section &
+      internalError("invalid section: '" & section &
                     "' at " & $r.line & " in " & r.filename)
       #MsgWriteln("skipping section: " & section &
       #           " at " & $r.line & " in " & r.filename)
@@ -658,7 +658,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
                   readerIndex: int): PRodReader = 
   new(result)
   try:
-    result.memFile = memfiles.open(modfilename)
+    result.memfile = memfiles.open(modfilename)
   except EOS:
     return nil
   result.files = @[]
@@ -670,13 +670,13 @@ proc newRodReader(modfilename: string, crc: TCrc32,
   r.line = 1
   r.readerIndex = readerIndex
   r.filename = modfilename
-  InitIdTable(r.syms)
+  initIdTable(r.syms)
   # we terminate the file explicitely with ``\0``, so the cast to `cstring`
   # is safe:
-  r.s = cast[cstring](r.memFile.mem)
+  r.s = cast[cstring](r.memfile.mem)
   if startsWith(r.s, "NIM:"): 
-    initIITable(r.index.tab)
-    initIITable(r.imports.tab) # looks like a ROD file
+    initIiTable(r.index.tab)
+    initIiTable(r.imports.tab) # looks like a ROD file
     inc(r.pos, 4)
     var version = ""
     while r.s[r.pos] notin {'\0', '\x0A'}:
@@ -691,12 +691,12 @@ proc newRodReader(modfilename: string, crc: TCrc32,
     result = nil
   
 proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType = 
-  result = PType(IdTableGet(gTypeTable, id))
+  result = PType(idTableGet(gTypeTable, id))
   if result == nil: 
     # load the type:
     var oldPos = r.pos
-    var d = IITableGet(r.index.tab, id)
-    if d == invalidKey: InternalError(info, "rrGetType")
+    var d = iiTableGet(r.index.tab, id)
+    if d == InvalidKey: internalError(info, "rrGetType")
     r.pos = d + r.dataIdx
     result = decodeType(r, info)
     r.pos = oldPos
@@ -715,7 +715,7 @@ var gMods*: TFileModuleMap = @[]
 
 proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym = 
   # all compiled modules
-  if rd.dataIdx == 0: InternalError(info, "dataIdx == 0")
+  if rd.dataIdx == 0: internalError(info, "dataIdx == 0")
   var oldPos = rd.pos
   rd.pos = offset + rd.dataIdx
   result = decodeSym(rd, info)
@@ -725,8 +725,8 @@ proc findSomeWhere(id: int) =
   for i in countup(0, high(gMods)): 
     var rd = gMods[i].rd
     if rd != nil: 
-      var d = IITableGet(rd.index.tab, id)
-      if d != invalidKey:
+      var d = iiTableGet(rd.index.tab, id)
+      if d != InvalidKey:
         echo "found id ", id, " in ", gMods[i].filename
 
 proc getReader(moduleId: int): PRodReader =
@@ -736,37 +736,37 @@ proc getReader(moduleId: int): PRodReader =
   # problems:
   for i in 0 .. <gMods.len:
     result = gMods[i].rd
-    if result != nil and result.moduleId == moduleId: return result
+    if result != nil and result.moduleID == moduleId: return result
   return nil
 
 proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym = 
-  result = PSym(IdTableGet(r.syms, id))
+  result = PSym(idTableGet(r.syms, id))
   if result == nil: 
     # load the symbol:
-    var d = IITableGet(r.index.tab, id)
-    if d == invalidKey: 
+    var d = iiTableGet(r.index.tab, id)
+    if d == InvalidKey: 
       # import from other module:
-      var moduleID = IiTableGet(r.imports.tab, id)
+      var moduleID = iiTableGet(r.imports.tab, id)
       if moduleID < 0:
         var x = ""
         encodeVInt(id, x)
-        InternalError(info, "missing from both indexes: +" & x)
+        internalError(info, "missing from both indexes: +" & x)
       var rd = getReader(moduleID)
-      d = IITableGet(rd.index.tab, id)
-      if d != invalidKey: 
+      d = iiTableGet(rd.index.tab, id)
+      if d != InvalidKey: 
         result = decodeSymSafePos(rd, d, info)
       else:
         var x = ""
         encodeVInt(id, x)
         when false: findSomeWhere(id)
-        InternalError(info, "rrGetSym: no reader found: +" & x)
+        internalError(info, "rrGetSym: no reader found: +" & x)
     else: 
       # own symbol:
       result = decodeSymSafePos(r, d, info)
   if result != nil and result.kind == skStub: rawLoadStub(result)
   
 proc loadInitSection(r: PRodReader): PNode = 
-  if r.initIdx == 0 or r.dataIdx == 0: InternalError("loadInitSection")
+  if r.initIdx == 0 or r.dataIdx == 0: internalError("loadInitSection")
   var oldPos = r.pos
   r.pos = r.initIdx
   result = newNode(nkStmtList)
@@ -775,7 +775,7 @@ proc loadInitSection(r: PRodReader): PNode =
     inc(r.pos)                # #10
     var p = r.pos
     r.pos = d + r.dataIdx
-    addSon(result, decodeNode(r, UnknownLineInfo()))
+    addSon(result, decodeNode(r, unknownLineInfo()))
     r.pos = p
   r.pos = oldPos
 
@@ -783,24 +783,24 @@ proc loadConverters(r: PRodReader) =
   # We have to ensure that no exported converter is a stub anymore, and the
   # import mechanism takes care of the rest.
   if r.convertersIdx == 0 or r.dataIdx == 0: 
-    InternalError("importConverters")
+    internalError("importConverters")
   r.pos = r.convertersIdx
   while r.s[r.pos] > '\x0A': 
     var d = decodeVInt(r.s, r.pos)
-    discard rrGetSym(r, d, UnknownLineInfo())
+    discard rrGetSym(r, d, unknownLineInfo())
     if r.s[r.pos] == ' ': inc(r.pos)
 
 proc loadMethods(r: PRodReader) =
   if r.methodsIdx == 0 or r.dataIdx == 0:
-    InternalError("loadMethods")
+    internalError("loadMethods")
   r.pos = r.methodsIdx
   while r.s[r.pos] > '\x0A':
     var d = decodeVInt(r.s, r.pos)
-    r.methods.add(rrGetSym(r, d, UnknownLineInfo()))
+    r.methods.add(rrGetSym(r, d, unknownLineInfo()))
     if r.s[r.pos] == ' ': inc(r.pos)
 
-proc GetCRC*(fileIdx: int32): TCrc32 =
-  InternalAssert fileIdx >= 0 and fileIdx < gMods.len
+proc getCRC*(fileIdx: int32): TCrc32 =
+  internalAssert fileIdx >= 0 and fileIdx < gMods.len
 
   if gMods[fileIdx].crcDone:
     return gMods[fileIdx].crc
@@ -818,14 +818,14 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
     # reason has already been computed for this module:
     return gMods[fileIdx].reason
   let filename = fileIdx.toFilename
-  var crc = GetCRC(fileIdx)
+  var crc = getCRC(fileIdx)
   gMods[fileIdx].reason = rrNone  # we need to set it here to avoid cycles
   result = rrNone
   var r: PRodReader = nil
   var rodfile = toGeneratedFile(filename.withPackageName, RodExt)
   r = newRodReader(rodfile, crc, fileIdx)
   if r == nil: 
-    result = (if ExistsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
+    result = (if existsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
   else:
     processRodFile(r, crc)
     result = r.reason
@@ -834,7 +834,7 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
       # NOTE: we need to process the entire module graph so that no ID will
       # be used twice! However, compilation speed does not suffer much from
       # this, since results are cached.
-      var res = checkDep(SystemFileIdx)
+      var res = checkDep(systemFileIdx)
       if res != rrNone: result = rrModDeps
       for i in countup(0, high(r.modDeps)):
         res = checkDep(r.modDeps[i])
@@ -845,7 +845,7 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
     rawMessage(hintProcessing, reasonToFrmt[result] % filename)
   if result != rrNone or optForceFullMake in gGlobalOptions:
     # recompilation is necessary:
-    if r != nil: memfiles.close(r.memFile)
+    if r != nil: memfiles.close(r.memfile)
     r = nil
   gMods[fileIdx].rd = r
   gMods[fileIdx].reason = result  # now we know better
@@ -858,11 +858,11 @@ proc handleSymbolFile(module: PSym): PRodReader =
   idgen.loadMaxIds(options.gProjectPath / options.gProjectName)
 
   discard checkDep(fileIdx)
-  if gMods[fileIdx].reason == rrEmpty: InternalError("handleSymbolFile")
+  if gMods[fileIdx].reason == rrEmpty: internalError("handleSymbolFile")
   result = gMods[fileIdx].rd
   if result != nil: 
     module.id = result.moduleID
-    IdTablePut(result.syms, module, module)
+    idTablePut(result.syms, module, module)
     processInterf(result, module)
     processCompilerProcs(result, module)
     loadConverters(result)
@@ -871,26 +871,26 @@ proc handleSymbolFile(module: PSym): PRodReader =
     module.id = getID()
 
 proc rawLoadStub(s: PSym) =
-  if s.kind != skStub: InternalError("loadStub")
+  if s.kind != skStub: internalError("loadStub")
   var rd = gMods[s.position].rd
   var theId = s.id                # used for later check
-  var d = IITableGet(rd.index.tab, s.id)
-  if d == invalidKey: InternalError("loadStub: invalid key")
-  var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
+  var d = iiTableGet(rd.index.tab, s.id)
+  if d == InvalidKey: internalError("loadStub: invalid key")
+  var rs = decodeSymSafePos(rd, d, unknownLineInfo())
   if rs != s:
     #echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2),
     #     "\ns:  ", toHex(cast[int](s.position), int.sizeof * 2)
-    InternalError(rs.info, "loadStub: wrong symbol")
+    internalError(rs.info, "loadStub: wrong symbol")
   elif rs.id != theId: 
-    InternalError(rs.info, "loadStub: wrong ID") 
+    internalError(rs.info, "loadStub: wrong ID") 
   #MessageOut('loaded stub: ' + s.name.s);
   
-proc LoadStub*(s: PSym) =
+proc loadStub*(s: PSym) =
   ## loads the stub symbol `s`.
   
   # deactivate the GC here because we do a deep recursion and generate no
   # garbage when restoring parts of the object graph anyway.
-  # Since we die with internal errors if this fails, so no try-finally is
+  # Since we die with internal errors if this fails, no try-finally is
   # necessary.
   GC_disable()
   rawLoadStub(s)
@@ -912,8 +912,8 @@ proc getBody*(s: PSym): PNode =
     s.ast.sons[bodyPos] = result
     s.offset = 0
   
-InitIdTable(gTypeTable)
-InitStrTable(rodCompilerProcs)
+initIdTable(gTypeTable)
+initStrTable(rodCompilerprocs)
 
 # viewer:
 proc writeNode(f: TFile; n: PNode) =
@@ -1038,7 +1038,7 @@ proc viewFile(rodfile: string) =
     of "ID": 
       inc(r.pos)              # skip ':'
       r.moduleID = decodeVInt(r.s, r.pos)
-      setID(r.moduleID)
+      setId(r.moduleID)
       outf.writeln("ID:", $r.moduleID)
     of "ORIGFILE":
       inc(r.pos)
@@ -1140,12 +1140,12 @@ proc viewFile(rodfile: string) =
       outf.write("DATA(\n")
       while r.s[r.pos] != ')':
         if r.s[r.pos] == '(':
-          outf.writeNode decodeNode(r, UnknownLineInfo())
+          outf.writeNode decodeNode(r, unknownLineInfo())
           outf.write("\n")
         elif r.s[r.pos] == '[':
-          outf.writeType decodeType(r, UnknownLineInfo())
+          outf.writeType decodeType(r, unknownLineInfo())
         else:
-          outf.writeSym decodeSym(r, UnknownLineInfo())
+          outf.writeSym decodeSym(r, unknownLineInfo())
         if r.s[r.pos] == '\x0A':
           inc(r.pos)
           inc(r.line)
@@ -1166,7 +1166,7 @@ proc viewFile(rodfile: string) =
       if r.s[r.pos] == ')': inc r.pos
       outf.write("<not supported by viewer>)\n")
     else:
-      InternalError("invalid section: '" & section &
+      internalError("invalid section: '" & section &
                     "' at " & $r.line & " in " & r.filename)
       skipSection(r)
     if r.s[r.pos] == '\x0A':
diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim
index 0ee3b1ec4..4433ed4ab 100644
--- a/compiler/rodutils.nim
+++ b/compiler/rodutils.nim
@@ -12,7 +12,7 @@ import strutils
 
 proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", nodecl, varargs.}
 
-proc ToStrMaxPrecision*(f: BiggestFloat): string = 
+proc toStrMaxPrecision*(f: BiggestFloat): string = 
   if f != f:
     result = "NAN"
   elif f == 0.0:
@@ -36,7 +36,7 @@ proc hexChar(c: char, xi: var int) =
   of '0'..'9': xi = (xi shl 4) or (ord(c) - ord('0'))
   of 'a'..'f': xi = (xi shl 4) or (ord(c) - ord('a') + 10)
   of 'A'..'F': xi = (xi shl 4) or (ord(c) - ord('A') + 10)
-  else: nil
+  else: discard
 
 proc decodeStr*(s: cstring, pos: var int): string =
   var i = pos
@@ -119,7 +119,7 @@ template decodeIntImpl() =
 proc decodeVInt*(s: cstring, pos: var int): int = 
   decodeIntImpl()
 
-proc decodeVBiggestInt*(s: cstring, pos: var int): biggestInt =
+proc decodeVBiggestInt*(s: cstring, pos: var int): BiggestInt =
   decodeIntImpl()
 
 iterator decodeVIntArray*(s: cstring): int =
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index 2e52aeaa7..4231da2d0 100644
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -56,7 +56,7 @@ proc fileIdx(w: PRodWriter, filename: string): int =
     if w.files[i] == filename: 
       return i
   result = len(w.files)
-  setlen(w.files, result + 1)
+  setLen(w.files, result + 1)
   w.files[result] = filename
 
 template filename*(w: PRodWriter): string =
@@ -66,8 +66,8 @@ proc newRodWriter(crc: TCrc32, module: PSym): PRodWriter =
   new(result)
   result.sstack = @[]
   result.tstack = @[]
-  InitIITable(result.index.tab)
-  InitIITable(result.imports.tab)
+  initIiTable(result.index.tab)
+  initIiTable(result.imports.tab)
   result.index.r = ""
   result.imports.r = ""
   result.crc = crc
@@ -101,12 +101,12 @@ proc addInclDep(w: PRodWriter, dep: string) =
 
 proc pushType(w: PRodWriter, t: PType) =
   # check so that the stack does not grow too large:
-  if IiTableGet(w.index.tab, t.id) == invalidKey:
+  if iiTableGet(w.index.tab, t.id) == InvalidKey:
     w.tstack.add(t)
 
 proc pushSym(w: PRodWriter, s: PSym) =
   # check so that the stack does not grow too large:
-  if IiTableGet(w.index.tab, s.id) == invalidKey:
+  if iiTableGet(w.index.tab, s.id) == InvalidKey:
     w.sstack.add(s)
 
 proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode, 
@@ -120,19 +120,19 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
   # we do not write comments for now
   # Line information takes easily 20% or more of the filesize! Therefore we
   # omit line information if it is the same as the father's line information:
-  if finfo.fileIndex != n.info.fileIndex: 
+  if fInfo.fileIndex != n.info.fileIndex: 
     result.add('?')
     encodeVInt(n.info.col, result)
     result.add(',')
     encodeVInt(n.info.line, result)
     result.add(',')
     encodeVInt(fileIdx(w, toFilename(n.info)), result)
-  elif finfo.line != n.info.line:
+  elif fInfo.line != n.info.line:
     result.add('?')
     encodeVInt(n.info.col, result)
     result.add(',')
     encodeVInt(n.info.line, result)
-  elif finfo.col != n.info.col:
+  elif fInfo.col != n.info.col:
     result.add('?')
     encodeVInt(n.info.col, result)
   # No need to output the file index, as this is the serialization of one
@@ -190,7 +190,7 @@ proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
   if loc.a != 0: 
     add(result, '?')
     encodeVInt(loc.a, result)
-  if oldlen + 1 == result.len:
+  if oldLen + 1 == result.len:
     # no data was necessary, so remove the '<' again:
     setLen(result, oldLen)
   else:
@@ -202,7 +202,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
     result.add("[]")
     return
   # we need no surrounding [] here because the type is in a line of its own
-  if t.kind == tyForward: InternalError("encodeType: tyForward")
+  if t.kind == tyForward: internalError("encodeType: tyForward")
   # for the new rodfile viewer we use a preceeding [ so that the data section
   # can easily be disambiguated:
   add(result, '[')
@@ -210,7 +210,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
   add(result, '+')
   encodeVInt(t.id, result)
   if t.n != nil: 
-    encodeNode(w, UnknownLineInfo(), t.n, result)
+    encodeNode(w, unknownLineInfo(), t.n, result)
   if t.flags != {}: 
     add(result, '$')
     encodeVInt(cast[int32](t.flags), result)
@@ -292,7 +292,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
   if s.annex != nil: encodeLib(w, s.annex, s.info, result)
   if s.constraint != nil:
     add(result, '#')
-    encodeNode(w, UnknownLineInfo(), s.constraint, result)
+    encodeNode(w, unknownLineInfo(), s.constraint, result)
   # lazy loading will soon reload the ast lazily, so the ast needs to be
   # the last entry of a symbol:
   if s.ast != nil:
@@ -322,7 +322,7 @@ proc addToIndex(w: var TIndex, key, val: int) =
   add(w.r, rodNL)
   w.lastIdxKey = key
   w.lastIdxVal = val
-  IiTablePut(w.tab, key, val)
+  iiTablePut(w.tab, key, val)
 
 const debugWrittenIds = false
 
@@ -336,9 +336,9 @@ proc symStack(w: PRodWriter): int =
     if sfForward in s.flags:
       w.sstack[result] = s
       inc result
-    elif IiTableGet(w.index.tab, s.id) == invalidKey:
+    elif iiTableGet(w.index.tab, s.id) == InvalidKey:
       var m = getModule(s)
-      if m == nil: InternalError("symStack: module nil: " & s.name.s)
+      if m == nil: internalError("symStack: module nil: " & s.name.s)
       if (m.id == w.module.id) or (sfFromGeneric in s.flags): 
         # put definition in here
         var L = w.data.len
@@ -364,7 +364,7 @@ proc symStack(w: PRodWriter): int =
         if s.kind == skMethod and sfDispatcher notin s.flags:
           if w.methods.len != 0: add(w.methods, ' ')
           encodeVInt(s.id, w.methods)
-      elif IiTableGet(w.imports.tab, s.id) == invalidKey: 
+      elif iiTableGet(w.imports.tab, s.id) == InvalidKey: 
         addToIndex(w.imports, s.id, m.id)
         when debugWrittenIds:
           if not Contains(debugWritten, s.id):
@@ -374,7 +374,7 @@ proc symStack(w: PRodWriter): int =
             debug(m)
             InternalError("Symbol referred to but never written")
     inc(i)
-  setlen(w.sstack, result)
+  setLen(w.sstack, result)
 
 proc typeStack(w: PRodWriter): int = 
   var i = 0
@@ -383,13 +383,13 @@ proc typeStack(w: PRodWriter): int =
     if t.kind == tyForward:
       w.tstack[result] = t
       inc result
-    elif IiTableGet(w.index.tab, t.id) == invalidKey: 
+    elif iiTableGet(w.index.tab, t.id) == InvalidKey: 
       var L = w.data.len
       addToIndex(w.index, t.id, L)
       encodeType(w, t, w.data)
       add(w.data, rodNL)
     inc(i)
-  setlen(w.tstack, result)
+  setLen(w.tstack, result)
 
 proc processStacks(w: PRodWriter, finalPass: bool) =
   var oldS = 0
@@ -401,7 +401,7 @@ proc processStacks(w: PRodWriter, finalPass: bool) =
     oldS = slen
     oldT = tlen
   if finalPass and (oldS != 0 or oldT != 0):
-    InternalError("could not serialize some forwarded symbols/types")
+    internalError("could not serialize some forwarded symbols/types")
 
 proc rawAddInterfaceSym(w: PRodWriter, s: PSym) = 
   pushSym(w, s)
@@ -416,7 +416,7 @@ proc addInterfaceSym(w: PRodWriter, s: PSym) =
 proc addStmt(w: PRodWriter, n: PNode) = 
   encodeVInt(w.data.len, w.init)
   add(w.init, rodNL)
-  encodeNode(w, UnknownLineInfo(), n, w.data)
+  encodeNode(w, unknownLineInfo(), n, w.data)
   add(w.data, rodNL)
   processStacks(w, false)
 
@@ -534,9 +534,9 @@ proc process(c: PPassContext, n: PNode): PNode =
   of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef, 
       nkTemplateDef, nkMacroDef: 
     var s = n.sons[namePos].sym
-    if s == nil: InternalError(n.info, "rodwrite.process")
+    if s == nil: internalError(n.info, "rodwrite.process")
     if n.sons[bodyPos] == nil:
-      InternalError(n.info, "rodwrite.process: body is nil")
+      internalError(n.info, "rodwrite.process: body is nil")
     if n.sons[bodyPos].kind != nkEmpty or s.magic != mNone or
         sfForward notin s.flags:
       addInterfaceSym(w, s)
@@ -549,7 +549,7 @@ proc process(c: PPassContext, n: PNode): PNode =
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if a.sons[0].kind != nkSym: InternalError(a.info, "rodwrite.process")
+      if a.sons[0].kind != nkSym: internalError(a.info, "rodwrite.process")
       var s = a.sons[0].sym
       addInterfaceSym(w, s) 
       # this takes care of enum fields too
@@ -573,11 +573,11 @@ proc process(c: PPassContext, n: PNode): PNode =
   of nkPragma: 
     addStmt(w, n)
   else: 
-    nil
+    discard
 
 proc myOpen(module: PSym): PPassContext =
-  if module.id < 0: InternalError("rodwrite: module ID not set")
-  var w = newRodWriter(module.fileIdx.GetCRC, module)
+  if module.id < 0: internalError("rodwrite: module ID not set")
+  var w = newRodWriter(module.fileIdx.getCRC, module)
   rawAddInterfaceSym(w, module)
   result = w
 
diff --git a/compiler/ropes.nim b/compiler/ropes.nim
index ce81aae37..fcf5dd202 100644
--- a/compiler/ropes.nim
+++ b/compiler/ropes.nim
@@ -91,13 +91,13 @@ proc writeRopeIfNotEqual*(r: PRope, filename: string): bool
 proc ropeToStr*(p: PRope): string
 proc ropef*(frmt: TFormatStr, args: varargs[PRope]): PRope
 proc appf*(c: var PRope, frmt: TFormatStr, args: varargs[PRope])
-proc RopeEqualsFile*(r: PRope, f: string): bool
+proc ropeEqualsFile*(r: PRope, f: string): bool
   # returns true if the rope r is the same as the contents of file f
-proc RopeInvariant*(r: PRope): bool
+proc ropeInvariant*(r: PRope): bool
   # exported for debugging
 # implementation
 
-var ErrorHandler*: proc(err: TRopesError, msg: string, useWarning = false)
+var errorHandler*: proc(err: TRopesError, msg: string, useWarning = false)
   # avoid dependency on msgs.nim
   
 proc ropeLen(a: PRope): int = 
@@ -126,7 +126,7 @@ proc resetRopeCache* =
   for i in low(cache)..high(cache):
     cache[i] = nil
 
-proc RopeInvariant(r: PRope): bool = 
+proc ropeInvariant(r: PRope): bool = 
   if r == nil: 
     result = true
   else: 
@@ -157,14 +157,14 @@ proc toRope(s: string): PRope =
     result = nil
   else:
     result = insertInCache(s)
-  assert(RopeInvariant(result))
+  assert(ropeInvariant(result))
 
-proc RopeSeqInsert(rs: var TRopeSeq, r: PRope, at: Natural) = 
+proc ropeSeqInsert(rs: var TRopeSeq, r: PRope, at: Natural) = 
   var length = len(rs)
   if at > length: 
-    setlen(rs, at + 1)
+    setLen(rs, at + 1)
   else: 
-    setlen(rs, length + 1)    # move old rope elements:
+    setLen(rs, length + 1)    # move old rope elements:
   for i in countdown(length, at + 1): 
     rs[i] = rs[i - 1] # this is correct, I used pen and paper to validate it
   rs[at] = r
@@ -177,8 +177,8 @@ proc newRecRopeToStr(result: var string, resultLen: var int, r: PRope) =
       add(stack, it.right)
       it = it.left
     assert(it.data != nil)
-    CopyMem(addr(result[resultLen]), addr(it.data[0]), it.length)
-    Inc(resultLen, it.length)
+    copyMem(addr(result[resultLen]), addr(it.data[0]), it.length)
+    inc(resultLen, it.length)
     assert(resultLen <= len(result))
 
 proc ropeToStr(p: PRope): string = 
@@ -227,13 +227,13 @@ proc writeRope*(f: TFile, c: PRope) =
     assert(it.data != nil)
     write(f, it.data)
 
-proc WriteRope*(head: PRope, filename: string, useWarning = false) =
-  var f: tfile
+proc writeRope*(head: PRope, filename: string, useWarning = false) =
+  var f: TFile
   if open(f, filename, fmWrite):
-    if head != nil: WriteRope(f, head)
+    if head != nil: writeRope(f, head)
     close(f)
   else:
-    ErrorHandler(rCannotOpenFile, filename, useWarning)
+    errorHandler(rCannotOpenFile, filename, useWarning)
 
 var
   rnl* = tnl.newRope
@@ -258,12 +258,12 @@ proc ropef(frmt: TFormatStr, args: varargs[PRope]): PRope =
       of '0'..'9': 
         var j = 0
         while true: 
-          j = (j * 10) + Ord(frmt[i]) - ord('0')
+          j = (j * 10) + ord(frmt[i]) - ord('0')
           inc(i)
           if (i > length + 0 - 1) or not (frmt[i] in {'0'..'9'}): break 
         num = j
         if j > high(args) + 1:
-          ErrorHandler(rInvalidFormatStr, $(j))
+          errorHandler(rInvalidFormatStr, $(j))
         else:
           app(result, args[j - 1])
       of 'n':
@@ -273,21 +273,25 @@ proc ropef(frmt: TFormatStr, args: varargs[PRope]): PRope =
         app(result, rnl)
         inc(i)
       else:
-        ErrorHandler(rInvalidFormatStr, $(frmt[i]))
+        errorHandler(rInvalidFormatStr, $(frmt[i]))
     var start = i
     while i < length:
       if frmt[i] != '$': inc(i)
       else: break
     if i - 1 >= start: 
       app(result, substr(frmt, start, i - 1))
-  assert(RopeInvariant(result))
-
-{.push stack_trace: off, line_trace: off.}
-proc `~`*(r: string): PRope =
-  # this is the new optimized "to rope" operator
-  # the mnemonic is that `~` looks a bit like a rope :)
-  return r.ropef
-{.pop.}
+  assert(ropeInvariant(result))
+
+when true:
+  template `~`*(r: string): PRope = r.ropef
+else:
+  {.push stack_trace: off, line_trace: off.}
+  proc `~`*(r: static[string]): PRope =
+    # this is the new optimized "to rope" operator
+    # the mnemonic is that `~` looks a bit like a rope :)
+    var r {.global.} = r.ropef
+    return r
+  {.pop.}
 
 proc appf(c: var PRope, frmt: TFormatStr, args: varargs[PRope]) = 
   app(c, ropef(frmt, args))
@@ -295,10 +299,10 @@ 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 TFile, buf: pointer): bool = 
   if r.data != nil:
     if r.length > bufSize:
-      ErrorHandler(rTokenTooLong, r.data)
+      errorHandler(rTokenTooLong, r.data)
       return
     var readBytes = readBuffer(bin, buf, r.length)
     result = readBytes == r.length and
@@ -307,12 +311,12 @@ proc auxRopeEqualsFile(r: PRope, bin: var tfile, buf: Pointer): bool =
     result = auxRopeEqualsFile(r.left, bin, buf)
     if result: result = auxRopeEqualsFile(r.right, bin, buf)
   
-proc RopeEqualsFile(r: PRope, f: string): bool = 
-  var bin: tfile
+proc ropeEqualsFile(r: PRope, f: string): bool = 
+  var bin: TFile
   result = open(bin, f)
   if not result: 
     return                    # not equal if file does not exist
-  var buf = alloc(BufSize)
+  var buf = alloc(bufSize)
   result = auxRopeEqualsFile(r, bin, buf)
   if result: 
     result = readBuffer(bin, buf, bufSize) == 0 # really at the end of file?
@@ -345,7 +349,7 @@ proc newCrcFromRopeAux(r: PRope, startVal: TCrc32): TCrc32 =
       inc(i)
 
 proc crcFromRope(r: PRope): TCrc32 = 
-  result = newCrcFromRopeAux(r, initCrc32)
+  result = newCrcFromRopeAux(r, InitCrc32)
 
 proc writeRopeIfNotEqual(r: PRope, filename: string): bool = 
   # returns true if overwritten
diff --git a/compiler/saturate.nim b/compiler/saturate.nim
index e0968843b..ed197bdd1 100644
--- a/compiler/saturate.nim
+++ b/compiler/saturate.nim
@@ -9,7 +9,7 @@
 
 ## Saturated arithmetic routines. XXX Make part of the stdlib?
 
-proc `|+|`*(a, b: biggestInt): biggestInt =
+proc `|+|`*(a, b: BiggestInt): BiggestInt =
   ## saturated addition.
   result = a +% b
   if (result xor a) >= 0'i64 or (result xor b) >= 0'i64:
@@ -19,7 +19,7 @@ proc `|+|`*(a, b: biggestInt): biggestInt =
   else:
     result = high(result)
 
-proc `|-|`*(a, b: biggestInt): biggestInt =
+proc `|-|`*(a, b: BiggestInt): BiggestInt =
   result = a -% b
   if (result xor a) >= 0'i64 or (result xor not b) >= 0'i64:
     return result
@@ -28,14 +28,14 @@ proc `|-|`*(a, b: biggestInt): biggestInt =
   else:
     result = high(result)
 
-proc `|abs|`*(a: biggestInt): biggestInt =
+proc `|abs|`*(a: BiggestInt): BiggestInt =
   if a != low(a):
     if a >= 0: result = a
     else: result = -a
   else:
     result = low(a)
 
-proc `|div|`*(a, b: biggestInt): biggestInt =
+proc `|div|`*(a, b: BiggestInt): BiggestInt =
   # (0..5) div (0..4) == (0..5) div (1..4) == (0 div 4) .. (5 div 1)
   if b == 0'i64:
     # make the same as ``div 1``:
@@ -45,13 +45,13 @@ proc `|div|`*(a, b: biggestInt): biggestInt =
   else:
     result = a div b
 
-proc `|mod|`*(a, b: biggestInt): biggestInt =
+proc `|mod|`*(a, b: BiggestInt): BiggestInt =
   if b == 0'i64:
     result = a
   else:
     result = a mod b
 
-proc `|*|`*(a, b: biggestInt): biggestInt =
+proc `|*|`*(a, b: BiggestInt): BiggestInt =
   var
     resAsFloat, floatProd: float64
   result = a *% b
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 3ace623bc..e7bff0665 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -14,8 +14,8 @@ import
   wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
   magicsys, parser, nversion, nimsets, semfold, importer,
   procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
-  semthreads, intsets, transf, evals, idgen, aliases, cgmeth, lambdalifting,
-  evaltempl, patterns, parampatterns, sempass2
+  semthreads, intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
+  evaltempl, patterns, parampatterns, sempass2, pretty, semmacrosanity
 
 # implementation
 
@@ -43,30 +43,33 @@ proc activate(c: PContext, n: PNode)
 proc semQuoteAst(c: PContext, n: PNode): PNode
 proc finishMethod(c: PContext, s: PSym)
 
-proc IndexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode
+proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode
 
 proc typeMismatch(n: PNode, formal, actual: PType) = 
   if formal.kind != tyError and actual.kind != tyError: 
-    LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
+    localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
         typeToString(actual) & ") " &
         `%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
 
 proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
   if arg.typ.isNil:
-    LocalError(arg.info, errExprXHasNoType,
+    localError(arg.info, errExprXHasNoType,
                renderTree(arg, {renderNoComments}))
     # error correction:
     result = copyNode(arg)
     result.typ = formal
   else:
-    result = IndexTypesMatch(c, formal, arg.typ, arg)
+    result = indexTypesMatch(c, formal, arg.typ, arg)
     if result == nil:
       typeMismatch(arg, formal, arg.typ)
       # error correction:
-      result = copyNode(arg)
+      result = copyTree(arg)
       result.typ = formal
 
-var CommonTypeBegin = PType(kind: tyExpr)
+proc inferWithMetatype(c: PContext, formal: PType,
+                       arg: PNode, coerceDistincts = false): PNode
+
+var commonTypeBegin = PType(kind: tyExpr)
 
 proc commonType*(x, y: PType): PType =
   # new type relation that is used for array constructors,
@@ -83,7 +86,9 @@ proc commonType*(x, y: PType): PType =
   elif a.kind == tyTypeDesc:
     # turn any concrete typedesc into the abstract typedesc type
     if a.sons == nil: result = a
-    else: result = newType(tyTypeDesc, a.owner)
+    else:
+      result = newType(tyTypeDesc, a.owner)
+      rawAddSon(result, newType(tyNone, a.owner))
   elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and 
       a.kind == b.kind:
     # check for seq[empty] vs. seq[int]
@@ -113,12 +118,13 @@ proc commonType*(x, y: PType): PType =
     if a.kind in {tyRef, tyPtr}:
       k = a.kind
       if b.kind != a.kind: return x
-      a = a.sons[0]
-      b = b.sons[0]
+      a = a.lastSon
+      b = b.lastSon
     if a.kind == tyObject and b.kind == tyObject:
       result = commonSuperclass(a, b)
       # this will trigger an error later:
-      if result.isNil: return x
+      if result.isNil or result == a: return x
+      if result == b: return y
       if k != tyNone:
         let r = result
         result = newType(k, r.owner)
@@ -134,8 +140,12 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
   # like newSymS, but considers gensym'ed symbols
   if n.kind == nkSym:
     result = n.sym
-    InternalAssert sfGenSym in result.flags
-    InternalAssert result.kind == kind
+    internalAssert sfGenSym in result.flags
+    internalAssert result.kind == kind
+    # when there is a nested proc inside a template, semtmpl
+    # will assign a wrong owner during the first pass over the
+    # template; we must fix it here: see #909
+    result.owner = getCurrOwner()
   else:
     result = newSym(kind, considerAcc(n), getCurrOwner(), n.info)
 
@@ -146,73 +156,123 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
                         allowed: TSymFlags): PSym
 proc semStmtScope(c: PContext, n: PNode): PNode
 
-proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
+proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
   if not typeAllowed(typ, skConst):
-    LocalError(typ.n.info, errXisNoType, typeToString(typ))
+    localError(typ.n.info, errXisNoType, typeToString(typ))
 
 proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
-proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
 proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
 proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
-proc IsOpImpl(c: PContext, n: PNode): PNode
+proc isOpImpl(c: PContext, n: PNode): PNode
+proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
+                     flags: TExprFlags = {}): PNode
 proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
-                  semCheck: bool = true): PNode
+                  flags: TExprFlags = {}): PNode
+
+proc symFromType(t: PType, info: TLineInfo): PSym =
+  if t.sym != nil: return t.sym
+  result = newSym(skType, getIdent"AnonType", t.owner, info)
+  result.flags.incl sfAnon
+  result.typ = t
+
+proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
+  result = newSymNode(symFromType(t, info), info)
+  result.typ = makeTypeDesc(c, t)
 
 when false:
-  proc symFromType(t: PType, info: TLineInfo): PSym =
-    if t.sym != nil: return t.sym
-    result = newSym(skType, getIdent"AnonType", t.owner, info)
-    result.flags.incl sfAnon
-    result.typ = t
-
-  proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
-    result = newSymNode(symFromType(t, info), info)
-    result.typ = makeTypeDesc(c, t)
-
-proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
-  result = newEvalContext(c.module, mode)
-  result.getType = proc (n: PNode): PNode =
-    result = tryExpr(c, n)
-    if result == nil:
-      result = newSymNode(errorSym(c, n))
-    elif result.typ == nil:
-      result = newSymNode(getSysSym"void")
+  proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
+    result = newEvalContext(c.module, mode)
+    result.getType = proc (n: PNode): PNode =
+      result = tryExpr(c, n)
+      if result == nil:
+        result = newSymNode(errorSym(c, n))
+      elif result.typ == nil:
+        result = newSymNode(getSysSym"void")
+      else:
+        result.typ = makeTypeDesc(c, result.typ)
+    
+    result.handleIsOperator = proc (n: PNode): PNode =
+      result = isOpImpl(c, n)
+
+proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
+  # recompute the types as 'eval' isn't guaranteed to construct types nor
+  # that the types are sound:
+  when true:
+    if eOrig.typ.kind in {tyExpr, tyStmt, tyTypeDesc}:
+      result = semExprWithType(c, evaluated)
     else:
-      result.typ = makeTypeDesc(c, result.typ)
+      result = evaluated
+      let expectedType = eOrig.typ.skipTypes({tyStatic})
+      semmacrosanity.annotateType(result, expectedType)
+  else:
+    result = semExprWithType(c, evaluated)
+    #result = fitNode(c, e.typ, result) inlined with special case:
+    let arg = result
+    result = indexTypesMatch(c, eOrig.typ, arg.typ, arg)
+    if result == nil:
+      result = arg
+      # for 'tcnstseq' we support [] to become 'seq'
+      if eOrig.typ.skipTypes(abstractInst).kind == tySequence and 
+         arg.typ.skipTypes(abstractInst).kind == tyArrayConstr:
+        arg.typ = eOrig.typ
 
-  result.handleIsOperator = proc (n: PNode): PNode =
-    result = IsOpImpl(c, n)
+proc tryConstExpr(c: PContext, n: PNode): PNode =
+  var e = semExprWithType(c, n)
+  if e == nil: return
 
-proc evalConstExpr(c: PContext, module: PSym, e: PNode): PNode = 
-  result = evalConstExprAux(c.createEvalContext(emConst), module, nil, e)
+  result = getConstExpr(c.module, e)
+  if result != nil: return
 
-proc evalStaticExpr(c: PContext, module: PSym, e: PNode, prc: PSym): PNode = 
-  result = evalConstExprAux(c.createEvalContext(emStatic), module, prc, e)
+  let oldErrorCount = msgs.gErrorCounter
+  let oldErrorMax = msgs.gErrorMax
+  let oldErrorOutputs = errorOutputs
+
+  errorOutputs = {}
+  msgs.gErrorMax = high(int)
+
+  try:
+    result = evalConstExpr(c.module, e)
+    if result == nil or result.kind == nkEmpty:
+      result = nil
+    else:
+      result = fixupTypeAfterEval(c, result, e)
+
+  except ERecoverableError:
+    result = nil
+
+  msgs.gErrorCounter = oldErrorCount
+  msgs.gErrorMax = oldErrorMax
+  errorOutputs = oldErrorOutputs
 
 proc semConstExpr(c: PContext, n: PNode): PNode =
   var e = semExprWithType(c, n)
   if e == nil:
-    LocalError(n.info, errConstExprExpected)
+    localError(n.info, errConstExprExpected)
     return n
   result = getConstExpr(c.module, e)
   if result == nil:
-    result = evalConstExpr(c, c.module, e)
+    result = evalConstExpr(c.module, e)
     if result == nil or result.kind == nkEmpty:
       if e.info != n.info:
         pushInfoContext(n.info)
-        LocalError(e.info, errConstExprExpected)
+        localError(e.info, errConstExprExpected)
         popInfoContext()
       else:
-        LocalError(e.info, errConstExprExpected)
+        localError(e.info, errConstExprExpected)
       # error correction:
       result = e
+    else:
+      result = fixupTypeAfterEval(c, result, e)
 
 include hlo, seminst, semcall
 
-proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode = 
+proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
+                       flags: TExprFlags): PNode =
   inc(evalTemplateCounter)
   if evalTemplateCounter > 100:
-    GlobalError(s.info, errTemplateInstantiationTooNested)
+    globalError(s.info, errTemplateInstantiationTooNested)
+  let oldFriend = c.friendModule
+  c.friendModule = s.owner.getModule
 
   result = n
   if s.typ.sons[0] == nil:
@@ -223,7 +283,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
       # BUGFIX: we cannot expect a type here, because module aliases would not 
       # work then (see the ``tmodulealias`` test)
       # semExprWithType(c, result)
-      result = semExpr(c, result)
+      result = semExpr(c, result, flags)
     of tyStmt:
       result = semStmt(c, result)
     of tyTypeDesc:
@@ -232,22 +292,24 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
       result.typ = makeTypeDesc(c, typ)
       #result = symNodeFromType(c, typ, n.info)
     else:
-      result = semExpr(c, result)
+      result = semExpr(c, result, flags)
       result = fitNode(c, s.typ.sons[0], result)
       #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
   dec(evalTemplateCounter)
+  c.friendModule = oldFriend
 
-proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, 
-                  semCheck: bool = true): PNode = 
+proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
+                  flags: TExprFlags = {}): PNode =
   markUsed(n, sym)
   if sym == c.p.owner:
-    GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
+    globalError(n.info, errRecursiveDependencyX, sym.name.s)
 
-  if c.evalContext == nil:
-    c.evalContext = c.createEvalContext(emStatic)
+  #if c.evalContext == nil:
+  #  c.evalContext = c.createEvalContext(emStatic)
 
-  result = evalMacroCall(c.evalContext, n, nOrig, sym)
-  if semCheck: result = semAfterMacroCall(c, result, sym)
+  result = evalMacroCall(c.module, n, nOrig, sym)
+  if efNoSemCheck notin flags:
+    result = semAfterMacroCall(c, result, sym, flags)
 
 proc forceBool(c: PContext, n: PNode): PNode = 
   result = fitNode(c, getSysType(tyBool), n)
@@ -257,13 +319,21 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
   let nn = semExprWithType(c, n)
   result = fitNode(c, getSysType(tyBool), nn)
   if result == nil:
-    LocalError(n.info, errConstExprExpected)
+    localError(n.info, errConstExprExpected)
     return nn
   result = getConstExpr(c.module, result)
   if result == nil: 
-    LocalError(n.info, errConstExprExpected)
+    localError(n.info, errConstExprExpected)
     result = nn
 
+type
+  TSemGenericFlag = enum
+    withinBind, withinTypeDesc, withinMixin
+  TSemGenericFlags = set[TSemGenericFlag]
+
+proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
+                    ctx: var TIntSet): PNode
+
 include semtypes, semtempl, semgnrc, semstmts, semexprs
 
 proc addCodeForGenerics(c: PContext, n: PNode) =
@@ -271,30 +341,33 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
     var prc = c.generics[i].inst.sym
     if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone:
       if prc.ast == nil or prc.ast.sons[bodyPos] == nil:
-        InternalError(prc.info, "no code for " & prc.name.s)
+        internalError(prc.info, "no code for " & prc.name.s)
       else:
         addSon(n, prc.ast)
   c.lastGenericIdx = c.generics.len
 
 proc myOpen(module: PSym): PPassContext =
   var c = newContext(module)
-  if c.p != nil: InternalError(module.info, "sem.myOpen")
+  if c.p != nil: internalError(module.info, "sem.myOpen")
   c.semConstExpr = semConstExpr
   c.semExpr = semExpr
   c.semTryExpr = tryExpr
+  c.semTryConstExpr = tryConstExpr
   c.semOperand = semOperand
   c.semConstBoolExpr = semConstBoolExpr
   c.semOverloadedCall = semOverloadedCall
+  c.semInferredLambda = semInferredLambda
+  c.semGenerateInstance = generateInstance
   c.semTypeNode = semTypeNode
   pushProcCon(c, module)
   pushOwner(c.module)
   c.importTable = openScope(c)
   c.importTable.addSym(module) # a module knows itself
   if sfSystemModule in module.flags: 
-    magicsys.SystemModule = module # set global variable!
+    magicsys.systemModule = module # set global variable!
   else: 
-    c.importTable.addSym magicsys.SystemModule # import the "System" identifier
-    importAllSymbols(c, magicsys.SystemModule)
+    c.importTable.addSym magicsys.systemModule # import the "System" identifier
+    importAllSymbols(c, magicsys.systemModule)
   c.topLevelScope = openScope(c)
   result = c
 
@@ -302,7 +375,7 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
   result = myOpen(module)
   for m in items(rd.methods): methodDef(m, true)
 
-proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
+proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
   result = semStmt(c, n)
   # BUGFIX: process newly generated generics here, not at the end!
   if c.lastGenericIdx < c.generics.len:
@@ -317,7 +390,7 @@ proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
     result = buildEchoStmt(c, result)
   result = transformStmt(c.module, result)
     
-proc RecoverContext(c: PContext) = 
+proc recoverContext(c: PContext) = 
   # clean up in case of a semantic error: We clean up the stacks, etc. This is
   # faster than wrapping every stack operation in a 'try finally' block and 
   # requires far less code.
@@ -329,15 +402,15 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
   var c = PContext(context)    
   # no need for an expensive 'try' if we stop after the first error anyway:
   if msgs.gErrorMax <= 1:
-    result = SemStmtAndGenerateGenerics(c, n)
+    result = semStmtAndGenerateGenerics(c, n)
   else:
     let oldContextLen = msgs.getInfoContextLen()
-    let oldInGenericInst = c.InGenericInst
+    let oldInGenericInst = c.inGenericInst
     try:
-      result = SemStmtAndGenerateGenerics(c, n)
+      result = semStmtAndGenerateGenerics(c, n)
     except ERecoverableError, ESuggestDone:
-      RecoverContext(c)
-      c.InGenericInst = oldInGenericInst
+      recoverContext(c)
+      c.inGenericInst = oldInGenericInst
       msgs.setInfoContextLen(oldContextLen)
       if getCurrentException() of ESuggestDone: result = nil
       else: result = ast.emptyNode
@@ -346,7 +419,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
 proc checkThreads(c: PContext) =
   if not needsGlobalAnalysis(): return
   for i in 0 .. c.threadEntries.len-1:
-    semthreads.AnalyseThreadProc(c.threadEntries[i])
+    semthreads.analyseThreadProc(c.threadEntries[i])
   
 proc myClose(context: PPassContext, n: PNode): PNode = 
   var c = PContext(context)
@@ -354,7 +427,7 @@ proc myClose(context: PPassContext, n: PNode): PNode =
   rawCloseScope(c)      # imported symbols; don't check for unused ones!
   result = newNode(nkStmtList)
   if n != nil:
-    InternalError(n.info, "n is not nil") #result := n;
+    internalError(n.info, "n is not nil") #result := n;
   addCodeForGenerics(c, result)
   if c.module.ast != nil:
     result.add(c.module.ast)
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 9e9614796..04d280ce2 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -19,7 +19,7 @@ proc sameMethodDispatcher(a, b: PSym): bool =
       if aa.sym == bb.sym: 
         result = true
     else:
-      nil
+      discard
       # generics have no dispatcher yet, so we need to compare the method
       # names; however, the names are equal anyway because otherwise we
       # wouldn't even consider them to be overloaded. But even this does
@@ -47,14 +47,14 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
   var z: TCandidate
   
   if sym == nil: return
-  initCandidate(best, sym, initialBinding, symScope)
-  initCandidate(alt, sym, initialBinding, symScope)
+  initCandidate(c, best, sym, initialBinding, symScope)
+  initCandidate(c, alt, sym, initialBinding, symScope)
   best.state = csNoMatch
   
   while sym != nil:
     if sym.kind in filter:
       determineType(c, sym)
-      initCandidate(z, sym, initialBinding, o.lastOverloadScope)
+      initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
       z.calleeSym = sym
       matches(c, n, orig, z)
       if errors != nil:
@@ -64,25 +64,25 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
             errors[errors.len - 1].add("\n  " & err)
       if z.state == csMatch:
         # little hack so that iterators are preferred over everything else:
-        if sym.kind == skIterator: inc(z.exactMatches, 200)
+        if sym.kind in skIterators: inc(z.exactMatches, 200)
         case best.state
         of csEmpty, csNoMatch: best = z
         of csMatch:
           var cmp = cmpCandidates(best, z)
           if cmp < 0: best = z   # x is better than the best so far
           elif cmp == 0: alt = z # x is as good as the best so far
-          else: nil
+          else: discard
     sym = nextOverloadIter(o, c, headSymbol)
 
-proc NotFoundError*(c: PContext, n: PNode, errors: seq[string]) =
+proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) =
   # 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).
-  if c.InCompilesContext > 0: 
+  if c.inCompilesContext > 0: 
     # fail fast:
-    GlobalError(n.info, errTypeMismatch, "")
+    globalError(n.info, errTypeMismatch, "")
   var result = msgKindToString(errTypeMismatch)
-  add(result, describeArgs(c, n, 1 + ord(nfDelegate in n.flags)))
+  add(result, describeArgs(c, n, 1))
   add(result, ')')
   
   var candidates = ""
@@ -93,7 +93,7 @@ proc NotFoundError*(c: PContext, n: PNode, errors: seq[string]) =
   if candidates != "":
     add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
 
-  LocalError(n.Info, errGenerated, result)
+  localError(n.info, errGenerated, result)
 
 proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) =
   for scope in walkScopes(c.currentScope):
@@ -114,7 +114,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
 
   var errors: seq[string]
   var usedSyms: seq[PNode]
- 
+
   template pickBest(headSymbol: expr) =
     pickBestCandidate(c, headSymbol, n, orig, initialBinding,
                       filter, result, alt, errors)
@@ -138,38 +138,62 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
 
   let overloadsState = result.state
   if overloadsState != csMatch:
-    if nfDelegate in n.flags:
-      InternalAssert f.kind == nkIdent
-      let calleeName = newStrNode(nkStrLit, f.ident.s)
-      calleeName.info = n.info
-
-      let callOp = newIdentNode(idDelegator, n.info)
-      n.sons[0..0] = [callOp, calleeName]
-      orig.sons[0..0] = [callOp, calleeName]
-     
-      pickBest(callOp)
+    if nfDotField in n.flags:
+      internalAssert f.kind == nkIdent and n.sonsLen >= 2
+      let calleeName = newStrNode(nkStrLit, f.ident.s).withInfo(n.info)
+
+      # leave the op head symbol empty,
+      # we are going to try multiple variants
+      n.sons[0..1] = [nil, n[1], calleeName]
+      orig.sons[0..1] = [nil, orig[1], calleeName]
+      
+      template tryOp(x) =
+        let op = newIdentNode(getIdent(x), n.info)
+        n.sons[0] = op
+        orig.sons[0] = op
+        pickBest(op)
+
+      if nfExplicitCall in n.flags:
+        tryOp ".()"
+   
+      if result.state in {csEmpty, csNoMatch}:
+        tryOp "."
 
+    elif nfDotSetter in n.flags:
+      internalAssert f.kind == nkIdent and n.sonsLen == 3
+      let calleeName = newStrNode(nkStrLit, f.ident.s[0.. -2]).withInfo(n.info)
+      let callOp = newIdentNode(getIdent".=", n.info)
+      n.sons[0..1] = [callOp, n[1], calleeName]
+      orig.sons[0..1] = [callOp, orig[1], calleeName]
+      pickBest(callOp)
+   
     if overloadsState == csEmpty and result.state == csEmpty:
-      LocalError(n.info, errUndeclaredIdentifier, considerAcc(f).s)
+      localError(n.info, errUndeclaredIdentifier, considerAcc(f).s)
       return
     elif result.state != csMatch:
       if nfExprCall in n.flags:
-        LocalError(n.info, errExprXCannotBeCalled,
+        localError(n.info, errExprXCannotBeCalled,
                    renderTree(n, {renderNoComments}))
       else:
+        if {nfDotField, nfDotSetter} * n.flags != {}:
+          # clean up the inserted ops
+          n.sons.delete(2)
+          n.sons[0] = f
+
         errors = @[]
         pickBest(f)
-        NotFoundError(c, n, errors)
+        notFoundError(c, n, errors)
+
       return
 
   if alt.state == csMatch and cmpCandidates(result, alt) == 0 and
       not sameMethodDispatcher(result.calleeSym, alt.calleeSym):
-    InternalAssert result.state == csMatch
+    internalAssert result.state == csMatch
     #writeMatches(result)
     #writeMatches(alt)
     if c.inCompilesContext > 0: 
       # quick error message for performance of 'compiles' built-in:
-      GlobalError(n.Info, errGenerated, "ambiguous call")
+      globalError(n.info, errGenerated, "ambiguous call")
     elif gErrorCounter == 0:
       # don't cascade errors
       var args = "("
@@ -178,7 +202,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
         add(args, typeToString(n.sons[i].typ))
       add(args, ")")
 
-      LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
+      localError(n.info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
         getProcHeader(result.calleeSym), getProcHeader(alt.calleeSym),
         args])
 
@@ -197,19 +221,32 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
     for i in 1 .. <n.len:
       instGenericConvertersArg(c, n.sons[i], x)
 
-proc IndexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode = 
+proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode = 
   var m: TCandidate
-  initCandidate(m, f)
-  result = paramTypesMatch(c, m, f, a, arg, nil)
+  initCandidate(c, m, f)
+  result = paramTypesMatch(m, f, a, arg, nil)
   if m.genericConverter and result != nil:
     instGenericConvertersArg(c, result, m)
 
-proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode = 
+proc inferWithMetatype(c: PContext, formal: PType,
+                       arg: PNode, coerceDistincts = false): PNode =
   var m: TCandidate
-  initCandidate(m, f)
-  result = paramTypesMatch(c, m, f, n.typ, n, nil)
+  initCandidate(c, m, formal)
+  m.coerceDistincts = coerceDistincts
+  result = paramTypesMatch(m, formal, arg.typ, arg, nil)
   if m.genericConverter and result != nil:
     instGenericConvertersArg(c, result, m)
+  if result != nil:
+    # This almost exactly replicates the steps taken by the compiler during
+    # param matching. It performs an embarassing ammount of back-and-forth
+    # type jugling, but it's the price to pay for consistency and correctness
+    result.typ = generateTypeInstance(c, m.bindings, arg.info,
+                                      formal.skipTypes({tyCompositeTypeClass}))
+  else:
+    typeMismatch(arg, formal, arg.typ)
+    # error correction:
+    result = copyTree(arg)
+    result.typ = formal
 
 proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
   assert x.state == csMatch
@@ -225,7 +262,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
       result = x.call
       result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
       result.typ = finalCallee.typ.sons[0]
-      if ContainsGenericType(result.typ): result.typ = errorType(c)
+      if containsGenericType(result.typ): result.typ = errorType(c)
       return
   result = x.call
   instGenericConvertersSons(c, result, x)
@@ -239,13 +276,13 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
   # else: result = errorNode(c, n)
     
 proc explicitGenericInstError(n: PNode): PNode =
-  LocalError(n.info, errCannotInstantiateX, renderTree(n))
+  localError(n.info, errCannotInstantiateX, renderTree(n))
   result = n
 
 proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
-  var x: TCandidate
-  initCandidate(x, s, n)
-  var newInst = generateInstance(c, s, x.bindings, n.info)
+  var m: TCandidate
+  initCandidate(c, m, s, n)
+  var newInst = generateInstance(c, s, m.bindings, n.info)
   markUsed(n, s)
   result = newSymNode(newInst, n.info)
 
@@ -260,7 +297,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     # number of generic type parameters:
     if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
       let expected = safeLen(s.ast.sons[genericParamsPos])
-      LocalError(n.info, errGenerated, "cannot instantiate: " & renderTree(n) &
+      localError(n.info, errGenerated, "cannot instantiate: " & renderTree(n) &
          "; got " & $(n.len-1) & " type(s) but expected " & $expected)
       return n
     result = explicitGenericSym(c, n, s)
@@ -271,8 +308,9 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     result = newNodeI(a.kind, n.info)
     for i in countup(0, len(a)-1): 
       var candidate = a.sons[i].sym
-      if candidate.kind in {skProc, skMethod, skConverter, skIterator}: 
-        # if suffices that the candidate has the proper number of generic 
+      if candidate.kind in {skProc, skMethod, skConverter,
+                            skIterator, skClosureIterator}:
+        # it suffices that the candidate has the proper number of generic 
         # type parameters:
         if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
           result.add(explicitGenericSym(c, n, candidate))
@@ -283,12 +321,12 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
   else:
     result = explicitGenericInstError(n)
 
-proc SearchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
+proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
   # Searchs for the fn in the symbol table. If the parameter lists are suitable
   # for borrowing the sym in the symbol table is returned, else nil.
   # New approach: generate fn(x, y, z) where x, y, z have the proper types
   # and use the overloading resolution mechanism:
-  var call = newNode(nkCall)
+  var call = newNodeI(nkCall, fn.info)
   var hasDistinct = false
   call.add(newIdentNode(fn.name, fn.info))
   for i in 1.. <fn.typ.n.len:
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index d02359d4c..4cb5ad38c 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -13,7 +13,7 @@ import
   strutils, lists, intsets, options, lexer, ast, astalgo, trees, treetab,
   wordrecg, 
   ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math, 
-  magicsys, nversion, nimsets, parser, times, passes, rodread, evals
+  magicsys, nversion, nimsets, parser, times, passes, rodread, vmdef
 
 type 
   TOptionEntry* = object of lists.TListEntry # entries to put on a
@@ -21,7 +21,7 @@ type
     options*: TOptions
     defaultCC*: TCallingConvention
     dynlib*: PLib
-    Notes*: TNoteKinds
+    notes*: TNoteKinds
     otherPragmas*: PNode      # every pragma can be pushed
 
   POptionEntry* = ref TOptionEntry
@@ -32,7 +32,7 @@ type
     resultSym*: PSym          # the result symbol (if we are in a proc)
     nestedLoopCounter*: int   # whether we are in a loop or not
     nestedBlockCounter*: int  # whether we are in a block or not
-    InTryStmt*: int           # whether we are in a try statement; works also
+    inTryStmt*: int           # whether we are in a try statement; works also
                               # in standalone ``except`` and ``finally``
     next*: PProcCon           # used for stacking procedure contexts
   
@@ -42,7 +42,7 @@ type
 
   TExprFlag* = enum 
     efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType,
-    efAllowDestructor
+    efAllowDestructor, efWantValue, efOperand, efNoSemCheck
   TExprFlags* = set[TExprFlag]
 
   PContext* = ref TContext
@@ -55,16 +55,16 @@ type
     friendModule*: PSym        # current friend module; may access private data;
                                # this is used so that generic instantiations
                                # can access private object fields
-    InstCounter*: int          # to prevent endless instantiations
+    instCounter*: int          # to prevent endless instantiations
    
     threadEntries*: TSymSeq    # list of thread entries to check
-    AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
+    ambiguousSymbols*: TIntSet # 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
-    InUnrolledContext*: int    # > 0 if we are unrolling a loop
-    InCompilesContext*: int    # > 0 if we are in a ``compiles`` magic
-    InGenericInst*: int        # > 0 if we are instantiating a generic
+    inTypeClass*: int          # > 0 if we are in a user-defined type class
+    inGenericContext*: int     # > 0 if we are in a generic type
+    inUnrolledContext*: int    # > 0 if we are unrolling a loop
+    inCompilesContext*: int    # > 0 if we are in a ``compiles`` magic
+    inGenericInst*: int        # > 0 if we are instantiating a generic
     converters*: TSymSeq       # sequence of converters
     patterns*: TSymSeq         # sequence of pattern matchers
     optionStack*: TLinkedList
@@ -75,15 +75,19 @@ type
     semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
     semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {},
                        bufferErrors = false): 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
     semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
                               filter: TSymKinds): PNode {.nimcall.}
     semTypeNode*: proc(c: PContext, n: PNode, prev: PType): PType {.nimcall.}
+    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
     userPragmas*: TStrTable
     evalContext*: PEvalContext
-    UnknownIdents*: TIntSet    # ids of all unknown identifiers to prevent
+    unknownIdents*: TIntSet    # 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
@@ -114,8 +118,8 @@ proc scopeDepth*(c: PContext): int {.inline.} =
 
 # owner handling:
 proc getCurrOwner*(): PSym
-proc PushOwner*(owner: PSym)
-proc PopOwner*()
+proc pushOwner*(owner: PSym)
+proc popOwner*()
 # implementation
 
 var gOwners*: seq[PSym] = @[]
@@ -128,20 +132,20 @@ proc getCurrOwner(): PSym =
   # BUGFIX: global array is needed!
   result = gOwners[high(gOwners)]
 
-proc PushOwner(owner: PSym) = 
+proc pushOwner(owner: PSym) = 
   add(gOwners, owner)
 
-proc PopOwner() = 
+proc popOwner() = 
   var length = len(gOwners)
-  if length > 0: setlen(gOwners, length - 1)
-  else: InternalError("popOwner")
+  if length > 0: setLen(gOwners, length - 1)
+  else: internalError("popOwner")
 
 proc lastOptionEntry(c: PContext): POptionEntry = 
   result = POptionEntry(c.optionStack.tail)
 
 proc pushProcCon*(c: PContext, owner: PSym) {.inline.} = 
   if owner == nil: 
-    InternalError("owner is nil")
+    internalError("owner is nil")
     return
   var x: PProcCon
   new(x)
@@ -160,7 +164,7 @@ proc newOptionEntry(): POptionEntry =
 
 proc newContext(module: PSym): PContext =
   new(result)
-  result.AmbiguousSymbols = initIntset()
+  result.ambiguousSymbols = initIntSet()
   initLinkedList(result.optionStack)
   initLinkedList(result.libs)
   append(result.optionStack, newOptionEntry())
@@ -172,13 +176,13 @@ proc newContext(module: PSym): PContext =
   result.includedFiles = initIntSet()
   initStrTable(result.userPragmas)
   result.generics = @[]
-  result.UnknownIdents = initIntSet()
+  result.unknownIdents = initIntSet()
 
 proc inclSym(sq: var TSymSeq, s: PSym) =
   var L = len(sq)
   for i in countup(0, L - 1): 
     if sq[i].id == s.id: return 
-  setlen(sq, L + 1)
+  setLen(sq, L + 1)
   sq[L] = s
 
 proc addConverter*(c: PContext, conv: PSym) =
@@ -198,29 +202,79 @@ proc addToLib(lib: PLib, sym: PSym) =
 
 proc makePtrType(c: PContext, baseType: PType): PType = 
   result = newTypeS(tyPtr, c)
-  addSonSkipIntLit(result, baseType.AssertNotNil)
+  addSonSkipIntLit(result, baseType.assertNotNil)
 
 proc makeVarType(c: PContext, baseType: PType): PType = 
   result = newTypeS(tyVar, c)
-  addSonSkipIntLit(result, baseType.AssertNotNil)
+  addSonSkipIntLit(result, baseType.assertNotNil)
 
 proc makeTypeDesc*(c: PContext, typ: PType): PType =
   result = newTypeS(tyTypeDesc, c)
-  result.addSonSkipIntLit(typ.AssertNotNil)
+  result.addSonSkipIntLit(typ.assertNotNil)
 
 proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
   let typedesc = makeTypeDesc(c, typ)
   let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
   return newSymNode(sym, info)
 
-proc newTypeS(kind: TTypeKind, c: PContext): PType = 
-  result = newType(kind, getCurrOwner())
+proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
+  result = newTypeS(tyFromExpr, c)
+  result.n = n
 
 proc newTypeWithSons*(c: PContext, kind: TTypeKind,
                       sons: seq[PType]): PType =
   result = newType(kind, getCurrOwner())
   result.sons = sons
 
+proc makeStaticExpr*(c: PContext, n: PNode): PNode =
+  result = newNodeI(nkStaticExpr, n.info)
+  result.sons = @[n]
+  result.typ = newTypeWithSons(c, tyStatic, @[n.typ])
+
+proc makeAndType*(c: PContext, t1, t2: PType): PType =
+  result = newTypeS(tyAnd, c)
+  result.sons = @[t1, t2]
+  propagateToOwner(result, t1)
+  propagateToOwner(result, t2)
+  result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
+
+proc makeOrType*(c: PContext, t1, t2: PType): PType =
+  result = newTypeS(tyOr, c)
+  result.sons = @[t1, t2]
+  propagateToOwner(result, t1)
+  propagateToOwner(result, t2)
+  result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
+
+proc makeNotType*(c: PContext, t1: PType): PType =
+  result = newTypeS(tyNot, c)
+  result.sons = @[t1]
+  propagateToOwner(result, t1)
+  result.flags.incl(t1.flags * {tfHasStatic})
+
+proc nMinusOne*(n: PNode): PNode =
+  result = newNode(nkCall, n.info, @[
+    newSymNode(getSysMagic("<", mUnaryLt)),
+    n])
+
+# Remember to fix the procs below this one when you make changes!
+proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
+  let intType = getSysType(tyInt)
+  result = newTypeS(tyRange, c)
+  result.sons = @[intType]
+  result.n = newNode(nkRange, n.info, @[
+    newIntTypeNode(nkIntLit, 0, intType),
+    makeStaticExpr(c, n.nMinusOne)])
+
+template rangeHasStaticIf*(t: PType): bool =
+  # this accepts the ranges's node
+  t.n[1].kind == nkStaticExpr
+
+template getStaticTypeFromRange*(t: PType): PType =
+  t.n[1][0][1].typ
+
+proc newTypeS(kind: TTypeKind, c: PContext): PType =
+  result = newType(kind, getCurrOwner())
+
 proc errorType*(c: PContext): PType =
   ## creates a type representing an error state
   result = newTypeS(tyError, c)
@@ -234,7 +288,7 @@ proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
   dest.owner = getCurrOwner()
   dest.size = - 1
 
-proc makeRangeType*(c: PContext; first, last: biggestInt;
+proc makeRangeType*(c: PContext; first, last: BiggestInt;
                     info: TLineInfo; intType = getSysType(tyInt)): PType =
   var n = newNodeI(nkRange, info)
   addSon(n, newIntTypeNode(nkIntLit, first, intType))
@@ -244,12 +298,12 @@ proc makeRangeType*(c: PContext; first, last: biggestInt;
   addSonSkipIntLit(result, intType) # basetype of range
 
 proc markIndirect*(c: PContext, s: PSym) {.inline.} =
-  if s.kind in {skProc, skConverter, skMethod, skIterator}:
+  if s.kind in {skProc, skConverter, skMethod, skIterator, skClosureIterator}:
     incl(s.flags, sfAddrTaken)
     # XXX add to 'c' for global analysis
 
 proc illFormedAst*(n: PNode) =
-  GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
+  globalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
 
 proc checkSonsLen*(n: PNode, length: int) = 
   if sonsLen(n) != length: illFormedAst(n)
diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim
index 797d8895e..791bef823 100644
--- a/compiler/semdestruct.nim
+++ b/compiler/semdestruct.nim
@@ -9,26 +9,39 @@
 
 ## This module implements destructors.
 
+# included from sem.nim
 
 # special marker values that indicates that we are
 # 1) AnalyzingDestructor: currently analyzing the type for destructor 
 # generation (needed for recursive types)
 # 2) DestructorIsTrivial: completed the analysis before and determined
 # that the type has a trivial destructor
-var AnalyzingDestructor, DestructorIsTrivial: PSym
-new(AnalyzingDestructor)
-new(DestructorIsTrivial)
+var analyzingDestructor, destructorIsTrivial: PSym
+new(analyzingDestructor)
+new(destructorIsTrivial)
 
 var
   destructorName = getIdent"destroy_"
   destructorParam = getIdent"this_"
-  destructorPragma = newIdentNode(getIdent"destructor", UnknownLineInfo())
+  destructorPragma = newIdentNode(getIdent"destructor", unknownLineInfo())
   rangeDestructorProc*: PSym
 
-proc instantiateDestructor(c: PContext, typ: PType): bool
+proc instantiateDestructor(c: PContext, typ: PType): PType
 
 proc doDestructorStuff(c: PContext, s: PSym, n: PNode) =
-  let t = s.typ.sons[1].skipTypes({tyVar})
+  var t = s.typ.sons[1].skipTypes({tyVar})
+  if t.kind == tyGenericInvokation:
+    for i in 1 .. <t.sonsLen:
+      if t.sons[i].kind != tyGenericParam:
+        localError(n.info, errDestructorNotGenericEnough)
+        return
+    t = t.base
+  elif t.kind == tyCompositeTypeClass:
+    t = t.base
+    if t.kind != tyGenericBody:
+      localError(n.info, errDestructorNotGenericEnough)
+      return
+  
   t.destructor = s
   # automatically insert calls to base classes' destructors
   if n.sons[bodyPos].kind != nkEmpty:
@@ -36,15 +49,19 @@ proc doDestructorStuff(c: PContext, s: PSym, n: PNode) =
       # when inheriting directly from object
       # there will be a single nil son
       if t.sons[i] == nil: continue
-      if instantiateDestructor(c, t.sons[i]):
+      let destructableT = instantiateDestructor(c, t.sons[i])
+      if destructableT != nil:
         n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[
-            useSym(t.sons[i].destructor),
+            useSym(destructableT.destructor),
             n.sons[paramsPos][1][0]]))
 
-proc destroyField(c: PContext, field: PSym, holder: PNode): PNode =
-  if instantiateDestructor(c, field.typ):
+proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode
+
+proc destroySym(c: PContext, field: PSym, holder: PNode): PNode =
+  let destructableT = instantiateDestructor(c, field.typ)
+  if destructableT != nil:
     result = newNode(nkCall, field.info, @[
-      useSym(field.typ.destructor),
+      useSym(destructableT.destructor),
       newNode(nkDotExpr, field.info, @[holder, useSym(field)])])
 
 proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
@@ -55,78 +72,83 @@ proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
   for i in countup(1, n.len - 1):
     # of A, B:
     var caseBranch = newNode(n[i].kind, n[i].info, n[i].sons[0 .. -2])
-    let recList = n[i].lastSon
-    var destroyRecList = newNode(nkStmtList, n[i].info, @[])
-    template addField(f: expr): stmt =
-      let stmt = destroyField(c, f, holder)
-      if stmt != nil:
-        destroyRecList.addSon(stmt)
-        inc nonTrivialFields
-        
-    case recList.kind
-    of nkSym:
-      addField(recList.sym)
-    of nkRecList:
-      for j in countup(0, recList.len - 1):
-        addField(recList[j].sym)
+    
+    let stmt = destroyFieldOrFields(c, n[i].lastSon, holder)
+    if stmt == nil:
+      caseBranch.addSon(newNode(nkStmtList, n[i].info, @[]))
     else:
-      internalAssert false
-      
-    caseBranch.addSon(destroyRecList)
+      caseBranch.addSon(stmt)
+      nonTrivialFields += stmt.len
+    
     result.addSon(caseBranch)
+  
   # maybe no fields were destroyed?
   if nonTrivialFields == 0:
     result = nil
- 
+
+proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode =
+  template maybeAddLine(e: expr): stmt =
+    let stmt = e
+    if stmt != nil:
+      if result == nil: result = newNode(nkStmtList)
+      result.addSon(stmt)
+
+  case field.kind
+  of nkRecCase:
+    maybeAddLine destroyCase(c, field, holder)
+  of nkSym:
+    maybeAddLine destroySym(c, field.sym, holder)
+  of nkRecList:
+    for son in field:
+      maybeAddLine destroyFieldOrFields(c, son, holder)
+  else:
+    internalAssert false
+
 proc generateDestructor(c: PContext, t: PType): PNode =
   ## generate a destructor for a user-defined object or tuple type
   ## returns nil if the destructor turns out to be trivial
   
-  template addLine(e: expr): stmt =
-    if result == nil: result = newNode(nkStmtList)
-    result.addSon(e)
-
   # XXX: This may be true for some C-imported types such as
   # Tposix_spawnattr
   if t.n == nil or t.n.sons == nil: return
   internalAssert t.n.kind == nkRecList
-  let destructedObj = newIdentNode(destructorParam, UnknownLineInfo())
+  let destructedObj = newIdentNode(destructorParam, unknownLineInfo())
   # call the destructods of all fields
-  for s in countup(0, t.n.sons.len - 1):
-    case t.n.sons[s].kind
-    of nkRecCase:
-      let stmt = destroyCase(c, t.n.sons[s], destructedObj)
-      if stmt != nil: addLine(stmt)
-    of nkSym:
-      let stmt = destroyField(c, t.n.sons[s].sym, destructedObj)
-      if stmt != nil: addLine(stmt)
-    else:
-      internalAssert false
+  result = destroyFieldOrFields(c, t.n, destructedObj)
   # base classes' destructors will be automatically called by
   # semProcAux for both auto-generated and user-defined destructors
 
-proc instantiateDestructor(c: PContext, typ: PType): bool =
-  # returns true if the type already had a user-defined
-  # destructor or if the compiler generated a default
-  # member-wise one
-  var t = skipTypes(typ, {tyConst, tyMutable})
+proc instantiateDestructor(c: PContext, typ: PType): PType =
+  # returns nil if a variable of type `typ` doesn't require a
+  # destructor. Otherwise, returns the type, which holds the 
+  # destructor that must be used for the varialbe.
+  # The destructor is either user-defined or automatically
+  # generated by the compiler in a member-wise fashion.
+  var t = skipTypes(typ, {tyConst, tyMutable}).skipGenericAlias
+  let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base
+                                  else: t
   
-  if t.destructor != nil:
+  if typeHoldingUserDefinition.destructor != nil:
     # XXX: This is not entirely correct for recursive types, but we need
     # it temporarily to hide the "destroy is already defined" problem
-    return t.destructor notin [AnalyzingDestructor, DestructorIsTrivial]
+    if typeHoldingUserDefinition.destructor notin
+        [analyzingDestructor, destructorIsTrivial]:
+      return typeHoldingUserDefinition
+    else:
+      return nil
   
+  t = t.skipTypes({tyGenericInst})
   case t.kind
   of tySequence, tyArray, tyArrayConstr, tyOpenArray, tyVarargs:
-    if instantiateDestructor(c, t.sons[0]):
+    if instantiateDestructor(c, t.sons[0]) != nil:
       if rangeDestructorProc == nil:
         rangeDestructorProc = searchInScopes(c, getIdent"nimDestroyRange")
       t.destructor = rangeDestructorProc
-      return true
+      return t
     else:
-      return false
+      return nil
   of tyTuple, tyObject:
-    t.destructor = AnalyzingDestructor
+    t.destructor = analyzingDestructor
     let generated = generateDestructor(c, t)
     if generated != nil:
       internalAssert t.sym != nil
@@ -139,21 +161,21 @@ proc instantiateDestructor(c: PContext, typ: PType): bool =
           emptyNode,
           newNode(nkIdentDefs, i, @[
             newIdentNode(destructorParam, i),
-            useSym(t.sym),
+            symNodeFromType(c, makeVarType(c, t), t.sym.info),
             emptyNode]),
           ]),
         newNode(nkPragma, i, @[destructorPragma]),
         emptyNode,
         generated
         ])
-      discard semProc(c, fullDef)
-      internalAssert t.destructor != nil
-      return true
+      let semantizedDef = semProc(c, fullDef)
+      t.destructor = semantizedDef[namePos].sym
+      return t
     else:
-      t.destructor = DestructorIsTrivial
-      return false
+      t.destructor = destructorIsTrivial
+      return nil
   else:
-    return false
+    return nil
 
 proc insertDestructors(c: PContext,
                        varSection: PNode): tuple[outer, inner: PNode] =
@@ -179,9 +201,11 @@ proc insertDestructors(c: PContext,
       varId = varSection[j][0]
       varTyp = varId.sym.typ
       info = varId.info
-
-    if varTyp != nil and instantiateDestructor(c, varTyp) and 
-        sfGlobal notin varId.sym.flags:
+    
+    if varTyp == nil or sfGlobal in varId.sym.flags: continue
+    let destructableT = instantiateDestructor(c, varTyp)
+    
+    if destructableT != nil:
       var tryStmt = newNodeI(nkTryStmt, info)
 
       if j < totalVars - 1:
@@ -198,11 +222,11 @@ proc insertDestructors(c: PContext,
       else:
         result.inner = newNodeI(nkStmtList, info)
         tryStmt.addSon(result.inner)
-
+    
       tryStmt.addSon(
         newNode(nkFinally, info, @[
           semStmt(c, newNode(nkCall, info, @[
-            useSym(varTyp.destructor),
+            useSym(destructableT.destructor),
             useSym(varId.sym)]))]))
 
       result.outer = newNodeI(nkStmtList, info)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 310aabc32..6c1721bdd 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -10,18 +10,19 @@
 # this module does the semantic checking for expressions
 # included from sem.nim
 
-proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = 
+proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
+                     flags: TExprFlags = {}): PNode =
   markUsed(n, s)
   pushInfoContext(n.info)
   result = evalTemplate(n, s, getCurrOwner())
-  if semCheck: result = semAfterMacroCall(c, result, s)
+  if efNoSemCheck notin flags: result = semAfterMacroCall(c, result, s, flags)
   popInfoContext()
 
 proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 
 proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   # same as 'semExprWithType' but doesn't check for proc vars
-  result = semExpr(c, n, flags)
+  result = semExpr(c, n, flags + {efOperand})
   if result.kind == nkEmpty: 
     # do not produce another redundant error message:
     #raiseRecoverableError("")
@@ -30,19 +31,19 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # XXX tyGenericInst here?
     if result.typ.kind == tyVar: result = newDeref(result)
   else:
-    LocalError(n.info, errExprXHasNoType, 
+    localError(n.info, errExprXHasNoType, 
                renderTree(result, {renderNoComments}))
     result.typ = errorType(c)
 
 proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
-  result = semExpr(c, n, flags)
+  result = semExpr(c, n, flags+{efWantValue})
   if result.isNil or result.kind == nkEmpty: 
     # do not produce another redundant error message:
     #raiseRecoverableError("")
     result = errorNode(c, n)
-  if result.typ == nil or result.typ == EnforceVoidContext:
+  if result.typ == nil or result.typ == enforceVoidContext:
     # we cannot check for 'void' in macros ...
-    LocalError(n.info, errExprXHasNoType, 
+    localError(n.info, errExprXHasNoType, 
                renderTree(result, {renderNoComments}))
     result.typ = errorType(c)
   else:
@@ -57,7 +58,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # do not produce another redundant error message:
     result = errorNode(c, n)
   if result.typ == nil:
-    LocalError(n.info, errExprXHasNoType, 
+    localError(n.info, errExprXHasNoType, 
                renderTree(result, {renderNoComments}))
     result.typ = errorType(c)
   else:
@@ -95,14 +96,14 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
       else: result = newSymNode(s, n.info)
     else:
       result = newSymNode(s, n.info)
-  of skMacro: result = semMacroExpr(c, n, n, s)
-  of skTemplate: result = semTemplateExpr(c, n, s)
+  of skMacro: result = semMacroExpr(c, n, n, s, flags)
+  of skTemplate: result = semTemplateExpr(c, n, s, flags)
   of skVar, skLet, skResult, skParam, skForVar:
     markUsed(n, 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)
-    elif s.kind == skParam and s.typ.kind == tyExpr and s.typ.n != nil:
+    elif s.kind == skParam and s.typ.kind == tyStatic and s.typ.n != nil:
       # XXX see the hack in sigmatch.nim ...
       return s.typ.n
     result = newSymNode(s, n.info)
@@ -111,16 +112,18 @@ 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:
-    if s.typ.kind == tyExpr:
+    if s.typ.kind == tyStatic:
       result = newSymNode(s, n.info)
       result.typ = s.typ
     elif s.ast != nil:
       result = semExpr(c, s.ast)
     else:
-      InternalError(n.info, "no default for")
-      result = emptyNode
+      n.typ = s.typ
+      return n
   of skType:
     markUsed(n, 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:
@@ -142,7 +145,7 @@ proc checkConversionBetweenObjects(castDest, src: PType): TConvStatus =
 const 
   IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
 
-proc checkConvertible(castDest, src: PType): TConvStatus =
+proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
   result = convOK
   if sameType(castDest, src) and castDest.sym == src.sym:
     # don't annoy conversions that may be needed on another processor:
@@ -151,31 +154,31 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
     return
   var d = skipTypes(castDest, abstractVar)
   var s = skipTypes(src, abstractVar-{tyTypeDesc})
-  while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
-    d = base(d)
-    s = base(s)
+  while (d != nil) and (d.kind in {tyPtr, tyRef}) and (d.kind == s.kind):
+    d = d.lastSon
+    s = s.lastSon
   if d == nil:
     result = convNotLegal
-  elif d.Kind == tyObject and s.Kind == tyObject:
+  elif d.kind == tyObject and s.kind == tyObject:
     result = checkConversionBetweenObjects(d, s)
-  elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
-      (skipTypes(src, abstractVarRange-{tyTypeDesc}).Kind in IntegralTypes):
+  elif (skipTypes(castDest, abstractVarRange).kind in IntegralTypes) and
+      (skipTypes(src, abstractVarRange-{tyTypeDesc}).kind in IntegralTypes):
     # accept conversion between integral types
   else:
     # we use d, s here to speed up that operation a bit:
-    case cmpTypes(d, s)
+    case cmpTypes(c, d, s)
     of isNone, isGeneric:
       if not compareTypes(castDest, src, dcEqIgnoreDistinct):
         result = convNotLegal
     else:
-      nil
+      discard
 
 proc isCastable(dst, src: PType): bool = 
   #const
   #  castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString, 
   #                       tySequence, tyPointer, tyNil, tyOpenArray,
   #                       tyProc, tySet, tyEnum, tyBool, tyChar}
-  var ds, ss: biggestInt
+  var ds, ss: BiggestInt
   # this is very unrestrictive; cast is allowed if castDest.size >= src.size
   ds = computeSize(dst)
   ss = computeSize(src)
@@ -191,30 +194,57 @@ proc isCastable(dst, src: PType): bool =
 proc isSymChoice(n: PNode): bool {.inline.} =
   result = n.kind in nkSymChoices
 
+proc maybeLiftType(t: var PType, c: PContext, info: TLineInfo) =
+  # XXX: liftParamType started to perform addDecl
+  # we could do that instead in semTypeNode by snooping for added
+  # gnrc. params, then it won't be necessary to open a new scope here
+  openScope(c)
+  var lifted = liftParamType(c, skType, newNodeI(nkArgList, info),
+                         t, ":anon", info)
+  closeScope(c)
+  if lifted != nil: t = lifted
+
 proc semConv(c: PContext, n: PNode): PNode =
   if sonsLen(n) != 2:
-    LocalError(n.info, errConvNeedsOneArg)
+    localError(n.info, errConvNeedsOneArg)
     return n
+
   result = newNodeI(nkConv, n.info)
-  result.typ = semTypeNode(c, n.sons[0], nil).skipTypes({tyGenericInst})
-  addSon(result, copyTree(n.sons[0]))
-  addSon(result, semExprWithType(c, n.sons[1]))
-  var op = result.sons[1]
+  var targetType = semTypeNode(c, n.sons[0], nil)
+  maybeLiftType(targetType, c, n[0].info)
+  result.addSon copyTree(n.sons[0])
+  var op = semExprWithType(c, n.sons[1])
+  
+  if targetType.isMetaType:
+    let final = inferWithMetatype(c, targetType, op, true)
+    result.addSon final
+    result.typ = final.typ
+    return
+
+  result.typ = targetType
+  addSon(result, op)
   
   if not isSymChoice(op):
-    let status = checkConvertible(result.typ, op.typ)
+    let status = checkConvertible(c, result.typ, op.typ)
     case status
-    of convOK: nil
+    of convOK:
+      # handle SomeProcType(SomeGenericProc)
+      # XXX: This needs fixing. checkConvertible uses typeRel internally, but
+      # doesn't bother to perform the work done in paramTypeMatchAux/fitNode
+      # so we are redoing the typeRel work here. Why does semConv exist as a
+      # separate proc from fitNode?
+      if op.kind == nkSym and op.sym.isGenericRoutine:
+        result.sons[1] = fitNode(c, result.typ, result.sons[1])
     of convNotNeedeed:
-      Message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString)
+      message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString)
     of convNotLegal:
-      LocalError(n.info, errGenerated, MsgKindToString(errIllegalConvFromXtoY)%
+      localError(n.info, errGenerated, msgKindToString(errIllegalConvFromXtoY)%
         [op.typ.typeToString, result.typ.typeToString])
   else:
     for i in countup(0, sonsLen(op) - 1):
       let it = op.sons[i]
-      let status = checkConvertible(result.typ, it.typ)
-      if status == convOK:
+      let status = checkConvertible(c, result.typ, it.typ)
+      if status in {convOK, convNotNeedeed}:
         markUsed(n, it.sym)
         markIndirect(c, it.sym)
         return it
@@ -228,36 +258,39 @@ proc semCast(c: PContext, n: PNode): PNode =
   result.typ = semTypeNode(c, n.sons[0], nil)
   addSon(result, copyTree(n.sons[0]))
   addSon(result, semExprWithType(c, n.sons[1]))
-  if not isCastable(result.typ, result.sons[1].Typ): 
-    LocalError(result.info, errExprCannotBeCastedToX, 
-               typeToString(result.Typ))
-  
+  if not isCastable(result.typ, result.sons[1].typ): 
+    localError(result.info, errExprCannotBeCastedToX, 
+               typeToString(result.typ))
+
 proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = 
   const 
     opToStr: array[mLow..mHigh, string] = ["low", "high"]
   if sonsLen(n) != 2: 
-    LocalError(n.info, errXExpectsTypeOrValue, opToStr[m])
+    localError(n.info, errXExpectsTypeOrValue, opToStr[m])
   else: 
     n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
-    var typ = skipTypes(n.sons[1].typ, abstractVarRange)
-    case typ.Kind
+    var typ = skipTypes(n.sons[1].typ, abstractVarRange +
+                                       {tyTypeDesc, tyFieldAccessor})
+    case typ.kind
     of tySequence, tyString, tyOpenArray, tyVarargs: 
       n.typ = getSysType(tyInt)
     of tyArrayConstr, tyArray: 
       n.typ = typ.sons[0] # indextype
     of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: 
       # do not skip the range!
-      n.typ = n.sons[1].typ.skipTypes(abstractVar)
+      n.typ = n.sons[1].typ.skipTypes(abstractVar + {tyFieldAccessor})
     of tyGenericParam:
-      # leave it for now, it will be resolved in semtypinst
-      n.typ = getSysType(tyInt)
+      # prepare this for resolving in semtypinst:
+      # we must use copyTree here in order to avoid creating a cycle
+      # that could easily turn into an infinite recursion in semtypinst
+      n.typ = makeTypeFromExpr(c, n.copyTree)
     else:
-      LocalError(n.info, errInvalidArgForX, opToStr[m])
+      localError(n.info, errInvalidArgForX, opToStr[m])
   result = n
 
 proc semSizeof(c: PContext, n: PNode): PNode =
   if sonsLen(n) != 2:
-    LocalError(n.info, errXExpectsTypeOrValue, "sizeof")
+    localError(n.info, errXExpectsTypeOrValue, "sizeof")
   else:
     n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
     #restoreOldStyleType(n.sons[1])
@@ -276,9 +309,9 @@ proc semOf(c: PContext, n: PNode): PNode =
     let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
 
     if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
-      LocalError(n.info, errXExpectsObjectTypes, "of")
+      localError(n.info, errXExpectsObjectTypes, "of")
     elif b.kind != tyObject or a.kind != tyObject:
-      LocalError(n.info, errXExpectsObjectTypes, "of")
+      localError(n.info, errXExpectsObjectTypes, "of")
     else:
       let diff = inheritanceDiff(a, b)
       # | returns: 0 iff `a` == `b`
@@ -287,24 +320,24 @@ proc semOf(c: PContext, n: PNode): PNode =
       # | returns: `maxint` iff `a` and `b` are not compatible at all
       if diff <= 0:
         # optimize to true:
-        Message(n.info, hintConditionAlwaysTrue, renderTree(n))
+        message(n.info, hintConditionAlwaysTrue, renderTree(n))
         result = newIntNode(nkIntLit, 1)
         result.info = n.info
         result.typ = getSysType(tyBool)
         return result
       elif diff == high(int):
-        LocalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
+        localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
   else:
-    LocalError(n.info, errXExpectsTwoArguments, "of")
+    localError(n.info, errXExpectsTwoArguments, "of")
   n.typ = getSysType(tyBool)
   result = n
 
 proc isOpImpl(c: PContext, n: PNode): PNode =
-  InternalAssert n.sonsLen == 3 and
-    n[1].kind == nkSym and n[1].sym.kind == skType and
+  internalAssert n.sonsLen == 3 and
+    n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
     n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
   
-  let t1 = n[1].sym.typ.skipTypes({tyTypeDesc})
+  let t1 = n[1].typ.skipTypes({tyTypeDesc, tyFieldAccessor})
 
   if n[2].kind in {nkStrLit..nkTripleStrLit}:
     case n[2].strVal.normalize
@@ -313,56 +346,37 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
       result = newIntNode(nkIntLit, ord(t.kind == tyProc and
                                         t.callConv == ccClosure and 
                                         tfIterator notin t.flags))
-    of "iterator":
-      let t = skipTypes(t1, abstractRange)
-      result = newIntNode(nkIntLit, ord(t.kind == tyProc and
-                                        t.callConv == ccClosure and 
-                                        tfIterator in t.flags))
   else:
-    var match: bool
-    let t2 = n[2].typ
-    case t2.kind
-    of tyTypeClasses:
-      var m: TCandidate
-      InitCandidate(m, t2)
-      match = matchUserTypeClass(c, m, emptyNode, t2, t1) != nil
-    of tyOrdinal:
-      var m: TCandidate
-      InitCandidate(m, t2)
-      match = isOrdinalType(t1)
-    of tySequence, tyArray, tySet:
-      var m: TCandidate
-      InitCandidate(m, t2)
-      match = typeRel(m, t2, t1) != isNone
-    else:
-      match = sameType(t1, t2)
- 
+    var t2 = n[2].typ.skipTypes({tyTypeDesc})
+    maybeLiftType(t2, c, n.info)
+    var m: TCandidate
+    initCandidate(c, m, t2)
+    let match = typeRel(m, t2, t1) != isNone
     result = newIntNode(nkIntLit, ord(match))
 
   result.typ = n.typ
 
 proc semIs(c: PContext, n: PNode): PNode =
   if sonsLen(n) != 3:
-    LocalError(n.info, errXExpectsTwoArguments, "is")
+    localError(n.info, errXExpectsTwoArguments, "is")
 
   result = n
   n.typ = getSysType(tyBool)
-  
-  n.sons[1] = semExprWithType(c, n[1], {efDetermineType})
-  
+ 
+  n.sons[1] = semExprWithType(c, n[1], {efDetermineType, efWantIterator})
   if n[2].kind notin {nkStrLit..nkTripleStrLit}:
     let t2 = semTypeNode(c, n[2], nil)
     n.sons[2] = newNodeIT(nkType, n[2].info, t2)
 
-  if n[1].typ.kind != tyTypeDesc:
-    n.sons[1] = makeTypeSymNode(c, n[1].typ, n[1].info)
-  elif n[1].typ.sonsLen == 0:
+  let lhsType = n[1].typ
+  if lhsType.kind != tyTypeDesc:
+    n.sons[1] = makeTypeSymNode(c, lhsType, n[1].info)
+  elif lhsType.base.kind == tyNone:
     # this is a typedesc variable, leave for evals
     return
 
-  let t1 = n[1].typ.sons[0]
   # BUGFIX: don't evaluate this too early: ``T is void``
-  if not containsGenericType(t1): result = isOpImpl(c, n)
+  if not n[1].typ.base.containsGenericType: result = isOpImpl(c, n)
 
 proc semOpAux(c: PContext, n: PNode) =
   const flags = {efDetermineType}
@@ -394,8 +408,8 @@ proc changeType(n: PNode, newType: PType, check: bool) =
       changeType(n.sons[i], elemType(newType), check)
   of nkPar: 
     if newType.kind != tyTuple: 
-      InternalError(n.info, "changeType: no tuple type for constructor")
-    elif newType.n == nil: nil
+      internalError(n.info, "changeType: no tuple type for constructor")
+    elif newType.n == nil: discard
     elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr: 
       for i in countup(0, sonsLen(n) - 1): 
         var m = n.sons[i].sons[0]
@@ -419,9 +433,9 @@ proc changeType(n: PNode, newType: PType, check: bool) =
     if check:
       let value = n.intVal
       if value < firstOrd(newType) or value > lastOrd(newType):
-        LocalError(n.info, errGenerated, "cannot convert " & $value &
+        localError(n.info, errGenerated, "cannot convert " & $value &
                                          " to " & typeToString(newType))
-  else: nil
+  else: discard
   n.typ = newType
 
 proc arrayConstrType(c: PContext, n: PNode): PType = 
@@ -431,7 +445,7 @@ proc arrayConstrType(c: PContext, n: PNode): PType =
     rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
   else:
     var x = n.sons[0]
-    var lastIndex: biggestInt = sonsLen(n) - 1
+    var lastIndex: BiggestInt = sonsLen(n) - 1
     var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
     addSonSkipIntLit(typ, t)
   typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
@@ -445,7 +459,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
     rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
   else:
     var x = n.sons[0]
-    var lastIndex: biggestInt = 0
+    var lastIndex: BiggestInt = 0
     var indexType = getSysType(tyInt)
     if x.kind == nkExprColonExpr and sonsLen(x) == 2: 
       var idx = semConstExpr(c, x.sons[0])
@@ -511,7 +525,7 @@ proc fixAbstractType(c: PContext, n: PNode) =
       # an implicitly constructed array (passed to an open array):
       n.sons[i] = semArrayConstr(c, it, {})
     else: 
-      nil
+      discard
       #if (it.typ == nil): 
       #  InternalError(it.info, "fixAbstractType: " & renderTree(it))  
   
@@ -582,7 +596,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
           skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar: 
         if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}: 
           if n.sons[i].kind != nkHiddenAddr:
-            LocalError(n.sons[i].info, errVarForOutParamNeeded)
+            localError(n.sons[i].info, errVarForOutParamNeeded)
     return
   for i in countup(1, sonsLen(n) - 1):
     if n.sons[i].kind == nkHiddenCallConv:
@@ -619,7 +633,19 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
       if result.isNil: result = n
       else: return result
     result.typ = semfold.getIntervalType(callee.magic, call)
-    
+  
+  block maybeLabelAsStatic:
+    # XXX: temporary work-around needed for tlateboundstatic.
+    # This is certainly not correct, but it will get the job
+    # done until we have a more robust infrastructure for
+    # implicit statics.
+    if n.len > 1:
+      for i in 1 .. <n.len:
+        if n[i].typ.kind != tyStatic or tfUnresolved notin n[i].typ.flags:
+          break maybeLabelAsStatic
+      n.typ = newTypeWithSons(c, tyStatic, @[n.typ])
+      n.typ.flags.incl tfUnresolved
+
   # optimization pass: not necessary for correctness of the semantic pass
   if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
      {sfForward, sfImportc} * callee.flags == {}:
@@ -640,78 +666,84 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
       call.add(a)
     #echo "NOW evaluating at compile time: ", call.renderTree
     if sfCompileTime in callee.flags:
-      result = evalStaticExpr(c, c.module, call, c.p.owner)
+      result = evalStaticExpr(c.module, call, c.p.owner)
       if result.isNil: 
-        LocalError(n.info, errCannotInterpretNodeX, renderTree(call))
+        localError(n.info, errCannotInterpretNodeX, renderTree(call))
+      else: result = fixupTypeAfterEval(c, result, n)
     else:
-      result = evalConstExpr(c, c.module, call)
+      result = evalConstExpr(c.module, call)
       if result.isNil: result = n
+      else: result = fixupTypeAfterEval(c, result, n)
     #if result != n:
     #  echo "SUCCESS evaluated at compile time: ", call.renderTree
 
 proc semStaticExpr(c: PContext, n: PNode): PNode =
   let a = semExpr(c, n.sons[0])
-  result = evalStaticExpr(c, c.module, a, c.p.owner)
+  result = evalStaticExpr(c.module, a, c.p.owner)
   if result.isNil:
-    LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
+    localError(n.info, errCannotInterpretNodeX, renderTree(n))
     result = emptyNode
+  else:
+    result = fixupTypeAfterEval(c, result, a)
 
 proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
                                      flags: TExprFlags): PNode =
-  if flags*{efInTypeOf, efWantIterator} != {}:
+  if flags*{efInTypeof, efWantIterator} != {}:
     # consider: 'for x in pReturningArray()' --> we don't want the restriction
-    # to 'skIterator' anymore; skIterator is preferred in sigmatch already for
-    # typeof support.
+    # to 'skIterators' anymore; skIterators are preferred in sigmatch already 
+    # for typeof support.
     # for ``type(countup(1,3))``, see ``tests/ttoseq``.
     result = semOverloadedCall(c, n, nOrig,
-      {skProc, skMethod, skConverter, skMacro, skTemplate, skIterator})
+      {skProc, skMethod, skConverter, skMacro, skTemplate}+skIterators)
   else:
     result = semOverloadedCall(c, n, nOrig, 
       {skProc, skMethod, skConverter, skMacro, skTemplate})
+ 
   if result != nil:
     if result.sons[0].kind != nkSym: 
-      InternalError("semOverloadedCallAnalyseEffects")
+      internalError("semOverloadedCallAnalyseEffects")
       return
     let callee = result.sons[0].sym
     case callee.kind
-    of skMacro, skTemplate: nil
+    of skMacro, skTemplate: discard
     else:
-      if (callee.kind == skIterator) and (callee.id == c.p.owner.id): 
-        LocalError(n.info, errRecursiveDependencyX, callee.name.s)
+      if (callee.kind in skIterators) and (callee.id == c.p.owner.id): 
+        localError(n.info, errRecursiveDependencyX, callee.name.s)
       if sfNoSideEffect notin callee.flags: 
         if {sfImportc, sfSideEffect} * callee.flags != {}:
           incl(c.p.owner.flags, sfSideEffect)
 
 proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
-proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = 
+proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = nil
   checkMinSonsLen(n, 1)
   var prc = n.sons[0]
-  if n.sons[0].kind == nkDotExpr: 
+  if n.sons[0].kind == nkDotExpr:
     checkSonsLen(n.sons[0], 2)
     n.sons[0] = semFieldAccess(c, n.sons[0])
-    if n.sons[0].kind == nkDotCall: 
+    if n.sons[0].kind == nkDotCall:
       # it is a static call!
       result = n.sons[0]
       result.kind = nkCall
+      result.flags.incl nfExplicitCall
       for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
       return semExpr(c, result, flags)
-  else: 
+  else:
     n.sons[0] = semExpr(c, n.sons[0])
   let nOrig = n.copyTree
   semOpAux(c, n)
   var t: PType = nil
   if n.sons[0].typ != nil:
-    t = skipTypes(n.sons[0].typ, abstractInst-{tyTypedesc})
+    t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
   if t != nil and t.kind == tyProc:
     # This is a proc variable, apply normal overload resolution
     var m: TCandidate
-    initCandidate(m, t)
+    initCandidate(c, m, t)
     matches(c, n, nOrig, m)
     if m.state != csMatch:
       if c.inCompilesContext > 0:
         # speed up error generation:
-        GlobalError(n.Info, errTypeMismatch, "")
+        globalError(n.info, errTypeMismatch, "")
         return emptyNode
       else:
         var hasErrorType = false
@@ -726,7 +758,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
         if not hasErrorType:
           add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
               typeToString(n.sons[0].typ))
-          LocalError(n.Info, errGenerated, msg)
+          localError(n.info, errGenerated, msg)
         return errorNode(c, n)
       result = nil
     else:
@@ -762,8 +794,8 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
   result = n
   let callee = result.sons[0].sym
   case callee.kind
-  of skMacro: result = semMacroExpr(c, result, orig, callee)
-  of skTemplate: result = semTemplateExpr(c, result, callee)
+  of skMacro: result = semMacroExpr(c, result, orig, callee, flags)
+  of skTemplate: result = semTemplateExpr(c, result, callee, flags)
   else:
     semFinishOperands(c, result)
     activate(c, result)
@@ -771,7 +803,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
     analyseIfAddressTakenInCall(c, result)
     if callee.magic != mNone:
       result = magicsAfterOverloadResolution(c, result, flags)
-  if c.InTypeClass == 0:
+  if c.inTypeClass == 0:
     result = evalAtCompileTime(c, result)
 
 proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = 
@@ -780,6 +812,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   #semLazyOpAux(c, n)
   result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
   if result != nil: result = afterCallActions(c, result, nOrig, flags)
+  else: result = errorNode(c, n)
 
 proc buildStringify(c: PContext, arg: PNode): PNode = 
   if arg.typ != nil and 
@@ -800,7 +833,7 @@ proc semEcho(c: PContext, n: PNode): PNode =
     let t = arg.typ
     if (t == nil or t.skipTypes(abstractInst).kind != tyString) and 
         arg.kind != nkEmpty:
-      LocalError(n.info, errGenerated,
+      localError(n.info, errGenerated,
                  "implicitly invoked '$' does not return string")
   let t = n.sons[0].typ
   if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
@@ -809,11 +842,11 @@ proc semEcho(c: PContext, n: PNode): PNode =
 proc buildEchoStmt(c: PContext, n: PNode): PNode = 
   # we MUST not check 'n' for semantics again here!
   result = newNodeI(nkCall, n.info)
-  var e = StrTableGet(magicsys.systemModule.Tab, getIdent"echo")
+  var e = strTableGet(magicsys.systemModule.tab, getIdent"echo")
   if e != nil:
     addSon(result, newSymNode(e))
   else:
-    LocalError(n.info, errSystemNeeds, "echo")
+    localError(n.info, errSystemNeeds, "echo")
     addSon(result, errorNode(c, n))
   var arg = buildStringify(c, n)
   # problem is: implicit '$' is not checked for semantics yet. So we give up
@@ -843,7 +876,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
       if result != nil: return 
   of nkRecCase: 
     checkMinSonsLen(r, 2)
-    if (r.sons[0].kind != nkSym): IllFormedAst(r)
+    if (r.sons[0].kind != nkSym): illFormedAst(r)
     result = lookupInRecordAndBuildCheck(c, n, r.sons[0], field, check)
     if result != nil: return 
     var s = newNodeI(nkCurly, r.info)
@@ -885,7 +918,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
   of nkSym: 
     if r.sym.name.id == field.id: result = r.sym
   else: illFormedAst(n)
-  
+
 proc makeDeref(n: PNode): PNode = 
   var t = skipTypes(n.typ, {tyGenericInst})
   result = n
@@ -897,16 +930,39 @@ proc makeDeref(n: PNode): PNode =
     var a = result
     result = newNodeIT(nkHiddenDeref, n.info, t.sons[0])
     addSon(result, a)
-    t = skipTypes(t.sons[0], {tyGenericInst})
+    t = skipTypes(t.lastSon, {tyGenericInst})
+
+const
+  tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass}
+  tyDotOpTransparent = {tyVar, tyPtr, tyRef}
+
+proc readTypeParameter(c: PContext, typ: PType,
+                       paramName: PIdent, info: TLineInfo): PNode =
+  let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
+           else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1])
+  
+  let tbody = ty.sons[0]
+  for s in countup(0, tbody.len-2):
+    let tParam = tbody.sons[s]
+    if tParam.sym.name == paramName:
+      let rawTyp = ty.sons[s + 1]
+      if rawTyp.kind == tyStatic:
+        return rawTyp.n
+      else:
+        let foundTyp = makeTypeDesc(c, rawTyp)
+        return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
 
 proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if it's not a built-in field access
   checkSonsLen(n, 2)
-  # early exit for this; see tests/compile/tbindoverload.nim:
-  if isSymChoice(n.sons[1]): return
+  # tests/bind/tbindoverload.nim wants an early exit here, but seems to
+  # work without now. template/tsymchoicefield doesn't like an early exit
+  # here at all!
+  #if isSymChoice(n.sons[1]): return
 
-  var s = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
+  var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
   if s != nil:
+    markUsed(n.sons[1], s)
     return semSym(c, n, s, flags)
 
   n.sons[0] = semExprWithType(c, n.sons[0], flags+{efDetermineType})
@@ -915,8 +971,9 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   var ty = n.sons[0].typ
   var f: PSym = nil
   result = nil
-  if isTypeExpr(n.sons[0]) or ty.kind == tyTypeDesc and ty.len == 1:
-    if ty.kind == tyTypeDesc: ty = ty.sons[0]
+  if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
+    if ty.kind == tyTypeDesc: ty = ty.base
+    ty = ty.skipTypes(tyDotOpTransparent)
     case ty.kind
     of tyEnum:
       # look up if the identifier belongs to the enum:
@@ -924,49 +981,46 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
         f = getSymFromList(ty.n, i)
         if f != nil: break 
         ty = ty.sons[0]         # enum inheritance
-      if f != nil: 
+      if f != nil:
         result = newSymNode(f)
         result.info = n.info
         result.typ = ty
         markUsed(n, f)
         return
-    of tyGenericInst:
-      assert ty.sons[0].kind == tyGenericBody
-      let tbody = ty.sons[0]
-      for s in countup(0, tbody.len-2):
-        let tParam = tbody.sons[s]
-        if tParam.sym.name == i:
-          let rawTyp = ty.sons[s + 1]
-          if rawTyp.kind == tyExpr:
-            return rawTyp.n
-          else:
-            let foundTyp = makeTypeDesc(c, rawTyp)
-            return newSymNode(copySym(tParam.sym).linkTo(foundTyp), n.info)
-      return
+    of tyTypeParamsHolders:
+      return readTypeParameter(c, ty, i, n.info)
+    of tyObject, tyTuple:
+      if ty.n.kind == nkRecList:
+        for field in ty.n:
+          if field.sym.name == i:
+            n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])
+            n.typ.n = copyTree(n)
+            return n
     else:
       # echo "TYPE FIELD ACCESS"
       # debug ty
       return
     # XXX: This is probably not relevant any more
     # reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
-    ty = n.sons[0].Typ
-    
+    ty = n.sons[0].typ
+    return nil
   ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
+  while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
   var check: PNode = nil
-  if ty.kind == tyObject: 
-    while true: 
+  if ty.kind == tyObject:
+    while true:
       check = nil
       f = lookupInRecordAndBuildCheck(c, n, ty.n, i, check)
-      if f != nil: break 
-      if ty.sons[0] == nil: break 
+      if f != nil: break
+      if ty.sons[0] == nil: break
       ty = skipTypes(ty.sons[0], {tyGenericInst})
     if f != nil:
       if fieldVisible(c, f):
         # is the access to a public field or in the same module or in a friend?
+        markUsed(n.sons[1], f)
         n.sons[0] = makeDeref(n.sons[0])
         n.sons[1] = newSymNode(f) # we now have the correct field
         n.typ = f.typ
-        markUsed(n, f)
         if check == nil: 
           result = n
         else: 
@@ -976,11 +1030,17 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   elif ty.kind == tyTuple and ty.n != nil: 
     f = getSymFromList(ty.n, i)
     if f != nil:
+      markUsed(n.sons[1], f)
       n.sons[0] = makeDeref(n.sons[0])
       n.sons[1] = newSymNode(f)
       n.typ = f.typ
       result = n
-      markUsed(n, f)
+
+  # we didn't find any field, let's look for a generic param
+  if result == nil:
+    let t = n.sons[0].typ.skipTypes(tyDotOpTransparent)
+    if t.kind in tyTypeParamsHolders:
+      result = readTypeParameter(c, t, i, n.info)
 
 proc dotTransformation(c: PContext, n: PNode): PNode =
   if isSymChoice(n.sons[1]):
@@ -990,7 +1050,7 @@ proc dotTransformation(c: PContext, n: PNode): PNode =
   else:
     var i = considerAcc(n.sons[1])
     result = newNodeI(nkDotCall, n.info)
-    result.flags.incl nfDelegate
+    result.flags.incl nfDotField
     addSon(result, newIdentNode(i, n[1].info))
     addSon(result, copyTree(n[0]))
   
@@ -1012,7 +1072,7 @@ proc semDeref(c: PContext, n: PNode): PNode =
   result = n
   var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar})
   case t.kind
-  of tyRef, tyPtr: n.typ = t.sons[0]
+  of tyRef, tyPtr: n.typ = t.lastSon
   else: result = nil
   #GlobalError(n.sons[0].info, errCircumNeedsPointer) 
 
@@ -1037,7 +1097,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
       n.sons[i] = semExprWithType(c, n.sons[i], 
                                   flags*{efInTypeof, efDetermineType})
     var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
-    var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
+    var arg = indexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
     if arg != nil:
       n.sons[1] = arg
       result = n
@@ -1059,11 +1119,11 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
         {tyInt..tyInt64}: 
       var idx = getOrdValue(n.sons[1])
       if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)]
-      else: LocalError(n.info, errInvalidIndexValueForTuple)
+      else: localError(n.info, errInvalidIndexValueForTuple)
     else: 
-      LocalError(n.info, errIndexTypesDoNotMatch)
+      localError(n.info, errIndexTypesDoNotMatch)
     result = n
-  else: nil
+  else: discard
   
 proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = 
   result = semSubscript(c, n, flags)
@@ -1073,12 +1133,13 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
 
 proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
   var id = considerAcc(a[1])
-  let setterId = newIdentNode(getIdent(id.s & '='), n.info)
+  var setterId = newIdentNode(getIdent(id.s & '='), n.info)
   # a[0] is already checked for semantics, that does ``builtinFieldAccess``
   # this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
   # nodes?
   let aOrig = nOrig[0]
   result = newNode(nkCall, n.info, sons = @[setterId, a[0], semExpr(c, n[1])])
+  result.flags.incl nfDotSetter
   let orig = newNode(nkCall, n.info, sons = @[setterId, aOrig[0], nOrig[1]])
   result = semOverloadedCallAnalyseEffects(c, result, orig, {})
   
@@ -1093,13 +1154,13 @@ proc takeImplicitAddr(c: PContext, n: PNode): PNode =
   of nkHiddenDeref, nkDerefExpr: return n.sons[0]
   of nkBracketExpr:
     if len(n) == 1: return n.sons[0]
-  else: nil
+  else: discard
   var valid = isAssignable(c, n)
   if valid != arLValue:
     if valid == arLocalLValue:
-      LocalError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
+      localError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
     else:
-      LocalError(n.info, errExprHasNoAddress)
+      localError(n.info, errExprHasNoAddress)
   result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
   result.add(n)
   
@@ -1110,6 +1171,9 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
       n.sons[0] = x # 'result[]' --> 'result'
       n.sons[1] = takeImplicitAddr(c, ri)
 
+template resultTypeIsInferrable(typ: PType): expr =
+  typ.isMetaType and typ.kind != tyTypeDesc
+
 proc semAsgn(c: PContext, n: PNode): PNode =
   checkSonsLen(n, 2)
   var a = n.sons[0]
@@ -1148,7 +1212,7 @@ proc semAsgn(c: PContext, n: PNode): PNode =
   # a = b # b no 'var T' means: a = addr(b)
   var le = a.typ
   if skipTypes(le, {tyGenericInst}).kind != tyVar and 
-      IsAssignable(c, a) == arNone:
+      isAssignable(c, a) == arNone:
     # Direct assignment to a discriminant is allowed!
     localError(a.info, errXCannotBeAssignedTo,
                renderTree(a, {renderNoComments}))
@@ -1160,10 +1224,10 @@ proc semAsgn(c: PContext, n: PNode): PNode =
       rhs = semExprWithType(c, n.sons[1], 
         if lhsIsResult: {efAllowDestructor} else: {})
     if lhsIsResult:
-      n.typ = EnforceVoidContext
-      if lhs.sym.typ.kind == tyGenericParam:
-        if matchTypeClass(lhs.typ, rhs.typ):
-          InternalAssert c.p.resultSym != nil
+      n.typ = enforceVoidContext
+      if c.p.owner.kind != skMacro and resultTypeIsInferrable(lhs.sym.typ):
+        if cmpTypes(c, lhs.typ, rhs.typ) == isGeneric:
+          internalAssert c.p.resultSym != nil
           lhs.typ = rhs.typ
           c.p.resultSym.typ = rhs.typ
           c.p.owner.typ.sons[0] = rhs.typ
@@ -1175,11 +1239,11 @@ proc semAsgn(c: PContext, n: PNode): PNode =
     asgnToResultVar(c, n, n.sons[0], n.sons[1])
   result = n
 
-proc SemReturn(c: PContext, n: PNode): PNode =
+proc semReturn(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
   if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro} or
-     (c.p.owner.kind == skIterator and c.p.owner.typ.callConv == ccClosure):
+     c.p.owner.kind == skClosureIterator:
     if n.sons[0].kind != nkEmpty:
       # transform ``return expr`` to ``result = expr; return``
       if c.p.resultSym != nil: 
@@ -1191,18 +1255,19 @@ proc SemReturn(c: PContext, n: PNode): PNode =
         if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym: 
           n.sons[0] = ast.emptyNode
       else:
-        LocalError(n.info, errNoReturnTypeDeclared)
+        localError(n.info, errNoReturnTypeDeclared)
   else:
-    LocalError(n.info, errXNotAllowedHere, "\'return\'")
+    localError(n.info, errXNotAllowedHere, "\'return\'")
 
 proc semProcBody(c: PContext, n: PNode): PNode =
   openScope(c)
+  
   result = semExpr(c, n)
   if c.p.resultSym != nil and not isEmptyType(result.typ):
     # transform ``expr`` to ``result = expr``, but not if the expr is already
     # ``result``:
     if result.kind == nkSym and result.sym == c.p.resultSym:
-      nil
+      discard
     elif result.kind == nkNilLit:
       # or ImplicitlyDiscardable(result):
       # new semantic: 'result = x' triggers the void context
@@ -1220,9 +1285,14 @@ proc semProcBody(c: PContext, n: PNode): PNode =
       result = semAsgn(c, a)
   else:
     discardCheck(c, result)
+  
+  if c.p.owner.kind notin {skMacro, skTemplate} and
+     c.p.resultSym != nil and c.p.resultSym.typ.isMetaType:
+    localError(c.p.resultSym.info, errCannotInferReturnType)
+
   closeScope(c)
 
-proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
+proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
   var t = skipTypes(restype, {tyGenericInst})
   case t.kind
   of tyVar:
@@ -1239,22 +1309,33 @@ proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
           a.sons[i] = takeImplicitAddr(c, a.sons[i])
         else:
           localError(n.sons[0].info, errXExpected, "tuple constructor")
-  else: nil
+  else: discard
   
-proc SemYield(c: PContext, n: PNode): PNode =
+proc semYield(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
-  if c.p.owner == nil or c.p.owner.kind != skIterator:
-    LocalError(n.info, errYieldNotAllowedHere)
+  if c.p.owner == nil or c.p.owner.kind notin skIterators:
+    localError(n.info, errYieldNotAllowedHere)
   elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
-    LocalError(n.info, errYieldNotAllowedInTryStmt)
+    localError(n.info, errYieldNotAllowedInTryStmt)
   elif n.sons[0].kind != nkEmpty:
-    n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
-    var restype = c.p.owner.typ.sons[0]
+    n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility:
+    var iterType = c.p.owner.typ
+    var restype = iterType.sons[0]
     if restype != nil:
-      n.sons[0] = fitNode(c, restype, n.sons[0])
-      if n.sons[0].typ == nil: InternalError(n.info, "semYield")
-      SemYieldVarResult(c, n, restype)
+      let adjustedRes = if c.p.owner.kind == skIterator: restype.base
+                        else: restype
+      n.sons[0] = fitNode(c, adjustedRes, n.sons[0])
+      if n.sons[0].typ == nil: internalError(n.info, "semYield")
+      
+      if resultTypeIsInferrable(adjustedRes):
+        let inferred = n.sons[0].typ
+        if c.p.owner.kind == skIterator:
+          iterType.sons[0].sons[0] = inferred
+        else:
+          iterType.sons[0] = inferred
+      
+      semYieldVarResult(c, n, adjustedRes)
     else:
       localError(n.info, errCannotReturnExpr)
   elif c.p.owner.typ.sons[0] != nil:
@@ -1266,37 +1347,37 @@ proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
   else: 
     result = searchInScopes(c, i) # no need for stub loading
 
-proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = 
+proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = 
   case n.kind
   of nkIdent: 
-    result = LookupForDefined(c, n.ident, onlyCurrentScope)
+    result = lookUpForDefined(c, n.ident, onlyCurrentScope)
   of nkDotExpr:
     result = nil
     if onlyCurrentScope: return 
     checkSonsLen(n, 2)
-    var m = LookupForDefined(c, n.sons[0], onlyCurrentScope)
+    var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope)
     if (m != nil) and (m.kind == skModule): 
       if (n.sons[1].kind == nkIdent): 
         var ident = n.sons[1].ident
         if m == c.module: 
-          result = StrTableGet(c.topLevelScope.symbols, ident)
+          result = strTableGet(c.topLevelScope.symbols, ident)
         else: 
-          result = StrTableGet(m.tab, ident)
+          result = strTableGet(m.tab, ident)
       else: 
-        LocalError(n.sons[1].info, errIdentifierExpected, "")
+        localError(n.sons[1].info, errIdentifierExpected, "")
   of nkAccQuoted:
-    result = lookupForDefined(c, considerAcc(n), onlyCurrentScope)
+    result = lookUpForDefined(c, considerAcc(n), onlyCurrentScope)
   of nkSym:
     result = n.sym
   else: 
-    LocalError(n.info, errIdentifierExpected, renderTree(n))
+    localError(n.info, errIdentifierExpected, renderTree(n))
     result = nil
 
 proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = 
   checkSonsLen(n, 2)
   # we replace this node by a 'true' or 'false' node:
   result = newIntNode(nkIntLit, 0)
-  if LookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: 
+  if lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: 
     result.intVal = 1
   elif not onlyCurrentScope and (n.sons[1].kind == nkIdent) and
       condsyms.isDefined(n.sons[1].ident): 
@@ -1313,18 +1394,18 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
   ## The argument to the proc should be nkCall(...) or similar
   ## Returns the macro/template symbol
   if isCallExpr(n):
-    var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared})
+    var expandedSym = qualifiedLookUp(c, n[0], {checkUndeclared})
     if expandedSym == nil:
-      LocalError(n.info, errUndeclaredIdentifier, n[0].renderTree)
+      localError(n.info, errUndeclaredIdentifier, n[0].renderTree)
       return errorSym(c, n[0])
 
     if expandedSym.kind notin {skMacro, skTemplate}:
-      LocalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
+      localError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
       return errorSym(c, n[0])
 
     result = expandedSym
   else:
-    LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
+    localError(n.info, errXisNoMacroOrTemplate, n.renderTree)
     result = errorSym(c, n)
 
 proc expectString(c: PContext, n: PNode): string =
@@ -1332,10 +1413,10 @@ proc expectString(c: PContext, n: PNode): string =
   if n.kind in nkStrKinds:
     return n.strVal
   else:
-    LocalError(n.info, errStringLiteralExpected)
+    localError(n.info, errStringLiteralExpected)
 
 proc getMagicSym(magic: TMagic): PSym =
-  result = newSym(skProc, getIdent($magic), GetCurrOwner(), gCodegenLineInfo)
+  result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo)
   result.magic = magic
 
 proc newAnonSym(kind: TSymKind, info: TLineInfo,
@@ -1355,9 +1436,9 @@ proc semUsing(c: PContext, n: PNode): PNode =
       of skProcKinds:
         addDeclAt(c.currentScope, usedSym.sym)
         continue
-      else: nil
+      else: discard
 
-    LocalError(e.info, errUsingNoSymbol, e.renderTree)
+    localError(e.info, errUsingNoSymbol, e.renderTree)
 
 proc semExpandToAst(c: PContext, n: PNode): PNode =
   var macroCall = n[1]
@@ -1371,7 +1452,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
     macroCall.sons[i] = semExprWithType(c, macroCall[i], {})
 
   # Preserve the magic symbol in order to be handled in evals.nim
-  InternalAssert n.sons[0].sym.magic == mExpandToAst
+  internalAssert n.sons[0].sym.magic == mExpandToAst
   n.typ = getSysSym("PNimrodNode").typ # expandedSym.getReturnType
   result = n
 
@@ -1403,12 +1484,11 @@ proc processQuotations(n: var PNode, op: string,
   elif n.kind == nkAccQuoted and op == "``":
     returnQuote n[0]
  
-  if not n.isAtom:
-    for i in 0 .. <n.len:
-      processQuotations(n.sons[i], op, quotes, ids)
+  for i in 0 .. <n.safeLen:
+    processQuotations(n.sons[i], op, quotes, ids)
 
 proc semQuoteAst(c: PContext, n: PNode): PNode =
-  InternalAssert n.len == 2 or n.len == 3
+  internalAssert n.len == 2 or n.len == 3
   # We transform the do block into a template with a param for
   # each interpolation. We'll pass this template to getAst.
   var
@@ -1421,7 +1501,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
       # this will store the generated param names
 
   if doBlk.kind != nkDo:
-    LocalError(n.info, errXExpected, "block")
+    localError(n.info, errXExpected, "block")
 
   processQuotations(doBlk.sons[bodyPos], op, quotes, ids)
   
@@ -1445,7 +1525,7 @@ proc tryExpr(c: PContext, n: PNode,
   # watch out, hacks ahead:
   let oldErrorCount = msgs.gErrorCounter
   let oldErrorMax = msgs.gErrorMax
-  inc c.InCompilesContext
+  inc c.inCompilesContext
   # do not halt after first error:
   msgs.gErrorMax = high(int)
   
@@ -1458,26 +1538,26 @@ proc tryExpr(c: PContext, n: PNode,
   errorOutputs = if bufferErrors: {eInMemory} else: {}
   let oldContextLen = msgs.getInfoContextLen()
   
-  let oldInGenericContext = c.InGenericContext
-  let oldInUnrolledContext = c.InUnrolledContext
-  let oldInGenericInst = c.InGenericInst
+  let oldInGenericContext = c.inGenericContext
+  let oldInUnrolledContext = c.inUnrolledContext
+  let oldInGenericInst = c.inGenericInst
   let oldProcCon = c.p
   c.generics = @[]
   try:
     result = semExpr(c, n, flags)
     if msgs.gErrorCounter != oldErrorCount: result = nil
   except ERecoverableError:
-    nil
+    discard
   # undo symbol table changes (as far as it's possible):
   c.generics = oldGenerics
-  c.InGenericContext = oldInGenericContext
-  c.InUnrolledContext = oldInUnrolledContext
-  c.InGenericInst = oldInGenericInst
+  c.inGenericContext = oldInGenericContext
+  c.inUnrolledContext = oldInUnrolledContext
+  c.inGenericInst = oldInGenericInst
   c.p = oldProcCon
   msgs.setInfoContextLen(oldContextLen)
-  setlen(gOwners, oldOwnerLen)
+  setLen(gOwners, oldOwnerLen)
   c.currentScope = oldScope
-  dec c.InCompilesContext
+  dec c.inCompilesContext
   errorOutputs = oldErrorOutputs
   msgs.gErrorCounter = oldErrorCount
   msgs.gErrorMax = oldErrorMax
@@ -1555,7 +1635,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
   # The ``when`` statement implements the mechanism for platform dependent
   # code. Thus we try to ensure here consistent ID allocation after the
   # ``when`` statement.
-  IDsynchronizationPoint(200)
+  idSynchronizationPoint(200)
 
 proc semSetConstr(c: PContext, n: PNode): PNode = 
   result = newNodeI(nkCurly, n.info)
@@ -1584,10 +1664,10 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
         if typ == nil: 
           typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
     if not isOrdinalType(typ):
-      LocalError(n.info, errOrdinalTypeExpected)
-      typ = makeRangeType(c, 0, MaxSetElements - 1, n.info)
+      localError(n.info, errOrdinalTypeExpected)
+      typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
     elif lengthOrd(typ) > MaxSetElements: 
-      typ = makeRangeType(c, 0, MaxSetElements - 1, n.info)
+      typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
     addSonSkipIntLit(result.typ, typ)
     for i in countup(0, sonsLen(n) - 1): 
       var m: PNode
@@ -1624,28 +1704,28 @@ proc semTableConstr(c: PContext, n: PNode): PNode =
   if lastKey != n.len: illFormedAst(n)
   result = semExpr(c, result)
 
-type 
-  TParKind = enum 
+type
+  TParKind = enum
     paNone, paSingle, paTupleFields, paTuplePositions
 
-proc checkPar(n: PNode): TParKind = 
+proc checkPar(n: PNode): TParKind =
   var length = sonsLen(n)
   if length == 0: 
     result = paTuplePositions # ()
   elif length == 1: 
     result = paSingle         # (expr)
-  else: 
+  else:
     if n.sons[0].kind == nkExprColonExpr: result = paTupleFields
     else: result = paTuplePositions
-    for i in countup(0, length - 1): 
-      if result == paTupleFields: 
+    for i in countup(0, length - 1):
+      if result == paTupleFields:
         if (n.sons[i].kind != nkExprColonExpr) or
-            not (n.sons[i].sons[0].kind in {nkSym, nkIdent}): 
-          LocalError(n.sons[i].info, errNamedExprExpected)
+            not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
+          localError(n.sons[i].info, errNamedExprExpected)
           return paNone
-      else: 
-        if n.sons[i].kind == nkExprColonExpr: 
-          LocalError(n.sons[i].info, errNamedExprNotAllowed)
+      else:
+        if n.sons[i].kind == nkExprColonExpr:
+          localError(n.sons[i].info, errNamedExprNotAllowed)
           return paNone
 
 proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
@@ -1654,13 +1734,12 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
   var ids = initIntSet()
   for i in countup(0, sonsLen(n) - 1):
-    if (n.sons[i].kind != nkExprColonExpr) or
-        not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
+    if n[i].kind != nkExprColonExpr or n[i][0].kind notin {nkSym, nkIdent}:
       illFormedAst(n.sons[i])
     var id: PIdent
     if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
     else: id = n.sons[i].sons[0].sym.name
-    if ContainsOrIncl(ids, id.id): 
+    if containsOrIncl(ids, id.id): 
       localError(n.sons[i].info, errFieldInitTwice, id.s)
     n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
                                         flags*{efAllowDestructor})
@@ -1687,7 +1766,7 @@ proc checkInitialized(n: PNode, ids: TIntSet, info: TLineInfo) =
     for i in countup(0, sonsLen(n) - 1):
       checkInitialized(n.sons[i], ids, info)
   of nkRecCase:
-    if (n.sons[0].kind != nkSym): InternalError(info, "checkInitialized")
+    if (n.sons[0].kind != nkSym): internalError(info, "checkInitialized")
     checkInitialized(n.sons[0], ids, info)
     when false:
       # XXX we cannot check here, as we don't know the branch!
@@ -1697,7 +1776,7 @@ proc checkInitialized(n: PNode, ids: TIntSet, info: TLineInfo) =
         else: internalError(info, "checkInitialized")
   of nkSym:
     if tfNeedsInit in n.sym.typ.flags and n.sym.name.id notin ids:
-      Message(info, errGenerated, "field not initialized: " & n.sym.name.s)
+      message(info, errGenerated, "field not initialized: " & n.sym.name.s)
   else: internalError(info, "checkInitialized")
 
 proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
@@ -1705,8 +1784,8 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = n
   result.typ = t
   result.kind = nkObjConstr
-  t = skipTypes(t, abstractInst)
-  if t.kind == tyRef: t = skipTypes(t.sons[0], abstractInst)
+  t = skipTypes(t, {tyGenericInst})
+  if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst})
   if t.kind != tyObject:
     localError(n.info, errGenerated, "object constructor needs an object type")
     return
@@ -1720,7 +1799,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
     var id: PIdent
     if it.sons[0].kind == nkIdent: id = it.sons[0].ident
     else: id = it.sons[0].sym.name
-    if ContainsOrIncl(ids, id.id):
+    if containsOrIncl(ids, id.id):
       localError(it.info, errFieldInitTwice, id.s)
     var e = semExprWithType(c, it.sons[1], flags*{efAllowDestructor})
     var
@@ -1753,7 +1832,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
 
 proc semBlock(c: PContext, n: PNode): PNode =
   result = n
-  Inc(c.p.nestedBlockCounter)
+  inc(c.p.nestedBlockCounter)
   checkSonsLen(n, 2)
   openScope(c) # BUGFIX: label is in the scope of block!
   if n.sons[0].kind != nkEmpty:
@@ -1767,23 +1846,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
   if isEmptyType(n.typ): n.kind = nkBlockStmt
   else: n.kind = nkBlockExpr
   closeScope(c)
-  Dec(c.p.nestedBlockCounter)
-
-proc buildCall(n: PNode): PNode =
-  if n.kind == nkDotExpr and n.len == 2:
-    # x.y --> y(x)
-    result = newNodeI(nkCall, n.info, 2)
-    result.sons[0] = n.sons[1]
-    result.sons[1] = n.sons[0]
-  elif n.kind in nkCallKinds and n.sons[0].kind == nkDotExpr:
-    # x.y(a) -> y(x, a)
-    let a = n.sons[0]
-    result = newNodeI(nkCall, n.info, n.len+1)
-    result.sons[0] = a.sons[1]
-    result.sons[1] = a.sons[0]
-    for i in 1 .. <n.len: result.sons[i+1] = n.sons[i]
-  else:
-    result = n
+  dec(c.p.nestedBlockCounter)
 
 proc doBlockIsStmtList(n: PNode): bool =
   result = n.kind == nkDo and
@@ -1818,6 +1881,10 @@ proc semExport(c: PContext, n: PNode): PNode =
   c.module.ast.add x
   result = n
 
+proc setGenericParams(c: PContext, n: PNode) =
+  for i in 1 .. <n.len:
+    n[i].typ = semTypeNode(c, n[i], nil)
+
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
   result = n
   if gCmd == cmdIdeTools: suggestExpr(c, n)
@@ -1827,19 +1894,19 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     var s = lookUp(c, n)
     semCaptureSym(s, c.p.owner)
     result = semSym(c, n, s, flags)
-    if s.kind in {skProc, skMethod, skIterator, skConverter}:
+    if s.kind in {skProc, skMethod, skConverter}+skIterators:
       #performProcvarCheck(c, n, s)
       result = symChoice(c, n, s, scClosed)
       if result.kind == nkSym:
         markIndirect(c, result.sym)
-        if isGenericRoutine(result.sym):
-          LocalError(n.info, errInstantiateXExplicitely, s.name.s)
+        # if isGenericRoutine(result.sym):
+        #   localError(n.info, errInstantiateXExplicitely, s.name.s)
   of nkSym:
     # because of the changed symbol binding, this does not mean that we
     # don't have to check the symbol for semantics here again!
     result = semSym(c, n, n.sym, flags)
   of nkEmpty, nkNone, nkCommentStmt: 
-    nil
+    discard
   of nkNilLit: 
     result.typ = getSysType(tyNil)
   of nkIntLit:
@@ -1880,51 +1947,55 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       result.kind = nkCall
       result = semExpr(c, result, flags)
   of nkBind:
-    Message(n.info, warnDeprecated, "bind")
+    message(n.info, warnDeprecated, "bind")
     result = semExpr(c, n.sons[0], flags)
-  of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy:
-    var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
+  of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy, nkStaticTy:
+    var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter})
     result.typ = makeTypeDesc(c, typ)
     #result = symNodeFromType(c, typ, n.info)
   of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: 
     # check if it is an expression macro:
     checkMinSonsLen(n, 1)
-    let mode = if nfDelegate in n.flags: {} else: {checkUndeclared}
-    var s = qualifiedLookup(c, n.sons[0], mode)
+    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], s)
       case s.kind
       of skMacro:
         if sfImmediate notin s.flags:
           result = semDirectOp(c, n, flags)
         else:
           var p = fixImmediateParams(n)
-          result = semMacroExpr(c, p, p, s)
+          result = semMacroExpr(c, p, p, s, flags)
       of skTemplate:
         if sfImmediate notin s.flags:
           result = semDirectOp(c, n, flags)
         else:
           var p = fixImmediateParams(n)
-          result = semTemplateExpr(c, p, s)
+          result = semTemplateExpr(c, p, s, flags)
       of skType:
         # XXX think about this more (``set`` procs)
         if n.len == 2:
           result = semConv(c, n)
         elif n.len == 1:
           result = semObjConstr(c, n, flags)
-        elif Contains(c.AmbiguousSymbols, s.id): 
-          LocalError(n.info, errUseQualifier, s.name.s)
+        elif contains(c.ambiguousSymbols, s.id): 
+          localError(n.info, errUseQualifier, s.name.s)
         elif s.magic == mNone: result = semDirectOp(c, n, flags)
         else: result = semMagic(c, n, s, flags)
-      of skProc, skMethod, skConverter, skIterator: 
+      of skProc, skMethod, skConverter, skIterators:
         if s.magic == mNone: result = semDirectOp(c, n, flags)
         else: result = semMagic(c, n, s, flags)
       else:
         #liMessage(n.info, warnUser, renderTree(n));
         result = semIndirectOp(c, n, flags)
-    elif isSymChoice(n.sons[0]) or n[0].kind == nkBracketExpr and 
-        isSymChoice(n[0][0]):
+    elif n[0].kind == nkBracketExpr and isSymChoice(n[0][0]):
+      # indirectOp can deal with explicit instantiations; the fixes
+      # the 'newSeq[T](x)' bug
+      setGenericParams(c, n.sons[0])
       result = semDirectOp(c, n, flags)
-    elif nfDelegate in n.flags:
+    elif isSymChoice(n.sons[0]) or nfDotField in n.flags:
       result = semDirectOp(c, n, flags)
     else:
       result = semIndirectOp(c, n, flags)
@@ -1936,12 +2007,15 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       result = semExpr(c, result, flags)
   of nkBracketExpr:
     checkMinSonsLen(n, 1)
-    var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
-    if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}: 
+    var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
+    if (s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators) or
+        n[0].kind in nkSymChoices:
       # type parameters: partial generic specialization
       n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
       result = explicitGenericInstantiation(c, n, s)
-    else: 
+    elif s != nil and s.kind in {skType}:
+      result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
+    else:
       result = semArrayAccess(c, n, flags)
   of nkCurlyExpr:
     result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
@@ -1964,7 +2038,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     checkSonsLen(n, 1)
     n.sons[0] = semExprWithType(c, n.sons[0])
     if isAssignable(c, n.sons[0]) notin {arLValue, arLocalLValue}: 
-      LocalError(n.info, errExprHasNoAddress)
+      localError(n.info, errExprHasNoAddress)
     n.typ = makePtrType(c, n.sons[0].typ)
   of nkHiddenAddr, nkHiddenDeref:
     checkSonsLen(n, 1)
@@ -1988,12 +2062,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result = semStaticExpr(c, n)
   of nkAsgn: result = semAsgn(c, n)
   of nkBlockStmt, nkBlockExpr: result = semBlock(c, n)
-  of nkStmtList, nkStmtListExpr: result = semStmtList(c, n)
+  of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags)
   of nkRaiseStmt: result = semRaise(c, n)
   of nkVarSection: result = semVarOrLet(c, n, skVar)
   of nkLetSection: result = semVarOrLet(c, n, skLet)
   of nkConstSection: result = semConst(c, n)
-  of nkTypeSection: result = SemTypeSection(c, n)
+  of nkTypeSection: result = semTypeSection(c, n)
   of nkDiscardStmt: result = semDiscard(c, n)
   of nkWhileStmt: result = semWhile(c, n)
   of nkTryStmt: result = semTry(c, n)
@@ -2012,25 +2086,25 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkMacroDef: result = semMacroDef(c, n)
   of nkTemplateDef: result = semTemplateDef(c, n)
   of nkImportStmt: 
-    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
+    if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "import")
     result = evalImport(c, n)
   of nkImportExceptStmt:
-    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
+    if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "import")
     result = evalImportExcept(c, n)
   of nkFromStmt: 
-    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
+    if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "from")
     result = evalFrom(c, n)
   of nkIncludeStmt: 
-    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
+    if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "include")
     result = evalInclude(c, n)
   of nkExportStmt, nkExportExceptStmt:
-    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "export")
+    if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "export")
     result = semExport(c, n)
   of nkPragmaBlock:
     result = semPragmaBlock(c, n)
   of nkStaticStmt:
     result = semStaticStmt(c, n)
   else:
-    LocalError(n.info, errInvalidExpressionX,
+    localError(n.info, errInvalidExpressionX,
                renderTree(n, {renderNoComments}))
   if result != nil: incl(result.flags, nfSem)
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index ca06ea1b6..caaab2291 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -66,14 +66,14 @@ proc ordinalValToString*(a: PNode): string =
   of tyEnum:
     var n = t.n
     for i in countup(0, sonsLen(n) - 1): 
-      if n.sons[i].kind != nkSym: InternalError(a.info, "ordinalValToString")
+      if n.sons[i].kind != nkSym: internalError(a.info, "ordinalValToString")
       var field = n.sons[i].sym
       if field.position == x: 
         if field.ast == nil: 
           return field.name.s
         else:
           return field.ast.strVal
-    InternalError(a.info, "no symbol for ordinal value: " & $x)
+    internalError(a.info, "no symbol for ordinal value: " & $x)
   else:
     result = $x
 
@@ -92,7 +92,7 @@ proc pickIntRange(a, b: PType): PType =
 proc isIntRangeOrLit(t: PType): bool =
   result = isIntRange(t) or isIntLit(t)
 
-proc pickMinInt(n: PNode): biggestInt =
+proc pickMinInt(n: PNode): BiggestInt =
   if n.kind in {nkIntLit..nkUInt64Lit}:
     result = n.intVal
   elif isIntLit(n.typ):
@@ -100,9 +100,9 @@ proc pickMinInt(n: PNode): biggestInt =
   elif isIntRange(n.typ):
     result = firstOrd(n.typ)
   else:
-    InternalError(n.info, "pickMinInt")
+    internalError(n.info, "pickMinInt")
 
-proc pickMaxInt(n: PNode): biggestInt =
+proc pickMaxInt(n: PNode): BiggestInt =
   if n.kind in {nkIntLit..nkUInt64Lit}:
     result = n.intVal
   elif isIntLit(n.typ):
@@ -110,17 +110,23 @@ proc pickMaxInt(n: PNode): biggestInt =
   elif isIntRange(n.typ):
     result = lastOrd(n.typ)
   else:
-    InternalError(n.info, "pickMaxInt")
+    internalError(n.info, "pickMaxInt")
 
-proc makeRange(typ: PType, first, last: biggestInt): PType = 
-  var n = newNode(nkRange)
-  addSon(n, newIntNode(nkIntLit, min(first, last)))
-  addSon(n, newIntNode(nkIntLit, max(first, last)))
-  result = newType(tyRange, typ.owner)
-  result.n = n
-  addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
+proc makeRange(typ: PType, first, last: BiggestInt): PType = 
+  let minA = min(first, last)
+  let maxA = max(first, last)
+  let lowerNode = newIntNode(nkIntLit, minA)
+  if typ.kind == tyInt and minA == maxA:
+    result = getIntLitType(lowerNode)
+  else:
+    var n = newNode(nkRange)
+    addSon(n, lowerNode)
+    addSon(n, newIntNode(nkIntLit, maxA))
+    result = newType(tyRange, typ.owner)
+    result.n = n
+    addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
 
-proc makeRangeF(typ: PType, first, last: biggestFloat): PType =
+proc makeRangeF(typ: PType, first, last: BiggestFloat): PType =
   var n = newNode(nkRange)
   addSon(n, newFloatNode(nkFloatLit, min(first.float, last.float)))
   addSon(n, newFloatNode(nkFloatLit, max(first.float, last.float)))
@@ -222,13 +228,40 @@ proc getIntervalType*(m: TMagic, n: PNode): PType =
     commutativeOp(min)
   of mMaxI, mMaxI64:
     commutativeOp(max)
-  else: nil
+  else: discard
   
 discard """
   mShlI, mShlI64,
   mShrI, mShrI64, mAddF64, mSubF64, mMulF64, mDivF64, mMaxF64, mMinF64
 """
 
+proc evalIs(n, a: PNode): PNode =
+  # XXX: This should use the standard isOpImpl
+  internalAssert a.kind == nkSym and a.sym.kind == skType
+  internalAssert n.sonsLen == 3 and
+    n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
+  
+  let t1 = a.sym.typ
+
+  if n[2].kind in {nkStrLit..nkTripleStrLit}:
+    case n[2].strVal.normalize
+    of "closure":
+      let t = skipTypes(t1, abstractRange)
+      result = newIntNode(nkIntLit, ord(t.kind == tyProc and
+                                        t.callConv == ccClosure and 
+                                        tfIterator notin t.flags))
+    of "iterator":
+      let t = skipTypes(t1, abstractRange)
+      result = newIntNode(nkIntLit, ord(t.kind == tyProc and
+                                        t.callConv == ccClosure and 
+                                        tfIterator in t.flags))
+  else:
+    # XXX semexprs.isOpImpl is slightly different and requires a context. yay.
+    let t2 = n[2].typ
+    var match = sameType(t1, t2)
+    result = newIntNode(nkIntLit, ord(match))
+  result.typ = n.typ
+
 proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = 
   # b and c may be nil
   result = nil
@@ -276,7 +309,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
     of tyInt32: result = newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n)
     of tyInt64, tyInt, tyUInt..tyUInt64: 
       result = newIntNodeT(`shl`(getInt(a), getInt(b)), n)
-    else: InternalError(n.info, "constant folding for shl")
+    else: internalError(n.info, "constant folding for shl")
   of mShrI, mShrI64: 
     case skipTypes(n.typ, abstractRange).kind
     of tyInt8: result = newIntNodeT(int8(getInt(a)) shr int8(getInt(b)), n)
@@ -284,7 +317,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
     of tyInt32: result = newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n)
     of tyInt64, tyInt, tyUInt..tyUInt64:
       result = newIntNodeT(`shr`(getInt(a), getInt(b)), n)
-    else: InternalError(n.info, "constant folding for shr")
+    else: internalError(n.info, "constant folding for shr")
   of mDivI, mDivI64: result = newIntNodeT(getInt(a) div getInt(b), n)
   of mModI, mModI64: result = newIntNodeT(getInt(a) mod getInt(b), n)
   of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n)
@@ -327,10 +360,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
   of mMulU: result = newIntNodeT(`*%`(getInt(a), getInt(b)), n)
   of mModU: result = newIntNodeT(`%%`(getInt(a), getInt(b)), n)
   of mDivU: result = newIntNodeT(`/%`(getInt(a), getInt(b)), n)
-  of mLeSet: result = newIntNodeT(Ord(containsSets(a, b)), n)
-  of mEqSet: result = newIntNodeT(Ord(equalSets(a, b)), n)
+  of mLeSet: result = newIntNodeT(ord(containsSets(a, b)), n)
+  of mEqSet: result = newIntNodeT(ord(equalSets(a, b)), n)
   of mLtSet: 
-    result = newIntNodeT(Ord(containsSets(a, b) and not equalSets(a, b)), n)
+    result = newIntNodeT(ord(containsSets(a, b) and not equalSets(a, b)), n)
   of mMulSet: 
     result = nimsets.intersectSets(a, b)
     result.info = n.info
@@ -344,7 +377,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
     result = nimsets.symdiffSets(a, b)
     result.info = n.info
   of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n)
-  of mInSet: result = newIntNodeT(Ord(inSet(a, b)), n)
+  of mInSet: result = newIntNodeT(ord(inSet(a, b)), n)
   of mRepr:
     # BUGFIX: we cannot eval mRepr here for reasons that I forgot.
   of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n)
@@ -363,19 +396,19 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
     result = copyTree(a)
     result.typ = n.typ
   of mCompileOption:
-    result = newIntNodeT(Ord(commands.testCompileOption(a.getStr, n.info)), n)  
+    result = newIntNodeT(ord(commands.testCompileOption(a.getStr, n.info)), n)  
   of mCompileOptionArg:
-    result = newIntNodeT(Ord(
+    result = newIntNodeT(ord(
       testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
   of mNewString, mNewStringOfCap, 
      mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh, 
      mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq, 
      mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait,
      mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym: 
-    nil
+    discard
   of mRand:
     result = newIntNodeT(math.random(a.getInt.int), n)
-  else: InternalError(a.info, "evalOp(" & $m & ')')
+  else: internalError(a.info, "evalOp(" & $m & ')')
   
 proc getConstIfExpr(c: PSym, n: PNode): PNode = 
   result = nil
@@ -425,13 +458,13 @@ proc leValueConv(a, b: PNode): bool =
     case b.kind
     of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
     of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal)
-    else: InternalError(a.info, "leValueConv")
+    else: internalError(a.info, "leValueConv")
   of nkFloatLit..nkFloat128Lit: 
     case b.kind
     of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
     of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
-    else: InternalError(a.info, "leValueConv")
-  else: InternalError(a.info, "leValueConv")
+    else: internalError(a.info, "leValueConv")
+  else: internalError(a.info, "leValueConv")
   
 proc magicCall(m: PSym, n: PNode): PNode =
   if sonsLen(n) <= 1: return
@@ -446,8 +479,6 @@ proc magicCall(m: PSym, n: PNode): PNode =
     if sonsLen(n) > 3: 
       c = getConstExpr(m, n.sons[3])
       if c == nil: return 
-  else: 
-    b = nil
   result = evalOp(s.magic, n, a, b, c)
   
 proc getAppType(n: PNode): PNode =
@@ -460,9 +491,9 @@ proc getAppType(n: PNode): PNode =
   else:
     result = newStrNodeT("console", n)
 
-proc rangeCheck(n: PNode, value: biggestInt) =
+proc rangeCheck(n: PNode, value: BiggestInt) =
   if value < firstOrd(n.typ) or value > lastOrd(n.typ):
-    LocalError(n.info, errGenerated, "cannot convert " & $value &
+    localError(n.info, errGenerated, "cannot convert " & $value &
                                      " to " & typeToString(n.typ))
 
 proc foldConv*(n, a: PNode; check = false): PNode = 
@@ -485,7 +516,7 @@ proc foldConv*(n, a: PNode; check = false): PNode =
       result = a
       result.typ = n.typ
   of tyOpenArray, tyVarargs, tyProc: 
-    nil
+    discard
   else: 
     result = a
     result.typ = n.typ
@@ -511,19 +542,19 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
       result = x.sons[int(idx)]
       if result.kind == nkExprColonExpr: result = result.sons[1]
     else:
-      LocalError(n.info, errIndexOutOfBounds)
-  of nkBracket, nkMetaNode: 
+      localError(n.info, errIndexOutOfBounds)
+  of nkBracket: 
     if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)]
-    else: LocalError(n.info, errIndexOutOfBounds)
+    else: localError(n.info, errIndexOutOfBounds)
   of nkStrLit..nkTripleStrLit: 
     result = newNodeIT(nkCharLit, x.info, n.typ)
     if (idx >= 0) and (idx < len(x.strVal)): 
       result.intVal = ord(x.strVal[int(idx)])
     elif idx == len(x.strVal): 
-      nil
+      discard
     else: 
-      LocalError(n.info, errIndexOutOfBounds)
-  else: nil
+      localError(n.info, errIndexOutOfBounds)
+  else: discard
   
 proc foldFieldAccess(m: PSym, n: PNode): PNode =
   # a real field access; proc calls have already been transformed
@@ -587,12 +618,13 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
     of skType:
       result = newSymNodeTypeDesc(s, n.info)
     of skGenericParam:
-      if s.typ.kind == tyExpr:
-        result = s.typ.n
-        result.typ = s.typ.sons[0]
+      if s.typ.kind == tyStatic:
+        if s.typ.n != nil:
+          result = s.typ.n
+          result.typ = s.typ.sons[0]
       else:
         result = newSymNodeTypeDesc(s, n.info)
-    else: nil
+    else: discard
   of nkCharLit..nkNilLit: 
     result = copyNode(n)
   of nkIfExpr: 
@@ -604,11 +636,12 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
     try:
       case s.magic
       of mNone:
-        return # XXX: if it has no sideEffect, it should be evaluated
+        # If it has no sideEffect, it should be evaluated. But not here.
+        return
       of mSizeOf:
         var a = n.sons[1]
         if computeSize(a.typ) < 0: 
-          LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined, 
+          localError(a.info, errCannotEvalXBecauseIncompletelyDefined, 
                      "sizeof")
           result = nil
         elif skipTypes(a.typ, typedescInst).kind in
@@ -644,12 +677,16 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
         result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
       of mConStrStr:
         result = foldConStrStr(m, n)
+      of mIs:
+        let a = getConstExpr(m, n[1])
+        if a != nil and a.kind == nkSym and a.sym.kind == skType:
+          result = evalIs(n, a)
       else:
         result = magicCall(m, n)
     except EOverflow: 
-      LocalError(n.info, errOverOrUnderflow)
+      localError(n.info, errOverOrUnderflow)
     except EDivByZero: 
-      LocalError(n.info, errConstantDivisionByZero)
+      localError(n.info, errConstantDivisionByZero)
   of nkAddr: 
     var a = getConstExpr(m, n.sons[0])
     if a != nil: 
@@ -705,7 +742,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
       result = a              # a <= x and x <= b
       result.typ = n.typ
     else: 
-      LocalError(n.info, errGenerated, `%`(
+      localError(n.info, errGenerated, `%`(
           msgKindToString(errIllegalConvFromXtoY), 
           [typeToString(n.sons[0].typ), typeToString(n.typ)]))
   of nkStringToCString, nkCStringToString: 
@@ -727,4 +764,4 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
   of nkBracketExpr: result = foldArrayAccess(m, n)
   of nkDotExpr: result = foldFieldAccess(m, n)
   else:
-    nil
+    discard
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index d626d2eb2..da4a2a132 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -17,11 +17,6 @@
 
 # included from sem.nim
 
-type
-  TSemGenericFlag = enum
-    withinBind, withinTypeDesc, withinMixin
-  TSemGenericFlags = set[TSemGenericFlag]
-
 proc getIdentNode(n: PNode): PNode =
   case n.kind
   of nkPostfix: result = getIdentNode(n.sons[1])
@@ -31,8 +26,6 @@ proc getIdentNode(n: PNode): PNode =
     illFormedAst(n)
     result = n
   
-proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
-                    ctx: var TIntSet): PNode
 proc semGenericStmtScope(c: PContext, n: PNode, 
                          flags: TSemGenericFlags,
                          ctx: var TIntSet): PNode = 
@@ -49,17 +42,17 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
   of skUnknown: 
     # Introduced in this pass! Leave it as an identifier.
     result = n
-  of skProc, skMethod, skIterator, skConverter: 
+  of skProc, skMethod, skIterators, skConverter:
     result = symChoice(c, n, s, scOpen)
   of skTemplate:
     if macroToExpand(s):
       let n = fixImmediateParams(n)
-      result = semTemplateExpr(c, n, s, false)
+      result = semTemplateExpr(c, n, s, {efNoSemCheck})
     else:
       result = symChoice(c, n, s, scOpen)
   of skMacro: 
     if macroToExpand(s):
-      result = semMacroExpr(c, n, n, s, false)
+      result = semMacroExpr(c, n, n, s, {efNoSemCheck})
     else:
       result = symChoice(c, n, s, scOpen)
   of skGenericParam: 
@@ -73,7 +66,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
       result = n
   else: result = newSymNode(s, n.info)
 
-proc Lookup(c: PContext, n: PNode, flags: TSemGenericFlags, 
+proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags, 
             ctx: var TIntSet): PNode =
   result = n
   let ident = considerAcc(n)
@@ -96,10 +89,10 @@ proc semGenericStmt(c: PContext, n: PNode,
   if gCmd == cmdIdeTools: suggestStmt(c, n)
   case n.kind
   of nkIdent, nkAccQuoted:
-    result = Lookup(c, n, flags, ctx)
+    result = lookup(c, n, flags, ctx)
   of nkDotExpr:
     let luf = if withinMixin notin flags: {checkUndeclared} else: {}
-    var s = QualifiedLookUp(c, n, luf)
+    var s = qualifiedLookUp(c, n, luf)
     if s != nil: result = semGenericStmtSymbol(c, n, s)
     # XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
   of nkEmpty, nkSym..nkNilLit:
@@ -110,7 +103,7 @@ proc semGenericStmt(c: PContext, n: PNode,
     # not work. Copying the symbol does not work either because we're already
     # the owner of the symbol! What we need to do is to copy the symbol
     # in the generic instantiation process...
-    nil
+    discard
   of nkBind:
     result = semGenericStmt(c, n.sons[0], flags+{withinBind}, ctx)
   of nkMixinStmt:
@@ -119,7 +112,7 @@ proc semGenericStmt(c: PContext, n: PNode,
     # check if it is an expression macro:
     checkMinSonsLen(n, 1)
     let fn = n.sons[0]
-    var s = qualifiedLookup(c, fn, {})
+    var s = qualifiedLookUp(c, fn, {})
     if s == nil and withinMixin notin flags and
         fn.kind in {nkIdent, nkAccQuoted} and considerAcc(fn).id notin ctx:
       localError(n.info, errUndeclaredIdentifier, fn.renderTree)
@@ -133,14 +126,14 @@ proc semGenericStmt(c: PContext, n: PNode,
       case s.kind
       of skMacro:
         if macroToExpand(s):
-          result = semMacroExpr(c, n, n, s, false)
+          result = semMacroExpr(c, n, n, s, {efNoSemCheck})
         else:
           n.sons[0] = symChoice(c, n.sons[0], s, scOption)
           result = n
       of skTemplate: 
         if macroToExpand(s):
           let n = fixImmediateParams(n)
-          result = semTemplateExpr(c, n, s, false)
+          result = semTemplateExpr(c, n, s, {efNoSemCheck})
         else:
           n.sons[0] = symChoice(c, n.sons[0], s, scOption)
           result = n
@@ -148,7 +141,7 @@ proc semGenericStmt(c: PContext, n: PNode,
         # symbol lookup ...
       of skUnknown, skParam: 
         # Leave it as an identifier.
-      of skProc, skMethod, skIterator, skConverter: 
+      of skProc, skMethod, skIterators, skConverter:
         result.sons[0] = symChoice(c, n.sons[0], s, scOption)
         first = 1
       of skGenericParam:
@@ -219,22 +212,20 @@ proc semGenericStmt(c: PContext, n: PNode,
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
+      if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a)
       checkMinSonsLen(a, 3)
       var L = sonsLen(a)
-      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, 
-                                   ctx)
+      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))
   of nkGenericParams: 
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
-      if (a.kind != nkIdentDefs): IllFormedAst(a)
+      if (a.kind != nkIdentDefs): illFormedAst(a)
       checkMinSonsLen(a, 3)
       var L = sonsLen(a)
-      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, 
-                                   ctx) 
+      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))
@@ -242,7 +233,7 @@ proc semGenericStmt(c: PContext, n: PNode,
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if (a.kind != nkConstDef): IllFormedAst(a)
+      if (a.kind != nkConstDef): illFormedAst(a)
       checkSonsLen(a, 3)
       addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c))
       a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, ctx)
@@ -251,13 +242,13 @@ proc semGenericStmt(c: PContext, n: PNode,
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if (a.kind != nkTypeDef): IllFormedAst(a)
+      if (a.kind != nkTypeDef): illFormedAst(a)
       checkSonsLen(a, 3)
       addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c))
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if (a.kind != nkTypeDef): IllFormedAst(a)
+      if (a.kind != nkTypeDef): illFormedAst(a)
       checkSonsLen(a, 3)
       if a.sons[1].kind != nkEmpty: 
         openScope(c)
@@ -278,18 +269,17 @@ proc semGenericStmt(c: PContext, n: PNode,
         else: illFormedAst(n)
         addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c))
   of nkObjectTy, nkTupleTy: 
-    nil
+    discard
   of nkFormalParams: 
     checkMinSonsLen(n, 1)
     if n.sons[0].kind != nkEmpty: 
       n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
     for i in countup(1, sonsLen(n) - 1): 
       var a = n.sons[i]
-      if (a.kind != nkIdentDefs): IllFormedAst(a)
+      if (a.kind != nkIdentDefs): illFormedAst(a)
       checkMinSonsLen(a, 3)
       var L = sonsLen(a)
-      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, 
-                                   ctx)
+      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))
@@ -311,7 +301,7 @@ proc semGenericStmt(c: PContext, n: PNode,
     else: body = n.sons[bodyPos]
     n.sons[bodyPos] = semGenericStmtScope(c, body, flags, ctx)
     closeScope(c)
-  of nkPragma, nkPragmaExpr: nil
+  of nkPragma, nkPragmaExpr: discard
   of nkExprColonExpr, nkExprEqExpr:
     checkMinSonsLen(n, 2)
     result.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index d7d64fd54..a5149a842 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -13,28 +13,27 @@
 proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
                                  entry: var TInstantiation) = 
   if n.kind != nkGenericParams: 
-    InternalError(n.info, "instantiateGenericParamList; no generic params")
+    internalError(n.info, "instantiateGenericParamList; no generic params")
   newSeq(entry.concreteTypes, n.len)
-  for i in countup(0, n.len - 1):
-    var a = n.sons[i]
+  for i, a in n.pairs:
     if a.kind != nkSym: 
-      InternalError(a.info, "instantiateGenericParamList; no symbol")
+      internalError(a.info, "instantiateGenericParamList; no symbol")
     var q = a.sym
-    if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyExpr}+tyTypeClasses:
+    if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
       continue
     var s = newSym(skType, q.name, getCurrOwner(), q.info)
     s.flags = s.flags + {sfUsed, sfFromGeneric}
-    var t = PType(IdTableGet(pt, q.typ))
+    var t = PType(idTableGet(pt, q.typ))
     if t == nil:
       if tfRetType in q.typ.flags:
         # keep the generic type and allow the return type to be bound 
         # later by semAsgn in return type inference scenario
         t = q.typ
       else:
-        LocalError(a.info, errCannotInstantiateX, s.name.s)
+        localError(a.info, errCannotInstantiateX, s.name.s)
         t = errorType(c)
     elif t.kind == tyGenericParam: 
-      InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
+      internalError(a.info, "instantiateGenericParamList: " & q.name.s)
     elif t.kind == tyGenericInvokation:
       #t = instGenericContainer(c, a, t)
       t = generateTypeInstance(c, pt, a, t)
@@ -47,10 +46,10 @@ proc sameInstantiation(a, b: TInstantiation): bool =
   if a.concreteTypes.len == b.concreteTypes.len:
     for i in 0..a.concreteTypes.high:
       if not compareTypes(a.concreteTypes[i], b.concreteTypes[i],
-                          flags = {TypeDescExactMatch}): return
+                          flags = {ExactTypeDescValues}): return
     result = true
 
-proc GenericCacheGet(genericSym: Psym, entry: TInstantiation): PSym =
+proc genericCacheGet(genericSym: PSym, entry: TInstantiation): PSym =
   if genericSym.procInstCache != nil:
     for inst in genericSym.procInstCache:
       if sameInstantiation(entry, inst[]):
@@ -75,41 +74,42 @@ proc removeDefaultParamValues(n: PNode) =
 proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
   # we need to create a fresh set of gensym'ed symbols:
   if n.kind == nkSym and sfGenSym in n.sym.flags:
-    var x = PSym(IdTableGet(symMap, n.sym))
+    var x = PSym(idTableGet(symMap, n.sym))
     if x == nil:
       x = copySym(n.sym, false)
       x.owner = owner
-      IdTablePut(symMap, n.sym, x)
+      idTablePut(symMap, n.sym, x)
     n.sym = x
   else:
     for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap)
 
 proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind)
 
+proc addProcDecls(c: PContext, fn: PSym) =
+  # get the proc itself in scope (e.g. for recursion)
+  addDecl(c, fn)
+
+  for i in 1 .. <fn.typ.n.len:
+    var param = fn.typ.n.sons[i].sym
+    param.owner = fn
+    addParamOrResult(c, param, fn.kind)
+  
+  maybeAddResult(c, fn, fn.ast)
+
 proc instantiateBody(c: PContext, n: PNode, result: PSym) =
   if n.sons[bodyPos].kind != nkEmpty:
-    inc c.InGenericInst
+    inc c.inGenericInst
     # add it here, so that recursive generic procs are possible:
-    addDecl(c, result)
-    pushProcCon(c, result)
-    # add params to scope
-    for i in 1 .. <result.typ.n.len:
-      var param = result.typ.n.sons[i].sym
-      param.owner = result
-      addParamOrResult(c, param, result.kind)
-    # debug result.typ.n
-    maybeAddResult(c, result, n)
     var b = n.sons[bodyPos]
     var symMap: TIdTable
-    InitIdTable symMap
+    initIdTable symMap
     freshGenSyms(b, result, symMap)
     b = semProcBody(c, b)
     b = hloBody(c, b)
     n.sons[bodyPos] = transformBody(c.module, b, result)
     #echo "code instantiated ", result.name.s
     excl(result.flags, sfForward)
-    popProcCon(c)
-    dec c.InGenericInst
+    dec c.inGenericInst
 
 proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
   for i in countup(0, c.generics.len - 1):
@@ -126,147 +126,78 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
 proc sideEffectsCheck(c: PContext, s: PSym) = 
   if {sfNoSideEffect, sfSideEffect} * s.flags ==
       {sfNoSideEffect, sfSideEffect}: 
-    LocalError(s.info, errXhasSideEffects, s.name.s)
+    localError(s.info, errXhasSideEffects, s.name.s)
   elif sfThread in s.flags and semthreads.needsGlobalAnalysis() and 
       s.ast.sons[genericParamsPos].kind == nkEmpty:
     c.threadEntries.add(s)
 
-proc lateInstantiateGeneric(c: PContext, invocation: PType, info: TLineInfo): PType =
-  InternalAssert invocation.kind == tyGenericInvokation
-  
-  let cacheHit = searchInstTypes(invocation)
-  if cacheHit != nil:
-    result = cacheHit
-  else:
-    let s = invocation.sons[0].sym
-    let oldScope = c.currentScope
-    c.currentScope = s.typScope
-    openScope(c)
-    pushInfoContext(info)
-    for i in 0 .. <s.typ.n.sons.len:
-      let genericParam = s.typ.n[i].sym
-      let symKind = if genericParam.typ.kind == tyExpr: skConst
-                    else: skType
-
-      var boundSym = newSym(symKind, s.typ.n[i].sym.name, s, info)
-      boundSym.typ = invocation.sons[i+1].skipTypes({tyExpr})
-      boundSym.ast = invocation.sons[i+1].n
-      addDecl(c, boundSym)
-    # XXX: copyTree would have been unnecessary here if semTypeNode
-    # didn't modify its input parameters. Currently, it does modify
-    # at least the record lists of the passed object and tuple types
-    var instantiated = semTypeNode(c, copyTree(s.ast[2]), nil)
-    popInfoContext()
-    closeScope(c)
-    c.currentScope = oldScope
-    if instantiated != nil:
-      result = invocation
-      result.kind = tyGenericInst
-      result.sons.add instantiated
-      cacheTypeInst result
-
-proc instGenericContainer(c: PContext, info: TLineInfo, header: PType): PType =
-  when oUseLateInstantiation:
-    lateInstantiateGeneric(c, header, info)
-  else:
-    var cl: TReplTypeVars
-    InitIdTable(cl.symMap)
-    InitIdTable(cl.typeMap)
-    cl.info = info
-    cl.c = c
-    result = ReplaceTypeVarsT(cl, header)
+proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
+                          allowMetaTypes = false): PType =
+  var cl: TReplTypeVars
+  initIdTable(cl.symMap)
+  initIdTable(cl.typeMap)
+  initIdTable(cl.localCache)
+  cl.info = info
+  cl.c = c
+  cl.allowMetaTypes = allowMetaTypes
+  result = replaceTypeVarsT(cl, header)
 
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
   result = instGenericContainer(c, n.info, header)
 
-proc fixupProcType(c: PContext, genericType: PType,
-                   inst: TInstantiation): PType =
-  # XXX: This is starting to look suspiciously like ReplaceTypeVarsT
-  # there are few apparent differences, but maybe the code could be
-  # moved over.
-  # * the code here uses the new genericSym.position property when
-  #   doing lookups. 
-  # * the handling of tyTypeDesc seems suspicious in ReplaceTypeVarsT
-  #   typedesc params were previously handled in the second pass of
-  #   semParamList
-  # * void (nkEmpty) params doesn't seem to be stripped in ReplaceTypeVarsT
-  result = genericType
-  if result == nil: return
-
-  case genericType.kind
-  of tyGenericParam, tyTypeClasses:
-    result = inst.concreteTypes[genericType.sym.position]
-  of tyTypeDesc:
-    result = inst.concreteTypes[genericType.sym.position]
-    if tfUnresolved in genericType.flags:
-      result = result.sons[0]
-  of tyExpr:
-    result = inst.concreteTypes[genericType.sym.position]
-  of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc,
-     tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs:
-    if genericType.sons == nil: return
-    var head = 0
-    for i in 0 .. <genericType.sons.len:
-      let origType = genericType.sons[i]
-      var changed = fixupProcType(c, origType, inst)
-      if changed != genericType.sons[i]:
-        var changed = changed.skipIntLit
-        if result == genericType:
-          # the first detected change initializes the result
-          result = copyType(genericType, genericType.owner, false)
-          if genericType.n != nil:
-            result.n = copyTree(genericType.n)
-
-        # XXX: doh, we have to treat seq and arrays as special case
-        # because sometimes the `@` magic will be applied to an empty
-        # sequence having the type tySequence(tyEmpty)
-        if changed.kind == tyEmpty and
-           genericType.kind notin {tyArray, tySequence}:
-          if genericType.kind == tyProc and i == 0:
-            # return types of procs are overwritten with nil
-            changed = nil
-          else:
-            # otherwise, `empty` is just erased from the signature
-            result.sons[i..i] = []
-            if result.n != nil: result.n.sons[i..i] = []
-            continue
-        
-        result.sons[head] = changed
-        
-        if result.n != nil:
-          if result.n.kind == nkRecList:
-            for son in result.n.sons:
-              if son.typ == origType:
-                son.typ = changed
-                son.sym = copySym(son.sym, true)
-                son.sym.typ = changed
-          if result.n.kind == nkFormalParams:
-            if i != 0:
-              let origParam = result.n.sons[head].sym
-              var param = copySym(origParam)
-              param.typ = changed
-              param.ast = origParam.ast
-              result.n.sons[head] = newSymNode(param)
-
-      # won't be advanced on empty (void) nodes
-      inc head
+proc instantiateProcType(c: PContext, pt: TIdTable,
+                          prc: PSym, info: TLineInfo) =
+  # XXX: Instantiates a generic proc signature, while at the same
+  # time adding the instantiated proc params into the current scope.
+  # This is necessary, because the instantiation process may refer to
+  # these params in situations like this:
+  # proc foo[Container](a: Container, b: a.type.Item): type(b.x)
+  #
+  # Alas, doing this here is probably not enough, because another
+  # proc signature could appear in the params:
+  # proc foo[T](a: proc (x: T, b: type(x.y))
+  #   
+  # The solution would be to move this logic into semtypinst, but
+  # at this point semtypinst have to become part of sem, because it
+  # will need to use openScope, addDecl, etc
+  #
+  addDecl(c, prc)
+  
+  pushInfoContext(info)
+  var cl = initTypeVars(c, pt, info)
+  var result = instCopyType(cl, prc.typ)
+  let originalParams = result.n
+  result.n = originalParams.shallowCopy
   
-  of tyGenericInvokation:
-    result = newTypeWithSons(c, tyGenericInvokation, genericType.sons)
-    for i in 1 .. <genericType.sons.len:
-      result.sons[i] = fixupProcType(c, result.sons[i], inst)
-    result = instGenericContainer(c, getInfoContext(-1), result)
+  for i in 1 .. <result.len:
+    result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
+    propagateToOwner(result, result.sons[i])
+    let param = replaceTypeVarsN(cl, originalParams[i])
+    result.n.sons[i] = param
+    if param.kind == nkSym:
+      # XXX: this won't be true for void params
+      # implement pass-through of void params and
+      # the "sort by distance to point" container
+      param.sym.owner = prc
+      addDecl(c, param.sym)
+    
+  result.sons[0] = replaceTypeVarsT(cl, result.sons[0])
+  result.n.sons[0] = originalParams[0].copyTree
   
-  else: nil
+  eraseVoidParams(result)
+  skipIntLiteralParams(result)
+ 
+  prc.typ = result
+  maybeAddResult(c, prc, prc.ast)
+  popInfoContext()
 
 proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
                       info: TLineInfo): PSym =
   # no need to instantiate generic templates/macros:
   if fn.kind in {skTemplate, skMacro}: return fn
-  
   # generates an instantiated proc
-  if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
-  inc(c.InstCounter)
+  if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
+  inc(c.instCounter)
   # careful! we copy the whole AST including the possibly nil body!
   var n = copyTree(fn.ast)
   # NOTE: for access of private fields within generics from a different module
@@ -281,16 +212,16 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   result.ast = n
   pushOwner(result)
   openScope(c)
-  if n.sons[genericParamsPos].kind == nkEmpty: 
-    InternalError(n.info, "generateInstance")
+  internalAssert n.sons[genericParamsPos].kind != nkEmpty
   n.sons[namePos] = newSymNode(result)
   pushInfoContext(info)
   var entry = TInstantiation.new
   entry.sym = result
   instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
-  result.typ = fixupProcType(c, fn.typ, entry[])
+  pushProcCon(c, result)
+  instantiateProcType(c, pt, result, info)
   n.sons[genericParamsPos] = ast.emptyNode
-  var oldPrc = GenericCacheGet(fn, entry[])
+  var oldPrc = genericCacheGet(fn, entry[])
   if oldPrc == nil:
     fn.procInstCache.safeAdd(entry)
     c.generics.add(makeInstPair(fn, entry))
@@ -298,18 +229,16 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
       pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
     if isNil(n.sons[bodyPos]):
       n.sons[bodyPos] = copyTree(fn.getBody)
-    if fn.kind != skTemplate:
-      instantiateBody(c, n, result)
-      sideEffectsCheck(c, result)
-    ParamsTypeCheck(c, result.typ)
+    instantiateBody(c, n, result)
+    sideEffectsCheck(c, result)
+    paramsTypeCheck(c, result.typ)
   else:
     result = oldPrc
+  popProcCon(c)
   popInfoContext()
   closeScope(c)           # close scope for parameters
   popOwner()
   #c.currentScope = oldScope
   c.friendModule = oldFriend
-  dec(c.InstCounter)
+  dec(c.instCounter)
   if result.kind == skMethod: finishMethod(c, result)
-
-
diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim
new file mode 100644
index 000000000..1bece95c2
--- /dev/null
+++ b/compiler/semmacrosanity.nim
@@ -0,0 +1,89 @@
+#
+#
+#           The Nimrod Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Implements type sanity checking for ASTs resulting from macros. Lots of
+## room for improvement here.
+
+import ast, astalgo, msgs, types
+
+proc ithField(n: PNode, field: int): PSym =
+  result = nil
+  case n.kind
+  of nkRecList:
+    for i in countup(0, sonsLen(n) - 1): 
+      result = ithField(n.sons[i], field-i)
+      if result != nil: return 
+  of nkRecCase:
+    if n.sons[0].kind != nkSym: internalError(n.info, "ithField")
+    result = ithField(n.sons[0], field-1)
+    if result != nil: return
+    for i in countup(1, sonsLen(n) - 1):
+      case n.sons[i].kind
+      of nkOfBranch, nkElse:
+        result = ithField(lastSon(n.sons[i]), field-1)
+        if result != nil: return
+      else: internalError(n.info, "ithField(record case branch)")
+  of nkSym:
+    if field == 0: result = n.sym
+  else: discard
+
+proc annotateType*(n: PNode, t: PType) =
+  let x = t.skipTypes(abstractInst)
+  # Note: x can be unequal to t and we need to be careful to use 't'
+  # to not to skip tyGenericInst
+  case n.kind
+  of nkPar:
+    if x.kind == tyObject:
+      n.typ = t
+      for i in 0 .. <n.len:
+        let field = x.n.ithField(i)
+        if field.isNil: globalError n.info, "invalid field at index " & $i
+        else: annotateType(n.sons[i], field.typ)
+    elif x.kind == tyTuple:
+      n.typ = t
+      for i in 0 .. <n.len:
+        if i >= x.len: globalError n.info, "invalid field at index " & $i
+        else: annotateType(n.sons[i], x.sons[i])
+    elif x.kind == tyProc and x.callConv == ccClosure:
+      n.typ = t
+    else:
+      globalError(n.info, "() must have an object or tuple type")
+  of nkBracket:
+    if x.kind in {tyArrayConstr, tyArray, tySequence, tyOpenarray}:
+      n.typ = t
+      for m in n: annotateType(m, x.elemType)
+    else:
+      globalError(n.info, "[] must have some form of array type")
+  of nkCurly:
+    if x.kind in {tySet}:
+      n.typ = t
+      for m in n: annotateType(m, x.elemType)
+    else:
+      globalError(n.info, "{} must have the set type")
+  of nkFloatLit..nkFloat128Lit:
+    if x.kind in {tyFloat..tyFloat128}:
+      n.typ = t
+    else:
+      globalError(n.info, "float literal must have some float type")
+  of nkCharLit..nkUInt64Lit:
+    if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
+      n.typ = t
+    else:
+      globalError(n.info, "integer literal must have some int type")
+  of nkStrLit..nkTripleStrLit:
+    if x.kind in {tyString, tyCString}:
+      n.typ = t
+    else:
+      globalError(n.info, "string literal must be of some string type")    
+  of nkNilLit:
+    if x.kind in NilableTypes:
+      n.typ = t
+    else:
+      globalError(n.info, "nil literal must be of some pointer type")
+  else: discard
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 88567b10a..4caf1fb8e 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -18,7 +18,7 @@ proc expectIntLit(c: PContext, n: PNode): int =
   let x = c.semConstExpr(c, n)
   case x.kind
   of nkIntLit..nkInt64Lit: result = int(x.intVal)
-  else: LocalError(n.info, errIntLiteralExpected)
+  else: localError(n.info, errIntLiteralExpected)
 
 proc semInstantiationInfo(c: PContext, n: PNode): PNode =
   result = newNodeIT(nkPar, n.info, n.typ)
@@ -26,21 +26,34 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
   let useFullPaths = expectIntLit(c, n.sons[2])
   let info = getInfoContext(idx)
   var filename = newNodeIT(nkStrLit, n.info, getSysType(tyString))
-  filename.strVal = if useFullPaths != 0: info.toFullPath else: info.ToFilename
+  filename.strVal = if useFullPaths != 0: info.toFullPath else: info.toFilename
   var line = newNodeIT(nkIntLit, n.info, getSysType(tyInt))
-  line.intVal = ToLinenumber(info)
+  line.intVal = toLinenumber(info)
   result.add(filename)
   result.add(line)
+ 
+proc evalTypeTrait(trait: PNode, operand: PType, context: PSym): PNode =
+  let typ = operand.skipTypes({tyTypeDesc})
+  case trait.sym.name.s.normalize
+  of "name":
+    result = newStrNode(nkStrLit, typ.typeToString(preferName))
+    result.typ = newType(tyString, context)
+    result.info = trait.info
+  of "arity":
+    result = newIntNode(nkIntLit, typ.n.len-1)
+    result.typ = newType(tyInt, context)
+    result.info = trait.info
+  else:
+    internalAssert false
 
 proc semTypeTraits(c: PContext, n: PNode): PNode =
   checkMinSonsLen(n, 2)
-  internalAssert n.sons[1].kind == nkSym
-  let typArg = n.sons[1].sym
-  if typArg.kind == skType or
-    (typArg.kind == skParam and typArg.typ.sonsLen > 0):
+  let t = n.sons[1].typ
+  internalAssert t != nil and t.kind == tyTypeDesc
+  if t.sonsLen > 0:
     # This is either a type known to sem or a typedesc
     # param to a regular proc (again, known at instantiation)
-    result = evalTypeTrait(n[0], n[1], GetCurrOwner())
+    result = evalTypeTrait(n[0], t, getCurrOwner())
   else:
     # a typedesc variable, pass unmodified to evals
     result = n
@@ -56,23 +69,23 @@ proc semBindSym(c: PContext, n: PNode): PNode =
   
   let sl = semConstExpr(c, n.sons[1])
   if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}: 
-    LocalError(n.sons[1].info, errStringLiteralExpected)
+    localError(n.sons[1].info, errStringLiteralExpected)
     return errorNode(c, n)
   
   let isMixin = semConstExpr(c, n.sons[2])
   if isMixin.kind != nkIntLit or isMixin.intVal < 0 or
       isMixin.intVal > high(TSymChoiceRule).int:
-    LocalError(n.sons[2].info, errConstExprExpected)
+    localError(n.sons[2].info, errConstExprExpected)
     return errorNode(c, n)
   
   let id = newIdentNode(getIdent(sl.strVal), n.info)
-  let s = QualifiedLookUp(c, id)
+  let s = qualifiedLookUp(c, id)
   if s != nil:
     # we need to mark all symbols:
     var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))
     result.add(sc)
   else:
-    LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
+    localError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
 
 proc semLocals(c: PContext, n: PNode): PNode =
   var counter = 0
@@ -88,7 +101,7 @@ proc semLocals(c: PContext, n: PNode): PNode =
       #if it.owner != c.p.owner: return result
       if it.kind in skLocalVars and
           it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
-              {tyVarargs, tyOpenArray, tyTypeDesc, tyExpr, tyStmt, tyEmpty}:
+            {tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyExpr, tyStmt, tyEmpty}:
 
         var field = newSym(skField, it.name, getCurrOwner(), n.info)
         field.typ = it.typ.skipTypes({tyGenericInst, tyVar})
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 7dec557be..a00325277 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -84,10 +84,10 @@ proc initVar(a: PEffects, n: PNode) =
 proc initVarViaNew(a: PEffects, n: PNode) =
   if n.kind != nkSym: return
   let s = n.sym
-  if {tfNeedsInit, tfNotNil} * s.typ.flags == {tfNotNil}:
+  if {tfNeedsInit, tfNotNil} * s.typ.flags <= {tfNotNil}:
     # 'x' is not nil, but that doesn't mean it's not nil children
     # are initialized:
-    initVarViaNew(a, n)
+    initVar(a, n)
 
 proc useVar(a: PEffects, n: PNode) =
   let s = n.sym
@@ -95,12 +95,12 @@ proc useVar(a: PEffects, n: PNode) =
     if s.id notin a.init:
       if {tfNeedsInit, tfNotNil} * s.typ.flags != {}:
         when true:
-          Message(n.info, warnProveInit, s.name.s)
+          message(n.info, warnProveInit, s.name.s)
         else:
           Message(n.info, errGenerated,
             "'$1' might not have been initialized" % s.name.s)
       else:
-        Message(n.info, warnUninit, s.name.s)
+        message(n.info, warnUninit, s.name.s)
       # prevent superfluous warnings about the same variable:
       a.init.add s.id
 
@@ -162,8 +162,8 @@ proc mergeTags(a: PEffects, b, comesFrom: PNode) =
     for effect in items(b): addTag(a, effect, useLineInfo=comesFrom != nil)
 
 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.exc):  message(e.info, hintUser, typeToString(e.typ))
+  for e in items(a.tags): message(e.info, hintUser, typeToString(e.typ))
 
 proc catches(tracked: PEffects, e: PType) =
   let e = skipTypes(e, skipPtrs)
@@ -305,21 +305,21 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
     if n.kind == nkAddr:
       # addr(x[]) can't be proven, but addr(x) can:
       if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return
-    elif n.kind == nkSym and n.sym.kind in RoutineKinds:
+    elif n.kind == nkSym and n.sym.kind in routineKinds:
       # 'p' is not nil obviously:
       return
     case impliesNotNil(tracked.guards, n)
     of impUnknown:
-      Message(n.info, errGenerated, 
+      message(n.info, errGenerated, 
               "cannot prove '$1' is not nil" % n.renderTree)
     of impNo:
-      Message(n.info, errGenerated, "'$1' is provably nil" % n.renderTree)
+      message(n.info, errGenerated, "'$1' is provably nil" % n.renderTree)
     of impYes: discard
 
 proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
   let op = n.typ
   if op != nil and op.kind == tyProc and n.kind != nkNilLit:
-    InternalAssert op.n.sons[0].kind == nkEffectList
+    internalAssert op.n.sons[0].kind == nkEffectList
     var effectList = op.n.sons[0]
     let s = n.skipConv
     if s.kind == nkSym and s.sym.kind in routineKinds:
@@ -367,7 +367,7 @@ proc trackCase(tracked: PEffects, n: PNode) =
     for i in oldState.. <tracked.init.len:
       addToIntersection(inter, tracked.init[i])
     
-  let exh = case skipTypes(n.sons[0].Typ, abstractVarRange-{tyTypeDesc}).Kind
+  let exh = case skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc}).kind
             of tyFloat..tyFloat128, tyString:
               lastSon(n).kind == nkElse
             else:
@@ -466,8 +466,7 @@ proc track(tracked: PEffects, n: PNode) =
         mergeEffects(tracked, effectList.sons[exceptionEffects], n)
         mergeTags(tracked, effectList.sons[tagEffects], n)
     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, mShallowCopy}:
+    if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
       # may not look like an assignment, but it is:
       initVarViaNew(tracked, n.sons[1])
     for i in 0 .. <safeLen(n):
@@ -477,7 +476,6 @@ proc track(tracked: PEffects, n: PNode) =
     if warnProveField in gNotes: checkFieldAccess(tracked.guards, n)
   of nkTryStmt: trackTryStmt(tracked, n)
   of nkPragma: trackPragmaStmt(tracked, n)
-  of nkMacroDef, nkTemplateDef: discard
   of nkAsgn, nkFastAsgn:
     track(tracked, n.sons[1])
     initVar(tracked, n.sons[0])
@@ -527,7 +525,9 @@ proc track(tracked: PEffects, n: PNode) =
       if sfDiscriminant in x.sons[0].sym.flags:
         addDiscriminantFact(tracked.guards, x)
     setLen(tracked.guards, oldFacts)
-  of nkTypeSection: discard
+  of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
+      nkMacroDef, nkTemplateDef:
+    discard
   else:
     for i in 0 .. <safeLen(n): track(tracked, n.sons[i])
 
@@ -549,7 +549,7 @@ proc checkRaisesSpec(spec, real: PNode, msg: string, hints: bool) =
   if hints:
     for s in 0 .. <spec.len:
       if not used.contains(s):
-        Message(spec[s].info, hintXDeclaredButNotUsed, renderTree(spec[s]))
+        message(spec[s].info, hintXDeclaredButNotUsed, renderTree(spec[s]))
 
 proc checkMethodEffects*(disp, branch: PSym) =
   ## checks for consistent effects for multi methods.
@@ -568,42 +568,46 @@ proc checkMethodEffects*(disp, branch: PSym) =
 
 proc setEffectsForProcType*(t: PType, n: PNode) =
   var effects = t.n.sons[0]
-  InternalAssert t.kind == tyProc and effects.kind == nkEffectList
+  internalAssert t.kind == tyProc and effects.kind == nkEffectList
 
   let
     raisesSpec = effectSpec(n, wRaises)
     tagsSpec = effectSpec(n, wTags)
   if not isNil(raisesSpec) or not isNil(tagsSpec):
-    InternalAssert effects.len == 0
+    internalAssert effects.len == 0
     newSeq(effects.sons, effectListLen)
     if not isNil(raisesSpec):
       effects.sons[exceptionEffects] = raisesSpec
     if not isNil(tagsSpec):
       effects.sons[tagEffects] = tagsSpec
 
-proc trackProc*(s: PSym, body: PNode) =
-  var effects = s.typ.n.sons[0]
-  InternalAssert effects.kind == nkEffectList
-  # effects already computed?
-  if sfForward in s.flags: return
-  if effects.len == effectListLen: return
+proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
   newSeq(effects.sons, effectListLen)
-  effects.sons[exceptionEffects] = newNodeI(nkArgList, body.info)
-  effects.sons[tagEffects] = newNodeI(nkArgList, body.info)
+  effects.sons[exceptionEffects] = newNodeI(nkArgList, s.info)
+  effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
   
-  var t: TEffects
   t.exc = effects.sons[exceptionEffects]
   t.tags = effects.sons[tagEffects]
   t.owner = s
   t.init = @[]
   t.guards = @[]
+  
+proc trackProc*(s: PSym, body: PNode) =
+  var effects = s.typ.n.sons[0]
+  internalAssert effects.kind == nkEffectList
+  # effects already computed?
+  if sfForward in s.flags: return
+  if effects.len == effectListLen: return
+  
+  var t: TEffects
+  initEffects(effects, s, t)
   track(t, body)
   
   if not isEmptyType(s.typ.sons[0]) and tfNeedsInit in s.typ.sons[0].flags and
       s.kind in {skProc, skConverter, skMethod}:
     var res = s.ast.sons[resultPos].sym # get result symbol
     if res.id notin t.init:
-      Message(body.info, warnProveInit, "result")
+      message(body.info, warnProveInit, "result")
   let p = s.ast.sons[pragmasPos]
   let raisesSpec = effectSpec(p, wRaises)
   if not isNil(raisesSpec):
@@ -618,4 +622,13 @@ proc trackProc*(s: PSym, body: PNode) =
                     hints=off)
     # after the check, use the formal spec:
     effects.sons[tagEffects] = tagsSpec
-    
\ No newline at end of file
+    
+proc trackTopLevelStmt*(module: PSym; n: PNode) =
+  if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef,
+                nkTypeSection, nkConverterDef, nkMethodDef, nkIteratorDef}:
+    return
+  var effects = newNode(nkEffectList, n.info)
+  var t: TEffects
+  initEffects(effects, module, t)
+
+  track(t, n)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index a1805fdec..2429e4183 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -10,11 +10,8 @@
 ## this module does the semantic checking of statements
 #  included from sem.nim
 
-var EnforceVoidContext = PType(kind: tyStmt)
+var enforceVoidContext = PType(kind: tyStmt)
 
-proc semCommand(c: PContext, n: PNode): PNode =
-  result = semExprNoType(c, n)
-  
 proc semDiscard(c: PContext, n: PNode): PNode = 
   result = n
   checkSonsLen(n, 1)
@@ -58,10 +55,10 @@ proc semWhile(c: PContext, n: PNode): PNode =
   n.sons[1] = semStmt(c, n.sons[1])
   dec(c.p.nestedLoopCounter)
   closeScope(c)
-  if n.sons[1].typ == EnforceVoidContext:
-    result.typ = EnforceVoidContext
+  if n.sons[1].typ == enforceVoidContext:
+    result.typ = enforceVoidContext
 
-proc toCover(t: PType): biggestInt = 
+proc toCover(t: PType): BiggestInt = 
   var t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
   if t2.kind == tyEnum and enumHasHoles(t2): 
     result = sonsLen(t2.n)
@@ -70,14 +67,14 @@ proc toCover(t: PType): biggestInt =
 
 proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
   var smoduleId = getModule(s).id
-  if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
+  if sfProcvar notin s.flags and s.typ.callConv == ccDefault and
       smoduleId != c.module.id and smoduleId != c.friendModule.id: 
-    LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
+    localError(n.info, errXCannotBePassedToProcVar, s.name.s)
 
 proc semProcvarCheck(c: PContext, n: PNode) =
   let n = n.skipConv
-  if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skIterator,
-                                        skConverter}:
+  if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skConverter,
+                                        skIterator, skClosureIterator}:
     performProcvarCheck(c, n, n.sym)
 
 proc semProc(c: PContext, n: PNode): PNode
@@ -86,8 +83,8 @@ include semdestruct
 
 proc semDestructorCheck(c: PContext, n: PNode, flags: TExprFlags) {.inline.} =
   if efAllowDestructor notin flags and n.kind in nkCallKinds+{nkObjConstr}:
-    if instantiateDestructor(c, n.typ):
-      LocalError(n.info, errGenerated,
+    if instantiateDestructor(c, n.typ) != nil:
+      localError(n.info, errGenerated,
         "usage of a type with a destructor in a non destructible context")
   # This still breaks too many things:
   when false:
@@ -117,7 +114,7 @@ const
     nkElse, nkStmtListExpr, nkTryStmt, nkFinally, nkExceptBranch,
     nkElifBranch, nkElifExpr, nkElseExpr, nkBlockStmt, nkBlockExpr}
 
-proc ImplicitlyDiscardable(n: PNode): bool =
+proc implicitlyDiscardable(n: PNode): bool =
   var n = n
   while n.kind in skipForDiscardable: n = n.lastSon
   result = isCallExpr(n) and n.sons[0].kind == nkSym and 
@@ -126,37 +123,36 @@ proc ImplicitlyDiscardable(n: PNode): bool =
 proc fixNilType(n: PNode) =
   if isAtom(n):
     if n.kind != nkNilLit and n.typ != nil:
-      localError(n.info, errDiscardValue)
+      localError(n.info, errDiscardValueX, n.typ.typeToString)
   elif n.kind in {nkStmtList, nkStmtListExpr}:
     n.kind = nkStmtList
     for it in n: fixNilType(it)
   n.typ = nil
 
 proc discardCheck(c: PContext, result: PNode) =
+  if c.inTypeClass > 0: return
   if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
     if result.kind == nkNilLit:
       result.typ = nil
-    elif ImplicitlyDiscardable(result):
+      message(result.info, warnNilStatement)
+    elif implicitlyDiscardable(result):
       var n = result
       result.typ = nil
       while n.kind in skipForDiscardable:
         n = n.lastSon
         n.typ = nil
-    elif c.InTypeClass > 0 and result.typ.kind == tyBool:
-      let verdict = semConstExpr(c, result)
-      if verdict.intVal == 0:
-        localError(result.info, "type class predicate failed.")
     elif result.typ.kind != tyError and gCmd != cmdInteractive:
       if result.typ.kind == tyNil:
         fixNilType(result)
+        message(result.info, warnNilStatement)
       else:
         var n = result
         while n.kind in skipForDiscardable: n = n.lastSon
-        localError(n.info, errDiscardValue)
+        localError(n.info, errDiscardValueX, result.typ.typeToString)
 
 proc semIf(c: PContext, n: PNode): PNode = 
   result = n
-  var typ = CommonTypeBegin
+  var typ = commonTypeBegin
   var hasElse = false
   for i in countup(0, sonsLen(n) - 1): 
     var it = n.sons[i]
@@ -176,7 +172,7 @@ proc semIf(c: PContext, n: PNode): PNode =
     for it in n: discardCheck(c, it.lastSon)
     result.kind = nkIfStmt
     # propagate any enforced VoidContext:
-    if typ == EnforceVoidContext: result.typ = EnforceVoidContext
+    if typ == enforceVoidContext: result.typ = enforceVoidContext
   else:
     for it in n:
       let j = it.len-1
@@ -190,16 +186,16 @@ proc semCase(c: PContext, n: PNode): PNode =
   openScope(c)
   n.sons[0] = semExprWithType(c, n.sons[0])
   var chckCovered = false
-  var covered: biggestint = 0
-  var typ = CommonTypeBegin
+  var covered: BiggestInt = 0
+  var typ = commonTypeBegin
   var hasElse = false
-  case skipTypes(n.sons[0].Typ, abstractVarRange-{tyTypeDesc}).Kind
+  case skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc}).kind
   of tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32:
     chckCovered = true
   of tyFloat..tyFloat128, tyString, tyError:
-    nil
+    discard
   else:
-    LocalError(n.info, errSelectorMustBeOfCertainTypes)
+    localError(n.info, errSelectorMustBeOfCertainTypes)
     return
   for i in countup(1, sonsLen(n) - 1): 
     var x = n.sons[i]
@@ -236,8 +232,8 @@ proc semCase(c: PContext, n: PNode): PNode =
   if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
     for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
     # propagate any enforced VoidContext:
-    if typ == EnforceVoidContext:
-      result.typ = EnforceVoidContext
+    if typ == enforceVoidContext:
+      result.typ = enforceVoidContext
   else:
     for i in 1..n.len-1:
       var it = n.sons[i]
@@ -249,7 +245,7 @@ proc semTry(c: PContext, n: PNode): PNode =
   result = n
   inc c.p.inTryStmt
   checkMinSonsLen(n, 2)
-  var typ = CommonTypeBegin
+  var typ = commonTypeBegin
   n.sons[0] = semExprBranchScope(c, n.sons[0])
   typ = commonType(typ, n.sons[0].typ)
   var check = initIntSet()
@@ -267,10 +263,10 @@ proc semTry(c: PContext, n: PNode): PNode =
         var typ = semTypeNode(c, a.sons[j], nil)
         if typ.kind == tyRef: typ = typ.sons[0]
         if typ.kind != tyObject:
-          LocalError(a.sons[j].info, errExprCannotBeRaised)
+          localError(a.sons[j].info, errExprCannotBeRaised)
         a.sons[j] = newNodeI(nkType, a.sons[j].info)
         a.sons[j].typ = typ
-        if ContainsOrIncl(check, typ.id):
+        if containsOrIncl(check, typ.id):
           localError(a.sons[j].info, errExceptionAlreadyHandled)
     elif a.kind != nkFinally: 
       illFormedAst(n)
@@ -281,8 +277,8 @@ proc semTry(c: PContext, n: PNode): PNode =
   if isEmptyType(typ) or typ.kind == tyNil:
     discardCheck(c, n.sons[0])
     for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
-    if typ == EnforceVoidContext:
-      result.typ = EnforceVoidContext
+    if typ == enforceVoidContext:
+      result.typ = enforceVoidContext
   else:
     n.sons[0] = fitNode(c, typ, n.sons[0])
     for i in 1..n.len-1:
@@ -291,7 +287,7 @@ proc semTry(c: PContext, n: PNode): PNode =
       it.sons[j] = fitNode(c, typ, it.sons[j])
     result.typ = typ
   
-proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode = 
+proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode = 
   result = fitNode(c, typ, n)
   if result.kind in {nkHiddenStdConv, nkHiddenSubConv}: 
     changeType(result.sons[1], typ, check=true)
@@ -302,7 +298,7 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
 proc findShadowedVar(c: PContext, v: PSym): PSym =
   for scope in walkScopes(c.currentScope.parent):
     if scope == c.topLevelScope: break
-    let shadowed = StrTableGet(scope.symbols, v.name)
+    let shadowed = strTableGet(scope.symbols, v.name)
     if shadowed != nil and shadowed.kind in skLocalVars:
       return shadowed
 
@@ -322,18 +318,19 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
 proc checkNilable(v: PSym) =
   if sfGlobal in v.flags and {tfNotNil, tfNeedsInit} * v.typ.flags != {}:
     if v.ast.isNil:
-      Message(v.info, warnProveInit, v.name.s)
+      message(v.info, warnProveInit, v.name.s)
     elif tfNotNil in v.typ.flags and tfNotNil notin v.ast.typ.flags:
-      Message(v.info, warnProveInit, v.name.s)
+      message(v.info, warnProveInit, v.name.s)
 
 proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = 
   var b: PNode
   result = copyNode(n)
+  var hasCompileTime = false
   for i in countup(0, sonsLen(n)-1): 
     var a = n.sons[i]
     if gCmd == cmdIdeTools: suggestStmt(c, a)
     if a.kind == nkCommentStmt: continue 
-    if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: IllFormedAst(a)
+    if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a)
     checkMinSonsLen(a, 3)
     var length = sonsLen(a)
     var typ: PType
@@ -347,15 +344,20 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
       # BUGFIX: ``fitNode`` is needed here!
       # check type compability between def.typ and typ:
       if typ != nil: def = fitNode(c, typ, def)
-      else: typ = skipIntLit(def.typ)
+      else:
+        typ = skipIntLit(def.typ)
+        if typ.kind in {tySequence, tyArray, tySet} and
+           typ.lastSon.kind == tyEmpty:
+          localError(def.info, errCannotInferTypeOfTheLiteral,
+                     ($typ.kind).substr(2).toLower)
     else:
       def = ast.emptyNode
-      if symkind == skLet: LocalError(a.info, errLetNeedsInit)
+      if symkind == skLet: localError(a.info, errLetNeedsInit)
       
     # this can only happen for errornous var statements:
     if typ == nil: continue
     if not typeAllowed(typ, symkind): 
-      LocalError(a.info, errXisNoType, typeToString(typ))
+      localError(a.info, errXisNoType, typeToString(typ))
     var tup = skipTypes(typ, {tyGenericInst})
     if a.kind == nkVarTuple: 
       if tup.kind != tyTuple: 
@@ -370,12 +372,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
         addSon(result, b)
     elif tup.kind == tyTuple and def.kind == nkPar and 
         a.kind == nkIdentDefs and a.len > 3:
-      Message(a.info, warnEachIdentIsTuple)
+      message(a.info, warnEachIdentIsTuple)
     for j in countup(0, length-3):
       var v = semIdentDef(c, a.sons[j], symkind)
       if sfGenSym notin v.flags: addInterfaceDecl(c, v)
       when oKeepVariableNames:
-        if c.InUnrolledContext > 0: v.flags.incl(sfShadowed)
+        if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
         else:
           let shadowed = findShadowedVar(c, v)
           if shadowed != nil:
@@ -383,12 +385,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
             # a shadowed variable is an error unless it appears on the right
             # side of the '=':
             if warnShadowIdent in gNotes and not identWithin(def, v.name):
-              Message(a.info, warnShadowIdent, v.name.s)
+              message(a.info, warnShadowIdent, v.name.s)
       if a.kind != nkVarTuple:
         if def != nil and def.kind != nkEmpty:
           # this is needed for the evaluation pass and for the guard checking:
           v.ast = def
-          if sfThread in v.flags: LocalError(def.info, errThreadvarCannotInit)
+          if sfThread in v.flags: localError(def.info, errThreadvarCannotInit)
         v.typ = typ
         b = newNodeI(nkIdentDefs, a.info)
         if importantComments():
@@ -403,14 +405,16 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
         v.typ = tup.sons[j]
         b.sons[j] = newSymNode(v)
       checkNilable(v)
-    
+      if sfCompileTime in v.flags: hasCompileTime = true
+  if hasCompileTime: vm.setupCompileTimeVar(c.module, result)
+
 proc semConst(c: PContext, n: PNode): PNode = 
   result = copyNode(n)
   for i in countup(0, sonsLen(n) - 1): 
     var a = n.sons[i]
     if gCmd == cmdIdeTools: suggestStmt(c, a)
     if a.kind == nkCommentStmt: continue 
-    if (a.kind != nkConstDef): IllFormedAst(a)
+    if (a.kind != nkConstDef): illFormedAst(a)
     checkSonsLen(a, 3)
     var v = semIdentDef(c, a.sons[0], skConst)
     var typ: PType = nil
@@ -418,16 +422,18 @@ proc semConst(c: PContext, n: PNode): PNode =
 
     var def = semConstExpr(c, a.sons[2])
     if def == nil:
-      LocalError(a.sons[2].info, errConstExprExpected)
+      localError(a.sons[2].info, errConstExprExpected)
       continue
     # check type compatibility between def.typ and typ:
     if typ != nil:
       def = fitRemoveHiddenConv(c, typ, def)
     else:
       typ = def.typ
-    if typ == nil: continue
+    if typ == nil:
+      localError(a.sons[2].info, errConstExprExpected)
+      continue
     if not typeAllowed(typ, skConst):
-      LocalError(a.info, errXisNoType, typeToString(typ))
+      localError(a.info, errXisNoType, typeToString(typ))
       continue
     v.typ = typ
     v.ast = def               # no need to copy
@@ -494,17 +500,17 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
     fc.field = typ.sym
     fc.replaceByFieldName = c.m == mFieldPairs
     openScope(c.c)
-    inc c.c.InUnrolledContext
+    inc c.c.inUnrolledContext
     let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
-    father.add(SemStmt(c.c, body))
-    dec c.c.InUnrolledContext
+    father.add(semStmt(c.c, body))
+    dec c.c.inUnrolledContext
     closeScope(c.c)
-  of nkNilLit: nil
+  of nkNilLit: discard
   of nkRecCase:
     let L = forLoop.len
     let call = forLoop.sons[L-2]
     if call.len > 2:
-      LocalError(forLoop.info, errGenerated, 
+      localError(forLoop.info, errGenerated, 
                  "parallel 'fields' iterator does not work for 'case' objects")
       return
     # iterate over the selector:
@@ -533,9 +539,9 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
   # so that 'break' etc. work as expected, we produce
   # a 'while true: stmt; break' loop ...
   result = newNodeI(nkWhileStmt, n.info, 2)
-  var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
+  var trueSymbol = strTableGet(magicsys.systemModule.tab, getIdent"true")
   if trueSymbol == nil: 
-    LocalError(n.info, errSystemNeeds, "true")
+    localError(n.info, errSystemNeeds, "true")
     trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info)
     trueSymbol.typ = getSysType(tyBool)
 
@@ -546,7 +552,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
   var length = sonsLen(n)
   var call = n.sons[length-2]
   if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
-    LocalError(n.info, errWrongNumberOfVariables)
+    localError(n.info, errWrongNumberOfVariables)
     return result
   
   var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar-{tyTypeDesc})
@@ -555,10 +561,10 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
     return result
   for i in 1..call.len-1:
     var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar-{tyTypeDesc})
-    if not SameType(tupleTypeA, tupleTypeB):
+    if not sameType(tupleTypeA, tupleTypeB):
       typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
   
-  Inc(c.p.nestedLoopCounter)
+  inc(c.p.nestedLoopCounter)
   if tupleTypeA.kind == tyTuple:
     var loopBody = n.sons[length-1]
     for i in 0..sonsLen(tupleTypeA)-1:
@@ -568,16 +574,16 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
       fc.tupleIndex = i
       fc.replaceByFieldName = m == mFieldPairs
       var body = instFieldLoopBody(fc, loopBody, n)
-      inc c.InUnrolledContext
-      stmts.add(SemStmt(c, body))
-      dec c.InUnrolledContext
+      inc c.inUnrolledContext
+      stmts.add(semStmt(c, body))
+      dec c.inUnrolledContext
       closeScope(c)
   else:
     var fc: TFieldsCtx
     fc.m = m
     fc.c = c
     semForObjectFields(fc, tupleTypeA.n, n, stmts)
-  Dec(c.p.nestedLoopCounter)
+  dec(c.p.nestedLoopCounter)
   # for TR macros this 'while true: ...; break' loop is pretty bad, so
   # we avoid it now if we can:
   if hasSonWith(stmts, nkBreakStmt):
@@ -593,7 +599,7 @@ proc addForVarDecl(c: PContext, v: PSym) =
     if shadowed != nil:
       # XXX should we do this here?
       #shadowed.flags.incl(sfShadowed)
-      Message(v.info, warnShadowIdent, v.name.s)
+      message(v.info, warnShadowIdent, v.name.s)
   addDecl(c, v)
 
 proc symForVar(c: PContext, n: PNode): PSym =
@@ -603,7 +609,8 @@ proc symForVar(c: PContext, n: PNode): PSym =
 proc semForVars(c: PContext, n: PNode): PNode =
   result = n
   var length = sonsLen(n)
-  var iter = skipTypes(n.sons[length-2].typ, {tyGenericInst})
+  let iterBase = n.sons[length-2].typ.skipTypes({tyIter})
+  var iter = skipTypes(iterBase, {tyGenericInst})
   # length == 3 means that there is one for loop variable
   # and thus no tuple unpacking:
   if iter.kind != tyTuple or length == 3: 
@@ -613,13 +620,13 @@ proc semForVars(c: PContext, n: PNode): PNode =
       # BUGFIX: don't use `iter` here as that would strip away
       # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
       # for an example:
-      v.typ = n.sons[length-2].typ
+      v.typ = iterBase
       n.sons[0] = newSymNode(v)
       if sfGenSym notin v.flags: addForVarDecl(c, v)
     else:
-      LocalError(n.info, errWrongNumberOfVariables)
+      localError(n.info, errWrongNumberOfVariables)
   elif length-2 != sonsLen(iter):
-    LocalError(n.info, errWrongNumberOfVariables)
+    localError(n.info, errWrongNumberOfVariables)
   else:
     for i in countup(0, length - 3):
       var v = symForVar(c, n.sons[i])
@@ -627,9 +634,9 @@ proc semForVars(c: PContext, n: PNode): PNode =
       v.typ = iter.sons[i]
       n.sons[i] = newSymNode(v)
       if sfGenSym notin v.flags: addForVarDecl(c, v)
-  Inc(c.p.nestedLoopCounter)
-  n.sons[length-1] = SemStmt(c, n.sons[length-1])
-  Dec(c.p.nestedLoopCounter)
+  inc(c.p.nestedLoopCounter)
+  n.sons[length-1] = semStmt(c, n.sons[length-1])
+  dec(c.p.nestedLoopCounter)
 
 proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
   result = newNodeI(nkCall, arg.info)
@@ -647,29 +654,31 @@ proc semFor(c: PContext, n: PNode): PNode =
   openScope(c)
   n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator})
   var call = n.sons[length-2]
-  if call.kind in nkCallKinds and call.sons[0].typ.callConv == ccClosure:
+  let isCallExpr = call.kind in nkCallKinds
+  if isCallExpr and call.sons[0].sym.magic != mNone:
+    if call.sons[0].sym.magic == mOmpParFor:
+      result = semForVars(c, n)
+      result.kind = nkParForStmt
+    else:
+      result = semForFields(c, n, call.sons[0].sym.magic)
+  elif (isCallExpr and call.sons[0].typ.callConv == ccClosure) or
+      call.typ.kind == tyIter:
     # first class iterator:
     result = semForVars(c, n)
-  elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
-      call.sons[0].sym.kind != skIterator: 
+  elif not isCallExpr or call.sons[0].kind != nkSym or
+      call.sons[0].sym.kind notin skIterators:
     if length == 3:
       n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
     elif length == 4:
       n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2])
     else:
-      LocalError(n.sons[length-2].info, errIteratorExpected)
+      localError(n.sons[length-2].info, errIteratorExpected)
     result = semForVars(c, n)
-  elif call.sons[0].sym.magic != mNone:
-    if call.sons[0].sym.magic == mOmpParFor:
-      result = semForVars(c, n)
-      result.kind = nkParForStmt
-    else:
-      result = semForFields(c, n, call.sons[0].sym.magic)
   else:
     result = semForVars(c, n)
   # propagate any enforced VoidContext:
-  if n.sons[length-1].typ == EnforceVoidContext:
-    result.typ = EnforceVoidContext
+  if n.sons[length-1].typ == enforceVoidContext:
+    result.typ = enforceVoidContext
   closeScope(c)
 
 proc semRaise(c: PContext, n: PNode): PNode = 
@@ -695,7 +704,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
     var a = n.sons[i]
     if gCmd == cmdIdeTools: suggestStmt(c, a)
     if a.kind == nkCommentStmt: continue 
-    if a.kind != nkTypeDef: IllFormedAst(a)
+    if a.kind != nkTypeDef: illFormedAst(a)
     checkSonsLen(a, 3)
     var s = semIdentDef(c, a.sons[0], skType)
     s.typ = newTypeS(tyForward, c)
@@ -710,12 +719,12 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
   for i in countup(0, sonsLen(n) - 1): 
     var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
-    if (a.kind != nkTypeDef): IllFormedAst(a)
+    if (a.kind != nkTypeDef): illFormedAst(a)
     checkSonsLen(a, 3)
-    if (a.sons[0].kind != nkSym): IllFormedAst(a)
+    if (a.sons[0].kind != nkSym): illFormedAst(a)
     var s = a.sons[0].sym
     if s.magic == mNone and a.sons[2].kind == nkEmpty: 
-      LocalError(a.info, errImplOfXexpected, s.name.s)
+      localError(a.info, errImplOfXexpected, s.name.s)
     if s.magic != mNone: processMagicType(c, s)
     if a.sons[1].kind != nkEmpty: 
       # We have a generic type declaration here. In generic types,
@@ -736,19 +745,15 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       # we fill it out later. For magic generics like 'seq', it won't be filled
       # so we use tyEmpty instead of nil to not crash for strange conversions
       # like: mydata.seq
-      rawAddSon(s.typ, newTypeS(tyEmpty, c))
+      rawAddSon(s.typ, newTypeS(tyNone, c))
       s.ast = a
-      when oUseLateInstantiation:
-        var body: PType = nil
-        s.typScope = c.currentScope.parent
-      else:
-        inc c.InGenericContext
-        var body = semTypeNode(c, a.sons[2], nil)
-        dec c.InGenericContext
-        if body != nil:
-          body.sym = s
-          body.size = -1 # could not be computed properly
-      s.typ.sons[sonsLen(s.typ) - 1] = body
+      inc c.inGenericContext
+      var body = semTypeNode(c, a.sons[2], nil)
+      dec c.inGenericContext
+      if body != nil:
+        body.sym = s
+        body.size = -1 # could not be computed properly
+        s.typ.sons[sonsLen(s.typ) - 1] = body
       popOwner()
       closeScope(c)
     elif a.sons[2].kind != nkEmpty: 
@@ -764,11 +769,34 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       s.ast = a
       popOwner()
 
+proc checkForMetaFields(n: PNode) =
+  template checkMeta(t) =
+    if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
+      localError(n.info, errTIsNotAConcreteType, t.typeToString)
+  
+  case n.kind
+  of nkRecList, nkRecCase:
+    for s in n: checkForMetaFields(s)
+  of nkOfBranch, nkElse:
+    checkForMetaFields(n.lastSon)
+  of nkSym:
+    let t = n.sym.typ
+    case t.kind
+    of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyPtr, tyRef,
+       tyProc, tyGenericInvokation, tyGenericInst:
+      let start = ord(t.kind in {tyGenericInvokation, tyGenericInst})
+      for i in start .. <t.sons.len:
+        checkMeta(t.sons[i])
+    else:
+      checkMeta(t)
+  else:
+    internalAssert false
+
 proc typeSectionFinalPass(c: PContext, n: PNode) = 
   for i in countup(0, sonsLen(n) - 1): 
     var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
-    if a.sons[0].kind != nkSym: IllFormedAst(a)
+    if a.sons[0].kind != nkSym: illFormedAst(a)
     var s = a.sons[0].sym
     # compute the type's size and check for illegal recursions:
     if a.sons[1].kind == nkEmpty: 
@@ -780,18 +808,20 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
           assignType(s.typ, t)
           s.typ.id = t.id     # same id
       checkConstructedType(s.info, s.typ)
+      if s.typ.kind in {tyObject, tyTuple}:
+        checkForMetaFields(s.typ.n)
     let aa = a.sons[2]
     if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
        aa.sons[0].kind == nkObjectTy:
       # give anonymous object a dummy symbol:
       var st = s.typ
       if st.kind == tyGenericBody: st = st.lastSon
-      InternalAssert st.kind in {tyPtr, tyRef}
-      InternalAssert st.sons[0].sym == nil
-      st.sons[0].sym = newSym(skType, getIdent(s.name.s & ":ObjectType"),
+      internalAssert st.kind in {tyPtr, tyRef}
+      internalAssert st.lastSon.sym == nil
+      st.lastSon.sym = newSym(skType, getIdent(s.name.s & ":ObjectType"),
                               getCurrOwner(), s.info)
 
-proc SemTypeSection(c: PContext, n: PNode): PNode =
+proc semTypeSection(c: PContext, n: PNode): PNode =
   typeSectionLeftSidePass(c, n)
   typeSectionRightSidePass(c, n)
   typeSectionFinalPass(c, n)
@@ -810,12 +840,12 @@ proc addParams(c: PContext, n: PNode, kind: TSymKind) =
 
 proc semBorrow(c: PContext, n: PNode, s: PSym) = 
   # search for the correct alias:
-  var b = SearchForBorrowProc(c, c.currentScope.parent, s)
+  var b = searchForBorrowProc(c, c.currentScope.parent, s)
   if b != nil: 
     # store the alias:
     n.sons[bodyPos] = newSymNode(b)
   else:
-    LocalError(n.info, errNoSymbolToBorrowFromFound) 
+    localError(n.info, errNoSymbolToBorrowFromFound) 
   
 proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) = 
   if t != nil: 
@@ -853,7 +883,7 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
           prc.sons[namePos] = newIdentNode(idDelegator, prc.info)
           prc.sons[pragmasPos] = copyExcept(n, i)
         else:
-          LocalError(prc.info, errOnlyACallOpCanBeDelegator)
+          localError(prc.info, errOnlyACallOpCanBeDelegator)
       continue
     # we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
     # let the semantic checker deal with it:
@@ -868,6 +898,8 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
     return semStmt(c, x)
 
 proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
+  # XXX semProcAux should be good enough for this now, we will eventually
+  # remove semLambda
   result = semProcAnnotation(c, n)
   if result != nil: return result
   result = n
@@ -881,12 +913,19 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
     s = n[namePos].sym
   pushOwner(s)
   openScope(c)
-  if n.sons[genericParamsPos].kind != nkEmpty:
-    illFormedAst(n)           # process parameters:
+  var gp: PNode
+  if n.sons[genericParamsPos].kind != nkEmpty: 
+    n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
+    gp = n.sons[genericParamsPos]
+  else:
+    gp = newNodeI(nkGenericParams, n.info)
+
   if n.sons[paramsPos].kind != nkEmpty:
-    var gp = newNodeI(nkGenericParams, n.info)
-    semParamList(c, n.sons[ParamsPos], gp, s)
-    ParamsTypeCheck(c, s.typ)
+    semParamList(c, n.sons[paramsPos], gp, s)
+    # paramsTypeCheck(c, s.typ)
+    if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
+      # we have a list of implicit type parameters:
+      n.sons[genericParamsPos] = gp
   else:
     s.typ = newTypeS(tyProc, c)
     rawAddSon(s.typ, nil)
@@ -895,22 +934,53 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
   s.options = gOptions
   if n.sons[bodyPos].kind != nkEmpty:
     if sfImportc in s.flags:
-      LocalError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
+      localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
     #if efDetermineType notin flags:
     # XXX not good enough; see tnamedparamanonproc.nim
-    pushProcCon(c, s)
-    addResult(c, s.typ.sons[0], n.info, skProc)
-    let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
-    n.sons[bodyPos] = transformBody(c.module, semBody, s)
-    addResultNode(c, n)
-    popProcCon(c)
+    if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags):
+      pushProcCon(c, s)
+      addResult(c, s.typ.sons[0], n.info, skProc)
+      let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
+      n.sons[bodyPos] = transformBody(c.module, semBody, s)
+      addResultNode(c, n)
+      popProcCon(c)
+    elif efOperand notin flags:
+      localError(n.info, errGenericLambdaNotAllowed)
     sideEffectsCheck(c, s)
   else:
-    LocalError(n.info, errImplOfXexpected, s.name.s)
+    localError(n.info, errImplOfXexpected, s.name.s)
   closeScope(c)           # close scope for parameters
   popOwner()
   result.typ = s.typ
 
+proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
+  var n = n
+  
+  n = replaceTypesInBody(c, pt, n)
+  result = n
+  
+  n.sons[genericParamsPos] = emptyNode
+  n.sons[paramsPos] = n.typ.n
+  
+  openScope(c)
+  var s = n.sons[namePos].sym
+  addParams(c, n.typ.n, skProc)
+  pushProcCon(c, s)
+  addResult(c, n.typ.sons[0], n.info, skProc)
+  let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
+  n.sons[bodyPos] = transformBody(c.module, semBody, n.sons[namePos].sym)
+  addResultNode(c, n)
+  popProcCon(c)
+  closeScope(c)
+  
+  s.ast = result
+
+  # alternative variant (not quite working):
+  # var prc = arg[0].sym
+  # let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
+  # result = inferred.ast
+  # result.kind = arg.kind
+
 proc activate(c: PContext, n: PNode) =
   # XXX: This proc is part of my plan for getting rid of
   # forward declarations. stay tuned.
@@ -922,11 +992,10 @@ proc activate(c: PContext, n: PNode) =
     of nkCallKinds:
       for i in 1 .. <n.len: activate(c, n[i])
     else:
-      nil
+      discard
 
 proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
-  if s.typ.sons[0] != nil and
-      (s.kind != skIterator or s.typ.callConv == ccClosure):
+  if s.typ.sons[0] != nil and s.kind != skIterator:
     addResult(c, s.typ.sons[0], n.info, s.kind)
     addResultNode(c, n)
 
@@ -937,7 +1006,7 @@ type
     stepCompileBody
 
 proc isForwardDecl(s: PSym): bool =
-  InternalAssert s.kind == skProc
+  internalAssert s.kind == skProc
   result = s.ast[bodyPos].kind != nkEmpty
 
 proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
@@ -949,9 +1018,15 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   checkSonsLen(n, bodyPos + 1)
   var s: PSym
   var typeIsDetermined = false
+  var isAnon = false
   if n[namePos].kind != nkSym:
     assert phase == stepRegisterSymbol
-    s = semIdentDef(c, n.sons[0], kind)
+
+    if n[namePos].kind == nkEmpty:
+      s = newSym(kind, idAnon, getCurrOwner(), n.info)
+      isAnon = true
+    else:
+      s = semIdentDef(c, n.sons[0], kind)
     n.sons[namePos] = newSymNode(s)
     s.ast = n
     s.scope = c.currentScope
@@ -963,7 +1038,11 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
       return
   else:
     s = n[namePos].sym
+    s.owner = getCurrOwner()
     typeIsDetermined = s.typ == nil
+    s.ast = n
+    s.scope = c.currentScope
+
     # if typeIsDetermined: assert phase == stepCompileBody
     # else: assert phase == stepDetermineType
   # before compiling the proc body, set as current the scope
@@ -980,7 +1059,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     gp = newNodeI(nkGenericParams, n.info)
   # process parameters:
   if n.sons[paramsPos].kind != nkEmpty:
-    semParamList(c, n.sons[ParamsPos], gp, s)
+    semParamList(c, n.sons[paramsPos], gp, s)
     if sonsLen(gp) > 0: 
       if n.sons[genericParamsPos].kind == nkEmpty:
         # we have a list of implicit type parameters:
@@ -992,13 +1071,15 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     rawAddSon(s.typ, nil)
   if n.sons[patternPos].kind != nkEmpty:
     n.sons[patternPos] = semPattern(c, n.sons[patternPos])
-  if s.kind == skIterator: s.typ.flags.incl(tfIterator)
+  if s.kind in skIterators:
+    s.typ.flags.incl(tfIterator)
   
-  var proto = SearchForProc(c, s.scope, s)
-  if proto == nil: 
-    s.typ.callConv = lastOptionEntry(c).defaultCC
+  var proto = searchForProc(c, s.scope, s)
+  if proto == nil:
+    if s.kind == skClosureIterator: s.typ.callConv = ccClosure
+    else: s.typ.callConv = lastOptionEntry(c).defaultCC
     # add it here, so that recursive procs are possible:
-    if sfGenSym in s.flags: nil
+    if sfGenSym in s.flags: discard
     elif kind in OverloadableSyms:
       if not typeIsDetermined:
         addInterfaceOverloadableSymAt(c, s.scope, s)
@@ -1008,12 +1089,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     if n.sons[pragmasPos].kind != nkEmpty:
       pragma(c, s, n.sons[pragmasPos], validPragmas)
     else:
-      implictPragmas(c, s, n, validPragmas)
+      implicitPragmas(c, s, n, validPragmas)
   else: 
     if n.sons[pragmasPos].kind != nkEmpty: 
-      LocalError(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
+      localError(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
     if sfForward notin proto.flags: 
-      WrongRedefinition(n.info, proto.name.s)
+      wrongRedefinition(n.info, proto.name.s)
     excl(proto.flags, sfForward)
     closeScope(c)         # close scope with wrong parameter symbols
     openScope(c)          # open scope for old (correct) parameter symbols
@@ -1026,7 +1107,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     n.sons[genericParamsPos] = proto.ast.sons[genericParamsPos]
     n.sons[paramsPos] = proto.ast.sons[paramsPos]
     n.sons[pragmasPos] = proto.ast.sons[pragmasPos]
-    if n.sons[namePos].kind != nkSym: InternalError(n.info, "semProcAux")
+    if n.sons[namePos].kind != nkSym: internalError(n.info, "semProcAux")
     n.sons[namePos].sym = proto
     if importantComments() and not isNil(proto.ast.comment):
       n.comment = proto.ast.comment
@@ -1035,12 +1116,16 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     pushOwner(s)
   s.options = gOptions
   if sfDestructor in s.flags: doDestructorStuff(c, s, n)
-  if n.sons[bodyPos].kind != nkEmpty: 
+  if n.sons[bodyPos].kind != nkEmpty:
     # for DLL generation it is annoying to check for sfImportc!
-    if sfBorrow in s.flags: 
-      LocalError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
-    if n.sons[genericParamsPos].kind == nkEmpty: 
-      ParamsTypeCheck(c, s.typ)
+    if sfBorrow in s.flags:
+      localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
+    let usePseudoGenerics = kind in {skMacro, skTemplate}
+    # Macros and Templates can have generic parameters, but they are
+    # only used for overload resolution (there is no instantiation of
+    # the symbol, so we must process the body now)
+    if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
+      if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
       pushProcCon(c, s)
       maybeAddResult(c, s, n)
       if sfImportc notin s.flags:
@@ -1050,17 +1135,17 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
         # context as it may even be evaluated in 'system.compiles':
         n.sons[bodyPos] = transformBody(c.module, semBody, s)
       popProcCon(c)
-    else: 
-      if s.typ.sons[0] != nil and kind != skIterator:
+    else:
+      if s.typ.sons[0] != nil and kind notin skIterators:
         addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
       var toBind = initIntSet()
       n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind)
       fixupInstantiatedSymbols(c, s)
-    if sfImportc in s.flags: 
+    if sfImportc in s.flags:
       # so we just ignore the body after semantic checking for importc:
       n.sons[bodyPos] = ast.emptyNode
   else:
-    if proto != nil: LocalError(n.info, errImplOfXexpected, proto.name.s)
+    if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s)
     if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone: 
       incl(s.flags, sfForward)
     elif sfBorrow in s.flags: semBorrow(c, n, s)
@@ -1070,6 +1155,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   popOwner()
   if n.sons[patternPos].kind != nkEmpty:
     c.patterns.add(s)
+  if isAnon: result.typ = s.typ
 
 proc determineType(c: PContext, s: PSym) =
   if s.typ != nil: return
@@ -1077,11 +1163,19 @@ proc determineType(c: PContext, s: PSym) =
   discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
 
 proc semIterator(c: PContext, n: PNode): PNode =
-  result = semProcAux(c, n, skIterator, iteratorPragmas)
+  let kind = if hasPragma(n[pragmasPos], wClosure) or
+                n[namePos].kind == nkEmpty: skClosureIterator
+             else: skIterator
+  # gensym'ed iterator?
+  if n[namePos].kind == nkSym:
+    # gensym'ed iterators might need to become closure iterators:
+    n[namePos].sym.owner = getCurrOwner()
+    n[namePos].sym.kind = kind
+  result = semProcAux(c, n, kind, iteratorPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
   if t.sons[0] == nil and s.typ.callConv != ccClosure:
-    LocalError(n.info, errXNeedsReturnType, "iterator")
+    localError(n.info, errXNeedsReturnType, "iterator")
   # iterators are either 'inline' or 'closure'; for backwards compatibility,
   # we require first class iterators to be marked with 'closure' explicitly
   # -- at least for 0.9.2.
@@ -1095,7 +1189,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
       # and they always at least use the 'env' for the state field:
       incl(s.typ.flags, tfCapturesEnv)
   if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone:
-    LocalError(n.info, errImplOfXexpected, s.name.s)
+    localError(n.info, errImplOfXexpected, s.name.s)
   
 proc semProc(c: PContext, n: PNode): PNode = 
   result = semProcAux(c, n, skProc, procPragmas)
@@ -1146,11 +1240,11 @@ proc evalInclude(c: PContext, n: PNode): PNode =
   for i in countup(0, sonsLen(n) - 1): 
     var f = checkModuleName(n.sons[i])
     if f != InvalidFileIDX:
-      if ContainsOrIncl(c.includedFiles, f): 
-        LocalError(n.info, errRecursiveDependencyX, f.toFilename)
+      if containsOrIncl(c.includedFiles, f): 
+        localError(n.info, errRecursiveDependencyX, f.toFilename)
       else:
         addSon(result, semStmt(c, gIncludeFile(c.module, f)))
-        Excl(c.includedFiles, f)
+        excl(c.includedFiles, f)
   
 proc setLine(n: PNode, info: TLineInfo) =
   for i in 0 .. <safeLen(n): setLine(n.sons[i], info)
@@ -1159,20 +1253,25 @@ proc setLine(n: PNode, info: TLineInfo) =
 proc semPragmaBlock(c: PContext, n: PNode): PNode =
   let pragmaList = n.sons[0]
   pragma(c, nil, pragmaList, exprPragmas)
-  result = semStmt(c, n.sons[1])
+  result = semExpr(c, n.sons[1])
   for i in 0 .. <pragmaList.len:
     if whichPragma(pragmaList.sons[i]) == wLine:
       setLine(result, pragmaList.sons[i].info)
 
 proc semStaticStmt(c: PContext, n: PNode): PNode =
   let a = semStmt(c, n.sons[0])
-  result = evalStaticExpr(c, c.module, a, c.p.owner)
-  if result.isNil:
-    LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
-    result = emptyNode
-  elif result.kind == nkEmpty:
-    result = newNodeI(nkDiscardStmt, n.info, 1)
-    result.sons[0] = emptyNode
+  n.sons[0] = a
+  evalStaticStmt(c.module, a, c.p.owner)
+  result = newNodeI(nkDiscardStmt, n.info, 1)
+  result.sons[0] = emptyNode
+  when false:
+    result = evalStaticStmt(c.module, a, c.p.owner)
+    if result.isNil:
+      LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
+      result = emptyNode
+    elif result.kind == nkEmpty:
+      result = newNodeI(nkDiscardStmt, n.info, 1)
+      result.sons[0] = emptyNode
 
 proc usesResult(n: PNode): bool =
   # nkStmtList(expr) properly propagates the void context,
@@ -1186,7 +1285,7 @@ proc usesResult(n: PNode): bool =
       for c in n:
         if usesResult(c): return true
 
-proc semStmtList(c: PContext, n: PNode): PNode =
+proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # these must be last statements in a block:
   const
     LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
@@ -1224,30 +1323,36 @@ proc semStmtList(c: PContext, n: PNode): PNode =
       return
     else:
       n.sons[i] = semExpr(c, n.sons[i])
-      if n.sons[i].typ == EnforceVoidContext or usesResult(n.sons[i]):
+      if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool:
+        let verdict = semConstExpr(c, n[i])
+        if verdict.intVal == 0:
+          localError(result.info, "type class predicate failed")
+      if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
         voidContext = true
-        n.typ = EnforceVoidContext
-      if i != last or voidContext:
+        n.typ = enforceVoidContext
+      if i == last and (length == 1 or efWantValue in flags):
+        n.typ = n.sons[i].typ
+        if not isEmptyType(n.typ): n.kind = nkStmtListExpr
+      elif i != last or voidContext:
         discardCheck(c, n.sons[i])
       else:
         n.typ = n.sons[i].typ
-        if not isEmptyType(n.typ):
-          n.kind = nkStmtListExpr
+        if not isEmptyType(n.typ): n.kind = nkStmtListExpr
       case n.sons[i].kind
       of nkVarSection, nkLetSection:
         let (outer, inner) = insertDestructors(c, n.sons[i])
         if outer != nil:
           n.sons[i] = outer
-          for j in countup(i+1, length-1):
-            inner.addSon(SemStmt(c, n.sons[j]))
+          var rest = newNode(nkStmtList, n.info, n.sons[i+1 .. length-1])
+          inner.addSon(semStmtList(c, rest, flags))
           n.sons.setLen(i+1)
           return
       of LastBlockStmts: 
         for j in countup(i + 1, length - 1): 
           case n.sons[j].kind
-          of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil
+          of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: discard
           else: localError(n.sons[j].info, errStmtInvalidAfterReturn)
-      else: nil
+      else: discard
   if result.len == 1:
     result = result.sons[0]
   when false:
@@ -1260,7 +1365,7 @@ proc semStmtList(c: PContext, n: PNode): PNode =
         #  "Last expression must be explicitly returned if it " &
         #  "is discardable or discarded")
 
-proc SemStmt(c: PContext, n: PNode): PNode = 
+proc semStmt(c: PContext, n: PNode): PNode = 
   # now: simply an alias:
   result = semExprNoType(c, n)
 
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 68abc9aa6..ad34eea65 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -14,7 +14,7 @@ discard """
   
     template `||` (a, b: expr): expr =
       let aa = a
-      (if aa: aa else: b)
+      if aa: aa else: b
     
     var
       a, b: T
@@ -36,9 +36,9 @@ proc symBinding(n: PNode): TSymBinding =
     var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
     if key.kind == nkIdent:
       case whichKeyword(key.ident)
-      of wGenSym: return spGenSym
+      of wGensym: return spGenSym
       of wInject: return spInject
-      else: nil
+      else: discard
 
 type
   TSymChoiceRule = enum
@@ -79,7 +79,7 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
     # the same symbol!
     # This is however not true anymore for hygienic templates as semantic
     # processing for them changes the symbol table...
-    let s = QualifiedLookUp(c, a)
+    let s = qualifiedLookUp(c, a)
     if s != nil:
       # we need to mark all symbols:
       let sc = symChoice(c, n, s, scClosed)
@@ -106,7 +106,7 @@ proc replaceIdentBySym(n: var PNode, s: PNode) =
 type
   TemplCtx {.pure, final.} = object
     c: PContext
-    toBind, toMixin: TIntSet
+    toBind, toMixin, toInject: TIntSet
     owner: PSym
 
 proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
@@ -115,7 +115,7 @@ proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
   of nkPragmaExpr: result = getIdentNode(c, n.sons[0])
   of nkIdent:
     result = n
-    let s = QualifiedLookUp(c.c, n, {})
+    let s = qualifiedLookUp(c.c, n, {})
     if s != nil:
       if s.owner == c.owner and s.kind == skParam:
         result = newSymNode(s, n.info)
@@ -138,6 +138,18 @@ proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
   result = semTemplBody(c, n)
   closeScope(c)
 
+proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
+  result = n
+  if n.kind == nkIdent:
+    let s = qualifiedLookUp(c.c, n, {})
+    if s != nil:
+      if s.owner == c.owner and s.kind == skParam:
+        incl(s.flags, sfUsed)
+        result = newSymNode(s, n.info)
+  else:
+    for i in 0 .. <n.safeLen:
+      result.sons[i] = onlyReplaceParams(c, n.sons[i])
+
 proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
   result = newSym(kind, considerAcc(n), c.owner, n.info)
   incl(result.flags, sfGenSym)
@@ -145,7 +157,28 @@ proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
 
 proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
   # locals default to 'gensym':
-  if n.kind != nkPragmaExpr or symBinding(n.sons[1]) != spInject:
+  if n.kind == nkPragmaExpr and symBinding(n.sons[1]) == spInject:
+    # even if injected, don't produce a sym choice here:
+    #n = semTemplBody(c, n)
+    var x = n[0]
+    while true:
+      case x.kind
+      of nkPostfix: x = x[1]
+      of nkPragmaExpr: x = x[0]
+      of nkIdent: break
+      of nkAccQuoted:
+        # consider:  type `T TemplParam` {.inject.}
+        # it suffices to return to treat it like 'inject':
+        n = onlyReplaceParams(c, n)
+        return
+      else:
+        illFormedAst(x)
+    let ident = getIdentNode(c, x)
+    if not isTemplParam(c, ident):
+      c.toInject.incl(x.ident.id)
+    else:
+      replaceIdentBySym(n, ident)
+  else:
     let ident = getIdentNode(c, n)
     if not isTemplParam(c, ident):
       let local = newGenSym(k, ident, c)
@@ -153,8 +186,37 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
       replaceIdentBySym(n, newSymNode(local, n.info))
     else:
       replaceIdentBySym(n, ident)
+
+proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode = 
+  incl(s.flags, sfUsed)
+  case s.kind
+  of skUnknown: 
+    # Introduced in this pass! Leave it as an identifier.
+    result = n
+  of OverloadableSyms:
+    result = symChoice(c, n, s, scOpen)
+  of skGenericParam: 
+    result = newSymNodeTypeDesc(s, n.info)
+  of skParam: 
+    result = n
+  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)
+
+proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
+  result = n
+  if n.kind == nkIdent:
+    let s = qualifiedLookUp(c.c, n, {})
+    if s != nil:
+      if s.owner == c.owner and (s.kind == skParam or sfGenSym in s.flags):
+        incl(s.flags, sfUsed)
+        result = newSymNode(s, n.info)
   else:
-    n = semTemplBody(c, n)
+    for i in countup(0, safeLen(n) - 1):
+      result.sons[i] = semRoutineInTemplName(c, n.sons[i])
 
 proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
   result = n
@@ -170,17 +232,17 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
     else:
       n.sons[namePos] = ident
   else:
-    n.sons[namePos] = semTemplBody(c, n.sons[namePos])
+    n.sons[namePos] = semRoutineInTemplName(c, n.sons[namePos])
   openScope(c)
   for i in patternPos..bodyPos:
     n.sons[i] = semTemplBody(c, n.sons[i])
   closeScope(c)
 
 proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind) =
-  for i in countup(ord(symkind == skConditional), sonsLen(n) - 1):
+  for i in countup(0, sonsLen(n) - 1):
     var a = n.sons[i]
     if a.kind == nkCommentStmt: continue
-    if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
+    if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a)
     checkMinSonsLen(a, 3)
     var L = sonsLen(a)
     a.sons[L-2] = semTemplBody(c, a.sons[L-2])
@@ -193,18 +255,23 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   result = n
   case n.kind
   of nkIdent:
-    let s = QualifiedLookUp(c.c, n, {})
+    if n.ident.id in c.toInject: return n
+    let s = qualifiedLookUp(c.c, n, {})
     if s != nil:
       if s.owner == c.owner and s.kind == skParam:
         incl(s.flags, sfUsed)
         result = newSymNode(s, n.info)
-      elif Contains(c.toBind, s.id):
+      elif contains(c.toBind, s.id):
         result = symChoice(c.c, n, s, scClosed)
+      elif contains(c.toMixin, s.name.id):
+        result = symChoice(c.c, n, s, scForceOpen)
       elif s.owner == c.owner and sfGenSym in s.flags:
         # template tmp[T](x: var seq[T]) =
         # var yz: T
         incl(s.flags, sfUsed)
         result = newSymNode(s, n.info)
+      else:
+        result = semTemplSymbol(c.c, n, s)
   of nkBind:
     result = semTemplBody(c, n.sons[0])
   of nkBindStmt:
@@ -212,7 +279,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   of nkMixinStmt:
     result = semMixinStmt(c.c, n, c.toMixin)
   of nkEmpty, nkSym..nkNilLit:
-    nil
+    discard
   of nkIfStmt:
     for i in countup(0, sonsLen(n)-1):
       var it = n.sons[i]
@@ -274,7 +341,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if (a.kind != nkConstDef): IllFormedAst(a)
+      if (a.kind != nkConstDef): illFormedAst(a)
       checkSonsLen(a, 3)
       addLocalDecl(c, a.sons[0], skConst)
       a.sons[1] = semTemplBody(c, a.sons[1])
@@ -283,13 +350,13 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if (a.kind != nkTypeDef): IllFormedAst(a)
+      if (a.kind != nkTypeDef): illFormedAst(a)
       checkSonsLen(a, 3)
       addLocalDecl(c, a.sons[0], skType)
     for i in countup(0, sonsLen(n) - 1):
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
-      if (a.kind != nkTypeDef): IllFormedAst(a)
+      if (a.kind != nkTypeDef): illFormedAst(a)
       checkSonsLen(a, 3)
       if a.sons[1].kind != nkEmpty: 
         openScope(c)
@@ -303,21 +370,33 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   of nkMethodDef:
     result = semRoutineInTemplBody(c, n, skMethod)
   of nkIteratorDef:
-    result = semRoutineInTemplBody(c, n, skIterator)
+    let kind = if hasPragma(n[pragmasPos], wClosure): skClosureIterator
+               else: skIterator
+    result = semRoutineInTemplBody(c, n, kind)
   of nkTemplateDef:
     result = semRoutineInTemplBody(c, n, skTemplate)
   of nkMacroDef:
     result = semRoutineInTemplBody(c, n, skMacro)
   of nkConverterDef:
     result = semRoutineInTemplBody(c, n, skConverter)
+  of nkPragmaExpr:
+    result.sons[0] = semTemplBody(c, n.sons[0])
+  of nkPostfix:
+    result.sons[1] = semTemplBody(c, n.sons[1])
+  of nkPragma:
+    result = onlyReplaceParams(c, n)
   else:
-    # dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam',
+    # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
     # so we use the generic code for nkDotExpr too
     if n.kind == nkDotExpr or n.kind == nkAccQuoted:
-      let s = QualifiedLookUp(c.c, n, {})
+      let s = qualifiedLookUp(c.c, n, {})
       if s != nil:
-        if Contains(c.toBind, s.id):
+        if contains(c.toBind, s.id):
           return symChoice(c.c, n, s, scClosed)
+        elif contains(c.toMixin, s.name.id):
+          return symChoice(c.c, n, s, scForceOpen)
+        else:
+          return symChoice(c.c, n, s, scOpen)
     result = n
     for i in countup(0, sonsLen(n) - 1):
       result.sons[i] = semTemplBody(c, n.sons[i])
@@ -326,24 +405,24 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
   result = n
   case n.kind
   of nkIdent:
-    let s = QualifiedLookUp(c.c, n, {})
+    let s = qualifiedLookUp(c.c, n, {})
     if s != nil:
       if s.owner == c.owner and s.kind == skParam:
         result = newSymNode(s, n.info)
-      elif Contains(c.toBind, s.id):
+      elif contains(c.toBind, s.id):
         result = symChoice(c.c, n, s, scClosed)
   of nkBind:
     result = semTemplBodyDirty(c, n.sons[0])
   of nkBindStmt:
     result = semBindStmt(c.c, n, c.toBind)
   of nkEmpty, nkSym..nkNilLit:
-    nil
+    discard
   else:
     # dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam',
     # so we use the generic code for nkDotExpr too
     if n.kind == nkDotExpr or n.kind == nkAccQuoted:
-      let s = QualifiedLookUp(c.c, n, {})
-      if s != nil and Contains(c.toBind, s.id):
+      let s = qualifiedLookUp(c.c, n, {})
+      if s != nil and contains(c.toBind, s.id):
         return symChoice(c.c, n, s, scClosed)
     result = n
     for i in countup(0, sonsLen(n) - 1):
@@ -358,7 +437,7 @@ proc transformToExpr(n: PNode): PNode =
     for i in countup(0, sonsLen(n) - 1): 
       case n.sons[i].kind
       of nkCommentStmt, nkEmpty, nkNilLit: 
-        nil
+        discard
       else: 
         if realStmt == - 1: realStmt = i
         else: realStmt = - 2
@@ -368,7 +447,7 @@ proc transformToExpr(n: PNode): PNode =
     n.kind = nkBlockExpr
     #nkIfStmt: n.kind = nkIfExpr // this is not correct!
   else:
-    nil
+    discard
 
 proc semTemplateDef(c: PContext, n: PNode): PNode = 
   var s: PSym
@@ -378,6 +457,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   else:
     s = semIdentVis(c, skTemplate, n.sons[0], {})
   # check parameter list:
+  s.scope = c.currentScope
   pushOwner(s)
   openScope(c)
   n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
@@ -392,7 +472,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
     gp = newNodeI(nkGenericParams, n.info)
   # process parameters:
   if n.sons[paramsPos].kind != nkEmpty:
-    semParamList(c, n.sons[ParamsPos], gp, s)
+    semParamList(c, n.sons[paramsPos], gp, s)
     if sonsLen(gp) > 0:
       if n.sons[genericParamsPos].kind == nkEmpty:
         # we have a list of implicit type parameters:
@@ -413,6 +493,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   var ctx: TemplCtx
   ctx.toBind = initIntSet()
   ctx.toMixin = initIntSet()
+  ctx.toInject = initIntSet()
   ctx.c = c
   ctx.owner = s
   if sfDirty in s.flags:
@@ -427,12 +508,12 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   s.ast = n
   result = n
   if n.sons[bodyPos].kind == nkEmpty: 
-    LocalError(n.info, errImplOfXexpected, s.name.s)
-  var proto = SearchForProc(c, c.currentScope, s)
+    localError(n.info, errImplOfXexpected, s.name.s)
+  var proto = searchForProc(c, c.currentScope, s)
   if proto == nil:
     addInterfaceOverloadableSymAt(c, c.currentScope, s)
   else:
-    SymTabReplace(c.currentScope.symbols, proto, s)
+    symTabReplace(c.currentScope.symbols, proto, s)
   if n.sons[patternPos].kind != nkEmpty:
     c.patterns.add(s)
 
@@ -455,17 +536,17 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
     if s != nil:
       if s.owner == c.owner and s.kind == skParam:
         result = newParam(c, n, s)
-      elif Contains(c.toBind, s.id):
+      elif contains(c.toBind, s.id):
         result = symChoice(c.c, n, s, scClosed)
       elif templToExpand(s):
-        result = semPatternBody(c, semTemplateExpr(c.c, n, s, false))
+        result = semPatternBody(c, semTemplateExpr(c.c, n, s, {efNoSemCheck}))
       else:
-        nil
+        discard
         # we keep the ident unbound for matching instantiated symbols and
         # more flexibility
   
   proc expectParam(c: var TemplCtx, n: PNode): PNode =
-    let s = QualifiedLookUp(c.c, n, {})
+    let s = qualifiedLookUp(c.c, n, {})
     if s != nil and s.owner == c.owner and s.kind == skParam:
       result = newParam(c, n, s)
     else:
@@ -475,11 +556,11 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
   result = n
   case n.kind
   of nkIdent:
-    let s = QualifiedLookUp(c.c, n, {})
+    let s = qualifiedLookUp(c.c, n, {})
     result = handleSym(c, n, s)
   of nkBindStmt:
     result = semBindStmt(c.c, n, c.toBind)
-  of nkEmpty, nkSym..nkNilLit: nil
+  of nkEmpty, nkSym..nkNilLit: discard
   of nkCurlyExpr:
     # we support '(pattern){x}' to bind a subpattern to a parameter 'x'; 
     # '(pattern){|x}' does the same but the matches will be gathered in 'x'
@@ -498,12 +579,12 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
     else:
       localError(n.info, errInvalidExpression)
   of nkCallKinds:
-    let s = QualifiedLookUp(c.c, n.sons[0], {})
+    let s = qualifiedLookUp(c.c, n.sons[0], {})
     if s != nil:
-      if s.owner == c.owner and s.kind == skParam: nil
-      elif Contains(c.toBind, s.id): nil
+      if s.owner == c.owner and s.kind == skParam: discard
+      elif contains(c.toBind, s.id): discard
       elif templToExpand(s):
-        return semPatternBody(c, semTemplateExpr(c.c, n, s, false))
+        return semPatternBody(c, semTemplateExpr(c.c, n, s, {efNoSemCheck}))
     
     if n.kind == nkInfix and n.sons[0].kind == nkIdent:
       # we interpret `*` and `|` only as pattern operators if they occur in
@@ -537,15 +618,15 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
     # so we use the generic code for nkDotExpr too
     case n.kind 
     of nkDotExpr, nkAccQuoted:
-      let s = QualifiedLookUp(c.c, n, {})
+      let s = qualifiedLookUp(c.c, n, {})
       if s != nil:
-        if Contains(c.toBind, s.id):
+        if contains(c.toBind, s.id):
           return symChoice(c.c, n, s, scClosed)
         else:
           return newIdentNode(s.name, n.info)
     of nkPar:
       if n.len == 1: return semPatternBody(c, n.sons[0])
-    else: nil
+    else: discard
     for i in countup(0, sonsLen(n) - 1):
       result.sons[i] = semPatternBody(c, n.sons[i])
 
@@ -554,6 +635,7 @@ proc semPattern(c: PContext, n: PNode): PNode =
   var ctx: TemplCtx
   ctx.toBind = initIntSet()
   ctx.toMixin = initIntSet()
+  ctx.toInject = initIntSet()
   ctx.c = c
   ctx.owner = getCurrOwner()
   result = flattenStmts(semPatternBody(ctx, n))
@@ -561,5 +643,5 @@ proc semPattern(c: PContext, n: PNode): PNode =
     if result.len == 1:
       result = result.sons[0]
     elif result.len == 0:
-      LocalError(n.info, errInvalidExpression)
+      localError(n.info, errInvalidExpression)
   closeScope(c)
diff --git a/compiler/semthreads.nim b/compiler/semthreads.nim
index eded99325..d3426ca3e 100644
--- a/compiler/semthreads.nim
+++ b/compiler/semthreads.nim
@@ -97,7 +97,7 @@ proc `==`(a, b: TCall): bool =
 proc newProcCtx(owner: PSym): PProcCtx =
   assert owner != nil
   new(result)
-  result.mapping = tables.InitTable[int, TThreadOwner]()
+  result.mapping = tables.initTable[int, TThreadOwner]()
   result.owner = owner
 
 proc analyse(c: PProcCtx, n: PNode): TThreadOwner
@@ -119,7 +119,7 @@ proc analyseSym(c: PProcCtx, n: PNode): TThreadOwner =
   of skParam: 
     result = c.mapping[v.id]
     if result == toUndefined:
-      InternalError(n.info, "param not set: " & v.name.s)
+      internalError(n.info, "param not set: " & v.name.s)
   else:
     result = toNil
   c.mapping[v.id] = result
@@ -132,7 +132,7 @@ proc lvalueSym(n: PNode): PNode =
 
 proc writeAccess(c: PProcCtx, n: PNode, owner: TThreadOwner) =
   if owner notin {toNil, toMine, toTheirs}:
-    InternalError(n.info, "writeAccess: " & $owner)
+    internalError(n.info, "writeAccess: " & $owner)
   var a = lvalueSym(n)
   if a.kind == nkSym: 
     var v = a.sym
@@ -151,21 +151,21 @@ proc writeAccess(c: PProcCtx, n: PNode, owner: TThreadOwner) =
         newOwner = toMine
         # XXX BUG what if the tuple contains both ``tyRef`` and ``tyString``?
       c.mapping[v.id] = newOwner
-    of toVoid, toUndefined: InternalError(n.info, "writeAccess")
-    of toTheirs: Message(n.info, warnWriteToForeignHeap)
+    of toVoid, toUndefined: internalError(n.info, "writeAccess")
+    of toTheirs: message(n.info, warnWriteToForeignHeap)
     of toMine:
       if lastOwner != owner and owner != toNil:
-        Message(n.info, warnDifferentHeaps)
+        message(n.info, warnDifferentHeaps)
   else:
     # we could not backtrack to a concrete symbol, but that's fine:
     var lastOwner = analyse(c, n)
     case lastOwner
-    of toNil: nil # fine, toNil can be overwritten
-    of toVoid, toUndefined: InternalError(n.info, "writeAccess")
-    of toTheirs: Message(n.info, warnWriteToForeignHeap)
+    of toNil: discard # fine, toNil can be overwritten
+    of toVoid, toUndefined: internalError(n.info, "writeAccess")
+    of toTheirs: message(n.info, warnWriteToForeignHeap)
     of toMine:
       if lastOwner != owner and owner != toNil:
-        Message(n.info, warnDifferentHeaps)
+        message(n.info, warnDifferentHeaps)
 
 proc analyseAssign(c: PProcCtx, le, ri: PNode) =
   var y = analyse(c, ri) # read access; ok
@@ -192,7 +192,7 @@ proc analyseCall(c: PProcCtx, n: PNode): TThreadOwner =
     result = analyse(newCtx, prc.getBody)
     if prc.ast.sons[bodyPos].kind == nkEmpty and 
        {sfNoSideEffect, sfThread, sfImportc} * prc.flags == {}:
-      Message(n.info, warnAnalysisLoophole, renderTree(n))
+      message(n.info, warnAnalysisLoophole, renderTree(n))
       if result == toUndefined: result = toNil
     if prc.typ.sons[0] != nil:
       if prc.ast.len > resultPos:
@@ -215,12 +215,12 @@ proc analyseCall(c: PProcCtx, n: PNode): TThreadOwner =
       else: result = toNil
 
 proc analyseVarTuple(c: PProcCtx, n: PNode) =
-  if n.kind != nkVarTuple: InternalError(n.info, "analyseVarTuple")
+  if n.kind != nkVarTuple: internalError(n.info, "analyseVarTuple")
   var L = n.len
-  for i in countup(0, L-3): AnalyseAssign(c, n.sons[i], n.sons[L-1])
+  for i in countup(0, L-3): analyseAssign(c, n.sons[i], n.sons[L-1])
 
 proc analyseSingleVar(c: PProcCtx, a: PNode) =
-  if a.sons[2].kind != nkEmpty: AnalyseAssign(c, a.sons[0], a.sons[2])
+  if a.sons[2].kind != nkEmpty: analyseAssign(c, a.sons[0], a.sons[2])
 
 proc analyseVarSection(c: PProcCtx, n: PNode): TThreadOwner = 
   for i in countup(0, sonsLen(n) - 1): 
@@ -238,7 +238,7 @@ proc analyseConstSection(c: PProcCtx, t: PNode): TThreadOwner =
   for i in countup(0, sonsLen(t) - 1): 
     var it = t.sons[i]
     if it.kind == nkCommentStmt: continue 
-    if it.kind != nkConstDef: InternalError(t.info, "analyseConstSection")
+    if it.kind != nkConstDef: internalError(t.info, "analyseConstSection")
     if sfFakeConst in it.sons[0].sym.flags: analyseSingleVar(c, it)
   result = toVoid
 
@@ -246,7 +246,7 @@ template aggregateOwner(result, ana: expr) =
   var a = ana # eval once
   if result != a:
     if result == toNil: result = a
-    elif a != toNil: Message(n.info, warnDifferentHeaps)
+    elif a != toNil: message(n.info, warnDifferentHeaps)
 
 proc analyseArgs(c: PProcCtx, n: PNode, start = 1) =
   for i in start..n.len-1: discard analyse(c, n[i])
@@ -254,7 +254,7 @@ proc analyseArgs(c: PProcCtx, n: PNode, start = 1) =
 proc analyseOp(c: PProcCtx, n: PNode): TThreadOwner =
   if n[0].kind != nkSym or n[0].sym.kind != skProc:
     if {tfNoSideEffect, tfThread} * n[0].typ.flags == {}:
-      Message(n.info, warnAnalysisLoophole, renderTree(n))
+      message(n.info, warnAnalysisLoophole, renderTree(n))
     result = toNil
   else:
     var prc = n[0].sym
@@ -352,13 +352,13 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
     result = analyse(c, n.sons[0])
   of nkRaiseStmt:
     var a = analyse(c, n.sons[0])
-    if a != toMine: Message(n.info, warnDifferentHeaps)
+    if a != toMine: message(n.info, warnDifferentHeaps)
     result = toVoid
   of nkVarSection, nkLetSection: result = analyseVarSection(c, n)
   of nkConstSection: result = analyseConstSection(c, n)
   of nkTypeSection, nkCommentStmt: result = toVoid
   of nkIfStmt, nkWhileStmt, nkTryStmt, nkCaseStmt, nkStmtList, nkBlockStmt, 
-     nkElifBranch, nkElse, nkExceptBranch, nkOfBranch:
+     nkElifBranch, nkElse, nkExceptBranch, nkOfBranch, nkFinally:
     for i in 0 .. <n.len: discard analyse(c, n[i])
     result = toVoid
   of nkBreakStmt, nkContinueStmt: result = toVoid
@@ -369,11 +369,11 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
     result = toMine
   of nkAsmStmt, nkPragma, nkIteratorDef, nkProcDef, nkMethodDef,
      nkConverterDef, nkMacroDef, nkTemplateDef,
-     nkGotoState, nkState, nkBreakState, nkType:
+     nkGotoState, nkState, nkBreakState, nkType, nkIdent:
       result = toVoid
   of nkExprColonExpr:
     result = analyse(c, n.sons[1])
-  else: InternalError(n.info, "analysis not implemented for: " & $n.kind)
+  else: internalError(n.info, "analysis not implemented for: " & $n.kind)
 
 proc analyseThreadProc*(prc: PSym) =
   var c = newProcCtx(prc)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 6c9c476d9..679a01699 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -18,7 +18,7 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
     if result.kind == tyForward: result.kind = kind
 
 proc newConstraint(c: PContext, k: TTypeKind): PType = 
-  result = newTypeS(tyTypeClass, c)
+  result = newTypeS(tyBuiltInTypeClass, c)
   result.addSonSkipIntLit(newTypeS(k, c))
 
 proc semEnum(c: PContext, n: PNode, prev: PType): PType =
@@ -50,13 +50,13 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       of tyTuple: 
         if sonsLen(v) == 2:
           strVal = v.sons[1] # second tuple part is the string value
-          if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCstring}:
+          if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
             x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
           else:
-            LocalError(strVal.info, errStringLiteralExpected)
+            localError(strVal.info, errStringLiteralExpected)
         else:
-          LocalError(v.info, errWrongNumberOfVariables)
-      of tyString, tyCstring:
+          localError(v.info, errWrongNumberOfVariables)
+      of tyString, tyCString:
         strVal = v
         x = counter
       else:
@@ -64,7 +64,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       if i != 1:
         if x != counter: incl(result.flags, tfEnumHasHoles)
         if x < counter: 
-          LocalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
+          localError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
           x = counter
       e.ast = strVal # might be nil
       counter = x
@@ -79,7 +79,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
     if result.sym != nil and sfExported in result.sym.flags:
       incl(e.flags, sfUsed)
       incl(e.flags, sfExported)
-      if not isPure: StrTableAdd(c.module.tab, e)
+      if not isPure: strTableAdd(c.module.tab, e)
     addSon(result.n, newSymNode(e))
     if sfGenSym notin e.flags and not isPure: addDecl(c, e)
     inc(counter)
@@ -93,11 +93,11 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
     if base.kind == tyGenericInst: base = lastSon(base)
     if base.kind != tyGenericParam: 
       if not isOrdinalType(base): 
-        LocalError(n.info, errOrdinalTypeExpected)
+        localError(n.info, errOrdinalTypeExpected)
       elif lengthOrd(base) > MaxSetElements: 
-        LocalError(n.info, errSetTooBig)
+        localError(n.info, errSetTooBig)
   else:
-    LocalError(n.info, errXExpectsOneTypeParam, "set")
+    localError(n.info, errXExpectsOneTypeParam, "set")
     addSonSkipIntLit(result, errorType(c))
   
 proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, 
@@ -107,7 +107,7 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
     var base = semTypeNode(c, n.sons[1], nil)
     addSonSkipIntLit(result, base)
   else: 
-    LocalError(n.info, errXExpectsOneTypeParam, kindStr)
+    localError(n.info, errXExpectsOneTypeParam, kindStr)
     addSonSkipIntLit(result, errorType(c))
 
 proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
@@ -118,55 +118,74 @@ proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
     if sonsLen(n) == 3:
       result.n = newIdentNode(considerAcc(n.sons[2]), n.sons[2].info)
   else:
-    LocalError(n.info, errXExpectsOneTypeParam, "varargs")
+    localError(n.info, errXExpectsOneTypeParam, "varargs")
     addSonSkipIntLit(result, errorType(c))
-  
-proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, prev: PType): PType = 
-  if sonsLen(n) == 1:
+
+proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
+  if n.len < 1:
+    result = newConstraint(c, kind)
+  else:
+    let n = if n[0].kind == nkBracket: n[0] else: n
+    checkMinSonsLen(n, 1)
     result = newOrPrevType(kind, prev, c)
-    var base = semTypeNode(c, n.sons[0], nil)
+    # check every except the last is an object:
+    for i in 0 .. n.len-2:
+      let region = semTypeNode(c, n[i], nil)
+      if region.skipTypes({tyGenericInst}).kind notin {tyError, tyObject}:
+        message n[i].info, errGenerated, "region needs to be an object type"
+      addSonSkipIntLit(result, region)
+    var base = semTypeNode(c, n.lastSon, nil)
     addSonSkipIntLit(result, base)
-  else:
-    result = newConstraint(c, kind)
-  
+
 proc semVarType(c: PContext, n: PNode, prev: PType): PType = 
   if sonsLen(n) == 1: 
     result = newOrPrevType(tyVar, prev, c)
     var base = semTypeNode(c, n.sons[0], nil)
     if base.kind == tyVar: 
-      LocalError(n.info, errVarVarTypeNotAllowed)
+      localError(n.info, errVarVarTypeNotAllowed)
       base = base.sons[0]
     addSonSkipIntLit(result, base)
   else:
     result = newConstraint(c, tyVar)
-  
+
 proc semDistinct(c: PContext, n: PNode, prev: PType): PType = 
-  if sonsLen(n) == 1:
-    result = newOrPrevType(tyDistinct, prev, c)
-    addSonSkipIntLit(result, semTypeNode(c, n.sons[0], nil))
-  else:
-    result = newConstraint(c, tyDistinct)
+  if n.len == 0: return newConstraint(c, tyDistinct)
+  result = newOrPrevType(tyDistinct, prev, c)
+  addSonSkipIntLit(result, semTypeNode(c, n.sons[0], nil))
+  if n.len > 1: result.n = n[1]
   
-proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = 
-  assert IsRange(n)
+proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
+  assert isRange(n)
   checkSonsLen(n, 3)
   result = newOrPrevType(tyRange, prev, c)
   result.n = newNodeI(nkRange, n.info)
-  if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): 
-    LocalError(n.Info, errRangeIsEmpty)
-  var a = semConstExpr(c, n[1])
-  var b = semConstExpr(c, n[2])
-  if not sameType(a.typ, b.typ):
-    LocalError(n.info, errPureTypeMismatch)
-  elif a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,
-                         tyFloat..tyFloat128,tyUInt8..tyUInt32}:
-    LocalError(n.info, errOrdinalTypeExpected)
-  elif enumHasHoles(a.typ): 
-    LocalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
-  elif not leValue(a, b): LocalError(n.Info, errRangeIsEmpty)
-  addSon(result.n, a)
-  addSon(result.n, b)
-  addSonSkipIntLit(result, b.typ)
+  if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty):
+    localError(n.info, errRangeIsEmpty)
+  
+  var range: array[2, PNode]
+  range[0] = semExprWithType(c, n[1], {efDetermineType})
+  range[1] = semExprWithType(c, n[2], {efDetermineType})
+  
+  var rangeT: array[2, PType]
+  for i in 0..1: rangeT[i] = range[i].typ.skipTypes({tyStatic}).skipIntLit
+
+  if not sameType(rangeT[0], rangeT[1]):
+    localError(n.info, errPureTypeMismatch)
+  elif not rangeT[0].isOrdinalType:
+    localError(n.info, errOrdinalTypeExpected)
+  elif enumHasHoles(rangeT[0]):
+    localError(n.info, errEnumXHasHoles, rangeT[0].sym.name.s)
+  
+  for i in 0..1:
+    if hasGenericArguments(range[i]):
+      result.n.addSon makeStaticExpr(c, range[i])
+    else:
+      result.n.addSon semConstExpr(c, range[i])
+ 
+  if weakLeValue(result.n[0], result.n[1]) == impNo:
+    localError(n.info, errRangeIsEmpty)
+
+  addSonSkipIntLit(result, rangeT[0])
 
 proc semRange(c: PContext, n: PNode, prev: PType): PType =
   result = nil
@@ -180,10 +199,10 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
       elif n.sons[0].floatVal > 0.0 or n.sons[1].floatVal < 0.0:
         incl(result.flags, tfNeedsInit)
     else:
-      LocalError(n.sons[0].info, errRangeExpected)
+      localError(n.sons[0].info, errRangeExpected)
       result = newOrPrevType(tyError, prev, c)
   else:
-    LocalError(n.info, errXExpectsOneTypeParam, "range")
+    localError(n.info, errXExpectsOneTypeParam, "range")
     result = newOrPrevType(tyError, prev, c)
 
 proc semArray(c: PContext, n: PNode, prev: PType): PType = 
@@ -194,27 +213,47 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
     if isRange(n[1]): indx = semRangeAux(c, n[1], nil)
     else:
       let e = semExprWithType(c, n.sons[1], {efDetermineType})
-      if e.kind in {nkIntLit..nkUInt64Lit}:
+      if e.typ.kind == tyFromExpr:
+        indx = makeRangeWithStaticExpr(c, e.typ.n)
+      elif e.kind in {nkIntLit..nkUInt64Lit}:
         indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
-      elif e.kind == nkSym and e.typ.kind == tyExpr:
+      elif e.kind == nkSym and e.typ.kind == tyStatic:
         if e.sym.ast != nil: return semArray(c, e.sym.ast, nil)
-        InternalAssert c.InGenericContext > 0
+        internalAssert c.inGenericContext > 0
         if not isOrdinalType(e.typ.lastSon):
           localError(n[1].info, errOrdinalTypeExpected)
-        indx = e.typ
-      else:
+        indx = makeRangeWithStaticExpr(c, e)
+        indx.flags.incl tfUnresolved
+      elif e.kind in nkCallKinds and hasGenericArguments(e):
+        if not isOrdinalType(e.typ):
+          localError(n[1].info, errOrdinalTypeExpected)
+        # This is an int returning call, depending on an
+        # yet unknown generic param (see tgenericshardcases).
+        # We are going to construct a range type that will be
+        # properly filled-out in semtypinst (see how tyStaticExpr
+        # is handled there).
+        indx = makeRangeWithStaticExpr(c, e)
+      elif e.kind == nkIdent:
         indx = e.typ.skipTypes({tyTypeDesc})
+      else:
+        let x = semConstExpr(c, e)
+        if x.kind in {nkIntLit..nkUInt64Lit}:
+          indx = makeRangeType(c, 0, x.intVal-1, n.info, 
+                               x.typ.skipTypes({tyTypeDesc}))
+        else:
+          indx = x.typ.skipTypes({tyTypeDesc})
+          #localError(n[1].info, errConstExprExpected)
     addSonSkipIntLit(result, indx)
     if indx.kind == tyGenericInst: indx = lastSon(indx)
-    if indx.kind notin {tyGenericParam, tyExpr}:
+    if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}:
       if not isOrdinalType(indx):
-        LocalError(n.sons[1].info, errOrdinalTypeExpected)
+        localError(n.sons[1].info, errOrdinalTypeExpected)
       elif enumHasHoles(indx): 
-        LocalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
+        localError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
     base = semTypeNode(c, n.sons[2], nil)
     addSonSkipIntLit(result, base)
   else: 
-    LocalError(n.info, errArrayExpectsTwoTypeParams)
+    localError(n.info, errArrayExpectsTwoTypeParams)
     result = newOrPrevType(tyError, prev, c)
   
 proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = 
@@ -223,42 +262,54 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
     var base = semTypeNode(c, n.sons[1], nil)
     if base.kind != tyGenericParam: 
       if not isOrdinalType(base): 
-        LocalError(n.sons[1].info, errOrdinalTypeExpected)
+        localError(n.sons[1].info, errOrdinalTypeExpected)
     addSonSkipIntLit(result, base)
   else:
-    LocalError(n.info, errXExpectsOneTypeParam, "ordinal")
+    localError(n.info, errXExpectsOneTypeParam, "ordinal")
     result = newOrPrevType(tyError, prev, c)
 
 proc semTypeIdent(c: PContext, n: PNode): PSym =
   if n.kind == nkSym: 
     result = n.sym
   else:
-    result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
+    result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
     if result != nil:
       markUsed(n, 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
         # proc signature for example
-        if c.InGenericInst > 0:
+        if c.inGenericInst > 0:
           let bound = result.typ.sons[0].sym
           if bound != nil: return bound
           return result
         if result.typ.sym == nil:
-          LocalError(n.info, errTypeExpected)
+          localError(n.info, errTypeExpected)
           return errorSym(c, n)
         result = result.typ.sym.copySym
         result.typ = copyType(result.typ, result.typ.owner, true)
         result.typ.flags.incl tfUnresolved
+      
+      if result.kind == skGenericParam:
+        if result.typ.kind == tyGenericParam and result.typ.len == 0 and
+           tfWildcard in result.typ.flags:
+          # collapse the wild-card param to a type
+          result.kind = skType
+          result.typ.flags.excl tfWildcard
+          return
+        else:
+          localError(n.info, errTypeExpected)
+          return errorSym(c, n)
+
       if result.kind != skType: 
         # this implements the wanted ``var v: V, x: V`` feature ...
         var ov: TOverloadIter
-        var amb = InitOverloadIter(ov, c, n)
+        var amb = initOverloadIter(ov, c, n)
         while amb != nil and amb.kind != skType:
           amb = nextOverloadIter(ov, c, n)
         if amb != nil: result = amb
         else:
-          if result.kind != skError: LocalError(n.info, errTypeExpected)
+          if result.kind != skError: localError(n.info, errTypeExpected)
           return errorSym(c, n)
       if result.typ.kind != tyGenericParam:
         # XXX get rid of this hack!
@@ -268,7 +319,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
         n.sym = result
         n.info = oldInfo
     else:
-      LocalError(n.info, errIdentifierExpected)
+      localError(n.info, errIdentifierExpected)
       result = errorSym(c, n)
   
 proc semTuple(c: PContext, n: PNode, prev: PType): PType = 
@@ -280,26 +331,27 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
   var counter = 0
   for i in countup(0, sonsLen(n) - 1): 
     var a = n.sons[i]
-    if (a.kind != nkIdentDefs): IllFormedAst(a)
+    if (a.kind != nkIdentDefs): illFormedAst(a)
     checkMinSonsLen(a, 3)
     var length = sonsLen(a)
     if a.sons[length - 2].kind != nkEmpty: 
       typ = semTypeNode(c, a.sons[length - 2], nil)
     else:
-      LocalError(a.info, errTypeExpected)
+      localError(a.info, errTypeExpected)
       typ = errorType(c)
     if a.sons[length - 1].kind != nkEmpty: 
-      LocalError(a.sons[length - 1].info, errInitHereNotAllowed)
+      localError(a.sons[length - 1].info, errInitHereNotAllowed)
     for j in countup(0, length - 3): 
       var field = newSymG(skField, a.sons[j], c)
       field.typ = typ
       field.position = counter
       inc(counter)
-      if ContainsOrIncl(check, field.name.id): 
-        LocalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
+      if containsOrIncl(check, field.name.id): 
+        localError(a.sons[j].info, errAttemptToRedefine, field.name.s)
       else:
         addSon(result.n, newSymNode(field))
         addSonSkipIntLit(result, typ)
+      if gCmd == cmdPretty: checkDef(a.sons[j], field)
 
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, 
                  allowed: TSymFlags): PSym = 
@@ -313,7 +365,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
       if sfExported in allowed and v.id == ord(wStar): 
         incl(result.flags, sfExported)
       else:
-        LocalError(n.sons[0].info, errInvalidVisibilityX, v.s)
+        localError(n.sons[0].info, errInvalidVisibilityX, v.s)
     else:
       illFormedAst(n)
   else:
@@ -331,9 +383,10 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
     of skVar:   pragma(c, result, n.sons[1], varPragmas)
     of skLet:   pragma(c, result, n.sons[1], letPragmas)
     of skConst: pragma(c, result, n.sons[1], constPragmas)
-    else: nil
+    else: discard
   else:
     result = semIdentVis(c, kind, n, allowed)
+  if gCmd == cmdPretty: checkDef(n, result)
   
 proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
   let ex = t[branchIndex][currentEx].skipConv
@@ -341,9 +394,9 @@ proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
     for j in countup(0, sonsLen(t.sons[i]) - 2): 
       if i == branchIndex and j == currentEx: break
       if overlap(t.sons[i].sons[j].skipConv, ex):
-        LocalError(ex.info, errDuplicateCaseLabel)
+        localError(ex.info, errDuplicateCaseLabel)
   
-proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode =
+proc semBranchRange(c: PContext, t, a, b: PNode, covered: var BiggestInt): PNode =
   checkMinSonsLen(t, 1)
   let ac = semConstExpr(c, a)
   let bc = semConstExpr(c, b)
@@ -353,16 +406,16 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode
   result = newNodeI(nkRange, a.info)
   result.add(at)
   result.add(bt)
-  if emptyRange(ac, bc): LocalError(b.info, errRangeIsEmpty)
+  if emptyRange(ac, bc): localError(b.info, errRangeIsEmpty)
   else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
 
-proc SemCaseBranchRange(c: PContext, t, b: PNode, 
-                        covered: var biggestInt): PNode = 
+proc semCaseBranchRange(c: PContext, t, b: PNode, 
+                        covered: var BiggestInt): PNode = 
   checkSonsLen(b, 3)
   result = semBranchRange(c, t, b.sons[1], b.sons[2], covered)
 
 proc semCaseBranchSetElem(c: PContext, t, b: PNode, 
-                          covered: var biggestInt): PNode = 
+                          covered: var BiggestInt): PNode = 
   if isRange(b):
     checkSonsLen(b, 3)
     result = semBranchRange(c, t, b.sons[1], b.sons[2], covered)
@@ -374,7 +427,7 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode,
     inc(covered)
 
 proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, 
-                   covered: var biggestInt) = 
+                   covered: var BiggestInt) = 
   for i in countup(0, sonsLen(branch) - 2): 
     var b = branch.sons[i]
     if b.kind == nkRange:
@@ -411,14 +464,14 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     internalError("semRecordCase: discriminant is no symbol")
     return
   incl(a.sons[0].sym.flags, sfDiscriminant)
-  var covered: biggestInt = 0
-  var typ = skipTypes(a.sons[0].Typ, abstractVar-{tyTypeDesc})
+  var covered: BiggestInt = 0
+  var typ = skipTypes(a.sons[0].typ, abstractVar-{tyTypeDesc})
   if not isOrdinalType(typ):
-    LocalError(n.info, errSelectorMustBeOrdinal)
+    localError(n.info, errSelectorMustBeOrdinal)
   elif firstOrd(typ) < 0:
-    LocalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
+    localError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
   elif lengthOrd(typ) > 0x00007FFF:
-    LocalError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
+    localError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
   var chckCovered = true
   for i in countup(1, sonsLen(n) - 1):
     var b = copyTree(n.sons[i])
@@ -450,9 +503,9 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
       case it.kind
       of nkElifBranch:
         checkSonsLen(it, 2)
-        if c.InGenericContext == 0:
+        if c.inGenericContext == 0:
           var e = semConstBoolExpr(c, it.sons[0])
-          if e.kind != nkIntLit: InternalError(e.info, "semRecordNodeAux")
+          if e.kind != nkIntLit: internalError(e.info, "semRecordNodeAux")
           elif e.intVal != 0 and branch == nil: branch = it.sons[1]
         else:
           it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
@@ -461,15 +514,15 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
         if branch == nil: branch = it.sons[0]
         idx = 0
       else: illFormedAst(n)
-      if c.InGenericContext > 0:
+      if c.inGenericContext > 0:
         # use a new check intset here for each branch:
         var newCheck: TIntSet
         assign(newCheck, check)
         var newPos = pos
         var newf = newNodeI(nkRecList, n.info)
-        semRecordNodeAux(c, it.sons[idx], newcheck, newpos, newf, rectype)
+        semRecordNodeAux(c, it.sons[idx], newCheck, newPos, newf, rectype)
         it.sons[idx] = if newf.len == 1: newf[0] else: newf
-    if c.InGenericContext > 0:
+    if c.inGenericContext > 0:
       addSon(father, n)
     elif branch != nil:
       semRecordNodeAux(c, branch, check, pos, father, rectype)
@@ -493,7 +546,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
       localError(n.sons[length-1].info, errInitHereNotAllowed)
     var typ: PType
     if n.sons[length-2].kind == nkEmpty: 
-      LocalError(n.info, errTypeExpected)
+      localError(n.info, errTypeExpected)
       typ = errorType(c)
     else:
       typ = semTypeNode(c, n.sons[length-2], nil)
@@ -509,19 +562,19 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
         f.loc.r = toRope(f.name.s)
         f.flags = f.flags + ({sfImportc, sfExportc} * rec.flags)
       inc(pos)
-      if ContainsOrIncl(check, f.name.id):
+      if containsOrIncl(check, f.name.id):
         localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
       if a.kind == nkEmpty: addSon(father, newSymNode(f))
       else: addSon(a, newSymNode(f))
     if a.kind != nkEmpty: addSon(father, a)
-  of nkEmpty: nil
+  of nkEmpty: discard
   else: illFormedAst(n)
   
 proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int, 
                            n: PNode) =
   case n.kind
   of nkRecCase:
-    if (n.sons[0].kind != nkSym): InternalError(n.info, "addInheritedFieldsAux")
+    if (n.sons[0].kind != nkSym): internalError(n.info, "addInheritedFieldsAux")
     addInheritedFieldsAux(c, check, pos, n.sons[0])
     for i in countup(1, sonsLen(n) - 1):
       case n.sons[i].kind
@@ -532,9 +585,9 @@ proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int,
     for i in countup(0, sonsLen(n) - 1):
       addInheritedFieldsAux(c, check, pos, n.sons[i])
   of nkSym:
-    Incl(check, n.sym.name.id)
+    incl(check, n.sym.name.id)
     inc(pos)
-  else: InternalError(n.info, "addInheritedFieldsAux()")
+  else: internalError(n.info, "addInheritedFieldsAux()")
   
 proc addInheritedFields(c: PContext, check: var TIntSet, pos: var int, 
                         obj: PType) = 
@@ -565,7 +618,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
       if concreteBase.kind != tyError:
         localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
       base = nil
-  if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode")
+  if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
   result = newOrPrevType(tyObject, prev, c)
   rawAddSon(result, base)
   result.n = newNodeI(nkRecList, n.info)
@@ -577,32 +630,56 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
     pragma(c, s, n.sons[0], typePragmas)
   if base == nil and tfInheritable notin result.flags:
     incl(result.flags, tfFinal)
-  
+
+proc findEnforcedStaticType(t: PType): PType =
+  # This handles types such as `static[T] and Foo`,
+  # which are subset of `static[T]`, hence they could
+  # be treated in the same way
+  if t.kind == tyStatic: return t
+  if t.kind == tyAnd:
+    for s in t.sons:
+      let t = findEnforcedStaticType(s)
+      if t != nil: return t
+
 proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
-  if kind == skMacro and param.typ.kind != tyTypeDesc:
-    # within a macro, every param has the type PNimrodNode!
-    # and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
-    let nn = getSysSym"PNimrodNode"
-    var a = copySym(param)
-    a.typ = nn.typ
-    if sfGenSym notin a.flags: addDecl(c, a)
+  template addDecl(x) =
+    if sfGenSym notin x.flags: addDecl(c, x)
+
+  if kind == skMacro:
+    let staticType = findEnforcedStaticType(param.typ)
+    if staticType != nil:
+      var a = copySym(param)
+      a.typ = staticType.base
+      addDecl(a)
+    elif param.typ.kind == tyTypeDesc:
+      addDecl(param)
+    else:
+      # within a macro, every param has the type PNimrodNode!
+      let nn = getSysSym"PNimrodNode"
+      var a = copySym(param)
+      a.typ = nn.typ
+      addDecl(a)
   else:
-    if sfGenSym notin param.flags: addDecl(c, param)
+    addDecl(param)
 
 let typedescId = getIdent"typedesc"
 
+template shouldHaveMeta(t) =
+  internalAssert tfHasMeta in t.flags
+  # result.lastSon.flags.incl tfHasMeta
+
 proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
                    paramType: PType, paramName: string,
                    info: TLineInfo, anon = false): PType =
-  if procKind in {skMacro, skTemplate}:
-    # generic param types in macros and templates affect overload
-    # resolution, but don't work as generic params when it comes
-    # to proc instantiation. We don't need to lift such params here.  
-    return
+  if paramType == nil: return # (e.g. proc return type)
 
   proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
     let finalTypId = if typId != nil: typId
                      else: getIdent(paramName & ":type")
+    if genericParams == nil:
+      # This happens with anonymous proc types appearing in signatures
+      # XXX: we need to lift these earlier
+      return
     # is this a bindOnce type class already present in the param list?
     for i in countup(0, genericParams.len - 1):
       if genericParams.sons[i].sym.name.id == finalTypId.id:
@@ -613,10 +690,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     var s = newSym(skType, finalTypId, owner, info)
     if typId == nil: s.flags.incl(sfAnon)
     s.linkTo(typeClass)
+    typeClass.flags.incl tfImplicitTypeParam
     s.position = genericParams.len
     genericParams.addSon(newSymNode(s))
     result = typeClass
-
+    addDecl(c, s)
+ 
   # XXX: There are codegen errors if this is turned into a nested proc
   template liftingWalk(typ: PType, anonFlag = false): expr =
     liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag)
@@ -625,38 +704,52 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   var paramTypId = if not anon and paramType.sym != nil: paramType.sym.name
                    else: nil
 
+  template maybeLift(typ: PType): expr =
+    let lifted = liftingWalk(typ)
+    (if lifted != nil: lifted else: typ)
+
   template addImplicitGeneric(e: expr): expr =
     addImplicitGenericImpl(e, paramTypId)
 
   case paramType.kind:
-  of tyExpr:
-    if paramType.sonsLen == 0:
-      # proc(a, b: expr)
-      # no constraints, treat like generic param
-      result = addImplicitGeneric(newTypeS(tyGenericParam, c))
-    else:
-      # proc(a: expr{string}, b: expr{nkLambda})
-      # overload on compile time values and AST trees
-      result = addImplicitGeneric(c.newTypeWithSons(tyExpr, paramType.sons))
+  of tyAnything:
+    result = addImplicitGeneric(newTypeS(tyGenericParam, c))
+  
+  of tyStatic:
+    # proc(a: expr{string}, b: expr{nkLambda})
+    # overload on compile time values and AST trees
+    if paramType.n != nil: return # this is a concrete type
+    if tfUnresolved in paramType.flags: return # already lifted
+    let base = paramType.base.maybeLift
+    if base.isMetaType and procKind == skMacro:
+      localError(info, errMacroBodyDependsOnGenericTypes, paramName)
+    result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
+    result.flags.incl({tfHasStatic, tfUnresolved})
+  
   of tyTypeDesc:
     if tfUnresolved notin paramType.flags:
       # naked typedescs are not bindOnce types
-      if paramType.sonsLen == 0 and paramTypId != nil and
+      if paramType.base.kind == tyNone and paramTypId != nil and
          paramTypId.id == typedescId.id: paramTypId = nil
-      result = addImplicitGeneric(c.newTypeWithSons(tyTypeDesc, paramType.sons))
+      result = addImplicitGeneric(
+        c.newTypeWithSons(tyTypeDesc, @[paramType.base]))
+  
   of tyDistinct:
     if paramType.sonsLen == 1:
       # disable the bindOnce behavior for the type class
       result = liftingWalk(paramType.sons[0], true)
-  of tySequence, tySet, tyArray, tyOpenArray:
+  
+  of tySequence, tySet, tyArray, tyOpenArray,
+     tyVar, tyPtr, tyRef, tyProc:
     # XXX: this is a bit strange, but proc(s: seq)
-    # produces tySequence(tyGenericParam, null).
+    # produces tySequence(tyGenericParam, tyNone).
     # This also seems to be true when creating aliases
     # like: type myseq = distinct seq.
     # Maybe there is another better place to associate
     # the seq type class with the seq identifier.
-    if paramType.lastSon == nil:
-      let typ = c.newTypeWithSons(tyTypeClass, @[newTypeS(paramType.kind, c)])
+    if paramType.kind == tySequence and paramType.lastSon.kind == tyNone:
+      let typ = c.newTypeWithSons(tyBuiltInTypeClass,
+                                  @[newTypeS(paramType.kind, c)])
       result = addImplicitGeneric(typ)
     else:
       for i in 0 .. <paramType.sons.len:
@@ -664,30 +757,74 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
         if lifted != nil:
           paramType.sons[i] = lifted
           result = paramType
+  
   of tyGenericBody:
-    # type Foo[T] = object
-    # proc x(a: Foo, b: Foo) 
-    var typ = newTypeS(tyTypeClass, c)
-    typ.addSonSkipIntLit(paramType)
-    result = addImplicitGeneric(typ)
+    result = newTypeS(tyGenericInvokation, c)
+    result.rawAddSon(paramType)
+    for i in 0 .. paramType.sonsLen - 2:
+      result.rawAddSon newTypeS(tyAnything, c)
+      # result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
+
+    if paramType.lastSon.kind == tyUserTypeClass:
+      result.kind = tyUserTypeClassInst
+      result.rawAddSon paramType.lastSon
+      return addImplicitGeneric(result)
+   
+    result = instGenericContainer(c, paramType.sym.info, result,
+                                  allowMetaTypes = true)
+    result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
+    result = addImplicitGeneric(result)
+
+  of tyIter:
+    if paramType.callConv == ccInline:
+      if procKind notin {skTemplate, skMacro, skIterator}:
+        localError(info, errInlineIteratorsAsProcParams)
+      if paramType.len == 1:
+        let lifted = liftingWalk(paramType.base)
+        if lifted != nil: paramType.sons[0] = lifted
+      result = addImplicitGeneric(paramType)
+
   of tyGenericInst:
+    if paramType.lastSon.kind == tyUserTypeClass:
+      var cp = copyType(paramType, getCurrOwner(), false)
+      cp.kind = tyUserTypeClassInst
+      return addImplicitGeneric(cp)
+
     for i in 1 .. (paramType.sons.len - 2):
       var lifted = liftingWalk(paramType.sons[i])
       if lifted != nil:
         paramType.sons[i] = lifted
         result = paramType
+        result.lastSon.shouldHaveMeta
+
+    let liftBody = liftingWalk(paramType.lastSon, true)
+    if liftBody != nil:
+      result = liftBody
+      result.shouldHaveMeta
+ 
+  of tyGenericInvokation:
+    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)
 
-    if paramType.lastSon.kind == tyTypeClass:
-      result = paramType
-      result.kind = tyParametricTypeClass
-      result = addImplicitGeneric(copyType(result,
-                                           getCurrOwner(), false))
-    elif result != nil:
-      result.kind = tyGenericInvokation
-      result.sons.setLen(result.sons.len - 1)
-  of tyTypeClass:
-    result = addImplicitGeneric(copyType(paramType, getCurrOwner(), false))
-  else: nil
+  of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
+    result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
+  
+  of tyExpr:
+    if procKind notin {skMacro, skTemplate}:
+      result = addImplicitGeneric(newTypeS(tyAnything, c))
+  
+  of tyGenericParam:
+    markUsed(genericParams, paramType.sym)
+    if tfWildcard in paramType.flags:
+      paramType.flags.excl tfWildcard
+      paramType.sym.kind = skType
+    
+  else: discard
 
   # result = liftingWalk(paramType)
 
@@ -698,8 +835,8 @@ proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
   else:
     result = semTypeNode(c, n, nil)
 
-proc semProcTypeNode(c: PContext, n, genericParams: PNode, 
-                     prev: PType, kind: TSymKind): PType = 
+proc semProcTypeNode(c: PContext, n, genericParams: PNode,
+                     prev: PType, kind: TSymKind): PType =
   var
     res: PNode
     cl: TIntSet
@@ -719,7 +856,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
   var counter = 0
   for i in countup(1, n.len - 1):
     var a = n.sons[i]
-    if a.kind != nkIdentDefs: IllFormedAst(a)
+    if a.kind != nkIdentDefs: illFormedAst(a)
     checkMinSonsLen(a, 3)
     var
       typ: PType = nil
@@ -743,8 +880,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
         if not containsGenericType(typ):
           def = fitNode(c, typ, def)
     if not (hasType or hasDefault):
-      typ = newTypeS(tyExpr, c)
-      
+      let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything
+      typ = newTypeS(tdef, c)
+
     if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
     for j in countup(0, length-3): 
       var arg = newSymG(skParam, a.sons[j], c)
@@ -756,14 +894,20 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       arg.constraint = constraint
       inc(counter)
       if def != nil and def.kind != nkEmpty: arg.ast = copyTree(def)
-      if ContainsOrIncl(check, arg.name.id): 
-        LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
+      if containsOrIncl(check, arg.name.id): 
+        localError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
       addSon(result.n, newSymNode(arg))
       rawAddSon(result, finalType)
       addParamOrResult(c, arg, kind)
+      if gCmd == cmdPretty: checkDef(a.sons[j], arg)
 
+  var r: PType
   if n.sons[0].kind != nkEmpty:
-    var r = semTypeNode(c, n.sons[0], nil)
+    r = semTypeNode(c, n.sons[0], nil)
+  elif kind == skIterator:
+    r = newTypeS(tyAnything, c)
+  
+  if r != nil:
     # turn explicit 'void' return type into 'nil' because the rest of the 
     # compiler only checks for 'nil':
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
@@ -772,8 +916,20 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
                                    n.sons[0].info)
         if lifted != nil: r = lifted
         r.flags.incl tfRetType
-      result.sons[0] = skipIntLit(r)
-      res.typ = result.sons[0]
+      r = skipIntLit(r)
+      if kind == skIterator:
+        # see tchainediterators
+        # in cases like iterator foo(it: iterator): type(it)
+        # we don't need to change the return type to iter[T]
+        if not r.isInlineIterator: r = newTypeWithSons(c, tyIter, @[r])
+      result.sons[0] = r
+      res.typ = r
+
+  if genericParams != nil:
+    for n in genericParams:
+      if tfWildcard in n.sym.typ.flags:
+        n.sym.kind = skType
+        n.sym.typ.flags.excl tfWildcard
 
 proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
   checkMinSonsLen(n, 1)
@@ -788,7 +944,7 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
     result = nil
   
 proc semBlockType(c: PContext, n: PNode, prev: PType): PType = 
-  Inc(c.p.nestedBlockCounter)
+  inc(c.p.nestedBlockCounter)
   checkSonsLen(n, 2)
   openScope(c)
   if n.sons[0].kind notin {nkEmpty, nkSym}:
@@ -797,80 +953,73 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
   n.sons[1].typ = result
   n.typ = result
   closeScope(c)
-  Dec(c.p.nestedBlockCounter)
+  dec(c.p.nestedBlockCounter)
 
 proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
-  # XXX hack 1022 for generics ... would have been nice if the compiler had
-  # been designed with them in mind from start ...
-  when false:
-    if n.kind == nkSym:
-      # for generics we need to lookup the type var again:
-      var s = searchInScopes(c, n.sym.name)
-      if s != nil:
-        if s.kind == skType and s.typ != nil:
-          var t = n.sym.typ
-          echo "came here"
-          return t
-        else:
-          echo "s is crap:"
-          debug(s)
-      else:
-        echo "s is nil!!!!"
   result = semTypeNode(c, n, nil)
 
-proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = 
-  result = newOrPrevType(tyGenericInvokation, prev, c)
-  addSonSkipIntLit(result, s.typ)
+proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
+  if s.typ == nil:
+    localError(n.info, "cannot instantiate the '$1' $2" %
+                       [s.name.s, ($s.kind).substr(2).toLower])
+    return newOrPrevType(tyError, prev, c)
   
+  var t = s.typ
+  if t.kind == tyCompositeTypeClass and t.base.kind == tyGenericBody:
+    t = t.base
+
+  result = newOrPrevType(tyGenericInvokation, prev, c)
+  addSonSkipIntLit(result, t)
+
   template addToResult(typ) =
     if typ.isNil:
-      InternalAssert false
+      internalAssert false
       rawAddSon(result, typ)
     else: addSonSkipIntLit(result, typ)
 
-  if s.typ == nil:
-    LocalError(n.info, errCannotInstantiateX, s.name.s)
-    return newOrPrevType(tyError, prev, c)
-  elif s.typ.kind == tyForward:
+  if t.kind == tyForward:
     for i in countup(1, sonsLen(n)-1):
       var elem = semGenericParamInInvokation(c, n.sons[i])
       addToResult(elem)
+    return
+  elif t.kind != tyGenericBody:
+    #we likely got code of the form TypeA[TypeB] where TypeA is
+    #not generic.
+    localError(n.info, errNoGenericParamsAllowedForX, s.name.s)
+    return newOrPrevType(tyError, prev, c)
   else:
-    internalAssert s.typ.kind == tyGenericBody
-
-    var m = newCandidate(s, n)
+    var m = newCandidate(c, t)
     matches(c, n, copyTree(n), m)
     
     if m.state != csMatch:
-      var err = "cannot instantiate " & typeToString(s.typ) & "\n" &
+      var err = "cannot instantiate " & typeToString(t) & "\n" &
                 "got: (" & describeArgs(c, n) & ")\n" &
-                "but expected: (" & describeArgs(c, s.typ.n, 0) & ")"
-      LocalError(n.info, errGenerated, err)
+                "but expected: (" & describeArgs(c, t.n, 0) & ")"
+      localError(n.info, errGenerated, err)
       return newOrPrevType(tyError, prev, c)
 
     var isConcrete = true
-  
+ 
     for i in 1 .. <m.call.len:
       let typ = m.call[i].typ.skipTypes({tyTypeDesc})
       if containsGenericType(typ): isConcrete = false
       addToResult(typ)
-    
+   
     if isConcrete:
-      if s.ast == nil:
-        LocalError(n.info, errCannotInstantiateX, s.name.s)
+      if s.ast == nil and s.typ.kind != tyCompositeTypeClass:
+        # XXX: What kind of error is this? is it still relevant?
+        localError(n.info, errCannotInstantiateX, s.name.s)
         result = newOrPrevType(tyError, prev, c)
       else:
-        when oUseLateInstantiation:
-          result = lateInstantiateGeneric(c, result, n.info)
-        else:
-          result = instGenericContainer(c, n, result)
+        result = instGenericContainer(c, n.info, result,
+                                      allowMetaTypes = false)
 
 proc semTypeExpr(c: PContext, n: PNode): PType =
   var n = semExprWithType(c, n, {efDetermineType})
-  if n.kind == nkSym and n.sym.kind == skType:
-    result = n.sym.typ
+  if n.typ.kind == tyTypeDesc:
+    result = n.typ.base
   else:
-    LocalError(n.info, errTypeExpected, n.renderTree)
+    localError(n.info, errTypeExpected, n.renderTree)
 
 proc freshType(res, prev: PType): PType {.inline.} =
   if prev.isNil:
@@ -880,7 +1029,7 @@ proc freshType(res, prev: PType): PType {.inline.} =
 
 proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
   # if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
-  result = newOrPrevType(tyTypeClass, prev, c)
+  result = newOrPrevType(tyUserTypeClass, prev, c)
   result.n = n
 
   let
@@ -892,20 +1041,38 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
       let typ = semTypeNode(c, n, nil)
       result.sons.safeAdd(typ)
 
+proc semProcTypeWithScope(c: PContext, n: PNode,
+                        prev: PType, kind: TSymKind): PType =
+  checkSonsLen(n, 2)
+  openScope(c)
+  result = semProcTypeNode(c, n.sons[0], nil, prev, kind)
+  # dummy symbol for `pragma`:
+  var s = newSymS(kind, newIdentNode(getIdent("dummy"), n.info), c)
+  s.typ = result
+  if n.sons[1].kind == nkEmpty or n.sons[1].len == 0:
+    if result.callConv == ccDefault:
+      result.callConv = ccClosure
+      #Message(n.info, warnImplicitClosure, renderTree(n))
+  else:
+    pragma(c, s, n.sons[1], procTypePragmas)
+    when useEffectSystem: setEffectsForProcType(result, n.sons[1])
+  closeScope(c)
+
 proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   result = nil
   if gCmd == cmdIdeTools: suggestExpr(c, n)
   case n.kind
-  of nkEmpty: nil
+  of nkEmpty: discard
   of nkTypeOfExpr:
     # for ``type(countup(1,3))``, see ``tests/ttoseq``.
     checkSonsLen(n, 1)
-    result = semExprWithType(c, n.sons[0], {efInTypeof}).typ
+    let typExpr = semExprWithType(c, n.sons[0], {efInTypeof})
+    result = typExpr.typ.skipTypes({tyIter})
   of nkPar: 
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
     else:
       # XXX support anon tuple here
-      LocalError(n.info, errTypeExpected)
+      localError(n.info, errTypeExpected)
       result = newOrPrevType(tyError, prev, c)
   of nkCallKinds:
     if isRange(n):
@@ -917,26 +1084,29 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         var
           t1 = semTypeNode(c, n.sons[1], nil)
           t2 = semTypeNode(c, n.sons[2], nil)
-        if t1 == nil: 
-          LocalError(n.sons[1].info, errTypeExpected)
+        if t1 == nil:
+          localError(n.sons[1].info, errTypeExpected)
           result = newOrPrevType(tyError, prev, c)
-        elif t2 == nil: 
-          LocalError(n.sons[2].info, errTypeExpected)
+        elif t2 == nil:
+          localError(n.sons[2].info, errTypeExpected)
           result = newOrPrevType(tyError, prev, c)
         else:
-          result = newTypeS(tyTypeClass, c)
-          result.addSonSkipIntLit(t1)
-          result.addSonSkipIntLit(t2)
-          result.flags.incl(if op.id == ord(wAnd): tfAll else: tfAny)
-          result.flags.incl(tfHasMeta)
+          result = if op.id == ord(wAnd): makeAndType(c, t1, t2)
+                   else: makeOrType(c, t1, t2)
       elif op.id == ord(wNot):
-        checkSonsLen(n, 3)
-        result = semTypeNode(c, n.sons[1], prev)
-        if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
-          result = freshType(result, prev)
-          result.flags.incl(tfNotNil)
+        case n.len
+        of 3:
+          result = semTypeNode(c, n.sons[1], prev)
+          if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
+            result = freshType(result, prev)
+            result.flags.incl(tfNotNil)
+          else:
+            localError(n.info, errGenerated, "invalid type")
+        of 2:
+          let negated = semTypeNode(c, n.sons[1], prev)
+          result = makeNotType(c, negated)
         else:
-          LocalError(n.info, errGenerated, "invalid type")
+          localError(n.info, errGenerated, "invalid type")
       else:
         result = semTypeExpr(c, n)
     else:
@@ -956,22 +1126,32 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     of mOrdinal: result = semOrdinal(c, n, prev)
     of mSeq: result = semContainer(c, n, tySequence, "seq", prev)
     of mVarargs: result = semVarargs(c, n, prev)
-    of mExpr, mTypeDesc:
+    of mTypeDesc: result = makeTypeDesc(c, semTypeNode(c, n[1], nil))
+    of mExpr:
       result = semTypeNode(c, n.sons[0], nil)
       if result != nil:
         result = copyType(result, getCurrOwner(), false)
         for i in countup(1, n.len - 1):
           result.rawAddSon(semTypeNode(c, n.sons[i], nil))
     else: result = semGeneric(c, n, s, prev)
-  of nkIdent, nkDotExpr, nkAccQuoted: 
+  of nkDotExpr:
+    var typeExpr = semExpr(c, n)
+    if typeExpr.typ.kind != tyTypeDesc:
+      localError(n.info, errTypeExpected)
+      return errorType(c)
+    result = typeExpr.typ.base
+    if result.isMetaType:
+      var toBind = initIntSet()
+      var preprocessed = semGenericStmt(c, n, {}, toBind)
+      return makeTypeFromExpr(c, preprocessed)
+  of nkIdent, nkAccQuoted:
     var s = semTypeIdent(c, n)
     if s.typ == nil: 
-      if s.kind != skError: LocalError(n.info, errTypeExpected)
+      if s.kind != skError: localError(n.info, errTypeExpected)
       result = newOrPrevType(tyError, prev, c)
     elif s.kind == skParam and s.typ.kind == tyTypeDesc:
-      assert s.typ.len > 0
-      InternalAssert prev == nil
-      result = s.typ.sons[0]
+      internalAssert s.typ.base.kind != tyNone and prev == nil
+      result = s.typ.base
     elif prev == nil:
       result = s.typ
     else: 
@@ -991,7 +1171,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         result = prev
       markUsed(n, n.sym)
     else:
-      if n.sym.kind != skError: LocalError(n.info, errTypeExpected)
+      if n.sym.kind != skError: localError(n.info, errTypeExpected)
       result = newOrPrevType(tyError, prev, c)
   of nkObjectTy: result = semObjectNode(c, n, prev)
   of nkTupleTy: result = semTuple(c, n, prev)
@@ -1000,27 +1180,27 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
   of nkVarTy: result = semVarType(c, n, prev)
   of nkDistinctTy: result = semDistinct(c, n, prev)
-  of nkProcTy, nkIteratorTy:
+  of nkStaticTy:
+    result = newOrPrevType(tyStatic, prev, c)
+    var base = semTypeNode(c, n.sons[0], nil)
+    result.rawAddSon(base)
+    result.flags.incl tfHasStatic
+  of nkIteratorTy:
     if n.sonsLen == 0:
-      result = newConstraint(c, tyProc)
+      result = newConstraint(c, tyIter)
     else:
-      checkSonsLen(n, 2)
-      openScope(c)
-      result = semProcTypeNode(c, n.sons[0], nil, prev, skProc)
-      # dummy symbol for `pragma`:
-      var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
-      s.typ = result
-      if n.sons[1].kind == nkEmpty or n.sons[1].len == 0:
-        if result.callConv == ccDefault:
-          result.callConv = ccClosure
-          #Message(n.info, warnImplicitClosure, renderTree(n))
+      result = semProcTypeWithScope(c, n, prev, skClosureIterator)
+      if n.lastSon.kind == nkPragma and hasPragma(n.lastSon, wInline):
+        result.kind = tyIter
+        result.callConv = ccInline
       else:
-        pragma(c, s, n.sons[1], procTypePragmas)
-        when useEffectSystem: SetEffectsForProcType(result, n.sons[1])
-      closeScope(c)
-    if n.kind == nkIteratorTy:
-      result.flags.incl(tfIterator)
-      result.callConv = ccClosure
+        result.flags.incl(tfIterator)
+        result.callConv = ccClosure
+  of nkProcTy:
+    if n.sonsLen == 0:
+      result = newConstraint(c, tyProc)
+    else:
+      result = semProcTypeWithScope(c, n, prev, skProc)
   of nkEnumTy: result = semEnum(c, n, prev)
   of nkType: result = n.typ
   of nkStmtListType: result = semStmtListType(c, n, prev)
@@ -1031,7 +1211,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     result = freshType(result, prev)
     result.flags.incl(tfShared)
   else:
-    LocalError(n.info, errTypeExpected)
+    localError(n.info, errTypeExpected)
     result = newOrPrevType(tyError, prev, c)
   
 proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
@@ -1071,24 +1251,31 @@ proc processMagicType(c: PContext, m: PSym) =
   of mNil: setMagicType(m, tyNil, ptrSize)
   of mExpr: setMagicType(m, tyExpr, 0)
   of mStmt: setMagicType(m, tyStmt, 0)
-  of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
+  of mTypeDesc: 
+    setMagicType(m, tyTypeDesc, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
   of mVoidType: setMagicType(m, tyEmpty, 0)
-  of mArray: setMagicType(m, tyArray, 0)
-  of mOpenArray: setMagicType(m, tyOpenArray, 0)
-  of mVarargs: setMagicType(m, tyVarargs, 0)
-  of mRange: setMagicType(m, tyRange, 0)
-  of mSet: setMagicType(m, tySet, 0) 
-  of mSeq: setMagicType(m, tySequence, 0)
-  of mOrdinal: setMagicType(m, tyOrdinal, 0)
-  of mPNimrodNode: nil
-  else: LocalError(m.info, errTypeExpected)
+  of mArray:
+    setMagicType(m, tyArray, 0)
+  of mOpenArray:
+    setMagicType(m, tyOpenArray, 0)
+  of mVarargs:
+    setMagicType(m, tyVarargs, 0)
+  of mRange:
+    setMagicType(m, tyRange, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
+  of mSet:
+    setMagicType(m, tySet, 0) 
+  of mSeq: 
+    setMagicType(m, tySequence, 0)
+  of mOrdinal:
+    setMagicType(m, tyOrdinal, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
+  of mPNimrodNode: discard
+  else: localError(m.info, errTypeExpected)
   
 proc semGenericConstraints(c: PContext, x: PType): PType =
-  if x.kind in StructuralEquivTypes and (
-      sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
-    result = newConstraint(c, x.kind)
-  else:
-    result = newTypeWithSons(c, tyGenericParam, @[x])
+  result = newTypeWithSons(c, tyGenericParam, @[x])
 
 proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = 
   result = copyNode(n)
@@ -1105,10 +1292,10 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
     
     if constraint.kind != nkEmpty:
       typ = semTypeNode(c, constraint, nil)
-      if typ.kind != tyExpr or typ.len == 0:
+      if typ.kind != tyStatic or typ.len == 0:
         if typ.kind == tyTypeDesc:
-          if typ.len == 0:
-            typ = newTypeS(tyTypeDesc, c)
+          if typ.sons[0].kind == tyNone:
+            typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
         else:
           typ = semGenericConstraints(c, typ)
     
@@ -1116,14 +1303,17 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
       def = semConstExpr(c, def)
       if typ == nil:
         if def.typ.kind != tyTypeDesc:
-          typ = newTypeWithSons(c, tyExpr, @[def.typ])
+          typ = newTypeWithSons(c, tyStatic, @[def.typ])
       else:
         if not containsGenericType(def.typ):
           def = fitNode(c, typ, def)
     
     if typ == nil:
       typ = newTypeS(tyGenericParam, c)
-    
+      if father == nil: typ.flags.incl tfWildcard
+
+    typ.flags.incl tfGenericTypeParam
+
     for j in countup(0, L-3):
       let finalType = if j == 0: typ
                       else: copyType(typ, typ.owner, false)
@@ -1131,8 +1321,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
                       # type for each generic param. the index
                       # of the parameter will be stored in the
                       # attached symbol.
-      var s = case finalType.kind
-        of tyExpr:
+      var s = if finalType.kind == tyStatic or tfWildcard in typ.flags:
           newSymG(skGenericParam, a.sons[j], c).linkTo(finalType)
         else:
           newSymG(skType, a.sons[j], c).linkTo(finalType)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 61c31a4fe..4a8a463f5 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -11,21 +11,25 @@
 
 import ast, astalgo, msgs, types, magicsys, semdata, renderer
 
+const
+  tfInstClearedFlags = {tfHasMeta}
+
 proc checkPartialConstructedType(info: TLineInfo, t: PType) =
   if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
-    LocalError(info, errInvalidPragmaX, "acyclic")
+    localError(info, errInvalidPragmaX, "acyclic")
   elif t.kind == tyVar and t.sons[0].kind == tyVar:
-    LocalError(info, errVarVarTypeNotAllowed)
+    localError(info, errVarVarTypeNotAllowed)
 
-proc checkConstructedType*(info: TLineInfo, typ: PType) = 
+proc checkConstructedType*(info: TLineInfo, typ: PType) =
   var t = typ.skipTypes({tyDistinct})
-  if t.kind in {tyTypeClass}: nil
+  if t.kind in tyTypeClasses: discard
   elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: 
-    LocalError(info, errInvalidPragmaX, "acyclic")
+    localError(info, errInvalidPragmaX, "acyclic")
   elif t.kind == tyVar and t.sons[0].kind == tyVar: 
-    LocalError(info, errVarVarTypeNotAllowed)
-  elif computeSize(t) < 0:
-    LocalError(info, errIllegalRecursionInTypeX, typeToString(t))
+    localError(info, errVarVarTypeNotAllowed)
+  elif computeSize(t) == szIllegalRecursion:
+    localError(info, errIllegalRecursionInTypeX, typeToString(t))
+  
   when false:
     if t.kind == tyObject and t.sons[0] != nil:
       if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags: 
@@ -33,7 +37,7 @@ proc checkConstructedType*(info: TLineInfo, typ: PType) =
 
 proc searchInstTypes*(key: PType): PType =
   let genericTyp = key.sons[0]
-  InternalAssert genericTyp.kind == tyGenericBody and
+  internalAssert genericTyp.kind == tyGenericBody and
                  key.sons[0] == genericTyp and
                  genericTyp.sym != nil
 
@@ -47,12 +51,13 @@ proc searchInstTypes*(key: PType): PType =
       # types such as TChannel[empty]. Why?
       # See the notes for PActor in handleGenericInvokation
       return
-    block MatchType:
+    block matchType:
       for j in 1 .. high(key.sons):
         # XXX sameType is not really correct for nested generics?
-        if not sameType(inst.sons[j], key.sons[j]):
-          break MatchType
-      
+        if not compareTypes(inst.sons[j], key.sons[j],
+                            flags = {ExactGenericParams}):
+          break matchType
+       
       return inst
 
 proc cacheTypeInst*(inst: PType) =
@@ -66,30 +71,95 @@ type
     c*: PContext
     typeMap*: TIdTable        # map PType to PType
     symMap*: TIdTable         # map PSym to PSym
+    localCache*: TIdTable     # local cache for remembering alraedy replaced
+                              # types during instantiation of meta types
+                              # (they are not stored in the global cache)
     info*: TLineInfo
+    allowMetaTypes*: bool     # allow types such as seq[Number]
+                              # i.e. the result contains unresolved generics
 
-proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType
-proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
-proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode
+proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType
+proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
+proc replaceTypeVarsN*(cl: var TReplTypeVars, n: PNode): PNode
+
+template checkMetaInvariants(cl: TReplTypeVars, t: PType) =
+  when false:
+    if t != nil and tfHasMeta in t.flags and
+       cl.allowMetaTypes == false:
+      echo "UNEXPECTED META ", t.id, " ", instantiationInfo(-1)
+      debug t
+      writeStackTrace()
+      quit 1
+
+proc replaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
+  result = replaceTypeVarsTAux(cl, t)
+  checkMetaInvariants(cl, result)
 
 proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
+  let t = replaceTypeVarsT(cl, n.typ)
+  if t != nil and t.kind == tyStatic and t.n != nil:
+    return t.n
   result = copyNode(n)
-  result.typ = ReplaceTypeVarsT(cl, n.typ)
-  if result.kind == nkSym: result.sym = ReplaceTypeVarsS(cl, n.sym)
-  for i in 0 .. safeLen(n)-1: 
-    # XXX HACK: ``f(a, b)``, avoid to instantiate `f` 
-    if i == 0: result.add(n[i])
+  result.typ = t
+  if result.kind == nkSym: result.sym = replaceTypeVarsS(cl, n.sym)
+  let isCall = result.kind in nkCallKinds
+  for i in 0 .. <n.safeLen:
+    # XXX HACK: ``f(a, b)``, avoid to instantiate `f`
+    if isCall and i == 0: result.add(n[i])
     else: result.add(prepareNode(cl, n[i]))
 
-proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
+proc isTypeParam(n: PNode): bool =
+  # XXX: generic params should use skGenericParam instead of skType
+  return n.kind == nkSym and
+         (n.sym.kind == skGenericParam or
+           (n.sym.kind == skType and sfFromGeneric in n.sym.flags))
+
+proc hasGenericArguments*(n: PNode): bool =
+  if n.kind == nkSym:
+    return n.sym.kind == skGenericParam or
+           (n.sym.kind == skType and
+            n.sym.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} != {})
+  else:
+    for i in 0.. <n.safeLen:
+      if hasGenericArguments(n.sons[i]): return true
+    return false
+
+proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode =
+  # This is needed fo tgenericshardcases
+  # It's possible that a generic param will be used in a proc call to a
+  # typedesc accepting proc. After generic param substitution, such procs
+  # should be optionally instantiated with the correct type. In order to
+  # perform this instantiation, we need to re-run the generateInstance path
+  # in the compiler, but it's quite complicated to do so at the moment so we
+  # resort to a mild hack; the head symbol of the call is temporary reset and
+  # overload resolution is executed again (which may trigger generateInstance).
+  if n.kind in nkCallKinds and sfFromGeneric in n[0].sym.flags:
+    var needsFixing = false
+    for i in 1 .. <n.safeLen:
+      if isTypeParam(n[i]): needsFixing = true
+    if needsFixing:
+      n.sons[0] = newSymNode(n.sons[0].sym.owner)
+      return cl.c.semOverloadedCall(cl.c, n, n, {skProc})
+  
+  for i in 0 .. <n.safeLen:
+    n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i])
+
+  return n
+
+proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
   if n == nil: return
   result = copyNode(n)
-  result.typ = ReplaceTypeVarsT(cl, n.typ)
+  if n.typ != nil:
+    result.typ = replaceTypeVarsT(cl, n.typ)
+    checkMetaInvariants(cl, result.typ)
   case n.kind
   of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
-    nil
+    discard
   of nkSym:
-    result.sym = ReplaceTypeVarsS(cl, n.sym)
+    result.sym = replaceTypeVarsS(cl, n.sym)
+    if result.sym.typ.kind == tyEmpty:
+      # don't add the 'void' field
+      result = newNode(nkRecList, n.info)
   of nkRecWhen:
     var branch: PNode = nil              # the branch to take
     for i in countup(0, sonsLen(n) - 1):
@@ -101,72 +171,95 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
         var cond = prepareNode(cl, it.sons[0])
         var e = cl.c.semConstExpr(cl.c, cond)
         if e.kind != nkIntLit:
-          InternalError(e.info, "ReplaceTypeVarsN: when condition not a bool")
+          internalError(e.info, "ReplaceTypeVarsN: when condition not a bool")
         if e.intVal != 0 and branch == nil: branch = it.sons[1]
       of nkElse:
         checkSonsLen(it, 1)
         if branch == nil: branch = it.sons[0]
       else: illFormedAst(n)
     if branch != nil:
-      result = ReplaceTypeVarsN(cl, branch)
+      result = replaceTypeVarsN(cl, branch)
     else:
       result = newNodeI(nkRecList, n.info)
+  of nkStaticExpr:
+    var n = prepareNode(cl, n)
+    n = reResolveCallsWithTypedescParams(cl, n)
+    result = if cl.allowMetaTypes: n
+             else: cl.c.semExpr(cl.c, n)
   else:
     var length = sonsLen(n)
     if length > 0:
       newSons(result, length)
       for i in countup(0, length - 1):
-        result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
+        result.sons[i] = replaceTypeVarsN(cl, n.sons[i])
   
-proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = 
+proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = 
   if s == nil: return nil
   result = PSym(idTableGet(cl.symMap, s))
   if result == nil: 
     result = copySym(s, false)
     incl(result.flags, sfFromGeneric)
     idTablePut(cl.symMap, s, result)
-    result.typ = ReplaceTypeVarsT(cl, s.typ)
     result.owner = s.owner
-    result.ast = ReplaceTypeVarsN(cl, s.ast)
-
+    result.typ = replaceTypeVarsT(cl, s.typ)
+    result.ast = replaceTypeVarsN(cl, s.ast)
+    
 proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil:
-    LocalError(t.sym.info, errCannotInstantiateX, typeToString(t))
+    if cl.allowMetaTypes or tfRetType in t.flags: return
+    localError(t.sym.info, errCannotInstantiateX, typeToString(t))
     result = errorType(cl.c)
-  elif result.kind == tyGenericParam: 
-    InternalError(cl.info, "substitution with generic parameter")
-  
+  elif result.kind == tyGenericParam and not cl.allowMetaTypes:
+    internalError(cl.info, "substitution with generic parameter")
+
+proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
+  # XXX: relying on allowMetaTypes is a kludge
+  result = copyType(t, t.owner, cl.allowMetaTypes)
+  result.flags.incl tfFromGeneric
+  result.flags.excl tfInstClearedFlags
+
 proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType = 
   # tyGenericInvokation[A, tyGenericInvokation[A, B]]
   # is difficult to handle: 
   var body = t.sons[0]
-  if body.kind != tyGenericBody: InternalError(cl.info, "no generic body")
-  var header: PType = nil
+  if body.kind != tyGenericBody: internalError(cl.info, "no generic body")
+  var header: PType = t
   # search for some instantiation here:
-  result = searchInstTypes(t)
+  if cl.allowMetaTypes:
+    result = PType(idTableGet(cl.localCache, t))
+  else:
+    result = searchInstTypes(t)
   if result != nil: return
   for i in countup(1, sonsLen(t) - 1):
     var x = t.sons[i]
     if x.kind == tyGenericParam:
       x = lookupTypeVar(cl, x)
-      if header == nil: header = copyType(t, t.owner, false)
-      header.sons[i] = x
+      if x != nil:
+        if header == t: header = instCopyType(cl, t)
+        header.sons[i] = x
+        propagateToOwner(header, x)
+    else:
       propagateToOwner(header, x)
-      #idTablePut(cl.typeMap, body.sons[i-1], x)  
-
-  if header != nil:
+  
+  if header != t:
     # search again after first pass:
     result = searchInstTypes(header)
     if result != nil: return
   else:
-    header = copyType(t, t.owner, false)
+    header = instCopyType(cl, t)
+  
+  result = newType(tyGenericInst, t.sons[0].owner)
+  result.flags = header.flags
+  # be careful not to propagate unnecessary flags here (don't use rawAddSon)
+  result.sons = @[header.sons[0]]
   # ugh need another pass for deeply recursive generic types (e.g. PActor)
   # we need to add the candidate here, before it's fully instantiated for
   # recursive instantions:
-  result = newType(tyGenericInst, t.sons[0].owner)
-  result.rawAddSon(header.sons[0])
-  cacheTypeInst(result)
+  if not cl.allowMetaTypes:
+    cacheTypeInst(result)
+  else:
+    idTablePut(cl.localCache, t, result)
 
   for i in countup(1, sonsLen(t) - 1):
     var x = replaceTypeVarsT(cl, t.sons[i])
@@ -175,71 +268,171 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
     propagateToOwner(header, x)
     idTablePut(cl.typeMap, body.sons[i-1], x)
   
-  for i in countup(1, sonsLen(t) - 1): 
+  for i in countup(1, sonsLen(t) - 1):
     # if one of the params is not concrete, we cannot do anything
     # but we already raised an error!
     rawAddSon(result, header.sons[i])
-  
-  var newbody = ReplaceTypeVarsT(cl, lastSon(body))
-  newbody.flags = newbody.flags + t.flags + body.flags
+
+  var newbody = replaceTypeVarsT(cl, lastSon(body))
+  newbody.flags = newbody.flags + (t.flags + body.flags - tfInstClearedFlags)
   result.flags = result.flags + newbody.flags
   newbody.callConv = body.callConv
-  newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
   # This type may be a generic alias and we want to resolve it here.
   # One step is enough, because the recursive nature of
   # handleGenericInvokation will handle the alias-to-alias-to-alias case
   if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
   rawAddSon(result, newbody)
   checkPartialConstructedType(cl.info, newbody)
+
+proc eraseVoidParams*(t: PType) =
+  if t.sons[0] != nil and t.sons[0].kind == tyEmpty:
+    t.sons[0] = nil
   
-proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType = 
+  for i in 1 .. <t.sonsLen:
+    # don't touch any memory unless necessary
+    if t.sons[i].kind == tyEmpty:
+      var pos = i
+      for j in i+1 .. <t.sonsLen:
+        if t.sons[j].kind != tyEmpty:
+          t.sons[pos] = t.sons[j]
+          t.n.sons[pos] = t.n.sons[j]
+          inc pos
+      setLen t.sons, pos
+      setLen t.n.sons, pos
+      return
+
+proc skipIntLiteralParams*(t: PType) =
+  for i in 0 .. <t.sonsLen:
+    let p = t.sons[i]
+    if p == nil: continue
+    let skipped = p.skipIntLit
+    if skipped != p:
+      t.sons[i] = skipped
+      if i > 0: t.n.sons[i].sym.typ = skipped
+  
+  # when the typeof operator is used on a static input
+  # param, the results gets infected with static as well:
+  if t.sons[0] != nil and t.sons[0].kind == tyStatic:
+    t.sons[0] = t.sons[0].base
+
+proc propagateFieldFlags(t: PType, n: PNode) =
+  # This is meant for objects and tuples
+  # The type must be fully instantiated!
+  internalAssert n.kind != nkRecWhen
+  case n.kind
+  of nkSym:
+    propagateToOwner(t, n.sym.typ)
+  of nkRecList, nkRecCase, nkOfBranch, nkElse:
+    for son in n:
+      propagateFieldFlags(t, son)
+  else: discard
+
+proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
   result = t
-  if t == nil: return 
+  if t == nil: return
+
+  if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses:
+    let lookup = PType(idTableGet(cl.typeMap, t))
+    if lookup != nil: return lookup
+  
   case t.kind
-  of tyTypeClass: nil
-  of tyGenericParam:
-    result = lookupTypeVar(cl, t)
-    if result.kind == tyGenericInvokation:
-      result = handleGenericInvokation(cl, result)
-  of tyExpr:
-    if t.sym != nil and t.sym.kind == skGenericParam:
-      result = lookupTypeVar(cl, t)
-  of tyGenericInvokation: 
+  of tyGenericInvokation:
     result = handleGenericInvokation(cl, t)
+
   of tyGenericBody:
-    InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody")
-    result = ReplaceTypeVarsT(cl, lastSon(t))
+    internalError(cl.info, "ReplaceTypeVarsT: tyGenericBody" )
+    result = replaceTypeVarsT(cl, lastSon(t))
+
+  of tyFromExpr:
+    if cl.allowMetaTypes: return
+    var n = prepareNode(cl, t.n)
+    n = cl.c.semConstExpr(cl.c, n)
+    if n.typ.kind == tyTypeDesc:
+      # XXX: sometimes, chained typedescs enter here.
+      # It may be worth investigating why this is happening,
+      # because it may cause other bugs elsewhere.
+      result = n.typ.skipTypes({tyTypeDesc})
+      # result = n.typ.base
+    else:
+      if n.typ.kind != tyStatic:
+        # XXX: In the future, semConstExpr should
+        # return tyStatic values to let anyone make
+        # use of this knowledge. The patching here
+        # won't be necessary then.
+        result = newTypeS(tyStatic, cl.c)
+        result.sons = @[n.typ]
+        result.n = n
+      else:
+        result = n.typ
+
   of tyInt:
     result = skipIntLit(t)
     # XXX now there are also float literals
+  
+  of tyTypeDesc:
+    let lookup = PType(idTableGet(cl.typeMap, t)) # lookupTypeVar(cl, t)
+    if lookup != nil:
+      result = lookup
+      if tfUnresolved in t.flags: result = result.base
+    elif t.sons[0].kind != tyNone:
+      result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
+ 
+  of tyUserTypeClass:
+    result = t
+
+  of tyGenericInst:
+    result = instCopyType(cl, t)
+    for i in 1 .. <result.sonsLen:
+      result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
+    propagateToOwner(result, result.lastSon)
+  
   else:
-    if t.kind == tyArray:
-      let idxt = t.sons[0]
-      if idxt.kind == tyExpr and 
-         idxt.sym != nil and idxt.sym.kind == skGenericParam:
-        let value = lookupTypeVar(cl, idxt).n
-        t.sons[0] = makeRangeType(cl.c, 0, value.intVal - 1, value.info)
     if containsGenericType(t):
-      result = copyType(t, t.owner, false)
-      incl(result.flags, tfFromGeneric)
+      result = instCopyType(cl, t)
       result.size = -1 # needs to be recomputed
+      
       for i in countup(0, sonsLen(result) - 1):
-        result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
-      result.n = ReplaceTypeVarsN(cl, result.n)
-      if result.Kind in GenericTypes:
-        LocalError(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
-      if result.kind == tyProc and result.sons[0] != nil:
-        if result.sons[0].kind == tyEmpty:
-          result.sons[0] = nil
+        if result.sons[i] != nil:
+          result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
+          propagateToOwner(result, result.sons[i])
+
+      result.n = replaceTypeVarsN(cl, result.n)
+     
+      case result.kind
+      of tyArray:
+        let idx = result.sons[0]
+        internalAssert idx.kind != tyStatic
+       
+      of tyObject, tyTuple:
+        propagateFieldFlags(result, result.n)
+      
+      of tyProc:
+        eraseVoidParams(result)
+        skipIntLiteralParams(result)
+      
+      else: discard
+
+proc initTypeVars*(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars =
+  initIdTable(result.symMap)
+  copyIdTable(result.typeMap, pt)
+  initIdTable(result.localCache)
+  result.info = info
+  result.c = p
+
+proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode): PNode =
+  var cl = initTypeVars(p, pt, n.info)
+  pushInfoContext(n.info)
+  result = replaceTypeVarsN(cl, n)
+  popInfoContext()
   
-proc generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode, 
-                           t: PType): PType = 
-  var cl: TReplTypeVars
-  InitIdTable(cl.symMap)
-  copyIdTable(cl.typeMap, pt)
-  cl.info = arg.info
-  cl.c = p
-  pushInfoContext(arg.info)
-  result = ReplaceTypeVarsT(cl, t)
+proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
+                           t: PType): PType =
+  var cl = initTypeVars(p, pt, info)
+  pushInfoContext(info)
+  result = replaceTypeVarsT(cl, t)
   popInfoContext()
 
+template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode,
+                               t: PType): expr =
+  generateTypeInstance(p, pt, arg.info, t)
+
diff --git a/compiler/service.nim b/compiler/service.nim
index 1de83af7c..42c4aa9f4 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -29,23 +29,23 @@ var
     # the arguments to be passed to the program that
     # should be run
 
-proc ProcessCmdLine*(pass: TCmdLinePass, cmd: string) =
+proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
   var p = parseopt.initOptParser(cmd)
   var argsCount = 0
   while true: 
     parseopt.next(p)
     case p.kind
     of cmdEnd: break 
-    of cmdLongOption, cmdShortOption: 
+    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)
+        processSwitch(key, val, pass, gCmdLineInfo)
       else: 
-        ProcessSwitch(p.key, p.val, pass, gCmdLineInfo)
+        processSwitch(p.key, p.val, pass, gCmdLineInfo)
     of cmdArgument:
       if argsCount == 0:
         options.command = p.key
@@ -79,11 +79,11 @@ proc serve*(action: proc (){.nimcall.}) =
       if line == "quit": quit()
       execute line
       echo ""
-      FlushFile(stdout)
+      flushFile(stdout)
 
   of "tcp", "":
     when useCaas:
-      var server = Socket()
+      var server = socket()
       let p = getConfigVar("server.port")
       let port = if p.len > 0: parseInt(p).TPort else: 6000.TPort
       server.bindAddr(port, getConfigVar("server.address"))
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index cacf4782e..9d1585c56 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -12,7 +12,7 @@
 
 import 
   intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
-  magicsys, condsyms, idents, lexer, options, parampatterns, strutils
+  magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees
 
 when not defined(noDocgen):
   import docgen
@@ -21,7 +21,8 @@ type
   TCandidateState* = enum 
     csEmpty, csMatch, csNoMatch
 
-  TCandidate* {.final.} = object 
+  TCandidate* {.final.} = object
+    c*: PContext
     exactMatches*: int       # also misused to prefer iters over procs
     genericMatches: int      # also misused to prefer constraints
     subtypeMatches: int
@@ -30,7 +31,8 @@ type
     state*: TCandidateState
     callee*: PType           # may not be nil!
     calleeSym*: PSym         # may be nil
-    calleeScope: int         # may be -1 for unknown scope
+    calleeScope*: int        # scope depth:
+                             # is this a top-level symbol or a nested proc?
     call*: PNode             # modified call
     bindings*: TIdTable      # maps types to types
     baseTypeMatch: bool      # needed for conversions from T to openarray[T]
@@ -38,6 +40,8 @@ type
     proxyMatch*: bool        # to prevent instantiations
     genericConverter*: bool  # true if a generic converter needs to
                              # be instantiated
+    coerceDistincts*: bool   # this is an explicit coercion that can strip away
+                             # a distrinct type
     typedescMatched: bool
     inheritancePenalty: int  # to prefer closest father object type
     errors*: seq[string]     # additional clarifications to be displayed to the
@@ -49,6 +53,8 @@ type
     isSubtype,
     isSubrange,              # subrange of the wanted type; no type conversion
                              # but apart from that counts as ``isSubtype``
+    isInferred,              # generic proc was matched against a concrete type
+    isInferredConvertible,   # same as above, but requiring proc CC conversion
     isGeneric,
     isFromIntLit,            # conversion *from* int literal; proven safe
     isEqual
@@ -58,7 +64,9 @@ const
     
 proc markUsed*(n: PNode, s: PSym)
 
-proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} = 
+proc initCandidateAux(ctx: PContext,
+                      c: var TCandidate, callee: PType) {.inline.} =
+  c.c = ctx
   c.exactMatches = 0
   c.subtypeMatches = 0
   c.convMatches = 0
@@ -71,32 +79,48 @@ proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
   c.genericConverter = false
   c.inheritancePenalty = 0
 
-proc initCandidate*(c: var TCandidate, callee: PType) = 
-  initCandidateAux(c, callee)
+proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) =
+  initCandidateAux(ctx, c, callee)
   c.calleeSym = nil
   initIdTable(c.bindings)
 
 proc put(t: var TIdTable, key, val: PType) {.inline.} =
-  IdTablePut(t, key, val)
+  idTablePut(t, key, val)
 
-proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode, 
-                    calleeScope = -1) =
-  initCandidateAux(c, callee.typ)
+proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
+                    binding: PNode, calleeScope = -1) =
+  initCandidateAux(ctx, c, callee.typ)
   c.calleeSym = callee
-  c.calleeScope = calleeScope
+  if callee.kind in skProcKinds and calleeScope == -1:
+    if callee.originatingModule == ctx.module:
+      let rootSym = if sfFromGeneric notin callee.flags: callee
+                    else: callee.owner
+      c.calleeScope = rootSym.scope.depthLevel
+    else:
+      c.calleeScope = 1
+  else:
+    c.calleeScope = calleeScope
   initIdTable(c.bindings)
   c.errors = nil
-  if binding != nil and callee.kind in RoutineKinds:
+  if binding != nil and callee.kind in routineKinds:
     var typeParams = callee.ast[genericParamsPos]
     for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
       var formalTypeParam = typeParams.sons[i-1].typ
-      #debug(formalTypeParam)
-      put(c.bindings, formalTypeParam, binding[i].typ)
+      var bound = binding[i].typ
+      if bound != nil and formalTypeParam.kind != tyTypeDesc:
+        bound = bound.skipTypes({tyTypeDesc})
+      assert bound != nil
+      put(c.bindings, formalTypeParam, bound)
 
-proc newCandidate*(callee: PSym, binding: PNode, calleeScope = -1): TCandidate =
-  initCandidate(result, callee, binding, calleeScope)
+proc newCandidate*(ctx: PContext, callee: PSym,
+                   binding: PNode, calleeScope = -1): TCandidate =
+  initCandidate(ctx, result, callee, binding, calleeScope)
+
+proc newCandidate*(ctx: PContext, callee: PType): TCandidate =
+  initCandidate(ctx, result, callee)
 
 proc copyCandidate(a: var TCandidate, b: TCandidate) = 
+  a.c = b.c
   a.exactMatches = b.exactMatches
   a.subtypeMatches = b.subtypeMatches
   a.convMatches = b.convMatches
@@ -124,7 +148,7 @@ proc sumGeneric(t: PType): int =
       result = ord(t.kind == tyGenericInvokation)
       for i in 0 .. <t.len: result += t.sons[i].sumGeneric
       break
-    of tyGenericParam, tyExpr, tyStmt, tyTypeDesc, tyTypeClass: break
+    of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc: break
     else: return 0
 
 proc complexDisambiguation(a, b: PType): int =
@@ -159,9 +183,8 @@ proc cmpCandidates*(a, b: TCandidate): int =
   if result != 0: return
   result = a.convMatches - b.convMatches
   if result != 0: return
-  if (a.calleeScope != -1) and (b.calleeScope != -1):
-    result = a.calleeScope - b.calleeScope
-    if result != 0: return
+  result = a.calleeScope - b.calleeScope
+  if result != 0: return
   # the other way round because of other semantics:
   result = b.inheritancePenalty - a.inheritancePenalty
   if result != 0: return
@@ -169,11 +192,11 @@ proc cmpCandidates*(a, b: TCandidate): int =
   result = complexDisambiguation(a.callee, b.callee)
 
 proc writeMatches*(c: TCandidate) = 
-  Writeln(stdout, "exact matches: " & $c.exactMatches)
-  Writeln(stdout, "subtype matches: " & $c.subtypeMatches)
-  Writeln(stdout, "conv matches: " & $c.convMatches)
-  Writeln(stdout, "intconv matches: " & $c.intConvMatches)
-  Writeln(stdout, "generic matches: " & $c.genericMatches)
+  writeln(stdout, "exact matches: " & $c.exactMatches)
+  writeln(stdout, "subtype matches: " & $c.subtypeMatches)
+  writeln(stdout, "conv matches: " & $c.convMatches)
+  writeln(stdout, "intconv matches: " & $c.intConvMatches)
+  writeln(stdout, "generic matches: " & $c.genericMatches)
 
 proc argTypeToString(arg: PNode): string =
   if arg.kind in nkSymChoices:
@@ -203,7 +226,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
     add(result, argTypeToString(arg))
     if i != sonsLen(n) - 1: add(result, ", ")
 
-proc typeRel*(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation
+proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation
 proc concreteType(c: TCandidate, t: PType): PType = 
   case t.kind
   of tyArrayConstr: 
@@ -223,7 +246,7 @@ proc concreteType(c: TCandidate, t: PType): PType =
         # proc sort[T](cmp: proc(a, b: T): int = cmp)
       if result.kind != tyGenericParam: break
   of tyGenericInvokation:
-    InternalError("cannot resolve type: " & typeToString(t))
+    internalError("cannot resolve type: " & typeToString(t))
     result = t
   else:
     result = t                # Note: empty is valid here
@@ -296,57 +319,86 @@ proc minRel(a, b: TTypeRelation): TTypeRelation =
   if a <= b: result = a
   else: result = b
   
-proc tupleRel(c: var TCandidate, f, a: PType): TTypeRelation =
+proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
   result = isNone
-  if sameType(f, a):
-    result = isEqual
+  if sameType(f, a): result = isEqual
   elif sonsLen(a) == sonsLen(f):
     result = isEqual
-    for i in countup(0, sonsLen(f) - 1):
+    let firstField = if f.kind == tyTuple: 0
+                     else: 1 
+    for i in countup(firstField, sonsLen(f) - 1):
       var m = typeRel(c, f.sons[i], a.sons[i])
       if m < isSubtype: return isNone
       result = minRel(result, m)
     if f.n != nil and a.n != nil:
       for i in countup(0, sonsLen(f.n) - 1):
         # check field names:
-        if f.n.sons[i].kind != nkSym: InternalError(f.n.info, "tupleRel")
-        elif a.n.sons[i].kind != nkSym: InternalError(a.n.info, "tupleRel")
+        if f.n.sons[i].kind != nkSym: internalError(f.n.info, "recordRel")
+        elif a.n.sons[i].kind != nkSym: internalError(a.n.info, "recordRel")
         else:
           var x = f.n.sons[i].sym
           var y = a.n.sons[i].sym
+          if f.kind == tyObject and typeRel(c, x.typ, y.typ) < isSubtype:
+            return isNone
           if x.name.id != y.name.id: return isNone
 
 proc allowsNil(f: PType): TTypeRelation {.inline.} =
   result = if tfNotNil notin f.flags: isSubtype else: isNone
 
-proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
-  proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
-    result = f.kind != a.kind and (f.kind == tyVar or a.kind == tyVar)
+proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
+  result = f.kind != a.kind and (f.kind == tyVar or a.kind == tyVar)
+
+proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
+  var f = f
+
+  if a.isMetaType:
+    if f.isMetaType:
+      # We are matching a generic proc (as proc param)
+      # to another generic type appearing in the proc
+      # signature. There is a change that the target
+      # type is already fully-determined, so we are 
+      # going to try resolve it
+      f = generateTypeInstance(c.c, c.bindings, c.call.info, f)
+      if f == nil or f.isMetaType:
+        # no luck resolving the type, so the inference fails
+        return isNone
+    let reverseRel = typeRel(c, a, f)
+    if reverseRel == isGeneric:
+      result = isInferred
+      inc c.genericMatches
+  else:
+    result = typeRel(c, f, a)
 
+  if result <= isSubtype or inconsistentVarTypes(f, a):
+    result = isNone
+ 
+  if result == isEqual:
+    inc c.exactMatches
+    
+proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
   case a.kind
   of tyProc:
     if sonsLen(f) != sonsLen(a): return
-    # Note: We have to do unification for the parameters before the
-    # return type!
     result = isEqual      # start with maximum; also correct for no
                           # params at all
-    for i in countup(1, sonsLen(f)-1):
-      var m = typeRel(c, f.sons[i], a.sons[i])
-      if m <= isSubtype or inconsistentVarTypes(f.sons[i], a.sons[i]):
-        return isNone
-      else: result = minRel(m, result)
+    
+    template checkParam(f, a) =
+      result = minRel(result, procParamTypeRel(c, f, a))
+      if result == isNone: return
+
+    # Note: We have to do unification for the parameters before the
+    # return type!
+    for i in 1 .. <f.sonsLen:
+      checkParam(f.sons[i], a.sons[i])
+    
     if f.sons[0] != nil:
       if a.sons[0] != nil:
-        var m = typeRel(c, f.sons[0], a.sons[0])
-        # Subtype is sufficient for return types!
-        if m < isSubtype or inconsistentVarTypes(f.sons[0], a.sons[0]):
-          return isNone
-        elif m == isSubtype: result = isConvertible
-        else: result = minRel(m, result)
+        checkParam(f.sons[0], a.sons[0])
       else:
         return isNone
     elif a.sons[0] != nil:
       return isNone
+
     if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
       return isNone
     elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
@@ -354,20 +406,20 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
       return isNone
     elif f.flags * {tfIterator} != a.flags * {tfIterator}:
       return isNone
-    elif f.callconv != a.callconv:
+    elif f.callConv != a.callConv:
       # valid to pass a 'nimcall' thingie to 'closure':
-      if f.callconv == ccClosure and a.callconv == ccDefault:
-        result = isConvertible
+      if f.callConv == ccClosure and a.callConv == ccDefault:
+        result = if result != isInferred: isConvertible
+                 else: isInferredConvertible
       else:
         return isNone
     when useEffectSystem:
       if not compatibleEffects(f, a): return isNone
-  of tyNil: result = f.allowsNil
-  else: nil
-
-proc matchTypeClass(c: var TCandidate, f, a: PType): TTypeRelation =
-  result = if matchTypeClass(c.bindings, f, a): isGeneric
-           else: isNone
+  of tyNil:
+    result = f.allowsNil
+  of tyIter:
+    if tfIterator in f.flags: result = typeRel(c, f.base, a.base)
+  else: discard
 
 proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
   let
@@ -385,7 +437,78 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
   else:
     result = isNone
 
-proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
+proc matchUserTypeClass*(c: PContext, m: var TCandidate,
+                         ff, a: PType): TTypeRelation =
+  var body = ff.skipTypes({tyUserTypeClassInst})
+
+  openScope(c)
+  inc c.inTypeClass
+
+  finally:
+    dec c.inTypeClass
+    closeScope(c)
+
+  if ff.kind == tyUserTypeClassInst:
+    for i in 1 .. <(ff.len - 1):
+      var
+        typeParamName = ff.base.sons[i-1].sym.name
+        typ = ff.sons[i]
+        param = newSym(skType, typeParamName, body.sym, body.sym.info)
+        
+      param.typ = makeTypeDesc(c, typ)
+      addDecl(c, param)
+
+  for param in body.n[0]:
+    var
+      dummyName: PNode
+      dummyType: PType
+    
+    if param.kind == nkVarTy:
+      dummyName = param[0]
+      dummyType = if a.kind != tyVar: makeVarType(c, a)
+                  else: a
+    else:
+      dummyName = param
+      dummyType = a
+
+    internalAssert dummyName.kind == nkIdent
+    var dummyParam = newSym(skType, dummyName.ident, body.sym, body.sym.info)
+    dummyParam.typ = dummyType
+    addDecl(c, dummyParam)
+
+  var checkedBody = c.semTryExpr(c, body.n[3].copyTree, bufferErrors = false)
+  m.errors = bufferedMsgs
+  clearBufferedMsgs()
+  if checkedBody == nil: return isNone
+
+  if checkedBody.kind == nkStmtList:
+    for stmt in checkedBody:
+      case stmt.kind
+      of nkReturnStmt: discard
+      of nkTypeSection: discard
+      of nkConstDef: discard
+      else: discard
+    
+  return isGeneric
+
+proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool =
+  if rules.kind == nkWith:
+    for r in rules:
+      if r.considerAcc == callIdent: return true
+    return false
+  else:
+    for r in rules:
+      if r.considerAcc == callIdent: return false
+    return true
+
+proc maybeSkipDistinct(t: PType, callee: PSym): PType =
+  if t != nil and t.kind == tyDistinct and t.n != nil and
+     shouldSkipDistinct(t.n, callee.name):
+    result = t.base
+  else:
+    result = t
+
+proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # typeRel can be used to establish various relationships between types:
   #
   # 1) When used with concrete types, it will check for type equivalence
@@ -401,22 +524,41 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
   # order to give preferrence to the most specific one:
   #
   # seq[seq[any]] is a strict subset of seq[any] and hence more specific.
-  
+
   result = isNone
   assert(f != nil)
-  assert(a != nil)
+  
+  if f.kind == tyExpr:
+    put(c.bindings, f, aOrig)
+    return isGeneric
+
+  assert(aOrig != nil)
+
+  # var and static arguments match regular modifier-free types
+  let a = aOrig.skipTypes({tyStatic, tyVar}).maybeSkipDistinct(c.calleeSym)
+  # XXX: Theoretically, maybeSkipDistinct could be called before we even
+  # start the param matching process. This could be done in `prepareOperand`
+  # for example, but unfortunately `prepareOperand` is not called in certain
+  # situation when nkDotExpr are rotated to nkDotCalls
+  
   if a.kind == tyGenericInst and
       skipTypes(f, {tyVar}).kind notin {
         tyGenericBody, tyGenericInvokation,
-        tyGenericParam, tyTypeClass}:
+        tyGenericInst, tyGenericParam} + tyTypeClasses:
     return typeRel(c, f, lastSon(a))
-  if a.kind == tyVar and f.kind != tyVar:
-    return typeRel(c, f, a.sons[0])
-  
+
   template bindingRet(res) =
-    when res == isGeneric: put(c.bindings, f, a)
+    when res == isGeneric:
+      if doBind:
+        let bound = aOrig.skipTypes({tyRange}).skipIntLit
+        if doBind: put(c.bindings, f, bound)
     return res
- 
+
+  template considerPreviousT(body: stmt) {.immediate.} =
+    var prev = PType(idTableGet(c.bindings, f))
+    if prev == nil: body
+    else: return typeRel(c, prev, a)
+
   case a.kind
   of tyOr:
     # seq[int|string] vs seq[number]
@@ -454,13 +596,13 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
   of tyAnything:
     return if f.kind == tyAnything: isGeneric
            else: isNone
-  else: nil
+  else: discard
 
   case f.kind
-  of tyEnum: 
+  of tyEnum:
     if a.kind == f.kind and sameEnumTypes(f, a): result = isEqual
     elif sameEnumTypes(f, skipTypes(a, {tyRange})): result = isSubtype
-  of tyBool, tyChar: 
+  of tyBool, tyChar:
     if a.kind == f.kind: result = isEqual
     elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
   of tyRange:
@@ -470,10 +612,11 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
       #if result < isGeneric: result = isNone
       if result notin {isNone, isGeneric}:
         result = typeRangeRel(f, a)
-    elif skipTypes(f, {tyRange}).kind == a.kind:
-      result = isIntConv
-    elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
-      result = isConvertible  # a convertible to f
+    else:
+      if skipTypes(f, {tyRange}).kind == a.kind:
+        result = isIntConv
+      elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
+        result = isConvertible  # a convertible to f
   of tyInt:      result = handleRange(f, a, tyInt8, tyInt32)
   of tyInt8:     result = handleRange(f, a, tyInt8, tyInt8)
   of tyInt16:    result = handleRange(f, a, tyInt8, tyInt16)
@@ -488,9 +631,9 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
   of tyFloat32:  result = handleFloatRange(f, a)
   of tyFloat64:  result = handleFloatRange(f, a)
   of tyFloat128: result = handleFloatRange(f, a)
-  of tyVar: 
-    if a.kind == f.kind: result = typeRel(c, base(f), base(a))
-    else: result = typeRel(c, base(f), a)
+  of tyVar:
+    if aOrig.kind == tyVar: result = typeRel(c, f.base, aOrig.base)
+    else: result = typeRel(c, f.base, aOrig)
   of tyArray, tyArrayConstr:
     # tyArrayConstr cannot happen really, but
     # we wanna be safe here
@@ -505,11 +648,29 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
         else:
           fRange = prev
       result = typeRel(c, f.sons[1], a.sons[1])
-      if result < isGeneric: result = isNone
-      elif lengthOrd(fRange) != lengthOrd(a): result = isNone
-    else: nil
+      if result < isGeneric:
+        result = isNone
+      elif tfUnresolved in fRange.flags and
+           rangeHasStaticIf(fRange):
+        # This is a range from an array instantiated with a generic
+        # static param. We must extract the static param here and bind
+        # it to the size of the currently supplied array.
+        var
+          rangeStaticT = fRange.getStaticTypeFromRange
+          replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType])
+          inputUpperBound = a.sons[0].n[1].intVal
+        # we must correct for the off-by-one discrepancy between
+        # ranges and static params:
+        replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
+        put(c.bindings, rangeStaticT, replacementT)
+        result = isGeneric
+      elif lengthOrd(fRange) != lengthOrd(a):
+        result = isNone
+    else: discard
   of tyOpenArray, tyVarargs:
-    case a.Kind
+    # varargs[expr] is special
+    if f.kind == tyVarargs and f.sons[0].kind == tyExpr: return
+    case a.kind
     of tyOpenArray, tyVarargs:
       result = typeRel(c, base(f), base(a))
       if result < isGeneric: result = isNone
@@ -528,9 +689,9 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
         result = isConvertible
       elif typeRel(c, base(f), a.sons[0]) >= isGeneric: 
         result = isConvertible
-    else: nil
+    else: discard
   of tySequence:
-    case a.Kind
+    case a.kind
     of tySequence:
       if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
         result = isSubtype
@@ -540,26 +701,27 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
         elif tfNotNil in f.flags and tfNotNil notin a.flags:
           result = isNilConversion
     of tyNil: result = f.allowsNil
-    else: nil
+    else: discard
   of tyOrdinal:
     if isOrdinalType(a):
       var x = if a.kind == tyOrdinal: a.sons[0] else: a
-     
-      if f.sonsLen == 0:
+      if f.sons[0].kind == tyNone:
         result = isGeneric
       else:
         result = typeRel(c, f.sons[0], x)
         if result < isGeneric: result = isNone
     elif a.kind == tyGenericParam:
       result = isGeneric
-  of tyForward: InternalError("forward type in typeRel()")
+  of tyForward: internalError("forward type in typeRel()")
   of tyNil:
     if a.kind == f.kind: result = isEqual
   of tyTuple: 
-    if a.kind == tyTuple: result = tupleRel(c, f, a)
+    if a.kind == tyTuple: result = recordRel(c, f, a)
   of tyObject:
     if a.kind == tyObject:
-      if sameObjectTypes(f, a): result = isEqual
+      if sameObjectTypes(f, a):
+        result = isEqual
+        # elif tfHasMeta in f.flags: result = recordRel(c, f, a)
       else:
         var depth = isObjectSubtype(a, f)
         if depth > 0:
@@ -567,6 +729,7 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
           result = isSubtype
   of tyDistinct:
     if (a.kind == tyDistinct) and sameDistinctTypes(f, a): result = isEqual
+    elif c.coerceDistincts: result = typeRel(c, f.base, a)
   of tySet: 
     if a.kind == tySet: 
       if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
@@ -575,24 +738,18 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
         result = typeRel(c, f.sons[0], a.sons[0])
         if result <= isConvertible: 
           result = isNone     # BUGFIX!
-  of tyPtr: 
-    case a.kind
-    of tyPtr: 
-      result = typeRel(c, base(f), base(a))
-      if result <= isConvertible: result = isNone
-      elif tfNotNil in f.flags and tfNotNil notin a.flags:
-        result = isNilConversion
-    of tyNil: result = f.allowsNil
-    else: nil
-  of tyRef: 
-    case a.kind
-    of tyRef:
-      result = typeRel(c, base(f), base(a))
+  of tyPtr, tyRef:
+    if a.kind == f.kind:
+      # ptr[R, T] can be passed to ptr[T], but not the other way round:
+      if a.len < f.len: return isNone
+      for i in 0..f.len-2:
+        if typeRel(c, f.sons[i], a.sons[i]) == isNone: return isNone
+      result = typeRel(c, f.lastSon, a.lastSon)
       if result <= isConvertible: result = isNone
       elif tfNotNil in f.flags and tfNotNil notin a.flags:
         result = isNilConversion
-    of tyNil: result = f.allowsNil
-    else: nil
+    elif a.kind == tyNil: result = f.allowsNil
+    else: discard
   of tyProc:
     result = procTypeRel(c, f, a)
     if result != isNone and tfNotNil in f.flags and tfNotNil notin a.flags:
@@ -607,8 +764,12 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
     of tyNil: result = f.allowsNil
     of tyProc:
       if a.callConv != ccClosure: result = isConvertible
-    of tyPtr, tyCString: result = isConvertible
-    else: nil
+    of tyPtr:
+      # 'pointer' is NOT compatible to regionized pointers
+      # so 'dealloc(regionPtr)' fails:
+      if a.len == 1: result = isConvertible
+    of tyCString: result = isConvertible
+    else: discard
   of tyString: 
     case a.kind
     of tyString: 
@@ -617,10 +778,10 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
       else:
         result = isEqual
     of tyNil: result = f.allowsNil
-    else: nil
+    else: discard
   of tyCString:
     # conversion from string to cstring is automatic:
-    case a.Kind
+    case a.kind
     of tyCString:
       if tfNotNil in f.flags and tfNotNil notin a.flags:
         result = isNilConversion
@@ -629,36 +790,52 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
     of tyNil: result = f.allowsNil
     of tyString: result = isConvertible
     of tyPtr:
-      if a.sons[0].kind == tyChar: result = isConvertible
-    of tyArray: 
+      # ptr[Tag, char] is not convertible to 'cstring' for now:
+      if a.len == 1 and a.sons[0].kind == tyChar: result = isConvertible
+    of tyArray:
       if (firstOrd(a.sons[0]) == 0) and
           (skipTypes(a.sons[0], {tyRange}).kind in {tyInt..tyInt64}) and
           (a.sons[1].kind == tyChar): 
         result = isConvertible
-    else: nil
+    else: discard
 
   of tyEmpty:
     if a.kind == tyEmpty: result = isEqual
 
   of tyGenericInst:
-    result = typeRel(c, lastSon(f), a)
+    let roota = a.skipGenericAlias
+    let rootf = f.skipGenericAlias
+    if a.kind == tyGenericInst and roota.base == rootf.base:
+      for i in 1 .. rootf.sonsLen-2:
+        let ff = rootf.sons[i]
+        let aa = roota.sons[i]
+        result = typeRel(c, ff, aa)
+        if result == isNone: return        
+        if ff.kind == tyRange and result != isEqual: return isNone
+
+      result = isGeneric
+    else:
+      result = typeRel(c, lastSon(f), a)
 
   of tyGenericBody:
-    let ff = lastSon(f)
-    if ff != nil: result = typeRel(c, ff, a)
+    considerPreviousT:
+      if a.kind == tyGenericInst and a.sons[0] == f:
+        bindingRet isGeneric
+      let ff = lastSon(f)
+      if ff != nil: result = typeRel(c, ff, a)
 
   of tyGenericInvokation:
     var x = a.skipGenericAlias
     if x.kind == tyGenericInvokation or f.sons[0].kind != tyGenericBody:
       #InternalError("typeRel: tyGenericInvokation -> tyGenericInvokation")
       # simply no match for now:
-      nil
+      discard
     elif x.kind == tyGenericInst and 
           (f.sons[0] == x.sons[0]) and
           (sonsLen(x) - 1 == sonsLen(f)):
       for i in countup(1, sonsLen(f) - 1):
         if x.sons[i].kind == tyGenericParam:
-          InternalError("wrong instantiated type!")
+          internalError("wrong instantiated type!")
         elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return 
       result = isGeneric
     else:
@@ -668,104 +845,175 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
         for i in countup(1, sonsLen(f) - 1):
           var x = PType(idTableGet(c.bindings, f.sons[0].sons[i - 1]))
           if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
-            InternalError("wrong instantiated type!")
+            internalError("wrong instantiated type!")
           put(c.bindings, f.sons[i], x)
   
   of tyAnd:
-    for branch in f.sons:
-      if typeRel(c, branch, a) == isNone:
-        return isNone
+    considerPreviousT:
+      for branch in f.sons:
+        if typeRel(c, branch, aOrig) == isNone:
+          return isNone
 
-    bindingRet isGeneric
+      bindingRet isGeneric
 
   of tyOr:
-    for branch in f.sons:
-      if typeRel(c, branch, a) != isNone:
-        bindingRet isGeneric
-
-    return isNone
+    considerPreviousT:
+      for branch in f.sons:
+        if typeRel(c, branch, aOrig) != isNone:
+          bindingRet isGeneric
+       
+      return isNone
 
   of tyNot:
-    for branch in f.sons:
-      if typeRel(c, branch, a) != isNone:
-        return isNone
-    
-    bindingRet isGeneric
+    considerPreviousT:
+      for branch in f.sons:
+        if typeRel(c, branch, aOrig) != isNone:
+          return isNone
+      
+      bindingRet isGeneric
 
   of tyAnything:
-    var prev = PType(idTableGet(c.bindings, f))
-    if prev == nil:
+    considerPreviousT:
       var concrete = concreteType(c, a)
       if concrete != nil and doBind:
         put(c.bindings, f, concrete)
       return isGeneric
-    else:
-      return typeRel(c, prev, a)
-    
-  of tyGenericParam, tyTypeClass:
+
+  of tyBuiltInTypeClass:
+    considerPreviousT:
+      let targetKind = f.sons[0].kind
+      if targetKind == a.skipTypes({tyRange, tyGenericInst}).kind or
+         (targetKind in {tyProc, tyPointer} and a.kind == tyNil):
+        put(c.bindings, f, a)
+        return isGeneric
+      else:
+        return isNone
+
+  of tyUserTypeClass, tyUserTypeClassInst:
+    considerPreviousT:
+      result = matchUserTypeClass(c.c, c, f, aOrig)
+      if result == isGeneric:
+        put(c.bindings, f, a)
+
+  of tyCompositeTypeClass:
+    considerPreviousT:
+      if typeRel(c, f.sons[1], a) != isNone:
+        put(c.bindings, f, a)
+        return isGeneric
+      else:
+        return isNone
+
+  of tyGenericParam:
     var x = PType(idTableGet(c.bindings, f))
     if x == nil:
-      if c.calleeSym != nil and c.calleeSym.kind == skType and
+      if c.callee.kind == tyGenericBody and
          f.kind == tyGenericParam and not c.typedescMatched:
         # XXX: The fact that generic types currently use tyGenericParam for 
         # their parameters is really a misnomer. tyGenericParam means "match
         # any value" and what we need is "match any type", which can be encoded
         # by a tyTypeDesc params. Unfortunately, this requires more substantial
         # changes in semtypinst and elsewhere.
-        if a.kind == tyTypeDesc:
-          if f.sons == nil or f.sons.len == 0:
+        if tfWildcard in a.flags:
+          result = isGeneric
+        elif a.kind == tyTypeDesc:
+          if f.sonsLen == 0:
             result = isGeneric
           else:
-            InternalAssert a.sons != nil and a.sons.len > 0
+            internalAssert a.sons != nil and a.sons.len > 0
             c.typedescMatched = true
-            result = typeRel(c, f.sons[0], a.sons[0])
+            result = typeRel(c, f.base, a.base)
         else:
           result = isNone
       else:
-        if a.kind == tyTypeClass:
-          result = isGeneric
+        if f.sonsLen > 0 and f.sons[0].kind != tyNone:
+          result = typeRel(c, f.lastSon, a)
         else:
-          result = matchTypeClass(c, f, a)
-        
+          result = isGeneric
+
       if result == isGeneric:
-        var concrete = concreteType(c, a)
-        if concrete == nil:
-          result = isNone
+        var concrete = a
+        if tfWildcard in a.flags:
+          a.sym.kind = skType
+          a.flags.excl tfWildcard
         else:
-          if doBind: put(c.bindings, f, concrete)
+          concrete = concreteType(c, a)
+          if concrete == nil:
+            return isNone
+        if doBind:
+          put(c.bindings, f, concrete)
     elif a.kind == tyEmpty:
       result = isGeneric
     elif x.kind == tyGenericParam:
       result = isGeneric
     else:
       result = typeRel(c, x, a) # check if it fits
+  
+  of tyStatic:
+    if aOrig.kind == tyStatic:
+      result = typeRel(c, f.lastSon, a)
+      if result != isNone: put(c.bindings, f, aOrig)
+    else:
+      result = isNone
+
   of tyTypeDesc:
     var prev = PType(idTableGet(c.bindings, f))
     if prev == nil:
-      if a.kind == tyTypeDesc:
-        if f.sonsLen == 0:
-          result = isGeneric
-        else:
-          result = matchTypeClass(c, f, a.sons[0])
-        if result == isGeneric:
-          put(c.bindings, f, a)
+      # proc foo(T: typedesc, x: T)
+      # when `f` is an unresolved typedesc, `a` could be any
+      # type, so we should not perform this check earlier
+      if a.kind != tyTypeDesc: return isNone
+    
+      if f.base.kind == tyNone:
+        result = isGeneric
+      else:
+        result = typeRel(c, f.base, a.base)
+      
+      if result != isNone:
+        put(c.bindings, f, a)
+    else:
+      if tfUnresolved in f.flags:
+        result = typeRel(c, prev.base, a)
+      elif a.kind == tyTypeDesc:
+        result = typeRel(c, prev.base, a.base)
       else:
         result = isNone
+ 
+  of tyIter:
+    if a.kind == tyIter or 
+      (a.kind == tyProc and tfIterator in a.flags):
+      result = typeRel(c, f.base, a.base)
     else:
-      InternalAssert prev.sonsLen == 1
-      let toMatch = if tfUnresolved in f.flags: a
-                    else: a.sons[0]
-      result = typeRel(c, prev.sons[0], toMatch)
-  of tyExpr, tyStmt:
+      result = isNone
+
+  of tyStmt:
     result = isGeneric
+  
   of tyProxy:
     result = isEqual
-  else: internalError("typeRel: " & $f.kind)
+
+  of tyFromExpr:
+    # fix the expression, so it contains the already instantiated types
+    let instantiated = replaceTypesInBody(c.c, c.bindings, f.n)
+    let reevaluted = c.c.semExpr(c.c, instantiated)
+    case reevaluted.typ.kind
+    of tyTypeDesc:
+      result = typeRel(c, a, reevaluted.typ.base)
+    of tyStatic:
+      result = typeRel(c, a, reevaluted.typ.base)
+      if result != isNone and reevaluted.typ.n != nil:
+        if not exprStructuralEquivalent(aOrig.n, reevaluted.typ.n):
+          result = isNone
+    else:
+      localError(f.n.info, errTypeExpected)
+      result = isNone
+  
+  else:
+    internalAssert false
   
-proc cmpTypes*(f, a: PType): TTypeRelation = 
-  var c: TCandidate
-  InitCandidate(c, f)
-  result = typeRel(c, f, a)
+proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation = 
+  var m: TCandidate
+  initCandidate(c, m, f)
+  result = typeRel(m, f, a)
 
 proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, 
                          f: PType): PType = 
@@ -773,7 +1021,7 @@ proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
   if result == nil: 
     result = generateTypeInstance(c, m.bindings, arg, f)
   if result == nil:
-    InternalError(arg.info, "getInstantiatedType")
+    internalError(arg.info, "getInstantiatedType")
     result = errorType(c)
   
 proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, 
@@ -786,7 +1034,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
       result.typ = errorType(c)
   else:
     result.typ = f
-  if result.typ == nil: InternalError(arg.info, "implicitConv")
+  if result.typ == nil: internalError(arg.info, "implicitConv")
   addSon(result, ast.emptyNode)
   addSon(result, arg)
 
@@ -825,7 +1073,7 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
   var call = newNodeI(nkCall, arg.info)
   call.add(f.n.copyTree)
   call.add(arg.copyTree)
-  result = c.semOverloadedCall(c, call, call, RoutineKinds)
+  result = c.semOverloadedCall(c, call, call, routineKinds)
   if result != nil:
     # resulting type must be consistent with the other arguments:
     var r = typeRel(m, f.sons[0], result.typ)
@@ -836,110 +1084,80 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
       result.typ = getInstantiatedType(c, arg, m, base(f))
     m.baseTypeMatch = true
 
-proc matchUserTypeClass*(c: PContext, m: var TCandidate,
-                         arg: PNode, f, a: PType): PNode =
-  if f.n == nil:
-    let r = typeRel(m, f, a)
-    return if r == isGeneric: arg else: nil
- 
-  var prev = PType(idTableGet(m.bindings, f))
-  if prev != nil:
-    if sameType(prev, a): return arg
-    else: return nil
-
-  # pushInfoContext(arg.info)
-  openScope(c)
-  inc c.InTypeClass
+proc isInlineIterator*(t: PType): bool =
+  result = t.kind == tyIter or
+          (t.kind == tyBuiltInTypeClass and t.base.kind == tyIter)
 
-  finally:
-    dec c.InTypeClass
-    closeScope(c)
-
-  for param in f.n[0]:
-    var
-      dummyName: PNode
-      dummyType: PType
-    
-    if param.kind == nkVarTy:
-      dummyName = param[0]
-      dummyType = makeVarType(c, a)
-    else:
-      dummyName = param
-      dummyType = a
-
-    InternalAssert dummyName.kind == nkIdent
-    var dummyParam = newSym(skType, dummyName.ident, f.sym, f.sym.info)
-    dummyParam.typ = dummyType
-    addDecl(c, dummyParam)
-
-  for stmt in f.n[3]:
-    var e = c.semTryExpr(c, copyTree(stmt), bufferErrors = false)
-    m.errors = bufferedMsgs
-    clearBufferedMsgs()
-    if e == nil: return nil
-
-    case e.kind
-    of nkReturnStmt: nil
-    of nkTypeSection: nil
-    of nkConstDef: nil
-    else: nil
-  
-  result = arg
-  put(m.bindings, f, a)
-
-proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
+proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
                         argSemantized, argOrig: PNode): PNode =
   var
-    r: TTypeRelation
+    fMaybeStatic = f.skipTypes({tyDistinct})
     arg = argSemantized
-
-  let
-    a = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc})
+    argType = argType
+    c = m.c
+ 
+  if tfHasStatic in fMaybeStatic.flags:
+    # XXX: When implicit statics are the default
+    # this will be done earlier - we just have to
+    # make sure that static types enter here
+     
+    # XXX: weaken tyGenericParam and call it tyGenericPlaceholder
+    # and finally start using tyTypedesc for generic types properly.
+    if argType.kind == tyGenericParam and tfWildcard in argType.flags:
+      argType.assignType(f)
+      # put(m.bindings, f, argType)
+      return argSemantized
+
+    if argType.kind == tyStatic:
+      if m.callee.kind == tyGenericBody:
+        result = newNodeI(nkType, argOrig.info)
+        result.typ = makeTypeFromExpr(c, arg)
+        return
+    else:
+      var evaluated = c.semTryConstExpr(c, arg)
+      if evaluated != nil:
+        arg.typ = newTypeS(tyStatic, c)
+        arg.typ.sons = @[evaluated.typ]
+        arg.typ.n = evaluated
+        argType = arg.typ
+ 
+  var
+    a = if c.inTypeClass > 0: argType.skipTypes({tyTypeDesc, tyFieldAccessor})
         else: argType
-    fMaybeExpr = f.skipTypes({tyDistinct})
+ 
+    r = typeRel(m, f, a)
 
-  case fMaybeExpr.kind
-  of tyExpr:
-    if fMaybeExpr.sonsLen == 0:
-      r = isGeneric
-    else:
-      if a.kind == tyExpr:
-        InternalAssert a.len > 0
-        r = typeRel(m, f.lastSon, a.lastSon)
-      else:
-        let match = matchTypeClass(m.bindings, fMaybeExpr, a)
-        if not match: r = isNone
-        else:
-          # XXX: Ideally, this should happen much earlier somewhere near 
-          # semOpAux, but to do that, we need to be able to query the 
-          # overload set to determine whether compile-time value is expected
-          # for the param before entering the full-blown sigmatch algorithm.
-          # This is related to the immediate pragma since querying the
-          # overload set could help there too.
-          var evaluated = c.semConstExpr(c, arg)
-          if evaluated != nil:
-            r = isGeneric
-            arg.typ = newTypeS(tyExpr, c)
-            arg.typ.sons = @[evaluated.typ]
-            arg.typ.n = evaluated
-        
-    if r == isGeneric:
-      put(m.bindings, f, arg.typ)
-  of tyTypeClass, tyParametricTypeClass:
-    if fMaybeExpr.n != nil:
-      let match = matchUserTypeClass(c, m, arg, fMaybeExpr, a)
-      if match != nil:
-        r = isGeneric
-        arg = match
-      else:
-        r = isNone
+  if r != isNone and m.calleeSym != nil and
+     m.calleeSym.kind in {skMacro, skTemplate}:
+    # XXX: duplicating this is ugly, maybe we should move this
+    # directly into typeRel using return-like templates
+    case r
+    of isConvertible, isIntConv: inc(m.convMatches)
+    of isSubtype, isSubrange: inc(m.subtypeMatches)
+    of isGeneric, isInferred: inc(m.genericMatches)
+    of isInferredConvertible: inc(m.genericMatches); inc(m.convMatches)
+    of isFromIntLit: inc(m.intConvMatches, 256)
+    of isEqual: inc(m.exactMatches)
+    of isNone: discard
+
+    if f.kind == tyStmt and argOrig.kind == nkDo:
+      return argOrig[bodyPos]
+    elif f.kind == tyTypeDesc:
+      return arg
+    elif f.kind == tyStatic:
+      return arg.typ.n
     else:
-      r = typeRel(m, f, a)
-  else:
-    r = typeRel(m, f, a)
+      return argOrig
+
+  if r != isNone and f.isInlineIterator:
+    var inlined = newTypeS(tyStatic, c)
+    inlined.sons = @[argType]
+    inlined.n = argSemantized
+    put(m.bindings, f, inlined)
+    return argSemantized
 
   case r
-  of isConvertible: 
+  of isConvertible:
     inc(m.convMatches)
     result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
   of isIntConv:
@@ -954,22 +1172,24 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
     inc(m.subtypeMatches)
     #result = copyTree(arg)
     result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isGeneric:
+  of isInferred, isInferredConvertible:
     inc(m.genericMatches)
-    if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}:
-      if f.kind == tyStmt and argOrig.kind == nkDo:
-        result = argOrig[bodyPos]
-      elif f.kind == tyTypeDesc:
-        result = arg
-      else:
-        result = argOrig
+    if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
+      result = c.semInferredLambda(c, m.bindings, arg)
     else:
-      result = copyTree(arg)
-      result.typ = getInstantiatedType(c, arg, m, f) 
-      # BUG: f may not be the right key!
-      if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
-        result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) 
-        # BUGFIX: use ``result.typ`` and not `f` here
+      let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info)
+      result = newSymNode(inferred, arg.info)
+    if r == isInferredConvertible:
+      inc(m.convMatches)
+      result = implicitConv(nkHiddenStdConv, f, result, m, c)
+  of isGeneric:
+    inc(m.genericMatches)
+    result = copyTree(arg)
+    result.typ = getInstantiatedType(c, arg, m, f)
+    # BUG: f may not be the right key!
+    if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
+      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+      # BUGFIX: use ``result.typ`` and not `f` here
   of isFromIntLit:
     # too lazy to introduce another ``*matches`` field, so we conflate
     # ``isIntConv`` and ``isIntLit`` here:
@@ -1003,25 +1223,27 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
         else:
           result = userConvMatch(c, m, base(f), a, arg)
 
-proc ParamTypesMatch*(c: PContext, m: var TCandidate, f, a: PType, 
+proc paramTypesMatch*(m: var TCandidate, f, a: PType,
                       arg, argOrig: PNode): PNode =
   if arg == nil or arg.kind notin nkSymChoices:
-    result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
+    result = paramTypesMatchAux(m, f, a, arg, argOrig)
   else: 
     # CAUTION: The order depends on the used hashing scheme. Thus it is
     # incorrect to simply use the first fitting match. However, to implement
     # this correctly is inefficient. We have to copy `m` here to be able to
     # roll back the side effects of the unification algorithm.
+
+    let c = m.c
     var x, y, z: TCandidate
-    initCandidate(x, m.callee)
-    initCandidate(y, m.callee)
-    initCandidate(z, m.callee)
+    initCandidate(c, x, m.callee)
+    initCandidate(c, y, m.callee)
+    initCandidate(c, z, m.callee)
     x.calleeSym = m.calleeSym
     y.calleeSym = m.calleeSym
     z.calleeSym = m.calleeSym
     var best = -1
     for i in countup(0, sonsLen(arg) - 1): 
-      if arg.sons[i].sym.kind in {skProc, skIterator, skMethod, skConverter}: 
+      if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}+skIterators:
         copyCandidate(z, m)
         var r = typeRel(z, f, arg.sons[i].typ)
         if r != isNone: 
@@ -1032,26 +1254,26 @@ proc ParamTypesMatch*(c: PContext, m: var TCandidate, f, a: PType,
             x.state = csMatch
           of csMatch: 
             var cmp = cmpCandidates(x, z)
-            if cmp < 0: 
+            if cmp < 0:
               best = i
               x = z
-            elif cmp == 0: 
+            elif cmp == 0:
               y = z           # z is as good as x
     if x.state == csEmpty: 
       result = nil
     elif (y.state == csMatch) and (cmpCandidates(x, y) == 0): 
       if x.state != csMatch: 
-        InternalError(arg.info, "x.state is not csMatch") 
+        internalError(arg.info, "x.state is not csMatch") 
       # ambiguous: more than one symbol fits
       result = nil
     else: 
       # only one valid interpretation found:
       markUsed(arg, arg.sons[best].sym)
-      result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best],
+      result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
                                   argOrig)
 
 proc setSon(father: PNode, at: int, son: PNode) = 
-  if sonsLen(father) <= at: setlen(father.sons, at + 1)
+  if sonsLen(father) <= at: setLen(father.sons, at + 1)
   father.sons[at] = son
 
 # we are allowed to modify the calling node in the 'prepare*' procs:
@@ -1061,7 +1283,9 @@ proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
     # a.typ == nil is valid
     result = a
   elif a.typ.isNil:
-    result = c.semOperand(c, a, {efDetermineType})
+    let flags = if formal.kind == tyIter: {efDetermineType, efWantIterator}
+                else: {efDetermineType}
+    result = c.semOperand(c, a, flags)
   else:
     result = a
 
@@ -1122,7 +1346,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       # check if m.callee has such a param:
       prepareNamedParam(n.sons[a])
       if n.sons[a].sons[0].kind != nkIdent: 
-        LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
+        localError(n.sons[a].info, errNamedParamHasToBeIdent)
         m.state = csNoMatch
         return 
       formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
@@ -1130,15 +1354,15 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         # no error message!
         m.state = csNoMatch
         return 
-      if ContainsOrIncl(marker, formal.position): 
+      if containsOrIncl(marker, formal.position): 
         # already in namedParams:
-        LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
+        localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
         m.state = csNoMatch
         return 
       m.baseTypeMatch = false
       n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1])
       n.sons[a].typ = n.sons[a].sons[1].typ
-      var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
+      var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                 n.sons[a].sons[1], nOrig.sons[a].sons[1])
       if arg == nil:
         m.state = csNoMatch
@@ -1156,7 +1380,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       # unnamed param
       if f >= formalLen:
         # too many arguments?
-        if tfVarArgs in m.callee.flags:
+        if tfVarargs in m.callee.flags:
           # is ok... but don't increment any counters...
           # we have no formal here to snoop at:
           n.sons[a] = prepareOperand(c, n.sons[a])
@@ -1168,7 +1392,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         elif formal != nil:
           m.baseTypeMatch = false
           n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
-          var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
+          var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                     n.sons[a], nOrig.sons[a])
           if (arg != nil) and m.baseTypeMatch and (container != nil):
             addSon(container, arg)
@@ -1181,17 +1405,17 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           return
       else:
         if m.callee.n.sons[f].kind != nkSym: 
-          InternalError(n.sons[a].info, "matches")
+          internalError(n.sons[a].info, "matches")
           return
         formal = m.callee.n.sons[f].sym
-        if ContainsOrIncl(marker, formal.position): 
+        if containsOrIncl(marker, formal.position): 
           # already in namedParams:
-          LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
+          localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
           m.state = csNoMatch
           return 
         m.baseTypeMatch = false
         n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
-        var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
+        var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                   n.sons[a], nOrig.sons[a])
         if arg == nil:
           m.state = csNoMatch
@@ -1228,7 +1452,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
   var f = 1
   while f < sonsLen(m.callee.n):
     var formal = m.callee.n.sons[f].sym
-    if not ContainsOrIncl(marker, formal.position):
+    if not containsOrIncl(marker, formal.position):
       if formal.ast == nil:
         if formal.typ.kind == tyVarargs:
           var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info))
@@ -1245,8 +1469,8 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
 
 proc argtypeMatches*(c: PContext, f, a: PType): bool =
   var m: TCandidate
-  initCandidate(m, f)
-  let res = paramTypesMatch(c, m, f, a, ast.emptyNode, nil)
+  initCandidate(c, m, f)
+  let res = paramTypesMatch(m, f, a, ast.emptyNode, nil)
   #instantiateGenericConverters(c, res, m)
   # XXX this is used by patterns.nim too; I think it's better to not
   # instantiate generic converters for that
@@ -1308,7 +1532,7 @@ tests:
 
     setup:
       var c: TCandidate
-      InitCandidate(c, nil)
+      InitCandidate(nil, c, nil)
 
     template yes(x, y) =
       test astToStr(x) & " is " & astToStr(y):
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 76a6c21d9..49611f649 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -11,7 +11,7 @@
 
 # included from sigmatch.nim
 
-import algorithm, sequtils
+import algorithm, sequtils, pretty
 
 const
   sep = '\t'
@@ -28,7 +28,7 @@ proc origModuleName(m: PSym): string =
            else:
              m.name.s
 
-proc SymToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string = 
+proc symToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string = 
   result = section
   result.add(sep)
   result.add($s.kind)
@@ -48,15 +48,15 @@ proc SymToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string =
   result.add(sep)
   result.add(toFullPath(li))
   result.add(sep)
-  result.add($ToLinenumber(li))
+  result.add($toLinenumber(li))
   result.add(sep)
-  result.add($ToColumn(li))
+  result.add($toColumn(li))
   result.add(sep)
   when not defined(noDocgen):
     result.add(s.extractDocComment.escape)
 
-proc SymToStr(s: PSym, isLocal: bool, section: string): string = 
-  result = SymToStr(s, isLocal, section, s.info)
+proc symToStr(s: PSym, isLocal: bool, section: string): string = 
+  result = symToStr(s, isLocal, section, s.info)
 
 proc filterSym(s: PSym): bool {.inline.} =
   result = s.name.s[0] in lexer.SymChars and s.kind != skModule
@@ -68,7 +68,7 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
 
 proc suggestField(c: PContext, s: PSym, outputs: var int) = 
   if filterSym(s) and fieldVisible(c, s):
-    SuggestWriteln(SymToStr(s, isLocal=true, sectionSuggest))
+    suggestWriteln(symToStr(s, isLocal=true, sectionSuggest))
     inc outputs
 
 when not defined(nimhygiene):
@@ -84,7 +84,7 @@ template wholeSymTab(cond, section: expr) {.immediate.} =
     for item in entries:
       let it {.inject.} = item
       if cond:
-        SuggestWriteln(SymToStr(it, isLocal = isLocal, section))
+        suggestWriteln(symToStr(it, isLocal = isLocal, section))
         inc outputs
 
 proc suggestSymList(c: PContext, list: PNode, outputs: var int) = 
@@ -103,7 +103,7 @@ proc suggestObject(c: PContext, n: PNode, outputs: var int) =
       suggestObject(c, n.sons[0], outputs)
       for i in countup(1, L-1): suggestObject(c, lastSon(n.sons[i]), outputs)
   of nkSym: suggestField(c, n.sym, outputs)
-  else: nil
+  else: discard
 
 proc nameFits(c: PContext, s: PSym, n: PNode): bool = 
   var op = n.sons[0]
@@ -119,7 +119,7 @@ proc argsFit(c: PContext, candidate: PSym, n, nOrig: PNode): bool =
   case candidate.kind 
   of OverloadableSyms:
     var m: TCandidate
-    initCandidate(m, candidate, nil)
+    initCandidate(c, m, candidate, nil)
     sigmatch.partialMatch(c, n, nOrig, m)
     result = m.state != csNoMatch
   else:
@@ -144,14 +144,14 @@ proc suggestEverything(c: PContext, n: PNode, outputs: var int) =
     if scope == c.topLevelScope: isLocal = false
     for it in items(scope.symbols):
       if filterSym(it):
-        SuggestWriteln(SymToStr(it, isLocal = isLocal, sectionSuggest))
+        suggestWriteln(symToStr(it, isLocal = isLocal, sectionSuggest))
         inc outputs
     if scope == c.topLevelScope: break
 
 proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
   # special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but
   # ``myObj``.
-  var typ = n.Typ
+  var typ = n.typ
   if typ == nil:
     # a module symbol has no type for example:
     if n.kind == nkSym and n.sym.kind == skModule: 
@@ -159,12 +159,12 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
         # all symbols accessible, because we are in the current module:
         for it in items(c.topLevelScope.symbols):
           if filterSym(it): 
-            SuggestWriteln(SymToStr(it, isLocal=false, sectionSuggest))
+            suggestWriteln(symToStr(it, isLocal=false, sectionSuggest))
             inc outputs
       else: 
         for it in items(n.sym.tab): 
           if filterSym(it): 
-            SuggestWriteln(SymToStr(it, isLocal=false, sectionSuggest))
+            suggestWriteln(symToStr(it, isLocal=false, sectionSuggest))
             inc outputs
     else:
       # fallback:
@@ -203,7 +203,7 @@ const
   CallNodes = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit}
 
 proc findClosestCall(n: PNode): PNode = 
-  if n.kind in callNodes and msgs.inCheckpoint(n.info) == cpExact: 
+  if n.kind in CallNodes and msgs.inCheckpoint(n.info) == cpExact: 
     result = n
   else:
     for i in 0.. <safeLen(n):
@@ -246,16 +246,16 @@ var
 proc findUsages(node: PNode, s: PSym) =
   if usageSym == nil and isTracked(node.info, s.name.s.len):
     usageSym = s
-    SuggestWriteln(SymToStr(s, isLocal=false, sectionUsage))
+    suggestWriteln(symToStr(s, isLocal=false, sectionUsage))
   elif s == usageSym:
     if lastLineInfo != node.info:
-      SuggestWriteln(SymToStr(s, isLocal=false, sectionUsage, node.info))
+      suggestWriteln(symToStr(s, isLocal=false, sectionUsage, node.info))
     lastLineInfo = node.info
 
 proc findDefinition(node: PNode, s: PSym) =
   if isTracked(node.info, s.name.s.len):
-    SuggestWriteln(SymToStr(s, isLocal=false, sectionDef))
-    SuggestQuit()
+    suggestWriteln(symToStr(s, isLocal=false, sectionDef))
+    suggestQuit()
 
 type
   TSourceMap = object
@@ -281,7 +281,7 @@ proc resetSourceMap*(fileIdx: int32) =
   ensureIdx(gSourceMaps, fileIdx)
   gSourceMaps[fileIdx].lines = @[]
 
-proc addToSourceMap(sym: Psym, info: TLineInfo) =
+proc addToSourceMap(sym: PSym, info: TLineInfo) =
   ensureIdx(gSourceMaps, info.fileIndex)
   ensureSeq(gSourceMaps[info.fileIndex].lines)
   ensureIdx(gSourceMaps[info.fileIndex].lines, info.line)
@@ -302,7 +302,7 @@ proc defFromLine(entries: var seq[TEntry], col: int32) =
     # that the first expr that ends after the cursor column is
     # the one we are looking for.
     if e.pos >= col:
-      SuggestWriteln(SymToStr(e.sym, isLocal=false, sectionDef))
+      suggestWriteln(symToStr(e.sym, isLocal=false, sectionDef))
       return
 
 proc defFromSourceMap*(i: TLineInfo) =
@@ -324,9 +324,10 @@ proc suggestSym*(n: PNode, s: PSym) {.inline.} =
 proc markUsed(n: PNode, s: PSym) =
   incl(s.flags, sfUsed)
   if {sfDeprecated, sfError} * s.flags != {}:
-    if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
-    if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s)
+    if sfDeprecated in s.flags: message(n.info, warnDeprecated, s.name.s)
+    if sfError in s.flags: localError(n.info, errWrongSymbolX, s.name.s)
   suggestSym(n, s)
+  if gCmd == cmdPretty: checkUse(n, s)
 
 proc useSym*(sym: PSym): PNode =
   result = newSymNode(sym)
@@ -337,8 +338,8 @@ proc suggestExpr*(c: PContext, node: PNode) =
   if cp == cpNone: return
   var outputs = 0
   # This keeps semExpr() from coming here recursively:
-  if c.InCompilesContext > 0: return
-  inc(c.InCompilesContext)
+  if c.inCompilesContext > 0: return
+  inc(c.inCompilesContext)
   
   if optSuggest in gGlobalOptions:
     var n = findClosestDot(node)
@@ -368,8 +369,8 @@ proc suggestExpr*(c: PContext, node: PNode) =
         addSon(a, x)
       suggestCall(c, a, n, outputs)
   
-  dec(c.InCompilesContext)
-  if outputs > 0 and optUsages notin gGlobalOptions: SuggestQuit()
+  dec(c.inCompilesContext)
+  if outputs > 0 and optUsages notin gGlobalOptions: suggestQuit()
 
 proc suggestStmt*(c: PContext, n: PNode) = 
   suggestExpr(c, n)
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index 3965cb3fe..478c2a837 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -17,14 +17,15 @@ type
   TFilterKind* = enum 
     filtNone, filtTemplate, filtReplace, filtStrip
   TParserKind* = enum 
-    skinStandard, skinBraces, skinEndX
+    skinStandard, skinStrongSpaces, skinBraces, skinEndX
 
 const 
-  parserNames*: array[TParserKind, string] = ["standard", "braces", "endx"]
-  filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace", 
-    "strip"]
+  parserNames*: array[TParserKind, string] = ["standard", "strongspaces",
+                                              "braces", "endx"]
+  filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace",
+                                              "strip"]
 
-type 
+type
   TParsers*{.final.} = object 
     skin*: TParserKind
     parser*: TParser
@@ -40,41 +41,41 @@ proc parseTopLevelStmt*(p: var TParsers): PNode
 
 # implementation
 
-proc ParseFile(fileIdx: int32): PNode =
+proc parseFile(fileIdx: int32): PNode =
   var 
     p: TParsers
-    f: tfile
+    f: TFile
   let filename = fileIdx.toFullPath
   if not open(f, filename):
     rawMessage(errCannotOpenFile, filename)
     return 
-  OpenParsers(p, fileIdx, LLStreamOpen(f))
-  result = ParseAll(p)
-  CloseParsers(p)
+  openParsers(p, fileIdx, llStreamOpen(f))
+  result = parseAll(p)
+  closeParsers(p)
 
 proc parseAll(p: var TParsers): PNode = 
   case p.skin
-  of skinStandard: 
+  of skinStandard, skinStrongSpaces:
     result = parser.parseAll(p.parser)
   of skinBraces: 
     result = pbraces.parseAll(p.parser)
   of skinEndX: 
-    InternalError("parser to implement") 
+    internalError("parser to implement") 
     result = ast.emptyNode
     # skinEndX: result := pendx.parseAll(p.parser);
   
 proc parseTopLevelStmt(p: var TParsers): PNode = 
   case p.skin
-  of skinStandard: 
+  of skinStandard, skinStrongSpaces:
     result = parser.parseTopLevelStmt(p.parser)
   of skinBraces: 
     result = pbraces.parseTopLevelStmt(p.parser)
   of skinEndX: 
-    InternalError("parser to implement") 
+    internalError("parser to implement") 
     result = ast.emptyNode
     #skinEndX: result := pendx.parseTopLevelStmt(p.parser);
   
-proc UTF8_BOM(s: string): int = 
+proc utf8Bom(s: string): int = 
   if (s[0] == '\xEF') and (s[1] == '\xBB') and (s[2] == '\xBF'): 
     result = 3
   else: 
@@ -83,37 +84,37 @@ proc UTF8_BOM(s: string): int =
 proc containsShebang(s: string, i: int): bool = 
   if (s[i] == '#') and (s[i + 1] == '!'): 
     var j = i + 2
-    while s[j] in WhiteSpace: inc(j)
+    while s[j] in Whitespace: inc(j)
     result = s[j] == '/'
 
 proc parsePipe(filename: string, inputStream: PLLStream): PNode = 
   result = ast.emptyNode
-  var s = LLStreamOpen(filename, fmRead)
+  var s = llStreamOpen(filename, fmRead)
   if s != nil: 
     var line = newStringOfCap(80)
-    discard LLStreamReadLine(s, line)
-    var i = UTF8_Bom(line)
+    discard llStreamReadLine(s, line)
+    var i = utf8Bom(line)
     if containsShebang(line, i):
-      discard LLStreamReadLine(s, line)
+      discard llStreamReadLine(s, line)
       i = 0
     if line[i] == '#' and line[i+1] == '!':
       inc(i, 2)
-      while line[i] in WhiteSpace: inc(i)
+      while line[i] in Whitespace: inc(i)
       var q: TParser
-      OpenParser(q, filename, LLStreamOpen(substr(line, i)))
+      openParser(q, filename, llStreamOpen(substr(line, i)))
       result = parser.parseAll(q)
-      CloseParser(q)
-    LLStreamClose(s)
+      closeParser(q)
+    llStreamClose(s)
 
 proc getFilter(ident: PIdent): TFilterKind = 
   for i in countup(low(TFilterKind), high(TFilterKind)): 
-    if IdentEq(ident, filterNames[i]): 
+    if identEq(ident, filterNames[i]): 
       return i
   result = filtNone
 
 proc getParser(ident: PIdent): TParserKind = 
   for i in countup(low(TParserKind), high(TParserKind)): 
-    if IdentEq(ident, parserNames[i]): 
+    if identEq(ident, parserNames[i]): 
       return i
   rawMessage(errInvalidDirectiveX, ident.s)
 
@@ -142,35 +143,37 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string,
   if f != filtNone: 
     if gVerbosity >= 2: 
       rawMessage(hintCodeBegin, [])
-      MsgWriteln(result.s)
+      msgWriteln(result.s)
       rawMessage(hintCodeEnd, [])
 
 proc evalPipe(p: var TParsers, n: PNode, filename: string, 
               start: PLLStream): PLLStream = 
   result = start
   if n.kind == nkEmpty: return 
-  if (n.kind == nkInfix) and (n.sons[0].kind == nkIdent) and
-      IdentEq(n.sons[0].ident, "|"): 
-    for i in countup(1, 2): 
-      if n.sons[i].kind == nkInfix: 
+  if n.kind == nkInfix and n.sons[0].kind == nkIdent and
+      identEq(n.sons[0].ident, "|"):
+    for i in countup(1, 2):
+      if n.sons[i].kind == nkInfix:
         result = evalPipe(p, n.sons[i], filename, result)
-      else: 
+      else:
         result = applyFilter(p, n.sons[i], filename, result)
-  elif n.kind == nkStmtList: 
+  elif n.kind == nkStmtList:
     result = evalPipe(p, n.sons[0], filename, result)
-  else: 
+  else:
     result = applyFilter(p, n, filename, result)
   
 proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) = 
   var s: PLLStream
   p.skin = skinStandard
   let filename = fileIdx.toFullPath
-  var pipe = parsePipe(filename, inputStream)
-  if pipe != nil: s = evalPipe(p, pipe, filename, inputStream)
-  else: s = inputStream
+  var pipe = parsePipe(filename, inputstream)
+  if pipe != nil: s = evalPipe(p, pipe, filename, inputstream)
+  else: s = inputstream
   case p.skin
   of skinStandard, skinBraces, skinEndX:
-    parser.openParser(p.parser, fileIdx, s)
+    parser.openParser(p.parser, fileIdx, s, false)
+  of skinStrongSpaces:
+    parser.openParser(p.parser, fileIdx, s, true)
   
-proc closeParsers(p: var TParsers) = 
+proc closeParsers(p: var TParsers) =
   parser.closeParser(p.parser)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 206c21c3d..fb5e321b6 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -20,10 +20,7 @@
 import 
   intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, 
   idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
-  lambdalifting, sempass2
-
-const 
-  genPrefix* = ":tmp"         # prefix for generated names
+  lambdalifting, sempass2, lowerings
 
 # implementation
 
@@ -88,7 +85,7 @@ proc pushTransCon(c: PTransf, t: PTransCon) =
   c.transCon = t
 
 proc popTransCon(c: PTransf) = 
-  if (c.transCon == nil): InternalError("popTransCon")
+  if (c.transCon == nil): internalError("popTransCon")
   c.transCon = c.transCon.next
 
 proc getCurrOwner(c: PTransf): PSym = 
@@ -113,8 +110,8 @@ proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode =
   result[1] = ri
 
 proc transformSymAux(c: PTransf, n: PNode): PNode =
-  if n.sym.kind == skIterator and n.sym.typ.callConv == ccClosure:
-    return liftIterSym(n)
+  #if n.sym.kind == skClosureIterator:
+  #  return liftIterSym(n)
   var b: PNode
   var tc = c.transCon
   if sfBorrow in n.sym.flags: 
@@ -126,7 +123,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
   else: 
     b = n
   while tc != nil: 
-    result = IdNodeTableGet(tc.mapping, b.sym)
+    result = idNodeTableGet(tc.mapping, b.sym)
     if result != nil: return
     tc = tc.next
   result = b
@@ -141,34 +138,35 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
     if it.kind == nkCommentStmt: 
       result[i] = PTransNode(it)
     elif it.kind == nkIdentDefs: 
-      if it.sons[0].kind != nkSym: InternalError(it.info, "transformVarSection")
-      InternalAssert(it.len == 3)
+      if it.sons[0].kind != nkSym: internalError(it.info, "transformVarSection")
+      internalAssert(it.len == 3)
       var newVar = copySym(it.sons[0].sym)
       incl(newVar.flags, sfFromGeneric)
       # fixes a strange bug for rodgen:
       #include(it.sons[0].sym.flags, sfFromGeneric);
       newVar.owner = getCurrOwner(c)
-      IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
+      idNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
       var defs = newTransNode(nkIdentDefs, it.info, 3)
       if importantComments():
         # keep documentation information:
-        pnode(defs).comment = it.comment
+        PNode(defs).comment = it.comment
       defs[0] = newSymNode(newVar).PTransNode
       defs[1] = it.sons[1].PTransNode
       defs[2] = transform(c, it.sons[2])
       result[i] = defs
     else: 
       if it.kind != nkVarTuple: 
-        InternalError(it.info, "transformVarSection: not nkVarTuple")
+        internalError(it.info, "transformVarSection: not nkVarTuple")
       var L = sonsLen(it)
       var defs = newTransNode(it.kind, it.info, L)
       for j in countup(0, L-3): 
         var newVar = copySym(it.sons[j].sym)
         incl(newVar.flags, sfFromGeneric)
         newVar.owner = getCurrOwner(c)
-        IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
+        idNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
         defs[j] = newSymNode(newVar).PTransNode
       assert(it.sons[L-2].kind == nkEmpty)
+      defs[L-2] = ast.emptyNode.PTransNode
       defs[L-1] = transform(c, it.sons[L-1])
       result[i] = defs
 
@@ -179,21 +177,21 @@ proc transformConstSection(c: PTransf, v: PNode): PTransNode =
     if it.kind == nkCommentStmt:
       result[i] = PTransNode(it)
     else:
-      if it.kind != nkConstDef: InternalError(it.info, "transformConstSection")
+      if it.kind != nkConstDef: internalError(it.info, "transformConstSection")
       if it.sons[0].kind != nkSym:
-        InternalError(it.info, "transformConstSection")
+        internalError(it.info, "transformConstSection")
       if sfFakeConst in it[0].sym.flags:
         var b = newNodeI(nkConstDef, it.info)
         addSon(b, it[0])
         addSon(b, ast.emptyNode)            # no type description
-        addSon(b, transform(c, it[2]).pnode)
+        addSon(b, transform(c, it[2]).PNode)
         result[i] = PTransNode(b)
       else:
         result[i] = PTransNode(it)
 
 proc hasContinue(n: PNode): bool = 
   case n.kind
-  of nkEmpty..nkNilLit, nkForStmt, nkParForStmt, nkWhileStmt: nil
+  of nkEmpty..nkNilLit, nkForStmt, nkParForStmt, nkWhileStmt: discard
   of nkContinueStmt: result = true
   else: 
     for i in countup(0, sonsLen(n) - 1): 
@@ -217,7 +215,7 @@ proc transformBlock(c: PTransf, n: PNode): PTransNode =
 
 proc transformBreak(c: PTransf, n: PNode): PTransNode =
   if c.inLoop > 0 or n.sons[0].kind != nkEmpty:
-    result = n.ptransNode
+    result = n.PTransNode
   else:
     let labl = c.breakSyms[c.breakSyms.high]
     result = transformSons(c, n)
@@ -240,13 +238,6 @@ proc transformLoopBody(c: PTransf, n: PNode): PTransNode =
     discard c.contSyms.pop()
   else: 
     result = transform(c, n)
-  
-proc newTupleAccess(tup: PNode, i: int): PNode = 
-  result = newNodeIT(nkBracketExpr, tup.info, tup.typ.sons[i])
-  addSon(result, copyTree(tup))
-  var lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
-  lit.intVal = i
-  addSon(result, lit)
 
 proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) = 
   # XXX: BUG: what if `n` is an expression with side-effects?
@@ -292,11 +283,11 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
     add(result, c.transCon.forLoopBody)
   else: 
     # we need to introduce new local variables:
-    add(result, introduceNewLocalVars(c, c.transCon.forLoopBody.pnode))
+    add(result, introduceNewLocalVars(c, c.transCon.forLoopBody.PNode))
 
 proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
   result = transformSons(c, n)
-  var n = result.pnode
+  var n = result.PNode
   case n.sons[0].kind
   of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
     var m = n.sons[0].sons[0]
@@ -389,7 +380,7 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
       result[0] = transform(c, n.sons[1])
     else: 
       result = transform(c, n.sons[1])
-  of tyGenericParam, tyOrdinal, tyTypeClass:
+  of tyGenericParam, tyOrdinal:
     result = transform(c, n.sons[1])
     # happens sometimes for generated assignments, etc.
   else: 
@@ -425,28 +416,28 @@ proc findWrongOwners(c: PTransf, n: PNode) =
         x.sym.owner.name.s & " " & getCurrOwner(c).name.s)
   else:
     for i in 0 .. <safeLen(n): findWrongOwners(c, n.sons[i])
-  
+
 proc transformFor(c: PTransf, n: PNode): PTransNode = 
   # generate access statements for the parameters (unless they are constant)
   # put mapping from formal parameters to actual parameters
-  if n.kind != nkForStmt: InternalError(n.info, "transformFor")
+  if n.kind != nkForStmt: internalError(n.info, "transformFor")
 
   var length = sonsLen(n)
   var call = n.sons[length - 2]
-  if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or 
-      call.sons[0].typ.callConv == ccClosure or
-      call.sons[0].sym.kind != skIterator:
-    n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).pnode
-    return lambdalifting.liftForLoop(n).ptransNode
+  if call.typ.kind != tyIter and
+    (call.kind notin nkCallKinds or call.sons[0].kind != nkSym or 
+      call.sons[0].sym.kind != skIterator):
+    n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
+    return lambdalifting.liftForLoop(n).PTransNode
     #InternalError(call.info, "transformFor")
-
+  
   #echo "transforming: ", renderTree(n)
   result = newTransNode(nkStmtList, n.info, 0)
   var loopBody = transformLoopBody(c, n.sons[length-1])
   var v = newNodeI(nkVarSection, n.info)
   for i in countup(0, length - 3): 
     addVar(v, copyTree(n.sons[i])) # declare new vars
-  add(result, v.ptransNode)
+  add(result, v.PTransNode)
   
   # Bugfix: inlined locals belong to the invoking routine, not to the invoked
   # iterator!
@@ -454,24 +445,25 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
   var newC = newTransCon(getCurrOwner(c))
   newC.forStmt = n
   newC.forLoopBody = loopBody
-  if iter.kind != skIterator: InternalError(call.info, "transformFor") 
+  internalAssert iter.kind == skIterator
   # generate access statements for the parameters (unless they are constant)
   pushTransCon(c, newC)
   for i in countup(1, sonsLen(call) - 1): 
-    var arg = transform(c, call.sons[i]).pnode
+    var arg = transform(c, call.sons[i]).PNode
     var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym 
+    if arg.typ.kind == tyIter: continue
     case putArgInto(arg, formal.typ)
     of paDirectMapping: 
-      IdNodeTablePut(newC.mapping, formal, arg)
+      idNodeTablePut(newC.mapping, formal, arg)
     of paFastAsgn: 
       # generate a temporary and produce an assignment statement:
       var temp = newTemp(c, formal.typ, formal.info)
       addVar(v, newSymNode(temp))
-      add(result, newAsgnStmt(c, newSymNode(temp), arg.ptransNode))
-      IdNodeTablePut(newC.mapping, formal, newSymNode(temp))
+      add(result, newAsgnStmt(c, newSymNode(temp), arg.PTransNode))
+      idNodeTablePut(newC.mapping, formal, newSymNode(temp))
     of paVarAsgn:
       assert(skipTypes(formal.typ, abstractInst).kind == tyVar)
-      IdNodeTablePut(newC.mapping, formal, arg)
+      idNodeTablePut(newC.mapping, formal, arg)
       # XXX BUG still not correct if the arg has a side effect!
   var body = iter.getBody
   pushInfoContext(n.info)
@@ -481,7 +473,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
   dec(c.inlining)
   popInfoContext()
   popTransCon(c)
-  #echo "transformed: ", renderTree(n)
+  # echo "transformed: ", result.PNode.renderTree
   
 proc getMagicOp(call: PNode): TMagic = 
   if call.sons[0].kind == nkSym and
@@ -500,20 +492,20 @@ proc transformCase(c: PTransf, n: PNode): PTransNode =
     var e = transform(c, it)
     case it.kind
     of nkElifBranch:
-      if ifs.pnode == nil:
+      if ifs.PNode == nil:
         ifs = newTransNode(nkIfStmt, it.info, 0)
       ifs.add(e)
     of nkElse:
-      if ifs.pnode == nil: result.add(e)
+      if ifs.PNode == nil: result.add(e)
       else: ifs.add(e)
     else:
       result.add(e)
-  if ifs.pnode != nil:
+  if ifs.PNode != nil:
     var elseBranch = newTransNode(nkElse, n.info, 1)
     elseBranch[0] = ifs
     result.add(elseBranch)
-  elif result.Pnode.lastSon.kind != nkElse and not (
-      skipTypes(n.sons[0].Typ, abstractVarRange).Kind in
+  elif result.PNode.lastSon.kind != nkElse and not (
+      skipTypes(n.sons[0].typ, abstractVarRange).kind in
         {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32}):
     # fix a stupid code gen bug by normalizing:
     var elseBranch = newTransNode(nkElse, n.info, 1)
@@ -523,7 +515,7 @@ proc transformCase(c: PTransf, n: PNode): PTransNode =
 proc transformArrayAccess(c: PTransf, n: PNode): PTransNode = 
   # XXX this is really bad; transf should use a proper AST visitor
   if n.sons[0].kind == nkSym and n.sons[0].sym.kind == skType:
-    result = n.ptransnode
+    result = n.PTransNode
   else:
     result = newTransNode(n)
     for i in 0 .. < n.len:
@@ -533,10 +525,10 @@ proc getMergeOp(n: PNode): PSym =
   case n.kind
   of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, 
      nkCallStrLit: 
-    if (n.sons[0].Kind == nkSym) and (n.sons[0].sym.kind == skProc) and
+    if (n.sons[0].kind == nkSym) and (n.sons[0].sym.kind == skProc) and
         (sfMerge in n.sons[0].sym.flags): 
       result = n.sons[0].sym
-  else: nil
+  else: discard
 
 proc flattenTreeAux(d, a: PNode, op: PSym) = 
   var op2 = getMergeOp(a)
@@ -563,24 +555,24 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
     add(result, transform(c, n.sons[0]))
     var j = 1
     while j < sonsLen(n): 
-      var a = transform(c, n.sons[j]).pnode
+      var a = transform(c, n.sons[j]).PNode
       inc(j)
       if isConstExpr(a): 
         while (j < sonsLen(n)):
-          let b = transform(c, n.sons[j]).pnode
+          let b = transform(c, n.sons[j]).PNode
           if not isConstExpr(b): break
           a = evalOp(op.magic, n, a, b, nil)
           inc(j)
-      add(result, a.ptransnode)
+      add(result, a.PTransNode)
     if len(result) == 2: result = result[1]
   else:
-    let s = transformSons(c, n).pnode
+    let s = transformSons(c, n).PNode
     # bugfix: check after 'transformSons' if it's still a method call:
     # use the dispatcher for the call:
     if s.sons[0].kind == nkSym and s.sons[0].sym.kind == skMethod:
-      result = methodCall(s).ptransNode
+      result = methodCall(s).PTransNode
     else:
-      result = s.ptransNode
+      result = s.PTransNode
 
 proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
   # symbols that expand to a complex constant (array, etc.) should not be
@@ -636,6 +628,8 @@ proc transform(c: PTransf, n: PNode): PTransNode =
           s.ast.sons[bodyPos] = n.sons[bodyPos]
         #n.sons[bodyPos] = liftLambdas(s, n)
         #if n.kind == nkMethodDef: methodDef(s, false)
+    #if n.kind == nkIteratorDef and n.typ != nil:
+    #  return liftIterSym(n.sons[namePos]).PTransNode
     result = PTransNode(n)
   of nkMacroDef:
     # XXX no proper closure support yet:
@@ -683,7 +677,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
         # completely:
         result = PTransNode(newNode(nkCommentStmt))
   of nkCommentStmt, nkTemplateDef: 
-    return n.ptransNode
+    return n.PTransNode
   of nkConstSection:
     # do not replace ``const c = 3`` with ``const 3 = 3``
     return transformConstSection(c, n)
@@ -707,7 +701,8 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     result = transformSons(c, n)
     # XXX comment handling really sucks:
     if importantComments():
-      pnode(result).comment = n.comment
+      PNode(result).comment = n.comment
+  of nkClosure: return PTransNode(n)
   else:
     result = transformSons(c, n)
   var cnst = getConstExpr(c.module, PNode(result))
@@ -719,7 +714,7 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode =
   # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip
   # this step! We have to rely that the semantic pass transforms too errornous
   # nodes into an empty node.
-  if passes.skipCodegen(n) or c.fromCache or nfTransf in n.flags: return n
+  if c.fromCache or nfTransf in n.flags: return n
   pushTransCon(c, newTransCon(owner))
   result = PNode(transform(c, n))
   popTransCon(c)
@@ -735,14 +730,11 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
   if nfTransf in n.flags or prc.kind in {skTemplate}:
     result = n
   else:
-    #when useEffectSystem: trackProc(prc, n)
     var c = openTransf(module, "")
     result = processTransf(c, n, prc)
-    if prc.kind != skMacro:
-      # XXX no closures yet for macros:
-      result = liftLambdas(prc, result)
-    if prc.kind == skIterator and prc.typ.callConv == ccClosure:
-      result = lambdalifting.liftIterator(prc, result)
+    result = liftLambdas(prc, result)
+    #if prc.kind == skClosureIterator:
+    #  result = lambdalifting.liftIterator(prc, result)
     incl(result.flags, nfTransf)
     when useEffectSystem: trackProc(prc, result)
 
@@ -754,6 +746,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode =
     result = processTransf(c, n, module)
     result = liftLambdasForTopLevel(module, result)
     incl(result.flags, nfTransf)
+    when useEffectSystem: trackTopLevelStmt(module, result)
 
 proc transformExpr*(module: PSym, n: PNode): PNode =
   if nfTransf in n.flags:
diff --git a/compiler/trees.nim b/compiler/trees.nim
index ab5c97a19..35e9334cc 100644
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -36,7 +36,7 @@ proc cyclicTree*(n: PNode): bool =
   var s = newNodeI(nkEmpty, n.info)
   result = cyclicTreeAux(n, s)
 
-proc ExprStructuralEquivalent*(a, b: PNode): bool = 
+proc exprStructuralEquivalent*(a, b: PNode): bool = 
   result = false
   if a == b: 
     result = true
@@ -53,17 +53,17 @@ proc ExprStructuralEquivalent*(a, b: PNode): bool =
     else: 
       if sonsLen(a) == sonsLen(b): 
         for i in countup(0, sonsLen(a) - 1): 
-          if not ExprStructuralEquivalent(a.sons[i], b.sons[i]): return 
+          if not exprStructuralEquivalent(a.sons[i], b.sons[i]): return 
         result = true
   
-proc sameTree*(a, b: PNode): bool = 
+proc sameTree*(a, b: PNode): bool =
   result = false
-  if a == b: 
+  if a == b:
     result = true
-  elif (a != nil) and (b != nil) and (a.kind == b.kind): 
-    if a.flags != b.flags: return 
-    if a.info.line != b.info.line: return 
-    if a.info.col != b.info.col: 
+  elif a != nil and b != nil and a.kind == b.kind:
+    if a.flags != b.flags: return
+    if a.info.line != b.info.line: return
+    if a.info.col != b.info.col:
       return                  #if a.info.fileIndex <> b.info.fileIndex then exit;
     case a.kind
     of nkSym: 
@@ -74,7 +74,7 @@ proc sameTree*(a, b: PNode): bool =
     of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
     of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
     of nkEmpty, nkNilLit, nkType: result = true
-    else: 
+    else:
       if sonsLen(a) == sonsLen(b): 
         for i in countup(0, sonsLen(a) - 1): 
           if not sameTree(a.sons[i], b.sons[i]): return 
@@ -84,22 +84,22 @@ proc getProcSym*(call: PNode): PSym =
   result = call.sons[0].sym
 
 proc getOpSym*(op: PNode): PSym = 
-  if not (op.kind in {nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit}): 
+  if op.kind notin {nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit}:
     result = nil
-  else: 
-    if (sonsLen(op) <= 0): InternalError(op.info, "getOpSym")
-    elif op.sons[0].Kind == nkSym: result = op.sons[0].sym
+  else:
+    if sonsLen(op) <= 0: internalError(op.info, "getOpSym")
+    elif op.sons[0].kind == nkSym: result = op.sons[0].sym
     else: result = nil
-  
+
 proc getMagic*(op: PNode): TMagic = 
   case op.kind
   of nkCallKinds:
-    case op.sons[0].Kind
+    case op.sons[0].kind
     of nkSym: result = op.sons[0].sym.magic
     else: result = mNone
   else: result = mNone
   
-proc TreeToSym*(t: PNode): PSym = 
+proc treeToSym*(t: PNode): PSym = 
   result = t.sym
 
 proc isConstExpr*(n: PNode): bool = 
@@ -118,7 +118,7 @@ proc isDeepConstExpr*(n: PNode): bool =
     for i in 0 .. <n.len:
       if not isDeepConstExpr(n.sons[i]): return false
     result = true
-  else: nil
+  else: discard
 
 proc flattenTreeAux(d, a: PNode, op: TMagic) = 
   if (getMagic(a) == op):     # a is a "leaf", so add it:
@@ -129,17 +129,17 @@ proc flattenTreeAux(d, a: PNode, op: TMagic) =
   
 proc flattenTree*(root: PNode, op: TMagic): PNode = 
   result = copyNode(root)
-  if (getMagic(root) == op): 
+  if getMagic(root) == op:
     # BUGFIX: forget to copy prc
     addSon(result, copyNode(root.sons[0]))
     flattenTreeAux(result, root, op)
 
-proc SwapOperands*(op: PNode) = 
+proc swapOperands*(op: PNode) = 
   var tmp = op.sons[1]
   op.sons[1] = op.sons[2]
   op.sons[2] = tmp
 
-proc IsRange*(n: PNode): bool {.inline.} = 
+proc isRange*(n: PNode): bool {.inline.} = 
   if n.kind == nkInfix:
     if n[0].kind == nkIdent and n[0].ident.id == ord(wDotDot) or
         n[0].kind in {nkClosedSymChoice, nkOpenSymChoice} and 
diff --git a/compiler/treetab.nim b/compiler/treetab.nim
index 75e3fd20a..ecb8fb083 100644
--- a/compiler/treetab.nim
+++ b/compiler/treetab.nim
@@ -17,7 +17,7 @@ proc hashTree(n: PNode): THash =
   result = ord(n.kind)
   case n.kind
   of nkEmpty, nkNilLit, nkType: 
-    nil
+    discard
   of nkIdent: 
     result = result !& n.ident.h
   of nkSym:
@@ -34,7 +34,7 @@ proc hashTree(n: PNode): THash =
     for i in countup(0, sonsLen(n) - 1): 
       result = result !& hashTree(n.sons[i])
   
-proc TreesEquivalent(a, b: PNode): bool = 
+proc treesEquivalent(a, b: PNode): bool = 
   if a == b: 
     result = true
   elif (a != nil) and (b != nil) and (a.kind == b.kind): 
@@ -48,24 +48,24 @@ proc TreesEquivalent(a, b: PNode): bool =
     else: 
       if sonsLen(a) == sonsLen(b): 
         for i in countup(0, sonsLen(a) - 1): 
-          if not TreesEquivalent(a.sons[i], b.sons[i]): return 
+          if not treesEquivalent(a.sons[i], b.sons[i]): return 
         result = true
     if result: result = sameTypeOrNil(a.typ, b.typ)
   
-proc NodeTableRawGet(t: TNodeTable, k: THash, key: PNode): int = 
+proc nodeTableRawGet(t: TNodeTable, k: THash, key: PNode): int = 
   var h: THash = k and high(t.data)
   while t.data[h].key != nil: 
-    if (t.data[h].h == k) and TreesEquivalent(t.data[h].key, key): 
+    if (t.data[h].h == k) and treesEquivalent(t.data[h].key, key): 
       return h
     h = nextTry(h, high(t.data))
   result = -1
 
-proc NodeTableGet*(t: TNodeTable, key: PNode): int = 
-  var index = NodeTableRawGet(t, hashTree(key), key)
+proc nodeTableGet*(t: TNodeTable, key: PNode): int = 
+  var index = nodeTableRawGet(t, hashTree(key), key)
   if index >= 0: result = t.data[index].val
   else: result = low(int)
   
-proc NodeTableRawInsert(data: var TNodePairSeq, k: THash, key: PNode, 
+proc nodeTableRawInsert(data: var TNodePairSeq, k: THash, key: PNode, 
                         val: int) = 
   var h: THash = k and high(data)
   while data[h].key != nil: h = nextTry(h, high(data))
@@ -74,37 +74,37 @@ proc NodeTableRawInsert(data: var TNodePairSeq, k: THash, key: PNode,
   data[h].key = key
   data[h].val = val
 
-proc NodeTablePut*(t: var TNodeTable, key: PNode, val: int) = 
+proc nodeTablePut*(t: var TNodeTable, key: PNode, val: int) = 
   var n: TNodePairSeq
   var k: THash = hashTree(key)
-  var index = NodeTableRawGet(t, k, key)
+  var index = nodeTableRawGet(t, k, key)
   if index >= 0: 
     assert(t.data[index].key != nil)
     t.data[index].val = val
   else: 
     if mustRehash(len(t.data), t.counter): 
-      newSeq(n, len(t.data) * growthFactor)
+      newSeq(n, len(t.data) * GrowthFactor)
       for i in countup(0, high(t.data)): 
         if t.data[i].key != nil: 
-          NodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
+          nodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
       swap(t.data, n)
-    NodeTableRawInsert(t.data, k, key, val)
+    nodeTableRawInsert(t.data, k, key, val)
     inc(t.counter)
 
-proc NodeTableTestOrSet*(t: var TNodeTable, key: PNode, val: int): int = 
+proc nodeTableTestOrSet*(t: var TNodeTable, key: PNode, val: int): int = 
   var n: TNodePairSeq
   var k: THash = hashTree(key)
-  var index = NodeTableRawGet(t, k, key)
+  var index = nodeTableRawGet(t, k, key)
   if index >= 0: 
     assert(t.data[index].key != nil)
     result = t.data[index].val
   else: 
     if mustRehash(len(t.data), t.counter): 
-      newSeq(n, len(t.data) * growthFactor)
+      newSeq(n, len(t.data) * GrowthFactor)
       for i in countup(0, high(t.data)): 
         if t.data[i].key != nil: 
-          NodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
+          nodeTableRawInsert(n, t.data[i].h, t.data[i].key, t.data[i].val)
       swap(t.data, n)
-    NodeTableRawInsert(t.data, k, key, val)
+    nodeTableRawInsert(t.data, k, key, val)
     result = val
     inc(t.counter)
diff --git a/compiler/types.nim b/compiler/types.nim
index 7e07a0667..1de0fc103 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -10,16 +10,16 @@
 # this module contains routines for accessing and iterating over types
 
 import 
-  intsets, ast, astalgo, trees, msgs, strutils, platform
+  intsets, ast, astalgo, trees, msgs, strutils, platform, renderer
 
-proc firstOrd*(t: PType): biggestInt
-proc lastOrd*(t: PType): biggestInt
-proc lengthOrd*(t: PType): biggestInt
+proc firstOrd*(t: PType): BiggestInt
+proc lastOrd*(t: PType): BiggestInt
+proc lengthOrd*(t: PType): BiggestInt
 type 
   TPreferedDesc* = enum 
     preferName, preferDesc, preferExported
 
-proc TypeToString*(typ: PType, prefer: TPreferedDesc = preferName): string
+proc typeToString*(typ: PType, prefer: TPreferedDesc = preferName): string
 proc getProcHeader*(sym: PSym): string
 proc base*(t: PType): PType
   # ------------------- type iterator: ----------------------------------------
@@ -28,7 +28,7 @@ type
   TTypeMutator* = proc (t: PType, closure: PObject): 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: PObject): bool
   # Returns result of `iter`.
 proc mutateType*(t: PType, iter: TTypeMutator, closure: PObject): PType
   # Returns result of `iter`.
@@ -47,7 +47,8 @@ proc equalParams*(a, b: PNode): TParamsEquality
   # returns whether the parameter lists of the procs a, b are exactly the same
 proc isOrdinalType*(t: PType): bool
 proc enumHasHoles*(t: PType): bool
-const 
+
+const
   abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
                    tyConst, tyMutable, tyTypeDesc}
   abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
@@ -64,17 +65,16 @@ const
   typedescPtrs* = abstractPtrs + {tyTypeDesc}
   typedescInst* = abstractInst + {tyTypeDesc}
 
-proc skipTypes*(t: PType, kinds: TTypeKinds): PType
 proc containsObject*(t: PType): bool
 proc containsGarbageCollectedRef*(typ: PType): bool
 proc containsHiddenPointer*(typ: PType): bool
 proc canFormAcycle*(typ: PType): bool
 proc isCompatibleToCString*(a: PType): bool
-proc getOrdValue*(n: PNode): biggestInt
-proc computeSize*(typ: PType): biggestInt
-proc getSize*(typ: PType): biggestInt
+proc getOrdValue*(n: PNode): BiggestInt
+proc computeSize*(typ: PType): BiggestInt
+proc getSize*(typ: PType): BiggestInt
 proc isPureObject*(typ: PType): bool
-proc InvalidGenericInst*(f: PType): bool
+proc invalidGenericInst*(f: PType): bool
   # for debugging
 type 
   TTypeFieldResult* = enum 
@@ -89,21 +89,21 @@ proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult
 proc typeAllowed*(t: PType, kind: TSymKind): bool
 # implementation
 
-proc InvalidGenericInst(f: PType): bool = 
-  result = (f.kind == tyGenericInst) and (lastSon(f) == nil)
+proc invalidGenericInst(f: PType): bool = 
+  result = f.kind == tyGenericInst and lastSon(f) == nil
 
 proc isPureObject(typ: PType): bool = 
   var t = typ
   while t.kind == tyObject and t.sons[0] != nil: t = t.sons[0]
   result = t.sym != nil and sfPure in t.sym.flags
 
-proc getOrdValue(n: PNode): biggestInt = 
+proc getOrdValue(n: PNode): BiggestInt = 
   case n.kind
   of nkCharLit..nkInt64Lit: result = n.intVal
   of nkNilLit: result = 0
   of nkHiddenStdConv: result = getOrdValue(n.sons[1])
   else:
-    LocalError(n.info, errOrdinalTypeExpected)
+    localError(n.info, errOrdinalTypeExpected)
     result = 0
 
 proc isIntLit*(t: PType): bool {.inline.} =
@@ -132,7 +132,7 @@ proc getProcHeader(sym: PSym): string =
       add(result, typeToString(p.sym.typ))
       if i != sonsLen(n)-1: add(result, ", ")
     else:
-      InternalError("getProcHeader")
+      internalError("getProcHeader")
   add(result, ')')
   if n.sons[0].typ != nil: result.add(": " & typeToString(n.sons[0].typ))
   
@@ -148,21 +148,17 @@ proc skipGeneric(t: PType): PType =
   result = t
   while result.kind == tyGenericInst: result = lastSon(result)
       
-proc skipTypes(t: PType, kinds: TTypeKinds): PType = 
-  result = t
-  while result.kind in kinds: result = lastSon(result)
-  
 proc isOrdinalType(t: PType): bool =
   assert(t != nil)
   # caution: uint, uint64 are no ordinal types!
-  result = t.Kind in {tyChar,tyInt..tyInt64,tyUInt8..tyUInt32,tyBool,tyEnum} or
-      (t.Kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
+  result = t.kind in {tyChar,tyInt..tyInt64,tyUInt8..tyUInt32,tyBool,tyEnum} or
+      (t.kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
        isOrdinalType(t.sons[0])
 
 proc enumHasHoles(t: PType): bool = 
   var b = t
   while b.kind in {tyConst, tyMutable, tyRange, tyGenericInst}: b = b.sons[0]
-  result = b.Kind == tyEnum and tfEnumHasHoles in b.flags
+  result = b.kind == tyEnum and tfEnumHasHoles in b.flags
 
 proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter, 
                      closure: PObject): bool
@@ -184,7 +180,7 @@ proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter,
   if t == nil: return 
   result = iter(t, closure)
   if result: return 
-  if not ContainsOrIncl(marker, t.id): 
+  if not containsOrIncl(marker, t.id): 
     case t.kind
     of tyGenericInst, tyGenericBody: 
       result = iterOverTypeAux(marker, lastSon(t), iter, closure)
@@ -194,8 +190,8 @@ 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 = 
-  var marker = InitIntSet()
+proc iterOverType(t: PType, iter: TTypeIter, closure: PObject): bool = 
+  var marker = initIntSet()
   result = iterOverTypeAux(marker, t, iter, closure)
 
 proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
@@ -228,8 +224,8 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate,
   # iterates over VALUE types!
   result = false
   if t == nil: return 
-  if ContainsOrIncl(marker, t.id): return 
-  result = Predicate(t)
+  if containsOrIncl(marker, t.id): return 
+  result = predicate(t)
   if result: return 
   case t.kind
   of tyObject: 
@@ -242,10 +238,10 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate,
       result = searchTypeForAux(t.sons[i], predicate, marker)
       if result: return 
   else: 
-    nil
+    discard
 
 proc searchTypeFor(t: PType, predicate: TTypePredicate): bool = 
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = searchTypeForAux(t, predicate, marker)
 
 proc isObjectPredicate(t: PType): bool = 
@@ -284,10 +280,10 @@ proc analyseObjectWithTypeFieldAux(t: PType,
       if res != frNone: 
         return frEmbedded
   else: 
-    nil
+    discard
 
 proc analyseObjectWithTypeField(t: PType): TTypeFieldResult = 
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = analyseObjectWithTypeFieldAux(t, marker)
 
 proc isGCRef(t: PType): bool =
@@ -322,7 +318,7 @@ proc canFormAcycleNode(marker: var TIntSet, n: PNode, startId: int): bool =
     if not result: 
       case n.kind
       of nkNone..nkNilLit: 
-        nil
+        discard
       else: 
         for i in countup(0, sonsLen(n) - 1): 
           result = canFormAcycleNode(marker, n.sons[i], startId)
@@ -337,7 +333,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
   case t.kind
   of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
      tyVarargs:
-    if not ContainsOrIncl(marker, t.id): 
+    if not containsOrIncl(marker, t.id): 
       for i in countup(0, sonsLen(t) - 1): 
         result = canFormAcycleAux(marker, t.sons[i], startId)
         if result: return 
@@ -350,10 +346,10 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
     #  # damn inheritance may introduce cycles:
     #  result = true
   of tyProc: result = typ.callConv == ccClosure
-  else: nil
+  else: discard
 
 proc canFormAcycle(typ: PType): bool =
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = canFormAcycleAux(marker, typ, typ.id)
 
 proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator, 
@@ -367,6 +363,7 @@ proc mutateNode(marker: var TIntSet, n: PNode, iter: TTypeMutator,
     case n.kind
     of nkNone..nkNilLit: 
       # a leaf
+      discard
     else: 
       for i in countup(0, sonsLen(n) - 1): 
         addSon(result, mutateNode(marker, n.sons[i], iter, closure))
@@ -376,26 +373,26 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
   result = nil
   if t == nil: return 
   result = iter(t, closure)
-  if not ContainsOrIncl(marker, t.id): 
+  if not containsOrIncl(marker, t.id): 
     for i in countup(0, sonsLen(t) - 1): 
       result.sons[i] = mutateTypeAux(marker, result.sons[i], iter, closure)
     if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure)
   assert(result != nil)
 
 proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType =
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = mutateTypeAux(marker, t, iter, closure)
 
-proc ValueToString(a: PNode): string =
+proc valueToString(a: PNode): string =
   case a.kind
-  of nkCharLit..nkUInt64Lit: result = $(a.intVal)
-  of nkFloatLit..nkFloat128Lit: result = $(a.floatVal)
+  of nkCharLit..nkUInt64Lit: result = $a.intVal
+  of nkFloatLit..nkFloat128Lit: result = $a.floatVal
   of nkStrLit..nkTripleStrLit: result = a.strVal
   else: result = "<invalid value>"
 
 proc rangeToStr(n: PNode): string =
   assert(n.kind == nkRange)
-  result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1])
+  result = valueToString(n.sons[0]) & ".." & valueToString(n.sons[1])
 
 const 
   typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
@@ -408,29 +405,20 @@ const
     "float", "float32", "float64", "float128",
     "uint", "uint8", "uint16", "uint32", "uint64",
     "bignum", "const ",
-    "!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
-    "ParametricTypeClass", "and", "or", "not", "any"]
+    "!", "varargs[$1]", "iter[$1]", "Error Type",
+    "BuiltInTypeClass", "UserTypeClass",
+    "UserTypeClassInst", "CompositeTypeClass",
+    "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"]
 
-proc consToStr(t: PType): string =
-  if t.len > 0: result = t.typeToString
-  else: result = typeToStr[t.kind].strip
-
-proc constraintsToStr(t: PType): string =
-  let sep = if tfAny in t.flags: " or " else: " and "
-  result = ""
-  for i in countup(0, t.len - 1):
-    if i > 0: result.add(sep)
-    result.add(t.sons[i].consToStr)
-
-proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
+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 t.kind == tyInt and isIntLit(t):
-      return t.sym.Name.s & " literal(" & $t.n.intVal & ")"
-    return t.sym.Name.s
-  case t.Kind
+      return t.sym.name.s & " literal(" & $t.n.intVal & ")"
+    return t.sym.name.s
+  case t.kind
   of tyInt:
     if not isIntLit(t) or prefer == preferExported:
       result = typeToStr[t.kind]
@@ -443,17 +431,48 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       add(result, typeToString(t.sons[i]))
     add(result, ']')
   of tyTypeDesc:
-    if t.len == 0: result = "typedesc"
-    else: result = "typedesc[" & constraintsToStr(t) & "]"
-  of tyTypeClass:
-    if t.n != nil: return t.sym.owner.name.s
-    case t.len
-    of 0: result = "typeclass[]"
-    of 1: result = "typeclass[" & consToStr(t.sons[0]) & "]"
-    else: result = constraintsToStr(t)
+    if t.base.kind == tyNone: result = "typedesc"
+    else: result = "typedesc[" & typeToString(t.base) & "]"
+  of tyStatic:
+    internalAssert t.len > 0
+    result = "static[" & typeToString(t.sons[0]) & "]"
+    if t.n != nil: result.add "(" & renderTree(t.n) & ")"
+  of tyUserTypeClass:
+    internalAssert t.sym != nil and t.sym.owner != nil
+    return t.sym.owner.name.s
+  of tyBuiltInTypeClass:
+    result = case t.base.kind:
+      of tyVar: "var"
+      of tyRef: "ref"
+      of tyPtr: "ptr"
+      of tySequence: "seq"
+      of tyArray: "array"
+      of tySet: "set"
+      of tyRange: "range"
+      of tyDistinct: "distinct"
+      of tyProc: "proc"
+      of tyObject: "object"
+      of tyTuple: "tuple"
+      of tyOpenArray: "openarray"
+      else: typeToStr[t.base.kind]
+  of tyUserTypeClassInst:
+    let body = t.base
+    result = body.sym.name.s & "["
+    for i in countup(1, sonsLen(t) - 2):
+      if i > 1: add(result, ", ")
+      add(result, typeToString(t.sons[i]))
+    result.add "]"
+  of tyAnd:
+    result = typeToString(t.sons[0]) & " and " & typeToString(t.sons[1])
+  of tyOr:
+    result = typeToString(t.sons[0]) & " or " & typeToString(t.sons[1])
+  of tyNot:
+    result = "not " & typeToString(t.sons[0])
   of tyExpr:
-    if t.len == 0: result = "expr"
-    else: result = "expr[" & constraintsToStr(t) & "]"
+    internalAssert t.len == 0
+    result = "expr"
+  of tyFromExpr, tyFieldAccessor:
+    result = renderTree(t.n)
   of tyArray: 
     if t.sons[0].kind == tyRange: 
       result = "array[" & rangeToStr(t.sons[0].n) & ", " &
@@ -489,7 +508,16 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
         if i < sonsLen(t) - 1: add(result, ", ")
     add(result, ']')
   of tyPtr, tyRef, tyVar, tyMutable, tyConst: 
-    result = typeToStr[t.kind] & typeToString(t.sons[0])
+    result = typeToStr[t.kind]
+    if t.len >= 2:
+      setLen(result, result.len-1)
+      result.add '['
+      for i in countup(0, sonsLen(t) - 1): 
+        add(result, typeToString(t.sons[i]))
+        if i < sonsLen(t) - 1: add(result, ", ")
+      result.add ']'
+    else:
+      result.add typeToString(t.sons[0])
   of tyRange:
     result = "range " & rangeToStr(t.n)
     if prefer != preferExported:
@@ -500,7 +528,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       add(result, typeToString(t.sons[i]))
       if i < sonsLen(t) - 1: add(result, ", ")
     add(result, ')')
-    if t.sons[0] != nil: add(result, ": " & TypeToString(t.sons[0]))
+    if t.sons[0] != nil: add(result, ": " & typeToString(t.sons[0]))
     var prag: string
     if t.callConv != ccDefault: prag = CallingConvToStr[t.callConv]
     else: prag = ""
@@ -525,7 +553,7 @@ proc resultType(t: PType): PType =
 proc base(t: PType): PType = 
   result = t.sons[0]
 
-proc firstOrd(t: PType): biggestInt = 
+proc firstOrd(t: PType): BiggestInt = 
   case t.kind
   of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
     result = 0
@@ -550,13 +578,14 @@ 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:
+  of tyGenericInst, tyDistinct, tyConst, tyMutable,
+     tyTypeDesc, tyFieldAccessor:
     result = firstOrd(lastSon(t))
   else: 
-    InternalError("invalid kind for first(" & $t.kind & ')')
+    internalError("invalid kind for first(" & $t.kind & ')')
     result = 0
 
-proc lastOrd(t: PType): biggestInt = 
+proc lastOrd(t: PType): BiggestInt = 
   case t.kind
   of tyBool: result = 1
   of tyChar: result = 255
@@ -583,14 +612,15 @@ proc lastOrd(t: PType): biggestInt =
   of tyEnum: 
     assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
     result = t.n.sons[sonsLen(t.n) - 1].sym.position
-  of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc: 
+  of tyGenericInst, tyDistinct, tyConst, tyMutable,
+     tyTypeDesc, tyFieldAccessor:
     result = lastOrd(lastSon(t))
   of tyProxy: result = 0
   else: 
-    InternalError("invalid kind for last(" & $t.kind & ')')
+    internalError("invalid kind for last(" & $t.kind & ')')
     result = 0
 
-proc lengthOrd(t: PType): biggestInt = 
+proc lengthOrd(t: PType): BiggestInt = 
   case t.kind
   of tyInt64, tyInt32, tyInt: result = lastOrd(t)
   of tyDistinct, tyConst, tyMutable: result = lengthOrd(t.sons[0])
@@ -606,8 +636,11 @@ type
     dcEqOrDistinctOf       ## a equals b or a is distinct of b
 
   TTypeCmpFlag* = enum
-    IgnoreTupleFields,
-    TypeDescExactMatch,
+    IgnoreTupleFields
+    IgnoreCC
+    ExactTypeDescValues
+    ExactGenericParams
+    ExactConstraints
     AllowCommonBase
 
   TTypeCmpFlags* = set[TTypeCmpFlag]
@@ -621,39 +654,41 @@ type
 
 proc initSameTypeClosure: TSameTypeClosure =
   # we do the initialization lazily for performance (avoids memory allocations)
-  nil
+  discard
   
 proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool =
-  result = not IsNil(c.s) and c.s.contains((a.id, b.id))
+  result = not isNil(c.s) and c.s.contains((a.id, b.id))
   if not result:
-    if IsNil(c.s): c.s = @[]
+    if isNil(c.s): c.s = @[]
     c.s.add((a.id, b.id))
 
-proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool
-proc SameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool =
+proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool
+proc sameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool =
   if a == b:
     result = true
   else:
     if a == nil or b == nil: result = false
-    else: result = SameTypeAux(a, b, c)
+    else: result = sameTypeAux(a, b, c)
 
-proc SameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
+proc sameType*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
+  var c = initSameTypeClosure()
+  c.flags = flags
+  result = sameTypeAux(a, b, c)
+
+proc sameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
   if a == b:
     result = true
-  else: 
+  else:
     if a == nil or b == nil: result = false
-    else:
-      var c = initSameTypeClosure()
-      c.flags = flags
-      result = SameTypeAux(a, b, c)
+    else: result = sameType(a, b, flags)
 
 proc equalParam(a, b: PSym): TParamsEquality = 
-  if SameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}) and
-      ExprStructuralEquivalent(a.constraint, b.constraint):
+  if sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}) and
+      exprStructuralEquivalent(a.constraint, b.constraint):
     if a.ast == b.ast: 
       result = paramsEqual
     elif a.ast != nil and b.ast != nil: 
-      if ExprStructuralEquivalent(a.ast, b.ast): result = paramsEqual
+      if exprStructuralEquivalent(a.ast, b.ast): result = paramsEqual
       else: result = paramsIncompatible
     elif a.ast != nil: 
       result = paramsEqual
@@ -661,7 +696,15 @@ proc equalParam(a, b: PSym): TParamsEquality =
       result = paramsIncompatible
   else:
     result = paramsNotEqual
-  
+
+proc sameConstraints(a, b: PNode): bool =
+  internalAssert a.len == b.len
+  for i in 1 .. <a.len:
+    if not exprStructuralEquivalent(a[i].sym.constraint,
+                                    b[i].sym.constraint):
+      return false
+  return true
+
 proc equalParams(a, b: PNode): TParamsEquality = 
   result = paramsEqual
   var length = sonsLen(a)
@@ -676,7 +719,7 @@ proc equalParams(a, b: PNode): TParamsEquality =
       of paramsNotEqual: 
         return paramsNotEqual
       of paramsEqual: 
-        nil
+        discard
       of paramsIncompatible: 
         result = paramsIncompatible
       if (m.name.id != n.name.id): 
@@ -684,14 +727,14 @@ proc equalParams(a, b: PNode): TParamsEquality =
         return paramsNotEqual # paramsIncompatible;
       # continue traversal! If not equal, we can return immediately; else
       # it stays incompatible
-    if not SameTypeOrNil(a.sons[0].typ, b.sons[0].typ, {TypeDescExactMatch}):
+    if not sameTypeOrNil(a.sons[0].typ, b.sons[0].typ, {ExactTypeDescValues}):
       if (a.sons[0].typ == nil) or (b.sons[0].typ == nil): 
         result = paramsNotEqual # one proc has a result, the other not is OK
       else: 
         result = paramsIncompatible # overloading by different
                                     # result types does not work
   
-proc SameLiteral(x, y: PNode): bool = 
+proc sameLiteral(x, y: PNode): bool = 
   if x.kind == y.kind: 
     case x.kind
     of nkCharLit..nkInt64Lit: result = x.intVal == y.intVal
@@ -699,9 +742,9 @@ proc SameLiteral(x, y: PNode): bool =
     of nkNilLit: result = true
     else: assert(false)
   
-proc SameRanges(a, b: PNode): bool = 
-  result = SameLiteral(a.sons[0], b.sons[0]) and
-           SameLiteral(a.sons[1], b.sons[1])
+proc sameRanges(a, b: PNode): bool = 
+  result = sameLiteral(a.sons[0], b.sons[0]) and
+           sameLiteral(a.sons[1], b.sons[1])
 
 proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool = 
   # two tuples are equivalent iff the names, types and positions are the same;
@@ -716,7 +759,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
         x = skipTypes(x, {tyRange})
         y = skipTypes(y, {tyRange})
       
-      result = SameTypeAux(x, y, c)
+      result = sameTypeAux(x, y, c)
       if not result: return 
     if a.n != nil and b.n != nil and IgnoreTupleFields notin c.flags:
       for i in countup(0, sonsLen(a.n) - 1): 
@@ -726,11 +769,11 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
           var y = b.n.sons[i].sym
           result = x.name.id == y.name.id
           if not result: break 
-        else: InternalError(a.n.info, "sameTuple")
+        else: internalError(a.n.info, "sameTuple")
   else:
     result = false
 
-template IfFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
+template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
   if tfFromGeneric notin a.flags + b.flags:
     # fast case: id comparison suffices:
     result = a.id == b.id
@@ -745,15 +788,15 @@ template IfFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
     #   TA[T] = object
     #   TB[T] = object
     # --> TA[int] != TB[int]
-    if tfFromGeneric in a.flags * b.flags and a.sym.Id == b.sym.Id:
+    if tfFromGeneric in a.flags * b.flags and a.sym.id == b.sym.id:
       # ok, we need the expensive structural check
       body
 
 proc sameObjectTypes*(a, b: PType): bool =
   # specialized for efficiency (sigmatch uses it)
-  IfFastObjectTypeCheckFailed(a, b):     
+  ifFastObjectTypeCheckFailed(a, b):
     var c = initSameTypeClosure()
-    result = sameTypeAux(a, b, c)    
+    result = sameTypeAux(a, b, c)
 
 proc sameDistinctTypes*(a, b: PType): bool {.inline.} =
   result = sameObjectTypes(a, b)
@@ -761,7 +804,7 @@ proc sameDistinctTypes*(a, b: PType): bool {.inline.} =
 proc sameEnumTypes*(a, b: PType): bool {.inline.} =
   result = a.id == b.id
 
-proc SameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
+proc sameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
   if a == b:
     result = true
   elif (a != nil) and (b != nil) and (a.kind == b.kind):
@@ -778,26 +821,32 @@ proc SameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
       else:
         if sonsLen(a) == sonsLen(b): 
           for i in countup(0, sonsLen(a) - 1): 
-            if not SameObjectTree(a.sons[i], b.sons[i], c): return 
+            if not sameObjectTree(a.sons[i], b.sons[i], c): return 
           result = true
 
 proc sameObjectStructures(a, b: PType, c: var TSameTypeClosure): bool =
   # check base types:
   if sonsLen(a) != sonsLen(b): return
   for i in countup(0, sonsLen(a) - 1):
-    if not SameTypeOrNilAux(a.sons[i], b.sons[i], c): return
-  if not SameObjectTree(a.n, b.n, c): return
+    if not sameTypeOrNilAux(a.sons[i], b.sons[i], c): return
+  if not sameObjectTree(a.n, b.n, c): return
   result = true
 
 proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool =
   if sonsLen(a) != sonsLen(b): return false
   result = true
   for i in countup(0, sonsLen(a) - 1):
-    result = SameTypeOrNilAux(a.sons[i], b.sons[i], c)
+    result = sameTypeOrNilAux(a.sons[i], b.sons[i], c)
     if not result: return 
 
-proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
-  template CycleCheck() =
+proc isGenericAlias*(t: PType): bool =
+  return t.kind == tyGenericInst and t.lastSon.kind == tyGenericInst
+
+proc skipGenericAlias*(t: PType): PType =
+  return if t.isGenericAlias: t.lastSon else: t
+
+proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
+  template cycleCheck() =
     # believe it or not, the direct check for ``containsOrIncl(c, a, b)``
     # increases bootstrapping time from 2.4s to 3.3s on my laptop! So we cheat
     # again: Since the recursion check is only to not get caught in an endless
@@ -825,22 +874,35 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
       if a.kind != b.kind: return false
     of dcEqOrDistinctOf:
       while a.kind == tyDistinct: a = a.sons[0]
-      if a.kind != b.kind: return false  
-  case a.Kind
+      if a.kind != b.kind: return false
+  
+  if x.kind == tyGenericInst:
+    let
+      lhs = x.skipGenericAlias
+      rhs = y.skipGenericAlias
+    if rhs.kind != tyGenericInst or lhs.base != rhs.base:
+      return false
+    for i in 1 .. lhs.len - 2:
+      let ff = rhs.sons[i]
+      let aa = lhs.sons[i]
+      if not sameTypeAux(ff, aa, c): return false
+    return true
+
+  case a.kind
   of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
-     tyInt..tyBigNum, tyStmt:
+     tyInt..tyBigNum, tyStmt, tyExpr:
     result = sameFlags(a, b)
-  of tyExpr:
-    result = ExprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
+  of tyStatic, tyFromExpr:
+    result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
   of tyObject:
-    IfFastObjectTypeCheckFailed(a, b):
-      CycleCheck()
+    ifFastObjectTypeCheckFailed(a, b):
+      cycleCheck()
       result = sameObjectStructures(a, b, c) and sameFlags(a, b)
   of tyDistinct:
-    CycleCheck()
+    cycleCheck()
     if c.cmp == dcEq:      
       if sameFlags(a, b):
-        IfFastObjectTypeCheckFailed(a, b):
+        ifFastObjectTypeCheckFailed(a, b):
           result = sameTypeAux(a.sons[0], b.sons[0], c)     
     else: 
       result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b)
@@ -848,36 +910,37 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     # XXX generic enums do not make much sense, but require structural checking
     result = a.id == b.id and sameFlags(a, b)
   of tyTuple:
-    CycleCheck()
+    cycleCheck()
     result = sameTuple(a, b, c) and sameFlags(a, b)
-  of tyGenericInst:    
-    result = sameTypeAux(lastSon(a), lastSon(b), c)
   of tyTypeDesc:
     if c.cmp == dcEqIgnoreDistinct: result = false
-    elif TypeDescExactMatch in c.flags:
-      CycleCheck()
+    elif ExactTypeDescValues in c.flags:
+      cycleCheck()
       result = sameChildrenAux(x, y, c) and sameFlags(a, b)
     else:
       result = sameFlags(a, b)
-  of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence,
+  of tyGenericParam:
+    result = sameChildrenAux(a, b, c) and sameFlags(a, b)
+    if result and ExactGenericParams in c.flags:
+      result = a.sym.position == b.sym.position
+  of tyGenericInvokation, tyGenericBody, tySequence,
      tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
      tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
-     tyOrdinal, tyTypeClasses:
-    CycleCheck()    
+     tyOrdinal, tyTypeClasses, tyFieldAccessor:
+    cycleCheck()
+    if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n
     result = sameChildrenAux(a, b, c) and sameFlags(a, b)
-    if result and (a.kind == tyProc):
-      result = a.callConv == b.callConv
+    if result and a.kind == tyProc:
+      result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and
+               ((ExactConstraints notin c.flags) or sameConstraints(a.n, b.n))
   of tyRange:
-    CycleCheck()
-    result = SameTypeOrNilAux(a.sons[0], b.sons[0], c) and
-        SameValue(a.n.sons[0], b.n.sons[0]) and
-        SameValue(a.n.sons[1], b.n.sons[1])
+    cycleCheck()
+    result = sameTypeOrNilAux(a.sons[0], b.sons[0], c) and
+        sameValue(a.n.sons[0], b.n.sons[0]) and
+        sameValue(a.n.sons[1], b.n.sons[1])
+  of tyGenericInst: discard
   of tyNone: result = false  
 
-proc sameType*(x, y: PType): bool =
-  var c = initSameTypeClosure()
-  result = sameTypeAux(x, y, c)
-
 proc sameBackendType*(x, y: PType): bool =
   var c = initSameTypeClosure()
   c.flags.incl IgnoreTupleFields
@@ -954,7 +1017,7 @@ proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind,
     if result: 
       case n.kind
       of nkNone..nkNilLit: 
-        nil
+        discard
       else: 
         for i in countup(0, sonsLen(n) - 1): 
           result = typeAllowedNode(marker, n.sons[i], kind, flags)
@@ -965,52 +1028,10 @@ proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]],
   var a = a
   for k, i in pattern.items:
     if a.kind != k: return false
-    if i >= a.sonslen or a.sons[i] == nil: return false
+    if i >= a.sonsLen or a.sons[i] == nil: return false
     a = a.sons[i]
   result = a.kind == last
 
-proc isGenericAlias*(t: PType): bool =
-  return t.kind == tyGenericInst and t.lastSon.kind == tyGenericInst
-
-proc skipGenericAlias*(t: PType): PType =
-  return if t.isGenericAlias: t.lastSon else: t
-
-proc matchTypeClass*(bindings: var TIdTable, typeClass, t: PType): bool =
-  for i in countup(0, typeClass.sonsLen - 1):
-    let req = typeClass.sons[i]
-    var match = req.kind == skipTypes(t, {tyRange, tyGenericInst}).kind
-
-    if not match:
-      case req.kind
-      of tyGenericBody:
-        if t.kind == tyGenericInst and t.sons[0] == req:
-          match = true
-          IdTablePut(bindings, typeClass, t)
-      of tyTypeClass:
-        match = matchTypeClass(bindings, req, t)
-      elif t.kind == tyTypeClass:
-        match = matchTypeClass(bindings, t, req)
-          
-    elif t.kind in {tyObject} and req.len != 0:
-      # empty 'object' is fine as constraint in a type class
-      match = sameType(t, req)
-
-    if tfAny in typeClass.flags:
-      if match: return true
-    else:
-      if not match: return false
-
-  # if the loop finished without returning, either all constraints matched
-  # or none of them matched.
-  result = if tfAny in typeClass.flags: false else: true
-  if result == true:
-    IdTablePut(bindings, typeClass, t)
-
-proc matchTypeClass*(typeClass, typ: PType): bool =
-  var bindings: TIdTable
-  initIdTable(bindings)
-  result = matchTypeClass(bindings, typeClass, typ)
-
 proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
                     flags: TTypeAllowedFlags = {}): bool =
   assert(kind in {skVar, skLet, skConst, skParam, skResult})
@@ -1018,7 +1039,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
   # evaluation if something is wrong:
   result = true
   if typ == nil: return
-  if ContainsOrIncl(marker, typ.id): return 
+  if containsOrIncl(marker, typ.id): return 
   var t = skipTypes(typ, abstractInst-{tyTypeDesc})
   case t.kind
   of tyVar:
@@ -1038,14 +1059,16 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
       if not result: break 
     if result and t.sons[0] != nil:
       result = typeAllowedAux(marker, t.sons[0], skResult, flags)
-  of tyExpr, tyStmt, tyTypeDesc:
+  of tyExpr, tyStmt, tyTypeDesc, tyStatic:
     result = true
     # XXX er ... no? these should not be allowed!
   of tyEmpty:
     result = taField in flags
   of tyTypeClasses:
-    result = true
-  of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation:
+    result = tfGenericTypeParam in t.flags or
+             taField notin flags
+  of tyGenericBody, tyGenericParam, tyGenericInvokation,
+     tyNone, tyForward, tyFromExpr, tyFieldAccessor:
     result = false
   of tyNil:
     result = kind == skConst
@@ -1068,9 +1091,9 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
         typeAllowedAux(marker, t.sons[1], skVar, flags)
   of tyRef:
     if kind == skConst: return false
-    result = typeAllowedAux(marker, t.sons[0], skVar, flags+{taHeap})
+    result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap})
   of tyPtr:
-    result = typeAllowedAux(marker, t.sons[0], skVar, flags+{taHeap})
+    result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap})
   of tyArrayConstr, tySet, tyConst, tyMutable, tyIter:
     for i in countup(0, sonsLen(t) - 1):
       result = typeAllowedAux(marker, t.sons[i], kind, flags)
@@ -1088,15 +1111,15 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
     result = true
 
 proc typeAllowed(t: PType, kind: TSymKind): bool = 
-  var marker = InitIntSet()
+  var marker = initIntSet()
   result = typeAllowedAux(marker, t, kind, {})
 
-proc align(address, alignment: biggestInt): biggestInt = 
+proc align(address, alignment: BiggestInt): BiggestInt = 
   result = (address + (alignment - 1)) and not (alignment - 1)
 
-proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt
-proc computeRecSizeAux(n: PNode, a, currOffset: var biggestInt): biggestInt = 
-  var maxAlign, maxSize, b, res: biggestInt
+proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt
+proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt = 
+  var maxAlign, maxSize, b, res: BiggestInt
   case n.kind
   of nkRecCase: 
     assert(n.sons[0].kind == nkSym)
@@ -1128,25 +1151,29 @@ proc computeRecSizeAux(n: PNode, a, currOffset: var biggestInt): biggestInt =
     result = computeSizeAux(n.sym.typ, a)
     n.sym.offset = int(currOffset)
   else: 
-    InternalError("computeRecSizeAux()")
+    internalError("computeRecSizeAux()")
     a = 1
     result = - 1
 
-proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt = 
-  var res, maxAlign, length, currOffset: biggestInt
-  if typ.size == - 2: 
+const 
+  szIllegalRecursion* = -2
+  szUnknownSize* = -1
+
+proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
+  var res, maxAlign, length, currOffset: BiggestInt
+  if typ.size == szIllegalRecursion:
     # we are already computing the size of the type
     # --> illegal recursion in type
-    return - 2
-  if typ.size >= 0: 
+    return szIllegalRecursion
+  if typ.size >= 0:
     # size already computed
     result = typ.size
     a = typ.align
     return 
-  typ.size = - 2              # mark as being computed
+  typ.size = szIllegalRecursion # mark as being computed
   case typ.kind
   of tyInt, tyUInt: 
-    result = IntSize
+    result = intSize
     a = result
   of tyInt8, tyUInt8, tyBool, tyChar: 
     result = 1
@@ -1174,8 +1201,10 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
      tyBigNum: 
     result = ptrSize
     a = result
-  of tyArray, tyArrayConstr: 
-    result = lengthOrd(typ.sons[0]) * computeSizeAux(typ.sons[1], a)
+  of tyArray, tyArrayConstr:
+    let elemSize = computeSizeAux(typ.sons[1], a)
+    if elemSize < 0: return elemSize
+    result = lengthOrd(typ.sons[0]) * elemSize
   of tyEnum: 
     if firstOrd(typ) < 0: 
       result = 4              # use signed int32
@@ -1183,7 +1212,7 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
       length = lastOrd(typ)   # BUGFIX: use lastOrd!
       if length + 1 < `shl`(1, 8): result = 1
       elif length + 1 < `shl`(1, 16): result = 2
-      elif length + 1 < `shl`(biggestInt(1), 32): result = 4
+      elif length + 1 < `shl`(BiggestInt(1), 32): result = 4
       else: result = 8
     a = result
   of tySet: 
@@ -1226,30 +1255,40 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
   of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst, tyIter:
     result = computeSizeAux(lastSon(typ), a)
   of tyTypeDesc:
-    result = (if typ.len == 1: computeSizeAux(typ.sons[0], a) else: -1)
-  of tyProxy: result = 1
+    result = computeSizeAux(typ.base, a)
+  of tyForward: return szIllegalRecursion
   else:
     #internalError("computeSizeAux()")
-    result = - 1
+    result = szUnknownSize
   typ.size = result
   typ.align = int(a)
 
-proc computeSize(typ: PType): biggestInt = 
-  var a: biggestInt = 1
+proc computeSize(typ: PType): BiggestInt = 
+  var a: BiggestInt = 1
   result = computeSizeAux(typ, a)
 
 proc getReturnType*(s: PSym): PType =
   # Obtains the return type of a iterator/proc/macro/template
-  assert s.kind in {skProc, skTemplate, skMacro, skIterator}
+  assert s.kind in skProcKinds
   result = s.typ.sons[0]
 
-proc getSize(typ: PType): biggestInt = 
+proc getSize(typ: PType): BiggestInt = 
   result = computeSize(typ)
-  if result < 0: InternalError("getSize: " & $typ.kind)
+  if result < 0: internalError("getSize: " & $typ.kind)
 
-  
-proc containsGenericTypeIter(t: PType, closure: PObject): bool = 
-  result = t.kind in GenericTypes
+proc containsGenericTypeIter(t: PType, closure: PObject): bool =
+  if t.kind == tyStatic:
+    return t.n == nil
+
+  if t.kind == tyTypeDesc:
+    if t.base.kind == tyNone: return true
+    if containsGenericTypeIter(t.base, closure): return true
+    return false
+
+  if t.kind in GenericTypes + tyTypeClasses + {tyFromExpr}:
+    return true
+
+  return false
 
 proc containsGenericType*(t: PType): bool = 
   result = iterOverType(t, containsGenericTypeIter, nil)
@@ -1263,7 +1302,7 @@ proc baseOfDistinct*(t: PType): PType =
     var it = result
     while it.kind in {tyPtr, tyRef}:
       parent = it
-      it = it.sons[0]
+      it = it.lastSon
     if it.kind == tyDistinct:
       internalAssert parent != nil
       parent.sons[0] = it.sons[0]
@@ -1288,8 +1327,8 @@ proc compatibleEffectsAux(se, re: PNode): bool =
 proc compatibleEffects*(formal, actual: PType): bool =
   # for proc type compatibility checking:
   assert formal.kind == tyProc and actual.kind == tyProc
-  InternalAssert formal.n.sons[0].kind == nkEffectList
-  InternalAssert actual.n.sons[0].kind == nkEffectList
+  internalAssert formal.n.sons[0].kind == nkEffectList
+  internalAssert actual.n.sons[0].kind == nkEffectList
   
   var spec = formal.n.sons[0]
   if spec.len != 0:
@@ -1299,7 +1338,7 @@ proc compatibleEffects*(formal, actual: PType): bool =
     # if 'se.kind == nkArgList' it is no formal type really, but a
     # computed effect and as such no spec:
     # 'r.msgHandler = if isNil(msgHandler): defaultMsgHandler else: msgHandler'
-    if not IsNil(se) and se.kind != nkArgList:
+    if not isNil(se) and se.kind != nkArgList:
       # spec requires some exception or tag, but we don't know anything:
       if real.len == 0: return false
       result = compatibleEffectsAux(se, real.sons[exceptionEffects])
@@ -1314,7 +1353,7 @@ proc compatibleEffects*(formal, actual: PType): bool =
   result = true
 
 proc isCompileTimeOnly*(t: PType): bool {.inline.} =
-  result = t.kind in {tyTypedesc, tyExpr}
+  result = t.kind in {tyTypeDesc, tyStatic}
 
 proc containsCompileTimeOnly*(t: PType): bool =
   if isCompileTimeOnly(t): return true
diff --git a/compiler/typesrenderer.nim b/compiler/typesrenderer.nim
new file mode 100644
index 000000000..ebb9b7e15
--- /dev/null
+++ b/compiler/typesrenderer.nim
@@ -0,0 +1,113 @@
+import renderer, strutils, ast, msgs, types
+
+const defaultParamSeparator* = ","
+
+proc renderPlainSymbolName*(n: PNode): string =
+  ## Returns the first non '*' nkIdent node from the tree.
+  ##
+  ## Use this on documentation name nodes to extract the *raw* symbol name,
+  ## without decorations, parameters, or anything. That can be used as the base
+  ## for the HTML hyperlinks.
+  result = ""
+  case n.kind
+  of nkPostfix:
+    for i in 0 .. <n.len:
+      result = renderPlainSymbolName(n[<n.len])
+      if result.len > 0:
+        return
+  of nkIdent:
+    if n.ident.s != "*":
+      result = n.ident.s
+  of nkSym:
+    result = n.sym.renderDefinitionName(noQuotes = true)
+  of nkPragmaExpr:
+    result = renderPlainSymbolName(n[0])
+  of nkAccQuoted:
+    result = renderPlainSymbolName(n[<n.len])
+  else:
+    internalError(n.info, "renderPlainSymbolName() with " & $n.kind)
+  assert (not result.isNil)
+
+proc renderType(n: PNode): string =
+  ## Returns a string with the node type or the empty string.
+  case n.kind:
+  of nkIdent: result = n.ident.s
+  of nkSym: result = typeToString(n.sym.typ)
+  of nkVarTy:
+    assert len(n) == 1
+    result = renderType(n[0])
+  of nkRefTy:
+    assert len(n) == 1
+    result = "ref." & renderType(n[0])
+  of nkPtrTy:
+    assert len(n) == 1
+    result = "ptr." & renderType(n[0])
+  of nkProcTy:
+    assert len(n) > 1
+    let params = n[0]
+    assert params.kind == nkFormalParams
+    assert len(params) > 0
+    result = "proc("
+    for i in 1 .. <len(params): result.add(renderType(params[i]) & ',')
+    result[<len(result)] = ')'
+  of nkIdentDefs:
+    assert len(n) >= 3
+    let typePos = len(n) - 2
+    let typeStr = renderType(n[typePos])
+    result = typeStr
+    for i in 1 .. <typePos:
+      assert n[i].kind == nkIdent
+      result.add(',' & typeStr)
+  of nkTupleTy:
+    assert len(n) > 0
+    result = "tuple["
+    for i in 0 .. <len(n): result.add(renderType(n[i]) & ',')
+    result[<len(result)] = ']'
+  of nkBracketExpr:
+    assert len(n) >= 2
+    result = renderType(n[0]) & '['
+    for i in 1 .. <len(n): result.add(renderType(n[i]) & ',')
+    result[<len(result)] = ']'
+  else: result = ""
+  assert (not result.isNil)
+
+
+proc renderParamTypes(found: var seq[string], n: PNode) =
+  ## Recursive helper, adds to `found` any types, or keeps diving the AST.
+  ##
+  ## The normal `doc` generator doesn't include .typ information, so the
+  ## function won't render types for parameters with default values. The `doc2`
+  ## generator does include the information.
+  case n.kind
+  of nkFormalParams:
+    for i in 1 .. <len(n): renderParamTypes(found, n[i])
+  of nkIdentDefs:
+    # These are parameter names + type + default value node.
+    let typePos = len(n) - 2
+    assert typePos > 0
+    var typeStr = renderType(n[typePos])
+    if typeStr.len < 1:
+      # Try with the last node, maybe its a default value.
+      assert n[typePos+1].kind != nkEmpty
+      let typ = n[typePos+1].typ
+      if not typ.isNil: typeStr = typeToString(typ, preferExported)
+      if typeStr.len < 1:
+        return
+    for i in 0 .. <typePos:
+      assert n[i].kind == nkIdent
+      found.add(typeStr)
+  else:
+    internalError(n.info, "renderParamTypes(found,n) with " & $n.kind)
+
+proc renderParamTypes*(n: PNode, sep = defaultParamSeparator): string =
+  ## Returns the types contained in `n` joined by `sep`.
+  ##
+  ## This proc expects to be passed as `n` the parameters of any callable. The
+  ## string output is meant for the HTML renderer. If there are no parameters,
+  ## the empty string is returned. The parameters will be joined by `sep` but
+  ## other characters may appear too, like ``[]`` or ``|``.
+  result = ""
+  var found: seq[string] = @[]
+  renderParamTypes(found, n)
+  if found.len > 0:
+    result = found.join(sep)
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 7705746de..fb8749250 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1,26 +1,46 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
 ## This file implements the new evaluation engine for Nimrod code.
-## An instruction is 1-2 int32s in memory, it is a register based VM.
+## An instruction is 1-3 int32s in memory, it is a register based VM.
+
+const debugEchoCode = false
+
+import ast except getstr
 
 import
-  strutils, ast, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
-  parser, vmdeps, idents
+  strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
+  parser, vmdeps, idents, trees, renderer, options, transf
 
 from semfold import leValueConv, ordinalValToString
+from evaltempl import evalTemplate
+
+when hasFFI:
+  import evalffi
 
 type
+  TRegisterKind = enum
+    rkNone, rkNode, rkInt, rkFloat, rkRegisterAddr, rkNodeAddr
+  TFullReg = object   # with a custom mark proc, we could use the same
+                      # data representation as LuaJit (tagged NaNs).
+    case kind: TRegisterKind
+    of rkNone: nil
+    of rkInt: intVal: BiggestInt
+    of rkFloat: floatVal: BiggestFloat
+    of rkNode: node: PNode
+    of rkRegisterAddr: regAddr: ptr TFullReg
+    of rkNodeAddr: nodeAddr: ptr PNode
+
   PStackFrame* = ref TStackFrame
   TStackFrame* = object
     prc: PSym                 # current prc; proc that is evaluated
-    slots: TNodeSeq           # parameters passed to the proc + locals;
+    slots: seq[TFullReg]      # parameters passed to the proc + locals;
                               # parameters come first
     next: PStackFrame         # for stacking
     comesFrom: int
@@ -28,13 +48,21 @@ type
                               # XXX 'break' should perform cleanup actions
                               # What does the C backend do for it?
 
-proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int) =
+proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
   if x != nil:
-    stackTraceAux(c, x.next, x.comesFrom)
+    if recursionLimit == 0:
+      var calls = 0
+      var x = x
+      while x != nil:
+        inc calls
+        x = x.next
+      msgWriteln($calls & " calls omitted\n")
+      return
+    stackTraceAux(c, x.next, x.comesFrom, recursionLimit-1)
     var info = c.debug[pc]
     # we now use the same format as in system/except.nim
     var s = toFilename(info)
-    var line = toLineNumber(info)
+    var line = toLinenumber(info)
     if line > 0:
       add(s, '(')
       add(s, $line)
@@ -42,13 +70,15 @@ proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int) =
     if x.prc != nil:
       for k in 1..max(1, 25-s.len): add(s, ' ')
       add(s, x.prc.name.s)
-    MsgWriteln(s)
+    msgWriteln(s)
 
 proc stackTrace(c: PCtx, tos: PStackFrame, pc: int,
                 msg: TMsgKind, arg = "") =
-  MsgWriteln("stack trace: (most recent call last)")
+  msgWriteln("stack trace: (most recent call last)")
   stackTraceAux(c, tos, pc)
-  LocalError(c.debug[pc], msg, arg)
+  # XXX test if we want 'globalError' for every mode
+  if c.mode == emRepl: globalError(c.debug[pc], msg, arg)
+  else: localError(c.debug[pc], msg, arg)
 
 proc bailOut(c: PCtx; tos: PStackFrame) =
   stackTrace(c, tos, c.exceptionInstr, errUnhandledExceptionX,
@@ -57,14 +87,9 @@ proc bailOut(c: PCtx; tos: PStackFrame) =
 when not defined(nimComputedGoto):
   {.pragma: computedGoto.}
 
-template inc(pc: ptr TInstr, diff = 1) =
-  inc cast[TAddress](pc), TInstr.sizeof * diff
-
-proc myreset(n: PNode) =
+proc myreset(n: var TFullReg) =
   when defined(system.reset): 
-    var oldInfo = n.info
-    reset(n[])
-    n.info = oldInfo
+    reset(n)
 
 template ensureKind(k: expr) {.immediate, dirty.} =
   if regs[ra].kind != k:
@@ -93,40 +118,111 @@ template decodeBx(k: expr) {.immediate, dirty.} =
   let rbx = instr.regBx - wordExcess
   ensureKind(k)
 
-template move(a, b: expr) = system.shallowCopy(a, b)
+template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b)
 # XXX fix minor 'shallowCopy' overloading bug in compiler
 
-proc asgnRef(x, y: PNode) =
-  myreset(x)
-  x.kind = y.kind
-  x.typ = y.typ
+proc createStrKeepNode(x: var TFullReg) =
+  if x.node.isNil:
+    x.node = newNode(nkStrLit)
+  elif x.node.kind == nkNilLit:
+    system.reset(x.node[])
+    x.node.kind = nkStrLit
+  elif x.node.kind notin {nkStrLit..nkTripleStrLit}:
+    # XXX this is hacky; tests/txmlgen triggers it:
+    x.node = newNode(nkStrLit)
+    #  debug x.node
+    #assert x.node.kind in {nkStrLit..nkTripleStrLit}
+
+template createStr(x) =
+  x.node = newNode(nkStrLit)
+
+proc moveConst(x: var TFullReg, y: TFullReg) =
+  if x.kind != y.kind:
+    myreset(x)
+    x.kind = y.kind
   case x.kind
-  of nkCharLit..nkInt64Lit: x.intVal = y.intVal
-  of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal
-  of nkStrLit..nkTripleStrLit: x.strVal = y.strVal
-  of nkIdent: x.ident = y.ident
-  of nkSym: x.sym = y.sym
+  of rkNone: discard
+  of rkInt: x.intVal = y.intVal
+  of rkFloat: x.floatVal = y.floatVal
+  of rkNode: x.node = y.node
+  of rkRegisterAddr: x.regAddr = y.regAddr
+  of rkNodeAddr: x.nodeAddr = y.nodeAddr
+
+# this seems to be the best way to model the reference semantics
+# of PNimrodNode:
+template asgnRef(x, y: expr) = moveConst(x, y)
+
+proc copyValue(src: PNode): PNode =
+  if src == nil or nfIsRef in src.flags:
+    return src
+  result = newNode(src.kind)
+  result.info = src.info
+  result.typ = src.typ
+  result.flags = src.flags * PersistentNodeFlags
+  when defined(useNodeIds):
+    if result.id == nodeIdToDebug:
+      echo "COMES FROM ", src.id
+  case src.kind
+  of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
+  of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
+  of nkSym: result.sym = src.sym
+  of nkIdent: result.ident = src.ident
+  of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
   else:
-    if x.kind notin {nkEmpty..nkNilLit}:
-      move(x.sons, y.sons)
+    newSeq(result.sons, sonsLen(src))
+    for i in countup(0, sonsLen(src) - 1):
+      result.sons[i] = copyValue(src.sons[i])
+
+proc asgnComplex(x: var TFullReg, y: TFullReg) =
+  if x.kind != y.kind:
+    myreset(x)
+    x.kind = y.kind
+  case x.kind
+  of rkNone: discard
+  of rkInt: x.intVal = y.intVal
+  of rkFloat: x.floatVal = y.floatVal
+  of rkNode: x.node = copyValue(y.node)
+  of rkRegisterAddr: x.regAddr = y.regAddr
+  of rkNodeAddr: x.nodeAddr = y.nodeAddr
 
-proc asgnComplex(x, y: PNode) =
-  myreset(x)
-  x.kind = y.kind
-  x.typ = y.typ
+proc putIntoNode(n: var PNode; x: TFullReg) =
   case x.kind
-  of nkCharLit..nkInt64Lit: x.intVal = y.intVal
-  of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal
-  of nkStrLit..nkTripleStrLit: x.strVal = y.strVal
-  of nkIdent: x.ident = y.ident
-  of nkSym: x.sym = y.sym
+  of rkNone: discard
+  of rkInt: n.intVal = x.intVal
+  of rkFloat: n.floatVal = x.floatVal
+  of rkNode:
+    if nfIsRef in x.node.flags: n = x.node
+    else: n[] = x.node[]
+  of rkRegisterAddr: putIntoNode(n, x.regAddr[])
+  of rkNodeAddr: n[] = x.nodeAddr[][]
+
+proc putIntoReg(dest: var TFullReg; n: PNode) =
+  case n.kind
+  of nkStrLit..nkTripleStrLit:
+    dest.kind = rkNode
+    createStr(dest)
+    dest.node.strVal = n.strVal
+  of nkCharLit..nkUInt64Lit:
+    dest.kind = rkInt
+    dest.intVal = n.intVal
+  of nkFloatLit..nkFloat128Lit:
+    dest.kind = rkFloat
+    dest.floatVal = n.floatVal
   else:
-    if x.kind notin {nkEmpty..nkNilLit}:
-      let y = y.copyTree
-      for i in countup(0, sonsLen(y) - 1): addSon(x, y.sons[i])
+    dest.kind = rkNode
+    dest.node = n
+
+proc regToNode(x: TFullReg): PNode =
+  case x.kind
+  of rkNone: result = newNode(nkEmpty)
+  of rkInt: result = newNode(nkIntLit); result.intVal = x.intVal
+  of rkFloat: result = newNode(nkFloatLit); result.floatVal = x.floatVal
+  of rkNode: result = x.node
+  of rkRegisterAddr: result = regToNode(x.regAddr[])
+  of rkNodeAddr: result = x.nodeAddr[]
 
 template getstr(a: expr): expr =
-  (if a.kind == nkStrLit: a.strVal else: $chr(int(a.intVal)))
+  (if a.kind == rkNode: a.node.strVal else: $chr(int(a.intVal)))
 
 proc pushSafePoint(f: PStackFrame; pc: int) =
   if f.safePoints.isNil: f.safePoints = @[]
@@ -134,13 +230,14 @@ proc pushSafePoint(f: PStackFrame; pc: int) =
 
 proc popSafePoint(f: PStackFrame) = discard f.safePoints.pop()
 
-proc cleanUpOnException(c: PCtx; tos: PStackFrame; regs: TNodeSeq): int =
+proc cleanUpOnException(c: PCtx; tos: PStackFrame): 
+                                              tuple[pc: int, f: PStackFrame] =
   let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs)
   var f = tos
   while true:
     while f.safePoints.isNil or f.safePoints.len == 0:
       f = f.next
-      if f.isNil: return -1
+      if f.isNil: return (-1, nil)
     var pc2 = f.safePoints[f.safePoints.high]
 
     var nextExceptOrFinally = -1
@@ -156,13 +253,13 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame; regs: TNodeSeq): int =
         c.currentExceptionB = c.currentExceptionA
         c.currentExceptionA = nil
         # execute the corresponding handler:
-        return pc2
+        return (pc2, f)
       inc pc2
     if nextExceptOrFinally >= 0:
       pc2 = nextExceptOrFinally
     if c.code[pc2].opcode == opcFinally:
       # execute the corresponding handler, but don't quit walking the stack:
-      return pc2
+      return (pc2, f)
     # not the right one:
     discard f.safePoints.pop
 
@@ -176,50 +273,65 @@ proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
       return pc
   return -1
 
-proc opConv*(dest, src: PNode, typ: PType): bool =
-  if typ.kind == tyString:
-    if dest.kind != nkStrLit:
+proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
+  if desttyp.kind == tyString:
+    if dest.kind != rkNode:
       myreset(dest)
-      dest.kind = nkStrLit
-    case src.typ.skipTypes(abstractRange).kind
-    of tyEnum: 
-      dest.strVal = ordinalValToString(src)
-    of tyInt..tyInt64, tyUInt..tyUInt64:
-      dest.strVal = $src.intVal
+      dest.kind = rkNode
+    dest.node = newNode(nkStrLit)
+    let styp = srctyp.skipTypes(abstractRange)
+    case styp.kind
+    of tyEnum:
+      let n = styp.n
+      let x = src.intVal.int
+      if x <% n.len and (let f = n.sons[x].sym; f.position == x):
+        dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
+      else:
+        for i in 0.. <n.len:
+          if n.sons[i].kind != nkSym: internalError("opConv for enum")
+          let f = n.sons[i].sym
+          if f.position == x:
+            dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
+            return
+        internalError("opConv for enum")
+    of tyInt..tyInt64:
+      dest.node.strVal = $src.intVal
+    of tyUInt..tyUInt64:
+      dest.node.strVal = $uint64(src.intVal)
     of tyBool:
-      dest.strVal = if src.intVal == 0: "false" else: "true"
+      dest.node.strVal = if src.intVal == 0: "false" else: "true"
     of tyFloat..tyFloat128:
-      dest.strVal = $src.floatVal
+      dest.node.strVal = $src.floatVal
     of tyString, tyCString:
-      dest.strVal = src.strVal
+      dest.node.strVal = src.node.strVal
     of tyChar:
-      dest.strVal = $chr(src.intVal)
+      dest.node.strVal = $chr(src.intVal)
     else:
-      internalError("cannot convert to string " & typ.typeToString)
+      internalError("cannot convert to string " & desttyp.typeToString)
   else:
-    case skipTypes(typ, abstractRange).kind
+    case skipTypes(desttyp, abstractRange).kind
     of tyInt..tyInt64:
-      if dest.kind != nkIntLit:
-        myreset(dest); dest.kind = nkIntLit
-      case skipTypes(src.typ, abstractRange).kind
+      if dest.kind != rkInt:
+        myreset(dest); dest.kind = rkInt
+      case skipTypes(srctyp, abstractRange).kind
       of tyFloat..tyFloat64:
         dest.intVal = system.toInt(src.floatVal)
       else:
         dest.intVal = src.intVal
-      if dest.intVal < firstOrd(typ) or dest.intVal > lastOrd(typ):
+      if dest.intVal < firstOrd(desttyp) or dest.intVal > lastOrd(desttyp):
         return true
     of tyUInt..tyUInt64:
-      if dest.kind != nkIntLit:
-        myreset(dest); dest.kind = nkIntLit
-      case skipTypes(src.typ, abstractRange).kind
+      if dest.kind != rkInt:
+        myreset(dest); dest.kind = rkInt
+      case skipTypes(srctyp, abstractRange).kind
       of tyFloat..tyFloat64:
         dest.intVal = system.toInt(src.floatVal)
       else:
-        dest.intVal = src.intVal and ((1 shl typ.size)-1)
+        dest.intVal = src.intVal and ((1 shl (desttyp.size*8))-1)
     of tyFloat..tyFloat64:
-      if dest.kind != nkFloatLit:
-        myreset(dest); dest.kind = nkFloatLit
-      case skipTypes(src.typ, abstractRange).kind
+      if dest.kind != rkFloat:
+        myreset(dest); dest.kind = rkFloat
+      case skipTypes(srctyp, abstractRange).kind
       of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar: 
         dest.floatVal = toFloat(src.intVal.int)
       else:
@@ -229,18 +341,32 @@ proc opConv*(dest, src: PNode, typ: PType): bool =
 
 proc compile(c: PCtx, s: PSym): int = 
   result = vmgen.genProc(c, s)
+  when debugEchoCode: c.echoCode result
   #c.echoCode
 
-proc rawExecute(c: PCtx, start: int, tos: PStackFrame) =
+template handleJmpBack() {.dirty.} =
+  if c.loopIterations <= 0:
+    if allowInfiniteLoops in c.features:
+      c.loopIterations = MaxLoopIterations
+    else:
+      msgWriteln("stack trace: (most recent call last)")
+      stackTraceAux(c, tos, pc)
+      globalError(c.debug[pc], errTooManyIterations)
+  dec(c.loopIterations)
+
+proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
   var pc = start
   var tos = tos
-  var regs: TNodeSeq # alias to tos.slots for performance
+  var regs: seq[TFullReg] # alias to tos.slots for performance
   move(regs, tos.slots)
+  #echo "NEW RUN ------------------------"
   while true:
-    {.computedGoto.}
+    #{.computedGoto.}
     let instr = c.code[pc]
     let ra = instr.regA
-    #echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
+    #if c.traceActive:
+    #  echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
+    #  message(c.debug[pc], warnUser, "Trace")
     case instr.opcode
     of opcEof: return regs[ra]
     of opcRet:
@@ -248,284 +374,403 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame) =
       pc = tos.comesFrom
       tos = tos.next
       let retVal = regs[0]
-      if tos.isNil: return retVal
+      if tos.isNil: 
+        #echo "RET ", retVal.rendertree
+        return retVal
       
       move(regs, tos.slots)
       assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
       if c.code[pc].opcode == opcIndCallAsgn:
         regs[c.code[pc].regA] = retVal
+        #echo "RET2 ", retVal.rendertree, " ", c.code[pc].regA
     of opcYldYoid: assert false
     of opcYldVal: assert false
     of opcAsgnInt:
-      decodeB(nkIntLit)
+      decodeB(rkInt)
       regs[ra].intVal = regs[rb].intVal
     of opcAsgnStr:
-      decodeB(nkStrLit)
-      regs[ra].strVal = regs[rb].strVal
+      decodeB(rkNode)
+      createStrKeepNode regs[ra]
+      regs[ra].node.strVal = regs[rb].node.strVal
     of opcAsgnFloat:
-      decodeB(nkFloatLit)
+      decodeB(rkFloat)
       regs[ra].floatVal = regs[rb].floatVal
     of opcAsgnComplex:
       asgnComplex(regs[ra], regs[instr.regB])
     of opcAsgnRef:
       asgnRef(regs[ra], regs[instr.regB])
-    of opcWrGlobalRef:
-      asgnRef(c.globals[instr.regBx-wordExcess-1], regs[ra])
-    of opcWrGlobal:
-      asgnComplex(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
+    of opcRegToNode:
+      decodeB(rkNode)
+      putIntoNode(regs[ra].node, regs[rb])
+    of opcNodeToReg:
+      let ra = instr.regA
+      let rb = instr.regB
+      # opcDeref might already have loaded it into a register. XXX Let's hope
+      # this is still correct this way:
+      if regs[rb].kind != rkNode:
+        regs[ra] = regs[rb]
+      else:
+        assert regs[rb].kind == rkNode
+        let nb = regs[rb].node
+        case nb.kind
+        of nkCharLit..nkInt64Lit:
+          ensureKind(rkInt)
+          regs[ra].intVal = nb.intVal
+        of nkFloatLit..nkFloat64Lit:
+          ensureKind(rkFloat)
+          regs[ra].floatVal = nb.floatVal
+        else:
+          ensureKind(rkNode)
+          regs[ra].node = nb
     of opcLdArr:
       # a = b[c]
-      let rb = instr.regB
-      let rc = instr.regC
-      let idx = regs[rc].intVal
+      decodeBC(rkNode)
+      if regs[rc].intVal > high(int):
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
+      let idx = regs[rc].intVal.int
       # XXX what if the array is not 0-based? -> codegen should insert a sub
-      regs[ra] = regs[rb].sons[idx.int]
+      let src = regs[rb].node
+      if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
+        regs[ra].node = src.sons[idx]
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcLdStrIdx:
-      decodeBC(nkIntLit)
-      let idx = regs[rc].intVal
-      regs[ra].intVal = regs[rb].strVal[idx.int].ord
+      decodeBC(rkInt)
+      let idx = regs[rc].intVal.int
+      if idx <=% regs[rb].node.strVal.len:
+        regs[ra].intVal = regs[rb].node.strVal[idx].ord
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcWrArr:
       # a[b] = c
-      let rb = instr.regB
-      let rc = instr.regC
-      let idx = regs[rb].intVal
-      asgnComplex(regs[ra].sons[idx.int], regs[rc])
-    of opcWrArrRef:
-      let rb = instr.regB
-      let rc = instr.regC
-      let idx = regs[rb].intVal
-      asgnRef(regs[ra].sons[idx.int], regs[rc])
+      decodeBC(rkNode)
+      let idx = regs[rb].intVal.int
+      if idx <% regs[ra].node.len:
+        putIntoNode(regs[ra].node.sons[idx], regs[rc])
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcLdObj:
       # a = b.c
-      let rb = instr.regB
-      let rc = instr.regC
-      # XXX this creates a wrong alias
-      #Message(c.debug[pc], warnUser, $regs[rb].len & " " & $rc)
-      asgnComplex(regs[ra], regs[rb].sons[rc])
+      decodeBC(rkNode)
+      let src = regs[rb].node
+      if src.kind notin {nkEmpty..nkNilLit}:
+        let n = src.sons[rc]
+        regs[ra].node = n
+      else:
+        stackTrace(c, tos, pc, errNilAccess)
     of opcWrObj:
       # a.b = c
-      let rb = instr.regB
-      let rc = instr.regC
-      asgnComplex(regs[ra].sons[rb], regs[rc])
-    of opcWrObjRef:
-      let rb = instr.regB
-      let rc = instr.regC
-      asgnRef(regs[ra].sons[rb], regs[rc])
+      decodeBC(rkNode)
+      putIntoNode(regs[ra].node.sons[rb], regs[rc])
     of opcWrStrIdx:
-      decodeBC(nkStrLit)
+      decodeBC(rkNode)
       let idx = regs[rb].intVal.int
-      regs[ra].strVal[idx] = chr(regs[rc].intVal)
-    of opcAddr:
-      decodeB(nkRefTy)
-      if regs[ra].len == 0: regs[ra].add regs[rb]
-      else: regs[ra].sons[0] = regs[rb]
-    of opcDeref:
+      if idx <% regs[ra].node.strVal.len:
+        regs[ra].node.strVal[idx] = chr(regs[rc].intVal)
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
+    of opcAddrReg:
+      decodeB(rkRegisterAddr)
+      regs[ra].regAddr = addr(regs[rb])
+    of opcAddrNode:
+      decodeB(rkNodeAddr)
+      regs[ra].nodeAddr = addr(regs[rb].node)
+    of opcLdDeref:
       # a = b[]
+      let ra = instr.regA
       let rb = instr.regB
-      if regs[rb].kind == nkNilLit:
+      case regs[rb].kind
+      of rkNodeAddr:
+        ensureKind(rkNode)
+        regs[ra].node = regs[rb].nodeAddr[]
+      of rkRegisterAddr:
+        ensureKind(regs[rb].regAddr.kind)
+        regs[ra] = regs[rb].regAddr[]
+      of rkNode:
+        if regs[rb].node.kind == nkNilLit:
+          stackTrace(c, tos, pc, errNilAccess)
+        assert regs[rb].node.kind == nkRefTy
+        regs[ra].node = regs[rb].node.sons[0]
+      else:
         stackTrace(c, tos, pc, errNilAccess)
-      assert regs[rb].kind == nkRefTy
-      regs[ra] = regs[rb].sons[0]
+    of opcWrDeref:
+      # a[] = b
+      let ra = instr.regA
+      let rb = instr.regB
+      case regs[ra].kind
+      of rkNodeAddr: putIntoNode(regs[ra].nodeAddr[], regs[rb])
+      of rkRegisterAddr: regs[ra].regAddr[] = regs[rb]
+      of rkNode: putIntoNode(regs[ra].node, regs[rb])
+      else: stackTrace(c, tos, pc, errNilAccess)
     of opcAddInt:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = regs[rb].intVal + regs[rc].intVal
+      decodeBC(rkInt)
+      let
+        bVal = regs[rb].intVal
+        cVal = regs[rc].intVal
+        sum = bVal +% cVal
+      if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
+        regs[ra].intVal = sum
+      else:
+        stackTrace(c, tos, pc, errOverOrUnderflow)
     of opcAddImmInt:
-      decodeBImm(nkIntLit)
-      regs[ra].intVal = regs[rb].intVal + imm
+      decodeBImm(rkInt)
+      #message(c.debug[pc], warnUser, "came here")
+      #debug regs[rb].node
+      let
+        bVal = regs[rb].intVal
+        cVal = imm
+        sum = bVal +% cVal
+      if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
+        regs[ra].intVal = sum
+      else:
+        stackTrace(c, tos, pc, errOverOrUnderflow)
     of opcSubInt:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = regs[rb].intVal - regs[rc].intVal
+      decodeBC(rkInt)
+      let
+        bVal = regs[rb].intVal
+        cVal = regs[rc].intVal
+        diff = bVal -% cVal
+      if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
+        regs[ra].intVal = diff
+      else:
+        stackTrace(c, tos, pc, errOverOrUnderflow)
     of opcSubImmInt:
-      decodeBImm(nkIntLit)
-      regs[ra].intVal = regs[rb].intVal - imm
+      decodeBImm(rkInt)
+      let
+        bVal = regs[rb].intVal
+        cVal = imm
+        diff = bVal -% cVal
+      if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
+        regs[ra].intVal = diff
+      else:
+        stackTrace(c, tos, pc, errOverOrUnderflow)
     of opcLenSeq:
-      decodeBImm(nkIntLit)
+      decodeBImm(rkInt)
       #assert regs[rb].kind == nkBracket
-      # also used by mNLen
-      regs[ra].intVal = regs[rb].len - imm
+      # also used by mNLen:
+      regs[ra].intVal = regs[rb].node.safeLen - imm
     of opcLenStr:
-      decodeBImm(nkIntLit)
-      assert regs[rb].kind == nkStrLit
-      regs[ra].intVal = regs[rb].strVal.len - imm
+      decodeBImm(rkInt)
+      assert regs[rb].kind == rkNode
+      regs[ra].intVal = regs[rb].node.strVal.len - imm
     of opcIncl:
-      decodeB(nkCurly)
-      if not inSet(regs[ra], regs[rb]): addSon(regs[ra], copyTree(regs[rb]))
+      decodeB(rkNode)
+      let b = regs[rb].regToNode
+      if not inSet(regs[ra].node, b):
+        addSon(regs[ra].node, copyTree(b))
+    of opcInclRange:
+      decodeBC(rkNode)
+      var r = newNode(nkRange)
+      r.add regs[rb].regToNode
+      r.add regs[rc].regToNode
+      addSon(regs[ra].node, r.copyTree)
     of opcExcl:
-      decodeB(nkCurly)
-      var b = newNodeIT(nkCurly, regs[rb].info, regs[rb].typ)
-      addSon(b, regs[rb])
-      var r = diffSets(regs[ra], b)
-      discardSons(regs[ra])
-      for i in countup(0, sonsLen(r) - 1): addSon(regs[ra], r.sons[i])
+      decodeB(rkNode)
+      var b = newNodeIT(nkCurly, regs[rb].node.info, regs[rb].node.typ)
+      addSon(b, regs[rb].regToNode)
+      var r = diffSets(regs[ra].node, b)
+      discardSons(regs[ra].node)
+      for i in countup(0, sonsLen(r) - 1): addSon(regs[ra].node, r.sons[i])
     of opcCard:
-      decodeB(nkIntLit)
-      regs[ra].intVal = nimsets.cardSet(regs[rb])
+      decodeB(rkInt)
+      regs[ra].intVal = nimsets.cardSet(regs[rb].node)
     of opcMulInt:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = regs[rb].intVal * regs[rc].intVal
+      decodeBC(rkInt)
+      let
+        bVal = regs[rb].intVal
+        cVal = regs[rc].intVal
+        product = bVal *% cVal
+        floatProd = toBiggestFloat(bVal) * toBiggestFloat(cVal)
+        resAsFloat = toBiggestFloat(product)
+      if resAsFloat == floatProd:
+        regs[ra].intVal = product
+      elif 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
+        regs[ra].intVal = product
+      else:
+        stackTrace(c, tos, pc, errOverOrUnderflow)
     of opcDivInt:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
+      decodeBC(rkInt)
+      if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
+      else: regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
     of opcModInt:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
+      decodeBC(rkInt)
+      if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
+      else: regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
     of opcAddFloat:
-      decodeBC(nkFloatLit)
+      decodeBC(rkFloat)
       regs[ra].floatVal = regs[rb].floatVal + regs[rc].floatVal
     of opcSubFloat:
-      decodeBC(nkFloatLit)
+      decodeBC(rkFloat)
       regs[ra].floatVal = regs[rb].floatVal - regs[rc].floatVal
     of opcMulFloat:
-      decodeBC(nkFloatLit)
+      decodeBC(rkFloat)
       regs[ra].floatVal = regs[rb].floatVal * regs[rc].floatVal
     of opcDivFloat:
-      decodeBC(nkFloatLit)
+      decodeBC(rkFloat)
       regs[ra].floatVal = regs[rb].floatVal / regs[rc].floatVal
     of opcShrInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal shr regs[rc].intVal
     of opcShlInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal shl regs[rc].intVal
     of opcBitandInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal and regs[rc].intVal
     of opcBitorInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal or regs[rc].intVal
     of opcBitxorInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal xor regs[rc].intVal
     of opcAddu:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal +% regs[rc].intVal
     of opcSubu:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal -% regs[rc].intVal
     of opcMulu: 
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal *% regs[rc].intVal
     of opcDivu:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal /% regs[rc].intVal
     of opcModu:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal %% regs[rc].intVal
     of opcEqInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].intVal == regs[rc].intVal)
     of opcLeInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].intVal <= regs[rc].intVal)
     of opcLtInt:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].intVal < regs[rc].intVal)
     of opcEqFloat:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].floatVal == regs[rc].floatVal)
     of opcLeFloat:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].floatVal <= regs[rc].floatVal)
     of opcLtFloat:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].floatVal < regs[rc].floatVal)
     of opcLeu:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].intVal <=% regs[rc].intVal)
     of opcLtu:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].intVal <% regs[rc].intVal)
     of opcEqRef:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = ord((regs[rb].kind == nkNilLit and
-                             regs[rc].kind == nkNilLit) or
-                             regs[rb].sons == regs[rc].sons)
+      decodeBC(rkInt)
+      regs[ra].intVal = ord((regs[rb].node.kind == nkNilLit and
+                             regs[rc].node.kind == nkNilLit) or
+                             regs[rb].node == regs[rc].node)
+    of opcEqNimrodNode:
+      decodeBC(rkInt)
+      regs[ra].intVal = ord(regs[rb].node == regs[rc].node)
     of opcXor:
-      decodeBC(nkIntLit)
+      decodeBC(rkInt)
       regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal)
     of opcNot:
-      decodeB(nkIntLit)
-      assert regs[rb].kind == nkIntLit
+      decodeB(rkInt)
+      assert regs[rb].kind == rkInt
       regs[ra].intVal = 1 - regs[rb].intVal
     of opcUnaryMinusInt:
-      decodeB(nkIntLit)
-      assert regs[rb].kind == nkIntLit
-      regs[ra].intVal = -regs[rb].intVal
+      decodeB(rkInt)
+      assert regs[rb].kind == rkInt
+      let val = regs[rb].intVal
+      if val != int64.low:
+        regs[ra].intVal = -val
+      else:
+        stackTrace(c, tos, pc, errOverOrUnderflow)
     of opcUnaryMinusFloat:
-      decodeB(nkFloatLit)
-      assert regs[rb].kind == nkFloatLit
+      decodeB(rkFloat)
+      assert regs[rb].kind == rkFloat
       regs[ra].floatVal = -regs[rb].floatVal
     of opcBitnotInt:
-      decodeB(nkIntLit)
-      assert regs[rb].kind == nkIntLit
+      decodeB(rkInt)
+      assert regs[rb].kind == rkInt
       regs[ra].intVal = not regs[rb].intVal
     of opcEqStr:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(regs[rb].strVal == regs[rc].strVal)
+      decodeBC(rkInt)
+      regs[ra].intVal = ord(regs[rb].node.strVal == regs[rc].node.strVal)
     of opcLeStr:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(regs[rb].strVal <= regs[rc].strVal)
+      decodeBC(rkInt)
+      regs[ra].intVal = ord(regs[rb].node.strVal <= regs[rc].node.strVal)
     of opcLtStr:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(regs[rb].strVal < regs[rc].strVal)
+      decodeBC(rkInt)
+      regs[ra].intVal = ord(regs[rb].node.strVal < regs[rc].node.strVal)
     of opcLeSet:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(containsSets(regs[rb], regs[rc]))
+      decodeBC(rkInt)
+      regs[ra].intVal = ord(containsSets(regs[rb].node, regs[rc].node))
     of opcEqSet: 
-      decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(equalSets(regs[rb], regs[rc]))
+      decodeBC(rkInt)
+      regs[ra].intVal = ord(equalSets(regs[rb].node, regs[rc].node))
     of opcLtSet:
-      decodeBC(nkIntLit)
-      let a = regs[rb]
-      let b = regs[rc]
-      regs[ra].intVal = Ord(containsSets(a, b) and not equalSets(a, b))
+      decodeBC(rkInt)
+      let a = regs[rb].node
+      let b = regs[rc].node
+      regs[ra].intVal = ord(containsSets(a, b) and not equalSets(a, b))
     of opcMulSet:
-      decodeBC(nkCurly)
-      move(regs[ra].sons, nimsets.intersectSets(regs[rb], regs[rc]).sons)
+      decodeBC(rkNode)
+      move(regs[ra].node.sons, 
+            nimsets.intersectSets(regs[rb].node, regs[rc].node).sons)
     of opcPlusSet: 
-      decodeBC(nkCurly)
-      move(regs[ra].sons, nimsets.unionSets(regs[rb], regs[rc]).sons)
+      decodeBC(rkNode)
+      move(regs[ra].node.sons,
+           nimsets.unionSets(regs[rb].node, regs[rc].node).sons)
     of opcMinusSet:
-      decodeBC(nkCurly)
-      move(regs[ra].sons, nimsets.diffSets(regs[rb], regs[rc]).sons)
-    of opcSymDiffSet:
-      decodeBC(nkCurly)
-      move(regs[ra].sons, nimsets.symdiffSets(regs[rb], regs[rc]).sons)    
+      decodeBC(rkNode)
+      move(regs[ra].node.sons,
+           nimsets.diffSets(regs[rb].node, regs[rc].node).sons)
+    of opcSymdiffSet:
+      decodeBC(rkNode)
+      move(regs[ra].node.sons,
+           nimsets.symdiffSets(regs[rb].node, regs[rc].node).sons)    
     of opcConcatStr:
-      decodeBC(nkStrLit)
-      regs[ra].strVal = getstr(regs[rb])
+      decodeBC(rkNode)
+      createStr regs[ra]
+      regs[ra].node.strVal = getstr(regs[rb])
       for i in rb+1..rb+rc-1:
-        regs[ra].strVal.add getstr(regs[i])
+        regs[ra].node.strVal.add getstr(regs[i])
     of opcAddStrCh:
-      decodeB(nkStrLit)
-      regs[ra].strVal.add(regs[rb].intVal.chr)
+      decodeB(rkNode)
+      createStrKeepNode regs[ra]
+      regs[ra].node.strVal.add(regs[rb].intVal.chr)
     of opcAddStrStr:
-      decodeB(nkStrLit)
-      regs[ra].strVal.add(regs[rb].strVal)
+      decodeB(rkNode)
+      createStrKeepNode regs[ra]
+      regs[ra].node.strVal.add(regs[rb].node.strVal)
     of opcAddSeqElem:
-      decodeB(nkBracket)
-      regs[ra].add(copyTree(regs[rb]))
+      decodeB(rkNode)
+      if regs[ra].node.kind == nkBracket:
+        regs[ra].node.add(copyTree(regs[rb].regToNode))
+      else:
+        stackTrace(c, tos, pc, errNilAccess)
     of opcEcho:
       let rb = instr.regB
       for i in ra..ra+rb-1:
-        if regs[i].kind != nkStrLit: debug regs[i]
-        write(stdout, regs[i].strVal)
+        #if regs[i].kind != rkNode: debug regs[i]
+        write(stdout, regs[i].node.strVal)
       writeln(stdout, "")
     of opcContainsSet:
-      decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(inSet(regs[rb], regs[rc]))
+      decodeBC(rkInt)
+      regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].regToNode))
     of opcSubStr:
-      decodeBC(nkStrLit)
+      decodeBC(rkNode)
       inc pc
       assert c.code[pc].opcode == opcSubStr
       let rd = c.code[pc].regA
-      regs[ra].strVal = substr(regs[rb].strVal, regs[rc].intVal.int, 
-                               regs[rd].intVal.int)
+      createStr regs[ra]
+      regs[ra].node.strVal = substr(regs[rb].node.strVal, 
+                                    regs[rc].intVal.int, regs[rd].intVal.int)
     of opcRangeChck:
       let rb = instr.regB
       let rc = instr.regC
-      if not (leValueConv(regs[rb], regs[ra]) and
-              leValueConv(regs[ra], regs[rc])):
+      if not (leValueConv(regs[rb].regToNode, regs[ra].regToNode) and
+              leValueConv(regs[ra].regToNode, regs[rc].regToNode)):
         stackTrace(c, tos, pc, errGenerated,
           msgKindToString(errIllegalConvFromXtoY) % [
           "unknown type" , "unknown type"])
@@ -533,22 +778,59 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame) =
       # dest = call regStart, n; where regStart = fn, arg1, ...
       let rb = instr.regB
       let rc = instr.regC
-      let prc = regs[rb].sym
-      let newPc = compile(c, prc)
-      var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
-      newSeq(newFrame.slots, prc.position)
-      if not isEmptyType(prc.typ.sons[0]):
-        newFrame.slots[0] = getNullValue(prc.typ.sons[0], prc.info)
-      # pass every parameter by var (the language definition allows this):
-      for i in 1 .. rc-1:
-        newFrame.slots[i] = regs[rb+i]
-      # allocate the temporaries:
-      for i in rc .. <prc.position:
-        newFrame.slots[i] = newNode(nkEmpty)
-      tos = newFrame
-      move(regs, newFrame.slots)
-      # -1 for the following 'inc pc'
-      pc = newPc-1
+      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 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
+        # 'regs' in a register:
+        when hasFFI:
+          let prcValue = c.globals.sons[prc.position-1]
+          if prcValue.kind == nkEmpty:
+            globalError(c.debug[pc], errGenerated, "canot run " & prc.name.s)
+          let newValue = callForeignFunction(prcValue, prc.typ, tos.slots,
+                                             rb+1, rc-1, c.debug[pc])
+          if newValue.kind != nkEmpty:
+            assert instr.opcode == opcIndCallAsgn
+            putIntoReg(regs[ra], newValue)
+        else:
+          globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
+      elif prc.kind != skTemplate:
+        let newPc = compile(c, prc)
+        # tricky: a recursion is also a jump back, so we use the same
+        # logic as for loops:
+        if newPc < pc: handleJmpBack()
+        #echo "new pc ", newPc, " calling: ", prc.name.s
+        var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
+        newSeq(newFrame.slots, prc.offset)
+        if not isEmptyType(prc.typ.sons[0]) or prc.kind == skMacro:
+          putIntoReg(newFrame.slots[0], getNullValue(prc.typ.sons[0], prc.info))
+        for i in 1 .. rc-1:
+          newFrame.slots[i] = regs[rb+i]
+        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'
+        pc = newPc-1
+      else:
+        # for 'getAst' support we need to support template expansion here:
+        let genSymOwner = if tos.next != nil and tos.next.prc != nil:
+                            tos.next.prc
+                          else:
+                            c.module
+        var macroCall = newNodeI(nkCall, c.debug[pc])
+        macroCall.add(newSymNode(prc))
+        for i in 1 .. rc-1: macroCall.add(regs[rb+i].regToNode)
+        let a = evalTemplate(macroCall, prc, genSymOwner)
+        ensureKind(rkNode)
+        regs[ra].node = a
     of opcTJmp:
       # jump Bx if A != 0
       let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
@@ -563,19 +845,23 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame) =
       # jump Bx
       let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
       inc pc, rbx
+    of opcJmpBack:
+      let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
+      inc pc, rbx
+      handleJmpBack()
     of opcBranch:
-      # we know the next instruction is a 'jmp':
+      # we know the next instruction is a 'fjmp':
       let branch = c.constants[instr.regBx-wordExcess]
       var cond = false
       for j in countup(0, sonsLen(branch) - 2): 
-        if overlap(regs[ra], branch.sons[j]): 
+        if overlap(regs[ra].regToNode, branch.sons[j]): 
           cond = true
           break
-      assert c.code[pc+1].opcode == opcJmp
+      assert c.code[pc+1].opcode == opcFJmp
       inc pc 
       # we skip this instruction so that the final 'inc(pc)' skips
       # the following jump
-      if cond:
+      if not cond:
         let instr2 = c.code[pc]
         let rbx = instr2.regBx - wordExcess - 1 # -1 for the following 'inc pc'
         inc pc, rbx
@@ -592,261 +878,402 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame) =
     of opcFinallyEnd:
       if c.currentExceptionA != nil:
         # we are in a cleanup run:
-        pc = cleanupOnException(c, tos, regs)-1
-        if pc < 0: 
+        let (newPc, newTos) = cleanUpOnException(c, tos)
+        if newPc-1 < 0:
           bailOut(c, tos)
           return
+        pc = newPc-1
+        if tos != newTos:
+          tos = newTos
+          move(regs, tos.slots)
     of opcRaise:
-      let raised = regs[ra]
+      let raised = regs[ra].node
       c.currentExceptionA = raised
       c.exceptionInstr = pc
+      let (newPc, newTos) = cleanUpOnException(c, tos)
       # -1 because of the following 'inc'
-      pc = cleanupOnException(c, tos, regs) - 1
-      if pc < 0:
+      if pc-1 < 0:
         bailOut(c, tos)
         return
+      pc = newPc -1
+      if tos != newTos:
+        tos = newTos
+        move(regs, tos.slots)
     of opcNew:
+      ensureKind(rkNode)
       let typ = c.types[instr.regBx - wordExcess]
-      regs[ra] = getNullValue(typ, regs[ra].info)
+      regs[ra].node = getNullValue(typ, c.debug[pc])
+      regs[ra].node.flags.incl nfIsRef
     of opcNewSeq:
       let typ = c.types[instr.regBx - wordExcess]
       inc pc
-      ensureKind(nkBracket)
+      ensureKind(rkNode)
       let instr2 = c.code[pc]
-      let rb = instr2.regA
-      regs[ra].typ = typ
-      newSeq(regs[ra].sons, rb)
-      for i in 0 .. <rb:
-        regs[ra].sons[i] = getNullValue(typ, regs[ra].info)
+      let count = regs[instr2.regA].intVal.int
+      regs[ra].node = newNodeI(nkBracket, c.debug[pc])
+      regs[ra].node.typ = typ
+      newSeq(regs[ra].node.sons, count)
+      for i in 0 .. <count:
+        regs[ra].node.sons[i] = getNullValue(typ.sons[0], c.debug[pc])
     of opcNewStr:
-      decodeB(nkStrLit)
-      regs[ra].strVal = newString(regs[rb].intVal.int)
+      decodeB(rkNode)
+      regs[ra].node = newNodeI(nkStrLit, c.debug[pc])
+      regs[ra].node.strVal = newString(regs[rb].intVal.int)
     of opcLdImmInt:
       # dest = immediate value
-      decodeBx(nkIntLit)
+      decodeBx(rkInt)
       regs[ra].intVal = rbx
     of opcLdNull:
+      ensureKind(rkNode)
       let typ = c.types[instr.regBx - wordExcess]
-      regs[ra] = getNullValue(typ, c.debug[pc])
+      regs[ra].node = getNullValue(typ, c.debug[pc])
+      # opcLdNull really is the gist of the VM's problems: should it load
+      # a fresh null to  regs[ra].node  or to regs[ra].node[]? This really
+      # depends on whether regs[ra] represents the variable itself or wether
+      # it holds the indirection! Due to the way registers are re-used we cannot
+      # say for sure here! --> The codegen has to deal with it
+      # via 'genAsgnPatch'.
+    of opcLdNullReg:
+      let typ = c.types[instr.regBx - wordExcess]
+      if typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}).kind in {
+          tyFloat..tyFloat128}:
+        ensureKind(rkFloat)
+        regs[ra].floatVal = 0.0
+      else:
+        ensureKind(rkInt)
+        regs[ra].intVal = 0
     of opcLdConst:
-      regs[ra] = c.constants.sons[instr.regBx - wordExcess]
+      let rb = instr.regBx - wordExcess
+      let cnst = c.constants.sons[rb]
+      if fitsRegister(cnst.typ):
+        putIntoReg(regs[ra], cnst)
+      else:
+        ensureKind(rkNode)
+        regs[ra].node = cnst
     of opcAsgnConst:
       let rb = instr.regBx - wordExcess
-      if regs[ra].isNil:
-        regs[ra] = copyTree(c.constants.sons[rb])
+      let cnst = c.constants.sons[rb]
+      if fitsRegister(cnst.typ):
+        putIntoReg(regs[ra], cnst)
       else:
-        asgnComplex(regs[ra], c.constants.sons[rb])
+        ensureKind(rkNode)
+        regs[ra].node = cnst.copyTree
     of opcLdGlobal:
-      let rb = instr.regBx - wordExcess
-      if regs[ra].isNil:
-        regs[ra] = copyTree(c.globals.sons[rb])
+      let rb = instr.regBx - wordExcess - 1
+      ensureKind(rkNode)
+      regs[ra].node = c.globals.sons[rb]
+    of opcLdGlobalAddr:
+      let rb = instr.regBx - wordExcess - 1
+      ensureKind(rkNodeAddr)
+      regs[ra].nodeAddr = addr(c.globals.sons[rb])
+    of opcRepr:
+      decodeB(rkNode)
+      createStr regs[ra]
+      regs[ra].node.strVal = renderTree(regs[rb].node, {renderNoComments})
+    of opcQuit:
+      if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
+        message(c.debug[pc], hintQuitCalled)
+        quit(int(getOrdValue(regs[ra].regToNode)))
       else:
-        asgnComplex(regs[ra], c.globals.sons[rb])
-    of opcRepr, opcSetLenStr, opcSetLenSeq,
-        opcSwap, opcIsNil, opcOf,
-        opcCast, opcQuit, opcReset:
+        return TFullReg(kind: rkNone)
+    of opcSetLenStr:
+      decodeB(rkNode)
+      createStrKeepNode regs[ra]
+      regs[ra].node.strVal.setLen(regs[rb].intVal.int)
+    of opcOf:
+      decodeBC(rkInt)
+      let typ = c.types[regs[rc].intVal.int]
+      regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) >= 0)
+    of opcIs:
+      decodeBC(rkInt)
+      let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc})
+      let t2 = c.types[regs[rc].intVal.int]
+      # XXX: This should use the standard isOpImpl
+      let match = if t2.kind == tyUserTypeClass: true
+                  else: sameType(t1, t2)
+      regs[ra].intVal = ord(match)
+    of opcSetLenSeq:
+      decodeB(rkNode)
+      let newLen = regs[rb].intVal.int
+      if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
+      else: setLen(regs[ra].node.sons, newLen)
+    of opcSwap:
+      let rb = instr.regB
+      if regs[ra].kind == regs[rb].kind:
+        case regs[ra].kind
+        of rkNone: discard
+        of rkInt: swap regs[ra].intVal, regs[rb].intVal
+        of rkFloat: swap regs[ra].floatVal, regs[rb].floatVal
+        of rkNode: swap regs[ra].node, regs[rb].node
+        of rkRegisterAddr: swap regs[ra].regAddr, regs[rb].regAddr
+        of rkNodeAddr: swap regs[ra].nodeAddr, regs[rb].nodeAddr
+      else:
+        internalError(c.debug[pc], "cannot swap operands")
+    of opcReset:
       internalError(c.debug[pc], "too implement")
+    of opcNarrowS:
+      decodeB(rkInt)
+      let min = -(1 shl (rb-1))
+      let max = (1 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")
+    of opcNarrowU:
+      decodeB(rkInt)
+      regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
+    of opcIsNil:
+      decodeB(rkInt)
+      regs[ra].intVal = ord(regs[rb].node.kind == nkNilLit)
     of opcNBindSym:
-      # trivial implementation:
-      let rb = instr.regB
-      regs[ra] = regs[rb].sons[1]
+      decodeBx(rkNode)
+      regs[ra].node = copyTree(c.constants.sons[rbx])
     of opcNChild:
-      let rb = instr.regB
-      let rc = instr.regC
-      regs[ra] = regs[rb].sons[regs[rc].intVal.int]
+      decodeBC(rkNode)
+      let idx = regs[rc].intVal.int
+      let src = regs[rb].node
+      if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
+        regs[ra].node = src.sons[idx]
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcNSetChild:
-      let rb = instr.regB
-      let rc = instr.regC
-      regs[ra].sons[regs[rb].intVal.int] = regs[rc]
+      decodeBC(rkNode)
+      let idx = regs[rb].intVal.int
+      var dest = regs[ra].node
+      if dest.kind notin {nkEmpty..nkNilLit} and idx <% dest.len:
+        dest.sons[idx] = regs[rc].node
+      else:
+        stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcNAdd:
-      declBC()
-      regs[rb].add(regs[rb])
-      regs[ra] = regs[rb]
+      decodeBC(rkNode)
+      var u = regs[rb].node
+      u.add(regs[rc].node)
+      regs[ra].node = u
     of opcNAddMultiple:
-      declBC()
-      let x = regs[rc]
+      decodeBC(rkNode)
+      let x = regs[rc].node
+      var u = regs[rb].node
       # XXX can be optimized:
-      for i in 0.. <x.len: regs[rb].add(x.sons[i])
-      regs[ra] = regs[rb]
+      for i in 0.. <x.len: u.add(x.sons[i])
+      regs[ra].node = u
     of opcNKind:
-      decodeB(nkIntLit)
-      regs[ra].intVal = ord(regs[rb].kind)
+      decodeB(rkInt)
+      regs[ra].intVal = ord(regs[rb].node.kind)
     of opcNIntVal:
-      decodeB(nkIntLit)
-      let a = regs[rb]
+      decodeB(rkInt)
+      let a = regs[rb].node
       case a.kind
       of nkCharLit..nkInt64Lit: regs[ra].intVal = a.intVal
       else: stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
     of opcNFloatVal:
-      decodeB(nkFloatLit)
-      let a = regs[rb]
+      decodeB(rkFloat)
+      let a = regs[rb].node
       case a.kind
       of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal
       else: stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
     of opcNSymbol:
-      let rb = instr.regB
-      if regs[rb].kind != nkSym: 
+      decodeB(rkNode)
+      let a = regs[rb].node
+      if a.kind == nkSym:
+        regs[ra].node = copyNode(a)
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
-      regs[ra] = regs[rb]
     of opcNIdent:
-      let rb = instr.regB
-      if regs[rb].kind != nkIdent: 
+      decodeB(rkNode)
+      let a = regs[rb].node
+      if a.kind == nkIdent:
+        regs[ra].node = copyNode(a)
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "ident")
-      regs[ra] = regs[rb]
     of opcNGetType:
-      InternalError(c.debug[pc], "unknown opcode " & $instr.opcode)      
+      internalError(c.debug[pc], "unknown opcode " & $instr.opcode)
     of opcNStrVal:
-      decodeB(nkStrLit)
-      let a = regs[rb]
-      case a.kind
-      of nkStrLit..nkTripleStrLit: regs[ra].strVal = a.strVal
+      decodeB(rkNode)
+      createStr regs[ra]
+      let a = regs[rb].node
+      if a.kind in {nkStrLit..nkTripleStrLit}: regs[ra].node.strVal = a.strVal
       else: stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
     of opcSlurp:
-      decodeB(nkStrLit)
-      regs[ra].strVal = opSlurp(regs[rb].strVal, c.debug[pc], c.module)
+      decodeB(rkNode)
+      createStr regs[ra]
+      regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
+                                     c.module)
     of opcGorge:
-      decodeBC(nkStrLit)
-      regs[ra].strVal = opGorge(regs[rb].strVal, regs[rc].strVal)
+      decodeBC(rkNode)
+      regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
+                                     regs[rc].node.strVal)
     of opcNError:
-      stackTrace(c, tos, pc, errUser, regs[ra].strVal)
+      stackTrace(c, tos, pc, errUser, regs[ra].node.strVal)
     of opcNWarning:
-      Message(c.debug[pc], warnUser, regs[ra].strVal)
+      message(c.debug[pc], warnUser, regs[ra].node.strVal)
     of opcNHint:
-      Message(c.debug[pc], hintUser, regs[ra].strVal)
+      message(c.debug[pc], hintUser, regs[ra].node.strVal)
     of opcParseExprToAst:
-      let rb = instr.regB
+      decodeB(rkNode)
       # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
-      let ast = parseString(regs[rb].strVal, c.debug[pc].toFilename,
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
                             c.debug[pc].line.int)
       if sonsLen(ast) != 1:
-        GlobalError(c.debug[pc], errExprExpected, "multiple statements")
-      regs[ra] = ast.sons[0]
+        globalError(c.debug[pc], errExprExpected, "multiple statements")
+      regs[ra].node = ast.sons[0]
     of opcParseStmtToAst:
-      let rb = instr.regB
-      let ast = parseString(regs[rb].strVal, c.debug[pc].toFilename,
+      decodeB(rkNode)
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
                             c.debug[pc].line.int)
-      regs[ra] = ast
+      regs[ra].node = ast
     of opcCallSite:
-      if c.callsite != nil: regs[ra] = c.callsite
+      ensureKind(rkNode)
+      if c.callsite != nil: regs[ra].node = c.callsite
       else: stackTrace(c, tos, pc, errFieldXNotFound, "callsite")
     of opcNLineInfo:
-      let rb = instr.regB
-      let n = regs[rb]
-      regs[ra] = newStrNode(nkStrLit, n.info.toFileLineCol)
-      regs[ra].info = c.debug[pc]
+      decodeB(rkNode)
+      let n = regs[rb].node
+      createStr regs[ra]
+      regs[ra].node.strVal = n.info.toFileLineCol
+      regs[ra].node.info = c.debug[pc]
     of opcEqIdent:
-      decodeBC(nkIntLit)
-      if regs[rb].kind == nkIdent and regs[rc].kind == nkIdent:
-        regs[ra].intVal = ord(regs[rb].ident.id == regs[rc].ident.id)
+      decodeBC(rkInt)
+      if regs[rb].node.kind == nkIdent and regs[rc].node.kind == nkIdent:
+        regs[ra].intVal = ord(regs[rb].node.ident.id == regs[rc].node.ident.id)
       else:
         regs[ra].intVal = 0
     of opcStrToIdent:
-      let rb = instr.regB
-      if regs[rb].kind notin {nkStrLit..nkTripleStrLit}:
+      decodeB(rkNode)
+      if regs[rb].node.kind notin {nkStrLit..nkTripleStrLit}:
         stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
       else:
-        regs[ra] = newNodeI(nkIdent, c.debug[pc])
-        regs[ra].ident = getIdent(regs[rb].strVal)
+        regs[ra].node = newNodeI(nkIdent, c.debug[pc])
+        regs[ra].node.ident = getIdent(regs[rb].node.strVal)
     of opcIdentToStr:
-      let rb = instr.regB
-      let a = regs[rb]
-      regs[ra] = newNodeI(nkStrLit, c.debug[pc])
+      decodeB(rkNode)
+      let a = regs[rb].node
+      createStr regs[ra]
+      regs[ra].node.info = c.debug[pc]
       if a.kind == nkSym:
-        regs[ra].strVal = a.sym.name.s
+        regs[ra].node.strVal = a.sym.name.s
       elif a.kind == nkIdent:
-        regs[ra].strVal = a.ident.s
+        regs[ra].node.strVal = a.ident.s
       else:
         stackTrace(c, tos, pc, errFieldXNotFound, "ident")
     of opcSetType:
-      regs[ra].typ = c.types[instr.regBx - wordExcess]
+      if regs[ra].kind != rkNode:
+        internalError(c.debug[pc], "cannot set type")
+      regs[ra].node.typ = c.types[instr.regBx - wordExcess]
     of opcConv:
       let rb = instr.regB
       inc pc
-      let typ = c.types[c.code[pc].regBx - wordExcess]
-      if opConv(regs[ra], regs[rb], typ):
+      let desttyp = c.types[c.code[pc].regBx - wordExcess]
+      inc pc
+      let srctyp = c.types[c.code[pc].regBx - wordExcess]
+
+      if opConv(regs[ra], regs[rb], desttyp, srctyp):
         stackTrace(c, tos, pc, errGenerated,
           msgKindToString(errIllegalConvFromXtoY) % [
-          "unknown type" , "unknown type"])
-    of opcNSetIntVal:
+          typeToString(srctyp), typeToString(desttyp)])
+    of opcCast:
       let rb = instr.regB
-      if regs[ra].kind in {nkCharLit..nkInt64Lit} and 
-         regs[rb].kind in {nkCharLit..nkInt64Lit}:
-        regs[ra].intVal = regs[rb].intVal
-      else: 
+      inc pc
+      let desttyp = c.types[c.code[pc].regBx - wordExcess]
+      inc pc
+      let srctyp = c.types[c.code[pc].regBx - wordExcess]
+
+      when hasFFI:
+        let dest = fficast(regs[rb], desttyp)
+        asgnRef(regs[ra], dest)
+      else:
+        globalError(c.debug[pc], "cannot evaluate cast")
+    of opcNSetIntVal:
+      decodeB(rkNode)
+      var dest = regs[ra].node
+      if dest.kind in {nkCharLit..nkInt64Lit} and 
+         regs[rb].kind in {rkInt}:
+        dest.intVal = regs[rb].intVal
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
     of opcNSetFloatVal:
-      let rb = instr.regB
-      if regs[ra].kind in {nkFloatLit..nkFloat64Lit} and 
-         regs[rb].kind in {nkFloatLit..nkFloat64Lit}:
-        regs[ra].floatVal = regs[rb].floatVal
+      decodeB(rkNode)
+      var dest = regs[ra].node
+      if dest.kind in {nkFloatLit..nkFloat64Lit} and 
+         regs[rb].kind in {rkFloat}:
+        dest.floatVal = regs[rb].floatVal
       else: 
         stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
     of opcNSetSymbol:
-      let rb = instr.regB
-      if regs[ra].kind == nkSym and regs[rb].kind == nkSym:
-        regs[ra].sym = regs[rb].sym
+      decodeB(rkNode)
+      var dest = regs[ra].node
+      if dest.kind == nkSym and regs[rb].node.kind == nkSym:
+        dest.sym = regs[rb].node.sym
       else: 
         stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
     of opcNSetIdent:
-      let rb = instr.regB
-      if regs[ra].kind == nkIdent and regs[rb].kind == nkIdent:
-        regs[ra].ident = regs[rb].ident
+      decodeB(rkNode)
+      var dest = regs[ra].node
+      if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
+        dest.ident = regs[rb].node.ident
       else: 
         stackTrace(c, tos, pc, errFieldXNotFound, "ident")
     of opcNSetType:
-      let b = regs[instr.regB]
-      InternalAssert b.kind == nkSym and b.sym.kind == skType
-      regs[ra].typ = b.sym.typ
+      decodeB(rkNode)
+      let b = regs[rb].node
+      internalAssert b.kind == nkSym and b.sym.kind == skType
+      internalAssert regs[ra].node != nil
+      regs[ra].node.typ = b.sym.typ
     of opcNSetStrVal:
-      let rb = instr.regB
-      if regs[ra].kind in {nkStrLit..nkTripleStrLit} and 
-         regs[rb].kind in {nkStrLit..nkTripleStrLit}:
-        regs[ra].strVal = regs[rb].strVal
+      decodeB(rkNode)
+      var dest = regs[ra].node
+      if dest.kind in {nkStrLit..nkTripleStrLit} and 
+         regs[rb].kind in {rkNode}:
+        dest.strVal = regs[rb].node.strVal
       else:
         stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
     of opcNNewNimNode:
-      let rb = instr.regB
-      let rc = instr.regC
+      decodeBC(rkNode)
       var k = regs[rb].intVal
-      if k < 0 or k > ord(high(TNodeKind)): 
+      if k < 0 or k > ord(high(TNodeKind)):
         internalError(c.debug[pc],
-          "request to create a NimNode with invalid kind")
-      regs[ra] = newNodeI(TNodeKind(int(k)), 
-        if regs[rc].kind == nkNilLit: c.debug[pc] else: regs[rc].info)
+          "request to create a NimNode of invalid kind")
+      let cc = regs[rc].node
+      regs[ra].node = newNodeI(TNodeKind(int(k)),
+        if cc.kind == nkNilLit: c.debug[pc] else: cc.info)
+      regs[ra].node.flags.incl nfIsRef
     of opcNCopyNimNode:
-      let rb = instr.regB
-      regs[ra] = copyNode(regs[rb])
+      decodeB(rkNode)
+      regs[ra].node = copyNode(regs[rb].node)
     of opcNCopyNimTree:
-      let rb = instr.regB
-      regs[ra] = copyTree(regs[rb])
+      decodeB(rkNode)
+      regs[ra].node = copyTree(regs[rb].node)
     of opcNDel:
-      let rb = instr.regB
-      let rc = instr.regC
+      decodeBC(rkNode)
+      let bb = regs[rb].intVal.int
       for i in countup(0, regs[rc].intVal.int-1):
-        delSon(regs[ra], regs[rb].intVal.int)
+        delSon(regs[ra].node, bb)
     of opcGenSym:
-      let k = regs[instr.regB].intVal
-      let b = regs[instr.regC]
-      let name = if b.strVal.len == 0: ":tmp" else: b.strVal
+      decodeBC(rkNode)
+      let k = regs[rb].intVal
+      let name = if regs[rc].node.strVal.len == 0: ":tmp"
+                 else: regs[rc].node.strVal
       if k < 0 or k > ord(high(TSymKind)):
         internalError(c.debug[pc], "request to create symbol of invalid kind")
-      regs[ra] = newSymNode(newSym(k.TSymKind, name.getIdent, c.module,
-                            c.debug[pc]))
-      incl(regs[ra].sym.flags, sfGenSym)
+      var sym = newSym(k.TSymKind, name.getIdent, c.module, c.debug[pc])
+      incl(sym.flags, sfGenSym)
+      regs[ra].node = newSymNode(sym)
     of opcTypeTrait:
       # XXX only supports 'name' for now; we can use regC to encode the
       # type trait operation
-      decodeB(nkStrLit)
-      let typ = regs[rb].sym.typ.skipTypes({tyTypeDesc})
-      regs[ra].strVal = typ.typeToString(preferExported)
+      decodeB(rkNode)
+      var typ = regs[rb].node.typ
+      internalAssert typ != nil
+      while typ.kind == tyTypeDesc and typ.len > 0: typ = typ.sons[0]
+      createStr regs[ra]
+      regs[ra].node.strVal = typ.typeToString(preferExported)
     inc pc
 
-proc execute(c: PCtx, start: int) =
+proc execute(c: PCtx, start: int): PNode =
   var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
   newSeq(tos.slots, c.prc.maxSlots)
-  rawExecute(c, start, tos)
+  result = rawExecute(c, start, tos).regToNode
 
 proc evalStmt*(c: PCtx, n: PNode) =
+  let n = transformExpr(c.module, n)
   let start = genStmt(c, n)
   # execute new instructions; this redundant opcEof check saves us lots
   # of allocations in 'execute':
@@ -854,15 +1281,31 @@ proc evalStmt*(c: PCtx, n: PNode) =
     discard execute(c, start)
 
 proc evalExpr*(c: PCtx, n: PNode): PNode =
+  let n = transformExpr(c.module, n)
   let start = genExpr(c, n)
   assert c.code[start].opcode != opcEof
   result = execute(c, start)
 
+# 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.
+var
+  globalCtx: PCtx
+
+proc setupGlobalCtx(module: PSym) =
+  if globalCtx.isNil: globalCtx = newCtx(module)
+  else: refresh(globalCtx, module)
+
 proc myOpen(module: PSym): PPassContext =
   #var c = newEvalContext(module, emRepl)
   #c.features = {allowCast, allowFFI, allowInfiniteLoops}
   #pushStackFrame(c, newStackFrame())
-  result = newCtx(module)
+
+  # XXX produce a new 'globals' environment here:
+  setupGlobalCtx(module)
+  result = globalCtx
+  when hasFFI:
+    globalCtx.features = {allowFFI, allowCast}
 
 var oldErrorCount: int
 
@@ -875,50 +1318,74 @@ proc myProcess(c: PPassContext, n: PNode): PNode =
     result = n
   oldErrorCount = msgs.gErrorCounter
 
-const vmPass* = makePass(myOpen, nil, myProcess, myProcess)
+const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
 
-proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode = 
-  var p = newCtx(module)
-  var s = newStackFrame()
-  s.call = e
-  s.prc = prc
-  pushStackFrame(p, s)
-  result = tryEval(p, e)
-  if result != nil and result.kind == nkExceptBranch: result = nil
-  popStackFrame(p)
+proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
+  let n = transformExpr(module, n)
+  setupGlobalCtx(module)
+  var c = globalCtx
+  c.mode = mode
+  let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
+  if c.code[start].opcode == opcEof: return emptyNode
+  assert c.code[start].opcode != opcEof
+  when debugEchoCode: c.echoCode start
+  var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
+  newSeq(tos.slots, c.prc.maxSlots)
+  #for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
+  result = rawExecute(c, start, tos).regToNode
 
 proc evalConstExpr*(module: PSym, e: PNode): PNode = 
   result = evalConstExprAux(module, nil, e, emConst)
 
-proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode = 
-  result = evalConstExprAux(module, prc, e, emStatic)
+proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
+  result = evalConstExprAux(module, prc, e, emStaticExpr)
+
+proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) =
+  discard evalConstExprAux(module, prc, e, emStaticStmt)
+
+proc setupCompileTimeVar*(module: PSym, n: PNode) =
+  discard evalConstExprAux(module, nil, n, emStaticStmt)
 
 proc setupMacroParam(x: PNode): PNode =
   result = x
   if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
+  result = canonValue(result)
+  result.flags.incl nfIsRef
+  result.typ = x.typ
+
+var evalMacroCounter: int
 
-proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
+proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   # XXX GlobalError() is ugly here, but I don't know a better solution for now
-  inc(evalTemplateCounter)
-  if evalTemplateCounter > 100:
-    GlobalError(n.info, errTemplateInstantiationTooNested)
+  inc(evalMacroCounter)
+  if evalMacroCounter > 100:
+    globalError(n.info, errTemplateInstantiationTooNested)
+  setupGlobalCtx(module)
+  var c = globalCtx
 
   c.callsite = nOrig
-  let body = optBody(c, sym)
-  let start = genStmt(c, body)
+  let start = genProc(c, sym)
 
   var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
-  newSeq(tos.slots, c.prc.maxSlots)
+  let maxSlots = sym.offset
+  newSeq(tos.slots, maxSlots)
   # setup arguments:
   var L = n.safeLen
   if L == 0: L = 1
-  InternalAssert tos.slots.len >= L
+  # This is wrong for tests/reject/tind1.nim where the passed 'else' part
+  # doesn't end up in the parameter:
+  #InternalAssert tos.slots.len >= L
   # return value:
-  tos.slots[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
+  tos.slots[0].kind = rkNode
+  tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
   # setup parameters:
-  for i in 1 .. < L: tos.slots[i] = setupMacroParam(n.sons[i])
-  rawExecute(c, start, tos)
-  result = tos.slots[0]
-  if cyclicTree(result): GlobalError(n.info, errCyclicTree)
-  dec(evalTemplateCounter)
+  for i in 1 .. < min(tos.slots.len, L):
+    tos.slots[i].kind = rkNode
+    tos.slots[i].node = setupMacroParam(n.sons[i])
+  # temporary storage:
+  #for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
+  result = rawExecute(c, start, tos).regToNode
+  if cyclicTree(result): globalError(n.info, errCyclicTree)
+  dec(evalMacroCounter)
   c.callsite = nil
+  #debug result
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index d4b3d891d..d0c38a2ad 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -8,7 +8,7 @@
 #
 
 ## This module contains the type definitions for the new evaluation engine.
-## An instruction is 1-2 int32s in memory, it is a register based VM.
+## An instruction is 1-3 int32s in memory, it is a register based VM.
 
 import ast, passes, msgs, intsets
 
@@ -16,6 +16,9 @@ const
   byteExcess* = 128 # we use excess-K for immediates
   wordExcess* = 32768
 
+  MaxLoopIterations* = 500_000 # max iterations of all loops
+
+
 type
   TRegister* = range[0..255]
   TDest* = range[-1 .. 255]
@@ -32,15 +35,17 @@ type
     opcAsgnFloat,
     opcAsgnRef,
     opcAsgnComplex,
+    opcRegToNode,
+    opcNodeToReg,
 
     opcLdArr,  # a = b[c]
     opcWrArr,  # a[b] = c
-    opcWrArrRef,
     opcLdObj,  # a = b.c
     opcWrObj,  # a.b = c
-    opcWrObjRef,
-    opcAddr,
-    opcDeref,
+    opcAddrReg,
+    opcAddrNode,
+    opcLdDeref,
+    opcWrDeref,
     opcWrStrIdx,
     opcLdStrIdx, # a = b[c]
     
@@ -51,17 +56,18 @@ type
     opcLenSeq,
     opcLenStr,
 
-    opcIncl, opcExcl, opcCard, opcMulInt, opcDivInt, opcModInt,
+    opcIncl, opcInclRange, opcExcl, opcCard, opcMulInt, opcDivInt, opcModInt,
     opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat, opcShrInt, opcShlInt,
     opcBitandInt, opcBitorInt, opcBitxorInt, opcAddu, opcSubu, opcMulu, 
     opcDivu, opcModu, opcEqInt, opcLeInt, opcLtInt, opcEqFloat, 
-    opcLeFloat, opcLtFloat, opcLeu, opcLtu, opcEqRef, opcXor, 
+    opcLeFloat, opcLtFloat, opcLeu, opcLtu, opcEqRef, opcEqNimrodNode, opcXor, 
     opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt, 
     opcEqStr, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
     opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr,
     opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
-    opcSwap, opcIsNil, opcOf,
+    opcSwap, opcIsNil, opcOf, opcIs,
     opcSubStr, opcConv, opcCast, opcQuit, opcReset,
+    opcNarrowS, opcNarrowU,
     
     opcAddStrCh,
     opcAddStrStr,
@@ -101,13 +107,13 @@ type
     opcRaise,
     opcNChild,
     opcNSetChild,
-    opcNBindSym, # opcodes for the AST manipulation following
     opcCallSite,
     opcNewStr,
   
     opcTJmp,  # jump Bx if A != 0
     opcFJmp,  # jump Bx if A == 0
     opcJmp,   # jump Bx
+    opcJmpBack, # jump Bx; resulting from a while loop
     opcBranch,  # branch for 'case'
     opcTry,
     opcExcept,
@@ -116,12 +122,14 @@ type
     opcNew,
     opcNewSeq,
     opcLdNull,    # dest = nullvalue(types[Bx])
+    opcLdNullReg,
     opcLdConst,   # dest = constants[Bx]
     opcAsgnConst, # dest = copy(constants[Bx])
     opcLdGlobal,  # dest = globals[Bx]
+    opcLdGlobalAddr, # dest = addr(globals[Bx])
+
     opcLdImmInt,  # dest = immediate value
-    opcWrGlobal,
-    opcWrGlobalRef,
+    opcNBindSym,
     opcSetType,   # dest.typ = types[Bx]
     opcTypeTrait
 
@@ -129,6 +137,21 @@ type
     label*: PSym
     fixups*: seq[TPosition]
 
+  TEvalMode* = enum           ## reason for evaluation
+    emRepl,                   ## evaluate because in REPL mode
+    emConst,                  ## evaluate for 'const' according to spec
+    emOptimize,               ## evaluate for optimization purposes (same as
+                              ## emConst?)
+    emStaticExpr,             ## evaluate for enforced compile time eval
+                              ## ('static' context)
+    emStaticStmt              ## 'static' as an expression
+
+  TSandboxFlag* = enum        ## what the evaluation engine should allow
+    allowCast,                ## allow unsafe language feature: 'cast'
+    allowFFI,                 ## allow the FFI
+    allowInfiniteLoops        ## allow endless loops
+  TSandboxFlags* = set[TSandboxFlag]
+
   TSlotKind* = enum   # We try to re-use slots in a smart way to
                       # minimize allocations; however the VM supports arbitrary
                       # temporary slot usage. This is required for the parameter
@@ -140,10 +163,11 @@ type
     slotTempInt,      # some temporary int
     slotTempFloat,    # some temporary float
     slotTempStr,      # some temporary string
-    slotTempComplex   # some complex temporary (n.sons field is used)
+    slotTempComplex   # some complex temporary (s.node field is used)
 
   PProc* = ref object
     blocks*: seq[TBlock]    # blocks; temp data structure
+    sym*: PSym
     slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
     maxSlots*: int
     
@@ -160,21 +184,28 @@ type
     prc*: PProc
     module*: PSym
     callsite*: PNode
+    mode*: TEvalMode
+    features*: TSandboxFlags
+    traceActive*: bool
+    loopIterations*: int
 
   TPosition* = distinct int
 
   PEvalContext* = PCtx
-
   
 proc newCtx*(module: PSym): PCtx =
   PCtx(code: @[], debug: @[],
-    globals: newNode(nkStmtList), constants: newNode(nkStmtList), types: @[],
-    prc: PProc(blocks: @[]), module: module)
+    globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
+    prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations)
+
+proc refresh*(c: PCtx, module: PSym) =
+  c.module = module
+  c.prc = PProc(blocks: @[])
 
 const
   firstABxInstr* = opcTJmp
   largeInstrs* = { # instructions which use 2 int32s instead of 1:
-    opcSubstr, opcConv, opcCast, opcNewSeq, opcOf}
+    opcSubStr, opcConv, opcCast, opcNewSeq, opcOf}
   slotSomeTemp* = slotTempUnknown
   relativeJumps* = {opcTJmp, opcFJmp, opcJmp}
 
@@ -183,3 +214,5 @@ template regA*(x: TInstr): TRegister {.immediate.} = TRegister(x.uint32 shr 8'u3
 template regB*(x: TInstr): TRegister {.immediate.} = TRegister(x.uint32 shr 16'u32 and 0xff'u32)
 template regC*(x: TInstr): TRegister {.immediate.} = TRegister(x.uint32 shr 24'u32)
 template regBx*(x: TInstr): int {.immediate.} = (x.uint32 shr 16'u32).int
+
+template jmpDiff*(x: TInstr): int {.immediate.} = regBx(x) - wordExcess
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 2a40276d1..0e01f5031 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -25,69 +25,12 @@ proc opGorge*(cmd, input: string): string =
 
 proc opSlurp*(file: string, info: TLineInfo, module: PSym): string = 
   try:
-    let filename = file.FindFile
+    let filename = file.findFile
     result = readFile(filename)
     # we produce a fake include statement for every slurped filename, so that
     # the module dependencies are accurate:
     appendToModule(module, newNode(nkIncludeStmt, info, @[
       newStrNode(nkStrLit, filename)]))
   except EIO:
+    localError(info, errCannotOpenFile, file)
     result = ""
-    LocalError(info, errCannotOpenFile, file)
-
-when false:
-  proc opExpandToAst*(c: PEvalContext, original: PNode): PNode =
-    var
-      n = original.copyTree
-      macroCall = n.sons[1]
-      expandedSym = macroCall.sons[0].sym
-
-    for i in countup(1, macroCall.sonsLen - 1):
-      macroCall.sons[i] = evalAux(c, macroCall.sons[i], {})
-
-    case expandedSym.kind
-    of skTemplate:
-      let genSymOwner = if c.tos != nil and c.tos.prc != nil:
-                          c.tos.prc 
-                        else:
-                          c.module
-      result = evalTemplate(macroCall, expandedSym, genSymOwner)
-    of skMacro:
-      # At this point macroCall.sons[0] is nkSym node.
-      # To be completely compatible with normal macro invocation,
-      # we want to replace it with nkIdent node featuring
-      # the original unmangled macro name.
-      macroCall.sons[0] = newIdentNode(expandedSym.name, expandedSym.info)
-      result = evalMacroCall(c, macroCall, original, expandedSym)
-    else:
-      InternalError(macroCall.info,
-        "ExpandToAst: expanded symbol is no macro or template")
-      result = emptyNode
-
-  proc opIs*(n: PNode): PNode =
-    InternalAssert n.sonsLen == 3 and
-      n[1].kind == nkSym and n[1].sym.kind == skType and
-      n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
-    
-    let t1 = n[1].sym.typ
-
-    if n[2].kind in {nkStrLit..nkTripleStrLit}:
-      case n[2].strVal.normalize
-      of "closure":
-        let t = skipTypes(t1, abstractRange)
-        result = newIntNode(nkIntLit, ord(t.kind == tyProc and
-                                          t.callConv == ccClosure and 
-                                          tfIterator notin t.flags))
-      of "iterator":
-        let t = skipTypes(t1, abstractRange)
-        result = newIntNode(nkIntLit, ord(t.kind == tyProc and
-                                          t.callConv == ccClosure and 
-                                          tfIterator in t.flags))
-    else:
-      let t2 = n[2].typ
-      var match = if t2.kind == tyTypeClass: matchTypeClass(t2, t1)
-                  else: sameType(t1, t2)
-      result = newIntNode(nkIntLit, ord(match))
-
-    result.typ = n.typ
-
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 84d82e117..7c0c3d4f5 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2013 Andreas Rumpf
+#        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -11,25 +11,44 @@
 
 import
   unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef, 
-  trees, intsets, rodread, magicsys
+  trees, intsets, rodread, magicsys, options, lowerings
 
-proc codeListing(c: PCtx, result: var string) =
+from os import splitFile
+
+when hasFFI:
+  import evalffi
+
+type
+  TGenFlag = enum gfNone, gfAddrOf
+  TGenFlags = set[TGenFlag]
+
+proc debugInfo(info: TLineInfo): string =
+  result = info.toFilename.splitFile.name & ":" & $info.line
+
+proc codeListing(c: PCtx, result: var string, start=0) =
   # first iteration: compute all necessary labels:
   var jumpTargets = initIntSet()
   
-  for i in 0.. < c.code.len:
+  for i in start.. < c.code.len:
     let x = c.code[i]
     if x.opcode in relativeJumps:
       jumpTargets.incl(i+x.regBx-wordExcess)
 
   # for debugging purposes
-  var i = 0
+  var i = start
   while i < c.code.len:
     if i in jumpTargets: result.addf("L$1:\n", i)
     let x = c.code[i]
 
     let opc = opcode(x)
-    if opc < firstABxInstr:
+    if opc in {opcConv, opcCast}:
+      let y = c.code[i+1]
+      let z = c.code[i+2]
+      result.addf("\t$#\tr$#, r$#, $#, $#", ($opc).substr(3), x.regA, x.regB,
+        c.types[y.regBx-wordExcess].typeToString, 
+        c.types[z.regBx-wordExcess].typeToString)
+      inc i, 2
+    elif opc < firstABxInstr:
       result.addf("\t$#\tr$#, r$#, r$#", ($opc).substr(3), x.regA, 
                   x.regB, x.regC)
     elif opc in relativeJumps:
@@ -41,13 +60,13 @@ proc codeListing(c: PCtx, result: var string) =
     else:
       result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, x.regBx-wordExcess)
     result.add("\t#")
-    result.add(toFileLine(c.debug[i]))
+    result.add(debugInfo(c.debug[i]))
     result.add("\n")
     inc i
 
-proc echoCode*(c: PCtx) =
+proc echoCode*(c: PCtx, start=0) {.deprecated.} =
   var buf = ""
-  codeListing(c, buf)
+  codeListing(c, buf, start)
   echo buf
 
 proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
@@ -58,7 +77,7 @@ proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
   ctx.code.add(ins)
   ctx.debug.add(n.info)
 
-proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: biggestInt) =
+proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
   let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
                            (b.uint32 shl 16'u32) or
                            (imm+byteExcess).uint32 shl 24'u32).TInstr
@@ -80,24 +99,24 @@ proc genLabel(c: PCtx): TPosition =
   result = TPosition(c.code.len)
   #c.jumpTargets.incl(c.code.len)
 
-proc jmpBack(c: PCtx, n: PNode, opc: TOpcode, p = TPosition(0)) =
+proc jmpBack(c: PCtx, n: PNode, p = TPosition(0)) =
   let dist = p.int - c.code.len
-  InternalAssert(-0x7fff < dist and dist < 0x7fff)
-  gABx(c, n, opc, 0, dist)
+  internalAssert(-0x7fff < dist and dist < 0x7fff)
+  gABx(c, n, opcJmpBack, 0, dist)
 
 proc patch(c: PCtx, p: TPosition) =
   # patch with current index
   let p = p.int
   let diff = c.code.len - p
   #c.jumpTargets.incl(c.code.len)
-  InternalAssert(-0x7fff < diff and diff < 0x7fff)
+  internalAssert(-0x7fff < diff and diff < 0x7fff)
   let oldInstr = c.code[p]
   # opcode and regA stay the same:
   c.code[p] = ((oldInstr.uint32 and 0xffff'u32).uint32 or
                uint32(diff+wordExcess) shl 16'u32).TInstr
 
 proc getSlotKind(t: PType): TSlotKind =
-  case t.skipTypes(abstractRange).kind
+  case t.skipTypes(abstractRange-{tyTypeDesc}).kind
   of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
     slotTempInt
   of tyString, tyCString:
@@ -112,8 +131,10 @@ const
 
 proc getTemp(c: PCtx; typ: PType): TRegister =
   let c = c.prc
-  # we prefer the same slot kind here for efficiency:
-  let k = typ.getSlotKind
+  # we prefer the same slot kind here for efficiency. Unfortunately for
+  # discardable return types we may not know the desired type. This can happen
+  # for e.g. mNAdd[Multiple]:
+  let k = if typ.isNil: slotTempComplex else: typ.getSlotKind
   for i in 0 .. c.maxSlots-1:
     if c.slots[i].kind == k and not c.slots[i].inUse:
       c.slots[i].inUse = true
@@ -125,6 +146,8 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
       if not c.slots[i].inUse:
         c.slots[i] = (inUse: true, kind: k)
         return TRegister(i)
+  if c.maxSlots >= high(TRegister):
+    internalError("cannot generate code; too many registers required")
   result = TRegister(c.maxSlots)
   c.slots[c.maxSlots] = (inUse: true, kind: k)
   inc c.maxSlots
@@ -146,7 +169,7 @@ proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister =
           for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
           return
   if c.maxSlots+n >= high(TRegister):
-    InternalError("cannot generate code; too many registers required")
+    internalError("cannot generate code; too many registers required")
   result = TRegister(c.maxSlots)
   inc c.maxSlots, n
   for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
@@ -170,22 +193,30 @@ template withBlock(labl: PSym; body: stmt) {.immediate, dirty.} =
   body
   popBlock(c, oldLen)
 
-proc gen(c: PCtx; n: PNode; dest: var TDest)
-proc gen(c: PCtx; n: PNode; dest: TRegister) =
+proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {})
+proc gen(c: PCtx; n: PNode; dest: TRegister; flags: TGenFlags = {}) =
   var d: TDest = dest
-  gen(c, n, d)
-  InternalAssert d == dest
+  gen(c, n, d, flags)
+  internalAssert d == dest
 
-proc gen(c: PCtx; n: PNode) =
+proc gen(c: PCtx; n: PNode; flags: TGenFlags = {}) =
   var tmp: TDest = -1
-  gen(c, n, tmp)
-  InternalAssert tmp < 0
+  gen(c, n, tmp, flags)
+  #if n.typ.isEmptyType: InternalAssert tmp < 0
 
-proc genx(c: PCtx; n: PNode): TRegister =
+proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
   var tmp: TDest = -1
-  gen(c, n, tmp)
+  gen(c, n, tmp, flags)
+  internalAssert tmp >= 0
   result = TRegister(tmp)
 
+proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} =
+  # stmt is different from 'void' in meta programming contexts.
+  # So we only set dest to -1 if 'void':
+  if dest >= 0 and (n.typ.isNil or n.typ.kind == tyEmpty):
+    c.freeTemp(dest)
+    dest = -1
+
 proc isNotOpr(n: PNode): bool =
   n.kind in nkCallKinds and n.sons[0].kind == nkSym and
     n.sons[0].sym.magic == mNot
@@ -205,25 +236,26 @@ proc genWhile(c: PCtx; n: PNode) =
   withBlock(nil):
     if isTrue(n.sons[0]):
       c.gen(n.sons[1])
-      c.jmpBack(n, opcJmp, L1)
+      c.jmpBack(n, L1)
     elif isNotOpr(n.sons[0]):
       var tmp = c.genx(n.sons[0].sons[1])
       let L2 = c.xjmp(n, opcTJmp, tmp)
       c.freeTemp(tmp)
       c.gen(n.sons[1])
-      c.jmpBack(n, opcJmp, L1)
+      c.jmpBack(n, L1)
       c.patch(L2)
     else:
       var tmp = c.genx(n.sons[0])
       let L2 = c.xjmp(n, opcFJmp, tmp)
       c.freeTemp(tmp)
       c.gen(n.sons[1])
-      c.jmpBack(n, opcJmp, L1)
+      c.jmpBack(n, L1)
       c.patch(L2)
 
 proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
   withBlock(n.sons[0].sym):
     c.gen(n.sons[1], dest)
+  c.clearDest(n, dest)
 
 proc genBreak(c: PCtx; n: PNode) =
   let L1 = c.xjmp(n, opcJmp)
@@ -233,7 +265,7 @@ proc genBreak(c: PCtx; n: PNode) =
       if c.prc.blocks[i].label == n.sons[0].sym:
         c.prc.blocks[i].fixups.add L1
         return
-    InternalError(n.info, "cannot find 'break' target")
+    internalError(n.info, "cannot find 'break' target")
   else:
     c.prc.blocks[c.prc.blocks.high].fixups.add L1
 
@@ -261,13 +293,16 @@ proc genIf(c: PCtx, n: PNode; dest: var TDest) =
         else:
           c.gen(it.sons[0], tmp)
           elsePos = c.xjmp(it.sons[0], opcFJmp, tmp) # if false
+      c.clearDest(n, dest)
       c.gen(it.sons[1], dest) # then part
       if i < sonsLen(n)-1:
         endings.add(c.xjmp(it.sons[1], opcJmp, 0))
       c.patch(elsePos)
     else:
+      c.clearDest(n, dest)
       c.gen(it.sons[0], dest)
   for endPos in endings: c.patch(endPos)
+  c.clearDest(n, dest)
 
 proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
   #   asgn dest, a
@@ -275,15 +310,27 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
   #   asgn dest, b
   # L1:
   if dest < 0: dest = getTemp(c, n.typ)
-  c.gen(n.sons[0], dest)
-  let L1 = c.xjmp(n, opc)
   c.gen(n.sons[1], dest)
+  let L1 = c.xjmp(n, opc, dest)
+  c.gen(n.sons[2], dest)
   c.patch(L1)
 
+proc canonValue*(n: PNode): PNode =
+  if n.kind == nkExprColonExpr:
+    result = n.sons[1]
+  elif n.hasSubnodeWith(nkExprColonExpr):
+    result = n.copyNode
+    newSeq(result.sons, n.len)
+    for i in 0.. <n.len:
+      result.sons[i] = canonValue(n.sons[i])
+  else:
+    result = n
+
 proc rawGenLiteral(c: PCtx; n: PNode): int =
   result = c.constants.len
-  c.constants.add n
-  InternalAssert result < 0x7fff
+  assert(n.kind != nkCall)
+  c.constants.add n.canonValue
+  internalAssert result < 0x7fff
 
 proc sameConstant*(a, b: PNode): bool =
   result = false
@@ -296,11 +343,12 @@ proc sameConstant*(a, b: PNode): bool =
     of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
     of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
     of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
-    of nkEmpty, nkNilLit, nkType: result = true
-    else: 
-      if sonsLen(a) == sonsLen(b): 
-        for i in countup(0, sonsLen(a) - 1): 
-          if not sameConstant(a.sons[i], b.sons[i]): return 
+    of nkType: result = a.typ == b.typ
+    of nkEmpty, nkNilLit: result = true
+    else:
+      if sonsLen(a) == sonsLen(b):
+        for i in countup(0, sonsLen(a) - 1):
+          if not sameConstant(a.sons[i], b.sons[i]): return
         result = true
 
 proc genLiteral(c: PCtx; n: PNode): int =
@@ -309,6 +357,11 @@ proc genLiteral(c: PCtx; n: PNode): int =
     if sameConstant(c.constants[i], n): return i
   result = rawGenLiteral(c, n)
 
+proc unused(n: PNode; x: TDest) {.inline.} =
+  if x >= 0: 
+    #debug(n)
+    internalError(n.info, "not unused")
+
 proc genCase(c: PCtx; n: PNode; dest: var TDest) =
   #  if (!expr1) goto L1;
   #    thenPart
@@ -320,7 +373,10 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) =
   #  L2:
   #    elsePart
   #  Lend:
-  if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
+  if not isEmptyType(n.typ):
+    if dest < 0: dest = getTemp(c, n.typ)
+  else:
+    unused(n, dest)
   var endings: seq[TPosition] = @[]
   withTemp(tmp, n.sons[0].typ):
     c.gen(n.sons[0], tmp)
@@ -339,6 +395,7 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) =
         if i < sonsLen(n)-1:
           endings.add(c.xjmp(it.lastSon, opcJmp, 0))
         c.patch(elsePos)
+      c.clearDest(n, dest)
   for endPos in endings: c.patch(endPos)
 
 proc genType(c: PCtx; typ: PType): int =
@@ -353,6 +410,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
   var endings: seq[TPosition] = @[]
   let elsePos = c.xjmp(n, opcTry, 0)
   c.gen(n.sons[0], dest)
+  c.clearDest(n, dest)
   c.patch(elsePos)
   for i in 1 .. <n.len:
     let it = n.sons[i]
@@ -362,12 +420,13 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
       let endExcept = c.xjmp(it, opcExcept, 0)
       for j in countup(0, blen - 2): 
         assert(it.sons[j].kind == nkType)
-        let typ = it.sons[j].typ.skipTypes(abstractPtrs)
+        let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
         c.gABx(it, opcExcept, 0, c.genType(typ))
       if blen == 1: 
         # general except section:
         c.gABx(it, opcExcept, 0, 0)
       c.gen(it.lastSon, dest)
+      c.clearDest(n, dest)
       if i < sonsLen(n)-1:
         endings.add(c.xjmp(it, opcJmp, 0))
       c.patch(endExcept)
@@ -378,6 +437,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
   c.gABx(fin, opcFinally, 0, 0)
   if fin.kind == nkFinally:
     c.gen(fin.sons[0], dest)
+    c.clearDest(n, dest)
   c.gABx(fin, opcFinallyEnd, 0, 0)
 
 proc genRaise(c: PCtx; n: PNode) =
@@ -393,30 +453,82 @@ proc genReturn(c: PCtx; n: PNode) =
 proc genCall(c: PCtx; n: PNode; dest: var TDest) =
   if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
   let x = c.getTempRange(n.len, slotTempUnknown)
-  for i in 0.. <n.len: 
+  # varargs need 'opcSetType' for the FFI support:
+  let fntyp = n.sons[0].typ
+  for i in 0.. <n.len:
     var r: TRegister = x+i
     c.gen(n.sons[i], r)
+    if i >= fntyp.len:
+      internalAssert tfVarargs in fntyp.flags
+      c.gABx(n, opcSetType, r, c.genType(n.sons[i].typ))
   if dest < 0:
     c.gABC(n, opcIndCall, 0, x, n.len)
   else:
     c.gABC(n, opcIndCallAsgn, dest, x, n.len)
   c.freeTempRange(x, n.len)
 
+template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
+
+proc needsAsgnPatch(n: PNode): bool = 
+  n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
+             nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
+
+proc genField(n: PNode): TRegister =
+  if n.kind != nkSym or n.sym.kind != skField:
+    internalError(n.info, "no field symbol")
+  let s = n.sym
+  if s.position > high(result):
+      internalError(n.info,
+        "too large offset! cannot generate code for: " & s.name.s)
+  result = s.position
+
+proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
+  case le.kind
+  of nkBracketExpr:
+    let dest = c.genx(le.sons[0], {gfAddrOf})
+    let idx = c.genx(le.sons[1])
+    c.gABC(le, opcWrArr, dest, idx, value)
+    c.freeTemp(dest)
+    c.freeTemp(idx)
+  of nkDotExpr, nkCheckedFieldExpr:
+    # XXX field checks here
+    let left = if le.kind == nkDotExpr: le else: le.sons[0]
+    let dest = c.genx(left.sons[0], {gfAddrOf})
+    let idx = genField(left.sons[1])
+    c.gABC(left, opcWrObj, dest, idx, value)
+    c.freeTemp(dest)
+  of nkDerefExpr, nkHiddenDeref:
+    let dest = c.genx(le.sons[0], {gfAddrOf})
+    c.gABC(le, opcWrDeref, dest, value)
+    c.freeTemp(dest)
+  of nkSym:
+    if le.sym.isGlobal:
+      let dest = c.genx(le, {gfAddrOf})
+      c.gABC(le, opcWrDeref, dest, value)
+      c.freeTemp(dest)
+  else:
+    discard
+
 proc genNew(c: PCtx; n: PNode) =
-  let dest = c.genx(n.sons[1])
+  let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
+             else: c.genx(n.sons[1])
   # we use the ref's base type here as the VM conflates 'ref object' 
   # and 'object' since internally we already have a pointer.
   c.gABx(n, opcNew, dest, 
-         c.genType(n.sons[1].typ.skipTypes(abstractVar).sons[0]))
+         c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
+  c.genAsgnPatch(n.sons[1], dest)
   c.freeTemp(dest)
 
 proc genNewSeq(c: PCtx; n: PNode) =
-  let dest = c.genx(n.sons[1])
-  c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(abstractVar)))
+  let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
+             else: c.genx(n.sons[1])
   let tmp = c.genx(n.sons[2])
+  c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(
+                                                  abstractVar-{tyTypeDesc})))
   c.gABx(n, opcNewSeq, tmp, 0)
-  c.freeTemp(dest)
   c.freeTemp(tmp)
+  c.genAsgnPatch(n.sons[1], dest)
+  c.freeTemp(dest)
 
 proc genUnaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   let tmp = c.genx(n.sons[1])
@@ -439,8 +551,32 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   c.freeTemp(tmp)
   c.freeTemp(tmp2)
 
+proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
+  let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
+  # uint is uint64 in the VM, we we only need to mask the result for
+  # other unsigned types:
+  if t.kind in {tyUInt8..tyUInt32}:
+    c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
+  elif t.kind in {tyInt8..tyInt32}:
+    c.gABC(n, opcNarrowS, dest, TRegister(t.size*8))
+
+proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
+  let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
+  # uint is uint64 in the VM, we we only need to mask the result for
+  # other unsigned types:
+  if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32}:
+    c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
+
+proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
+  genBinaryABC(c, n, dest, opc)
+  genNarrow(c, n, dest)
+
+proc genBinaryABCnarrowU(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
+  genBinaryABC(c, n, dest, opc)
+  genNarrowU(c, n, dest)
+
 proc genSetType(c: PCtx; n: PNode; dest: TRegister) =
-  let t = skipTypes(n.typ, abstractInst)
+  let t = skipTypes(n.typ, abstractInst-{tyTypeDesc})
   if t.kind == tySet:
     c.gABx(n, opcSetType, dest, c.genType(t))
 
@@ -462,8 +598,16 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
   c.gABC(n, opc, dest, tmp, 0)
   c.freeTemp(tmp)
 
+proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
+  let
+    dest = c.genx(n.sons[1], {gfAddrOf})
+    tmp = c.genx(n.sons[2])
+  c.gABC(n, opc, dest, tmp, 0)
+  #c.genAsgnPatch(n.sons[1], dest)
+  c.freeTemp(tmp)
+
 proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
-  let tmp = c.genx(n.sons[2])
+  let tmp = c.genx(n.sons[1])
   c.gABC(n, opc, tmp, 0, 0)
   c.freeTemp(tmp)
 
@@ -492,23 +636,21 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
     c.freeTemp(tmp)
   else:
     genBinaryABC(c, n, dest, opc)
-
-proc unused(n: PNode; x: TDest) {.inline.} =
-  if x >= 0: InternalError(n.info, "not unused")
+  c.genNarrow(n, dest)
 
 proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =  
   let tmp = c.genx(arg)
-  c.gABx(n, opcSetType, tmp, genType(c, arg.typ))
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABC(n, opc, dest, tmp)
   c.gABx(n, opc, 0, genType(c, n.typ))
+  c.gABx(n, opc, 0, genType(c, arg.typ))
   c.freeTemp(tmp)
 
 proc genCard(c: PCtx; n: PNode; dest: var TDest) =
   let tmp = c.genx(n.sons[1])
   if dest < 0: dest = c.getTemp(n.typ)
   c.genSetType(n.sons[1], tmp)
-  c.gABC(n, opc, dest, tmp)
+  c.gABC(n, opcCard, dest, tmp)
   c.freeTemp(tmp)
 
 proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
@@ -527,9 +669,17 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     c.genAddSubInt(n, dest, opcAddInt)
   of mInc, mDec:
     unused(n, dest)
-    var d = c.genx(n.sons[1]).TDest
-    c.genAddSubInt(n, d, if m == mInc: opcAddInt else: opcSubInt)
-    c.freeTemp(d.TRegister)
+    let opc = if m == mInc: opcAddInt else: opcSubInt
+    let d = c.genx(n.sons[1])
+    if n.sons[2].isInt8Lit:
+      c.gABI(n, succ(opc), d, d, n.sons[2].intVal)
+    else:
+      let tmp = c.genx(n.sons[2])
+      c.gABC(n, opc, d, d, tmp)
+      c.freeTemp(tmp)
+    c.genNarrow(n.sons[1], d)
+    c.genAsgnPatch(n.sons[1], d)
+    c.freeTemp(d)
   of mOrd, mChr, mArrToSeq: c.gen(n.sons[1], dest)
   of mNew, mNewFinalize:
     unused(n, dest)
@@ -539,6 +689,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     c.genNewSeq(n)
   of mNewString:
     genUnaryABC(c, n, dest, opcNewStr)
+    # XXX buggy
   of mNewStringOfCap:
     # we ignore the 'cap' argument and translate it as 'newString(0)'.
     # eval n.sons[1] for possible side effects:
@@ -547,6 +698,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     if dest < 0: dest = c.getTemp(n.typ)
     c.gABC(n, opcNewStr, dest, tmp)
     c.freeTemp(tmp)
+    # XXX buggy
   of mLengthOpenArray, mLengthArray, mLengthSeq:
     genUnaryABI(c, n, dest, opcLenSeq)
   of mLengthStr:
@@ -560,23 +712,23 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     c.freeTemp(d)
     c.freeTemp(tmp)
   of mCard: genCard(c, n, dest)
-  of mMulI, mMulI64: genBinaryABC(c, n, dest, opcMulInt)
-  of mDivI, mDivI64: genBinaryABC(c, n, dest, opcDivInt)
-  of mModI, mModI64: genBinaryABC(c, n, dest, opcModInt)
+  of mMulI, mMulI64: genBinaryABCnarrow(c, n, dest, opcMulInt)
+  of mDivI, mDivI64: genBinaryABCnarrow(c, n, dest, opcDivInt)
+  of mModI, mModI64: genBinaryABCnarrow(c, n, dest, opcModInt)
   of mAddF64: genBinaryABC(c, n, dest, opcAddFloat)
   of mSubF64: genBinaryABC(c, n, dest, opcSubFloat)
   of mMulF64: genBinaryABC(c, n, dest, opcMulFloat)
   of mDivF64: genBinaryABC(c, n, dest, opcDivFloat)
-  of mShrI, mShrI64: genBinaryABC(c, n, dest, opcShrInt)
-  of mShlI, mShlI64: genBinaryABC(c, n, dest, opcShlInt)
-  of mBitandI, mBitandI64: genBinaryABC(c, n, dest, opcBitandInt)
-  of mBitorI, mBitorI64: genBinaryABC(c, n, dest, opcBitorInt)
-  of mBitxorI, mBitxorI64: genBinaryABC(c, n, dest, opcBitxorInt)
-  of mAddU: genBinaryABC(c, n, dest, opcAddu)
-  of mSubU: genBinaryABC(c, n, dest, opcSubu)
-  of mMulU: genBinaryABC(c, n, dest, opcMulu)
-  of mDivU: genBinaryABC(c, n, dest, opcDivu)
-  of mModU: genBinaryABC(c, n, dest, opcModu)
+  of mShrI, mShrI64: genBinaryABCnarrowU(c, n, dest, opcShrInt)
+  of mShlI, mShlI64: genBinaryABCnarrowU(c, n, dest, opcShlInt)
+  of mBitandI, mBitandI64: genBinaryABCnarrowU(c, n, dest, opcBitandInt)
+  of mBitorI, mBitorI64: genBinaryABCnarrowU(c, n, dest, opcBitorInt)
+  of mBitxorI, mBitxorI64: genBinaryABCnarrowU(c, n, dest, opcBitxorInt)
+  of mAddU: genBinaryABCnarrowU(c, n, dest, opcAddu)
+  of mSubU: genBinaryABCnarrowU(c, n, dest, opcSubu)
+  of mMulU: genBinaryABCnarrowU(c, n, dest, opcMulu)
+  of mDivU: genBinaryABCnarrowU(c, n, dest, opcDivu)
+  of mModU: genBinaryABCnarrowU(c, n, dest, opcModu)
   of mEqI, mEqI64, mEqB, mEqEnum, mEqCh:
     genBinaryABC(c, n, dest, opcEqInt)
   of mLeI, mLeI64, mLeEnum, mLeCh, mLeB:
@@ -590,12 +742,16 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
   of mLtPtr, mLtU, mLtU64: genBinaryABC(c, n, dest, opcLtu)
   of mEqProc, mEqRef, mEqUntracedRef, mEqCString:
     genBinaryABC(c, n, dest, opcEqRef)
-  of mXor: genBinaryABC(c, n, dest, opcXor)
+  of mXor: genBinaryABCnarrowU(c, n, dest, opcXor)
   of mNot: genUnaryABC(c, n, dest, opcNot)
-  of mUnaryMinusI, mUnaryMinusI64: genUnaryABC(c, n, dest, opcUnaryMinusInt)
+  of mUnaryMinusI, mUnaryMinusI64:
+    genUnaryABC(c, n, dest, opcUnaryMinusInt)
+    genNarrow(c, n, dest)
   of mUnaryMinusF64: genUnaryABC(c, n, dest, opcUnaryMinusFloat)
   of mUnaryPlusI, mUnaryPlusI64, mUnaryPlusF64: gen(c, n.sons[1], dest)
-  of mBitnotI, mBitnotI64: genUnaryABC(c, n, dest, opcBitnotInt)
+  of mBitnotI, mBitnotI64: 
+    genUnaryABC(c, n, dest, opcBitnotInt)
+    genNarrowU(c, n, dest)
   of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64,
      mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt, 
      mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, 
@@ -624,6 +780,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     var d = c.genx(n.sons[1])
     var tmp = c.genx(n.sons[2])
     c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
+    c.genAsgnPatch(n.sons[1], d)
     c.freeTemp(tmp)
   of mSwap: 
     unused(n, dest)
@@ -639,8 +796,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
       tmp2 = c.genx(n.sons[2])
       tmp3 = c.getTemp(n.sons[2].typ)
     c.gABC(n, opcLenStr, tmp3, tmp1)
-    c.gABC(n, opcSubstr, dest, tmp1, tmp2)
-    c.gABC(n, opcSubstr, tmp3)
+    c.gABC(n, opcSubStr, dest, tmp1, tmp2)
+    c.gABC(n, opcSubStr, tmp3)
     c.freeTemp(tmp1)
     c.freeTemp(tmp2)
     c.freeTemp(tmp3)
@@ -650,8 +807,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
       tmp1 = c.genx(n.sons[1])
       tmp2 = c.genx(n.sons[2])
       tmp3 = c.genx(n.sons[3])
-    c.gABC(n, opcSubstr, dest, tmp1, tmp2)
-    c.gABC(n, opcSubstr, tmp3)
+    c.gABC(n, opcSubStr, dest, tmp1, tmp2)
+    c.gABC(n, opcSubStr, tmp3)
     c.freeTemp(tmp1)
     c.freeTemp(tmp2)
     c.freeTemp(tmp3)
@@ -659,18 +816,22 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     unused(n, dest)
     var d = c.genx(n.sons[1])
     c.gABC(n, opcReset, d)
-  of mOf: 
+  of mOf, mIs:
     if dest < 0: dest = c.getTemp(n.typ)
     var tmp = c.genx(n.sons[1])
-    c.gABC(n, opcOf, dest, tmp)
-    c.gABx(n, opcOf, 0, c.genType(n.sons[2].typ.skipTypes(abstractPtrs)))
+    var idx = c.getTemp(getSysType(tyInt))
+    var typ = n.sons[2].typ
+    if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc})
+    c.gABx(n, opcLdImmInt, idx, c.genType(typ))
+    c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
     c.freeTemp(tmp)
+    c.freeTemp(idx)
   of mSizeOf:
-    GlobalError(n.info, errCannotInterpretNodeX, renderTree(n))
+    globalError(n.info, errCannotInterpretNodeX, renderTree(n))
   of mHigh:
     if dest < 0: dest = c.getTemp(n.typ)
     let tmp = c.genx(n.sons[1])
-    if n.sons[1].typ.skipTypes(abstractVar).kind == tyString:
+    if n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind == tyString:
       c.gABI(n, opcLenStr, dest, tmp, 1)
     else:
       c.gABI(n, opcLenSeq, dest, tmp, 1)
@@ -685,27 +846,23 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     c.freeTempRange(x, n.len-1)
   of mAppendStrCh:
     unused(n, dest)
-    genBinaryStmt(c, n, opcAddStrCh)
+    genBinaryStmtVar(c, n, opcAddStrCh)
   of mAppendStrStr: 
     unused(n, dest)
-    genBinaryStmt(c, n, opcAddStrStr)
+    genBinaryStmtVar(c, n, opcAddStrStr)
   of mAppendSeqElem:
     unused(n, dest)
-    genBinaryStmt(c, n, opcAddSeqElem)
+    genBinaryStmtVar(c, n, opcAddSeqElem)
   of mParseExprToAst:
     genUnaryABC(c, n, dest, opcParseExprToAst)
   of mParseStmtToAst:
     genUnaryABC(c, n, dest, opcParseStmtToAst)
-  of mExpandToAst:
-    InternalError(n.info, "cannot generate code for: " & $m)
   of mTypeTrait: 
     let tmp = c.genx(n.sons[1])
     if dest < 0: dest = c.getTemp(n.typ)
-    c.gABx(n, opcSetType, tmp, c.genType(n.sons[1]))
+    c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ))
     c.gABC(n, opcTypeTrait, dest, tmp)
     c.freeTemp(tmp)
-  of mIs:
-    InternalError(n.info, "cannot generate code for: " & $m)
   of mSlurp: genUnaryABC(c, n, dest, opcSlurp)
   of mStaticExec: genBinaryABC(c, n, dest, opcGorge)
   of mNLen: genUnaryABI(c, n, dest, opcLenSeq)
@@ -750,11 +907,17 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
   of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
   of mNCopyNimNode: genUnaryABC(c, n, dest, opcNCopyNimNode)
   of mNCopyNimTree: genUnaryABC(c, n, dest, opcNCopyNimTree)
-  of mNBindSym: genUnaryABC(c, n, dest, opcNBindSym)
+  of mNBindSym:
+    if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}:
+      let idx = c.genLiteral(n[1])
+      if dest < 0: dest = c.getTemp(n.typ)
+      c.gABx(n, opcNBindSym, dest, idx)
+    else:
+      internalError(n.info, "invalid bindSym usage")
   of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
   of mIdentToStr: genUnaryABC(c, n, dest, opcIdentToStr)
   of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
-  of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqRef)
+  of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
   of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo)
   of mNHint: 
     unused(n, dest)
@@ -771,13 +934,26 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
   of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
   of mMinI, mMaxI, mMinI64, mMaxI64, mAbsF64, mMinF64, mMaxF64, mAbsI, mAbsI64:
     c.genCall(n, dest)
+  of mExpandToAst:
+    if n.len != 2:
+      globalError(n.info, errGenerated, "expandToAst requires 1 argument")
+    let arg = n.sons[1]
+    if arg.kind in nkCallKinds:
+      #if arg[0].kind != nkSym or arg[0].sym.kind notin {skTemplate, skMacro}:
+      #      "ExpandToAst: expanded symbol is no macro or template"
+      if dest < 0: dest = c.getTemp(n.typ)
+      c.genCall(arg, dest)
+      # do not call clearDest(n, dest) here as getAst has a meta-type as such
+      # produces a value
+    else:
+      globalError(n.info, "expandToAst requires a call expression")
   else:
     # mGCref, mGCunref, 
-    InternalError(n.info, "cannot generate code for: " & $m)
+    internalError(n.info, "cannot generate code for: " & $m)
 
 const
   atomicTypes = {tyBool, tyChar,
-    tyExpr, tyStmt, tyTypeDesc,
+    tyExpr, tyStmt, tyTypeDesc, tyStatic,
     tyEnum,
     tyOrdinal,
     tyRange,
@@ -788,8 +964,12 @@ const
     tyFloat, tyFloat32, tyFloat64, tyFloat128,
     tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
 
+proc fitsRegister*(t: PType): bool =
+  t.skipTypes(abstractInst-{tyTypeDesc}).kind in {
+    tyRange, tyEnum, tyBool, tyInt..tyUInt64}
+
 proc requiresCopy(n: PNode): bool =
-  if n.typ.skipTypes(abstractInst).kind in atomicTypes:
+  if n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind in atomicTypes:
     result = false
   elif n.kind in ({nkCurly, nkBracket, nkPar, nkObjConstr}+nkCallKinds):
     result = false
@@ -797,41 +977,53 @@ proc requiresCopy(n: PNode): bool =
     result = true
 
 proc unneededIndirection(n: PNode): bool =
-  n.typ.skipTypes(abstractInst).kind == tyRef
+  n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
 
-proc skipDeref(n: PNode): PNode =
-  if n.kind in {nkDerefExpr, nkHiddenDeref} and unneededIndirection(n.sons[0]):
-    result = n.sons[0]
-  else:
-    result = n
-
-proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = 
+proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
+                  flags: TGenFlags) = 
   # a nop for certain types
-  if unneededIndirection(n.sons[0]):
-    gen(c, n.sons[0], dest)
+  let isAddr = opc in {opcAddrNode, opcAddrReg}
+  let newflags = if isAddr: flags+{gfAddrOf} else: flags
+  # consider:
+  # proc foo(f: var ref int) =
+  #   f = new(int)
+  # proc blah() =
+  #   var x: ref int
+  #   foo x
+  #
+  # The type of 'f' is 'var ref int' and of 'x' is 'ref int'. Hence for
+  # nkAddr we must not use 'unneededIndirection', but for deref we use it.
+  if not isAddr and unneededIndirection(n.sons[0]):
+    gen(c, n.sons[0], dest, newflags)
   else:
-    let tmp = c.genx(n.sons[0])
+    let tmp = c.genx(n.sons[0], newflags)
     if dest < 0: dest = c.getTemp(n.typ)
-    gABC(c, n, opc, dest, tmp)
+    if not isAddr:
+      gABC(c, n, opc, dest, tmp)
+      if gfAddrOf notin flags and fitsRegister(n.typ):
+        c.gABC(n, opcNodeToReg, dest, dest)
+    elif c.prc.slots[tmp].kind >= slotTempUnknown:
+      gABC(c, n, opcAddrNode, dest, tmp)
+    else:
+      gABC(c, n, opcAddrReg, dest, tmp)
     c.freeTemp(tmp)
 
 proc whichAsgnOpc(n: PNode): TOpcode =
-  case n.typ.skipTypes(abstractRange).kind
+  case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
   of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
     opcAsgnInt
   of tyString, tyCString:
     opcAsgnStr
   of tyFloat..tyFloat128:
     opcAsgnFloat
-  of tyRef, tyNil:
+  of tyRef, tyNil, tyVar:
     opcAsgnRef
   else:
     opcAsgnComplex
 
-proc isRef(t: PType): bool = t.skipTypes(abstractRange).kind == tyRef
+proc isRef(t: PType): bool = t.skipTypes(abstractRange-{tyTypeDesc}).kind == tyRef
 
-proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode =
-  if isRef(n.typ): succ(opc) else: opc
+proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc
 
 proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
   let tmp = c.genx(ri)
@@ -839,36 +1031,80 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
   gABC(c, ri, whichAsgnOpc(ri), dest, tmp)
   c.freeTemp(tmp)
 
+proc setSlot(c: PCtx; v: PSym) =
+  # XXX generate type initialization here?
+  if v.position == 0:
+    if c.prc.maxSlots == 0: c.prc.maxSlots = 1
+    v.position = c.prc.maxSlots
+    c.prc.slots[v.position] = (inUse: true,
+        kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
+    inc c.prc.maxSlots
+
+proc cannotEval(n: PNode) {.noinline.} =
+  globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
+    n.renderTree)
+
+proc isOwnedBy(a, b: PSym): bool =
+  var a = a.owner
+  while a != nil and a.kind != skModule:
+    if a == b: return true
+    a = a.owner
+
+proc getOwner(c: PCtx): PSym =
+  result = c.prc.sym
+  if result.isNil: result = c.module
+
+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 s.position == 0:
+    if s.kind in {skVar, skTemp, skLet, skParam, skResult} and 
+        not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
+      cannotEval(n)
+
 proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   case le.kind
   of nkBracketExpr:
-    let dest = c.genx(le.sons[0])
+    let dest = c.genx(le.sons[0], {gfAddrOf})
     let idx = c.genx(le.sons[1])
     let tmp = c.genx(ri)
-    if le.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
+    if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
+        tyString, tyCString}:
       c.gABC(le, opcWrStrIdx, dest, idx, tmp)
     else:
-      c.gABC(le, whichAsgnOpc(le, opcWrArr), dest, idx, tmp)
+      c.gABC(le, opcWrArr, dest, idx, tmp)
     c.freeTemp(tmp)
-  of nkDotExpr:
-    let dest = c.genx(le.sons[0])
-    let idx = c.genx(le.sons[1])
+  of nkDotExpr, nkCheckedFieldExpr:
+    # XXX field checks here
+    let left = if le.kind == nkDotExpr: le else: le.sons[0]
+    let dest = c.genx(left.sons[0], {gfAddrOf})
+    let idx = genField(left.sons[1])
+    let tmp = c.genx(ri)
+    c.gABC(left, opcWrObj, dest, idx, tmp)
+    c.freeTemp(tmp)
+  of nkDerefExpr, nkHiddenDeref:
+    let dest = c.genx(le.sons[0], {gfAddrOf})
     let tmp = c.genx(ri)
-    c.gABC(le, whichAsgnOpc(le, opcWrObj), dest, idx, tmp)
+    c.gABC(le, opcWrDeref, dest, tmp)
     c.freeTemp(tmp)
   of nkSym:
     let s = le.sym
-    if sfGlobal in s.flags:
+    checkCanEval(c, le)
+    if s.isGlobal:
       withTemp(tmp, le.typ):
-        gen(c, ri, tmp)
-        c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
+        c.gen(le, tmp, {gfAddrOf})
+        let val = c.genx(ri)
+        c.gABC(le, opcWrDeref, tmp, val)
+        c.freeTemp(val)
     else:
-      InternalAssert s.position > 0 or (s.position == 0 and
-                                        s.kind in {skParam, skResult})
+      if s.kind == skForVar: c.setSlot s
+      internalAssert s.position > 0 or (s.position == 0 and
+                                        s.kind in {skParam,skResult})
       var dest: TRegister = s.position + ord(s.kind == skParam)
       gen(c, ri, dest)
   else:
-    let dest = c.genx(le)
+    let dest = c.genx(le, {gfAddrOf})
     genAsgn(c, dest, ri, requiresCopy)
 
 proc genLit(c: PCtx; n: PNode; dest: var TDest) =
@@ -878,43 +1114,108 @@ proc genLit(c: PCtx; n: PNode; dest: var TDest) =
   let lit = genLiteral(c, n)
   c.gABx(n, opc, dest, lit)
 
-proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
+proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
+  var n = newNode(nkType)
+  n.typ = t
+  genLit(c, n, dest)
+
+proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
+  when hasFFI:
+    if allowFFI in c.features:
+      c.globals.add(importcSymbol(s))
+      s.position = c.globals.len
+    else:
+      localError(info, errGenerated, "VM is not allowed to 'importc'")
+  else:
+    localError(info, errGenerated,
+               "cannot 'importc' variable at compile time")
+
+proc getNullValue*(typ: PType, info: TLineInfo): PNode
+
+proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
+  c.globals.add(getNullValue(s.typ, n.info))
+  s.position = c.globals.len
+  # This is rather hard to support, due to the laziness of the VM code
+  # generator. See tests/compile/tmacro2 for why this is necesary:
+  #   var decls{.compileTime.}: seq[PNimrodNode] = @[]
+  let dest = c.getTemp(s.typ)
+  c.gABx(n, opcLdGlobal, dest, s.position)
+  let tmp = c.genx(s.ast)
+  c.gABC(n, opcWrDeref, dest, tmp)
+  c.freeTemp(dest)
+  c.freeTemp(tmp)
+
+proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
   let s = n.sym
-  if sfGlobal in s.flags:
-    if dest < 0: dest = c.getTemp(s.typ)
+  if s.isGlobal:
+    if sfCompileTime in s.flags or c.mode == emRepl:
+      discard
+    elif s.position == 0:
+      cannotEval(n)
     if s.position == 0:
-      c.globals.add(s.ast)
-      s.position = c.globals.len
-      # XXX var g = codeHere() ?
-    c.gABx(n, opcLdGlobal, dest, s.position)
+      if sfImportc in s.flags: c.importcSym(n.info, s)
+      else: genGlobalInit(c, n, s)
+    if dest < 0: dest = c.getTemp(n.typ)
+    if gfAddrOf notin flags and fitsRegister(s.typ):
+      var cc = c.getTemp(n.typ)
+      c.gABx(n, opcLdGlobal, cc, s.position)
+      c.gABC(n, opcNodeToReg, dest, cc)
+      c.freeTemp(cc)
+    else:
+      c.gABx(n, opcLdGlobal, dest, s.position)
   else:
-    if s.position > 0 or (s.position == 0 and s.kind in {skParam, skResult}):
+    if s.kind == skForVar and c.mode == emRepl: c.setSlot(s)
+    if s.position > 0 or (s.position == 0 and
+                          s.kind in {skParam,skResult}):
       if dest < 0:
         dest = s.position + ord(s.kind == skParam)
+        internalAssert(c.prc.slots[dest].kind < slotSomeTemp)
       else:
         # we need to generate an assignment:
         genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp)
     else:
-      InternalError(n.info, s.name.s & " " & $s.position)
+      # see tests/t99bott for an example that triggers it:
+      cannotEval(n)
 
-proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
-  let a = c.genx(n.sons[0])
-  let b = c.genx(n.sons[1])
+proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
+                   flags: TGenFlags) =
+  let a = c.genx(n.sons[0], flags)
+  let b = c.genx(n.sons[1], {})
   if dest < 0: dest = c.getTemp(n.typ)
-  c.gABC(n, opc, dest, a, b)
+  if gfAddrOf notin flags and fitsRegister(n.typ):
+    var cc = c.getTemp(n.typ)
+    c.gABC(n, opc, cc, a, b)
+    c.gABC(n, opcNodeToReg, dest, cc)
+    c.freeTemp(cc)
+  else:
+    c.gABC(n, opc, dest, a, b)
   c.freeTemp(a)
   c.freeTemp(b)
 
-proc genObjAccess(c: PCtx; n: PNode; dest: var TDest) =
-  genAccess(c, n, dest, opcLdObj)
+proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
+  let a = c.genx(n.sons[0], flags)
+  let b = genField(n.sons[1])
+  if dest < 0: dest = c.getTemp(n.typ)
+  if gfAddrOf notin flags and fitsRegister(n.typ.skipTypes({tyVar})):
+    var cc = c.getTemp(n.typ)
+    c.gABC(n, opcLdObj, cc, a, b)
+    c.gABC(n, opcNodeToReg, dest, cc)
+    c.freeTemp(cc)
+  else:
+    c.gABC(n, opcLdObj, dest, a, b)
+  c.freeTemp(a)
+
+proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
+  # XXX implement field checks!
+  genObjAccess(c, n.sons[0], dest, flags)
 
-proc genArrAccess(c: PCtx; n: PNode; dest: var TDest) =
-  if n.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
-    genAccess(c, n, dest, opcLdStrIdx)
+proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
+  if n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
+      tyString, tyCString}:
+    genArrAccess2(c, n, dest, opcLdStrIdx, {})
   else:
-    genAccess(c, n, dest, opcLdArr)
+    genArrAccess2(c, n, dest, opcLdArr, flags)
 
-proc getNullValue*(typ: PType, info: TLineInfo): PNode
 proc getNullValueAux(obj: PNode, result: PNode) = 
   case obj.kind
   of nkRecList:
@@ -925,7 +1226,7 @@ proc getNullValueAux(obj: PNode, result: PNode) =
       getNullValueAux(lastSon(obj.sons[i]), result)
   of nkSym:
     addSon(result, getNullValue(obj.sym.typ, result.info))
-  else: InternalError(result.info, "getNullValueAux")
+  else: internalError(result.info, "getNullValueAux")
   
 proc getNullValue(typ: PType, info: TLineInfo): PNode = 
   var t = skipTypes(typ, abstractRange-{tyTypeDesc})
@@ -936,10 +1237,17 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
   of tyUInt..tyUInt64:
     result = newNodeIT(nkUIntLit, info, t)
   of tyFloat..tyFloat128: 
-    result = newNodeIt(nkFloatLit, info, t)
-  of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr, 
-     tyStmt, tyTypeDesc, tyProc, tyRef:
+    result = newNodeIT(nkFloatLit, info, t)
+  of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr,
+     tyStmt, tyTypeDesc, tyStatic, tyRef:
     result = newNodeIT(nkNilLit, info, t)
+  of tyProc:
+    if t.callConv != ccClosure:
+      result = newNodeIT(nkNilLit, info, t)
+    else:
+      result = newNodeIT(nkPar, info, t)
+      result.add(newNodeIT(nkNilLit, info, t))
+      result.add(newNodeIT(nkNilLit, info, t))
   of tyObject: 
     result = newNodeIT(nkPar, info, t)
     getNullValueAux(t.n, result)
@@ -958,57 +1266,50 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
       addSon(result, getNullValue(t.sons[i], info))
   of tySet:
     result = newNodeIT(nkCurly, info, t)
-  else: InternalError("getNullValue: " & $t.kind)
+  else: internalError("getNullValue: " & $t.kind)
 
-proc setSlot(c: PCtx; v: PSym) =
-  # XXX generate type initialization here?
-  if v.position == 0:
-    v.position = c.prc.maxSlots
-    c.prc.slots[v.position] = (inUse: true,
-        kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
-    inc c.prc.maxSlots
+proc ldNullOpcode(t: PType): TOpcode =
+  if fitsRegister(t): opcLdNullReg else: opcLdNull
 
 proc genVarSection(c: PCtx; n: PNode) =
   for a in n:
     if a.kind == nkCommentStmt: continue
     #assert(a.sons[0].kind == nkSym) can happen for transformed vars
     if a.kind == nkVarTuple:
-      let tmp = c.genx(a.lastSon)
       for i in 0 .. a.len-3:
         setSlot(c, a[i].sym)
-        # v = t[i]
-        var v: TDest = -1
-        genRdVar(c, a[i], v)
-        c.gABC(n, opcLdObj, v, tmp, i)
-        # XXX globals?
-      c.freeTemp(tmp)
+        checkCanEval(c, a[i])
+      c.gen(lowerTupleUnpacking(a, c.getOwner))
     elif a.sons[0].kind == nkSym:
       let s = a.sons[0].sym
-      if sfGlobal in s.flags:
+      checkCanEval(c, a.sons[0])
+      if s.isGlobal:
         if s.position == 0:
-          let sa = if s.ast.isNil: getNullValue(s.typ, a.info) else: s.ast
-          c.globals.add(sa)
-          s.position = c.globals.len
-        if a.sons[2].kind == nkEmpty:
-          when false:
-            withTemp(tmp, s.typ):
-              c.gABx(a, opcLdNull, tmp, c.genType(s.typ))
-              c.gABx(a, whichAsgnOpc(a.sons[0], opcWrGlobal), tmp, s.position)
-        else:
-          let tmp = genx(c, a.sons[2])
-          c.gABx(a, whichAsgnOpc(a.sons[0], opcWrGlobal), tmp, s.position)
+          if sfImportc in s.flags: c.importcSym(a.info, s)
+          else:
+            let sa = getNullValue(s.typ, a.info)
+            #if s.ast.isNil: getNullValue(s.typ, a.info)
+            #else: canonValue(s.ast)
+            assert sa.kind != nkCall
+            c.globals.add(sa)
+            s.position = c.globals.len
+        if a.sons[2].kind != nkEmpty:
+          let tmp = c.genx(a.sons[0], {gfAddrOf})
+          let val = c.genx(a.sons[2])
+          c.gABC(a, opcWrDeref, tmp, val)
+          c.freeTemp(val)
           c.freeTemp(tmp)
       else:
         setSlot(c, s)
         if a.sons[2].kind == nkEmpty:
-          c.gABx(a, opcLdNull, s.position, c.genType(s.typ))
+          c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
         else:
           gen(c, a.sons[2], s.position.TRegister)
     else:
       # assign to a.sons[0]; happens for closures
       if a.sons[2].kind == nkEmpty:
         let tmp = genx(c, a.sons[0])
-        c.gABx(a, opcLdNull, tmp, c.genType(a.sons[0].typ))
+        c.gABx(a, ldNullOpcode(a[0].typ), tmp, c.genType(a.sons[0].typ))
         c.freeTemp(tmp)
       else:
         genAsgn(c, a.sons[0], a.sons[2], true)
@@ -1016,27 +1317,44 @@ proc genVarSection(c: PCtx; n: PNode) =
 proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABx(n, opcLdNull, dest, c.genType(n.typ))
+
   let intType = getSysType(tyInt)
-  var tmp = getTemp(c, intType)
-  c.gABx(n, opcLdNull, tmp, c.genType(intType))
-  for x in n:
-    let a = c.genx(x)
-    c.gABC(n, opcWrArr, dest, a, tmp)
-    c.gABI(n, opcAddImmInt, tmp, tmp, 1)
-    c.freeTemp(a)
-  c.freeTemp(tmp)
+  let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
+  if seqType.kind == tySequence:
+    var tmp = c.getTemp(intType)
+    c.gABx(n, opcLdImmInt, tmp, n.len)
+    c.gABx(n, opcNewSeq, dest, c.genType(seqType))
+    c.gABx(n, opcNewSeq, tmp, 0)
+    c.freeTemp(tmp)
+  
+  if n.len > 0:
+    var tmp = getTemp(c, intType)
+    c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
+    for x in n:
+      let a = c.genx(x)
+      c.gABC(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
+      c.gABI(n, opcAddImmInt, tmp, tmp, 1)
+      c.freeTemp(a)
+    c.freeTemp(tmp)
 
 proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABx(n, opcLdNull, dest, c.genType(n.typ))
   for x in n:
-    let a = c.genx(x)
-    c.gABC(n, opcIncl, dest, a)
-    c.freeTemp(a)
+    if x.kind == nkRange:
+      let a = c.genx(x.sons[0])
+      let b = c.genx(x.sons[1])
+      c.gABC(n, opcInclRange, dest, a, b)
+      c.freeTemp(b)
+      c.freeTemp(a)
+    else:
+      let a = c.genx(x)
+      c.gABC(n, opcIncl, dest, a)
+      c.freeTemp(a)
 
 proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
   if dest < 0: dest = c.getTemp(n.typ)
-  let t = n.typ.skipTypes(abstractRange)
+  let t = n.typ.skipTypes(abstractRange-{tyTypeDesc})
   if t.kind == tyRef:
     c.gABx(n, opcNew, dest, c.genType(t.sons[0]))
   else:
@@ -1044,42 +1362,42 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
   for i in 1.. <n.len:
     let it = n.sons[i]
     if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
-      let idx = c.genx(it.sons[0])
+      let idx = genField(it.sons[0])
       let tmp = c.genx(it.sons[1])
       c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
       c.freeTemp(tmp)
-      c.freeTemp(idx)
     else:
       internalError(n.info, "invalid object constructor")
 
 proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
   if dest < 0: dest = c.getTemp(n.typ)
-  var idx = getTemp(c, getSysType(tyInt))
+  c.gABx(n, opcLdNull, dest, c.genType(n.typ))
+  # XXX x = (x.old, 22)  produces wrong code ... stupid self assignments
   for i in 0.. <n.len:
     let it = n.sons[i]
     if it.kind == nkExprColonExpr:
-      let idx = c.genx(it.sons[0])
+      let idx = genField(it.sons[0])
       let tmp = c.genx(it.sons[1])
       c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
       c.freeTemp(tmp)
-      c.freeTemp(idx)
     else:
       let tmp = c.genx(it)
-      c.gABx(it, opcLdImmInt, idx, i)
-      c.gABC(it, whichAsgnOpc(it, opcWrObj), dest, idx, tmp)
+      c.gABC(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
       c.freeTemp(tmp)
-  c.freeTemp(idx)
 
 proc genProc*(c: PCtx; s: PSym): int
 
-proc gen(c: PCtx; n: PNode; dest: var TDest) =
+proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   case n.kind
   of nkSym:
     let s = n.sym
+    checkCanEval(c, n)
     case s.kind
     of skVar, skForVar, skTemp, skLet, skParam, skResult:
-      genRdVar(c, n, dest)
-    of skProc, skConverter, skMacro, skMethod, skIterator:
+      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)
       genLit(c, n, dest)
     of skConst:
       gen(c, s.ast, dest)
@@ -1090,33 +1408,34 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
       else:
         var lit = genLiteral(c, newIntNode(nkIntLit, s.position))
         c.gABx(n, opcLdConst, dest, lit)
-    of skField:
-      InternalAssert dest < 0
-      if s.position > high(dest):
-        InternalError(n.info, 
-          "too large offset! cannot generate code for: " & s.name.s)
-      dest = s.position
+    of skType:
+      genTypeLit(c, s.typ, dest)
     else:
-      InternalError(n.info, "cannot generate code for: " & s.name.s)
+      internalError(n.info, "cannot generate code for: " & s.name.s)
   of nkCallKinds:
     if n.sons[0].kind == nkSym and n.sons[0].sym.magic != mNone:
       genMagic(c, n, dest)
     else:
       genCall(c, n, dest)
+      clearDest(c, n, dest)
   of nkCharLit..nkInt64Lit:
     if isInt16Lit(n):
       if dest < 0: dest = c.getTemp(n.typ)
       c.gABx(n, opcLdImmInt, dest, n.intVal.int)
     else:
       genLit(c, n, dest)
-  of nkUIntLit..nkNilLit: genLit(c, n, dest)
+  of nkUIntLit..pred(nkNilLit): genLit(c, n, dest)
+  of nkNilLit:
+    if not n.typ.isEmptyType: genLit(c, n, dest)
+    else: unused(n, dest)
   of nkAsgn, nkFastAsgn: 
     unused(n, dest)
     genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
-  of nkDotExpr: genObjAccess(c, n, dest)
-  of nkBracketExpr: genArrAccess(c, n, dest)
-  of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcDeref)
-  of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddr)
+  of nkDotExpr: genObjAccess(c, n, dest, flags)
+  of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
+  of nkBracketExpr: genArrAccess(c, n, dest, flags)
+  of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcLdDeref, flags)
+  of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddrNode, flags)
   of nkWhenStmt, nkIfStmt, nkIfExpr: genIf(c, n, dest)
   of nkCaseStmt: genCase(c, n, dest)
   of nkWhileStmt:
@@ -1139,7 +1458,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
   of nkStmtListExpr:
     let L = n.len-1
     for i in 0 .. <L: gen(c, n.sons[i])
-    gen(c, n.sons[L], dest)
+    gen(c, n.sons[L], dest, flags)
   of nkDiscardStmt:
     unused(n, dest)
     gen(c, n.sons[0])
@@ -1168,7 +1487,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
     else:
       dest = tmp0
   of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
-     nkTemplateDef, nkIncludeStmt, nkImportStmt:
+     nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt:
     unused(n, dest)
   of nkStringToCString, nkCStringToString:
     gen(c, n.sons[0], dest)
@@ -1176,8 +1495,13 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
   of nkCurly: genSetConstr(c, n, dest)
   of nkObjConstr: genObjConstr(c, n, dest)
   of nkPar, nkClosure: genTupleConstr(c, n, dest)
+  of nkCast:
+    if allowCast in c.features:
+      genConv(c, n, n.sons[1], dest, opcCast)
+    else:
+      localError(n.info, errGenerated, "VM is not allowed to 'cast'")
   else:
-    InternalError n.info, "too implement " & $n.kind
+    internalError n.info, "cannot generate VM code for " & n.renderTree
 
 proc removeLastEof(c: PCtx) =
   let last = c.code.len-1
@@ -1193,14 +1517,16 @@ proc genStmt*(c: PCtx; n: PNode): int =
   var d: TDest = -1
   c.gen(n, d)
   c.gABC(n, opcEof)
-  InternalAssert d < 0
+  if d >= 0: internalError(n.info, "some destination set")
 
-proc genExpr*(c: PCtx; n: PNode): int =
+proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int =
   c.removeLastEof
   result = c.code.len
   var d: TDest = -1
   c.gen(n, d)
-  InternalAssert d >= 0
+  if d < 0:
+    if requiresValue: internalError(n.info, "no destination set")
+    d = 0
   c.gABC(n, opcEof, d)
 
 proc genParams(c: PCtx; params: PNode) =
@@ -1212,7 +1538,7 @@ proc genParams(c: PCtx; params: PNode) =
   c.prc.maxSlots = max(params.len, 1)
 
 proc finalJumpTarget(c: PCtx; pc, diff: int) =
-  InternalAssert(-0x7fff < diff and diff < 0x7fff)
+  internalAssert(-0x7fff < diff and diff < 0x7fff)
   let oldInstr = c.code[pc]
   # opcode and regA stay the same:
   c.code[pc] = ((oldInstr.uint32 and 0xffff'u32).uint32 or
@@ -1225,12 +1551,11 @@ proc optimizeJumps(c: PCtx; start: int) =
     case opc
     of opcTJmp, opcFJmp:
       var reg = c.code[i].regA
-      var d = i + c.code[i].regBx
-      var iters = maxIterations
-      while iters > 0:
+      var d = i + c.code[i].jmpDiff
+      for iters in countdown(maxIterations, 0):
         case c.code[d].opcode
-        of opcJmp:
-          d = d + c.code[d].regBx
+        of opcJmp, opcJmpBack:
+          d = d + c.code[d].jmpDiff
         of opcTJmp, opcFJmp:
           if c.code[d].regA != reg: break
           # tjmp x, 23
@@ -1238,46 +1563,67 @@ proc optimizeJumps(c: PCtx; start: int) =
           # tjmp x, 12
           # -- we know 'x' is true, and so can jump to 12+13:
           if c.code[d].opcode == opc:
-            d = d + c.code[d].regBx
+            d = d + c.code[d].jmpDiff
           else:
             # tjmp x, 23
             # fjmp x, 22
             # We know 'x' is true so skip to the next instruction:
             d = d + 1
         else: break
-        dec iters
-      c.finalJumpTarget(i, d - i)
-    of opcJmp:
-      var d = i + c.code[i].regBx
+      if d != i + c.code[i].jmpDiff:
+        c.finalJumpTarget(i, d - i)
+    of opcJmp, opcJmpBack:
+      var d = i + c.code[i].jmpDiff
       var iters = maxIterations
       while c.code[d].opcode == opcJmp and iters > 0:
-        d = d + c.code[d].regBx
+        d = d + c.code[d].jmpDiff
         dec iters
-      c.finalJumpTarget(i, d - i)
+      if c.code[d].opcode == opcRet:
+        # optimize 'jmp to ret' to 'ret' here
+        c.code[i] = c.code[d]
+      elif d != i + c.code[i].jmpDiff:
+        c.finalJumpTarget(i, d - i)
     else: discard
 
 proc genProc(c: PCtx; s: PSym): int =
   let x = s.ast.sons[optimizedCodePos]
   if x.kind == nkEmpty:
-    c.removeLastEof
+    #if s.name.s == "outterMacro" or s.name.s == "innerProc":
+    #  echo "GENERATING CODE FOR ", s.name.s
+    let last = c.code.len-1
+    var eofInstr: TInstr
+    if last >= 0 and c.code[last].opcode == opcEof:
+      eofInstr = c.code[last]
+      c.code.setLen(last)
+      c.debug.setLen(last)
+    #c.removeLastEof
     result = c.code.len+1 # skip the jump instruction
     s.ast.sons[optimizedCodePos] = newIntNode(nkIntLit, result)
     # thanks to the jmp we can add top level statements easily and also nest
     # procs easily:
     let body = s.getBody
     let procStart = c.xjmp(body, opcJmp, 0)
-    var p = PProc(blocks: @[])
+    var p = PProc(blocks: @[], sym: s)
     let oldPrc = c.prc
     c.prc = p
     # iterate over the parameters and allocate space for them:
     genParams(c, s.typ.n)
+    if tfCapturesEnv in s.typ.flags:
+      #let env = s.ast.sons[paramsPos].lastSon.sym
+      #assert env.position == 2
+      c.prc.slots[c.prc.maxSlots] = (inUse: true, kind: slotFixedLet)
+      inc c.prc.maxSlots
     gen(c, body)
     # generate final 'return' statement:
     c.gABC(body, opcRet)
     c.patch(procStart)
-    c.gABC(body, opcEof)
-    s.position = c.prc.maxSlots
+    c.gABC(body, opcEof, eofInstr.regA)
+    c.optimizeJumps(result)
+    s.offset = c.prc.maxSlots
+    #if s.name.s == "addStuff":
+    #  echo renderTree(body)
+    #  c.echoCode(result)
     c.prc = oldPrc
-    #c.echoCode
   else:
+    c.prc.maxSlots = s.offset
     result = x.intVal.int
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 39b19646e..9fdb3bac6 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -28,9 +28,9 @@ type
     wElif, wElse, wEnd, wEnum, wExcept, wExport,
     wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, 
     wInclude, wInterface, wIs, wIsnot, wIterator, wLambda, wLet,
-    wMacro, wMethod, wMixin, wUsing, wMod, wNil, 
+    wMacro, wMethod, wMixin, wMod, wNil, 
     wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, 
-    wShared, wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wVar, 
+    wShared, wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, 
     wWhen, wWhile, wWith, wWithout, wXor, wYield,
     
     wColon, wColonColon, wEquals, wDot, wDotDot,
@@ -62,8 +62,8 @@ type
     wWatchPoint, wSubsChar, 
     wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt,
     wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, 
-    wNoStackFrame,
-    wImplicitStatic, wGlobal, wCodegenDecl,
+    wAsmNoStackFrame,
+    wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked,
 
     wAuto, wBool, wCatch, wChar, wClass,
     wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@@ -72,7 +72,7 @@ type
     wPrivate, wProtected, wPublic, wRegister, wReinterpret_cast,
     wShort, wSigned, wSizeof, wStatic_cast, wStruct, wSwitch,
     wThis, wThrow, wTrue, wTypedef, wTypeid, wTypename,
-    wUnion, wUnsigned, wVirtual, wVoid, wVolatile, wWchar_t,
+    wUnion, wPacked, wUnsigned, wVirtual, wVoid, wVolatile, wWchar_t,
 
     wAlignas, wAlignof, wConstexpr, wDecltype, wNullptr, wNoexcept,
     wThread_local, wStatic_assert, wChar16_t, wChar32_t,
@@ -95,7 +95,7 @@ const
   
   cppNimSharedKeywords* = {
     wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport,
-    wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing }
+    wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing}
 
   specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", 
     
@@ -107,11 +107,11 @@ const
     "finally", "for", "from", "generic", "if", 
     "import", "in", "include", "interface", "is", "isnot", "iterator",
     "lambda", "let",
-    "macro", "method", "mixin", "using", "mod", "nil", "not", "notin",
+    "macro", "method", "mixin", "mod", "nil", "not", "notin",
     "object", "of", "or", 
     "out", "proc", "ptr", "raise", "ref", "return",
     "shared", "shl", "shr", "static",
-    "template", "try", "tuple", "type", "var", 
+    "template", "try", "tuple", "type", "using", "var", 
     "when", "while", "with", "without", "xor",
     "yield",
 
@@ -145,7 +145,7 @@ const
     "subschar", "acyclic", "shallow", "unroll", "linearscanend",
     "computedgoto", "injectstmt",
     "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
-    "nostackframe", "implicitstatic", "global", "codegendecl",
+    "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
     
     "auto", "bool", "catch", "char", "class",
     "const_cast", "default", "delete", "double",
@@ -155,7 +155,7 @@ const
     "private", "protected", "public", "register", "reinterpret_cast",
     "short", "signed", "sizeof", "static_cast", "struct", "switch",
     "this", "throw", "true", "typedef", "typeid",
-    "typename", "union", "unsigned", "virtual", "void", "volatile",
+    "typename", "union", "packed", "unsigned", "virtual", "void", "volatile",
     "wchar_t",
 
     "alignas", "alignof", "constexpr", "decltype", "nullptr", "noexcept",
@@ -166,7 +166,7 @@ const
     "inout", "bycopy", "byref", "oneway",
     ]
 
-proc findStr*(a: openarray[string], s: string): int = 
+proc findStr*(a: openArray[string], s: string): int = 
   for i in countup(low(a), high(a)): 
     if cmpIgnoreStyle(a[i], s) == 0: 
       return i
@@ -176,7 +176,7 @@ proc whichKeyword*(id: PIdent): TSpecialWord =
   if id.id < 0: result = wInvalid
   else: result = TSpecialWord(id.id)
 
-proc whichKeyword*(id: String): TSpecialWord = 
+proc whichKeyword*(id: string): TSpecialWord = 
   result = whichKeyword(getIdent(id))
   
 proc initSpecials() =