mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: remove remaining nodeSeqIterate calls
Mix in several other minor cleanups, including adding some new methods to Nodes: Index, Addr, SetIndex, SetNodes. Passes toolstash -cmp. Update #14473. Change-Id: I8bd4ae3fde7c5e20ba66e7dd1654fbc70c3ddeb8 Reviewed-on: https://go-review.googlesource.com/20491 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
862b9ddda7
commit
cd6619d2e6
15 changed files with 327 additions and 408 deletions
|
|
@ -806,24 +806,23 @@ func (p *exporter) inlinedBody(n *Node) {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1762,7 +1762,7 @@ func bvgenjump(n, res *Node, wantTrue, geninit bool) {
|
|||
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.
|
||||
|
|
@ -2943,9 +2943,7 @@ func cgen_append(n, res *Node) {
|
|||
// 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)
|
||||
|
|
@ -2966,7 +2964,7 @@ func cgen_append(n, res *Node) {
|
|||
|
||||
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++
|
||||
}
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ func colasdefn(left Nodes, defn *Node) {
|
|||
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 {
|
||||
|
|
@ -833,9 +833,9 @@ func tostruct0(t *Type, l []*Node) {
|
|||
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
|
||||
}
|
||||
|
|
@ -860,13 +860,14 @@ func tofunargs(l []*Node) *Type {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -722,10 +722,9 @@ func esc(e *EscState, n *Node, up *Node) {
|
|||
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -759,14 +758,14 @@ func esc(e *EscState, n *Node, up *Node) {
|
|||
|
||||
// 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
|
||||
}
|
||||
if !llit.Done() || !lrit.Done() {
|
||||
escassign(e, n, rs[i])
|
||||
}
|
||||
if n.List.Len() != len(rs) {
|
||||
Fatalf("esc oas2func")
|
||||
}
|
||||
|
||||
|
|
@ -779,19 +778,19 @@ func esc(e *EscState, n *Node, up *Node) {
|
|||
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")
|
||||
}
|
||||
|
||||
|
|
@ -801,10 +800,8 @@ func esc(e *EscState, n *Node, up *Node) {
|
|||
|
||||
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.
|
||||
|
|
@ -1229,8 +1226,8 @@ func escassignfromtag(e *EscState, note *string, dsts Nodes, src *Node) uint16 {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
@ -1242,15 +1239,15 @@ func escassignfromtag(e *EscState, note *string, dsts Nodes, src *Node) uint16 {
|
|||
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
|
||||
|
|
@ -1419,36 +1416,37 @@ func esccall(e *EscState, n *Node, up *Node) {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
@ -1478,16 +1476,17 @@ func esccall(e *EscState, n *Node, up *Node) {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
@ -1520,18 +1519,18 @@ func esccall(e *EscState, n *Node, up *Node) {
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1257,10 +1257,10 @@ func exprfmt(n *Node, prec int) string {
|
|||
} 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 += " "
|
||||
|
|
@ -1725,9 +1725,9 @@ func Hconv(l Nodes, flag int) string {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,8 +325,9 @@ func inlconv2list(n *Node) []*Node {
|
|||
}
|
||||
|
||||
func inlnodelist(l Nodes) {
|
||||
for i := range l.Slice() {
|
||||
inlnode(&l.Slice()[i])
|
||||
s := l.Slice()
|
||||
for i := range s {
|
||||
inlnode(&s[i])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -411,9 +412,10 @@ func inlnode(np **Node) {
|
|||
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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -431,12 +433,13 @@ func inlnode(np **Node) {
|
|||
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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -670,7 +673,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
|||
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 {
|
||||
|
|
@ -689,7 +692,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
|||
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.
|
||||
|
|
@ -703,7 +706,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
|||
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)
|
||||
|
|
@ -718,7 +721,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
|||
// 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 {
|
||||
|
|
@ -726,18 +729,18 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
|||
}
|
||||
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 {
|
||||
|
|
@ -745,7 +748,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
|||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,14 +376,17 @@ func ordercall(n *Node, order *Order) {
|
|||
|
||||
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
|
||||
}
|
||||
|
|
@ -452,14 +455,15 @@ func ordermapassign(n *Node, order *Order) {
|
|||
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)
|
||||
}
|
||||
|
|
@ -651,9 +655,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
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)
|
||||
|
||||
|
|
@ -666,11 +668,9 @@ func orderstmt(n *Node, order *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)
|
||||
|
||||
|
|
@ -771,8 +771,8 @@ func orderstmt(n *Node, order *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)
|
||||
|
|
@ -821,14 +821,14 @@ func orderstmt(n *Node, order *Order) {
|
|||
// 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)
|
||||
}
|
||||
}
|
||||
|
|
@ -967,16 +967,18 @@ func orderstmt(n *Node, order *Order) {
|
|||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,11 +87,12 @@ func instrument(fn *Node) {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -146,25 +147,26 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) {
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ func typecheckrange(n *Node) {
|
|||
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),
|
||||
|
|
@ -32,9 +33,10 @@ func typecheckrange(n *Node) {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,9 +121,10 @@ func typecheckrange(n *Node) {
|
|||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -342,10 +345,10 @@ func memclrrange(n, v1, v2, a *Node) bool {
|
|||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ func typecheckselect(sel *Node) {
|
|||
} 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)
|
||||
|
|
@ -101,7 +100,6 @@ func walkselect(sel *Node) {
|
|||
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
|
||||
|
|
@ -172,8 +170,7 @@ func walkselect(sel *Node) {
|
|||
|
||||
// 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 {
|
||||
|
|
@ -189,9 +186,8 @@ func walkselect(sel *Node) {
|
|||
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 {
|
||||
|
|
@ -268,7 +264,7 @@ func walkselect(sel *Node) {
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -2066,14 +2066,12 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||
// 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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,30 +115,33 @@ func typecheckswitch(n *Node) {
|
|||
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
|
||||
|
|
@ -146,16 +149,17 @@ func typecheckswitch(n *Node) {
|
|||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -175,8 +179,7 @@ func typecheckswitch(n *Node) {
|
|||
}
|
||||
|
||||
typecheck(&nvar, Erv|Easgn)
|
||||
rit := nodeSeqIterate(ncase.Rlist)
|
||||
*rit.P() = nvar
|
||||
ncase.Rlist.SetIndex(0, nvar)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -344,8 +347,7 @@ func casebody(sw *Node, typeswvar *Node) {
|
|||
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))
|
||||
|
|
@ -395,7 +397,7 @@ func casebody(sw *Node, typeswvar *Node) {
|
|||
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -437,14 +437,20 @@ func (n *Nodes) Len() int {
|
|||
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]
|
||||
}
|
||||
|
|
@ -464,7 +470,7 @@ func (n *Nodes) NodeList() *NodeList {
|
|||
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 {
|
||||
|
|
@ -474,6 +480,24 @@ func (n *Nodes) Set(s []*Node) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
|
@ -530,106 +554,6 @@ type nodesOrNodeList interface{}
|
|||
// 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) {
|
||||
|
|
|
|||
|
|
@ -1289,8 +1289,7 @@ OpSwitch:
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -1576,9 +1575,7 @@ OpSwitch:
|
|||
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:
|
||||
|
|
@ -1591,8 +1588,7 @@ OpSwitch:
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -1637,15 +1633,11 @@ OpSwitch:
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -1656,13 +1648,12 @@ 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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1777,16 +1768,15 @@ OpSwitch:
|
|||
|
||||
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 {
|
||||
|
|
@ -1794,6 +1784,7 @@ OpSwitch:
|
|||
return
|
||||
}
|
||||
|
||||
i := 1
|
||||
switch t.Etype {
|
||||
default:
|
||||
Yyerror("cannot make type %v", t)
|
||||
|
|
@ -1807,19 +1798,19 @@ OpSwitch:
|
|||
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)
|
||||
}
|
||||
|
||||
|
|
@ -1842,9 +1833,9 @@ OpSwitch:
|
|||
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 {
|
||||
|
|
@ -1863,9 +1854,9 @@ OpSwitch:
|
|||
|
||||
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 {
|
||||
|
|
@ -1883,7 +1874,7 @@ OpSwitch:
|
|||
n.Op = OMAKECHAN
|
||||
}
|
||||
|
||||
if !args.Done() {
|
||||
if i < len(args) {
|
||||
Yyerror("too many arguments to make(%v)", t)
|
||||
n.Op = OMAKE
|
||||
n.Type = nil
|
||||
|
|
@ -1922,12 +1913,13 @@ OpSwitch:
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2611,7 +2603,7 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
|
|||
var n *Node
|
||||
var n1 int
|
||||
var n2 int
|
||||
var it nodeSeqIterator
|
||||
var i int
|
||||
|
||||
lno := lineno
|
||||
|
||||
|
|
@ -2698,48 +2690,48 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
@ -2983,7 +2975,7 @@ func typecheckcomplit(np **Node) {
|
|||
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)
|
||||
|
|
@ -3030,7 +3022,7 @@ func typecheckcomplit(np **Node) {
|
|||
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
|
||||
}
|
||||
|
|
@ -3060,9 +3052,11 @@ func typecheckcomplit(np **Node) {
|
|||
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")
|
||||
|
|
@ -3076,10 +3070,11 @@ func typecheckcomplit(np **Node) {
|
|||
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
|
||||
}
|
||||
|
||||
|
|
@ -3090,23 +3085,19 @@ func typecheckcomplit(np **Node) {
|
|||
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)
|
||||
|
|
@ -3117,13 +3108,13 @@ func typecheckcomplit(np **Node) {
|
|||
// 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
|
||||
|
|
@ -3313,20 +3304,21 @@ func checkassignto(src *Type, dst *Node) {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -3336,16 +3328,17 @@ func typecheckas2(n *Node) {
|
|||
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
|
||||
|
|
@ -3426,9 +3419,10 @@ mismatch:
|
|||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3886,9 +3880,10 @@ func markbreak(n *Node, implicit *Node) {
|
|||
}
|
||||
|
||||
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)
|
||||
|
|
@ -3896,7 +3891,7 @@ func markbreaklist(l Nodes, implicit *Node) {
|
|||
n.Left.Sym.Label = lab
|
||||
markbreak(n.Name.Defn, n.Name.Defn)
|
||||
n.Left.Sym.Label = nil
|
||||
it.Next()
|
||||
i++
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
@ -3920,11 +3915,12 @@ func (l *NodeList) isterminating() bool {
|
|||
// 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
|
||||
|
|
|
|||
|
|
@ -321,8 +321,9 @@ func walkstmt(np **Node) {
|
|||
|
||||
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
|
||||
}
|
||||
|
|
@ -884,8 +885,7 @@ opswitch:
|
|||
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))
|
||||
|
|
@ -1661,20 +1661,20 @@ func ascompatee(op Op, nl, nr []*Node, init *Nodes) []*Node {
|
|||
}
|
||||
|
||||
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)
|
||||
|
|
@ -1714,12 +1714,12 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node {
|
|||
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
|
||||
|
|
@ -1749,7 +1749,7 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node {
|
|||
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))
|
||||
}
|
||||
|
||||
|
|
@ -1985,7 +1985,7 @@ func walkprint(nn *Node, init *Nodes) *Node {
|
|||
defaultlit(&n, Types[TINT64])
|
||||
}
|
||||
defaultlit(&n, nil)
|
||||
all.Slice()[i1] = n
|
||||
all.SetIndex(i1, n)
|
||||
if n.Type == nil || n.Type.Etype == TFORW {
|
||||
continue
|
||||
}
|
||||
|
|
@ -2811,14 +2811,13 @@ func addstr(n *Node, init *Nodes) *Node {
|
|||
// 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()
|
||||
|
|
@ -2933,9 +2932,8 @@ func appendslice(n *Node, init *Nodes) *Node {
|
|||
// 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)
|
||||
|
||||
|
|
@ -2945,10 +2943,9 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
|
|||
// 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()
|
||||
|
|
@ -2991,13 +2988,12 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue