@@ -6,7 +6,7 @@ use num_traits::{One, Signed, Zero};
6
6
7
7
use crate :: function:: { OptionalArg , PyFuncArgs } ;
8
8
use crate :: pyobject:: {
9
- PyContext , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject , TypeProtocol ,
9
+ PyClassImpl , PyContext , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject , TypeProtocol ,
10
10
} ;
11
11
use crate :: vm:: VirtualMachine ;
12
12
@@ -15,6 +15,15 @@ use super::objiter;
15
15
use super :: objslice:: { PySlice , PySliceRef } ;
16
16
use super :: objtype:: { self , PyClassRef } ;
17
17
18
+ /// range(stop) -> range object
19
+ /// range(start, stop[, step]) -> range object
20
+ ///
21
+ /// Return an object that produces a sequence of integers from start (inclusive)
22
+ /// to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
23
+ /// start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
24
+ /// These are exactly the valid indices for a list of 4 elements.
25
+ /// When step is given, it specifies the increment (or decrement).
26
+ #[ pyclass]
18
27
#[ derive( Debug , Clone ) ]
19
28
pub struct PyRange {
20
29
pub start : PyIntRef ,
@@ -96,33 +105,7 @@ pub fn get_value(obj: &PyObjectRef) -> PyRange {
96
105
}
97
106
98
107
pub fn init ( context : & PyContext ) {
99
- let range_type = & context. range_type ;
100
-
101
- let range_doc = "range(stop) -> range object\n \
102
- range(start, stop[, step]) -> range object\n \n \
103
- Return an object that produces a sequence of integers from start (inclusive)\n \
104
- to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n \
105
- start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.\n \
106
- These are exactly the valid indices for a list of 4 elements.\n \
107
- When step is given, it specifies the increment (or decrement).";
108
-
109
- extend_class ! ( context, range_type, {
110
- "__bool__" => context. new_rustfunc( PyRange :: bool ) ,
111
- "__contains__" => context. new_rustfunc( PyRange :: contains) ,
112
- "__doc__" => context. new_str( range_doc. to_string( ) ) ,
113
- "__eq__" => context. new_rustfunc( PyRange :: eq) ,
114
- "__getitem__" => context. new_rustfunc( PyRange :: getitem) ,
115
- "__iter__" => context. new_rustfunc( PyRange :: iter) ,
116
- "__len__" => context. new_rustfunc( PyRange :: len) ,
117
- "__new__" => context. new_rustfunc( range_new) ,
118
- "__repr__" => context. new_rustfunc( PyRange :: repr) ,
119
- "__reversed__" => context. new_rustfunc( PyRange :: reversed) ,
120
- "count" => context. new_rustfunc( PyRange :: count) ,
121
- "index" => context. new_rustfunc( PyRange :: index) ,
122
- "start" => context. new_property( PyRange :: start) ,
123
- "stop" => context. new_property( PyRange :: stop) ,
124
- "step" => context. new_property( PyRange :: step) ,
125
- } ) ;
108
+ PyRange :: extend_class ( context, & context. range_type ) ;
126
109
127
110
let rangeiterator_type = & context. rangeiterator_type ;
128
111
extend_class ! ( context, rangeiterator_type, {
@@ -133,6 +116,7 @@ pub fn init(context: &PyContext) {
133
116
134
117
type PyRangeRef = PyRef < PyRange > ;
135
118
119
+ #[ pyimpl]
136
120
impl PyRange {
137
121
fn new ( cls : PyClassRef , stop : PyIntRef , vm : & VirtualMachine ) -> PyResult < PyRangeRef > {
138
122
PyRange {
@@ -160,25 +144,30 @@ impl PyRange {
160
144
. into_ref_with_type ( vm, cls)
161
145
}
162
146
147
+ #[ pyproperty( name = "start" ) ]
163
148
fn start ( & self , _vm : & VirtualMachine ) -> PyIntRef {
164
149
self . start . clone ( )
165
150
}
166
151
152
+ #[ pyproperty( name = "stop" ) ]
167
153
fn stop ( & self , _vm : & VirtualMachine ) -> PyIntRef {
168
154
self . stop . clone ( )
169
155
}
170
156
157
+ #[ pyproperty( name = "step" ) ]
171
158
fn step ( & self , _vm : & VirtualMachine ) -> PyIntRef {
172
159
self . step . clone ( )
173
160
}
174
161
162
+ #[ pymethod( name = "__iter__" ) ]
175
163
fn iter ( zelf : PyRef < Self > , _vm : & VirtualMachine ) -> PyRangeIterator {
176
164
PyRangeIterator {
177
165
position : Cell :: new ( 0 ) ,
178
166
range : zelf,
179
167
}
180
168
}
181
169
170
+ #[ pymethod( name = "__reversed__" ) ]
182
171
fn reversed ( & self , vm : & VirtualMachine ) -> PyRangeIterator {
183
172
let start = self . start . as_bigint ( ) ;
184
173
let stop = self . stop . as_bigint ( ) ;
@@ -211,6 +200,7 @@ impl PyRange {
211
200
}
212
201
}
213
202
203
+ #[ pymethod( name = "__len__" ) ]
214
204
fn len ( & self , _vm : & VirtualMachine ) -> PyInt {
215
205
let start = self . start . as_bigint ( ) ;
216
206
let stop = self . stop . as_bigint ( ) ;
@@ -224,6 +214,7 @@ impl PyRange {
224
214
}
225
215
}
226
216
217
+ #[ pymethod( name = "__repr__" ) ]
227
218
fn repr ( & self , _vm : & VirtualMachine ) -> String {
228
219
if self . step . as_bigint ( ) . is_one ( ) {
229
220
format ! ( "range({}, {})" , self . start, self . stop)
@@ -232,10 +223,12 @@ impl PyRange {
232
223
}
233
224
}
234
225
226
+ #[ pymethod( name = "__bool__" ) ]
235
227
fn bool ( & self , _vm : & VirtualMachine ) -> bool {
236
228
!self . is_empty ( )
237
229
}
238
230
231
+ #[ pymethod( name = "__contains__" ) ]
239
232
fn contains ( & self , needle : PyObjectRef , _vm : & VirtualMachine ) -> bool {
240
233
if let Ok ( int) = needle. downcast :: < PyInt > ( ) {
241
234
match self . offset ( int. as_bigint ( ) ) {
@@ -247,6 +240,7 @@ impl PyRange {
247
240
}
248
241
}
249
242
243
+ #[ pymethod( name = "__eq__" ) ]
250
244
fn eq ( & self , rhs : PyObjectRef , vm : & VirtualMachine ) -> bool {
251
245
if objtype:: isinstance ( & rhs, & vm. ctx . range_type ( ) ) {
252
246
let rhs = get_value ( & rhs) ;
@@ -258,6 +252,7 @@ impl PyRange {
258
252
}
259
253
}
260
254
255
+ #[ pymethod( name = "index" ) ]
261
256
fn index ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult < PyInt > {
262
257
if let Ok ( int) = needle. downcast :: < PyInt > ( ) {
263
258
match self . index_of ( int. as_bigint ( ) ) {
@@ -269,6 +264,7 @@ impl PyRange {
269
264
}
270
265
}
271
266
267
+ #[ pymethod( name = "count" ) ]
272
268
fn count ( & self , item : PyObjectRef , _vm : & VirtualMachine ) -> PyInt {
273
269
if let Ok ( int) = item. downcast :: < PyInt > ( ) {
274
270
if self . index_of ( int. as_bigint ( ) ) . is_some ( ) {
@@ -281,6 +277,7 @@ impl PyRange {
281
277
}
282
278
}
283
279
280
+ #[ pymethod( name = "__getitem__" ) ]
284
281
fn getitem ( & self , subscript : RangeIndex , vm : & VirtualMachine ) -> PyResult {
285
282
match subscript {
286
283
RangeIndex :: Int ( index) => {
@@ -327,18 +324,19 @@ impl PyRange {
327
324
}
328
325
}
329
326
}
330
- }
331
327
332
- fn range_new ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
333
- let range = if args. args . len ( ) <= 2 {
334
- let ( cls, stop) = args. bind ( vm) ?;
335
- PyRange :: new ( cls, stop, vm)
336
- } else {
337
- let ( cls, start, stop, step) = args. bind ( vm) ?;
338
- PyRange :: new_from ( cls, start, stop, step, vm)
339
- } ?;
328
+ #[ pymethod( name = "__new__" ) ]
329
+ fn range_new ( args : PyFuncArgs , vm : & VirtualMachine ) -> PyResult {
330
+ let range = if args. args . len ( ) <= 2 {
331
+ let ( cls, stop) = args. bind ( vm) ?;
332
+ PyRange :: new ( cls, stop, vm)
333
+ } else {
334
+ let ( cls, start, stop, step) = args. bind ( vm) ?;
335
+ PyRange :: new_from ( cls, start, stop, step, vm)
336
+ } ?;
340
337
341
- Ok ( range. into_object ( ) )
338
+ Ok ( range. into_object ( ) )
339
+ }
342
340
}
343
341
344
342
#[ derive( Debug ) ]
0 commit comments