Skip to content

Commit fea7ad6

Browse files
committed
implement "@cython.inline" decorator for functions
1 parent ebc39e3 commit fea7ad6

6 files changed

Lines changed: 45 additions & 5 deletions

File tree

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ Latest
99
Features added
1010
--------------
1111

12+
* The ``inline`` function modifier is available as a decorator
13+
``@cython.inline`` in pure mode.
14+
1215
* When cygdb is run in a virtualenv, it enables the same virtualenv
1316
inside of the debugger. Patch by Marc Abramowitz.
1417

Cython/Compiler/Nodes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,7 +2539,7 @@ def __init__(self, pos, **kwds):
25392539
self.num_required_kw_args = rk
25402540
self.num_required_args = r
25412541

2542-
def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None):
2542+
def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None, modifiers=None):
25432543
if self.star_arg:
25442544
error(self.star_arg.pos, "cdef function cannot have star argument")
25452545
if self.starstar_arg:
@@ -2588,7 +2588,7 @@ def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None):
25882588
with_gil = cfunc_type.with_gil,
25892589
nogil = cfunc_type.nogil)
25902590
return CFuncDefNode(self.pos,
2591-
modifiers = [],
2591+
modifiers = modifiers or [],
25922592
base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
25932593
declarator = declarator,
25942594
body = self.body,

Cython/Compiler/Options.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ def normalise_encoding_name(option_name, encoding):
206206
'binding' : bool,
207207
'cfunc' : None, # decorators do not take directive value
208208
'ccall' : None,
209+
'inline' : None,
209210
'cclass' : None,
210211
'returns' : type,
211212
'set_initial_path': str,
@@ -221,6 +222,7 @@ def normalise_encoding_name(option_name, encoding):
221222
directive_scopes = { # defaults to available everywhere
222223
# 'module', 'function', 'class', 'with statement'
223224
'final' : ('cclass', 'function'),
225+
'inline' : ('function',),
224226
'no_gc_clear' : ('cclass',),
225227
'internal' : ('cclass',),
226228
'autotestdict' : ('module',),

Cython/Compiler/ParseTreeTransforms.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,13 +2011,15 @@ def visit_ExprNode(self, node):
20112011
# In-place assignments can't happen within an expression.
20122012
return node
20132013

2014+
20142015
class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
20152016
"""
20162017
Adjust function and class definitions by the decorator directives:
20172018
20182019
@cython.cfunc
20192020
@cython.cclass
20202021
@cython.ccall
2022+
@cython.inline
20212023
"""
20222024

20232025
def visit_ModuleNode(self, node):
@@ -2034,15 +2036,22 @@ def visit_CompilerDirectivesNode(self, node):
20342036
return node
20352037

20362038
def visit_DefNode(self, node):
2039+
modifiers = []
2040+
if 'inline' in self.directives:
2041+
modifiers.append('inline')
20372042
if 'ccall' in self.directives:
2038-
node = node.as_cfunction(overridable=True, returns=self.directives.get('returns'))
2043+
node = node.as_cfunction(
2044+
overridable=True, returns=self.directives.get('returns'), modifiers=modifiers)
20392045
return self.visit(node)
20402046
if 'cfunc' in self.directives:
20412047
if self.in_py_class:
20422048
error(node.pos, "cfunc directive is not allowed here")
20432049
else:
2044-
node = node.as_cfunction(overridable=False, returns=self.directives.get('returns'))
2050+
node = node.as_cfunction(
2051+
overridable=False, returns=self.directives.get('returns'), modifiers=modifiers)
20452052
return self.visit(node)
2053+
if 'inline' in modifiers:
2054+
error(node.pos, "Python functions cannot be declared 'inline'")
20462055
self.visitchildren(node)
20472056
return node
20482057

docs/src/tutorial/pure.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ Use the ``@cython.cfunc`` decorator for :keyword:`cdef` functions
164164
and the ``@cython.ccall`` decorators for :keyword:`cpdef` functions
165165
respectively. To declare the argument types, use the
166166
``@cython.locals()`` decorator. For the return type, use
167-
``@cython.returns(a_type)``.
167+
``@cython.returns(a_type)``. The C ``inline`` modifier is available
168+
as ``@cython.inline`` decorator.
168169

169170
Here is an example of a :keyword:`cdef` function::
170171

tests/run/pure_py.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ def test_declare_c_types(n):
173173
#z02 = cython.declare(cython.doublecomplex, n+1j)
174174
#z03 = cython.declare(cython.longdoublecomplex, n+1j)
175175

176+
176177
@cython.ccall
177178
@cython.returns(cython.double)
178179
def c_call(x):
@@ -193,6 +194,30 @@ def c_call(x):
193194
"""
194195
return x
195196

197+
196198
def call_ccall(x):
197199
ret = c_call(x)
198200
return ret, cython.typeof(ret)
201+
202+
203+
@cython.cfunc
204+
@cython.inline
205+
@cython.returns(cython.double)
206+
def cdef_inline(x):
207+
"""
208+
>>> result, return_type = call_cdef_inline(1)
209+
>>> (not is_compiled and 'float') or type(return_type).__name__
210+
'float'
211+
>>> (not is_compiled and 'double') or return_type
212+
'double'
213+
>>> (is_compiled and 'int') or return_type
214+
'int'
215+
>>> result == 2.0 or result
216+
True
217+
"""
218+
return x + 1
219+
220+
221+
def call_cdef_inline(x):
222+
ret = cdef_inline(x)
223+
return ret, cython.typeof(ret)

0 commit comments

Comments
 (0)