Commit 5f3824b8 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents 0ee7c0c9 6a6f9b58
......@@ -10,7 +10,7 @@ debug_temp_code_comments = 0
debug_trace_code_generation = 0
# Do not replace exceptions with user-friendly error messages
debug_no_exception_intercept = 1
debug_no_exception_intercept = 0
# Print a message each time a new stage in the pipeline is entered
debug_verbose_pipeline = 0
......@@ -3177,7 +3177,7 @@ class SequenceNode(ExprNode):
arg.py_result(),
target_list, target_list))
# resize the list the hard way
code.putln("((PyListObject*)%s)->ob_size--;" % target_list)
code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
code.put_gotref(arg.py_result())
coerced_arg.generate_evaluation_code(code)
......
......@@ -2477,6 +2477,7 @@ class PyClassDefNode(ClassDefNode):
# body StatNode Attribute definition code
# entry Symtab.Entry
# scope PyClassScope
# decorators [DecoratorNode] list of decorators or None
#
# The following subnodes are constructed internally:
#
......@@ -2485,12 +2486,14 @@ class PyClassDefNode(ClassDefNode):
# target NameNode Variable to assign class object to
child_attrs = ["body", "dict", "classobj", "target"]
decorators = None
def __init__(self, pos, name, bases, doc, body):
def __init__(self, pos, name, bases, doc, body, decorators = None):
StatNode.__init__(self, pos)
self.name = name
self.doc = doc
self.body = body
self.decorators = decorators
import ExprNodes
self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
if self.doc and Options.docstrings:
......@@ -2536,6 +2539,7 @@ class PyClassDefNode(ClassDefNode):
class_name = self.name,
base_class_module = base_class_module,
base_class_name = base_class_name,
decorators = self.decorators,
body = self.body,
in_pxd = False,
doc = self.doc)
......@@ -2592,6 +2596,7 @@ class CClassDefNode(ClassDefNode):
# objstruct_name string or None Specified C name of object struct
# typeobj_name string or None Specified C name of type object
# in_pxd boolean Is in a .pxd file
# decorators [DecoratorNode] list of decorators or None
# doc string or None
# body StatNode or None
# entry Symtab.Entry
......@@ -2606,6 +2611,7 @@ class CClassDefNode(ClassDefNode):
api = False
objstruct_name = None
typeobj_name = None
decorators = None
def analyse_declarations(self, env):
#print "CClassDefNode.analyse_declarations:", self.class_name
......
......@@ -148,13 +148,16 @@ class IterationTransform(Visitor.VisitorTransform):
# nothing we can do here, I guess
return node
temp = UtilNodes.LetRefNode(ExprNodes.IntNode(enumerate_function.pos, value='0',
type=counter_type))
temp = UtilNodes.LetRefNode(ExprNodes.IntNode(enumerate_function.pos,
value='0',
type=counter_type,
constant_result=0))
inc_expression = ExprNodes.AddNode(
enumerate_function.pos,
operand1 = temp,
operand2 = ExprNodes.IntNode(node.pos, value='1',
type=counter_type),
type=counter_type,
constant_result=1),
operator = '+',
type = counter_type,
is_temp = counter_type.is_pyobject
......@@ -190,7 +193,8 @@ class IterationTransform(Visitor.VisitorTransform):
if len(args) < 3:
step_pos = range_function.pos
step_value = 1
step = ExprNodes.IntNode(step_pos, value=1)
step = ExprNodes.IntNode(step_pos, value='1',
constant_result=1)
else:
step = args[2]
step_pos = step.pos
......@@ -202,7 +206,8 @@ class IterationTransform(Visitor.VisitorTransform):
# will lead to an error elsewhere
return node
if not isinstance(step, ExprNodes.IntNode):
step = ExprNodes.IntNode(step_pos, value=step_value)
step = ExprNodes.IntNode(step_pos, value=str(step_value),
constant_result=step_value)
if step_value < 0:
step.value = -step_value
......@@ -213,7 +218,8 @@ class IterationTransform(Visitor.VisitorTransform):
relation2 = '<'
if len(args) == 1:
bound1 = ExprNodes.IntNode(range_function.pos, value=0)
bound1 = ExprNodes.IntNode(range_function.pos, value='0',
constant_result=0)
bound2 = args[0].coerce_to_integer(self.current_scope)
else:
bound1 = args[0].coerce_to_integer(self.current_scope)
......@@ -350,7 +356,8 @@ class IterationTransform(Visitor.VisitorTransform):
Nodes.SingleAssignmentNode(
pos = node.pos,
lhs = pos_temp,
rhs = ExprNodes.IntNode(node.pos, value=0)),
rhs = ExprNodes.IntNode(node.pos, value='0',
constant_result=0)),
Nodes.WhileStatNode(
pos = node.pos,
condition = ExprNodes.SimpleCallNode(
......
......@@ -597,22 +597,48 @@ class WithTransform(CythonTransform, SkipDeclarations):
class DecoratorTransform(CythonTransform, SkipDeclarations):
def visit_DefNode(self, func_node):
self.visitchildren(func_node)
if not func_node.decorators:
return func_node
decorator_result = NameNode(func_node.pos, name = func_node.name)
for decorator in func_node.decorators[::-1]:
return self._handle_decorators(
func_node, func_node.name)
def _visit_CClassDefNode(self, class_node):
# This doesn't currently work, so it's disabled (also in the
# parser).
#
# Problem: assignments to cdef class names do not work. They
# would require an additional check anyway, as the extension
# type must not change its C type, so decorators cannot
# replace an extension type, just alter it and return it.
self.visitchildren(class_node)
if not class_node.decorators:
return class_node
return self._handle_decorators(
class_node, class_node.class_name)
def visit_ClassDefNode(self, class_node):
self.visitchildren(class_node)
if not class_node.decorators:
return class_node
return self._handle_decorators(
class_node, class_node.name)
def _handle_decorators(self, node, name):
decorator_result = NameNode(node.pos, name = name)
for decorator in node.decorators[::-1]:
decorator_result = SimpleCallNode(
decorator.pos,
function = decorator.decorator,
args = [decorator_result])
func_name_node = NameNode(func_node.pos, name = func_node.name)
name_node = NameNode(node.pos, name = name)
reassignment = SingleAssignmentNode(
func_node.pos,
lhs = func_name_node,
node.pos,
lhs = name_node,
rhs = decorator_result)
return [func_node, reassignment]
return [node, reassignment]
class AnalyseDeclarationsTransform(CythonTransform):
......
......@@ -141,7 +141,7 @@ cpdef p_ctypedef_statement(PyrexScanner s, ctx)
cpdef p_decorators(PyrexScanner s)
cpdef p_def_statement(PyrexScanner s, decorators = *)
cpdef p_py_arg_decl(PyrexScanner s)
cpdef p_class_statement(PyrexScanner s)
cpdef p_class_statement(PyrexScanner s, decorators = *)
cpdef p_c_class_definition(PyrexScanner s, pos, ctx)
cpdef p_c_class_options(PyrexScanner s)
cpdef p_property_decl(PyrexScanner s)
......
......@@ -1574,8 +1574,8 @@ def p_statement(s, ctx, first_statement = 0):
s.error('decorator not allowed here')
s.level = ctx.level
decorators = p_decorators(s)
if s.sy not in ('def', 'cdef', 'cpdef'):
s.error("Decorators can only be followed by functions ")
if s.sy not in ('def', 'cdef', 'cpdef', 'class'):
s.error("Decorators can only be followed by functions or classes")
elif s.sy == 'pass' and cdef_flag:
# empty cdef block
return p_pass_statement(s, with_newline = 1)
......@@ -1595,7 +1595,7 @@ def p_statement(s, ctx, first_statement = 0):
node = p_cdef_statement(s, ctx(overridable = overridable))
if decorators is not None:
if not isinstance(node, (Nodes.CFuncDefNode, Nodes.CVarDefNode)):
s.error("Decorators can only be followed by functions ")
s.error("Decorators can only be followed by functions or Python classes")
node.decorators = decorators
return node
else:
......@@ -1609,7 +1609,7 @@ def p_statement(s, ctx, first_statement = 0):
elif s.sy == 'class':
if ctx.level != 'module':
s.error("class definition not allowed here")
return p_class_statement(s)
return p_class_statement(s, decorators)
elif s.sy == 'include':
if ctx.level not in ('module', 'module_pxd'):
s.error("include statement not allowed here")
......@@ -2426,7 +2426,7 @@ def p_py_arg_decl(s):
name = p_ident(s)
return Nodes.PyArgDeclNode(pos, name = name)
def p_class_statement(s):
def p_class_statement(s, decorators):
# s.sy == 'class'
pos = s.position()
s.next()
......@@ -2442,7 +2442,7 @@ def p_class_statement(s):
return Nodes.PyClassDefNode(pos,
name = class_name,
bases = ExprNodes.TupleNode(pos, args = base_list),
doc = doc, body = body)
doc = doc, body = body, decorators = decorators)
def p_c_class_definition(s, pos, ctx):
# s.sy == 'class'
......
__doc__ = u"""
>>> print('\\n'.join(calls))
Py-Honk PyTestClass
PyTestClass
Py-Hello PyTestClass
PyTestClass
Py-Done PyTestClass
>>> c = PyTestClass()
Ho, Ho, Ho!
"""
calls = []
class print_msg(object):
def __init__(self, message):
self.msg = message
def __call__(self, c):
calls.append( self.msg + c.__name__ )
return c
def print_name(c):
calls.append( c.__name__ )
return c
@print_msg(u"Py-Done ")
@print_name
@print_msg(u"Py-Hello ")
@print_name
@print_msg(u"Py-Honk ")
class PyTestClass(object):
def __init__(self):
print u"Ho, Ho, Ho!"
# not currently working:
#
## @print_msg("Cy-Done ")
## @print_name
## @print_msg("Cy-Hello ")
## @print_name
## @print_msg("Cy-Honk ")
## cdef class CyTestClass(object):
## def __init__(self):
## print u"Ho, Ho, Ho!"
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