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
6775ce65
Commit
6775ce65
authored
May 26, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #555 from undingen/dictproxy
Add __cmp__ and dictproxy
parents
a1aed5de
f677127a
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
548 additions
and
42 deletions
+548
-42
Makefile
Makefile
+1
-0
from_cpython/CMakeLists.txt
from_cpython/CMakeLists.txt
+1
-0
from_cpython/Include/descrobject.h
from_cpython/Include/descrobject.h
+2
-0
from_cpython/Objects/bufferobject.c
from_cpython/Objects/bufferobject.c
+1
-3
from_cpython/Objects/dictproxy.c
from_cpython/Objects/dictproxy.c
+244
-0
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/dict.cpp
src/runtime/dict.cpp
+10
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+36
-2
src/runtime/types.cpp
src/runtime/types.cpp
+26
-3
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
test/tests/data_descriptors.py
test/tests/data_descriptors.py
+9
-10
test/tests/dict_setting.py
test/tests/dict_setting.py
+11
-0
No files found.
Makefile
View file @
6775ce65
...
...
@@ -390,6 +390,7 @@ STDOBJECT_SRCS := \
iterobject.c
\
bufferobject.c
\
cobject.c
\
dictproxy.c
\
$(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS
:=
\
...
...
from_cpython/CMakeLists.txt
View file @
6775ce65
...
...
@@ -78,6 +78,7 @@ file(GLOB_RECURSE STDOBJECT_SRCS Objects
bytes_methods.c
capsule.c
cobject.c
dictproxy.c
exceptions.c
floatobject.c
iterobject.c
...
...
from_cpython/Include/descrobject.h
View file @
6775ce65
...
...
@@ -80,6 +80,8 @@ PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type;
PyAPI_DATA(PyTypeObject) PyDictProxy_Type;
PyAPI_DATA(PyTypeObject) PyGetSetDescr_Type;
PyAPI_DATA(PyTypeObject) PyMemberDescr_Type;
#else
PyAPI_DATA
(
PyTypeObject
)
PyDictProxy_Type
;
#endif
// (Pyston TODO: add #defines to our names)
PyAPI_DATA
(
PyTypeObject
*
)
wrapperdescr_cls
;
...
...
from_cpython/Objects/bufferobject.c
View file @
6775ce65
...
...
@@ -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/dictproxy.c
0 → 100644
View file @
6775ce65
// This file is originally from CPython 2.7, with modifications for Pyston
// The code is normally part of descrobject.c
#include "Python.h"
/* --- Readonly proxy for dictionaries (actually any mapping) --- */
/* This has no reason to be in this file except that adding new files is a
bit of a pain */
typedef
struct
{
PyObject_HEAD
PyObject
*
dict
;
}
proxyobject
;
static
Py_ssize_t
proxy_len
(
proxyobject
*
pp
)
{
return
PyObject_Size
(
pp
->
dict
);
}
static
PyObject
*
proxy_getitem
(
proxyobject
*
pp
,
PyObject
*
key
)
{
return
PyObject_GetItem
(
pp
->
dict
,
key
);
}
static
PyMappingMethods
proxy_as_mapping
=
{
(
lenfunc
)
proxy_len
,
/* mp_length */
(
binaryfunc
)
proxy_getitem
,
/* mp_subscript */
0
,
/* mp_ass_subscript */
};
static
int
proxy_contains
(
proxyobject
*
pp
,
PyObject
*
key
)
{
return
PyDict_Contains
(
pp
->
dict
,
key
);
}
static
PySequenceMethods
proxy_as_sequence
=
{
0
,
/* sq_length */
0
,
/* sq_concat */
0
,
/* sq_repeat */
0
,
/* sq_item */
0
,
/* sq_slice */
0
,
/* sq_ass_item */
0
,
/* sq_ass_slice */
(
objobjproc
)
proxy_contains
,
/* sq_contains */
0
,
/* sq_inplace_concat */
0
,
/* sq_inplace_repeat */
};
static
PyObject
*
proxy_has_key
(
proxyobject
*
pp
,
PyObject
*
key
)
{
int
res
=
PyDict_Contains
(
pp
->
dict
,
key
);
if
(
res
<
0
)
return
NULL
;
return
PyBool_FromLong
(
res
);
}
static
PyObject
*
proxy_get
(
proxyobject
*
pp
,
PyObject
*
args
)
{
PyObject
*
key
,
*
def
=
Py_None
;
if
(
!
PyArg_UnpackTuple
(
args
,
"get"
,
1
,
2
,
&
key
,
&
def
))
return
NULL
;
return
PyObject_CallMethod
(
pp
->
dict
,
"get"
,
"(OO)"
,
key
,
def
);
}
static
PyObject
*
proxy_keys
(
proxyobject
*
pp
)
{
return
PyMapping_Keys
(
pp
->
dict
);
}
static
PyObject
*
proxy_values
(
proxyobject
*
pp
)
{
return
PyMapping_Values
(
pp
->
dict
);
}
static
PyObject
*
proxy_items
(
proxyobject
*
pp
)
{
return
PyMapping_Items
(
pp
->
dict
);
}
static
PyObject
*
proxy_iterkeys
(
proxyobject
*
pp
)
{
return
PyObject_CallMethod
(
pp
->
dict
,
"iterkeys"
,
NULL
);
}
static
PyObject
*
proxy_itervalues
(
proxyobject
*
pp
)
{
return
PyObject_CallMethod
(
pp
->
dict
,
"itervalues"
,
NULL
);
}
static
PyObject
*
proxy_iteritems
(
proxyobject
*
pp
)
{
return
PyObject_CallMethod
(
pp
->
dict
,
"iteritems"
,
NULL
);
}
static
PyObject
*
proxy_copy
(
proxyobject
*
pp
)
{
return
PyObject_CallMethod
(
pp
->
dict
,
"copy"
,
NULL
);
}
static
PyMethodDef
proxy_methods
[]
=
{
{
"has_key"
,
(
PyCFunction
)
proxy_has_key
,
METH_O
,
PyDoc_STR
(
"D.has_key(k) -> True if D has a key k, else False"
)},
{
"get"
,
(
PyCFunction
)
proxy_get
,
METH_VARARGS
,
PyDoc_STR
(
"D.get(k[,d]) -> D[k] if D.has_key(k), else d."
" d defaults to None."
)},
{
"keys"
,
(
PyCFunction
)
proxy_keys
,
METH_NOARGS
,
PyDoc_STR
(
"D.keys() -> list of D's keys"
)},
{
"values"
,
(
PyCFunction
)
proxy_values
,
METH_NOARGS
,
PyDoc_STR
(
"D.values() -> list of D's values"
)},
{
"items"
,
(
PyCFunction
)
proxy_items
,
METH_NOARGS
,
PyDoc_STR
(
"D.items() -> list of D's (key, value) pairs, as 2-tuples"
)},
{
"iterkeys"
,
(
PyCFunction
)
proxy_iterkeys
,
METH_NOARGS
,
PyDoc_STR
(
"D.iterkeys() -> an iterator over the keys of D"
)},
{
"itervalues"
,(
PyCFunction
)
proxy_itervalues
,
METH_NOARGS
,
PyDoc_STR
(
"D.itervalues() -> an iterator over the values of D"
)},
{
"iteritems"
,
(
PyCFunction
)
proxy_iteritems
,
METH_NOARGS
,
PyDoc_STR
(
"D.iteritems() ->"
" an iterator over the (key, value) items of D"
)},
{
"copy"
,
(
PyCFunction
)
proxy_copy
,
METH_NOARGS
,
PyDoc_STR
(
"D.copy() -> a shallow copy of D"
)},
{
0
}
};
static
void
proxy_dealloc
(
proxyobject
*
pp
)
{
_PyObject_GC_UNTRACK
(
pp
);
Py_DECREF
(
pp
->
dict
);
PyObject_GC_Del
(
pp
);
}
static
PyObject
*
proxy_getiter
(
proxyobject
*
pp
)
{
return
PyObject_GetIter
(
pp
->
dict
);
}
static
PyObject
*
proxy_str
(
proxyobject
*
pp
)
{
return
PyObject_Str
(
pp
->
dict
);
}
static
PyObject
*
proxy_repr
(
proxyobject
*
pp
)
{
PyObject
*
dictrepr
;
PyObject
*
result
;
dictrepr
=
PyObject_Repr
(
pp
->
dict
);
if
(
dictrepr
==
NULL
)
return
NULL
;
result
=
PyString_FromFormat
(
"dict_proxy(%s)"
,
PyString_AS_STRING
(
dictrepr
));
Py_DECREF
(
dictrepr
);
return
result
;
}
static
int
proxy_traverse
(
PyObject
*
self
,
visitproc
visit
,
void
*
arg
)
{
proxyobject
*
pp
=
(
proxyobject
*
)
self
;
Py_VISIT
(
pp
->
dict
);
return
0
;
}
static
int
proxy_compare
(
proxyobject
*
v
,
PyObject
*
w
)
{
return
PyObject_Compare
(
v
->
dict
,
w
);
}
static
PyObject
*
proxy_richcompare
(
proxyobject
*
v
,
PyObject
*
w
,
int
op
)
{
return
PyObject_RichCompare
(
v
->
dict
,
w
,
op
);
}
PyTypeObject
PyDictProxy_Type
=
{
// Pyston change:
// PyVarObject_HEAD_INIT(&PyType_Type, 0)
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"dictproxy"
,
/* tp_name */
sizeof
(
proxyobject
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
(
destructor
)
proxy_dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
(
cmpfunc
)
proxy_compare
,
/* tp_compare */
(
reprfunc
)
proxy_repr
,
/* tp_repr */
0
,
/* tp_as_number */
&
proxy_as_sequence
,
/* tp_as_sequence */
&
proxy_as_mapping
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
(
reprfunc
)
proxy_str
,
/* tp_str */
PyObject_GenericGetAttr
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_HAVE_GC
,
/* tp_flags */
0
,
/* tp_doc */
proxy_traverse
,
/* tp_traverse */
0
,
/* tp_clear */
(
richcmpfunc
)
proxy_richcompare
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
(
getiterfunc
)
proxy_getiter
,
/* tp_iter */
0
,
/* tp_iternext */
proxy_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
};
PyObject
*
PyDictProxy_New
(
PyObject
*
dict
)
{
proxyobject
*
pp
;
pp
=
PyObject_GC_New
(
proxyobject
,
&
PyDictProxy_Type
);
if
(
pp
!=
NULL
)
{
Py_INCREF
(
dict
);
pp
->
dict
=
dict
;
_PyObject_GC_TRACK
(
pp
);
}
return
(
PyObject
*
)
pp
;
}
from_cpython/Objects/weakrefobject.c
View file @
6775ce65
...
...
@@ -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 @
6775ce65
...
...
@@ -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 @
6775ce65
...
...
@@ -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 @
6775ce65
...
...
@@ -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 @
6775ce65
...
...
@@ -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/dict.cpp
View file @
6775ce65
...
...
@@ -439,8 +439,17 @@ Box* dictContains(BoxedDict* self, Box* k) {
/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */
extern
"C"
int
PyDict_Contains
(
PyObject
*
op
,
PyObject
*
key
)
noexcept
{
BoxedDict
*
mp
=
(
BoxedDict
*
)
op
;
try
{
if
(
op
->
cls
==
attrwrapper_cls
)
{
Box
*
rtn
=
PyObject_CallMethod
(
op
,
"__contains__"
,
"O"
,
key
);
if
(
!
rtn
)
return
-
1
;
return
rtn
==
True
;
}
BoxedDict
*
mp
=
(
BoxedDict
*
)
op
;
assert
(
isSubclass
(
mp
->
cls
,
dict_cls
));
return
mp
->
getOrNull
(
key
)
?
1
:
0
;
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
...
...
src/runtime/objmodel.cpp
View file @
6775ce65
...
...
@@ -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
);
...
...
@@ -4357,8 +4391,8 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
base_heap_cls
->
nslots
()
*
sizeof
(
BoxedHeapClass
::
SlotOffset
));
}
if
(
!
made
->
getattr
(
"__dict__"
)
&&
(
made
->
instancesHaveHCAttrs
()
||
made
->
instancesHaveDictAttrs
()
))
made
->
giveAttr
(
"__dict__"
,
dict_descr
);
if
(
made
->
instancesHaveHCAttrs
()
||
made
->
instancesHaveDictAttrs
(
))
made
->
setattr
(
"__dict__"
,
dict_descr
,
NULL
);
for
(
const
auto
&
p
:
attr_dict
->
d
)
{
auto
k
=
coerceUnicodeToStr
(
p
.
first
);
...
...
src/runtime/types.cpp
View file @
6775ce65
...
...
@@ -495,6 +495,12 @@ extern "C" void typeGCHandler(GCVisitor* v, Box* b) {
}
static
Box
*
typeDict
(
Box
*
obj
,
void
*
context
)
{
if
(
obj
->
cls
->
instancesHaveHCAttrs
())
return
PyDictProxy_New
(
obj
->
getAttrWrapper
());
abort
();
}
static
Box
*
typeSubDict
(
Box
*
obj
,
void
*
context
)
{
if
(
obj
->
cls
->
instancesHaveHCAttrs
())
return
obj
->
getAttrWrapper
();
if
(
obj
->
cls
->
instancesHaveDictAttrs
())
...
...
@@ -502,7 +508,7 @@ static Box* typeDict(Box* obj, void* context) {
abort
();
}
static
void
typeSetDict
(
Box
*
obj
,
Box
*
val
,
void
*
context
)
{
static
void
typeS
ubS
etDict
(
Box
*
obj
,
Box
*
val
,
void
*
context
)
{
if
(
obj
->
cls
->
instancesHaveDictAttrs
())
{
RELEASE_ASSERT
(
val
->
cls
==
dict_cls
,
""
);
obj
->
setDict
(
static_cast
<
BoxedDict
*>
(
val
));
...
...
@@ -1635,6 +1641,20 @@ public:
return
new
AttrWrapperIter
(
self
);
}
static
Box
*
eq
(
Box
*
_self
,
Box
*
_other
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
// In order to not have to reimplement dict cmp: just create a real dict for now and us it.
BoxedDict
*
dict
=
(
BoxedDict
*
)
AttrWrapper
::
copy
(
_self
);
assert
(
dict
->
cls
==
dict_cls
);
const
std
::
string
eq_str
=
"__eq__"
;
return
callattrInternal
(
dict
,
&
eq_str
,
LookupScope
::
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
1
),
_other
,
NULL
,
NULL
,
NULL
,
NULL
);
}
static
Box
*
ne
(
Box
*
_self
,
Box
*
_other
)
{
return
eq
(
_self
,
_other
)
==
True
?
False
:
True
;
}
friend
class
AttrWrapperIter
;
};
...
...
@@ -2437,9 +2457,9 @@ void setupRuntime() {
str_cls
->
tp_flags
|=
Py_TPFLAGS_HAVE_NEWBUFFER
;
dict_descr
=
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
type
Dict
,
type
SetDict
,
NULL
);
dict_descr
=
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
type
SubDict
,
typeSub
SetDict
,
NULL
);
gc
::
registerPermanentRoot
(
dict_descr
);
type_cls
->
giveAttr
(
"__dict__"
,
dict_descr
);
type_cls
->
giveAttr
(
"__dict__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
typeDict
,
NULL
,
NULL
)
);
instancemethod_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
instancemethodGCHandler
,
0
,
...
...
@@ -2619,6 +2639,8 @@ void setupRuntime() {
attrwrapper_cls
->
giveAttr
(
"__str__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
str
,
UNKNOWN
,
1
)));
attrwrapper_cls
->
giveAttr
(
"__contains__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
contains
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"__eq__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
eq
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"__ne__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
ne
,
UNKNOWN
,
2
)));
attrwrapper_cls
->
giveAttr
(
"keys"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
keys
,
LIST
,
1
)));
attrwrapper_cls
->
giveAttr
(
"values"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
values
,
LIST
,
1
)));
attrwrapper_cls
->
giveAttr
(
"items"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
AttrWrapper
::
items
,
LIST
,
1
)));
...
...
@@ -2652,6 +2674,7 @@ void setupRuntime() {
PyCallIter_AddHasNext
();
PyType_Ready
(
&
PyCallIter_Type
);
PyType_Ready
(
&
PyCObject_Type
);
PyType_Ready
(
&
PyDictProxy_Type
);
initerrno
();
init_sha
();
...
...
test/test_extension/slots_test.c
View file @
6775ce65
...
...
@@ -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 @
a1aed5de
# 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 @
6775ce65
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 @
6775ce65
...
...
@@ -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 @
6775ce65
...
...
@@ -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
test/tests/data_descriptors.py
View file @
6775ce65
...
...
@@ -31,9 +31,8 @@ print 'C.dd is %s' % str(C.dd)
print
'C.ndd is %s'
%
str
(
C
.
ndd
)
C
.
dd
=
6
C
.
ndd
=
7
#TODO it would be nice to print these out (once __dict__ is implemented)
#print C.__dict__['dd']
#print C.__dict__['ndd']
print
C
.
__dict__
[
'dd'
]
print
C
.
__dict__
[
'ndd'
]
print
C
.
dd
print
C
.
ndd
...
...
@@ -62,8 +61,8 @@ print 'D.dd is %s' % str(D.dd)
print
'D.ndd is %s'
%
str
(
D
.
ndd
)
D
.
dd
=
6
D
.
ndd
=
7
#
print D.__dict__['dd']
#
print D.__dict__['ndd']
print
D
.
__dict__
[
'dd'
]
print
D
.
__dict__
[
'ndd'
]
class
DataDescriptor
(
object
):
def
__get__
(
self
,
obj
,
type
):
return
1
...
...
@@ -82,7 +81,7 @@ print d1.a
print
'D1.a is %s'
%
str
(
D1
.
a
)
D1
.
a
=
6
#
print D1.__dict__['a']
print
D1
.
__dict__
[
'a'
]
class
C2
(
object
):
a
=
4
...
...
@@ -93,7 +92,7 @@ print d2.a
print
'D2.a is %s'
%
str
(
D2
.
a
)
D2
.
a
=
6
#
print D2.__dict__['a']
print
D2
.
__dict__
[
'a'
]
class
C3
(
object
):
a
=
NonDataDescriptor
()
...
...
@@ -104,15 +103,15 @@ print d3.a
print
'D3.a is %s'
%
str
(
D3
.
a
)
D3
.
a
=
6
#
print D3.__dict__['a']
print
D3
.
__dict__
[
'a'
]
class
C4
(
object
):
a
=
6
class
D4
(
C4
):
a
=
NonDataDescriptor
()
d4
=
D4
()
#
print d4.a
print
d4
.
a
print
'D4.a is %s'
%
str
(
D4
.
a
)
D4
.
a
=
6
#
print D4.__dict__['a']
print
D4
.
__dict__
[
'a'
]
test/tests/dict_setting.py
View file @
6775ce65
...
...
@@ -49,3 +49,14 @@ d1.clear()
print
hasattr
(
c
,
"attr"
)
print
hasattr
(
c
,
"foo"
)
print
c
.
__dict__
is
d1
dictproxy
=
C
.
__dict__
print
type
(
dictproxy
)
print
"foo"
in
dictproxy
print
"foo"
in
dictproxy
.
keys
()
print
type
(
dictproxy
[
"foo"
])
print
dictproxy
==
dict
(
C
.
__dict__
)
try
:
dictproxy
[
"test"
]
=
"val"
except
Exception
as
e
:
print
e
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