Commit 53c0810f authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Give compiler error on cdef assignments in class bodies, more comments.

parent 689f6281
......@@ -33,6 +33,7 @@ class CompileError(PyrexError):
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:
......@@ -88,17 +89,23 @@ def close_listing_file():
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
......
......@@ -329,8 +329,9 @@ class Context:
try:
for phase in pipeline:
data = phase(data)
except CompileError:
except CompileError, err:
errors_occurred = True
Errors.report_error(err)
return (errors_occurred, data)
def create_parse(context):
......
......@@ -388,7 +388,7 @@ class CNameDeclaratorNode(CDeclaratorNode):
self.default.release_temp(env)
def generate_execution_code(self, code):
assert self.default is None
raise RuntimeError("Deprecated")
# PostParse creates assignment statements for any
# default values
......
......@@ -82,6 +82,7 @@ ERR_BUF_DUP = '"%s" buffer option already supplied'
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):
"""
......@@ -92,7 +93,8 @@ 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
......@@ -103,9 +105,28 @@ class PostParse(CythonTransform):
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:
......@@ -113,13 +134,15 @@ class PostParse(CythonTransform):
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 = {}
......
cdef class A:
cdef int value = 3
_ERRORS = u"""
2:13: Cannot assign default value to cdef class attributes
"""
__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():
......
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