summary refs log tree commit diff stats
path: root/rod
diff options
context:
space:
mode:
Diffstat (limited to 'rod')
-rwxr-xr-xrod/ccgexprs.nim120
-rwxr-xr-xrod/ccgstmts.nim65
-rwxr-xr-xrod/ccgtypes.nim91
-rwxr-xr-xrod/cgen.nim13
-rwxr-xr-xrod/commands.nim6
-rwxr-xr-xrod/rst.nim2
-rwxr-xr-x[-rw-r--r--]rod/semcall.nim0
-rwxr-xr-xrod/semexprs.nim15
-rwxr-xr-xrod/semtempl.nim2
-rwxr-xr-xrod/semtypes.nim4
-rwxr-xr-x[-rw-r--r--]rod/semtypinst.nim0
-rwxr-xr-x[-rw-r--r--]rod/suggest.nim0
12 files changed, 191 insertions, 127 deletions
diff --git a/rod/ccgexprs.nim b/rod/ccgexprs.nim
index 65cc33fd4..8da08347c 100755
--- a/rod/ccgexprs.nim
+++ b/rod/ccgexprs.nim
@@ -184,6 +184,26 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
          [addrLoc(dest), rdLoc(src)])
 
+proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
+  # Consider: 
+  # type TMyFastString {.shallow.} = string
+  # Due to the implementation of pragmas this would end up to set the
+  # tfShallow flag for the built-in string type too! So we check only
+  # here for this flag, where it is reasonably safe to do so
+  # (for objects, etc.):
+  if needToCopy notin flags or 
+      tfShallow in skipTypes(dest.t, abstractVarRange).flags:
+    if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
+      appcg(p, cpsStmts,
+           "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
+           [addrLoc(dest), addrLoc(src), rdLoc(dest)])
+    else:
+      appcg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
+           [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
+  else:
+    appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
+         [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
+
 proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # This function replaces all other methods for generating
   # the assignment operation in C.
@@ -192,13 +212,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   of tyRef:
     genRefAssign(p, dest, src, flags)
   of tySequence:
-    if not (needToCopy in flags):
+    if needToCopy notin flags:
       genRefAssign(p, dest, src, flags)
     else:
       appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
            [addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
   of tyString:
-    if not (needToCopy in flags):
+    if needToCopy notin flags:
       genRefAssign(p, dest, src, flags)
     else:
       if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
@@ -209,23 +229,15 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
       else:
         appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
              [addrLoc(dest), rdLoc(src)])
-  of tyTuple:
-    if needsComplexAssignment(dest.t):
-      appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
-           [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
-    else:
-      appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
-  of tyObject:                
+  of tyTuple, tyObject:
     # XXX: check for subtyping?
     if needsComplexAssignment(dest.t):
-      appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
-           [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
+      genGenericAsgn(p, dest, src, flags)
     else:
       appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
   of tyArray, tyArrayConstr:
     if needsComplexAssignment(dest.t):
-      appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
-           [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
+      genGenericAsgn(p, dest, src, flags)
     else:
       appcg(p, cpsStmts,
            "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
@@ -363,10 +375,11 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
 
 proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   const
-    opr: array[mUnaryMinusI..mAbsI64, string] = ["((NI$2)-($1))", # UnaryMinusI
-      "-($1)",                # UnaryMinusI64
-      "(NI$2)abs($1)",        # AbsI
-      "($1 > 0? ($1) : -($1))"] # AbsI64
+    opr: array[mUnaryMinusI..mAbsI64, string] = [
+      mUnaryMinusI: "((NI$2)-($1))",
+      mUnaryMinusI64: "-($1)",
+      mAbsI: "(NI$2)abs($1)",
+      mAbsI64: "($1 > 0? ($1) : -($1))"]
   var
     a: TLoc
     t: PType
@@ -760,47 +773,68 @@ proc genEcho(p: BProc, n: PNode) =
   appcg(p, cpsStmts, "#rawEchoNL();$n")
 
 proc genCall(p: BProc, t: PNode, d: var TLoc) =
-  var
-    param: PSym
-    invalidRetType: bool
-    typ: PType
-    pl: PRope                 # parameter list
-    op, list, a: TLoc
-    length: int
+  var op, a: TLoc
   # this is a hotspot in the compiler
   initLocExpr(p, t.sons[0], op)
-  pl = con(op.r, "(")         #typ := getUniqueType(t.sons[0].typ);
-  typ = t.sons[0].typ         # getUniqueType() is too expensive here!
+  var pl = con(op.r, "(")
+  var typ = t.sons[0].typ # getUniqueType() is too expensive here!
   assert(typ.kind == tyProc)
-  invalidRetType = isInvalidReturnType(typ.sons[0])
-  length = sonsLen(t)
+  var invalidRetType = isInvalidReturnType(typ.sons[0])
+  var length = sonsLen(t)
   for i in countup(1, length - 1):
     initLocExpr(p, t.sons[i], a) # generate expression for param
     assert(sonsLen(typ) == sonsLen(typ.n))
     if (i < sonsLen(typ)):
       assert(typ.n.sons[i].kind == nkSym)
-      param = typ.n.sons[i].sym
+      var param = typ.n.sons[i].sym
       if ccgIntroducedPtr(param): app(pl, addrLoc(a))
       else: app(pl, rdLoc(a))
     else:
       app(pl, rdLoc(a))
-    if (i < length - 1) or (invalidRetType and (typ.sons[0] != nil)):
-      app(pl, ", ")
-  if (typ.sons[0] != nil) and invalidRetType:
-    # XXX (detected by pegs module 64bit): p(result, result) is not
-    # correct here. Thus we always allocate a temporary:
-    if d.k == locNone: getTemp(p, typ.sons[0], d)
-    app(pl, addrLoc(d))
-  app(pl, ")")
-  if (typ.sons[0] != nil) and not invalidRetType:
-    if d.k == locNone: getTemp(p, typ.sons[0], d)
-    assert(d.t != nil)        # generate an assignment to d:
-    initLoc(list, locCall, nil, OnUnknown)
-    list.r = pl
-    genAssignment(p, d, list, {}) # no need for deep copying
+    if i < length - 1: app(pl, ", ")
+  if typ.sons[0] != nil:
+    if invalidRetType:
+      if length > 1: app(pl, ", ")
+      # beware of 'result = p(result)'. We always allocate a temporary:
+      if d.k in {locTemp, locNone}:
+        # We already got a temp. Great, special case it:
+        if d.k == locNone: getTemp(p, typ.sons[0], d)
+        app(pl, addrLoc(d))
+        app(pl, ")")
+        app(p.s[cpsStmts], pl)
+        app(p.s[cpsStmts], ';' & tnl)
+      else:
+        var tmp: TLoc
+        getTemp(p, typ.sons[0], tmp)
+        app(pl, addrLoc(tmp))
+        app(pl, ")")
+        app(p.s[cpsStmts], pl)
+        app(p.s[cpsStmts], ';' & tnl)
+        genAssignment(p, d, tmp, {}) # no need for deep copying
+    else:
+      app(pl, ")")
+      if d.k == locNone: getTemp(p, typ.sons[0], d)
+      assert(d.t != nil)        # generate an assignment to d:
+      var list: TLoc
+      initLoc(list, locCall, nil, OnUnknown)
+      list.r = pl
+      genAssignment(p, d, list, {}) # no need for deep copying
   else:
+    app(pl, ")")
     app(p.s[cpsStmts], pl)
     app(p.s[cpsStmts], ';' & tnl)
+    
+  when false:
+    app(pl, ")")
+    if (typ.sons[0] != nil) and not invalidRetType:
+      if d.k == locNone: getTemp(p, typ.sons[0], d)
+      assert(d.t != nil)        # generate an assignment to d:
+      initLoc(list, locCall, nil, OnUnknown)
+      list.r = pl
+      genAssignment(p, d, list, {}) # no need for deep copying
+    else:
+      app(p.s[cpsStmts], pl)
+      app(p.s[cpsStmts], ';' & tnl)
 
 proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   #   <Nimrod code>
diff --git a/rod/ccgstmts.nim b/rod/ccgstmts.nim
index e87305065..da6ca377f 100755
--- a/rod/ccgstmts.nim
+++ b/rod/ccgstmts.nim
@@ -162,6 +162,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
     a: TLoc
     Labl: TLabel
     length: int
+  inc(p.withinLoop)
   genLineDir(p, t)
   assert(sonsLen(t) == 2)
   inc(p.labels)
@@ -179,6 +180,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
   if p.blocks[length].id > 0: appf(p.s[cpsStmts], "} $1: ;$n", [Labl])
   else: app(p.s[cpsStmts], '}' & tnl)
   setlen(p.blocks, len(p.blocks) - 1)
+  dec(p.withinLoop)
 
 proc genBlock(p: BProc, t: PNode, d: var TLoc) = 
   inc(p.labels)
@@ -619,21 +621,52 @@ proc genPragma(p: BProc, n: PNode) =
         if (sfDeadCodeElim in p.module.module.flags): 
           addPendingModule(p.module)
     else: nil
-  
-proc genAsgn(p: BProc, e: PNode) = 
-  var a: TLoc
-  genLineDir(p, e)            # BUGFIX
-  InitLocExpr(p, e.sons[0], a)
-  assert(a.t != nil)
-  expr(p, e.sons[1], a)
 
-proc genFastAsgn(p: BProc, e: PNode) = 
-  var a: TLoc
-  genLineDir(p, e)            # BUGFIX
+proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool = 
+  if optFieldCheck in p.options:
+    var le = asgn.sons[0]
+    if le.kind == nkCheckedFieldExpr:
+      var field = le.sons[0].sons[1].sym
+      result = sfDiscriminant in field.flags
+    elif le.kind == nkDotExpr:
+      var field = le.sons[1].sym
+      result = sfDiscriminant in field.flags      
+
+proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType, 
+                          field: PSym) = 
+  var t = skipTypes(objtype, abstractVar)
+  assert t.kind == tyObject
+  discard genTypeInfo(p.module, t)
+  var L = lengthOrd(field.typ)
+  if not IntSetContainsOrIncl(p.module.declaredThings, field.id):
+    appcg(p.module, cfsVars, "extern $1", 
+          discriminatorTableDecl(p.module, t, field))
+  appcg(p, cpsStmts,
+        "#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
+        [rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
+         intLiteral(L+1)])
+
+proc asgnFieldDiscriminant(p: BProc, e: PNode) = 
+  var a, tmp: TLoc
+  var dotExpr = e.sons[0]
+  var d: PSym
+  if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr.sons[0]
   InitLocExpr(p, e.sons[0], a)
-  incl(a.flags, lfNoDeepCopy)
-  assert(a.t != nil)
-  expr(p, e.sons[1], a)
+  getTemp(p, a.t, tmp)
+  expr(p, e.sons[1], tmp)
+  genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, dotExpr.sons[1].sym)
+  genAssignment(p, a, tmp, {})
+  
+proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = 
+  genLineDir(p, e)
+  if not FieldDiscriminantCheckNeeded(p, e):
+    var a: TLoc
+    InitLocExpr(p, e.sons[0], a)
+    if fastAsgn: incl(a.flags, lfNoDeepCopy)
+    assert(a.t != nil)
+    expr(p, e.sons[1], a)
+  else:
+    asgnFieldDiscriminant(p, e)
 
 proc genStmts(p: BProc, t: PNode) = 
   var 
@@ -657,8 +690,8 @@ proc genStmts(p: BProc, t: PNode) =
      nkCallStrLit: 
     genLineDir(p, t)
     initLocExpr(p, t, a)
-  of nkAsgn: genAsgn(p, t)
-  of nkFastAsgn: genFastAsgn(p, t)
+  of nkAsgn: genAsgn(p, t, fastAsgn=false)
+  of nkFastAsgn: genAsgn(p, t, fastAsgn=true)
   of nkDiscardStmt: 
     genLineDir(p, t)
     initLocExpr(p, t.sons[0], a)
@@ -684,7 +717,7 @@ proc genStmts(p: BProc, t: PNode) =
           (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
           (prc.kind == skMethod): 
         # we have not only the header: 
-        if (t.sons[codePos].kind != nkEmpty) or (lfDynamicLib in prc.loc.flags): 
+        if t.sons[codePos].kind != nkEmpty or lfDynamicLib in prc.loc.flags: 
           genProc(p.module, prc)
   else: internalError(t.info, "genStmts(" & $t.kind & ')')
   
diff --git a/rod/ccgtypes.nim b/rod/ccgtypes.nim
index 43b4f173d..1920da599 100755
--- a/rod/ccgtypes.nim
+++ b/rod/ccgtypes.nim
@@ -7,9 +7,6 @@
 #    distribution, for details about the copyright.
 #
 
-#var
-#  newDummyVar: int # just to check the symbol file mechanism
-
 # ------------------------- Name Mangling --------------------------------
 
 proc mangle(name: string): string = 
@@ -566,46 +563,51 @@ proc genTypeInfoAux(m: BModule, typ: PType, name: PRope) =
     base = toRope("0")
   genTypeInfoAuxBase(m, typ, name, base)
 
+proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope = 
+  if objType.sym == nil: 
+    InternalError(d.info, "anonymous obj with discriminator")
+  result = ropef("NimDT_$1_$2", [
+    toRope(objType.sym.name.s), toRope(d.name.s)])
+
+proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope = 
+  discard cgsym(m, "TNimNode")
+  var tmp = discriminatorTableName(m, objtype, d)
+  result = ropef("TNimNode* $1[$2];$n", [tmp, toRope(lengthOrd(d.typ)+1)])
+
 proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) = 
-  var 
-    tmp, tmp2: PRope
-    length, x, y: int
-    field: PSym
-    b: PNode
   case n.kind
   of nkRecList: 
-    length = sonsLen(n)
-    if length == 1: 
+    var L = sonsLen(n)
+    if L == 1: 
       genObjectFields(m, typ, n.sons[0], expr)
-    elif length > 0: 
-      tmp = getTempName()
-      appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", 
-           [tmp, toRope(length)])
-      for i in countup(0, length - 1): 
-        tmp2 = getNimNode(m)
+    elif L > 0: 
+      var tmp = getTempName()
+      appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, toRope(L)])
+      for i in countup(0, L-1): 
+        var tmp2 = getNimNode(m)
         appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
         genObjectFields(m, typ, n.sons[i], tmp2)
       appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n", 
-           [expr, toRope(length), tmp])
-    else: 
-      appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n", 
-           [expr, toRope(length)])
+           [expr, toRope(L), tmp])
+    else:
+      appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n", [expr, toRope(L)])
   of nkRecCase: 
-    length = sonsLen(n)
     assert(n.sons[0].kind == nkSym)
-    field = n.sons[0].sym
-    tmp = getTempName()
+    var field = n.sons[0].sym
+    var tmp = discriminatorTableName(m, typ, field)
+    var L = lengthOrd(field.typ)
+    assert L > 0
     appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
         "$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
         "$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
         "$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r, 
-                           genTypeInfo(m, field.typ), makeCString(field.name.s), 
-                           tmp, toRope(lengthOrd(field.typ))])
-    appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", 
-         [tmp, toRope(lengthOrd(field.typ) + 1)])
-    for i in countup(1, length - 1): 
-      b = n.sons[i]           # branch
-      tmp2 = getNimNode(m)
+                           genTypeInfo(m, field.typ), 
+                           makeCString(field.name.s), 
+                           tmp, toRope(L)])
+    appf(m.s[cfsData], "TNimNode* $1[$2];$n", [tmp, toRope(L+1)])
+    for i in countup(1, sonsLen(n)-1): 
+      var b = n.sons[i]           # branch
+      var tmp2 = getNimNode(m)
       genObjectFields(m, typ, lastSon(b), tmp2)
       case b.kind
       of nkOfBranch: 
@@ -613,8 +615,8 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
           internalError(b.info, "genObjectFields; nkOfBranch broken")
         for j in countup(0, sonsLen(b) - 2): 
           if b.sons[j].kind == nkRange: 
-            x = int(getOrdValue(b.sons[j].sons[0]))
-            y = int(getOrdValue(b.sons[j].sons[1]))
+            var x = int(getOrdValue(b.sons[j].sons[0]))
+            var y = int(getOrdValue(b.sons[j].sons[1]))
             while x <= y: 
               appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(x), tmp2])
               inc(x)
@@ -623,10 +625,10 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
                  [tmp, toRope(getOrdValue(b.sons[j])), tmp2])
       of nkElse: 
         appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", 
-             [tmp, toRope(lengthOrd(field.typ)), tmp2])
+             [tmp, toRope(L), tmp2])
       else: internalError(n.info, "genObjectFields(nkRecCase)")
   of nkSym: 
-    field = n.sym
+    var field = n.sym
     appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
         "$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
         "$1.name = $5;$n", [expr, getTypeDesc(m, typ), 
@@ -634,10 +636,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
   else: internalError(n.info, "genObjectFields")
   
 proc genObjectInfo(m: BModule, typ: PType, name: PRope) = 
-  var tmp: PRope
   if typ.kind == tyObject: genTypeInfoAux(m, typ, name)
   else: genTypeInfoAuxBase(m, typ, name, toRope("0"))
-  tmp = getNimNode(m)
+  var tmp = getNimNode(m)
   genObjectFields(m, typ, typ.n, tmp)
   appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
 
@@ -742,21 +743,15 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
          [result, toRope(typeToString(t))])
   if dataGenerated: return 
   case t.kind
-  of tyEmpty: 
-    result = toRope("0")
+  of tyEmpty: result = toRope("0")
   of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128, 
      tyVar: 
     genTypeInfoAuxBase(gNimDat, t, result, toRope("0"))
-  of tyRef, tyPtr, tySequence, tyRange: 
-    genTypeInfoAux(gNimDat, t, result)
-  of tyArrayConstr, tyArray: 
-    genArrayInfo(gNimDat, t, result)
-  of tySet: 
-    genSetInfo(gNimDat, t, result)
-  of tyEnum: 
-    genEnumInfo(gNimDat, t, result)
-  of tyObject: 
-    genObjectInfo(gNimDat, t, result)
+  of tyRef, tyPtr, tySequence, tyRange: genTypeInfoAux(gNimDat, t, result)
+  of tyArrayConstr, tyArray: genArrayInfo(gNimDat, t, result)
+  of tySet: genSetInfo(gNimDat, t, result)
+  of tyEnum: genEnumInfo(gNimDat, t, result)
+  of tyObject: genObjectInfo(gNimDat, t, result)
   of tyTuple: 
     if t.n != nil: genObjectInfo(gNimDat, t, result)
     else: genTupleInfo(gNimDat, t, result)
diff --git a/rod/cgen.nim b/rod/cgen.nim
index 7df9f3d11..51aee87ab 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -77,6 +77,7 @@ type
     sendClosure: PType       # closure record type that we pass
     receiveClosure: PType    # closure record type that we get
     module: BModule          # used to prevent excessive parameter passing
+    withinLoop: int          # > 0 if we are within a loop
   
   TTypeSeq = seq[PType]
   TCGen = object of TPassContext # represents a C source file
@@ -131,8 +132,7 @@ proc addPendingModule(m: BModule) =
 
 proc findPendingModule(m: BModule, s: PSym): BModule = 
   var ms = getModule(s)
-  if ms.id == m.module.id: 
-    return m
+  if ms.id == m.module.id: return m
   for i in countup(0, high(gPendingModules)): 
     result = gPendingModules[i]
     if result.module.id == ms.id: return 
@@ -231,6 +231,9 @@ proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
            args: openarray[PRope]) = 
   app(c, ropecg(m, frmt, args))
 
+proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr, 
+           args: openarray[PRope]) = 
+  app(m.s[s], ropecg(m, frmt, args))
 
 proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr, 
            args: openarray[PRope]) = 
@@ -248,7 +251,7 @@ proc rdLoc(a: TLoc): PRope =
 
 proc addrLoc(a: TLoc): PRope =
   result = a.r
-  if not (lfIndirect in a.flags): result = con("&", result)
+  if lfIndirect notin a.flags: result = con("&", result)
 
 proc rdCharLoc(a: TLoc): PRope =
   # read a location that may need a char-cast:
@@ -285,7 +288,7 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
 proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) = 
   if skipTypes(loc.t, abstractVarRange).Kind notin
       {tyArray, tyArrayConstr, tySet, tyTuple, tyObject}: 
-    if containsGcref:
+    if containsGcref and p.WithInLoop > 0:
       appf(p.s[cpsInit], "$1 = 0;$n", [rdLoc(loc)])
       var nilLoc: TLoc
       initLoc(nilLoc, locTemp, loc.t, onStack)
@@ -295,7 +298,7 @@ proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) =
     else:
       appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)])
   else: 
-    if containsGcref:
+    if containsGcref and p.WithInLoop > 0:
       appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n", 
            [addrLoc(loc), rdLoc(loc)])
       appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", 
diff --git a/rod/commands.nim b/rod/commands.nim
index 83c01f0ed..d3eaf94a9 100755
--- a/rod/commands.nim
+++ b/rod/commands.nim
@@ -200,12 +200,12 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
   var id = ""  # arg = "X]:on|off"
   var i = 0
   var n = hintMin
-  while (i < len(arg) + 0) and (arg[i] != ']'): 
+  while i < len(arg) and (arg[i] != ']'): 
     add(id, arg[i])
     inc(i)
-  if (i < len(arg) + 0) and (arg[i] == ']'): inc(i)
+  if i < len(arg) and (arg[i] == ']'): inc(i)
   else: InvalidCmdLineOption(pass, arg, info)
-  if (i < len(arg) + 0) and (arg[i] in {':', '='}): inc(i)
+  if i < len(arg) and (arg[i] in {':', '='}): inc(i)
   else: InvalidCmdLineOption(pass, arg, info)
   if state == wHint: 
     var x = findStr(msgs.HintsToStr, id)
diff --git a/rod/rst.nim b/rod/rst.nim
index dace43a44..85b0cf54e 100755
--- a/rod/rst.nim
+++ b/rod/rst.nim
@@ -432,7 +432,7 @@ proc matchesHyperlink(h: PRstNode, filename: string): bool =
     result = matchesHyperlink(h.sons[0], filename)
   elif h.kind == rnHyperlink: 
     var s = addNodes(h.sons[1])
-    if startsWith(s, filename) and (s[len(filename) + 0] == '#'): result = true
+    if startsWith(s, filename) and (s[len(filename)] == '#'): result = true
     else: result = false
   else: 
     result = false
diff --git a/rod/semcall.nim b/rod/semcall.nim
index 294c0399b..294c0399b 100644..100755
--- a/rod/semcall.nim
+++ b/rod/semcall.nim
diff --git a/rod/semexprs.nim b/rod/semexprs.nim
index 7a14b931a..712ce4e6e 100755
--- a/rod/semexprs.nim
+++ b/rod/semexprs.nim
@@ -412,10 +412,8 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
                                  flags: TExprFlags): PNode = 
   var symflags = {skProc, skMethod, skConverter}
   if efWantIterator in flags:
-    symflags = {skIterator}
-  elif efAllowType in flags: 
     # for ``type countup(1,3)``, see ``tests/ttoseq``.
-    symflags.incl(skIterator)
+    symflags = {skIterator}
   result = semDirectCall(c, n, symflags)
   if result != nil: 
     if result.sons[0].kind != nkSym: 
@@ -571,7 +569,6 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
                                  check: var PNode): PSym = 
   # transform in a node that contains the runtime check for the
   # field, if it is in a case-part...
-  var s, it, inExpr, notExpr: PNode
   result = nil
   case r.kind
   of nkRecList: 
@@ -583,9 +580,9 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
     if (r.sons[0].kind != nkSym): IllFormedAst(r)
     result = lookupInRecordAndBuildCheck(c, n, r.sons[0], field, check)
     if result != nil: return 
-    s = newNodeI(nkCurly, r.info)
+    var s = newNodeI(nkCurly, r.info)
     for i in countup(1, sonsLen(r) - 1): 
-      it = r.sons[i]
+      var it = r.sons[i]
       case it.kind
       of nkOfBranch: 
         result = lookupInRecordAndBuildCheck(c, n, lastSon(it), field, check)
@@ -597,7 +594,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
             addSon(check, ast.emptyNode) # make space for access node
           s = newNodeI(nkCurly, n.info)
           for j in countup(0, sonsLen(it) - 2): addSon(s, copyTree(it.sons[j]))
-          inExpr = newNodeI(nkCall, n.info)
+          var inExpr = newNodeI(nkCall, n.info)
           addSon(inExpr, newIdentNode(getIdent("in"), n.info))
           addSon(inExpr, copyTree(r.sons[0]))
           addSon(inExpr, s)   #writeln(output, renderTree(inExpr));
@@ -609,11 +606,11 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
           if check == nil: 
             check = newNodeI(nkCheckedFieldExpr, n.info)
             addSon(check, ast.emptyNode) # make space for access node
-          inExpr = newNodeI(nkCall, n.info)
+          var inExpr = newNodeI(nkCall, n.info)
           addSon(inExpr, newIdentNode(getIdent("in"), n.info))
           addSon(inExpr, copyTree(r.sons[0]))
           addSon(inExpr, s)
-          notExpr = newNodeI(nkCall, n.info)
+          var notExpr = newNodeI(nkCall, n.info)
           addSon(notExpr, newIdentNode(getIdent("not"), n.info))
           addSon(notExpr, inExpr)
           addSon(check, semExpr(c, notExpr))
diff --git a/rod/semtempl.nim b/rod/semtempl.nim
index 1fbcbe227..7782c7b42 100755
--- a/rod/semtempl.nim
+++ b/rod/semtempl.nim
@@ -152,7 +152,7 @@ proc transformToExpr(n: PNode): PNode =
     if realStmt >= 0: result = transformToExpr(n.sons[realStmt])
     else: n.kind = nkStmtListExpr
   of nkBlockStmt: 
-    n.kind = nkBlockExpr      
+    n.kind = nkBlockExpr
     #nkIfStmt: n.kind := nkIfExpr; // this is not correct!
   else: 
     nil
diff --git a/rod/semtypes.nim b/rod/semtypes.nim
index 8dae5c27b..d2e6cd7f5 100755
--- a/rod/semtypes.nim
+++ b/rod/semtypes.nim
@@ -574,8 +574,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   case n.kind
   of nkEmpty: nil
   of nkTypeOfExpr: 
+    # for ``type countup(1,3)``, see ``tests/ttoseq``.
+    # XXX We should find a better solution.
     checkSonsLen(n, 1)
-    result = semExprWithType(c, n.sons[0], {efAllowType}).typ
+    result = semExprWithType(c, n.sons[0], {efWantIterator}).typ
   of nkPar: 
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
     else: GlobalError(n.info, errTypeExpected)
diff --git a/rod/semtypinst.nim b/rod/semtypinst.nim
index 6427d7858..6427d7858 100644..100755
--- a/rod/semtypinst.nim
+++ b/rod/semtypinst.nim
diff --git a/rod/suggest.nim b/rod/suggest.nim
index 6f4babe63..6f4babe63 100644..100755
--- a/rod/suggest.nim
+++ b/rod/suggest.nim