Commit fea7ad6e authored by Stefan Behnel's avatar Stefan Behnel

implement "@cython.inline" decorator for functions

parent ebc39e39
...@@ -9,6 +9,9 @@ Latest ...@@ -9,6 +9,9 @@ Latest
Features added Features added
-------------- --------------
* The ``inline`` function modifier is available as a decorator
``@cython.inline`` in pure mode.
* When cygdb is run in a virtualenv, it enables the same virtualenv * When cygdb is run in a virtualenv, it enables the same virtualenv
inside of the debugger. Patch by Marc Abramowitz. inside of the debugger. Patch by Marc Abramowitz.
......
...@@ -2539,7 +2539,7 @@ class DefNode(FuncDefNode): ...@@ -2539,7 +2539,7 @@ class DefNode(FuncDefNode):
self.num_required_kw_args = rk self.num_required_kw_args = rk
self.num_required_args = r self.num_required_args = r
def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None): def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None, modifiers=None):
if self.star_arg: if self.star_arg:
error(self.star_arg.pos, "cdef function cannot have star argument") error(self.star_arg.pos, "cdef function cannot have star argument")
if self.starstar_arg: if self.starstar_arg:
...@@ -2588,7 +2588,7 @@ class DefNode(FuncDefNode): ...@@ -2588,7 +2588,7 @@ class DefNode(FuncDefNode):
with_gil = cfunc_type.with_gil, with_gil = cfunc_type.with_gil,
nogil = cfunc_type.nogil) nogil = cfunc_type.nogil)
return CFuncDefNode(self.pos, return CFuncDefNode(self.pos,
modifiers = [], modifiers = modifiers or [],
base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type), base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
declarator = declarator, declarator = declarator,
body = self.body, body = self.body,
......
...@@ -206,6 +206,7 @@ directive_types = { ...@@ -206,6 +206,7 @@ directive_types = {
'binding' : bool, 'binding' : bool,
'cfunc' : None, # decorators do not take directive value 'cfunc' : None, # decorators do not take directive value
'ccall' : None, 'ccall' : None,
'inline' : None,
'cclass' : None, 'cclass' : None,
'returns' : type, 'returns' : type,
'set_initial_path': str, 'set_initial_path': str,
...@@ -221,6 +222,7 @@ for key, val in directive_defaults.items(): ...@@ -221,6 +222,7 @@ for key, val in directive_defaults.items():
directive_scopes = { # defaults to available everywhere directive_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement' # 'module', 'function', 'class', 'with statement'
'final' : ('cclass', 'function'), 'final' : ('cclass', 'function'),
'inline' : ('function',),
'no_gc_clear' : ('cclass',), 'no_gc_clear' : ('cclass',),
'internal' : ('cclass',), 'internal' : ('cclass',),
'autotestdict' : ('module',), 'autotestdict' : ('module',),
......
...@@ -2011,6 +2011,7 @@ class ExpandInplaceOperators(EnvTransform): ...@@ -2011,6 +2011,7 @@ class ExpandInplaceOperators(EnvTransform):
# In-place assignments can't happen within an expression. # In-place assignments can't happen within an expression.
return node return node
class AdjustDefByDirectives(CythonTransform, SkipDeclarations): class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
""" """
Adjust function and class definitions by the decorator directives: Adjust function and class definitions by the decorator directives:
...@@ -2018,6 +2019,7 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations): ...@@ -2018,6 +2019,7 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
@cython.cfunc @cython.cfunc
@cython.cclass @cython.cclass
@cython.ccall @cython.ccall
@cython.inline
""" """
def visit_ModuleNode(self, node): def visit_ModuleNode(self, node):
...@@ -2034,15 +2036,22 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations): ...@@ -2034,15 +2036,22 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
return node return node
def visit_DefNode(self, node): def visit_DefNode(self, node):
modifiers = []
if 'inline' in self.directives:
modifiers.append('inline')
if 'ccall' in self.directives: if 'ccall' in self.directives:
node = node.as_cfunction(overridable=True, returns=self.directives.get('returns')) node = node.as_cfunction(
overridable=True, returns=self.directives.get('returns'), modifiers=modifiers)
return self.visit(node) return self.visit(node)
if 'cfunc' in self.directives: if 'cfunc' in self.directives:
if self.in_py_class: if self.in_py_class:
error(node.pos, "cfunc directive is not allowed here") error(node.pos, "cfunc directive is not allowed here")
else: else:
node = node.as_cfunction(overridable=False, returns=self.directives.get('returns')) node = node.as_cfunction(
overridable=False, returns=self.directives.get('returns'), modifiers=modifiers)
return self.visit(node) return self.visit(node)
if 'inline' in modifiers:
error(node.pos, "Python functions cannot be declared 'inline'")
self.visitchildren(node) self.visitchildren(node)
return node return node
......
...@@ -164,7 +164,8 @@ Use the ``@cython.cfunc`` decorator for :keyword:`cdef` functions ...@@ -164,7 +164,8 @@ Use the ``@cython.cfunc`` decorator for :keyword:`cdef` functions
and the ``@cython.ccall`` decorators for :keyword:`cpdef` functions and the ``@cython.ccall`` decorators for :keyword:`cpdef` functions
respectively. To declare the argument types, use the respectively. To declare the argument types, use the
``@cython.locals()`` decorator. For the return type, use ``@cython.locals()`` decorator. For the return type, use
``@cython.returns(a_type)``. ``@cython.returns(a_type)``. The C ``inline`` modifier is available
as ``@cython.inline`` decorator.
Here is an example of a :keyword:`cdef` function:: Here is an example of a :keyword:`cdef` function::
......
...@@ -173,6 +173,7 @@ def test_declare_c_types(n): ...@@ -173,6 +173,7 @@ def test_declare_c_types(n):
#z02 = cython.declare(cython.doublecomplex, n+1j) #z02 = cython.declare(cython.doublecomplex, n+1j)
#z03 = cython.declare(cython.longdoublecomplex, n+1j) #z03 = cython.declare(cython.longdoublecomplex, n+1j)
@cython.ccall @cython.ccall
@cython.returns(cython.double) @cython.returns(cython.double)
def c_call(x): def c_call(x):
...@@ -193,6 +194,30 @@ def c_call(x): ...@@ -193,6 +194,30 @@ def c_call(x):
""" """
return x return x
def call_ccall(x): def call_ccall(x):
ret = c_call(x) ret = c_call(x)
return ret, cython.typeof(ret) return ret, cython.typeof(ret)
@cython.cfunc
@cython.inline
@cython.returns(cython.double)
def cdef_inline(x):
"""
>>> result, return_type = call_cdef_inline(1)
>>> (not is_compiled and 'float') or type(return_type).__name__
'float'
>>> (not is_compiled and 'double') or return_type
'double'
>>> (is_compiled and 'int') or return_type
'int'
>>> result == 2.0 or result
True
"""
return x + 1
def call_cdef_inline(x):
ret = cdef_inline(x)
return ret, cython.typeof(ret)
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