Commit 4b61e74c authored by Haoyu Bai's avatar Haoyu Bai

@cython.cfunc decorator

parent 1e4a346e
......@@ -108,7 +108,7 @@ class Context(object):
from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods
from ParseTreeTransforms import ExpandInplaceOperators
from TypeInference import MarkAssignments, MarkOverflowingArithmetic
from ParseTreeTransforms import AlignFunctionDefinitions, GilCheck
from ParseTreeTransforms import AdjustDefByDirectives, AlignFunctionDefinitions, GilCheck
from AnalysedTreeTransforms import AutoTestDictTransform
from AutoDocTransforms import EmbedSignature
from Optimize import FlattenInListTransform, SwitchTransform, IterationTransform
......@@ -135,6 +135,7 @@ class Context(object):
PostParse(self),
_specific_post_parse,
InterpretCompilerDirectives(self, self.compiler_directives),
AdjustDefByDirectives(self),
_align_function_definitions,
MarkClosureVisitor(self),
ConstantFolding(),
......
......@@ -1947,7 +1947,7 @@ class DefNode(FuncDefNode):
self.num_required_kw_args = rk
self.num_required_args = r
def as_cfunction(self, cfunc=None, scope=None):
def as_cfunction(self, cfunc=None, scope=None, overridable=True):
if self.star_arg:
error(self.star_arg.pos, "cdef function cannot have star argument")
if self.starstar_arg:
......@@ -1967,7 +1967,7 @@ class DefNode(FuncDefNode):
exception_check = False,
nogil = False,
with_gil = False,
is_overridable = True)
is_overridable = overridable)
cfunc = CVarDefNode(self.pos, type=cfunc_type)
else:
if scope is None:
......
......@@ -95,6 +95,7 @@ directive_types = {
'final' : bool, # final cdef classes and methods
'internal' : bool, # cdef class visibility in the module dict
'infer_types' : bool, # values can be True/None/False
'cfunc' : None, # decorators do not take directive value
}
for key, val in directive_defaults.items():
......
......@@ -1378,6 +1378,51 @@ class ExpandInplaceOperators(EnvTransform):
# In-place assignments can't happen within an expression.
return node
class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
"""
Adjust function and class definitions by the decorator directives:
@cython.cfunc
@cython.cclass
@cython.ccall
"""
def visit_ModuleNode(self, node):
self.directives = node.directives
self.in_py_class = False
self.visitchildren(node)
return node
def visit_CompilerDirectivesNode(self, node):
old_directives = self.directives
self.directives = node.directives
self.visitchildren(node)
self.directives = old_directives
return node
def visit_DefNode(self, node):
if 'cfunc' in self.directives:
if self.in_py_class:
error(node.pos, "cfunc directive is not allowed here")
else:
node = node.as_cfunction(overridable=False)
return self.visit(node)
self.visitchildren(node)
return node
def visit_PyClassDefNode(self, node):
old_in_pyclass = self.in_py_class
self.in_py_class = True
self.visitchildren(node)
self.in_py_class = old_in_pyclass
return node
def visit_CClassDefNode(self, node):
old_in_pyclass = self.in_py_class
self.in_py_class = False
self.visitchildren(node)
self.in_py_class = old_in_pyclass
return node
class AlignFunctionDefinitions(CythonTransform):
"""
......
......@@ -1711,7 +1711,7 @@ def p_statement(s, ctx, first_statement = 0):
elif s.sy == 'IF':
return p_IF_statement(s, ctx)
elif s.sy == 'DECORATOR':
if ctx.level not in ('module', 'class', 'c_class', 'function', 'property', 'module_pxd', 'c_class_pxd'):
if ctx.level not in ('module', 'class', 'c_class', 'function', 'property', 'module_pxd', 'c_class_pxd', 'other'):
s.error('decorator not allowed here')
s.level = ctx.level
decorators = p_decorators(s)
......
......@@ -23,6 +23,8 @@ class _EmptyDecoratorAndManager(object):
def __exit__(self, exc_type, exc_value, traceback):
pass
cfunc = _EmptyDecoratorAndManager()
def inline(f, *args, **kwds):
if isinstance(f, basestring):
from Cython.Build.Inline import cython_inline
......
import cython
from cython import cfunc
@cython.test_assert_path_exists('//CFuncDefNode')
@cython.cfunc
def ftang():
x = 0
@cython.test_assert_path_exists('//CFuncDefNode')
@cfunc
def fpure(a):
return a*2
def test():
"""
>>> test()
4
"""
ftang()
return fpure(2)
with cfunc:
@cython.test_assert_path_exists('//CFuncDefNode')
def fwith1(a):
return a*3
@cython.test_assert_path_exists('//CFuncDefNode')
def fwith2(a):
return a*4
def test_with():
"""
>>> test_with()
(3, 4)
"""
return fwith1(1), fwith2(1)
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