def __init__(self, position = None, message = ""):
self.position = position
self.message_only = message
+ self.reported = False
# Deprecated and withdrawn in 2.6:
# self.message = message
if position:
listing_file.close()
listing_file = None
-def error(position, message):
- #print "Errors.error:", repr(position), repr(message) ###
+def report_error(err):
global num_errors
- err = CompileError(position, message)
-# if position is not None: raise Exception(err) # debug
+ # See Main.py for why dual reporting occurs. Quick fix for now.
+ if err.reported: return
+ err.reported = True
line = "%s\n" % err
if listing_file:
listing_file.write(line)
if echo_file:
echo_file.write(line)
num_errors = num_errors + 1
+
+def error(position, message):
+ #print "Errors.error:", repr(position), repr(message) ###
+ err = CompileError(position, message)
+# if position is not None: raise Exception(err) # debug
+ report_error(err)
return err
LEVEL=1 # warn about all errors level 1 or higher
ERR_BUF_MISSING = '"%s" missing'
ERR_BUF_INT = '"%s" must be an integer'
ERR_BUF_NONNEG = '"%s" must be non-negative'
+ERR_CDEF_INCLASS = 'Cannot assign default value to cdef class attributes'
class PostParse(CythonTransform):
"""
Specifically:
- Default values to cdef assignments are turned into single
- assignments following the declaration.
+ assignments following the declaration (everywhere but in class
+ bodies, where they raise a compile error)
- CBufferAccessTypeNode has its options interpreted:
Any first positional argument goes into the "dtype" attribute,
any "ndim" keyword argument goes into the "ndim" attribute and
if a more pure Abstract Syntax Tree is wanted.
"""
+ # Track our context.
+ in_class_body = False
+ def visit_ClassDefNode(self, node):
+ prev = self.in_class_body
+ self.in_class_body = True
+ self.visitchildren(node)
+ self.in_class_body = prev
+ return node
+
+ def visit_FuncDefNode(self, node):
+ prev = self.in_class_body
+ self.in_class_body = False
+ self.visitchildren(node)
+ self.in_class_body = prev
+ return node
+
+ # cdef variables
def visit_CVarDefNode(self, node):
# This assumes only plain names and pointers are assignable on
- # declaration.
+ # declaration. Also, it makes use of the fact that a cdef decl
+ # must appear before the first use, so we don't have to deal with
+ # "i = 3; cdef int i = i" and can simply move the nodes around.
self.visitchildren(node)
stats = [node]
for decl in node.declarators:
decl = decl.base
if isinstance(decl, CNameDeclaratorNode):
if decl.default is not None:
+ if self.in_class_body:
+ raise PostParseError(decl.pos, ERR_CDEF_INCLASS)
stats.append(SingleAssignmentNode(node.pos,
lhs=NameNode(node.pos, name=decl.name),
rhs=decl.default))
decl.default = None
return stats
-
+ # buffer access
buffer_options = ("dtype", "ndim") # ordered!
def visit_CBufferAccessTypeNode(self, node):
options = {}
__doc__ = """
>>> test(1, 2)
- 4 1 2 2 0
- >>> A().value
- 4
+ 4 1 2 2 0 7 8
"""
-cdef class A:
- cdef int value = 4
+cdef int g = 7
def test(x, int y):
if True:
before = 0
cdef int a = 4, b = x, c = y, *p = &y
- print a, b, c, p[0], before
+ cdef object o = int(8)
+ print a, b, c, p[0], before, g, o
# Also test that pruning cdefs doesn't hurt
def empty():