Commit 16afe72d authored by Stefan Behnel's avatar Stefan Behnel

merge in latest cython-devel

parents 0e14b4b5 defbb401
...@@ -1586,8 +1586,6 @@ class IndexNode(ExprNode): ...@@ -1586,8 +1586,6 @@ class IndexNode(ExprNode):
if self.indices: if self.indices:
indices = self.indices indices = self.indices
else: else:
# On cloning, indices is cloned. Otherwise, unpack index into indices
assert not isinstance(self.index, CloneNode)
if isinstance(self.index, TupleNode): if isinstance(self.index, TupleNode):
indices = self.index.args indices = self.index.args
else: else:
...@@ -1600,6 +1598,9 @@ class IndexNode(ExprNode): ...@@ -1600,6 +1598,9 @@ class IndexNode(ExprNode):
if not x.type.is_int: if not x.type.is_int:
buffer_access = False buffer_access = False
# On cloning, indices is cloned. Otherwise, unpack index into indices
assert not (buffer_access and isinstance(self.index, CloneNode))
if buffer_access: if buffer_access:
self.indices = indices self.indices = indices
self.index = None self.index = None
......
...@@ -640,9 +640,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -640,9 +640,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type = entry.type type = entry.type
scope = type.scope scope = type.scope
if scope: if scope:
kind = type.kind
packed = type.is_struct and type.packed
if packed:
kind = "%s %s" % (type.kind, "__Pyx_PACKED")
code.globalstate.use_utility_code(packed_struct_utility_code)
header, footer = \ header, footer = \
self.sue_header_footer(type, type.kind, type.cname) self.sue_header_footer(type, kind, type.cname)
code.putln("") code.putln("")
if packed:
code.putln("#if !defined(__GNUC__)")
code.putln("#pragma pack(push, 1)")
code.putln("#endif")
code.putln(header) code.putln(header)
var_entries = scope.var_entries var_entries = scope.var_entries
if not var_entries: if not var_entries:
...@@ -654,6 +663,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -654,6 +663,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"%s;" % "%s;" %
attr.type.declaration_code(attr.cname)) attr.type.declaration_code(attr.cname))
code.putln(footer) code.putln(footer)
if packed:
code.putln("#if !defined(__GNUC__)")
code.putln("#pragma pack(pop)")
code.putln("#endif")
def generate_enum_definition(self, entry, code): def generate_enum_definition(self, entry, code):
code.mark_pos(entry.pos) code.mark_pos(entry.pos)
...@@ -2468,3 +2481,11 @@ int main(int argc, char** argv) { ...@@ -2468,3 +2481,11 @@ int main(int argc, char** argv) {
return r; return r;
} }
""") """)
packed_struct_utility_code = UtilityCode(proto="""
#if defined(__GNUC__)
#define __Pyx_PACKED __attribute__((__packed__))
#else
#define __Pyx_PACKED
#endif
""", impl="")
...@@ -816,16 +816,19 @@ class CStructOrUnionDefNode(StatNode): ...@@ -816,16 +816,19 @@ class CStructOrUnionDefNode(StatNode):
# in_pxd boolean # in_pxd boolean
# attributes [CVarDefNode] or None # attributes [CVarDefNode] or None
# entry Entry # entry Entry
# packed boolean
child_attrs = ["attributes"] child_attrs = ["attributes"]
def analyse_declarations(self, env): def analyse_declarations(self, env):
scope = None scope = None
if self.visibility == 'extern' and self.packed:
error(self.pos, "Cannot declare extern struct as 'packed'")
if self.attributes is not None: if self.attributes is not None:
scope = StructOrUnionScope(self.name) scope = StructOrUnionScope(self.name)
self.entry = env.declare_struct_or_union( self.entry = env.declare_struct_or_union(
self.name, self.kind, scope, self.typedef_flag, self.pos, self.name, self.kind, scope, self.typedef_flag, self.pos,
self.cname, visibility = self.visibility) self.cname, visibility = self.visibility, packed = self.packed)
if self.attributes is not None: if self.attributes is not None:
if self.in_pxd and not env.in_cinclude: if self.in_pxd and not env.in_cinclude:
self.entry.defined_in_pxd = 1 self.entry.defined_in_pxd = 1
...@@ -1644,9 +1647,11 @@ class DefNode(FuncDefNode): ...@@ -1644,9 +1647,11 @@ class DefNode(FuncDefNode):
def analyse_signature(self, env): def analyse_signature(self, env):
any_type_tests_needed = 0 any_type_tests_needed = 0
if self.entry.is_special:
self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
# Use the simpler calling signature for zero- and one-argument functions. # Use the simpler calling signature for zero- and one-argument functions.
if not self.entry.is_special and not self.star_arg and not self.starstar_arg: if self.entry.signature is TypeSlots.pyfunction_signature:
if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
if len(self.args) == 0: if len(self.args) == 0:
self.entry.signature = TypeSlots.pyfunction_noargs self.entry.signature = TypeSlots.pyfunction_noargs
elif len(self.args) == 1: elif len(self.args) == 1:
...@@ -1658,8 +1663,6 @@ class DefNode(FuncDefNode): ...@@ -1658,8 +1663,6 @@ class DefNode(FuncDefNode):
elif len(self.args) == 2: elif len(self.args) == 2:
if self.args[1].default is None and not self.args[1].kw_only: if self.args[1].default is None and not self.args[1].kw_only:
self.entry.signature = TypeSlots.ibinaryfunc self.entry.signature = TypeSlots.ibinaryfunc
elif self.entry.is_special:
self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
sig = self.entry.signature sig = self.entry.signature
nfixed = sig.num_fixed_args() nfixed = sig.num_fixed_args()
for i in range(nfixed): for i in range(nfixed):
......
...@@ -45,11 +45,6 @@ lookup_module_cpdef = 0 ...@@ -45,11 +45,6 @@ lookup_module_cpdef = 0
# WARNING: This is a work in progress, may currently segfault. # WARNING: This is a work in progress, may currently segfault.
init_local_none = 1 init_local_none = 1
# Optimize no argument and one argument methods by using the METH_O and METH_NOARGS
# calling conventions. These are faster calling conventions, but disallow the use of
# keywords (which, admittedly, are of little use in these cases).
optimize_simple_methods = 1
# Append the c file and line number to the traceback for exceptions. # Append the c file and line number to the traceback for exceptions.
c_line_in_traceback = 1 c_line_in_traceback = 1
...@@ -68,6 +63,7 @@ option_defaults = { ...@@ -68,6 +63,7 @@ option_defaults = {
'auto_cpdef': False, 'auto_cpdef': False,
'cdivision': True, # Will be False in 0.12 'cdivision': True, # Will be False in 0.12
'cdivision_warnings': False, 'cdivision_warnings': False,
'always_allow_keywords': False,
} }
# Override types possibilities above, if needed # Override types possibilities above, if needed
......
...@@ -2156,7 +2156,7 @@ def p_cdef_statement(s, ctx): ...@@ -2156,7 +2156,7 @@ def p_cdef_statement(s, ctx):
#if ctx.api: #if ctx.api:
# error(pos, "'api' not allowed with extension class") # error(pos, "'api' not allowed with extension class")
return p_c_class_definition(s, pos, ctx) return p_c_class_definition(s, pos, ctx)
elif s.sy == 'IDENT' and s.systring in struct_union_or_enum: elif s.sy == 'IDENT' and s.systring in ("struct", "union", "enum", "packed"):
if ctx.level not in ('module', 'module_pxd'): if ctx.level not in ('module', 'module_pxd'):
error(pos, "C struct/union/enum definition not allowed here") error(pos, "C struct/union/enum definition not allowed here")
#if ctx.visibility == 'public': #if ctx.visibility == 'public':
...@@ -2192,10 +2192,6 @@ def p_cdef_extern_block(s, pos, ctx): ...@@ -2192,10 +2192,6 @@ def p_cdef_extern_block(s, pos, ctx):
include_file = include_file, include_file = include_file,
body = body) body = body)
struct_union_or_enum = (
"struct", "union", "enum"
)
def p_c_enum_definition(s, pos, ctx): def p_c_enum_definition(s, pos, ctx):
# s.sy == ident 'enum' # s.sy == ident 'enum'
s.next() s.next()
...@@ -2246,6 +2242,12 @@ def p_c_enum_item(s, items): ...@@ -2246,6 +2242,12 @@ def p_c_enum_item(s, items):
name = name, cname = cname, value = value)) name = name, cname = cname, value = value))
def p_c_struct_or_union_definition(s, pos, ctx): def p_c_struct_or_union_definition(s, pos, ctx):
packed = False
if s.systring == 'packed':
packed = True
s.next()
if s.sy != 'IDENT' or s.systring != 'struct':
s.expected('struct')
# s.sy == ident 'struct' or 'union' # s.sy == ident 'struct' or 'union'
kind = s.systring kind = s.systring
s.next() s.next()
...@@ -2271,7 +2273,7 @@ def p_c_struct_or_union_definition(s, pos, ctx): ...@@ -2271,7 +2273,7 @@ def p_c_struct_or_union_definition(s, pos, ctx):
return Nodes.CStructOrUnionDefNode(pos, return Nodes.CStructOrUnionDefNode(pos,
name = name, cname = cname, kind = kind, attributes = attributes, name = name, cname = cname, kind = kind, attributes = attributes,
typedef_flag = ctx.typedef_flag, visibility = ctx.visibility, typedef_flag = ctx.typedef_flag, visibility = ctx.visibility,
in_pxd = ctx.level == 'module_pxd') in_pxd = ctx.level == 'module_pxd', packed = packed)
def p_visibility(s, prev_visibility): def p_visibility(s, prev_visibility):
pos = s.position() pos = s.position()
...@@ -2343,7 +2345,7 @@ def p_ctypedef_statement(s, ctx): ...@@ -2343,7 +2345,7 @@ def p_ctypedef_statement(s, ctx):
ctx.api = 1 ctx.api = 1
if s.sy == 'class': if s.sy == 'class':
return p_c_class_definition(s, pos, ctx) return p_c_class_definition(s, pos, ctx)
elif s.sy == 'IDENT' and s.systring in ('struct', 'union', 'enum'): elif s.sy == 'IDENT' and s.systring in ('packed', 'struct', 'union', 'enum'):
if s.systring == 'enum': if s.systring == 'enum':
return p_c_enum_definition(s, pos, ctx) return p_c_enum_definition(s, pos, ctx)
else: else:
......
...@@ -1024,11 +1024,12 @@ class CStructOrUnionType(CType): ...@@ -1024,11 +1024,12 @@ class CStructOrUnionType(CType):
# kind string "struct" or "union" # kind string "struct" or "union"
# scope StructOrUnionScope, or None if incomplete # scope StructOrUnionScope, or None if incomplete
# typedef_flag boolean # typedef_flag boolean
# packed boolean
is_struct_or_union = 1 is_struct_or_union = 1
has_attributes = 1 has_attributes = 1
def __init__(self, name, kind, scope, typedef_flag, cname): def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
self.name = name self.name = name
self.cname = cname self.cname = cname
self.kind = kind self.kind = kind
...@@ -1039,6 +1040,7 @@ class CStructOrUnionType(CType): ...@@ -1039,6 +1040,7 @@ class CStructOrUnionType(CType):
self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname) self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname)
self.exception_check = True self.exception_check = True
self._convert_code = None self._convert_code = None
self.packed = packed
def create_convert_utility_code(self, env): def create_convert_utility_code(self, env):
if env.outer_scope is None: if env.outer_scope is None:
......
...@@ -490,7 +490,7 @@ class PyrexScanner(Scanner): ...@@ -490,7 +490,7 @@ class PyrexScanner(Scanner):
else: else:
self.expected(what, message) self.expected(what, message)
def expected(self, what, message): def expected(self, what, message = None):
if message: if message:
self.error(message) self.error(message)
else: else:
......
...@@ -341,7 +341,8 @@ class Scope(object): ...@@ -341,7 +341,8 @@ class Scope(object):
return entry return entry
def declare_struct_or_union(self, name, kind, scope, def declare_struct_or_union(self, name, kind, scope,
typedef_flag, pos, cname = None, visibility = 'private'): typedef_flag, pos, cname = None, visibility = 'private',
packed = False):
# Add an entry for a struct or union definition. # Add an entry for a struct or union definition.
if not cname: if not cname:
if self.in_cinclude or visibility == 'public': if self.in_cinclude or visibility == 'public':
...@@ -351,7 +352,7 @@ class Scope(object): ...@@ -351,7 +352,7 @@ class Scope(object):
entry = self.lookup_here(name) entry = self.lookup_here(name)
if not entry: if not entry:
type = PyrexTypes.CStructOrUnionType( type = PyrexTypes.CStructOrUnionType(
name, kind, scope, typedef_flag, cname) name, kind, scope, typedef_flag, cname, packed)
entry = self.declare_type(name, type, pos, cname, entry = self.declare_type(name, type, pos, cname,
visibility = visibility, defining = scope is not None) visibility = visibility, defining = scope is not None)
self.sue_entries.append(entry) self.sue_entries.append(entry)
......
...@@ -642,7 +642,7 @@ if __name__ == '__main__': ...@@ -642,7 +642,7 @@ if __name__ == '__main__':
filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors, filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors,
options.annotate_source, options.cleanup_workdir, options.annotate_source, options.cleanup_workdir,
options.cleanup_sharedlibs, True, options.cleanup_sharedlibs, True,
options.cython_only, languages) options.cython_only, languages, test_bugs)
test_suite.addTest( test_suite.addTest(
filetests.handle_directory( filetests.handle_directory(
os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test'), os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test'),
......
cdef packed foo:
pass
_ERRORS = u"""
1:12: Expected 'struct'
"""
cdef extern:
cdef packed struct MyStruct:
char a
_ERRORS = u"""
2:9: Cannot declare extern struct as 'packed'
"""
__doc__ = """
>>> func1(None)
>>> func1(*[None])
>>> func1(arg=None)
Traceback (most recent call last):
...
TypeError: func1() takes no keyword arguments
>>> func2(None)
>>> func2(*[None])
>>> func2(arg=None)
Traceback (most recent call last):
...
TypeError: func2() takes no keyword arguments
>>> func3(None)
>>> func3(*[None])
>>> func3(arg=None)
>>> A().meth1(None)
>>> A().meth1(*[None])
>>> A().meth1(arg=None)
Traceback (most recent call last):
...
TypeError: meth1() takes no keyword arguments
>>> A().meth2(None)
>>> A().meth2(*[None])
>>> A().meth2(arg=None)
Traceback (most recent call last):
...
TypeError: meth2() takes no keyword arguments
>>> A().meth3(None)
>>> A().meth3(*[None])
>>> A().meth3(arg=None)
"""
cimport cython
def func1(arg):
pass
@cython.always_allow_keywords(False)
def func2(arg):
pass
@cython.always_allow_keywords(True)
def func3(arg):
pass
cdef class A:
def meth1(self, arg):
pass
@cython.always_allow_keywords(False)
def meth2(self, arg):
pass
@cython.always_allow_keywords(True)
def meth3(self, arg):
pass
"""
>>> myfunc()
0.5
"""
cimport numpy as np
import numpy as np
def myfunc():
cdef np.ndarray[float, ndim=2] A = np.ones((1,1), dtype=np.float32)
cdef int i
for i from 0 <= i < A.shape[0]:
A[i, :] /= 2
return A[0,0]
"""
>>> f()
(9, 9)
"""
cdef packed struct MyCdefStruct:
char a
double b
ctypedef packed struct MyCTypeDefStruct:
char a
double b
def f():
return (sizeof(MyCdefStruct), sizeof(MyCTypeDefStruct))
"""
>>> func()
0 0
0
0
1 1
1
1
2 2
2
2
>>> func2()
"""
def g():
return ((3, 2), 1, 0)
def func2():
(a, b), c, d = g()
def func():
for (a, b),c ,d in zip(zip(range(3), range(3)), range(3), range(3)):
print a, b
print c
print d
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