Add Slice function for range type (#83) · go-python/gpython@e427daf · GitHub
Skip to content

Commit e427daf

Browse files
HyeockJinKimcorona10
authored andcommitted
Add Slice function for range type (#83)
* 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 * Add typecall for __index__ in Index function If __index__ is defined when class is used as index value, __index__ value is used. * Add tests for range
1 parent 16d3870 commit e427daf

3 files changed

Lines changed: 123 additions & 9 deletions

File tree

py/internal.go

Lines changed: 13 additions & 2 deletions

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
@@ -160,6 +160,69 @@ func computeRangeLength(start, stop, step Int) Int {
160160
return res
161161
}
162162

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

py/tests/range.py

Lines changed: 40 additions & 0 deletions

0 commit comments

Comments
 (0)