return nil
}
- if expr == syntax.ImplicitOne {
- base.Fatalf("expr of ImplicitOne")
- }
-
if expr, ok := expr.(*syntax.Name); ok && expr.Value == "_" {
return ir.BlankNode
}
case *syntax.Name:
return p.mkname(expr)
case *syntax.BasicLit:
- pos := base.Pos
- if expr != syntax.ImplicitOne { // ImplicitOne doesn't have a unique position
- pos = p.pos(expr)
- }
- n := ir.NewBasicLit(pos, p.basicLit(expr))
+ n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
if expr.Kind == syntax.RuneLit {
n.SetType(types.UntypedRune)
}
case *syntax.DeclStmt:
return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
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 {
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
}
}
func (p *noder) setlineno(n syntax.Node) {
- if n != nil && n != syntax.ImplicitOne {
+ if n != nil {
base.Pos = p.pos(n)
}
}
case *syntax.AssignStmt:
if stmt.Op != 0 && stmt.Op != syntax.Def {
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 ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs))
AssignStmt struct {
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
}
// ----------------------------------------------------------------------------
// 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 .
func (p *parser) simpleStmt(lhs Expr, keyword token) SimpleStmt {
if trace {
// lhs++ or lhs--
op := p.op
p.next()
- return p.newAssignStmt(pos, op, lhs, ImplicitOne)
+ return p.newAssignStmt(pos, op, lhs, nil)
case _Arrow:
// lhs <- rhs
case *AssignStmt:
p.print(n.Lhs)
- if n.Rhs == ImplicitOne {
+ if n.Rhs == nil {
// TODO(gri) This is going to break the mayCombine
// check once we enable that again.
p.print(n.Op, n.Op) // ++ or --
case *AssignStmt:
w.node(n.Lhs)
- w.node(n.Rhs)
+ if n.Rhs != nil {
+ w.node(n.Rhs)
+ }
case *BranchStmt:
if n.Label != nil {
}
// 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) {
var y operand
return n.Pos()
case *syntax.AssignStmt:
m = n.Rhs
- if m == syntax.ImplicitOne {
+ if m == nil {
p := endPos(n.Lhs)
return syntax.MakePos(p.Base(), p.Line(), p.Col()+2)
}
case *syntax.AssignStmt:
lhs := unpackExpr(s.Lhs)
- rhs := unpackExpr(s.Rhs)
- if s.Op == 0 || s.Op == syntax.Def {
- // regular assignment or short variable declaration
- if len(lhs) == 0 {
- check.invalidASTf(s, "missing lhs in assignment")
- 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)
+ if s.Rhs == nil {
+ // x++ or x--
+ if len(lhs) != 1 {
+ check.invalidASTf(s, "%s%s requires one operand", s.Op, 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
- 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 {
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)
+ 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:
// check.suspendedCall("go", s.Call)