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
Show 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) */
/* Abstract Object Interface (many thanks to Jim Fulton) */
#include "Python.h"
#include "Python.h"
#include <ctype.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 */
/* Shorthands to return certain errors */
...
@@ -281,328 +286,230 @@ PyNumber_Check(PyObject *o)
...
@@ -281,328 +286,230 @@ PyNumber_Check(PyObject *o)
/* Binary operators */
/* Binary operators */
#define BINOP(v, w, opname, ropname, thisfunc) \
/* New style number protocol support */
if (PyInstance_Check(v) || PyInstance_Check(w)) \
return PyInstance_DoBinOp(v, w, opname, ropname, thisfunc)
PyObject
*
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
PyNumber_Or
(
PyObject
*
v
,
PyObject
*
w
)
#define NB_BINOP(nb_methods, slot) \
((binaryfunc*)(& ((char*)nb_methods)[slot] ))
#define NB_TERNOP(nb_methods, slot) \
((ternaryfunc*)(& ((char*)nb_methods)[slot] ))
/*
Calling scheme used for binary operations:
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)
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
,
"__or__"
,
"__ror__"
,
PyNumber_Or
);
PyObject
*
x
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
binaryfunc
*
slot
;
PyObject
*
x
=
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
slot
=
NB_BINOP
(
v
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
if
(
*
slot
)
{
return
NULL
;
x
=
(
*
slot
)(
v
,
w
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
if
(
x
!=
Py_NotImplemented
)
{
(
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
x
;
}
}
return
type_error
(
"bad operand type(s) for |"
);
Py_DECREF
(
x
);
/* can't do it */
}
}
if
(
v
->
ob_type
==
w
->
ob_type
)
{
PyObject
*
goto
binop_error
;
PyNumber_Xor
(
PyObject
*
v
,
PyObject
*
w
)
}
{
}
BINOP
(
v
,
w
,
"__xor__"
,
"__rxor__"
,
PyNumber_Xor
);
if
(
w
->
ob_type
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
slot
=
NB_BINOP
(
w
->
ob_type
->
tp_as_number
,
op_slot
);
PyObject
*
x
=
NULL
;
if
(
*
slot
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
x
=
(
*
slot
)(
v
,
w
);
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
if
(
x
!=
Py_NotImplemented
)
{
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
x
;
}
}
return
type_error
(
"bad operand type(s) for ^"
);
Py_DECREF
(
x
);
/* can't do it */
}
}
}
PyObject
*
if
(
!
NEW_STYLE_NUMBER
(
v
)
||
!
NEW_STYLE_NUMBER
(
w
))
{
PyNumber_And
(
PyObject
*
v
,
PyObject
*
w
)
int
err
=
PyNumber_CoerceEx
(
&
v
,
&
w
);
{
if
(
err
<
0
)
{
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
;
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
}
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_and
)
!=
NULL
)
if
(
err
==
0
)
{
x
=
(
*
f
)(
v
,
w
);
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
(
v
);
Py_DECREF
(
w
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
return
x
;
}
}
return
type_error
(
"bad operand type(s) for &"
);
}
}
/* CoerceEx incremented the reference counts */
PyObject
*
PyNumber_Lshift
(
PyObject
*
v
,
PyObject
*
w
)
{
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
)
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
(
v
);
Py_DECREF
(
w
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
}
return
type_error
(
"bad operand type(s) for <<"
);
}
binop_error:
Py_INCREF
(
Py_NotImplemented
);
return
Py_NotImplemented
;
}
}
PyObject
*
static
PyObject
*
PyNumber_Rshift
(
PyObject
*
v
,
PyObject
*
w
)
binary_op
(
PyObject
*
v
,
PyObject
*
w
,
const
int
op_slot
,
const
char
*
op_name
)
{
{
BINOP
(
v
,
w
,
"__rshift__"
,
"__rrshift__"
,
PyNumber_Rshif
t
);
PyObject
*
result
=
binary_op1
(
v
,
w
,
op_slo
t
);
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
if
(
result
==
Py_NotImplemented
)
{
Py
Object
*
x
=
NULL
;
Py
_DECREF
(
Py_NotImplemented
)
;
Py
Object
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
Py
Err_Format
(
PyExc_TypeError
,
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
"unsupported operand type(s) for %s"
,
op_name
);
return
NULL
;
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
;
}
}
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
;
Calling scheme used for ternary operations:
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 +"
);
}
PyObject
*
v w z Action
PyNumber_Subtract
(
PyObject
*
v
,
PyObject
*
w
)
-------------------------------------------------------------------
{
new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
BINOP
(
v
,
w
,
"__sub__"
,
"__rsub__"
,
PyNumber_Subtract
);
new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
PyObject
*
x
=
NULL
;
old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
return
NULL
;
old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
old old old coerce(v,w,z), v.op(v,w,z)
(
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 -"
);
}
PyObject
*
Legend:
PyNumber_Multiply
(
PyObject
*
v
,
PyObject
*
w
)
-------
{
* new == new style number
PyTypeObject
*
tp
=
v
->
ob_type
;
* old == old style number
PySequenceMethods
*
m
;
* 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
)
{
static
PyObject
*
/* number*sequence -- swap v and w */
ternary_op
(
PyObject
*
v
,
PyObject
*
tmp
=
v
;
PyObject
*
w
,
v
=
w
;
PyObject
*
z
,
w
=
tmp
;
const
int
op_slot
,
tp
=
v
->
ob_type
;
const
char
*
op_name
)
}
{
if
(
tp
->
tp_as_number
!=
NULL
)
{
PyNumberMethods
*
mv
,
*
mw
,
*
mz
;
PyObject
*
x
=
NULL
;
register
PyObject
*
x
=
NULL
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
register
ternaryfunc
*
slot
;
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
mv
=
v
->
ob_type
->
tp_as_number
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
if
(
mv
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
{
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_multiply
)
!=
NULL
)
/* try v.op(v,w,z) */
x
=
(
*
f
)(
v
,
w
);
slot
=
NB_TERNOP
(
mv
,
op_slot
);
Py_DECREF
(
v
);
if
(
*
slot
)
{
Py_DECREF
(
w
);
x
=
(
*
slot
)(
v
,
w
,
z
);
if
(
f
!=
NULL
)
if
(
x
!=
Py_NotImplemented
)
return
x
;
return
x
;
/* Can't do it... fall through */
Py_DECREF
(
x
);
}
}
m
=
tp
->
tp_as_sequence
;
if
(
v
->
ob_type
==
w
->
ob_type
&&
if
(
m
&&
m
->
sq_repeat
)
{
(
z
==
Py_None
||
z
->
ob_type
==
v
->
ob_type
))
{
long
mul_value
;
goto
ternary_error
;
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
;
}
}
else
{
mw
=
w
->
ob_type
->
tp_as_number
;
return
type_error
(
if
(
mw
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
"can't multiply sequence with non-int"
);
/* 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
);
}
}
return
(
*
m
->
sq_repeat
)(
v
,
(
int
)
mul_value
);
if
(
NEW_STYLE_NUMBER
(
v
)
&&
(
z
==
Py_None
||
z
->
ob_type
==
v
->
ob_type
))
{
goto
ternary_error
;
}
}
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
;
}
}
return
type_error
(
"bad operand type(s) for /"
);
mz
=
z
->
ob_type
->
tp_as_number
;
}
if
(
mz
!=
NULL
&&
NEW_STYLE_NUMBER
(
z
))
{
/* try: z.op(v,w,z) */
PyObject
*
slot
=
NB_TERNOP
(
mz
,
op_slot
);
PyNumber_Remainder
(
PyObject
*
v
,
PyObject
*
w
)
if
(
*
slot
)
{
{
x
=
(
*
slot
)(
v
,
w
,
z
);
if
(
PyString_Check
(
v
))
if
(
x
!=
Py_NotImplemented
)
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
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
return
x
;
/* Can't do it... fall through */
Py_DECREF
(
x
);
}
}
return
type_error
(
"bad operand type(s) for %"
);
}
PyObject
*
PyNumber_Divmod
(
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
;
}
}
return
type_error
(
"bad operand type(s) for divmod()"
);
}
/* Power (binary or ternary) */
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
;
static
PyObject
*
c
=
PyNumber_Coerce
(
&
v
,
&
w
);
do_pow
(
PyObject
*
v
,
PyObject
*
w
)
if
(
c
!=
0
)
{
goto
error3
;
PyObject
*
res
;
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
,
PyObject
*
);
/* Special case: if the third argument is None, it is
BINOP
(
v
,
w
,
"__pow__"
,
"__rpow__"
,
do_pow
);
treated as absent argument and not coerced. */
if
(
v
->
ob_type
->
tp_as_number
==
NULL
||
if
(
z
==
Py_None
)
{
w
->
ob_type
->
tp_as_number
==
NULL
)
{
if
(
v
->
ob_type
->
tp_as_number
)
{
PyErr_SetString
(
PyExc_TypeError
,
slot
=
NB_TERNOP
(
v
->
ob_type
->
tp_as_number
,
"pow(x, y) requires numeric arguments"
);
op_slot
);
return
NULL
;
if
(
*
slot
)
x
=
(
*
slot
)(
v
,
w
,
z
);
else
c
=
-
1
;
}
}
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
else
res
=
type_error
(
"pow(x, y) not defined for these operands"
);
c
=
-
1
;
Py_DECREF
(
v
);
goto
error2
;
Py_DECREF
(
w
);
}
return
res
;
}
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
;
v1
=
v
;
z1
=
z
;
z1
=
z
;
if
(
PyNumber_Coerce
(
&
v1
,
&
z1
)
!=
0
)
c
=
PyNumber_Coerce
(
&
v1
,
&
z1
);
if
(
c
!=
0
)
goto
error2
;
goto
error2
;
w2
=
w
;
w2
=
w
;
z2
=
z1
;
z2
=
z1
;
if
(
PyNumber_Coerce
(
&
w2
,
&
z2
)
!=
0
)
c
=
PyNumber_Coerce
(
&
w2
,
&
z2
);
if
(
c
!=
0
)
goto
error1
;
goto
error1
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
(
f
=
v1
->
ob_type
->
tp_as_number
->
nb_power
)
!=
NULL
)
if
(
v1
->
ob_type
->
tp_as_number
!=
NULL
)
{
res
=
(
*
f
)(
v1
,
w2
,
z2
);
slot
=
NB_TERNOP
(
v1
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
*
slot
)
x
=
(
*
slot
)(
v1
,
w2
,
z2
);
else
else
res
=
type_error
(
c
=
-
1
;
"pow(x, y, z) not defined for these operands"
);
}
else
c
=
-
1
;
Py_DECREF
(
w2
);
Py_DECREF
(
w2
);
Py_DECREF
(
z2
);
Py_DECREF
(
z2
);
error1:
error1:
...
@@ -611,500 +518,183 @@ PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
...
@@ -611,500 +518,183 @@ PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
error2:
error2:
Py_DECREF
(
v
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
Py_DECREF
(
w
);
return
res
;
error3:
}
if
(
c
>=
0
)
/* 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:
- If either object is an instance, let PyInstance_DoBinOp() handle it.
- 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.
*/
#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
;
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
);
ternary_error:
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for %s"
,
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
op_name
);
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
return
NULL
;
return
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
}
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_or
)
!=
NULL
)
x
=
(
*
f
)(
v
,
w
);
#define BINARY_FUNC(func, op, op_name) \
Py_DECREF
(
v
);
PyObject * \
Py_DECREF
(
w
);
func(PyObject *v, PyObject *w) { \
if
(
f
!=
NULL
)
return binary_op(v, w, NB_SLOT(op), op_name); \
return
x
;
}
}
return
type_error
(
"bad operand type(s) for |="
);
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
*
PyObject
*
PyNumber_
InPlaceXor
(
PyObject
*
v
,
PyObject
*
w
)
PyNumber_
Add
(
PyObject
*
v
,
PyObject
*
w
)
{
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
result
=
binary_op1
(
v
,
w
,
NB_SLOT
(
nb_add
));
PyObject
*
x
=
NULL
;
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
m
=
v
->
ob_type
->
tp_as_sequence
;
if
(
PyInstance_Check
(
v
))
{
Py_DECREF
(
Py_NotImplemented
);
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__ixor__"
,
&
x
,
if
(
m
&&
m
->
sq_concat
)
{
PyNumber_Xor
,
0
)
<=
0
)
result
=
(
*
m
->
sq_concat
)(
v
,
w
);
return
x
;
}
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
else
{
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_xor
)
!=
NULL
)
PyErr_SetString
(
PyExc_TypeError
,
return
(
*
f
)(
v
,
w
);
"unsupported operand types for +"
);
result
=
NULL
;
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 ^="
)
;
return
result
;
}
}
PyObject
*
PyObject
*
PyNumber_
InPlaceAnd
(
PyObject
*
v
,
PyObject
*
w
)
PyNumber_
Remainder
(
PyObject
*
v
,
PyObject
*
w
)
{
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
if
(
PyString_Check
(
v
))
PyObject
*
x
=
NULL
;
return
PyString_Format
(
v
,
w
);
else
if
(
PyUnicode_Check
(
v
))
if
(
PyInstance_Check
(
v
))
{
return
PyUnicode_Format
(
v
,
w
);
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__iand__"
,
&
x
,
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_remainder
),
"%"
);
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
*
PyObject
*
PyNumber_
InPlaceLshift
(
PyObject
*
v
,
PyObject
*
w
)
PyNumber_
Power
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
{
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
return
ternary_op
(
v
,
w
,
z
,
NB_SLOT
(
nb_power
),
"** or pow()"
)
;
PyObject
*
x
=
NULL
;
}
if
(
PyInstance_Check
(
v
))
{
/* Binary in-place operators */
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
);
/* 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.
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
- If the left hand object has the appropriate struct members, and
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
they are filled, call the appropriate function and return the
return
NULL
;
result. No coercion is done on the arguments; the left-hand object
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
is the one the operation is performed on, and it's up to the
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_lshift
)
!=
NULL
)
function to deal with the right-hand object.
x
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
f
!=
NULL
)
return
x
;
}
return
type_error
(
"bad operand type(s) for <<="
);
- Otherwise, in-place modification is not supported. Handle it exactly as
}
a non in-place operation of the same kind.
PyObject
*
*/
PyNumber_InPlaceRshift
(
PyObject
*
v
,
PyObject
*
w
)
{
#define HASINPLACE(t) PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
PyInstance_Check
(
v
))
{
static
PyObject
*
if
(
PyInstance_HalfBinOp
(
v
,
w
,
"__irshift__"
,
&
x
,
binary_iop
(
PyObject
*
v
,
PyObject
*
w
,
const
int
iop_slot
,
const
int
op_slot
,
PyNumber_Rshift
,
0
)
<=
0
)
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
;
return
x
;
}
}
else
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
HASINPLACE
(
v
)
&&
Py_DECREF
(
x
);
(
f
=
v
->
ob_type
->
tp_as_number
->
nb_inplace_rshift
)
!=
NULL
)
}
return
(
*
f
)(
v
,
w
);
}
return
binary_op
(
v
,
w
,
op_slot
,
op_name
);
BINOP
(
v
,
w
,
"__rshift__"
,
"__rrshift__"
,
PyNumber_Rshift
);
}
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
#define INPLACE_BINOP(func, iop, op, op_name) \
if
(
PyNumber_Coerce
(
&
v
,
&
w
)
!=
0
)
PyObject * \
return
NULL
;
func(PyObject *v, PyObject *w) { \
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \
(
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
;
}
}
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
*
PyObject
*
PyNumber_InPlaceAdd
(
PyObject
*
v
,
PyObject
*
w
)
PyNumber_InPlaceAdd
(
PyObject
*
v
,
PyObject
*
w
)
{
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
binaryfunc
f
=
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
);
if
(
v
->
ob_type
->
tp_as_sequence
!=
NULL
)
{
if
(
v
->
ob_type
->
tp_as_sequence
!=
NULL
)
{
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
;
f
=
v
->
ob_type
->
tp_as_sequence
->
sq_concat
;
if
(
f
!=
NULL
)
if
(
f
!=
NULL
)
return
(
*
f
)(
v
,
w
);
return
(
*
f
)(
v
,
w
);
}
}
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
)
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_add
),
NB_SLOT
(
nb_add
),
"+="
);
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 -="
);
}
}
PyObject
*
PyObject
*
PyNumber_InPlaceMultiply
(
PyObject
*
v
,
PyObject
*
w
)
PyNumber_InPlaceMultiply
(
PyObject
*
v
,
PyObject
*
w
)
{
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
)
=
NULL
;
PyObject
*
(
*
g
)(
PyObject
*
,
int
)
=
NULL
;
PyObject
*
(
*
g
)(
PyObject
*
,
int
)
=
NULL
;
PyObject
*
x
=
NULL
;
if
(
HASINPLACE
(
v
)
&&
v
->
ob_type
->
tp_as_sequence
&&
(
g
=
v
->
ob_type
->
tp_as_sequence
->
sq_inplace_repeat
))
{
if
(
PyInstance_Check
(
v
))
{
long
n
;
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
(
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
;
}
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
))
{
if
(
PyInt_Check
(
w
))
{
mul_value
=
PyInt_AsLong
(
w
);
n
=
PyInt_AsLong
(
w
);
}
}
else
if
(
PyLong_Check
(
w
))
{
else
if
(
PyLong_Check
(
w
))
{
mul_value
=
PyLong_AsLong
(
w
);
n
=
PyLong_AsLong
(
w
);
if
(
mul_value
==
-
1
&&
PyErr_Occurred
())
if
(
n
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
return
NULL
;
}
}
else
{
else
{
return
type_error
(
return
type_error
(
"can't multiply sequence to non-int"
);
"can't multiply sequence with 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
*
PyObject
*
PyNumber_InPlaceRemainder
(
PyObject
*
v
,
PyObject
*
w
)
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
))
if
(
PyString_Check
(
v
))
return
PyString_Format
(
v
,
w
);
return
PyString_Format
(
v
,
w
);
else
if
(
PyUnicode_Check
(
v
))
else
if
(
PyUnicode_Check
(
v
))
return
PyUnicode_Format
(
v
,
w
);
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
else
x
=
type_error
(
"bad operand type(s) for **="
);
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_remainder
),
Py_DECREF
(
v
);
NB_SLOT
(
nb_remainder
),
"%="
);
Py_DECREF
(
w
);
return
x
;
}
}
PyObject
*
PyObject
*
PyNumber_InPlacePower
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
PyNumber_InPlacePower
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
{
{
PyObject
*
res
;
if
(
HASINPLACE
(
v
)
&&
v
->
ob_type
->
tp_as_number
&&
PyObject
*
v1
,
*
z1
,
*
w2
,
*
z2
,
*
oldv
;
v
->
ob_type
->
tp_as_number
->
nb_inplace_power
!=
NULL
)
{
PyObject
*
(
*
f
)(
PyObject
*
,
PyObject
*
,
PyObject
*
);
return
ternary_op
(
v
,
w
,
z
,
NB_SLOT
(
nb_inplace_power
),
"**="
);
}
if
(
z
==
Py_None
)
else
{
return
do_inplace_pow
(
v
,
w
);
return
ternary_op
(
v
,
w
,
z
,
NB_SLOT
(
nb_power
),
"**="
);
/* 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
;
}
}
...
...
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