Commit 18469076 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents daa3f7f7 3a955f5c
...@@ -10,7 +10,7 @@ debug_temp_code_comments = 0 ...@@ -10,7 +10,7 @@ debug_temp_code_comments = 0
debug_trace_code_generation = 0 debug_trace_code_generation = 0
# Do not replace exceptions with user-friendly error messages # 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 # Print a message each time a new stage in the pipeline is entered
debug_verbose_pipeline = 0 debug_verbose_pipeline = 0
...@@ -2477,6 +2477,7 @@ class PyClassDefNode(ClassDefNode): ...@@ -2477,6 +2477,7 @@ class PyClassDefNode(ClassDefNode):
# body StatNode Attribute definition code # body StatNode Attribute definition code
# entry Symtab.Entry # entry Symtab.Entry
# scope PyClassScope # scope PyClassScope
# decorators [DecoratorNode] list of decorators or None
# #
# The following subnodes are constructed internally: # The following subnodes are constructed internally:
# #
...@@ -2485,12 +2486,14 @@ class PyClassDefNode(ClassDefNode): ...@@ -2485,12 +2486,14 @@ class PyClassDefNode(ClassDefNode):
# target NameNode Variable to assign class object to # target NameNode Variable to assign class object to
child_attrs = ["body", "dict", "classobj", "target"] 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) StatNode.__init__(self, pos)
self.name = name self.name = name
self.doc = doc self.doc = doc
self.body = body self.body = body
self.decorators = decorators
import ExprNodes import ExprNodes
self.dict = ExprNodes.DictNode(pos, key_value_pairs = []) self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
if self.doc and Options.docstrings: if self.doc and Options.docstrings:
...@@ -2536,6 +2539,7 @@ class PyClassDefNode(ClassDefNode): ...@@ -2536,6 +2539,7 @@ class PyClassDefNode(ClassDefNode):
class_name = self.name, class_name = self.name,
base_class_module = base_class_module, base_class_module = base_class_module,
base_class_name = base_class_name, base_class_name = base_class_name,
decorators = self.decorators,
body = self.body, body = self.body,
in_pxd = False, in_pxd = False,
doc = self.doc) doc = self.doc)
...@@ -2592,6 +2596,7 @@ class CClassDefNode(ClassDefNode): ...@@ -2592,6 +2596,7 @@ class CClassDefNode(ClassDefNode):
# objstruct_name string or None Specified C name of object struct # objstruct_name string or None Specified C name of object struct
# typeobj_name string or None Specified C name of type object # typeobj_name string or None Specified C name of type object
# in_pxd boolean Is in a .pxd file # in_pxd boolean Is in a .pxd file
# decorators [DecoratorNode] list of decorators or None
# doc string or None # doc string or None
# body StatNode or None # body StatNode or None
# entry Symtab.Entry # entry Symtab.Entry
...@@ -2606,6 +2611,7 @@ class CClassDefNode(ClassDefNode): ...@@ -2606,6 +2611,7 @@ class CClassDefNode(ClassDefNode):
api = False api = False
objstruct_name = None objstruct_name = None
typeobj_name = None typeobj_name = None
decorators = None
def analyse_declarations(self, env): def analyse_declarations(self, env):
#print "CClassDefNode.analyse_declarations:", self.class_name #print "CClassDefNode.analyse_declarations:", self.class_name
......
...@@ -148,13 +148,16 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -148,13 +148,16 @@ class IterationTransform(Visitor.VisitorTransform):
# nothing we can do here, I guess # nothing we can do here, I guess
return node return node
temp = UtilNodes.LetRefNode(ExprNodes.IntNode(enumerate_function.pos, value='0', temp = UtilNodes.LetRefNode(ExprNodes.IntNode(enumerate_function.pos,
type=counter_type)) value='0',
type=counter_type,
constant_result=0))
inc_expression = ExprNodes.AddNode( inc_expression = ExprNodes.AddNode(
enumerate_function.pos, enumerate_function.pos,
operand1 = temp, operand1 = temp,
operand2 = ExprNodes.IntNode(node.pos, value='1', operand2 = ExprNodes.IntNode(node.pos, value='1',
type=counter_type), type=counter_type,
constant_result=1),
operator = '+', operator = '+',
type = counter_type, type = counter_type,
is_temp = counter_type.is_pyobject is_temp = counter_type.is_pyobject
...@@ -190,7 +193,8 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -190,7 +193,8 @@ class IterationTransform(Visitor.VisitorTransform):
if len(args) < 3: if len(args) < 3:
step_pos = range_function.pos step_pos = range_function.pos
step_value = 1 step_value = 1
step = ExprNodes.IntNode(step_pos, value=1) step = ExprNodes.IntNode(step_pos, value='1',
constant_result=1)
else: else:
step = args[2] step = args[2]
step_pos = step.pos step_pos = step.pos
...@@ -202,7 +206,8 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -202,7 +206,8 @@ class IterationTransform(Visitor.VisitorTransform):
# will lead to an error elsewhere # will lead to an error elsewhere
return node return node
if not isinstance(step, ExprNodes.IntNode): 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: if step_value < 0:
step.value = -step_value step.value = -step_value
...@@ -213,7 +218,8 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -213,7 +218,8 @@ class IterationTransform(Visitor.VisitorTransform):
relation2 = '<' relation2 = '<'
if len(args) == 1: 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) bound2 = args[0].coerce_to_integer(self.current_scope)
else: else:
bound1 = args[0].coerce_to_integer(self.current_scope) bound1 = args[0].coerce_to_integer(self.current_scope)
...@@ -350,7 +356,8 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -350,7 +356,8 @@ class IterationTransform(Visitor.VisitorTransform):
Nodes.SingleAssignmentNode( Nodes.SingleAssignmentNode(
pos = node.pos, pos = node.pos,
lhs = pos_temp, lhs = pos_temp,
rhs = ExprNodes.IntNode(node.pos, value=0)), rhs = ExprNodes.IntNode(node.pos, value='0',
constant_result=0)),
Nodes.WhileStatNode( Nodes.WhileStatNode(
pos = node.pos, pos = node.pos,
condition = ExprNodes.SimpleCallNode( condition = ExprNodes.SimpleCallNode(
......
...@@ -597,22 +597,48 @@ class WithTransform(CythonTransform, SkipDeclarations): ...@@ -597,22 +597,48 @@ class WithTransform(CythonTransform, SkipDeclarations):
class DecoratorTransform(CythonTransform, SkipDeclarations): class DecoratorTransform(CythonTransform, SkipDeclarations):
def visit_DefNode(self, func_node): def visit_DefNode(self, func_node):
self.visitchildren(func_node)
if not func_node.decorators: if not func_node.decorators:
return func_node return func_node
return self._handle_decorators(
decorator_result = NameNode(func_node.pos, name = func_node.name) func_node, func_node.name)
for decorator in func_node.decorators[::-1]:
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_result = SimpleCallNode(
decorator.pos, decorator.pos,
function = decorator.decorator, function = decorator.decorator,
args = [decorator_result]) args = [decorator_result])
func_name_node = NameNode(func_node.pos, name = func_node.name) name_node = NameNode(node.pos, name = name)
reassignment = SingleAssignmentNode( reassignment = SingleAssignmentNode(
func_node.pos, node.pos,
lhs = func_name_node, lhs = name_node,
rhs = decorator_result) rhs = decorator_result)
return [func_node, reassignment] return [node, reassignment]
class AnalyseDeclarationsTransform(CythonTransform): class AnalyseDeclarationsTransform(CythonTransform):
......
...@@ -141,7 +141,7 @@ cpdef p_ctypedef_statement(PyrexScanner s, ctx) ...@@ -141,7 +141,7 @@ cpdef p_ctypedef_statement(PyrexScanner s, ctx)
cpdef p_decorators(PyrexScanner s) cpdef p_decorators(PyrexScanner s)
cpdef p_def_statement(PyrexScanner s, decorators = *) cpdef p_def_statement(PyrexScanner s, decorators = *)
cpdef p_py_arg_decl(PyrexScanner s) 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_definition(PyrexScanner s, pos, ctx)
cpdef p_c_class_options(PyrexScanner s) cpdef p_c_class_options(PyrexScanner s)
cpdef p_property_decl(PyrexScanner s) cpdef p_property_decl(PyrexScanner s)
......
...@@ -1574,8 +1574,8 @@ def p_statement(s, ctx, first_statement = 0): ...@@ -1574,8 +1574,8 @@ def p_statement(s, ctx, first_statement = 0):
s.error('decorator not allowed here') s.error('decorator not allowed here')
s.level = ctx.level s.level = ctx.level
decorators = p_decorators(s) decorators = p_decorators(s)
if s.sy not in ('def', 'cdef', 'cpdef'): if s.sy not in ('def', 'cdef', 'cpdef', 'class'):
s.error("Decorators can only be followed by functions ") s.error("Decorators can only be followed by functions or classes")
elif s.sy == 'pass' and cdef_flag: elif s.sy == 'pass' and cdef_flag:
# empty cdef block # empty cdef block
return p_pass_statement(s, with_newline = 1) return p_pass_statement(s, with_newline = 1)
...@@ -1595,7 +1595,7 @@ def p_statement(s, ctx, first_statement = 0): ...@@ -1595,7 +1595,7 @@ def p_statement(s, ctx, first_statement = 0):
node = p_cdef_statement(s, ctx(overridable = overridable)) node = p_cdef_statement(s, ctx(overridable = overridable))
if decorators is not None: if decorators is not None:
if not isinstance(node, (Nodes.CFuncDefNode, Nodes.CVarDefNode)): 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 node.decorators = decorators
return node return node
else: else:
...@@ -1609,7 +1609,7 @@ def p_statement(s, ctx, first_statement = 0): ...@@ -1609,7 +1609,7 @@ def p_statement(s, ctx, first_statement = 0):
elif s.sy == 'class': elif s.sy == 'class':
if ctx.level != 'module': if ctx.level != 'module':
s.error("class definition not allowed here") s.error("class definition not allowed here")
return p_class_statement(s) return p_class_statement(s, decorators)
elif s.sy == 'include': elif s.sy == 'include':
if ctx.level not in ('module', 'module_pxd'): if ctx.level not in ('module', 'module_pxd'):
s.error("include statement not allowed here") s.error("include statement not allowed here")
...@@ -2426,7 +2426,7 @@ def p_py_arg_decl(s): ...@@ -2426,7 +2426,7 @@ def p_py_arg_decl(s):
name = p_ident(s) name = p_ident(s)
return Nodes.PyArgDeclNode(pos, name = name) return Nodes.PyArgDeclNode(pos, name = name)
def p_class_statement(s): def p_class_statement(s, decorators):
# s.sy == 'class' # s.sy == 'class'
pos = s.position() pos = s.position()
s.next() s.next()
...@@ -2442,7 +2442,7 @@ def p_class_statement(s): ...@@ -2442,7 +2442,7 @@ def p_class_statement(s):
return Nodes.PyClassDefNode(pos, return Nodes.PyClassDefNode(pos,
name = class_name, name = class_name,
bases = ExprNodes.TupleNode(pos, args = base_list), 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): def p_c_class_definition(s, pos, ctx):
# s.sy == 'class' # s.sy == 'class'
......
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