@@ -79,18 +79,18 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) {
7979}
8080
8181func (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
164227var _ I__getitem__ = (* Range )(nil )
165228var _ I__iter__ = (* Range )(nil )
0 commit comments