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
b7d6e693
Commit
b7d6e693
authored
Apr 13, 2012
by
Robert Bradshaw
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'main/release'
parents
449e3b58
b8a87f10
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
338 additions
and
84 deletions
+338
-84
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+48
-15
Cython/Compiler/Main.py
Cython/Compiler/Main.py
+4
-2
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+6
-12
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+28
-27
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+15
-11
Cython/Compiler/NumpySupport.py
Cython/Compiler/NumpySupport.py
+15
-4
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+10
-6
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+65
-1
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+17
-0
Cython/__init__.py
Cython/__init__.py
+1
-1
tests/run/fused_cpp.pyx
tests/run/fused_cpp.pyx
+16
-0
tests/run/fused_types.pyx
tests/run/fused_types.pyx
+24
-1
tests/run/memoryview.pyx
tests/run/memoryview.pyx
+10
-0
tests/run/numpy_attributes.pyx
tests/run/numpy_attributes.pyx
+12
-3
tests/run/numpy_test.pyx
tests/run/numpy_test.pyx
+67
-1
No files found.
Cython/Compiler/ExprNodes.py
View file @
b7d6e693
...
...
@@ -13,6 +13,7 @@ cython.declare(error=object, warning=object, warn_once=object, InternalError=obj
debug_disposal_code
=
object
,
debug_temp_alloc
=
object
,
debug_coercion
=
object
)
import
sys
import
copy
import
operator
from
Errors
import
error
,
warning
,
warn_once
,
InternalError
,
CompileError
...
...
@@ -33,6 +34,8 @@ import Symtab
import
Options
from
Cython
import
Utils
from
Annotate
import
AnnotationItem
from
NumpySupport
import
numpy_transform_attribute_node
,
\
should_apply_numpy_hack
from
Cython.Debugging
import
print_call_chain
from
DebugFlags
import
debug_disposal_code
,
debug_temp_alloc
,
\
...
...
@@ -488,11 +491,21 @@ class ExprNode(Node):
# ---------------- Code Generation -----------------
def
make_owned_reference
(
self
,
code
):
# If result is a pyobject, make sure we own
# a reference to it.
"""
If result is a pyobject, make sure we own a reference to it.
If the result is in a temp, it is already a new reference.
"""
if
self
.
type
.
is_pyobject
and
not
self
.
result_in_temp
():
code
.
put_incref
(
self
.
result
(),
self
.
ctype
())
def
make_owned_memoryviewslice
(
self
,
code
):
"""
Make sure we own the reference to this memoryview slice.
"""
if
not
self
.
result_in_temp
():
code
.
put_incref_memoryviewslice
(
self
.
result
(),
have_gil
=
self
.
in_nogil_context
)
def
generate_evaluation_code
(
self
,
code
):
code
.
mark_pos
(
self
.
pos
)
...
...
@@ -623,7 +636,7 @@ class ExprNode(Node):
return
self
if
src_type
.
is_fused
:
error
(
self
.
pos
,
"Type is not speci
fic
"
)
error
(
self
.
pos
,
"Type is not speci
alized
"
)
else
:
error
(
self
.
pos
,
"Cannot coerce to a type that is not specialized"
)
...
...
@@ -2586,8 +2599,9 @@ class IndexNode(ExprNode):
self
.
nogil
=
env
.
nogil
if
buffer_access
or
self
.
memslice_index
:
if
self
.
base
.
type
.
is_memoryviewslice
and
not
self
.
base
.
is_name
:
self
.
base
=
self
.
base
.
coerce_to_temp
(
env
)
#if self.base.type.is_memoryviewslice and not self.base.is_name:
# self.base = self.base.coerce_to_temp(env)
self
.
base
=
self
.
base
.
coerce_to_simple
(
env
)
self
.
indices
=
indices
self
.
index
=
None
...
...
@@ -2724,7 +2738,7 @@ class IndexNode(ExprNode):
specific_types
=
[]
positions
=
[]
if
self
.
index
.
is_name
:
if
self
.
index
.
is_name
or
self
.
index
.
is_attribute
:
positions
.
append
(
self
.
index
.
pos
)
specific_types
.
append
(
self
.
index
.
analyse_as_type
(
env
))
elif
isinstance
(
self
.
index
,
TupleNode
):
...
...
@@ -3042,7 +3056,8 @@ class IndexNode(ExprNode):
if
self
.
base
.
is_name
:
entry
=
self
.
base
.
entry
else
:
assert
self
.
base
.
is_temp
# SimpleCallNode is_simple is not consistent with coerce_to_simple
assert
self
.
base
.
is_simple
()
or
self
.
base
.
is_temp
cname
=
self
.
base
.
result
()
entry
=
Symtab
.
Entry
(
cname
,
cname
,
self
.
base
.
type
,
self
.
base
.
pos
)
...
...
@@ -3452,6 +3467,19 @@ class SliceNode(ExprNode):
if
self
.
is_literal
:
code
.
put_giveref
(
self
.
py_result
())
def
__deepcopy__
(
self
,
memo
):
"""
There is a copy bug in python 2.4 for slice objects.
"""
return
SliceNode
(
self
.
pos
,
start
=
copy
.
deepcopy
(
self
.
start
,
memo
),
stop
=
copy
.
deepcopy
(
self
.
stop
,
memo
),
step
=
copy
.
deepcopy
(
self
.
step
,
memo
),
is_temp
=
self
.
is_temp
,
is_literal
=
self
.
is_literal
,
constant_result
=
self
.
constant_result
)
class
CallNode
(
ExprNode
):
...
...
@@ -4417,9 +4445,13 @@ class AttributeNode(ExprNode):
if
entry
:
if
obj_type
.
is_extension_type
and
entry
.
name
==
"__weakref__"
:
error
(
self
.
pos
,
"Illegal use of special attribute __weakref__"
)
# methods need the normal attribute lookup
# def methods need the normal attribute lookup
# because they do not have struct entries
if
entry
.
is_variable
or
entry
.
is_cmethod
:
# fused function go through assignment synthesis
# (foo = pycfunction(foo_func_obj)) and need to go through
# regular Python lookup as well
if
(
entry
.
is_variable
and
not
entry
.
fused_cfunction
)
or
entry
.
is_cmethod
:
self
.
type
=
entry
.
type
self
.
member
=
entry
.
cname
return
...
...
@@ -4429,10 +4461,8 @@ class AttributeNode(ExprNode):
# attribute.
pass
# NumPy hack
if
(
getattr
(
self
.
obj
,
'type'
,
None
)
and
obj_type
.
is_extension_type
and
obj_type
.
objstruct_cname
==
'PyArrayObject'
):
from
NumpySupport
import
numpy_transform_attribute_node
if
(
getattr
(
self
.
obj
,
'type'
,
None
)
and
obj_type
.
is_extension_type
and
should_apply_numpy_hack
(
obj_type
)):
replacement_node
=
numpy_transform_attribute_node
(
self
)
# Since we can't actually replace our node yet, we only grasp its
# type, and then the replacement happens in
...
...
@@ -4440,7 +4470,6 @@ class AttributeNode(ExprNode):
self
.
type
=
replacement_node
.
type
if
replacement_node
is
not
self
:
return
# If we get here, the base object is not a struct/union/extension
# type, or it is an extension type and the attribute is either not
# declared or is declared as a Python method. Treat it as a Python
...
...
@@ -7244,7 +7273,7 @@ class CythonArrayNode(ExprNode):
else
:
return
error
()
if
not
base_type
.
same_as
(
array_dtype
):
if
not
(
base_type
.
same_as
(
array_dtype
)
or
base_type
.
is_void
):
return
error
(
self
.
operand
.
pos
,
ERR_BASE_TYPE
)
elif
self
.
operand
.
type
.
is_array
and
len
(
array_dimension_sizes
)
!=
ndim
:
return
error
(
self
.
operand
.
pos
,
...
...
@@ -8912,6 +8941,10 @@ class CoercionNode(ExprNode):
code
.
annotate
((
file
,
line
,
col
-
1
),
AnnotationItem
(
style
=
'coerce'
,
tag
=
'coerce'
,
text
=
'[%s] to [%s]'
%
(
self
.
arg
.
type
,
self
.
type
)))
class
CoerceToMemViewSliceNode
(
CoercionNode
):
"""
Coerce an object to a memoryview slice. This holds a new reference in
a managed temp.
"""
def
__init__
(
self
,
arg
,
dst_type
,
env
):
assert
dst_type
.
is_memoryviewslice
...
...
Cython/Compiler/Main.py
View file @
b7d6e693
...
...
@@ -24,6 +24,10 @@ module_name_pattern = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_
verbose
=
0
standard_include_path
=
os
.
path
.
abspath
(
os
.
path
.
normpath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
os
.
path
.
pardir
,
'Includes'
)))
class
CompilationData
(
object
):
# Bundles the information that is passed from transform to transform.
# (For now, this is only)
...
...
@@ -70,8 +74,6 @@ class Context(object):
self
.
pxds
=
{}
# full name -> node tree
standard_include_path
=
os
.
path
.
abspath
(
os
.
path
.
normpath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
os
.
path
.
pardir
,
'Includes'
)))
self
.
include_directories
=
include_directories
+
[
standard_include_path
]
self
.
set_language_level
(
language_level
)
...
...
Cython/Compiler/MemoryView.py
View file @
b7d6e693
...
...
@@ -86,7 +86,7 @@ def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code,
"We can avoid decreffing the lhs if we know it is the first assignment"
assert
rhs
.
type
.
is_memoryviewslice
pretty_rhs
=
isinstance
(
rhs
,
NameNode
)
or
rhs
.
result_in_temp
()
pretty_rhs
=
rhs
.
result_in_temp
()
or
rhs
.
is_simple
()
if
pretty_rhs
:
rhstmp
=
rhs
.
result
()
else
:
...
...
@@ -106,19 +106,11 @@ def put_assign_to_memviewslice(lhs_cname, rhs, rhs_cname, memviewslicetype, code
if
not
first_assignment
:
code
.
put_xdecref_memoryviewslice
(
lhs_cname
,
have_gil
=
have_gil
)
if
rhs
.
is_name
:
code
.
put_incref_memoryviewslice
(
rhs_cname
,
have_gil
=
have_gil
)
if
not
rhs
.
result_in_temp
()
:
rhs
.
make_owned_memoryviewslice
(
code
)
code
.
putln
(
"%s = %s;"
%
(
lhs_cname
,
rhs_cname
))
#code.putln("%s.memview = %s.memview;" % (lhs_cname, rhs_cname))
#code.putln("%s.data = %s.data;" % (lhs_cname, rhs_cname))
#for i in range(memviewslicetype.ndim):
# tup = (lhs_cname, i, rhs_cname, i)
# code.putln("%s.shape[%d] = %s.shape[%d];" % tup)
# code.putln("%s.strides[%d] = %s.strides[%d];" % tup)
# code.putln("%s.suboffsets[%d] = %s.suboffsets[%d];" % tup)
def
get_buf_flags
(
specs
):
is_c_contig
,
is_f_contig
=
is_cf_contig
(
specs
)
...
...
@@ -888,7 +880,8 @@ context = {
memviewslice_declare_code
=
load_memview_c_utility
(
"MemviewSliceStruct"
,
proto_block
=
'utility_code_proto_before_types'
,
context
=
context
)
context
=
context
,
requires
=
[])
atomic_utility
=
load_memview_c_utility
(
"Atomics"
,
context
,
proto_block
=
'utility_code_proto_before_types'
)
...
...
@@ -931,4 +924,5 @@ view_utility_whitelist = ('array', 'memoryview', 'array_cwrapper',
'generic'
,
'strided'
,
'indirect'
,
'contiguous'
,
'indirect_contiguous'
)
memviewslice_declare_code
.
requires
.
append
(
view_utility_code
)
copy_contents_new_utility
.
requires
.
append
(
view_utility_code
)
\ No newline at end of file
Cython/Compiler/ModuleNode.py
View file @
b7d6e693
...
...
@@ -988,18 +988,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type
=
scope
.
parent_type
base_type
=
type
.
base_type
py_attrs
=
[]
memviewslice_attrs
=
[]
py_buffers
=
[]
for
entry
in
scope
.
var_entries
:
if
entry
.
type
.
is_pyobject
:
py_attrs
.
append
(
entry
)
elif
entry
.
type
.
is_memoryviewslice
:
memviewslice_attrs
.
append
(
entry
)
elif
entry
.
type
==
PyrexTypes
.
c_py_buffer_type
:
py_buffers
.
append
(
entry
)
have_entries
,
(
py_attrs
,
py_buffers
,
memoryview_slices
)
=
\
scope
.
get_refcounted_entries
(
include_weakref
=
True
)
need_self_cast
=
type
.
vtabslot_cname
or
py_attrs
or
memviewslice_attrs
or
py_buffer
s
need_self_cast
=
type
.
vtabslot_cname
or
have_entrie
s
code
.
putln
(
""
)
code
.
putln
(
"static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {"
...
...
@@ -1044,7 +1036,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else
:
code
.
put_init_var_to_py_none
(
entry
,
"p->%s"
,
nanny
=
False
)
for
entry
in
mem
viewslice_attr
s
:
for
entry
in
mem
oryview_slice
s
:
code
.
putln
(
"p->%s.data = NULL;"
%
entry
.
cname
)
code
.
putln
(
"p->%s.memview = NULL;"
%
entry
.
cname
)
...
...
@@ -1081,18 +1073,25 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
"static void %s(PyObject *o) {"
%
scope
.
mangle_internal
(
"tp_dealloc"
))
py_attrs
=
[]
weakref_slot
=
scope
.
lookup_here
(
"__weakref__"
)
for
entry
in
scope
.
var_entries
:
if
entry
.
type
.
is_pyobject
and
entry
is
not
weakref_slot
:
py_attrs
.
append
(
entry
)
if
py_attrs
or
weakref_slot
in
scope
.
var_entries
:
_
,
(
py_attrs
,
_
,
memoryview_slices
)
=
scope
.
get_refcounted_entries
()
if
py_attrs
or
memoryview_slices
or
weakref_slot
in
scope
.
var_entries
:
self
.
generate_self_cast
(
scope
,
code
)
# call the user's __dealloc__
self
.
generate_usr_dealloc_call
(
scope
,
code
)
if
weakref_slot
in
scope
.
var_entries
:
code
.
putln
(
"if (p->__weakref__) PyObject_ClearWeakRefs(o);"
)
for
entry
in
py_attrs
:
code
.
put_xdecref
(
"p->%s"
%
entry
.
cname
,
entry
.
type
,
nanny
=
False
)
for
entry
in
memoryview_slices
:
code
.
put_xdecref_memoryviewslice
(
"p->%s"
%
entry
.
cname
,
have_gil
=
True
)
if
base_type
:
tp_dealloc
=
TypeSlots
.
get_base_slot_function
(
scope
,
tp_slot
)
if
tp_dealloc
is
None
:
...
...
@@ -1139,13 +1138,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"static int %s(PyObject *o, visitproc v, void *a) {"
%
slot_func
)
py_attrs
=
[]
py_buffers
=
[]
for
entry
in
scope
.
var_entries
:
if
entry
.
type
.
is_pyobject
and
entry
.
name
!=
"__weakref__"
:
py_attrs
.
append
(
entry
)
if
entry
.
type
==
PyrexTypes
.
c_py_buffer_type
:
py_buffers
.
append
(
entry
)
have_entries
,
(
py_attrs
,
py_buffers
,
memoryview_slices
)
=
scope
.
get_refcounted_entries
()
if
base_type
or
py_attrs
:
code
.
putln
(
"int e;"
)
...
...
@@ -1178,9 +1172,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
"}"
)
for
entry
in
py_buffers
:
code
.
putln
(
"if (p->%s.obj) {"
%
entry
.
cname
)
code
.
putln
(
"e = (*v)(p->%s.obj, a); if (e) return e;"
%
entry
.
cname
)
for
entry
in
py_buffers
+
memoryview_slices
:
if
entry
.
type
==
PyrexTypes
.
c_py_buffer_type
:
cname
=
entry
.
cname
+
".obj"
else
:
# traverse the memoryview object, which should traverse the
# object exposing the buffer
cname
=
entry
.
cname
+
".memview"
code
.
putln
(
"if (p->%s) {"
%
cname
)
code
.
putln
(
"e = (*v)(p->%s, a); if (e) return e;"
%
cname
)
code
.
putln
(
"}"
)
if
cclass_entry
.
cname
==
'__pyx_memoryviewslice'
:
...
...
Cython/Compiler/Nodes.py
View file @
b7d6e693
...
...
@@ -439,6 +439,10 @@ class CNameDeclaratorNode(CDeclaratorNode):
else
:
self
.
name
=
base_type
.
declaration_code
(
""
,
for_display
=
1
,
pyrex
=
1
)
base_type
=
py_object_type
if
base_type
.
is_fused
and
env
.
fused_to_specific
:
base_type
=
base_type
.
specialize
(
env
.
fused_to_specific
)
self
.
type
=
base_type
return
self
,
base_type
...
...
@@ -982,6 +986,9 @@ class TemplatedTypeNode(CBaseTypeNode):
dimension
=
dimension
)
self
.
type
=
self
.
array_declarator
.
analyse
(
base_type
,
env
)[
1
]
if
self
.
type
.
is_fused
and
env
.
fused_to_specific
:
self
.
type
=
self
.
type
.
specialize
(
env
.
fused_to_specific
)
return
self
.
type
class
CComplexBaseTypeNode
(
CBaseTypeNode
):
...
...
@@ -1031,8 +1038,8 @@ class FusedTypeNode(CBaseTypeNode):
else
:
types
.
append
(
type
)
if
len
(
self
.
types
)
==
1
:
return
types
[
0
]
#
if len(self.types) == 1:
#
return types[0]
return
PyrexTypes
.
FusedType
(
types
,
name
=
self
.
name
)
...
...
@@ -2279,7 +2286,6 @@ class FusedCFuncDefNode(StatListNode):
else
:
node
.
py_func
.
fused_py_func
=
self
.
py_func
node
.
entry
.
as_variable
=
self
.
py_func
.
entry
# Copy the nodes as AnalyseDeclarationsTransform will prepend
# self.py_func to self.stats, as we only want specialized
# CFuncDefNodes in self.nodes
...
...
@@ -2294,9 +2300,9 @@ class FusedCFuncDefNode(StatListNode):
Create a copy of the original def or lambda function for specialized
versions.
"""
fused_types
=
PyrexTypes
.
unique
(
fused_
compound_
types
=
PyrexTypes
.
unique
(
[
arg
.
type
for
arg
in
self
.
node
.
args
if
arg
.
type
.
is_fused
])
permutations
=
PyrexTypes
.
get_all_specialized_permutations
(
fused_types
)
permutations
=
PyrexTypes
.
get_all_specialized_permutations
(
fused_
compound_
types
)
if
self
.
node
.
entry
in
env
.
pyfunc_entries
:
env
.
pyfunc_entries
.
remove
(
self
.
node
.
entry
)
...
...
@@ -2311,7 +2317,7 @@ class FusedCFuncDefNode(StatListNode):
copied_node
.
analyse_declarations
(
env
)
self
.
create_new_local_scope
(
copied_node
,
env
,
fused_to_specific
)
self
.
specialize_copied_def
(
copied_node
,
cname
,
self
.
node
.
entry
,
fused_to_specific
,
fused_types
)
fused_to_specific
,
fused_
compound_
types
)
PyrexTypes
.
specialize_entry
(
copied_node
.
entry
,
cname
)
copied_node
.
entry
.
used
=
True
...
...
@@ -2420,11 +2426,9 @@ class FusedCFuncDefNode(StatListNode):
"""Specialize the copy of a DefNode given the copied node,
the specialization cname and the original DefNode entry"""
type_strings
=
[
fused_type
.
specialize
(
f2s
).
typeof_name
(
)
PyrexTypes
.
specialization_signature_string
(
fused_type
,
f2s
)
for
fused_type
in
fused_types
]
#type_strings = [f2s[fused_type].typeof_name()
# for fused_type in fused_types]
node
.
specialized_signature_string
=
', '
.
join
(
type_strings
)
...
...
@@ -2574,7 +2578,7 @@ def __pyx_fused_cpdef(signatures, args, kwargs):
candidates = []
for sig in signatures:
match_found =
True
match_found =
[x for x in dest_sig if x]
for src_type, dst_type in zip(sig.strip('()').split(', '), dest_sig):
if dst_type is not None and match_found:
match_found = src_type == dst_type
...
...
@@ -5355,7 +5359,7 @@ class ReturnStatNode(StatNode):
"%s = %s;"
%
(
Naming
.
retval_cname
,
self
.
value
.
result_as
(
self
.
return_type
)))
self
.
value
.
generate_post_assignment_code
(
code
)
self
.
value
.
generate_post_assignment_code
(
code
)
self
.
value
.
free_temps
(
code
)
else
:
if
self
.
return_type
.
is_pyobject
:
...
...
Cython/Compiler/NumpySupport.py
View file @
b7d6e693
...
...
@@ -2,20 +2,31 @@
# the NumPy ABI changed so that the shape, ndim, strides, etc. fields were
# no longer available, however the use of these were so entrenched in
# Cython codes
import
PyrexTypes
import
ExprNodes
import
os
from
StringEncoding
import
EncodedString
def
should_apply_numpy_hack
(
obj_type
):
if
not
obj_type
.
is_extension_type
or
obj_type
.
objstruct_cname
!=
'PyArrayObject'
:
return
False
from
Scanning
import
FileSourceDescriptor
from
Main
import
standard_include_path
type_source
=
obj_type
.
pos
[
0
]
if
isinstance
(
type_source
,
FileSourceDescriptor
):
type_source_path
=
os
.
path
.
abspath
(
os
.
path
.
normpath
(
type_source
.
filename
))
return
type_source_path
==
os
.
path
.
join
(
standard_include_path
,
'numpy.pxd'
)
else
:
return
False
def
numpy_transform_attribute_node
(
node
):
import
PyrexTypes
import
ExprNodes
assert
isinstance
(
node
,
ExprNodes
.
AttributeNode
)
if
node
.
obj
.
type
.
objstruct_cname
!=
'PyArrayObject'
:
return
node
pos
=
node
.
pos
numpy_pxd_scope
=
node
.
obj
.
entry
.
type
.
scope
.
parent_scope
numpy_pxd_scope
=
node
.
obj
.
type
.
scope
.
parent_scope
def
macro_call_node
(
numpy_macro_name
):
array_node
=
node
.
obj
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
b7d6e693
...
...
@@ -18,7 +18,8 @@ from Cython.Compiler.TreeFragment import TreeFragment
from
Cython.Compiler.StringEncoding
import
EncodedString
from
Cython.Compiler.Errors
import
error
,
warning
,
CompileError
,
InternalError
from
Cython.Compiler.Code
import
UtilityCode
from
Cython.Compiler.NumpySupport
import
(
should_apply_numpy_hack
,
numpy_transform_attribute_node
)
import
copy
...
...
@@ -1495,12 +1496,15 @@ if VALUE is not None:
self
.
fused_function
=
None
if
node
.
py_func
:
# Create PyCFunction nodes for each specialization
node
.
stats
.
insert
(
0
,
node
.
py_func
)
node
.
py_func
=
self
.
visit
(
node
.
py_func
)
pycfunc
=
ExprNodes
.
PyCFunctionNode
.
from_defnode
(
node
.
py_func
,
True
)
pycfunc
=
ExprNodes
.
ProxyNode
(
pycfunc
.
coerce_to_temp
(
env
))
node
.
resulting_fused_function
=
pycfunc
# Create assignment node for our def function
node
.
fused_func_assignment
=
self
.
_create_assignment
(
node
.
py_func
,
ExprNodes
.
CloneNode
(
pycfunc
),
env
)
else
:
...
...
@@ -1781,7 +1785,7 @@ class AnalyseExpressionsTransform(CythonTransform):
"""
self
.
visit_Node
(
node
)
if
node
.
is_fused_index
and
no
de
.
type
is
not
PyrexTypes
.
error_type
:
if
node
.
is_fused_index
and
no
t
node
.
type
.
is_error
:
node
=
node
.
base
elif
node
.
memslice_ellipsis_noop
:
# memoryviewslice[...] expression, drop the IndexNode
...
...
@@ -1792,8 +1796,8 @@ class AnalyseExpressionsTransform(CythonTransform):
self
.
visitchildren
(
node
)
type
=
node
.
obj
.
type
if
type
.
is_extension_type
and
type
.
objstruct_cname
==
'PyArrayObject'
:
from
NumpySupport
import
numpy_transform_attribute_node
if
(
not
node
.
type
.
is_error
and
type
.
is_extension_type
and
should_apply_numpy_hack
(
type
)):
node
=
numpy_transform_attribute_node
(
node
)
self
.
visitchildren
(
node
)
...
...
@@ -2603,8 +2607,8 @@ class ReplaceFusedTypeChecks(VisitorTransform):
else
:
types
=
PyrexTypes
.
get_specialized_types
(
type2
)
for
speci
fic
_type
in
types
:
if
type1
.
same_as
(
speci
fic
_type
):
for
speci
alized
_type
in
types
:
if
type1
.
same_as
(
speci
alized
_type
):
if
op
==
'in'
:
return
true_node
else
:
...
...
Cython/Compiler/PyrexTypes.py
View file @
b7d6e693
...
...
@@ -767,12 +767,46 @@ class BufferType(BaseType):
def
as_argument_type
(
self
):
return
self
def
specialize
(
self
,
values
):
dtype
=
self
.
dtype
.
specialize
(
values
)
if
dtype
is
not
self
.
dtype
:
return
BufferType
(
self
.
base
,
dtype
,
self
.
ndim
,
self
.
mode
,
self
.
negative_indices
,
self
.
cast
)
return
self
def
__getattr__
(
self
,
name
):
return
getattr
(
self
.
base
,
name
)
def
__repr__
(
self
):
return
"<BufferType %r>"
%
self
.
base
def
__str__
(
self
):
# avoid ', ', as fused functions split the signature string on ', '
if
self
.
cast
:
cast_str
=
',cast=True'
else
:
cast_str
=
''
return
"%s[%s,ndim=%d%s]"
%
(
self
.
base
,
self
.
dtype
,
self
.
ndim
,
cast_str
)
def
assignable_from
(
self
,
other_type
):
if
other_type
.
is_buffer
:
return
(
self
.
same_as
(
other_type
,
compare_base
=
False
)
and
self
.
base
.
assignable_from
(
other_type
.
base
))
return
self
.
base
.
assignable_from
(
other_type
)
def
same_as
(
self
,
other_type
,
compare_base
=
True
):
if
not
other_type
.
is_buffer
:
return
other_type
.
same_as
(
self
.
base
)
return
(
self
.
dtype
.
same_as
(
other_type
.
dtype
)
and
self
.
ndim
==
other_type
.
ndim
and
self
.
mode
==
other_type
.
mode
and
self
.
cast
==
other_type
.
cast
and
(
not
compare_base
or
self
.
base
.
same_as
(
other_type
.
base
)))
class
PyObjectType
(
PyrexType
):
#
...
...
@@ -2631,6 +2665,31 @@ def _get_all_specialized_permutations(fused_types, id="", f2s=()):
return
result
def
specialization_signature_string
(
fused_compound_type
,
fused_to_specific
):
"""
Return the signature for a specialization of a fused type. e.g.
floating[:] ->
'float' or 'double'
cdef fused ft:
float[:]
double[:]
ft ->
'float[:]' or 'double[:]'
integral func(floating) ->
'int (*func)(float)' or ...
"""
fused_types
=
fused_compound_type
.
get_fused_types
()
if
len
(
fused_types
)
==
1
:
fused_type
=
fused_types
[
0
]
else
:
fused_type
=
fused_compound_type
return
fused_type
.
specialize
(
fused_to_specific
).
typeof_name
()
def
get_specialized_types
(
type
):
"""
Return a list of specialized types sorted in reverse order in accordance
...
...
@@ -2640,10 +2699,15 @@ def get_specialized_types(type):
if
isinstance
(
type
,
FusedType
):
result
=
type
.
types
for
specialized_type
in
result
:
specialized_type
.
specialization_string
=
specialized_type
.
typeof_name
()
else
:
result
=
[]
for
cname
,
f2s
in
get_all_specialized_permutations
(
type
.
get_fused_types
()):
result
.
append
(
type
.
specialize
(
f2s
))
specialized_type
=
type
.
specialize
(
f2s
)
specialized_type
.
specialization_string
=
(
specialization_signature_string
(
type
,
f2s
))
result
.
append
(
specialized_type
)
return
sorted
(
result
)
...
...
Cython/Compiler/Symtab.py
View file @
b7d6e693
...
...
@@ -784,6 +784,23 @@ class Scope(object):
def add_include_file(self, filename):
self.outer_scope.add_include_file(filename)
def get_refcounted_entries(self, include_weakref=False):
py_attrs = []
py_buffers = []
memoryview_slices = []
for entry in self.var_entries:
if entry.type.is_pyobject:
if include_weakref or entry.name != "
weakref
":
py_attrs.append(entry)
elif entry.type == PyrexTypes.c_py_buffer_type:
py_buffers.append(entry)
elif entry.type.is_memoryviewslice:
memoryview_slices.append(entry)
have_entries = py_attrs or py_buffers or memoryview_slices
return have_entries, (py_attrs, py_buffers, memoryview_slices)
class PreImportScope(Scope):
...
...
Cython/__init__.py
View file @
b7d6e693
__version__
=
"0.16
.beta0
"
__version__
=
"0.16
rc1
"
# Void cython.* directives (for case insensitive operating systems).
from
Cython.Shadow
import
*
tests/run/fused_cpp.pyx
0 → 100644
View file @
b7d6e693
# tag: cpp
cimport
cython
from
libcpp.vector
cimport
vector
def
test_cpp_specialization
(
cython
.
floating
element
):
"""
>>> import cython
>>> test_cpp_specialization[cython.float](10.0)
vector<float> * float 10.0
>>> test_cpp_specialization[cython.double](10.0)
vector<double> * double 10.0
"""
cdef
vector
[
cython
.
floating
]
*
v
=
new
vector
[
cython
.
floating
]()
v
.
push_back
(
element
)
print
cython
.
typeof
(
v
),
cython
.
typeof
(
element
),
v
.
at
(
0
)
\ No newline at end of file
tests/run/fused_types.pyx
View file @
b7d6e693
# mode: run
cimport
cython
from
cython.view
cimport
array
from
cython
cimport
integral
from
cpython
cimport
Py_INCREF
from
Cython
import
Shadow
as
pure_cython
ctypedef
char
*
string_t
# floating = cython.fused_type(float, double) floating
...
...
@@ -249,3 +249,26 @@ def test_sizeof_fused_type(fused_type1 b):
"""
t
=
sizeof
(
b
),
sizeof
(
fused_type1
),
sizeof
(
double
)
assert
t
[
0
]
==
t
[
1
]
==
t
[
2
],
t
def
get_array
(
itemsize
,
format
):
result
=
array
((
10
,),
itemsize
,
format
)
result
[
5
]
=
5.0
result
[
6
]
=
6.0
return
result
def
test_fused_memslice_dtype
(
cython
.
floating
[:]
array
):
"""
Note: the np.ndarray dtype test is in numpy_test
>>> import cython
>>> sorted(test_fused_memslice_dtype.__signatures__)
['double', 'float']
>>> test_fused_memslice_dtype[cython.double](get_array(8, 'd'))
double[:] double[:] 5.0 6.0
>>> test_fused_memslice_dtype[cython.float](get_array(4, 'f'))
float[:] float[:] 5.0 6.0
"""
cdef
cython
.
floating
[:]
otherarray
=
array
[
0
:
100
:
1
]
print
cython
.
typeof
(
array
),
cython
.
typeof
(
otherarray
),
\
array
[
5
],
otherarray
[
6
]
tests/run/memoryview.pyx
View file @
b7d6e693
...
...
@@ -133,6 +133,16 @@ def test_coerce_to_temp():
print
print
_coerce_to_temp
()[
4
][
4
]
def
test_extclass_attribute_dealloc
():
"""
>>> test_extclass_attribute_dealloc()
acquired self.arr
2
released self.arr
"""
cdef
ExtClassMockedAttr
obj
=
ExtClassMockedAttr
()
print
obj
.
arr
[
4
,
4
]
cdef
float
[:,::
1
]
global_mv
=
array
((
10
,
10
),
itemsize
=
sizeof
(
float
),
format
=
'f'
)
global_mv
=
array
((
10
,
10
),
itemsize
=
sizeof
(
float
),
format
=
'f'
)
cdef
object
global_obj
...
...
tests/run/numpy_attributes.pyx
View file @
b7d6e693
...
...
@@ -4,6 +4,7 @@
import
numpy
as
np
cimport
numpy
as
np
int64_array
=
np
.
ones
((
3
,
2
),
dtype
=
np
.
int64
)
def
f
():
"""
...
...
@@ -14,7 +15,7 @@ def f():
shape[1] 2
strides 16 8
"""
cdef
np
.
ndarray
x
=
np
.
ones
((
3
,
2
),
dtype
=
np
.
int64
)
cdef
np
.
ndarray
x
=
int64_array
cdef
int
i
cdef
Py_ssize_t
j
,
k
cdef
char
*
p
...
...
@@ -23,7 +24,7 @@ def f():
with
nogil
:
i
=
x
.
ndim
print
'ndim'
,
i
with
nogil
:
p
=
x
.
data
print
'data'
,
(
<
np
.
int64_t
*>
p
)[
0
]
...
...
@@ -42,4 +43,12 @@ def f():
j
=
x
.
strides
[
0
]
k
=
x
.
strides
[
1
]
print
'strides'
,
j
,
k
def
test_non_namenode_attribute_access
(
obj
):
"""
>>> test_non_namenode_attribute_access(int64_array)
data 1
"""
# Try casting, resulting in an AttributeNode with a TypeCastNode as object
# and 'data' as attribute
print
"data"
,
(
<
np
.
int64_t
*>
(
<
np
.
ndarray
>
obj
).
data
)[
0
]
tests/run/numpy_test.pyx
View file @
b7d6e693
...
...
@@ -2,6 +2,7 @@
# cannot be named "numpy" in order to not clash with the numpy module!
cimport
numpy
as
np
cimport
cython
def
little_endian
():
cdef
int
endian_detector
=
1
...
...
@@ -35,7 +36,7 @@ try:
[[ 16. 17. 18. 19.]
[ 20. 21. 22. 23.]]]
6.0 0.0 13.0 8.0
>>> obj_array()
[a 1 {}]
a 1 {}
...
...
@@ -502,4 +503,69 @@ def test_point_record():
test
[
i
].
y
=
-
i
print
repr
(
test
).
replace
(
'<'
,
'!'
).
replace
(
'>'
,
'!'
)
def
test_fused_ndarray_dtype
(
np
.
ndarray
[
cython
.
floating
,
ndim
=
1
]
a
):
"""
>>> import cython
>>> sorted(test_fused_ndarray_dtype.__signatures__)
['double', 'float']
>>> test_fused_ndarray_dtype[cython.double](np.arange(10, dtype=np.float64))
ndarray[double,ndim=1] ndarray[double,ndim=1] 5.0 6.0
>>> test_fused_ndarray_dtype[cython.float](np.arange(10, dtype=np.float32))
ndarray[float,ndim=1] ndarray[float,ndim=1] 5.0 6.0
"""
cdef
np
.
ndarray
[
cython
.
floating
,
ndim
=
1
]
b
=
a
print
cython
.
typeof
(
a
),
cython
.
typeof
(
b
),
a
[
5
],
b
[
6
]
double_array
=
np
.
linspace
(
0
,
1
,
100
)
int32_array
=
np
.
arange
(
100
,
dtype
=
np
.
int32
)
cdef
fused
fused_external
:
np
.
int32_t
np
.
int64_t
np
.
float32_t
np
.
float64_t
def
test_fused_external
(
np
.
ndarray
[
fused_external
,
ndim
=
1
]
a
):
"""
>>> import cython
>>> sorted(test_fused_external.__signatures__)
['float32_t', 'float64_t', 'int32_t', 'int64_t']
>>> test_fused_external["float64_t"](double_array)
float64
>>> test_fused_external["int32_t"](int32_array)
int32
>>> test_fused_external(np.arange(100)) # fix in next release
Traceback (most recent call last):
...
TypeError: No matching signature found
"""
print
a
.
dtype
cdef
fused
fused_buffers
:
np
.
ndarray
[
np
.
int32_t
,
ndim
=
1
]
np
.
int64_t
[::
1
]
def
test_fused_buffers
(
fused_buffers
arg
):
"""
>>> sorted(test_fused_buffers.__signatures__)
['int64_t[::1]', 'ndarray[int32_t,ndim=1]']
"""
cpdef
_fused_cpdef_buffers
(
np
.
ndarray
[
fused_external
]
a
):
print
a
.
dtype
def
test_fused_cpdef_buffers
():
"""
>>> test_fused_cpdef_buffers()
int32
int32
"""
_fused_cpdef_buffers
[
np
.
int32_t
](
int32_array
)
cdef
np
.
ndarray
[
np
.
int32_t
]
typed_array
=
int32_array
_fused_cpdef_buffers
(
typed_array
)
include
"numpy_common.pxi"
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