summary refs log tree commit diff stats
path: root/compiler/ccgstmts.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/ccgstmts.nim')
-rw-r--r--compiler/ccgstmts.nim339
1 files changed, 165 insertions, 174 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index a3d807e26..130c41011 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -46,7 +46,7 @@ proc inExceptBlockLen(p: BProc): int =
 
 proc startBlockInternal(p: BProc): int {.discardable.} =
   inc(p.labels)
-  result = len(p.blocks)
+  result = p.blocks.len
   setLen(p.blocks, result + 1)
   p.blocks[result].id = p.labels
   p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
@@ -62,16 +62,15 @@ proc endBlock(p: BProc)
 proc genVarTuple(p: BProc, n: PNode) =
   var tup, field: TLoc
   if n.kind != nkVarTuple: internalError(p.config, n.info, "genVarTuple")
-  var L = len(n)
 
   # if we have a something that's been captured, use the lowering instead:
-  for i in 0 .. L-3:
+  for i in 0..<n.len-2:
     if n[i].kind != nkSym:
       genStmts(p, lowerTupleUnpacking(p.module.g.graph, n, p.prc))
       return
 
   # check only the first son
-  var forHcr = treatGlobalDifferentlyForHCR(p.module, n.sons[0].sym)
+  var forHcr = treatGlobalDifferentlyForHCR(p.module, n[0].sym)
   let hcrCond = if forHcr: getTempName(p.module) else: nil
   var hcrGlobals: seq[tuple[loc: TLoc, tp: Rope]]
   # determine if the tuple is constructed at top-level scope or inside of a block (if/while/block)
@@ -85,10 +84,10 @@ proc genVarTuple(p: BProc, n: PNode) =
     startBlock(p)
 
   genLineDir(p, n)
-  initLocExpr(p, n.sons[L-1], tup)
+  initLocExpr(p, n[^1], tup)
   var t = tup.t.skipTypes(abstractInst)
-  for i in 0 .. L-3:
-    let vn = n.sons[i]
+  for i in 0..<n.len-2:
+    let vn = n[i]
     let v = vn.sym
     if sfCompileTime in v.flags: continue
     var traverseProc: Rope
@@ -100,13 +99,13 @@ proc genVarTuple(p: BProc, n: PNode) =
         registerTraverseProc(p, v, traverseProc)
     else:
       assignLocalVar(p, vn)
-      initLocalVar(p, v, immediateAsgn=isAssignedImmediately(p.config, n[L-1]))
+      initLocalVar(p, v, immediateAsgn=isAssignedImmediately(p.config, n[^1]))
     initLoc(field, locExpr, vn, tup.storage)
     if t.kind == tyTuple:
       field.r = "$1.Field$2" % [rdLoc(tup), rope(i)]
     else:
-      if t.n.sons[i].kind != nkSym: internalError(p.config, n.info, "genVarTuple")
-      field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(p.module, t.n.sons[i].sym)]
+      if t.n[i].kind != nkSym: internalError(p.config, n.info, "genVarTuple")
+      field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(p.module, t.n[i].sym)]
     putLocIntoDest(p, v.loc, field)
     if forHcr or isGlobalInBlock:
       hcrGlobals.add((loc: v.loc, tp: if traverseProc == nil: ~"NULL" else: traverseProc))
@@ -121,12 +120,12 @@ proc genVarTuple(p: BProc, n: PNode) =
     lineCg(p, cpsLocals, "NIM_BOOL $1 = NIM_FALSE;$n", [hcrCond])
     for curr in hcrGlobals:
       lineCg(p, cpsLocals, "$1 |= hcrRegisterGlobal($4, \"$2\", sizeof($3), $5, (void**)&$2);$N",
-              [hcrCond, curr.loc.r, rdLoc(curr.loc), getModuleDllPath(p.module, n.sons[0].sym), curr.tp])
+              [hcrCond, curr.loc.r, rdLoc(curr.loc), getModuleDllPath(p.module, n[0].sym), curr.tp])
 
 
 proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
-  if ri.kind in nkCallKinds and (ri.sons[0].kind != nkSym or
-                                 ri.sons[0].sym.magic == mNone):
+  if ri.kind in nkCallKinds and (ri[0].kind != nkSym or
+                                 ri[0].sym.magic == mNone):
     genAsgnCall(p, le, ri, a)
   else:
     # this is a hacky way to fix #1181 (tmissingderef)::
@@ -153,7 +152,7 @@ proc blockBody(b: var TBlock): Rope =
 proc endBlock(p: BProc, blockEnd: Rope) =
   let topBlock = p.blocks.len-1
   # the block is merged into the parent block
-  add(p.blocks[topBlock-1].sections[cpsStmts], p.blocks[topBlock].blockBody)
+  p.blocks[topBlock-1].sections[cpsStmts].add(p.blocks[topBlock].blockBody)
   setLen(p.blocks, topBlock)
   # this is done after the block is popped so $n is
   # properly indented when pretty printing is enabled
@@ -190,7 +189,7 @@ proc genState(p: BProc, n: PNode) =
   internalAssert p.config, n.len == 1
   let n0 = n[0]
   if n0.kind == nkIntLit:
-    let idx = n.sons[0].intVal
+    let idx = n[0].intVal
     linefmt(p, cpsStmts, "STATE$1: ;$n", [idx])
   elif n0.kind == nkStrLit:
     linefmt(p, cpsStmts, "$1: ;$n", [n0.strVal])
@@ -201,7 +200,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
 
   var stack = newSeq[tuple[fin: PNode, inExcept: bool]](0)
 
-  for i in 1 .. howManyTrys:
+  for i in 1..howManyTrys:
     let tryStmt = p.nestedTryStmts.pop
     if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
       # Pop safe points generated by try
@@ -236,7 +235,7 @@ proc genGotoState(p: BProc, n: PNode) =
   #   case 0: goto STATE0;
   # ...
   var a: TLoc
-  initLocExpr(p, n.sons[0], a)
+  initLocExpr(p, n[0], a)
   lineF(p, cpsStmts, "switch ($1) {$n", [rdLoc(a)])
   p.beforeRetNeeded = true
   lineF(p, cpsStmts, "case -1:$n", [])
@@ -244,12 +243,12 @@ proc genGotoState(p: BProc, n: PNode) =
     howManyTrys    = p.nestedTryStmts.len,
     howManyExcepts = p.inExceptBlockLen)
   lineF(p, cpsStmts, " goto BeforeRet_;$n", [])
-  var statesCounter = lastOrd(p.config, n.sons[0].typ)
+  var statesCounter = lastOrd(p.config, n[0].typ)
   if n.len >= 2 and n[1].kind == nkIntLit:
     statesCounter = getInt(n[1])
   let prefix = if n.len == 3 and n[2].kind == nkStrLit: n[2].strVal.rope
                else: rope"STATE"
-  for i in 0i64 .. toInt64(statesCounter):
+  for i in 0i64..toInt64(statesCounter):
     lineF(p, cpsStmts, "case $2: goto $1$2;$n", [prefix, rope(i)])
   lineF(p, cpsStmts, "}$n", [])
 
@@ -257,11 +256,11 @@ proc genBreakState(p: BProc, n: PNode, d: var TLoc) =
   var a: TLoc
   initLoc(d, locExpr, n, OnUnknown)
 
-  if n.sons[0].kind == nkClosure:
-    initLocExpr(p, n.sons[0].sons[1], a)
+  if n[0].kind == nkClosure:
+    initLocExpr(p, n[0][1], a)
     d.r = "(((NI*) $1)[1] < 0)" % [rdLoc(a)]
   else:
-    initLocExpr(p, n.sons[0], a)
+    initLocExpr(p, n[0], a)
     # the environment is guaranteed to contain the 'state' field at offset 1:
     d.r = "((((NI*) $1.ClE_0)[1]) < 0)" % [rdLoc(a)]
 
@@ -322,12 +321,12 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
       if value.kind in nkCallKinds and value[0].kind == nkSym and
            sfConstructor in value[0].sym.flags:
         var params: Rope
-        let typ = skipTypes(value.sons[0].typ, abstractInst)
+        let typ = skipTypes(value[0].typ, abstractInst)
         assert(typ.kind == tyProc)
         for i in 1..<value.len:
           if params != nil: params.add(~", ")
-          assert(len(typ) == len(typ.n))
-          add(params, genOtherArg(p, value, i, typ))
+          assert(typ.len == typ.n.len)
+          params.add(genOtherArg(p, value, i, typ))
         if params == nil:
           lineF(p, cpsStmts, "$#;$n", [decl])
         else:
@@ -368,15 +367,15 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
 proc genSingleVar(p: BProc, a: PNode) =
   let v = a[0].sym
   if sfCompileTime in v.flags: return
-  genSingleVar(p, v, a[0], a.sons[2])
+  genSingleVar(p, v, a[0], a[2])
 
 proc genClosureVar(p: BProc, a: PNode) =
-  var immediateAsgn = a.sons[2].kind != nkEmpty
+  var immediateAsgn = a[2].kind != nkEmpty
   var v: TLoc
-  initLocExpr(p, a.sons[0], v)
+  initLocExpr(p, a[0], v)
   genLineDir(p, a)
   if immediateAsgn:
-    loadInto(p, a.sons[0], a.sons[2], v)
+    loadInto(p, a[0], a[2], v)
   else:
     constructLoc(p, v)
 
@@ -385,7 +384,7 @@ proc genVarStmt(p: BProc, n: PNode) =
     if it.kind == nkCommentStmt: continue
     if it.kind == nkIdentDefs:
       # can be a lifted var nowadays ...
-      if it.sons[0].kind == nkSym:
+      if it[0].kind == nkSym:
         genSingleVar(p, it)
       else:
         genClosureVar(p, it)
@@ -416,53 +415,53 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
     if d.k == locTemp and isEmptyType(n.typ): d.k = locNone
     if it.len == 2:
       startBlock(p)
-      initLocExprSingleUse(p, it.sons[0], a)
+      initLocExprSingleUse(p, it[0], a)
       lelse = getLabel(p)
       inc(p.labels)
       lineF(p, cpsStmts, "if (!$1) goto $2;$n",
             [rdLoc(a), lelse])
       if p.module.compileToCpp:
         # avoid "jump to label crosses initialization" error:
-        add(p.s(cpsStmts), "{")
-        expr(p, it.sons[1], d)
-        add(p.s(cpsStmts), "}")
+        p.s(cpsStmts).add "{"
+        expr(p, it[1], d)
+        p.s(cpsStmts).add "}"
       else:
-        expr(p, it.sons[1], d)
+        expr(p, it[1], d)
       endBlock(p)
-      if len(n) > 1:
+      if n.len > 1:
         lineF(p, cpsStmts, "goto $1;$n", [lend])
       fixLabel(p, lelse)
     elif it.len == 1:
       startBlock(p)
-      expr(p, it.sons[0], d)
+      expr(p, it[0], d)
       endBlock(p)
     else: internalError(p.config, n.info, "genIf()")
-  if len(n) > 1: fixLabel(p, lend)
+  if n.len > 1: fixLabel(p, lend)
 
 proc genReturnStmt(p: BProc, t: PNode) =
   if nfPreventCg in t.flags: return
   p.beforeRetNeeded = true
   genLineDir(p, t)
-  if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
+  if (t[0].kind != nkEmpty): genStmts(p, t[0])
   blockLeaveActions(p,
     howManyTrys    = p.nestedTryStmts.len,
     howManyExcepts = p.inExceptBlockLen)
   if (p.finallySafePoints.len > 0) and not p.noSafePoints:
     # 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]
+    var safePoint = p.finallySafePoints[^1]
     linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", [safePoint])
   lineF(p, cpsStmts, "goto BeforeRet_;$n", [])
 
 proc genGotoForCase(p: BProc; caseStmt: PNode) =
-  for i in 1 ..< caseStmt.len:
+  for i in 1..<caseStmt.len:
     startBlock(p)
-    let it = caseStmt.sons[i]
-    for j in 0 .. it.len-2:
-      if it.sons[j].kind == nkRange:
+    let it = caseStmt[i]
+    for j in 0..<it.len-1:
+      if it[j].kind == nkRange:
         localError(p.config, it.info, "range notation not available for computed goto")
         return
-      let val = getOrdValue(it.sons[j])
+      let val = getOrdValue(it[j])
       lineF(p, cpsStmts, "NIMSTATE_$#:$n", [val.rope])
     genStmts(p, it.lastSon)
     endBlock(p)
@@ -473,7 +472,7 @@ iterator fieldValuePairs(n: PNode): tuple[memberSym, valueSym: PNode] =
   for identDefs in n:
     if identDefs.kind == nkIdentDefs:
       let valueSym = identDefs[^1]
-      for i in 0 ..< identDefs.len-2:
+      for i in 0..<identDefs.len-2:
         let memberSym = identDefs[i]
         yield((memberSym: memberSym, valueSym: valueSym))
 
@@ -481,22 +480,22 @@ proc genComputedGoto(p: BProc; n: PNode) =
   # first pass: Generate array of computed labels:
   var casePos = -1
   var arraySize: int
-  for i in 0 ..< n.len:
-    let it = n.sons[i]
+  for i in 0..<n.len:
+    let it = n[i]
     if it.kind == nkCaseStmt:
       if lastSon(it).kind != nkOfBranch:
         localError(p.config, it.info,
             "case statement must be exhaustive for computed goto"); return
       casePos = i
-      if enumHasHoles(it.sons[0].typ):
+      if enumHasHoles(it[0].typ):
         localError(p.config, it.info,
             "case statement cannot work on enums with holes for computed goto"); return
-      let aSize = lengthOrd(p.config, it.sons[0].typ)
+      let aSize = lengthOrd(p.config, it[0].typ)
       if aSize > 10_000:
         localError(p.config, it.info,
             "case statement has too many cases for computed goto"); return
       arraySize = toInt(aSize)
-      if firstOrd(p.config, it.sons[0].typ) != 0:
+      if firstOrd(p.config, it[0].typ) != 0:
         localError(p.config, it.info,
             "case statement has to start at 0 for computed goto"); return
   if casePos < 0:
@@ -510,54 +509,54 @@ proc genComputedGoto(p: BProc; n: PNode) =
   gotoArray.addf("&&TMP$#_};$n", [rope(id+arraySize)])
   line(p, cpsLocals, gotoArray)
 
-  for j in 0 ..< casePos:
-    genStmts(p, n.sons[j])
+  for j in 0..<casePos:
+    genStmts(p, n[j])
 
-  let caseStmt = n.sons[casePos]
+  let caseStmt = n[casePos]
   var a: TLoc
-  initLocExpr(p, caseStmt.sons[0], a)
+  initLocExpr(p, caseStmt[0], a)
   # first goto:
   lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc])
 
-  for i in 1 ..< caseStmt.len:
+  for i in 1..<caseStmt.len:
     startBlock(p)
-    let it = caseStmt.sons[i]
-    for j in 0 .. it.len-2:
-      if it.sons[j].kind == nkRange:
+    let it = caseStmt[i]
+    for j in 0..<it.len-1:
+      if it[j].kind == nkRange:
         localError(p.config, it.info, "range notation not available for computed goto")
         return
 
-      let val = getOrdValue(it.sons[j])
+      let val = getOrdValue(it[j])
       lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(toInt64(val)+id+1)])
 
     genStmts(p, it.lastSon)
 
-    for j in casePos+1 ..< n.sons.len:
-      genStmts(p, n.sons[j])
+    for j in casePos+1..<n.len:
+      genStmts(p, n[j])
 
-    for j in 0 ..< casePos:
+    for j in 0..<casePos:
       # prevent new local declarations
       # compile declarations as assignments
-      let it = n.sons[j]
+      let it = n[j]
       if it.kind in {nkLetSection, nkVarSection}:
         let asgn = copyNode(it)
         asgn.kind = nkAsgn
         asgn.sons.setLen 2
         for sym, value in it.fieldValuePairs:
           if value.kind != nkEmpty:
-            asgn.sons[0] = sym
-            asgn.sons[1] = value
+            asgn[0] = sym
+            asgn[1] = value
             genStmts(p, asgn)
       else:
         genStmts(p, it)
 
     var a: TLoc
-    initLocExpr(p, caseStmt.sons[0], a)
+    initLocExpr(p, caseStmt[0], a)
     lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc])
     endBlock(p)
 
-  for j in casePos+1 ..< n.sons.len:
-    genStmts(p, n.sons[j])
+  for j in casePos+1..<n.len:
+    genStmts(p, n[j])
 
 
 proc genWhileStmt(p: BProc, t: PNode) =
@@ -565,23 +564,23 @@ proc genWhileStmt(p: BProc, t: PNode) =
   # significantly worse code
   var
     a: TLoc
-  assert(len(t) == 2)
+  assert(t.len == 2)
   inc(p.withinLoop)
   genLineDir(p, t)
 
   preserveBreakIdx:
-    var loopBody = t.sons[1]
+    var loopBody = t[1]
     if loopBody.stmtsContainPragma(wComputedGoto) and
        hasComputedGoto in CC[p.config.cCompiler].props:
          # for closure support weird loop bodies are generated:
-      if loopBody.len == 2 and loopBody.sons[0].kind == nkEmpty:
-        loopBody = loopBody.sons[1]
+      if loopBody.len == 2 and loopBody[0].kind == nkEmpty:
+        loopBody = loopBody[1]
       genComputedGoto(p, loopBody)
     else:
       p.breakIdx = startBlock(p, "while (1) {$n")
       p.blocks[p.breakIdx].isLoop = true
-      initLocExpr(p, t.sons[0], a)
-      if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
+      initLocExpr(p, t[0], a)
+      if (t[0].kind != nkIntLit) or (t[0].intVal == 0):
         let label = assignLabel(p.blocks[p.breakIdx])
         lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
       genStmts(p, loopBody)
@@ -602,30 +601,30 @@ proc genBlock(p: BProc, n: PNode, d: var TLoc) =
     d.flags.incl(lfEnforceDeref)
   preserveBreakIdx:
     p.breakIdx = startBlock(p)
-    if n.sons[0].kind != nkEmpty:
+    if n[0].kind != nkEmpty:
       # named block?
-      assert(n.sons[0].kind == nkSym)
-      var sym = n.sons[0].sym
+      assert(n[0].kind == nkSym)
+      var sym = n[0].sym
       sym.loc.k = locOther
       sym.position = p.breakIdx+1
-    expr(p, n.sons[1], d)
+    expr(p, n[1], d)
     endBlock(p)
 
 proc genParForStmt(p: BProc, t: PNode) =
-  assert(len(t) == 3)
+  assert(t.len == 3)
   inc(p.withinLoop)
   genLineDir(p, t)
 
   preserveBreakIdx:
-    let forLoopVar = t.sons[0].sym
+    let forLoopVar = t[0].sym
     var rangeA, rangeB: TLoc
-    assignLocalVar(p, t.sons[0])
+    assignLocalVar(p, t[0])
     #initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
     #discard mangleName(forLoopVar)
-    let call = t.sons[1]
-    assert(len(call) in {4, 5})
-    initLocExpr(p, call.sons[1], rangeA)
-    initLocExpr(p, call.sons[2], rangeB)
+    let call = t[1]
+    assert(call.len in {4, 5})
+    initLocExpr(p, call[1], rangeA)
+    initLocExpr(p, call[2], rangeB)
 
     # $n at the beginning because of #9710
     if call.len == 4: # `||`(a, b, annotation)
@@ -633,29 +632,29 @@ proc genParForStmt(p: BProc, t: PNode) =
                           "for ($1 = $2; $1 <= $3; ++$1)",
                           [forLoopVar.loc.rdLoc,
                           rangeA.rdLoc, rangeB.rdLoc,
-                          call.sons[3].getStr.rope])
+                          call[3].getStr.rope])
     else: # `||`(a, b, step, annotation)
       var step: TLoc
-      initLocExpr(p, call.sons[3], step)
+      initLocExpr(p, call[3], step)
       lineF(p, cpsStmts, "$n#pragma omp $5$n" &
                     "for ($1 = $2; $1 <= $3; $1 += $4)",
                     [forLoopVar.loc.rdLoc,
                     rangeA.rdLoc, rangeB.rdLoc, step.rdLoc,
-                    call.sons[4].getStr.rope])
+                    call[4].getStr.rope])
 
     p.breakIdx = startBlock(p)
     p.blocks[p.breakIdx].isLoop = true
-    genStmts(p, t.sons[2])
+    genStmts(p, t[2])
     endBlock(p)
 
   dec(p.withinLoop)
 
 proc genBreakStmt(p: BProc, t: PNode) =
   var idx = p.breakIdx
-  if t.sons[0].kind != nkEmpty:
+  if t[0].kind != nkEmpty:
     # named break?
-    assert(t.sons[0].kind == nkSym)
-    var sym = t.sons[0].sym
+    assert(t[0].kind == nkSym)
+    var sym = t[0].sym
     doAssert(sym.loc.k == locOther)
     idx = sym.position-1
   else:
@@ -704,17 +703,15 @@ proc genRaiseStmt(p: BProc, t: PNode) =
 
 template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
                           rangeFormat, eqFormat: FormatStr, labl: TLabel) =
-  var
-    x, y: TLoc
-  var length = len(b)
-  for i in 0 .. length - 2:
-    if b.sons[i].kind == nkRange:
-      initLocExpr(p, b.sons[i].sons[0], x)
-      initLocExpr(p, b.sons[i].sons[1], y)
+  var x, y: TLoc
+  for i in 0..<b.len - 1:
+    if b[i].kind == nkRange:
+      initLocExpr(p, b[i][0], x)
+      initLocExpr(p, b[i][1], y)
       lineCg(p, cpsStmts, rangeFormat,
            [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
     else:
-      initLocExpr(p, b.sons[i], x)
+      initLocExpr(p, b[i], x)
       lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
 
 proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
@@ -724,12 +721,11 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
     # bug #4230: avoid false sharing between branches:
     if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
     lineF(p, cpsStmts, "LA$1_: ;$n", [rope(labId + i)])
-    if t.sons[i].kind == nkOfBranch:
-      var length = len(t.sons[i])
-      exprBlock(p, t.sons[i].sons[length - 1], d)
+    if t[i].kind == nkOfBranch:
+      exprBlock(p, t[i][^1], d)
       lineF(p, cpsStmts, "goto $1;$n", [lend])
     else:
-      exprBlock(p, t.sons[i].sons[0], d)
+      exprBlock(p, t[i][0], d)
   result = lend
 
 template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
@@ -740,8 +736,8 @@ template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
   var labId = p.labels
   for i in 1..until:
     inc(p.labels)
-    if t.sons[i].kind == nkOfBranch: # else statement
-      genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
+    if t[i].kind == nkOfBranch: # else statement
+      genCaseGenericBranch(p, t[i], a, rangeFormat, eqFormat,
                            "LA" & rope(p.labels) & "_")
     else:
       lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
@@ -758,38 +754,37 @@ template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
 template genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
                     rangeFormat, eqFormat: FormatStr) =
   var a: TLoc
-  initLocExpr(p, t.sons[0], a)
-  var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, len(t)-1, a)
+  initLocExpr(p, t[0], a)
+  var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, t.len-1, a)
   fixLabel(p, lend)
 
 proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
                          branches: var openArray[Rope]) =
   var x: TLoc
-  var length = len(b)
-  for i in 0 .. length - 2:
-    assert(b.sons[i].kind != nkRange)
-    initLocExpr(p, b.sons[i], x)
-    assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit})
-    var j = int(hashString(p.config, b.sons[i].strVal) and high(branches))
+  for i in 0..<b.len - 1:
+    assert(b[i].kind != nkRange)
+    initLocExpr(p, b[i], x)
+    assert(b[i].kind in {nkStrLit..nkTripleStrLit})
+    var j = int(hashString(p.config, b[i].strVal) and high(branches))
     appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n",
          [rdLoc(e), rdLoc(x), labl])
 
 proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
   # count how many constant strings there are in the case:
   var strings = 0
-  for i in 1 ..< len(t):
-    if t.sons[i].kind == nkOfBranch: inc(strings, len(t.sons[i]) - 1)
+  for i in 1..<t.len:
+    if t[i].kind == nkOfBranch: inc(strings, t[i].len - 1)
   if strings > stringCaseThreshold:
     var bitMask = math.nextPowerOfTwo(strings) - 1
     var branches: seq[Rope]
     newSeq(branches, bitMask + 1)
     var a: TLoc
-    initLocExpr(p, t.sons[0], a) # fist pass: generate ifs+goto:
+    initLocExpr(p, t[0], a) # fist pass: generate ifs+goto:
     var labId = p.labels
-    for i in 1 ..< len(t):
+    for i in 1..<t.len:
       inc(p.labels)
-      if t.sons[i].kind == nkOfBranch:
-        genCaseStringBranch(p, t.sons[i], a, "LA" & rope(p.labels) & "_",
+      if t[i].kind == nkOfBranch:
+        genCaseStringBranch(p, t[i], a, "LA" & rope(p.labels) & "_",
                             branches)
       else:
         # else statement: nothing to do yet
@@ -797,28 +792,28 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
         discard
     linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
             [rdLoc(a), bitMask])
-    for j in 0 .. high(branches):
+    for j in 0..high(branches):
       if branches[j] != nil:
         lineF(p, cpsStmts, "case $1: $n$2break;$n",
              [intLiteral(j), branches[j]])
     lineF(p, cpsStmts, "}$n", []) # else statement:
-    if t.sons[len(t)-1].kind != nkOfBranch:
+    if t[^1].kind != nkOfBranch:
       lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
     # third pass: generate statements
-    var lend = genCaseSecondPass(p, t, d, labId, len(t)-1)
+    var lend = genCaseSecondPass(p, t, d, labId, t.len-1)
     fixLabel(p, lend)
   else:
     genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n")
 
 proc branchHasTooBigRange(b: PNode): bool =
-  for i in 0 .. len(b)-2:
+  for i in 0..<b.len-1:
     # last son is block
-    if (b.sons[i].kind == nkRange) and
-        b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit:
+    if (b[i].kind == nkRange) and
+        b[i][1].intVal - b[i][0].intVal > RangeExpandLimit:
       return true
 
 proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
-  for i in 1..n.len-1:
+  for i in 1..<n.len:
     var branch = n[i]
     var stmtBlock = lastSon(branch)
     if stmtBlock.stmtsContainPragma(wLinearScanEnd):
@@ -828,8 +823,7 @@ proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
         result = i
 
 proc genCaseRange(p: BProc, branch: PNode) =
-  var length = branch.len
-  for j in 0 .. length-2:
+  for j in 0..<branch.len-1:
     if branch[j].kind == nkRange:
       if hasSwitchRange in CC[p.config.cCompiler].props:
         lineF(p, cpsStmts, "case $1 ... $2:$n", [
@@ -849,7 +843,7 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
 
   # generate if part (might be empty):
   var a: TLoc
-  initLocExpr(p, n.sons[0], a)
+  initLocExpr(p, n[0], a)
   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",
@@ -859,7 +853,7 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
   if splitPoint+1 < n.len:
     lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)])
     var hasDefault = false
-    for i in splitPoint+1 ..< n.len:
+    for i in splitPoint+1..<n.len:
       # bug #4230: avoid false sharing between branches:
       if d.k == locTemp and isEmptyType(n.typ): d.k = locNone
       var branch = n[i]
@@ -880,14 +874,14 @@ proc genCase(p: BProc, t: PNode, d: var TLoc) =
   genLineDir(p, t)
   if not isEmptyType(t.typ) and d.k == locNone:
     getTemp(p, t.typ, d)
-  case skipTypes(t.sons[0].typ, abstractVarRange).kind
+  case skipTypes(t[0].typ, abstractVarRange).kind
   of tyString:
     genStringCase(p, t, d)
   of tyFloat..tyFloat128:
     genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n",
                             "if ($1 == $2) goto $3;$n")
   else:
-    if t.sons[0].kind == nkSym and sfGoto in t.sons[0].sym.flags:
+    if t[0].kind == nkSym and sfGoto in t[0].sym.flags:
       genGotoForCase(p, t)
     else:
       genOrdinalCase(p, t, d)
@@ -926,7 +920,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
   genLineDir(p, t)
   discard cgsym(p.module, "popCurrentExceptionEx")
   let fin = if t[^1].kind == nkFinally: t[^1] else: nil
-  add(p.nestedTryStmts, (fin, false))
+  p.nestedTryStmts.add((fin, false))
   startBlock(p, "try {$n")
   expr(p, t[0], d)
   endBlock(p)
@@ -947,7 +941,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
       genExceptBranchBody(t[i][0])
       endBlock(p)
     else:
-      for j in 0..t[i].len-2:
+      for j in 0..<t[i].len-1:
         if t[i][j].isInfixAs():
           let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
           fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnUnknown)
@@ -1023,40 +1017,38 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
     else:
       linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
     startBlock(p, "if ($1.status == 0) {$n", [safePoint])
-  let length = len(t)
   let fin = if t[^1].kind == nkFinally: t[^1] else: nil
-  add(p.nestedTryStmts, (fin, quirkyExceptions))
-  expr(p, t.sons[0], d)
+  p.nestedTryStmts.add((fin, quirkyExceptions))
+  expr(p, t[0], d)
   if not quirkyExceptions:
     linefmt(p, cpsStmts, "#popSafePoint();$n", [])
     endBlock(p)
     startBlock(p, "else {$n")
     linefmt(p, cpsStmts, "#popSafePoint();$n", [])
     genRestoreFrameAfterException(p)
-  elif 1 < length and t.sons[1].kind == nkExceptBranch:
+  elif 1 < t.len and t[1].kind == nkExceptBranch:
     startBlock(p, "if (#getCurrentException()) {$n")
   else:
     startBlock(p)
   p.nestedTryStmts[^1].inExcept = true
   var i = 1
-  while (i < length) and (t.sons[i].kind == nkExceptBranch):
+  while (i < t.len) and (t[i].kind == nkExceptBranch):
     # bug #4230: avoid false sharing between branches:
     if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
-    var blen = len(t.sons[i])
-    if blen == 1:
+    if t[i].len == 1:
       # general except section:
       if i > 1: lineF(p, cpsStmts, "else", [])
       startBlock(p)
       if not quirkyExceptions:
         linefmt(p, cpsStmts, "$1.status = 0;$n", [safePoint])
-      expr(p, t.sons[i].sons[0], d)
+      expr(p, t[i][0], d)
       linefmt(p, cpsStmts, "#popCurrentException();$n", [])
       endBlock(p)
     else:
       var orExpr: Rope = nil
-      for j in 0 .. blen - 2:
-        assert(t.sons[i].sons[j].kind == nkType)
-        if orExpr != nil: add(orExpr, "||")
+      for j in 0..<t[i].len - 1:
+        assert(t[i][j].kind == nkType)
+        if orExpr != nil: orExpr.add("||")
         let checkFor = if optTinyRtti in p.config.globalOptions:
           genTypeInfo2Name(p.module, t[i][j].typ)
         else:
@@ -1068,15 +1060,15 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
       startBlock(p, "if ($1) {$n", [orExpr])
       if not quirkyExceptions:
         linefmt(p, cpsStmts, "$1.status = 0;$n", [safePoint])
-      expr(p, t.sons[i].sons[blen-1], d)
+      expr(p, t[i][^1], d)
       linefmt(p, cpsStmts, "#popCurrentException();$n", [])
       endBlock(p)
     inc(i)
   discard pop(p.nestedTryStmts)
   endBlock(p) # end of else block
-  if i < length and t.sons[i].kind == nkFinally:
+  if i < t.len and t[i].kind == nkFinally:
     p.finallySafePoints.add(safePoint)
-    genSimpleBlock(p, t.sons[i].sons[0])
+    genSimpleBlock(p, t[i][0])
     discard pop(p.finallySafePoints)
   if not quirkyExceptions:
     linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
@@ -1120,12 +1112,12 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
         if x[j] in {'"', ':'}:
           # don't modify the line if already in quotes or
           # some clobber register list:
-          add(result, x); add(result, "\L")
+          result.add(x); result.add("\L")
         else:
           # ignore empty lines
-          add(result, "\"")
-          add(result, x)
-          add(result, "\\n\"\n")
+          result.add("\"")
+          result.add(x)
+          result.add("\\n\"\n")
   else:
     res.add("\L")
     result = res.rope
@@ -1139,25 +1131,25 @@ proc genAsmStmt(p: BProc, t: PNode) =
   # work:
   if p.prc == nil:
     # top level asm statement?
-    add(p.module.s[cfsProcHeaders], runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s]))
+    p.module.s[cfsProcHeaders].add runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s])
   else:
-    add(p.s(cpsStmts), indentLine(p, runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s])))
+    p.s(cpsStmts).add indentLine(p, runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s]))
 
 proc determineSection(n: PNode): TCFileSection =
   result = cfsProcHeaders
-  if n.len >= 1 and n.sons[0].kind in {nkStrLit..nkTripleStrLit}:
-    let sec = n.sons[0].strVal
+  if n.len >= 1 and n[0].kind in {nkStrLit..nkTripleStrLit}:
+    let sec = n[0].strVal
     if sec.startsWith("/*TYPESECTION*/"): result = cfsTypes
     elif sec.startsWith("/*VARSECTION*/"): result = cfsVars
     elif sec.startsWith("/*INCLUDESECTION*/"): result = cfsHeaders
 
 proc genEmit(p: BProc, t: PNode) =
-  var s = genAsmOrEmitStmt(p, t.sons[1])
+  var s = genAsmOrEmitStmt(p, t[1])
   if p.prc == nil:
     # top level emit pragma?
     let section = determineSection(t[1])
     genCLineDir(p.module.s[section], t.info, p.config)
-    add(p.module.s[section], s)
+    p.module.s[section].add(s)
   else:
     genLineDir(p, t)
     line(p, cpsStmts, s)
@@ -1169,18 +1161,18 @@ proc genPragma(p: BProc, n: PNode) =
     of wInjectStmt:
       var p = newProc(nil, p.module)
       p.options = p.options - {optLineTrace, optStackTrace}
-      genStmts(p, it.sons[1])
+      genStmts(p, it[1])
       p.module.injectStmt = p.s(cpsStmts)
     else: discard
 
 proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
   if optFieldCheck in p.options:
-    var le = asgn.sons[0]
+    var le = asgn[0]
     if le.kind == nkCheckedFieldExpr:
-      var field = le.sons[0].sons[1].sym
+      var field = le[0][1].sym
       result = sfDiscriminant in field.flags
     elif le.kind == nkDotExpr:
-      var field = le.sons[1].sym
+      var field = le[1].sym
       result = sfDiscriminant in field.flags
 
 proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
@@ -1188,14 +1180,13 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
   var t = skipTypes(objtype, abstractVar)
   assert t.kind == tyObject
   discard genTypeInfo(p.module, t, a.lode.info)
-  var L = toInt64(lengthOrd(p.config, field.typ))
   if not containsOrIncl(p.module.declaredThings, field.id):
     appcg(p.module, cfsVars, "extern $1",
           [discriminatorTableDecl(p.module, t, field)])
   lineCg(p, cpsStmts,
         "#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
         [rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
-         intLiteral(L+1)])
+         intLiteral(toInt64(lengthOrd(p.config, field.typ))+1)])
 
 proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLoc) =
   const ObjDiscMappingProcSlot = -5
@@ -1214,12 +1205,12 @@ proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLo
 
 proc asgnFieldDiscriminant(p: BProc, e: PNode) =
   var a, tmp: TLoc
-  var dotExpr = e.sons[0]
-  if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr.sons[0]
-  initLocExpr(p, e.sons[0], a)
+  var dotExpr = e[0]
+  if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr[0]
+  initLocExpr(p, e[0], a)
   getTemp(p, a.t, tmp)
-  expr(p, e.sons[1], tmp)
-  let field = dotExpr.sons[1].sym
+  expr(p, e[1], tmp)
+  let field = dotExpr[1].sym
   if optTinyRtti in p.config.globalOptions:
     let t = dotExpr[0].typ.skipTypes(abstractInst)
     var oldVal, newVal: TLoc
@@ -1229,13 +1220,13 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
           "#nimFieldDiscriminantCheckV2($1, $2);$n",
           [rdLoc(oldVal), rdLoc(newVal)])
   else:
-    genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, field)
+    genDiscriminantCheck(p, a, tmp, dotExpr[0].typ, field)
   genAssignment(p, a, tmp, {})
 
 proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
-  if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags:
+  if e[0].kind == nkSym and sfGoto in e[0].sym.flags:
     genLineDir(p, e)
-    genGotoVar(p, e.sons[1])
+    genGotoVar(p, e[1])
   elif not fieldDiscriminantCheckNeeded(p, e):
     let le = e[0]
     let ri = e[1]