@@ -6,103 +6,76 @@ use std::char;
6
6
use std:: io:: { self , Write } ;
7
7
use std:: path:: PathBuf ;
8
8
9
- use num_traits:: { Signed , ToPrimitive } ;
9
+ use num_traits:: Signed ;
10
10
11
11
use crate :: compile;
12
12
use crate :: import:: import_module;
13
13
use crate :: obj:: objbool;
14
- use crate :: obj:: objint;
14
+ use crate :: obj:: objdict:: PyDictRef ;
15
+ use crate :: obj:: objint:: { self , PyIntRef } ;
15
16
use crate :: obj:: objiter;
16
- use crate :: obj:: objstr:: { self , PyStringRef } ;
17
+ use crate :: obj:: objstr:: { self , PyString , PyStringRef } ;
17
18
use crate :: obj:: objtype:: { self , PyClassRef } ;
18
19
19
20
use crate :: frame:: Scope ;
20
21
use crate :: function:: { Args , OptionalArg , PyFuncArgs } ;
21
22
use crate :: pyobject:: {
22
- DictProtocol , IdProtocol , PyContext , PyObjectRef , PyResult , TryFromObject , TypeProtocol ,
23
+ DictProtocol , IdProtocol , PyContext , PyIterable , PyObjectRef , PyResult , PyValue , TryFromObject ,
24
+ TypeProtocol ,
23
25
} ;
24
26
use crate :: vm:: VirtualMachine ;
25
27
26
28
use crate :: obj:: objcode:: PyCodeRef ;
27
29
#[ cfg( not( target_arch = "wasm32" ) ) ]
28
30
use crate :: stdlib:: io:: io_open;
29
31
30
- fn get_locals ( vm : & VirtualMachine ) -> PyObjectRef {
31
- vm. get_locals ( )
32
- }
33
-
34
- fn dir_locals ( vm : & VirtualMachine ) -> PyObjectRef {
35
- get_locals ( vm)
36
- }
37
-
38
- fn builtin_abs ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
39
- arg_check ! ( vm, args, required = [ ( x, None ) ] ) ;
32
+ fn builtin_abs ( x : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
40
33
match vm. get_method ( x. clone ( ) , "__abs__" ) {
41
34
Ok ( attrib) => vm. invoke ( attrib, PyFuncArgs :: new ( vec ! [ ] , vec ! [ ] ) ) ,
42
35
Err ( ..) => Err ( vm. new_type_error ( "bad operand for abs" . to_string ( ) ) ) ,
43
36
}
44
37
}
45
38
46
- fn builtin_all ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
47
- arg_check ! ( vm, args, required = [ ( iterable, None ) ] ) ;
48
- let items = vm. extract_elements ( iterable) ?;
49
- for item in items {
50
- let result = objbool:: boolval ( vm, item) ?;
51
- if !result {
52
- return Ok ( vm. new_bool ( false ) ) ;
39
+ fn builtin_all ( iterable : PyIterable < bool > , vm : & VirtualMachine ) -> PyResult < bool > {
40
+ for item in iterable. iter ( vm) ? {
41
+ if !item? {
42
+ return Ok ( false ) ;
53
43
}
54
44
}
55
- Ok ( vm . new_bool ( true ) )
45
+ Ok ( true )
56
46
}
57
47
58
- fn builtin_any ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
59
- arg_check ! ( vm, args, required = [ ( iterable, None ) ] ) ;
60
- let iterator = objiter:: get_iter ( vm, iterable) ?;
61
-
62
- while let Some ( item) = objiter:: get_next_object ( vm, & iterator) ? {
63
- let result = objbool:: boolval ( vm, item) ?;
64
- if result {
65
- return Ok ( vm. new_bool ( true ) ) ;
48
+ fn builtin_any ( iterable : PyIterable < bool > , vm : & VirtualMachine ) -> PyResult < bool > {
49
+ for item in iterable. iter ( vm) ? {
50
+ if item? {
51
+ return Ok ( true ) ;
66
52
}
67
53
}
68
-
69
- Ok ( vm. new_bool ( false ) )
54
+ Ok ( false )
70
55
}
71
56
72
57
// builtin_ascii
73
58
74
- fn builtin_bin ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
75
- arg_check ! ( vm, args, required = [ ( number, Some ( vm. ctx. int_type( ) ) ) ] ) ;
76
-
77
- let n = objint:: get_value ( number) ;
78
- let s = if n. is_negative ( ) {
79
- format ! ( "-0b{:b}" , n. abs( ) )
59
+ fn builtin_bin ( x : PyIntRef , _vm : & VirtualMachine ) -> String {
60
+ let x = x. as_bigint ( ) ;
61
+ if x. is_negative ( ) {
62
+ format ! ( "-0b{:b}" , x. abs( ) )
80
63
} else {
81
- format ! ( "0b{:b}" , n)
82
- } ;
83
-
84
- Ok ( vm. new_str ( s) )
64
+ format ! ( "0b{:b}" , x)
65
+ }
85
66
}
86
67
87
68
// builtin_breakpoint
88
69
89
- fn builtin_callable ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
90
- arg_check ! ( vm, args, required = [ ( obj, None ) ] ) ;
91
- let is_callable = objtype:: class_has_attr ( & obj. type_pyref ( ) , "__call__" ) ;
92
- Ok ( vm. new_bool ( is_callable) )
70
+ fn builtin_callable ( obj : PyObjectRef , _vm : & VirtualMachine ) -> bool {
71
+ objtype:: class_has_attr ( & obj. class ( ) , "__call__" )
93
72
}
94
73
95
- fn builtin_chr ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
96
- arg_check ! ( vm, args, required = [ ( i, Some ( vm. ctx. int_type( ) ) ) ] ) ;
97
-
98
- let code_point = objint:: get_value ( i) . to_u32 ( ) . unwrap ( ) ;
99
-
100
- let txt = match char:: from_u32 ( code_point) {
74
+ fn builtin_chr ( i : u32 , _vm : & VirtualMachine ) -> String {
75
+ match char:: from_u32 ( i) {
101
76
Some ( value) => value. to_string ( ) ,
102
77
None => '_' . to_string ( ) ,
103
- } ;
104
-
105
- Ok ( vm. new_str ( txt) )
78
+ }
106
79
}
107
80
108
81
fn builtin_compile (
@@ -135,18 +108,13 @@ fn builtin_compile(
135
108
} )
136
109
}
137
110
138
- fn builtin_delattr ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
139
- arg_check ! (
140
- vm,
141
- args,
142
- required = [ ( obj, None ) , ( attr, Some ( vm. ctx. str_type( ) ) ) ]
143
- ) ;
144
- vm. del_attr ( obj, attr. clone ( ) )
111
+ fn builtin_delattr ( obj : PyObjectRef , attr : PyStringRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
112
+ vm. del_attr ( & obj, attr. into_object ( ) )
145
113
}
146
114
147
115
fn builtin_dir ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
148
116
if args. args . is_empty ( ) {
149
- Ok ( dir_locals ( vm ) )
117
+ Ok ( vm . get_locals ( ) . into_object ( ) )
150
118
} else {
151
119
let obj = args. args . into_iter ( ) . next ( ) . unwrap ( ) ;
152
120
let seq = vm. call_method ( & obj, "__dir__" , vec ! [ ] ) ?;
@@ -240,7 +208,7 @@ fn make_scope(
240
208
} else if vm. isinstance ( arg, & dict_type) ? {
241
209
Some ( arg)
242
210
} else {
243
- let arg_typ = arg. typ ( ) ;
211
+ let arg_typ = arg. class ( ) ;
244
212
let actual_type = vm. to_pystr ( & arg_typ) ?;
245
213
let expected_type_name = vm. to_pystr ( & dict_type) ?;
246
214
return Err ( vm. new_type_error ( format ! (
@@ -254,28 +222,37 @@ fn make_scope(
254
222
255
223
let current_scope = vm. current_scope ( ) ;
256
224
let globals = match globals {
257
- Some ( dict) => dict. clone ( ) ,
225
+ Some ( dict) => dict. clone ( ) . downcast ( ) . unwrap ( ) ,
258
226
None => current_scope. globals . clone ( ) ,
259
227
} ;
260
228
let locals = match locals {
261
- Some ( dict) => Some ( dict. clone ( ) ) ,
229
+ Some ( dict) => dict. clone ( ) . downcast ( ) . ok ( ) ,
262
230
None => current_scope. get_only_locals ( ) ,
263
231
} ;
264
232
265
233
Ok ( Scope :: new ( locals, globals) )
266
234
}
267
235
268
- fn builtin_format ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
269
- arg_check ! (
270
- vm,
271
- args,
272
- required = [ ( obj, None ) ] ,
273
- optional = [ ( format_spec, Some ( vm. ctx. str_type( ) ) ) ]
274
- ) ;
275
- let format_spec = format_spec
276
- . cloned ( )
277
- . unwrap_or_else ( || vm. new_str ( "" . to_string ( ) ) ) ;
278
- vm. call_method ( obj, "__format__" , vec ! [ format_spec] )
236
+ fn builtin_format (
237
+ value : PyObjectRef ,
238
+ format_spec : OptionalArg < PyStringRef > ,
239
+ vm : & VirtualMachine ,
240
+ ) -> PyResult < PyStringRef > {
241
+ let format_spec = format_spec. into_option ( ) . unwrap_or_else ( || {
242
+ PyString {
243
+ value : "" . to_string ( ) ,
244
+ }
245
+ . into_ref ( vm)
246
+ } ) ;
247
+
248
+ vm. call_method ( & value, "__format__" , vec ! [ format_spec. into_object( ) ] ) ?
249
+ . downcast ( )
250
+ . map_err ( |obj| {
251
+ vm. new_type_error ( format ! (
252
+ "__format__ must return a str, not {}" ,
253
+ obj. class( ) . name
254
+ ) )
255
+ } )
279
256
}
280
257
281
258
fn catch_attr_exception < T > ( ex : PyObjectRef , default : T , vm : & VirtualMachine ) -> PyResult < T > {
@@ -300,7 +277,7 @@ fn builtin_getattr(
300
277
}
301
278
}
302
279
303
- fn builtin_globals ( vm : & VirtualMachine , _args : PyFuncArgs ) -> PyResult {
280
+ fn builtin_globals ( vm : & VirtualMachine ) -> PyResult < PyDictRef > {
304
281
Ok ( vm. current_scope ( ) . globals . clone ( ) )
305
282
}
306
283
@@ -368,15 +345,14 @@ fn builtin_len(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
368
345
Ok ( value) => vm. invoke ( value, PyFuncArgs :: default ( ) ) ,
369
346
Err ( ..) => Err ( vm. new_type_error ( format ! (
370
347
"object of type '{}' has no method {:?}" ,
371
- objtype :: get_type_name ( & obj. typ ( ) ) ,
348
+ obj. class ( ) . name ,
372
349
len_method_name
373
350
) ) ) ,
374
351
}
375
352
}
376
353
377
- fn builtin_locals ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
378
- arg_check ! ( vm, args) ;
379
- Ok ( vm. get_locals ( ) )
354
+ fn builtin_locals ( vm : & VirtualMachine ) -> PyDictRef {
355
+ vm. get_locals ( )
380
356
}
381
357
382
358
fn builtin_max ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
@@ -608,10 +584,9 @@ fn builtin_reversed(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
608
584
match vm. get_method ( obj. clone ( ) , "__reversed__" ) {
609
585
Ok ( value) => vm. invoke ( value, PyFuncArgs :: default ( ) ) ,
610
586
// TODO: fallback to using __len__ and __getitem__, if object supports sequence protocol
611
- Err ( ..) => Err ( vm. new_type_error ( format ! (
612
- "'{}' object is not reversible" ,
613
- objtype:: get_type_name( & obj. typ( ) ) ,
614
- ) ) ) ,
587
+ Err ( ..) => {
588
+ Err ( vm. new_type_error ( format ! ( "'{}' object is not reversible" , obj. class( ) . name) ) )
589
+ }
615
590
}
616
591
}
617
592
// builtin_reversed
@@ -656,14 +631,11 @@ fn builtin_sorted(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResult {
656
631
Ok ( lst)
657
632
}
658
633
659
- fn builtin_sum ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
660
- arg_check ! ( vm, args, required = [ ( iterable, None ) ] ) ;
661
- let items = vm. extract_elements ( iterable) ?;
662
-
634
+ fn builtin_sum ( iterable : PyIterable , start : OptionalArg , vm : & VirtualMachine ) -> PyResult {
663
635
// Start with zero and add at will:
664
- let mut sum = vm. ctx . new_int ( 0 ) ;
665
- for item in items {
666
- sum = vm. _add ( sum, item) ?;
636
+ let mut sum = start . into_option ( ) . unwrap_or_else ( || vm. ctx . new_int ( 0 ) ) ;
637
+ for item in iterable . iter ( vm ) ? {
638
+ sum = vm. _add ( sum, item? ) ?;
667
639
}
668
640
Ok ( sum)
669
641
}
@@ -805,9 +777,9 @@ pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResu
805
777
} ;
806
778
807
779
for base in bases. clone ( ) {
808
- if objtype:: issubclass ( & base. type_pyref ( ) , & metaclass) {
809
- metaclass = base. type_pyref ( ) ;
810
- } else if !objtype:: issubclass ( & metaclass, & base. type_pyref ( ) ) {
780
+ if objtype:: issubclass ( & base. class ( ) , & metaclass) {
781
+ metaclass = base. class ( ) ;
782
+ } else if !objtype:: issubclass ( & metaclass, & base. class ( ) ) {
811
783
return Err ( vm. new_type_error ( "metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases" . to_string ( ) ) ) ;
812
784
}
813
785
}
@@ -818,13 +790,15 @@ pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResu
818
790
let prepare = vm. get_attribute ( metaclass. clone ( ) . into_object ( ) , "__prepare__" ) ?;
819
791
let namespace = vm. invoke ( prepare, vec ! [ name_arg. clone( ) , bases. clone( ) ] ) ?;
820
792
793
+ let namespace: PyDictRef = TryFromObject :: try_from_object ( vm, namespace) ?;
794
+
821
795
let cells = vm. ctx . new_dict ( ) ;
822
796
823
- vm. invoke_with_locals ( function, cells. clone ( ) . into_object ( ) , namespace. clone ( ) ) ?;
797
+ vm. invoke_with_locals ( function, cells. clone ( ) , namespace. clone ( ) ) ?;
824
798
let class = vm. call_method (
825
799
metaclass. as_object ( ) ,
826
800
"__call__" ,
827
- vec ! [ name_arg, bases, namespace] ,
801
+ vec ! [ name_arg, bases, namespace. into_object ( ) ] ,
828
802
) ?;
829
803
cells. set_item ( & vm. ctx , "__class__" , class. clone ( ) ) ;
830
804
Ok ( class)
0 commit comments