@@ -24,12 +24,9 @@ mod decl {
2424 #[ cfg( feature = "rustpython-compiler" ) ]
2525 use crate :: compile;
2626 use crate :: exceptions:: PyBaseExceptionRef ;
27- use crate :: function:: { single_or_tuple_any, Args , FuncArgs , KwArgs , OptionalArg } ;
27+ use crate :: function:: { single_or_tuple_any, Args , FuncArgs , KwArgs , OptionalArg , OptionalOption } ;
2828 use crate :: iterator;
29- use crate :: pyobject:: {
30- BorrowValue , Either , IdProtocol , ItemProtocol , PyCallable , PyIterable , PyObjectRef ,
31- PyResult , PyValue , TryFromObject , TypeProtocol ,
32- } ;
29+ use crate :: pyobject:: { BorrowValue , Either , IdProtocol , ItemProtocol , PyCallable , PyIterable , PyObjectRef , PyResult , PyValue , TryFromObject , TypeProtocol , PyArithmaticValue } ;
3330 use crate :: readline:: { Readline , ReadlineResult } ;
3431 use crate :: scope:: Scope ;
3532 use crate :: sliceable;
@@ -38,6 +35,7 @@ mod decl {
3835 use crate :: { py_io, sysmodule} ;
3936 use num_bigint:: Sign ;
4037 use num_traits:: { Signed , ToPrimitive , Zero } ;
38+ use crate :: builtins:: PyInt ;
4139
4240 #[ pyfunction]
4341 fn abs ( x : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
@@ -177,7 +175,7 @@ mod decl {
177175 #[ pyfunction]
178176 fn divmod ( a : PyObjectRef , b : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
179177 vm. call_or_reflection ( & a, & b, "__divmod__" , "__rdivmod__" , |vm, a, b| {
180- Err ( vm. new_unsupported_operand_error ( a, b, "divmod" ) )
178+ Err ( vm. new_unsupported_binop_error ( a, b, "divmod" ) )
181179 } )
182180 }
183181
@@ -586,36 +584,46 @@ mod decl {
586584 fn pow (
587585 x : PyObjectRef ,
588586 y : PyObjectRef ,
589- mod_value : OptionalArg < PyIntRef > ,
587+ mod_value : OptionalOption < PyObjectRef > ,
590588 vm : & VirtualMachine ,
591589 ) -> PyResult {
592- match mod_value {
593- OptionalArg :: Missing => {
590+ match mod_value. flatten ( ) {
591+ None => {
594592 vm. call_or_reflection ( & x, & y, "__pow__" , "__rpow__" , |vm, x, y| {
595- Err ( vm. new_unsupported_operand_error ( x, y, "pow" ) )
593+ Err ( vm. new_unsupported_binop_error ( x, y, "pow" ) )
596594 } )
597595 }
598- OptionalArg :: Present ( m) => {
599- // Check if the 3rd argument is defined and perform modulus on the result
600- if !( x. isinstance ( & vm. ctx . types . int_type ) && y. isinstance ( & vm. ctx . types . int_type ) ) {
601- return Err ( vm. new_type_error (
602- "pow() 3rd argument not allowed unless all arguments are integers"
603- . to_owned ( ) ,
604- ) ) ;
596+ Some ( z) => {
597+ let try_pow_value = |obj : & PyObjectRef , args : ( PyObjectRef , PyObjectRef , PyObjectRef ) | -> Option < PyResult > {
598+ if let Some ( method) = obj. get_class_attr ( "__pow__" ) {
599+ let result = match vm. invoke ( & method, args) {
600+ Ok ( x) => x,
601+ Err ( e) => return Some ( Err ( e) ) ,
602+ } ;
603+ if let PyArithmaticValue :: Implemented ( x) = PyArithmaticValue :: from_object ( vm, result) {
604+ return Some ( Ok ( x) )
605+ }
606+ }
607+ None
608+ } ;
609+
610+ if let Some ( val) = try_pow_value ( & x, ( x. clone ( ) , y. clone ( ) , z. clone ( ) ) ) {
611+ return val
605612 }
606- let y = int:: get_value ( & y) ;
607- if y. sign ( ) == Sign :: Minus {
608- return Err ( vm. new_value_error (
609- "pow() 2nd argument cannot be negative when 3rd argument specified"
610- . to_owned ( ) ,
611- ) ) ;
613+
614+ if !x. class ( ) . is ( & y. class ( ) ) {
615+ if let Some ( val) = try_pow_value ( & y, ( x. clone ( ) , y. clone ( ) , z. clone ( ) ) ) {
616+ return val
617+ }
612618 }
613- let m = m. borrow_value ( ) ;
614- if m. is_zero ( ) {
615- return Err ( vm. new_value_error ( "pow() 3rd argument cannot be 0" . to_owned ( ) ) ) ;
619+
620+ if !x. class ( ) . is ( & z. class ( ) ) && !y. class ( ) . is ( & z. class ( ) ) {
621+ if let Some ( val) = try_pow_value ( & z, ( x. clone ( ) , y. clone ( ) , z. clone ( ) ) ) {
622+ return val
623+ }
616624 }
617- let x = int :: get_value ( & x ) ;
618- Ok ( vm. ctx . new_int ( x . modpow ( & y, & m ) ) )
625+
626+ Err ( vm. new_unsupported_ternop_error ( & x , & y, & z , "pow" ) )
619627 }
620628 }
621629 }
0 commit comments