Skip to content

Commit dafaabf

Browse files
committed
py: Support __len__ of rangetype.
1 parent f7ea0a4 commit dafaabf

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

py/range.go

+37-10
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ package py
99
// A python Range object
1010
// FIXME one day support BigInts too!
1111
type Range struct {
12-
Start Int
13-
Stop Int
14-
Step Int
15-
//Length Object
12+
Start Int
13+
Stop Int
14+
Step Int
15+
Length Int
1616
}
1717

1818
// A python Range iterator
@@ -53,10 +53,12 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) {
5353
return nil, err
5454
}
5555
if len(args) == 1 {
56+
length := computeRangeLength(0, startIndex, 1)
5657
return &Range{
57-
Start: Int(0),
58-
Stop: startIndex,
59-
Step: Int(1),
58+
Start: Int(0),
59+
Stop: startIndex,
60+
Step: Int(1),
61+
Length: length,
6062
}, nil
6163
}
6264
stopIndex, err := Index(stop)
@@ -67,10 +69,12 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) {
6769
if err != nil {
6870
return nil, err
6971
}
72+
length := computeRangeLength(startIndex, stopIndex, stepIndex)
7073
return &Range{
71-
Start: startIndex,
72-
Stop: stopIndex,
73-
Step: stepIndex,
74+
Start: startIndex,
75+
Stop: stopIndex,
76+
Step: stepIndex,
77+
Length: length,
7478
}, nil
7579
}
7680

@@ -82,6 +86,10 @@ func (r *Range) M__iter__() (Object, error) {
8286
}, nil
8387
}
8488

89+
func (r *Range) M__len__() (Object, error) {
90+
return r.Length, nil
91+
}
92+
8593
// Range iterator
8694
func (it *RangeIterator) M__iter__() (Object, error) {
8795
return it, nil
@@ -97,6 +105,25 @@ func (it *RangeIterator) M__next__() (Object, error) {
97105
return r, nil
98106
}
99107

108+
func computeRangeLength(start, stop, step Int) Int {
109+
var lo, hi Int
110+
if step > 0 {
111+
lo = start
112+
hi = stop
113+
step = step
114+
} else {
115+
lo = stop
116+
hi = start
117+
step = (-step)
118+
}
119+
120+
if lo >= hi {
121+
return Int(0)
122+
}
123+
res := (hi-lo-1)/step + 1
124+
return res
125+
}
126+
100127
// Check interface is satisfied
101128
var _ I__iter__ = (*Range)(nil)
102129
var _ I_iterator = (*RangeIterator)(nil)

py/tests/range.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2018 The go-python Authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style
3+
# license that can be found in the LICENSE file.
4+
5+
doc="range"
6+
a = range(255)
7+
b = [e for e in a]
8+
assert len(a) == len(b)
9+
a = range(5, 100, 5)
10+
b = [e for e in a]
11+
assert len(a) == len(b)
12+
a = range(100 ,0, 1)
13+
b = [e for e in a]
14+
assert len(a) == len(b)
15+
16+
doc="finished"

0 commit comments

Comments
 (0)