diff options
| author | Dan Scales <danscales@google.com> | 2021-02-02 12:17:57 -0800 |
|---|---|---|
| committer | Dan Scales <danscales@google.com> | 2021-02-03 01:18:23 +0000 |
| commit | e633f343ba791e770c6a6c2f8ff3640d2e8ff079 (patch) | |
| tree | 862cd9c47e985812e60310dd31a75a803b3f584c /src/cmd/compile/internal/noder | |
| parent | 0d2d6c74644c4e09655225894e6eca2a06aeeef4 (diff) | |
| download | go-e633f343ba791e770c6a6c2f8ff3640d2e8ff079.tar.xz | |
[dev.typeparams] cmd/compile: add OFUNCINST/OTYPEINST nodes for generic func/type instantiation
Expresses things more clearly, especially in cases like 'f := min[int]'
where we create a xsgeneric function instantiation, but don't immediately
call it.
min[int](2, 3) now looks like:
. CALLFUNC tc(1) Use:1 int # min1.go:11 int
. . FUNCINST tc(1) FUNC-func(int, int) int # min1.go:11 FUNC-func(int, int) int
. . . NAME-main.min tc(1) Class:PFUNC Offset:0 Used FUNC-func[T](T, T) T # min1.go:3
. . FUNCINST-Targs
. . . TYPE .int Offset:0 type int
. CALLFUNC-Args
. . LITERAL-2 tc(1) int # min1.go:11
. . LITERAL-3 tc(1) int # min1.go:11
Remove the targs parameter from ir.NewCallExpr(), not needed anymore,
since type arguments are included in the FUNCINST.
Change-Id: I23438b75288330475294d7ace239ba64acfa641e
Reviewed-on: https://go-review.googlesource.com/c/go/+/288951
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Dan Scales <danscales@google.com>
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/noder')
| -rw-r--r-- | src/cmd/compile/internal/noder/expr.go | 31 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/helpers.go | 25 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/noder.go | 2 |
3 files changed, 24 insertions, 34 deletions
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 41d54441d4..3c18bdcc24 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -99,23 +99,28 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } return Call(pos, g.typ(typ), g.expr(expr.Fun), g.exprs(expr.ArgList), expr.HasDots) case *syntax.IndexExpr: - var index ir.Node - - // We are using IndexExpr in two ways, as an standard index - // operation (with expression) and as a function/type - // instantiation (with a type list). We will soon make this - // clearer by having separate function/type instantiation nodes. + var targs []ir.Node if _, ok := expr.Index.(*syntax.ListExpr); ok { - // List of types for a generic function call or type instantiation - index = ir.NewListExpr(pos, g.exprList(expr.Index)) + targs = g.exprList(expr.Index) } else { - index = g.expr(expr.Index) - if index.Op() == ir.OTYPE { - // Single type for a generic function call or type instantiation - index = ir.NewListExpr(pos, []ir.Node{index}) + index := g.expr(expr.Index) + if index.Op() != ir.OTYPE { + // This is just a normal index expression + return Index(pos, g.expr(expr.X), index) } + // This is generic function instantiation with a single type + targs = []ir.Node{index} + } + // This is a generic function instantiation + x := g.expr(expr.X) + if x.Op() != ir.ONAME || x.Type().Kind() != types.TFUNC { + panic("Incorrect argument for generic func instantiation") } - return Index(pos, g.typ(typ), g.expr(expr.X), index) + // This could also be an OTYPEINST once we can handle those examples. + n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs) + typed(g.typ(typ), n) + return n + case *syntax.ParenExpr: return g.expr(expr.X) // skip parens; unneeded after parse+typecheck case *syntax.SelectorExpr: diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index d97dacfc8b..fcbb3a6ce5 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -83,13 +83,13 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) // TODO(mdempsky): This should not be so difficult. if fun.Op() == ir.OTYPE { // Actually a type conversion, not a function call. - n := ir.NewCallExpr(pos, ir.OCALL, fun, nil, args) + n := ir.NewCallExpr(pos, ir.OCALL, fun, args) return typecheck.Expr(n) } if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 { // Call to a builtin function. - n := ir.NewCallExpr(pos, ir.OCALL, fun, nil, args) + n := ir.NewCallExpr(pos, ir.OCALL, fun, args) n.IsDDD = dots switch fun.BuiltinOp { case ir.OCLOSE, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN: @@ -116,20 +116,10 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } } - var targs []ir.Node - if indexExpr, ok := fun.(*ir.IndexExpr); ok { - if indexExpr.Index.Op() == ir.OLIST { - // Called function is an instantiated generic function - fun = indexExpr.X - // Don't need to copy, since the node list was just created - targs = indexExpr.Index.(*ir.ListExpr).List - } - } - - n := ir.NewCallExpr(pos, ir.OCALL, fun, targs, args) + n := ir.NewCallExpr(pos, ir.OCALL, fun, args) n.IsDDD = dots - if targs == nil { + if n.X.Op() != ir.OFUNCINST { // If no type params, still do normal typechecking, since we're // still missing some things done by tcCall below (mainly // typecheckargs and typecheckaste). @@ -233,12 +223,7 @@ func method(typ *types.Type, index int) *types.Field { return types.ReceiverBaseType(typ).Methods().Index(index) } -func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node { - if index.Op() == ir.OLIST { - n := ir.NewIndexExpr(pos, x, index) - typed(typ, n) - return n - } +func Index(pos src.XPos, x, index ir.Node) ir.Node { // TODO(mdempsky): Avoid typecheck.Expr (which will call tcIndex) return typecheck.Expr(ir.NewIndexExpr(pos, x, index)) } diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 492c2c242a..1c38f1a934 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -755,7 +755,7 @@ func (p *noder) expr(expr syntax.Expr) ir.Node { } return ir.NewBinaryExpr(pos, op, x, y) case *syntax.CallExpr: - n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), nil, p.exprs(expr.ArgList)) + n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList)) n.IsDDD = expr.HasDots return n |
