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
Xavier Thompson
cython
Commits
6c5fab7c
Commit
6c5fab7c
authored
7 years ago
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement PEP 530 by allowing async generator expressions
parent
ddec13cb
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
33 additions
and
16 deletions
+33
-16
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+16
-5
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+17
-11
No files found.
Cython/Compiler/ParseTreeTransforms.py
View file @
6c5fab7c
...
@@ -208,11 +208,22 @@ class PostParse(ScopeTrackingTransform):
...
@@ -208,11 +208,22 @@ class PostParse(ScopeTrackingTransform):
def
visit_GeneratorExpressionNode
(
self
,
node
):
def
visit_GeneratorExpressionNode
(
self
,
node
):
# unpack a generator expression into the corresponding DefNode
# unpack a generator expression into the corresponding DefNode
node
.
def_node
=
Nodes
.
DefNode
(
node
.
pos
,
name
=
node
.
name
,
collector
=
YieldNodeCollector
()
doc
=
None
,
collector
.
visitchildren
(
node
.
loop
)
args
=
[],
star_arg
=
None
,
node
.
def_node
=
Nodes
.
DefNode
(
starstar_arg
=
None
,
node
.
pos
,
name
=
node
.
name
,
doc
=
None
,
body
=
node
.
loop
)
args
=
[],
star_arg
=
None
,
starstar_arg
=
None
,
body
=
node
.
loop
,
is_async_def
=
collector
.
has_await
)
self
.
visitchildren
(
node
)
return
node
def
visit_ComprehensionNode
(
self
,
node
):
# enforce local scope also in Py2 for async generators (seriously, that's a Py3.6 feature...)
if
not
node
.
has_local_scope
:
collector
=
YieldNodeCollector
()
collector
.
visitchildren
(
node
.
loop
)
if
collector
.
has_await
:
node
.
has_local_scope
=
True
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
return
node
return
node
...
...
This diff is collapsed.
Click to expand it.
Cython/Compiler/Parsing.py
View file @
6c5fab7c
...
@@ -501,7 +501,7 @@ def p_call_parse_args(s, allow_genexp=True):
...
@@ -501,7 +501,7 @@ def p_call_parse_args(s, allow_genexp=True):
break
break
s
.
next
()
s
.
next
()
if
s
.
sy
==
'for'
:
if
s
.
sy
in
(
'for'
,
'async'
)
:
if
not
keyword_args
and
not
last_was_tuple_unpack
:
if
not
keyword_args
and
not
last_was_tuple_unpack
:
if
len
(
positional_args
)
==
1
and
len
(
positional_args
[
0
])
==
1
:
if
len
(
positional_args
)
==
1
and
len
(
positional_args
[
0
])
==
1
:
positional_args
=
[[
p_genexp
(
s
,
positional_args
[
0
][
0
])]]
positional_args
=
[[
p_genexp
(
s
,
positional_args
[
0
][
0
])]]
...
@@ -1196,7 +1196,7 @@ def p_f_string_expr(s, unicode_value, pos, starting_index, is_raw):
...
@@ -1196,7 +1196,7 @@ def p_f_string_expr(s, unicode_value, pos, starting_index, is_raw):
# list_display ::= "[" [listmaker] "]"
# list_display ::= "[" [listmaker] "]"
# listmaker ::= (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
# listmaker ::= (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
# comp_iter ::= comp_for | comp_if
# comp_iter ::= comp_for | comp_if
# comp_for ::= "for" expression_list "in" testlist [comp_iter]
# comp_for ::=
["async"]
"for" expression_list "in" testlist [comp_iter]
# comp_if ::= "if" test [comp_iter]
# comp_if ::= "if" test [comp_iter]
def
p_list_maker
(
s
):
def
p_list_maker
(
s
):
...
@@ -1208,7 +1208,7 @@ def p_list_maker(s):
...
@@ -1208,7 +1208,7 @@ def p_list_maker(s):
return
ExprNodes
.
ListNode
(
pos
,
args
=
[])
return
ExprNodes
.
ListNode
(
pos
,
args
=
[])
expr
=
p_test_or_starred_expr
(
s
)
expr
=
p_test_or_starred_expr
(
s
)
if
s
.
sy
==
'for'
:
if
s
.
sy
in
(
'for'
,
'async'
)
:
if
expr
.
is_starred
:
if
expr
.
is_starred
:
s
.
error
(
"iterable unpacking cannot be used in comprehension"
)
s
.
error
(
"iterable unpacking cannot be used in comprehension"
)
append
=
ExprNodes
.
ComprehensionAppendNode
(
pos
,
expr
=
expr
)
append
=
ExprNodes
.
ComprehensionAppendNode
(
pos
,
expr
=
expr
)
...
@@ -1230,7 +1230,7 @@ def p_list_maker(s):
...
@@ -1230,7 +1230,7 @@ def p_list_maker(s):
def
p_comp_iter
(
s
,
body
):
def
p_comp_iter
(
s
,
body
):
if
s
.
sy
==
'for'
:
if
s
.
sy
in
(
'for'
,
'async'
)
:
return
p_comp_for
(
s
,
body
)
return
p_comp_for
(
s
,
body
)
elif
s
.
sy
==
'if'
:
elif
s
.
sy
==
'if'
:
return
p_comp_if
(
s
,
body
)
return
p_comp_if
(
s
,
body
)
...
@@ -1239,11 +1239,17 @@ def p_comp_iter(s, body):
...
@@ -1239,11 +1239,17 @@ def p_comp_iter(s, body):
return
body
return
body
def
p_comp_for
(
s
,
body
):
def
p_comp_for
(
s
,
body
):
# s.sy == 'for'
pos
=
s
.
position
()
pos
=
s
.
position
()
# [async] for ...
is_async
=
False
if
s
.
sy
==
'async'
:
is_async
=
True
s
.
next
()
s
.
next
()
kw
=
p_for_bounds
(
s
,
allow_testlist
=
False
)
kw
.
update
(
else_clause
=
None
,
body
=
p_comp_iter
(
s
,
body
))
# s.sy == 'for'
s
.
expect
(
'for'
)
kw
=
p_for_bounds
(
s
,
allow_testlist
=
False
,
is_async
=
is_async
)
kw
.
update
(
else_clause
=
None
,
body
=
p_comp_iter
(
s
,
body
),
is_async
=
is_async
)
return
Nodes
.
ForStatNode
(
pos
,
**
kw
)
return
Nodes
.
ForStatNode
(
pos
,
**
kw
)
def
p_comp_if
(
s
,
body
):
def
p_comp_if
(
s
,
body
):
...
@@ -1311,7 +1317,7 @@ def p_dict_or_set_maker(s):
...
@@ -1311,7 +1317,7 @@ def p_dict_or_set_maker(s):
else
:
else
:
break
break
if
s
.
sy
==
'for'
:
if
s
.
sy
in
(
'for'
,
'async'
)
:
# dict/set comprehension
# dict/set comprehension
if
len
(
parts
)
==
1
and
isinstance
(
parts
[
0
],
list
)
and
len
(
parts
[
0
])
==
1
:
if
len
(
parts
)
==
1
and
isinstance
(
parts
[
0
],
list
)
and
len
(
parts
[
0
])
==
1
:
item
=
parts
[
0
][
0
]
item
=
parts
[
0
][
0
]
...
@@ -1441,13 +1447,13 @@ def p_testlist_comp(s):
...
@@ -1441,13 +1447,13 @@ def p_testlist_comp(s):
s
.
next
()
s
.
next
()
exprs
=
p_test_or_starred_expr_list
(
s
,
expr
)
exprs
=
p_test_or_starred_expr_list
(
s
,
expr
)
return
ExprNodes
.
TupleNode
(
pos
,
args
=
exprs
)
return
ExprNodes
.
TupleNode
(
pos
,
args
=
exprs
)
elif
s
.
sy
==
'for'
:
elif
s
.
sy
in
(
'for'
,
'async'
)
:
return
p_genexp
(
s
,
expr
)
return
p_genexp
(
s
,
expr
)
else
:
else
:
return
expr
return
expr
def
p_genexp
(
s
,
expr
):
def
p_genexp
(
s
,
expr
):
# s.sy == 'for'
# s.sy == '
async' | '
for'
loop
=
p_comp_for
(
s
,
Nodes
.
ExprStatNode
(
loop
=
p_comp_for
(
s
,
Nodes
.
ExprStatNode
(
expr
.
pos
,
expr
=
ExprNodes
.
YieldExprNode
(
expr
.
pos
,
arg
=
expr
)))
expr
.
pos
,
expr
=
ExprNodes
.
YieldExprNode
(
expr
.
pos
,
arg
=
expr
)))
return
ExprNodes
.
GeneratorExpressionNode
(
expr
.
pos
,
loop
=
loop
)
return
ExprNodes
.
GeneratorExpressionNode
(
expr
.
pos
,
loop
=
loop
)
...
...
This diff is collapsed.
Click to expand it.
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