mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
SF bug #436207: "if 0: yield x" is ignored.
Not anymore <wink>. Pure hack. Doesn't fix any other "if 0:" glitches.
This commit is contained in:
parent
3e7b1a04a0
commit
b6c3ceae79
2 changed files with 161 additions and 8 deletions
|
@ -431,6 +431,9 @@ in increasing order, where i,j,k >= 0. Trickier than it may look at first!
|
||||||
Try writing it without generators, and correctly, and without generating
|
Try writing it without generators, and correctly, and without generating
|
||||||
3 internal results for each result output.
|
3 internal results for each result output.
|
||||||
|
|
||||||
|
XXX Suspect there's memory leaks in this one; definitely in the next
|
||||||
|
XXX version.
|
||||||
|
|
||||||
>>> def times(n, g):
|
>>> def times(n, g):
|
||||||
... for i in g:
|
... for i in g:
|
||||||
... yield n * i
|
... yield n * i
|
||||||
|
@ -482,6 +485,8 @@ namespace renaming trick. The *pretty* part is that the times() and merge()
|
||||||
functions can be reused as-is, because they only assume their stream
|
functions can be reused as-is, because they only assume their stream
|
||||||
arguments are iterable -- a LazyList is the same as a generator to times().
|
arguments are iterable -- a LazyList is the same as a generator to times().
|
||||||
|
|
||||||
|
XXX Massive memory leaks in this; see Python-Iterators.
|
||||||
|
|
||||||
>>> class LazyList:
|
>>> class LazyList:
|
||||||
... def __init__(self, g):
|
... def __init__(self, g):
|
||||||
... self.sofar = []
|
... self.sofar = []
|
||||||
|
@ -514,7 +519,8 @@ arguments are iterable -- a LazyList is the same as a generator to times().
|
||||||
[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
|
[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# syntax_tests mostly provokes SyntaxErrors.
|
# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
|
||||||
|
# hackery.
|
||||||
|
|
||||||
syntax_tests = """
|
syntax_tests = """
|
||||||
|
|
||||||
|
@ -588,13 +594,128 @@ But this is fine:
|
||||||
... return
|
... return
|
||||||
>>> list(f())
|
>>> list(f())
|
||||||
[12, 666]
|
[12, 666]
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... if 0:
|
||||||
|
... yield 1
|
||||||
|
>>> type(f())
|
||||||
|
<type 'generator'>
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... if "":
|
||||||
|
... yield None
|
||||||
|
>>> type(f())
|
||||||
|
<type 'generator'>
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... return
|
||||||
|
... try:
|
||||||
|
... if x==4:
|
||||||
|
... pass
|
||||||
|
... elif 0:
|
||||||
|
... try:
|
||||||
|
... 1/0
|
||||||
|
... except SyntaxError:
|
||||||
|
... pass
|
||||||
|
... else:
|
||||||
|
... if 0:
|
||||||
|
... while 12:
|
||||||
|
... x += 1
|
||||||
|
... yield 2 # don't blink
|
||||||
|
... f(a, b, c, d, e)
|
||||||
|
... else:
|
||||||
|
... pass
|
||||||
|
... except:
|
||||||
|
... x = 1
|
||||||
|
... return
|
||||||
|
>>> type(f())
|
||||||
|
<type 'generator'>
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... if 0:
|
||||||
|
... def g():
|
||||||
|
... yield 1
|
||||||
|
...
|
||||||
|
>>> type(f())
|
||||||
|
<type 'None'>
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... if 0:
|
||||||
|
... class C:
|
||||||
|
... def __init__(self):
|
||||||
|
... yield 1
|
||||||
|
... def f(self):
|
||||||
|
... yield 2
|
||||||
|
>>> type(f())
|
||||||
|
<type 'None'>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__test__ = {"tut": tutorial_tests,
|
|
||||||
"pep": pep_tests,
|
x_tests = """
|
||||||
"email": email_tests,
|
|
||||||
"fun": fun_tests,
|
>>> def firstn(g, n):
|
||||||
"syntax": syntax_tests}
|
... return [g.next() for i in range(n)]
|
||||||
|
|
||||||
|
>>> def times(n, g):
|
||||||
|
... for i in g:
|
||||||
|
... yield n * i
|
||||||
|
|
||||||
|
>>> def merge(g, h):
|
||||||
|
... ng = g.next()
|
||||||
|
... nh = h.next()
|
||||||
|
... while 1:
|
||||||
|
... if ng < nh:
|
||||||
|
... yield ng
|
||||||
|
... ng = g.next()
|
||||||
|
... elif ng > nh:
|
||||||
|
... yield nh
|
||||||
|
... nh = h.next()
|
||||||
|
... else:
|
||||||
|
... yield ng
|
||||||
|
... ng = g.next()
|
||||||
|
... nh = h.next()
|
||||||
|
|
||||||
|
>>> class LazyList:
|
||||||
|
... def __init__(self, g):
|
||||||
|
... self.sofar = []
|
||||||
|
... self.fetch = g.next
|
||||||
|
...
|
||||||
|
... def __getitem__(self, i):
|
||||||
|
... sofar, fetch = self.sofar, self.fetch
|
||||||
|
... while i >= len(sofar):
|
||||||
|
... sofar.append(fetch())
|
||||||
|
... return sofar[i]
|
||||||
|
|
||||||
|
>>> def m235():
|
||||||
|
... yield 1
|
||||||
|
... # Gack: m235 below actually refers to a LazyList.
|
||||||
|
... me_times2 = times(2, m235)
|
||||||
|
... me_times3 = times(3, m235)
|
||||||
|
... me_times5 = times(5, m235)
|
||||||
|
... for i in merge(merge(me_times2,
|
||||||
|
... me_times3),
|
||||||
|
... me_times5):
|
||||||
|
... yield i
|
||||||
|
|
||||||
|
>>> m235 = LazyList(m235())
|
||||||
|
>>> for i in range(5):
|
||||||
|
... x = [m235[j] for j in range(15*i, 15*(i+1))]
|
||||||
|
|
||||||
|
|
||||||
|
[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
|
||||||
|
[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
|
||||||
|
[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
|
||||||
|
[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
|
||||||
|
[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
|
||||||
|
"""
|
||||||
|
|
||||||
|
__test__ = {"tut": tutorial_tests, # clean
|
||||||
|
"pep": pep_tests, # clean
|
||||||
|
"email": email_tests, # clean
|
||||||
|
"fun": fun_tests, # leaks
|
||||||
|
"syntax": syntax_tests # clean
|
||||||
|
#"x": x_tests
|
||||||
|
}
|
||||||
|
|
||||||
# Magic test name that regrtest.py invokes *after* importing this module.
|
# Magic test name that regrtest.py invokes *after* importing this module.
|
||||||
# This worms around a bootstrap problem.
|
# This worms around a bootstrap problem.
|
||||||
|
@ -605,7 +726,7 @@ def test_main():
|
||||||
if 0:
|
if 0:
|
||||||
# Temporary block to help track down leaks. So far, the blame
|
# Temporary block to help track down leaks. So far, the blame
|
||||||
# has fallen mostly on doctest.
|
# has fallen mostly on doctest.
|
||||||
for i in range(1000):
|
for i in range(5000):
|
||||||
doctest.master = None
|
doctest.master = None
|
||||||
doctest.testmod(test_generators)
|
doctest.testmod(test_generators)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -4840,6 +4840,34 @@ symtable_add_def_o(struct symtable *st, PyObject *dict,
|
||||||
|
|
||||||
#define symtable_add_use(ST, NAME) symtable_add_def((ST), (NAME), USE)
|
#define symtable_add_use(ST, NAME) symtable_add_def((ST), (NAME), USE)
|
||||||
|
|
||||||
|
/* Look for a yield stmt under n. Return 1 if found, else 0. */
|
||||||
|
static int
|
||||||
|
look_for_yield(node *n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NCH(n); ++i) {
|
||||||
|
node *kid = CHILD(n, i);
|
||||||
|
|
||||||
|
switch (TYPE(kid)) {
|
||||||
|
|
||||||
|
case classdef:
|
||||||
|
case funcdef:
|
||||||
|
/* Stuff in nested functions and classes can't make
|
||||||
|
the parent a generator. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case yield_stmt:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (look_for_yield(kid))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
symtable_node(struct symtable *st, node *n)
|
symtable_node(struct symtable *st, node *n)
|
||||||
{
|
{
|
||||||
|
@ -4883,8 +4911,12 @@ symtable_node(struct symtable *st, node *n)
|
||||||
}
|
}
|
||||||
case if_stmt:
|
case if_stmt:
|
||||||
for (i = 0; i + 3 < NCH(n); i += 4) {
|
for (i = 0; i + 3 < NCH(n); i += 4) {
|
||||||
if (is_constant_false(NULL, (CHILD(n, i + 1))))
|
if (is_constant_false(NULL, (CHILD(n, i + 1)))) {
|
||||||
|
if (st->st_cur->ste_generator == 0)
|
||||||
|
st->st_cur->ste_generator =
|
||||||
|
look_for_yield(CHILD(n, i+3));
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
symtable_node(st, CHILD(n, i + 1));
|
symtable_node(st, CHILD(n, i + 1));
|
||||||
symtable_node(st, CHILD(n, i + 3));
|
symtable_node(st, CHILD(n, i + 3));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue