Commit 1b78c83c authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents 7fa1a3b4 139823ed
......@@ -15,7 +15,7 @@ class CythonScope(ModuleScope):
pos=None,
defining = 1,
cname='<error>')
def lookup_type(self, name):
# This function should go away when types are all first-level objects.
type = parse_basic_type(name)
......@@ -23,4 +23,27 @@ class CythonScope(ModuleScope):
return type
def create_cython_scope(context):
create_utility_scope(context)
return CythonScope(context)
def create_utility_scope(context):
global utility_scope
utility_scope = ModuleScope(u'utility', None, context)
# These are used to optimize isinstance in FinalOptimizePhase
type_object = utility_scope.declare_typedef('PyTypeObject',
base_type = c_void_type,
pos = None,
cname = 'PyTypeObject')
type_object.is_void = True
utility_scope.declare_cfunction(
'PyObject_TypeCheck',
CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
CFuncTypeArg("t", c_ptr_type(type_object), None)]),
pos = None,
defining = 1,
cname = 'PyObject_TypeCheck')
return utility_scope
......@@ -9,6 +9,7 @@ from Errors import hold_errors, release_errors, held_errors, report_error
from Cython.Utils import UtilityCode
import StringEncoding
import Naming
import Nodes
from Nodes import Node
import PyrexTypes
from PyrexTypes import py_object_type, c_long_type, typecast, error_type
......@@ -384,6 +385,7 @@ class ExprNode(Node):
# this must be a temp node and the specified variable
# is used as the result instead of allocating a new
# one.
assert result is None, "deprecated, contact dagss if this triggers"
if debug_temp_alloc:
print("%s Allocating temps" % self)
self.allocate_subexpr_temps(env)
......@@ -620,7 +622,6 @@ class RemoveAllocateTemps(type):
setattr(cls, 'release_temp', noop)
class NewTempExprNode(ExprNode):
backwards_compatible_result = None
temp_code = None
old_temp = None # error checker for multiple frees etc.
......@@ -643,8 +644,8 @@ class NewTempExprNode(ExprNode):
self.release_subexpr_temps(env)
def allocate_temps(self, env, result = None):
assert result is None, "deprecated, contact dagss if this triggers"
self.allocate_subexpr_temps(env)
self.backwards_compatible_result = result
if self.is_temp:
self.release_subexpr_temps(env)
......@@ -664,11 +665,8 @@ class NewTempExprNode(ExprNode):
if not type.is_void:
if type.is_pyobject:
type = PyrexTypes.py_object_type
if self.backwards_compatible_result:
self.temp_code = self.backwards_compatible_result
else:
self.temp_code = code.funcstate.allocate_temp(
type, manage_ref=True)
self.temp_code = code.funcstate.allocate_temp(
type, manage_ref=True)
else:
self.temp_code = None
......@@ -4265,7 +4263,14 @@ class DivNode(NumBinopNode):
# '/' or '//' operator.
cdivision = None
cdivision_warnings = False
def analyse_types(self, env):
NumBinopNode.analyse_types(self, env)
if not self.type.is_pyobject and env.directives['cdivision_warnings']:
self.operand1 = self.operand1.coerce_to_simple(env)
self.operand2 = self.operand2.coerce_to_simple(env)
def generate_evaluation_code(self, code):
if not self.type.is_pyobject:
if self.cdivision is None:
......@@ -4273,11 +4278,27 @@ class DivNode(NumBinopNode):
or not self.type.signed
or self.type.is_float)
if not self.cdivision:
code.globalstate.use_utility_code(div_utility_code.specialize(self.type))
code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
NumBinopNode.generate_evaluation_code(self, code)
if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
self.generate_div_warning_code(code)
def generate_div_warning_code(self, code):
code.globalstate.use_utility_code(cdivision_warning_utility_code)
code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
self.operand1.result(),
self.operand2.result()))
code.putln(code.set_error_info(self.pos));
code.put("if (__Pyx_cdivision_warning()) ")
code.put_goto(code.error_label)
code.putln("}")
def calculate_result_code(self):
if self.cdivision:
if self.type.is_float and self.operator == '//':
return "floor(%s / %s)" % (
self.operand1.result(),
self.operand2.result())
elif self.cdivision:
return "(%s / %s)" % (
self.operand1.result(),
self.operand2.result())
......@@ -4288,11 +4309,9 @@ class DivNode(NumBinopNode):
self.operand2.result())
class ModNode(NumBinopNode):
class ModNode(DivNode):
# '%' operator.
cdivision = None
def is_py_operation(self):
return (self.operand1.type.is_string
or self.operand2.type.is_string
......@@ -4303,11 +4322,14 @@ class ModNode(NumBinopNode):
if self.cdivision is None:
self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
if not self.cdivision:
math_h_modifier = getattr(self.type, 'math_h_modifier', '__Pyx_INT')
if self.type.is_int:
code.globalstate.use_utility_code(mod_int_helper_macro)
code.globalstate.use_utility_code(mod_utility_code.specialize(self.type, math_h_modifier=math_h_modifier))
code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
else:
code.globalstate.use_utility_code(
mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
NumBinopNode.generate_evaluation_code(self, code)
if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
self.generate_div_warning_code(code)
def calculate_result_code(self):
if self.cdivision:
......@@ -4510,32 +4532,9 @@ class CondExprNode(ExprNode):
if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
self.true_val = self.true_val.coerce_to(self.type, env)
self.false_val = self.false_val.coerce_to(self.type, env)
# must be tmp variables so they can share a result
self.true_val = self.true_val.coerce_to_temp(env)
self.false_val = self.false_val.coerce_to_temp(env)
self.is_temp = 1
if self.type == PyrexTypes.error_type:
self.type_error()
def allocate_temps(self, env, result_code = None):
# We only ever evaluate one side, and this is
# after evaluating the truth value, so we may
# use an allocation strategy here which results in
# this node and both its operands sharing the same
# result variable. This allows us to avoid some
# assignments and increfs/decrefs that would otherwise
# be necessary.
self.allocate_temp(env, result_code)
self.test.allocate_temps(env, result_code)
self.true_val.allocate_temps(env, self.result())
self.false_val.allocate_temps(env, self.result())
# We haven't called release_temp on either value,
# because although they are temp nodes, they don't own
# their result variable. And because they are temp
# nodes, any temps in their subnodes will have been
# released before their allocate_temps returned.
# Therefore, they contain no temp vars that need to
# be released.
def compute_result_type(self, type1, type2):
if type1 == type2:
......@@ -4567,15 +4566,27 @@ class CondExprNode(ExprNode):
self.false_val.check_const()
def generate_evaluation_code(self, code):
# Because subexprs may not be evaluated we can use a more optimal
# subexpr allocation strategy than the default, so override evaluation_code.
code.mark_pos(self.pos)
#self.allocate_temp_result(code) # uncomment this when we switch to new temps
self.test.generate_evaluation_code(code)
code.putln("if (%s) {" % self.test.result() )
self.true_val.generate_evaluation_code(code)
self.eval_and_get(code, self.true_val)
code.putln("} else {")
self.false_val.generate_evaluation_code(code)
self.eval_and_get(code, self.false_val)
code.putln("}")
self.test.generate_disposal_code(code)
self.test.free_temps(code)
def eval_and_get(self, code, expr):
expr.generate_evaluation_code(code)
expr.make_owned_reference(code)
code.putln("%s = %s;" % (self.result(), expr.result()))
expr.generate_post_assignment_code(code)
expr.free_temps(code)
richcmp_constants = {
"<" : "Py_LT",
"<=": "Py_LE",
......@@ -5716,31 +5727,58 @@ static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
# ------------------------------ Division ------------------------------------
# This is so we can treat floating point and integer mod simultaneously.
mod_int_helper_macro = UtilityCode(proto="""
#define fmod__Pyx_INT(a, b) ((a) % (b))
div_int_utility_code = UtilityCode(
proto="""
static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
""",
impl="""
static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
%(type)s q = a / b;
%(type)s r = a - q*b;
q -= ((r != 0) & ((r ^ b) < 0));
return q;
}
""")
mod_utility_code = UtilityCode(
mod_int_utility_code = UtilityCode(
proto="""
static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
""",
impl="""
static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
%(type)s res = fmod%(math_h_modifier)s(a, b);
res += (res * b < 0) * b;
return res;
%(type)s r = a %% b;
r += ((r != 0) & ((r ^ b) < 0)) * b;
return r;
}
""")
div_utility_code = UtilityCode(
mod_float_utility_code = UtilityCode(
proto="""
static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
""",
impl="""
static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
%(type)s res = a / b;
res -= (res < 0);
return res;
static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
%(type)s r = fmod%(math_h_modifier)s(a, b);
r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
return r;
}
""")
cdivision_warning_utility_code = UtilityCode(
proto="""
static int __Pyx_cdivision_warning(void); /* proto */
""",
impl="""
static int __Pyx_cdivision_warning(void) {
return PyErr_WarnExplicit(PyExc_RuntimeWarning,
"division with oppositely signed operands, C and Python semantics differ",
%(FILENAME)s,
%(LINENO)s,
%(MODULENAME)s,
NULL);
}
""" % {
'FILENAME': Naming.filename_cname,
'MODULENAME': Naming.modulename_cname,
'LINENO': Naming.lineno_cname,
})
......@@ -253,6 +253,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.globalstate.use_utility_code(refcount_utility_code)
code.putln('const char *%s = "%s";' % (Naming.modulename_cname, self.full_module_name))
code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name)
......
......@@ -53,6 +53,7 @@ preimport_cname = pyrex_prefix + "i"
moddict_cname = pyrex_prefix + "d"
dummy_cname = pyrex_prefix + "dummy"
filename_cname = pyrex_prefix + "filename"
modulename_cname = pyrex_prefix + "modulename"
filetable_cname = pyrex_prefix + "f"
filenames_cname = pyrex_prefix + "filenames"
fileinit_cname = pyrex_prefix + "init_filenames"
......
......@@ -515,7 +515,8 @@ class CFuncDeclaratorNode(CDeclaratorNode):
if self.optional_arg_count:
scope = StructOrUnionScope()
scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
arg_count_member = '%sn' % Naming.pyrex_prefix
scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
......@@ -541,6 +542,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
exc_val = self.exception_value.get_constant_result_code()
if self.exception_check == '+':
exc_val_type = self.exception_value.type
env.add_include_file('stdexcept')
if not exc_val_type.is_error and \
not exc_val_type.is_pyobject and \
not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
......@@ -1354,6 +1356,7 @@ class CFuncDefNode(FuncDefNode):
error(self.pos, "Function declared nogil has Python locals or temporaries")
def analyse_expressions(self, env):
self.local_scope.directives = env.directives
if self.py_func is not None:
# this will also analyse the default values
self.py_func.analyse_expressions(env)
......@@ -1410,6 +1413,8 @@ class CFuncDefNode(FuncDefNode):
code.putln('if (%s) {' % Naming.optional_args_cname)
for arg in self.args:
if arg.default:
# FIXME: simple name prefixing doesn't work when
# argument name mangling is in place
code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
declarator = arg.declarator
while not hasattr(declarator, 'name'):
......@@ -1778,6 +1783,7 @@ class DefNode(FuncDefNode):
env.control_flow.set_state((), (arg.name, 'initalized'), True)
def analyse_expressions(self, env):
self.local_scope.directives = env.directives
self.analyse_default_values(env)
if env.is_py_class_scope:
self.synthesize_assignment_node(env)
......@@ -4943,7 +4949,8 @@ static int __Pyx_PrintOne(PyObject *o) {
}
#endif
""")
""",
requires=[printing_utility_code])
......@@ -5308,32 +5315,6 @@ bad:
#------------------------------------------------------------------------------------
unraisable_exception_utility_code = UtilityCode(
proto = """
static void __Pyx_WriteUnraisable(const char *name); /*proto*/
""",
impl = """
static void __Pyx_WriteUnraisable(const char *name) {
PyObject *old_exc, *old_val, *old_tb;
PyObject *ctx;
__Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
#if PY_MAJOR_VERSION < 3
ctx = PyString_FromString(name);
#else
ctx = PyUnicode_FromString(name);
#endif
__Pyx_ErrRestore(old_exc, old_val, old_tb);
if (!ctx) {
PyErr_WriteUnraisable(Py_None);
} else {
PyErr_WriteUnraisable(ctx);
Py_DECREF(ctx);
}
}
""")
#------------------------------------------------------------------------------------
traceback_utility_code = UtilityCode(
proto = """
static void __Pyx_AddTraceback(const char *funcname); /*proto*/
......@@ -5478,6 +5459,33 @@ static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **
#------------------------------------------------------------------------------------
unraisable_exception_utility_code = UtilityCode(
proto = """
static void __Pyx_WriteUnraisable(const char *name); /*proto*/
""",
impl = """
static void __Pyx_WriteUnraisable(const char *name) {
PyObject *old_exc, *old_val, *old_tb;
PyObject *ctx;
__Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
#if PY_MAJOR_VERSION < 3
ctx = PyString_FromString(name);
#else
ctx = PyUnicode_FromString(name);
#endif
__Pyx_ErrRestore(old_exc, old_val, old_tb);
if (!ctx) {
PyErr_WriteUnraisable(Py_None);
} else {
PyErr_WriteUnraisable(ctx);
Py_DECREF(ctx);
}
}
""",
requires=[restore_exception_utility_code])
#------------------------------------------------------------------------------------
set_vtable_utility_code = UtilityCode(
proto = """
static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
......
......@@ -655,11 +655,9 @@ class FinalOptimizePhase(Visitor.CythonTransform):
if node.function.name == 'isinstance':
type_arg = node.args[1]
if type_arg.type.is_builtin_type and type_arg.type.name == 'type':
object_module = self.context.find_module('python_object')
node.function.entry = object_module.lookup('PyObject_TypeCheck')
if node.function.entry is None:
return node # only happens when there was an error earlier
from CythonScope import utility_scope
node.function.entry = utility_scope.lookup('PyObject_TypeCheck')
node.function.type = node.function.entry.type
PyTypeObjectPtr = PyrexTypes.CPtrType(object_module.lookup('PyTypeObject').type)
PyTypeObjectPtr = PyrexTypes.CPtrType(utility_scope.lookup('PyTypeObject').type)
node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr)
return node
......@@ -62,6 +62,7 @@ option_defaults = {
'locals' : {},
'auto_cpdef': False,
'cdivision': True, # Will be False in 0.12
'cdivision_warnings': False,
}
# Override types possibilities above, if needed
......
......@@ -23,6 +23,19 @@ except NameError:
possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
ansi_c_keywords = set(
['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do',
'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if',
'int', 'long', 'register', 'return', 'short', 'signed', 'sizeof',
'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void',
'volatile', 'while'])
def c_safe_identifier(cname):
# There are some C limitations on struct entry names.
if (cname[:2] == '__' and not cname.startswith(Naming.pyrex_prefix)) or cname in ansi_c_keywords:
cname = Naming.pyrex_prefix + cname
return cname
class BufferAux(object):
writable_needed = False
......@@ -1125,6 +1138,8 @@ class StructOrUnionScope(Scope):
# Add an entry for an attribute.
if not cname:
cname = name
if visibility == 'private':
cname = c_safe_identifier(cname)
if type.is_cfunction:
type = PyrexTypes.CPtrType(type)
entry = self.declare(name, cname, type, pos, visibility)
......@@ -1259,6 +1274,8 @@ class CClassScope(ClassScope):
% name)
if not cname:
cname = name
if visibility == 'private':
cname = c_safe_identifier(cname)
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
self.var_entries.append(entry)
......
......@@ -6,6 +6,19 @@ def empty_decorator(x):
def locals(**arg_types):
return empty_decorator
# Special functions
def cdiv(a, b):
q = a / b
if q < 0:
q += 1
def cmod(a, b):
r = a % b
if (a*b) < 0:
r -= b
return r
# Emulated language constructs
......
......@@ -106,6 +106,7 @@ setup(
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: C",
"Programming Language :: Cython",
"Topic :: Software Development :: Code Generators",
"Topic :: Software Development :: Compilers",
"Topic :: Software Development :: Libraries :: Python Modules"
......
"""
>>> constants(4)
1
>>> constants(5)
10
>>> temps(4)
1
>>> temps(5)
10
>>> nested(1)
1
>>> nested(2)
2
>>> nested(3)
3
"""
def ident(x): return x
def constants(x):
a = 1 if x < 5 else 10
return a
def temps(x):
return ident(1) if ident(x) < ident(5) else ident(10)
def nested(x):
return 1 if x == 1 else (2 if x == 2 else 3)
cdef class Album
cdef class SessionStruct:
cdef Album _create_album(self, void* album, bint take_owner):
pass
cdef class Album(SessionStruct):
pass
_ERROR = u"""
"""
cdef f(void=None):
pass
cdef struct foo:
int void
cdef class Foo:
cdef int void
......@@ -23,9 +23,9 @@ else:
_ERRORS = u'''
2:0: break statement not inside loop
5:4: break statement not inside loop
8:4: break statement not inside loop
2:0: break statement not inside loop
5:4: break statement not inside loop
8:4: break statement not inside loop
11:4: break statement not inside loop
16:5: break statement not inside loop
20:4: break statement not inside loop
......
......@@ -10,6 +10,6 @@ NEW_ERRORS = u"""
"""
_ERRORS = u"""
:5:16: Cannot coerce list to type 'list'
5:16: Cannot coerce list to type 'list'
"""
......@@ -23,9 +23,9 @@ else:
_ERRORS = u'''
2:0: continue statement not inside loop
5:4: continue statement not inside loop
8:4: continue statement not inside loop
2:0: continue statement not inside loop
5:4: continue statement not inside loop
8:4: continue statement not inside loop
11:4: continue statement not inside loop
16:5: continue statement not inside loop
20:4: continue statement not inside loop
......
......@@ -5,6 +5,6 @@ cdef void foo(obj):
i1 = p1 # error
p2 = obj # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_ass.pyx:5:16: Cannot assign type 'char *' to 'int'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_ass.pyx:6:17: Cannot convert Python object to 'int *'
5:16: Cannot assign type 'char *' to 'int'
6:17: Cannot convert Python object to 'int *'
"""
cdef void spam():
None = 42
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_assnone.pyx:2:1: Cannot assign to or delete this
2:1: Cannot assign to or delete this
"""
......@@ -3,5 +3,5 @@ cdef struct Foo
def f(Foo *p):
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_badpyparam.pyx:3:6: Cannot convert Python object argument to type 'Foo *'
3:6: Cannot convert Python object argument to type 'Foo *'
"""
......@@ -3,5 +3,5 @@ def f():
cdef char *ptr
int1 = int2 | ptr # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_bitop.pyx:4:13: Invalid operand types for '|' (int; char *)
4:13: Invalid operand types for '|' (int; char *)
"""
......@@ -28,8 +28,8 @@ if union_not_boolean:
_ERRORS = u"""
5:26: 'struct_type_not_boolean' is not a constant, variable or function identifier
5:26: Type 'struct_type_not_boolean' not acceptable as a boolean
5:26: 'struct_type_not_boolean' is not a constant, variable or function identifier
5:26: Type 'struct_type_not_boolean' not acceptable as a boolean
12:21: 'struct_not_boolean' is not a constant, variable or function identifier
12:21: Type 'struct_not_boolean' not acceptable as a boolean
......
......@@ -14,6 +14,6 @@ a.some_method(1, 2)
a.some_method(1, y=2)
_ERRORS = u"""
:9:13: Keyword arguments not allowed in cdef functions.
:14:13: Keyword arguments not allowed in cdef functions.
9:13: Keyword arguments not allowed in cdef functions.
14:13: Keyword arguments not allowed in cdef functions.
"""
......@@ -3,5 +3,5 @@ cdef int
cdef extern from *:
void f(int)
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_cdef_missing_declarator.pyx:1:8: Empty declarator
1:8: Empty declarator
"""
......@@ -7,7 +7,7 @@ ctypedef union eggs:
cdef enum ham:
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cdefemptysue.pyx:1:5: Empty struct or union definition not allowed outside a 'cdef extern from' block
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cdefemptysue.pyx:4:0: Empty struct or union definition not allowed outside a 'cdef extern from' block
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cdefemptysue.pyx:7:5: Empty enum definition not allowed outside a 'cdef extern from' block
1:5: Empty struct or union definition not allowed outside a 'cdef extern from' block
4:0: Empty struct or union definition not allowed outside a 'cdef extern from' block
7:5: Empty enum definition not allowed outside a 'cdef extern from' block
"""
......@@ -6,5 +6,5 @@ cdef void f():
a = 42 # assignment to non-lvalue
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cenum.pyx:6:3: Assignment to non-lvalue 'a'
6:3: Assignment to non-lvalue 'a'
"""
......@@ -6,6 +6,6 @@ cdef class D(C):
cdef void f(self, int x):
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_cmethbasematch.pyx:6:6: Signature not compatible with previous declaration
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_cmethbasematch.pyx:2:6: Previous declaration is here
6:6: Signature not compatible with previous declaration
2:6: Previous declaration is here
"""
......@@ -5,6 +5,6 @@ cdef void foo():
bool = int1 == ptr2 # error
bool = ptr2 == ptr3 # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cmp.pyx:5:13: Invalid types for '==' (int, char *)
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cmp.pyx:6:13: Invalid types for '==' (char *, int *)
5:13: Invalid types for '==' (int, char *)
6:13: Invalid types for '==' (char *, int *)
"""
......@@ -20,12 +20,12 @@ cdef void eggs(Spam s):
j = gp.x # error - incomplete type
gp.x = j # error - incomplete type
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:5:36: C struct/union member cannot be a Python object
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:15:6: Object of type 'Spam' has no attribute 'k'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:16:6: Cannot assign type 'float *[42]' to 'int'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:17:21: Cannot assign type 'int' to 'float *[42]'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:18:6: Object of type 'int' has no attribute 'i'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:19:2: Object of type 'int' has no attribute 'i'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:20:7: Cannot select attribute of incomplete type 'Grail'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_cstruct.pyx:21:3: Cannot select attribute of incomplete type 'Grail'
5:36: C struct/union member cannot be a Python object
15:6: Object of type 'Spam' has no attribute 'k'
16:6: Cannot assign type 'float *[42]' to 'int'
17:21: Cannot assign type 'int' to 'float *[42]'
18:6: Object of type 'int' has no attribute 'i'
19:2: Object of type 'int' has no attribute 'i'
20:7: Cannot select attribute of incomplete type 'Grail'
21:3: Cannot select attribute of incomplete type 'Grail'
"""
......@@ -13,6 +13,6 @@ ctypedef class Eggs:
ctypedef struct Spam
ctypedef class Eggs
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_ctypedefforward.pyx:1:0: Forward-referenced type must use 'cdef', not 'ctypedef'
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_ctypedefforward.pyx:2:0: Forward-referenced type must use 'cdef', not 'ctypedef'
1:0: Forward-referenced type must use 'cdef', not 'ctypedef'
2:0: Forward-referenced type must use 'cdef', not 'ctypedef'
"""
......@@ -17,7 +17,7 @@ cdef Foo f
cdef Blarg b
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_ctypedefornot.pyx:3:0: 'Foo' previously declared using 'cdef'
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_ctypedefornot.pyx:9:5: 'Blarg' previously declared using 'ctypedef'
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_ctypedefornot.pyx:13:0: 'Spam' previously declared using 'cdef'
3:0: 'Foo' previously declared using 'cdef'
9:5: 'Blarg' previously declared using 'ctypedef'
13:0: 'Spam' previously declared using 'cdef'
"""
......@@ -8,9 +8,9 @@ cdef void f():
h = <int ()()>f # this is an error
h = <int (*)()>f # this is OK
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_declarations.pyx:1:19: Array element cannot be a function
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_declarations.pyx:2:18: Function cannot return an array
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_declarations.pyx:3:18: Function cannot return a function
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_declarations.pyx:8:10: Function cannot return a function
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_declarations.pyx:8:5: Cannot cast to a function type
1:19: Array element cannot be a function
2:18: Function cannot return an array
3:18: Function cannot return a function
8:10: Function cannot return a function
8:5: Cannot cast to a function type
"""
......@@ -12,9 +12,9 @@ def f(a):
del x[i] # error: deletion of non-Python object
del s.m # error: deletion of non-Python object
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_del.pyx:8:6: Cannot assign to or delete this
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_del.pyx:9:45: Deletion of non-Python object
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_del.pyx:12:6: Deletion of non-Python object
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_del.pyx:13:6: Deletion of non-Python object
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_del.pyx:11:52: Deletion of local or C global name not supported
8:6: Cannot assign to or delete this
9:45: Deletion of non-Python object
12:6: Deletion of non-Python object
13:6: Deletion of non-Python object
11:52: Deletion of local or C global name not supported
"""
......@@ -11,6 +11,6 @@ except AttributeError:
pass
_ERRORS = u"""
8:0: default 'except:' must be last
8:0: default 'except:' must be last
10:0: default 'except:' must be last
"""
......@@ -7,6 +7,6 @@ cdef spamfunc spam
grail = spam # type mismatch
spam = grail # type mismatch
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_excvalfunctype.pyx:7:28: Cannot assign type 'e_excvalfunctype.spamfunc' to 'e_excvalfunctype.grailfunc'
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_excvalfunctype.pyx:8:28: Cannot assign type 'e_excvalfunctype.grailfunc' to 'e_excvalfunctype.spamfunc'
7:28: Cannot assign type 'e_excvalfunctype.spamfunc' to 'e_excvalfunctype.grailfunc'
8:28: Cannot assign type 'e_excvalfunctype.grailfunc' to 'e_excvalfunctype.spamfunc'
"""
......@@ -13,8 +13,8 @@ cdef void f():
x = c.__weakref__
c.__weakref__ = x
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_extweakref.pyx:5:20: Special attribute __weakref__ cannot be exposed to Python
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_extweakref.pyx:8:22: Special attribute __weakref__ cannot be exposed to Python
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_extweakref.pyx:13:6: Illegal use of special attribute __weakref__
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_extweakref.pyx:14:2: Illegal use of special attribute __weakref__
5:20: Special attribute __weakref__ cannot be exposed to Python
8:22: Special attribute __weakref__ cannot be exposed to Python
13:6: Illegal use of special attribute __weakref__
14:2: Illegal use of special attribute __weakref__
"""
......@@ -7,8 +7,8 @@ def f(obj1, obj2):
int1 = int2[int3] # error
obj1 = obj2[ptr1] # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_index.pyx:5:14: Invalid index type 'float'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_index.pyx:6:14: Invalid index type 'float *'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_index.pyx:7:12: Attempting to index non-array type 'int'
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_index.pyx:8:17: Cannot convert 'float *' to Python object
5:14: Invalid index type 'float'
6:14: Invalid index type 'float *'
7:12: Attempting to index non-array type 'int'
8:17: Cannot convert 'float *' to Python object
"""
......@@ -3,5 +3,5 @@ def f(obj1a, obj1b):
cdef int *ptr2
int1, int3, obj1a = int2, ptr2, obj1b # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_multass.pyx:4:31: Cannot assign type 'int *' to 'int'
4:31: Cannot assign type 'int *' to 'int'
"""
......@@ -8,9 +8,9 @@ cdef f():
spam() # too few args
spam("blarg") # too few args
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_nargs.pyx:5:6: Call with wrong number of arguments (expected 2, got 0)
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_nargs.pyx:6:6: Call with wrong number of arguments (expected 2, got 1)
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_nargs.pyx:7:6: Call with wrong number of arguments (expected 2, got 3)
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_nargs.pyx:8:5: Call with wrong number of arguments (expected at least 2, got 0)
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_nargs.pyx:9:5: Call with wrong number of arguments (expected at least 2, got 1)
5:6: Call with wrong number of arguments (expected 2, got 0)
6:6: Call with wrong number of arguments (expected 2, got 1)
7:6: Call with wrong number of arguments (expected 2, got 3)
8:5: Call with wrong number of arguments (expected at least 2, got 0)
9:5: Call with wrong number of arguments (expected at least 2, got 1)
"""
......@@ -3,6 +3,6 @@ cdef class C:
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_nogilcmeth.pyx:2:6: Signature not compatible with previous declaration
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_nogilcmeth.pxd:2:12: Previous declaration is here
2:6: Signature not compatible with previous declaration
2:12: Previous declaration is here
"""
......@@ -4,5 +4,5 @@ cdef extern from *:
fp = f
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors3/e_nogilfunctype.pyx:5:6: Cannot assign type 'void (void)' to 'void (*)(void) nogil'
5:6: Cannot assign type 'void (void)' to 'void (*)(void) nogil'
"""
......@@ -3,5 +3,5 @@ cdef extern class Grail.Shrubbery
cdef void spam(Shrubbery sh not None):
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_notnone.pyx:3:15: 'not None' only allowed in Python functions
3:15: 'not None' only allowed in Python functions
"""
def eggs(int x not None, y not None):
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_notnone2.pyx:1:0: Only extension type arguments can have 'not None'
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_notnone2.pyx:1:0: Only extension type arguments can have 'not None'
1:0: Only extension type arguments can have 'not None'
1:0: Only extension type arguments can have 'not None'
"""
......@@ -3,5 +3,5 @@ def f():
cdef int *ptr
int1 = int2 * ptr # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_numop.pyx:4:13: Invalid operand types for '*' (int; int *)
4:13: Invalid operand types for '*' (int; int *)
"""
......@@ -7,5 +7,5 @@ def f():
cdef spam s
s.parrot = x
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_pyobinstruct.pyx:4:8: C struct/union member cannot be a Python object
4:8: C struct/union member cannot be a Python object
"""
......@@ -4,5 +4,5 @@ class C:
def f(self):
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_redeclmeth.pyx:4:1: 'f' already declared
4:1: 'f' already declared
"""
......@@ -7,7 +7,7 @@ cdef int h():
return # error
return p # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_return.pyx:3:17: Return with value in void function
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_return.pyx:7:1: Return value required
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_return.pyx:8:17: Cannot assign type 'int *' to 'int'
3:17: Return with value in void function
7:1: Return value required
8:17: Cannot assign type 'int *' to 'int'
"""
......@@ -2,5 +2,5 @@ cdef struct unbekannt
cdef int n
n = sizeof(unbekannt)
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_sizeofincomplete.pyx:3:4: Cannot take sizeof incomplete type 'unbekannt'
3:4: Cannot take sizeof incomplete type 'unbekannt'
"""
......@@ -4,7 +4,7 @@ def f(obj2):
obj1 = obj2[:ptr1:] # error
obj1 = obj2[::ptr1] # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_slice.pyx:3:17: Cannot convert 'int *' to Python object
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_slice.pyx:4:18: Cannot convert 'int *' to Python object
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_slice.pyx:5:19: Cannot convert 'int *' to Python object
3:17: Cannot convert 'int *' to Python object
4:18: Cannot convert 'int *' to Python object
5:19: Cannot convert 'int *' to Python object
"""
......@@ -4,6 +4,6 @@ def f():
ptr1 = int2 - ptr3 # error
ptr1 = ptr2 - ptr3 # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_subop.pyx:4:13: Invalid operand types for '-' (int; char *)
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_subop.pyx:5:13: Cannot assign type 'int' to 'char *'
4:13: Invalid operand types for '-' (int; char *)
5:13: Cannot assign type 'int' to 'char *'
"""
......@@ -5,5 +5,5 @@ def foo(obj):
p = <int *>blarg # okay
p = <int *>(foo + blarg) # error - temporary
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_tempcast.pyx:6:5: Casting temporary Python object to non-numeric non-Python type
6:5: Casting temporary Python object to non-numeric non-Python type
"""
cdef class Spam
cdef extern class external.Eggs
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_undefexttype.pyx:1:5: C class 'Spam' is declared but not defined
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_undefexttype.pyx:2:5: C class 'Eggs' is declared but not defined
1:5: C class 'Spam' is declared but not defined
2:5: C class 'Eggs' is declared but not defined
"""
......@@ -4,6 +4,6 @@ def f():
int1 = -str2 # error
int1 = ~str2 # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_unop.pyx:4:8: Invalid operand type for '-' (char *)
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_unop.pyx:5:8: Invalid operand type for '~' (char *)
4:8: Invalid operand type for '-' (char *)
5:8: Invalid operand type for '~' (char *)
"""
......@@ -3,6 +3,6 @@ def f(a, b):
break # error
continue # error
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_while.pyx:3:1: break statement not inside loop
/Local/Projects/D/Pyrex/Source/Tests/Errors2/e_while.pyx:4:1: continue statement not inside loop
3:1: break statement not inside loop
4:1: continue statement not inside loop
"""
......@@ -4,5 +4,5 @@ cdef class B:
pass
_ERRORS = u"""
:3:10: C method has no self argument
3:10: C method has no self argument
"""
......@@ -78,9 +78,9 @@ cdef void t(C c) nogil:
_ERRORS = u"""
1: 5: Function with Python return type cannot be declared nogil
6: 6: Assignment of Python object not allowed without gil
4: 5: Function declared nogil has Python locals or temporaries
1: 5: Function with Python return type cannot be declared nogil
6: 6: Assignment of Python object not allowed without gil
4: 5: Function declared nogil has Python locals or temporaries
11: 5: Function with Python return type cannot be declared nogil
15: 5: Calling gil-requiring function not allowed without gil
24: 9: Calling gil-requiring function not allowed without gil
......
......@@ -3,6 +3,6 @@ cdef class C:
pass
_ERRORS = u"""
nogilcmeth.pyx:2:9: Signature not compatible with previous declaration
nogilcmeth.pxd:2:15: Previous declaration is here
2:9: Signature not compatible with previous declaration
2:15: Previous declaration is here
"""
......@@ -2,5 +2,5 @@ def f():
a = b # space space
c = d # space tab
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/se_badindent.pyx:3:0: Mixed use of tabs and spaces
3:0: Mixed use of tabs and spaces
"""
......@@ -2,6 +2,6 @@ def f():
a = b
c = d
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/se_badindent2.pyx:3:0: Possible inconsistent indentation
/Local/Projects/D/Pyrex/Source/Tests/Errors1/se_badindent2.pyx:3:0: Expected an identifier or literal
3:0: Possible inconsistent indentation
3:0: Expected an identifier or literal
"""
......@@ -2,5 +2,5 @@ if x:
def h():
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/se_conddef.pyx:2:1: def statement not allowed here
2:1: def statement not allowed here
"""
......@@ -2,5 +2,5 @@ def f():
a = b # space space
c = d # tab
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/se_mixtabspace.pyx:3:0: Mixed use of tabs and spaces
3:0: Mixed use of tabs and spaces
"""
......@@ -2,5 +2,5 @@ def f():
def g():
pass
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/se_nestdef.pyx:2:1: def statement not allowed here
2:1: def statement not allowed here
"""
__doc__ = u"""
>>> cdiv_decorator(-12, 5)
-2
>>> pydiv_decorator(-12, 5)
-3
"""
cimport cython
@cython.cdivision(True)
cpdef cdiv_decorator(int a, int b):
return a / b
@cython.cdivision(False)
cpdef pydiv_decorator(int a, int b):
return a / b
......@@ -26,6 +26,28 @@ True
>>> [test_cdiv_cmod(a, b) for a, b in v]
[(1, 7), (-1, -7), (1, -7), (-1, 7)]
>>> all([mod_int_py(a,b) == a % b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True
>>> all([div_int_py(a,b) == a // b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True
>>> def simple_warn(msg, *args): print msg
>>> import warnings
>>> warnings.showwarning = simple_warn
>>> mod_int_c_warn(-17, 10)
division with oppositely signed operands, C and Python semantics differ
-7
>>> div_int_c_warn(-17, 10)
division with oppositely signed operands, C and Python semantics differ
-1
>>> complex_expression(-150, 20, 20, -7)
verbose_call(-150)
division with oppositely signed operands, C and Python semantics differ
verbose_call(20)
division with oppositely signed operands, C and Python semantics differ
-2
"""
cimport cython
......@@ -73,3 +95,22 @@ def test_cdiv_cmod(short a, short b):
cdef short q = cython.cdiv(a, b)
cdef short r = cython.cmod(a, b)
return q, r
@cython.cdivision(True)
@cython.cdivision_warnings(True)
def mod_int_c_warn(int a, int b):
return a % b
@cython.cdivision(True)
@cython.cdivision_warnings(True)
def div_int_c_warn(int a, int b):
return a // b
@cython.cdivision(False)
@cython.cdivision_warnings(True)
def complex_expression(int a, int b, int c, int d):
return (verbose_call(a) // b) % (verbose_call(c) // d)
cdef int verbose_call(int x):
print "verbose_call(%s)" % x
return x
__doc__ = u"""
>>> floor_div_float(2, 1.5)
1.0
>>> floor_div_float(2, -1.5)
-2.0
>>> floor_div_float(-2.3, 1.5)
-2.0
>>> floor_div_float(1e10, 1e-10)
1e+20
"""
def floor_div_float(double a, double b):
return a // b
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