Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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
  • Loading branch information
HyeockJinKim committed Sep 25, 2019
commit 0203481f3655b21918e901ce518084f1df754519
77 changes: 70 additions & 7 deletions py/range.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,18 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) {
}

func (r *Range) M__getitem__(key Object) (Object, error) {
if slice, ok := key.(*Slice); ok {
return computeRangeSlice(r, slice)
}

index, err := Index(key)
if err != nil {
return nil, err
}
// TODO(corona10): Support slice case
length := computeRangeLength(r.Start, r.Stop, r.Step)
if index < 0 {
index += length
}
index = computeNegativeIndex(index, r.Length)

if index < 0 || index >= length {
return nil, ExceptionNewf(TypeError, "range object index out of range")
if index < 0 || index >= r.Length {
return nil, ExceptionNewf(IndexError, "range object index out of range")
}
result := computeItem(r, index)
return result, nil
Expand Down Expand Up @@ -160,6 +160,69 @@ func computeRangeLength(start, stop, step Int) Int {
return res
}

func computeNegativeIndex(index, length Int) Int {
if index < 0 {
index += length
}
return index
}

func computeBoundIndex(index, length Int) Int {
if index < 0 {
index = 0
} else if index > length {
index = length
}
return index
}

func computeRangeSlice(r *Range, s *Slice) (Object, error) {
start, err := Index(s.Start)
if err != nil {
start = 0
}
stop, err := Index(s.Stop)
if err != nil {
stop = r.Length
}

step, err := Index(s.Step)
if err != nil {
step = 1
}
if step == 0 {
return nil, ExceptionNewf(ValueError, "slice step cannot be zero")
}
start = computeNegativeIndex(start, r.Length)
stop = computeNegativeIndex(stop, r.Length)

start = computeBoundIndex(start, r.Length)
stop = computeBoundIndex(stop, r.Length)

startIndex := computeItem(r, start)
stopIndex := computeItem(r, stop)
stepIndex := step * r.Step

var sliceLength Int
if start < stop {
if stepIndex < 0 {
startIndex, stopIndex = stopIndex-1, startIndex-1
}
} else {
if stepIndex < 0 {
startIndex, stopIndex = stopIndex+1, startIndex+1
}
}
sliceLength = computeRangeLength(startIndex, stopIndex, stepIndex)

return &Range{
Start: startIndex,
Stop: stopIndex,
Step: stepIndex,
Length: sliceLength,
}, nil
}

// Check interface is satisfied
var _ I__getitem__ = (*Range)(nil)
var _ I__iter__ = (*Range)(nil)
Expand Down