473,545 Members | 2,451 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Generator comprehensions -- patch for compiler module

Hello.

Recently, Generator Comprehensions were mentioned again on python-list.
I have written an implementation for the compiler module. To try it
out, however, you must be able to rebuild Python from source, because it
also requires a change to Grammar.

1. Edit Python-2.3/Grammar/Grammar and add an alternative to the
"listmaker" production:
-listmaker: test ( list_for | (',' test)* [','] )
+listmaker: test ( list_for | (',' test)* [','] ) | 'yield' test list_for

1.5. Now [yield None for x in []] parses, but crashes the written-in-C
compiler:
[yield None for x in []]

SystemError: com_node: unexpected node type

2. Apply the patch below to Lib/compiler

3. Use compiler.compil e to compile code with generator comprehensions:
from compiler import compile
import dis

code = compile("""
def f():
gg = [yield (x,y) for x in range(10) for y in range(10) if y > x]
print gg, type(gg), list(gg)
""", "<None>", "exec")
exec code
dis.dis(f.func_ code.co_consts[1])
f()

4. It's possible to write code so that __import__ uses compiler.compil e
instead of the written-in-C compiler, but I don't have this code handy.
Also, a test suite is needed, and presumably a written-in-C implementation
as well. (option 2: make the compiler.compil e interface the standard
compiler, and let the builtin compiler support a Python subset
sufficient to bootstrap the written-in-python compiler, or arrange
to ship .pyc of the compiler package and completely get rid of the
written-in-C compiler)

5. PEP remains rejected by BDFL anyway
diff -ur compiler.orig/ast.py compiler/ast.py
--- compiler.orig/ast.py 2002-02-23 16:35:33.000000 000 -0600
+++ compiler/ast.py 2003-08-26 06:55:51.000000 000 -0500
@@ -1191,6 +1191,53 @@
def __repr__(self):
return "If(%s, %s)" % (repr(self.test s), repr(self.else_ ))

+class GenCompInner(No de):
+ nodes["gencompinn er"] = "GenCompInn er"
+ def __init__(self, expr, quals):
+ self.expr = expr
+ self.quals = quals
+
+ def getChildren(sel f):
+ children = []
+ children.append (self.expr)
+ children.extend (flatten(self.q uals))
+ return tuple(children)
+
+ def getChildNodes(s elf):
+ nodelist = []
+ nodelist.append (self.expr)
+ nodelist.extend (flatten_nodes( self.quals))
+ return tuple(nodelist)
+
+ def __repr__(self):
+ return "GenCompInner(% s, %s)" % (repr(self.expr ), repr(self.quals ))
+
+class GenComp(Node):
+ nodes["gencomp"] = "GenComp"
+ def __init__(self, inner):
+ self.argnames = ()
+ self.defaults = ()
+ self.flags = 0
+ self.code = inner
+ self.varargs = self.kwargs = None
+
+ def getChildren(sel f):
+ children = []
+ children.append (self.argnames)
+ children.extend (flatten(self.d efaults))
+ children.append (self.flags)
+ children.append (self.code)
+ return tuple(children)
+
+ def getChildNodes(s elf):
+ nodelist = []
+ nodelist.extend (flatten_nodes( self.defaults))
+ nodelist.append (self.code)
+ return tuple(nodelist)
+
+ def __repr__(self):
+ return "GenComp(%s )" % (repr(self.code ),)
+
class ListComp(Node):
nodes["listcomp"] = "ListComp"
def __init__(self, expr, quals):
diff -ur compiler.orig/pycodegen.py compiler/pycodegen.py
--- compiler.orig/pycodegen.py 2002-12-31 12:26:17.000000 000 -0600
+++ compiler/pycodegen.py 2003-08-26 06:54:53.000000 000 -0500
@@ -563,6 +563,51 @@
# list comprehensions
__list_count = 0

+ def visitGenCompInn er(self, node):
+ self.set_lineno (node)
+ # setup list
+
+ stack = []
+ for i, for_ in zip(range(len(n ode.quals)), node.quals):
+ start, anchor = self.visit(for_ )
+ cont = None
+ for if_ in for_.ifs:
+ if cont is None:
+ cont = self.newBlock()
+ self.visit(if_, cont)
+ stack.insert(0, (start, cont, anchor))
+
+ self.visit(node .expr)
+ self.emit('YIEL D_VALUE')
+
+ for start, cont, anchor in stack:
+ if cont:
+ skip_one = self.newBlock()
+ self.emit('JUMP _FORWARD', skip_one)
+ self.startBlock (cont)
+ self.emit('POP_ TOP')
+ self.nextBlock( skip_one)
+ self.emit('JUMP _ABSOLUTE', start)
+ self.startBlock (anchor)
+ self.emit('LOAD _CONST', None)
+
+ def visitGenComp(se lf, node):
+ gen = GenCompCodeGene rator(node, self.scopes, self.class_name ,
+ self.get_module ())
+ walk(node.code, gen)
+ gen.finish()
+ self.set_lineno (node)
+ frees = gen.scope.get_f ree_vars()
+ if frees:
+ for name in frees:
+ self.emit('LOAD _CLOSURE', name)
+ self.emit('LOAD _CONST', gen)
+ self.emit('MAKE _CLOSURE', len(node.defaul ts))
+ else:
+ self.emit('LOAD _CONST', gen)
+ self.emit('MAKE _FUNCTION', len(node.defaul ts))
+ self.emit('CALL _FUNCTION', 0)
+
def visitListComp(s elf, node):
self.set_lineno (node)
# setup list
@@ -1245,6 +1290,20 @@

unpackTuple = unpackSequence

+class GenCompCodeGene rator(NestedSco peMixin, AbstractFunctio nCode,
+ CodeGenerator):
+ super_init = CodeGenerator._ _init__ # call be other init
+
+ __super_init = AbstractFunctio nCode.__init__
+
+ def __init__(self, comp, scopes, class_name, mod):
+ self.scopes = scopes
+ self.scope = scopes[comp]
+ self.__super_in it(comp, scopes, 1, class_name, mod)
+ self.graph.setF reeVars(self.sc ope.get_free_va rs())
+ self.graph.setC ellVars(self.sc ope.get_cell_va rs())
+ self.graph.setF lag(CO_GENERATO R)
+
class FunctionCodeGen erator(NestedSc opeMixin, AbstractFunctio nCode,
CodeGenerator):
super_init = CodeGenerator._ _init__ # call be other init
diff -ur compiler.orig/symbols.py compiler/symbols.py
--- compiler.orig/symbols.py 2002-12-31 12:17:42.000000 000 -0600
+++ compiler/symbols.py 2003-08-25 17:03:27.000000 000 -0500
@@ -231,6 +231,15 @@
self.visit(node .code, scope)
self.handle_fre e_vars(scope, parent)

+ def visitGenComp(se lf, node, parent):
+ scope = LambdaScope(sel f.module, self.klass);
+ if parent.nested or isinstance(pare nt, FunctionScope):
+ scope.nested = 1
+ self.scopes[node] = scope
+ self._do_args(s cope, node.argnames)
+ self.visit(node .code, scope)
+ self.handle_fre e_vars(scope, parent)
+
def _do_args(self, scope, args):
for name in args:
if type(name) == types.TupleType :
diff -ur compiler.orig/transformer.py compiler/transformer.py
--- compiler.orig/transformer.py 2003-04-06 04:00:45.000000 000 -0500
+++ compiler/transformer.py 2003-08-26 06:56:02.000000 000 -0500
@@ -1026,18 +1026,25 @@
if hasattr(symbol, 'list_for'):
def com_list_constr uctor(self, nodelist):
# listmaker: test ( list_for | (',' test)* [','] )
+ # | 'yield' list_for
values = []
+ yield_flag = 0
+ if nodelist[1][1] == 'yield':
+ yield_flag = 1
+ nodelist = nodelist[1:]
for i in range(1, len(nodelist)):
if nodelist[i][0] == symbol.list_for :
assert len(nodelist[i:]) == 1
return self.com_list_c omprehension(va lues[0],
- nodelist[i])
+ nodelist[i],
+ yield_flag)
elif nodelist[i][0] == token.COMMA:
continue
values.append(s elf.com_node(no delist[i]))
+ assert not yieldflag
return List(values)

- def com_list_compre hension(self, expr, node):
+ def com_list_compre hension(self, expr, node, yield_flag):
# list_iter: list_for | list_if
# list_for: 'for' exprlist 'in' testlist[list_iter]
# list_if: 'if' test[list_iter]
@@ -1071,7 +1078,10 @@
raise SyntaxError, \
("unexpected list comprehension element: %s %d"
% (node, lineno))
- n = ListComp(expr, fors)
+ if yield_flag:
+ n = GenComp(GenComp Inner(expr, fors))
+ else:
+ n = ListComp(expr, fors)
n.lineno = lineno
return n
Jul 18 '05 #1
2 2316
[Jeff Epler]
Recently, Generator Comprehensions were mentioned again on python-list.
I have written an implementation for the compiler module. To try it
out, however, you must be able to rebuild Python from source, because it
also requires a change to Grammar.


If you put your patch on SourceForge, I'll add a link to it
from the PEP. That way, everyone who is interested in the
subject can experiment with it.

only-a-revolutionary-implements-a-rejected-pep-ly yours,
Raymond Hettinger
Jul 18 '05 #2
On Tue, Aug 26, 2003 at 10:31:15PM +0000, Raymond Hettinger wrote:
If you put your patch on SourceForge, I'll add a link to it
from the PEP. That way, everyone who is interested in the
subject can experiment with it.
http://python.org/sf/795947
only-a-revolutionary-implements-a-rejected-pep-ly yours,


Well, it's only half-implemented, since I didn't touch the written-in-C
compiler. It's also half-implemented in terms of lacking tests.

Jeff

Jul 18 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

72
4337
by: Raymond Hettinger | last post by:
Peter Norvig's creative thinking triggered renewed interest in PEP 289. That led to a number of contributors helping to re-work the pep details into a form that has been well received on the python-dev list: http://www.python.org/peps/pep-0289.html In brief, the PEP proposes a list comprehension style syntax for creating fast, memory...
24
3324
by: Mahesh Padmanabhan | last post by:
Hi, When list comprehension was added to the language, I had a lot of trouble understanding it but now that I am familiar with it, I am not sure how I programmed in Python without it. Now I see that generator expressions have been added to the language with 2.4 and I question the need for it. I know that it allows for lazy evaluation...
6
6156
by: Martin Bless | last post by:
The good news: Along with Python-2.4 comes really good news to Windows users. Yes, you now CAN build extension modules yourself using the SAME C++ compiler and linker Python is built with itself. Everything you need is available at no costs (except download hassle and installation time). Once your system is set up properly its just a matter...
45
2981
by: Joh | last post by:
hello, i'm trying to understand how i could build following consecutive sets from a root one using generator : l = would like to produce : , , , ,
10
1388
by: jamesthiele.usenet | last post by:
I wrote this little piece of code to get a list of relative paths of all files in or below the current directory (*NIX): walkList = , x) for x in os.walk(".")] filenames = for dir, files in walkList: filenames.extend() for f in files]) It works fine, I don't need to change it, but I know there is a one liner list/generator...
23
2228
by: Mike Meyer | last post by:
Ok, we've added list comprehensions to the language, and seen that they were good. We've added generator expressions to the language, and seen that they were good as well. I'm left a bit confused, though - when would I use a list comp instead of a generator expression if I'm going to require 2.4 anyway? Thanks, <mike --
0
1564
by: Kurt B. Kaiser | last post by:
Patch / Bug Summary ___________________ Patches : 391 open ( +7) / 3028 closed (+12) / 3419 total (+19) Bugs : 906 open ( -3) / 5519 closed (+19) / 6425 total (+16) RFE : 207 open ( -1) / 197 closed ( +1) / 404 total ( +0) New / Reopened Patches ______________________
0
361
by: Kurt B. Kaiser | last post by:
Patch / Bug Summary ___________________ Patches : 378 open ( +3) / 3298 closed (+34) / 3676 total (+37) Bugs : 886 open (-24) / 5926 closed (+75) / 6812 total (+51) RFE : 224 open ( +7) / 227 closed ( +7) / 451 total (+14) New / Reopened Patches ______________________
1
1842
by: cokofreedom | last post by:
if __name__ == '__main__': print "Globals (For Loop):" try: for i in globals(): print "\t%s" % i except RuntimeError: print "Only some globals() printed\n" else: print "All globals() printed\n"
0
7420
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
1
7446
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7778
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6003
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5349
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
4966
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3476
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1033
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
731
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.