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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
ac87fcc9
Commit
ac87fcc9
authored
Jul 06, 2014
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
reduce redundant coercions in cascaded assignments
parent
86c39f80
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
64 additions
and
20 deletions
+64
-20
CHANGES.rst
CHANGES.rst
+3
-0
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+5
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+34
-17
tests/memoryview/memslice.pyx
tests/memoryview/memslice.pyx
+0
-2
tests/run/cascaded_typed_assignments_T466.pyx
tests/run/cascaded_typed_assignments_T466.pyx
+12
-0
tests/run/cascadedassignment.pyx
tests/run/cascadedassignment.pyx
+10
-1
No files found.
CHANGES.rst
View file @
ac87fcc9
...
@@ -9,6 +9,9 @@ Latest
...
@@ -9,6 +9,9 @@ Latest
Features added
Features added
--------------
--------------
* Cascaded assignments (a = b = X) try to minimise the number of
type coercions.
* Generators have new properties ``__name__`` and ``__qualname__``
* Generators have new properties ``__name__`` and ``__qualname__``
that provide the plain/qualified name of the generator function
that provide the plain/qualified name of the generator function
(following CPython 3.5). See http://bugs.python.org/issue21205
(following CPython 3.5). See http://bugs.python.org/issue21205
...
...
Cython/Compiler/ExprNodes.py
View file @
ac87fcc9
...
@@ -11097,6 +11097,11 @@ class CloneNode(CoercionNode):
...
@@ -11097,6 +11097,11 @@ class CloneNode(CoercionNode):
self
.
entry
=
self
.
arg
.
entry
self
.
entry
=
self
.
arg
.
entry
return
self
return
self
def
coerce_to
(
self
,
dest_type
,
env
):
if
self
.
arg
.
is_literal
:
return
self
.
arg
.
coerce_to
(
dest_type
,
env
)
return
super
(
CloneNode
,
self
).
coerce_to
(
dest_type
,
env
)
def
is_simple
(
self
):
def
is_simple
(
self
):
return
True
# result is always in a temp (or a name)
return
True
# result is always in a temp (or a name)
...
...
Cython/Compiler/Nodes.py
View file @
ac87fcc9
...
@@ -4718,41 +4718,56 @@ class CascadedAssignmentNode(AssignmentNode):
...
@@ -4718,41 +4718,56 @@ class CascadedAssignmentNode(AssignmentNode):
#
#
# coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
# coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
child_attrs
=
[
"lhs_list"
,
"rhs"
,
"coerced_rhs_list"
]
child_attrs
=
[
"lhs_list"
,
"rhs"
,
"coerced_
values"
,
"coerced_
rhs_list"
]
coerced_rhs_list
=
None
coerced_rhs_list
=
None
coerced_values
=
None
def
analyse_declarations
(
self
,
env
):
def
analyse_declarations
(
self
,
env
):
for
lhs
in
self
.
lhs_list
:
for
lhs
in
self
.
lhs_list
:
lhs
.
analyse_target_declaration
(
env
)
lhs
.
analyse_target_declaration
(
env
)
def
analyse_types
(
self
,
env
,
use_temp
=
0
):
def
analyse_types
(
self
,
env
,
use_temp
=
0
):
from
.ExprNodes
import
CloneNode
,
ProxyNode
from
.ExprNodes
import
CloneNode
,
ProxyNode
lhs_types
=
set
()
for
lhs
in
self
.
lhs_list
:
lhs
.
analyse_target_types
(
env
)
lhs
.
gil_assignment_check
(
env
)
lhs_types
.
add
(
lhs
.
type
)
rhs
=
self
.
rhs
.
analyse_types
(
env
)
rhs
=
self
.
rhs
.
analyse_types
(
env
)
if
use_temp
or
rhs
.
is_attribute
or
(
if
len
(
lhs_types
)
==
1
:
not
rhs
.
is_name
and
not
rhs
.
is_literal
and
# common special case: only one type needed on the LHS => coerce only once
rhs
.
type
.
is_pyobject
):
rhs
=
rhs
.
coerce_to
(
lhs_types
.
pop
(),
env
)
if
not
rhs
.
is_name
and
not
rhs
.
is_literal
and
(
use_temp
or
rhs
.
is_attribute
or
rhs
.
type
.
is_pyobject
):
rhs
=
rhs
.
coerce_to_temp
(
env
)
rhs
=
rhs
.
coerce_to_temp
(
env
)
else
:
else
:
rhs
=
rhs
.
coerce_to_simple
(
env
)
rhs
=
rhs
.
coerce_to_simple
(
env
)
self
.
rhs
=
ProxyNode
(
rhs
)
self
.
rhs
=
ProxyNode
(
rhs
)
if
rhs
.
is_temp
else
rhs
self
.
coerced_values
=
[]
coerced_values
=
{}
for
lhs
in
self
.
lhs_list
:
if
lhs
.
type
not
in
coerced_values
and
lhs
.
type
!=
rhs
.
type
:
rhs
=
CloneNode
(
self
.
rhs
).
coerce_to
(
lhs
.
type
,
env
)
self
.
coerced_values
.
append
(
rhs
)
coerced_values
[
lhs
.
type
]
=
rhs
self
.
coerced_rhs_list
=
[]
self
.
coerced_rhs_list
=
[]
for
lhs
in
self
.
lhs_list
:
for
lhs
in
self
.
lhs_list
:
lhs
.
analyse_target_types
(
env
)
rhs
=
coerced_values
.
get
(
lhs
.
type
,
self
.
rhs
)
lhs
.
gil_assignment_check
(
env
)
self
.
coerced_rhs_list
.
append
(
CloneNode
(
rhs
))
rhs
=
CloneNode
(
self
.
rhs
)
rhs
=
rhs
.
coerce_to
(
lhs
.
type
,
env
)
self
.
coerced_rhs_list
.
append
(
rhs
)
return
self
return
self
def
generate_rhs_evaluation_code
(
self
,
code
):
def
generate_rhs_evaluation_code
(
self
,
code
):
self
.
rhs
.
generate_evaluation_code
(
code
)
self
.
rhs
.
generate_evaluation_code
(
code
)
def
generate_assignment_code
(
self
,
code
):
def
generate_assignment_code
(
self
,
code
):
for
i
in
range
(
len
(
self
.
lhs_list
))
:
for
rhs
in
self
.
coerced_values
:
lhs
=
self
.
lhs_list
[
i
]
rhs
.
generate_evaluation_code
(
code
)
rhs
=
self
.
coerced_rhs_list
[
i
]
for
lhs
,
rhs
in
zip
(
self
.
lhs_list
,
self
.
coerced_rhs_list
):
rhs
.
generate_evaluation_code
(
code
)
rhs
.
generate_evaluation_code
(
code
)
lhs
.
generate_assignment_code
(
rhs
,
code
)
lhs
.
generate_assignment_code
(
rhs
,
code
)
# Assignment has disposed of the cloned RHS
# Assignment has disposed of the cloned RHS
...
@@ -4763,9 +4778,11 @@ class CascadedAssignmentNode(AssignmentNode):
...
@@ -4763,9 +4778,11 @@ class CascadedAssignmentNode(AssignmentNode):
self
.
rhs
.
generate_function_definitions
(
env
,
code
)
self
.
rhs
.
generate_function_definitions
(
env
,
code
)
def
annotate
(
self
,
code
):
def
annotate
(
self
,
code
):
for
i
in
range
(
len
(
self
.
lhs_list
)):
for
rhs
in
self
.
coerced_values
:
self
.
lhs_list
[
i
].
annotate
(
code
)
rhs
.
annotate
(
code
)
self
.
coerced_rhs_list
[
i
].
annotate
(
code
)
for
lhs
,
rhs
in
zip
(
self
.
lhs_list
,
self
.
coerced_rhs_list
):
lhs
.
annotate
(
code
)
rhs
.
annotate
(
code
)
self
.
rhs
.
annotate
(
code
)
self
.
rhs
.
annotate
(
code
)
...
...
tests/memoryview/memslice.pyx
View file @
ac87fcc9
...
@@ -275,8 +275,6 @@ def cascaded_buffer_assignment(obj):
...
@@ -275,8 +275,6 @@ def cascaded_buffer_assignment(obj):
>>> A = IntMockBuffer("A", range(6))
>>> A = IntMockBuffer("A", range(6))
>>> cascaded_buffer_assignment(A)
>>> cascaded_buffer_assignment(A)
acquired A
acquired A
acquired A
released A
released A
released A
"""
"""
cdef
int
[:]
a
,
b
cdef
int
[:]
a
,
b
...
...
tests/run/cascaded_typed_assignments_T466.pyx
View file @
ac87fcc9
...
@@ -24,6 +24,18 @@ def simple_parallel_int_mix():
...
@@ -24,6 +24,18 @@ def simple_parallel_int_mix():
ai
,
bi
=
al
,
bl
=
ao
,
bo
=
c
=
d
=
[
1
,
2
]
ai
,
bi
=
al
,
bl
=
ao
,
bo
=
c
=
d
=
[
1
,
2
]
return
ao
,
bo
,
ai
,
bi
,
al
,
bl
,
c
,
d
return
ao
,
bo
,
ai
,
bi
,
al
,
bl
,
c
,
d
def
simple_parallel_int_mix_recursive
():
"""
>>> simple_parallel_int_mix_recursive()
(1, 2, 3, 1, [2, 3], 1, 2, 3, 1, 2, 3, [1, [2, 3]], [1, [2, 3]])
"""
cdef
int
ai
,
bi
,
ci
cdef
long
al
,
bl
,
cl
cdef
object
ao
,
bo
,
co
cdef
object
xo
,
yo
ai
,
[
bi
,
ci
]
=
al
,
[
bl
,
cl
]
=
xo
,
yo
=
ao
,
[
bo
,
co
]
=
c
=
d
=
[
1
,
[
2
,
3
]]
return
ao
,
bo
,
co
,
xo
,
yo
,
ai
,
bi
,
ci
,
al
,
bl
,
cl
,
c
,
d
cdef
int
called
=
0
cdef
int
called
=
0
cdef
char
*
get_string
():
cdef
char
*
get_string
():
...
...
tests/run/cascadedassignment.pyx
View file @
ac87fcc9
import
cython
import
cython
@
cython
.
test_fail_if_path_exists
(
'//CascadedAssignmentNode//CoerceFromPyTypeNode'
,
'//CascadedAssignmentNode//CoerceToPyTypeNode'
,
)
@
cython
.
test_assert_path_exists
(
'//CascadedAssignmentNode'
)
def
test_cascaded_assignment_simple
():
def
test_cascaded_assignment_simple
():
"""
"""
>>> test_cascaded_assignment_simple()
>>> test_cascaded_assignment_simple()
...
@@ -8,6 +13,11 @@ def test_cascaded_assignment_simple():
...
@@ -8,6 +13,11 @@ def test_cascaded_assignment_simple():
a
=
b
=
c
=
5
a
=
b
=
c
=
5
return
a
return
a
@
cython
.
test_fail_if_path_exists
(
'//CascadedAssignmentNode//CoerceFromPyTypeNode'
,
'//CascadedAssignmentNode//CoerceToPyTypeNode'
,
)
@
cython
.
test_assert_path_exists
(
'//CascadedAssignmentNode'
)
def
test_cascaded_assignment_typed
():
def
test_cascaded_assignment_typed
():
"""
"""
>>> test_cascaded_assignment_typed()
>>> test_cascaded_assignment_typed()
...
@@ -46,4 +56,3 @@ def test_cascaded_assignment_evaluate_expr():
...
@@ -46,4 +56,3 @@ def test_cascaded_assignment_evaluate_expr():
"""
"""
a
=
b
=
c
=
float
(
expr
())
a
=
b
=
c
=
float
(
expr
())
return
a
,
b
,
c
return
a
,
b
,
c
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