@@ -5,7 +5,8 @@ use core::ptr::NonNull;
55use rustpython_vm:: builtins:: { PyStr , PyType , object_generic_set_dict, object_get_dict} ;
66use rustpython_vm:: bytecode:: ComparisonOperator ;
77use rustpython_vm:: function:: PySetterValue ;
8- use rustpython_vm:: { AsObject , Py , PyPayload } ;
8+ use rustpython_vm:: types:: { PyComparisonOp , hash_not_implemented} ;
9+ use rustpython_vm:: { AsObject , Py , PyPayload , PyResult , VirtualMachine } ;
910
1011pub type PyTypeObject = Py < PyType > ;
1112
@@ -100,25 +101,27 @@ pub unsafe extern "C" fn PyType_GetFullyQualifiedName(ptr: *const PyTypeObject)
100101 } )
101102}
102103
104+ #[ inline]
105+ fn get_constant ( vm : & VirtualMachine , constant_id : c_uint ) -> PyResult < & PyObject > {
106+ let ctx = & vm. ctx ;
107+ match constant_id {
108+ 0 => Ok ( ctx. none . as_object ( ) ) ,
109+ 1 => Ok ( ctx. false_value . as_object ( ) ) ,
110+ 2 => Ok ( ctx. true_value . as_object ( ) ) ,
111+ 3 => Ok ( ctx. ellipsis . as_object ( ) ) ,
112+ 4 => Ok ( ctx. not_implemented . as_object ( ) ) ,
113+ _ => Err ( vm. new_system_error ( "Invalid constant ID passed to Py_GetConstantBorrowed" ) ) ,
114+ }
115+ }
116+
103117#[ unsafe( no_mangle) ]
104118pub extern "C" fn Py_GetConstantBorrowed ( constant_id : c_uint ) -> * mut PyObject {
105- with_vm ( |vm| {
106- let ctx = & vm. ctx ;
107- let constant = match constant_id {
108- 0 => ctx. none . as_object ( ) ,
109- 1 => ctx. false_value . as_object ( ) ,
110- 2 => ctx. true_value . as_object ( ) ,
111- 3 => ctx. ellipsis . as_object ( ) ,
112- 4 => ctx. not_implemented . as_object ( ) ,
113- _ => {
114- return Err (
115- vm. new_system_error ( "Invalid constant ID passed to Py_GetConstantBorrowed" )
116- ) ;
117- }
118- }
119- . as_raw ( ) ;
120- Ok ( constant)
121- } )
119+ with_vm ( |vm| get_constant ( vm, constant_id) . map ( PyObject :: as_raw) )
120+ }
121+
122+ #[ unsafe( no_mangle) ]
123+ pub extern "C" fn Py_GetConstant ( constant_id : c_uint ) -> * mut PyObject {
124+ with_vm ( |vm| get_constant ( vm, constant_id) . map ( ToOwned :: to_owned) )
122125}
123126
124127#[ unsafe( no_mangle) ]
@@ -143,12 +146,22 @@ pub unsafe extern "C" fn PyObject_GetAttrString(
143146 let name = unsafe {
144147 CStr :: from_ptr ( attr_name)
145148 . to_str ( )
146- . expect ( "attribute name must be valid UTF-8" )
149+ . map_err ( |_| vm . new_value_error ( "attribute name must be valid UTF-8" ) ) ?
147150 } ;
148151 obj. get_attr ( name, vm)
149152 } )
150153}
151154
155+ #[ unsafe( no_mangle) ]
156+ pub unsafe extern "C" fn PyObject_ASCII ( obj : * mut PyObject ) -> * mut PyObject {
157+ with_vm ( |vm| unsafe { & * obj } . ascii ( vm) )
158+ }
159+
160+ #[ unsafe( no_mangle) ]
161+ pub unsafe extern "C" fn PyObject_Bytes ( obj : * mut PyObject ) -> * mut PyObject {
162+ with_vm ( |vm| unsafe { & * obj } . to_owned ( ) . bytes ( vm) )
163+ }
164+
152165#[ unsafe( no_mangle) ]
153166pub unsafe extern "C" fn PyObject_GetOptionalAttr (
154167 obj : * mut PyObject ,
@@ -172,6 +185,31 @@ pub unsafe extern "C" fn PyObject_GetOptionalAttr(
172185 } )
173186}
174187
188+ #[ unsafe( no_mangle) ]
189+ pub unsafe extern "C" fn PyObject_GetOptionalAttrString (
190+ obj : * mut PyObject ,
191+ attr_name : * const c_char ,
192+ result : * mut * mut PyObject ,
193+ ) -> c_int {
194+ with_vm ( |vm| {
195+ unsafe {
196+ * result = core:: ptr:: null_mut ( ) ;
197+ }
198+ let obj = unsafe { & * obj } ;
199+ let name = unsafe { CStr :: from_ptr ( attr_name) }
200+ . to_str ( )
201+ . map_err ( |_| vm. new_value_error ( "attribute name must be valid UTF-8" ) ) ?;
202+ if let Some ( attr) = vm. get_attribute_opt ( obj. to_owned ( ) , name) ? {
203+ unsafe {
204+ * result = attr. into_raw ( ) . as_ptr ( ) ;
205+ }
206+ Ok ( true )
207+ } else {
208+ Ok ( false )
209+ }
210+ } )
211+ }
212+
175213#[ unsafe( no_mangle) ]
176214pub unsafe extern "C" fn PyObject_SetAttrString (
177215 obj : * mut PyObject ,
@@ -182,7 +220,7 @@ pub unsafe extern "C" fn PyObject_SetAttrString(
182220 let obj = unsafe { & * obj } ;
183221 let name = unsafe { CStr :: from_ptr ( attr_name) }
184222 . to_str ( )
185- . expect ( "attribute name must be valid UTF-8" ) ;
223+ . map_err ( |_| vm . new_value_error ( "attribute name must be valid UTF-8" ) ) ? ;
186224 let value = unsafe { & * value } . to_owned ( ) ;
187225 obj. set_attr ( name, value, vm)
188226 } )
@@ -202,6 +240,46 @@ pub unsafe extern "C" fn PyObject_SetAttr(
202240 } )
203241}
204242
243+ #[ unsafe( no_mangle) ]
244+ pub unsafe extern "C" fn PyObject_DelAttr ( obj : * mut PyObject , name : * mut PyObject ) -> c_int {
245+ with_vm ( |vm| {
246+ let obj = unsafe { & * obj } ;
247+ let name = unsafe { & * name } . try_downcast_ref :: < PyStr > ( vm) ?;
248+ obj. del_attr ( name, vm)
249+ } )
250+ }
251+
252+ #[ unsafe( no_mangle) ]
253+ pub unsafe extern "C" fn PyObject_DelAttrString (
254+ obj : * mut PyObject ,
255+ attr_name : * const c_char ,
256+ ) -> c_int {
257+ with_vm ( |vm| {
258+ let obj = unsafe { & * obj } ;
259+ let name = unsafe { CStr :: from_ptr ( attr_name) }
260+ . to_str ( )
261+ . map_err ( |_| vm. new_value_error ( "attribute name must be valid UTF-8" ) ) ?;
262+ obj. del_attr ( name, vm)
263+ } )
264+ }
265+
266+ #[ unsafe( no_mangle) ]
267+ pub unsafe extern "C" fn PyObject_GenericSetAttr (
268+ obj : * mut PyObject ,
269+ name : * mut PyObject ,
270+ value : * mut PyObject ,
271+ ) -> c_int {
272+ with_vm ( |vm| {
273+ let obj = unsafe { & * obj } ;
274+ let name = unsafe { & * name } . try_downcast_ref :: < PyStr > ( vm) ?;
275+ let value = match NonNull :: new ( value) {
276+ Some ( value) => PySetterValue :: Assign ( unsafe { value. as_ref ( ) } . to_owned ( ) ) ,
277+ None => PySetterValue :: Delete ,
278+ } ;
279+ obj. generic_setattr ( name, value, vm)
280+ } )
281+ }
282+
205283#[ unsafe( no_mangle) ]
206284pub unsafe extern "C" fn PyObject_HasAttrWithError (
207285 obj : * mut PyObject ,
@@ -214,6 +292,63 @@ pub unsafe extern "C" fn PyObject_HasAttrWithError(
214292 } )
215293}
216294
295+ #[ unsafe( no_mangle) ]
296+ pub unsafe extern "C" fn PyObject_HasAttr ( obj : * mut PyObject , attr_name : * mut PyObject ) -> c_int {
297+ with_vm ( |vm| {
298+ let obj = unsafe { & * obj } ;
299+ let name = match unsafe { & * attr_name } . try_downcast_ref :: < PyStr > ( vm) {
300+ Ok ( name) => name,
301+ Err ( err) => {
302+ vm. run_unraisable ( err, None , obj. to_owned ( ) ) ;
303+ return false ;
304+ }
305+ } ;
306+
307+ match obj. has_attr ( name, vm) {
308+ Ok ( has_attr) => has_attr,
309+ Err ( err) => {
310+ vm. run_unraisable ( err, None , obj. to_owned ( ) ) ;
311+ false
312+ }
313+ }
314+ } )
315+ }
316+
317+ #[ unsafe( no_mangle) ]
318+ pub unsafe extern "C" fn PyObject_HasAttrString (
319+ obj : * mut PyObject ,
320+ attr_name : * const c_char ,
321+ ) -> c_int {
322+ with_vm ( |vm| {
323+ let obj = unsafe { & * obj } ;
324+ let Ok ( name) = unsafe { CStr :: from_ptr ( attr_name) } . to_str ( ) else {
325+ return false ;
326+ } ;
327+
328+ match obj. has_attr ( name, vm) {
329+ Ok ( has_attr) => has_attr,
330+ Err ( err) => {
331+ vm. run_unraisable ( err, None , obj. to_owned ( ) ) ;
332+ false
333+ }
334+ }
335+ } )
336+ }
337+
338+ #[ unsafe( no_mangle) ]
339+ pub unsafe extern "C" fn PyObject_HasAttrStringWithError (
340+ obj : * mut PyObject ,
341+ attr_name : * const c_char ,
342+ ) -> c_int {
343+ with_vm ( |vm| {
344+ let obj = unsafe { & * obj } ;
345+ let name = unsafe { CStr :: from_ptr ( attr_name) }
346+ . to_str ( )
347+ . map_err ( |_| vm. new_value_error ( "attribute name must be valid UTF-8" ) ) ?;
348+ obj. has_attr ( name, vm)
349+ } )
350+ }
351+
217352#[ unsafe( no_mangle) ]
218353pub unsafe extern "C" fn PyObject_GenericGetAttr (
219354 obj : * mut PyObject ,
@@ -248,26 +383,44 @@ pub extern "C" fn PyObject_Str(obj: *mut PyObject) -> *mut PyObject {
248383 } )
249384}
250385
386+ #[ inline]
387+ fn parse_richcompare_op ( vm : & VirtualMachine , op : c_int ) -> PyResult < PyComparisonOp > {
388+ match op {
389+ 0 => Ok ( ComparisonOperator :: Less ) ,
390+ 1 => Ok ( ComparisonOperator :: LessOrEqual ) ,
391+ 2 => Ok ( ComparisonOperator :: Equal ) ,
392+ 3 => Ok ( ComparisonOperator :: NotEqual ) ,
393+ 4 => Ok ( ComparisonOperator :: Greater ) ,
394+ 5 => Ok ( ComparisonOperator :: GreaterOrEqual ) ,
395+ _ => Err ( vm. new_system_error ( "invalid comparison operator" ) ) ,
396+ }
397+ . map ( Into :: into)
398+ }
399+
251400#[ unsafe( no_mangle) ]
252401pub unsafe extern "C" fn PyObject_RichCompare (
253402 left : * mut PyObject ,
254403 right : * mut PyObject ,
255404 op : c_int ,
256405) -> * mut PyObject {
257406 with_vm ( |vm| {
258- let op = match op {
259- 0 => ComparisonOperator :: Less ,
260- 1 => ComparisonOperator :: LessOrEqual ,
261- 2 => ComparisonOperator :: Equal ,
262- 3 => ComparisonOperator :: NotEqual ,
263- 4 => ComparisonOperator :: Greater ,
264- 5 => ComparisonOperator :: GreaterOrEqual ,
265- _ => return Err ( vm. new_system_error ( "invalid comparison operator" ) ) ,
266- } ;
267407 let left = unsafe { & * left } ;
268408 let right = unsafe { & * right } ;
269409 left. to_owned ( )
270- . rich_compare ( right. to_owned ( ) , op. into ( ) , vm)
410+ . rich_compare ( right. to_owned ( ) , parse_richcompare_op ( vm, op) ?, vm)
411+ } )
412+ }
413+
414+ #[ unsafe( no_mangle) ]
415+ pub unsafe extern "C" fn PyObject_RichCompareBool (
416+ left : * mut PyObject ,
417+ right : * mut PyObject ,
418+ op : c_int ,
419+ ) -> c_int {
420+ with_vm ( |vm| {
421+ let left = unsafe { & * left } ;
422+ let right = unsafe { & * right } ;
423+ left. rich_compare_bool ( right, parse_richcompare_op ( vm, op) ?, vm)
271424 } )
272425}
273426
@@ -298,6 +451,69 @@ pub unsafe extern "C" fn PyObject_IsTrue(obj: *mut PyObject) -> c_int {
298451 } )
299452}
300453
454+ #[ unsafe( no_mangle) ]
455+ pub unsafe extern "C" fn PyObject_Not ( obj : * mut PyObject ) -> c_int {
456+ with_vm ( |vm| {
457+ let obj = unsafe { & * obj } ;
458+ obj. to_owned ( ) . not ( vm)
459+ } )
460+ }
461+
462+ #[ unsafe( no_mangle) ]
463+ pub unsafe extern "C" fn PyObject_Hash ( obj : * mut PyObject ) -> isize {
464+ with_vm ( |vm| {
465+ let obj = unsafe { & * obj } ;
466+ obj. hash ( vm) . map ( |hash| hash as isize )
467+ } )
468+ }
469+
470+ #[ unsafe( no_mangle) ]
471+ pub unsafe extern "C" fn PyObject_HashNotImplemented ( obj : * mut PyObject ) -> isize {
472+ with_vm ( |vm| {
473+ let obj = unsafe { & * obj } ;
474+ hash_not_implemented ( obj, vm) . map ( |hash| hash as isize )
475+ } )
476+ }
477+
478+ #[ unsafe( no_mangle) ]
479+ pub unsafe extern "C" fn PyObject_SelfIter ( obj : * mut PyObject ) -> * mut PyObject {
480+ with_vm ( |_vm| unsafe { ( & * obj) . to_owned ( ) } )
481+ }
482+
483+ #[ unsafe( no_mangle) ]
484+ pub unsafe extern "C" fn Py_Is ( x : * mut PyObject , y : * mut PyObject ) -> c_int {
485+ ( x == y) as c_int
486+ }
487+
488+ #[ unsafe( no_mangle) ]
489+ pub unsafe extern "C" fn Py_IsNone ( x : * mut PyObject ) -> c_int {
490+ with_vm ( |vm| vm. is_none ( unsafe { & * x } ) )
491+ }
492+
493+ #[ unsafe( no_mangle) ]
494+ pub unsafe extern "C" fn Py_ReprEnter ( obj : * mut PyObject ) -> c_int {
495+ with_vm ( |vm| {
496+ let obj = unsafe { & * obj } ;
497+ let id = obj. get_id ( ) ;
498+ let mut guards = vm. repr_guards . borrow_mut ( ) ;
499+ if guards. contains ( & id) {
500+ true
501+ } else {
502+ guards. insert ( id) ;
503+ false
504+ }
505+ } )
506+ }
507+
508+ #[ unsafe( no_mangle) ]
509+ pub unsafe extern "C" fn Py_ReprLeave ( obj : * mut PyObject ) {
510+ with_vm ( |vm| {
511+ vm. repr_guards
512+ . borrow_mut ( )
513+ . remove ( & unsafe { & * obj } . get_id ( ) ) ;
514+ } )
515+ }
516+
301517#[ unsafe( no_mangle) ]
302518pub unsafe extern "C" fn PyObject_GenericGetDict (
303519 obj : * mut PyObject ,
0 commit comments