Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
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
Boxiang Sun
Pyston
Commits
27410967
Commit
27410967
authored
Jul 27, 2016
by
Marius Wachtler
Committed by
GitHub
Jul 27, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1249 from aisk/cpython-abstract
use cpython's abstract.c instead of src/capi/abstract.cpp
parents
82c402a6
57c801a8
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
3646 additions
and
2116 deletions
+3646
-2116
from_cpython/CMakeLists.txt
from_cpython/CMakeLists.txt
+2
-0
from_cpython/Include/classobject.h
from_cpython/Include/classobject.h
+4
-1
from_cpython/Objects/abstract.c
from_cpython/Objects/abstract.c
+3168
-0
from_cpython/Objects/sliceobject.c
from_cpython/Objects/sliceobject.c
+371
-0
src/CMakeLists.txt
src/CMakeLists.txt
+1
-1
src/capi/abstract.cpp
src/capi/abstract.cpp
+62
-2114
src/runtime/capi.cpp
src/runtime/capi.cpp
+32
-0
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+6
-0
No files found.
from_cpython/CMakeLists.txt
View file @
27410967
...
@@ -81,6 +81,7 @@ file(GLOB_RECURSE STDMODULE_SRCS Modules
...
@@ -81,6 +81,7 @@ file(GLOB_RECURSE STDMODULE_SRCS Modules
# compile specified files in from_cpython/Objects
# compile specified files in from_cpython/Objects
file
(
GLOB_RECURSE STDOBJECT_SRCS Objects
file
(
GLOB_RECURSE STDOBJECT_SRCS Objects
abstract.c
bufferobject.c
bufferobject.c
bytearrayobject.c
bytearrayobject.c
bytes_methods.c
bytes_methods.c
...
@@ -97,6 +98,7 @@ file(GLOB_RECURSE STDOBJECT_SRCS Objects
...
@@ -97,6 +98,7 @@ file(GLOB_RECURSE STDOBJECT_SRCS Objects
iterobject.c
iterobject.c
memoryobject.c
memoryobject.c
obmalloc.c
obmalloc.c
sliceobject.c
stringobject.c
stringobject.c
structseq.c
structseq.c
traceback.c
traceback.c
...
...
from_cpython/Include/classobject.h
View file @
27410967
...
@@ -64,9 +64,13 @@ PyAPI_FUNC(BORROWED(PyObject *)) PyClass_Name(PyObject *) PYSTON_NOEXCEPT;
...
@@ -64,9 +64,13 @@ PyAPI_FUNC(BORROWED(PyObject *)) PyClass_Name(PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC
(
PyObject
*
)
PyInstance_New
(
PyObject
*
,
PyObject
*
,
PyAPI_FUNC
(
PyObject
*
)
PyInstance_New
(
PyObject
*
,
PyObject
*
,
PyObject
*
)
PYSTON_NOEXCEPT
;
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyInstance_NewRaw
(
PyObject
*
,
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyInstance_NewRaw
(
PyObject
*
,
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_New
(
PyObject
*
,
PyObject
*
,
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_New
(
PyObject
*
,
PyObject
*
,
PyObject
*
)
PYSTON_NOEXCEPT
;
// Pyston change: pyston addition returns PyInstanceObject->in_class
PyAPI_FUNC
(
BORROWED
(
PyObject
*
))
PyInstance_Class
(
PyObject
*
_inst
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_Function
(
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_Function
(
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_Self
(
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_Self
(
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_Class
(
PyObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
PyMethod_Class
(
PyObject
*
)
PYSTON_NOEXCEPT
;
...
@@ -107,4 +111,3 @@ PyAPI_FUNC(int) PyMethod_ClearFreeList(void) PYSTON_NOEXCEPT;
...
@@ -107,4 +111,3 @@ PyAPI_FUNC(int) PyMethod_ClearFreeList(void) PYSTON_NOEXCEPT;
}
}
#endif
#endif
#endif
/* !Py_CLASSOBJECT_H */
#endif
/* !Py_CLASSOBJECT_H */
from_cpython/Objects/abstract.c
0 → 100644
View file @
27410967
// This file is originally from CPython 2.7, with modifications for Pyston
/* Abstract Object Interface (many thanks to Jim Fulton) */
#include "Python.h"
#include <ctype.h>
#include "structmember.h"
/* we need the offsetof() macro from there */
// pyston change: comment this out
#if 0
#include "longintrepr.h"
#endif
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
Py_TPFLAGS_CHECKTYPES)
/* Shorthands to return certain errors */
static
PyObject
*
type_error
(
const
char
*
msg
,
PyObject
*
obj
)
{
PyErr_Format
(
PyExc_TypeError
,
msg
,
obj
->
ob_type
->
tp_name
);
return
NULL
;
}
// pyston change: removed the static keyword, this function is also used in src/capi/abstract.cpp
PyObject
*
null_error
(
void
)
{
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_SystemError
,
"null argument to internal routine"
);
return
NULL
;
}
/* Operations on any object */
int
PyObject_Cmp
(
PyObject
*
o1
,
PyObject
*
o2
,
int
*
result
)
{
int
r
;
if
(
o1
==
NULL
||
o2
==
NULL
)
{
null_error
();
return
-
1
;
}
r
=
PyObject_Compare
(
o1
,
o2
);
if
(
PyErr_Occurred
())
return
-
1
;
*
result
=
r
;
return
0
;
}
PyObject
*
PyObject_Type
(
PyObject
*
o
)
{
PyObject
*
v
;
if
(
o
==
NULL
)
return
null_error
();
v
=
(
PyObject
*
)
o
->
ob_type
;
Py_INCREF
(
v
);
return
v
;
}
// pyston change: comment this out
#if 0
Py_ssize_t
PyObject_Size(PyObject *o)
{
PySequenceMethods *m;
if (o == NULL) {
null_error();
return -1;
}
m = o->ob_type->tp_as_sequence;
if (m && m->sq_length)
return m->sq_length(o);
return PyMapping_Size(o);
}
#endif
#undef PyObject_Length
Py_ssize_t
PyObject_Length
(
PyObject
*
o
)
{
return
PyObject_Size
(
o
);
}
#define PyObject_Length PyObject_Size
/* The length hint function returns a non-negative value from o.__len__()
or o.__length_hint__(). If those methods aren't found or return a negative
value, then the defaultvalue is returned. If one of the calls fails,
this function returns -1.
*/
Py_ssize_t
_PyObject_LengthHint
(
PyObject
*
o
,
Py_ssize_t
defaultvalue
)
{
static
PyObject
*
hintstrobj
=
NULL
;
PyObject
*
ro
,
*
hintmeth
;
Py_ssize_t
rv
;
/* try o.__len__() */
rv
=
PyObject_Size
(
o
);
if
(
rv
>=
0
)
return
rv
;
if
(
PyErr_Occurred
())
{
if
(
!
PyErr_ExceptionMatches
(
PyExc_TypeError
)
&&
!
PyErr_ExceptionMatches
(
PyExc_AttributeError
))
return
-
1
;
PyErr_Clear
();
}
if
(
PyInstance_Check
(
o
))
return
defaultvalue
;
/* try o.__length_hint__() */
hintmeth
=
_PyObject_LookupSpecial
(
o
,
"__length_hint__"
,
&
hintstrobj
);
if
(
hintmeth
==
NULL
)
{
if
(
PyErr_Occurred
())
return
-
1
;
else
return
defaultvalue
;
}
ro
=
PyObject_CallFunctionObjArgs
(
hintmeth
,
NULL
);
Py_DECREF
(
hintmeth
);
if
(
ro
==
NULL
)
{
if
(
!
PyErr_ExceptionMatches
(
PyExc_TypeError
)
&&
!
PyErr_ExceptionMatches
(
PyExc_AttributeError
))
return
-
1
;
PyErr_Clear
();
return
defaultvalue
;
}
rv
=
PyNumber_Check
(
ro
)
?
PyInt_AsSsize_t
(
ro
)
:
defaultvalue
;
Py_DECREF
(
ro
);
return
rv
;
}
// pyston change: comment this out
#if 0
PyObject *
PyObject_GetItem(PyObject *o, PyObject *key)
{
PyMappingMethods *m;
if (o == NULL || key == NULL)
return null_error();
m = o->ob_type->tp_as_mapping;
if (m && m->mp_subscript)
return m->mp_subscript(o, key);
if (o->ob_type->tp_as_sequence) {
if (PyIndex_Check(key)) {
Py_ssize_t key_value;
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (key_value == -1 && PyErr_Occurred())
return NULL;
return PySequence_GetItem(o, key_value);
}
else if (o->ob_type->tp_as_sequence->sq_item)
return type_error("sequence index must "
"be integer, not '%.200s'", key);
}
return type_error("'%.200s' object has no attribute '__getitem__'", o);
}
int
PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
{
PyMappingMethods *m;
if (o == NULL || key == NULL || value == NULL) {
null_error();
return -1;
}
m = o->ob_type->tp_as_mapping;
if (m && m->mp_ass_subscript)
return m->mp_ass_subscript(o, key, value);
if (o->ob_type->tp_as_sequence) {
if (PyIndex_Check(key)) {
Py_ssize_t key_value;
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (key_value == -1 && PyErr_Occurred())
return -1;
return PySequence_SetItem(o, key_value, value);
}
else if (o->ob_type->tp_as_sequence->sq_ass_item) {
type_error("sequence index must be "
"integer, not '%.200s'", key);
return -1;
}
}
type_error("'%.200s' object does not support item assignment", o);
return -1;
}
int
PyObject_DelItem(PyObject *o, PyObject *key)
{
PyMappingMethods *m;
if (o == NULL || key == NULL) {
null_error();
return -1;
}
m = o->ob_type->tp_as_mapping;
if (m && m->mp_ass_subscript)
return m->mp_ass_subscript(o, key, (PyObject*)NULL);
if (o->ob_type->tp_as_sequence) {
if (PyIndex_Check(key)) {
Py_ssize_t key_value;
key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
if (key_value == -1 && PyErr_Occurred())
return -1;
return PySequence_DelItem(o, key_value);
}
else if (o->ob_type->tp_as_sequence->sq_ass_item) {
type_error("sequence index must be "
"integer, not '%.200s'", key);
return -1;
}
}
type_error("'%.200s' object does not support item deletion", o);
return -1;
}
#endif
int
PyObject_DelItemString
(
PyObject
*
o
,
char
*
key
)
{
PyObject
*
okey
;
int
ret
;
if
(
o
==
NULL
||
key
==
NULL
)
{
null_error
();
return
-
1
;
}
okey
=
PyString_FromString
(
key
);
if
(
okey
==
NULL
)
return
-
1
;
ret
=
PyObject_DelItem
(
o
,
okey
);
Py_DECREF
(
okey
);
return
ret
;
}
int
PyObject_AsCharBuffer
(
PyObject
*
obj
,
const
char
**
buffer
,
Py_ssize_t
*
buffer_len
)
{
PyBufferProcs
*
pb
;
char
*
pp
;
Py_ssize_t
len
;
if
(
obj
==
NULL
||
buffer
==
NULL
||
buffer_len
==
NULL
)
{
null_error
();
return
-
1
;
}
pb
=
obj
->
ob_type
->
tp_as_buffer
;
if
(
pb
==
NULL
||
pb
->
bf_getcharbuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a character buffer object"
);
return
-
1
;
}
if
((
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a single-segment buffer object"
);
return
-
1
;
}
len
=
(
*
pb
->
bf_getcharbuffer
)(
obj
,
0
,
&
pp
);
if
(
len
<
0
)
return
-
1
;
*
buffer
=
pp
;
*
buffer_len
=
len
;
return
0
;
}
int
PyObject_CheckReadBuffer
(
PyObject
*
obj
)
{
PyBufferProcs
*
pb
=
obj
->
ob_type
->
tp_as_buffer
;
if
(
pb
==
NULL
||
pb
->
bf_getreadbuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
||
(
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
return
0
;
return
1
;
}
int
PyObject_AsReadBuffer
(
PyObject
*
obj
,
const
void
**
buffer
,
Py_ssize_t
*
buffer_len
)
{
PyBufferProcs
*
pb
;
void
*
pp
;
Py_ssize_t
len
;
if
(
obj
==
NULL
||
buffer
==
NULL
||
buffer_len
==
NULL
)
{
null_error
();
return
-
1
;
}
pb
=
obj
->
ob_type
->
tp_as_buffer
;
if
(
pb
==
NULL
||
pb
->
bf_getreadbuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a readable buffer object"
);
return
-
1
;
}
if
((
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a single-segment buffer object"
);
return
-
1
;
}
len
=
(
*
pb
->
bf_getreadbuffer
)(
obj
,
0
,
&
pp
);
if
(
len
<
0
)
return
-
1
;
*
buffer
=
pp
;
*
buffer_len
=
len
;
return
0
;
}
int
PyObject_AsWriteBuffer
(
PyObject
*
obj
,
void
**
buffer
,
Py_ssize_t
*
buffer_len
)
{
PyBufferProcs
*
pb
;
void
*
pp
;
Py_ssize_t
len
;
if
(
obj
==
NULL
||
buffer
==
NULL
||
buffer_len
==
NULL
)
{
null_error
();
return
-
1
;
}
pb
=
obj
->
ob_type
->
tp_as_buffer
;
if
(
pb
==
NULL
||
pb
->
bf_getwritebuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a writeable buffer object"
);
return
-
1
;
}
if
((
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a single-segment buffer object"
);
return
-
1
;
}
len
=
(
*
pb
->
bf_getwritebuffer
)(
obj
,
0
,
&
pp
);
if
(
len
<
0
)
return
-
1
;
*
buffer
=
pp
;
*
buffer_len
=
len
;
return
0
;
}
/* Buffer C-API for Python 3.0 */
// pyston change: comment this out
#if 0
int
PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
{
if (!PyObject_CheckBuffer(obj)) {
PyErr_Format(PyExc_TypeError,
"'%100s' does not have the buffer interface",
Py_TYPE(obj)->tp_name);
return -1;
}
return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
}
#endif
static
int
_IsFortranContiguous
(
Py_buffer
*
view
)
{
Py_ssize_t
sd
,
dim
;
int
i
;
if
(
view
->
ndim
==
0
)
return
1
;
if
(
view
->
strides
==
NULL
)
return
(
view
->
ndim
==
1
);
sd
=
view
->
itemsize
;
if
(
view
->
ndim
==
1
)
return
(
view
->
shape
[
0
]
==
1
||
sd
==
view
->
strides
[
0
]);
for
(
i
=
0
;
i
<
view
->
ndim
;
i
++
)
{
dim
=
view
->
shape
[
i
];
if
(
dim
==
0
)
return
1
;
if
(
view
->
strides
[
i
]
!=
sd
)
return
0
;
sd
*=
dim
;
}
return
1
;
}
static
int
_IsCContiguous
(
Py_buffer
*
view
)
{
Py_ssize_t
sd
,
dim
;
int
i
;
if
(
view
->
ndim
==
0
)
return
1
;
if
(
view
->
strides
==
NULL
)
return
1
;
sd
=
view
->
itemsize
;
if
(
view
->
ndim
==
1
)
return
(
view
->
shape
[
0
]
==
1
||
sd
==
view
->
strides
[
0
]);
for
(
i
=
view
->
ndim
-
1
;
i
>=
0
;
i
--
)
{
dim
=
view
->
shape
[
i
];
if
(
dim
==
0
)
return
1
;
if
(
view
->
strides
[
i
]
!=
sd
)
return
0
;
sd
*=
dim
;
}
return
1
;
}
int
PyBuffer_IsContiguous
(
Py_buffer
*
view
,
char
fort
)
{
if
(
view
->
suboffsets
!=
NULL
)
return
0
;
if
(
fort
==
'C'
)
return
_IsCContiguous
(
view
);
else
if
(
fort
==
'F'
)
return
_IsFortranContiguous
(
view
);
else
if
(
fort
==
'A'
)
return
(
_IsCContiguous
(
view
)
||
_IsFortranContiguous
(
view
));
return
0
;
}
void
*
PyBuffer_GetPointer
(
Py_buffer
*
view
,
Py_ssize_t
*
indices
)
{
char
*
pointer
;
int
i
;
pointer
=
(
char
*
)
view
->
buf
;
for
(
i
=
0
;
i
<
view
->
ndim
;
i
++
)
{
pointer
+=
view
->
strides
[
i
]
*
indices
[
i
];
if
((
view
->
suboffsets
!=
NULL
)
&&
(
view
->
suboffsets
[
i
]
>=
0
))
{
pointer
=
*
((
char
**
)
pointer
)
+
view
->
suboffsets
[
i
];
}
}
return
(
void
*
)
pointer
;
}
void
_Py_add_one_to_index_F
(
int
nd
,
Py_ssize_t
*
index
,
const
Py_ssize_t
*
shape
)
{
int
k
;
for
(
k
=
0
;
k
<
nd
;
k
++
)
{
if
(
index
[
k
]
<
shape
[
k
]
-
1
)
{
index
[
k
]
++
;
break
;
}
else
{
index
[
k
]
=
0
;
}
}
}
void
_Py_add_one_to_index_C
(
int
nd
,
Py_ssize_t
*
index
,
const
Py_ssize_t
*
shape
)
{
int
k
;
for
(
k
=
nd
-
1
;
k
>=
0
;
k
--
)
{
if
(
index
[
k
]
<
shape
[
k
]
-
1
)
{
index
[
k
]
++
;
break
;
}
else
{
index
[
k
]
=
0
;
}
}
}
/* view is not checked for consistency in either of these. It is
assumed that the size of the buffer is view->len in
view->len / view->itemsize elements.
*/
int
PyBuffer_ToContiguous
(
void
*
buf
,
Py_buffer
*
view
,
Py_ssize_t
len
,
char
fort
)
{
int
k
;
void
(
*
addone
)(
int
,
Py_ssize_t
*
,
const
Py_ssize_t
*
);
Py_ssize_t
*
indices
,
elements
;
char
*
dest
,
*
ptr
;
if
(
len
>
view
->
len
)
{
len
=
view
->
len
;
}
if
(
PyBuffer_IsContiguous
(
view
,
fort
))
{
/* simplest copy is all that is needed */
memcpy
(
buf
,
view
->
buf
,
len
);
return
0
;
}
/* Otherwise a more elaborate scheme is needed */
/* XXX(nnorwitz): need to check for overflow! */
indices
=
(
Py_ssize_t
*
)
PyMem_Malloc
(
sizeof
(
Py_ssize_t
)
*
(
view
->
ndim
));
if
(
indices
==
NULL
)
{
PyErr_NoMemory
();
return
-
1
;
}
for
(
k
=
0
;
k
<
view
->
ndim
;
k
++
)
{
indices
[
k
]
=
0
;
}
if
(
fort
==
'F'
)
{
addone
=
_Py_add_one_to_index_F
;
}
else
{
addone
=
_Py_add_one_to_index_C
;
}
dest
=
buf
;
/* XXX : This is not going to be the fastest code in the world
several optimizations are possible.
*/
elements
=
len
/
view
->
itemsize
;
while
(
elements
--
)
{
addone
(
view
->
ndim
,
indices
,
view
->
shape
);
ptr
=
PyBuffer_GetPointer
(
view
,
indices
);
memcpy
(
dest
,
ptr
,
view
->
itemsize
);
dest
+=
view
->
itemsize
;
}
PyMem_Free
(
indices
);
return
0
;
}
int
PyBuffer_FromContiguous
(
Py_buffer
*
view
,
void
*
buf
,
Py_ssize_t
len
,
char
fort
)
{
int
k
;
void
(
*
addone
)(
int
,
Py_ssize_t
*
,
const
Py_ssize_t
*
);
Py_ssize_t
*
indices
,
elements
;
char
*
src
,
*
ptr
;
if
(
len
>
view
->
len
)
{
len
=
view
->
len
;
}
if
(
PyBuffer_IsContiguous
(
view
,
fort
))
{
/* simplest copy is all that is needed */
memcpy
(
view
->
buf
,
buf
,
len
);
return
0
;
}
/* Otherwise a more elaborate scheme is needed */
/* XXX(nnorwitz): need to check for overflow! */
indices
=
(
Py_ssize_t
*
)
PyMem_Malloc
(
sizeof
(
Py_ssize_t
)
*
(
view
->
ndim
));
if
(
indices
==
NULL
)
{
PyErr_NoMemory
();
return
-
1
;
}
for
(
k
=
0
;
k
<
view
->
ndim
;
k
++
)
{
indices
[
k
]
=
0
;
}
if
(
fort
==
'F'
)
{
addone
=
_Py_add_one_to_index_F
;
}
else
{
addone
=
_Py_add_one_to_index_C
;
}
src
=
buf
;
/* XXX : This is not going to be the fastest code in the world
several optimizations are possible.
*/
elements
=
len
/
view
->
itemsize
;
while
(
elements
--
)
{
addone
(
view
->
ndim
,
indices
,
view
->
shape
);
ptr
=
PyBuffer_GetPointer
(
view
,
indices
);
memcpy
(
ptr
,
src
,
view
->
itemsize
);
src
+=
view
->
itemsize
;
}
PyMem_Free
(
indices
);
return
0
;
}
int
PyObject_CopyData
(
PyObject
*
dest
,
PyObject
*
src
)
{
Py_buffer
view_dest
,
view_src
;
int
k
;
Py_ssize_t
*
indices
,
elements
;
char
*
dptr
,
*
sptr
;
if
(
!
PyObject_CheckBuffer
(
dest
)
||
!
PyObject_CheckBuffer
(
src
))
{
PyErr_SetString
(
PyExc_TypeError
,
"both destination and source must have the "
\
"buffer interface"
);
return
-
1
;
}
if
(
PyObject_GetBuffer
(
dest
,
&
view_dest
,
PyBUF_FULL
)
!=
0
)
return
-
1
;
if
(
PyObject_GetBuffer
(
src
,
&
view_src
,
PyBUF_FULL_RO
)
!=
0
)
{
PyBuffer_Release
(
&
view_dest
);
return
-
1
;
}
if
(
view_dest
.
len
<
view_src
.
len
)
{
PyErr_SetString
(
PyExc_BufferError
,
"destination is too small to receive data from source"
);
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
-
1
;
}
if
((
PyBuffer_IsContiguous
(
&
view_dest
,
'C'
)
&&
PyBuffer_IsContiguous
(
&
view_src
,
'C'
))
||
(
PyBuffer_IsContiguous
(
&
view_dest
,
'F'
)
&&
PyBuffer_IsContiguous
(
&
view_src
,
'F'
)))
{
/* simplest copy is all that is needed */
memcpy
(
view_dest
.
buf
,
view_src
.
buf
,
view_src
.
len
);
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
0
;
}
/* Otherwise a more elaborate copy scheme is needed */
/* XXX(nnorwitz): need to check for overflow! */
indices
=
(
Py_ssize_t
*
)
PyMem_Malloc
(
sizeof
(
Py_ssize_t
)
*
view_src
.
ndim
);
if
(
indices
==
NULL
)
{
PyErr_NoMemory
();
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
-
1
;
}
for
(
k
=
0
;
k
<
view_src
.
ndim
;
k
++
)
{
indices
[
k
]
=
0
;
}
elements
=
1
;
for
(
k
=
0
;
k
<
view_src
.
ndim
;
k
++
)
{
/* XXX(nnorwitz): can this overflow? */
elements
*=
view_src
.
shape
[
k
];
}
while
(
elements
--
)
{
_Py_add_one_to_index_C
(
view_src
.
ndim
,
indices
,
view_src
.
shape
);
dptr
=
PyBuffer_GetPointer
(
&
view_dest
,
indices
);
sptr
=
PyBuffer_GetPointer
(
&
view_src
,
indices
);
memcpy
(
dptr
,
sptr
,
view_src
.
itemsize
);
}
PyMem_Free
(
indices
);
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
0
;
}
void
PyBuffer_FillContiguousStrides
(
int
nd
,
Py_ssize_t
*
shape
,
Py_ssize_t
*
strides
,
int
itemsize
,
char
fort
)
{
int
k
;
Py_ssize_t
sd
;
sd
=
itemsize
;
if
(
fort
==
'F'
)
{
for
(
k
=
0
;
k
<
nd
;
k
++
)
{
strides
[
k
]
=
sd
;
sd
*=
shape
[
k
];
}
}
else
{
for
(
k
=
nd
-
1
;
k
>=
0
;
k
--
)
{
strides
[
k
]
=
sd
;
sd
*=
shape
[
k
];
}
}
return
;
}
int
PyBuffer_FillInfo
(
Py_buffer
*
view
,
PyObject
*
obj
,
void
*
buf
,
Py_ssize_t
len
,
int
readonly
,
int
flags
)
{
if
(
view
==
NULL
)
return
0
;
if
(((
flags
&
PyBUF_WRITABLE
)
==
PyBUF_WRITABLE
)
&&
(
readonly
==
1
))
{
PyErr_SetString
(
PyExc_BufferError
,
"Object is not writable."
);
return
-
1
;
}
view
->
obj
=
obj
;
if
(
obj
)
Py_INCREF
(
obj
);
view
->
buf
=
buf
;
view
->
len
=
len
;
view
->
readonly
=
readonly
;
view
->
itemsize
=
1
;
view
->
format
=
NULL
;
if
((
flags
&
PyBUF_FORMAT
)
==
PyBUF_FORMAT
)
view
->
format
=
"B"
;
view
->
ndim
=
1
;
view
->
shape
=
NULL
;
if
((
flags
&
PyBUF_ND
)
==
PyBUF_ND
)
view
->
shape
=
&
(
view
->
len
);
view
->
strides
=
NULL
;
if
((
flags
&
PyBUF_STRIDES
)
==
PyBUF_STRIDES
)
view
->
strides
=
&
(
view
->
itemsize
);
view
->
suboffsets
=
NULL
;
view
->
internal
=
NULL
;
return
0
;
}
void
PyBuffer_Release
(
Py_buffer
*
view
)
{
PyObject
*
obj
=
view
->
obj
;
if
(
obj
&&
Py_TYPE
(
obj
)
->
tp_as_buffer
&&
Py_TYPE
(
obj
)
->
tp_as_buffer
->
bf_releasebuffer
)
Py_TYPE
(
obj
)
->
tp_as_buffer
->
bf_releasebuffer
(
obj
,
view
);
Py_XDECREF
(
obj
);
view
->
obj
=
NULL
;
}
// pyston change: comment this out
#if 0
PyObject *
PyObject_Format(PyObject* obj, PyObject *format_spec)
{
PyObject *empty = NULL;
PyObject *result = NULL;
#ifdef Py_USING_UNICODE
int spec_is_unicode;
int result_is_unicode;
#endif
/* If no format_spec is provided, use an empty string */
if (format_spec == NULL) {
empty = PyString_FromStringAndSize(NULL, 0);
format_spec = empty;
}
/* Check the format_spec type, and make sure it's str or unicode */
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(format_spec))
spec_is_unicode = 1;
else if (PyString_Check(format_spec))
spec_is_unicode = 0;
else {
#else
if (!PyString_Check(format_spec)) {
#endif
PyErr_Format
(
PyExc_TypeError
,
"format expects arg 2 to be string "
"or unicode, not %.100s"
,
Py_TYPE
(
format_spec
)
->
tp_name
);
goto
done
;
}
/* Check for a __format__ method and call it. */
if
(
PyInstance_Check
(
obj
))
{
/* We're an instance of a classic class */
PyObject
*
bound_method
=
PyObject_GetAttrString
(
obj
,
"__format__"
);
if
(
bound_method
!=
NULL
)
{
result
=
PyObject_CallFunctionObjArgs
(
bound_method
,
format_spec
,
NULL
);
Py_DECREF
(
bound_method
);
}
else
{
PyObject
*
self_as_str
=
NULL
;
PyObject
*
format_method
=
NULL
;
Py_ssize_t
format_len
;
PyErr_Clear
();
/* Per the PEP, convert to str (or unicode,
depending on the type of the format
specifier). For new-style classes, this
logic is done by object.__format__(). */
#ifdef Py_USING_UNICODE
if
(
spec_is_unicode
)
{
format_len
=
PyUnicode_GET_SIZE
(
format_spec
);
self_as_str
=
PyObject_Unicode
(
obj
);
}
else
#endif
{
format_len
=
PyString_GET_SIZE
(
format_spec
);
self_as_str
=
PyObject_Str
(
obj
);
}
if
(
self_as_str
==
NULL
)
goto
done1
;
if
(
format_len
>
0
)
{
/* See the almost identical code in
typeobject.c for new-style
classes. */
if
(
PyErr_WarnEx
(
PyExc_PendingDeprecationWarning
,
"object.__format__ with a non-empty "
"format string is deprecated"
,
1
)
<
0
)
{
goto
done1
;
}
/* Eventually this will become an
error:
PyErr_Format(PyExc_TypeError,
"non-empty format string passed to "
"object.__format__");
goto done1;
*/
}
/* Then call str.__format__ on that result */
format_method
=
PyObject_GetAttrString
(
self_as_str
,
"__format__"
);
if
(
format_method
==
NULL
)
{
goto
done1
;
}
result
=
PyObject_CallFunctionObjArgs
(
format_method
,
format_spec
,
NULL
);
done1:
Py_XDECREF
(
self_as_str
);
Py_XDECREF
(
format_method
);
if
(
result
==
NULL
)
goto
done
;
}
}
else
{
/* Not an instance of a classic class, use the code
from py3k */
static
PyObject
*
format_cache
=
NULL
;
/* Find the (unbound!) __format__ method (a borrowed
reference) */
PyObject
*
method
=
_PyObject_LookupSpecial
(
obj
,
"__format__"
,
&
format_cache
);
if
(
method
==
NULL
)
{
if
(
!
PyErr_Occurred
())
PyErr_Format
(
PyExc_TypeError
,
"Type %.100s doesn't define __format__"
,
Py_TYPE
(
obj
)
->
tp_name
);
goto
done
;
}
/* And call it. */
result
=
PyObject_CallFunctionObjArgs
(
method
,
format_spec
,
NULL
);
Py_DECREF
(
method
);
}
if
(
result
==
NULL
)
goto
done
;
/* Check the result type, and make sure it's str or unicode */
#ifdef Py_USING_UNICODE
if
(
PyUnicode_Check
(
result
))
result_is_unicode
=
1
;
else
if
(
PyString_Check
(
result
))
result_is_unicode
=
0
;
else
{
#else
if
(
!
PyString_Check
(
result
))
{
#endif
PyErr_Format
(
PyExc_TypeError
,
"%.100s.__format__ must return string or "
"unicode, not %.100s"
,
Py_TYPE
(
obj
)
->
tp_name
,
Py_TYPE
(
result
)
->
tp_name
);
Py_DECREF
(
result
);
result
=
NULL
;
goto
done
;
}
/* Convert to unicode, if needed. Required if spec is unicode
and result is str */
#ifdef Py_USING_UNICODE
if
(
spec_is_unicode
&&
!
result_is_unicode
)
{
PyObject
*
tmp
=
PyObject_Unicode
(
result
);
/* This logic works whether or not tmp is NULL */
Py_DECREF
(
result
);
result
=
tmp
;
}
#endif
done:
Py_XDECREF
(
empty
);
return
result
;
}
#endif
/* Operations on numbers */
int
PyNumber_Check
(
PyObject
*
o
)
{
return
o
&&
o
->
ob_type
->
tp_as_number
&&
(
o
->
ob_type
->
tp_as_number
->
nb_int
||
o
->
ob_type
->
tp_as_number
->
nb_float
);
}
/* Binary operators */
/* New style number protocol support */
#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]))
/*
Calling scheme used for binary operations:
v w Action
-------------------------------------------------------------------
new new w.op(v,w)[*], 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)
[*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
v->ob_type
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
)
{
PyObject
*
x
;
binaryfunc
slotv
=
NULL
;
binaryfunc
slotw
=
NULL
;
if
(
v
->
ob_type
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
slotv
=
NB_BINOP
(
v
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
w
->
ob_type
!=
v
->
ob_type
&&
w
->
ob_type
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
slotw
=
NB_BINOP
(
w
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
slotw
==
slotv
)
slotw
=
NULL
;
}
if
(
slotv
)
{
if
(
slotw
&&
PyType_IsSubtype
(
w
->
ob_type
,
v
->
ob_type
))
{
x
=
slotw
(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
slotw
=
NULL
;
}
x
=
slotv
(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
if
(
slotw
)
{
x
=
slotw
(
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
(
err
==
0
)
{
PyNumberMethods
*
mv
=
v
->
ob_type
->
tp_as_number
;
if
(
mv
)
{
binaryfunc
slot
;
slot
=
NB_BINOP
(
mv
,
op_slot
);
if
(
slot
)
{
x
=
slot
(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
x
;
}
}
/* CoerceEx incremented the reference counts */
Py_DECREF
(
v
);
Py_DECREF
(
w
);
}
}
Py_INCREF
(
Py_NotImplemented
);
return
Py_NotImplemented
;
}
static
PyObject
*
binop_type_error
(
PyObject
*
v
,
PyObject
*
w
,
const
char
*
op_name
)
{
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for %.100s: "
"'%.100s' and '%.100s'"
,
op_name
,
v
->
ob_type
->
tp_name
,
w
->
ob_type
->
tp_name
);
return
NULL
;
}
static
PyObject
*
binary_op
(
PyObject
*
v
,
PyObject
*
w
,
const
int
op_slot
,
const
char
*
op_name
)
{
PyObject
*
result
=
binary_op1
(
v
,
w
,
op_slot
);
if
(
result
==
Py_NotImplemented
)
{
Py_DECREF
(
result
);
return
binop_type_error
(
v
,
w
,
op_name
);
}
return
result
;
}
/*
Calling scheme used for ternary operations:
*** In some cases, w.op is called before v.op; see binary_op1. ***
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)
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.
*/
static
PyObject
*
ternary_op
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
,
const
int
op_slot
,
const
char
*
op_name
)
{
PyNumberMethods
*
mv
,
*
mw
,
*
mz
;
PyObject
*
x
=
NULL
;
ternaryfunc
slotv
=
NULL
;
ternaryfunc
slotw
=
NULL
;
ternaryfunc
slotz
=
NULL
;
mv
=
v
->
ob_type
->
tp_as_number
;
mw
=
w
->
ob_type
->
tp_as_number
;
if
(
mv
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
slotv
=
NB_TERNOP
(
mv
,
op_slot
);
if
(
w
->
ob_type
!=
v
->
ob_type
&&
mw
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
slotw
=
NB_TERNOP
(
mw
,
op_slot
);
if
(
slotw
==
slotv
)
slotw
=
NULL
;
}
if
(
slotv
)
{
if
(
slotw
&&
PyType_IsSubtype
(
w
->
ob_type
,
v
->
ob_type
))
{
x
=
slotw
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
slotw
=
NULL
;
}
x
=
slotv
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
if
(
slotw
)
{
x
=
slotw
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
mz
=
z
->
ob_type
->
tp_as_number
;
if
(
mz
!=
NULL
&&
NEW_STYLE_NUMBER
(
z
))
{
slotz
=
NB_TERNOP
(
mz
,
op_slot
);
if
(
slotz
==
slotv
||
slotz
==
slotw
)
slotz
=
NULL
;
if
(
slotz
)
{
x
=
slotz
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
}
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
)
{
slotz
=
NB_TERNOP
(
v
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
slotz
)
x
=
slotz
(
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
)
{
slotv
=
NB_TERNOP
(
v1
->
ob_type
->
tp_as_number
,
op_slot
);
if
(
slotv
)
x
=
slotv
(
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
);
error3:
if
(
c
>=
0
)
return
x
;
}
if
(
z
==
Py_None
)
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for ** or pow(): "
"'%.100s' and '%.100s'"
,
v
->
ob_type
->
tp_name
,
w
->
ob_type
->
tp_name
);
else
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for pow(): "
"'%.100s', '%.100s', '%.100s'"
,
v
->
ob_type
->
tp_name
,
w
->
ob_type
->
tp_name
,
z
->
ob_type
->
tp_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_Divide
,
nb_divide
,
"/"
)
BINARY_FUNC
(
PyNumber_Divmod
,
nb_divmod
,
"divmod()"
)
PyObject
*
PyNumber_Add
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
result
=
binary_op1
(
v
,
w
,
NB_SLOT
(
nb_add
));
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
m
=
v
->
ob_type
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
m
&&
m
->
sq_concat
)
{
return
(
*
m
->
sq_concat
)(
v
,
w
);
}
result
=
binop_type_error
(
v
,
w
,
"+"
);
}
return
result
;
}
static
PyObject
*
sequence_repeat
(
ssizeargfunc
repeatfunc
,
PyObject
*
seq
,
PyObject
*
n
)
{
Py_ssize_t
count
;
if
(
PyIndex_Check
(
n
))
{
count
=
PyNumber_AsSsize_t
(
n
,
PyExc_OverflowError
);
if
(
count
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
}
else
{
return
type_error
(
"can't multiply sequence by "
"non-int of type '%.200s'"
,
n
);
}
return
(
*
repeatfunc
)(
seq
,
count
);
}
PyObject
*
PyNumber_Multiply
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
result
=
binary_op1
(
v
,
w
,
NB_SLOT
(
nb_multiply
));
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
mv
=
v
->
ob_type
->
tp_as_sequence
;
PySequenceMethods
*
mw
=
w
->
ob_type
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
mv
&&
mv
->
sq_repeat
)
{
return
sequence_repeat
(
mv
->
sq_repeat
,
v
,
w
);
}
else
if
(
mw
&&
mw
->
sq_repeat
)
{
return
sequence_repeat
(
mw
->
sq_repeat
,
w
,
v
);
}
result
=
binop_type_error
(
v
,
w
,
"*"
);
}
return
result
;
}
PyObject
*
PyNumber_FloorDivide
(
PyObject
*
v
,
PyObject
*
w
)
{
/* XXX tp_flags test */
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_floor_divide
),
"//"
);
}
PyObject
*
PyNumber_TrueDivide
(
PyObject
*
v
,
PyObject
*
w
)
{
/* XXX tp_flags test */
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_true_divide
),
"/"
);
}
PyObject
*
PyNumber_Remainder
(
PyObject
*
v
,
PyObject
*
w
)
{
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_remainder
),
"%"
);
}
PyObject
*
PyNumber_Power
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
{
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.
- 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, 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)
static
PyObject
*
binary_iop1
(
PyObject
*
v
,
PyObject
*
w
,
const
int
iop_slot
,
const
int
op_slot
)
{
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
binary_op1
(
v
,
w
,
op_slot
);
}
static
PyObject
*
binary_iop
(
PyObject
*
v
,
PyObject
*
w
,
const
int
iop_slot
,
const
int
op_slot
,
const
char
*
op_name
)
{
PyObject
*
result
=
binary_iop1
(
v
,
w
,
iop_slot
,
op_slot
);
if
(
result
==
Py_NotImplemented
)
{
Py_DECREF
(
result
);
return
binop_type_error
(
v
,
w
,
op_name
);
}
return
result
;
}
#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); \
}
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_InPlaceFloorDivide
(
PyObject
*
v
,
PyObject
*
w
)
{
/* XXX tp_flags test */
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_floor_divide
),
NB_SLOT
(
nb_floor_divide
),
"//="
);
}
PyObject
*
PyNumber_InPlaceTrueDivide
(
PyObject
*
v
,
PyObject
*
w
)
{
/* XXX tp_flags test */
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_true_divide
),
NB_SLOT
(
nb_true_divide
),
"/="
);
}
PyObject
*
PyNumber_InPlaceAdd
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
result
=
binary_iop1
(
v
,
w
,
NB_SLOT
(
nb_inplace_add
),
NB_SLOT
(
nb_add
));
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
m
=
v
->
ob_type
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
m
!=
NULL
)
{
binaryfunc
f
=
NULL
;
if
(
HASINPLACE
(
v
))
f
=
m
->
sq_inplace_concat
;
if
(
f
==
NULL
)
f
=
m
->
sq_concat
;
if
(
f
!=
NULL
)
return
(
*
f
)(
v
,
w
);
}
result
=
binop_type_error
(
v
,
w
,
"+="
);
}
return
result
;
}
PyObject
*
PyNumber_InPlaceMultiply
(
PyObject
*
v
,
PyObject
*
w
)
{
PyObject
*
result
=
binary_iop1
(
v
,
w
,
NB_SLOT
(
nb_inplace_multiply
),
NB_SLOT
(
nb_multiply
));
if
(
result
==
Py_NotImplemented
)
{
ssizeargfunc
f
=
NULL
;
PySequenceMethods
*
mv
=
v
->
ob_type
->
tp_as_sequence
;
PySequenceMethods
*
mw
=
w
->
ob_type
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
mv
!=
NULL
)
{
if
(
HASINPLACE
(
v
))
f
=
mv
->
sq_inplace_repeat
;
if
(
f
==
NULL
)
f
=
mv
->
sq_repeat
;
if
(
f
!=
NULL
)
return
sequence_repeat
(
f
,
v
,
w
);
}
else
if
(
mw
!=
NULL
)
{
/* Note that the right hand operand should not be
* mutated in this case so sq_inplace_repeat is not
* used. */
if
(
mw
->
sq_repeat
)
return
sequence_repeat
(
mw
->
sq_repeat
,
w
,
v
);
}
result
=
binop_type_error
(
v
,
w
,
"*="
);
}
return
result
;
}
PyObject
*
PyNumber_InPlaceRemainder
(
PyObject
*
v
,
PyObject
*
w
)
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_remainder
),
NB_SLOT
(
nb_remainder
),
"%="
);
}
PyObject
*
PyNumber_InPlacePower
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
{
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
),
"**="
);
}
}
/* Unary operators and functions */
PyObject
*
PyNumber_Negative
(
PyObject
*
o
)
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_number
;
if
(
m
&&
m
->
nb_negative
)
return
(
*
m
->
nb_negative
)(
o
);
return
type_error
(
"bad operand type for unary -: '%.200s'"
,
o
);
}
PyObject
*
PyNumber_Positive
(
PyObject
*
o
)
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_number
;
if
(
m
&&
m
->
nb_positive
)
return
(
*
m
->
nb_positive
)(
o
);
return
type_error
(
"bad operand type for unary +: '%.200s'"
,
o
);
}
PyObject
*
PyNumber_Invert
(
PyObject
*
o
)
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_number
;
if
(
m
&&
m
->
nb_invert
)
return
(
*
m
->
nb_invert
)(
o
);
return
type_error
(
"bad operand type for unary ~: '%.200s'"
,
o
);
}
PyObject
*
PyNumber_Absolute
(
PyObject
*
o
)
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_number
;
if
(
m
&&
m
->
nb_absolute
)
return
m
->
nb_absolute
(
o
);
return
type_error
(
"bad operand type for abs(): '%.200s'"
,
o
);
}
/* Add a check for embedded NULL-bytes in the argument. */
static
PyObject
*
int_from_string
(
const
char
*
s
,
Py_ssize_t
len
)
{
char
*
end
;
PyObject
*
x
;
x
=
PyInt_FromString
((
char
*
)
s
,
&
end
,
10
);
if
(
x
==
NULL
)
return
NULL
;
if
(
end
!=
s
+
len
)
{
PyErr_SetString
(
PyExc_ValueError
,
"null byte in argument for int()"
);
Py_DECREF
(
x
);
return
NULL
;
}
return
x
;
}
/* Return a Python Int or Long from the object item
Raise TypeError if the result is not an int-or-long
or if the object cannot be interpreted as an index.
*/
PyObject
*
PyNumber_Index
(
PyObject
*
item
)
{
PyObject
*
result
=
NULL
;
if
(
item
==
NULL
)
return
null_error
();
if
(
PyInt_Check
(
item
)
||
PyLong_Check
(
item
))
{
Py_INCREF
(
item
);
return
item
;
}
if
(
PyIndex_Check
(
item
))
{
result
=
item
->
ob_type
->
tp_as_number
->
nb_index
(
item
);
if
(
result
&&
!
PyInt_Check
(
result
)
&&
!
PyLong_Check
(
result
))
{
PyErr_Format
(
PyExc_TypeError
,
"__index__ returned non-(int,long) "
\
"(type %.200s)"
,
result
->
ob_type
->
tp_name
);
Py_DECREF
(
result
);
return
NULL
;
}
}
else
{
PyErr_Format
(
PyExc_TypeError
,
"'%.200s' object cannot be interpreted "
"as an index"
,
item
->
ob_type
->
tp_name
);
}
return
result
;
}
/* Return an error on Overflow only if err is not NULL*/
Py_ssize_t
PyNumber_AsSsize_t
(
PyObject
*
item
,
PyObject
*
err
)
{
Py_ssize_t
result
;
PyObject
*
runerr
;
PyObject
*
value
=
PyNumber_Index
(
item
);
if
(
value
==
NULL
)
return
-
1
;
/* We're done if PyInt_AsSsize_t() returns without error. */
result
=
PyInt_AsSsize_t
(
value
);
if
(
result
!=
-
1
||
!
(
runerr
=
PyErr_Occurred
()))
goto
finish
;
/* Error handling code -- only manage OverflowError differently */
if
(
!
PyErr_GivenExceptionMatches
(
runerr
,
PyExc_OverflowError
))
goto
finish
;
PyErr_Clear
();
/* If no error-handling desired then the default clipping
is sufficient.
*/
if
(
!
err
)
{
assert
(
PyLong_Check
(
value
));
/* Whether or not it is less than or equal to
zero is determined by the sign of ob_size
*/
if
(
_PyLong_Sign
(
value
)
<
0
)
result
=
PY_SSIZE_T_MIN
;
else
result
=
PY_SSIZE_T_MAX
;
}
else
{
/* Otherwise replace the error with caller's error object. */
PyErr_Format
(
err
,
"cannot fit '%.200s' into an index-sized integer"
,
item
->
ob_type
->
tp_name
);
}
finish:
Py_DECREF
(
value
);
return
result
;
}
PyObject
*
_PyNumber_ConvertIntegralToInt
(
PyObject
*
integral
,
const
char
*
error_format
)
{
const
char
*
type_name
;
static
PyObject
*
int_name
=
NULL
;
if
(
int_name
==
NULL
)
{
int_name
=
PyString_InternFromString
(
"__int__"
);
if
(
int_name
==
NULL
)
return
NULL
;
// Pyston change:
PyGC_RegisterStaticConstant
(
int_name
);
}
if
(
integral
&&
(
!
PyInt_Check
(
integral
)
&&
!
PyLong_Check
(
integral
)))
{
/* Don't go through tp_as_number->nb_int to avoid
hitting the classic class fallback to __trunc__. */
PyObject
*
int_func
=
PyObject_GetAttr
(
integral
,
int_name
);
if
(
int_func
==
NULL
)
{
PyErr_Clear
();
/* Raise a different error. */
goto
non_integral_error
;
}
Py_DECREF
(
integral
);
integral
=
PyEval_CallObject
(
int_func
,
NULL
);
Py_DECREF
(
int_func
);
if
(
integral
&&
(
!
PyInt_Check
(
integral
)
&&
!
PyLong_Check
(
integral
)))
{
goto
non_integral_error
;
}
}
return
integral
;
non_integral_error:
if
(
PyInstance_Check
(
integral
))
{
// Pyston change:
// type_name = PyString_AS_STRING(((PyInstanceObject *)integral)
// ->in_class->cl_name);
// type_name = static_cast<BoxedInstance*>(integral)->inst_cls->name->data();
type_name
=
PyString_AS_STRING
(
PyClass_Name
(
PyInstance_Class
(
integral
)));
}
else
{
type_name
=
integral
->
ob_type
->
tp_name
;
}
PyErr_Format
(
PyExc_TypeError
,
error_format
,
type_name
);
Py_DECREF
(
integral
);
return
NULL
;
}
PyObject
*
PyNumber_Int
(
PyObject
*
o
)
{
PyNumberMethods
*
m
;
static
PyObject
*
trunc_name
=
NULL
;
PyObject
*
trunc_func
;
const
char
*
buffer
;
Py_ssize_t
buffer_len
;
if
(
trunc_name
==
NULL
)
{
trunc_name
=
PyString_InternFromString
(
"__trunc__"
);
if
(
trunc_name
==
NULL
)
return
NULL
;
// Pyston change:
PyGC_RegisterStaticConstant
(
trunc_name
);
}
if
(
o
==
NULL
)
return
null_error
();
if
(
PyInt_CheckExact
(
o
))
{
Py_INCREF
(
o
);
return
o
;
}
m
=
o
->
ob_type
->
tp_as_number
;
if
(
m
&&
m
->
nb_int
)
{
/* This should include subclasses of int */
/* Classic classes always take this branch. */
PyObject
*
res
=
m
->
nb_int
(
o
);
if
(
res
&&
(
!
PyInt_Check
(
res
)
&&
!
PyLong_Check
(
res
)))
{
PyErr_Format
(
PyExc_TypeError
,
"__int__ returned non-int (type %.200s)"
,
res
->
ob_type
->
tp_name
);
Py_DECREF
(
res
);
return
NULL
;
}
return
res
;
}
if
(
PyInt_Check
(
o
))
{
/* A int subclass without nb_int */
PyIntObject
*
io
=
(
PyIntObject
*
)
o
;
return
PyInt_FromLong
(
io
->
ob_ival
);
}
trunc_func
=
PyObject_GetAttr
(
o
,
trunc_name
);
if
(
trunc_func
)
{
PyObject
*
truncated
=
PyEval_CallObject
(
trunc_func
,
NULL
);
Py_DECREF
(
trunc_func
);
/* __trunc__ is specified to return an Integral type, but
int() needs to return an int. */
return
_PyNumber_ConvertIntegralToInt
(
truncated
,
"__trunc__ returned non-Integral (type %.200s)"
);
}
PyErr_Clear
();
/* It's not an error if o.__trunc__ doesn't exist. */
if
(
PyString_Check
(
o
))
return
int_from_string
(
PyString_AS_STRING
(
o
),
PyString_GET_SIZE
(
o
));
#ifdef Py_USING_UNICODE
if
(
PyUnicode_Check
(
o
))
return
PyInt_FromUnicode
(
PyUnicode_AS_UNICODE
(
o
),
PyUnicode_GET_SIZE
(
o
),
10
);
#endif
if
(
!
PyObject_AsCharBuffer
(
o
,
&
buffer
,
&
buffer_len
))
return
int_from_string
((
char
*
)
buffer
,
buffer_len
);
return
type_error
(
"int() argument must be a string or a "
"number, not '%.200s'"
,
o
);
}
/* Add a check for embedded NULL-bytes in the argument. */
static
PyObject
*
long_from_string
(
const
char
*
s
,
Py_ssize_t
len
)
{
char
*
end
;
PyObject
*
x
;
x
=
PyLong_FromString
((
char
*
)
s
,
&
end
,
10
);
if
(
x
==
NULL
)
return
NULL
;
if
(
end
!=
s
+
len
)
{
PyErr_SetString
(
PyExc_ValueError
,
"null byte in argument for long()"
);
Py_DECREF
(
x
);
return
NULL
;
}
return
x
;
}
PyObject
*
PyNumber_Long
(
PyObject
*
o
)
{
PyNumberMethods
*
m
;
static
PyObject
*
trunc_name
=
NULL
;
PyObject
*
trunc_func
;
const
char
*
buffer
;
Py_ssize_t
buffer_len
;
if
(
trunc_name
==
NULL
)
{
trunc_name
=
PyString_InternFromString
(
"__trunc__"
);
if
(
trunc_name
==
NULL
)
return
NULL
;
// Pyston change:
PyGC_RegisterStaticConstant
(
trunc_name
);
}
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_number
;
if
(
m
&&
m
->
nb_long
)
{
/* This should include subclasses of long */
/* Classic classes always take this branch. */
PyObject
*
res
=
m
->
nb_long
(
o
);
if
(
res
==
NULL
)
return
NULL
;
if
(
PyInt_Check
(
res
))
{
long
value
=
PyInt_AS_LONG
(
res
);
Py_DECREF
(
res
);
return
PyLong_FromLong
(
value
);
}
else
if
(
!
PyLong_Check
(
res
))
{
PyErr_Format
(
PyExc_TypeError
,
"__long__ returned non-long (type %.200s)"
,
res
->
ob_type
->
tp_name
);
Py_DECREF
(
res
);
return
NULL
;
}
return
res
;
}
if
(
PyLong_Check
(
o
))
/* A long subclass without nb_long */
return
_PyLong_Copy
((
PyLongObject
*
)
o
);
trunc_func
=
PyObject_GetAttr
(
o
,
trunc_name
);
if
(
trunc_func
)
{
PyObject
*
truncated
=
PyEval_CallObject
(
trunc_func
,
NULL
);
PyObject
*
int_instance
;
Py_DECREF
(
trunc_func
);
/* __trunc__ is specified to return an Integral type,
but long() needs to return a long. */
int_instance
=
_PyNumber_ConvertIntegralToInt
(
truncated
,
"__trunc__ returned non-Integral (type %.200s)"
);
if
(
int_instance
&&
PyInt_Check
(
int_instance
))
{
/* Make sure that long() returns a long instance. */
long
value
=
PyInt_AS_LONG
(
int_instance
);
Py_DECREF
(
int_instance
);
return
PyLong_FromLong
(
value
);
}
return
int_instance
;
}
PyErr_Clear
();
/* It's not an error if o.__trunc__ doesn't exist. */
if
(
PyString_Check
(
o
))
/* need to do extra error checking that PyLong_FromString()
* doesn't do. In particular long('9.5') must raise an
* exception, not truncate the float.
*/
return
long_from_string
(
PyString_AS_STRING
(
o
),
PyString_GET_SIZE
(
o
));
#ifdef Py_USING_UNICODE
if
(
PyUnicode_Check
(
o
))
/* The above check is done in PyLong_FromUnicode(). */
return
PyLong_FromUnicode
(
PyUnicode_AS_UNICODE
(
o
),
PyUnicode_GET_SIZE
(
o
),
10
);
#endif
if
(
!
PyObject_AsCharBuffer
(
o
,
&
buffer
,
&
buffer_len
))
return
long_from_string
(
buffer
,
buffer_len
);
return
type_error
(
"long() argument must be a string or a "
"number, not '%.200s'"
,
o
);
}
PyObject
*
PyNumber_Float
(
PyObject
*
o
)
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_number
;
if
(
m
&&
m
->
nb_float
)
{
/* This should include subclasses of float */
PyObject
*
res
=
m
->
nb_float
(
o
);
if
(
res
&&
!
PyFloat_Check
(
res
))
{
PyErr_Format
(
PyExc_TypeError
,
"__float__ returned non-float (type %.200s)"
,
res
->
ob_type
->
tp_name
);
Py_DECREF
(
res
);
return
NULL
;
}
return
res
;
}
if
(
PyFloat_Check
(
o
))
{
/* A float subclass with nb_float == NULL */
PyFloatObject
*
po
=
(
PyFloatObject
*
)
o
;
return
PyFloat_FromDouble
(
po
->
ob_fval
);
}
return
PyFloat_FromString
(
o
,
NULL
);
}
PyObject
*
PyNumber_ToBase
(
PyObject
*
n
,
int
base
)
{
PyObject
*
res
=
NULL
;
PyObject
*
index
=
PyNumber_Index
(
n
);
if
(
!
index
)
return
NULL
;
if
(
PyLong_Check
(
index
))
res
=
_PyLong_Format
(
index
,
base
,
0
,
1
);
else
if
(
PyInt_Check
(
index
))
res
=
_PyInt_Format
((
PyIntObject
*
)
index
,
base
,
1
);
else
/* It should not be possible to get here, as
PyNumber_Index already has a check for the same
condition */
PyErr_SetString
(
PyExc_ValueError
,
"PyNumber_ToBase: index not "
"int or long"
);
Py_DECREF
(
index
);
return
res
;
}
/* Operations on sequences */
int
PySequence_Check
(
PyObject
*
s
)
{
if
(
s
==
NULL
)
return
0
;
if
(
PyInstance_Check
(
s
))
return
PyObject_HasAttrString
(
s
,
"__getitem__"
);
if
(
PyDict_Check
(
s
))
return
0
;
return
s
->
ob_type
->
tp_as_sequence
&&
s
->
ob_type
->
tp_as_sequence
->
sq_item
!=
NULL
;
}
Py_ssize_t
PySequence_Size
(
PyObject
*
s
)
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_length
)
return
m
->
sq_length
(
s
);
type_error
(
"object of type '%.200s' has no len()"
,
s
);
return
-
1
;
}
#undef PySequence_Length
Py_ssize_t
PySequence_Length
(
PyObject
*
s
)
{
return
PySequence_Size
(
s
);
}
#define PySequence_Length PySequence_Size
PyObject
*
PySequence_Concat
(
PyObject
*
s
,
PyObject
*
o
)
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
||
o
==
NULL
)
return
null_error
();
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_concat
)
return
m
->
sq_concat
(
s
,
o
);
/* Instances of user classes defining an __add__() method only
have an nb_add slot, not an sq_concat slot. So we fall back
to nb_add if both arguments appear to be sequences. */
if
(
PySequence_Check
(
s
)
&&
PySequence_Check
(
o
))
{
PyObject
*
result
=
binary_op1
(
s
,
o
,
NB_SLOT
(
nb_add
));
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be concatenated"
,
s
);
}
PyObject
*
PySequence_Repeat
(
PyObject
*
o
,
Py_ssize_t
count
)
{
PySequenceMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_repeat
)
return
m
->
sq_repeat
(
o
,
count
);
/* Instances of user classes defining a __mul__() method only
have an nb_multiply slot, not an sq_repeat slot. so we fall back
to nb_multiply if o appears to be a sequence. */
if
(
PySequence_Check
(
o
))
{
PyObject
*
n
,
*
result
;
n
=
PyInt_FromSsize_t
(
count
);
if
(
n
==
NULL
)
return
NULL
;
result
=
binary_op1
(
o
,
n
,
NB_SLOT
(
nb_multiply
));
Py_DECREF
(
n
);
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be repeated"
,
o
);
}
PyObject
*
PySequence_InPlaceConcat
(
PyObject
*
s
,
PyObject
*
o
)
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
||
o
==
NULL
)
return
null_error
();
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
HASINPLACE
(
s
)
&&
m
->
sq_inplace_concat
)
return
m
->
sq_inplace_concat
(
s
,
o
);
if
(
m
&&
m
->
sq_concat
)
return
m
->
sq_concat
(
s
,
o
);
if
(
PySequence_Check
(
s
)
&&
PySequence_Check
(
o
))
{
PyObject
*
result
=
binary_iop1
(
s
,
o
,
NB_SLOT
(
nb_inplace_add
),
NB_SLOT
(
nb_add
));
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be concatenated"
,
s
);
}
PyObject
*
PySequence_InPlaceRepeat
(
PyObject
*
o
,
Py_ssize_t
count
)
{
PySequenceMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
HASINPLACE
(
o
)
&&
m
->
sq_inplace_repeat
)
return
m
->
sq_inplace_repeat
(
o
,
count
);
if
(
m
&&
m
->
sq_repeat
)
return
m
->
sq_repeat
(
o
,
count
);
if
(
PySequence_Check
(
o
))
{
PyObject
*
n
,
*
result
;
n
=
PyInt_FromSsize_t
(
count
);
if
(
n
==
NULL
)
return
NULL
;
result
=
binary_iop1
(
o
,
n
,
NB_SLOT
(
nb_inplace_multiply
),
NB_SLOT
(
nb_multiply
));
Py_DECREF
(
n
);
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be repeated"
,
o
);
}
PyObject
*
PySequence_GetItem
(
PyObject
*
s
,
Py_ssize_t
i
)
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
return
null_error
();
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_item
)
{
if
(
i
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
NULL
;
i
+=
l
;
}
}
return
m
->
sq_item
(
s
,
i
);
}
return
type_error
(
"'%.200s' object does not support indexing"
,
s
);
}
PyObject
*
PySequence_GetSlice
(
PyObject
*
s
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
{
PySequenceMethods
*
m
;
PyMappingMethods
*
mp
;
if
(
!
s
)
return
null_error
();
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_slice
)
{
if
(
i1
<
0
||
i2
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
NULL
;
if
(
i1
<
0
)
i1
+=
l
;
if
(
i2
<
0
)
i2
+=
l
;
}
}
return
m
->
sq_slice
(
s
,
i1
,
i2
);
}
else
if
((
mp
=
s
->
ob_type
->
tp_as_mapping
)
&&
mp
->
mp_subscript
)
{
PyObject
*
res
;
PyObject
*
slice
=
_PySlice_FromIndices
(
i1
,
i2
);
if
(
!
slice
)
return
NULL
;
res
=
mp
->
mp_subscript
(
s
,
slice
);
Py_DECREF
(
slice
);
return
res
;
}
return
type_error
(
"'%.200s' object is unsliceable"
,
s
);
}
int
PySequence_SetItem
(
PyObject
*
s
,
Py_ssize_t
i
,
PyObject
*
o
)
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_item
)
{
if
(
i
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
-
1
;
i
+=
l
;
}
}
return
m
->
sq_ass_item
(
s
,
i
,
o
);
}
type_error
(
"'%.200s' object does not support item assignment"
,
s
);
return
-
1
;
}
int
PySequence_DelItem
(
PyObject
*
s
,
Py_ssize_t
i
)
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_item
)
{
if
(
i
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
-
1
;
i
+=
l
;
}
}
return
m
->
sq_ass_item
(
s
,
i
,
(
PyObject
*
)
NULL
);
}
type_error
(
"'%.200s' object doesn't support item deletion"
,
s
);
return
-
1
;
}
int
PySequence_SetSlice
(
PyObject
*
s
,
Py_ssize_t
i1
,
Py_ssize_t
i2
,
PyObject
*
o
)
{
PySequenceMethods
*
m
;
PyMappingMethods
*
mp
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_slice
)
{
if
(
i1
<
0
||
i2
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
-
1
;
if
(
i1
<
0
)
i1
+=
l
;
if
(
i2
<
0
)
i2
+=
l
;
}
}
return
m
->
sq_ass_slice
(
s
,
i1
,
i2
,
o
);
}
else
if
((
mp
=
s
->
ob_type
->
tp_as_mapping
)
&&
mp
->
mp_ass_subscript
)
{
int
res
;
PyObject
*
slice
=
_PySlice_FromIndices
(
i1
,
i2
);
if
(
!
slice
)
return
-
1
;
res
=
mp
->
mp_ass_subscript
(
s
,
slice
,
o
);
Py_DECREF
(
slice
);
return
res
;
}
type_error
(
"'%.200s' object doesn't support slice assignment"
,
s
);
return
-
1
;
}
int
PySequence_DelSlice
(
PyObject
*
s
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
ob_type
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_slice
)
{
if
(
i1
<
0
||
i2
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
-
1
;
if
(
i1
<
0
)
i1
+=
l
;
if
(
i2
<
0
)
i2
+=
l
;
}
}
return
m
->
sq_ass_slice
(
s
,
i1
,
i2
,
(
PyObject
*
)
NULL
);
}
type_error
(
"'%.200s' object doesn't support slice deletion"
,
s
);
return
-
1
;
}
PyObject
*
PySequence_Tuple
(
PyObject
*
v
)
{
PyObject
*
it
;
/* iter(v) */
Py_ssize_t
n
;
/* guess for result tuple size */
PyObject
*
result
=
NULL
;
Py_ssize_t
j
;
if
(
v
==
NULL
)
return
null_error
();
/* Special-case the common tuple and list cases, for efficiency. */
if
(
PyTuple_CheckExact
(
v
))
{
/* Note that we can't know whether it's safe to return
a tuple *subclass* instance as-is, hence the restriction
to exact tuples here. In contrast, lists always make
a copy, so there's no need for exactness below. */
Py_INCREF
(
v
);
return
v
;
}
if
(
PyList_Check
(
v
))
return
PyList_AsTuple
(
v
);
/* Get iterator. */
it
=
PyObject_GetIter
(
v
);
if
(
it
==
NULL
)
return
NULL
;
/* Guess result size and allocate space. */
n
=
_PyObject_LengthHint
(
v
,
10
);
if
(
n
==
-
1
)
goto
Fail
;
result
=
PyTuple_New
(
n
);
if
(
result
==
NULL
)
goto
Fail
;
/* Fill the tuple. */
for
(
j
=
0
;
;
++
j
)
{
PyObject
*
item
=
PyIter_Next
(
it
);
if
(
item
==
NULL
)
{
if
(
PyErr_Occurred
())
goto
Fail
;
break
;
}
if
(
j
>=
n
)
{
Py_ssize_t
oldn
=
n
;
/* The over-allocation strategy can grow a bit faster
than for lists because unlike lists the
over-allocation isn't permanent -- we reclaim
the excess before the end of this routine.
So, grow by ten and then add 25%.
*/
n
+=
10
;
n
+=
n
>>
2
;
if
(
n
<
oldn
)
{
/* Check for overflow */
PyErr_NoMemory
();
Py_DECREF
(
item
);
goto
Fail
;
}
if
(
_PyTuple_Resize
(
&
result
,
n
)
!=
0
)
{
Py_DECREF
(
item
);
goto
Fail
;
}
}
PyTuple_SET_ITEM
(
result
,
j
,
item
);
}
/* Cut tuple back if guess was too large. */
if
(
j
<
n
&&
_PyTuple_Resize
(
&
result
,
j
)
!=
0
)
goto
Fail
;
Py_DECREF
(
it
);
return
result
;
Fail:
Py_XDECREF
(
result
);
Py_DECREF
(
it
);
return
NULL
;
}
PyObject
*
PySequence_List
(
PyObject
*
v
)
{
PyObject
*
result
;
/* result list */
PyObject
*
rv
;
/* return value from PyList_Extend */
if
(
v
==
NULL
)
return
null_error
();
result
=
PyList_New
(
0
);
if
(
result
==
NULL
)
return
NULL
;
rv
=
_PyList_Extend
((
PyListObject
*
)
result
,
v
);
if
(
rv
==
NULL
)
{
Py_DECREF
(
result
);
return
NULL
;
}
Py_DECREF
(
rv
);
return
result
;
}
PyObject
*
PySequence_Fast
(
PyObject
*
v
,
const
char
*
m
)
{
PyObject
*
it
;
if
(
v
==
NULL
)
return
null_error
();
if
(
PyList_CheckExact
(
v
)
||
PyTuple_CheckExact
(
v
))
{
Py_INCREF
(
v
);
return
v
;
}
it
=
PyObject_GetIter
(
v
);
if
(
it
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_TypeError
))
PyErr_SetString
(
PyExc_TypeError
,
m
);
return
NULL
;
}
v
=
PySequence_List
(
it
);
Py_DECREF
(
it
);
return
v
;
}
/* Iterate over seq. Result depends on the operation:
PY_ITERSEARCH_COUNT: -1 if error, else # of times obj appears in seq.
PY_ITERSEARCH_INDEX: 0-based index of first occurrence of obj in seq;
set ValueError and return -1 if none found; also return -1 on error.
Py_ITERSEARCH_CONTAINS: return 1 if obj in seq, else 0; -1 on error.
*/
Py_ssize_t
_PySequence_IterSearch
(
PyObject
*
seq
,
PyObject
*
obj
,
int
operation
)
{
Py_ssize_t
n
;
int
wrapped
;
/* for PY_ITERSEARCH_INDEX, true iff n wrapped around */
PyObject
*
it
;
/* iter(seq) */
if
(
seq
==
NULL
||
obj
==
NULL
)
{
null_error
();
return
-
1
;
}
it
=
PyObject_GetIter
(
seq
);
if
(
it
==
NULL
)
{
type_error
(
"argument of type '%.200s' is not iterable"
,
seq
);
return
-
1
;
}
n
=
wrapped
=
0
;
for
(;;)
{
int
cmp
;
PyObject
*
item
=
PyIter_Next
(
it
);
if
(
item
==
NULL
)
{
if
(
PyErr_Occurred
())
goto
Fail
;
break
;
}
cmp
=
PyObject_RichCompareBool
(
obj
,
item
,
Py_EQ
);
Py_DECREF
(
item
);
if
(
cmp
<
0
)
goto
Fail
;
if
(
cmp
>
0
)
{
switch
(
operation
)
{
case
PY_ITERSEARCH_COUNT
:
if
(
n
==
PY_SSIZE_T_MAX
)
{
PyErr_SetString
(
PyExc_OverflowError
,
"count exceeds C integer size"
);
goto
Fail
;
}
++
n
;
break
;
case
PY_ITERSEARCH_INDEX
:
if
(
wrapped
)
{
PyErr_SetString
(
PyExc_OverflowError
,
"index exceeds C integer size"
);
goto
Fail
;
}
goto
Done
;
case
PY_ITERSEARCH_CONTAINS
:
n
=
1
;
goto
Done
;
default:
assert
(
!
"unknown operation"
);
}
}
if
(
operation
==
PY_ITERSEARCH_INDEX
)
{
if
(
n
==
PY_SSIZE_T_MAX
)
wrapped
=
1
;
++
n
;
}
}
if
(
operation
!=
PY_ITERSEARCH_INDEX
)
goto
Done
;
PyErr_SetString
(
PyExc_ValueError
,
"sequence.index(x): x not in sequence"
);
/* fall into failure code */
Fail:
n
=
-
1
;
/* fall through */
Done:
Py_DECREF
(
it
);
return
n
;
}
/* Return # of times o appears in s. */
Py_ssize_t
PySequence_Count
(
PyObject
*
s
,
PyObject
*
o
)
{
return
_PySequence_IterSearch
(
s
,
o
,
PY_ITERSEARCH_COUNT
);
}
/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
* Use sq_contains if possible, else defer to _PySequence_IterSearch().
*/
int
PySequence_Contains
(
PyObject
*
seq
,
PyObject
*
ob
)
{
Py_ssize_t
result
;
if
(
PyType_HasFeature
(
seq
->
ob_type
,
Py_TPFLAGS_HAVE_SEQUENCE_IN
))
{
PySequenceMethods
*
sqm
=
seq
->
ob_type
->
tp_as_sequence
;
if
(
sqm
!=
NULL
&&
sqm
->
sq_contains
!=
NULL
)
return
(
*
sqm
->
sq_contains
)(
seq
,
ob
);
}
result
=
_PySequence_IterSearch
(
seq
,
ob
,
PY_ITERSEARCH_CONTAINS
);
return
Py_SAFE_DOWNCAST
(
result
,
Py_ssize_t
,
int
);
}
/* Backwards compatibility */
#undef PySequence_In
int
PySequence_In
(
PyObject
*
w
,
PyObject
*
v
)
{
return
PySequence_Contains
(
w
,
v
);
}
Py_ssize_t
PySequence_Index
(
PyObject
*
s
,
PyObject
*
o
)
{
return
_PySequence_IterSearch
(
s
,
o
,
PY_ITERSEARCH_INDEX
);
}
/* Operations on mappings */
int
PyMapping_Check
(
PyObject
*
o
)
{
if
(
o
&&
PyInstance_Check
(
o
))
return
PyObject_HasAttrString
(
o
,
"__getitem__"
);
return
o
&&
o
->
ob_type
->
tp_as_mapping
&&
o
->
ob_type
->
tp_as_mapping
->
mp_subscript
&&
!
(
o
->
ob_type
->
tp_as_sequence
&&
o
->
ob_type
->
tp_as_sequence
->
sq_slice
);
}
Py_ssize_t
PyMapping_Size
(
PyObject
*
o
)
{
PyMappingMethods
*
m
;
if
(
o
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
o
->
ob_type
->
tp_as_mapping
;
if
(
m
&&
m
->
mp_length
)
return
m
->
mp_length
(
o
);
type_error
(
"object of type '%.200s' has no len()"
,
o
);
return
-
1
;
}
#undef PyMapping_Length
Py_ssize_t
PyMapping_Length
(
PyObject
*
o
)
{
return
PyMapping_Size
(
o
);
}
#define PyMapping_Length PyMapping_Size
PyObject
*
PyMapping_GetItemString
(
PyObject
*
o
,
const
char
*
key
)
{
PyObject
*
okey
,
*
r
;
if
(
key
==
NULL
)
return
null_error
();
okey
=
PyString_FromString
(
key
);
if
(
okey
==
NULL
)
return
NULL
;
r
=
PyObject_GetItem
(
o
,
okey
);
Py_DECREF
(
okey
);
return
r
;
}
int
PyMapping_SetItemString
(
PyObject
*
o
,
const
char
*
key
,
PyObject
*
value
)
{
PyObject
*
okey
;
int
r
;
if
(
key
==
NULL
)
{
null_error
();
return
-
1
;
}
okey
=
PyString_FromString
(
key
);
if
(
okey
==
NULL
)
return
-
1
;
r
=
PyObject_SetItem
(
o
,
okey
,
value
);
Py_DECREF
(
okey
);
return
r
;
}
int
PyMapping_HasKeyString
(
PyObject
*
o
,
char
*
key
)
{
PyObject
*
v
;
v
=
PyMapping_GetItemString
(
o
,
key
);
if
(
v
)
{
Py_DECREF
(
v
);
return
1
;
}
PyErr_Clear
();
return
0
;
}
int
PyMapping_HasKey
(
PyObject
*
o
,
PyObject
*
key
)
{
PyObject
*
v
;
v
=
PyObject_GetItem
(
o
,
key
);
if
(
v
)
{
Py_DECREF
(
v
);
return
1
;
}
PyErr_Clear
();
return
0
;
}
/* Operations on callable objects */
/* XXX PyCallable_Check() is in object.c */
PyObject
*
PyObject_CallObject
(
PyObject
*
o
,
PyObject
*
a
)
{
return
PyEval_CallObjectWithKeywords
(
o
,
a
,
NULL
);
}
// pyston change: comment this out
#if 0
PyObject *
PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
ternaryfunc call;
if ((call = func->ob_type->tp_call) != NULL) {
PyObject *result;
if (Py_EnterRecursiveCall(" while calling a Python object"))
return NULL;
result = (*call)(func, arg, kw);
Py_LeaveRecursiveCall();
if (result == NULL && !PyErr_Occurred())
PyErr_SetString(
PyExc_SystemError,
"NULL result without error in PyObject_Call");
return result;
}
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
func->ob_type->tp_name);
return NULL;
}
#endif
static
PyObject
*
call_function_tail
(
PyObject
*
callable
,
PyObject
*
args
)
{
PyObject
*
retval
;
if
(
args
==
NULL
)
return
NULL
;
if
(
!
PyTuple_Check
(
args
))
{
PyObject
*
a
;
a
=
PyTuple_New
(
1
);
if
(
a
==
NULL
)
{
Py_DECREF
(
args
);
return
NULL
;
}
PyTuple_SET_ITEM
(
a
,
0
,
args
);
args
=
a
;
}
retval
=
PyObject_Call
(
callable
,
args
,
NULL
);
Py_DECREF
(
args
);
return
retval
;
}
PyObject
*
PyObject_CallFunction
(
PyObject
*
callable
,
const
char
*
format
,
...)
{
va_list
va
;
PyObject
*
args
;
if
(
callable
==
NULL
)
return
null_error
();
if
(
format
&&
*
format
)
{
va_start
(
va
,
format
);
args
=
Py_VaBuildValue
(
format
,
va
);
va_end
(
va
);
}
else
args
=
PyTuple_New
(
0
);
return
call_function_tail
(
callable
,
args
);
}
PyObject
*
_PyObject_CallFunction_SizeT
(
PyObject
*
callable
,
const
char
*
format
,
...)
{
va_list
va
;
PyObject
*
args
;
if
(
callable
==
NULL
)
return
null_error
();
if
(
format
&&
*
format
)
{
va_start
(
va
,
format
);
args
=
_Py_VaBuildValue_SizeT
(
format
,
va
);
va_end
(
va
);
}
else
args
=
PyTuple_New
(
0
);
return
call_function_tail
(
callable
,
args
);
}
// pyston change: comment this out
#if 0
PyObject *
PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
{
va_list va;
PyObject *args;
PyObject *func = NULL;
PyObject *retval = NULL;
if (o == NULL || name == NULL)
return null_error();
func = PyObject_GetAttrString(o, name);
if (func == NULL) {
PyErr_SetString(PyExc_AttributeError, name);
return 0;
}
if (!PyCallable_Check(func)) {
type_error("attribute of type '%.200s' is not callable", func);
goto exit;
}
if (format && *format) {
va_start(va, format);
args = Py_VaBuildValue(format, va);
va_end(va);
}
else
args = PyTuple_New(0);
retval = call_function_tail(func, args);
exit:
/* args gets consumed in call_function_tail */
Py_XDECREF(func);
return retval;
}
PyObject *
_PyObject_CallMethod_SizeT(PyObject *o, const char *name, const char *format, ...)
{
va_list va;
PyObject *args;
PyObject *func = NULL;
PyObject *retval = NULL;
if (o == NULL || name == NULL)
return null_error();
func = PyObject_GetAttrString(o, name);
if (func == NULL) {
PyErr_SetString(PyExc_AttributeError, name);
return 0;
}
if (!PyCallable_Check(func)) {
type_error("attribute of type '%.200s' is not callable", func);
goto exit;
}
if (format && *format) {
va_start(va, format);
args = _Py_VaBuildValue_SizeT(format, va);
va_end(va);
}
else
args = PyTuple_New(0);
retval = call_function_tail(func, args);
exit:
/* args gets consumed in call_function_tail */
Py_XDECREF(func);
return retval;
}
#endif
// pyston change: removed the static keyword, this function is also used in src/capi/abstract.cpp
PyObject
*
objargs_mktuple
(
va_list
va
)
{
int
i
,
n
=
0
;
va_list
countva
;
PyObject
*
result
,
*
tmp
;
#ifdef VA_LIST_IS_ARRAY
memcpy
(
countva
,
va
,
sizeof
(
va_list
));
#else
#ifdef __va_copy
__va_copy
(
countva
,
va
);
#else
countva
=
va
;
#endif
#endif
while
(((
PyObject
*
)
va_arg
(
countva
,
PyObject
*
))
!=
NULL
)
++
n
;
result
=
PyTuple_New
(
n
);
if
(
result
!=
NULL
&&
n
>
0
)
{
for
(
i
=
0
;
i
<
n
;
++
i
)
{
tmp
=
(
PyObject
*
)
va_arg
(
va
,
PyObject
*
);
PyTuple_SET_ITEM
(
result
,
i
,
tmp
);
Py_INCREF
(
tmp
);
}
}
return
result
;
}
// pyston change: comment this out
#if 0
PyObject *
PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
{
PyObject *args, *tmp;
va_list vargs;
if (callable == NULL || name == NULL)
return null_error();
callable = PyObject_GetAttr(callable, name);
if (callable == NULL)
return NULL;
/* count the args */
va_start(vargs, name);
args = objargs_mktuple(vargs);
va_end(vargs);
if (args == NULL) {
Py_DECREF(callable);
return NULL;
}
tmp = PyObject_Call(callable, args, NULL);
Py_DECREF(args);
Py_DECREF(callable);
return tmp;
}
#endif
PyObject
*
PyObject_CallFunctionObjArgs
(
PyObject
*
callable
,
...)
{
PyObject
*
args
,
*
tmp
;
va_list
vargs
;
if
(
callable
==
NULL
)
return
null_error
();
/* count the args */
va_start
(
vargs
,
callable
);
args
=
objargs_mktuple
(
vargs
);
va_end
(
vargs
);
if
(
args
==
NULL
)
return
NULL
;
tmp
=
PyObject_Call
(
callable
,
args
,
NULL
);
Py_DECREF
(
args
);
return
tmp
;
}
/* isinstance(), issubclass() */
/* abstract_get_bases() has logically 4 return states, with a sort of 0th
* state that will almost never happen.
*
* 0. creating the __bases__ static string could get a MemoryError
* 1. getattr(cls, '__bases__') could raise an AttributeError
* 2. getattr(cls, '__bases__') could raise some other exception
* 3. getattr(cls, '__bases__') could return a tuple
* 4. getattr(cls, '__bases__') could return something other than a tuple
*
* Only state #3 is a non-error state and only it returns a non-NULL object
* (it returns the retrieved tuple).
*
* Any raised AttributeErrors are masked by clearing the exception and
* returning NULL. If an object other than a tuple comes out of __bases__,
* then again, the return value is NULL. So yes, these two situations
* produce exactly the same results: NULL is returned and no error is set.
*
* If some exception other than AttributeError is raised, then NULL is also
* returned, but the exception is not cleared. That's because we want the
* exception to be propagated along.
*
* Callers are expected to test for PyErr_Occurred() when the return value
* is NULL to decide whether a valid exception should be propagated or not.
* When there's no exception to propagate, it's customary for the caller to
* set a TypeError.
*/
// pyston change: removed the static keyword, this function is also used in src/capi/abstract.cpp
PyObject
*
abstract_get_bases
(
PyObject
*
cls
)
{
static
PyObject
*
__bases__
=
NULL
;
PyObject
*
bases
;
if
(
__bases__
==
NULL
)
{
__bases__
=
PyString_InternFromString
(
"__bases__"
);
if
(
__bases__
==
NULL
)
return
NULL
;
// Pyston change:
PyGC_RegisterStaticConstant
(
__bases__
);
}
bases
=
PyObject_GetAttr
(
cls
,
__bases__
);
if
(
bases
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_AttributeError
))
PyErr_Clear
();
return
NULL
;
}
if
(
!
PyTuple_Check
(
bases
))
{
Py_DECREF
(
bases
);
return
NULL
;
}
return
bases
;
}
static
int
abstract_issubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
{
PyObject
*
bases
=
NULL
;
Py_ssize_t
i
,
n
;
int
r
=
0
;
while
(
1
)
{
if
(
derived
==
cls
)
return
1
;
bases
=
abstract_get_bases
(
derived
);
if
(
bases
==
NULL
)
{
if
(
PyErr_Occurred
())
return
-
1
;
return
0
;
}
n
=
PyTuple_GET_SIZE
(
bases
);
if
(
n
==
0
)
{
Py_DECREF
(
bases
);
return
0
;
}
/* Avoid recursivity in the single inheritance case */
if
(
n
==
1
)
{
derived
=
PyTuple_GET_ITEM
(
bases
,
0
);
Py_DECREF
(
bases
);
continue
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
r
=
abstract_issubclass
(
PyTuple_GET_ITEM
(
bases
,
i
),
cls
);
if
(
r
!=
0
)
break
;
}
Py_DECREF
(
bases
);
return
r
;
}
}
// pyston change: removed the static keyword, this function is also used in src/capi/abstract.cpp
int
check_class
(
PyObject
*
cls
,
const
char
*
error
)
{
PyObject
*
bases
=
abstract_get_bases
(
cls
);
if
(
bases
==
NULL
)
{
/* Do not mask errors. */
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_TypeError
,
error
);
return
0
;
}
Py_DECREF
(
bases
);
return
-
1
;
}
static
int
recursive_isinstance
(
PyObject
*
inst
,
PyObject
*
cls
)
{
PyObject
*
icls
;
static
PyObject
*
__class__
=
NULL
;
int
retval
=
0
;
if
(
__class__
==
NULL
)
{
__class__
=
PyString_InternFromString
(
"__class__"
);
if
(
__class__
==
NULL
)
return
-
1
;
// Pyston change:
PyGC_RegisterStaticConstant
(
__class__
);
}
if
(
PyClass_Check
(
cls
)
&&
PyInstance_Check
(
inst
))
{
// Pyston change:
// PyObject *inclass =
// (PyObject*)((PyInstanceObject*)inst)->in_class;
PyObject
*
inclass
=
PyInstance_Class
(
inst
);
retval
=
PyClass_IsSubclass
(
inclass
,
cls
);
}
else
if
(
PyType_Check
(
cls
))
{
retval
=
PyObject_TypeCheck
(
inst
,
(
PyTypeObject
*
)
cls
);
if
(
retval
==
0
)
{
PyObject
*
c
=
PyObject_GetAttr
(
inst
,
__class__
);
if
(
c
==
NULL
)
{
PyErr_Clear
();
}
else
{
if
(
c
!=
(
PyObject
*
)(
inst
->
ob_type
)
&&
PyType_Check
(
c
))
retval
=
PyType_IsSubtype
(
(
PyTypeObject
*
)
c
,
(
PyTypeObject
*
)
cls
);
Py_DECREF
(
c
);
}
}
}
else
{
if
(
!
check_class
(
cls
,
"isinstance() arg 2 must be a class, type,"
" or tuple of classes and types"
))
return
-
1
;
icls
=
PyObject_GetAttr
(
inst
,
__class__
);
if
(
icls
==
NULL
)
{
PyErr_Clear
();
retval
=
0
;
}
else
{
retval
=
abstract_issubclass
(
icls
,
cls
);
Py_DECREF
(
icls
);
}
}
return
retval
;
}
// pyston change: comment this out
#if 0
int
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
static PyObject *name = NULL;
/* Quick test for an exact match */
if (Py_TYPE(inst) == (PyTypeObject *)cls)
return 1;
if (PyTuple_Check(cls)) {
Py_ssize_t i;
Py_ssize_t n;
int r = 0;
if (Py_EnterRecursiveCall(" in __instancecheck__"))
return -1;
n = PyTuple_GET_SIZE(cls);
for (i = 0; i < n; ++i) {
PyObject *item = PyTuple_GET_ITEM(cls, i);
r = PyObject_IsInstance(inst, item);
if (r != 0)
/* either found it, or got an error */
break;
}
Py_LeaveRecursiveCall();
return r;
}
if (!(PyClass_Check(cls) || PyInstance_Check(cls))) {
PyObject *checker;
checker = _PyObject_LookupSpecial(cls, "__instancecheck__", &name);
if (checker != NULL) {
PyObject *res;
int ok = -1;
if (Py_EnterRecursiveCall(" in __instancecheck__")) {
Py_DECREF(checker);
return ok;
}
res = PyObject_CallFunctionObjArgs(checker, inst, NULL);
Py_LeaveRecursiveCall();
Py_DECREF(checker);
if (res != NULL) {
ok = PyObject_IsTrue(res);
Py_DECREF(res);
}
return ok;
}
else if (PyErr_Occurred())
return -1;
}
return recursive_isinstance(inst, cls);
}
#endif
// pyston change: removed the static keyword, this function is also used in src/capi/abstract.cpp
int
recursive_issubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
{
int
retval
;
if
(
PyType_Check
(
cls
)
&&
PyType_Check
(
derived
))
{
/* Fast path (non-recursive) */
return
PyType_IsSubtype
(
(
PyTypeObject
*
)
derived
,
(
PyTypeObject
*
)
cls
);
}
if
(
!
PyClass_Check
(
derived
)
||
!
PyClass_Check
(
cls
))
{
if
(
!
check_class
(
derived
,
"issubclass() arg 1 must be a class"
))
return
-
1
;
if
(
!
check_class
(
cls
,
"issubclass() arg 2 must be a class"
" or tuple of classes"
))
return
-
1
;
retval
=
abstract_issubclass
(
derived
,
cls
);
}
else
{
/* shortcut */
if
(
!
(
retval
=
(
derived
==
cls
)))
retval
=
PyClass_IsSubclass
(
derived
,
cls
);
}
return
retval
;
}
// pyston change: comment this out
#if 0
int
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
{
static PyObject *name = NULL;
if (PyTuple_Check(cls)) {
Py_ssize_t i;
Py_ssize_t n;
int r = 0;
if (Py_EnterRecursiveCall(" in __subclasscheck__"))
return -1;
n = PyTuple_GET_SIZE(cls);
for (i = 0; i < n; ++i) {
PyObject *item = PyTuple_GET_ITEM(cls, i);
r = PyObject_IsSubclass(derived, item);
if (r != 0)
/* either found it, or got an error */
break;
}
Py_LeaveRecursiveCall();
return r;
}
if (!(PyClass_Check(cls) || PyInstance_Check(cls))) {
PyObject *checker;
checker = _PyObject_LookupSpecial(cls, "__subclasscheck__", &name);
if (checker != NULL) {
PyObject *res;
int ok = -1;
if (Py_EnterRecursiveCall(" in __subclasscheck__")) {
Py_DECREF(checker);
return ok;
}
res = PyObject_CallFunctionObjArgs(checker, derived, NULL);
Py_LeaveRecursiveCall();
Py_DECREF(checker);
if (res != NULL) {
ok = PyObject_IsTrue(res);
Py_DECREF(res);
}
return ok;
}
else if (PyErr_Occurred()) {
return -1;
}
}
return recursive_issubclass(derived, cls);
}
int
_PyObject_RealIsInstance(PyObject *inst, PyObject *cls)
{
return recursive_isinstance(inst, cls);
}
#endif
int
_PyObject_RealIsSubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
{
return
recursive_issubclass
(
derived
,
cls
);
}
// pyston change: comment this out
#if 0
PyObject *
PyObject_GetIter(PyObject *o)
{
PyTypeObject *t = o->ob_type;
getiterfunc f = NULL;
if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER))
f = t->tp_iter;
if (f == NULL) {
if (PySequence_Check(o))
return PySeqIter_New(o);
return type_error("'%.200s' object is not iterable", o);
}
else {
PyObject *res = (*f)(o);
if (res != NULL && !PyIter_Check(res)) {
PyErr_Format(PyExc_TypeError,
"iter() returned non-iterator "
"of type '%.100s'",
res->ob_type->tp_name);
Py_DECREF(res);
res = NULL;
}
return res;
}
}
/* Return next item.
* If an error occurs, return NULL. PyErr_Occurred() will be true.
* If the iteration terminates normally, return NULL and clear the
* PyExc_StopIteration exception (if it was set). PyErr_Occurred()
* will be false.
* Else return the next object. PyErr_Occurred() will be false.
*/
PyObject *
PyIter_Next(PyObject *iter)
{
PyObject *result;
result = (*iter->ob_type->tp_iternext)(iter);
if (result == NULL &&
PyErr_Occurred() &&
PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
return result;
}
#endif
from_cpython/Objects/sliceobject.c
0 → 100644
View file @
27410967
// This file is originally from CPython 2.7, with modifications for Pyston
/*
Written by Jim Hugunin and Chris Chase.
This includes both the singular ellipsis object and slice objects.
Guido, feel free to do whatever you want in the way of copyrights
for this file.
*/
/*
Py_Ellipsis encodes the '...' rubber index token. It is similar to
the Py_NoneStruct in that there is no way to create other objects of
this type and there is exactly one in existence.
*/
#include "Python.h"
// pyston change: comment this out
#if 0
#include "structmember.h"
static PyObject *
ellipsis_repr(PyObject *op)
{
return PyString_FromString("Ellipsis");
}
PyTypeObject PyEllipsis_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"ellipsis", /* tp_name */
0, /* tp_basicsize */
0, /* tp_itemsize */
0, /*never called*/ /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
ellipsis_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
};
PyObject _Py_EllipsisObject = {
_PyObject_EXTRA_INIT
1, &PyEllipsis_Type
};
/* Slice object implementation
start, stop, and step are python objects with None indicating no
index is present.
*/
PyObject *
PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
{
PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type);
if (obj == NULL)
return NULL;
if (step == NULL) step = Py_None;
Py_INCREF(step);
if (start == NULL) start = Py_None;
Py_INCREF(start);
if (stop == NULL) stop = Py_None;
Py_INCREF(stop);
obj->step = step;
obj->start = start;
obj->stop = stop;
return (PyObject *) obj;
}
#endif
PyObject
*
_PySlice_FromIndices
(
Py_ssize_t
istart
,
Py_ssize_t
istop
)
{
PyObject
*
start
,
*
end
,
*
slice
;
start
=
PyInt_FromSsize_t
(
istart
);
if
(
!
start
)
return
NULL
;
end
=
PyInt_FromSsize_t
(
istop
);
if
(
!
end
)
{
Py_DECREF
(
start
);
return
NULL
;
}
slice
=
PySlice_New
(
start
,
end
,
NULL
);
Py_DECREF
(
start
);
Py_DECREF
(
end
);
return
slice
;
}
// pyston change: comment this out
#if 0
int
PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
{
/* XXX support long ints */
if (r->step == Py_None) {
*step = 1;
} else {
if (!PyInt_Check(r->step) && !PyLong_Check(r->step)) return -1;
*step = PyInt_AsSsize_t(r->step);
}
if (r->start == Py_None) {
*start = *step < 0 ? length-1 : 0;
} else {
if (!PyInt_Check(r->start) && !PyLong_Check(r->step)) return -1;
*start = PyInt_AsSsize_t(r->start);
if (*start < 0) *start += length;
}
if (r->stop == Py_None) {
*stop = *step < 0 ? -1 : length;
} else {
if (!PyInt_Check(r->stop) && !PyLong_Check(r->step)) return -1;
*stop = PyInt_AsSsize_t(r->stop);
if (*stop < 0) *stop += length;
}
if (*stop > length) return -1;
if (*start >= length) return -1;
if (*step == 0) return -1;
return 0;
}
int
PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength)
{
/* this is harder to get right than you might think */
Py_ssize_t defstart, defstop;
if (r->step == Py_None) {
*step = 1;
}
else {
if (!_PyEval_SliceIndex(r->step, step)) return -1;
if (*step == 0) {
PyErr_SetString(PyExc_ValueError,
"slice step cannot be zero");
return -1;
}
}
defstart = *step < 0 ? length-1 : 0;
defstop = *step < 0 ? -1 : length;
if (r->start == Py_None) {
*start = defstart;
}
else {
if (!_PyEval_SliceIndex(r->start, start)) return -1;
if (*start < 0) *start += length;
if (*start < 0) *start = (*step < 0) ? -1 : 0;
if (*start >= length)
*start = (*step < 0) ? length - 1 : length;
}
if (r->stop == Py_None) {
*stop = defstop;
}
else {
if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
if (*stop < 0) *stop += length;
if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
if (*stop >= length)
*stop = (*step < 0) ? length - 1 : length;
}
if ((*step < 0 && *stop >= *start)
|| (*step > 0 && *start >= *stop)) {
*slicelength = 0;
}
else if (*step < 0) {
*slicelength = (*stop-*start+1)/(*step)+1;
}
else {
*slicelength = (*stop-*start-1)/(*step)+1;
}
return 0;
}
static PyObject *
slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
PyObject *start, *stop, *step;
start = stop = step = NULL;
if (!_PyArg_NoKeywords("slice()", kw))
return NULL;
if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
return NULL;
/* This swapping of stop and start is to maintain similarity with
range(). */
if (stop == NULL) {
stop = start;
start = NULL;
}
return PySlice_New(start, stop, step);
}
PyDoc_STRVAR(slice_doc,
"slice(stop)\n\
slice(start, stop[, step])\n\
\n\
Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
static void
slice_dealloc(PySliceObject *r)
{
Py_DECREF(r->step);
Py_DECREF(r->start);
Py_DECREF(r->stop);
PyObject_Del(r);
}
static PyObject *
slice_repr(PySliceObject *r)
{
PyObject *s, *comma;
s = PyString_FromString("slice(");
comma = PyString_FromString(", ");
PyString_ConcatAndDel(&s, PyObject_Repr(r->start));
PyString_Concat(&s, comma);
PyString_ConcatAndDel(&s, PyObject_Repr(r->stop));
PyString_Concat(&s, comma);
PyString_ConcatAndDel(&s, PyObject_Repr(r->step));
PyString_ConcatAndDel(&s, PyString_FromString(")"));
Py_DECREF(comma);
return s;
}
static PyMemberDef slice_members[] = {
{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
{0}
};
static PyObject*
slice_indices(PySliceObject* self, PyObject* len)
{
Py_ssize_t ilen, start, stop, step, slicelength;
ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
if (ilen == -1 && PyErr_Occurred()) {
return NULL;
}
if (PySlice_GetIndicesEx(self, ilen, &start, &stop,
&step, &slicelength) < 0) {
return NULL;
}
return Py_BuildValue("(nnn)", start, stop, step);
}
PyDoc_STRVAR(slice_indices_doc,
"S.indices(len) -> (start, stop, stride)\n\
\n\
Assuming a sequence of length len, calculate the start and stop\n\
indices, and the stride length of the extended slice described by\n\
S. Out of bounds indices are clipped in a manner consistent with the\n\
handling of normal slices.");
static PyObject *
slice_reduce(PySliceObject* self)
{
return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
}
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
static PyMethodDef slice_methods[] = {
{"indices", (PyCFunction)slice_indices,
METH_O, slice_indices_doc},
{"__reduce__", (PyCFunction)slice_reduce,
METH_NOARGS, reduce_doc},
{NULL, NULL}
};
static int
slice_compare(PySliceObject *v, PySliceObject *w)
{
int result = 0;
if (v == w)
return 0;
if (PyObject_Cmp(v->start, w->start, &result) < 0)
return -2;
if (result != 0)
return result;
if (PyObject_Cmp(v->stop, w->stop, &result) < 0)
return -2;
if (result != 0)
return result;
if (PyObject_Cmp(v->step, w->step, &result) < 0)
return -2;
return result;
}
static long
slice_hash(PySliceObject *v)
{
PyErr_SetString(PyExc_TypeError, "unhashable type");
return -1L;
}
PyTypeObject PySlice_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"slice", /* Name of this type */
sizeof(PySliceObject), /* Basic object size */
0, /* Item size for varobject */
(destructor)slice_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)slice_compare, /* tp_compare */
(reprfunc)slice_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)slice_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
slice_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
slice_methods, /* tp_methods */
slice_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
slice_new, /* tp_new */
};
#endif
src/CMakeLists.txt
View file @
27410967
...
@@ -38,7 +38,7 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
...
@@ -38,7 +38,7 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
codegen/baseline_jit.cpp
codegen/baseline_jit.cpp
codegen/codegen.cpp
codegen/codegen.cpp
codegen/compvars.cpp
codegen/compvars.cpp
codegen/cpython_ast.cpp
codegen/cpython_ast.cpp
codegen/entry.cpp
codegen/entry.cpp
codegen/gcbuilder.cpp
codegen/gcbuilder.cpp
codegen/irgen.cpp
codegen/irgen.cpp
...
...
src/capi/abstract.cpp
View file @
27410967
...
@@ -27,318 +27,13 @@
...
@@ -27,318 +27,13 @@
#include "runtime/objmodel.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/types.h"
namespace
pyston
{
extern
"C"
int
recursive_issubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
noexcept
;
extern
"C"
int
check_class
(
PyObject
*
cls
,
const
char
*
error
)
noexcept
;
static
PyObject
*
type_error
(
const
char
*
msg
,
PyObject
*
obj
)
noexcept
{
extern
"C"
PyObject
*
abstract_get_bases
(
PyObject
*
cls
)
noexcept
;
PyErr_Format
(
PyExc_TypeError
,
msg
,
Py_TYPE
(
obj
)
->
tp_name
);
extern
"C"
PyObject
*
null_error
(
void
)
noexcept
;
return
NULL
;
extern
"C"
PyObject
*
objargs_mktuple
(
va_list
va
)
noexcept
;
}
static
PyObject
*
null_error
(
void
)
noexcept
{
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_SystemError
,
"null argument to internal routine"
);
return
NULL
;
}
extern
"C"
int
PyObject_Cmp
(
PyObject
*
o1
,
PyObject
*
o2
,
int
*
result
)
noexcept
{
int
r
;
if
(
o1
==
NULL
||
o2
==
NULL
)
{
null_error
();
return
-
1
;
}
r
=
PyObject_Compare
(
o1
,
o2
);
if
(
PyErr_Occurred
())
return
-
1
;
*
result
=
r
;
return
0
;
}
extern
"C"
PyObject
*
PyObject_Type
(
PyObject
*
o
)
noexcept
{
if
(
o
==
NULL
)
return
null_error
();
return
incref
(
o
->
cls
);
}
extern
"C"
Py_ssize_t
_PyObject_LengthHint
(
PyObject
*
o
,
Py_ssize_t
defaultvalue
)
noexcept
{
static
PyObject
*
hintstrobj
=
NULL
;
PyObject
*
ro
,
*
hintmeth
;
Py_ssize_t
rv
;
/* try o.__len__() */
rv
=
PyObject_Size
(
o
);
if
(
rv
>=
0
)
return
rv
;
if
(
PyErr_Occurred
())
{
if
(
!
PyErr_ExceptionMatches
(
PyExc_TypeError
)
&&
!
PyErr_ExceptionMatches
(
PyExc_AttributeError
))
return
-
1
;
PyErr_Clear
();
}
if
(
PyInstance_Check
(
o
))
return
defaultvalue
;
/* try o.__length_hint__() */
hintmeth
=
_PyObject_LookupSpecial
(
o
,
"__length_hint__"
,
&
hintstrobj
);
if
(
hintmeth
==
NULL
)
{
if
(
PyErr_Occurred
())
return
-
1
;
else
return
defaultvalue
;
}
ro
=
PyObject_CallFunctionObjArgs
(
hintmeth
,
NULL
);
Py_DECREF
(
hintmeth
);
if
(
ro
==
NULL
)
{
if
(
!
PyErr_ExceptionMatches
(
PyExc_TypeError
)
&&
!
PyErr_ExceptionMatches
(
PyExc_AttributeError
))
return
-
1
;
PyErr_Clear
();
return
defaultvalue
;
}
rv
=
PyNumber_Check
(
ro
)
?
PyInt_AsSsize_t
(
ro
)
:
defaultvalue
;
Py_DECREF
(
ro
);
return
rv
;
}
static
int
_IsFortranContiguous
(
Py_buffer
*
view
)
{
Py_ssize_t
sd
,
dim
;
int
i
;
if
(
view
->
ndim
==
0
)
return
1
;
if
(
view
->
strides
==
NULL
)
return
(
view
->
ndim
==
1
);
sd
=
view
->
itemsize
;
if
(
view
->
ndim
==
1
)
return
(
view
->
shape
[
0
]
==
1
||
sd
==
view
->
strides
[
0
]);
for
(
i
=
0
;
i
<
view
->
ndim
;
i
++
)
{
dim
=
view
->
shape
[
i
];
if
(
dim
==
0
)
return
1
;
if
(
view
->
strides
[
i
]
!=
sd
)
return
0
;
sd
*=
dim
;
}
return
1
;
}
static
int
_IsCContiguous
(
Py_buffer
*
view
)
{
Py_ssize_t
sd
,
dim
;
int
i
;
if
(
view
->
ndim
==
0
)
return
1
;
if
(
view
->
strides
==
NULL
)
return
1
;
sd
=
view
->
itemsize
;
if
(
view
->
ndim
==
1
)
return
(
view
->
shape
[
0
]
==
1
||
sd
==
view
->
strides
[
0
]);
for
(
i
=
view
->
ndim
-
1
;
i
>=
0
;
i
--
)
{
dim
=
view
->
shape
[
i
];
if
(
dim
==
0
)
return
1
;
if
(
view
->
strides
[
i
]
!=
sd
)
return
0
;
sd
*=
dim
;
}
return
1
;
}
extern
"C"
int
PyBuffer_IsContiguous
(
Py_buffer
*
view
,
char
fort
)
noexcept
{
if
(
view
->
suboffsets
!=
NULL
)
return
0
;
if
(
fort
==
'C'
)
return
_IsCContiguous
(
view
);
else
if
(
fort
==
'F'
)
return
_IsFortranContiguous
(
view
);
else
if
(
fort
==
'A'
)
return
(
_IsCContiguous
(
view
)
||
_IsFortranContiguous
(
view
));
return
0
;
}
/* view is not checked for consistency in either of these. It is
assumed that the size of the buffer is view->len in
view->len / view->itemsize elements.
*/
extern
"C"
int
PyBuffer_ToContiguous
(
void
*
buf
,
Py_buffer
*
view
,
Py_ssize_t
len
,
char
fort
)
noexcept
{
int
k
;
void
(
*
addone
)(
int
,
Py_ssize_t
*
,
const
Py_ssize_t
*
);
Py_ssize_t
*
indices
,
elements
;
char
*
dest
,
*
ptr
;
if
(
len
>
view
->
len
)
{
len
=
view
->
len
;
}
if
(
PyBuffer_IsContiguous
(
view
,
fort
))
{
/* simplest copy is all that is needed */
memcpy
(
buf
,
view
->
buf
,
len
);
return
0
;
}
/* Otherwise a more elaborate scheme is needed */
/* XXX(nnorwitz): need to check for overflow! */
indices
=
(
Py_ssize_t
*
)
PyMem_Malloc
(
sizeof
(
Py_ssize_t
)
*
(
view
->
ndim
));
if
(
indices
==
NULL
)
{
PyErr_NoMemory
();
return
-
1
;
}
for
(
k
=
0
;
k
<
view
->
ndim
;
k
++
)
{
indices
[
k
]
=
0
;
}
if
(
fort
==
'F'
)
{
addone
=
_Py_add_one_to_index_F
;
}
else
{
addone
=
_Py_add_one_to_index_C
;
}
dest
=
(
char
*
)
buf
;
/* XXX : This is not going to be the fastest code in the world
several optimizations are possible.
*/
elements
=
len
/
view
->
itemsize
;
while
(
elements
--
)
{
addone
(
view
->
ndim
,
indices
,
view
->
shape
);
ptr
=
(
char
*
)
PyBuffer_GetPointer
(
view
,
indices
);
memcpy
(
dest
,
ptr
,
view
->
itemsize
);
dest
+=
view
->
itemsize
;
}
PyMem_Free
(
indices
);
return
0
;
}
extern
"C"
int
PyBuffer_FillInfo
(
Py_buffer
*
view
,
PyObject
*
obj
,
void
*
buf
,
Py_ssize_t
len
,
int
readonly
,
int
flags
)
noexcept
{
if
(
view
==
NULL
)
return
0
;
if
(((
flags
&
PyBUF_WRITABLE
)
==
PyBUF_WRITABLE
)
&&
(
readonly
==
1
))
{
// https://docs.python.org/3/c-api/buffer.html#c.PyBuffer_FillInfo
// '[On failure], raise PyExc_BufferError, set view->obj to NULL and return -1'
view
->
obj
=
NULL
;
PyErr_SetString
(
PyExc_BufferError
,
"Object is not writable."
);
return
-
1
;
}
view
->
obj
=
obj
;
if
(
obj
)
Py_INCREF
(
obj
);
view
->
buf
=
buf
;
view
->
len
=
len
;
view
->
readonly
=
readonly
;
view
->
itemsize
=
1
;
view
->
format
=
NULL
;
if
((
flags
&
PyBUF_FORMAT
)
==
PyBUF_FORMAT
)
view
->
format
=
"B"
;
view
->
ndim
=
1
;
view
->
shape
=
NULL
;
if
((
flags
&
PyBUF_ND
)
==
PyBUF_ND
)
view
->
shape
=
&
(
view
->
len
);
view
->
strides
=
NULL
;
if
((
flags
&
PyBUF_STRIDES
)
==
PyBUF_STRIDES
)
view
->
strides
=
&
(
view
->
itemsize
);
view
->
suboffsets
=
NULL
;
view
->
internal
=
NULL
;
return
0
;
}
extern
"C"
void
PyBuffer_Release
(
Py_buffer
*
view
)
noexcept
{
if
(
!
view
->
buf
)
{
assert
(
!
view
->
obj
);
return
;
}
PyObject
*
obj
=
view
->
obj
;
if
(
obj
)
{
if
(
obj
&&
Py_TYPE
(
obj
)
->
tp_as_buffer
&&
Py_TYPE
(
obj
)
->
tp_as_buffer
->
bf_releasebuffer
)
Py_TYPE
(
obj
)
->
tp_as_buffer
->
bf_releasebuffer
(
obj
,
view
);
Py_XDECREF
(
obj
);
}
view
->
obj
=
NULL
;
}
static
PyObject
*
objargs_mktuple
(
va_list
va
)
noexcept
{
int
i
,
n
=
0
;
va_list
countva
;
PyObject
*
result
,
*
tmp
;
#ifdef VA_LIST_IS_ARRAY
memcpy
(
countva
,
va
,
sizeof
(
va_list
));
#else
#ifdef __va_copy
__va_copy
(
countva
,
va
);
#else
countva
=
va
;
#endif
#endif
while
(((
PyObject
*
)
va_arg
(
countva
,
PyObject
*
))
!=
NULL
)
++
n
;
result
=
PyTuple_New
(
n
);
if
(
result
!=
NULL
&&
n
>
0
)
{
for
(
i
=
0
;
i
<
n
;
++
i
)
{
tmp
=
(
PyObject
*
)
va_arg
(
va
,
PyObject
*
);
PyTuple_SET_ITEM
(
result
,
i
,
tmp
);
Py_INCREF
(
tmp
);
}
}
return
result
;
}
/* isinstance(), issubclass() */
/* abstract_get_bases() has logically 4 return states, with a sort of 0th
* state that will almost never happen.
*
* 0. creating the __bases__ static string could get a MemoryError
* 1. getattr(cls, '__bases__') could raise an AttributeError
* 2. getattr(cls, '__bases__') could raise some other exception
* 3. getattr(cls, '__bases__') could return a tuple
* 4. getattr(cls, '__bases__') could return something other than a tuple
*
* Only state #3 is a non-error state and only it returns a non-NULL object
* (it returns the retrieved tuple).
*
* Any raised AttributeErrors are masked by clearing the exception and
* returning NULL. If an object other than a tuple comes out of __bases__,
* then again, the return value is NULL. So yes, these two situations
* produce exactly the same results: NULL is returned and no error is set.
*
* If some exception other than AttributeError is raised, then NULL is also
* returned, but the exception is not cleared. That's because we want the
* exception to be propagated along.
*
* Callers are expected to test for PyErr_Occurred() when the return value
* is NULL to decide whether a valid exception should be propagated or not.
* When there's no exception to propagate, it's customary for the caller to
* set a TypeError.
*/
static
PyObject
*
abstract_get_bases
(
PyObject
*
cls
)
noexcept
{
PyObject
*
bases
;
static
PyObject
*
__bases__
=
NULL
;
if
(
__bases__
==
NULL
)
{
__bases__
=
getStaticString
(
"__bases__"
);
if
(
__bases__
==
NULL
)
return
NULL
;
}
bases
=
PyObject_GetAttr
(
cls
,
__bases__
);
if
(
bases
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_AttributeError
))
PyErr_Clear
();
return
NULL
;
}
if
(
!
PyTuple_Check
(
bases
))
{
Py_DECREF
(
bases
);
return
NULL
;
}
return
bases
;
}
namespace
pyston
{
static
int
abstract_issubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
noexcept
{
static
int
abstract_issubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
noexcept
{
PyObject
*
bases
=
NULL
;
PyObject
*
bases
=
NULL
;
...
@@ -375,19 +70,6 @@ static int abstract_issubclass(PyObject* derived, PyObject* cls) noexcept {
...
@@ -375,19 +70,6 @@ static int abstract_issubclass(PyObject* derived, PyObject* cls) noexcept {
}
}
}
}
static
int
check_class
(
PyObject
*
cls
,
const
char
*
error
)
noexcept
{
PyObject
*
bases
=
abstract_get_bases
(
cls
);
if
(
bases
==
NULL
)
{
/* Do not mask errors. */
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_TypeError
,
error
);
return
0
;
}
Py_DECREF
(
bases
);
return
-
1
;
}
static
int
recursive_isinstance
(
PyObject
*
inst
,
PyObject
*
cls
)
noexcept
{
static
int
recursive_isinstance
(
PyObject
*
inst
,
PyObject
*
cls
)
noexcept
{
PyObject
*
icls
;
PyObject
*
icls
;
int
retval
=
0
;
int
retval
=
0
;
...
@@ -445,10 +127,6 @@ static int recursive_isinstance(PyObject* inst, PyObject* cls) noexcept {
...
@@ -445,10 +127,6 @@ static int recursive_isinstance(PyObject* inst, PyObject* cls) noexcept {
return
retval
;
return
retval
;
}
}
extern
"C"
int
_PyObject_RealIsInstance
(
PyObject
*
inst
,
PyObject
*
cls
)
noexcept
{
return
recursive_isinstance
(
inst
,
cls
);
}
extern
"C"
int
PyObject_IsInstance
(
PyObject
*
inst
,
PyObject
*
cls
)
noexcept
{
extern
"C"
int
PyObject_IsInstance
(
PyObject
*
inst
,
PyObject
*
cls
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_pyobject_isinstance"
,
20
);
STAT_TIMER
(
t0
,
"us_timer_pyobject_isinstance"
,
20
);
...
@@ -507,140 +185,78 @@ extern "C" int PyObject_IsInstance(PyObject* inst, PyObject* cls) noexcept {
...
@@ -507,140 +185,78 @@ extern "C" int PyObject_IsInstance(PyObject* inst, PyObject* cls) noexcept {
return
recursive_isinstance
(
inst
,
cls
);
return
recursive_isinstance
(
inst
,
cls
);
}
}
extern
"C"
PyObject
*
PyObject_CallFunctionObjArgs
(
PyObject
*
callable
,
...)
noexcept
{
PyObject
*
args
,
*
tmp
;
va_list
vargs
;
if
(
callable
==
NULL
)
return
null_error
();
/* count the args */
va_start
(
vargs
,
callable
);
args
=
objargs_mktuple
(
vargs
);
va_end
(
vargs
);
if
(
args
==
NULL
)
return
NULL
;
tmp
=
PyObject_Call
(
callable
,
args
,
NULL
);
Py_DECREF
(
args
);
return
tmp
;
}
extern
"C"
PyObject
*
PyObject_CallObject
(
PyObject
*
obj
,
PyObject
*
args
)
noexcept
{
extern
"C"
int
PyObject_IsSubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
noexcept
{
return
PyEval_CallObjectWithKeywords
(
obj
,
args
,
NULL
);
static
PyObject
*
name
=
NULL
;
}
extern
"C"
int
PyObject_AsCharBuffer
(
PyObject
*
obj
,
const
char
**
buffer
,
Py_ssize_t
*
buffer_len
)
noexcept
{
if
(
PyTuple_Check
(
cls
))
{
PyBufferProcs
*
pb
;
Py_ssize_t
i
;
char
*
pp
;
Py_ssize_t
n
;
Py_ssize_t
len
;
int
r
=
0
;
if
(
obj
==
NULL
||
buffer
==
NULL
||
buffer_len
==
NULL
)
{
if
(
Py_EnterRecursiveCall
(
" in __subclasscheck__"
))
null_error
()
;
return
-
1
;
return
-
1
;
n
=
PyTuple_GET_SIZE
(
cls
)
;
}
for
(
i
=
0
;
i
<
n
;
++
i
)
{
pb
=
obj
->
cls
->
tp_as_buffer
;
PyObject
*
item
=
PyTuple_GET_ITEM
(
cls
,
i
)
;
if
(
pb
==
NULL
||
pb
->
bf_getcharbuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
)
{
r
=
PyObject_IsSubclass
(
derived
,
item
);
PyErr_SetString
(
PyExc_TypeError
,
"expected a character buffer object"
);
if
(
r
!=
0
)
return
-
1
;
/* either found it, or got an error */
}
break
;
if
((
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
{
}
Py
Err_SetString
(
PyExc_TypeError
,
"expected a single-segment buffer object"
);
Py
_LeaveRecursiveCall
(
);
return
-
1
;
return
r
;
}
}
len
=
(
*
pb
->
bf_getcharbuffer
)(
obj
,
0
,
&
pp
);
if
(
!
(
PyClass_Check
(
cls
)
||
PyInstance_Check
(
cls
)))
{
if
(
len
<
0
)
PyObject
*
checker
=
NULL
;
return
-
1
;
if
(
cls
->
cls
->
has_subclasscheck
)
{
*
buffer
=
pp
;
checker
=
_PyObject_LookupSpecial
(
cls
,
"__subclasscheck__"
,
&
name
);
*
buffer_len
=
len
;
if
(
!
checker
&&
PyErr_Occurred
())
return
0
;
return
-
1
;
}
extern
"C"
int
PyObject_CheckReadBuffer
(
PyObject
*
obj
)
noexcept
{
PyBufferProcs
*
pb
=
obj
->
cls
->
tp_as_buffer
;
if
(
pb
==
NULL
||
pb
->
bf_getreadbuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
||
(
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
return
0
;
return
1
;
}
extern
"C"
int
PyObject_AsReadBuffer
(
PyObject
*
obj
,
const
void
**
buffer
,
Py_ssize_t
*
buffer_len
)
noexcept
{
assert
(
checker
);
PyBufferProcs
*
pb
;
}
void
*
pp
;
Py_ssize_t
len
;
if
(
obj
==
NULL
||
buffer
==
NULL
||
buffer_len
==
NULL
)
{
if
(
checker
!=
NULL
)
{
null_error
();
PyObject
*
res
;
return
-
1
;
int
ok
=
-
1
;
}
if
(
Py_EnterRecursiveCall
(
" in __subclasscheck__"
))
{
pb
=
obj
->
cls
->
tp_as_buffer
;
Py_DECREF
(
checker
);
if
(
pb
==
NULL
||
pb
->
bf_getreadbuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
)
{
return
ok
;
PyErr_SetString
(
PyExc_TypeError
,
"expected a readable buffer object"
);
}
return
-
1
;
res
=
PyObject_CallFunctionObjArgs
(
checker
,
derived
,
NULL
);
}
Py_LeaveRecursiveCall
();
if
((
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
{
Py_DECREF
(
checker
);
PyErr_SetString
(
PyExc_TypeError
,
"expected a single-segment buffer object"
);
if
(
res
!=
NULL
)
{
return
-
1
;
ok
=
PyObject_IsTrue
(
res
);
Py_DECREF
(
res
);
}
return
ok
;
}
else
if
(
PyErr_Occurred
())
{
return
-
1
;
}
}
}
len
=
(
*
pb
->
bf_getreadbuffer
)(
obj
,
0
,
&
pp
);
return
recursive_issubclass
(
derived
,
cls
);
if
(
len
<
0
)
return
-
1
;
*
buffer
=
pp
;
*
buffer_len
=
len
;
return
0
;
}
}
extern
"C"
int
PyObject_AsWriteBuffer
(
PyObject
*
obj
,
void
**
buffer
,
Py_ssize_t
*
buffer_len
)
noexcept
{
extern
"C"
Py_ssize_t
PyObject_Size
(
PyObject
*
o
)
noexcept
{
PyBufferProcs
*
pb
;
BoxedInt
*
r
=
lenInternal
<
ExceptionStyle
::
CAPI
,
NOT_REWRITABLE
>
(
o
,
NULL
);
void
*
pp
;
if
(
!
r
)
Py_ssize_t
len
;
if
(
obj
==
NULL
||
buffer
==
NULL
||
buffer_len
==
NULL
)
{
null_error
();
return
-
1
;
}
pb
=
obj
->
cls
->
tp_as_buffer
;
if
(
pb
==
NULL
||
pb
->
bf_getwritebuffer
==
NULL
||
pb
->
bf_getsegcount
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a writeable buffer object"
);
return
-
1
;
}
if
((
*
pb
->
bf_getsegcount
)(
obj
,
NULL
)
!=
1
)
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a single-segment buffer object"
);
return
-
1
;
}
len
=
(
*
pb
->
bf_getwritebuffer
)(
obj
,
0
,
&
pp
);
if
(
len
<
0
)
return
-
1
;
return
-
1
;
*
buffer
=
pp
;
AUTO_DECREF
(
r
);
*
buffer_len
=
len
;
return
r
->
n
;
return
0
;
}
}
static
PyObject
*
call_function_tail
(
PyObject
*
callable
,
PyObject
*
args
)
{
extern
"C"
PyObject
*
PyObject_GetIter
(
PyObject
*
o
)
noexcept
{
PyObject
*
retval
;
try
{
return
getiter
(
o
);
if
(
args
==
NULL
)
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
return
NULL
;
if
(
!
PyTuple_Check
(
args
))
{
PyObject
*
a
;
a
=
PyTuple_New
(
1
);
if
(
a
==
NULL
)
{
Py_DECREF
(
args
);
return
NULL
;
}
PyTuple_SET_ITEM
(
a
,
0
,
args
);
args
=
a
;
}
}
retval
=
PyObject_Call
(
callable
,
args
,
NULL
);
Py_DECREF
(
args
);
return
retval
;
}
}
extern
"C"
PyObject
*
PyObject_CallMethod
(
PyObject
*
o
,
const
char
*
name
,
const
char
*
format
,
...)
noexcept
{
extern
"C"
PyObject
*
PyObject_CallMethod
(
PyObject
*
o
,
const
char
*
name
,
const
char
*
format
,
...)
noexcept
{
va_list
va
;
va_list
va
;
PyObject
*
args
=
NULL
;
PyObject
*
args
=
NULL
;
...
@@ -740,1672 +356,4 @@ extern "C" PyObject* _PyObject_CallMethod_SizeT(PyObject* o, const char* name, c
...
@@ -740,1672 +356,4 @@ extern "C" PyObject* _PyObject_CallMethod_SizeT(PyObject* o, const char* name, c
return
tmp
;
return
tmp
;
}
}
extern
"C"
Py_ssize_t
PyObject_Size
(
PyObject
*
o
)
noexcept
{
BoxedInt
*
r
=
lenInternal
<
ExceptionStyle
::
CAPI
,
NOT_REWRITABLE
>
(
o
,
NULL
);
if
(
!
r
)
return
-
1
;
AUTO_DECREF
(
r
);
return
r
->
n
;
}
extern
"C"
PyObject
*
PyObject_GetIter
(
PyObject
*
o
)
noexcept
{
try
{
return
getiter
(
o
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
static
int
recursive_issubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
noexcept
{
int
retval
;
if
(
PyType_Check
(
cls
)
&&
PyType_Check
(
derived
))
{
/* Fast path (non-recursive) */
return
PyType_IsSubtype
((
PyTypeObject
*
)
derived
,
(
PyTypeObject
*
)
cls
);
}
if
(
!
PyClass_Check
(
derived
)
||
!
PyClass_Check
(
cls
))
{
if
(
!
check_class
(
derived
,
"issubclass() arg 1 must be a class"
))
return
-
1
;
if
(
!
check_class
(
cls
,
"issubclass() arg 2 must be a class"
" or tuple of classes"
))
return
-
1
;
retval
=
abstract_issubclass
(
derived
,
cls
);
}
else
{
/* shortcut */
if
(
!
(
retval
=
(
derived
==
cls
)))
retval
=
PyClass_IsSubclass
(
derived
,
cls
);
}
return
retval
;
}
extern
"C"
int
_PyObject_RealIsSubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
noexcept
{
return
recursive_issubclass
(
derived
,
cls
);
}
extern
"C"
int
PyObject_IsSubclass
(
PyObject
*
derived
,
PyObject
*
cls
)
noexcept
{
static
PyObject
*
name
=
NULL
;
if
(
PyTuple_Check
(
cls
))
{
Py_ssize_t
i
;
Py_ssize_t
n
;
int
r
=
0
;
if
(
Py_EnterRecursiveCall
(
" in __subclasscheck__"
))
return
-
1
;
n
=
PyTuple_GET_SIZE
(
cls
);
for
(
i
=
0
;
i
<
n
;
++
i
)
{
PyObject
*
item
=
PyTuple_GET_ITEM
(
cls
,
i
);
r
=
PyObject_IsSubclass
(
derived
,
item
);
if
(
r
!=
0
)
/* either found it, or got an error */
break
;
}
Py_LeaveRecursiveCall
();
return
r
;
}
if
(
!
(
PyClass_Check
(
cls
)
||
PyInstance_Check
(
cls
)))
{
PyObject
*
checker
=
NULL
;
if
(
cls
->
cls
->
has_subclasscheck
)
{
checker
=
_PyObject_LookupSpecial
(
cls
,
"__subclasscheck__"
,
&
name
);
if
(
!
checker
&&
PyErr_Occurred
())
return
-
1
;
assert
(
checker
);
}
if
(
checker
!=
NULL
)
{
PyObject
*
res
;
int
ok
=
-
1
;
if
(
Py_EnterRecursiveCall
(
" in __subclasscheck__"
))
{
Py_DECREF
(
checker
);
return
ok
;
}
res
=
PyObject_CallFunctionObjArgs
(
checker
,
derived
,
NULL
);
Py_LeaveRecursiveCall
();
Py_DECREF
(
checker
);
if
(
res
!=
NULL
)
{
ok
=
PyObject_IsTrue
(
res
);
Py_DECREF
(
res
);
}
return
ok
;
}
else
if
(
PyErr_Occurred
())
{
return
-
1
;
}
}
return
recursive_issubclass
(
derived
,
cls
);
}
extern
"C"
PyObject
*
_PyObject_CallFunction_SizeT
(
PyObject
*
callable
,
const
char
*
format
,
...)
noexcept
{
va_list
va
;
PyObject
*
args
;
if
(
callable
==
NULL
)
return
null_error
();
if
(
format
&&
*
format
)
{
va_start
(
va
,
format
);
args
=
_Py_VaBuildValue_SizeT
(
format
,
va
);
va_end
(
va
);
}
else
args
=
PyTuple_New
(
0
);
return
call_function_tail
(
callable
,
args
);
}
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->cls, Py_TPFLAGS_CHECKTYPES)
#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]))
extern
"C"
int
PySequence_Check
(
PyObject
*
s
)
noexcept
{
if
(
s
==
NULL
)
return
0
;
if
(
PyInstance_Check
(
s
))
return
PyObject_HasAttrString
(
s
,
"__getitem__"
);
if
(
PyDict_Check
(
s
))
return
0
;
return
s
->
cls
->
tp_as_sequence
&&
s
->
cls
->
tp_as_sequence
->
sq_item
!=
NULL
;
}
extern
"C"
Py_ssize_t
PySequence_Size
(
PyObject
*
s
)
noexcept
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_length
)
return
m
->
sq_length
(
s
);
type_error
(
"object of type '%.200s' has no len()"
,
s
);
return
-
1
;
}
extern
"C"
PyObject
*
PySequence_Fast
(
PyObject
*
v
,
const
char
*
m
)
noexcept
{
PyObject
*
it
;
if
(
v
==
NULL
)
return
null_error
();
if
(
PyList_CheckExact
(
v
)
||
PyTuple_CheckExact
(
v
))
{
Py_INCREF
(
v
);
return
v
;
}
it
=
PyObject_GetIter
(
v
);
if
(
it
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_TypeError
))
PyErr_SetString
(
PyExc_TypeError
,
m
);
return
NULL
;
}
v
=
PySequence_List
(
it
);
Py_DECREF
(
it
);
return
v
;
}
extern
"C"
void
*
PyBuffer_GetPointer
(
Py_buffer
*
view
,
Py_ssize_t
*
indices
)
noexcept
{
char
*
pointer
;
int
i
;
pointer
=
(
char
*
)
view
->
buf
;
for
(
i
=
0
;
i
<
view
->
ndim
;
i
++
)
{
pointer
+=
view
->
strides
[
i
]
*
indices
[
i
];
if
((
view
->
suboffsets
!=
NULL
)
&&
(
view
->
suboffsets
[
i
]
>=
0
))
{
pointer
=
*
((
char
**
)
pointer
)
+
view
->
suboffsets
[
i
];
}
}
return
(
void
*
)
pointer
;
}
extern
"C"
void
_Py_add_one_to_index_F
(
int
nd
,
Py_ssize_t
*
index
,
const
Py_ssize_t
*
shape
)
noexcept
{
int
k
;
for
(
k
=
0
;
k
<
nd
;
k
++
)
{
if
(
index
[
k
]
<
shape
[
k
]
-
1
)
{
index
[
k
]
++
;
break
;
}
else
{
index
[
k
]
=
0
;
}
}
}
extern
"C"
void
_Py_add_one_to_index_C
(
int
nd
,
Py_ssize_t
*
index
,
const
Py_ssize_t
*
shape
)
noexcept
{
int
k
;
for
(
k
=
nd
-
1
;
k
>=
0
;
k
--
)
{
if
(
index
[
k
]
<
shape
[
k
]
-
1
)
{
index
[
k
]
++
;
break
;
}
else
{
index
[
k
]
=
0
;
}
}
}
extern
"C"
int
PyObject_CopyData
(
PyObject
*
dest
,
PyObject
*
src
)
noexcept
{
Py_buffer
view_dest
,
view_src
;
int
k
;
Py_ssize_t
*
indices
,
elements
;
char
*
dptr
,
*
sptr
;
if
(
!
PyObject_CheckBuffer
(
dest
)
||
!
PyObject_CheckBuffer
(
src
))
{
PyErr_SetString
(
PyExc_TypeError
,
"both destination and source must have the "
"buffer interface"
);
return
-
1
;
}
if
(
PyObject_GetBuffer
(
dest
,
&
view_dest
,
PyBUF_FULL
)
!=
0
)
return
-
1
;
if
(
PyObject_GetBuffer
(
src
,
&
view_src
,
PyBUF_FULL_RO
)
!=
0
)
{
PyBuffer_Release
(
&
view_dest
);
return
-
1
;
}
if
(
view_dest
.
len
<
view_src
.
len
)
{
PyErr_SetString
(
PyExc_BufferError
,
"destination is too small to receive data from source"
);
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
-
1
;
}
if
((
PyBuffer_IsContiguous
(
&
view_dest
,
'C'
)
&&
PyBuffer_IsContiguous
(
&
view_src
,
'C'
))
||
(
PyBuffer_IsContiguous
(
&
view_dest
,
'F'
)
&&
PyBuffer_IsContiguous
(
&
view_src
,
'F'
)))
{
/* simplest copy is all that is needed */
memcpy
(
view_dest
.
buf
,
view_src
.
buf
,
view_src
.
len
);
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
0
;
}
/* Otherwise a more elaborate copy scheme is needed */
/* XXX(nnorwitz): need to check for overflow! */
indices
=
(
Py_ssize_t
*
)
PyMem_Malloc
(
sizeof
(
Py_ssize_t
)
*
view_src
.
ndim
);
if
(
indices
==
NULL
)
{
PyErr_NoMemory
();
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
-
1
;
}
for
(
k
=
0
;
k
<
view_src
.
ndim
;
k
++
)
{
indices
[
k
]
=
0
;
}
elements
=
1
;
for
(
k
=
0
;
k
<
view_src
.
ndim
;
k
++
)
{
/* XXX(nnorwitz): can this overflow? */
elements
*=
view_src
.
shape
[
k
];
}
while
(
elements
--
)
{
_Py_add_one_to_index_C
(
view_src
.
ndim
,
indices
,
view_src
.
shape
);
dptr
=
(
char
*
)
PyBuffer_GetPointer
(
&
view_dest
,
indices
);
sptr
=
(
char
*
)
PyBuffer_GetPointer
(
&
view_src
,
indices
);
memcpy
(
dptr
,
sptr
,
view_src
.
itemsize
);
}
PyMem_Free
(
indices
);
PyBuffer_Release
(
&
view_dest
);
PyBuffer_Release
(
&
view_src
);
return
0
;
}
static
PyObject
*
binary_op1
(
PyObject
*
v
,
PyObject
*
w
,
const
int
op_slot
)
{
PyObject
*
x
;
binaryfunc
slotv
=
NULL
;
binaryfunc
slotw
=
NULL
;
if
(
v
->
cls
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
slotv
=
NB_BINOP
(
v
->
cls
->
tp_as_number
,
op_slot
);
if
(
w
->
cls
!=
v
->
cls
&&
w
->
cls
->
tp_as_number
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
slotw
=
NB_BINOP
(
w
->
cls
->
tp_as_number
,
op_slot
);
if
(
slotw
==
slotv
)
slotw
=
NULL
;
}
if
(
slotv
)
{
if
(
slotw
&&
PyType_IsSubtype
(
w
->
cls
,
v
->
cls
))
{
x
=
slotw
(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
slotw
=
NULL
;
}
x
=
slotv
(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
if
(
slotw
)
{
x
=
slotw
(
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
(
err
==
0
)
{
PyNumberMethods
*
mv
=
v
->
cls
->
tp_as_number
;
if
(
mv
)
{
binaryfunc
slot
;
slot
=
NB_BINOP
(
mv
,
op_slot
);
if
(
slot
)
{
x
=
slot
(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
x
;
}
}
/* CoerceEx incremented the reference counts */
Py_DECREF
(
v
);
Py_DECREF
(
w
);
}
}
Py_INCREF
(
Py_NotImplemented
);
return
Py_NotImplemented
;
}
static
PyObject
*
binop_type_error
(
PyObject
*
v
,
PyObject
*
w
,
const
char
*
op_name
)
{
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for %.100s: "
"'%.100s' and '%.100s'"
,
op_name
,
v
->
cls
->
tp_name
,
w
->
cls
->
tp_name
);
return
NULL
;
}
static
PyObject
*
binary_op
(
PyObject
*
v
,
PyObject
*
w
,
const
int
op_slot
,
const
char
*
op_name
)
{
PyObject
*
result
=
binary_op1
(
v
,
w
,
op_slot
);
if
(
result
==
Py_NotImplemented
)
{
Py_DECREF
(
result
);
return
binop_type_error
(
v
,
w
,
op_name
);
}
return
result
;
}
static
PyObject
*
binary_iop1
(
PyObject
*
v
,
PyObject
*
w
,
const
int
iop_slot
,
const
int
op_slot
)
{
PyNumberMethods
*
mv
=
v
->
cls
->
tp_as_number
;
if
(
mv
!=
NULL
&&
PyType_HasFeature
((
v
)
->
cls
,
Py_TPFLAGS_HAVE_INPLACEOPS
))
{
binaryfunc
slot
=
NB_BINOP
(
mv
,
iop_slot
);
if
(
slot
)
{
PyObject
*
x
=
(
slot
)(
v
,
w
);
if
(
x
!=
Py_NotImplemented
)
{
return
x
;
}
Py_DECREF
(
x
);
}
}
return
binary_op1
(
v
,
w
,
op_slot
);
}
static
PyObject
*
binary_iop
(
PyObject
*
v
,
PyObject
*
w
,
const
int
iop_slot
,
const
int
op_slot
,
const
char
*
op_name
)
{
PyObject
*
result
=
binary_iop1
(
v
,
w
,
iop_slot
,
op_slot
);
if
(
result
==
Py_NotImplemented
)
{
Py_DECREF
(
result
);
return
binop_type_error
(
v
,
w
,
op_name
);
}
return
result
;
}
/*
Calling scheme used for ternary operations:
*** In some cases, w.op is called before v.op; see binary_op1. ***
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)
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.
*/
static
PyObject
*
ternary_op
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
,
const
int
op_slot
,
const
char
*
op_name
)
noexcept
{
PyNumberMethods
*
mv
,
*
mw
,
*
mz
;
PyObject
*
x
=
NULL
;
ternaryfunc
slotv
=
NULL
;
ternaryfunc
slotw
=
NULL
;
ternaryfunc
slotz
=
NULL
;
mv
=
v
->
cls
->
tp_as_number
;
mw
=
w
->
cls
->
tp_as_number
;
if
(
mv
!=
NULL
&&
NEW_STYLE_NUMBER
(
v
))
slotv
=
NB_TERNOP
(
mv
,
op_slot
);
if
(
w
->
cls
!=
v
->
cls
&&
mw
!=
NULL
&&
NEW_STYLE_NUMBER
(
w
))
{
slotw
=
NB_TERNOP
(
mw
,
op_slot
);
if
(
slotw
==
slotv
)
slotw
=
NULL
;
}
if
(
slotv
)
{
if
(
slotw
&&
PyType_IsSubtype
(
w
->
cls
,
v
->
cls
))
{
x
=
slotw
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
slotw
=
NULL
;
}
x
=
slotv
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
if
(
slotw
)
{
x
=
slotw
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
mz
=
z
->
cls
->
tp_as_number
;
if
(
mz
!=
NULL
&&
NEW_STYLE_NUMBER
(
z
))
{
slotz
=
NB_TERNOP
(
mz
,
op_slot
);
if
(
slotz
==
slotv
||
slotz
==
slotw
)
slotz
=
NULL
;
if
(
slotz
)
{
x
=
slotz
(
v
,
w
,
z
);
if
(
x
!=
Py_NotImplemented
)
return
x
;
Py_DECREF
(
x
);
/* can't do it */
}
}
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
->
cls
->
tp_as_number
)
{
slotz
=
NB_TERNOP
(
v
->
cls
->
tp_as_number
,
op_slot
);
if
(
slotz
)
x
=
slotz
(
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
->
cls
->
tp_as_number
!=
NULL
)
{
slotv
=
NB_TERNOP
(
v1
->
cls
->
tp_as_number
,
op_slot
);
if
(
slotv
)
x
=
slotv
(
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
);
error3:
if
(
c
>=
0
)
return
x
;
}
if
(
z
==
Py_None
)
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for ** or pow(): "
"'%.100s' and '%.100s'"
,
v
->
cls
->
tp_name
,
w
->
cls
->
tp_name
);
else
PyErr_Format
(
PyExc_TypeError
,
"unsupported operand type(s) for pow(): "
"'%.100s', '%.100s', '%.100s'"
,
v
->
cls
->
tp_name
,
w
->
cls
->
tp_name
,
z
->
cls
->
tp_name
);
return
NULL
;
}
extern
"C"
PyObject
*
PySequence_Concat
(
PyObject
*
s
,
PyObject
*
o
)
noexcept
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
||
o
==
NULL
)
return
null_error
();
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_concat
)
return
m
->
sq_concat
(
s
,
o
);
/* Instances of user classes defining an __add__() method only
have an nb_add slot, not an sq_concat slot. So we fall back
to nb_add if both arguments appear to be sequences. */
if
(
PySequence_Check
(
s
)
&&
PySequence_Check
(
o
))
{
PyObject
*
result
=
binary_op1
(
s
,
o
,
NB_SLOT
(
nb_add
));
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be concatenated"
,
s
);
}
extern
"C"
PyObject
*
PySequence_List
(
PyObject
*
v
)
noexcept
{
PyObject
*
result
;
/* result list */
PyObject
*
rv
;
/* return value from PyList_Extend */
if
(
v
==
NULL
)
return
null_error
();
result
=
PyList_New
(
0
);
if
(
result
==
NULL
)
return
NULL
;
rv
=
_PyList_Extend
((
PyListObject
*
)
result
,
v
);
if
(
rv
==
NULL
)
{
Py_DECREF
(
result
);
return
NULL
;
}
Py_DECREF
(
rv
);
return
result
;
}
/* Iterate over seq. Result depends on the operation:
PY_ITERSEARCH_COUNT: -1 if error, else # of times obj appears in seq.
PY_ITERSEARCH_INDEX: 0-based index of first occurrence of obj in seq;
set ValueError and return -1 if none found; also return -1 on error.
Py_ITERSEARCH_CONTAINS: return 1 if obj in seq, else 0; -1 on error.
*/
extern
"C"
Py_ssize_t
_PySequence_IterSearch
(
PyObject
*
seq
,
PyObject
*
obj
,
int
operation
)
noexcept
{
Py_ssize_t
n
;
int
wrapped
;
/* for PY_ITERSEARCH_INDEX, true iff n wrapped around */
PyObject
*
it
;
/* iter(seq) */
if
(
seq
==
NULL
||
obj
==
NULL
)
{
null_error
();
return
-
1
;
}
it
=
PyObject_GetIter
(
seq
);
if
(
it
==
NULL
)
{
type_error
(
"argument of type '%.200s' is not iterable"
,
seq
);
return
-
1
;
}
n
=
wrapped
=
0
;
for
(;;)
{
int
cmp
;
PyObject
*
item
=
PyIter_Next
(
it
);
if
(
item
==
NULL
)
{
if
(
PyErr_Occurred
())
goto
Fail
;
break
;
}
cmp
=
PyObject_RichCompareBool
(
obj
,
item
,
Py_EQ
);
Py_DECREF
(
item
);
if
(
cmp
<
0
)
goto
Fail
;
if
(
cmp
>
0
)
{
switch
(
operation
)
{
case
PY_ITERSEARCH_COUNT
:
if
(
n
==
PY_SSIZE_T_MAX
)
{
PyErr_SetString
(
PyExc_OverflowError
,
"count exceeds C integer size"
);
goto
Fail
;
}
++
n
;
break
;
case
PY_ITERSEARCH_INDEX
:
if
(
wrapped
)
{
PyErr_SetString
(
PyExc_OverflowError
,
"index exceeds C integer size"
);
goto
Fail
;
}
goto
Done
;
case
PY_ITERSEARCH_CONTAINS
:
n
=
1
;
goto
Done
;
default:
assert
(
!
"unknown operation"
);
}
}
if
(
operation
==
PY_ITERSEARCH_INDEX
)
{
if
(
n
==
PY_SSIZE_T_MAX
)
wrapped
=
1
;
++
n
;
}
}
if
(
operation
!=
PY_ITERSEARCH_INDEX
)
goto
Done
;
PyErr_SetString
(
PyExc_ValueError
,
"sequence.index(x): x not in sequence"
);
/* fall into failure code */
Fail:
n
=
-
1
;
/* fall through */
Done:
Py_DECREF
(
it
);
return
n
;
}
extern
"C"
int
PySequence_Contains
(
PyObject
*
seq
,
PyObject
*
ob
)
noexcept
{
Py_ssize_t
result
;
if
(
PyType_HasFeature
(
seq
->
cls
,
Py_TPFLAGS_HAVE_SEQUENCE_IN
))
{
PySequenceMethods
*
sqm
=
seq
->
cls
->
tp_as_sequence
;
if
(
sqm
!=
NULL
&&
sqm
->
sq_contains
!=
NULL
)
return
(
*
sqm
->
sq_contains
)(
seq
,
ob
);
}
result
=
_PySequence_IterSearch
(
seq
,
ob
,
PY_ITERSEARCH_CONTAINS
);
return
Py_SAFE_DOWNCAST
(
result
,
Py_ssize_t
,
int
);
}
extern
"C"
PyObject
*
PySequence_Tuple
(
PyObject
*
v
)
noexcept
{
PyObject
*
it
;
/* iter(v) */
Py_ssize_t
n
;
/* guess for result tuple size */
PyObject
*
result
=
NULL
;
Py_ssize_t
j
;
if
(
v
==
NULL
)
return
null_error
();
/* Special-case the common tuple and list cases, for efficiency. */
if
(
PyTuple_CheckExact
(
v
))
{
/* Note that we can't know whether it's safe to return
a tuple *subclass* instance as-is, hence the restriction
to exact tuples here. In contrast, lists always make
a copy, so there's no need for exactness below. */
Py_INCREF
(
v
);
return
v
;
}
if
(
PyList_Check
(
v
))
return
PyList_AsTuple
(
v
);
/* Get iterator. */
it
=
PyObject_GetIter
(
v
);
if
(
it
==
NULL
)
return
NULL
;
/* Guess result size and allocate space. */
n
=
_PyObject_LengthHint
(
v
,
10
);
if
(
n
==
-
1
)
goto
Fail
;
result
=
PyTuple_New
(
n
);
if
(
result
==
NULL
)
goto
Fail
;
/* Fill the tuple. */
for
(
j
=
0
;;
++
j
)
{
PyObject
*
item
=
PyIter_Next
(
it
);
if
(
item
==
NULL
)
{
if
(
PyErr_Occurred
())
goto
Fail
;
break
;
}
if
(
j
>=
n
)
{
Py_ssize_t
oldn
=
n
;
/* The over-allocation strategy can grow a bit faster
than for lists because unlike lists the
over-allocation isn't permanent -- we reclaim
the excess before the end of this routine.
So, grow by ten and then add 25%.
*/
n
+=
10
;
n
+=
n
>>
2
;
if
(
n
<
oldn
)
{
/* Check for overflow */
PyErr_NoMemory
();
Py_DECREF
(
item
);
goto
Fail
;
}
if
(
_PyTuple_Resize
(
&
result
,
n
)
!=
0
)
{
Py_DECREF
(
item
);
goto
Fail
;
}
}
PyTuple_SET_ITEM
(
result
,
j
,
item
);
}
/* Cut tuple back if guess was too large. */
if
(
j
<
n
&&
_PyTuple_Resize
(
&
result
,
j
)
!=
0
)
goto
Fail
;
Py_DECREF
(
it
);
return
result
;
Fail:
Py_XDECREF
(
result
);
Py_DECREF
(
it
);
return
NULL
;
}
extern
"C"
PyObject
*
PySequence_Repeat
(
PyObject
*
o
,
Py_ssize_t
count
)
noexcept
{
PySequenceMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_repeat
)
return
m
->
sq_repeat
(
o
,
count
);
/* Instances of user classes defining a __mul__() method only
have an nb_multiply slot, not an sq_repeat slot. so we fall back
to nb_multiply if o appears to be a sequence. */
if
(
PySequence_Check
(
o
))
{
PyObject
*
n
,
*
result
;
n
=
PyInt_FromSsize_t
(
count
);
if
(
n
==
NULL
)
return
NULL
;
result
=
binary_op1
(
o
,
n
,
NB_SLOT
(
nb_multiply
));
Py_DECREF
(
n
);
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be repeated"
,
o
);
}
extern
"C"
PyObject
*
PySequence_InPlaceConcat
(
PyObject
*
s
,
PyObject
*
o
)
noexcept
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
||
o
==
NULL
)
return
null_error
();
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
PyType_HasFeature
((
s
)
->
cls
,
Py_TPFLAGS_HAVE_INPLACEOPS
)
&&
m
->
sq_inplace_concat
)
return
m
->
sq_inplace_concat
(
s
,
o
);
if
(
m
&&
m
->
sq_concat
)
return
m
->
sq_concat
(
s
,
o
);
if
(
PySequence_Check
(
s
)
&&
PySequence_Check
(
o
))
{
PyObject
*
result
=
binary_iop1
(
s
,
o
,
NB_SLOT
(
nb_inplace_add
),
NB_SLOT
(
nb_add
));
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be concatenated"
,
s
);
}
extern
"C"
PyObject
*
PySequence_InPlaceRepeat
(
PyObject
*
o
,
Py_ssize_t
count
)
noexcept
{
PySequenceMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
cls
->
tp_as_sequence
;
if
(
m
&&
PyType_HasFeature
((
o
)
->
cls
,
Py_TPFLAGS_HAVE_INPLACEOPS
)
&&
m
->
sq_inplace_repeat
)
return
m
->
sq_inplace_repeat
(
o
,
count
);
if
(
m
&&
m
->
sq_repeat
)
return
m
->
sq_repeat
(
o
,
count
);
if
(
PySequence_Check
(
o
))
{
PyObject
*
n
,
*
result
;
n
=
PyInt_FromSsize_t
(
count
);
if
(
n
==
NULL
)
return
NULL
;
result
=
binary_iop1
(
o
,
n
,
NB_SLOT
(
nb_inplace_multiply
),
NB_SLOT
(
nb_multiply
));
Py_DECREF
(
n
);
if
(
result
!=
Py_NotImplemented
)
return
result
;
Py_DECREF
(
result
);
}
return
type_error
(
"'%.200s' object can't be repeated"
,
o
);
}
extern
"C"
PyObject
*
PySequence_GetItem
(
PyObject
*
s
,
Py_ssize_t
i
)
noexcept
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
return
null_error
();
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_item
)
{
if
(
i
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
NULL
;
i
+=
l
;
}
}
return
m
->
sq_item
(
s
,
i
);
}
return
type_error
(
"'%.200s' object does not support indexing"
,
s
);
}
PyObject
*
_PySlice_FromIndices
(
Py_ssize_t
istart
,
Py_ssize_t
istop
)
{
PyObject
*
start
,
*
end
,
*
slice
;
start
=
PyInt_FromSsize_t
(
istart
);
if
(
!
start
)
return
NULL
;
end
=
PyInt_FromSsize_t
(
istop
);
if
(
!
end
)
{
Py_DECREF
(
start
);
return
NULL
;
}
slice
=
PySlice_New
(
start
,
end
,
NULL
);
Py_DECREF
(
start
);
Py_DECREF
(
end
);
return
slice
;
}
extern
"C"
PyObject
*
PySequence_GetSlice
(
PyObject
*
s
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
noexcept
{
PySequenceMethods
*
m
;
PyMappingMethods
*
mp
;
if
(
!
s
)
return
null_error
();
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_slice
)
{
if
(
i1
<
0
||
i2
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
NULL
;
if
(
i1
<
0
)
i1
+=
l
;
if
(
i2
<
0
)
i2
+=
l
;
}
}
return
m
->
sq_slice
(
s
,
i1
,
i2
);
}
else
if
((
mp
=
s
->
cls
->
tp_as_mapping
)
&&
mp
->
mp_subscript
)
{
PyObject
*
res
;
PyObject
*
slice
=
_PySlice_FromIndices
(
i1
,
i2
);
if
(
!
slice
)
return
NULL
;
res
=
mp
->
mp_subscript
(
s
,
slice
);
Py_DECREF
(
slice
);
return
res
;
}
return
type_error
(
"'%.200s' object is unsliceable"
,
s
);
}
extern
"C"
int
PySequence_SetItem
(
PyObject
*
s
,
Py_ssize_t
i
,
PyObject
*
o
)
noexcept
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_item
)
{
if
(
i
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
-
1
;
i
+=
l
;
}
}
return
m
->
sq_ass_item
(
s
,
i
,
o
);
}
type_error
(
"'%.200s' object does not support item assignment"
,
s
);
return
-
1
;
}
extern
"C"
int
PySequence_DelItem
(
PyObject
*
s
,
Py_ssize_t
i
)
noexcept
{
PySequenceMethods
*
m
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_item
)
{
if
(
i
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
-
1
;
i
+=
l
;
}
}
return
m
->
sq_ass_item
(
s
,
i
,
(
PyObject
*
)
NULL
);
}
type_error
(
"'%.200s' object doesn't support item deletion"
,
s
);
return
-
1
;
}
extern
"C"
int
PySequence_SetSlice
(
PyObject
*
s
,
Py_ssize_t
i1
,
Py_ssize_t
i2
,
PyObject
*
o
)
noexcept
{
PySequenceMethods
*
m
;
PyMappingMethods
*
mp
;
if
(
s
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
s
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_slice
)
{
if
(
i1
<
0
||
i2
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
s
);
if
(
l
<
0
)
return
-
1
;
if
(
i1
<
0
)
i1
+=
l
;
if
(
i2
<
0
)
i2
+=
l
;
}
}
return
m
->
sq_ass_slice
(
s
,
i1
,
i2
,
o
);
}
else
if
((
mp
=
s
->
cls
->
tp_as_mapping
)
&&
mp
->
mp_ass_subscript
)
{
int
res
;
PyObject
*
slice
=
_PySlice_FromIndices
(
i1
,
i2
);
if
(
!
slice
)
return
-
1
;
res
=
mp
->
mp_ass_subscript
(
s
,
slice
,
o
);
Py_DECREF
(
slice
);
return
res
;
}
type_error
(
"'%.200s' object doesn't support slice assignment"
,
s
);
return
-
1
;
}
extern
"C"
int
PySequence_DelSlice
(
PyObject
*
o
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
noexcept
{
PySequenceMethods
*
m
;
if
(
o
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
o
->
cls
->
tp_as_sequence
;
if
(
m
&&
m
->
sq_ass_slice
)
{
if
(
i1
<
0
||
i2
<
0
)
{
if
(
m
->
sq_length
)
{
Py_ssize_t
l
=
(
*
m
->
sq_length
)(
o
);
if
(
l
<
0
)
return
-
1
;
if
(
i1
<
0
)
i1
+=
l
;
if
(
i2
<
0
)
i2
+=
l
;
}
}
return
m
->
sq_ass_slice
(
o
,
i1
,
i2
,
(
PyObject
*
)
NULL
);
}
type_error
(
"'%.200s' object doesn't support slice deletion"
,
o
);
return
-
1
;
}
extern
"C"
Py_ssize_t
PySequence_Count
(
PyObject
*
o
,
PyObject
*
value
)
noexcept
{
return
_PySequence_IterSearch
(
o
,
value
,
PY_ITERSEARCH_COUNT
);
}
extern
"C"
Py_ssize_t
PySequence_Index
(
PyObject
*
o
,
PyObject
*
value
)
noexcept
{
return
_PySequence_IterSearch
(
o
,
value
,
PY_ITERSEARCH_INDEX
);
}
extern
"C"
PyObject
*
PyObject_CallFunction
(
PyObject
*
callable
,
const
char
*
format
,
...)
noexcept
{
va_list
va
;
PyObject
*
args
;
if
(
callable
==
NULL
)
return
null_error
();
if
(
format
&&
*
format
)
{
va_start
(
va
,
format
);
args
=
Py_VaBuildValue
(
format
,
va
);
va_end
(
va
);
}
else
args
=
PyTuple_New
(
0
);
return
call_function_tail
(
callable
,
args
);
}
extern
"C"
int
PyMapping_Check
(
PyObject
*
o
)
noexcept
{
if
(
o
&&
PyInstance_Check
(
o
))
return
PyObject_HasAttrString
(
o
,
"__getitem__"
);
return
o
&&
o
->
cls
->
tp_as_mapping
&&
o
->
cls
->
tp_as_mapping
->
mp_subscript
&&
!
(
o
->
cls
->
tp_as_sequence
&&
o
->
cls
->
tp_as_sequence
->
sq_slice
);
}
extern
"C"
Py_ssize_t
PyMapping_Size
(
PyObject
*
o
)
noexcept
{
PyMappingMethods
*
m
;
if
(
o
==
NULL
)
{
null_error
();
return
-
1
;
}
m
=
o
->
cls
->
tp_as_mapping
;
if
(
m
&&
m
->
mp_length
)
return
m
->
mp_length
(
o
);
type_error
(
"object of type '%.200s' has no len()"
,
o
);
return
-
1
;
}
extern
"C"
int
PyMapping_HasKeyString
(
PyObject
*
o
,
char
*
key
)
noexcept
{
PyObject
*
v
;
v
=
PyMapping_GetItemString
(
o
,
key
);
if
(
v
)
{
Py_DECREF
(
v
);
return
1
;
}
PyErr_Clear
();
return
0
;
}
extern
"C"
int
PyMapping_HasKey
(
PyObject
*
o
,
PyObject
*
key
)
noexcept
{
PyObject
*
v
;
v
=
PyObject_GetItem
(
o
,
key
);
if
(
v
)
{
Py_DECREF
(
v
);
return
1
;
}
PyErr_Clear
();
return
0
;
}
extern
"C"
PyObject
*
PyMapping_GetItemString
(
PyObject
*
o
,
const
char
*
key
)
noexcept
{
PyObject
*
okey
,
*
r
;
if
(
key
==
NULL
)
return
null_error
();
okey
=
PyString_FromString
(
key
);
if
(
okey
==
NULL
)
return
NULL
;
r
=
PyObject_GetItem
(
o
,
okey
);
Py_DECREF
(
okey
);
return
r
;
}
extern
"C"
int
PyMapping_SetItemString
(
PyObject
*
o
,
const
char
*
key
,
PyObject
*
value
)
noexcept
{
PyObject
*
okey
;
int
r
;
if
(
key
==
NULL
)
{
null_error
();
return
-
1
;
}
okey
=
PyString_FromString
(
key
);
if
(
okey
==
NULL
)
return
-
1
;
r
=
PyObject_SetItem
(
o
,
okey
,
value
);
Py_DECREF
(
okey
);
return
r
;
}
extern
"C"
int
PyNumber_Check
(
PyObject
*
obj
)
noexcept
{
assert
(
obj
&&
obj
->
cls
);
// Our check, since we don't currently fill in tp_as_number:
if
(
PyInt_Check
(
obj
)
||
PyLong_Check
(
obj
)
||
PyFloat_Check
(
obj
)
||
PyComplex_Check
(
obj
))
return
true
;
// The CPython check:
return
obj
->
cls
->
tp_as_number
&&
(
obj
->
cls
->
tp_as_number
->
nb_int
||
obj
->
cls
->
tp_as_number
->
nb_float
);
}
extern
"C"
PyObject
*
PyNumber_Add
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
PyObject
*
result
=
binary_op1
(
v
,
w
,
NB_SLOT
(
nb_add
));
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
m
=
v
->
cls
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
m
&&
m
->
sq_concat
)
{
return
(
*
m
->
sq_concat
)(
v
,
w
);
}
result
=
binop_type_error
(
v
,
w
,
"+"
);
}
return
result
;
}
#define BINARY_FUNC(func, op, op_name) \
extern "C" PyObject* func(PyObject* v, PyObject* w) noexcept { 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_Divide
,
nb_divide
,
"/"
)
BINARY_FUNC
(
PyNumber_Divmod
,
nb_divmod
,
"divmod()"
)
static
PyObject
*
sequence_repeat
(
ssizeargfunc
repeatfunc
,
PyObject
*
seq
,
PyObject
*
n
)
noexcept
{
Py_ssize_t
count
;
if
(
PyIndex_Check
(
n
))
{
count
=
PyNumber_AsSsize_t
(
n
,
PyExc_OverflowError
);
if
(
count
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
}
else
{
return
type_error
(
"can't multiply sequence by "
"non-int of type '%.200s'"
,
n
);
}
return
(
*
repeatfunc
)(
seq
,
count
);
}
extern
"C"
PyObject
*
PyNumber_Multiply
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
PyObject
*
result
=
binary_op1
(
v
,
w
,
NB_SLOT
(
nb_multiply
));
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
mv
=
v
->
cls
->
tp_as_sequence
;
PySequenceMethods
*
mw
=
w
->
cls
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
mv
&&
mv
->
sq_repeat
)
{
return
sequence_repeat
(
mv
->
sq_repeat
,
v
,
w
);
}
else
if
(
mw
&&
mw
->
sq_repeat
)
{
return
sequence_repeat
(
mw
->
sq_repeat
,
w
,
v
);
}
result
=
binop_type_error
(
v
,
w
,
"*"
);
}
return
result
;
}
extern
"C"
PyObject
*
PyNumber_FloorDivide
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
/* XXX tp_flags test */
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_floor_divide
),
"//"
);
}
extern
"C"
PyObject
*
PyNumber_TrueDivide
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
/* XXX tp_flags test */
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_true_divide
),
"/"
);
}
extern
"C"
PyObject
*
PyNumber_Remainder
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_op
(
v
,
w
,
NB_SLOT
(
nb_remainder
),
"%"
);
}
extern
"C"
PyObject
*
PyNumber_Power
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
noexcept
{
return
ternary_op
(
v
,
w
,
z
,
NB_SLOT
(
nb_power
),
"** or pow()"
);
}
extern
"C"
PyObject
*
PyNumber_Negative
(
PyObject
*
o
)
noexcept
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
cls
->
tp_as_number
;
if
(
m
&&
m
->
nb_negative
)
return
(
*
m
->
nb_negative
)(
o
);
return
type_error
(
"bad operand type for unary -: '%.200s'"
,
o
);
}
extern
"C"
PyObject
*
PyNumber_Positive
(
PyObject
*
o
)
noexcept
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
cls
->
tp_as_number
;
if
(
m
&&
m
->
nb_positive
)
return
(
*
m
->
nb_positive
)(
o
);
return
type_error
(
"bad operand type for unary +: '%.200s'"
,
o
);
}
extern
"C"
PyObject
*
PyNumber_Absolute
(
PyObject
*
o
)
noexcept
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
cls
->
tp_as_number
;
if
(
m
&&
m
->
nb_absolute
)
return
m
->
nb_absolute
(
o
);
return
type_error
(
"bad operand type for abs(): '%.200s'"
,
o
);
}
extern
"C"
PyObject
*
PyNumber_Invert
(
PyObject
*
o
)
noexcept
{
PyNumberMethods
*
m
;
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
cls
->
tp_as_number
;
if
(
m
&&
m
->
nb_invert
)
return
(
*
m
->
nb_invert
)(
o
);
return
type_error
(
"bad operand type for unary ~: '%.200s'"
,
o
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceAdd
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
PyObject
*
result
=
binary_iop1
(
v
,
w
,
NB_SLOT
(
nb_inplace_add
),
NB_SLOT
(
nb_add
));
if
(
result
==
Py_NotImplemented
)
{
PySequenceMethods
*
m
=
v
->
cls
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
m
!=
NULL
)
{
binaryfunc
f
=
NULL
;
if
(
PyType_HasFeature
((
v
)
->
cls
,
Py_TPFLAGS_HAVE_INPLACEOPS
))
f
=
m
->
sq_inplace_concat
;
if
(
f
==
NULL
)
f
=
m
->
sq_concat
;
if
(
f
!=
NULL
)
return
(
*
f
)(
v
,
w
);
}
result
=
binop_type_error
(
v
,
w
,
"+="
);
}
return
result
;
}
extern
"C"
PyObject
*
PyNumber_InPlaceSubtract
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_subtract
),
NB_SLOT
(
nb_subtract
),
"-="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceMultiply
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
PyObject
*
result
=
binary_iop1
(
v
,
w
,
NB_SLOT
(
nb_inplace_multiply
),
NB_SLOT
(
nb_multiply
));
if
(
result
==
Py_NotImplemented
)
{
ssizeargfunc
f
=
NULL
;
PySequenceMethods
*
mv
=
v
->
cls
->
tp_as_sequence
;
PySequenceMethods
*
mw
=
w
->
cls
->
tp_as_sequence
;
Py_DECREF
(
result
);
if
(
mv
!=
NULL
)
{
if
(
PyType_HasFeature
((
v
)
->
cls
,
Py_TPFLAGS_HAVE_INPLACEOPS
))
f
=
mv
->
sq_inplace_repeat
;
if
(
f
==
NULL
)
f
=
mv
->
sq_repeat
;
if
(
f
!=
NULL
)
return
sequence_repeat
(
f
,
v
,
w
);
}
else
if
(
mw
!=
NULL
)
{
/* Note that the right hand operand should not be
* mutated in this case so sq_inplace_repeat is not
* used. */
if
(
mw
->
sq_repeat
)
return
sequence_repeat
(
mw
->
sq_repeat
,
w
,
v
);
}
result
=
binop_type_error
(
v
,
w
,
"*="
);
}
return
result
;
}
extern
"C"
PyObject
*
PyNumber_InPlaceDivide
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_divide
),
NB_SLOT
(
nb_divide
),
"/="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceFloorDivide
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_floor_divide
),
NB_SLOT
(
nb_floor_divide
),
"//="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceTrueDivide
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_true_divide
),
NB_SLOT
(
nb_true_divide
),
"/="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceRemainder
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_remainder
),
NB_SLOT
(
nb_remainder
),
"%="
);
}
extern
"C"
PyObject
*
PyNumber_InPlacePower
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
noexcept
{
if
(
PyType_HasFeature
((
v
)
->
cls
,
Py_TPFLAGS_HAVE_INPLACEOPS
)
&&
v
->
cls
->
tp_as_number
&&
v
->
cls
->
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
),
"**="
);
}
}
extern
"C"
PyObject
*
PyNumber_InPlaceLshift
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_lshift
),
NB_SLOT
(
nb_lshift
),
"<<="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceRshift
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_rshift
),
NB_SLOT
(
nb_rshift
),
">>="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceAnd
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_and
),
NB_SLOT
(
nb_and
),
"%="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceXor
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_xor
),
NB_SLOT
(
nb_xor
),
"^="
);
}
extern
"C"
PyObject
*
PyNumber_InPlaceOr
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
return
binary_iop
(
v
,
w
,
NB_SLOT
(
nb_inplace_or
),
NB_SLOT
(
nb_or
),
"|="
);
}
extern
"C"
int
PyNumber_Coerce
(
PyObject
**
pv
,
PyObject
**
pw
)
noexcept
{
int
err
=
PyNumber_CoerceEx
(
pv
,
pw
);
if
(
err
<=
0
)
return
err
;
PyErr_SetString
(
PyExc_TypeError
,
"number coercion failed"
);
return
-
1
;
}
extern
"C"
int
PyNumber_CoerceEx
(
PyObject
**
pv
,
PyObject
**
pw
)
noexcept
{
PyObject
*
v
=
*
pv
;
PyObject
*
w
=
*
pw
;
int
res
;
/* Shortcut only for old-style types */
if
(
v
->
cls
==
w
->
cls
&&
!
PyType_HasFeature
(
v
->
cls
,
Py_TPFLAGS_CHECKTYPES
))
{
Py_INCREF
(
v
);
Py_INCREF
(
w
);
return
0
;
}
if
(
v
->
cls
->
tp_as_number
&&
v
->
cls
->
tp_as_number
->
nb_coerce
)
{
res
=
(
*
v
->
cls
->
tp_as_number
->
nb_coerce
)(
pv
,
pw
);
if
(
res
<=
0
)
return
res
;
}
if
(
w
->
cls
->
tp_as_number
&&
w
->
cls
->
tp_as_number
->
nb_coerce
)
{
res
=
(
*
w
->
cls
->
tp_as_number
->
nb_coerce
)(
pw
,
pv
);
if
(
res
<=
0
)
return
res
;
}
return
1
;
}
extern
"C"
PyObject
*
_PyNumber_ConvertIntegralToInt
(
STOLEN
(
PyObject
*
)
integral
,
const
char
*
error_format
)
noexcept
{
const
char
*
type_name
;
static
PyObject
*
int_name
=
NULL
;
if
(
int_name
==
NULL
)
{
int_name
=
getStaticString
(
"__int__"
);
if
(
int_name
==
NULL
)
return
NULL
;
}
if
(
integral
&&
(
!
PyInt_Check
(
integral
)
&&
!
PyLong_Check
(
integral
)))
{
/* Don't go through tp_as_number->nb_int to avoid
hitting the classic class fallback to __trunc__. */
PyObject
*
int_func
=
PyObject_GetAttr
(
integral
,
int_name
);
if
(
int_func
==
NULL
)
{
PyErr_Clear
();
/* Raise a different error. */
goto
non_integral_error
;
}
Py_DECREF
(
integral
);
integral
=
PyEval_CallObject
(
int_func
,
NULL
);
Py_DECREF
(
int_func
);
if
(
integral
&&
(
!
PyInt_Check
(
integral
)
&&
!
PyLong_Check
(
integral
)))
{
goto
non_integral_error
;
}
}
return
integral
;
non_integral_error:
if
(
PyInstance_Check
(
integral
))
{
type_name
=
static_cast
<
BoxedInstance
*>
(
integral
)
->
inst_cls
->
name
->
data
();
}
else
{
type_name
=
integral
->
cls
->
tp_name
;
}
PyErr_Format
(
PyExc_TypeError
,
error_format
,
type_name
);
Py_DECREF
(
integral
);
return
NULL
;
}
/* Add a check for embedded NULL-bytes in the argument. */
static
PyObject
*
int_from_string
(
const
char
*
s
,
Py_ssize_t
len
)
noexcept
{
char
*
end
;
PyObject
*
x
;
x
=
PyInt_FromString
(
s
,
&
end
,
10
);
if
(
x
==
NULL
)
return
NULL
;
if
(
end
!=
s
+
len
)
{
PyErr_SetString
(
PyExc_ValueError
,
"null byte in argument for int()"
);
Py_DECREF
(
x
);
return
NULL
;
}
return
x
;
}
extern
"C"
PyObject
*
PyNumber_Int
(
PyObject
*
o
)
noexcept
{
PyNumberMethods
*
m
;
const
char
*
buffer
;
Py_ssize_t
buffer_len
;
if
(
o
==
NULL
)
{
PyErr_SetString
(
PyExc_SystemError
,
"null argument to internal routing"
);
return
NULL
;
}
if
(
PyInt_CheckExact
(
o
))
{
Py_INCREF
(
o
);
return
o
;
}
m
=
o
->
cls
->
tp_as_number
;
if
(
m
&&
m
->
nb_int
)
{
/* This should include subclasses of int */
/* Classic classes always take this branch. */
PyObject
*
res
=
m
->
nb_int
(
o
);
if
(
res
&&
(
!
PyInt_Check
(
res
)
&&
!
PyLong_Check
(
res
)))
{
PyErr_Format
(
PyExc_TypeError
,
"__int__ returned non-int (type %.200s)"
,
res
->
cls
->
tp_name
);
Py_DECREF
(
res
);
return
NULL
;
}
return
res
;
}
if
(
PyInt_Check
(
o
))
{
/* A int subclass without nb_int */
BoxedInt
*
io
=
(
BoxedInt
*
)
o
;
return
PyInt_FromLong
(
io
->
n
);
}
// Pyston change: this should be an optimization
// PyObject* trunc_func = PyObject_GetAttrString(o, "__trunc__");
static
BoxedString
*
trunc_str
=
getStaticString
(
"__trunc__"
);
PyObject
*
trunc_func
=
getattrInternal
<
ExceptionStyle
::
CAPI
>
(
o
,
trunc_str
);
if
(
trunc_func
)
{
PyObject
*
truncated
=
PyEval_CallObject
(
trunc_func
,
NULL
);
Py_DECREF
(
trunc_func
);
/* __trunc__ is specified to return an Integral type, but
int() needs to return an int. */
return
_PyNumber_ConvertIntegralToInt
(
truncated
,
"__trunc__ returned non-Integral (type %.200s)"
);
}
PyErr_Clear
();
/* It's not an error if o.__trunc__ doesn't exist. */
if
(
PyString_Check
(
o
))
return
int_from_string
(
PyString_AS_STRING
(
o
),
PyString_GET_SIZE
(
o
));
#ifdef Py_USING_UNICODE
if
(
PyUnicode_Check
(
o
))
return
PyInt_FromUnicode
(
PyUnicode_AS_UNICODE
(
o
),
PyUnicode_GET_SIZE
(
o
),
10
);
#endif
if
(
!
PyObject_AsCharBuffer
(
o
,
&
buffer
,
&
buffer_len
))
return
int_from_string
(
buffer
,
buffer_len
);
return
type_error
(
"int() argument must be a string or a "
"number, not '%.200s'"
,
o
);
}
/* Add a check for embedded NULL-bytes in the argument. */
static
PyObject
*
long_from_string
(
const
char
*
s
,
Py_ssize_t
len
)
noexcept
{
char
*
end
;
PyObject
*
x
;
x
=
PyLong_FromString
(
s
,
&
end
,
10
);
if
(
x
==
NULL
)
return
NULL
;
if
(
end
!=
s
+
len
)
{
PyErr_SetString
(
PyExc_ValueError
,
"null byte in argument for long()"
);
Py_DECREF
(
x
);
return
NULL
;
}
return
x
;
}
extern
"C"
PyObject
*
PyNumber_Long
(
PyObject
*
o
)
noexcept
{
PyNumberMethods
*
m
;
static
PyObject
*
trunc_name
=
NULL
;
PyObject
*
trunc_func
;
const
char
*
buffer
;
Py_ssize_t
buffer_len
;
if
(
trunc_name
==
NULL
)
{
trunc_name
=
getStaticString
(
"__trunc__"
);
if
(
trunc_name
==
NULL
)
return
NULL
;
}
if
(
o
==
NULL
)
return
null_error
();
m
=
o
->
cls
->
tp_as_number
;
if
(
m
&&
m
->
nb_long
)
{
/* This should include subclasses of long */
/* Classic classes always take this branch. */
PyObject
*
res
=
m
->
nb_long
(
o
);
if
(
res
==
NULL
)
return
NULL
;
if
(
PyInt_Check
(
res
))
{
long
value
=
PyInt_AS_LONG
(
res
);
Py_DECREF
(
res
);
return
PyLong_FromLong
(
value
);
}
else
if
(
!
PyLong_Check
(
res
))
{
PyErr_Format
(
PyExc_TypeError
,
"__long__ returned non-long (type %.200s)"
,
res
->
cls
->
tp_name
);
Py_DECREF
(
res
);
return
NULL
;
}
return
res
;
}
if
(
PyLong_Check
(
o
))
{
/* A long subclass without nb_long */
return
_PyLong_Copy
((
PyLongObject
*
)
o
);
}
trunc_func
=
PyObject_GetAttr
(
o
,
trunc_name
);
if
(
trunc_func
)
{
PyObject
*
truncated
=
PyEval_CallObject
(
trunc_func
,
NULL
);
PyObject
*
int_instance
;
Py_DECREF
(
trunc_func
);
/* __trunc__ is specified to return an Integral type,
but long() needs to return a long. */
int_instance
=
_PyNumber_ConvertIntegralToInt
(
truncated
,
"__trunc__ returned non-Integral (type %.200s)"
);
if
(
int_instance
&&
PyInt_Check
(
int_instance
))
{
/* Make sure that long() returns a long instance. */
long
value
=
PyInt_AS_LONG
(
int_instance
);
Py_DECREF
(
int_instance
);
return
PyLong_FromLong
(
value
);
}
return
int_instance
;
}
PyErr_Clear
();
/* It's not an error if o.__trunc__ doesn't exist. */
if
(
PyString_Check
(
o
))
/* need to do extra error checking that PyLong_FromString()
* doesn't do. In particular long('9.5') must raise an
* exception, not truncate the float.
*/
return
long_from_string
(
PyString_AS_STRING
(
o
),
PyString_GET_SIZE
(
o
));
#ifdef Py_USING_UNICODE
if
(
PyUnicode_Check
(
o
))
/* The above check is done in PyLong_FromUnicode(). */
return
PyLong_FromUnicode
(
PyUnicode_AS_UNICODE
(
o
),
PyUnicode_GET_SIZE
(
o
),
10
);
#endif
if
(
!
PyObject_AsCharBuffer
(
o
,
&
buffer
,
&
buffer_len
))
return
long_from_string
(
buffer
,
buffer_len
);
return
type_error
(
"long() argument must be a string or a "
"number, not '%.200s'"
,
o
);
}
extern
"C"
PyObject
*
PyNumber_Float
(
PyObject
*
o
)
noexcept
{
if
(
o
==
NULL
)
return
null_error
();
if
(
o
->
cls
==
float_cls
)
{
Py_INCREF
(
o
);
return
o
;
}
PyNumberMethods
*
m
;
m
=
o
->
cls
->
tp_as_number
;
if
(
m
&&
m
->
nb_float
)
{
/* This should include subclasses of float */
PyObject
*
res
=
m
->
nb_float
(
o
);
if
(
res
&&
!
PyFloat_Check
(
res
))
{
PyErr_Format
(
PyExc_TypeError
,
"__float__ returned non-float (type %.200s)"
,
res
->
cls
->
tp_name
);
Py_DECREF
(
res
);
return
NULL
;
}
return
res
;
}
if
(
PyInt_Check
(
o
))
return
boxFloat
(((
BoxedInt
*
)
o
)
->
n
);
else
if
(
PyLong_Check
(
o
))
{
double
result
=
PyLong_AsDouble
(
o
);
if
(
result
==
-
1.0
&&
PyErr_Occurred
())
return
NULL
;
return
boxFloat
(
result
);
}
return
PyFloat_FromString
(
o
,
NULL
);
}
extern
"C"
PyObject
*
PyNumber_Index
(
PyObject
*
o
)
noexcept
{
PyObject
*
result
=
NULL
;
if
(
o
==
NULL
)
return
null_error
();
if
(
PyInt_Check
(
o
)
||
PyLong_Check
(
o
))
{
Py_INCREF
(
o
);
return
o
;
}
if
(
PyIndex_Check
(
o
))
{
result
=
o
->
cls
->
tp_as_number
->
nb_index
(
o
);
if
(
result
&&
!
PyInt_Check
(
result
)
&&
!
PyLong_Check
(
result
))
{
PyErr_Format
(
PyExc_TypeError
,
"__index__ returned non-(int,long) "
"(type %.200s)"
,
result
->
cls
->
tp_name
);
Py_DECREF
(
result
);
return
NULL
;
}
}
else
{
PyErr_Format
(
PyExc_TypeError
,
"'%.200s' object cannot be interpreted "
"as an index"
,
o
->
cls
->
tp_name
);
}
return
result
;
}
extern
"C"
PyObject
*
PyNumber_ToBase
(
PyObject
*
n
,
int
base
)
noexcept
{
PyObject
*
res
=
NULL
;
PyObject
*
index
=
PyNumber_Index
(
n
);
if
(
!
index
)
return
NULL
;
if
(
PyLong_Check
(
index
))
res
=
_PyLong_Format
(
index
,
base
,
0
,
1
);
else
if
(
PyInt_Check
(
index
))
res
=
_PyInt_Format
((
PyIntObject
*
)
index
,
base
,
1
);
else
/* It should not be possible to get here, as
PyNumber_Index already has a check for the same
condition */
PyErr_SetString
(
PyExc_ValueError
,
"PyNumber_ToBase: index not int or long"
);
Py_DECREF
(
index
);
return
res
;
}
extern
"C"
Py_ssize_t
PyNumber_AsSsize_t
(
PyObject
*
item
,
PyObject
*
err
)
noexcept
{
Py_ssize_t
result
;
PyObject
*
runerr
;
PyObject
*
value
=
PyNumber_Index
(
item
);
if
(
value
==
NULL
)
return
-
1
;
/* We're done if PyInt_AsSsize_t() returns without error. */
result
=
PyInt_AsSsize_t
(
value
);
if
(
result
!=
-
1
||
!
(
runerr
=
PyErr_Occurred
()))
goto
finish
;
/* Error handling code -- only manage OverflowError differently */
if
(
!
PyErr_GivenExceptionMatches
(
runerr
,
PyExc_OverflowError
))
goto
finish
;
PyErr_Clear
();
/* If no error-handling desired then the default clipping
is sufficient.
*/
if
(
!
err
)
{
assert
(
PyLong_Check
(
value
));
/* Whether or not it is less than or equal to
zero is determined by the sign of ob_size
*/
if
(
_PyLong_Sign
(
value
)
<
0
)
result
=
PY_SSIZE_T_MIN
;
else
result
=
PY_SSIZE_T_MAX
;
}
else
{
/* Otherwise replace the error with caller's error object. */
PyErr_Format
(
err
,
"cannot fit '%.200s' into an index-sized integer"
,
item
->
cls
->
tp_name
);
}
finish:
Py_DECREF
(
value
);
return
result
;
}
}
}
src/runtime/capi.cpp
View file @
27410967
...
@@ -1906,6 +1906,38 @@ extern "C" int PyCFunction_ClearFreeList() noexcept {
...
@@ -1906,6 +1906,38 @@ extern "C" int PyCFunction_ClearFreeList() noexcept {
return
0
;
// number of entries cleared
return
0
;
// number of entries cleared
}
}
extern
"C"
int
PyNumber_Coerce
(
PyObject
**
pv
,
PyObject
**
pw
)
noexcept
{
int
err
=
PyNumber_CoerceEx
(
pv
,
pw
);
if
(
err
<=
0
)
return
err
;
PyErr_SetString
(
PyExc_TypeError
,
"number coercion failed"
);
return
-
1
;
}
extern
"C"
int
PyNumber_CoerceEx
(
PyObject
**
pv
,
PyObject
**
pw
)
noexcept
{
PyObject
*
v
=
*
pv
;
PyObject
*
w
=
*
pw
;
int
res
;
/* Shortcut only for old-style types */
if
(
v
->
cls
==
w
->
cls
&&
!
PyType_HasFeature
(
v
->
cls
,
Py_TPFLAGS_CHECKTYPES
))
{
Py_INCREF
(
v
);
Py_INCREF
(
w
);
return
0
;
}
if
(
v
->
cls
->
tp_as_number
&&
v
->
cls
->
tp_as_number
->
nb_coerce
)
{
res
=
(
*
v
->
cls
->
tp_as_number
->
nb_coerce
)(
pv
,
pw
);
if
(
res
<=
0
)
return
res
;
}
if
(
w
->
cls
->
tp_as_number
&&
w
->
cls
->
tp_as_number
->
nb_coerce
)
{
res
=
(
*
w
->
cls
->
tp_as_number
->
nb_coerce
)(
pw
,
pv
);
if
(
res
<=
0
)
return
res
;
}
return
1
;
}
void
setupCAPI
()
{
void
setupCAPI
()
{
capifunc_cls
->
giveAttr
(
capifunc_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
BoxedCApiFunction
::
__repr__
<
CXX
>
,
UNKNOWN
,
1
)));
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
BoxedCApiFunction
::
__repr__
<
CXX
>
,
UNKNOWN
,
1
)));
...
...
src/runtime/classobj.cpp
View file @
27410967
...
@@ -215,6 +215,12 @@ extern "C" PyObject* PyInstance_New(PyObject* klass, PyObject* arg, PyObject* kw
...
@@ -215,6 +215,12 @@ extern "C" PyObject* PyInstance_New(PyObject* klass, PyObject* arg, PyObject* kw
}
}
}
}
extern
"C"
BORROWED
(
PyObject
*
)
PyInstance_Class
(
PyObject
*
_inst
)
noexcept
{
RELEASE_ASSERT
(
PyInstance_Check
(
_inst
),
""
);
BoxedInstance
*
inst
=
(
BoxedInstance
*
)
_inst
;
return
inst
->
inst_cls
;
}
static
Box
*
classobjGetattribute
(
Box
*
_cls
,
Box
*
_attr
)
{
static
Box
*
classobjGetattribute
(
Box
*
_cls
,
Box
*
_attr
)
{
RELEASE_ASSERT
(
_cls
->
cls
==
classobj_cls
,
""
);
RELEASE_ASSERT
(
_cls
->
cls
==
classobj_cls
,
""
);
BoxedClassobj
*
cls
=
static_cast
<
BoxedClassobj
*>
(
_cls
);
BoxedClassobj
*
cls
=
static_cast
<
BoxedClassobj
*>
(
_cls
);
...
...
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