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

merge

parents d1a841b9 cf38d155
...@@ -6,3 +6,4 @@ a09347d7b470290076b983aef98707921445a038 0.9.8.1 ...@@ -6,3 +6,4 @@ a09347d7b470290076b983aef98707921445a038 0.9.8.1
a89b05b78236a27a654f3004bdffc7b8a56311a7 0.10 a89b05b78236a27a654f3004bdffc7b8a56311a7 0.10
ef9d2c680684d0df7d81f529cda29e9e1741f575 cython-0.10.1 ef9d2c680684d0df7d81f529cda29e9e1741f575 cython-0.10.1
92baafe0edf3cea00deb7ce1e31e337bb485af1a 0.10.2 92baafe0edf3cea00deb7ce1e31e337bb485af1a 0.10.2
cdf889c30e7a7053de20bae3a578dad09ebcbdf5 0.10.3
...@@ -64,6 +64,9 @@ class IntroduceBufferAuxiliaryVars(CythonTransform): ...@@ -64,6 +64,9 @@ class IntroduceBufferAuxiliaryVars(CythonTransform):
# for now...note that pos is wrong # for now...note that pos is wrong
raise CompileError(node.pos, "Buffer vars not allowed in module scope") raise CompileError(node.pos, "Buffer vars not allowed in module scope")
for entry in bufvars: for entry in bufvars:
if entry.type.dtype.is_ptr:
raise CompileError(node.pos, "Buffers with pointer types not yet supported.")
name = entry.name name = entry.name
buftype = entry.type buftype = entry.type
if buftype.ndim > self.max_ndim: if buftype.ndim > self.max_ndim:
...@@ -497,7 +500,7 @@ def mangle_dtype_name(dtype): ...@@ -497,7 +500,7 @@ def mangle_dtype_name(dtype):
elif dtype.is_ptr: elif dtype.is_ptr:
return "ptr" return "ptr"
else: else:
if dtype.typestring is None: if dtype.is_typedef or dtype.is_struct_or_union:
prefix = "nn_" prefix = "nn_"
else: else:
prefix = "" prefix = ""
...@@ -549,10 +552,8 @@ def create_typestringchecker(protocode, defcode, name, dtype): ...@@ -549,10 +552,8 @@ def create_typestringchecker(protocode, defcode, name, dtype):
defcode.putln("int ok;") defcode.putln("int ok;")
defcode.putln("ts = __Pyx_ConsumeWhitespace(ts); if (!ts) return NULL;") defcode.putln("ts = __Pyx_ConsumeWhitespace(ts); if (!ts) return NULL;")
defcode.putln("if (*ts == '1') ++ts;") defcode.putln("if (*ts == '1') ++ts;")
if dtype.typestring is not None: if dtype.is_pyobject:
assert len(dtype.typestring) == 1 defcode.putln("ok = (*ts == 'O');")
# Can use direct comparison
defcode.putln("ok = (*ts == '%s');" % dtype.typestring)
else: else:
# Cannot trust declared size; but rely on int vs float and # Cannot trust declared size; but rely on int vs float and
# signed/unsigned to be correctly declared. Use a switch statement # signed/unsigned to be correctly declared. Use a switch statement
......
...@@ -10,6 +10,7 @@ from PyrexTypes import py_object_type, typecast ...@@ -10,6 +10,7 @@ from PyrexTypes import py_object_type, typecast
from TypeSlots import method_coexist from TypeSlots import method_coexist
from Scanning import SourceDescriptor from Scanning import SourceDescriptor
from Cython.StringIOTree import StringIOTree from Cython.StringIOTree import StringIOTree
import DebugFlags
try: try:
set set
except NameError: except NameError:
...@@ -737,47 +738,53 @@ class CCodeWriter(object): ...@@ -737,47 +738,53 @@ class CCodeWriter(object):
def as_pyobject(self, cname, type): def as_pyobject(self, cname, type):
return typecast(py_object_type, type, cname) return typecast(py_object_type, type, cname)
def put_gotref(self, cname):
self.putln("__Pyx_GOTREF(%s);" % cname)
def put_giveref(self, cname):
self.putln("__Pyx_GIVEREF(%s);" % cname)
def put_incref(self, cname, type): def put_incref(self, cname, type):
self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type)) self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
def put_decref(self, cname, type): def put_decref(self, cname, type):
self.putln("Py_DECREF(%s);" % self.as_pyobject(cname, type)) self.putln("__Pyx_DECREF(%s);" % self.as_pyobject(cname, type))
def put_var_incref(self, entry): def put_var_incref(self, entry):
if entry.type.is_pyobject: if entry.type.is_pyobject:
self.putln("Py_INCREF(%s);" % self.entry_as_pyobject(entry)) self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
def put_decref_clear(self, cname, type): def put_decref_clear(self, cname, type):
self.putln("Py_DECREF(%s); %s = 0;" % ( self.putln("__Pyx_DECREF(%s); %s = 0;" % (
typecast(py_object_type, type, cname), cname)) typecast(py_object_type, type, cname), cname))
#self.as_pyobject(cname, type), cname)) #self.as_pyobject(cname, type), cname))
def put_xdecref(self, cname, type): def put_xdecref(self, cname, type):
self.putln("Py_XDECREF(%s);" % self.as_pyobject(cname, type)) self.putln("__Pyx_XDECREF(%s);" % self.as_pyobject(cname, type))
def put_xdecref_clear(self, cname, type): def put_xdecref_clear(self, cname, type):
self.putln("Py_XDECREF(%s); %s = 0;" % ( self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
self.as_pyobject(cname, type), cname)) self.as_pyobject(cname, type), cname))
def put_var_decref(self, entry): def put_var_decref(self, entry):
if entry.type.is_pyobject: if entry.type.is_pyobject:
if entry.init_to_none is False: if entry.init_to_none is False:
self.putln("Py_XDECREF(%s);" % self.entry_as_pyobject(entry)) self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
else: else:
self.putln("Py_DECREF(%s);" % self.entry_as_pyobject(entry)) self.putln("__Pyx_DECREF(%s);" % self.entry_as_pyobject(entry))
def put_var_decref_clear(self, entry): def put_var_decref_clear(self, entry):
if entry.type.is_pyobject: if entry.type.is_pyobject:
self.putln("Py_DECREF(%s); %s = 0;" % ( self.putln("__Pyx_DECREF(%s); %s = 0;" % (
self.entry_as_pyobject(entry), entry.cname)) self.entry_as_pyobject(entry), entry.cname))
def put_var_xdecref(self, entry): def put_var_xdecref(self, entry):
if entry.type.is_pyobject: if entry.type.is_pyobject:
self.putln("Py_XDECREF(%s);" % self.entry_as_pyobject(entry)) self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
def put_var_xdecref_clear(self, entry): def put_var_xdecref_clear(self, entry):
if entry.type.is_pyobject: if entry.type.is_pyobject:
self.putln("Py_XDECREF(%s); %s = 0;" % ( self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
self.entry_as_pyobject(entry), entry.cname)) self.entry_as_pyobject(entry), entry.cname))
def put_var_decrefs(self, entries, used_only = 0): def put_var_decrefs(self, entries, used_only = 0):
...@@ -798,7 +805,7 @@ class CCodeWriter(object): ...@@ -798,7 +805,7 @@ class CCodeWriter(object):
def put_init_to_py_none(self, cname, type): def put_init_to_py_none(self, cname, type):
py_none = typecast(type, py_object_type, "Py_None") py_none = typecast(type, py_object_type, "Py_None")
self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none)) self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
def put_init_var_to_py_none(self, entry, template = "%s"): def put_init_var_to_py_none(self, entry, template = "%s"):
code = template % entry.cname code = template % entry.cname
...@@ -837,20 +844,24 @@ class CCodeWriter(object): ...@@ -837,20 +844,24 @@ class CCodeWriter(object):
else: else:
return cond return cond
def error_goto(self, pos): def set_error_info(self, pos):
lbl = self.funcstate.error_label
self.funcstate.use_label(lbl)
if Options.c_line_in_traceback: if Options.c_line_in_traceback:
cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro) cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
else: else:
cinfo = "" cinfo = ""
return "{%s = %s[%s]; %s = %s;%s goto %s;}" % ( return "%s = %s[%s]; %s = %s;%s" % (
Naming.filename_cname, Naming.filename_cname,
Naming.filetable_cname, Naming.filetable_cname,
self.lookup_filename(pos[0]), self.lookup_filename(pos[0]),
Naming.lineno_cname, Naming.lineno_cname,
pos[1], pos[1],
cinfo, cinfo)
def error_goto(self, pos):
lbl = self.funcstate.error_label
self.funcstate.use_label(lbl)
return "{%s goto %s;}" % (
self.set_error_info(pos),
lbl) lbl)
def error_goto_if(self, cond, pos): def error_goto_if(self, cond, pos):
......
...@@ -3,3 +3,4 @@ debug_temp_alloc = 0 ...@@ -3,3 +3,4 @@ debug_temp_alloc = 0
debug_coercion = 0 debug_coercion = 0
debug_temp_code_comments = 1 debug_temp_code_comments = 1
...@@ -1016,6 +1016,7 @@ class LongNode(AtomicNewTempExprNode): ...@@ -1016,6 +1016,7 @@ class LongNode(AtomicNewTempExprNode):
self.result(), self.result(),
self.value, self.value,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class ImagNode(AtomicNewTempExprNode): class ImagNode(AtomicNewTempExprNode):
...@@ -1042,6 +1043,8 @@ class ImagNode(AtomicNewTempExprNode): ...@@ -1042,6 +1043,8 @@ class ImagNode(AtomicNewTempExprNode):
self.result(), self.result(),
self.value, self.value,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class NameNode(AtomicExprNode): class NameNode(AtomicExprNode):
...@@ -1262,13 +1265,16 @@ class NameNode(AtomicExprNode): ...@@ -1262,13 +1265,16 @@ class NameNode(AtomicExprNode):
namespace, namespace,
self.interned_cname, self.interned_cname,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
elif entry.is_local and False: elif entry.is_local and False:
# control flow not good enough yet # control flow not good enough yet
assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos) assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
if assigned is False: if assigned is False:
error(self.pos, "local variable '%s' referenced before assignment" % entry.name) error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
elif not Options.init_local_none and assigned is None: elif not Options.init_local_none and assigned is None:
code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos))) code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
(entry.cname, entry.name, code.error_goto(self.pos)))
entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True) entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
def generate_assignment_code(self, rhs, code): def generate_assignment_code(self, rhs, code):
...@@ -1406,6 +1412,8 @@ class BackquoteNode(ExprNode): ...@@ -1406,6 +1412,8 @@ class BackquoteNode(ExprNode):
self.result(), self.result(),
self.arg.py_result(), self.arg.py_result(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class ImportNode(ExprNode): class ImportNode(ExprNode):
...@@ -1442,6 +1450,7 @@ class ImportNode(ExprNode): ...@@ -1442,6 +1450,7 @@ class ImportNode(ExprNode):
self.module_name.py_result(), self.module_name.py_result(),
name_list_code, name_list_code,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class IteratorNode(NewTempExprNode): class IteratorNode(NewTempExprNode):
...@@ -1500,6 +1509,7 @@ class IteratorNode(NewTempExprNode): ...@@ -1500,6 +1509,7 @@ class IteratorNode(NewTempExprNode):
self.result(), self.result(),
self.sequence.py_result(), self.sequence.py_result(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
code.putln("}") code.putln("}")
...@@ -1558,6 +1568,7 @@ class NextNode(AtomicNewTempExprNode): ...@@ -1558,6 +1568,7 @@ class NextNode(AtomicNewTempExprNode):
code.putln(code.error_goto_if_PyErr(self.pos)) code.putln(code.error_goto_if_PyErr(self.pos))
code.putln("break;") code.putln("break;")
code.putln("}") code.putln("}")
code.put_gotref(self.result())
code.putln("}") code.putln("}")
...@@ -1819,6 +1830,7 @@ class IndexNode(ExprNode): ...@@ -1819,6 +1830,7 @@ class IndexNode(ExprNode):
self.index_unsigned_parameter(), self.index_unsigned_parameter(),
self.result(), self.result(),
code.error_goto(self.pos))) code.error_goto(self.pos)))
code.put_gotref(self.result())
def generate_setitem_code(self, value_code, code): def generate_setitem_code(self, value_code, code):
if self.index.type.is_int: if self.index.type.is_int:
...@@ -1994,6 +2006,7 @@ class SliceIndexNode(ExprNode): ...@@ -1994,6 +2006,7 @@ class SliceIndexNode(ExprNode):
self.start_code(), self.start_code(),
self.stop_code(), self.stop_code(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
def generate_assignment_code(self, rhs, code): def generate_assignment_code(self, rhs, code):
self.generate_subexpr_evaluation_code(code) self.generate_subexpr_evaluation_code(code)
...@@ -2158,6 +2171,7 @@ class SliceNode(ExprNode): ...@@ -2158,6 +2171,7 @@ class SliceNode(ExprNode):
self.stop.py_result(), self.stop.py_result(),
self.step.py_result(), self.step.py_result(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class CallNode(NewTempExprNode): class CallNode(NewTempExprNode):
...@@ -2378,6 +2392,7 @@ class SimpleCallNode(CallNode): ...@@ -2378,6 +2392,7 @@ class SimpleCallNode(CallNode):
self.function.py_result(), self.function.py_result(),
arg_code, arg_code,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
elif func_type.is_cfunction: elif func_type.is_cfunction:
if self.has_optional_args: if self.has_optional_args:
actual_nargs = len(self.args) actual_nargs = len(self.args)
...@@ -2432,6 +2447,9 @@ class SimpleCallNode(CallNode): ...@@ -2432,6 +2447,9 @@ class SimpleCallNode(CallNode):
else: else:
goto_error = "" goto_error = ""
code.putln("%s%s; %s" % (lhs, rhs, goto_error)) code.putln("%s%s; %s" % (lhs, rhs, goto_error))
if self.type.is_pyobject and self.result():
code.put_gotref(self.result())
class GeneralCallNode(CallNode): class GeneralCallNode(CallNode):
# General Python function call, including keyword, # General Python function call, including keyword,
...@@ -2507,6 +2525,7 @@ class GeneralCallNode(CallNode): ...@@ -2507,6 +2525,7 @@ class GeneralCallNode(CallNode):
self.result(), self.result(),
call_code, call_code,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class AsTupleNode(ExprNode): class AsTupleNode(ExprNode):
...@@ -2542,6 +2561,7 @@ class AsTupleNode(ExprNode): ...@@ -2542,6 +2561,7 @@ class AsTupleNode(ExprNode):
self.result(), self.result(),
self.arg.py_result(), self.arg.py_result(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class AttributeNode(ExprNode): class AttributeNode(ExprNode):
...@@ -2811,6 +2831,7 @@ class AttributeNode(ExprNode): ...@@ -2811,6 +2831,7 @@ class AttributeNode(ExprNode):
self.obj.py_result(), self.obj.py_result(),
self.interned_attr_cname, self.interned_attr_cname,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
else: else:
# result_code contains what is needed, but we may need to insert # result_code contains what is needed, but we may need to insert
# a check and raise an exception # a check and raise an exception
...@@ -2980,6 +3001,7 @@ class SequenceNode(NewTempExprNode): ...@@ -2980,6 +3001,7 @@ class SequenceNode(NewTempExprNode):
self.iterator.result(), self.iterator.result(),
rhs.py_result(), rhs.py_result(),
code.error_goto_if_null(self.iterator.result(), self.pos))) code.error_goto_if_null(self.iterator.result(), self.pos)))
code.put_gotref(self.iterator.result())
rhs.generate_disposal_code(code) rhs.generate_disposal_code(code)
for i in range(len(self.args)): for i in range(len(self.args)):
item = self.unpacked_items[i] item = self.unpacked_items[i]
...@@ -2990,6 +3012,7 @@ class SequenceNode(NewTempExprNode): ...@@ -2990,6 +3012,7 @@ class SequenceNode(NewTempExprNode):
item.result(), item.result(),
typecast(item.ctype(), py_object_type, unpack_code), typecast(item.ctype(), py_object_type, unpack_code),
code.error_goto_if_null(item.result(), self.pos))) code.error_goto_if_null(item.result(), self.pos)))
code.put_gotref(item.result())
value_node = self.coerced_unpacked_items[i] value_node = self.coerced_unpacked_items[i]
value_node.generate_evaluation_code(code) value_node.generate_evaluation_code(code)
code.put_error_if_neg(self.pos, code.put_error_if_neg(self.pos,
...@@ -3056,6 +3079,7 @@ class TupleNode(SequenceNode): ...@@ -3056,6 +3079,7 @@ class TupleNode(SequenceNode):
self.result(), self.result(),
len(self.args), len(self.args),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
for i in range(len(self.args)): for i in range(len(self.args)):
arg = self.args[i] arg = self.args[i]
if not arg.result_in_temp(): if not arg.result_in_temp():
...@@ -3065,6 +3089,7 @@ class TupleNode(SequenceNode): ...@@ -3065,6 +3089,7 @@ class TupleNode(SequenceNode):
self.result(), self.result(),
i, i,
arg.py_result())) arg.py_result()))
code.put_giveref(arg.py_result())
def generate_subexpr_disposal_code(self, code): def generate_subexpr_disposal_code(self, code):
# We call generate_post_assignment_code here instead # We call generate_post_assignment_code here instead
...@@ -3150,6 +3175,7 @@ class ListNode(SequenceNode): ...@@ -3150,6 +3175,7 @@ class ListNode(SequenceNode):
(self.result(), (self.result(),
len(self.args), len(self.args),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
for i in range(len(self.args)): for i in range(len(self.args)):
arg = self.args[i] arg = self.args[i]
#if not arg.is_temp: #if not arg.is_temp:
...@@ -3159,6 +3185,7 @@ class ListNode(SequenceNode): ...@@ -3159,6 +3185,7 @@ class ListNode(SequenceNode):
(self.result(), (self.result(),
i, i,
arg.py_result())) arg.py_result()))
code.put_giveref(arg.py_result())
elif self.type.is_array: elif self.type.is_array:
for i, arg in enumerate(self.args): for i, arg in enumerate(self.args):
code.putln("%s[%s] = %s;" % ( code.putln("%s[%s] = %s;" % (
...@@ -3397,6 +3424,7 @@ class DictNode(ExprNode): ...@@ -3397,6 +3424,7 @@ class DictNode(ExprNode):
"%s = PyDict_New(); %s" % ( "%s = PyDict_New(); %s" % (
self.result(), self.result(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
for item in self.key_value_pairs: for item in self.key_value_pairs:
item.generate_evaluation_code(code) item.generate_evaluation_code(code)
if self.type.is_pyobject: if self.type.is_pyobject:
...@@ -3492,6 +3520,7 @@ class ClassNode(ExprNode): ...@@ -3492,6 +3520,7 @@ class ClassNode(ExprNode):
self.cname, self.cname,
self.module_name, self.module_name,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class UnboundMethodNode(ExprNode): class UnboundMethodNode(ExprNode):
...@@ -3519,7 +3548,7 @@ class UnboundMethodNode(ExprNode): ...@@ -3519,7 +3548,7 @@ class UnboundMethodNode(ExprNode):
self.function.py_result(), self.function.py_result(),
self.class_cname, self.class_cname,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class PyCFunctionNode(AtomicNewTempExprNode): class PyCFunctionNode(AtomicNewTempExprNode):
# Helper class used in the implementation of Python # Helper class used in the implementation of Python
...@@ -3541,6 +3570,7 @@ class PyCFunctionNode(AtomicNewTempExprNode): ...@@ -3541,6 +3570,7 @@ class PyCFunctionNode(AtomicNewTempExprNode):
self.result(), self.result(),
self.pymethdef_cname, self.pymethdef_cname,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
#------------------------------------------------------------------- #-------------------------------------------------------------------
# #
...@@ -3619,6 +3649,7 @@ class UnopNode(ExprNode): ...@@ -3619,6 +3649,7 @@ class UnopNode(ExprNode):
function, function,
self.operand.py_result(), self.operand.py_result(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
def type_error(self): def type_error(self):
if not self.operand.type.is_error: if not self.operand.type.is_error:
...@@ -4025,6 +4056,7 @@ class BinopNode(NewTempExprNode): ...@@ -4025,6 +4056,7 @@ class BinopNode(NewTempExprNode):
self.operand2.py_result(), self.operand2.py_result(),
extra_args, extra_args,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
else: else:
if self.is_temp: if self.is_temp:
self.generate_c_operation_code(code) self.generate_c_operation_code(code)
...@@ -4522,6 +4554,7 @@ class CmpNode(object): ...@@ -4522,6 +4554,7 @@ class CmpNode(object):
operand2.py_result(), operand2.py_result(),
richcmp_constants[op], richcmp_constants[op],
code.error_goto_if_null(result_code, self.pos))) code.error_goto_if_null(result_code, self.pos)))
code.put_gotref(result_code)
else: else:
type1 = operand1.type type1 = operand1.type
type2 = operand2.type type2 = operand2.type
...@@ -4923,6 +4956,7 @@ class CoerceToPyTypeNode(CoercionNode): ...@@ -4923,6 +4956,7 @@ class CoerceToPyTypeNode(CoercionNode):
function, function,
self.arg.result(), self.arg.result(),
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class CoerceFromPyTypeNode(CoercionNode): class CoerceFromPyTypeNode(CoercionNode):
...@@ -4954,6 +4988,8 @@ class CoerceFromPyTypeNode(CoercionNode): ...@@ -4954,6 +4988,8 @@ class CoerceFromPyTypeNode(CoercionNode):
self.result(), self.result(),
rhs, rhs,
code.error_goto_if(self.type.error_condition(self.result()), self.pos))) code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
if self.type.is_pyobject:
code.put_gotref(self.result())
class CoerceToBooleanNode(CoercionNode): class CoerceToBooleanNode(CoercionNode):
......
...@@ -19,6 +19,7 @@ import Options ...@@ -19,6 +19,7 @@ import Options
import PyrexTypes import PyrexTypes
import TypeSlots import TypeSlots
import Version import Version
import DebugFlags
from Errors import error, warning from Errors import error, warning
from PyrexTypes import py_object_type from PyrexTypes import py_object_type
...@@ -250,6 +251,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -250,6 +251,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.globalstate.module_pos = self.pos code.globalstate.module_pos = self.pos
code.globalstate.directives = self.directives code.globalstate.directives = self.directives
code.globalstate.use_utility_code(refcount_utility_code)
code.putln("") code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name) code.putln("/* Implementation of %s */" % env.qualified_name)
self.generate_const_definitions(env, code) self.generate_const_definitions(env, code)
...@@ -1586,6 +1589,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1586,6 +1589,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#endif") code.putln("#endif")
code.putln("{") code.putln("{")
tempdecl_code = code.insertion_point() tempdecl_code = code.insertion_point()
code.putln('__Pyx_SetupRefcountContext("%s");' % header3)
code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos))); code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
code.putln("/*--- Library function declarations ---*/") code.putln("/*--- Library function declarations ---*/")
...@@ -2312,3 +2318,36 @@ bad: ...@@ -2312,3 +2318,36 @@ bad:
} }
""" % {'IMPORT_STAR' : Naming.import_star, """ % {'IMPORT_STAR' : Naming.import_star,
'IMPORT_STAR_SET' : Naming.import_star_set } 'IMPORT_STAR_SET' : Naming.import_star_set }
refcount_utility_code = UtilityCode(proto="""
#ifdef CYTHON_REFNANNY
void __Pyx_Refnanny_INCREF(void*, PyObject*, int);
void __Pyx_Refnanny_GOTREF(void*, PyObject*, int);
void __Pyx_Refnanny_GIVEREF(void*, PyObject*, int);
void __Pyx_Refnanny_INCREF(void*, PyObject*, int);
void __Pyx_Refnanny_DECREF(void*, PyObject*, int);
void* __Pyx_Refnanny_NewContext(char*, int);
int __Pyx_Refnanny_FinishContext(void*);
#define __Pyx_INCREF(r) __Pyx_Refnanny_INCREF(__pyx_refchk, r, __LINE__)
#define __Pyx_GOTREF(r) __Pyx_Refnanny_GOTREF(__pyx_refchk, r, __LINE__)
#define __Pyx_GIVEREF(r) __Pyx_Refnanny_GIVEREF(__pyx_refchk, r, __LINE__)
#define __Pyx_DECREF(r) __Pyx_Refnanny_DECREF(__pyx_refchk, r, __LINE__)
#define __Pyx_XDECREF(r) (r ? __Pyx_Refnanny_DECREF(__pyx_refchk, r, __LINE__) : 0)
#define __Pyx_SetupRefcountContext(name) \
void* __pyx_refchk = __Pyx_Refnanny_NewContext(name, __LINE__)
#define __Pyx_FinishRefcountContext() __Pyx_Refnanny_FinishContext(__pyx_refchk)
#else
#define __Pyx_INCREF(r) Py_INCREF(r)
#define __Pyx_GOTREF(r)
#define __Pyx_GIVEREF(r)
#define __Pyx_DECREF(r) Py_DECREF(r)
#define __Pyx_XDECREF(r) Py_XDECREF(r)
#define __Pyx_SetupRefcountContext(name)
#define __Pyx_FinishRefcountContext() 0
#endif /* CYTHON_REFNANNY */
""")
...@@ -17,6 +17,7 @@ from Cython.Utils import open_new_file, replace_suffix, UtilityCode ...@@ -17,6 +17,7 @@ from Cython.Utils import open_new_file, replace_suffix, UtilityCode
from StringEncoding import EncodedString, escape_byte_string, split_docstring from StringEncoding import EncodedString, escape_byte_string, split_docstring
import Options import Options
import ControlFlow import ControlFlow
import DebugFlags
from DebugFlags import debug_disposal_code from DebugFlags import debug_disposal_code
...@@ -1022,6 +1023,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1022,6 +1023,7 @@ class FuncDefNode(StatNode, BlockNode):
# ----- Automatic lead-ins for certain special functions # ----- Automatic lead-ins for certain special functions
if is_getbuffer_slot: if is_getbuffer_slot:
self.getbuffer_init(code) self.getbuffer_init(code)
code.putln('__Pyx_SetupRefcountContext("%s");' % self.entry.name)
# ----- Fetch arguments # ----- Fetch arguments
self.generate_argument_parsing_code(env, code) self.generate_argument_parsing_code(env, code)
# If an argument is assigned to in the body, we must # If an argument is assigned to in the body, we must
...@@ -1135,8 +1137,24 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1135,8 +1137,24 @@ class FuncDefNode(StatNode, BlockNode):
code.putln("PyGILState_Release(_save);") code.putln("PyGILState_Release(_save);")
# code.putln("/* TODO: decref scope object */") # code.putln("/* TODO: decref scope object */")
# ----- Return # ----- Return
default_retval = self.return_type.default_value
err_val = self.error_value()
if err_val is None and default_retval:
err_val = default_retval
if self.return_type.is_pyobject:
code.put_giveref(Naming.retval_cname)
if err_val is None:
code.putln('__Pyx_FinishRefcountContext();')
else:
code.putln('if (__Pyx_FinishRefcountContext() == -1) {')
code.putln(code.set_error_info(self.pos))
code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
code.putln('%s = %s;' % (Naming.retval_cname, err_val))
code.putln('}')
if not self.return_type.is_void: if not self.return_type.is_void:
code.putln("return %s;" % Naming.retval_cname) code.putln("return %s;" % Naming.retval_cname)
code.putln("}") code.putln("}")
# ----- Go back and insert temp variable declarations # ----- Go back and insert temp variable declarations
tempvardecl_code.put_var_declarations(lenv.temp_entries) tempvardecl_code.put_var_declarations(lenv.temp_entries)
...@@ -1188,16 +1206,16 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1188,16 +1206,16 @@ class FuncDefNode(StatNode, BlockNode):
# getbuffer with a NULL parameter. For now we work around this; # getbuffer with a NULL parameter. For now we work around this;
# the following line should be removed when this bug is fixed. # the following line should be removed when this bug is fixed.
code.putln("if (%s == NULL) return 0;" % info) code.putln("if (%s == NULL) return 0;" % info)
code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info) code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
def getbuffer_error_cleanup(self, code): def getbuffer_error_cleanup(self, code):
info = self.local_scope.arg_entries[1].cname info = self.local_scope.arg_entries[1].cname
code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" % code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
(info, info)) (info, info))
def getbuffer_normal_cleanup(self, code): def getbuffer_normal_cleanup(self, code):
info = self.local_scope.arg_entries[1].cname info = self.local_scope.arg_entries[1].cname
code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" % code.putln("if (%s->obj == Py_None) { __Pyx_DECREF(Py_None); %s->obj = NULL; }" %
(info, info)) (info, info))
class CFuncDefNode(FuncDefNode): class CFuncDefNode(FuncDefNode):
...@@ -2268,6 +2286,7 @@ class DefNode(FuncDefNode): ...@@ -2268,6 +2286,7 @@ class DefNode(FuncDefNode):
func, func,
arg.hdr_cname, arg.hdr_cname,
code.error_goto_if_null(arg.entry.cname, arg.pos))) code.error_goto_if_null(arg.entry.cname, arg.pos)))
code.put_gotref(arg.entry.cname)
else: else:
error(arg.pos, error(arg.pos,
"Cannot convert argument of type '%s' to Python object" "Cannot convert argument of type '%s' to Python object"
...@@ -2347,6 +2366,7 @@ class OverrideCheckNode(StatNode): ...@@ -2347,6 +2366,7 @@ class OverrideCheckNode(StatNode):
else: else:
code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg) code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
err = code.error_goto_if_null(self.func_node.result(), self.pos) err = code.error_goto_if_null(self.func_node.result(), self.pos)
code.put_gotref(self.func_node.result())
# need to get attribute manually--scope would return cdef method # need to get attribute manually--scope would return cdef method
code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err)) code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
# It appears that this type is not anywhere exposed in the Python/C API # It appears that this type is not anywhere exposed in the Python/C API
...@@ -3047,6 +3067,7 @@ class InPlaceAssignmentNode(AssignmentNode): ...@@ -3047,6 +3067,7 @@ class InPlaceAssignmentNode(AssignmentNode):
self.rhs.py_result(), self.rhs.py_result(),
extra, extra,
code.error_goto_if_null(self.result_value.py_result(), self.pos))) code.error_goto_if_null(self.result_value.py_result(), self.pos)))
code.put_gotref(self.result_value.result())
self.result_value.generate_evaluation_code(code) # May be a type check... self.result_value.generate_evaluation_code(code) # May be a type check...
self.rhs.generate_disposal_code(code) self.rhs.generate_disposal_code(code)
self.rhs.free_temps(code) self.rhs.free_temps(code)
...@@ -3981,6 +4002,7 @@ class TryExceptStatNode(StatNode): ...@@ -3981,6 +4002,7 @@ class TryExceptStatNode(StatNode):
except_end_label = code.new_label('exception_handled') except_end_label = code.new_label('exception_handled')
except_error_label = code.new_label('except_error') except_error_label = code.new_label('except_error')
except_return_label = code.new_label('except_return') except_return_label = code.new_label('except_return')
try_return_label = code.new_label('try_return')
try_end_label = code.new_label('try') try_end_label = code.new_label('try')
code.putln("{") code.putln("{")
...@@ -3990,6 +4012,7 @@ class TryExceptStatNode(StatNode): ...@@ -3990,6 +4012,7 @@ class TryExceptStatNode(StatNode):
', '.join(['&%s' % var for var in Naming.exc_save_vars])) ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
code.putln( code.putln(
"/*try:*/ {") "/*try:*/ {")
code.return_label = try_return_label
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
code.putln( code.putln(
"}") "}")
...@@ -4005,6 +4028,11 @@ class TryExceptStatNode(StatNode): ...@@ -4005,6 +4028,11 @@ class TryExceptStatNode(StatNode):
for var in Naming.exc_save_vars: for var in Naming.exc_save_vars:
code.put_xdecref_clear(var, py_object_type) code.put_xdecref_clear(var, py_object_type)
code.put_goto(try_end_label) code.put_goto(try_end_label)
if code.label_used(try_return_label):
code.put_label(try_return_label)
for var in Naming.exc_save_vars:
code.put_xdecref_clear(var, py_object_type)
code.put_goto(old_return_label)
code.put_label(our_error_label) code.put_label(our_error_label)
code.put_var_xdecrefs_clear(self.cleanup_list) code.put_var_xdecrefs_clear(self.cleanup_list)
for temp_name, type in temps_to_clean_up: for temp_name, type in temps_to_clean_up:
...@@ -4138,7 +4166,7 @@ class ExceptClauseNode(Node): ...@@ -4138,7 +4166,7 @@ class ExceptClauseNode(Node):
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
code.funcstate.exc_vars = old_exc_vars code.funcstate.exc_vars = old_exc_vars
for var in self.exc_vars: for var in self.exc_vars:
code.putln("Py_DECREF(%s); %s = 0;" % (var, var)) code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
code.put_goto(end_label) code.put_goto(end_label)
code.putln( code.putln(
"}") "}")
...@@ -4551,6 +4579,7 @@ class FromImportStatNode(StatNode): ...@@ -4551,6 +4579,7 @@ class FromImportStatNode(StatNode):
self.module.py_result(), self.module.py_result(),
cname, cname,
code.error_goto_if_null(self.item.result(), self.pos))) code.error_goto_if_null(self.item.result(), self.pos)))
code.put_gotref(self.item.result())
target.generate_assignment_code(self.item, code) target.generate_assignment_code(self.item, code)
self.module.generate_disposal_code(code) self.module.generate_disposal_code(code)
self.module.free_temps(code) self.module.free_temps(code)
......
...@@ -49,7 +49,6 @@ class PyrexType(BaseType): ...@@ -49,7 +49,6 @@ class PyrexType(BaseType):
# default_value string Initial value # default_value string Initial value
# parsetuple_format string Format char for PyArg_ParseTuple # parsetuple_format string Format char for PyArg_ParseTuple
# pymemberdef_typecode string Type code for PyMemberDef struct # pymemberdef_typecode string Type code for PyMemberDef struct
# typestring string String char defining the type (see Python struct module)
# #
# declaration_code(entity_code, # declaration_code(entity_code,
# for_display = 0, dll_linkage = None, pyrex = 0) # for_display = 0, dll_linkage = None, pyrex = 0)
...@@ -101,7 +100,6 @@ class PyrexType(BaseType): ...@@ -101,7 +100,6 @@ class PyrexType(BaseType):
default_value = "" default_value = ""
parsetuple_format = "" parsetuple_format = ""
pymemberdef_typecode = None pymemberdef_typecode = None
typestring = None
def resolve(self): def resolve(self):
# If a typedef, returns the base type. # If a typedef, returns the base type.
...@@ -157,7 +155,6 @@ class CTypedefType(BaseType): ...@@ -157,7 +155,6 @@ class CTypedefType(BaseType):
# typedef_base_type PyrexType # typedef_base_type PyrexType
is_typedef = 1 is_typedef = 1
typestring = None # Because typedefs are not known exactly
def __init__(self, cname, base_type): def __init__(self, cname, base_type):
self.typedef_cname = cname self.typedef_cname = cname
...@@ -243,7 +240,6 @@ class PyObjectType(PyrexType): ...@@ -243,7 +240,6 @@ class PyObjectType(PyrexType):
parsetuple_format = "O" parsetuple_format = "O"
pymemberdef_typecode = "T_OBJECT" pymemberdef_typecode = "T_OBJECT"
buffer_defaults = None buffer_defaults = None
typestring = "O"
def __str__(self): def __str__(self):
return "Python object" return "Python object"
...@@ -469,10 +465,9 @@ class CNumericType(CType): ...@@ -469,10 +465,9 @@ class CNumericType(CType):
sign_words = ("unsigned ", "", "signed ") sign_words = ("unsigned ", "", "signed ")
def __init__(self, rank, signed = 1, pymemberdef_typecode = None, typestring = None): def __init__(self, rank, signed = 1, pymemberdef_typecode = None):
self.rank = rank self.rank = rank
self.signed = signed self.signed = signed
self.typestring = typestring
ptf = self.parsetuple_formats[signed][rank] ptf = self.parsetuple_formats[signed][rank]
if ptf == '?': if ptf == '?':
ptf = None ptf = None
...@@ -507,9 +502,8 @@ class CIntType(CNumericType): ...@@ -507,9 +502,8 @@ class CIntType(CNumericType):
from_py_function = "__pyx_PyInt_AsLong" from_py_function = "__pyx_PyInt_AsLong"
exception_value = -1 exception_value = -1
def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0, def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0):
typestring=None): CNumericType.__init__(self, rank, signed, pymemberdef_typecode)
CNumericType.__init__(self, rank, signed, pymemberdef_typecode, typestring=typestring)
self.is_returncode = is_returncode self.is_returncode = is_returncode
if self.from_py_function == '__pyx_PyInt_AsLong': if self.from_py_function == '__pyx_PyInt_AsLong':
self.from_py_function = self.get_type_conversion() self.from_py_function = self.get_type_conversion()
...@@ -602,8 +596,8 @@ class CFloatType(CNumericType): ...@@ -602,8 +596,8 @@ class CFloatType(CNumericType):
to_py_function = "PyFloat_FromDouble" to_py_function = "PyFloat_FromDouble"
from_py_function = "__pyx_PyFloat_AsDouble" from_py_function = "__pyx_PyFloat_AsDouble"
def __init__(self, rank, pymemberdef_typecode = None, typestring=None): def __init__(self, rank, pymemberdef_typecode = None):
CNumericType.__init__(self, rank, 1, pymemberdef_typecode, typestring = typestring) CNumericType.__init__(self, rank, 1, pymemberdef_typecode)
def assignable_from_resolved_type(self, src_type): def assignable_from_resolved_type(self, src_type):
return src_type.is_numeric or src_type is error_type return src_type.is_numeric or src_type is error_type
...@@ -1133,7 +1127,6 @@ class ErrorType(PyrexType): ...@@ -1133,7 +1127,6 @@ class ErrorType(PyrexType):
exception_check = 0 exception_check = 0
to_py_function = "dummy" to_py_function = "dummy"
from_py_function = "dummy" from_py_function = "dummy"
typestring = None
def create_convert_utility_code(self, env): def create_convert_utility_code(self, env):
return True return True
...@@ -1167,29 +1160,29 @@ c_void_type = CVoidType() ...@@ -1167,29 +1160,29 @@ c_void_type = CVoidType()
c_void_ptr_type = CPtrType(c_void_type) c_void_ptr_type = CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type) c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
c_uchar_type = CIntType(0, 0, "T_UBYTE", typestring="B") c_uchar_type = CIntType(0, 0, "T_UBYTE")
c_ushort_type = CIntType(1, 0, "T_USHORT", typestring="H") c_ushort_type = CIntType(1, 0, "T_USHORT")
c_uint_type = CUIntType(2, 0, "T_UINT", typestring="I") c_uint_type = CUIntType(2, 0, "T_UINT")
c_ulong_type = CULongType(3, 0, "T_ULONG", typestring="L") c_ulong_type = CULongType(3, 0, "T_ULONG")
c_ulonglong_type = CULongLongType(4, 0, "T_ULONGLONG", typestring="Q") c_ulonglong_type = CULongLongType(4, 0, "T_ULONGLONG")
c_char_type = CIntType(0, 1, "T_CHAR", typestring="b") c_char_type = CIntType(0, 1, "T_CHAR")
c_short_type = CIntType(1, 1, "T_SHORT", typestring="h") c_short_type = CIntType(1, 1, "T_SHORT")
c_int_type = CIntType(2, 1, "T_INT", typestring="i") c_int_type = CIntType(2, 1, "T_INT")
c_long_type = CIntType(3, 1, "T_LONG", typestring="l") c_long_type = CIntType(3, 1, "T_LONG")
c_longlong_type = CLongLongType(4, 1, "T_LONGLONG", typestring="q") c_longlong_type = CLongLongType(4, 1, "T_LONGLONG")
c_py_ssize_t_type = CPySSizeTType(5, 1) c_py_ssize_t_type = CPySSizeTType(5, 1)
c_bint_type = CBIntType(2, 1, "T_INT", typestring="i") c_bint_type = CBIntType(2, 1, "T_INT")
c_schar_type = CIntType(0, 2, "T_CHAR", typestring="b") c_schar_type = CIntType(0, 2, "T_CHAR")
c_sshort_type = CIntType(1, 2, "T_SHORT", typestring="h") c_sshort_type = CIntType(1, 2, "T_SHORT")
c_sint_type = CIntType(2, 2, "T_INT", typestring="i") c_sint_type = CIntType(2, 2, "T_INT")
c_slong_type = CIntType(3, 2, "T_LONG", typestring="l") c_slong_type = CIntType(3, 2, "T_LONG")
c_slonglong_type = CLongLongType(4, 2, "T_LONGLONG", typestring="q") c_slonglong_type = CLongLongType(4, 2, "T_LONGLONG")
c_float_type = CFloatType(6, "T_FLOAT", typestring="f") c_float_type = CFloatType(6, "T_FLOAT")
c_double_type = CFloatType(7, "T_DOUBLE", typestring="d") c_double_type = CFloatType(7, "T_DOUBLE")
c_longdouble_type = CFloatType(8, typestring="g") c_longdouble_type = CFloatType(8)
c_null_ptr_type = CNullPtrType(c_void_type) c_null_ptr_type = CNullPtrType(c_void_type)
c_char_array_type = CCharArrayType(None) c_char_array_type = CCharArrayType(None)
......
version = '0.10.2' version = '0.10.3'
...@@ -26,19 +26,19 @@ class BasicVisitor(object): ...@@ -26,19 +26,19 @@ class BasicVisitor(object):
# Must resolve, try entire hierarchy # Must resolve, try entire hierarchy
pattern = "visit_%s" pattern = "visit_%s"
mro = inspect.getmro(cls) mro = inspect.getmro(cls)
handler_method = None
for mro_cls in mro: for mro_cls in mro:
try: if hasattr(self, pattern % mro_cls.__name__):
handler_method = getattr(self, pattern % mro_cls.__name__) handler_method = getattr(self, pattern % mro_cls.__name__)
break break
except AttributeError: if handler_method is None:
pass
else:
print type(self), type(obj) print type(self), type(obj)
if hasattr(self, 'access_path') and self.access_path: if hasattr(self, 'access_path') and self.access_path:
print self.access_path print self.access_path
if self.access_path:
print self.access_path[-1][0].pos print self.access_path[-1][0].pos
print self.access_path[-1][0].__dict__ print self.access_path[-1][0].__dict__
raise RuntimeError("Visitor does not accept object: %s" % (obj,)) raise RuntimeError("Visitor does not accept object: %s" % obj)
#print "Caching " + cls.__name__ #print "Caching " + cls.__name__
self.dispatch_table[cls] = handler_method self.dispatch_table[cls] = handler_method
return handler_method(obj) return handler_method(obj)
......
cat <<EOF > ../../Cython/Compiler/DebugFlags.py
debug_disposal_code = 0
debug_temp_alloc = 0
debug_coercion = 0
debug_refnanny = 0
EOF
python ../../cython.py refnanny.pyx
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall \
-fno-strict-aliasing -I/local/include/python2.5 \
-o refnanny.so -I. refnanny.c
cat <<EOF > ../../Cython/Compiler/DebugFlags.py
debug_disposal_code = 0
debug_temp_alloc = 0
debug_coercion = 0
debug_refnanny = 1
EOF
from python_ref cimport Py_INCREF, Py_DECREF
loglevel = 0
reflog = []
cdef log(level, action, obj, lineno):
if loglevel >= level:
reflog.append((lineno, action, id(obj)))
LOG_NONE, LOG_ALL = range(2)
class RefnannyException(Exception):
pass
class RefnannyContext(object):
def __init__(self):
self.refs = {} # id -> (count, [lineno])
self.errors = []
def regref(self, obj, lineno):
log(LOG_ALL, 'regref', obj, lineno)
id_ = id(obj)
count, linenumbers = self.refs.get(id_, (0, []))
self.refs[id_] = (count + 1, linenumbers)
linenumbers.append(lineno)
def delref(self, obj, lineno):
log(LOG_ALL, 'delref', obj, lineno)
id_ = id(obj)
count, linenumbers = self.refs.get(id_, (0, []))
if count == 0:
self.errors.append("Too many decrefs on line %d, reference acquired on lines %r" %
(lineno, linenumbers))
elif count == 1:
del self.refs[id_]
else:
self.refs[id_] = (count - 1, linenumbers)
def end(self):
if len(self.refs) > 0:
msg = ""
for count, linenos in self.refs.itervalues():
msg += "\n Acquired on lines: " + ", ".join(["%d" % x for x in linenos])
self.errors.append("References leaked: %s" % msg)
if self.errors:
raise RefnannyException("\n".join(self.errors))
cdef public void* __Pyx_Refnanny_NewContext(char* funcname, int lineno) except NULL:
ctx = RefnannyContext()
Py_INCREF(ctx)
return <void*>ctx
cdef public void __Pyx_Refnanny_GOTREF(void* ctx, object obj, int lineno):
if ctx == NULL: return
(<object>ctx).regref(obj, lineno)
cdef public void __Pyx_Refnanny_GIVEREF(void* ctx, object obj, int lineno):
if ctx == NULL: return
(<object>ctx).delref(obj, lineno)
cdef public void __Pyx_Refnanny_INCREF(void* ctx, object obj, int lineno):
Py_INCREF(obj)
__Pyx_Refnanny_GOTREF(ctx, obj, lineno)
cdef public void __Pyx_Refnanny_DECREF(void* ctx, object obj, int lineno):
# GIVEREF raises exception if we hit 0
#
__Pyx_Refnanny_GIVEREF(ctx, obj, lineno)
Py_DECREF(obj)
cdef public int __Pyx_Refnanny_FinishContext(void* ctx) except -1:
obj = <object>ctx
try:
obj.end()
finally:
Py_DECREF(obj)
return 0
#!/usr/bin/python #!/usr/bin/python
import os, sys, re, shutil, unittest, doctest import os, sys, re, shutil, unittest, doctest, ctypes
WITH_CYTHON = True WITH_CYTHON = True
...@@ -480,6 +480,9 @@ if __name__ == '__main__': ...@@ -480,6 +480,9 @@ if __name__ == '__main__':
parser.add_option("--cython-only", dest="cython_only", parser.add_option("--cython-only", dest="cython_only",
action="store_true", default=False, action="store_true", default=False,
help="only compile pyx to c, do not run C compiler or run the tests") help="only compile pyx to c, do not run C compiler or run the tests")
parser.add_option("--refnanny", dest="with_refnanny",
action="store_true", default=False,
help="also test that Cython-generated code does correct reference counting")
parser.add_option("--sys-pyregr", dest="system_pyregr", parser.add_option("--sys-pyregr", dest="system_pyregr",
action="store_true", default=False, action="store_true", default=False,
help="run the regression tests of the CPython installation") help="run the regression tests of the CPython installation")
...@@ -523,6 +526,13 @@ if __name__ == '__main__': ...@@ -523,6 +526,13 @@ if __name__ == '__main__':
from Cython.Compiler import Errors from Cython.Compiler import Errors
Errors.LEVEL = 0 # show all warnings Errors.LEVEL = 0 # show all warnings
if options.with_refnanny:
ctypes.PyDLL("Cython/Runtime/refnanny.so", mode=ctypes.RTLD_GLOBAL)
sys.path.append("Cython/Runtime")
import refnanny
del sys.path[-1]
CFLAGS.append("-DCYTHON_REFNANNY")
# RUN ALL TESTS! # RUN ALL TESTS!
ROOTDIR = os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), 'tests') ROOTDIR = os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), 'tests')
WORKDIR = os.path.join(os.getcwd(), 'BUILD') WORKDIR = os.path.join(os.getcwd(), 'BUILD')
...@@ -603,3 +613,6 @@ if __name__ == '__main__': ...@@ -603,3 +613,6 @@ if __name__ == '__main__':
sys.stderr.write("Following tests excluded because of missing dependencies on your system:\n") sys.stderr.write("Following tests excluded because of missing dependencies on your system:\n")
for test in missing_dep_excluder.tests_missing_deps: for test in missing_dep_excluder.tests_missing_deps:
sys.stderr.write(" %s\n" % test) sys.stderr.write(" %s\n" % test)
if options.with_refnanny:
sys.stderr.write("\n".join([repr(x) for x in refnanny.reflog]))
...@@ -384,6 +384,17 @@ def wrong_string(object[int] buf): ...@@ -384,6 +384,17 @@ def wrong_string(object[int] buf):
""" """
print buf[1] print buf[1]
@testcase
def int_and_long_are_same():
"""
>>> int_and_long_are_same()
"""
cdef object[int] intarr
cdef object[long] longarr
if sizeof(int) == sizeof(long):
intarr = IntMockBuffer(None, [1,2], format='l')
longarr = IntMockBuffer(None, [1,2])
# #
# Getting items and index bounds checking # Getting items and index bounds checking
# #
......
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