Commit ca56c590 authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/compile: add setNodeSeq, and use it in bimport.go

Also rewrite bexport.go to use nodeSeqIterate.

The new setNodeSeq is a transitional generic function to set either a
NodeList or a slice to either a NodeList or a slice.  This should permit
us to flip fields from *NodeList to []*Node, or Nodes, without changing
other code.

Passes toolstash -cmp.

Change-Id: I872cbfe45bc5f432595737c1f6da641c502b1ab6
Reviewed-on: https://go-review.googlesource.com/20194Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent d55a099e
...@@ -335,7 +335,7 @@ func Export(out *obj.Biobuf, trace bool) int { ...@@ -335,7 +335,7 @@ func Export(out *obj.Biobuf, trace bool) int {
if p.trace { if p.trace {
p.tracef("{ %s }\n", Hconvslice(f.Inl.Slice(), obj.FmtSharp)) p.tracef("{ %s }\n", Hconvslice(f.Inl.Slice(), obj.FmtSharp))
} }
p.nodeSlice(f.Inl.Slice()) p.nodeList(f.Inl)
if p.trace { if p.trace {
p.tracef("\n") p.tracef("\n")
} }
...@@ -806,45 +806,25 @@ func (p *exporter) inlinedBody(n *Node) { ...@@ -806,45 +806,25 @@ func (p *exporter) inlinedBody(n *Node) {
p.int(index) p.int(index)
} }
func (p *exporter) nodeSlice(list []*Node) { func (p *exporter) nodeList(list nodesOrNodeList) {
it := nodeSeqIterate(list)
if p.trace { if p.trace {
p.tracef("[ ") p.tracef("[ ")
} }
p.int(len(list)) p.int(it.Len())
if p.trace { if p.trace {
if len(list) == 0 { if it.Len() == 0 {
p.tracef("] {}") p.tracef("] {}")
} else { } else {
p.tracef("] {>") p.tracef("] {>")
defer p.tracef("<\n}") defer p.tracef("<\n}")
} }
} }
for _, n := range list { for ; !it.Done(); it.Next() {
if p.trace { if p.trace {
p.tracef("\n") p.tracef("\n")
} }
p.node(n) p.node(it.N())
}
}
func (p *exporter) nodeList(list *NodeList) {
if p.trace {
p.tracef("[ ")
}
p.int(count(list))
if p.trace {
if list == nil {
p.tracef("] {}")
} else {
p.tracef("] {>")
defer p.tracef("<\n}")
}
}
for q := list; q != nil; q = q.Next {
if p.trace {
p.tracef("\n")
}
p.node(q.N)
} }
} }
...@@ -982,20 +962,20 @@ func (p *exporter) node(n *Node) { ...@@ -982,20 +962,20 @@ func (p *exporter) node(n *Node) {
case OIF: case OIF:
p.nodeList(n.Ninit) p.nodeList(n.Ninit)
p.node(n.Left) p.node(n.Left)
p.nodeSlice(n.Nbody.Slice()) p.nodeList(n.Nbody)
p.nodeList(n.Rlist) p.nodeList(n.Rlist)
case OFOR: case OFOR:
p.nodeList(n.Ninit) p.nodeList(n.Ninit)
p.nodesOrNil(n.Left, n.Right) p.nodesOrNil(n.Left, n.Right)
p.nodeSlice(n.Nbody.Slice()) p.nodeList(n.Nbody)
case ORANGE: case ORANGE:
if p.bool(n.List != nil) { if p.bool(n.List != nil) {
p.nodeList(n.List) p.nodeList(n.List)
} }
p.node(n.Right) p.node(n.Right)
p.nodeSlice(n.Nbody.Slice()) p.nodeList(n.Nbody)
case OSELECT, OSWITCH: case OSELECT, OSWITCH:
p.nodeList(n.Ninit) p.nodeList(n.Ninit)
...@@ -1006,7 +986,7 @@ func (p *exporter) node(n *Node) { ...@@ -1006,7 +986,7 @@ func (p *exporter) node(n *Node) {
if p.bool(n.List != nil) { if p.bool(n.List != nil) {
p.nodeList(n.List) p.nodeList(n.List)
} }
p.nodeSlice(n.Nbody.Slice()) p.nodeList(n.Nbody)
case OBREAK, OCONTINUE, OGOTO, OFALL, OXFALL: case OBREAK, OCONTINUE, OGOTO, OFALL, OXFALL:
p.nodesOrNil(n.Left, nil) p.nodesOrNil(n.Left, nil)
......
...@@ -113,7 +113,7 @@ func Import(in *obj.Biobuf) { ...@@ -113,7 +113,7 @@ func Import(in *obj.Biobuf) {
// read inlined functions bodies // read inlined functions bodies
n := p.int() n := p.int()
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
body := p.nodeSlice() body := p.nodeList()
const hookup = false // TODO(gri) enable and remove this condition const hookup = false // TODO(gri) enable and remove this condition
if hookup { if hookup {
p.inlined[i].Inl.Set(body) p.inlined[i].Inl.Set(body)
...@@ -550,20 +550,13 @@ func (p *importer) float(x *Mpflt) { ...@@ -550,20 +550,13 @@ func (p *importer) float(x *Mpflt) {
// Inlined function bodies // Inlined function bodies
// go.y:stmt_list // go.y:stmt_list
func (p *importer) nodeSlice() []*Node { func (p *importer) nodeList() []*Node {
var l []*Node c := p.int()
for i := p.int(); i > 0; i-- { s := make([]*Node, 0, c)
l = append(l, p.node()) for i := 0; i < c; i++ {
} s = append(s, p.node())
return l
}
func (p *importer) nodeList() *NodeList {
var l *NodeList
for i := p.int(); i > 0; i-- {
l = list(l, p.node())
} }
return l return s
} }
func (p *importer) node() *Node { func (p *importer) node() *Node {
...@@ -597,7 +590,7 @@ func (p *importer) node() *Node { ...@@ -597,7 +590,7 @@ func (p *importer) node() *Node {
// expressions // expressions
case OMAKEMAP, OMAKECHAN, OMAKESLICE: case OMAKEMAP, OMAKECHAN, OMAKESLICE:
if p.bool() { if p.bool() {
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
} }
n.Left, n.Right = p.nodesOrNil() n.Left, n.Right = p.nodesOrNil()
n.Type = p.typ() n.Type = p.typ()
...@@ -612,19 +605,19 @@ func (p *importer) node() *Node { ...@@ -612,19 +605,19 @@ func (p *importer) node() *Node {
n.Right = p.node() n.Right = p.node()
case OADDSTR: case OADDSTR:
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
case OPTRLIT: case OPTRLIT:
n.Left = p.node() n.Left = p.node()
case OSTRUCTLIT: case OSTRUCTLIT:
n.Type = p.typ() n.Type = p.typ()
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
n.Implicit = p.bool() n.Implicit = p.bool()
case OARRAYLIT, OMAPLIT: case OARRAYLIT, OMAPLIT:
n.Type = p.typ() n.Type = p.typ()
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
n.Implicit = p.bool() n.Implicit = p.bool()
case OKEY: case OKEY:
...@@ -639,13 +632,13 @@ func (p *importer) node() *Node { ...@@ -639,13 +632,13 @@ func (p *importer) node() *Node {
// if p.bool() { // if p.bool() {
// n.Left = p.node() // n.Left = p.node()
// } else { // } else {
// n.List = p.nodeList() // setNodeSeq(&n.List, p.nodeList())
// } // }
x := Nod(OCALL, p.typ().Nod, nil) x := Nod(OCALL, p.typ().Nod, nil)
if p.bool() { if p.bool() {
x.List = list1(p.node()) x.List = list1(p.node())
} else { } else {
x.List = p.nodeList() setNodeSeq(&x.List, p.nodeList())
} }
return x return x
...@@ -675,12 +668,12 @@ func (p *importer) node() *Node { ...@@ -675,12 +668,12 @@ func (p *importer) node() *Node {
case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC,
ORECOVER, OPRINT, OPRINTN: ORECOVER, OPRINT, OPRINTN:
n.Left, _ = p.nodesOrNil() n.Left, _ = p.nodesOrNil()
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
n.Isddd = p.bool() n.Isddd = p.bool()
case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
n.Left = p.node() n.Left = p.node()
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
n.Isddd = p.bool() n.Isddd = p.bool()
case OCMPSTR, OCMPIFACE: case OCMPSTR, OCMPIFACE:
...@@ -706,47 +699,47 @@ func (p *importer) node() *Node { ...@@ -706,47 +699,47 @@ func (p *importer) node() *Node {
n.Etype = EType(p.int()) n.Etype = EType(p.int())
case OAS2, OASWB: case OAS2, OASWB:
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
n.Rlist = p.nodeList() setNodeSeq(&n.Rlist, p.nodeList())
case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
n.Rlist = p.nodeList() setNodeSeq(&n.Rlist, p.nodeList())
case ORETURN: case ORETURN:
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
case OPROC, ODEFER: case OPROC, ODEFER:
n.Left = p.node() n.Left = p.node()
case OIF: case OIF:
n.Ninit = p.nodeList() setNodeSeq(&n.Ninit, p.nodeList())
n.Left = p.node() n.Left = p.node()
n.Nbody.Set(p.nodeSlice()) n.Nbody.Set(p.nodeList())
n.Rlist = p.nodeList() setNodeSeq(&n.Rlist, p.nodeList())
case OFOR: case OFOR:
n.Ninit = p.nodeList() setNodeSeq(&n.Ninit, p.nodeList())
n.Left, n.Right = p.nodesOrNil() n.Left, n.Right = p.nodesOrNil()
n.Nbody.Set(p.nodeSlice()) n.Nbody.Set(p.nodeList())
case ORANGE: case ORANGE:
if p.bool() { if p.bool() {
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
} }
n.Right = p.node() n.Right = p.node()
n.Nbody.Set(p.nodeSlice()) n.Nbody.Set(p.nodeList())
case OSELECT, OSWITCH: case OSELECT, OSWITCH:
n.Ninit = p.nodeList() setNodeSeq(&n.Ninit, p.nodeList())
n.Left, _ = p.nodesOrNil() n.Left, _ = p.nodesOrNil()
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
case OCASE, OXCASE: case OCASE, OXCASE:
if p.bool() { if p.bool() {
n.List = p.nodeList() setNodeSeq(&n.List, p.nodeList())
} }
n.Nbody.Set(p.nodeSlice()) n.Nbody.Set(p.nodeList())
case OBREAK, OCONTINUE, OGOTO, OFALL, OXFALL: case OBREAK, OCONTINUE, OGOTO, OFALL, OXFALL:
n.Left, _ = p.nodesOrNil() n.Left, _ = p.nodesOrNil()
......
...@@ -495,6 +495,18 @@ func (n *Nodes) AppendNodeList(l *NodeList) { ...@@ -495,6 +495,18 @@ func (n *Nodes) AppendNodeList(l *NodeList) {
} }
} }
// nodesOrNodeList must be either type Nodes or type *NodeList, or, in
// some cases, []*Node. It exists during the transition from NodeList
// to Nodes only and then should be deleted. See nodeSeqIterate to
// return an iterator from a nodesOrNodeList.
type nodesOrNodeList interface{}
// nodesOrNodeListPtr must be type *Nodes or type **NodeList, or, in
// some cases, *[]*Node. It exists during the transition from NodeList
// to Nodes only, and then should be deleted. See setNodeSeq to assign
// to a generic value.
type nodesOrNodeListPtr interface{}
// nodeSeqIterator is an interface used to iterate over a sequence of nodes. // nodeSeqIterator is an interface used to iterate over a sequence of nodes.
// TODO(iant): Remove after conversion from NodeList to Nodes is complete. // TODO(iant): Remove after conversion from NodeList to Nodes is complete.
type nodeSeqIterator interface { type nodeSeqIterator interface {
...@@ -506,6 +518,8 @@ type nodeSeqIterator interface { ...@@ -506,6 +518,8 @@ type nodeSeqIterator interface {
N() *Node N() *Node
// Return the address of the current node. // Return the address of the current node.
P() **Node P() **Node
// Return the number of items remaining in the iteration.
Len() int
} }
// nodeListIterator is a type that implements nodeSeqIterator using a // nodeListIterator is a type that implements nodeSeqIterator using a
...@@ -530,6 +544,10 @@ func (nli *nodeListIterator) P() **Node { ...@@ -530,6 +544,10 @@ func (nli *nodeListIterator) P() **Node {
return &nli.l.N return &nli.l.N
} }
func (nli *nodeListIterator) Len() int {
return count(nli.l)
}
// nodesIterator implements nodeSeqIterator using a Nodes. // nodesIterator implements nodeSeqIterator using a Nodes.
type nodesIterator struct { type nodesIterator struct {
n Nodes n Nodes
...@@ -552,8 +570,12 @@ func (ni *nodesIterator) P() **Node { ...@@ -552,8 +570,12 @@ func (ni *nodesIterator) P() **Node {
return &ni.n.Slice()[ni.i] return &ni.n.Slice()[ni.i]
} }
func (ni *nodesIterator) Len() int {
return len(ni.n.Slice())
}
// nodeSeqIterate returns an iterator over either a *Nodelist or a *Nodes. // nodeSeqIterate returns an iterator over either a *Nodelist or a *Nodes.
func nodeSeqIterate(ns interface{}) nodeSeqIterator { func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator {
switch ns := ns.(type) { switch ns := ns.(type) {
case *NodeList: case *NodeList:
return &nodeListIterator{ns} return &nodeListIterator{ns}
...@@ -563,3 +585,51 @@ func nodeSeqIterate(ns interface{}) nodeSeqIterator { ...@@ -563,3 +585,51 @@ func nodeSeqIterate(ns interface{}) nodeSeqIterator {
panic("can't happen") panic("can't happen")
} }
} }
// setNodeSeq implements *a = b.
// a must have type **NodeList, *Nodes, or *[]*Node.
// b must have type *NodeList, Nodes, or []*Node.
// This is an interim function during the transition from NodeList to Nodes.
// TODO(iant): Remove when transition is complete.
func setNodeSeq(a nodesOrNodeListPtr, b nodesOrNodeList) {
// Simplify b to either *Nodelist or []*Node.
if n, ok := b.(Nodes); ok {
b = n.Slice()
}
if l, ok := a.(**NodeList); ok {
switch b := b.(type) {
case *NodeList:
*l = b
case []*Node:
var ll *NodeList
for _, n := range b {
ll = list(ll, n)
}
*l = ll
default:
panic("can't happen")
}
} else {
var s []*Node
switch b := b.(type) {
case *NodeList:
for l := b; l != nil; l = l.Next {
s = append(s, l.N)
}
case []*Node:
s = b
default:
panic("can't happen")
}
switch a := a.(type) {
case *Nodes:
a.Set(s)
case *[]*Node:
*a = s
default:
panic("can't happen")
}
}
}
...@@ -34,7 +34,7 @@ func resolve(n *Node) *Node { ...@@ -34,7 +34,7 @@ func resolve(n *Node) *Node {
return n return n
} }
func typechecklist(l interface{}, top int) { func typechecklist(l nodesOrNodeList, top int) {
for it := nodeSeqIterate(l); !it.Done(); it.Next() { for it := nodeSeqIterate(l); !it.Done(); it.Next() {
typecheck(it.P(), top) typecheck(it.P(), top)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment