aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-01-22 01:46:42 -0800
committerMatthew Dempsky <mdempsky@google.com>2021-01-22 19:23:32 +0000
commite4ef30a66751c39bdd24764763531f1a4c325845 (patch)
tree90f5ba028e2d0c70c39d1257324276c3b9ca5a36
parent626406b703a418acd41c4163b5c58d832c09e1e4 (diff)
downloadgo-e4ef30a66751c39bdd24764763531f1a4c325845.tar.gz
go-e4ef30a66751c39bdd24764763531f1a4c325845.zip
[dev.typeparams] cmd/compile: refactor irgen's handling of ":="
The previous code was stylized after noder, which was written when it was more idiomatic to simple create a gc.Node and then populate and shuffle around its fields as appropriate. Now with package ir, it's somewhat nicer to compute all the fields up front and pass them to the constructor functions, rather than passing nil and populating the fields afterwards. Net addition of lines of code, but I think the new code is overall still somewhat simpler, and will be easier to refactor out into code for helpers.go. Change-Id: I8c6f6b65e0a8317129655a0fc493d8af75527b97 Reviewed-on: https://go-review.googlesource.com/c/go/+/285732 Trust: Matthew Dempsky <mdempsky@google.com> Trust: Dan Scales <danscales@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com>
-rw-r--r--src/cmd/compile/internal/noder/stmt.go73
1 files changed, 48 insertions, 25 deletions
diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go
index 267a34dbc8..1775116f41 100644
--- a/src/cmd/compile/internal/noder/stmt.go
+++ b/src/cmd/compile/internal/noder/stmt.go
@@ -59,19 +59,17 @@ func (g *irgen) stmt0(stmt syntax.Stmt) ir.Node {
return ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs))
}
+ names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def)
rhs := g.exprList(stmt.Rhs)
- if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
- n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, nil, nil)
- n.Def = stmt.Op == syntax.Def
- n.Lhs = g.assignList(stmt.Lhs, n, n.Def)
- n.Rhs = rhs
+
+ if len(lhs) == 1 && len(rhs) == 1 {
+ n := ir.NewAssignStmt(g.pos(stmt), lhs[0], rhs[0])
+ n.Def = initDefn(n, names)
return n
}
- n := ir.NewAssignStmt(g.pos(stmt), nil, nil)
- n.Def = stmt.Op == syntax.Def
- n.X = g.assignList(stmt.Lhs, n, n.Def)[0]
- n.Y = rhs[0]
+ n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs)
+ n.Def = initDefn(n, names)
return n
case *syntax.BranchStmt:
@@ -119,9 +117,9 @@ func (g *irgen) op(op syntax.Operator, ops []ir.Op) ir.Op {
return ops[op]
}
-func (g *irgen) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.Node {
- if !colas {
- return g.exprList(expr)
+func (g *irgen) assignList(expr syntax.Expr, def bool) ([]*ir.Name, []ir.Node) {
+ if !def {
+ return nil, g.exprList(expr)
}
var exprs []syntax.Expr
@@ -131,6 +129,7 @@ func (g *irgen) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.
exprs = []syntax.Expr{expr}
}
+ var names []*ir.Name
res := make([]ir.Node, len(exprs))
for i, expr := range exprs {
expr := expr.(*syntax.Name)
@@ -145,11 +144,28 @@ func (g *irgen) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.
}
name, _ := g.def(expr)
- name.Defn = defn
- defn.PtrInit().Append(ir.NewDecl(name.Pos(), ir.ODCL, name))
+ names = append(names, name)
res[i] = name
}
- return res
+
+ return names, res
+}
+
+// initDefn marks the given names as declared by defn and populates
+// its Init field with ODCL nodes. It then reports whether any names
+// were so declared, which can be used to initialize defn.Def.
+func initDefn(defn ir.InitNode, names []*ir.Name) bool {
+ if len(names) == 0 {
+ return false
+ }
+
+ init := make([]ir.Node, len(names))
+ for i, name := range names {
+ name.Defn = defn
+ init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
+ }
+ defn.SetInit(init)
+ return true
}
func (g *irgen) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
@@ -171,18 +187,25 @@ func (g *irgen) ifStmt(stmt *syntax.IfStmt) ir.Node {
return g.init(init, n)
}
+// unpackTwo returns the first two nodes in list. If list has fewer
+// than 2 nodes, then the missing nodes are replaced with nils.
+func unpackTwo(list []ir.Node) (fst, snd ir.Node) {
+ switch len(list) {
+ case 0:
+ return nil, nil
+ case 1:
+ return list[0], nil
+ default:
+ return list[0], list[1]
+ }
+}
+
func (g *irgen) forStmt(stmt *syntax.ForStmt) ir.Node {
if r, ok := stmt.Init.(*syntax.RangeClause); ok {
- n := ir.NewRangeStmt(g.pos(r), nil, nil, g.expr(r.X), nil)
- if r.Lhs != nil {
- n.Def = r.Def
- lhs := g.assignList(r.Lhs, n, n.Def)
- n.Key = lhs[0]
- if len(lhs) > 1 {
- n.Value = lhs[1]
- }
- }
- n.Body = g.blockStmt(stmt.Body)
+ names, lhs := g.assignList(r.Lhs, r.Def)
+ key, value := unpackTwo(lhs)
+ n := ir.NewRangeStmt(g.pos(r), key, value, g.expr(r.X), g.blockStmt(stmt.Body))
+ n.Def = initDefn(n, names)
return n
}