mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] cmd/compile: use nil instead of syntax.ImplicitOne
Represent x++/-- as x +=/-= with the RHS of the assignment being nil rather than syntax.ImplicitOne. Dependent code already had to check for syntax.ImplicitOne, but then shared some existing code for regular assignment operations. Now always handle this case fully explicit, which simplifies the code. Change-Id: I28c7918153c27cbbf97b041d0c85ff027c58687c Reviewed-on: https://go-review.googlesource.com/c/go/+/285172 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
2427f6e6c0
commit
18bd7aa625
10 changed files with 48 additions and 53 deletions
|
|
@ -19,10 +19,6 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if expr == syntax.ImplicitOne {
|
|
||||||
base.Fatalf("expr of ImplicitOne")
|
|
||||||
}
|
|
||||||
|
|
||||||
if expr, ok := expr.(*syntax.Name); ok && expr.Value == "_" {
|
if expr, ok := expr.(*syntax.Name); ok && expr.Value == "_" {
|
||||||
return ir.BlankNode
|
return ir.BlankNode
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -677,11 +677,7 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
|
||||||
case *syntax.Name:
|
case *syntax.Name:
|
||||||
return p.mkname(expr)
|
return p.mkname(expr)
|
||||||
case *syntax.BasicLit:
|
case *syntax.BasicLit:
|
||||||
pos := base.Pos
|
n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
|
||||||
if expr != syntax.ImplicitOne { // ImplicitOne doesn't have a unique position
|
|
||||||
pos = p.pos(expr)
|
|
||||||
}
|
|
||||||
n := ir.NewBasicLit(pos, p.basicLit(expr))
|
|
||||||
if expr.Kind == syntax.RuneLit {
|
if expr.Kind == syntax.RuneLit {
|
||||||
n.SetType(types.UntypedRune)
|
n.SetType(types.UntypedRune)
|
||||||
}
|
}
|
||||||
|
|
@ -1039,9 +1035,15 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
|
||||||
case *syntax.DeclStmt:
|
case *syntax.DeclStmt:
|
||||||
return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
|
return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
|
||||||
case *syntax.AssignStmt:
|
case *syntax.AssignStmt:
|
||||||
|
if stmt.Rhs == nil {
|
||||||
|
pos := p.pos(stmt)
|
||||||
|
n := ir.NewAssignOpStmt(pos, p.binOp(stmt.Op), p.expr(stmt.Lhs), ir.NewBasicLit(pos, one))
|
||||||
|
n.IncDec = true
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
if stmt.Op != 0 && stmt.Op != syntax.Def {
|
if stmt.Op != 0 && stmt.Op != syntax.Def {
|
||||||
n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
|
n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
|
||||||
n.IncDec = stmt.Rhs == syntax.ImplicitOne
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1502,7 +1504,7 @@ func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) setlineno(n syntax.Node) {
|
func (p *noder) setlineno(n syntax.Node) {
|
||||||
if n != nil && n != syntax.ImplicitOne {
|
if n != nil {
|
||||||
base.Pos = p.pos(n)
|
base.Pos = p.pos(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ func (g *irgen) stmt0(stmt syntax.Stmt) ir.Node {
|
||||||
case *syntax.AssignStmt:
|
case *syntax.AssignStmt:
|
||||||
if stmt.Op != 0 && stmt.Op != syntax.Def {
|
if stmt.Op != 0 && stmt.Op != syntax.Def {
|
||||||
op := g.op(stmt.Op, binOps[:])
|
op := g.op(stmt.Op, binOps[:])
|
||||||
if stmt.Rhs == syntax.ImplicitOne {
|
if stmt.Rhs == nil {
|
||||||
return IncDec(g.pos(stmt), op, g.expr(stmt.Lhs))
|
return IncDec(g.pos(stmt), op, g.expr(stmt.Lhs))
|
||||||
}
|
}
|
||||||
return ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs))
|
return ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs))
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,7 @@ type (
|
||||||
|
|
||||||
AssignStmt struct {
|
AssignStmt struct {
|
||||||
Op Operator // 0 means no operation
|
Op Operator // 0 means no operation
|
||||||
Lhs, Rhs Expr // Rhs == ImplicitOne means Lhs++ (Op == Add) or Lhs-- (Op == Sub)
|
Lhs, Rhs Expr // Rhs == nil means Lhs++ (Op == Add) or Lhs-- (Op == Sub)
|
||||||
simpleStmt
|
simpleStmt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1874,10 +1874,6 @@ func (p *parser) badExpr() *BadExpr {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
// We represent x++, x-- as assignments x += ImplicitOne, x -= ImplicitOne.
|
|
||||||
// ImplicitOne should not be used elsewhere.
|
|
||||||
var ImplicitOne = &BasicLit{Value: "1"}
|
|
||||||
|
|
||||||
// SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
|
// SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
|
||||||
func (p *parser) simpleStmt(lhs Expr, keyword token) SimpleStmt {
|
func (p *parser) simpleStmt(lhs Expr, keyword token) SimpleStmt {
|
||||||
if trace {
|
if trace {
|
||||||
|
|
@ -1910,7 +1906,7 @@ func (p *parser) simpleStmt(lhs Expr, keyword token) SimpleStmt {
|
||||||
// lhs++ or lhs--
|
// lhs++ or lhs--
|
||||||
op := p.op
|
op := p.op
|
||||||
p.next()
|
p.next()
|
||||||
return p.newAssignStmt(pos, op, lhs, ImplicitOne)
|
return p.newAssignStmt(pos, op, lhs, nil)
|
||||||
|
|
||||||
case _Arrow:
|
case _Arrow:
|
||||||
// lhs <- rhs
|
// lhs <- rhs
|
||||||
|
|
|
||||||
|
|
@ -549,7 +549,7 @@ func (p *printer) printRawNode(n Node) {
|
||||||
|
|
||||||
case *AssignStmt:
|
case *AssignStmt:
|
||||||
p.print(n.Lhs)
|
p.print(n.Lhs)
|
||||||
if n.Rhs == ImplicitOne {
|
if n.Rhs == nil {
|
||||||
// TODO(gri) This is going to break the mayCombine
|
// TODO(gri) This is going to break the mayCombine
|
||||||
// check once we enable that again.
|
// check once we enable that again.
|
||||||
p.print(n.Op, n.Op) // ++ or --
|
p.print(n.Op, n.Op) // ++ or --
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,9 @@ func (w *walker) node(n Node) {
|
||||||
|
|
||||||
case *AssignStmt:
|
case *AssignStmt:
|
||||||
w.node(n.Lhs)
|
w.node(n.Lhs)
|
||||||
w.node(n.Rhs)
|
if n.Rhs != nil {
|
||||||
|
w.node(n.Rhs)
|
||||||
|
}
|
||||||
|
|
||||||
case *BranchStmt:
|
case *BranchStmt:
|
||||||
if n.Label != nil {
|
if n.Label != nil {
|
||||||
|
|
|
||||||
|
|
@ -889,6 +889,7 @@ var binaryOpPredicates = opPredicates{
|
||||||
}
|
}
|
||||||
|
|
||||||
// The binary expression e may be nil. It's passed in for better error messages only.
|
// The binary expression e may be nil. It's passed in for better error messages only.
|
||||||
|
// TODO(gri) revisit use of e and opPos
|
||||||
func (check *Checker) binary(x *operand, e *syntax.Operation, lhs, rhs syntax.Expr, op syntax.Operator, opPos syntax.Pos) {
|
func (check *Checker) binary(x *operand, e *syntax.Operation, lhs, rhs syntax.Expr, op syntax.Operator, opPos syntax.Pos) {
|
||||||
var y operand
|
var y operand
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||||
return n.Pos()
|
return n.Pos()
|
||||||
case *syntax.AssignStmt:
|
case *syntax.AssignStmt:
|
||||||
m = n.Rhs
|
m = n.Rhs
|
||||||
if m == syntax.ImplicitOne {
|
if m == nil {
|
||||||
p := endPos(n.Lhs)
|
p := endPos(n.Lhs)
|
||||||
return syntax.MakePos(p.Base(), p.Line(), p.Col()+2)
|
return syntax.MakePos(p.Base(), p.Line(), p.Col()+2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -367,47 +367,45 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
|
||||||
|
|
||||||
case *syntax.AssignStmt:
|
case *syntax.AssignStmt:
|
||||||
lhs := unpackExpr(s.Lhs)
|
lhs := unpackExpr(s.Lhs)
|
||||||
rhs := unpackExpr(s.Rhs)
|
if s.Rhs == nil {
|
||||||
if s.Op == 0 || s.Op == syntax.Def {
|
// x++ or x--
|
||||||
// regular assignment or short variable declaration
|
if len(lhs) != 1 {
|
||||||
if len(lhs) == 0 {
|
check.invalidASTf(s, "%s%s requires one operand", s.Op, s.Op)
|
||||||
check.invalidASTf(s, "missing lhs in assignment")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.Op == syntax.Def {
|
|
||||||
check.shortVarDecl(s.Pos(), lhs, rhs)
|
|
||||||
} else {
|
|
||||||
// regular assignment
|
|
||||||
check.assignVars(lhs, rhs)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// assignment operations
|
|
||||||
if len(lhs) != 1 || len(rhs) != 1 {
|
|
||||||
check.errorf(s, "assignment operation %s requires single-valued expressions", s.Op)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// provide better error messages for x++ and x--
|
|
||||||
if rhs[0] == syntax.ImplicitOne {
|
|
||||||
var x operand
|
|
||||||
check.expr(&x, lhs[0])
|
|
||||||
if x.mode == invalid {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !isNumeric(x.typ) {
|
|
||||||
check.invalidOpf(lhs[0], "%s%s%s (non-numeric type %s)", lhs[0], s.Op, s.Op, x.typ)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var x operand
|
var x operand
|
||||||
check.binary(&x, nil, lhs[0], rhs[0], s.Op, rhs[0].Pos()) // TODO(gri) should have TokPos here (like in go/types)
|
check.expr(&x, lhs[0])
|
||||||
if x.mode == invalid {
|
if x.mode == invalid {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !isNumeric(x.typ) {
|
||||||
|
check.invalidOpf(lhs[0], "%s%s%s (non-numeric type %s)", lhs[0], s.Op, s.Op, x.typ)
|
||||||
|
return
|
||||||
|
}
|
||||||
check.assignVar(lhs[0], &x)
|
check.assignVar(lhs[0], &x)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rhs := unpackExpr(s.Rhs)
|
||||||
|
switch s.Op {
|
||||||
|
case 0:
|
||||||
|
check.assignVars(lhs, rhs)
|
||||||
|
return
|
||||||
|
case syntax.Def:
|
||||||
|
check.shortVarDecl(s.Pos(), lhs, rhs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// assignment operations
|
||||||
|
if len(lhs) != 1 || len(rhs) != 1 {
|
||||||
|
check.errorf(s, "assignment operation %s requires single-valued expressions", s.Op)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var x operand
|
||||||
|
check.binary(&x, nil, lhs[0], rhs[0], s.Op, s.Pos())
|
||||||
|
check.assignVar(lhs[0], &x)
|
||||||
|
|
||||||
// case *syntax.GoStmt:
|
// case *syntax.GoStmt:
|
||||||
// check.suspendedCall("go", s.Call)
|
// check.suspendedCall("go", s.Call)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue