aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-02-02 12:17:57 -0800
committerDan Scales <danscales@google.com>2021-02-03 01:18:23 +0000
commite633f343ba791e770c6a6c2f8ff3640d2e8ff079 (patch)
tree862cd9c47e985812e60310dd31a75a803b3f584c /src/cmd/compile/internal/noder
parent0d2d6c74644c4e09655225894e6eca2a06aeeef4 (diff)
downloadgo-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.go31
-rw-r--r--src/cmd/compile/internal/noder/helpers.go25
-rw-r--r--src/cmd/compile/internal/noder/noder.go2
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