summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorMichał Zieliński <michal@zielinscy.org.pl>2014-02-09 15:34:18 +0100
committerMichał Zieliński <michal@zielinscy.org.pl>2014-02-09 15:34:18 +0100
commit820fdd634870686082ad01896327f67cf45cd96f (patch)
treeffe146b77359f616d25a28b85ab2ba8efd604f4c /compiler
parent11053afff83e00bb04be05590a169ed79ce5f0d3 (diff)
parente6a50307bb505304b37147417ba2a93586d59a51 (diff)
downloadNim-820fdd634870686082ad01896327f67cf45cd96f.tar.gz
Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim6
-rw-r--r--compiler/astalgo.nim33
-rw-r--r--compiler/ccgexprs.nim4
-rw-r--r--compiler/evalffi.nim56
-rw-r--r--compiler/lambdalifting.nim53
-rw-r--r--compiler/lookups.nim14
-rw-r--r--compiler/main.nim7
-rw-r--r--compiler/parser.nim50
-rw-r--r--compiler/sem.nim4
-rw-r--r--compiler/semdata.nim3
-rw-r--r--compiler/semexprs.nim20
-rw-r--r--compiler/semgnrc.nim11
-rw-r--r--compiler/semstmts.nim17
-rw-r--r--compiler/semthreads.nim2
-rw-r--r--compiler/semtypes.nim41
-rw-r--r--compiler/semtypinst.nim2
-rw-r--r--compiler/sigmatch.nim20
-rw-r--r--compiler/types.nim7
-rw-r--r--compiler/vm.nim27
-rw-r--r--compiler/vmdef.nim2
-rw-r--r--compiler/vmgen.nim146
21 files changed, 320 insertions, 205 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 7138b5f52..cd002eef1 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1129,7 +1129,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))
   
@@ -1166,7 +1166,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
   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 = 
@@ -1177,7 +1177,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:
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 2505bc687..64c1b717c 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -561,14 +561,31 @@ proc strTableContains(t: TStrTable, n: PSym): bool =
 
 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
+  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
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index ba543039e..031ab8d70 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -343,7 +343,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)
@@ -1049,7 +1049,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     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:
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index 74f0663f3..54be0ccb2 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.
@@ -102,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
@@ -164,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
@@ -193,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)
@@ -207,7 +207,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     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
@@ -217,7 +217,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     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))
       dec packRecCheck
@@ -233,7 +233,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   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
 
@@ -243,7 +243,7 @@ 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
@@ -262,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:
@@ -288,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])
@@ -312,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() =
@@ -337,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))
@@ -374,7 +374,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
       n.sons[0] = unpack(p, typ.sons[0], 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:
@@ -391,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, 
@@ -414,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
@@ -422,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)
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 00fa04556..ebb4aeac4 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -637,6 +637,22 @@ proc outerProcSons(o: POuterContext, n: PNode) =
     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 == skIterator
+
+  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
@@ -649,17 +665,22 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
       return indirectAccess(newSymNode(o.closureParam), local, n.info)
 
     var closure = PEnv(idTableGet(o.lambdasToEnv, local))
-    if closure != nil:
-      # we need to replace the lambda with '(lambda, env)':
-      if local.kind == skIterator and local.typ.callConv == ccClosure:
-        # 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 local.kind == skIterator and local.typ.callConv == ccClosure:
+      # 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.createdVar
       if a != nil:
@@ -773,22 +794,6 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
 
 # ------------------- iterator transformation --------------------------------
 
-proc liftIterSym*(n: PNode): PNode =
-  # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env)) 
-  let iter = n.sym
-  assert iter.kind == skIterator
-
-  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 liftForLoop*(body: PNode): PNode =
   # problem ahead: the iterator could be invoked indirectly, but then
   # we don't know what environment to create here: 
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 6dfd25968..c31eb3121 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -339,4 +339,16 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
                                    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/main.nim b/compiler/main.nim
index cdea7b5ca..f6d11d960 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -135,7 +135,7 @@ proc interactivePasses =
   #setTarget(osNimrodVM, cpuNimrodVM)
   initDefines()
   defineSymbol("nimrodvm")
-  when hasFFI: DefineSymbol("nimffi")
+  when hasFFI: defineSymbol("nimffi")
   registerPass(verbosePass)
   registerPass(semPass)
   registerPass(evalPass)
@@ -324,7 +324,7 @@ proc mainCommand* =
     wantMainModule()
     when hasTinyCBackend:
       extccomp.setCC("tcc")
-      CommandCompileToC()
+      commandCompileToC()
     else:
       rawMessage(errInvalidCommandX, command)
   of "js", "compiletojs":
@@ -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/parser.nim b/compiler/parser.nim
index 3765557b9..ff3324b47 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -35,6 +35,7 @@ type
     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)
@@ -455,11 +456,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:
     getTok(p)
     optInd(p, result)
     result.add(complexOrSimpleStmt(p))
+  dec p.inSemiStmtList
   result.kind = nkStmtListExpr
 
 proc parsePar(p: var TParser): PNode =
@@ -642,8 +645,7 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
   #|               | '.' optInd ('type' | 'addr' | symbol) generalizedLit?
   #|               | '[' optInd indexExprList optPar ']'
   #|               | '{' optInd indexExprList optPar '}'
-  #|               | &( '`'|IDENT|literal|'cast') expr ^+ ',' # command syntax
-  #|                      (doBlock | macroColon)?
+  #|               | &( '`'|IDENT|literal|'cast') expr # command syntax
   result = r
   while p.tok.indent < 0:
     case p.tok.tokType
@@ -672,16 +674,18 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
         let a = result
         result = newNodeP(nkCommand, p)
         addSon(result, a)
-        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)
+        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
@@ -1103,7 +1107,9 @@ proc parseExprStmt(p: var TParser): PNode =
   #|              doBlocks
   #|               / macroColon
   #|            ))?
+  inc p.inPragma
   var a = simpleExpr(p)
+  dec p.inPragma
   if p.tok.tokType == tkEquals: 
     getTok(p)
     optInd(p, result)
@@ -1878,14 +1884,18 @@ 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)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index e89e32f4e..00ac79716 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -83,7 +83,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]
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 980abb865..c9d95e1bf 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -42,7 +42,7 @@ type
 
   TExprFlag* = enum 
     efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType,
-    efAllowDestructor
+    efAllowDestructor, efWantValue
   TExprFlags* = set[TExprFlag]
 
   PContext* = ref TContext
@@ -211,6 +211,7 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
 
 proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
   let typedesc = makeTypeDesc(c, typ)
+  rawAddSon(typedesc, newTypeS(tyNone, c))
   let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
   return newSymNode(sym, info)
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 84303b6cd..a8a16672d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -35,7 +35,7 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     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("")
@@ -1706,8 +1706,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
@@ -1819,6 +1819,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)
@@ -1924,10 +1928,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       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 nfDelegate in n.flags:
       result = semDirectOp(c, n, flags)
     else:
       result = semIndirectOp(c, n, flags)
@@ -1993,7 +1999,7 @@ 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)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 89a167b96..b21d851c9 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.
@@ -215,8 +215,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       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))
@@ -226,8 +225,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       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))
@@ -281,8 +279,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       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))
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index caa719c7e..0871b7fb7 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -740,7 +740,7 @@ 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
       inc c.inGenericContext
       var body = semTypeNode(c, a.sons[2], nil)
@@ -748,7 +748,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       if body != nil:
         body.sym = s
         body.size = -1 # could not be computed properly
-      s.typ.sons[sonsLen(s.typ) - 1] = body
+        s.typ.sons[sonsLen(s.typ) - 1] = body
       popOwner()
       closeScope(c)
     elif a.sons[2].kind != nkEmpty: 
@@ -972,6 +972,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   else:
     s = n[namePos].sym
     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
@@ -1206,7 +1209,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}
@@ -1247,12 +1250,14 @@ proc semStmtList(c: PContext, n: PNode): PNode =
       if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
         voidContext = true
         n.typ = enforceVoidContext
-      if i != last or voidContext or c.inTypeClass > 0:
+      if i == last and efWantValue in flags:
+        n.typ = n.sons[i].typ
+        if not isEmptyType(n.typ): n.kind = nkStmtListExpr
+      elif i != last or voidContext or c.inTypeClass > 0:
         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])
diff --git a/compiler/semthreads.nim b/compiler/semthreads.nim
index f7322db80..d3426ca3e 100644
--- a/compiler/semthreads.nim
+++ b/compiler/semthreads.nim
@@ -358,7 +358,7 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
   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
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 408b1b62e..44e414e9c 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -681,12 +681,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   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.kind == tySequence and paramType.lastSon == nil:
+    if paramType.kind == tySequence and paramType.lastSon.kind == tyNone:
       let typ = c.newTypeWithSons(tyBuiltInTypeClass,
                                   @[newTypeS(paramType.kind, c)])
       result = addImplicitGeneric(typ)
@@ -885,8 +885,12 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     for i in countup(1, sonsLen(n)-1):
       var elem = semGenericParamInInvokation(c, n.sons[i])
       addToResult(elem)
+  elif s.typ.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(c, s, n)
     matches(c, n, copyTree(n), m)
@@ -1133,15 +1137,26 @@ 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 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)
   
@@ -1165,8 +1180,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
       typ = semTypeNode(c, constraint, nil)
       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)
     
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 1158335a8..a07d91241 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -358,7 +358,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
     if lookup != nil:
       result = lookup
       if tfUnresolved in t.flags: result = result.base
-    elif t.sonsLen > 0:
+    elif t.sons[0].kind != tyNone:
       result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
  
   of tyUserTypeClass:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index d269e9e69..335ceafeb 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -105,6 +105,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
       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*(ctx: PContext, callee: PSym,
@@ -562,10 +563,11 @@ proc typeRel(c: var TCandidate, f, aOrig: 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)
@@ -636,7 +638,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   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)
@@ -736,7 +738,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyGenericInst:
     let roota = a.skipGenericAlias
     let rootf = f.skipGenericAlias
-    if a.kind == tyGenericInst and roota.base == rootf.base :
+    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]
@@ -845,7 +847,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         # 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 f.sonsLen == 0:
             result = isGeneric
           else:
             internalAssert a.sons != nil and a.sons.len > 0
@@ -854,7 +856,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         else:
           result = isNone
       else:
-        if f.sonsLen > 0:
+        if f.sonsLen > 0 and f.sons[0].kind != tyNone:
           result = typeRel(c, f.lastSon, a)
         else:
           result = isGeneric
@@ -883,7 +885,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     var prev = PType(idTableGet(c.bindings, f))
     if prev == nil:
       if a.kind == tyTypeDesc:
-        if f.sonsLen == 0:
+        if f.sons[0].kind == tyNone:
           result = isGeneric
         else:
           result = typeRel(c, f.sons[0], a.sons[0])
diff --git a/compiler/types.nim b/compiler/types.nim
index 4a53a84c9..db75cd3c0 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -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,
@@ -451,7 +452,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       of tyProc: "proc"
       of tyObject: "object"
       of tyTuple: "tuple"
-      else: (internalAssert false; "")
+      else: (internalAssert(false); "")
   of tyUserTypeClassInst:
     let body = t.base
     result = body.sym.name.s & "["
@@ -1257,7 +1258,7 @@ proc containsGenericTypeIter(t: PType, closure: PObject): bool =
     return true
 
   if t.kind == tyTypeDesc:
-    if t.sonsLen == 0: return true
+    if t.sons[0].kind == tyNone: return true
     if containsGenericTypeIter(t.base, closure): return true
     return false
   
diff --git a/compiler/vm.nim b/compiler/vm.nim
index deca288b5..10ac7aaaf 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -14,7 +14,7 @@ import ast except getstr
 
 import
   strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
-  parser, vmdeps, idents, trees, renderer, options
+  parser, vmdeps, idents, trees, renderer, options, transf
 
 from semfold import leValueConv, ordinalValToString
 from evaltempl import evalTemplate
@@ -337,7 +337,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       asgnRef(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
     of opcWrGlobal:
       asgnComplex(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
-    of opcLdArr:
+    of opcLdArr, opcLdArrRef:
       # a = b[c]
       let rb = instr.regB
       let rc = instr.regC
@@ -348,7 +348,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       assert regs[rb].kind != nkMetaNode
       let src = regs[rb]
       if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
-        asgnComplex(regs[ra], src.sons[idx])
+        if instr.opcode == opcLdArrRef and false:
+          # XXX activate when seqs are fixed
+          asgnRef(regs[ra], src.sons[idx])
+        else:
+          asgnComplex(regs[ra], src.sons[idx])
       else:
         stackTrace(c, tos, pc, errIndexOutOfBounds)
     of opcLdStrIdx:
@@ -379,9 +383,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       # a = b.c
       let rb = instr.regB
       let rc = instr.regC
-      # XXX this creates a wrong alias
       #Message(c.debug[pc], warnUser, $regs[rb].safeLen & " " & $rc)
       asgnComplex(regs[ra], regs[rb].sons[rc])
+    of opcLdObjRef:
+      # a = b.c
+      let rb = instr.regB
+      let rc = instr.regC
+      # XXX activate when seqs are fixed
+      asgnComplex(regs[ra], regs[rb].sons[rc])
+      #asgnRef(regs[ra], regs[rb].sons[rc])
     of opcWrObj:
       # a.b = c
       let rb = instr.regB
@@ -1037,7 +1047,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       # 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})
+      var typ = regs[rb].typ
+      internalAssert typ != nil
+      while typ.kind == tyTypeDesc and typ.len > 0: typ = typ.sons[0]
       regs[ra].strVal = typ.typeToString(preferExported)
     of opcGlobalOnce:
       let rb = instr.regBx
@@ -1066,6 +1078,7 @@ proc execute(c: PCtx, start: int): PNode =
   result = rawExecute(c, start, tos)
 
 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':
@@ -1073,6 +1086,7 @@ 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)
@@ -1115,6 +1129,7 @@ proc myProcess(c: PPassContext, n: PNode): PNode =
 const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
 
 proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
+  let n = transformExpr(module, n)
   setupGlobalCtx(module)
   var c = globalCtx
   c.mode = mode
@@ -1168,7 +1183,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   # 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] = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
   # setup parameters:
   for i in 1 .. < min(tos.slots.len, L):
     tos.slots[i] = setupMacroParam(n.sons[i])
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 480c7f31b..87159c813 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -34,9 +34,11 @@ type
     opcAsgnComplex,
 
     opcLdArr,  # a = b[c]
+    opcLdArrRef,
     opcWrArr,  # a[b] = c
     opcWrArrRef,
     opcLdObj,  # a = b.c
+    opcLdObjRef,
     opcWrObj,  # a.b = c
     opcWrObjRef,
     opcAddr,
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index a41e60e7d..d0e8dacf3 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.
@@ -13,9 +13,18 @@ import
   unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef, 
   trees, intsets, rodread, magicsys, options
 
+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()
@@ -44,7 +53,7 @@ proc codeListing(c: PCtx, result: var string, start=0) =
     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
 
@@ -100,7 +109,7 @@ proc patch(c: PCtx, p: TPosition) =
                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:
@@ -190,20 +199,20 @@ 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)
+  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)
+  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)
 
@@ -400,7 +409,7 @@ 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:
@@ -470,15 +479,16 @@ proc genNew(c: PCtx; n: PNode) =
   # 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 = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
              else: c.genx(n.sons[1])
-  c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(abstractVar)))
   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(tmp)
   c.genAsgnPatch(n.sons[1], dest)
@@ -506,7 +516,7 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   c.freeTemp(tmp2)
 
 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))
 
@@ -528,6 +538,14 @@ 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[1])
   c.gABC(n, opc, tmp, 0, 0)
@@ -729,7 +747,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     var tmp = c.genx(n.sons[1])
     var idx = c.getTemp(getSysType(tyInt))
     var typ = n.sons[2].typ
-    if m == mOf: typ = typ.skipTypes(abstractPtrs)
+    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)
@@ -739,7 +757,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
   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)
@@ -754,13 +772,13 @@ 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:
@@ -874,7 +892,7 @@ const
     tyUInt, tyUInt8, tyUInt16, tyUInt32, 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
@@ -882,7 +900,7 @@ 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]):
@@ -890,18 +908,20 @@ proc skipDeref(n: PNode): PNode =
   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
+  let flags = if opc == opcAddr: flags+{gfAddrOf} else: flags
   if unneededIndirection(n.sons[0]):
-    gen(c, n.sons[0], dest)
+    gen(c, n.sons[0], dest, flags)
   else:
-    let tmp = c.genx(n.sons[0])
+    let tmp = c.genx(n.sons[0], flags)
     if dest < 0: dest = c.getTemp(n.typ)
     gABC(c, n, opc, 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:
@@ -913,7 +933,7 @@ proc whichAsgnOpc(n: PNode): TOpcode =
   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
@@ -926,13 +946,22 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
 
 template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
 
+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 genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   case le.kind
   of nkBracketExpr:
     let dest = c.genx(le.sons[0])
     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)
@@ -952,8 +981,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
         gen(c, ri, tmp)
         c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
     else:
+      if s.kind == skForVar and c.mode == emRepl: c.setSlot s
       internalAssert s.position > 0 or (s.position == 0 and
-                                        s.kind in {skParam,skResult,skForVar})
+                                        s.kind in {skParam,skResult})
       var dest: TRegister = s.position + ord(s.kind == skParam)
       gen(c, ri, dest)
   else:
@@ -1003,7 +1033,7 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
   if s.isGlobal:
     if sfCompileTime in s.flags or c.mode == emRepl:
       discard
-    else:
+    elif s.position == 0:
       cannotEval(n)
     if s.position == 0:
       if sfImportc in s.flags: c.importcSym(n.info, s)
@@ -1014,8 +1044,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
     else:
       c.gABx(n, opcLdGlobal, dest, s.position)
   else:
+    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,skForVar}):
+                          s.kind in {skParam,skResult}):
       if dest < 0:
         dest = s.position + ord(s.kind == skParam)
       else:
@@ -1024,28 +1055,29 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
     else:
       # see tests/t99bott for an example that triggers it:
       cannotEval(n)
-      #InternalError(n.info, s.name.s & " " & $s.position)
 
-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 genAccess(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)
+  c.gABC(n, (if gfAddrOf in flags: succ(opc) else: 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) =
+  genAccess(c, n, dest, opcLdObj, flags)
 
-proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest) =
+proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
   # XXX implement field checks!
-  genAccess(c, n.sons[0], dest, opcLdObj)
+  genAccess(c, n.sons[0], dest, opcLdObj, 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}:
+    genAccess(c, n, dest, opcLdStrIdx, {})
   else:
-    genAccess(c, n, dest, opcLdArr)
+    genAccess(c, n, dest, opcLdArr, flags)
 
 proc getNullValue*(typ: PType, info: TLineInfo): PNode
 proc getNullValueAux(obj: PNode, result: PNode) = 
@@ -1100,14 +1132,6 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
     result = newNodeIT(nkCurly, info, t)
   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 genVarSection(c: PCtx; n: PNode) =
   for a in n:
     if a.kind == nkCommentStmt: continue
@@ -1187,7 +1211,7 @@ proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
 
 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:
@@ -1222,7 +1246,7 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
 
 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
@@ -1271,11 +1295,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
   of nkAsgn, nkFastAsgn: 
     unused(n, dest)
     genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
-  of nkDotExpr: genObjAccess(c, n, dest)
-  of nkCheckedFieldExpr: genCheckedObjAccess(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, opcDeref, flags)
+  of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddr, flags)
   of nkWhenStmt, nkIfStmt, nkIfExpr: genIf(c, n, dest)
   of nkCaseStmt: genCase(c, n, dest)
   of nkWhileStmt:
@@ -1298,7 +1322,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])
@@ -1460,9 +1484,9 @@ proc genProc(c: PCtx; s: PSym): int =
     c.gABC(body, opcEof, eofInstr.regA)
     c.optimizeJumps(result)
     s.offset = c.prc.maxSlots
-    #if s.name.s == "rawGet":
+    #if s.name.s == "concatStyleInterpolation":
     #  c.echoCode(result)
-    #  echo renderTree(body)
+    # echo renderTree(body)
     c.prc = oldPrc
   else:
     c.prc.maxSlots = s.offset