mirror of https://github.com/golang/go.git
go/*: permit "for range x"
LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/112970044
This commit is contained in:
parent
81e661aa45
commit
d3a2f58700
|
|
@ -699,9 +699,9 @@ type (
|
|||
// A RangeStmt represents a for statement with a range clause.
|
||||
RangeStmt struct {
|
||||
For token.Pos // position of "for" keyword
|
||||
Key, Value Expr // Value may be nil
|
||||
TokPos token.Pos // position of Tok
|
||||
Tok token.Token // ASSIGN, DEFINE
|
||||
Key, Value Expr // Key, Value may be nil
|
||||
TokPos token.Pos // position of Tok; invalid if Key == nil
|
||||
Tok token.Token // ILLEGAL if Key == nil, ASSIGN, DEFINE
|
||||
X Expr // value to range over
|
||||
Body *BlockStmt
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2041,7 +2041,16 @@ func (p *parser) parseForStmt() ast.Stmt {
|
|||
prevLev := p.exprLev
|
||||
p.exprLev = -1
|
||||
if p.tok != token.SEMICOLON {
|
||||
s2, isRange = p.parseSimpleStmt(rangeOk)
|
||||
if p.tok == token.RANGE {
|
||||
// "for range x" (nil lhs in assignment)
|
||||
pos := p.pos
|
||||
p.next()
|
||||
y := []ast.Expr{&ast.UnaryExpr{OpPos: pos, Op: token.RANGE, X: p.parseRhs()}}
|
||||
s2 = &ast.AssignStmt{Rhs: y}
|
||||
isRange = true
|
||||
} else {
|
||||
s2, isRange = p.parseSimpleStmt(rangeOk)
|
||||
}
|
||||
}
|
||||
if !isRange && p.tok == token.SEMICOLON {
|
||||
p.next()
|
||||
|
|
@ -2066,12 +2075,14 @@ func (p *parser) parseForStmt() ast.Stmt {
|
|||
// check lhs
|
||||
var key, value ast.Expr
|
||||
switch len(as.Lhs) {
|
||||
case 2:
|
||||
key, value = as.Lhs[0], as.Lhs[1]
|
||||
case 0:
|
||||
// nothing to do
|
||||
case 1:
|
||||
key = as.Lhs[0]
|
||||
case 2:
|
||||
key, value = as.Lhs[0], as.Lhs[1]
|
||||
default:
|
||||
p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions")
|
||||
p.errorExpected(as.Lhs[len(as.Lhs)-1].Pos(), "at most 2 expressions")
|
||||
return &ast.BadStmt{From: pos, To: p.safePos(body.End())}
|
||||
}
|
||||
// parseSimpleStmt returned a right-hand side that
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ var valids = []string{
|
|||
`package p; func ((T),) m() {}`,
|
||||
`package p; func ((*T),) m() {}`,
|
||||
`package p; func (*(T),) m() {}`,
|
||||
`package p; func _(x []int) { for range x {} }`,
|
||||
}
|
||||
|
||||
func TestValid(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -1216,14 +1216,17 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
|
|||
|
||||
case *ast.RangeStmt:
|
||||
p.print(token.FOR, blank)
|
||||
p.expr(s.Key)
|
||||
if s.Value != nil {
|
||||
// use position of value following the comma as
|
||||
// comma position for correct comment placement
|
||||
p.print(s.Value.Pos(), token.COMMA, blank)
|
||||
p.expr(s.Value)
|
||||
if s.Key != nil {
|
||||
p.expr(s.Key)
|
||||
if s.Value != nil {
|
||||
// use position of value following the comma as
|
||||
// comma position for correct comment placement
|
||||
p.print(s.Value.Pos(), token.COMMA, blank)
|
||||
p.expr(s.Value)
|
||||
}
|
||||
p.print(blank, s.TokPos, s.Tok, blank)
|
||||
}
|
||||
p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank)
|
||||
p.print(token.RANGE, blank)
|
||||
p.expr(stripParens(s.X))
|
||||
p.print(blank)
|
||||
p.block(s.Body, 1)
|
||||
|
|
|
|||
|
|
@ -309,6 +309,9 @@ func _() {
|
|||
for x := expr; expr; expr = false {
|
||||
use(x)
|
||||
}
|
||||
for range []int{} {
|
||||
println("foo")
|
||||
}
|
||||
for x := range []int{} {
|
||||
use(x)
|
||||
}
|
||||
|
|
@ -338,6 +341,12 @@ func _() {
|
|||
a[i] = i
|
||||
} // multiple lines
|
||||
|
||||
for range a {
|
||||
}
|
||||
for _ = range a {
|
||||
}
|
||||
for _, _ = range a {
|
||||
}
|
||||
for i := range a {
|
||||
}
|
||||
for i := range a {
|
||||
|
|
|
|||
|
|
@ -269,6 +269,8 @@ func _() {
|
|||
for x := expr;expr;expr = false {
|
||||
use(x)
|
||||
}
|
||||
for range []int{} {
|
||||
println("foo")}
|
||||
for x := range []int{} {
|
||||
use(x) }
|
||||
for x := range (([]int{})) {
|
||||
|
|
@ -289,6 +291,9 @@ func _() {
|
|||
for i := 0; i < len(a); 1++ { a[i] = i
|
||||
} // multiple lines
|
||||
|
||||
for range a{}
|
||||
for _ = range a{}
|
||||
for _, _ = range a{}
|
||||
for i := range a {}
|
||||
for i := range a { a[i] = i }
|
||||
for i := range a { a[i] = i
|
||||
|
|
|
|||
Loading…
Reference in New Issue