mirror of
https://github.com/golang/go
synced 2024-11-02 09:28:34 +00:00
cmd/compile/internal/noder: explicit receiver expression handling
This CL adds a helper expression code for receiver addressing; i.e., the implicit addressing, dereferencing, and field selections involved in changing the `x` in `x.M()` into an appropriate expression to pass as an argument to the method. Change-Id: I9be933e2a38c8f94f6a85d95b54f34164e5efb0a Reviewed-on: https://go-review.googlesource.com/c/go/+/421820 Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
29b07037b1
commit
de95dca32f
3 changed files with 50 additions and 2 deletions
|
@ -57,6 +57,7 @@ const (
|
|||
exprMake
|
||||
exprNil
|
||||
exprFuncInst
|
||||
exprRecv
|
||||
)
|
||||
|
||||
type codeAssign int
|
||||
|
|
|
@ -1914,6 +1914,19 @@ func (r *reader) expr() (res ir.Node) {
|
|||
}
|
||||
return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
|
||||
|
||||
case exprRecv:
|
||||
x := r.expr()
|
||||
pos := r.pos()
|
||||
for i, n := 0, r.Len(); i < n; i++ {
|
||||
x = Implicit(DotField(pos, x, r.Len()))
|
||||
}
|
||||
if r.Bool() { // needs deref
|
||||
x = Implicit(Deref(pos, x.Type().Elem(), x))
|
||||
} else if r.Bool() { // needs addr
|
||||
x = Implicit(Addr(pos, x))
|
||||
}
|
||||
return x
|
||||
|
||||
case exprCall:
|
||||
fun := r.expr()
|
||||
if r.Bool() { // method call
|
||||
|
|
|
@ -1540,7 +1540,7 @@ func (w *writer) expr(expr syntax.Expr) {
|
|||
|
||||
case types2.MethodVal:
|
||||
w.Code(exprMethodVal)
|
||||
w.expr(expr.X)
|
||||
w.recvExpr(expr, sel)
|
||||
w.pos(expr)
|
||||
w.selector(sel.Obj())
|
||||
|
||||
|
@ -1697,7 +1697,7 @@ func (w *writer) expr(expr syntax.Expr) {
|
|||
writeFunExpr := func() {
|
||||
if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok {
|
||||
if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
|
||||
w.expr(selector.X)
|
||||
w.recvExpr(selector, sel)
|
||||
w.Bool(true) // method call
|
||||
w.pos(selector)
|
||||
w.selector(sel.Obj())
|
||||
|
@ -1741,6 +1741,40 @@ func (w *writer) optExpr(expr syntax.Expr) {
|
|||
}
|
||||
}
|
||||
|
||||
// recvExpr writes out expr.X, but handles any implicit addressing,
|
||||
// dereferencing, and field selections.
|
||||
func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
|
||||
index := sel.Index()
|
||||
implicits := index[:len(index)-1]
|
||||
|
||||
w.Code(exprRecv)
|
||||
w.expr(expr.X)
|
||||
w.pos(expr)
|
||||
w.Len(len(implicits))
|
||||
|
||||
typ := w.p.typeOf(expr.X)
|
||||
for _, ix := range implicits {
|
||||
typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
|
||||
w.Len(ix)
|
||||
}
|
||||
|
||||
isPtrTo := func(from, to types2.Type) bool {
|
||||
if from, ok := from.(*types2.Pointer); ok {
|
||||
return types2.Identical(from.Elem(), to)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
|
||||
if w.Bool(isPtrTo(typ, recv)) { // needs deref
|
||||
typ = recv
|
||||
} else if w.Bool(isPtrTo(recv, typ)) { // needs addr
|
||||
typ = recv
|
||||
}
|
||||
|
||||
return typ
|
||||
}
|
||||
|
||||
// multiExpr writes a sequence of expressions, where the i'th value is
|
||||
// implicitly converted to dstType(i). It also handles when exprs is a
|
||||
// single, multi-valued expression (e.g., the multi-valued argument in
|
||||
|
|
Loading…
Reference in a new issue