Commit 4b4d3f43 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Inline function definitions in pxd files

parent 55ac39ee
......@@ -757,8 +757,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_cfunction_predeclarations(self, env, code, definition):
for entry in env.cfunc_entries:
if not entry.in_cinclude and (definition
or entry.defined_in_pxd or entry.visibility == 'extern'):
if entry.inline_func_in_pxd or (not entry.in_cinclude and (definition
or entry.defined_in_pxd or entry.visibility == 'extern')):
if entry.visibility in ('public', 'extern'):
dll_linkage = "DL_EXPORT"
else:
......
......@@ -1212,9 +1212,12 @@ class CFuncDefNode(FuncDefNode):
# type CFuncType
# py_func wrapper for calling from Python
# overridable whether or not this is a cpdef function
# inline_in_pxd whether this is an inline function in a pxd file
child_attrs = ["base_type", "declarator", "body", "py_func"]
inline_in_pxd = False
def unqualified_name(self):
return self.entry.name
......@@ -1251,6 +1254,7 @@ class CFuncDefNode(FuncDefNode):
cname = cname, visibility = self.visibility,
defining = self.body is not None,
api = self.api, modifiers = self.modifiers)
self.entry.inline_func_in_pxd = self.inline_in_pxd
self.return_type = type.return_type
if self.overridable:
......
......@@ -212,8 +212,12 @@ class PxdPostParse(CythonTransform):
- "def" functions are let through only if they fill the
getbuffer/releasebuffer slots
- cdef functions are let through only if they are on the
top level and are declared "inline"
"""
ERR_FUNCDEF_NOT_ALLOWED = 'function definition not allowed here'
ERR_INLINE_ONLY = "function definition in pxd file must be declared 'cdef inline'"
ERR_NOGO_WITH_INLINE = "inline function definition in pxd file cannot be '%s'"
def __call__(self, node):
self.scope_type = 'pxd'
......@@ -229,30 +233,37 @@ class PxdPostParse(CythonTransform):
def visit_FuncDefNode(self, node):
# FuncDefNode always come with an implementation (without
# an imp they are CVarDefNodes..)
ok = False
err = self.ERR_INLINE_ONLY
if (isinstance(node, DefNode) and self.scope_type == 'cclass'
and node.name in ('__getbuffer__', '__releasebuffer__')):
ok = True
err = None # allow these slots
if isinstance(node, CFuncDefNode):
ok = True
for stat in node.body.stats:
if not isinstance(stat, CVarDefNode):
ok = False
break
node = CVarDefNode(node.pos,
visibility = node.visibility,
base_type = node.base_type,
declarators = [node.declarator],
in_pxd = True,
api = node.api,
overridable = node.overridable,
pxd_locals = node.body.stats)
if not ok:
self.context.nonfatal_error(PostParseError(node.pos,
self.ERR_FUNCDEF_NOT_ALLOWED))
if u'inline' in node.modifiers and self.scope_type == 'pxd':
node.inline_in_pxd = True
if node.visibility != 'private':
err = self.ERR_NOGO_WITH_INLINE % node.visibility
elif node.api:
err = self.ERR_NOGO_WITH_INLINE % 'api'
else:
err = None # allow inline function
else:
err = None
for stat in node.body.stats:
if not isinstance(stat, CVarDefNode):
err = self.ERR_INLINE_ONLY
break
node = CVarDefNode(node.pos,
visibility = node.visibility,
base_type = node.base_type,
declarators = [node.declarator],
in_pxd = True,
api = node.api,
overridable = node.overridable,
pxd_locals = node.body.stats)
if err:
self.context.nonfatal_error(PostParseError(node.pos, err))
return None
else:
return node
......
......@@ -97,7 +97,10 @@ class Entry:
# utility_code string Utility code needed when this entry is used
#
# buffer_aux BufferAux or None Extra information needed for buffer variables
# inline_func_in_pxd boolean Hacky special case for inline function in pxd file.
# Ideally this should not be necesarry.
inline_func_in_pxd = False
borrowed = 0
init = ""
visibility = 'private'
......
cimport e_func_in_pxd_support
_ERRORS = u"""
1:5: function definition not allowed here
1:5: function definition in pxd file must be declared 'cdef inline'
4:5: inline function definition in pxd file cannot be 'public'
7:5: inline function definition in pxd file cannot be 'api'
"""
cdef foo():
return 1
cdef public inline foo2():
return 1
cdef api inline foo3():
return 1
cdef inline int my_add(int a, int b):
return a + b
"""
>>> f()
3
>>> g()
6
>>> h()
6
"""
cimport inlinepxd_support
from inlinepxd_support cimport my_add as my_add3
def f():
return my_add(1, 2)
def g():
return inlinepxd_support.my_add(1, 2, 3)
def h():
return my_add3(1, 2, 3)
cdef inline int my_add(int a, int b, int c):
return a + b + c
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