Commit daa3f7f7 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents 0b29a562 89905c70
...@@ -574,8 +574,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -574,8 +574,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static const char *%s;' % Naming.filename_cname) code.putln('static const char *%s;' % Naming.filename_cname)
code.putln('static const char **%s;' % Naming.filetable_cname) code.putln('static const char **%s;' % Naming.filetable_cname)
env.use_utility_code(streq_utility_code)
# XXX this is a mess # XXX this is a mess
for utility_code in PyrexTypes.c_int_from_py_function.specialize_list: for utility_code in PyrexTypes.c_int_from_py_function.specialize_list:
env.use_utility_code(utility_code) env.use_utility_code(utility_code)
...@@ -1548,6 +1546,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1548,6 +1546,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname) code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname)
def generate_import_star(self, env, code): def generate_import_star(self, env, code):
env.use_utility_code(streq_utility_code)
code.putln() code.putln()
code.putln("char* %s_type_names[] = {" % Naming.import_star) code.putln("char* %s_type_names[] = {" % Naming.import_star)
for name, entry in env.entries.items(): for name, entry in env.entries.items():
......
...@@ -778,25 +778,18 @@ class CVarDefNode(StatNode): ...@@ -778,25 +778,18 @@ class CVarDefNode(StatNode):
self.dest_scope = dest_scope self.dest_scope = dest_scope
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
need_property = False # If the field is an external typedef, we cannot be sure about the type,
# so do conversion ourself rather than rely on the CPython mechanism (through
# a property; made in AnalyseDeclarationsTransform).
if (dest_scope.is_c_class_scope if (dest_scope.is_c_class_scope
and self.visibility == 'public' and self.visibility == 'public'
and base_type.is_pyobject and base_type.is_pyobject
and (base_type.is_builtin_type or base_type.is_extension_type)): and (base_type.is_builtin_type or base_type.is_extension_type)):
# If the field is settable and extension type, then the CPython mechanism does self.need_properties = []
# not do enough type-checking for us.
need_property = True
elif (base_type.is_typedef and base_type.typedef_is_external
and (self.visibility in ('public', 'readonly'))):
# If the field is an external typedef, we cannot be sure about the type,
# so do conversion ourself rather than rely on the CPython mechanism (through
# a property; made in AnalyseDeclarationsTransform).
need_property = True need_property = True
if need_property:
visibility = 'private' visibility = 'private'
self.need_properties = []
else: else:
need_property = False
visibility = self.visibility visibility = self.visibility
for declarator in self.declarators: for declarator in self.declarators:
...@@ -1188,6 +1181,11 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1188,6 +1181,11 @@ class FuncDefNode(StatNode, BlockNode):
code.put_finish_refcount_context() code.put_finish_refcount_context()
if self.entry.is_special and self.entry.name == "__hash__":
# Returning -1 for __hash__ is supposed to signal an error
# We do as Python instances and coerce -1 into -2.
code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (Naming.retval_cname, Naming.retval_cname))
if acquire_gil: if acquire_gil:
code.putln("PyGILState_Release(_save);") code.putln("PyGILState_Release(_save);")
......
...@@ -625,12 +625,6 @@ property NAME: ...@@ -625,12 +625,6 @@ property NAME:
ATTR = value ATTR = value
""", level='c_class') """, level='c_class')
readonly_property = TreeFragment(u"""
property NAME:
def __get__(self):
return ATTR
""", level='c_class')
def __call__(self, root): def __call__(self, root):
self.env_stack = [root.scope] self.env_stack = [root.scope]
# needed to determine if a cdef var is declared after it's used. # needed to determine if a cdef var is declared after it's used.
...@@ -707,7 +701,7 @@ property NAME: ...@@ -707,7 +701,7 @@ property NAME:
# mechanism for them. # mechanism for them.
stats = [] stats = []
for entry in node.need_properties: for entry in node.need_properties:
property = self.create_Property(entry, node.visibility == 'readonly') property = self.create_Property(entry)
property.analyse_declarations(node.dest_scope) property.analyse_declarations(node.dest_scope)
self.visit(property) self.visit(property)
stats.append(property) stats.append(property)
...@@ -715,11 +709,8 @@ property NAME: ...@@ -715,11 +709,8 @@ property NAME:
else: else:
return None return None
def create_Property(self, entry, readonly): def create_Property(self, entry):
if readonly: template = self.basic_property
template = self.readonly_property
else:
template = self.basic_property
property = template.substitute({ property = template.substitute({
u"ATTR": AttributeNode(pos=entry.pos, u"ATTR": AttributeNode(pos=entry.pos,
obj=NameNode(pos=entry.pos, name="self"), obj=NameNode(pos=entry.pos, name="self"),
......
...@@ -170,6 +170,19 @@ class CTypedefType(BaseType): ...@@ -170,6 +170,19 @@ class CTypedefType(BaseType):
self.typedef_cname = cname self.typedef_cname = cname
self.typedef_base_type = base_type self.typedef_base_type = base_type
self.typedef_is_external = is_external self.typedef_is_external = is_external
# Make typecodes in external typedefs use typesize-neutral macros
if is_external:
typecode = None
if base_type.is_int:
if base_type.signed == 0:
typecode = "__Pyx_T_UNSIGNED_INT"
else:
typecode = "__Pyx_T_SIGNED_INT"
elif base_type.is_float and not rank_to_type_name[base_type.rank] == "long double":
typecode = "__Pyx_T_FLOATING"
if typecode:
self.pymemberdef_typecode = "%s(%s)" % (typecode, cname)
def resolve(self): def resolve(self):
return self.typedef_base_type.resolve() return self.typedef_base_type.resolve()
...@@ -1744,6 +1757,40 @@ static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); ...@@ -1744,6 +1757,40 @@ static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
#endif #endif
#endif #endif
#if !defined(T_ULONGLONG)
#define __Pyx_T_UNSIGNED_INT(x) \\
((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : -1))))
#else
#define __Pyx_T_UNSIGNED_INT(x) \\
((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : \\
((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))))
#endif
#if !defined(T_LONGLONG)
#define __Pyx_T_SIGNED_INT(x) \\
((sizeof(x) == sizeof(char)) ? T_BYTE : \\
((sizeof(x) == sizeof(short)) ? T_SHORT : \\
((sizeof(x) == sizeof(int)) ? T_INT : \\
((sizeof(x) == sizeof(long)) ? T_LONG : -1))))
#else
#define __Pyx_T_SIGNED_INT(x) \\
((sizeof(x) == sizeof(char)) ? T_BYTE : \\
((sizeof(x) == sizeof(short)) ? T_SHORT : \\
((sizeof(x) == sizeof(int)) ? T_INT : \\
((sizeof(x) == sizeof(long)) ? T_LONG : \\
((sizeof(x) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1)))))
#endif
#define __Pyx_T_FLOATING(x) \\
((sizeof(x) == sizeof(float)) ? T_FLOAT : \\
((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1))
#if !defined(T_SIZET) #if !defined(T_SIZET)
#if !defined(T_ULONGLONG) #if !defined(T_ULONGLONG)
#define T_SIZET \\ #define T_SIZET \\
......
...@@ -1391,8 +1391,14 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/ ...@@ -1391,8 +1391,14 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
impl = """ impl = """
static PyObject* __Pyx_Method_ClassMethod(PyObject *method) { static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
/* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */ /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
/* if (!PyObject_TypeCheck(method, &PyMethodDescr_Type)) { */ static PyTypeObject *methoddescr_type = NULL;
if (__Pyx_StrEq(Py_TYPE(method)->tp_name, "method_descriptor")) { /* cdef classes */ if (methoddescr_type == NULL) {
PyObject *meth = __Pyx_GetAttrString((PyObject*)&PyList_Type, "append");
if (!meth) return NULL;
methoddescr_type = Py_TYPE(meth);
Py_DECREF(meth);
}
if (PyObject_TypeCheck(method, methoddescr_type)) { /* cdef classes */
PyMethodDescrObject *descr = (PyMethodDescrObject *)method; PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
return PyDescr_NewClassMethod(descr->d_type, descr->d_method); return PyDescr_NewClassMethod(descr->d_type, descr->d_method);
} }
......
cdef extern from "Python.h":
ctypedef struct PyObject
ctypedef struct Py_buffer:
void *buf
Py_ssize_t len
int readonly
char *format
int ndim
Py_ssize_t *shape
Py_ssize_t *strides
Py_ssize_t *suboffsets
Py_ssize_t itemsize
void *internal
int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) except -1
void PyObject_ReleaseBuffer(PyObject* obj, Py_buffer* view)
void PyErr_Format(int, char*, ...)
enum:
PyExc_TypeError
# int PyObject_GetBuffer(PyObject *obj, Py_buffer *view,
# int flags)
...@@ -28,5 +28,5 @@ cdef extern from *: ...@@ -28,5 +28,5 @@ cdef extern from *:
# 0xC (release candidate) # 0xC (release candidate)
# 0xF (final) # 0xF (final)
char[] PY_VERSION char PY_VERSION[]
char[] PY_PATCHLEVEL_REVISION char PY_PATCHLEVEL_REVISION[]
cimport python_bool
cimport python_buffer
cimport python_complex
cimport python_dict
cimport python_exc
cimport python_float
cimport python_function
cimport python_instance
cimport python_int
cimport python_iterator
cimport python_list
cimport python_long
cimport python_mapping
cimport python_mem
cimport python_method
cimport python_module
cimport python_number
cimport python_object
cimport python_parse
cimport python
cimport python_ref
cimport python_sequence
cimport python_set
cimport python_string
cimport python_tuple
cimport python_type
cimport python_unicode
cimport python_version
cimport stdio
cimport stdlib
typedef float FloatTypedef;
typedef double DoubleTypedef; typedef double DoubleTypedef;
typedef long double LongDoubleTypedef;
typedef char CharTypedef;
typedef short ShortTypedef;
typedef int IntTypedef;
typedef long LongTypedef;
#if defined(T_LONGLONG)
typedef PY_LONG_LONG LongLongTypedef;
#else
typedef long LongLongTypedef;
#endif
typedef unsigned char UCharTypedef;
typedef unsigned short UShortTypedef;
typedef unsigned int UIntTypedef;
typedef unsigned long ULongTypedef;
#if defined(T_LONGLONG)
typedef unsigned PY_LONG_LONG ULongLongTypedef;
#else
typedef unsigned long ULongLongTypedef;
#endif
__doc__ = u"""
>>> hash(A(5))
5
>>> hash(A(-1))
-2
>>> hash(A(-2))
-2
>>> hash(A(100))
Traceback (most recent call last):
...
TypeError: That's kind of a round number...
>>> __hash__(-1)
-1
"""
cdef class A:
cdef long a
def __init__(self, a):
self.a = a
def __hash__(self):
if self.a == 100:
raise TypeError, "That's kind of a round number..."
else:
return self.a
cpdef long __hash__(long x):
return x
""" """
>>> f() >>> f()
42.0 42.0 42.0 42.0
42.0
>>> global_vars(12.0)
12.0 12.0
>>> readonly() >>> readonly()
Traceback (most recent call last): Traceback (most recent call last):
... ...
AttributeError: attribute 'var_nf' of 'typedfieldbug_T303.MyClass' objects is not writable TypeError: readonly attribute
>>> longdouble_access()
Traceback (most recent call last):
...
SystemError: bad memberdescr type
""" """
cdef extern from "external_defs.h": cdef extern from "external_defs.h":
ctypedef float DoubleTypedef ctypedef float DoubleTypedef
ctypedef float LongDoubleTypedef
cdef public DoubleTypedef global_tdef
cdef public double global_double
cdef class MyClass: cdef class MyClass:
cdef readonly: cdef readonly:
double var_d double actual_double
DoubleTypedef var_nf DoubleTypedef float_isreally_double
cdef public: LongDoubleTypedef float_isreally_longdouble
DoubleTypedef var_mutable
def __init__(self): def __init__(self):
self.var_d = 42.0 self.actual_double = 42.0
self.var_nf = 42.0 self.float_isreally_double = 42.0
self.var_mutable = 1 self.float_isreally_longdouble = 42.0
def global_vars(x):
global global_tdef, global_double
global_tdef = x
global_double = x
print global_tdef, global_double
def f(): def f():
c = MyClass() c = MyClass()
c.var_mutable = 42.0 print c.actual_double
print c.var_d, c.var_nf, c.var_mutable print c.float_isreally_double
def longdouble_access():
c = MyClass()
print c.float_isreally_longdouble
def readonly(): def readonly():
c = MyClass() c = MyClass()
c.var_nf = 3 c.actual_double = 3
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment