summary refs log tree commit diff stats
path: root/compiler/vmgen.nim
diff options
context:
space:
mode:
authorClyybber <darkmine956@gmail.com>2019-11-28 17:13:04 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-11-28 17:13:04 +0100
commit7e747d11c66405f08cc7c69e5afc18348663275e (patch)
treed6277a88b503ddd503d8b769bdae6c72fcf3d27b /compiler/vmgen.nim
parentb662842bd04852a751993ed506f9e38155a4e4aa (diff)
downloadNim-7e747d11c66405f08cc7c69e5afc18348663275e.tar.gz
Cosmetic compiler cleanup (#12718)
* Cleanup compiler code base

* Unify add calls

* Unify len invocations

* Unify range operators

* Fix oversight

* Remove {.procvar.} pragma

* initCandidate -> newCandidate where reasonable

* Unify safeLen calls
Diffstat (limited to 'compiler/vmgen.nim')
-rw-r--r--compiler/vmgen.nim518
1 files changed, 256 insertions, 262 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 668c496c6..17e9f8de3 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -16,7 +16,7 @@
 #   types that use the 'node' field; the reason is that slots are
 #   re-used in a register based VM. Example:
 #
-# .. code-block:: nim
+#..code-block:: nim
 #   let s = a & b  # no matter what, create fresh node
 #   s = a & b  # no matter what, keep the node
 #
@@ -207,14 +207,14 @@ proc getFreeRegister(cc: PCtx; k: TSlotKind; start: int): TRegister =
   # we prefer the same slot kind here for efficiency. Unfortunately for
   # discardable return types we may not know the desired type. This can happen
   # for e.g. mNAdd[Multiple]:
-  for i in start .. c.maxSlots-1:
+  for i in start..c.maxSlots-1:
     if c.slots[i].kind == k and not c.slots[i].inUse:
       c.slots[i].inUse = true
       return TRegister(i)
 
   # if register pressure is high, we re-use more aggressively:
   if c.maxSlots >= high(TRegister):
-    for i in start .. c.maxSlots-1:
+    for i in start..c.maxSlots-1:
       if not c.slots[i].inUse:
         c.slots[i] = (inUse: true, kind: k)
         return TRegister(i)
@@ -248,22 +248,22 @@ proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister =
   # if register pressure is high, we re-use more aggressively:
   let c = cc.prc
   if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister):
-    for i in 0 .. c.maxSlots-n:
+    for i in 0..c.maxSlots-n:
       if not c.slots[i].inUse:
         block search:
-          for j in i+1 .. i+n-1:
+          for j in i+1..i+n-1:
             if c.slots[j].inUse: break search
           result = TRegister(i)
-          for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
+          for k in result..result+n-1: c.slots[k] = (inUse: true, kind: kind)
           return
   if c.maxSlots+n >= high(TRegister):
     globalError(cc.config, cc.bestEffort, "VM problem: too many registers required")
   result = TRegister(c.maxSlots)
   inc c.maxSlots, n
-  for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
+  for k in result..result+n-1: c.slots[k] = (inUse: true, kind: kind)
 
 proc freeTempRange(c: PCtx; start: TRegister, n: int) =
-  for i in start .. start+n-1: c.freeTemp(TRegister(i))
+  for i in start..start+n-1: c.freeTemp(TRegister(i))
 
 template withTemp(tmp, typ, body: untyped) {.dirty.} =
   var tmp = getTemp(c, typ)
@@ -309,8 +309,8 @@ proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} =
     dest = -1
 
 proc isNotOpr(n: PNode): bool =
-  n.kind in nkCallKinds and n.sons[0].kind == nkSym and
-    n.sons[0].sym.magic == mNot
+  n.kind in nkCallKinds and n[0].kind == nkSym and
+    n[0].sym.magic == mNot
 
 proc isTrue(n: PNode): bool =
   n.kind == nkSym and n.sym.kind == skEnumField and n.sym.position != 0 or
@@ -325,30 +325,30 @@ proc genWhile(c: PCtx; n: PNode) =
   # lab2:
   let lab1 = c.genLabel
   withBlock(nil):
-    if isTrue(n.sons[0]):
-      c.gen(n.sons[1])
+    if isTrue(n[0]):
+      c.gen(n[1])
       c.jmpBack(n, lab1)
-    elif isNotOpr(n.sons[0]):
-      var tmp = c.genx(n.sons[0].sons[1])
+    elif isNotOpr(n[0]):
+      var tmp = c.genx(n[0][1])
       let lab2 = c.xjmp(n, opcTJmp, tmp)
       c.freeTemp(tmp)
-      c.gen(n.sons[1])
+      c.gen(n[1])
       c.jmpBack(n, lab1)
       c.patch(lab2)
     else:
-      var tmp = c.genx(n.sons[0])
+      var tmp = c.genx(n[0])
       let lab2 = c.xjmp(n, opcFJmp, tmp)
       c.freeTemp(tmp)
-      c.gen(n.sons[1])
+      c.gen(n[1])
       c.jmpBack(n, lab1)
       c.patch(lab2)
 
 proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
   let oldRegisterCount = c.prc.maxSlots
-  withBlock(n.sons[0].sym):
-    c.gen(n.sons[1], dest)
+  withBlock(n[0].sym):
+    c.gen(n[1], dest)
 
-  for i in oldRegisterCount ..< c.prc.maxSlots:
+  for i in oldRegisterCount..<c.prc.maxSlots:
     #if c.prc.slots[i].kind in {slotFixedVar, slotFixedLet}:
     if i != dest:
       when not defined(release):
@@ -364,10 +364,10 @@ proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
 
 proc genBreak(c: PCtx; n: PNode) =
   let lab1 = c.xjmp(n, opcJmp)
-  if n.sons[0].kind == nkSym:
-    #echo cast[int](n.sons[0].sym)
+  if n[0].kind == nkSym:
+    #echo cast[int](n[0].sym)
     for i in countdown(c.prc.blocks.len-1, 0):
-      if c.prc.blocks[i].label == n.sons[0].sym:
+      if c.prc.blocks[i].label == n[0].sym:
         c.prc.blocks[i].fixups.add lab1
         return
     globalError(c.config, n.info, "VM problem: cannot find 'break' target")
@@ -387,25 +387,25 @@ proc genIf(c: PCtx, n: PNode; dest: var TDest) =
   #  Lend:
   if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
   var endings: seq[TPosition] = @[]
-  for i in 0 ..< len(n):
-    var it = n.sons[i]
+  for i in 0..<n.len:
+    var it = n[i]
     if it.len == 2:
-      withTemp(tmp, it.sons[0].typ):
+      withTemp(tmp, it[0].typ):
         var elsePos: TPosition
-        if isNotOpr(it.sons[0]):
-          c.gen(it.sons[0].sons[1], tmp)
-          elsePos = c.xjmp(it.sons[0].sons[1], opcTJmp, tmp) # if true
+        if isNotOpr(it[0]):
+          c.gen(it[0][1], tmp)
+          elsePos = c.xjmp(it[0][1], opcTJmp, tmp) # if true
         else:
-          c.gen(it.sons[0], tmp)
-          elsePos = c.xjmp(it.sons[0], opcFJmp, tmp) # if false
+          c.gen(it[0], tmp)
+          elsePos = c.xjmp(it[0], opcFJmp, tmp) # if false
       c.clearDest(n, dest)
-      c.gen(it.sons[1], dest) # then part
-      if i < len(n)-1:
-        endings.add(c.xjmp(it.sons[1], opcJmp, 0))
+      c.gen(it[1], dest) # then part
+      if i < n.len-1:
+        endings.add(c.xjmp(it[1], opcJmp, 0))
       c.patch(elsePos)
     else:
       c.clearDest(n, dest)
-      c.gen(it.sons[0], dest)
+      c.gen(it[0], dest)
   for endPos in endings: c.patch(endPos)
   c.clearDest(n, dest)
 
@@ -422,9 +422,9 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
               getTemp(c, n.typ)
             else:
               TRegister dest
-  c.gen(n.sons[1], tmp)
+  c.gen(n[1], tmp)
   let lab1 = c.xjmp(n, opc, tmp)
-  c.gen(n.sons[2], tmp)
+  c.gen(n[2], tmp)
   c.patch(lab1)
   if dest < 0:
     dest = tmp
@@ -456,14 +456,14 @@ proc sameConstant*(a, b: PNode): bool =
     of nkType, nkNilLit: result = a.typ == b.typ
     of nkEmpty: result = true
     else:
-      if len(a) == len(b):
-        for i in 0 ..< len(a):
-          if not sameConstant(a.sons[i], b.sons[i]): return
+      if a.len == b.len:
+        for i in 0..<a.len:
+          if not sameConstant(a[i], b[i]): return
         result = true
 
 proc genLiteral(c: PCtx; n: PNode): int =
   # types do not matter here:
-  for i in 0 ..< c.constants.len:
+  for i in 0..<c.constants.len:
     if sameConstant(c.constants[i], n): return i
   result = rawGenLiteral(c, n)
 
@@ -488,21 +488,21 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) =
   else:
     unused(c, n, dest)
   var endings: seq[TPosition] = @[]
-  withTemp(tmp, n.sons[0].typ):
-    c.gen(n.sons[0], tmp)
+  withTemp(tmp, n[0].typ):
+    c.gen(n[0], tmp)
     # branch tmp, codeIdx
     # fjmp   elseLabel
-    for i in 1 ..< n.len:
-      let it = n.sons[i]
+    for i in 1..<n.len:
+      let it = n[i]
       if it.len == 1:
         # else stmt:
-        c.gen(it.sons[0], dest)
+        c.gen(it[0], dest)
       else:
         let b = rawGenLiteral(c, it)
         c.gABx(it, opcBranch, tmp, b)
         let elsePos = c.xjmp(it.lastSon, opcFJmp, tmp)
         c.gen(it.lastSon, dest)
-        if i < len(n)-1:
+        if i < n.len-1:
           endings.add(c.xjmp(it.lastSon, opcJmp, 0))
         c.patch(elsePos)
       c.clearDest(n, dest)
@@ -519,28 +519,27 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
   if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
   var endings: seq[TPosition] = @[]
   let ehPos = c.xjmp(n, opcTry, 0)
-  c.gen(n.sons[0], dest)
+  c.gen(n[0], dest)
   c.clearDest(n, dest)
   # Add a jump past the exception handling code
   let jumpToFinally = c.xjmp(n, opcJmp, 0)
   # This signals where the body ends and where the exception handling begins
   c.patch(ehPos)
-  for i in 1 ..< n.len:
-    let it = n.sons[i]
+  for i in 1..<n.len:
+    let it = n[i]
     if it.kind != nkFinally:
-      var blen = len(it)
       # first opcExcept contains the end label of the 'except' block:
       let endExcept = c.xjmp(it, opcExcept, 0)
-      for j in 0 .. blen - 2:
-        assert(it.sons[j].kind == nkType)
-        let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
+      for j in 0..<it.len - 1:
+        assert(it[j].kind == nkType)
+        let typ = it[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
         c.gABx(it, opcExcept, 0, c.genType(typ))
-      if blen == 1:
+      if it.len == 1:
         # general except section:
         c.gABx(it, opcExcept, 0, 0)
       c.gen(it.lastSon, dest)
       c.clearDest(n, dest)
-      if i < len(n):
+      if i < n.len:
         endings.add(c.xjmp(it, opcJmp, 0))
       c.patch(endExcept)
   let fin = lastSon(n)
@@ -550,18 +549,18 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
   c.gABx(fin, opcFinally, 0, 0)
   for endPos in endings: c.patch(endPos)
   if fin.kind == nkFinally:
-    c.gen(fin.sons[0])
+    c.gen(fin[0])
     c.clearDest(n, dest)
   c.gABx(fin, opcFinallyEnd, 0, 0)
 
 proc genRaise(c: PCtx; n: PNode) =
-  let dest = genx(c, n.sons[0])
+  let dest = genx(c, n[0])
   c.gABC(n, opcRaise, dest)
   c.freeTemp(dest)
 
 proc genReturn(c: PCtx; n: PNode) =
-  if n.sons[0].kind != nkEmpty:
-    gen(c, n.sons[0])
+  if n[0].kind != nkEmpty:
+    gen(c, n[0])
   c.gABC(n, opcRet)
 
 
@@ -585,16 +584,16 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
   if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
   let x = c.getTempRange(n.len, slotTempUnknown)
   # varargs need 'opcSetType' for the FFI support:
-  let fntyp = skipTypes(n.sons[0].typ, abstractInst)
+  let fntyp = skipTypes(n[0].typ, abstractInst)
   for i in 0..<n.len:
-    #if i > 0 and i < len(fntyp):
-    #  let paramType = fntyp.n.sons[i]
+    #if i > 0 and i < fntyp.len:
+    #  let paramType = fntyp.n[i]
     #  if paramType.typ.isCompileTimeOnly: continue
     var r: TRegister = x+i
-    c.gen(n.sons[i], r, {gfIsParam})
+    c.gen(n[i], r, {gfIsParam})
     if i >= fntyp.len:
       internalAssert c.config, tfVarargs in fntyp.flags
-      c.gABx(n, opcSetType, r, c.genType(n.sons[i].typ))
+      c.gABx(n, opcSetType, r, c.genType(n[i].typ))
   if dest < 0:
     c.gABC(n, opcIndCall, 0, x, n.len)
   else:
@@ -633,24 +632,24 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
 proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
   case le.kind
   of nkBracketExpr:
-    let dest = c.genx(le.sons[0], {gfNode})
-    let idx = c.genIndex(le.sons[1], le.sons[0].typ)
+    let dest = c.genx(le[0], {gfNode})
+    let idx = c.genIndex(le[1], le[0].typ)
     c.gABC(le, opcWrArr, dest, idx, value)
     c.freeTemp(dest)
     c.freeTemp(idx)
   of nkCheckedFieldExpr:
     var objR: TDest = -1
     genCheckedObjAccessAux(c, le, objR, {gfNode})
-    let idx = genField(c, le[0].sons[1])
+    let idx = genField(c, le[0][1])
     c.gABC(le[0], opcWrObj, objR, idx, value)
     c.freeTemp(objR)
   of nkDotExpr:
-    let dest = c.genx(le.sons[0], {gfNode})
-    let idx = genField(c, le.sons[1])
+    let dest = c.genx(le[0], {gfNode})
+    let idx = genField(c, le[1])
     c.gABC(le, opcWrObj, dest, idx, value)
     c.freeTemp(dest)
   of nkDerefExpr, nkHiddenDeref:
-    let dest = c.genx(le.sons[0], {gfNode})
+    let dest = c.genx(le[0], {gfNode})
     c.gABC(le, opcWrDeref, dest, 0, value)
     c.freeTemp(dest)
   of nkSym:
@@ -662,30 +661,30 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
     discard
 
 proc genNew(c: PCtx; n: PNode) =
-  let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
-             else: c.genx(n.sons[1])
+  let dest = if needsAsgnPatch(n[1]): c.getTemp(n[1].typ)
+             else: c.genx(n[1])
   # we use the ref's base type here as the VM conflates 'ref object'
   # and 'object' since internally we already have a pointer.
   c.gABx(n, opcNew, dest,
-         c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
-  c.genAsgnPatch(n.sons[1], dest)
+         c.genType(n[1].typ.skipTypes(abstractVar-{tyTypeDesc})[0]))
+  c.genAsgnPatch(n[1], dest)
   c.freeTemp(dest)
 
 proc genNewSeq(c: PCtx; n: PNode) =
-  let t = n.sons[1].typ
-  let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(t)
-             else: c.genx(n.sons[1])
-  let tmp = c.genx(n.sons[2])
+  let t = n[1].typ
+  let dest = if needsAsgnPatch(n[1]): c.getTemp(t)
+             else: c.genx(n[1])
+  let tmp = c.genx(n[2])
   c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
                                                   abstractVar-{tyTypeDesc})))
   c.gABx(n, opcNewSeq, tmp, 0)
   c.freeTemp(tmp)
-  c.genAsgnPatch(n.sons[1], dest)
+  c.genAsgnPatch(n[1], dest)
   c.freeTemp(dest)
 
 proc genNewSeqOfCap(c: PCtx; n: PNode; dest: var TDest) =
   let t = n.typ
-  let tmp = c.getTemp(n.sons[1].typ)
+  let tmp = c.getTemp(n[1].typ)
   c.gABx(n, opcLdNull, dest, c.genType(t))
   c.gABx(n, opcLdImmInt, tmp, 0)
   c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
@@ -694,13 +693,13 @@ proc genNewSeqOfCap(c: PCtx; n: PNode; dest: var TDest) =
   c.freeTemp(tmp)
 
 proc genUnaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
-  let tmp = c.genx(n.sons[1])
+  let tmp = c.genx(n[1])
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABC(n, opc, dest, tmp)
   c.freeTemp(tmp)
 
 proc genUnaryABI(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; imm: BiggestInt=0) =
-  let tmp = c.genx(n.sons[1])
+  let tmp = c.genx(n[1])
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABI(n, opc, dest, tmp, imm)
   c.freeTemp(tmp)
@@ -708,8 +707,8 @@ proc genUnaryABI(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; imm: BiggestI
 
 proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   let
-    tmp = c.genx(n.sons[1])
-    tmp2 = c.genx(n.sons[2])
+    tmp = c.genx(n[1])
+    tmp2 = c.genx(n[2])
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABC(n, opc, dest, tmp, tmp2)
   c.freeTemp(tmp)
@@ -717,9 +716,9 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
 
 proc genBinaryABCD(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   let
-    tmp = c.genx(n.sons[1])
-    tmp2 = c.genx(n.sons[2])
-    tmp3 = c.genx(n.sons[3])
+    tmp = c.genx(n[1])
+    tmp2 = c.genx(n[2])
+    tmp3 = c.genx(n[3])
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABC(n, opc, dest, tmp, tmp2)
   c.gABC(n, opc, tmp3)
@@ -759,45 +758,45 @@ proc genSetType(c: PCtx; n: PNode; dest: TRegister) =
 
 proc genBinarySet(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   let
-    tmp = c.genx(n.sons[1])
-    tmp2 = c.genx(n.sons[2])
+    tmp = c.genx(n[1])
+    tmp2 = c.genx(n[2])
   if dest < 0: dest = c.getTemp(n.typ)
-  c.genSetType(n.sons[1], tmp)
-  c.genSetType(n.sons[2], tmp2)
+  c.genSetType(n[1], tmp)
+  c.genSetType(n[2], tmp2)
   c.gABC(n, opc, dest, tmp, tmp2)
   c.freeTemp(tmp)
   c.freeTemp(tmp2)
 
 proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
   let
-    dest = c.genx(n.sons[1])
-    tmp = c.genx(n.sons[2])
+    dest = c.genx(n[1])
+    tmp = c.genx(n[2])
   c.gABC(n, opc, dest, tmp, 0)
   c.freeTemp(tmp)
   c.freeTemp(dest)
 
 proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
-  var x = n.sons[1]
-  if x.kind in {nkAddr, nkHiddenAddr}: x = x.sons[0]
+  var x = n[1]
+  if x.kind in {nkAddr, nkHiddenAddr}: x = x[0]
   let
     dest = c.genx(x)
-    tmp = c.genx(n.sons[2])
+    tmp = c.genx(n[2])
   c.gABC(n, opc, dest, tmp, 0)
-  #c.genAsgnPatch(n.sons[1], dest)
+  #c.genAsgnPatch(n[1], dest)
   c.freeTemp(tmp)
   c.freeTemp(dest)
 
 proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
-  let tmp = c.genx(n.sons[1])
+  let tmp = c.genx(n[1])
   c.gABC(n, opc, tmp, 0, 0)
   c.freeTemp(tmp)
 
 proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   if dest < 0: dest = getTemp(c, n.typ)
   var x = c.getTempRange(n.len-1, slotTempStr)
-  for i in 1..n.len-1:
+  for i in 1..<n.len:
     var r: TRegister = x+i-1
-    c.gen(n.sons[i], r)
+    c.gen(n[i], r)
   c.gABC(n, opc, dest, x, n.len-1)
   c.freeTempRange(x, n.len)
 
@@ -810,10 +809,10 @@ proc isInt16Lit(n: PNode): bool =
     result = n.intVal >= low(int16) and n.intVal <= high(int16)
 
 proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
-  if n.sons[2].isInt8Lit:
-    let tmp = c.genx(n.sons[1])
+  if n[2].isInt8Lit:
+    let tmp = c.genx(n[1])
     if dest < 0: dest = c.getTemp(n.typ)
-    c.gABI(n, succ(opc), dest, tmp, n.sons[2].intVal)
+    c.gABI(n, succ(opc), dest, tmp, n[2].intVal)
     c.freeTemp(tmp)
   else:
     genBinaryABC(c, n, dest, opc)
@@ -832,9 +831,9 @@ proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
   c.freeTemp(tmp)
 
 proc genCard(c: PCtx; n: PNode; dest: var TDest) =
-  let tmp = c.genx(n.sons[1])
+  let tmp = c.genx(n[1])
   if dest < 0: dest = c.getTemp(n.typ)
-  c.genSetType(n.sons[1], tmp)
+  c.genSetType(n[1], tmp)
   c.gABC(n, opcCard, dest, tmp)
   c.freeTemp(tmp)
 
@@ -842,12 +841,12 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
   const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar}
   var signedIntegers = {tyInt..tyInt64}
   var unsignedIntegers = {tyUInt..tyUInt64, tyChar}
-  let src = n.sons[1].typ.skipTypes(abstractRange)#.kind
-  let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind
+  let src = n[1].typ.skipTypes(abstractRange)#.kind
+  let dst = n[0].typ.skipTypes(abstractRange)#.kind
   let srcSize = getSize(c.config, src)
   let dstSize = getSize(c.config, dst)
   if src.kind in allowedIntegers and dst.kind in allowedIntegers:
-    let tmp = c.genx(n.sons[1])
+    let tmp = c.genx(n[1])
     if dest < 0: dest = c.getTemp(n[0].typ)
     c.gABC(n, opcAsgnInt, dest, tmp)
     if dstSize != sizeof(BiggestInt): # don't do anything on biggest int types
@@ -919,20 +918,20 @@ proc genBindSym(c: PCtx; n: PNode; dest: var TDest) =
 
     # callee symbol
     var tmp0 = TDest(x)
-    c.genLit(n.sons[0], tmp0)
+    c.genLit(n[0], tmp0)
 
     # original parameters
     for i in 1..<n.len-2:
       var r = TRegister(x+i)
-      c.gen(n.sons[i], r)
+      c.gen(n[i], r)
 
     # info node
     var tmp1 = TDest(x+n.len-2)
-    c.genLit(n.sons[^2], tmp1)
+    c.genLit(n[^2], tmp1)
 
     # payload idx
     var tmp2 = TDest(x+n.len-1)
-    c.genLit(n.sons[^1], tmp2)
+    c.genLit(n[^1], tmp2)
 
     c.gABC(n, opcNDynBindSym, dest, x, n.len)
     c.freeTempRange(x, n.len)
@@ -962,7 +961,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mAnd: c.genAndOr(n, opcFJmp, dest)
   of mOr:  c.genAndOr(n, opcTJmp, dest)
   of mUnaryLt:
-    let tmp = c.genx(n.sons[1])
+    let tmp = c.genx(n[1])
     if dest < 0: dest = c.getTemp(n.typ)
     c.gABI(n, opcSubImmInt, dest, tmp, 1)
     c.freeTemp(tmp)
@@ -972,22 +971,22 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     c.genAddSubInt(n, dest, opcAddInt)
   of mInc, mDec:
     unused(c, n, dest)
-    let isUnsigned = n.sons[1].typ.skipTypes(abstractVarRange).kind in {tyUInt..tyUInt64}
+    let isUnsigned = n[1].typ.skipTypes(abstractVarRange).kind in {tyUInt..tyUInt64}
     let opc = if not isUnsigned:
                 if m == mInc: opcAddInt else: opcSubInt
               else:
                 if m == mInc: opcAddu else: opcSubu
-    let d = c.genx(n.sons[1])
-    if n.sons[2].isInt8Lit and not isUnsigned:
-      c.gABI(n, succ(opc), d, d, n.sons[2].intVal)
+    let d = c.genx(n[1])
+    if n[2].isInt8Lit and not isUnsigned:
+      c.gABI(n, succ(opc), d, d, n[2].intVal)
     else:
-      let tmp = c.genx(n.sons[2])
+      let tmp = c.genx(n[2])
       c.gABC(n, opc, d, d, tmp)
       c.freeTemp(tmp)
-    c.genNarrow(n.sons[1], d)
-    c.genAsgnPatch(n.sons[1], d)
+    c.genNarrow(n[1], d)
+    c.genAsgnPatch(n[1], d)
     c.freeTemp(d)
-  of mOrd, mChr, mArrToSeq, mUnown: c.gen(n.sons[1], dest)
+  of mOrd, mChr, mArrToSeq, mUnown: c.gen(n[1], dest)
   of mNew, mNewFinalize:
     unused(c, n, dest)
     c.genNew(n)
@@ -1000,9 +999,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     # XXX buggy
   of mNewStringOfCap:
     # we ignore the 'cap' argument and translate it as 'newString(0)'.
-    # eval n.sons[1] for possible side effects:
-    c.freeTemp(c.genx(n.sons[1]))
-    var tmp = c.getTemp(n.sons[1].typ)
+    # eval n[1] for possible side effects:
+    c.freeTemp(c.genx(n[1]))
+    var tmp = c.getTemp(n[1].typ)
     c.gABx(n, opcLdImmInt, tmp, 0)
     if dest < 0: dest = c.getTemp(n.typ)
     c.gABC(n, opcNewStr, dest, tmp)
@@ -1014,9 +1013,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     genUnaryABI(c, n, dest, opcLenStr)
   of mIncl, mExcl:
     unused(c, n, dest)
-    var d = c.genx(n.sons[1])
-    var tmp = c.genx(n.sons[2])
-    c.genSetType(n.sons[1], d)
+    var d = c.genx(n[1])
+    var tmp = c.genx(n[2])
+    c.genSetType(n[1], d)
     c.gABC(n, if m == mIncl: opcIncl else: opcExcl, d, tmp)
     c.freeTemp(d)
     c.freeTemp(tmp)
@@ -1031,9 +1030,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mShrI:
     # modified: genBinaryABC(c, n, dest, opcShrInt)
     # narrowU is applied to the left operandthe idea here is to narrow the left operand
-    let tmp = c.genx(n.sons[1])
+    let tmp = c.genx(n[1])
     c.genNarrowU(n, tmp)
-    let tmp2 = c.genx(n.sons[2])
+    let tmp2 = c.genx(n[2])
     if dest < 0: dest = c.getTemp(n.typ)
     c.gABC(n, opcShrInt, dest, tmp, tmp2)
     c.freeTemp(tmp)
@@ -1074,7 +1073,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     genUnaryABC(c, n, dest, opcUnaryMinusInt)
     genNarrow(c, n, dest)
   of mUnaryMinusF64: genUnaryABC(c, n, dest, opcUnaryMinusFloat)
-  of mUnaryPlusI, mUnaryPlusF64: gen(c, n.sons[1], dest)
+  of mUnaryPlusI, mUnaryPlusF64: gen(c, n[1], dest)
   of mBitnotI:
     genUnaryABC(c, n, dest, opcBitnotInt)
     #genNarrowU modified, do not narrow signed types
@@ -1083,7 +1082,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
       c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
   of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
      mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
-    genConv(c, n, n.sons[1], dest)
+    genConv(c, n, n[1], dest)
   of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
   of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
   of mLtStr: genBinaryABC(c, n, dest, opcLtStr)
@@ -1099,15 +1098,15 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mRepr: genUnaryABC(c, n, dest, opcRepr)
   of mExit:
     unused(c, n, dest)
-    var tmp = c.genx(n.sons[1])
+    var tmp = c.genx(n[1])
     c.gABC(n, opcQuit, tmp)
     c.freeTemp(tmp)
   of mSetLengthStr, mSetLengthSeq:
     unused(c, n, dest)
-    var d = c.genx(n.sons[1])
-    var tmp = c.genx(n.sons[2])
+    var d = c.genx(n[1])
+    var tmp = c.genx(n[2])
     c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
-    c.genAsgnPatch(n.sons[1], d)
+    c.genAsgnPatch(n[1], d)
     c.freeTemp(tmp)
     c.freeTemp(d)
   of mSwap:
@@ -1117,9 +1116,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mCopyStr:
     if dest < 0: dest = c.getTemp(n.typ)
     var
-      tmp1 = c.genx(n.sons[1])
-      tmp2 = c.genx(n.sons[2])
-      tmp3 = c.getTemp(n.sons[2].typ)
+      tmp1 = c.genx(n[1])
+      tmp2 = c.genx(n[2])
+      tmp3 = c.getTemp(n[2].typ)
     c.gABC(n, opcLenStr, tmp3, tmp1)
     c.gABC(n, opcSubStr, dest, tmp1, tmp2)
     c.gABC(n, opcSubStr, tmp3)
@@ -1129,9 +1128,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mCopyStrLast:
     if dest < 0: dest = c.getTemp(n.typ)
     var
-      tmp1 = c.genx(n.sons[1])
-      tmp2 = c.genx(n.sons[2])
-      tmp3 = c.genx(n.sons[3])
+      tmp1 = c.genx(n[1])
+      tmp2 = c.genx(n[2])
+      tmp3 = c.genx(n[3])
     c.gABC(n, opcSubStr, dest, tmp1, tmp2)
     c.gABC(n, opcSubStr, tmp3)
     c.freeTemp(tmp1)
@@ -1141,14 +1140,14 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     if dest < 0: dest = c.getTemp(n.typ)
     var d2: TRegister
     # skip 'nkHiddenAddr':
-    let d2AsNode = n.sons[2].sons[0]
+    let d2AsNode = n[2][0]
     if needsAsgnPatch(d2AsNode):
       d2 = c.getTemp(getSysType(c.graph, n.info, tyFloat))
     else:
       d2 = c.genx(d2AsNode)
     var
-      tmp1 = c.genx(n.sons[1])
-      tmp3 = c.genx(n.sons[3])
+      tmp1 = c.genx(n[1])
+      tmp3 = c.genx(n[3])
     c.gABC(n, opcParseFloat, dest, tmp1, d2)
     c.gABC(n, opcParseFloat, tmp3)
     c.freeTemp(tmp1)
@@ -1157,19 +1156,19 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     c.freeTemp(d2)
   of mReset:
     unused(c, n, dest)
-    var d = c.genx(n.sons[1])
+    var d = c.genx(n[1])
     # XXX use ldNullOpcode() here?
-    c.gABx(n, opcLdNull, d, c.genType(n.sons[1].typ))
+    c.gABx(n, opcLdNull, d, c.genType(n[1].typ))
     c.gABx(n, opcNodeToReg, d, d)
-    c.genAsgnPatch(n.sons[1], d)
+    c.genAsgnPatch(n[1], d)
   of mDefault:
     if dest < 0: dest = c.getTemp(n.typ)
     c.gABx(n, ldNullOpcode(n.typ), dest, c.genType(n.typ))
   of mOf, mIs:
     if dest < 0: dest = c.getTemp(n.typ)
-    var tmp = c.genx(n.sons[1])
+    var tmp = c.genx(n[1])
     var idx = c.getTemp(getSysType(c.graph, n.info, tyInt))
-    var typ = n.sons[2].typ
+    var typ = n[2].typ
     if m == mOf: typ = typ.skipTypes(abstractPtrs)
     c.gABx(n, opcLdImmInt, idx, c.genType(typ))
     c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
@@ -1177,8 +1176,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     c.freeTemp(idx)
   of mHigh:
     if dest < 0: dest = c.getTemp(n.typ)
-    let tmp = c.genx(n.sons[1])
-    case n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind:
+    let tmp = c.genx(n[1])
+    case n[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind:
     of tyString, tyCString:
       c.gABI(n, opcLenStr, dest, tmp, 1)
     else:
@@ -1192,7 +1191,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
       let x = c.getTempRange(n.len, slotTempUnknown)
       for i in 0..<n.len:
         var r: TRegister = x+i
-        c.gen(n.sons[i], r)
+        c.gen(n[i], r)
       c.gABC(n, opcEcho, x, n.len)
       c.freeTempRange(x, n.len)
   of mAppendStrCh:
@@ -1209,9 +1208,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mParseStmtToAst:
     genUnaryABC(c, n, dest, opcParseStmtToAst)
   of mTypeTrait:
-    let tmp = c.genx(n.sons[1])
+    let tmp = c.genx(n[1])
     if dest < 0: dest = c.getTemp(n.typ)
-    c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ))
+    c.gABx(n, opcSetType, tmp, c.genType(n[1].typ))
     c.gABC(n, opcTypeTrait, dest, tmp)
     c.freeTemp(tmp)
   of mSlurp: genUnaryABC(c, n, dest, opcSlurp)
@@ -1246,7 +1245,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mNSymbol: genUnaryABC(c, n, dest, opcNSymbol)
   of mNIdent: genUnaryABC(c, n, dest, opcNIdent)
   of mNGetType:
-    let tmp = c.genx(n.sons[1])
+    let tmp = c.genx(n[1])
     if dest < 0: dest = c.getTemp(n.typ)
     let rc = case n[0].sym.name.s:
       of "getType": 0
@@ -1323,7 +1322,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   of mExpandToAst:
     if n.len != 2:
       globalError(c.config, n.info, "expandToAst requires 1 argument")
-    let arg = n.sons[1]
+    let arg = n[1]
     if arg.kind in nkCallKinds:
       #if arg[0].kind != nkSym or arg[0].sym.kind notin {skTemplate, skMacro}:
       #      "ExpandToAst: expanded symbol is no macro or template"
@@ -1361,7 +1360,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
 proc genMarshalLoad(c: PCtx, n: PNode, dest: var TDest) =
   ## Signature: proc to*[T](data: string): T
   if dest < 0: dest = c.getTemp(n.typ)
-  var tmp = c.genx(n.sons[1])
+  var tmp = c.genx(n[1])
   c.gABC(n, opcMarshalLoad, dest, tmp)
   c.gABx(n, opcMarshalLoad, 0, c.genType(n.typ))
   c.freeTemp(tmp)
@@ -1369,9 +1368,9 @@ proc genMarshalLoad(c: PCtx, n: PNode, dest: var TDest) =
 proc genMarshalStore(c: PCtx, n: PNode, dest: var TDest) =
   ## Signature: proc `$$`*[T](x: T): string
   if dest < 0: dest = c.getTemp(n.typ)
-  var tmp = c.genx(n.sons[1])
+  var tmp = c.genx(n[1])
   c.gABC(n, opcMarshalStore, dest, tmp)
-  c.gABx(n, opcMarshalStore, 0, c.genType(n.sons[1].typ))
+  c.gABx(n, opcMarshalStore, 0, c.genType(n[1].typ))
   c.freeTemp(tmp)
 
 const
@@ -1391,26 +1390,26 @@ proc unneededIndirection(n: PNode): bool =
   n.typ.skipTypes(abstractInstOwned-{tyTypeDesc}).kind == tyRef
 
 proc canElimAddr(n: PNode): PNode =
-  if n.sons[0].typ.skipTypes(abstractInst).kind in {tyObject, tyTuple, tyArray}:
+  if n[0].typ.skipTypes(abstractInst).kind in {tyObject, tyTuple, tyArray}:
     # objects are reference types in the VM
     return n[0]
-  case n.sons[0].kind
+  case n[0].kind
   of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
-    var m = n.sons[0].sons[0]
+    var m = n[0][0]
     if m.kind in {nkDerefExpr, nkHiddenDeref}:
       # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
-      result = copyNode(n.sons[0])
-      result.add m.sons[0]
+      result = copyNode(n[0])
+      result.add m[0]
   of nkHiddenStdConv, nkHiddenSubConv, nkConv:
-    var m = n.sons[0].sons[1]
+    var m = n[0][1]
     if m.kind in {nkDerefExpr, nkHiddenDeref}:
       # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
-      result = copyNode(n.sons[0])
-      result.add m.sons[0]
+      result = copyNode(n[0])
+      result.add m[0]
   else:
-    if n.sons[0].kind in {nkDerefExpr, nkHiddenDeref}:
+    if n[0].kind in {nkDerefExpr, nkHiddenDeref}:
       # addr ( deref ( x )) --> x
-      result = n.sons[0].sons[0]
+      result = n[0][0]
 
 proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
   if (let m = canElimAddr(n); m != nil):
@@ -1419,11 +1418,11 @@ proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
 
   let newflags = flags-{gfNode}+{gfNodeAddr}
 
-  if isGlobal(n.sons[0]) or n[0].kind in {nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}:
+  if isGlobal(n[0]) or n[0].kind in {nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}:
     # checking for this pattern:  addr(obj.field) / addr(array[i])
-    gen(c, n.sons[0], dest, newflags)
+    gen(c, n[0], dest, newflags)
   else:
-    let tmp = c.genx(n.sons[0], newflags)
+    let tmp = c.genx(n[0], newflags)
     if dest < 0: dest = c.getTemp(n.typ)
     if c.prc.slots[tmp].kind >= slotTempUnknown:
       gABC(c, n, opcAddrNode, dest, tmp)
@@ -1437,12 +1436,12 @@ proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
     c.freeTemp(tmp)
 
 proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
-  if unneededIndirection(n.sons[0]):
-    gen(c, n.sons[0], dest, flags)
+  if unneededIndirection(n[0]):
+    gen(c, n[0], dest, flags)
     if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
       c.gABC(n, opcNodeToReg, dest, dest)
   else:
-    let tmp = c.genx(n.sons[0], flags)
+    let tmp = c.genx(n[0], flags)
     if dest < 0: dest = c.getTemp(n.typ)
     gABC(c, n, opcLdDeref, dest, tmp)
     assert n.typ != nil
@@ -1514,10 +1513,10 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
 proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   case le.kind
   of nkBracketExpr:
-    let dest = c.genx(le.sons[0], {gfNode})
-    let idx = c.genIndex(le.sons[1], le.sons[0].typ)
+    let dest = c.genx(le[0], {gfNode})
+    let idx = c.genIndex(le[1], le[0].typ)
     let tmp = c.genx(ri)
-    if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
+    if le[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
         tyString, tyCString}:
       c.preventFalseAlias(le, opcWrStrIdx, dest, idx, tmp)
     else:
@@ -1528,22 +1527,22 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   of nkCheckedFieldExpr:
     var objR: TDest = -1
     genCheckedObjAccessAux(c, le, objR, {gfNode})
-    let idx = genField(c, le[0].sons[1])
+    let idx = genField(c, le[0][1])
     let tmp = c.genx(ri)
     c.preventFalseAlias(le[0], opcWrObj, objR, idx, tmp)
     c.freeTemp(tmp)
     c.freeTemp(idx)
     c.freeTemp(objR)
   of nkDotExpr:
-    let dest = c.genx(le.sons[0], {gfNode})
-    let idx = genField(c, le.sons[1])
+    let dest = c.genx(le[0], {gfNode})
+    let idx = genField(c, le[1])
     let tmp = c.genx(ri)
     c.preventFalseAlias(le, opcWrObj, dest, idx, tmp)
     c.freeTemp(idx)
     c.freeTemp(tmp)
     c.freeTemp(dest)
   of nkDerefExpr, nkHiddenDeref:
-    let dest = c.genx(le.sons[0], {gfNode})
+    let dest = c.genx(le[0], {gfNode})
     let tmp = c.genx(ri)
     c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp)
     c.freeTemp(dest)
@@ -1584,7 +1583,7 @@ proc importcCond*(s: PSym): bool {.inline.} =
   ## return true to importc `s`, false to execute its body instead (refs #8405)
   if sfImportc in s.flags:
     if s.kind in routineKinds:
-      return s.ast.sons[bodyPos].kind == nkEmpty
+      return s.ast[bodyPos].kind == nkEmpty
 
 proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
   when hasFFI:
@@ -1659,8 +1658,8 @@ template needsRegLoad(): untyped =
 
 proc genArrAccessOpcode(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
                         flags: TGenFlags) =
-  let a = c.genx(n.sons[0], flags)
-  let b = c.genIndex(n.sons[1], n.sons[0].typ)
+  let a = c.genx(n[0], flags)
+  let b = c.genIndex(n[1], n[0].typ)
   if dest < 0: dest = c.getTemp(n.typ)
   if opc == opcLdArr and {gfNodeAddr} * flags != {}:
     c.gABC(n, opcLdArrAddr, dest, a, b)
@@ -1677,8 +1676,8 @@ proc genArrAccessOpcode(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
   c.freeTemp(b)
 
 proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
-  let a = c.genx(n.sons[0], flags)
-  let b = genField(c, n.sons[1])
+  let a = c.genx(n[0], flags)
+  let b = genField(c, n[1])
   if dest < 0: dest = c.getTemp(n.typ)
   if {gfNodeAddr} * flags != {}:
     c.gABC(n, opcLdObjAddr, dest, a, b)
@@ -1750,7 +1749,7 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
   c.freeTemp(objR)
 
 proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
-  let arrayType = n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind
+  let arrayType = n[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind
   if arrayType in {tyString, tyCString}:
     genArrAccessOpcode(c, n, dest, opcLdStrIdx, {})
   elif arrayType == tyTypeDesc:
@@ -1759,21 +1758,21 @@ proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
     genArrAccessOpcode(c, n, dest, opcLdArr, flags)
 
 proc getNullValueAux(t: PType; obj: PNode, result: PNode; conf: ConfigRef; currPosition: var int) =
-  if t != nil and t.len > 0 and t.sons[0] != nil:
-    let b = skipTypes(t.sons[0], skipPtrs)
+  if t != nil and t.len > 0 and t[0] != nil:
+    let b = skipTypes(t[0], skipPtrs)
     getNullValueAux(b, b.n, result, conf, currPosition)
   case obj.kind
   of nkRecList:
-    for i in 0 ..< len(obj): getNullValueAux(nil, obj.sons[i], result, conf, currPosition)
+    for i in 0..<obj.len: getNullValueAux(nil, obj[i], result, conf, currPosition)
   of nkRecCase:
-    getNullValueAux(nil, obj.sons[0], result, conf, currPosition)
-    for i in 1 ..< len(obj):
-      getNullValueAux(nil, lastSon(obj.sons[i]), result, conf, currPosition)
+    getNullValueAux(nil, obj[0], result, conf, currPosition)
+    for i in 1..<obj.len:
+      getNullValueAux(nil, lastSon(obj[i]), result, conf, currPosition)
   of nkSym:
     let field = newNodeI(nkExprColonExpr, result.info)
     field.add(obj)
     field.add(getNullValue(obj.sym.typ, result.info, conf))
-    addSon(result, field)
+    result.add field
     doAssert obj.sym.position == currPosition
     inc currPosition
   else: globalError(conf, result.info, "cannot create null element for: " & $obj)
@@ -1808,12 +1807,12 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
     getNullValueAux(t, t.n, result, conf, currPosition)
   of tyArray:
     result = newNodeIT(nkBracket, info, t)
-    for i in 0 ..< toInt(lengthOrd(conf, t)):
-      addSon(result, getNullValue(elemType(t), info, conf))
+    for i in 0..<toInt(lengthOrd(conf, t)):
+      result.add getNullValue(elemType(t), info, conf)
   of tyTuple:
     result = newNodeIT(nkTupleConstr, info, t)
-    for i in 0 ..< len(t):
-      addSon(result, getNullValue(t.sons[i], info, conf))
+    for i in 0..<t.len:
+      result.add getNullValue(t[i], info, conf)
   of tySet:
     result = newNodeIT(nkCurly, info, t)
   of tyOpt:
@@ -1827,16 +1826,16 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
 proc genVarSection(c: PCtx; n: PNode) =
   for a in n:
     if a.kind == nkCommentStmt: continue
-    #assert(a.sons[0].kind == nkSym) can happen for transformed vars
+    #assert(a[0].kind == nkSym) can happen for transformed vars
     if a.kind == nkVarTuple:
-      for i in 0 .. a.len-3:
+      for i in 0..<a.len-2:
         if a[i].kind == nkSym:
           if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
           checkCanEval(c, a[i])
       c.gen(lowerTupleUnpacking(c.graph, a, c.getOwner))
-    elif a.sons[0].kind == nkSym:
-      let s = a.sons[0].sym
-      checkCanEval(c, a.sons[0])
+    elif a[0].kind == nkSym:
+      let s = a[0].sym
+      checkCanEval(c, a[0])
       if s.isGlobal:
         if s.position == 0:
           if importcCond(s): c.importcSym(a.info, s)
@@ -1847,37 +1846,37 @@ proc genVarSection(c: PCtx; n: PNode) =
             assert sa.kind != nkCall
             c.globals.add(sa)
             s.position = c.globals.len
-        if a.sons[2].kind != nkEmpty:
-          let tmp = c.genx(a.sons[0], {gfNodeAddr})
-          let val = c.genx(a.sons[2])
-          c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val)
+        if a[2].kind != nkEmpty:
+          let tmp = c.genx(a[0], {gfNodeAddr})
+          let val = c.genx(a[2])
+          c.genAdditionalCopy(a[2], opcWrDeref, tmp, 0, val)
           c.freeTemp(val)
           c.freeTemp(tmp)
       else:
         setSlot(c, s)
-        if a.sons[2].kind == nkEmpty:
+        if a[2].kind == nkEmpty:
           c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
         else:
           assert s.typ != nil
           if not fitsRegister(s.typ):
             c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
-          let le = a.sons[0]
+          let le = a[0]
           assert le.typ != nil
           if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}:
             var cc = c.getTemp(le.typ)
-            gen(c, a.sons[2], cc)
+            gen(c, a[2], cc)
             c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc)
             c.freeTemp(cc)
           else:
-            gen(c, a.sons[2], s.position.TRegister)
+            gen(c, a[2], s.position.TRegister)
     else:
-      # assign to a.sons[0]; happens for closures
-      if a.sons[2].kind == nkEmpty:
-        let tmp = genx(c, a.sons[0])
-        c.gABx(a, ldNullOpcode(a[0].typ), tmp, c.genType(a.sons[0].typ))
+      # assign to a[0]; happens for closures
+      if a[2].kind == nkEmpty:
+        let tmp = genx(c, a[0])
+        c.gABx(a, ldNullOpcode(a[0].typ), tmp, c.genType(a[0].typ))
         c.freeTemp(tmp)
       else:
-        genAsgn(c, a.sons[0], a.sons[2], true)
+        genAsgn(c, a[0], a[2], true)
 
 proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
   if dest < 0: dest = c.getTemp(n.typ)
@@ -1907,8 +1906,8 @@ proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
   c.gABx(n, opcLdNull, dest, c.genType(n.typ))
   for x in n:
     if x.kind == nkRange:
-      let a = c.genx(x.sons[0])
-      let b = c.genx(x.sons[1])
+      let a = c.genx(x[0])
+      let b = c.genx(x[1])
       c.gABC(n, opcInclRange, dest, a, b)
       c.freeTemp(b)
       c.freeTemp(a)
@@ -1921,15 +1920,15 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
   if dest < 0: dest = c.getTemp(n.typ)
   let t = n.typ.skipTypes(abstractRange+{tyOwned}-{tyTypeDesc})
   if t.kind == tyRef:
-    c.gABx(n, opcNew, dest, c.genType(t.sons[0]))
+    c.gABx(n, opcNew, dest, c.genType(t[0]))
   else:
     c.gABx(n, opcLdNull, dest, c.genType(n.typ))
   for i in 1..<n.len:
-    let it = n.sons[i]
-    if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
-      let idx = genField(c, it.sons[0])
-      let tmp = c.genx(it.sons[1])
-      c.preventFalseAlias(it.sons[1], opcWrObj,
+    let it = n[i]
+    if it.kind == nkExprColonExpr and it[0].kind == nkSym:
+      let idx = genField(c, it[0])
+      let tmp = c.genx(it[1])
+      c.preventFalseAlias(it[1], opcWrObj,
                           dest, idx, tmp)
       c.freeTemp(tmp)
     else:
@@ -1940,11 +1939,11 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
   c.gABx(n, opcLdNull, dest, c.genType(n.typ))
   # XXX x = (x.old, 22)  produces wrong code ... stupid self assignments
   for i in 0..<n.len:
-    let it = n.sons[i]
+    let it = n[i]
     if it.kind == nkExprColonExpr:
-      let idx = genField(c, it.sons[0])
-      let tmp = c.genx(it.sons[1])
-      c.preventFalseAlias(it.sons[1], opcWrObj,
+      let idx = genField(c, it[0])
+      let tmp = c.genx(it[1])
+      c.preventFalseAlias(it[1], opcWrObj,
                           dest, idx, tmp)
       c.freeTemp(tmp)
     else:
@@ -1957,22 +1956,18 @@ proc genProc*(c: PCtx; s: PSym): int
 proc matches(s: PSym; x: string): bool =
   let y = x.split('.')
   var s = s
-  var L = y.len-1
-  while L >= 0:
-    if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
+  for i in 1..y.len:
+    if s == nil or (y[^i].cmpIgnoreStyle(s.name.s) != 0 and y[^i] != "*"):
       return false
     s = s.owner
-    dec L
   result = true
 
 proc matches(s: PSym; y: varargs[string]): bool =
   var s = s
-  var L = y.len-1
-  while L >= 0:
-    if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
+  for i in 1..y.len:
+    if s == nil or (y[^i].cmpIgnoreStyle(s.name.s) != 0 and y[^i] != "*"):
       return false
     s = if sfFromGeneric in s.flags: s.owner.owner else: s.owner
-    dec L
   result = true
 
 proc procIsCallback(c: PCtx; s: PSym): bool =
@@ -2021,8 +2016,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
     else:
       globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
   of nkCallKinds:
-    if n.sons[0].kind == nkSym:
-      let s = n.sons[0].sym
+    if n[0].kind == nkSym:
+      let s = n[0].sym
       if s.magic != mNone:
         genMagic(c, n, dest, s.magic)
       elif s.kind == skMethod:
@@ -2052,7 +2047,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
     else: unused(c, n, dest)
   of nkAsgn, nkFastAsgn:
     unused(c, n, dest)
-    genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
+    genAsgn(c, n[0], n[1], n.kind == nkAsgn)
   of nkDotExpr: genObjAccess(c, n, dest, flags)
   of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
   of nkBracketExpr: genArrAccess(c, n, dest, flags)
@@ -2061,7 +2056,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   of nkIfStmt, nkIfExpr: genIf(c, n, dest)
   of nkWhenStmt:
     # This is "when nimvm" node. Chose the first branch.
-    gen(c, n.sons[0].sons[1], dest)
+    gen(c, n[0][1], dest)
   of nkCaseStmt: genCase(c, n, dest)
   of nkWhileStmt:
     unused(c, n, dest)
@@ -2081,34 +2076,33 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
     # XXX Fix this bug properly, lexim triggers it
     for x in n: gen(c, x)
   of nkStmtListExpr:
-    let L = n.len-1
-    for i in 0 ..< L: gen(c, n.sons[i])
-    gen(c, n.sons[L], dest, flags)
+    for i in 0..<n.len-1: gen(c, n[i])
+    gen(c, n[^1], dest, flags)
   of nkPragmaBlock:
     gen(c, n.lastSon, dest, flags)
   of nkDiscardStmt:
     unused(c, n, dest)
-    gen(c, n.sons[0])
+    gen(c, n[0])
   of nkHiddenStdConv, nkHiddenSubConv, nkConv:
-    genConv(c, n, n.sons[1], dest)
+    genConv(c, n, n[1], dest)
   of nkObjDownConv:
-    genConv(c, n, n.sons[0], dest)
+    genConv(c, n, n[0], dest)
   of nkObjUpConv:
-    genConv(c, n, n.sons[0], dest)
+    genConv(c, n, n[0], dest)
   of nkVarSection, nkLetSection:
     unused(c, n, dest)
     genVarSection(c, n)
   of declarativeDefs, nkMacroDef:
     unused(c, n, dest)
   of nkLambdaKinds:
-    #let s = n.sons[namePos].sym
+    #let s = n[namePos].sym
     #discard genProc(c, s)
-    genLit(c, newSymNode(n.sons[namePos].sym), dest)
+    genLit(c, newSymNode(n[namePos].sym), dest)
   of nkChckRangeF, nkChckRange64, nkChckRange:
     let
-      tmp0 = c.genx(n.sons[0])
-      tmp1 = c.genx(n.sons[1])
-      tmp2 = c.genx(n.sons[2])
+      tmp0 = c.genx(n[0])
+      tmp1 = c.genx(n[1])
+      tmp2 = c.genx(n[2])
     c.gABC(n, opcRangeChck, tmp0, tmp1, tmp2)
     c.freeTemp(tmp1)
     c.freeTemp(tmp2)
@@ -2121,14 +2115,14 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
      nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt:
     unused(c, n, dest)
   of nkStringToCString, nkCStringToString:
-    gen(c, n.sons[0], dest)
+    gen(c, n[0], dest)
   of nkBracket: genArrayConstr(c, n, dest)
   of nkCurly: genSetConstr(c, n, dest)
   of nkObjConstr: genObjConstr(c, n, dest)
   of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest)
   of nkCast:
     if allowCast in c.features:
-      genConv(c, n, n.sons[1], dest, opcCast)
+      genConv(c, n, n[1], dest, opcCast)
     else:
       genCastIntFloat(c, n, dest)
   of nkTypeOfExpr:
@@ -2186,14 +2180,14 @@ proc finalJumpTarget(c: PCtx; pc, diff: int) =
 proc genGenericParams(c: PCtx; gp: PNode) =
   var base = c.prc.maxSlots
   for i in 0..<gp.len:
-    var param = gp.sons[i].sym
+    var param = gp[i].sym
     param.position = base + i # XXX: fix this earlier; make it consistent with templates
     c.prc.slots[base + i] = (inUse: true, kind: slotFixedLet)
   c.prc.maxSlots = base + gp.len
 
 proc optimizeJumps(c: PCtx; start: int) =
   const maxIterations = 10
-  for i in start ..< c.code.len:
+  for i in start..<c.code.len:
     let opc = c.code[i].opcode
     case opc
     of opcTJmp, opcFJmp:
@@ -2233,7 +2227,7 @@ proc optimizeJumps(c: PCtx; start: int) =
     else: discard
 
 proc genProc(c: PCtx; s: PSym): int =
-  var x = s.ast.sons[miscPos]
+  var x = s.ast[miscPos]
   if x.kind == nkEmpty or x[0].kind == nkEmpty:
     #if s.name.s == "outterMacro" or s.name.s == "innerProc":
     #  echo "GENERATING CODE FOR ", s.name.s
@@ -2248,8 +2242,8 @@ proc genProc(c: PCtx; s: PSym): int =
     if x.kind == nkEmpty:
       x = newTree(nkBracket, newIntNode(nkIntLit, result), x)
     else:
-      x.sons[0] = newIntNode(nkIntLit, result)
-    s.ast.sons[miscPos] = x
+      x[0] = newIntNode(nkIntLit, result)
+    s.ast[miscPos] = x
     # thanks to the jmp we can add top level statements easily and also nest
     # procs easily:
     let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s))
@@ -2265,7 +2259,7 @@ proc genProc(c: PCtx; s: PSym): int =
       genGenericParams(c, s.ast[genericParamsPos])
 
     if tfCapturesEnv in s.typ.flags:
-      #let env = s.ast.sons[paramsPos].lastSon.sym
+      #let env = s.ast[paramsPos].lastSon.sym
       #assert env.position == 2
       c.prc.slots[c.prc.maxSlots] = (inUse: true, kind: slotFixedLet)
       inc c.prc.maxSlots