Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
8d7ee810
Commit
8d7ee810
authored
Jan 04, 2001
by
Neil Schemenauer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Massive changes as per PEP 208. Read it for details.
parent
7f2458c3
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
318 additions
and
728 deletions
+318
-728
Objects/abstract.c
Objects/abstract.c
+318
-728
No files found.
Objects/abstract.c
View file @
8d7ee810
/* Abstract Object Interface (many thanks to Jim Fulton) */
#include "Python.h"
#include <ctype.h>
#include "structmember.h"
/* we need the offsetof() macro from there */
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
Py_TPFLAGS_NEWSTYLENUMBER)
/* Shorthands to return certain errors */
...
...
@@ -281,830 +286,415 @@ PyNumber_Check(PyObject *o)
/* Binary operators */
#define BINOP(v, w, opname, ropname, thisfunc) \
if (PyInstance_Check(v) || PyInstance_Check(w)) \
return PyInstance_DoBinOp(v, w, opname, ropname, thisfunc)
/* New style number protocol support */
PyObject
*
PyNumber_Or
(
PyObject
*
v
,
PyObject
*
w
)
{
BINOP
(
v
,
w
,
"__or__"
,
"__ror__"
,
PyNumber_Or
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_or
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for |"
);
}
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
#define NB_BINOP(nb_methods, slot) \
((binaryfunc*)(& ((char*)nb_methods)[slot] ))
#define NB_TERNOP(nb_methods, slot) \
((ternaryfunc*)(& ((char*)nb_methods)[slot] ))
PyObject
*
PyNumber_Xor
(
PyObject
*
v
,
PyObject
*
w
)
{
BINOP
(
v
,
w
,
"__xor__"
,
"__rxor__"
,
PyNumber_Xor
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_xor
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for ^"
);
}
/*
Calling scheme used for binary operations:
PyObject
*
PyNumber_And
(
PyObject
*
v
,
PyObject
*
w
)
{
BINOP
(
v
,
w
,
"__and__"
,
"__rand__"
,
PyNumber_And
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_and
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for &"
);
}
v w Action
-------------------------------------------------------------------
new new v.op(v,w), w.op(v,w)
new old v.op(v,w), coerce(v,w), v.op(v,w)
old new w.op(v,w), coerce(v,w), v.op(v,w)
old old coerce(v,w), v.op(v,w)
PyObject
*
PyNumber_Lshift
(
PyObject
*
v
,
PyObject
*
w
)
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
*/
static
PyObject
*
binary_op1
(
PyObject
*
v
,
PyObject
*
w
,
const
int
op_slot
)
{
BINOP
(
v
,
w
,
"__lshift__"
,
"__rlshift__"
,
PyNumber_Lshift
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
PyObject
*
x
;
binaryfunc
*
slot
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
{
slot
=
NB_BINOP
(
v
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
*
slot
)
{
x
=
(
*
slot
)(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
{
return
x
;
}
Py_DECREF
(
x
);
/* can't do it */
}
if
(
v
->
ob_type
==
w
->
ob_type
)
{
goto
binop_error
;
}
}
if
(
w
->
ob_type
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
slot
=
NB_BINOP
(
w
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
*
slot
)
{
x
=
(
*
slot
)(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
{
return
x
;
}
Py_DECREF
(
x
);
/* can't do it */
}
}
if
(
!
NEW_STYLE_NUMBER
(
v
)
||
!
NEW_STYLE_NUMBER
(
w
))
{
int
err
=
PyNumber_CoerceEx
(
&
v
,
&
w
);
if
(
err
<
0
)
{
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_lshift
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
if
(
err
==
0
)
{
PyNumberMethods
*
mv
=
v
->
ob_type
->
tp_as_number
;
if
(
mv
)
{
slot
=
NB_BINOP
(
mv
,
op_slot
);
if
(
*
slot
)
{
PyObject
*
x
=
(
*
slot
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
x
;
}
}
/* CoerceEx incremented the reference counts */
Py_DECREF
(
v
);
Py_DECREF
(
w
);
}
}
return
type_error
(
"bad operand type(s) for <<"
);
binop_error:
Py_INCREF
(
Py_NotImplemented
);
return
Py_NotImplemented
;
}
PyObject
*
PyNumber_Rshift
(
PyObject
*
v
,
PyObject
*
w
)
static
PyObject
*
binary_op
(
PyObject
*
v
,
PyObject
*
w
,
const
int
op_slot
,
const
char
*
op_name
)
{
BINOP
(
v
,
w
,
"__rshift__"
,
"__rrshift__"
,
PyNumber_Rshift
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_rshift
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
PyObject
*
result
=
binary_op1
(
v
,
w
,
op_slot
);
if
(
result
==
Py_NotImplemented
)
{
Py_DECREF
(
Py_NotImplemented
);
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for %s"
,
op_name
);
return
NULL
;
}
return
type_error
(
"bad operand type(s) for >>"
)
;
return
result
;
}
PyObject
*
PyNumber_Add
(
PyObject
*
v
,
PyObject
*
w
)
{
PySequenceMethods
*
m
;
BINOP
(
v
,
w
,
"__add__"
,
"__radd__"
,
PyNumber_Add
);
m
=
v
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_concat
)
return
(
*
m
->
sq_concat
)(
v
,
w
);
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_add
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for +"
);
}
/*
Calling scheme used for ternary operations:
PyObject
*
PyNumber_Subtract
(
PyObject
*
v
,
PyObject
*
w
)
{
BINOP
(
v
,
w
,
"__sub__"
,
"__rsub__"
,
PyNumber_Subtract
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_subtract
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for -"
);
}
v w z Action
-------------------------------------------------------------------
new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old old coerce(v,w,z), v.op(v,w,z)
PyObject
*
PyNumber_Multiply
(
PyObject
*
v
,
PyObject
*
w
)
{
PyTypeObject
*
tp
=
v
->
ob_type
;
PySequenceMethods
*
m
;
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
* coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
only if z != Py_None; if z == Py_None, then it is treated as absent
variable and only coerce(v,w) is tried.
BINOP
(
v
,
w
,
"__mul__"
,
"__rmul__"
,
PyNumber_Multiply
);
if
(
tp
->
tp_as_number
!=
NULL
&&
w
->
ob_type
->
tp_as_sequence
!=
NULL
)
{
/* number*sequence -- swap v and w */
PyObject
*
tmp
=
v
;
v
=
w
;
w
=
tmp
;
tp
=
v
->
ob_type
;
}
if
(
tp
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_multiply
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
m
=
tp
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_repeat
)
{
long
mul_value
;
*/
if
(
PyInt_Check
(
w
))
{
mul_value
=
PyInt_AsLong
(
w
);
static
PyObject
*
ternary_op
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
,
const
int
op_slot
,
const
char
*
op_name
)
{
PyNumberMethods
*
mv
,
*
mw
,
*
mz
;
register
PyObject
*
x
=
NULL
;
register
ternaryfunc
*
slot
;
mv
=
v
->
ob_type
->
tp_as_number
;
if
(
mv
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
{
/* try v.op(v,w,z) */
slot
=
NB_TERNOP
(
mv
,
op_slot
);
if
(
*
slot
)
{
x
=
(
*
slot
)(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
/* Can't do it... fall through */
Py_DECREF
(
x
);
}
else
if
(
PyLong_Check
(
w
))
{
mul_value
=
PyLong_AsLong
(
w
);
if
(
mul_value
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
v
->
ob_type
==
w
->
ob_type
&&
(
z
==
Py_None
||
z
->
ob_type
==
v
->
ob_type
))
{
goto
ternary_error
;
}
else
{
return
type_error
(
"can't multiply sequence with non-int"
);
}
mw
=
w
->
ob_type
->
tp_as_number
;
if
(
mw
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
/* try w.op(v,w,z) */
slot
=
NB_TERNOP
(
mw
,
op_slot
);
if
(
*
slot
)
{
x
=
(
*
slot
)(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
/* Can't do it... fall through */
Py_DECREF
(
x
);
}
if
(
NEW_STYLE_NUMBER
(
v
)
&&
(
z
==
Py_None
||
z
->
ob_type
==
v
->
ob_type
))
{
goto
ternary_error
;
}
return
(
*
m
->
sq_repeat
)(
v
,
(
int
)
mul_value
);
}
return
type_error
(
"bad operand type(s) for *"
);
}
PyObject
*
PyNumber_Divide
(
PyObject
*
v
,
PyObject
*
w
)
{
BINOP
(
v
,
w
,
"__div__"
,
"__rdiv__"
,
PyNumber_Divide
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_divide
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
mz
=
z
->
ob_type
->
tp_as_number
;
if
(
mz
!=
NULL
&&
NEW_STYLE_NUMBER
(
z
))
{
/* try: z.op(v,w,z) */
slot
=
NB_TERNOP
(
mz
,
op_slot
);
if
(
*
slot
)
{
x
=
(
*
slot
)(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
/* Can't do it... fall through */
Py_DECREF
(
x
);
}
}
return
type_error
(
"bad operand type(s) for /"
);
}
PyObject
*
PyNumber_Remainder
(
PyObject
*
v
,
PyObject
*
w
)
{
if
(
PyString_Check
(
v
))
return
PyString_Format
(
v
,
w
);
else
if
(
PyUnicode_Check
(
v
))
return
PyUnicode_Format
(
v
,
w
);
BINOP
(
v
,
w
,
"__mod__"
,
"__rmod__"
,
PyNumber_Remainder
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_remainder
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
if
(
!
NEW_STYLE_NUMBER
(
v
)
||
!
NEW_STYLE_NUMBER
(
w
)
||
(
z
!=
Py_None
&&
!
NEW_STYLE_NUMBER
(
z
)))
{
/* we have an old style operand, coerce */
PyObject
*
v1
,
*
z1
,
*
w2
,
*
z2
;
int
c
;
c
=
PyNumber_Coerce
(
&
v
,
&
w
);
if
(
c
!=
0
)
goto
error3
;
/* Special case: if the third argument is None, it is
treated as absent argument and not coerced. */
if
(
z
==
Py_None
)
{
if
(
v
->
ob_type
->
tp_as_number
)
{
slot
=
NB_TERNOP
(
v
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
*
slot
)
x
=
(
*
slot
)(
v
,
w
,
z
);
else
c
=
-
1
;
}
else
c
=
-
1
;
goto
error2
;
}
v1
=
v
;
z1
=
z
;
c
=
PyNumber_Coerce
(
&
v1
,
&
z1
);
if
(
c
!=
0
)
goto
error2
;
w2
=
w
;
z2
=
z1
;
c
=
PyNumber_Coerce
(
&
w2
,
&
z2
);
if
(
c
!=
0
)
goto
error1
;
if
(
v1
->
ob_type
->
tp_as_number
!=
NULL
)
{
slot
=
NB_TERNOP
(
v1
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
*
slot
)
x
=
(
*
slot
)(
v1
,
w2
,
z2
);
else
c
=
-
1
;
}
else
c
=
-
1
;
Py_DECREF
(
w2
);
Py_DECREF
(
z2
);
error1:
Py_DECREF
(
v1
);
Py_DECREF
(
z1
);
error2:
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
error3:
if
(
c
>=
0
)
return
x
;
}
return
type_error
(
"bad operand type(s) for %"
);
ternary_error:
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for %s"
,
op_name
);
return
NULL
;
}
#define BINARY_FUNC(func, op, op_name) \
PyObject * \
func(PyObject *v, PyObject *w) { \
return binary_op(v, w, NB_SLOT(op), op_name); \
}
BINARY_FUNC
(
PyNumber_Or
,
nb_or
,
"|"
)
BINARY_FUNC
(
PyNumber_Xor
,
nb_xor
,
"^"
)
BINARY_FUNC
(
PyNumber_And
,
nb_and
,
"&"
)
BINARY_FUNC
(
PyNumber_Lshift
,
nb_lshift
,
"<<"
)
BINARY_FUNC
(
PyNumber_Rshift
,
nb_rshift
,
">>"
)
BINARY_FUNC
(
PyNumber_Subtract
,
nb_subtract
,
"-"
)
BINARY_FUNC
(
PyNumber_Multiply
,
nb_multiply
,
"*"
)
BINARY_FUNC
(
PyNumber_Divide
,
nb_divide
,
"/"
)
BINARY_FUNC
(
PyNumber_Divmod
,
nb_divmod
,
"divmod()"
)
PyObject
*
PyNumber_
Divmo
d
(
PyObject
*
v
,
PyObject
*
w
)
PyNumber_
Ad
d
(
PyObject
*
v
,
PyObject
*
w
)
{
BINOP
(
v
,
w
,
"__divmod__"
,
"__rdivmod__"
,
PyNumber_Divmod
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_divmod
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
PyObject
*
result
=
binary_op1
(
v
,
w
,
NB_SLOT
(
nb_add
));
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
m
=
v
->
ob_type
->
tp_as_sequence
;
Py_DECREF
(
Py_NotImplemented
);
if
(
m
&&
m
->
sq_concat
)
{
result
=
(
*
m
->
sq_concat
)(
v
,
w
);
}
else
{
PyErr_SetString
(
PyExc_TypeError
,
"unsupported operand types for +"
);
result
=
NULL
;
}
}
return
type_error
(
"bad operand type(s) for divmod()"
)
;
return
result
;
}
/* Power (binary or ternary) */
static
PyObject
*
do_pow
(
PyObject
*
v
,
PyObject
*
w
)
PyObject
*
PyNumber_Remainder
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
res
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
,
PyObject
*
);
BINOP
(
v
,
w
,
"__pow__"
,
"__rpow__"
,
do_pow
);
if
(
v
->
ob_type
->
tp_as_number
==
NULL
||
w
->
ob_type
->
tp_as_number
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"pow(x, y) requires numeric arguments"
);
return
NULL
;
}
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_power
)
!=
NULL
)
res
=
(
*
f
)(
v
,
w
,
Py_None
);
else
res
=
type_error
(
"pow(x, y) not defined for these operands"
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
res
;
if
(
PyString_Check
(
v
))
return
PyString_Format
(
v
,
w
);
else
if
(
PyUnicode_Check
(
v
))
return
PyUnicode_Format
(
v
,
w
);
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_remainder
),
"%"
);
}
PyObject
*
PyNumber_Power
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
{
PyObject
*
res
;
PyObject
*
v1
,
*
z1
,
*
w2
,
*
z2
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
,
PyObject
*
);
if
(
z
==
Py_None
)
return
do_pow
(
v
,
w
);
/* XXX The ternary version doesn't do class instance coercions */
if
(
PyInstance_Check
(
v
))
return
v
->
ob_type
->
tp_as_number
->
nb_power
(
v
,
w
,
z
);
if
(
v
->
ob_type
->
tp_as_number
==
NULL
||
z
->
ob_type
->
tp_as_number
==
NULL
||
w
->
ob_type
->
tp_as_number
==
NULL
)
{
return
type_error
(
"pow(x, y, z) requires numeric arguments"
);
}
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
res
=
NULL
;
v1
=
v
;
z1
=
z
;
if
(
PyNumber_Coerce
(
&
v1
,
&
z1
)
!=
0
)
goto
error2
;
w2
=
w
;
z2
=
z1
;
if
(
PyNumber_Coerce
(
&
w2
,
&
z2
)
!=
0
)
goto
error1
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v1
->
ob_type
->
tp_as_number
->
nb_power
)
!=
NULL
)
res
=
(
*
f
)(
v1
,
w2
,
z2
);
else
res
=
type_error
(
"pow(x, y, z) not defined for these operands"
);
Py_DECREF
(
w2
);
Py_DECREF
(
z2
);
error1:
Py_DECREF
(
v1
);
Py_DECREF
(
z1
);
error2:
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
res
;
return
ternary_op
(
v
,
w
,
z
,
NB_SLOT
(
nb_power
),
"** or pow()"
);
}
/* Binary in-place operators */
/* The in-place operators are defined to fall back to the 'normal',
non in-place operations, if the in-place methods are not in place, and to
take class instances into account. This is how it is supposed to work:
- If the left-hand-side object (the first argument) is an
instance object, try to let PyInstance_HalfBinOp() handle it. Pass the
non in-place variant of the function as callback, because it will only
be used if the left-hand object is changed by coercion.
- Otherwise, if the left hand object is not an instance object, it has
the appropriate struct members, and they are filled, call the
appropriate function and return the result. No coercion is done on the
arguments; the left-hand object is the one the operation is performed
on, and it's up to the function to deal with the right-hand object.
- Otherwise, in-place modification is not supported. Handle it exactly as
a non in-place operation of the same kind:
non in-place operations, if the in-place methods are not in place.
- If either object is an instance, let PyInstance_DoBinOp() handle it.
- If the left hand object has the appropriate struct members, and
they are filled, call the appropriate function and return the
result. No coercion is done on the arguments; the left-hand object
is the one the operation is performed on, and it's up to the
function to deal with the right-hand object.
- Otherwise, both arguments are C types. If the left-hand object has
the appropriate struct members filled, coerce, call the
appropriate function, and return the result.
- Otherwise, we are out of options: raise a type error specific to
augmented assignment.
- Otherwise, in-place modification is not supported. Handle it exactly as
a non in-place operation of the same kind.
*/
#define HASINPLACE(t) PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)
PyObject
*
PyNumber_InPlaceOr
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__ior__"
,
&
x
,
PyNumber_Or
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_or
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
BINOP
(
v
,
w
,
"__or__"
,
"__ror__"
,
PyNumber_Or
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_or
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for |="
);
}
PyObject
*
PyNumber_InPlaceXor
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__ixor__"
,
&
x
,
PyNumber_Xor
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_xor
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
BINOP
(
v
,
w
,
"__xor__"
,
"__rxor__"
,
PyNumber_Xor
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_xor
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for ^="
);
}
PyObject
*
PyNumber_InPlaceAnd
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__iand__"
,
&
x
,
PyNumber_And
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_and
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
BINOP
(
v
,
w
,
"__and__"
,
"__rand__"
,
PyNumber_And
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_and
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for &="
);
}
PyObject
*
PyNumber_InPlaceLshift
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__ilshift__"
,
&
x
,
PyNumber_Lshift
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_lshift
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
BINOP
(
v
,
w
,
"__lshift__"
,
"__rlshift__"
,
PyNumber_Lshift
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_lshift
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
static
PyObject
*
binary_iop
(
PyObject
*
v
,
PyObject
*
w
,
const
int
iop_slot
,
const
int
op_slot
,
const
char
*
op_name
)
{
PyNumberMethods
*
mv
=
v
->
ob_type
->
tp_as_number
;
if
(
mv
!=
NULL
&&
HASINPLACE
(
v
))
{
binaryfunc
*
slot
=
NB_BINOP
(
mv
,
iop_slot
);
if
(
*
slot
)
{
PyObject
*
x
=
(
*
slot
)(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
{
return
x
;
}
Py_DECREF
(
x
);
}
}
return
type_error
(
"bad operand type(s) for <<="
);
return
binary_op
(
v
,
w
,
op_slot
,
op_name
);
}
PyObject
*
PyNumber_InPlaceRshift
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__irshift__"
,
&
x
,
PyNumber_Rshift
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_rshift
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
BINOP
(
v
,
w
,
"__rshift__"
,
"__rrshift__"
,
PyNumber_Rshift
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_rshift
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
#define INPLACE_BINOP(func, iop, op, op_name) \
PyObject * \
func(PyObject *v, PyObject *w) { \
return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \
}
return
type_error
(
"bad operand type(s) for >>="
);
}
INPLACE_BINOP
(
PyNumber_InPlaceOr
,
nb_inplace_or
,
nb_or
,
"|="
)
INPLACE_BINOP
(
PyNumber_InPlaceXor
,
nb_inplace_xor
,
nb_xor
,
"^="
)
INPLACE_BINOP
(
PyNumber_InPlaceAnd
,
nb_inplace_and
,
nb_and
,
"&="
)
INPLACE_BINOP
(
PyNumber_InPlaceLshift
,
nb_inplace_lshift
,
nb_lshift
,
"<<="
)
INPLACE_BINOP
(
PyNumber_InPlaceRshift
,
nb_inplace_rshift
,
nb_rshift
,
">>="
)
INPLACE_BINOP
(
PyNumber_InPlaceSubtract
,
nb_inplace_subtract
,
nb_subtract
,
"-="
)
INPLACE_BINOP
(
PyNumber_InPlaceDivide
,
nb_inplace_divide
,
nb_divide
,
"/="
)
PyObject
*
PyNumber_InPlaceAdd
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__iadd__"
,
&
x
,
PyNumber_Add
,
0
)
<=
0
)
return
x
;
}
else
if
(
HASINPLACE
(
v
))
{
if
(
v
->
ob_type
->
tp_as_sequence
!=
NULL
)
f
=
v
->
ob_type
->
tp_as_sequence
->
sq_inplace_concat
;
if
(
f
==
NULL
&&
v
->
ob_type
->
tp_as_number
!=
NULL
)
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_add
;
if
(
f
!=
NULL
)
return
(
*
f
)(
v
,
w
);
}
BINOP
(
v
,
w
,
"__add__"
,
"__radd__"
,
PyNumber_Add
);
binaryfunc
f
=
NULL
;
if
(
v
->
ob_type
->
tp_as_sequence
!=
NULL
)
{
f
=
v
->
ob_type
->
tp_as_sequence
->
sq_concat
;
if
(
HASINPLACE
(
v
))
f
=
v
->
ob_type
->
tp_as_sequence
->
sq_inplace_concat
;
if
(
f
==
NULL
)
f
=
v
->
ob_type
->
tp_as_sequence
->
sq_concat
;
if
(
f
!=
NULL
)
return
(
*
f
)(
v
,
w
);
}
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
f
=
v
->
ob_type
->
tp_as_number
->
nb_add
;
if
(
f
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
}
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for +="
);
}
PyObject
*
PyNumber_InPlaceSubtract
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__isub__"
,
&
x
,
PyNumber_Subtract
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_subtract
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
BINOP
(
v
,
w
,
"__sub__"
,
"__rsub__"
,
PyNumber_Subtract
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_subtract
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for -="
);
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_add
),
NB_SLOT
(
nb_add
),
"+="
);
}
PyObject
*
PyNumber_InPlaceMultiply
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
(
*
g
)(
PyObject
*
,
int
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__imul__"
,
&
x
,
PyNumber_Multiply
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_multiply
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
else
if
(
v
->
ob_type
->
tp_as_sequence
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
g
=
v
->
ob_type
->
tp_as_sequence
->
sq_inplace_repeat
)
!=
NULL
)
{
long
mul_value
;
if
(
HASINPLACE
(
v
)
&&
v
->
ob_type
->
tp_as_sequence
&&
(
g
=
v
->
ob_type
->
tp_as_sequence
->
sq_inplace_repeat
))
{
long
n
;
if
(
PyInt_Check
(
w
))
{
mul_value
=
PyInt_AsLong
(
w
);
n
=
PyInt_AsLong
(
w
);
}
else
if
(
PyLong_Check
(
w
))
{
mul_value
=
PyLong_AsLong
(
w
);
if
(
mul_value
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
}
else
{
return
type_error
(
"can't multiply sequence with non-int"
);
}
return
(
*
g
)(
v
,
(
int
)
mul_value
);
}
BINOP
(
v
,
w
,
"__mul__"
,
"__rmul__"
,
PyNumber_Multiply
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_multiply
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_sequence
!=
NULL
&&
(
g
=
v
->
ob_type
->
tp_as_sequence
->
sq_repeat
)
!=
NULL
)
{
long
mul_value
;
if
(
PyInt_Check
(
w
))
{
mul_value
=
PyInt_AsLong
(
w
);
}
else
if
(
PyLong_Check
(
w
))
{
mul_value
=
PyLong_AsLong
(
w
);
if
(
mul_value
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
n
=
PyLong_AsLong
(
w
);
if
(
n
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
}
else
{
return
type_error
(
"can't multiply sequence with non-int"
);
return
type_error
(
"can't multiply sequence to non-int"
);
}
return
(
*
g
)(
v
,
(
int
)
mul_value
);
return
(
*
g
)(
v
,
(
int
)
n
);
}
return
type_error
(
"bad operand type(s) for *="
);
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_multiply
),
NB_SLOT
(
nb_multiply
),
"*="
);
}
PyObject
*
PyNumber_InPlaceDivide
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__idiv__"
,
&
x
,
PyNumber_Divide
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_divide
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
BINOP
(
v
,
w
,
"__div__"
,
"__rdiv__"
,
PyNumber_Divide
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_divide
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for /="
);
}
PyObject
*
PyNumber_InPlaceRemainder
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__imod__"
,
&
x
,
PyNumber_Remainder
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_remainder
)
!=
NULL
)
return
(
*
f
)(
v
,
w
);
if
(
PyString_Check
(
v
))
return
PyString_Format
(
v
,
w
);
else
if
(
PyUnicode_Check
(
v
))
return
PyUnicode_Format
(
v
,
w
);
BINOP
(
v
,
w
,
"__mod__"
,
"__rmod__"
,
PyNumber_Remainder
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
((
f
=
v
->
ob_type
->
tp_as_number
->
nb_remainder
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for %="
);
}
/* In-place Power (binary or ternary, for API consistency) */
static
PyObject
*
do_inplace_pow
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__ipow__"
,
&
x
,
do_pow
,
0
)
<=
0
)
return
x
;
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_power
)
!=
NULL
)
return
(
*
f
)(
v
,
w
,
Py_None
);
BINOP
(
v
,
w
,
"__pow__"
,
"__rpow__"
,
do_pow
);
if
(
v
->
ob_type
->
tp_as_number
==
NULL
||
w
->
ob_type
->
tp_as_number
==
NULL
)
{
return
type_error
(
"bad operand type(s) for **="
);
}
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
if
((
f
=
v
->
ob_type
->
tp_as_number
->
nb_power
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
,
Py_None
);
else
x
=
type_error
(
"bad operand type(s) for **="
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
x
;
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_remainder
),
NB_SLOT
(
nb_remainder
),
"%="
);
}
PyObject
*
PyNumber_InPlacePower
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
{
PyObject
*
res
;
PyObject
*
v1
,
*
z1
,
*
w2
,
*
z2
,
*
oldv
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
,
PyObject
*
);
if
(
z
==
Py_None
)
return
do_inplace_pow
(
v
,
w
);
/* XXX The ternary version doesn't do class instance coercions */
if
(
PyInstance_Check
(
v
))
return
v
->
ob_type
->
tp_as_number
->
nb_inplace_power
(
v
,
w
,
z
);
if
(
v
->
ob_type
->
tp_as_number
==
NULL
||
z
->
ob_type
->
tp_as_number
==
NULL
||
w
->
ob_type
->
tp_as_number
==
NULL
)
{
return
type_error
(
"(inplace) pow(x, y, z) requires numeric arguments"
);
}
oldv
=
v
;
Py_INCREF
(
oldv
);
res
=
NULL
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
goto
error3
;
v1
=
v
;
z1
=
z
;
if
(
PyNumber_Coerce
(
&
v1
,
&
z1
)
!=
0
)
goto
error2
;
w2
=
w
;
z2
=
z1
;
if
(
PyNumber_Coerce
(
&
w2
,
&
z2
)
!=
0
)
goto
error1
;
if
(
oldv
==
v1
&&
HASINPLACE
(
v1
)
&&
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v1
->
ob_type
->
tp_as_number
->
nb_inplace_power
)
!=
NULL
)
res
=
(
*
f
)(
v1
,
w2
,
z2
);
else
if
(
v1
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v1
->
ob_type
->
tp_as_number
->
nb_power
)
!=
NULL
)
res
=
(
*
f
)(
v1
,
w2
,
z2
);
else
res
=
type_error
(
"(inplace) pow(x, y, z) not defined for these operands"
);
Py_DECREF
(
w2
);
Py_DECREF
(
z2
);
error1:
Py_DECREF
(
v1
);
Py_DECREF
(
z1
);
error2:
Py_DECREF
(
v
);
Py_DECREF
(
w
);
error3:
Py_DECREF
(
oldv
);
return
res
;
if
(
HASINPLACE
(
v
)
&&
v
->
ob_type
->
tp_as_number
&&
v
->
ob_type
->
tp_as_number
->
nb_inplace_power
!=
NULL
)
{
return
ternary_op
(
v
,
w
,
z
,
NB_SLOT
(
nb_inplace_power
),
"**="
);
}
else
{
return
ternary_op
(
v
,
w
,
z
,
NB_SLOT
(
nb_power
),
"**="
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment