mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
[dev.regabi] cmd/compile: generalize ir/mknode.go
This CL generalizes ir/mknode.go to get rid of most of almost all of its special cases for node field types. The only remaining speciale case now is Field, which doesn't implement Node any more, but perhaps should. To help with removing special cases, node fields can now be tagged with `mknode:"-"` so that mknode ignores them when generating its helper methods. Further, to simplify skipping all of the orig fields, a new origNode helper type is added which declares an orig field marked as `mknode:"-"` and also provides the Orig and SetOrig methods needed to implement the OrigNode interface. Passes toolstash -cmp. Change-Id: Ic68d4f0a9d2ef6e57e9fe87cdc641e5c4859830b Reviewed-on: https://go-review.googlesource.com/c/go/+/280674 Trust: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
82ab3d1448
commit
499851bac8
|
@ -25,6 +25,14 @@ type OrigNode interface {
|
||||||
SetOrig(Node)
|
SetOrig(Node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// origNode may be embedded into a Node to make it implement OrigNode.
|
||||||
|
type origNode struct {
|
||||||
|
orig Node `mknode:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *origNode) Orig() Node { return n.orig }
|
||||||
|
func (n *origNode) SetOrig(o Node) { n.orig = o }
|
||||||
|
|
||||||
// Orig returns the “original” node for n.
|
// Orig returns the “original” node for n.
|
||||||
// If n implements OrigNode, Orig returns n.Orig().
|
// If n implements OrigNode, Orig returns n.Orig().
|
||||||
// Otherwise Orig returns n itself.
|
// Otherwise Orig returns n itself.
|
||||||
|
|
|
@ -14,27 +14,6 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
func maybeDo(x Node, err error, do func(Node) error) error {
|
|
||||||
if x != nil && err == nil {
|
|
||||||
err = do(x)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func maybeDoList(x Nodes, err error, do func(Node) error) error {
|
|
||||||
if err == nil {
|
|
||||||
err = DoList(x, do)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func maybeEdit(x Node, edit func(Node) Node) Node {
|
|
||||||
if x == nil {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
return edit(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// An Expr is a Node that can appear as an expression.
|
// An Expr is a Node that can appear as an expression.
|
||||||
type Expr interface {
|
type Expr interface {
|
||||||
Node
|
Node
|
||||||
|
@ -77,16 +56,6 @@ func (n *miniExpr) Init() Nodes { return n.init }
|
||||||
func (n *miniExpr) PtrInit() *Nodes { return &n.init }
|
func (n *miniExpr) PtrInit() *Nodes { return &n.init }
|
||||||
func (n *miniExpr) SetInit(x Nodes) { n.init = x }
|
func (n *miniExpr) SetInit(x Nodes) { n.init = x }
|
||||||
|
|
||||||
func toNtype(x Node) Ntype {
|
|
||||||
if x == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if _, ok := x.(Ntype); !ok {
|
|
||||||
Dump("not Ntype", x)
|
|
||||||
}
|
|
||||||
return x.(Ntype)
|
|
||||||
}
|
|
||||||
|
|
||||||
// An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1].
|
// An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1].
|
||||||
type AddStringExpr struct {
|
type AddStringExpr struct {
|
||||||
miniExpr
|
miniExpr
|
||||||
|
@ -210,9 +179,6 @@ func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
|
||||||
|
|
||||||
func (*CallExpr) isStmt() {}
|
func (*CallExpr) isStmt() {}
|
||||||
|
|
||||||
func (n *CallExpr) Orig() Node { return n.orig }
|
|
||||||
func (n *CallExpr) SetOrig(x Node) { n.orig = x }
|
|
||||||
|
|
||||||
func (n *CallExpr) SetOp(op Op) {
|
func (n *CallExpr) SetOp(op Op) {
|
||||||
switch op {
|
switch op {
|
||||||
default:
|
default:
|
||||||
|
@ -226,7 +192,7 @@ func (n *CallExpr) SetOp(op Op) {
|
||||||
// A ClosureExpr is a function literal expression.
|
// A ClosureExpr is a function literal expression.
|
||||||
type ClosureExpr struct {
|
type ClosureExpr struct {
|
||||||
miniExpr
|
miniExpr
|
||||||
Func *Func
|
Func *Func `mknode:"-"`
|
||||||
Prealloc *Name
|
Prealloc *Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,8 +236,6 @@ func NewCompLitExpr(pos src.XPos, op Op, typ Ntype, list []Node) *CompLitExpr {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *CompLitExpr) Orig() Node { return n.orig }
|
|
||||||
func (n *CompLitExpr) SetOrig(x Node) { n.orig = x }
|
|
||||||
func (n *CompLitExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
|
func (n *CompLitExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
|
||||||
func (n *CompLitExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
|
func (n *CompLitExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
|
||||||
|
|
||||||
|
@ -286,14 +250,15 @@ func (n *CompLitExpr) SetOp(op Op) {
|
||||||
|
|
||||||
type ConstExpr struct {
|
type ConstExpr struct {
|
||||||
miniExpr
|
miniExpr
|
||||||
val constant.Value
|
|
||||||
origNode
|
origNode
|
||||||
|
val constant.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConstExpr(val constant.Value, orig Node) Node {
|
func NewConstExpr(val constant.Value, orig Node) Node {
|
||||||
n := &ConstExpr{orig: orig, val: val}
|
n := &ConstExpr{val: val}
|
||||||
n.op = OLITERAL
|
n.op = OLITERAL
|
||||||
n.pos = orig.Pos()
|
n.pos = orig.Pos()
|
||||||
|
n.orig = orig
|
||||||
n.SetType(orig.Type())
|
n.SetType(orig.Type())
|
||||||
n.SetTypecheck(orig.Typecheck())
|
n.SetTypecheck(orig.Typecheck())
|
||||||
n.SetDiag(orig.Diag())
|
n.SetDiag(orig.Diag())
|
||||||
|
@ -301,8 +266,6 @@ func NewConstExpr(val constant.Value, orig Node) Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() }
|
func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() }
|
||||||
func (n *ConstExpr) Orig() Node { return n.orig }
|
|
||||||
func (n *ConstExpr) SetOrig(orig Node) { panic(n.no("SetOrig")) }
|
|
||||||
func (n *ConstExpr) Val() constant.Value { return n.val }
|
func (n *ConstExpr) Val() constant.Value { return n.val }
|
||||||
|
|
||||||
// A ConvExpr is a conversion Type(X).
|
// A ConvExpr is a conversion Type(X).
|
||||||
|
@ -664,9 +627,9 @@ type TypeAssertExpr struct {
|
||||||
|
|
||||||
// Runtime type information provided by walkDotType.
|
// Runtime type information provided by walkDotType.
|
||||||
// Caution: These aren't always populated; see walkDotType.
|
// Caution: These aren't always populated; see walkDotType.
|
||||||
SrcType *AddrExpr // *runtime._type for X's type
|
SrcType *AddrExpr `mknode:"-"` // *runtime._type for X's type
|
||||||
DstType *AddrExpr // *runtime._type for Type
|
DstType *AddrExpr `mknode:"-"` // *runtime._type for Type
|
||||||
Itab *AddrExpr // *runtime.itab for Type implementing X's type
|
Itab *AddrExpr `mknode:"-"` // *runtime.itab for Type implementing X's type
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr {
|
func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr {
|
||||||
|
|
|
@ -115,6 +115,10 @@ func NewFunc(pos src.XPos) *Func {
|
||||||
|
|
||||||
func (f *Func) isStmt() {}
|
func (f *Func) isStmt() {}
|
||||||
|
|
||||||
|
func (n *Func) copy() Node { panic(n.no("copy")) }
|
||||||
|
func (n *Func) doChildren(do func(Node) error) error { return doNodes(n.Body, do) }
|
||||||
|
func (n *Func) editChildren(edit func(Node) Node) { editNodes(n.Body, edit) }
|
||||||
|
|
||||||
func (f *Func) Type() *types.Type { return f.Nname.Type() }
|
func (f *Func) Type() *types.Type { return f.Nname.Type() }
|
||||||
func (f *Func) Sym() *types.Sym { return f.Nname.Sym() }
|
func (f *Func) Sym() *types.Sym { return f.Nname.Sym() }
|
||||||
func (f *Func) Linksym() *obj.LSym { return f.Nname.Linksym() }
|
func (f *Func) Linksym() *obj.LSym { return f.Nname.Linksym() }
|
||||||
|
|
|
@ -13,11 +13,16 @@ import (
|
||||||
"go/types"
|
"go/types"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var irPkg *types.Package
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg := &packages.Config{
|
cfg := &packages.Config{
|
||||||
Mode: packages.NeedSyntax | packages.NeedTypes,
|
Mode: packages.NeedSyntax | packages.NeedTypes,
|
||||||
|
@ -26,44 +31,26 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
irPkg = pkgs[0].Types
|
||||||
|
|
||||||
pkg := pkgs[0].Types
|
|
||||||
scope := pkg.Scope()
|
|
||||||
|
|
||||||
lookup := func(name string) *types.Named {
|
|
||||||
return scope.Lookup(name).(*types.TypeName).Type().(*types.Named)
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeType := lookup("Node")
|
|
||||||
ptrNameType := types.NewPointer(lookup("Name"))
|
|
||||||
ntypeType := lookup("Ntype")
|
|
||||||
nodesType := lookup("Nodes")
|
|
||||||
slicePtrCaseClauseType := types.NewSlice(types.NewPointer(lookup("CaseClause")))
|
|
||||||
slicePtrCommClauseType := types.NewSlice(types.NewPointer(lookup("CommClause")))
|
|
||||||
ptrFieldType := types.NewPointer(lookup("Field"))
|
|
||||||
slicePtrFieldType := types.NewSlice(ptrFieldType)
|
|
||||||
ptrIdentType := types.NewPointer(lookup("Ident"))
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
fmt.Fprintln(&buf, "// Code generated by mknode.go. DO NOT EDIT.")
|
fmt.Fprintln(&buf, "// Code generated by mknode.go. DO NOT EDIT.")
|
||||||
fmt.Fprintln(&buf)
|
fmt.Fprintln(&buf)
|
||||||
fmt.Fprintln(&buf, "package ir")
|
fmt.Fprintln(&buf, "package ir")
|
||||||
fmt.Fprintln(&buf)
|
fmt.Fprintln(&buf)
|
||||||
fmt.Fprintln(&buf, `import "fmt"`)
|
fmt.Fprintln(&buf, `import "fmt"`)
|
||||||
|
|
||||||
|
scope := irPkg.Scope()
|
||||||
for _, name := range scope.Names() {
|
for _, name := range scope.Names() {
|
||||||
|
if strings.HasPrefix(name, "mini") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
obj, ok := scope.Lookup(name).(*types.TypeName)
|
obj, ok := scope.Lookup(name).(*types.TypeName)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
typ := obj.Type().(*types.Named)
|
||||||
typName := obj.Name()
|
if !implementsNode(types.NewPointer(typ)) {
|
||||||
typ, ok := obj.Type().(*types.Named).Underlying().(*types.Struct)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(typName, "mini") || !hasMiniNode(typ) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,77 +58,31 @@ func main() {
|
||||||
fmt.Fprintf(&buf, "func (n *%s) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }\n", name)
|
fmt.Fprintf(&buf, "func (n *%s) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }\n", name)
|
||||||
|
|
||||||
switch name {
|
switch name {
|
||||||
case "Name":
|
case "Name", "Func":
|
||||||
fmt.Fprintf(&buf, "func (n *%s) copy() Node {panic(\"%s.copy\")}\n", name, name)
|
// Too specialized to automate.
|
||||||
default:
|
continue
|
||||||
fmt.Fprintf(&buf, "func (n *%s) copy() Node { c := *n\n", name)
|
|
||||||
forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
|
|
||||||
switch {
|
|
||||||
case is(nodesType):
|
|
||||||
fmt.Fprintf(&buf, "c.%s = c.%s.Copy()\n", name, name)
|
|
||||||
case is(slicePtrCaseClauseType):
|
|
||||||
fmt.Fprintf(&buf, "c.%s = copyCases(c.%s)\n", name, name)
|
|
||||||
case is(slicePtrCommClauseType):
|
|
||||||
fmt.Fprintf(&buf, "c.%s = copyComms(c.%s)\n", name, name)
|
|
||||||
case is(ptrFieldType):
|
|
||||||
fmt.Fprintf(&buf, "if c.%s != nil { c.%s = c.%s.copy() }\n", name, name, name)
|
|
||||||
case is(slicePtrFieldType):
|
|
||||||
fmt.Fprintf(&buf, "c.%s = copyFields(c.%s)\n", name, name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
fmt.Fprintf(&buf, "return &c }\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) error) error { var err error\n", name)
|
forNodeFields(typ,
|
||||||
forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
|
"func (n *%[1]s) copy() Node { c := *n\n",
|
||||||
switch {
|
"",
|
||||||
case is(ptrIdentType), is(ptrNameType):
|
"c.%[1]s = copy%[2]s(c.%[1]s)",
|
||||||
fmt.Fprintf(&buf, "if n.%s != nil { err = maybeDo(n.%s, err, do) }\n", name, name)
|
"return &c }\n")
|
||||||
case is(nodeType), is(ntypeType):
|
|
||||||
fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name)
|
|
||||||
case is(nodesType):
|
|
||||||
fmt.Fprintf(&buf, "err = maybeDoList(n.%s, err, do)\n", name)
|
|
||||||
case is(slicePtrCaseClauseType):
|
|
||||||
fmt.Fprintf(&buf, "err = maybeDoCases(n.%s, err, do)\n", name)
|
|
||||||
case is(slicePtrCommClauseType):
|
|
||||||
fmt.Fprintf(&buf, "err = maybeDoComms(n.%s, err, do)\n", name)
|
|
||||||
case is(ptrFieldType):
|
|
||||||
fmt.Fprintf(&buf, "err = maybeDoField(n.%s, err, do)\n", name)
|
|
||||||
case is(slicePtrFieldType):
|
|
||||||
fmt.Fprintf(&buf, "err = maybeDoFields(n.%s, err, do)\n", name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
fmt.Fprintf(&buf, "return err }\n")
|
|
||||||
|
|
||||||
fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name)
|
forNodeFields(typ,
|
||||||
forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
|
"func (n *%[1]s) doChildren(do func(Node) error) error {\n",
|
||||||
switch {
|
"if n.%[1]s != nil { if err := do(n.%[1]s); err != nil { return err } }",
|
||||||
case is(ptrIdentType):
|
"if err := do%[2]s(n.%[1]s, do); err != nil { return err }",
|
||||||
fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Ident) }\n", name, name, name)
|
"return nil }\n")
|
||||||
case is(ptrNameType):
|
|
||||||
fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Name) }\n", name, name, name)
|
forNodeFields(typ,
|
||||||
case is(nodeType):
|
"func (n *%[1]s) editChildren(edit func(Node) Node) {\n",
|
||||||
fmt.Fprintf(&buf, "n.%s = maybeEdit(n.%s, edit)\n", name, name)
|
"if n.%[1]s != nil { n.%[1]s = edit(n.%[1]s).(%[2]s) }",
|
||||||
case is(ntypeType):
|
"edit%[2]s(n.%[1]s, edit)",
|
||||||
fmt.Fprintf(&buf, "n.%s = toNtype(maybeEdit(n.%s, edit))\n", name, name)
|
"}\n")
|
||||||
case is(nodesType):
|
|
||||||
fmt.Fprintf(&buf, "editList(n.%s, edit)\n", name)
|
|
||||||
case is(slicePtrCaseClauseType):
|
|
||||||
fmt.Fprintf(&buf, "editCases(n.%s, edit)\n", name)
|
|
||||||
case is(slicePtrCommClauseType):
|
|
||||||
fmt.Fprintf(&buf, "editComms(n.%s, edit)\n", name)
|
|
||||||
case is(ptrFieldType):
|
|
||||||
fmt.Fprintf(&buf, "editField(n.%s, edit)\n", name)
|
|
||||||
case is(slicePtrFieldType):
|
|
||||||
fmt.Fprintf(&buf, "editFields(n.%s, edit)\n", name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
fmt.Fprintf(&buf, "}\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range []string{"CaseClause", "CommClause"} {
|
makeHelpers()
|
||||||
sliceHelper(&buf, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := format.Source(buf.Bytes())
|
out, err := format.Source(buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -155,20 +96,32 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sliceHelper(buf *bytes.Buffer, name string) {
|
// needHelper maps needed slice helpers from their base name to their
|
||||||
tmpl := fmt.Sprintf(`
|
// respective slice-element type.
|
||||||
func copy%[1]ss(list []*%[2]s) []*%[2]s {
|
var needHelper = map[string]string{}
|
||||||
|
|
||||||
|
func makeHelpers() {
|
||||||
|
var names []string
|
||||||
|
for name := range needHelper {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
fmt.Fprintf(&buf, sliceHelperTmpl, name, needHelper[name])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sliceHelperTmpl = `
|
||||||
|
func copy%[1]s(list []%[2]s) []%[2]s {
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
c := make([]*%[2]s, len(list))
|
c := make([]%[2]s, len(list))
|
||||||
copy(c, list)
|
copy(c, list)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
func maybeDo%[1]ss(list []*%[2]s, err error, do func(Node) error) error {
|
func do%[1]s(list []%[2]s, do func(Node) error) error {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, x := range list {
|
for _, x := range list {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
if err := do(x); err != nil {
|
if err := do(x); err != nil {
|
||||||
|
@ -178,53 +131,100 @@ func maybeDo%[1]ss(list []*%[2]s, err error, do func(Node) error) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func edit%[1]ss(list []*%[2]s, edit func(Node) Node) {
|
func edit%[1]s(list []%[2]s, edit func(Node) Node) {
|
||||||
for i, x := range list {
|
for i, x := range list {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
list[i] = edit(x).(*%[2]s)
|
list[i] = edit(x).(%[2]s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, strings.TrimSuffix(name, "Clause"), name)
|
`
|
||||||
fmt.Fprintln(buf, tmpl)
|
|
||||||
|
func forNodeFields(named *types.Named, prologue, singleTmpl, sliceTmpl, epilogue string) {
|
||||||
|
fmt.Fprintf(&buf, prologue, named.Obj().Name())
|
||||||
|
|
||||||
|
anyField(named.Underlying().(*types.Struct), func(f *types.Var) bool {
|
||||||
|
if f.Embedded() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
name, typ := f.Name(), f.Type()
|
||||||
|
|
||||||
|
slice, _ := typ.Underlying().(*types.Slice)
|
||||||
|
if slice != nil {
|
||||||
|
typ = slice.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
func forNodeFields(typName string, typ *types.Struct, f func(name string, is func(types.Type) bool)) {
|
tmpl, what := singleTmpl, types.TypeString(typ, types.RelativeTo(irPkg))
|
||||||
for i, n := 0, typ.NumFields(); i < n; i++ {
|
if implementsNode(typ) {
|
||||||
v := typ.Field(i)
|
if slice != nil {
|
||||||
if v.Embedded() {
|
helper := strings.TrimPrefix(what, "*") + "s"
|
||||||
if typ, ok := v.Type().Underlying().(*types.Struct); ok {
|
needHelper[helper] = what
|
||||||
forNodeFields(typName, typ, f)
|
tmpl, what = sliceTmpl, helper
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
} else if what == "*Field" {
|
||||||
|
// Special case for *Field.
|
||||||
|
tmpl = sliceTmpl
|
||||||
|
if slice != nil {
|
||||||
|
what = "Fields"
|
||||||
|
} else {
|
||||||
|
what = "Field"
|
||||||
}
|
}
|
||||||
switch typName {
|
} else {
|
||||||
case "Func":
|
return false
|
||||||
if strings.ToLower(strings.TrimSuffix(v.Name(), "_")) != "body" {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
case "Name":
|
|
||||||
continue
|
if tmpl == "" {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
switch v.Name() {
|
|
||||||
case "orig":
|
// Allow template to not use all arguments without
|
||||||
continue
|
// upsetting fmt.Printf.
|
||||||
|
s := fmt.Sprintf(tmpl+"\x00 %[1]s %[2]s", name, what)
|
||||||
|
fmt.Fprintln(&buf, s[:strings.LastIndex(s, "\x00")])
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Fprintf(&buf, epilogue)
|
||||||
}
|
}
|
||||||
f(v.Name(), func(t types.Type) bool { return types.Identical(t, v.Type()) })
|
|
||||||
|
func implementsNode(typ types.Type) bool {
|
||||||
|
if _, ok := typ.Underlying().(*types.Interface); ok {
|
||||||
|
// TODO(mdempsky): Check the interface implements Node.
|
||||||
|
// Worst case, node_gen.go will fail to compile if we're wrong.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ptr, ok := typ.(*types.Pointer); ok {
|
||||||
|
if str, ok := ptr.Elem().Underlying().(*types.Struct); ok {
|
||||||
|
return anyField(str, func(f *types.Var) bool {
|
||||||
|
return f.Embedded() && f.Name() == "miniNode"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasMiniNode(typ *types.Struct) bool {
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func anyField(typ *types.Struct, pred func(f *types.Var) bool) bool {
|
||||||
for i, n := 0, typ.NumFields(); i < n; i++ {
|
for i, n := 0, typ.NumFields(); i < n; i++ {
|
||||||
v := typ.Field(i)
|
if value, ok := reflect.StructTag(typ.Tag(i)).Lookup("mknode"); ok {
|
||||||
if v.Name() == "miniNode" {
|
if value != "-" {
|
||||||
|
panic(fmt.Sprintf("unexpected tag value: %q", value))
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
f := typ.Field(i)
|
||||||
|
if pred(f) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if v.Embedded() {
|
if f.Embedded() {
|
||||||
if typ, ok := v.Type().Underlying().(*types.Struct); ok && hasMiniNode(typ) {
|
if typ, ok := f.Type().Underlying().(*types.Struct); ok {
|
||||||
|
if anyField(typ, pred) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,10 @@ type Name struct {
|
||||||
|
|
||||||
func (n *Name) isExpr() {}
|
func (n *Name) isExpr() {}
|
||||||
|
|
||||||
|
func (n *Name) copy() Node { panic(n.no("copy")) }
|
||||||
|
func (n *Name) doChildren(do func(Node) error) error { return nil }
|
||||||
|
func (n *Name) editChildren(edit func(Node) Node) {}
|
||||||
|
|
||||||
// CloneName makes a cloned copy of the name.
|
// CloneName makes a cloned copy of the name.
|
||||||
// It's not ir.Copy(n) because in general that operation is a mistake on names,
|
// It's not ir.Copy(n) because in general that operation is a mistake on names,
|
||||||
// which uniquely identify variables.
|
// which uniquely identify variables.
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -335,9 +335,6 @@ func NewReturnStmt(pos src.XPos, results []Node) *ReturnStmt {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ReturnStmt) Orig() Node { return n.orig }
|
|
||||||
func (n *ReturnStmt) SetOrig(x Node) { n.orig = x }
|
|
||||||
|
|
||||||
// A SelectStmt is a block: { Cases }.
|
// A SelectStmt is a block: { Cases }.
|
||||||
type SelectStmt struct {
|
type SelectStmt struct {
|
||||||
miniStmt
|
miniStmt
|
||||||
|
|
|
@ -185,45 +185,32 @@ func (f *Field) String() string {
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Field) copy() *Field {
|
// TODO(mdempsky): Make Field a Node again so these can be generated?
|
||||||
|
// Fields are Nodes in go/ast and cmd/compile/internal/syntax.
|
||||||
|
|
||||||
|
func copyField(f *Field) *Field {
|
||||||
|
if f == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
c := *f
|
c := *f
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
func doField(f *Field, do func(Node) error) error {
|
||||||
func copyFields(list []*Field) []*Field {
|
if f == nil {
|
||||||
out := make([]*Field, len(list))
|
return nil
|
||||||
copy(out, list)
|
|
||||||
for i, f := range out {
|
|
||||||
out[i] = f.copy()
|
|
||||||
}
|
}
|
||||||
return out
|
if f.Decl != nil {
|
||||||
}
|
if err := do(f.Decl); err != nil {
|
||||||
|
|
||||||
func maybeDoField(f *Field, err error, do func(Node) error) error {
|
|
||||||
if f != nil {
|
|
||||||
if err == nil && f.Decl != nil {
|
|
||||||
err = do(f.Decl)
|
|
||||||
}
|
|
||||||
if err == nil && f.Ntype != nil {
|
|
||||||
err = do(f.Ntype)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func maybeDoFields(list []*Field, err error, do func(Node) error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, f := range list {
|
|
||||||
err = maybeDoField(f, err, do)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if f.Ntype != nil {
|
||||||
|
if err := do(f.Ntype); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func editField(f *Field, edit func(Node) Node) {
|
func editField(f *Field, edit func(Node) Node) {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return
|
return
|
||||||
|
@ -232,10 +219,25 @@ func editField(f *Field, edit func(Node) Node) {
|
||||||
f.Decl = edit(f.Decl).(*Name)
|
f.Decl = edit(f.Decl).(*Name)
|
||||||
}
|
}
|
||||||
if f.Ntype != nil {
|
if f.Ntype != nil {
|
||||||
f.Ntype = toNtype(edit(f.Ntype))
|
f.Ntype = edit(f.Ntype).(Ntype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyFields(list []*Field) []*Field {
|
||||||
|
out := make([]*Field, len(list))
|
||||||
|
for i, f := range list {
|
||||||
|
out[i] = copyField(f)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
func doFields(list []*Field, do func(Node) error) error {
|
||||||
|
for _, x := range list {
|
||||||
|
if err := doField(x, do); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func editFields(list []*Field, edit func(Node) Node) {
|
func editFields(list []*Field, edit func(Node) Node) {
|
||||||
for _, f := range list {
|
for _, f := range list {
|
||||||
editField(f, edit)
|
editField(f, edit)
|
||||||
|
|
|
@ -106,14 +106,7 @@ func DoChildren(n Node, do func(Node) error) error {
|
||||||
// Note that DoList only calls do on the nodes in the list, not their children.
|
// Note that DoList only calls do on the nodes in the list, not their children.
|
||||||
// If x's children should be processed, do(x) must call DoChildren(x, do) itself.
|
// If x's children should be processed, do(x) must call DoChildren(x, do) itself.
|
||||||
func DoList(list Nodes, do func(Node) error) error {
|
func DoList(list Nodes, do func(Node) error) error {
|
||||||
for _, x := range list {
|
return doNodes(list, do)
|
||||||
if x != nil {
|
|
||||||
if err := do(x); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit visits each non-nil node x in the IR tree rooted at n
|
// Visit visits each non-nil node x in the IR tree rooted at n
|
||||||
|
@ -210,16 +203,3 @@ func EditChildren(n Node, edit func(Node) Node) {
|
||||||
}
|
}
|
||||||
n.editChildren(edit)
|
n.editChildren(edit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// editList calls edit on each non-nil node x in the list,
|
|
||||||
// saving the result of edit back into the list.
|
|
||||||
//
|
|
||||||
// Note that editList only calls edit on the nodes in the list, not their children.
|
|
||||||
// If x's children should be processed, edit(x) must call EditChildren(x, edit) itself.
|
|
||||||
func editList(list Nodes, edit func(Node) Node) {
|
|
||||||
for i, x := range list {
|
|
||||||
if x != nil {
|
|
||||||
list[i] = edit(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue