Skip to content

Commit 570ec8e

Browse files
committed
Add Slice function for range type
Crate a new range object by calculating start, stop, and step when slice is entered as argument to the __getitem__ function of the range Fixes #77
1 parent eb115a9 commit 570ec8e

File tree

1 file changed

+64
-4
lines changed

1 file changed

+64
-4
lines changed

py/range.go

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,19 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) {
7979
}
8080

8181
func (r *Range) M__getitem__(key Object) (Object, error) {
82+
if slice, ok := key.(*Slice); ok {
83+
return computeRangeSlice(r, slice)
84+
}
85+
8286
index, err := Index(key)
8387
if err != nil {
8488
return nil, err
8589
}
86-
// TODO(corona10): Support slice case
87-
length := computeRangeLength(r.Start, r.Stop, r.Step)
8890
if index < 0 {
89-
index += length
91+
index += r.Length
9092
}
9193

92-
if index < 0 || index >= length {
94+
if index < 0 || index >= r.Length {
9395
return nil, ExceptionNewf(TypeError, "range object index out of range")
9496
}
9597
result := computeItem(r, index)
@@ -152,6 +154,64 @@ func computeRangeLength(start, stop, step Int) Int {
152154
return res
153155
}
154156

157+
func computeRangeSlice(r *Range, s *Slice) (Object, error) {
158+
length, err := r.Length.GoInt()
159+
if err != nil {
160+
return nil, err
161+
}
162+
163+
start, err := IndexInt(s.Start)
164+
if err != nil {
165+
start = 0
166+
}
167+
stop, err := IndexInt(s.Stop)
168+
if err != nil {
169+
stop = length
170+
}
171+
172+
step, err := IndexInt(s.Step)
173+
if err != nil {
174+
step = 1
175+
}
176+
if step == 0 {
177+
return nil, ExceptionNewf(ValueError, "slice step cannot be zero")
178+
}
179+
if start < 0 {
180+
start += length
181+
}
182+
if stop < 0 {
183+
stop += length
184+
}
185+
186+
if start < 0 {
187+
start = 0
188+
} else if start >= length {
189+
start = length
190+
}
191+
if stop < 0 {
192+
stop = 0
193+
} else if stop >= length {
194+
stop = length
195+
}
196+
197+
startIndex := computeItem(r, Int(start))
198+
stopIndex := computeItem(r, Int(stop))
199+
stepIndex := Int(step) * r.Step
200+
var sliceLength Int
201+
if startIndex < stopIndex {
202+
sliceLength = (stopIndex - startIndex - 1) / stepIndex + 1
203+
} else {
204+
sliceLength = (stopIndex - startIndex + 1) / stepIndex + 1
205+
}
206+
207+
return &Range{
208+
Start: startIndex,
209+
Stop: stopIndex,
210+
Step: stepIndex,
211+
Length: sliceLength,
212+
}, nil
213+
}
214+
155215
// Check interface is satisfied
156216
var _ I__getitem__ = (*Range)(nil)
157217
var _ I__iter__ = (*Range)(nil)

0 commit comments

Comments
 (0)