Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
a8305590
Commit
a8305590
authored
May 06, 2011
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support optional fused-typed arguments in cdef functions
parent
430ec7cf
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
90 additions
and
28 deletions
+90
-28
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+50
-17
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+23
-4
tests/run/fused_types.pyx
tests/run/fused_types.pyx
+7
-7
tests/run/public_fused_types.srctree
tests/run/public_fused_types.srctree
+10
-0
No files found.
Cython/Compiler/Nodes.py
View file @
a8305590
...
...
@@ -572,22 +572,6 @@ class CFuncDeclaratorNode(CDeclaratorNode):
elif
self
.
optional_arg_count
:
error
(
self
.
pos
,
"Non-default argument follows default argument"
)
if
self
.
optional_arg_count
:
scope
=
StructOrUnionScope
()
arg_count_member
=
'%sn'
%
Naming
.
pyrex_prefix
scope
.
declare_var
(
arg_count_member
,
PyrexTypes
.
c_int_type
,
self
.
pos
)
for
arg
in
func_type_args
[
len
(
func_type_args
)
-
self
.
optional_arg_count
:]:
scope
.
declare_var
(
arg
.
name
,
arg
.
type
,
arg
.
pos
,
allow_pyobject
=
1
)
struct_cname
=
env
.
mangle
(
Naming
.
opt_arg_prefix
,
self
.
base
.
name
)
self
.
op_args_struct
=
env
.
global_scope
().
declare_struct_or_union
(
name
=
struct_cname
,
kind
=
'struct'
,
scope
=
scope
,
typedef_flag
=
0
,
pos
=
self
.
pos
,
cname
=
struct_cname
)
self
.
op_args_struct
.
defined_in_pxd
=
1
self
.
op_args_struct
.
used
=
1
exc_val
=
None
exc_check
=
0
if
self
.
exception_check
==
'+'
:
...
...
@@ -629,8 +613,19 @@ class CFuncDeclaratorNode(CDeclaratorNode):
exception_value
=
exc_val
,
exception_check
=
exc_check
,
calling_convention
=
self
.
base
.
calling_convention
,
nogil
=
self
.
nogil
,
with_gil
=
self
.
with_gil
,
is_overridable
=
self
.
overridable
)
if
self
.
optional_arg_count
:
func_type
.
op_arg_struct
=
PyrexTypes
.
c_ptr_type
(
self
.
op_args_struct
.
type
)
if
func_type
.
is_fused
:
# This is a bit of a hack... When we need to create specialized CFuncTypes
# on the fly because the cdef is defined in a pxd, we need to declare the specialized optional arg
# struct
def
declare_opt_arg_struct
(
func_type
,
fused_cname
):
self
.
declare_optional_arg_struct
(
func_type
,
env
,
fused_cname
)
func_type
.
declare_opt_arg_struct
=
declare_opt_arg_struct
else
:
self
.
declare_optional_arg_struct
(
func_type
,
env
)
callspec
=
env
.
directives
[
'callspec'
]
if
callspec
:
current
=
func_type
.
calling_convention
...
...
@@ -640,6 +635,38 @@ class CFuncDeclaratorNode(CDeclaratorNode):
func_type
.
calling_convention
=
callspec
return
self
.
base
.
analyse
(
func_type
,
env
)
def
declare_optional_arg_struct
(
self
,
func_type
,
env
,
fused_cname
=
None
):
"""
Declares the optional argument struct (the struct used to hold the
values for optional arguments). For fused cdef functions, this is
deferred as analyse_declarations is called only once (on the fused
cdef function).
"""
scope
=
StructOrUnionScope
()
arg_count_member
=
'%sn'
%
Naming
.
pyrex_prefix
scope
.
declare_var
(
arg_count_member
,
PyrexTypes
.
c_int_type
,
self
.
pos
)
for
arg
in
func_type
.
args
[
len
(
func_type
.
args
)
-
self
.
optional_arg_count
:]:
scope
.
declare_var
(
arg
.
name
,
arg
.
type
,
arg
.
pos
,
allow_pyobject
=
1
)
struct_cname
=
env
.
mangle
(
Naming
.
opt_arg_prefix
,
self
.
base
.
name
)
if
fused_cname
is
not
None
:
struct_cname
=
PyrexTypes
.
get_fused_cname
(
fused_cname
,
struct_cname
)
op_args_struct
=
env
.
global_scope
().
declare_struct_or_union
(
name
=
struct_cname
,
kind
=
'struct'
,
scope
=
scope
,
typedef_flag
=
0
,
pos
=
self
.
pos
,
cname
=
struct_cname
)
op_args_struct
.
defined_in_pxd
=
1
op_args_struct
.
used
=
1
func_type
.
op_arg_struct
=
PyrexTypes
.
c_ptr_type
(
op_args_struct
.
type
)
class
CArgDeclNode
(
Node
):
# Item in a function declaration argument list.
...
...
@@ -2020,6 +2047,9 @@ class FusedCFuncDefNode(StatListNode):
if
node
.
return_type
.
is_fused
:
assert
not
n
.
return_type
.
is_fused
if
n
.
cfunc_declarator
.
optional_arg_count
:
assert
n
.
type
.
op_arg_struct
assert
node
.
type
.
is_fused
node
.
entry
.
fused_cfunction
=
self
...
...
@@ -2044,6 +2074,9 @@ class FusedCFuncDefNode(StatListNode):
copied_node
.
entry
.
type
=
newtype
newtype
.
entry
=
copied_node
.
entry
self
.
node
.
cfunc_declarator
.
declare_optional_arg_struct
(
newtype
,
env
,
fused_cname
=
cname
)
copied_node
.
return_type
=
newtype
.
return_type
copied_node
.
create_local_scope
(
env
)
copied_node
.
local_scope
.
fused_to_specific
=
fused_to_specific
...
...
Cython/Compiler/PyrexTypes.py
View file @
a8305590
...
...
@@ -1762,9 +1762,11 @@ class CFuncType(CType):
# nogil boolean Can be called without gil
# with_gil boolean Acquire gil around function body
# templates [string] or None
# cached_specialized_types [CFuncType] cached specialized versions of the CFuncType if defined in a pxd
is_cfunction
=
1
original_sig
=
None
cached_specialized_types
=
None
subtypes
=
[
'return_type'
,
'args'
]
...
...
@@ -1991,6 +1993,7 @@ class CFuncType(CType):
new_templates
=
None
else
:
new_templates
=
[
v
.
specialize
(
values
)
for
v
in
self
.
templates
]
return
CFuncType
(
self
.
return_type
.
specialize
(
values
),
[
arg
.
specialize
(
values
)
for
arg
in
self
.
args
],
has_varargs
=
0
,
...
...
@@ -2032,11 +2035,20 @@ class CFuncType(CType):
"""
assert
self
.
is_fused
if
self
.
entry
.
fused_cfunction
:
return
[
n
.
type
for
n
in
self
.
entry
.
fused_cfunction
.
nodes
]
elif
self
.
cached_specialized_types
is
not
None
:
return
self
.
cached_specialized_types
result
=
[]
permutations
=
self
.
get_all_specific_permutations
()
for
cname
,
fused_to_specific
in
permutations
:
new_func_type
=
self
.
entry
.
type
.
specialize
(
fused_to_specific
)
if
self
.
optional_arg_count
:
# Remember, this method is set by CFuncDeclaratorNode
self
.
declare_opt_arg_struct
(
new_func_type
,
cname
)
new_entry
=
copy
.
deepcopy
(
self
.
entry
)
new_entry
.
cname
=
self
.
get_specific_cname
(
cname
)
...
...
@@ -2045,6 +2057,8 @@ class CFuncType(CType):
result
.
append
(
new_func_type
)
self
.
cached_specialized_types
=
result
return
result
def
get_specific_cname
(
self
,
fused_cname
):
...
...
@@ -2053,11 +2067,16 @@ class CFuncType(CType):
for the corresponding function with specific types.
"""
assert
self
.
is_fused
return
'%s%s%s'
%
(
Naming
.
fused_func_prefix
,
fused_cname
,
self
.
entry
.
func_cname
)
return
get_fused_cname
(
fused_cname
,
self
.
entry
.
func_cname
)
def
get_fused_cname
(
fused_cname
,
orig_cname
):
"""
Given the fused cname id and an original cname, return a specialized cname
"""
return
'%s%s%s'
%
(
Naming
.
fused_func_prefix
,
fused_cname
,
orig_cname
)
def
map_with_specific_entries
(
entry
,
func
,
*
args
,
**
kwargs
):
"""
Call func for every specific function instance. If this is not a
...
...
@@ -2089,7 +2108,7 @@ def get_all_specific_permutations(fused_types, id="", f2s=()):
if
id
:
cname
=
'%s_%s'
%
(
id
,
newid
)
else
:
cname
=
newid
cname
=
str
(
newid
)
if
len
(
fused_types
)
>
1
:
result
.
extend
(
get_all_specific_permutations
(
...
...
tests/run/fused_types.pyx
View file @
a8305590
...
...
@@ -13,7 +13,7 @@ ctypedef cython.fused_type(int, long) integral
ctypedef
cython
.
fused_type
(
int
,
long
,
float
,
double
,
string_t
)
fused_type1
ctypedef
cython
.
fused_type
(
string_t
)
fused_type2
ctypedef
fused_type1
*
composed_t
ctypedef
cython
.
fused_type
(
int
,
long
,
float
,
double
)
other_t
ctypedef
cython
.
fused_type
(
int
,
double
)
other_t
ctypedef
double
*
p_double
ctypedef
int
*
p_int
...
...
@@ -164,8 +164,8 @@ def test_specializations():
# print test_specialize[double](1.1, somedouble_p, otherdouble_p)
# print
#
cdef opt_args(integral x, floating y = 4.0):
#
print x, y
cdef
opt_args
(
integral
x
,
floating
y
=
4.0
):
print
x
,
y
def
test_opt_args
():
"""
...
...
@@ -176,8 +176,8 @@ def test_opt_args():
3 4.0
3 4.0
"""
#
opt_args[int, float](3)
#
opt_args[int, double](3)
#
opt_args[int, float](3, 4.0)
#
opt_args[int, double](3, 4.0)
opt_args
[
int
,
float
](
3
)
opt_args
[
int
,
double
](
3
)
opt_args
[
int
,
float
](
3
,
4.0
)
opt_args
[
int
,
double
](
3
,
4.0
)
tests/run/public_fused_types.srctree
View file @
a8305590
...
...
@@ -37,6 +37,7 @@ ctypedef cython.fused_type(str, unicode, bytes) builtin_t
cdef object_t add_simple(object_t obj, simple_t simple)
cdef less_simple_t add_to_simple(object_t obj, less_simple_t simple)
cdef public_optional_args(object_t obj, simple_t simple = *)
######## header.h ########
...
...
@@ -54,6 +55,9 @@ cdef object_t add_simple(object_t obj, simple_t simple):
cdef less_simple_t add_to_simple(object_t obj, less_simple_t simple):
return obj.a + simple
cdef public_optional_args(object_t obj, simple_t simple = 6):
return obj.a, simple
######## b.pyx ########
from a cimport *
...
...
@@ -82,3 +86,9 @@ assert f(mystruct, 5).a == 10
f = add_simple[mystruct_t, int]
assert f(mystruct, 5).a == 10
assert public_optional_args(mystruct, 5) == (5, 5)
assert public_optional_args[mystruct_t, int](mystruct) == (5, 6)
assert public_optional_args[mystruct_t, float](mystruct) == (5, 6.0)
assert public_optional_args[mystruct_t, float](mystruct, 7.0) == (5, 7.0)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment