Commit 466c948b authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/compile: add nodeSeqIterator interface

I tried to write a program to convert *NodeList to Node, but ran into
too many problem cases.  I'm backing off and trying a more iterative
approach using interfaces.

This CL adds an interface for iteration over either a *NodeList or a
Nodes.  I changed typechecklist to use it, to show how it works.  After
NodeList is eliminated, we can change the typechecklist parameter type
to Nodes.

Passes toolstash -cmp.

Change-Id: I5c7593714b020d20868b99151b1e7cadbbdbc397
Reviewed-on: https://go-review.googlesource.com/20190
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 0c84c4f1
......@@ -303,7 +303,7 @@ func genhash(sym *Sym, t *Type) {
Curfn = fn
fn.Func.Dupok = true
typecheck(&fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop)
typechecklist(fn.Nbody, Etop)
Curfn = nil
// Disable safemode while compiling this code: the code we
......@@ -511,7 +511,7 @@ func geneq(sym *Sym, t *Type) {
Curfn = fn
fn.Func.Dupok = true
typecheck(&fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop)
typechecklist(fn.Nbody, Etop)
Curfn = nil
// Disable safemode while compiling this code: the code we
......
......@@ -111,7 +111,7 @@ func typecheckclosure(func_ *Node, top int) {
Curfn = func_
olddd := decldepth
decldepth = 1
typecheckslice(func_.Nbody.Slice(), Etop)
typechecklist(func_.Nbody, Etop)
decldepth = olddd
Curfn = oldfn
}
......
......@@ -87,7 +87,7 @@ func typecheckinl(fn *Node) {
savefn := Curfn
Curfn = fn
typecheckslice(fn.Func.Inl.Slice(), Etop)
typechecklist(fn.Func.Inl, Etop)
Curfn = savefn
safemode = save_safemode
......
......@@ -406,7 +406,7 @@ func Main() {
Curfn = l.N
decldepth = 1
saveerrors()
typecheckslice(l.N.Nbody.Slice(), Etop)
typechecklist(l.N.Nbody, Etop)
checkreturn(l.N)
if nerrors != 0 {
l.N.Nbody.Set(nil) // type errors; do not compile
......
......@@ -128,7 +128,7 @@ out:
}
decldepth++
typecheckslice(n.Nbody.Slice(), Etop)
typechecklist(n.Nbody, Etop)
decldepth--
}
......@@ -400,7 +400,7 @@ func memclrrange(n, v1, v2, a *Node) bool {
n.Nbody.Append(v1)
typecheck(&n.Left, Erv)
typecheckslice(n.Nbody.Slice(), Etop)
typechecklist(n.Nbody, Etop)
walkstmt(&n)
return true
}
......@@ -79,7 +79,7 @@ func typecheckselect(sel *Node) {
}
}
typecheckslice(ncase.Nbody.Slice(), Etop)
typechecklist(ncase.Nbody, Etop)
}
sel.Xoffset = int64(count)
......
......@@ -2215,7 +2215,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
fn.Func.Dupok = true
}
typecheck(&fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop)
typechecklist(fn.Nbody, Etop)
inlcalls(fn)
escAnalyze([]*Node{fn}, false)
......
......@@ -181,7 +181,7 @@ func typecheckswitch(n *Node) {
}
}
typecheckslice(ncase.Nbody.Slice(), Etop)
typechecklist(ncase.Nbody, Etop)
}
lineno = lno
......
......@@ -494,3 +494,72 @@ func (n *Nodes) AppendNodeList(l *NodeList) {
}
}
}
// 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
}
// 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
}
// 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]
}
// nodeSeqIterate returns an iterator over either a *Nodelist or a *Nodes.
func nodeSeqIterate(ns interface{}) nodeSeqIterator {
switch ns := ns.(type) {
case *NodeList:
return &nodeListIterator{ns}
case Nodes:
return &nodesIterator{ns, 0}
default:
panic("can't happen")
}
}
......@@ -34,9 +34,9 @@ func resolve(n *Node) *Node {
return n
}
func typechecklist(l *NodeList, top int) {
for ; l != nil; l = l.Next {
typecheck(&l.N, top)
func typechecklist(l interface{}, top int) {
for it := nodeSeqIterate(l); !it.Done(); it.Next() {
typecheck(it.P(), top)
}
}
......@@ -2073,7 +2073,7 @@ OpSwitch:
}
}
typecheck(&n.Right, Etop)
typecheckslice(n.Nbody.Slice(), Etop)
typechecklist(n.Nbody, Etop)
decldepth--
break OpSwitch
......@@ -2087,7 +2087,7 @@ OpSwitch:
Yyerror("non-bool %v used as if condition", Nconv(n.Left, obj.FmtLong))
}
}
typecheckslice(n.Nbody.Slice(), Etop)
typechecklist(n.Nbody, Etop)
typechecklist(n.Rlist, Etop)
break OpSwitch
......@@ -2137,7 +2137,7 @@ OpSwitch:
case OXCASE:
ok |= Etop
typechecklist(n.List, Erv)
typecheckslice(n.Nbody.Slice(), Etop)
typechecklist(n.Nbody, Etop)
break OpSwitch
case ODCLFUNC:
......
......@@ -3965,7 +3965,7 @@ func walkprintfunc(np **Node, init **NodeList) {
funcbody(fn)
typecheck(&fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop)
typechecklist(fn.Nbody, Etop)
xtop = list(xtop, fn)
Curfn = oldfn
......
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