Skip to content

Commit 0431510

Browse files
authored
Merge pull request #877 from xushiwei/f
for range `start:end:step` support step < 0
2 parents e71ea0e + 33e69e4 commit 0431510

File tree

8 files changed

+67
-61
lines changed

8 files changed

+67
-61
lines changed

Diff for: ast/ast_gop.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -186,31 +186,31 @@ func (*ForPhraseStmt) stmtNode() {}
186186

187187
// A RangeExpr node represents a range expression.
188188
type RangeExpr struct {
189-
Low Expr // start of composite elements; or nil
189+
First Expr // start of composite elements; or nil
190190
To token.Pos // position of ":"
191-
High Expr // end of composite elements; or nil
191+
Last Expr // end of composite elements
192192
Colon2 token.Pos // position of ":" or token.NoPos
193-
Last Expr // step (or max) of composite elements; or nil
193+
Expr3 Expr // step (or max) of composite elements; or nil
194194
}
195195

196196
// Pos - position of first character belonging to the node
197197
func (p *RangeExpr) Pos() token.Pos {
198-
if p.Low != nil {
199-
return p.Low.Pos()
198+
if p.First != nil {
199+
return p.First.Pos()
200200
}
201201
return p.To
202202
}
203203

204204
// End - position of first character immediately after the node
205205
func (p *RangeExpr) End() token.Pos {
206-
if p.Last != nil {
207-
return p.Last.End()
206+
if p.Expr3 != nil {
207+
return p.Expr3.End()
208208
}
209209
if p.Colon2 != token.NoPos {
210210
return p.Colon2 + 1
211211
}
212-
if p.High != nil {
213-
return p.High.End()
212+
if p.Last != nil {
213+
return p.Last.End()
214214
}
215215
return p.To + 1
216216
}

Diff for: builtin/range.go

+20-30
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,40 @@
1313

1414
package builtin
1515

16-
func NewRange__0(low, high, step int) *IntRange {
17-
return &IntRange{Low: low, High: high, Step: step}
18-
}
19-
20-
func NewRange__1(low, high, step float64) *FloatRange {
21-
return &FloatRange{Low: low, High: high, Step: step}
22-
}
16+
// -----------------------------------------------------------------------------
2317

2418
type IntRange struct {
25-
Low, High, Step int
19+
Start, End, Step int
2620
}
2721

28-
func (p *IntRange) Gop_Enum() *intRangeIter {
29-
return &intRangeIter{i: p.Low, high: p.High, step: p.Step}
22+
func NewRange__0(start, end, step int) *IntRange {
23+
return &IntRange{Start: start, End: end, Step: step}
3024
}
3125

32-
type FloatRange struct {
33-
Low, High, Step float64
26+
func (p *IntRange) Gop_Enum() *intRangeIter {
27+
step := p.Step
28+
n := p.End - p.Start + step
29+
if step > 0 {
30+
n = (n - 1) / step
31+
} else {
32+
n = (n + 1) / step
33+
}
34+
return &intRangeIter{n: n, val: p.Start, step: p.Step}
3435
}
3536

36-
func (p *FloatRange) Gop_Enum() *floatRangeIter {
37-
return &floatRangeIter{i: p.Low, high: p.High, step: p.Step}
38-
}
37+
// -----------------------------------------------------------------------------
3938

4039
type intRangeIter struct {
41-
i, high, step int
40+
n, val, step int
4241
}
4342

4443
func (p *intRangeIter) Next() (val int, ok bool) {
45-
if p.i < p.high {
46-
val, ok = p.i, true
47-
p.i += p.step
44+
if p.n > 0 {
45+
val, ok = p.val, true
46+
p.val += p.step
47+
p.n--
4848
}
4949
return
5050
}
5151

52-
type floatRangeIter struct {
53-
i, high, step float64
54-
}
55-
56-
func (p *floatRangeIter) Next() (val float64, ok bool) {
57-
if p.i < p.high {
58-
val, ok = p.i, true
59-
p.i += p.step
60-
}
61-
return
62-
}
52+
// -----------------------------------------------------------------------------

Diff for: cl/builtin.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func initBuiltin(pkg gox.PkgImporter, builtin *types.Package, fmt, big *gox.PkgR
4747
fnTitle := string(fn[0]-'a'+'A') + fn[1:]
4848
scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, fn, fmt.Ref(fnTitle)))
4949
}
50-
scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "newRange", big.Ref("NewRange__0"), big.Ref("NewRange__1")))
50+
scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "newRange", big.Ref("NewRange__0")))
5151
}
5252

5353
func newBuiltinDefault(pkg gox.PkgImporter, conf *gox.Config) *types.Package {

Diff for: cl/expr.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -691,16 +691,16 @@ func compileSliceLit(ctx *blockCtx, v *ast.SliceLit) {
691691
func compileRangeExpr(ctx *blockCtx, v *ast.RangeExpr) {
692692
pkg, cb := ctx.pkg, ctx.cb
693693
cb.Val(pkg.Builtin().Ref("newRange"))
694-
if v.Low == nil {
694+
if v.First == nil {
695695
ctx.cb.Val(0, v)
696696
} else {
697-
compileExpr(ctx, v.Low)
697+
compileExpr(ctx, v.First)
698698
}
699-
compileExpr(ctx, v.High)
700-
if v.Last == nil {
699+
compileExpr(ctx, v.Last)
700+
if v.Expr3 == nil {
701701
ctx.cb.Val(1, v)
702702
} else {
703-
compileExpr(ctx, v.Last)
703+
compileExpr(ctx, v.Expr3)
704704
}
705705
cb.Call(3)
706706
}

Diff for: parser/_testdata/rangeexpr/parser.expect

+6-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ast.FuncDecl:
1919
Tok: :=
2020
X:
2121
ast.RangeExpr:
22-
High:
22+
Last:
2323
ast.BasicLit:
2424
Kind: INT
2525
Value: 10
@@ -43,11 +43,11 @@ ast.FuncDecl:
4343
Name: i
4444
X:
4545
ast.RangeExpr:
46-
Low:
46+
First:
4747
ast.BasicLit:
4848
Kind: INT
4949
Value: 1
50-
High:
50+
Last:
5151
ast.BasicLit:
5252
Kind: INT
5353
Value: 10
@@ -70,11 +70,11 @@ ast.FuncDecl:
7070
Tok: :=
7171
X:
7272
ast.RangeExpr:
73-
High:
73+
Last:
7474
ast.BasicLit:
7575
Kind: INT
7676
Value: 10
77-
Last:
77+
Expr3:
7878
ast.BasicLit:
7979
Kind: INT
8080
Value: 2
@@ -94,7 +94,7 @@ ast.FuncDecl:
9494
Tok: ILLEGAL
9595
X:
9696
ast.RangeExpr:
97-
High:
97+
Last:
9898
ast.BasicLit:
9999
Kind: INT
100100
Value: 10

Diff for: parser/parser.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -2025,16 +2025,16 @@ func (p *parser) parseRangeExpr(allowCmd bool) ast.Expr {
20252025
p.next()
20262026
high := p.parseBinaryExpr(false, token.LowestPrec+1, false, false)
20272027
var colon2 token.Pos
2028-
var last ast.Expr
2028+
var expr3 ast.Expr
20292029
if p.tok == token.COLON {
20302030
colon2 = p.pos
20312031
p.next()
2032-
last = p.parseBinaryExpr(false, token.LowestPrec+1, false, false)
2032+
expr3 = p.parseBinaryExpr(false, token.LowestPrec+1, false, false)
20332033
}
20342034
if debugParseOutput {
2035-
log.Printf("ast.RangeExpr{Low: %v, High: %v, Last: %v}\n", low, high, last)
2035+
log.Printf("ast.RangeExpr{First: %v, Last: %v, Expr3: %v}\n", low, high, expr3)
20362036
}
2037-
return &ast.RangeExpr{Low: low, To: to, High: high, Colon2: colon2, Last: last}
2037+
return &ast.RangeExpr{First: low, To: to, Last: high, Colon2: colon2, Expr3: expr3}
20382038
}
20392039

20402040
type tupleExpr struct {

Diff for: printer/nodes.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -1085,17 +1085,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
10851085
p.block(x.Body, 1)
10861086

10871087
case *ast.RangeExpr:
1088-
if x.Low != nil {
1089-
p.expr(x.Low)
1088+
if x.First != nil {
1089+
p.expr(x.First)
10901090
}
10911091
p.print(token.COLON)
1092-
if x.High != nil {
1093-
p.expr(x.High)
1092+
if x.Last != nil {
1093+
p.expr(x.Last)
10941094
}
10951095
if x.Colon2 != token.NoPos {
10961096
p.print(token.COLON)
1097-
if x.Last != nil {
1098-
p.expr(x.Last)
1097+
if x.Expr3 != nil {
1098+
p.expr(x.Expr3)
10991099
}
11001100
}
11011101

Diff for: tutorial/43-RangeExpr/rangeexpr.gop

+16
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
1+
println "---------------------------"
2+
13
for i <- :10 {
24
println(i)
35
}
46

7+
println "---------------------------"
8+
9+
for i <- 9:-1:-1 {
10+
println(i)
11+
}
12+
13+
println "---------------------------"
14+
515
for i := range :10:2 {
616
println(i)
717
}
818

19+
println "---------------------------"
20+
921
for i := range 1:10:3 {
1022
println(i)
1123
}
1224

25+
println "---------------------------"
26+
1327
for range :10 {
1428
println("Range expression")
1529
}
30+
31+
println "---------------------------"

0 commit comments

Comments
 (0)