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