There's a bunch of implementations of ad hoc, generic IR tree walking code within the compiler frontend.
Examples:
|
if n.Left() != nil && hasCall(n.Left()) { |
|
return true |
|
} |
|
if n.Right() != nil && hasCall(n.Right()) { |
|
return true |
|
} |
|
for _, x := range n.Init().Slice() { |
|
if hasCall(x) { |
|
return true |
|
} |
|
} |
|
for _, x := range n.Body().Slice() { |
|
if hasCall(x) { |
|
return true |
|
} |
|
} |
|
for _, x := range n.List().Slice() { |
|
if hasCall(x) { |
|
return true |
|
} |
|
} |
|
for _, x := range n.Rlist().Slice() { |
|
if hasCall(x) { |
|
return true |
|
} |
|
} |
|
if hascallchan(n.Left()) || hascallchan(n.Right()) { |
|
return true |
|
} |
|
for _, n1 := range n.List().Slice() { |
|
if hascallchan(n1) { |
|
return true |
|
} |
|
} |
|
for _, n2 := range n.Rlist().Slice() { |
|
return v.visit(n.Left()) || v.visit(n.Right()) || |
|
v.visitList(n.List()) || v.visitList(n.Rlist()) || |
|
v.visitList(n.Init()) || v.visitList(n.Body()) |
|
cnt += countNodes(n.Left()) |
|
cnt += countNodes(n.Right()) |
|
for _, n1 := range n.Init().Slice() { |
|
cnt += countNodes(n1) |
|
} |
|
for _, n1 := range n.Body().Slice() { |
|
cnt += countNodes(n1) |
|
} |
|
for _, n1 := range n.List().Slice() { |
|
cnt += countNodes(n1) |
|
} |
|
for _, n1 := range n.Rlist().Slice() { |
|
cnt += countNodes(n1) |
|
} |
|
if a := v.visit(n.Left()); a != nil { |
|
return a |
|
} |
|
if a := v.visit(n.Right()); a != nil { |
|
return a |
|
} |
|
if a := v.visitList(n.List()); a != nil { |
|
return a |
|
} |
|
if a := v.visitList(n.Rlist()); a != nil { |
|
return a |
|
} |
|
if a := v.visitList(n.Init()); a != nil { |
|
return a |
|
} |
|
if a := v.visitList(n.Body()); a != nil { |
|
return a |
|
} |
|
markbreak(labels, n.Left(), implicit) |
|
markbreak(labels, n.Right(), implicit) |
|
markbreaklist(labels, n.Init(), implicit) |
|
markbreaklist(labels, n.Body(), implicit) |
|
markbreaklist(labels, n.List(), implicit) |
|
markbreaklist(labels, n.Rlist(), implicit) |
It should be possible to rewrite a lot of this code to use ir.Inspect or ir.InspectList instead. This will eventually be helpful for getting rid of the generic Left/Right/etc methods.
For the markbreak case (and maybe others), it might be useful to provide ir analogs to ast.Walk and ast.Visitor. (See also how ast.Inspect is implemented, as that API was inspirational for ir.Inspect.)
/cc @cuonglm
There's a bunch of implementations of ad hoc, generic IR tree walking code within the compiler frontend.
Examples:
go/src/cmd/compile/internal/gc/alg.go
Lines 789 to 814 in 351bc2f
go/src/cmd/compile/internal/gc/const.go
Lines 810 to 818 in 351bc2f
go/src/cmd/compile/internal/gc/inl.go
Lines 445 to 447 in 351bc2f
go/src/cmd/compile/internal/gc/inl.go
Lines 490 to 503 in 351bc2f
go/src/cmd/compile/internal/gc/inl.go
Lines 828 to 845 in 351bc2f
go/src/cmd/compile/internal/gc/typecheck.go
Lines 3700 to 3705 in 351bc2f
It should be possible to rewrite a lot of this code to use
ir.Inspectorir.InspectListinstead. This will eventually be helpful for getting rid of the generic Left/Right/etc methods.For the markbreak case (and maybe others), it might be useful to provide ir analogs to
ast.Walkandast.Visitor. (See also how ast.Inspect is implemented, as that API was inspirational for ir.Inspect.)/cc @cuonglm