}
func (p *exporter) nodeList(list Nodes) {
- it := nodeSeqIterate(list)
if p.trace {
p.tracef("[ ")
}
- p.int(it.Len())
+ p.int(list.Len())
if p.trace {
- if it.Len() <= 1 {
+ if list.Len() == 0 {
p.tracef("] {}")
} else {
p.tracef("] {>")
defer p.tracef("<\n}")
}
}
- for ; !it.Done(); it.Next() {
+ for _, n := range list.Slice() {
if p.trace {
p.tracef("\n")
}
- p.node(it.N())
+ p.node(n)
}
}
Bgen(n, wantTrue, 0, p2)
Thearch.Gmove(Nodbool(false), res)
Patch(p3, Pc)
- n.Ninit.Set(init.Slice())
+ n.Ninit.MoveNodes(&init)
}
// bgenx is the backend for Bgen and Bvgen.
// is not going to use a write barrier.
i := 0
var r2 Node
- it := nodeSeqIterate(n.List)
- it.Next()
- for ; !it.Done(); it.Next() {
+ for _, n2 := range n.List.Slice()[1:] {
Regalloc(&r1, Types[Tptr], nil)
Thearch.Gmove(base, &r1)
Regalloc(&r2, Types[TUINT], nil)
r1.Op = OINDREG
r1.Type = res.Type.Type
- cgen_wb(it.N(), &r1, needwritebarrier(&r1, it.N()))
+ cgen_wb(n2, &r1, needwritebarrier(&r1, n2))
Regfree(&r1)
i++
}
declare(n, dclcontext)
n.Name.Defn = defn
defn.Ninit.Append(Nod(ODCL, n, nil))
- left.Slice()[i2] = n
+ left.SetIndex(i2, n)
}
if nnew == 0 && nerr == 0 {
Fatalf("struct expected")
}
- for tp, it := &t.Type, nodeSeqIterate(l); !it.Done(); it.Next() {
- f := structfield(it.N())
-
+ tp := &t.Type
+ for _, n := range l {
+ f := structfield(n)
*tp = f
tp = &f.Down
}
t := typ(TSTRUCT)
t.Funarg = true
- for tp, it := &t.Type, nodeSeqIterate(l); !it.Done(); it.Next() {
- f = structfield(it.N())
+ tp := &t.Type
+ for _, n := range l {
+ f = structfield(n)
f.Funarg = true
// esc.go needs to find f given a PPARAM to add the tag.
- if it.N().Left != nil && it.N().Left.Class == PPARAM {
- it.N().Left.Name.Param.Field = f
+ if n.Left != nil && n.Left.Class == PPARAM {
+ n.Left.Name.Param.Field = f
}
*tp = f
case OAS2: // x,y = a,b
if n.List.Len() == n.Rlist.Len() {
- lrit := nodeSeqIterate(n.Rlist)
- for _, n3 := range n.List.Slice() {
- escassign(e, n3, lrit.N())
- lrit.Next()
+ rs := n.Rlist.Slice()
+ for i, n := range n.List.Slice() {
+ escassign(e, n, rs[i])
}
}
// esccall already done on n->rlist->n. tie it's escretval to n->list
case OAS2FUNC: // x,y = f()
- lrit := nodeSeqIterate(e.nodeEscState(n.Rlist.First()).Escretval)
-
- var llit nodeSeqIterator
- for llit = nodeSeqIterate(n.List); !lrit.Done() && !llit.Done(); llit.Next() {
- escassign(e, llit.N(), lrit.N())
- lrit.Next()
+ rs := e.nodeEscState(n.Rlist.First()).Escretval.Slice()
+ for i, n := range n.List.Slice() {
+ if i >= len(rs) {
+ break
+ }
+ escassign(e, n, rs[i])
}
- if !llit.Done() || !lrit.Done() {
+ if n.List.Len() != len(rs) {
Fatalf("esc oas2func")
}
ll = e.nodeEscState(n.List.First()).Escretval
}
- llit := nodeSeqIterate(ll)
+ i := 0
for _, lrn := range Curfn.Func.Dcl {
- if llit.Done() {
+ if i >= ll.Len() {
break
}
if lrn.Op != ONAME || lrn.Class != PPARAMOUT {
continue
}
- escassign(e, lrn, llit.N())
- llit.Next()
+ escassign(e, lrn, ll.Index(i))
+ i++
}
- if !llit.Done() {
+ if i < ll.Len() {
Fatalf("esc return list")
}
case OAPPEND:
if !n.Isddd {
- llit := nodeSeqIterate(n.List)
- llit.Next()
- for ; !llit.Done(); llit.Next() {
- escassign(e, &e.theSink, llit.N()) // lose track of assign to dereference
+ for _, n := range n.List.Slice()[1:] {
+ escassign(e, &e.theSink, n) // lose track of assign to dereference
}
} else {
// append(slice1, slice2...) -- slice2 itself does not escape, but contents do.
}
em0 := em
- it := nodeSeqIterate(dsts)
- for em >>= EscReturnBits; em != 0 && !it.Done(); em = em >> bitsPerOutputInTag {
+ dstsi := 0
+ for em >>= EscReturnBits; em != 0 && dstsi < dsts.Len(); em = em >> bitsPerOutputInTag {
// Prefer the lowest-level path to the reference (for escape purposes).
// Two-bit encoding (for example. 1, 3, and 4 bits are other options)
// 01 = 0-level
for i := uint16(0); i < embits-1; i++ {
n = e.addDereference(n) // encode level>0 as indirections
}
- escassign(e, it.N(), n)
+ escassign(e, dsts.Index(dstsi), n)
}
- it.Next()
+ dstsi++
}
// If there are too many outputs to fit in the tag,
// that is handled at the encoding end as EscHeap,
// so there is no need to check here.
- if em != 0 && it.Done() {
+ if em != 0 && dstsi >= dsts.Len() {
Fatalf("corrupt esc tag %q or messed up escretval list\n", note)
}
return em0
}
var src *Node
- llit := nodeSeqIterate(ll)
- for lrit := nodeSeqIterate(fn.Name.Param.Ntype.List); !llit.Done() && !lrit.Done(); llit.Next() {
- src = llit.N()
- if lrit.N().Isddd && !n.Isddd {
+ lls := ll.Slice()
+ lrs := fn.Name.Param.Ntype.List.Slice()
+ i := 0
+ for ; i < len(lls) && i < len(lrs); i++ {
+ src = lls[i]
+ if lrs[i].Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil)
src.Type = typ(TARRAY)
- src.Type.Type = lrit.N().Type.Type
- src.Type.Bound = int64(llit.Len())
+ src.Type.Type = lrs[i].Type.Type
+ src.Type.Bound = int64(len(lls) - i)
src.Type = Ptrto(src.Type) // make pointer so it will be tracked
src.Lineno = n.Lineno
e.track(src)
n.Right = src
}
- if lrit.N().Left != nil {
- escassign(e, lrit.N().Left, src)
+ if lrs[i].Left != nil {
+ escassign(e, lrs[i].Left, src)
}
- if src != llit.N() {
+ if src != lls[i] {
break
}
- lrit.Next()
}
// "..." arguments are untracked
- for ; !llit.Done(); llit.Next() {
+ for ; i < len(lls); i++ {
if Debug['m'] > 2 {
- fmt.Printf("%v::esccall:: ... <- %v, untracked\n", linestr(lineno), Nconv(llit.N(), obj.FmtShort))
+ fmt.Printf("%v::esccall:: ... <- %v, untracked\n", linestr(lineno), Nconv(lls[i], obj.FmtShort))
}
- escassign(e, &e.theSink, llit.N())
+ escassign(e, &e.theSink, lls[i])
}
return
}
var src *Node
- it := nodeSeqIterate(ll)
- for t := fntype.Params().Type; !it.Done(); it.Next() {
- src = it.N()
+ i := 0
+ lls := ll.Slice()
+ for t := fntype.Params().Type; i < len(lls); i++ {
+ src = lls[i]
if t.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil)
src.Lineno = n.Lineno
src.Type = typ(TARRAY)
src.Type.Type = t.Type.Type
- src.Type.Bound = int64(it.Len())
+ src.Type.Bound = int64(len(lls) - i)
src.Type = Ptrto(src.Type) // make pointer so it will be tracked
e.track(src)
n.Right = src
}
}
- if src != it.N() {
+ if src != lls[i] {
// This occurs when function parameter type Isddd and n not Isddd
break
}
t = t.Down
}
- for ; !it.Done(); it.Next() {
+ for ; i < len(lls); i++ {
if Debug['m'] > 2 {
- fmt.Printf("%v::esccall:: ... <- %v\n", linestr(lineno), Nconv(it.N(), obj.FmtShort))
+ fmt.Printf("%v::esccall:: ... <- %v\n", linestr(lineno), Nconv(lls[i], obj.FmtShort))
}
- escassign(e, src, it.N()) // args to slice
+ escassign(e, src, lls[i]) // args to slice
}
}
} else {
f += fmt.Sprintf("(%v{", n.Type)
}
- for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
- f += fmt.Sprintf(" %v:%v", Sconv(it.N().Left.Sym, obj.FmtShort|obj.FmtByte), it.N().Right)
+ for i1, n1 := range n.List.Slice() {
+ f += fmt.Sprintf(" %v:%v", Sconv(n1.Left.Sym, obj.FmtShort|obj.FmtByte), n1.Right)
- if it.Len() > 1 {
+ if i1+1 < n.List.Len() {
f += ","
} else {
f += " "
}
var buf bytes.Buffer
- for it := nodeSeqIterate(l); !it.Done(); it.Next() {
- buf.WriteString(Nconv(it.N(), 0))
- if it.Len() > 1 {
+ for i, n := range l.Slice() {
+ buf.WriteString(Nconv(n, 0))
+ if i+1 < l.Len() {
buf.WriteString(sep)
}
}
}
func inlnodelist(l Nodes) {
- for i := range l.Slice() {
- inlnode(&l.Slice()[i])
+ s := l.Slice()
+ for i := range s {
+ inlnode(&s[i])
}
}
fallthrough
default:
- for i3, n3 := range n.List.Slice() {
- if n3.Op == OINLCALL {
- inlconv2expr(&n.List.Slice()[i3])
+ s := n.List.Slice()
+ for i1, n1 := range s {
+ if n1.Op == OINLCALL {
+ inlconv2expr(&s[i1])
}
}
}
fallthrough
default:
- for i4, n4 := range n.Rlist.Slice() {
- if n4.Op == OINLCALL {
+ s := n.Rlist.Slice()
+ for i1, n1 := range s {
+ if n1.Op == OINLCALL {
if n.Op == OIF {
- inlconv2stmt(n4)
+ inlconv2stmt(n1)
} else {
- inlconv2expr(&n.Rlist.Slice()[i4])
+ inlconv2expr(&s[i1])
}
}
}
as = Nod(OAS2, nil, nil)
as.Rlist.Set(n.List.Slice())
- it := nodeSeqIterate(n.List)
+ li := 0
// TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
if fn.Type.Thistuple != 0 && n.Left.Op != ODOTMETH {
Fatalf("method call unknown receiver type: %v", Nconv(n, obj.FmtSign))
}
as.List.Append(tinlvar(t))
- it.Next() // track argument count.
+ li++
}
// append ordinary arguments to LHS.
for t, it2 := IterFields(fn.Type.Params()); t != nil; t = it2.Next() {
if variadic && t.Isddd {
vararg = tinlvar(t)
- for i = 0; i < varargcount && it.Len() != 0; i++ {
+ for i = 0; i < varargcount && li < n.List.Len(); i++ {
m = argvar(varargtype, i)
varargs = append(varargs, m)
as.List.Append(m)
// match arguments except final variadic (unless the call is dotted itself)
var t *Type
for t = fn.Type.Params().Type; t != nil; {
- if it.Done() {
+ if li >= n.List.Len() {
break
}
if variadic && t.Isddd {
}
as.List.Append(tinlvar(t))
t = t.Down
- it.Next()
+ li++
}
// match varargcount arguments with variadic parameters.
if variadic && t != nil && t.Isddd {
vararg = tinlvar(t)
var i int
- for i = 0; i < varargcount && !it.Done(); i++ {
+ for i = 0; i < varargcount && li < n.List.Len(); i++ {
m = argvar(varargtype, i)
varargs = append(varargs, m)
as.List.Append(m)
- it.Next()
+ li++
}
if i == varargcount {
}
}
- if !it.Done() || t != nil {
+ if li < n.List.Len() || t != nil {
Fatalf("arg count mismatch: %v vs %v\n", Tconv(fn.Type.Params(), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
}
}
if n.Op == OCALLFUNC {
t := n.Left.Type.Params().Type
- for it := nodeSeqIterate(n.List); !it.Done() && t != nil; it.Next() {
+ for i := range n.List.Slice() {
// Check for "unsafe-uintptr" tag provided by escape analysis.
// If present and the argument is really a pointer being converted
// to uintptr, arrange for the pointer to be kept alive until the call
// returns, by copying it into a temp and marking that temp
// still alive when we pop the temp stack.
+ if t == nil {
+ break
+ }
if t.Note != nil && *t.Note == unsafeUintptrTag {
- xp := it.P()
+ xp := n.List.Addr(i)
for (*xp).Op == OCONVNOP && !Isptr[(*xp).Type.Etype] {
xp = &(*xp).Left
}
if !istemp(m.Right) {
m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0)
}
- n.List.Slice()[i1] = ordertemp(m.Type, order, false)
- a = Nod(OAS, m, n.List.Slice()[i1])
+ n.List.SetIndex(i1, ordertemp(m.Type, order, false))
+ a = Nod(OAS, m, n.List.Index(i1))
typecheck(&a, Etop)
post = append(post, a)
- } else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Slice()[i1]) {
- m = n.List.Slice()[i1]
- n.List.Slice()[i1] = ordertemp(m.Type, order, false)
- a = Nod(OAS, m, n.List.Slice()[i1])
+ } else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) {
+ m = n.List.Index(i1)
+ t := ordertemp(m.Type, order, false)
+ n.List.SetIndex(i1, t)
+ a = Nod(OAS, m, t)
typecheck(&a, Etop)
post = append(post, a)
}
orderexprlist(n.Left.List, order)
t1 := marktemp(order)
- it := nodeSeqIterate(n.Left.List)
- it.Next()
- np := it.P() // map key
+ np := n.Left.List.Addr(1) // map key
*np = ordercopyexpr(*np, (*np).Type, order, 0)
poptemp(t1, order)
case ODELETE:
t := marktemp(order)
- it := nodeSeqIterate(n.List)
- orderexpr(it.P(), order, nil)
- it.Next()
- orderexpr(it.P(), order, nil)
- orderaddrtemp(it.P(), order) // map key
+ orderexpr(n.List.Addr(0), order, nil)
+ orderexpr(n.List.Addr(1), order, nil)
+ orderaddrtemp(n.List.Addr(1), order) // map key
order.out = append(order.out, n)
cleantemp(t, order)
// n->alloc is the temp for the iterator.
prealloc[n] = ordertemp(Types[TUINT8], order, true)
}
- for i1 := range n.List.Slice() {
- orderexprinplace(&n.List.Slice()[i1], order)
+ for i := range n.List.Slice() {
+ orderexprinplace(n.List.Addr(i), order)
}
orderblockNodes(&n.Nbody)
order.out = append(order.out, n)
Yyerror("unknown op in select %v", Oconv(r.Op, 0))
Dump("select case", r)
- // If this is case x := <-ch or case x, y := <-ch, the case has
+ // If this is case x := <-ch or case x, y := <-ch, the case has
// the ODCL nodes to declare x and y. We want to delay that
// declaration (and possible allocation) until inside the case body.
// Delete the ODCL nodes here and recreate them inside the body below.
case OSELRECV, OSELRECV2:
if r.Colas {
- itinit := nodeSeqIterate(r.Ninit)
- if itinit.Len() != 0 && itinit.N().Op == ODCL && itinit.N().Left == r.Left {
- itinit.Next()
+ i := 0
+ if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
+ i++
}
- if itinit.Len() != 0 && itinit.N().Op == ODCL && r.List.Len() != 0 && itinit.N().Left == r.List.First() {
- itinit.Next()
+ if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
+ i++
}
- if itinit.Done() {
+ if i >= r.Ninit.Len() {
r.Ninit.Set(nil)
}
}
// Orderexprlist orders the expression list l into order.
func orderexprlist(l Nodes, order *Order) {
- for i := range l.Slice() {
- orderexpr(&l.Slice()[i], order, nil)
+ s := l.Slice()
+ for i := range s {
+ orderexpr(&s[i], order, nil)
}
}
// Orderexprlist orders the expression list l but saves
// the side effects on the individual expression ninit lists.
func orderexprlistinplace(l Nodes, order *Order) {
- for i := range l.Slice() {
- orderexprinplace(&l.Slice()[i], order)
+ s := l.Slice()
+ for i := range s {
+ orderexprinplace(&s[i], order)
}
}
}
func instrumentlist(l Nodes, init *Nodes) {
- for i := range l.Slice() {
+ s := l.Slice()
+ for i := range s {
var instr Nodes
- instrumentnode(&l.Slice()[i], &instr, 0, 0)
+ instrumentnode(&s[i], &instr, 0, 0)
if init == nil {
- l.Slice()[i].Ninit.AppendNodes(&instr)
+ s[i].Ninit.AppendNodes(&instr)
} else {
init.AppendNodes(&instr)
}
case OBLOCK:
var out []*Node
- for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
- switch it.N().Op {
+ ls := n.List.Slice()
+ for i := 0; i < len(ls); i++ {
+ switch ls[i].Op {
case OCALLFUNC, OCALLMETH, OCALLINTER:
- instrumentnode(it.P(), &it.N().Ninit, 0, 0)
- out = append(out, it.N())
+ instrumentnode(&ls[i], &ls[i].Ninit, 0, 0)
+ out = append(out, ls[i])
// Scan past OAS nodes copying results off stack.
// Those must not be instrumented, because the
// instrumentation calls will smash the results.
// The assignments are to temporaries, so they cannot
// be involved in races and need not be instrumented.
- for it.Len() > 1 && nodeSeqSecond(it.Seq()).Op == OAS && iscallret(nodeSeqSecond(it.Seq()).Right) {
- it.Next()
- out = append(out, it.N())
+ for i+1 < len(ls) && ls[i+1].Op == OAS && iscallret(ls[i+1].Right) {
+ i++
+ out = append(out, ls[i])
}
default:
var outn Nodes
outn.Set(out)
- instrumentnode(it.P(), &outn, 0, 0)
- out = append(outn.Slice(), it.N())
+ instrumentnode(&ls[i], &outn, 0, 0)
+ out = append(outn.Slice(), ls[i])
}
}
n.List.Set(out)
var t2 *Type
var v1 *Node
var v2 *Node
+ var ls []*Node
// Typechecking order is important here:
// 0. first typecheck range expression (slice/map/chan),
goto out
}
// delicate little dance. see typecheckas2
- for i1, n1 := range n.List.Slice() {
+ ls = n.List.Slice()
+ for i1, n1 := range ls {
if n1.Name == nil || n1.Name.Defn != n {
- typecheck(&n.List.Slice()[i1], Erv|Easgn)
+ typecheck(&ls[i1], Erv|Easgn)
}
}
// second half of dance
out:
n.Typecheck = 1
- for i2, n2 := range n.List.Slice() {
- if n2.Typecheck == 0 {
- typecheck(&n.List.Slice()[i2], Erv|Easgn)
+ ls = n.List.Slice()
+ for i1, n1 := range ls {
+ if n1.Typecheck == 0 {
+ typecheck(&ls[i1], Erv|Easgn)
}
}
if v1 == nil || v2 != nil {
return false
}
- if len(n.Nbody.Slice()) == 0 || n.Nbody.Slice()[0] == nil || len(n.Nbody.Slice()) > 1 {
+ if n.Nbody.Len() == 0 || n.Nbody.First() == nil || n.Nbody.Len() > 1 {
return false
}
- stmt := n.Nbody.Slice()[0] // only stmt in body
+ stmt := n.Nbody.First() // only stmt in body
if stmt.Op != OAS || stmt.Left.Op != OINDEX {
return false
}
} else if ncase.List.Len() > 1 {
Yyerror("select cases cannot be lists")
} else {
- it2 := nodeSeqIterate(ncase.List)
- n = typecheck(it2.P(), Etop)
+ n = typecheck(ncase.List.Addr(0), Etop)
ncase.Left = n
ncase.List.Set(nil)
setlineno(n)
var n *Node
var var_ *Node
var selv *Node
- var cas *Node
if i == 0 {
sel.Nbody.Set([]*Node{mkcall("block", nil, nil)})
goto out
// convert case value arguments to addresses.
// this rewrite is used by both the general code and the next optimization.
- for it := nodeSeqIterate(sel.List); !it.Done(); it.Next() {
- cas = it.N()
+ for _, cas := range sel.List.Slice() {
setlineno(cas)
n = cas.Left
if n == nil {
n.Op = OSELRECV
}
if n.Op == OSELRECV2 {
- it := nodeSeqIterate(n.List)
- *it.P() = Nod(OADDR, it.N(), nil)
- typecheck(it.P(), Erv)
+ n.List.SetIndex(0, Nod(OADDR, n.List.First(), nil))
+ typecheck(n.List.Addr(0), Erv)
}
if n.Left == nil {
typecheck(&r, Etop)
init = append(init, r)
// register cases
- for _, cas = range sel.List.Slice() {
+ for _, cas := range sel.List.Slice() {
setlineno(cas)
n = cas.Left
r = Nod(OIF, nil, nil)
// Evaluate args
args := make([]*ssa.Value, 0, nargs)
store := make([]bool, 0, nargs)
- it := nodeSeqIterate(n.List)
- it.Next()
- for ; !it.Done(); it.Next() {
- if canSSAType(it.N().Type) {
- args = append(args, s.expr(it.N()))
+ for _, n := range n.List.Slice()[1:] {
+ if canSSAType(n.Type) {
+ args = append(args, s.expr(n))
store = append(store, true)
} else {
- args = append(args, s.addr(it.N(), false))
+ args = append(args, s.addr(n, false))
store = append(store, false)
}
}
def = ncase
}
} else {
- for i1, n1 := range ncase.List.Slice() {
+ ls := ncase.List.Slice()
+ for i1, n1 := range ls {
setlineno(n1)
- typecheck(&ncase.List.Slice()[i1], Erv|Etype)
- if ncase.List.Slice()[i1].Type == nil || t == nil {
+ typecheck(&ls[i1], Erv|Etype)
+ n1 = ls[i1]
+ if n1.Type == nil || t == nil {
continue
}
setlineno(ncase)
switch top {
// expression switch
case Erv:
- defaultlit(&ncase.List.Slice()[i1], t)
+ defaultlit(&ls[i1], t)
+ n1 = ls[i1]
switch {
- case ncase.List.Slice()[i1].Op == OTYPE:
- Yyerror("type %v is not an expression", ncase.List.Slice()[i1].Type)
- case ncase.List.Slice()[i1].Type != nil && assignop(ncase.List.Slice()[i1].Type, t, nil) == 0 && assignop(t, ncase.List.Slice()[i1].Type, nil) == 0:
+ case n1.Op == OTYPE:
+ Yyerror("type %v is not an expression", n1.Type)
+ case n1.Type != nil && assignop(n1.Type, t, nil) == 0 && assignop(t, n1.Type, nil) == 0:
if n.Left != nil {
- Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ncase.List.Slice()[i1], n.Left, ncase.List.Slice()[i1].Type, t)
+ Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
} else {
- Yyerror("invalid case %v in switch (mismatched types %v and bool)", ncase.List.Slice()[i1], ncase.List.Slice()[i1].Type)
+ Yyerror("invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
}
- case nilonly != "" && !isnil(ncase.List.Slice()[i1]):
- Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ncase.List.Slice()[i1], nilonly, n.Left)
- case Isinter(t) && !Isinter(ncase.List.Slice()[i1].Type) && algtype1(ncase.List.Slice()[i1].Type, nil) == ANOEQ:
- Yyerror("invalid case %v in switch (incomparable type)", Nconv(ncase.List.Slice()[i1], obj.FmtLong))
+ case nilonly != "" && !isnil(n1):
+ Yyerror("invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
+ case Isinter(t) && !Isinter(n1.Type) && algtype1(n1.Type, nil) == ANOEQ:
+ Yyerror("invalid case %v in switch (incomparable type)", Nconv(n1, obj.FmtLong))
}
// type switch
var missing, have *Type
var ptr int
switch {
- case ncase.List.Slice()[i1].Op == OLITERAL && Istype(ncase.List.Slice()[i1].Type, TNIL):
- case ncase.List.Slice()[i1].Op != OTYPE && ncase.List.Slice()[i1].Type != nil: // should this be ||?
- Yyerror("%v is not a type", Nconv(ncase.List.Slice()[i1], obj.FmtLong))
+ case n1.Op == OLITERAL && Istype(n1.Type, TNIL):
+ case n1.Op != OTYPE && n1.Type != nil: // should this be ||?
+ Yyerror("%v is not a type", Nconv(n1, obj.FmtLong))
// reset to original type
- ncase.List.Slice()[i1] = n.Left.Right
- case ncase.List.Slice()[i1].Type.Etype != TINTER && t.Etype == TINTER && !implements(ncase.List.Slice()[i1].Type, t, &missing, &have, &ptr):
+ n1 = n.Left.Right
+ ls[i1] = n1
+ case n1.Type.Etype != TINTER && t.Etype == TINTER && !implements(n1.Type, t, &missing, &have, &ptr):
if have != nil && !missing.Broke && !have.Broke {
- Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ncase.List.Slice()[i1].Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
+ Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), n1.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
} else if !missing.Broke {
- Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ncase.List.Slice()[i1].Type, missing.Sym)
+ Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), n1.Type, missing.Sym)
}
}
}
}
typecheck(&nvar, Erv|Easgn)
- rit := nodeSeqIterate(ncase.Rlist)
- *rit.P() = nvar
+ ncase.Rlist.SetIndex(0, nvar)
}
}
var def *Node // defaults
br := Nod(OBREAK, nil, nil)
- for it := nodeSeqIterate(sw.List); !it.Done(); it.Next() {
- n := it.N()
+ for i, n := range sw.List.Slice() {
setlineno(n)
if n.Op != OXCASE {
Fatalf("casebody %v", Oconv(n.Op, 0))
Yyerror("cannot fallthrough in type switch")
}
- if it.Len() <= 1 {
+ if i+1 >= sw.List.Len() {
setlineno(last)
Yyerror("cannot fallthrough final case in switch")
}
return len(*n.slice)
}
-// First returns the first element of Nodes.
-// It panics if Nodes has no elements.
+// Index returns the i'th element of Nodes.
+// It panics if n does not have at least i+1 elements.
+func (n *Nodes) Index(i int) *Node {
+ return (*n.slice)[i]
+}
+
+// First returns the first element of Nodes (same as n.Index(0)).
+// It panics if n has no elements.
func (n *Nodes) First() *Node {
return (*n.slice)[0]
}
-// Second returns the second element of Nodes.
-// It panics if Nodes has fewer than two elements.
+// Second returns the second element of Nodes (same as n.Index(1)).
+// It panics if n has fewer than two elements.
func (n *Nodes) Second() *Node {
return (*n.slice)[1]
}
return ret
}
-// Set sets Nodes to a slice.
+// Set sets n to a slice.
// This takes ownership of the slice.
func (n *Nodes) Set(s []*Node) {
if len(s) == 0 {
}
}
+// MoveNodes sets n to the contents of n2, then clears n2.
+func (n *Nodes) MoveNodes(n2 *Nodes) {
+ n.slice = n2.slice
+ n2.slice = nil
+}
+
+// SetIndex sets the i'th element of Nodes to node.
+// It panics if n does not have at least i+1 elements.
+func (n *Nodes) SetIndex(i int, node *Node) {
+ (*n.slice)[i] = node
+}
+
+// Addr returns the address of the i'th element of Nodes.
+// It panics if n does not have at least i+1 elements.
+func (n *Nodes) Addr(i int) **Node {
+ return &(*n.slice)[i]
+}
+
// Append appends entries to Nodes.
// If a slice is passed in, this will take ownership of it.
func (n *Nodes) Append(a ...*Node) {
// to a generic value.
type nodesOrNodeListPtr interface{}
-// nodeSeqIterator is an interface used to iterate over a sequence of nodes.
-// TODO(iant): Remove after conversion from NodeList to Nodes is complete.
-type nodeSeqIterator interface {
- // Return whether iteration is complete.
- Done() bool
- // Advance to the next node.
- Next()
- // Return the current node.
- N() *Node
- // Return the address of the current node.
- P() **Node
- // Return the number of items remaining in the iteration.
- Len() int
- // Return the remaining items as a sequence.
- // This will have the same type as that passed to nodeSeqIterate.
- Seq() nodesOrNodeList
-}
-
-// nodeListIterator is a type that implements nodeSeqIterator using a
-// *NodeList.
-type nodeListIterator struct {
- l *NodeList
-}
-
-func (nli *nodeListIterator) Done() bool {
- return nli.l == nil
-}
-
-func (nli *nodeListIterator) Next() {
- nli.l = nli.l.Next
-}
-
-func (nli *nodeListIterator) N() *Node {
- return nli.l.N
-}
-
-func (nli *nodeListIterator) P() **Node {
- return &nli.l.N
-}
-
-func (nli *nodeListIterator) Len() int {
- return count(nli.l)
-}
-
-func (nli *nodeListIterator) Seq() nodesOrNodeList {
- return nli.l
-}
-
-// nodesIterator implements nodeSeqIterator using a Nodes.
-type nodesIterator struct {
- n Nodes
- i int
-}
-
-func (ni *nodesIterator) Done() bool {
- return ni.i >= len(ni.n.Slice())
-}
-
-func (ni *nodesIterator) Next() {
- ni.i++
-}
-
-func (ni *nodesIterator) N() *Node {
- return ni.n.Slice()[ni.i]
-}
-
-func (ni *nodesIterator) P() **Node {
- return &ni.n.Slice()[ni.i]
-}
-
-func (ni *nodesIterator) Len() int {
- return len(ni.n.Slice()[ni.i:])
-}
-
-func (ni *nodesIterator) Seq() nodesOrNodeList {
- var r Nodes
- r.Set(ni.n.Slice()[ni.i:])
- return r
-}
-
-// nodeSeqIterate returns an iterator over a *NodeList, a Nodes,
-// a []*Node, or nil.
-func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator {
- switch ns := ns.(type) {
- case *NodeList:
- return &nodeListIterator{ns}
- case Nodes:
- return &nodesIterator{ns, 0}
- case []*Node:
- var r Nodes
- r.Set(ns)
- return &nodesIterator{r, 0}
- case nil:
- var r Nodes
- return &nodesIterator{r, 0}
- default:
- panic("can't happen")
- }
-}
-
// nodeSeqLen returns the length of a *NodeList, a Nodes, a []*Node, or nil.
func nodeSeqLen(ns nodesOrNodeList) int {
switch ns := ns.(type) {
}
if n.List.Len() == 1 && !n.Isddd {
- it := nodeSeqIterate(n.List)
- typecheck(it.P(), Erv|Efnstruct)
+ typecheck(n.List.Addr(0), Erv|Efnstruct)
} else {
typechecklist(n.List.Slice(), Erv)
}
return
}
- it := nodeSeqIterate(args)
- it.Next()
- *it.P() = assignconv(r, l.Type.Down, "delete")
+ args.SetIndex(1, assignconv(r, l.Type.Down, "delete"))
break OpSwitch
case OAPPEND:
}
if args.Len() == 1 && !n.Isddd {
- it := nodeSeqIterate(args)
- typecheck(it.P(), Erv|Efnstruct)
+ typecheck(args.Addr(0), Erv|Efnstruct)
} else {
typechecklist(args.Slice(), Erv)
}
}
if Istype(t.Type, TUINT8) && Istype(args.Second().Type, TSTRING) {
- it := nodeSeqIterate(args)
- it.Next()
- defaultlit(it.P(), Types[TSTRING])
+ defaultlit(args.Addr(1), Types[TSTRING])
break OpSwitch
}
- it := nodeSeqIterate(args)
- it.Next()
- *it.P() = assignconv(args.Second(), t.Orig, "append")
+ args.SetIndex(1, assignconv(args.Index(1), t.Orig, "append"))
break OpSwitch
}
}
}
} else {
- it := nodeSeqIterate(args)
- it.Next()
- for ; !it.Done(); it.Next() {
- if it.N().Type == nil {
+ as := args.Slice()[1:]
+ for i, n := range as {
+ if n.Type == nil {
continue
}
- *it.P() = assignconv(it.N(), t.Type, "append")
+ as[i] = assignconv(n, t.Type, "append")
}
}
case OMAKE:
ok |= Erv
- args := nodeSeqIterate(n.List)
- if args.Len() == 0 {
+ args := n.List.Slice()
+ if len(args) == 0 {
Yyerror("missing argument to make")
n.Type = nil
return
}
n.List.Set(nil)
- l := args.N()
- args.Next()
+ l := args[0]
typecheck(&l, Etype)
t := l.Type
if t == nil {
return
}
+ i := 1
switch t.Etype {
default:
Yyerror("cannot make type %v", t)
return
}
- if args.Done() {
+ if i >= len(args) {
Yyerror("missing len argument to make(%v)", t)
n.Type = nil
return
}
- l = args.N()
- args.Next()
+ l = args[i]
+ i++
typecheck(&l, Erv)
var r *Node
- if !args.Done() {
- r = args.N()
- args.Next()
+ if i < len(args) {
+ r = args[i]
+ i++
typecheck(&r, Erv)
}
n.Op = OMAKESLICE
case TMAP:
- if !args.Done() {
- l = args.N()
- args.Next()
+ if i < len(args) {
+ l = args[i]
+ i++
typecheck(&l, Erv)
defaultlit(&l, Types[TINT])
if l.Type == nil {
case TCHAN:
l = nil
- if !args.Done() {
- l = args.N()
- args.Next()
+ if i < len(args) {
+ l = args[i]
+ i++
typecheck(&l, Erv)
defaultlit(&l, Types[TINT])
if l.Type == nil {
n.Op = OMAKECHAN
}
- if !args.Done() {
+ if i < len(args) {
Yyerror("too many arguments to make(%v)", t)
n.Op = OMAKE
n.Type = nil
case OPRINT, OPRINTN:
ok |= Etop
typechecklist(n.List.Slice(), Erv|Eindir) // Eindir: address does not escape
- for i1, n1 := range n.List.Slice() {
+ ls := n.List.Slice()
+ for i1, n1 := range ls {
// Special case for print: int constant is int64, not int.
if Isconst(n1, CTINT) {
- defaultlit(&n.List.Slice()[i1], Types[TINT64])
+ defaultlit(&ls[i1], Types[TINT64])
} else {
- defaultlit(&n.List.Slice()[i1], nil)
+ defaultlit(&ls[i1], nil)
}
}
var n *Node
var n1 int
var n2 int
- var it nodeSeqIterator
+ var i int
lno := lineno
}
}
- it = nodeSeqIterate(nl)
+ i = 0
for tl := tstruct.Type; tl != nil; tl = tl.Down {
t = tl.Type
if tl.Isddd {
if isddd {
- if it.Done() {
+ if i >= nl.Len() {
goto notenough
}
- if it.Len() > 1 {
+ if nl.Len()-i > 1 {
goto toomany
}
- n = it.N()
+ n = nl.Index(i)
setlineno(n)
if n.Type != nil {
- *it.P() = assignconvfn(n, t, desc)
+ nl.SetIndex(i, assignconvfn(n, t, desc))
}
goto out
}
- for ; !it.Done(); it.Next() {
- n = it.N()
- setlineno(it.N())
+ for ; i < nl.Len(); i++ {
+ n = nl.Index(i)
+ setlineno(n)
if n.Type != nil {
- *it.P() = assignconvfn(n, t.Type, desc)
+ nl.SetIndex(i, assignconvfn(n, t.Type, desc))
}
}
goto out
}
- if it.Done() {
+ if i >= nl.Len() {
goto notenough
}
- n = it.N()
+ n = nl.Index(i)
setlineno(n)
if n.Type != nil {
- *it.P() = assignconvfn(n, t, desc)
+ nl.SetIndex(i, assignconvfn(n, t, desc))
}
- it.Next()
+ i++
}
- if !it.Done() {
+ if i < nl.Len() {
goto toomany
}
if isddd {
l = Nod(OKEY, Nodintconst(int64(i)), l)
l.Left.Type = Types[TINT]
l.Left.Typecheck = 1
- n.List.Slice()[i2] = l
+ n.List.SetIndex(i2, l)
}
typecheck(&l.Left, Erv)
l = n3
setlineno(l)
if l.Op != OKEY {
- typecheck(&n.List.Slice()[i3], Erv)
+ typecheck(n.List.Addr(i3), Erv)
Yyerror("missing key in map literal")
continue
}
f := t.Type
var s *Sym
- for i4, n4 := range n.List.Slice() {
- setlineno(n4)
- typecheck(&n.List.Slice()[i4], Erv)
+ ls := n.List.Slice()
+ for i1, n1 := range ls {
+ setlineno(n1)
+ typecheck(&ls[i1], Erv)
+ n1 = ls[i1]
if f == nil {
if bad == 0 {
Yyerror("too many values in struct initializer")
Yyerror("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
}
// No pushtype allowed here. Must name fields for that.
- n.List.Slice()[i4] = assignconv(n.List.Slice()[i4], f.Type, "field value")
- n.List.Slice()[i4] = Nod(OKEY, newname(f.Sym), n.List.Slice()[i4])
- n.List.Slice()[i4].Left.Type = f
- n.List.Slice()[i4].Left.Typecheck = 1
+ n1 = assignconv(n1, f.Type, "field value")
+ n1 = Nod(OKEY, newname(f.Sym), n1)
+ n1.Left.Type = f
+ n1.Left.Typecheck = 1
+ ls[i1] = n1
f = f.Down
}
hash := make(map[string]bool)
// keyed list
- var s *Sym
- var f *Type
- var l *Node
- var s1 *Sym
- for i5, n5 := range n.List.Slice() {
- l = n5
+ ls := n.List.Slice()
+ for i, l := range ls {
setlineno(l)
if l.Op != OKEY {
if bad == 0 {
Yyerror("mixture of field:value and value initializers")
}
bad++
- typecheck(&n.List.Slice()[i5], Erv)
+ typecheck(&ls[i], Erv)
continue
}
- s = l.Left.Sym
+ s := l.Left.Sym
if s == nil {
Yyerror("invalid field name %v in struct initializer", l.Left)
typecheck(&l.Right, Erv)
// package, because of import dot. Redirect to correct sym
// before we do the lookup.
if s.Pkg != localpkg && exportname(s.Name) {
- s1 = Lookup(s.Name)
+ s1 := Lookup(s.Name)
if s1.Origpkg == s.Pkg {
s = s1
}
}
- f = lookdot1(nil, s, t, t.Type, 0)
+ f := lookdot1(nil, s, t, t.Type, 0)
if f == nil {
Yyerror("unknown %v field '%v' in struct literal", t, s)
continue
}
func typecheckas2(n *Node) {
- for i1 := range n.List.Slice() {
+ ls := n.List.Slice()
+ for i1, n1 := range ls {
// delicate little dance.
- n.List.Slice()[i1] = resolve(n.List.Slice()[i1])
+ n1 = resolve(n1)
+ ls[i1] = n1
- if n.List.Slice()[i1].Name == nil || n.List.Slice()[i1].Name.Defn != n || n.List.Slice()[i1].Name.Param.Ntype != nil {
- typecheck(&n.List.Slice()[i1], Erv|Easgn)
+ if n1.Name == nil || n1.Name.Defn != n || n1.Name.Param.Ntype != nil {
+ typecheck(&ls[i1], Erv|Easgn)
}
}
cl := n.List.Len()
cr := n.Rlist.Len()
if cl > 1 && cr == 1 {
- it := nodeSeqIterate(n.Rlist)
- typecheck(it.P(), Erv|Efnstruct)
+ typecheck(n.Rlist.Addr(0), Erv|Efnstruct)
} else {
typechecklist(n.Rlist.Slice(), Erv)
}
var r *Node
if cl == cr {
// easy
- lrit := nodeSeqIterate(n.Rlist)
- for _, n2 := range n.List.Slice() {
- if n2.Type != nil && lrit.N().Type != nil {
- *lrit.P() = assignconv(lrit.N(), n2.Type, "assignment")
+ ls := n.List.Slice()
+ rs := n.Rlist.Slice()
+ for il, nl := range ls {
+ nr := rs[il]
+ if nl.Type != nil && nr.Type != nil {
+ rs[il] = assignconv(nr, nl.Type, "assignment")
}
- if n2.Name != nil && n2.Name.Defn == n && n2.Name.Param.Ntype == nil {
- defaultlit(lrit.P(), nil)
- n2.Type = lrit.N().Type
+ if nl.Name != nil && nl.Name.Defn == n && nl.Name.Param.Ntype == nil {
+ defaultlit(&rs[il], nil)
+ nl.Type = rs[il].Type
}
- lrit.Next()
}
goto out
// second half of dance
out:
n.Typecheck = 1
- for i4, n4 := range n.List.Slice() {
- if n4.Typecheck == 0 {
- typecheck(&n.List.Slice()[i4], Erv|Easgn)
+ ls = n.List.Slice()
+ for i1, n1 := range ls {
+ if n1.Typecheck == 0 {
+ typecheck(&ls[i1], Erv|Easgn)
}
}
}
}
func markbreaklist(l Nodes, implicit *Node) {
- for it := nodeSeqIterate(l); !it.Done(); it.Next() {
- n := it.N()
- if n.Op == OLABEL && it.Len() > 1 && n.Name.Defn == nodeSeqSlice(it.Seq())[1] {
+ s := l.Slice()
+ for i := 0; i < len(s); i++ {
+ n := s[i]
+ if n.Op == OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] {
switch n.Name.Defn.Op {
case OFOR, OSWITCH, OTYPESW, OSELECT, ORANGE:
lab := new(Label)
n.Left.Sym.Label = lab
markbreak(n.Name.Defn, n.Name.Defn)
n.Left.Sym.Label = nil
- it.Next()
+ i++
continue
}
}
// Isterminating whether the Nodes list ends with a terminating
// statement.
func (l Nodes) isterminating() bool {
- c := len(l.Slice())
+ s := l.Slice()
+ c := len(s)
if c == 0 {
return false
}
- return l.Slice()[c-1].isterminating()
+ return s[c-1].isterminating()
}
// Isterminating returns whether the node n, the last one in a
ll := ascompatee(n.Op, rl, n.List.Slice(), &n.Ninit)
n.List.Set(reorder3(ll))
- for i1 := range n.List.Slice() {
- n.List.Slice()[i1] = applywritebarrier(n.List.Slice()[i1])
+ ls := n.List.Slice()
+ for i, n := range ls {
+ ls[i] = applywritebarrier(n)
}
break
}
if !isblank(a) {
var_ := temp(Ptrto(t.Type))
var_.Typecheck = 1
- it := nodeSeqIterate(n.List)
- *it.P() = var_
+ n.List.SetIndex(0, var_)
walkexpr(&n, init)
init.Append(n)
n = Nod(OAS, a, Nod(OIND, var_, nil))
}
var nn []*Node
- nlit := nodeSeqIterate(nl)
- nrit := nodeSeqIterate(nr)
- for ; !nlit.Done() && !nrit.Done(); nlit.Next() {
+ i := 0
+ for ; i < len(nl); i++ {
+ if i >= len(nr) {
+ break
+ }
// Do not generate 'x = x' during return. See issue 4014.
- if op == ORETURN && nlit.N() == nrit.N() {
- nrit.Next()
+ if op == ORETURN && nl[i] == nr[i] {
continue
}
- nn = append(nn, ascompatee1(op, nlit.N(), nrit.N(), init))
- nrit.Next()
+ nn = append(nn, ascompatee1(op, nl[i], nr[i], init))
}
// cannot happen: caller checked that lists had same length
- if !nlit.Done() || !nrit.Done() {
+ if i < len(nl) || i < len(nr) {
var nln, nrn Nodes
nln.Set(nl)
nrn.Set(nr)
var nn []*Node
var mm []*Node
ucount := 0
- it := nodeSeqIterate(nl)
- for ; !it.Done(); it.Next() {
+ var i int
+ for i = 0; i < nl.Len(); i++ {
if r == nil {
break
}
- l = it.N()
+ l = nl.Index(i)
if isblank(l) {
r = saver.Next()
continue
r = saver.Next()
}
- if !it.Done() || r != nil {
+ if i < nl.Len() || r != nil {
Yyerror("ascompatet: assignment count mismatch: %d = %d", nl.Len(), structcount(*nr))
}
defaultlit(&n, Types[TINT64])
}
defaultlit(&n, nil)
- all.Slice()[i1] = n
+ all.SetIndex(i1, n)
if n.Type == nil || n.Type.Etype == TFORW {
continue
}
// l2 is allowed to be a string.
func appendslice(n *Node, init *Nodes) *Node {
walkexprlistsafe(n.List.Slice(), init)
- for i1 := range
// walkexprlistsafe will leave OINDEX (s[n]) alone if both s
// and n are name or literal, but those may index the slice we're
// modifying here. Fix explicitly.
- n.List.Slice() {
- n.List.Slice()[i1] = cheapexpr(n.List.Slice()[i1],
- init)
+ ls := n.List.Slice()
+ for i1, n1 := range ls {
+ ls[i1] = cheapexpr(n1, init)
}
l1 := n.List.First()
// s
func walkappend(n *Node, init *Nodes, dst *Node) *Node {
if !samesafeexpr(dst, n.List.First()) {
- it := nodeSeqIterate(n.List)
- *it.P() = safeexpr(it.N(), init)
- walkexpr(it.P(), init)
+ n.List.SetIndex(0, safeexpr(n.List.Index(0), init))
+ walkexpr(n.List.Addr(0), init)
}
walkexprlistsafe(n.List.Slice()[1:], init)
// Using cheapexpr also makes sure that the evaluation
// of all arguments (and especially any panics) happen
// before we begin to modify the slice in a visible way.
- it := nodeSeqIterate(n.List)
- it.Next()
- for ; !it.Done(); it.Next() {
- *it.P() = cheapexpr(it.N(), init)
+ ls := n.List.Slice()[1:]
+ for i, n := range ls {
+ ls[i] = cheapexpr(n, init)
}
nsrc := n.List.First()
nx.Etype = 1
l = append(l, Nod(OAS, ns, nx)) // s = s[:n+argc]
- it = nodeSeqIterate(n.List)
- it.Next()
- for ; !it.Done(); it.Next() {
+ ls = n.List.Slice()[1:]
+ for i, n := range ls {
nx = Nod(OINDEX, ns, nn) // s[n] ...
nx.Bounded = true
- l = append(l, Nod(OAS, nx, it.N())) // s[n] = arg
- if it.Len() > 1 {
+ l = append(l, Nod(OAS, nx, n)) // s[n] = arg
+ if i+1 < len(ls) {
l = append(l, Nod(OAS, nn, Nod(OADD, nn, Nodintconst(1)))) // n = n + 1
}
}