1
- use num_bigint:: BigInt ;
2
-
3
- use crate :: function:: PyFuncArgs ;
4
- use crate :: pyobject:: { PyContext , PyObjectRef , PyRef , PyResult , PyValue } ;
1
+ use crate :: function:: { OptionalArg , PyFuncArgs } ;
2
+ use crate :: pyobject:: { IdProtocol , PyContext , PyObjectRef , PyRef , PyResult , PyValue , TypeProtocol } ;
5
3
use crate :: vm:: VirtualMachine ;
6
4
7
- use super :: objint;
8
- use crate :: obj:: objtype:: PyClassRef ;
5
+ use crate :: obj:: objint:: PyInt ;
6
+ use crate :: obj:: objtype:: { class_has_attr, PyClassRef } ;
7
+ use num_bigint:: BigInt ;
9
8
10
9
#[ derive( Debug ) ]
11
10
pub struct PySlice {
12
- // TODO: should be private
13
- pub start : Option < BigInt > ,
14
- pub stop : Option < BigInt > ,
15
- pub step : Option < BigInt > ,
11
+ pub start : Option < PyObjectRef > ,
12
+ pub stop : PyObjectRef ,
13
+ pub step : Option < PyObjectRef > ,
16
14
}
17
15
18
16
impl PyValue for PySlice {
@@ -23,52 +21,35 @@ impl PyValue for PySlice {
23
21
24
22
pub type PySliceRef = PyRef < PySlice > ;
25
23
26
- fn slice_new ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
27
- no_kwargs ! ( vm, args) ;
28
- let ( cls, start, stop, step) : (
29
- & PyObjectRef ,
30
- Option < & PyObjectRef > ,
31
- Option < & PyObjectRef > ,
32
- Option < & PyObjectRef > ,
33
- ) = match args. args . len ( ) {
34
- 0 | 1 => Err ( vm. new_type_error ( "slice() must have at least one arguments." . to_owned ( ) ) ) ,
35
- 2 => {
36
- arg_check ! (
37
- vm,
38
- args,
39
- required = [
40
- ( cls, Some ( vm. ctx. type_type( ) ) ) ,
41
- ( stop, Some ( vm. ctx. int_type( ) ) )
42
- ]
43
- ) ;
44
- Ok ( ( cls, None , Some ( stop) , None ) )
24
+ fn slice_new ( cls : PyClassRef , args : PyFuncArgs , vm : & VirtualMachine ) -> PyResult < PySliceRef > {
25
+ let slice: PySlice = match args. args . len ( ) {
26
+ 0 => {
27
+ return Err ( vm. new_type_error ( "slice() must have at least one arguments." . to_owned ( ) ) ) ;
28
+ }
29
+ 1 => {
30
+ let stop = args. bind ( vm) ?;
31
+ PySlice {
32
+ start : None ,
33
+ stop,
34
+ step : None ,
35
+ }
45
36
}
46
37
_ => {
47
- arg_check ! (
48
- vm,
49
- args,
50
- required = [
51
- ( cls, Some ( vm. ctx. type_type( ) ) ) ,
52
- ( start, Some ( vm. ctx. int_type( ) ) ) ,
53
- ( stop, Some ( vm. ctx. int_type( ) ) )
54
- ] ,
55
- optional = [ ( step, Some ( vm. ctx. int_type( ) ) ) ]
56
- ) ;
57
- Ok ( ( cls, Some ( start) , Some ( stop) , step) )
38
+ let ( start, stop, step) : ( PyObjectRef , PyObjectRef , OptionalArg < PyObjectRef > ) =
39
+ args. bind ( vm) ?;
40
+ PySlice {
41
+ start : Some ( start) ,
42
+ stop,
43
+ step : step. into_option ( ) ,
44
+ }
58
45
}
59
- } ?;
60
- PySlice {
61
- start : start. map ( |x| objint:: get_value ( x) . clone ( ) ) ,
62
- stop : stop. map ( |x| objint:: get_value ( x) . clone ( ) ) ,
63
- step : step. map ( |x| objint:: get_value ( x) . clone ( ) ) ,
64
- }
65
- . into_ref_with_type ( vm, cls. clone ( ) . downcast ( ) . unwrap ( ) )
66
- . map ( PyRef :: into_object)
46
+ } ;
47
+ slice. into_ref_with_type ( vm, cls)
67
48
}
68
49
69
- fn get_property_value ( vm : & VirtualMachine , value : & Option < BigInt > ) -> PyObjectRef {
50
+ fn get_property_value ( vm : & VirtualMachine , value : & Option < PyObjectRef > ) -> PyObjectRef {
70
51
if let Some ( value) = value {
71
- vm . ctx . new_int ( value. clone ( ) )
52
+ value. clone ( )
72
53
} else {
73
54
vm. get_none ( )
74
55
}
@@ -79,13 +60,57 @@ impl PySliceRef {
79
60
get_property_value ( vm, & self . start )
80
61
}
81
62
82
- fn stop ( self , vm : & VirtualMachine ) -> PyObjectRef {
83
- get_property_value ( vm , & self . stop )
63
+ fn stop ( self , _vm : & VirtualMachine ) -> PyObjectRef {
64
+ self . stop . clone ( )
84
65
}
85
66
86
67
fn step ( self , vm : & VirtualMachine ) -> PyObjectRef {
87
68
get_property_value ( vm, & self . step )
88
69
}
70
+
71
+ pub fn start_index ( & self , vm : & VirtualMachine ) -> PyResult < Option < BigInt > > {
72
+ if let Some ( obj) = & self . start {
73
+ to_index_value ( vm, obj)
74
+ } else {
75
+ Ok ( None )
76
+ }
77
+ }
78
+
79
+ pub fn stop_index ( & self , vm : & VirtualMachine ) -> PyResult < Option < BigInt > > {
80
+ to_index_value ( vm, & self . stop )
81
+ }
82
+
83
+ pub fn step_index ( & self , vm : & VirtualMachine ) -> PyResult < Option < BigInt > > {
84
+ if let Some ( obj) = & self . step {
85
+ to_index_value ( vm, obj)
86
+ } else {
87
+ Ok ( None )
88
+ }
89
+ }
90
+ }
91
+
92
+ fn to_index_value ( vm : & VirtualMachine , obj : & PyObjectRef ) -> PyResult < Option < BigInt > > {
93
+ if obj. is ( & vm. ctx . none ) {
94
+ return Ok ( None ) ;
95
+ }
96
+
97
+ if let Some ( val) = obj. payload :: < PyInt > ( ) {
98
+ Ok ( Some ( val. as_bigint ( ) . clone ( ) ) )
99
+ } else {
100
+ let cls = obj. class ( ) ;
101
+ if class_has_attr ( & cls, "__index__" ) {
102
+ let index_result = vm. call_method ( obj, "__index__" , vec ! [ ] ) ?;
103
+ if let Some ( val) = index_result. payload :: < PyInt > ( ) {
104
+ Ok ( Some ( val. as_bigint ( ) . clone ( ) ) )
105
+ } else {
106
+ Err ( vm. new_type_error ( "__index__ method returned non integer" . to_string ( ) ) )
107
+ }
108
+ } else {
109
+ Err ( vm. new_type_error (
110
+ "slice indices must be integers or None or have an __index__ method" . to_string ( ) ,
111
+ ) )
112
+ }
113
+ }
89
114
}
90
115
91
116
pub fn init ( context : & PyContext ) {
0 commit comments