Skip to content

Commit 86ed164

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 86ed164

File tree

1 file changed

+70
-7
lines changed

1 file changed

+70
-7
lines changed

py/range.go

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,18 @@ 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)
88-
if index < 0 {
89-
index += length
90-
}
90+
index = computeNegativeIndex(index, r.Length)
9191

92-
if index < 0 || index >= length {
93-
return nil, ExceptionNewf(TypeError, "range object index out of range")
92+
if index < 0 || index >= r.Length {
93+
return nil, ExceptionNewf(IndexError, "range object index out of range")
9494
}
9595
result := computeItem(r, index)
9696
return result, nil
@@ -152,6 +152,69 @@ func computeRangeLength(start, stop, step Int) Int {
152152
return res
153153
}
154154

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

0 commit comments

Comments
 (0)