rhs = decorator_result)
return [func_node, reassignment]
+
+ERR_DEC_AFTER = "cdef variable '%s' declared after it's used."
class AnalyseDeclarationsTransform(CythonTransform):
basic_property = TreeFragment(u"""
def __call__(self, root):
self.env_stack = [root.scope]
+ # needed to determine if a cdef var is declared after it's used.
+ self.local_scope_stack = []
return super(AnalyseDeclarationsTransform, self).__call__(root)
+ def visit_NameNode(self, node):
+ self.local_scope_stack[-1].add(node.name)
+ return node
+
def visit_ModuleNode(self, node):
+ self.local_scope_stack.append(set())
node.analyse_declarations(self.env_stack[-1])
self.visitchildren(node)
+ self.local_scope_stack.pop()
return node
def visit_FuncDefNode(self, node):
+ self.local_scope_stack.append(set())
lenv = node.create_local_scope(self.env_stack[-1])
node.body.analyse_control_flow(lenv) # this will be totally refactored
node.declare_arguments(lenv)
self.env_stack.append(lenv)
self.visitchildren(node)
self.env_stack.pop()
+ self.local_scope_stack.pop()
return node
# Some nodes are no longer needed after declaration
# on these nodes in a seperate recursive process from the
# enclosing function or module, so we can simply drop them.
def visit_CDeclaratorNode(self, node):
+ # necessary to ensure that all CNameDeclaratorNodes are visited.
+ self.visitchildren(node)
return node
def visit_CTypeDefNode(self, node):
def visit_CStructOrUnionDefNode(self, node):
return None
+ def visit_CNameDeclaratorNode(self, node):
+ if node.name in self.local_scope_stack[-1]:
+ # cdef variable declared after it's used.
+ error(node.pos, ERR_DEC_AFTER % node.name)
+ self.visitchildren(node)
+ return node
+
def visit_CVarDefNode(self, node):
+
+ # to ensure all CNameDeclaratorNodes are visited.
+ self.visitchildren(node)
+
if node.need_properties:
# cdef public attributes may need type testing on
# assignment, so we create a property accesss
--- /dev/null
+def mult_decl_test():
+ print "%s" % vv
+ print "%s" % s
+ cdef str s, vv = "Test"
+
+def def_test():
+ cdef int j = 10
+ i[0] = j
+ cdef int *i = NULL # pointer variables are special case
+
+cdef cdef_test():
+ cdef int j = 10
+ i[0] = j
+ print "%d" % i[0]
+ cdef int *i = NULL
+
+cpdef cpdef_test():
+ cdef int j = 10
+ i[0] = j
+ print "%d" % i[0]
+ cdef int *i = NULL
+
+s.upper()
+cdef str s = "Test"
+
+class Foo(object):
+ def bar(self, x, y):
+ cdef unsigned long w = 20
+ z = w + t
+ cdef int t = 10
+
+cdef class Foo2(object):
+ print '%s' % r # check error inside class scope
+ cdef str r
+ def bar(self, x, y):
+ cdef unsigned long w = 20
+ self.r = c'r'
+ print self.r
+ z = w + g(t)
+ cdef int t = 10
+
+def g(x):
+ return x
+
+cdef int d = 20
+baz[0] = d
+cdef int *baz
+
+print var[0][0]
+cdef unsigned long long var[100][100]
+
+
+_ERRORS = u"""
+4:13: cdef variable 's' declared after it's used.
+4:16: cdef variable 'vv' declared after it's used.
+9:14: cdef variable 'i' declared after it's used.
+15:14: cdef variable 'i' declared after it's used.
+21:14: cdef variable 'i' declared after it's used.
+24:9: cdef variable 's' declared after it's used.
+30:17: cdef variable 't' declared after it's used.
+34:13: cdef variable 'r' declared after it's used.
+40:17: cdef variable 't' declared after it's used.
+47:10: cdef variable 'baz' declared after it's used.
+50:24: cdef variable 'var' declared after it's used.
+"""