cmd/compile: refactor method expression detection
Eliminates lots of ad hoc code for recognizing the same thing in
different ways.
Passes toolstash-check.
Change-Id: Ic0bb005308e96331b4ef30f455b860e476725b61
Reviewed-on: https://go-review.googlesource.com/73190
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index 9564a59..9950f8b 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -1192,7 +1192,7 @@
// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
// but for export, this should be rendered as (*pkg.T).meth.
// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
- if n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
+ if n.isMethodExpression() {
p.op(OXDOT)
p.pos(n)
p.expr(n.Left) // n.Left.Op == OTYPE
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 8175119..2c44785 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -112,10 +112,10 @@
switch n.Op {
case ONAME:
switch n.Class() {
- // methods will be printed along with their type
- // nodes for T.Method expressions
case PFUNC:
- if n.Left != nil && n.Left.Op == OTYPE {
+ // methods will be printed along with their type
+ // nodes for T.Method expressions
+ if n.isMethodExpression() {
break
}
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index 9a43460..1b52acd 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -244,7 +244,7 @@
break
}
- if n.isMethodCalledAsFunction() {
+ if n.Left.isMethodExpression() {
if d := asNode(n.Left.Sym.Def); d != nil && d.Func.Inl.Len() != 0 {
v.budget -= d.Func.InlCost
break
@@ -536,7 +536,7 @@
}
if n.Left.Func != nil && n.Left.Func.Inl.Len() != 0 && !isIntrinsicCall(n) { // normal case
n = mkinlcall(n, n.Left, n.Isddd())
- } else if n.isMethodCalledAsFunction() && asNode(n.Left.Sym.Def) != nil {
+ } else if n.Left.isMethodExpression() && asNode(n.Left.Sym.Def) != nil {
n = mkinlcall(n, asNode(n.Left.Sym.Def), n.Isddd())
} else if n.Left.Op == OCLOSURE {
if f := inlinableClosure(n.Left); f != nil {
@@ -1095,7 +1095,3 @@
pos.SetBase(newbase)
return Ctxt.PosTable.XPos(pos)
}
-
-func (n *Node) isMethodCalledAsFunction() bool {
- return n.Left.Op == ONAME && n.Left.Left != nil && n.Left.Left.Op == OTYPE && n.Left.Right != nil && n.Left.Right.Op == ONAME
-}
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index e884ab1..3af2460 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -44,7 +44,7 @@
init1(n1, out)
}
- if n.Left != nil && n.Type != nil && n.Left.Op == OTYPE && n.Class() == PFUNC {
+ if n.isMethodExpression() {
// Methods called as Type.Method(receiver, ...).
// Definitions for method expressions are stored in type->nname.
init1(asNode(n.Type.FuncType().Nname), out)
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 68067bf..9a07f0e 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -209,6 +209,11 @@
return false
}
+// isMethodExpression reports whether n represents a method expression T.M.
+func (n *Node) isMethodExpression() bool {
+ return n.Op == ONAME && n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME
+}
+
// funcname returns the name of the function n.
func (n *Node) funcname() string {
if n == nil || n.Func == nil || n.Func.Nname == nil {
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 78c59b5..f6e3633 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -2709,7 +2709,7 @@
// call is the expression being called, not the overall call.
// Method expressions have the form T.M, and the compiler has
// rewritten those to ONAME nodes but left T in Left.
- if call.Op == ONAME && call.Left != nil && call.Left.Op == OTYPE {
+ if call.isMethodExpression() {
yyerror("not enough arguments in call to method expression %v%s", call, details)
} else {
yyerror("not enough arguments in call to %v%s", call, details)