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
e95f4bef
Commit
e95f4bef
authored
May 26, 2015
by
Marius Wachtler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement __cmp__ alias tp_compare
parent
3ebd2551
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
242 additions
and
26 deletions
+242
-26
from_cpython/Objects/bufferobject.c
from_cpython/Objects/bufferobject.c
+1
-3
from_cpython/Objects/weakrefobject.c
from_cpython/Objects/weakrefobject.c
+2
-3
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+0
-2
src/core/ast.cpp
src/core/ast.cpp
+16
-7
src/core/ast.h
src/core/ast.h
+1
-0
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+135
-0
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+34
-0
test/test_extension/slots_test.c
test/test_extension/slots_test.c
+12
-1
test/tests/buffer_compare.py
test/tests/buffer_compare.py
+0
-10
test/tests/buffer_test.py
test/tests/buffer_test.py
+5
-0
test/tests/capi_slots.py
test/tests/capi_slots.py
+2
-0
test/tests/comparisons.py
test/tests/comparisons.py
+34
-0
No files found.
from_cpython/Objects/bufferobject.c
View file @
e95f4bef
...
...
@@ -848,9 +848,7 @@ PyTypeObject PyBuffer_Type = {
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
// Pyston change:
//(cmpfunc)buffer_compare, /* tp_compare */
NULL
,
/* tp_compare */
(
cmpfunc
)
buffer_compare
,
/* tp_compare */
(
reprfunc
)
buffer_repr
,
/* tp_repr */
0
,
/* tp_as_number */
&
buffer_as_sequence
,
/* tp_as_sequence */
...
...
from_cpython/Objects/weakrefobject.c
View file @
e95f4bef
...
...
@@ -699,8 +699,7 @@ _PyWeakref_ProxyType = {
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
// Pyston change:
0
,
//proxy_compare, /* tp_compare */
proxy_compare
,
/* tp_compare */
(
reprfunc
)
proxy_repr
,
/* tp_repr */
&
proxy_as_number
,
/* tp_as_number */
&
proxy_as_sequence
,
/* tp_as_sequence */
...
...
@@ -737,7 +736,7 @@ _PyWeakref_CallableProxyType = {
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
//
proxy_compare, /* tp_compare */
proxy_compare
,
/* tp_compare */
(
unaryfunc
)
proxy_repr
,
/* tp_repr */
&
proxy_as_number
,
/* tp_as_number */
&
proxy_as_sequence
,
/* tp_as_sequence */
...
...
src/capi/typeobject.cpp
View file @
e95f4bef
...
...
@@ -2934,8 +2934,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
gc
::
registerNonheapRootObject
(
cls
);
// unhandled fields:
RELEASE_ASSERT
(
cls
->
tp_compare
==
NULL
,
""
);
int
ALLOWABLE_FLAGS
=
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
|
Py_TPFLAGS_HAVE_GC
|
Py_TPFLAGS_CHECKTYPES
|
Py_TPFLAGS_HAVE_NEWBUFFER
;
ALLOWABLE_FLAGS
|=
Py_TPFLAGS_INT_SUBCLASS
|
Py_TPFLAGS_LONG_SUBCLASS
|
Py_TPFLAGS_LIST_SUBCLASS
...
...
src/core/ast.cpp
View file @
e95f4bef
...
...
@@ -177,20 +177,29 @@ std::string getInplaceOpName(int op_type) {
// Maybe better name is "swapped" -- it's what the runtime will try if the normal op
// name fails, it will switch the order of the lhs/rhs and call the reverse op.
// Calling it "reverse" because that's what I'm assuming the 'r' stands for in ex __radd__
std
::
string
getReverseOpName
(
int
op_type
)
{
int
getReverseCmpOp
(
int
op_type
,
bool
&
success
)
{
success
=
true
;
if
(
op_type
==
AST_TYPE
::
Lt
)
return
getOpName
(
AST_TYPE
::
Gt
)
;
return
AST_TYPE
::
Gt
;
if
(
op_type
==
AST_TYPE
::
LtE
)
return
getOpName
(
AST_TYPE
::
GtE
)
;
return
AST_TYPE
::
GtE
;
if
(
op_type
==
AST_TYPE
::
Gt
)
return
getOpName
(
AST_TYPE
::
Lt
)
;
return
AST_TYPE
::
Lt
;
if
(
op_type
==
AST_TYPE
::
GtE
)
return
getOpName
(
AST_TYPE
::
LtE
)
;
return
AST_TYPE
::
LtE
;
if
(
op_type
==
AST_TYPE
::
NotEq
)
return
getOpName
(
AST_TYPE
::
NotEq
)
;
return
AST_TYPE
::
NotEq
;
if
(
op_type
==
AST_TYPE
::
Eq
)
return
getOpName
(
AST_TYPE
::
Eq
);
return
AST_TYPE
::
Eq
;
success
=
false
;
return
op_type
;
}
std
::
string
getReverseOpName
(
int
op_type
)
{
bool
reversed
=
false
;
op_type
=
getReverseCmpOp
(
op_type
,
reversed
);
if
(
reversed
)
return
getOpName
(
op_type
);
const
std
::
string
&
normal_name
=
getOpName
(
op_type
);
return
"__r"
+
normal_name
.
substr
(
2
);
}
...
...
src/core/ast.h
View file @
e95f4bef
...
...
@@ -1402,6 +1402,7 @@ template <class T, class R> void findNodes(const R& roots, std::vector<T*>& outp
llvm
::
StringRef
getOpSymbol
(
int
op_type
);
const
std
::
string
&
getOpName
(
int
op_type
);
int
getReverseCmpOp
(
int
op_type
,
bool
&
success
);
std
::
string
getReverseOpName
(
int
op_type
);
std
::
string
getInplaceOpName
(
int
op_type
);
std
::
string
getInplaceOpSymbol
(
int
op_type
);
...
...
src/runtime/classobj.cpp
View file @
e95f4bef
...
...
@@ -467,6 +467,140 @@ Box* instanceDelitem(Box* _inst, Box* key) {
return
runtimeCall
(
delitem_func
,
ArgPassSpec
(
1
),
key
,
NULL
,
NULL
,
NULL
,
NULL
);
}
/* Try a 3-way comparison, returning an int; v is an instance. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular 3-way comparison is not implemented or undefined.
*/
static
int
half_cmp
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
// static PyObject* cmp_obj;
PyObject
*
args
;
PyObject
*
cmp_func
;
PyObject
*
result
;
long
l
;
assert
(
PyInstance_Check
(
v
));
// Pyston change:
#if 0
if (cmp_obj == NULL) {
cmp_obj = PyString_InternFromString("__cmp__");
if (cmp_obj == NULL)
return -2;
}
cmp_func = PyObject_GetAttr(v, cmp_obj);
if (cmp_func == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return -2;
PyErr_Clear();
return 2;
}
#else
try
{
cmp_func
=
_instanceGetattribute
(
v
,
boxStrConstant
(
"__cmp__"
),
false
);
if
(
!
cmp_func
)
return
2
;
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
2
;
}
#endif
args
=
PyTuple_Pack
(
1
,
w
);
if
(
args
==
NULL
)
{
Py_DECREF
(
cmp_func
);
return
-
2
;
}
result
=
PyEval_CallObject
(
cmp_func
,
args
);
Py_DECREF
(
args
);
Py_DECREF
(
cmp_func
);
if
(
result
==
NULL
)
return
-
2
;
if
(
result
==
Py_NotImplemented
)
{
Py_DECREF
(
result
);
return
2
;
}
l
=
PyInt_AsLong
(
result
);
Py_DECREF
(
result
);
if
(
l
==
-
1
&&
PyErr_Occurred
())
{
PyErr_SetString
(
PyExc_TypeError
,
"comparison did not return an int"
);
return
-
2
;
}
return
l
<
0
?
-
1
:
l
>
0
?
1
:
0
;
}
/* Try a 3-way comparison, returning an int; either v or w is an instance.
We first try a coercion. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular 3-way comparison is not implemented or undefined.
*/
static
int
instance_compare
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
int
c
;
c
=
PyNumber_CoerceEx
(
&
v
,
&
w
);
if
(
c
<
0
)
return
-
2
;
if
(
c
==
0
)
{
/* If neither is now an instance, use regular comparison */
if
(
!
PyInstance_Check
(
v
)
&&
!
PyInstance_Check
(
w
))
{
c
=
PyObject_Compare
(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
PyErr_Occurred
())
return
-
2
;
return
c
<
0
?
-
1
:
c
>
0
?
1
:
0
;
}
}
else
{
/* The coercion didn't do anything.
Treat this the same as returning v and w unchanged. */
Py_INCREF
(
v
);
Py_INCREF
(
w
);
}
if
(
PyInstance_Check
(
v
))
{
c
=
half_cmp
(
v
,
w
);
if
(
c
<=
1
)
{
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
c
;
}
}
if
(
PyInstance_Check
(
w
))
{
c
=
half_cmp
(
w
,
v
);
if
(
c
<=
1
)
{
Py_DECREF
(
v
);
Py_DECREF
(
w
);
if
(
c
>=
-
1
)
c
=
-
c
;
return
c
;
}
}
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
2
;
}
Box
*
instanceCompare
(
Box
*
_inst
,
Box
*
other
)
{
int
rtn
=
instance_compare
(
_inst
,
other
);
if
(
rtn
==
2
)
return
NotImplemented
;
if
(
rtn
==
-
2
)
throwCAPIException
();
return
boxInt
(
rtn
);
}
Box
*
instanceContains
(
Box
*
_inst
,
Box
*
key
)
{
RELEASE_ASSERT
(
_inst
->
cls
==
instance_cls
,
""
);
BoxedInstance
*
inst
=
static_cast
<
BoxedInstance
*>
(
_inst
);
...
...
@@ -695,6 +829,7 @@ void setupClassobj() {
instance_cls
->
giveAttr
(
"__getitem__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
instanceGetitem
,
UNKNOWN
,
2
)));
instance_cls
->
giveAttr
(
"__setitem__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
instanceSetitem
,
UNKNOWN
,
3
)));
instance_cls
->
giveAttr
(
"__delitem__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
instanceDelitem
,
UNKNOWN
,
2
)));
instance_cls
->
giveAttr
(
"__cmp__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
instanceCompare
,
UNKNOWN
,
2
)));
instance_cls
->
giveAttr
(
"__contains__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
instanceContains
,
UNKNOWN
,
2
)));
instance_cls
->
giveAttr
(
"__hash__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
instanceHash
,
UNKNOWN
,
1
)));
instance_cls
->
giveAttr
(
"__iter__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
instanceIter
,
UNKNOWN
,
1
)));
...
...
src/runtime/objmodel.cpp
View file @
e95f4bef
...
...
@@ -3620,6 +3620,28 @@ extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type) {
return
rtn
;
}
static
bool
convert3wayCompareResultToBool
(
Box
*
v
,
int
op_type
)
{
long
result
=
PyInt_AsLong
(
v
);
if
(
result
==
-
1
&&
PyErr_Occurred
())
throwCAPIException
();
switch
(
op_type
)
{
case
AST_TYPE
:
:
Eq
:
return
result
==
0
;
case
AST_TYPE
:
:
NotEq
:
return
result
!=
0
;
case
AST_TYPE
:
:
Lt
:
return
result
<
0
;
case
AST_TYPE
:
:
Gt
:
return
result
>
0
;
case
AST_TYPE
:
:
LtE
:
return
result
<
0
||
result
==
0
;
case
AST_TYPE
:
:
GtE
:
return
result
>
0
||
result
==
0
;
default:
RELEASE_ASSERT
(
0
,
"op type %d not implemented"
,
op_type
);
};
}
Box
*
compareInternal
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
,
CompareRewriteArgs
*
rewrite_args
)
{
if
(
op_type
==
AST_TYPE
::
Is
||
op_type
==
AST_TYPE
::
IsNot
)
{
bool
neg
=
(
op_type
==
AST_TYPE
::
IsNot
);
...
...
@@ -3704,6 +3726,18 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
if
(
rrtn
!=
NULL
&&
rrtn
!=
NotImplemented
)
return
rrtn
;
std
::
string
cmp_name
=
"__cmp__"
;
lrtn
=
callattrInternal1
(
lhs
,
&
cmp_name
,
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
1
),
rhs
);
if
(
lrtn
&&
lrtn
!=
NotImplemented
)
{
return
boxBool
(
convert3wayCompareResultToBool
(
lrtn
,
op_type
));
}
rrtn
=
callattrInternal1
(
rhs
,
&
cmp_name
,
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
1
),
lhs
);
if
(
rrtn
&&
rrtn
!=
NotImplemented
)
{
bool
success
=
false
;
int
reversed_op
=
getReverseCmpOp
(
op_type
,
success
);
assert
(
success
);
return
boxBool
(
convert3wayCompareResultToBool
(
rrtn
,
reversed_op
));
}
if
(
op_type
==
AST_TYPE
::
Eq
)
return
boxBool
(
lhs
==
rhs
);
...
...
test/test_extension/slots_test.c
View file @
e95f4bef
...
...
@@ -391,6 +391,17 @@ CREATE_UN(s_hex, PyString_FromString("hex"));
#undef CREATE_BIN
static
int
slots_tester_compare
(
PyObject
*
x
,
PyObject
*
y
)
{
printf
(
"inside slots_tester_compare
\n
"
);
if
(
x
<
y
)
return
-
1
;
else
if
(
x
==
y
)
return
0
;
return
1
;
}
static
PyNumberMethods
slots_tester_as_number
=
{
(
binaryfunc
)
s_add
,
/* nb_add */
(
binaryfunc
)
s_subtract
,
/* nb_subtract */
...
...
@@ -442,7 +453,7 @@ static PyTypeObject slots_tester_num = {
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
slots_tester_compare
,
/* tp_compare */
0
,
/* tp_repr */
&
slots_tester_as_number
,
/* tp_as_number */
0
,
/* tp_as_sequence */
...
...
test/tests/buffer_compare.py
deleted
100644 → 0
View file @
3ebd2551
# expected: fail
# we don't support tp_compare yet
s
=
'Hello world'
t
=
buffer
(
s
,
6
,
5
)
s2
=
"Goodbye world"
t2
=
buffer
(
s2
,
8
,
5
)
print
t
==
t2
test/tests/buffer_test.py
View file @
e95f4bef
s
=
'Hello world'
t
=
buffer
(
s
,
6
,
5
)
print
t
s2
=
"Goodbye world"
t2
=
buffer
(
s2
,
8
,
5
)
print
t2
print
t
==
t2
test/tests/capi_slots.py
View file @
e95f4bef
...
...
@@ -38,6 +38,8 @@ for i in xrange(3):
print
float
(
t
)
print
hex
(
t
)
print
oct
(
t
)
print
slots_test
.
SlotsTesterNum
(
0
)
==
slots_test
.
SlotsTesterNum
(
0
)
print
slots_test
.
SlotsTesterNum
(
0
)
==
slots_test
.
SlotsTesterNum
(
1
)
for
i
in
slots_test
.
SlotsTesterSeq
(
6
):
print
i
...
...
test/tests/comparisons.py
View file @
e95f4bef
...
...
@@ -59,6 +59,9 @@ class C(object):
def
__ge__
(
self
,
rhs
):
print
"ge"
return
False
def
__cmp__
(
self
,
rhs
):
print
"cmp"
assert
False
for
i
in
xrange
(
2
):
print
C
(
""
)
>
2
...
...
@@ -113,3 +116,34 @@ d = {}
for
i
in
xrange
(
20
):
d
[
NonboolEq
(
i
%
10
)]
=
i
print
len
(
d
),
sorted
(
d
.
values
())
class
C
(
object
):
def
__init__
(
self
,
n
):
self
.
n
=
n
def
__eq__
(
self
,
rhs
):
print
"eq"
if
isinstance
(
rhs
,
C
):
return
self
.
n
==
rhs
.
n
return
self
.
n
==
int
(
rhs
)
def
__cmp__
(
self
,
rhs
):
print
"cmp"
v
=
0
if
isinstance
(
rhs
,
C
):
v
=
rhs
.
n
else
:
v
=
int
(
rhs
)
if
self
.
n
<
v
:
return
-
2L
elif
self
.
n
>
v
:
return
2L
return
0L
for
lhs
in
(
C
(
0
),
C
(
1
),
0
,
1
):
for
rhs
in
(
C
(
0
),
C
(
1
),
0
,
1
):
print
lhs
<
rhs
,
lhs
==
rhs
,
lhs
!=
rhs
,
lhs
>
rhs
,
lhs
<=
rhs
,
lhs
>=
rhs
del
C
.
__eq__
for
lhs
in
(
C
(
0
),
C
(
1
),
0
,
1
):
for
rhs
in
(
C
(
0
),
C
(
1
),
0
,
1
):
print
lhs
<
rhs
,
lhs
==
rhs
,
lhs
!=
rhs
,
lhs
>
rhs
,
lhs
<=
rhs
,
lhs
>=
rhs
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