if p.trace {
p.tracef("{ %s }\n", Hconvslice(f.Inl.Slice(), obj.FmtSharp))
}
- p.nodeSlice(f.Inl.Slice())
+ p.nodeList(f.Inl)
if p.trace {
p.tracef("\n")
}
p.int(index)
}
-func (p *exporter) nodeSlice(list []*Node) {
+func (p *exporter) nodeList(list nodesOrNodeList) {
+ it := nodeSeqIterate(list)
if p.trace {
p.tracef("[ ")
}
- p.int(len(list))
+ p.int(it.Len())
if p.trace {
- if len(list) == 0 {
+ if it.Len() == 0 {
p.tracef("] {}")
} else {
p.tracef("] {>")
defer p.tracef("<\n}")
}
}
- for _, n := range list {
+ for ; !it.Done(); it.Next() {
if p.trace {
p.tracef("\n")
}
- p.node(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)
+ p.node(it.N())
}
}
case OIF:
p.nodeList(n.Ninit)
p.node(n.Left)
- p.nodeSlice(n.Nbody.Slice())
+ p.nodeList(n.Nbody)
p.nodeList(n.Rlist)
case OFOR:
p.nodeList(n.Ninit)
p.nodesOrNil(n.Left, n.Right)
- p.nodeSlice(n.Nbody.Slice())
+ p.nodeList(n.Nbody)
case ORANGE:
if p.bool(n.List != nil) {
p.nodeList(n.List)
}
p.node(n.Right)
- p.nodeSlice(n.Nbody.Slice())
+ p.nodeList(n.Nbody)
case OSELECT, OSWITCH:
p.nodeList(n.Ninit)
if p.bool(n.List != nil) {
p.nodeList(n.List)
}
- p.nodeSlice(n.Nbody.Slice())
+ p.nodeList(n.Nbody)
case OBREAK, OCONTINUE, OGOTO, OFALL, OXFALL:
p.nodesOrNil(n.Left, nil)
// read inlined functions bodies
n := p.int()
for i := 0; i < n; i++ {
- body := p.nodeSlice()
+ body := p.nodeList()
const hookup = false // TODO(gri) enable and remove this condition
if hookup {
p.inlined[i].Inl.Set(body)
// Inlined function bodies
// go.y:stmt_list
-func (p *importer) nodeSlice() []*Node {
- var l []*Node
- for i := p.int(); i > 0; i-- {
- l = append(l, p.node())
- }
- return l
-}
-
-func (p *importer) nodeList() *NodeList {
- var l *NodeList
- for i := p.int(); i > 0; i-- {
- l = list(l, p.node())
+func (p *importer) nodeList() []*Node {
+ c := p.int()
+ s := make([]*Node, 0, c)
+ for i := 0; i < c; i++ {
+ s = append(s, p.node())
}
- return l
+ return s
}
func (p *importer) node() *Node {
// expressions
case OMAKEMAP, OMAKECHAN, OMAKESLICE:
if p.bool() {
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
}
n.Left, n.Right = p.nodesOrNil()
n.Type = p.typ()
n.Right = p.node()
case OADDSTR:
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
case OPTRLIT:
n.Left = p.node()
case OSTRUCTLIT:
n.Type = p.typ()
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
n.Implicit = p.bool()
case OARRAYLIT, OMAPLIT:
n.Type = p.typ()
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
n.Implicit = p.bool()
case OKEY:
// if p.bool() {
// n.Left = p.node()
// } else {
- // n.List = p.nodeList()
+ // setNodeSeq(&n.List, p.nodeList())
// }
x := Nod(OCALL, p.typ().Nod, nil)
if p.bool() {
x.List = list1(p.node())
} else {
- x.List = p.nodeList()
+ setNodeSeq(&x.List, p.nodeList())
}
return x
case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC,
ORECOVER, OPRINT, OPRINTN:
n.Left, _ = p.nodesOrNil()
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
n.Isddd = p.bool()
case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
n.Left = p.node()
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
n.Isddd = p.bool()
case OCMPSTR, OCMPIFACE:
n.Etype = EType(p.int())
case OAS2, OASWB:
- n.List = p.nodeList()
- n.Rlist = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
+ setNodeSeq(&n.Rlist, p.nodeList())
case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
- n.List = p.nodeList()
- n.Rlist = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
+ setNodeSeq(&n.Rlist, p.nodeList())
case ORETURN:
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
case OPROC, ODEFER:
n.Left = p.node()
case OIF:
- n.Ninit = p.nodeList()
+ setNodeSeq(&n.Ninit, p.nodeList())
n.Left = p.node()
- n.Nbody.Set(p.nodeSlice())
- n.Rlist = p.nodeList()
+ n.Nbody.Set(p.nodeList())
+ setNodeSeq(&n.Rlist, p.nodeList())
case OFOR:
- n.Ninit = p.nodeList()
+ setNodeSeq(&n.Ninit, p.nodeList())
n.Left, n.Right = p.nodesOrNil()
- n.Nbody.Set(p.nodeSlice())
+ n.Nbody.Set(p.nodeList())
case ORANGE:
if p.bool() {
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
}
n.Right = p.node()
- n.Nbody.Set(p.nodeSlice())
+ n.Nbody.Set(p.nodeList())
case OSELECT, OSWITCH:
- n.Ninit = p.nodeList()
+ setNodeSeq(&n.Ninit, p.nodeList())
n.Left, _ = p.nodesOrNil()
- n.List = p.nodeList()
+ setNodeSeq(&n.List, p.nodeList())
case OCASE, OXCASE:
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:
n.Left, _ = p.nodesOrNil()
}
}
+// 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.
// TODO(iant): Remove after conversion from NodeList to Nodes is complete.
type nodeSeqIterator interface {
N() *Node
// Return the address of the current node.
P() **Node
+ // Return the number of items remaining in the iteration.
+ Len() int
}
// nodeListIterator is a type that implements nodeSeqIterator using a
return &nli.l.N
}
+func (nli *nodeListIterator) Len() int {
+ return count(nli.l)
+}
+
// nodesIterator implements nodeSeqIterator using a Nodes.
type nodesIterator struct {
n Nodes
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.
-func nodeSeqIterate(ns interface{}) nodeSeqIterator {
+func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator {
switch ns := ns.(type) {
case *NodeList:
return &nodeListIterator{ns}
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")
+ }
+ }
+}