| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  | import imp | 
					
						
							| 
									
										
										
										
											2000-02-08 19:01:29 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | import marshal | 
					
						
							| 
									
										
										
										
											2000-02-08 19:01:29 +00:00
										 |  |  | import struct | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | from cStringIO import StringIO | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  | from compiler import ast, parse, walk, syntax | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | from compiler import pyassem, misc, future, symbols | 
					
						
							|  |  |  | from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL | 
					
						
							| 
									
										
										
										
											2001-08-30 20:25:55 +00:00
										 |  |  | from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\ | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |      CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION | 
					
						
							| 
									
										
										
										
											2001-08-30 20:25:55 +00:00
										 |  |  | from compiler.pyassem import TupleArg | 
					
						
							| 
									
										
										
										
											2000-02-11 20:27:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  | # XXX The version-specific code can go, since this code only works with 2.x. | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  | # Do we have Python 1.x or Python 2.x? | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     VERSION = sys.version_info[0] | 
					
						
							|  |  |  | except AttributeError: | 
					
						
							|  |  |  |     VERSION = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-02 22:32:59 +00:00
										 |  |  | callfunc_opcode_info = { | 
					
						
							|  |  |  |     # (Have *args, Have **args) : opcode | 
					
						
							|  |  |  |     (0,0) : "CALL_FUNCTION", | 
					
						
							|  |  |  |     (1,0) : "CALL_FUNCTION_VAR", | 
					
						
							|  |  |  |     (0,1) : "CALL_FUNCTION_KW", | 
					
						
							|  |  |  |     (1,1) : "CALL_FUNCTION_VAR_KW", | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  | LOOP = 1 | 
					
						
							|  |  |  | EXCEPT = 2 | 
					
						
							|  |  |  | TRY_FINALLY = 3 | 
					
						
							|  |  |  | END_FINALLY = 4 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  | def compileFile(filename, display=0): | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |     f = open(filename, 'U') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     buf = f.read() | 
					
						
							|  |  |  |     f.close() | 
					
						
							|  |  |  |     mod = Module(buf, filename) | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         mod.compile(display) | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |     except SyntaxError: | 
					
						
							| 
									
										
										
										
											2001-09-17 19:33:48 +00:00
										 |  |  |         raise | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         f = open(filename + "c", "wb") | 
					
						
							|  |  |  |         mod.dump(f) | 
					
						
							|  |  |  |         f.close() | 
					
						
							| 
									
										
										
										
											2000-02-16 00:55:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  | def compile(source, filename, mode, flags=None, dont_inherit=None): | 
					
						
							|  |  |  |     """Replacement for builtin compile() function""" | 
					
						
							|  |  |  |     if flags is not None or dont_inherit is not None: | 
					
						
							|  |  |  |         raise RuntimeError, "not implemented yet" | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  |     if mode == "single": | 
					
						
							|  |  |  |         gen = Interactive(source, filename) | 
					
						
							|  |  |  |     elif mode == "exec": | 
					
						
							|  |  |  |         gen = Module(source, filename) | 
					
						
							|  |  |  |     elif mode == "eval": | 
					
						
							|  |  |  |         gen = Expression(source, filename) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         raise ValueError("compile() 3rd arg must be 'exec' or " | 
					
						
							|  |  |  |                          "'eval' or 'single'") | 
					
						
							|  |  |  |     gen.compile() | 
					
						
							|  |  |  |     return gen.code | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AbstractCompileMode: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mode = None # defined by subclass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def __init__(self, source, filename): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.source = source | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  |         self.filename = filename | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.code = None | 
					
						
							| 
									
										
										
										
											2000-02-16 00:55:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  |     def _get_tree(self): | 
					
						
							|  |  |  |         tree = parse(self.source, self.mode) | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         misc.set_filename(self.filename, tree) | 
					
						
							|  |  |  |         syntax.check(tree) | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  |         return tree | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def compile(self): | 
					
						
							|  |  |  |         pass # implemented by subclass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getCode(self): | 
					
						
							|  |  |  |         return self.code | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Expression(AbstractCompileMode): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mode = "eval" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def compile(self): | 
					
						
							|  |  |  |         tree = self._get_tree() | 
					
						
							|  |  |  |         gen = ExpressionCodeGenerator(tree) | 
					
						
							|  |  |  |         self.code = gen.getCode() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Interactive(AbstractCompileMode): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mode = "single" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def compile(self): | 
					
						
							|  |  |  |         tree = self._get_tree() | 
					
						
							|  |  |  |         gen = InteractiveCodeGenerator(tree) | 
					
						
							|  |  |  |         self.code = gen.getCode() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Module(AbstractCompileMode): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mode = "exec" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def compile(self, display=0): | 
					
						
							|  |  |  |         tree = self._get_tree() | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         gen = ModuleCodeGenerator(tree) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         if display: | 
					
						
							|  |  |  |             import pprint | 
					
						
							| 
									
										
										
										
											2001-04-09 04:28:48 +00:00
										 |  |  |             print pprint.pprint(tree) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.code = gen.getCode() | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def dump(self, f): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         f.write(self.getPycHeader()) | 
					
						
							|  |  |  |         marshal.dump(self.code, f) | 
					
						
							| 
									
										
										
										
											2000-02-12 00:12:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |     MAGIC = imp.get_magic() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def getPycHeader(self): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         # compile.c uses marshal to write a long directly, with | 
					
						
							|  |  |  |         # calling the interface that would also generate a 1-byte code | 
					
						
							|  |  |  |         # to indicate the type of the value.  simplest way to get the | 
					
						
							|  |  |  |         # same effect is to call marshal and then skip the code. | 
					
						
							| 
									
										
										
										
											2002-06-06 18:30:10 +00:00
										 |  |  |         mtime = os.path.getmtime(self.filename) | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |         mtime = struct.pack('<i', mtime) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         return self.MAGIC + mtime | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | class LocalNameFinder: | 
					
						
							|  |  |  |     """Find local names in scope""" | 
					
						
							|  |  |  |     def __init__(self, names=()): | 
					
						
							|  |  |  |         self.names = misc.Set() | 
					
						
							|  |  |  |         self.globals = misc.Set() | 
					
						
							|  |  |  |         for name in names: | 
					
						
							|  |  |  |             self.names.add(name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # XXX list comprehensions and for loops | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getLocals(self): | 
					
						
							|  |  |  |         for elt in self.globals.elements(): | 
					
						
							|  |  |  |             if self.names.has_elt(elt): | 
					
						
							|  |  |  |                 self.names.remove(elt) | 
					
						
							|  |  |  |         return self.names | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitDict(self, node): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitGlobal(self, node): | 
					
						
							|  |  |  |         for name in node.names: | 
					
						
							|  |  |  |             self.globals.add(name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitFunction(self, node): | 
					
						
							|  |  |  |         self.names.add(node.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitLambda(self, node): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitImport(self, node): | 
					
						
							|  |  |  |         for name, alias in node.names: | 
					
						
							|  |  |  |             self.names.add(alias or name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitFrom(self, node): | 
					
						
							|  |  |  |         for name, alias in node.names: | 
					
						
							|  |  |  |             self.names.add(alias or name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitClass(self, node): | 
					
						
							|  |  |  |         self.names.add(node.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitAssName(self, node): | 
					
						
							|  |  |  |         self.names.add(node.name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  | def is_constant_false(node): | 
					
						
							|  |  |  |     if isinstance(node, ast.Const): | 
					
						
							|  |  |  |         if not node.value: | 
					
						
							|  |  |  |             return 1 | 
					
						
							|  |  |  |     return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | class CodeGenerator: | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     """Defines basic code generator for Python bytecode
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This class is an abstract base class.  Concrete subclasses must | 
					
						
							|  |  |  |     define an __init__() that defines self.graph and then calls the | 
					
						
							|  |  |  |     __init__() defined in this class. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The concrete class must also define the class attributes | 
					
						
							|  |  |  |     NameFinder, FunctionGen, and ClassGen.  These attributes can be | 
					
						
							|  |  |  |     defined in the initClass() method, which is a hook for | 
					
						
							|  |  |  |     initializing these methods after all the classes have been | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  |     defined. | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     optimized = 0 # is namespace access optimized? | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     __initialized = None | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |     class_name = None # provide default for instance variable | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     def __init__(self): | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |         if self.__initialized is None: | 
					
						
							|  |  |  |             self.initClass() | 
					
						
							|  |  |  |             self.__class__.__initialized = 1 | 
					
						
							|  |  |  |         self.checkClass() | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.locals = misc.Stack() | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups = misc.Stack() | 
					
						
							| 
									
										
										
										
											2000-09-01 20:47:37 +00:00
										 |  |  |         self.last_lineno = None | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self._setupGraphDelegation() | 
					
						
							| 
									
										
										
										
											2001-09-17 16:41:02 +00:00
										 |  |  |         self._div_op = "BINARY_DIVIDE" | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         # XXX set flags based on future features | 
					
						
							|  |  |  |         futures = self.get_module().futures | 
					
						
							|  |  |  |         for feature in futures: | 
					
						
							|  |  |  |             if feature == "division": | 
					
						
							|  |  |  |                 self.graph.setFlag(CO_FUTURE_DIVISION) | 
					
						
							| 
									
										
										
										
											2001-09-17 16:41:02 +00:00
										 |  |  |                 self._div_op = "BINARY_TRUE_DIVIDE" | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |             elif feature == "generators": | 
					
						
							|  |  |  |                 self.graph.setFlag(CO_GENERATOR_ALLOWED) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     def initClass(self): | 
					
						
							|  |  |  |         """This method is called once for each class""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def checkClass(self): | 
					
						
							|  |  |  |         """Verify that class is constructed correctly""" | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             assert hasattr(self, 'graph') | 
					
						
							|  |  |  |             assert getattr(self, 'NameFinder') | 
					
						
							|  |  |  |             assert getattr(self, 'FunctionGen') | 
					
						
							|  |  |  |             assert getattr(self, 'ClassGen') | 
					
						
							|  |  |  |         except AssertionError, msg: | 
					
						
							|  |  |  |             intro = "Bad class construction for %s" % self.__class__.__name__ | 
					
						
							|  |  |  |             raise AssertionError, intro | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def _setupGraphDelegation(self): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.emit = self.graph.emit | 
					
						
							|  |  |  |         self.newBlock = self.graph.newBlock | 
					
						
							|  |  |  |         self.startBlock = self.graph.startBlock | 
					
						
							|  |  |  |         self.nextBlock = self.graph.nextBlock | 
					
						
							|  |  |  |         self.setDocstring = self.graph.setDocstring | 
					
						
							| 
									
										
										
										
											2000-02-11 20:27:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def getCode(self): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         """Return a code object""" | 
					
						
							|  |  |  |         return self.graph.getCode() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |     def mangle(self, name): | 
					
						
							|  |  |  |         if self.class_name is not None: | 
					
						
							|  |  |  |             return misc.mangle(name, self.class_name) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |     def parseSymbols(self, tree): | 
					
						
							|  |  |  |         s = symbols.SymbolVisitor() | 
					
						
							|  |  |  |         walk(tree, s) | 
					
						
							|  |  |  |         return s.scopes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_module(self): | 
					
						
							|  |  |  |         raise RuntimeError, "should be implemented by subclasses" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # Next five methods handle name access | 
					
						
							| 
									
										
										
										
											2000-02-08 19:01:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |     def isLocalName(self, name): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.locals.top().has_elt(name) | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-10 17:20:39 +00:00
										 |  |  |     def storeName(self, name): | 
					
						
							|  |  |  |         self._nameOp('STORE', name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def loadName(self, name): | 
					
						
							|  |  |  |         self._nameOp('LOAD', name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def delName(self, name): | 
					
						
							|  |  |  |         self._nameOp('DELETE', name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def _nameOp(self, prefix, name): | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |         name = self.mangle(name) | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         scope = self.scope.check_name(name) | 
					
						
							|  |  |  |         if scope == SC_LOCAL: | 
					
						
							|  |  |  |             if not self.optimized: | 
					
						
							|  |  |  |                 self.emit(prefix + '_NAME', name) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.emit(prefix + '_FAST', name) | 
					
						
							|  |  |  |         elif scope == SC_GLOBAL: | 
					
						
							|  |  |  |             if not self.optimized: | 
					
						
							|  |  |  |                 self.emit(prefix + '_NAME', name) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.emit(prefix + '_GLOBAL', name) | 
					
						
							|  |  |  |         elif scope == SC_FREE or scope == SC_CELL: | 
					
						
							|  |  |  |             self.emit(prefix + '_DEREF', name) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |             raise RuntimeError, "unsupported scope for var %s: %d" % \ | 
					
						
							|  |  |  |                   (name, scope) | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 21:04:43 +00:00
										 |  |  |     def _implicitNameOp(self, prefix, name): | 
					
						
							|  |  |  |         """Emit name ops for names generated implicitly by for loops
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The interpreter generates names that start with a period or | 
					
						
							|  |  |  |         dollar sign.  The symbol table ignores these names because | 
					
						
							|  |  |  |         they aren't present in the program text. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         if self.optimized: | 
					
						
							|  |  |  |             self.emit(prefix + '_FAST', name) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.emit(prefix + '_NAME', name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |     # The set_lineno() function and the explicit emit() calls for | 
					
						
							|  |  |  |     # SET_LINENO below are only used to generate the line number table. | 
					
						
							|  |  |  |     # As of Python 2.3, the interpreter does not have a SET_LINENO | 
					
						
							|  |  |  |     # instruction.  pyassem treats SET_LINENO opcodes as a special case. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_lineno(self, node, force=False): | 
					
						
							|  |  |  |         """Emit SET_LINENO if necessary.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The instruction is considered necessary if the node has a | 
					
						
							|  |  |  |         lineno attribute and it is different than the last lineno | 
					
						
							|  |  |  |         emitted. | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Returns true if SET_LINENO was emitted. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         There are no rules for when an AST node should have a lineno | 
					
						
							|  |  |  |         attribute.  The transformer and AST code need to be reviewed | 
					
						
							|  |  |  |         and a consistent policy implemented and documented.  Until | 
					
						
							|  |  |  |         then, this method works around missing line numbers. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         lineno = getattr(node, 'lineno', None) | 
					
						
							| 
									
										
										
										
											2001-04-12 20:21:39 +00:00
										 |  |  |         if lineno is not None and (lineno != self.last_lineno | 
					
						
							|  |  |  |                                    or force): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |             self.emit('SET_LINENO', lineno) | 
					
						
							| 
									
										
										
										
											2000-09-01 20:47:37 +00:00
										 |  |  |             self.last_lineno = lineno | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |             return True | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # The first few visitor methods handle nodes that generator new | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     # code objects.  They use class attributes to determine what | 
					
						
							|  |  |  |     # specialized code generators to use. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NameFinder = LocalNameFinder | 
					
						
							|  |  |  |     FunctionGen = None | 
					
						
							|  |  |  |     ClassGen = None | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  |     def visitModule(self, node): | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         self.scopes = self.parseSymbols(node) | 
					
						
							|  |  |  |         self.scope = self.scopes[node] | 
					
						
							| 
									
										
										
										
											2001-04-12 21:04:43 +00:00
										 |  |  |         self.emit('SET_LINENO', 0) | 
					
						
							| 
									
										
										
										
											2001-04-11 16:24:30 +00:00
										 |  |  |         if node.doc: | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |             self.emit('LOAD_CONST', node.doc) | 
					
						
							|  |  |  |             self.storeName('__doc__') | 
					
						
							|  |  |  |         lnf = walk(node.node, self.NameFinder(), verbose=0) | 
					
						
							|  |  |  |         self.locals.push(lnf.getLocals()) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.visit(node.node) | 
					
						
							|  |  |  |         self.emit('LOAD_CONST', None) | 
					
						
							|  |  |  |         self.emit('RETURN_VALUE') | 
					
						
							| 
									
										
										
										
											2000-02-04 19:37:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-21 20:04:22 +00:00
										 |  |  |     def visitExpression(self, node): | 
					
						
							|  |  |  |         self.set_lineno(node) | 
					
						
							|  |  |  |         self.scopes = self.parseSymbols(node) | 
					
						
							|  |  |  |         self.scope = self.scopes[node] | 
					
						
							|  |  |  |         self.visit(node.node) | 
					
						
							|  |  |  |         self.emit('RETURN_VALUE') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitFunction(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self._visitFuncOrLambda(node, isLambda=0) | 
					
						
							| 
									
										
										
										
											2001-04-11 16:24:30 +00:00
										 |  |  |         if node.doc: | 
					
						
							|  |  |  |             self.setDocstring(node.doc) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.storeName(node.name) | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitLambda(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self._visitFuncOrLambda(node, isLambda=1) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     def _visitFuncOrLambda(self, node, isLambda=0): | 
					
						
							| 
									
										
										
										
											2004-08-02 06:10:11 +00:00
										 |  |  |         if not isLambda and node.decorators: | 
					
						
							| 
									
										
										
										
											2004-08-17 17:29:16 +00:00
										 |  |  |             for decorator in node.decorators.nodes: | 
					
						
							| 
									
										
										
										
											2004-08-02 06:10:11 +00:00
										 |  |  |                 self.visit(decorator) | 
					
						
							|  |  |  |             ndecorators = len(node.decorators.nodes) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             ndecorators = 0 | 
					
						
							| 
									
										
										
										
											2004-08-20 03:47:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         gen = self.FunctionGen(node, self.scopes, isLambda, | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |                                self.class_name, self.get_module()) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         walk(node.code, gen) | 
					
						
							|  |  |  |         gen.finish() | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         for default in node.defaults: | 
					
						
							|  |  |  |             self.visit(default) | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         frees = gen.scope.get_free_vars() | 
					
						
							|  |  |  |         if frees: | 
					
						
							|  |  |  |             for name in frees: | 
					
						
							|  |  |  |                 self.emit('LOAD_CLOSURE', name) | 
					
						
							|  |  |  |             self.emit('LOAD_CONST', gen) | 
					
						
							|  |  |  |             self.emit('MAKE_CLOSURE', len(node.defaults)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.emit('LOAD_CONST', gen) | 
					
						
							|  |  |  |             self.emit('MAKE_FUNCTION', len(node.defaults)) | 
					
						
							| 
									
										
										
										
											2004-08-04 02:36:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-02 06:10:11 +00:00
										 |  |  |         for i in range(ndecorators): | 
					
						
							|  |  |  |             self.emit('CALL_FUNCTION', 1) | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-06 19:10:54 +00:00
										 |  |  |     def visitClass(self, node): | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         gen = self.ClassGen(node, self.scopes, | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |                             self.get_module()) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         walk(node.code, gen) | 
					
						
							|  |  |  |         gen.finish() | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |         self.emit('LOAD_CONST', node.name) | 
					
						
							| 
									
										
										
										
											2000-02-12 00:12:38 +00:00
										 |  |  |         for base in node.bases: | 
					
						
							|  |  |  |             self.visit(base) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |         self.emit('BUILD_TUPLE', len(node.bases)) | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         frees = gen.scope.get_free_vars() | 
					
						
							|  |  |  |         for name in frees: | 
					
						
							|  |  |  |             self.emit('LOAD_CLOSURE', name) | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |         self.emit('LOAD_CONST', gen) | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         if frees: | 
					
						
							|  |  |  |             self.emit('MAKE_CLOSURE', 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.emit('MAKE_FUNCTION', 0) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |         self.emit('CALL_FUNCTION', 0) | 
					
						
							|  |  |  |         self.emit('BUILD_CLASS') | 
					
						
							| 
									
										
										
										
											2000-02-12 00:12:38 +00:00
										 |  |  |         self.storeName(node.name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # The rest are standard visitor methods | 
					
						
							| 
									
										
										
										
											2000-02-11 20:27:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # The next few implement control-flow statements | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitIf(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         end = self.newBlock() | 
					
						
							|  |  |  |         numtests = len(node.tests) | 
					
						
							|  |  |  |         for i in range(numtests): | 
					
						
							|  |  |  |             test, suite = node.tests[i] | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |             if is_constant_false(test): | 
					
						
							|  |  |  |                 # XXX will need to check generator stuff here | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |             self.set_lineno(test) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             self.visit(test) | 
					
						
							|  |  |  |             nextTest = self.newBlock() | 
					
						
							|  |  |  |             self.emit('JUMP_IF_FALSE', nextTest) | 
					
						
							|  |  |  |             self.nextBlock() | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |             self.visit(suite) | 
					
						
							|  |  |  |             self.emit('JUMP_FORWARD', end) | 
					
						
							| 
									
										
										
										
											2000-11-06 03:43:11 +00:00
										 |  |  |             self.startBlock(nextTest) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |         if node.else_: | 
					
						
							|  |  |  |             self.visit(node.else_) | 
					
						
							|  |  |  |         self.nextBlock(end) | 
					
						
							| 
									
										
										
										
											2000-02-11 20:27:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitWhile(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         loop = self.newBlock() | 
					
						
							|  |  |  |         else_ = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-02-12 00:12:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         after = self.newBlock() | 
					
						
							|  |  |  |         self.emit('SETUP_LOOP', after) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.nextBlock(loop) | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.push((LOOP, loop)) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |         self.set_lineno(node, force=True) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.visit(node.test) | 
					
						
							|  |  |  |         self.emit('JUMP_IF_FALSE', else_ or after) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.nextBlock() | 
					
						
							|  |  |  |         self.emit('POP_TOP') | 
					
						
							|  |  |  |         self.visit(node.body) | 
					
						
							|  |  |  |         self.emit('JUMP_ABSOLUTE', loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.startBlock(else_) # or just the POPs if not else clause | 
					
						
							|  |  |  |         self.emit('POP_TOP') | 
					
						
							|  |  |  |         self.emit('POP_BLOCK') | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.pop() | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         if node.else_: | 
					
						
							|  |  |  |             self.visit(node.else_) | 
					
						
							|  |  |  |         self.nextBlock(after) | 
					
						
							| 
									
										
										
										
											2000-02-10 20:55:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |     def visitFor(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         start = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         anchor = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         after = self.newBlock() | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.push((LOOP, start)) | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.emit('SETUP_LOOP', after) | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |         self.visit(node.list) | 
					
						
							| 
									
										
										
										
											2001-08-28 16:35:18 +00:00
										 |  |  |         self.emit('GET_ITER') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.nextBlock(start) | 
					
						
							| 
									
										
										
										
											2001-04-12 21:54:41 +00:00
										 |  |  |         self.set_lineno(node, force=1) | 
					
						
							| 
									
										
										
										
											2001-08-28 16:35:18 +00:00
										 |  |  |         self.emit('FOR_ITER', anchor) | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |         self.visit(node.assign) | 
					
						
							|  |  |  |         self.visit(node.body) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.emit('JUMP_ABSOLUTE', start) | 
					
						
							| 
									
										
										
										
											2001-08-28 17:28:33 +00:00
										 |  |  |         self.nextBlock(anchor) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |         self.emit('POP_BLOCK') | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.pop() | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |         if node.else_: | 
					
						
							|  |  |  |             self.visit(node.else_) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.nextBlock(after) | 
					
						
							| 
									
										
										
										
											2000-02-10 20:55:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitBreak(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         if not self.setups: | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             raise SyntaxError, "'break' outside loop (%s, %d)" % \ | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |                   (node.filename, node.lineno) | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.emit('BREAK_LOOP') | 
					
						
							| 
									
										
										
										
											2000-02-10 20:55:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitContinue(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         if not self.setups: | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |             raise SyntaxError, "'continue' outside loop (%s, %d)" % \ | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |                   (node.filename, node.lineno) | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         kind, block = self.setups.top() | 
					
						
							|  |  |  |         if kind == LOOP: | 
					
						
							|  |  |  |             self.set_lineno(node) | 
					
						
							|  |  |  |             self.emit('JUMP_ABSOLUTE', block) | 
					
						
							|  |  |  |             self.nextBlock() | 
					
						
							|  |  |  |         elif kind == EXCEPT or kind == TRY_FINALLY: | 
					
						
							|  |  |  |             self.set_lineno(node) | 
					
						
							|  |  |  |             # find the block that starts the loop | 
					
						
							|  |  |  |             top = len(self.setups) | 
					
						
							|  |  |  |             while top > 0: | 
					
						
							|  |  |  |                 top = top - 1 | 
					
						
							|  |  |  |                 kind, loop_block = self.setups[top] | 
					
						
							|  |  |  |                 if kind == LOOP: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |             if kind != LOOP: | 
					
						
							|  |  |  |                 raise SyntaxError, "'continue' outside loop (%s, %d)" % \ | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |                       (node.filename, node.lineno) | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |             self.emit('CONTINUE_LOOP', loop_block) | 
					
						
							|  |  |  |             self.nextBlock() | 
					
						
							|  |  |  |         elif kind == END_FINALLY: | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  |             msg = "'continue' not allowed inside 'finally' clause (%s, %d)" | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |             raise SyntaxError, msg % (node.filename, node.lineno) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitTest(self, node, jump): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         end = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         for child in node.nodes[:-1]: | 
					
						
							|  |  |  |             self.visit(child) | 
					
						
							|  |  |  |             self.emit(jump, end) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             self.nextBlock() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |         self.visit(node.nodes[-1]) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.nextBlock(end) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitAnd(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.visitTest(node, 'JUMP_IF_FALSE') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitOr(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.visitTest(node, 'JUMP_IF_TRUE') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitCompare(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         cleanup = self.newBlock() | 
					
						
							|  |  |  |         for op, code in node.ops[:-1]: | 
					
						
							|  |  |  |             self.visit(code) | 
					
						
							|  |  |  |             self.emit('DUP_TOP') | 
					
						
							|  |  |  |             self.emit('ROT_THREE') | 
					
						
							|  |  |  |             self.emit('COMPARE_OP', op) | 
					
						
							|  |  |  |             self.emit('JUMP_IF_FALSE', cleanup) | 
					
						
							|  |  |  |             self.nextBlock() | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |         # now do the last comparison | 
					
						
							|  |  |  |         if node.ops: | 
					
						
							|  |  |  |             op, code = node.ops[-1] | 
					
						
							|  |  |  |             self.visit(code) | 
					
						
							|  |  |  |             self.emit('COMPARE_OP', op) | 
					
						
							|  |  |  |         if len(node.ops) > 1: | 
					
						
							|  |  |  |             end = self.newBlock() | 
					
						
							|  |  |  |             self.emit('JUMP_FORWARD', end) | 
					
						
							| 
									
										
										
										
											2000-11-06 03:43:11 +00:00
										 |  |  |             self.startBlock(cleanup) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             self.emit('ROT_TWO') | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |             self.nextBlock(end) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |     # list comprehensions | 
					
						
							|  |  |  |     __list_count = 0 | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |     def visitListComp(self, node): | 
					
						
							|  |  |  |         self.set_lineno(node) | 
					
						
							|  |  |  |         # setup list | 
					
						
							|  |  |  |         append = "$append%d" % self.__list_count | 
					
						
							|  |  |  |         self.__list_count = self.__list_count + 1 | 
					
						
							|  |  |  |         self.emit('BUILD_LIST', 0) | 
					
						
							|  |  |  |         self.emit('DUP_TOP') | 
					
						
							|  |  |  |         self.emit('LOAD_ATTR', 'append') | 
					
						
							| 
									
										
										
										
											2001-04-12 21:04:43 +00:00
										 |  |  |         self._implicitNameOp('STORE', append) | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         stack = [] | 
					
						
							| 
									
										
										
										
											2001-04-12 20:21:39 +00:00
										 |  |  |         for i, for_ in zip(range(len(node.quals)), node.quals): | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |             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)) | 
					
						
							| 
									
										
										
										
											2001-04-12 20:21:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 21:04:43 +00:00
										 |  |  |         self._implicitNameOp('LOAD', append) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         self.emit('CALL_FUNCTION', 1) | 
					
						
							|  |  |  |         self.emit('POP_TOP') | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         for start, cont, anchor in stack: | 
					
						
							|  |  |  |             if cont: | 
					
						
							|  |  |  |                 skip_one = self.newBlock() | 
					
						
							|  |  |  |                 self.emit('JUMP_FORWARD', skip_one) | 
					
						
							| 
									
										
										
										
											2000-11-06 03:43:11 +00:00
										 |  |  |                 self.startBlock(cont) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |                 self.emit('POP_TOP') | 
					
						
							|  |  |  |                 self.nextBlock(skip_one) | 
					
						
							|  |  |  |             self.emit('JUMP_ABSOLUTE', start) | 
					
						
							| 
									
										
										
										
											2000-11-06 03:43:11 +00:00
										 |  |  |             self.startBlock(anchor) | 
					
						
							| 
									
										
										
										
											2001-04-12 21:04:43 +00:00
										 |  |  |         self._implicitNameOp('DELETE', append) | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         self.__list_count = self.__list_count - 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitListCompFor(self, node): | 
					
						
							|  |  |  |         start = self.newBlock() | 
					
						
							|  |  |  |         anchor = self.newBlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.visit(node.list) | 
					
						
							| 
									
										
										
										
											2001-08-30 20:25:55 +00:00
										 |  |  |         self.emit('GET_ITER') | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         self.nextBlock(start) | 
					
						
							| 
									
										
										
										
											2002-12-31 18:26:17 +00:00
										 |  |  |         self.set_lineno(node, force=True) | 
					
						
							| 
									
										
										
										
											2001-08-30 20:25:55 +00:00
										 |  |  |         self.emit('FOR_ITER', anchor) | 
					
						
							| 
									
										
										
										
											2000-11-06 03:43:11 +00:00
										 |  |  |         self.nextBlock() | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         self.visit(node.assign) | 
					
						
							|  |  |  |         return start, anchor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitListCompIf(self, node, branch): | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |         self.set_lineno(node, force=True) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         self.visit(node.test) | 
					
						
							|  |  |  |         self.emit('JUMP_IF_FALSE', branch) | 
					
						
							|  |  |  |         self.newBlock() | 
					
						
							|  |  |  |         self.emit('POP_TOP') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-19 08:20:33 +00:00
										 |  |  |     def visitGenExpr(self, node): | 
					
						
							|  |  |  |         gen = GenExprCodeGenerator(node, self.scopes, self.class_name, | 
					
						
							|  |  |  |                                    self.get_module()) | 
					
						
							|  |  |  |         walk(node.code, gen) | 
					
						
							|  |  |  |         gen.finish() | 
					
						
							|  |  |  |         self.set_lineno(node) | 
					
						
							|  |  |  |         frees = gen.scope.get_free_vars() | 
					
						
							|  |  |  |         if frees: | 
					
						
							|  |  |  |             for name in frees: | 
					
						
							|  |  |  |                 self.emit('LOAD_CLOSURE', name) | 
					
						
							|  |  |  |             self.emit('LOAD_CONST', gen) | 
					
						
							|  |  |  |             self.emit('MAKE_CLOSURE', 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.emit('LOAD_CONST', gen) | 
					
						
							|  |  |  |             self.emit('MAKE_FUNCTION', 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # precomputation of outmost iterable | 
					
						
							|  |  |  |         self.visit(node.code.quals[0].iter) | 
					
						
							|  |  |  |         self.emit('GET_ITER') | 
					
						
							|  |  |  |         self.emit('CALL_FUNCTION', 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitGenExprInner(self, node): | 
					
						
							|  |  |  |         self.set_lineno(node) | 
					
						
							|  |  |  |         # setup list | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         stack = [] | 
					
						
							|  |  |  |         for i, for_ in zip(range(len(node.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('YIELD_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 visitGenExprFor(self, node): | 
					
						
							|  |  |  |         start = self.newBlock() | 
					
						
							|  |  |  |         anchor = self.newBlock() | 
					
						
							| 
									
										
										
										
											2004-07-07 20:54:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-19 08:20:33 +00:00
										 |  |  |         if node.is_outmost: | 
					
						
							|  |  |  |             self.loadName('[outmost-iterable]') | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.visit(node.iter) | 
					
						
							|  |  |  |             self.emit('GET_ITER') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.nextBlock(start) | 
					
						
							|  |  |  |         self.set_lineno(node, force=True) | 
					
						
							|  |  |  |         self.emit('FOR_ITER', anchor) | 
					
						
							|  |  |  |         self.nextBlock() | 
					
						
							|  |  |  |         self.visit(node.assign) | 
					
						
							|  |  |  |         return start, anchor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitGenExprIf(self, node, branch): | 
					
						
							|  |  |  |         self.set_lineno(node, force=True) | 
					
						
							|  |  |  |         self.visit(node.test) | 
					
						
							|  |  |  |         self.emit('JUMP_IF_FALSE', branch) | 
					
						
							|  |  |  |         self.newBlock() | 
					
						
							|  |  |  |         self.emit('POP_TOP') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # exception related | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitAssert(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         # XXX would be interesting to implement this via a | 
					
						
							|  |  |  |         # transformation of the AST before this stage | 
					
						
							| 
									
										
										
										
											2004-08-07 19:21:56 +00:00
										 |  |  |         if __debug__: | 
					
						
							|  |  |  |             end = self.newBlock() | 
					
						
							|  |  |  |             self.set_lineno(node) | 
					
						
							|  |  |  |             # XXX AssertionError appears to be special case -- it is always | 
					
						
							|  |  |  |             # loaded as a global even if there is a local name.  I guess this | 
					
						
							|  |  |  |             # is a sort of renaming op. | 
					
						
							|  |  |  |             self.nextBlock() | 
					
						
							|  |  |  |             self.visit(node.test) | 
					
						
							|  |  |  |             self.emit('JUMP_IF_TRUE', end) | 
					
						
							|  |  |  |             self.nextBlock() | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |             self.emit('LOAD_GLOBAL', 'AssertionError') | 
					
						
							|  |  |  |             if node.fail: | 
					
						
							|  |  |  |                 self.visit(node.fail) | 
					
						
							|  |  |  |                 self.emit('RAISE_VARARGS', 2) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.emit('RAISE_VARARGS', 1) | 
					
						
							|  |  |  |             self.nextBlock(end) | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitRaise(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         n = 0 | 
					
						
							|  |  |  |         if node.expr1: | 
					
						
							|  |  |  |             self.visit(node.expr1) | 
					
						
							|  |  |  |             n = n + 1 | 
					
						
							|  |  |  |         if node.expr2: | 
					
						
							|  |  |  |             self.visit(node.expr2) | 
					
						
							|  |  |  |             n = n + 1 | 
					
						
							|  |  |  |         if node.expr3: | 
					
						
							|  |  |  |             self.visit(node.expr3) | 
					
						
							|  |  |  |             n = n + 1 | 
					
						
							|  |  |  |         self.emit('RAISE_VARARGS', n) | 
					
						
							| 
									
										
										
										
											2000-02-10 20:55:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |     def visitTryExcept(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         body = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         handlers = self.newBlock() | 
					
						
							|  |  |  |         end = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         if node.else_: | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |             lElse = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             lElse = end | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.emit('SETUP_EXCEPT', handlers) | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.nextBlock(body) | 
					
						
							|  |  |  |         self.setups.push((EXCEPT, body)) | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.visit(node.body) | 
					
						
							|  |  |  |         self.emit('POP_BLOCK') | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.pop() | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.emit('JUMP_FORWARD', lElse) | 
					
						
							| 
									
										
										
										
											2000-11-06 03:43:11 +00:00
										 |  |  |         self.startBlock(handlers) | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         last = len(node.handlers) - 1 | 
					
						
							|  |  |  |         for i in range(len(node.handlers)): | 
					
						
							|  |  |  |             expr, target, body = node.handlers[i] | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |             self.set_lineno(expr) | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |             if expr: | 
					
						
							|  |  |  |                 self.emit('DUP_TOP') | 
					
						
							|  |  |  |                 self.visit(expr) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |                 self.emit('COMPARE_OP', 'exception match') | 
					
						
							|  |  |  |                 next = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |                 self.emit('JUMP_IF_FALSE', next) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |                 self.nextBlock() | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |                 self.emit('POP_TOP') | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |             if target: | 
					
						
							|  |  |  |                 self.visit(target) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.emit('POP_TOP') | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |             self.visit(body) | 
					
						
							|  |  |  |             self.emit('JUMP_FORWARD', end) | 
					
						
							| 
									
										
										
										
											2000-02-16 00:55:44 +00:00
										 |  |  |             if expr: | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |                 self.nextBlock(next) | 
					
						
							| 
									
										
										
										
											2000-11-06 03:43:11 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 self.nextBlock() | 
					
						
							| 
									
										
										
										
											2001-08-28 16:35:18 +00:00
										 |  |  |             if expr: # XXX | 
					
						
							|  |  |  |                 self.emit('POP_TOP') | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.emit('END_FINALLY') | 
					
						
							|  |  |  |         if node.else_: | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             self.nextBlock(lElse) | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |             self.visit(node.else_) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.nextBlock(end) | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |     def visitTryFinally(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         body = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         final = self.newBlock() | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.emit('SETUP_FINALLY', final) | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.nextBlock(body) | 
					
						
							|  |  |  |         self.setups.push((TRY_FINALLY, body)) | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.visit(node.body) | 
					
						
							|  |  |  |         self.emit('POP_BLOCK') | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.pop() | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.emit('LOAD_CONST', None) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.nextBlock(final) | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.push((END_FINALLY, final)) | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  |         self.visit(node.final) | 
					
						
							|  |  |  |         self.emit('END_FINALLY') | 
					
						
							| 
									
										
										
										
											2001-08-29 22:30:09 +00:00
										 |  |  |         self.setups.pop() | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 00:32:16 +00:00
										 |  |  |     __with_count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitWith(self, node): | 
					
						
							|  |  |  |         body = self.newBlock() | 
					
						
							|  |  |  |         final = self.newBlock() | 
					
						
							|  |  |  |         exitvar = "$exit%d" % self.__with_count | 
					
						
							|  |  |  |         valuevar = "$value%d" % self.__with_count | 
					
						
							|  |  |  |         self.__with_count += 1 | 
					
						
							|  |  |  |         self.set_lineno(node) | 
					
						
							|  |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         self.emit('LOAD_ATTR', '__context__') | 
					
						
							|  |  |  |         self.emit('CALL_FUNCTION', 0) | 
					
						
							|  |  |  |         self.emit('DUP_TOP') | 
					
						
							|  |  |  |         self.emit('LOAD_ATTR', '__exit__') | 
					
						
							|  |  |  |         self._implicitNameOp('STORE', exitvar) | 
					
						
							|  |  |  |         self.emit('LOAD_ATTR', '__enter__') | 
					
						
							|  |  |  |         self.emit('CALL_FUNCTION', 0) | 
					
						
							|  |  |  |         if node.vars is None: | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self._implicitNameOp('STORE', valuevar) | 
					
						
							|  |  |  |         self.emit('SETUP_FINALLY', final) | 
					
						
							|  |  |  |         self.nextBlock(body) | 
					
						
							|  |  |  |         self.setups.push((TRY_FINALLY, body)) | 
					
						
							|  |  |  |         if node.vars is not None: | 
					
						
							|  |  |  |             self._implicitNameOp('LOAD', valuevar) | 
					
						
							|  |  |  |             self._implicitNameOp('DELETE', valuevar) | 
					
						
							|  |  |  |             self.visit(node.vars) | 
					
						
							|  |  |  |         self.visit(node.body) | 
					
						
							|  |  |  |         self.emit('POP_BLOCK') | 
					
						
							|  |  |  |         self.setups.pop() | 
					
						
							|  |  |  |         self.emit('LOAD_CONST', None) | 
					
						
							|  |  |  |         self.nextBlock(final) | 
					
						
							|  |  |  |         self.setups.push((END_FINALLY, final)) | 
					
						
							|  |  |  |         self.emit('WITH_CLEANUP') | 
					
						
							|  |  |  |         self.emit('CALL_FUNCTION', 3) | 
					
						
							|  |  |  |         self.emit('POP_TOP') | 
					
						
							|  |  |  |         self.emit('END_FINALLY') | 
					
						
							|  |  |  |         self.setups.pop() | 
					
						
							|  |  |  |         self.__with_count -= 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # misc | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitDiscard(self, node): | 
					
						
							| 
									
										
										
										
											2001-04-11 16:36:25 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.emit('POP_TOP') | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitConst(self, node): | 
					
						
							|  |  |  |         self.emit('LOAD_CONST', node.value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitKeyword(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.emit('LOAD_CONST', node.name) | 
					
						
							|  |  |  |         self.visit(node.expr) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitGlobal(self, node): | 
					
						
							|  |  |  |         # no code to generate | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         pass | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitName(self, node): | 
					
						
							| 
									
										
										
										
											2000-09-01 20:47:37 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.loadName(node.name) | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitPass(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitImport(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-09-01 20:33:26 +00:00
										 |  |  |         for name, alias in node.names: | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |             if VERSION > 1: | 
					
						
							|  |  |  |                 self.emit('LOAD_CONST', None) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |             self.emit('IMPORT_NAME', name) | 
					
						
							| 
									
										
										
										
											2002-06-06 18:30:10 +00:00
										 |  |  |             mod = name.split(".")[0] | 
					
						
							| 
									
										
										
										
											2003-06-27 12:32:39 +00:00
										 |  |  |             if alias: | 
					
						
							|  |  |  |                 self._resolveDots(name) | 
					
						
							|  |  |  |                 self.storeName(alias) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.storeName(mod) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitFrom(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-09-01 20:33:26 +00:00
										 |  |  |         fromlist = map(lambda (name, alias): name, node.names) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         if VERSION > 1: | 
					
						
							|  |  |  |             self.emit('LOAD_CONST', tuple(fromlist)) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.emit('IMPORT_NAME', node.modname) | 
					
						
							| 
									
										
										
										
											2000-09-01 20:33:26 +00:00
										 |  |  |         for name, alias in node.names: | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |             if VERSION > 1: | 
					
						
							|  |  |  |                 if name == '*': | 
					
						
							|  |  |  |                     self.namespace = 0 | 
					
						
							|  |  |  |                     self.emit('IMPORT_STAR') | 
					
						
							|  |  |  |                     # There can only be one name w/ from ... import * | 
					
						
							|  |  |  |                     assert len(node.names) == 1 | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     self.emit('IMPORT_FROM', name) | 
					
						
							|  |  |  |                     self._resolveDots(name) | 
					
						
							|  |  |  |                     self.storeName(alias or name) | 
					
						
							| 
									
										
										
										
											2000-10-12 20:23:23 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 self.emit('IMPORT_FROM', name) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.emit('POP_TOP') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-01 20:33:26 +00:00
										 |  |  |     def _resolveDots(self, name): | 
					
						
							| 
									
										
										
										
											2002-06-06 18:30:10 +00:00
										 |  |  |         elts = name.split(".") | 
					
						
							| 
									
										
										
										
											2000-09-01 20:33:26 +00:00
										 |  |  |         if len(elts) == 1: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         for elt in elts[1:]: | 
					
						
							|  |  |  |             self.emit('LOAD_ATTR', elt) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitGetattr(self, node): | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |         self.emit('LOAD_ATTR', self.mangle(node.attrname)) | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # next five implement assignments | 
					
						
							| 
									
										
										
										
											2000-02-15 23:45:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |     def visitAssign(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         dups = len(node.nodes) - 1 | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |         for i in range(len(node.nodes)): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |             elt = node.nodes[i] | 
					
						
							|  |  |  |             if i < dups: | 
					
						
							|  |  |  |                 self.emit('DUP_TOP') | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |             if isinstance(elt, ast.Node): | 
					
						
							|  |  |  |                 self.visit(elt) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitAssName(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 22:09:35 +00:00
										 |  |  |         if node.flags == 'OP_ASSIGN': | 
					
						
							|  |  |  |             self.storeName(node.name) | 
					
						
							|  |  |  |         elif node.flags == 'OP_DELETE': | 
					
						
							| 
									
										
										
										
											2001-08-29 18:14:39 +00:00
										 |  |  |             self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-17 22:09:35 +00:00
										 |  |  |             self.delName(node.name) | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |             print "oops", node.flags | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |     def visitAssAttr(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-16 00:55:44 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         if node.flags == 'OP_ASSIGN': | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |             self.emit('STORE_ATTR', self.mangle(node.attrname)) | 
					
						
							| 
									
										
										
										
											2000-02-16 00:55:44 +00:00
										 |  |  |         elif node.flags == 'OP_DELETE': | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |             self.emit('DELETE_ATTR', self.mangle(node.attrname)) | 
					
						
							| 
									
										
										
										
											2000-02-16 00:55:44 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |             print "warning: unexpected flags:", node.flags | 
					
						
							|  |  |  |             print node | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |     def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'): | 
					
						
							| 
									
										
										
										
											2000-02-17 22:09:35 +00:00
										 |  |  |         if findOp(node) != 'OP_DELETE': | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |             self.emit(op, len(node.nodes)) | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |         for child in node.nodes: | 
					
						
							|  |  |  |             self.visit(child) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |     if VERSION > 1: | 
					
						
							|  |  |  |         visitAssTuple = _visitAssSequence | 
					
						
							|  |  |  |         visitAssList = _visitAssSequence | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         def visitAssTuple(self, node): | 
					
						
							|  |  |  |             self._visitAssSequence(node, 'UNPACK_TUPLE') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def visitAssList(self, node): | 
					
						
							|  |  |  |             self._visitAssSequence(node, 'UNPACK_LIST') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # augmented assignment | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitAugAssign(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-27 21:58:09 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         aug_node = wrap_aug(node.node) | 
					
						
							|  |  |  |         self.visit(aug_node, "load") | 
					
						
							|  |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         self.emit(self._augmented_opcode[node.op]) | 
					
						
							|  |  |  |         self.visit(aug_node, "store") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _augmented_opcode = { | 
					
						
							|  |  |  |         '+=' : 'INPLACE_ADD', | 
					
						
							|  |  |  |         '-=' : 'INPLACE_SUBTRACT', | 
					
						
							|  |  |  |         '*=' : 'INPLACE_MULTIPLY', | 
					
						
							|  |  |  |         '/=' : 'INPLACE_DIVIDE', | 
					
						
							| 
									
										
										
										
											2001-08-29 18:14:39 +00:00
										 |  |  |         '//=': 'INPLACE_FLOOR_DIVIDE', | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         '%=' : 'INPLACE_MODULO', | 
					
						
							|  |  |  |         '**=': 'INPLACE_POWER', | 
					
						
							|  |  |  |         '>>=': 'INPLACE_RSHIFT', | 
					
						
							|  |  |  |         '<<=': 'INPLACE_LSHIFT', | 
					
						
							|  |  |  |         '&=' : 'INPLACE_AND', | 
					
						
							|  |  |  |         '^=' : 'INPLACE_XOR', | 
					
						
							|  |  |  |         '|=' : 'INPLACE_OR', | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitAugName(self, node, mode): | 
					
						
							|  |  |  |         if mode == "load": | 
					
						
							|  |  |  |             self.loadName(node.name) | 
					
						
							|  |  |  |         elif mode == "store": | 
					
						
							|  |  |  |             self.storeName(node.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitAugGetattr(self, node, mode): | 
					
						
							|  |  |  |         if mode == "load": | 
					
						
							|  |  |  |             self.visit(node.expr) | 
					
						
							|  |  |  |             self.emit('DUP_TOP') | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |             self.emit('LOAD_ATTR', self.mangle(node.attrname)) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         elif mode == "store": | 
					
						
							|  |  |  |             self.emit('ROT_TWO') | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |             self.emit('STORE_ATTR', self.mangle(node.attrname)) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitAugSlice(self, node, mode): | 
					
						
							|  |  |  |         if mode == "load": | 
					
						
							| 
									
										
										
										
											2001-04-11 16:43:13 +00:00
										 |  |  |             self.visitSlice(node, 1) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         elif mode == "store": | 
					
						
							|  |  |  |             slice = 0 | 
					
						
							|  |  |  |             if node.lower: | 
					
						
							|  |  |  |                 slice = slice | 1 | 
					
						
							|  |  |  |             if node.upper: | 
					
						
							|  |  |  |                 slice = slice | 2 | 
					
						
							|  |  |  |             if slice == 0: | 
					
						
							|  |  |  |                 self.emit('ROT_TWO') | 
					
						
							|  |  |  |             elif slice == 3: | 
					
						
							|  |  |  |                 self.emit('ROT_FOUR') | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.emit('ROT_THREE') | 
					
						
							|  |  |  |             self.emit('STORE_SLICE+%d' % slice) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitAugSubscript(self, node, mode): | 
					
						
							|  |  |  |         if len(node.subs) > 1: | 
					
						
							|  |  |  |             raise SyntaxError, "augmented assignment to tuple is not possible" | 
					
						
							|  |  |  |         if mode == "load": | 
					
						
							|  |  |  |             self.visitSubscript(node, 1) | 
					
						
							|  |  |  |         elif mode == "store": | 
					
						
							|  |  |  |             self.emit('ROT_THREE') | 
					
						
							|  |  |  |             self.emit('STORE_SUBSCR') | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def visitExec(self, node): | 
					
						
							|  |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         if node.locals is None: | 
					
						
							|  |  |  |             self.emit('LOAD_CONST', None) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.visit(node.locals) | 
					
						
							|  |  |  |         if node.globals is None: | 
					
						
							|  |  |  |             self.emit('DUP_TOP') | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.visit(node.globals) | 
					
						
							|  |  |  |         self.emit('EXEC_STMT') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitCallFunc(self, node): | 
					
						
							|  |  |  |         pos = 0 | 
					
						
							|  |  |  |         kw = 0 | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.visit(node.node) | 
					
						
							|  |  |  |         for arg in node.args: | 
					
						
							|  |  |  |             self.visit(arg) | 
					
						
							|  |  |  |             if isinstance(arg, ast.Keyword): | 
					
						
							|  |  |  |                 kw = kw + 1 | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 pos = pos + 1 | 
					
						
							| 
									
										
										
										
											2000-05-02 22:32:59 +00:00
										 |  |  |         if node.star_args is not None: | 
					
						
							|  |  |  |             self.visit(node.star_args) | 
					
						
							|  |  |  |         if node.dstar_args is not None: | 
					
						
							|  |  |  |             self.visit(node.dstar_args) | 
					
						
							|  |  |  |         have_star = node.star_args is not None | 
					
						
							|  |  |  |         have_dstar = node.dstar_args is not None | 
					
						
							|  |  |  |         opcode = callfunc_opcode_info[have_star, have_dstar] | 
					
						
							|  |  |  |         self.emit(opcode, kw << 8 | pos) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |     def visitPrint(self, node, newline=0): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         if node.dest: | 
					
						
							|  |  |  |             self.visit(node.dest) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         for child in node.nodes: | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |             if node.dest: | 
					
						
							|  |  |  |                 self.emit('DUP_TOP') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |             self.visit(child) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |             if node.dest: | 
					
						
							|  |  |  |                 self.emit('ROT_TWO') | 
					
						
							|  |  |  |                 self.emit('PRINT_ITEM_TO') | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.emit('PRINT_ITEM') | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |         if node.dest and not newline: | 
					
						
							|  |  |  |             self.emit('POP_TOP') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitPrintnl(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |         self.visitPrint(node, newline=1) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         if node.dest: | 
					
						
							|  |  |  |             self.emit('PRINT_NEWLINE_TO') | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.emit('PRINT_NEWLINE') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitReturn(self, node): | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.visit(node.value) | 
					
						
							|  |  |  |         self.emit('RETURN_VALUE') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 23:17:55 +00:00
										 |  |  |     def visitYield(self, node): | 
					
						
							|  |  |  |         self.set_lineno(node) | 
					
						
							|  |  |  |         self.visit(node.value) | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |         self.emit('YIELD_VALUE') | 
					
						
							| 
									
										
										
										
											2001-09-14 23:17:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # slice and subscript stuff | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |     def visitSlice(self, node, aug_flag=None): | 
					
						
							|  |  |  |         # aug_flag is used by visitAugSlice | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         slice = 0 | 
					
						
							|  |  |  |         if node.lower: | 
					
						
							|  |  |  |             self.visit(node.lower) | 
					
						
							|  |  |  |             slice = slice | 1 | 
					
						
							|  |  |  |         if node.upper: | 
					
						
							|  |  |  |             self.visit(node.upper) | 
					
						
							|  |  |  |             slice = slice | 2 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         if aug_flag: | 
					
						
							|  |  |  |             if slice == 0: | 
					
						
							|  |  |  |                 self.emit('DUP_TOP') | 
					
						
							|  |  |  |             elif slice == 3: | 
					
						
							|  |  |  |                 self.emit('DUP_TOPX', 3) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.emit('DUP_TOPX', 2) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         if node.flags == 'OP_APPLY': | 
					
						
							|  |  |  |             self.emit('SLICE+%d' % slice) | 
					
						
							|  |  |  |         elif node.flags == 'OP_ASSIGN': | 
					
						
							|  |  |  |             self.emit('STORE_SLICE+%d' % slice) | 
					
						
							|  |  |  |         elif node.flags == 'OP_DELETE': | 
					
						
							|  |  |  |             self.emit('DELETE_SLICE+%d' % slice) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             print "weird slice", node.flags | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |     def visitSubscript(self, node, aug_flag=None): | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         for sub in node.subs: | 
					
						
							|  |  |  |             self.visit(sub) | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         if aug_flag: | 
					
						
							|  |  |  |             self.emit('DUP_TOPX', 2) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         if len(node.subs) > 1: | 
					
						
							|  |  |  |             self.emit('BUILD_TUPLE', len(node.subs)) | 
					
						
							|  |  |  |         if node.flags == 'OP_APPLY': | 
					
						
							|  |  |  |             self.emit('BINARY_SUBSCR') | 
					
						
							|  |  |  |         elif node.flags == 'OP_ASSIGN': | 
					
						
							|  |  |  |             self.emit('STORE_SUBSCR') | 
					
						
							|  |  |  |         elif node.flags == 'OP_DELETE': | 
					
						
							|  |  |  |             self.emit('DELETE_SUBSCR') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-06 19:10:54 +00:00
										 |  |  |     # binary ops | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  |     def binaryOp(self, node, op): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         self.visit(node.left) | 
					
						
							|  |  |  |         self.visit(node.right) | 
					
						
							|  |  |  |         self.emit(op) | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitAdd(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.binaryOp(node, 'BINARY_ADD') | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitSub(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.binaryOp(node, 'BINARY_SUBTRACT') | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitMul(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.binaryOp(node, 'BINARY_MULTIPLY') | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitDiv(self, node): | 
					
						
							| 
									
										
										
										
											2001-09-17 16:41:02 +00:00
										 |  |  |         return self.binaryOp(node, self._div_op) | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-29 18:14:39 +00:00
										 |  |  |     def visitFloorDiv(self, node): | 
					
						
							|  |  |  |         return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |     def visitMod(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.binaryOp(node, 'BINARY_MODULO') | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-14 21:33:10 +00:00
										 |  |  |     def visitPower(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.binaryOp(node, 'BINARY_POWER') | 
					
						
							| 
									
										
										
										
											2000-02-14 21:33:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitLeftShift(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.binaryOp(node, 'BINARY_LSHIFT') | 
					
						
							| 
									
										
										
										
											2000-02-14 21:33:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitRightShift(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.binaryOp(node, 'BINARY_RSHIFT') | 
					
						
							| 
									
										
										
										
											2000-02-14 21:33:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-06 19:10:54 +00:00
										 |  |  |     # unary ops | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def unaryOp(self, node, op): | 
					
						
							|  |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         self.emit(op) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-14 21:33:10 +00:00
										 |  |  |     def visitInvert(self, node): | 
					
						
							|  |  |  |         return self.unaryOp(node, 'UNARY_INVERT') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |     def visitUnarySub(self, node): | 
					
						
							|  |  |  |         return self.unaryOp(node, 'UNARY_NEGATIVE') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitUnaryAdd(self, node): | 
					
						
							|  |  |  |         return self.unaryOp(node, 'UNARY_POSITIVE') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitUnaryInvert(self, node): | 
					
						
							|  |  |  |         return self.unaryOp(node, 'UNARY_INVERT') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |     def visitNot(self, node): | 
					
						
							|  |  |  |         return self.unaryOp(node, 'UNARY_NOT') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |     def visitBackquote(self, node): | 
					
						
							|  |  |  |         return self.unaryOp(node, 'UNARY_CONVERT') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-06 19:10:54 +00:00
										 |  |  |     # bit ops | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |     def bitOp(self, nodes, op): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         self.visit(nodes[0]) | 
					
						
							|  |  |  |         for node in nodes[1:]: | 
					
						
							|  |  |  |             self.visit(node) | 
					
						
							|  |  |  |             self.emit(op) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitBitand(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.bitOp(node.nodes, 'BINARY_AND') | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitBitor(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.bitOp(node.nodes, 'BINARY_OR') | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitBitxor(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         return self.bitOp(node.nodes, 'BINARY_XOR') | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     # object constructors | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |     def visitEllipsis(self, node): | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         self.emit('LOAD_CONST', Ellipsis) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |     def visitTuple(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-29 20:57:43 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-08 21:15:48 +00:00
										 |  |  |         for elt in node.nodes: | 
					
						
							|  |  |  |             self.visit(elt) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |         self.emit('BUILD_TUPLE', len(node.nodes)) | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |     def visitList(self, node): | 
					
						
							| 
									
										
										
										
											2001-08-29 20:57:43 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  |         for elt in node.nodes: | 
					
						
							|  |  |  |             self.visit(elt) | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |         self.emit('BUILD_LIST', len(node.nodes)) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def visitSliceobj(self, node): | 
					
						
							|  |  |  |         for child in node.nodes: | 
					
						
							|  |  |  |             self.visit(child) | 
					
						
							|  |  |  |         self.emit('BUILD_SLICE', len(node.nodes)) | 
					
						
							| 
									
										
										
											
												add ExampleASTVisitor:
* prints out examples of nodes that are handled by visitor.  simply a
  development convenience
remove NestedCodeGenerator -- it was bogus after all
replace with generateFunctionCode, a method to call to generate code
  for a function instead of a top-level module
fix impl of visitDiscard (most pop stack)
emit lineno for pass
handle the following new node types: Import, From, Getattr, Subscript,
Slice, AssAttr, AssTuple, Mod, Not, And, Or, List
LocalNameFinder: remove names declared as globals for locals
PythonVMCode: pass arg names to constructor, force varnames to contain
them all (even if they aren't referenced)
add -q option on command line to disable stdout
											
										 
											2000-02-10 00:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  |     def visitDict(self, node): | 
					
						
							| 
									
										
										
										
											2002-12-31 18:26:17 +00:00
										 |  |  |         self.set_lineno(node) | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |         self.emit('BUILD_MAP', 0) | 
					
						
							|  |  |  |         for k, v in node.items: | 
					
						
							|  |  |  |             self.emit('DUP_TOP') | 
					
						
							|  |  |  |             self.visit(k) | 
					
						
							| 
									
										
										
										
											2002-12-16 13:54:02 +00:00
										 |  |  |             self.visit(v) | 
					
						
							|  |  |  |             self.emit('ROT_THREE') | 
					
						
							| 
									
										
										
										
											2000-02-17 17:56:29 +00:00
										 |  |  |             self.emit('STORE_SUBSCR') | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | class NestedScopeMixin: | 
					
						
							|  |  |  |     """Defines initClass() for nested scoping (Python 2.2-compatible)""" | 
					
						
							|  |  |  |     def initClass(self): | 
					
						
							|  |  |  |         self.__class__.NameFinder = LocalNameFinder | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         self.__class__.FunctionGen = FunctionCodeGenerator | 
					
						
							|  |  |  |         self.__class__.ClassGen = ClassCodeGenerator | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  | class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator): | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     __super_init = CodeGenerator.__init__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     scopes = None | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     def __init__(self, tree): | 
					
						
							|  |  |  |         self.graph = pyassem.PyFlowGraph("<module>", tree.filename) | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         self.futures = future.find_futures(tree) | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         self.__super_init() | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         walk(tree, self) | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |     def get_module(self): | 
					
						
							|  |  |  |         return self | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  | class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator): | 
					
						
							|  |  |  |     __super_init = CodeGenerator.__init__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     scopes = None | 
					
						
							|  |  |  |     futures = () | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  |     def __init__(self, tree): | 
					
						
							|  |  |  |         self.graph = pyassem.PyFlowGraph("<expression>", tree.filename) | 
					
						
							|  |  |  |         self.__super_init() | 
					
						
							|  |  |  |         walk(tree, self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_module(self): | 
					
						
							|  |  |  |         return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __super_init = CodeGenerator.__init__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     scopes = None | 
					
						
							|  |  |  |     futures = () | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  |     def __init__(self, tree): | 
					
						
							|  |  |  |         self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename) | 
					
						
							|  |  |  |         self.__super_init() | 
					
						
							|  |  |  |         self.set_lineno(tree) | 
					
						
							|  |  |  |         walk(tree, self) | 
					
						
							|  |  |  |         self.emit('RETURN_VALUE') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_module(self): | 
					
						
							|  |  |  |         return self | 
					
						
							| 
									
										
										
										
											2002-02-16 07:34:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 21:02:51 +00:00
										 |  |  |     def visitDiscard(self, node): | 
					
						
							|  |  |  |         # XXX Discard means it's an expression.  Perhaps this is a bad | 
					
						
							|  |  |  |         # name. | 
					
						
							|  |  |  |         self.visit(node.expr) | 
					
						
							|  |  |  |         self.emit('PRINT_EXPR') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | class AbstractFunctionCode: | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     optimized = 1 | 
					
						
							|  |  |  |     lambdaCount = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     def __init__(self, func, scopes, isLambda, class_name, mod): | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |         self.class_name = class_name | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         self.module = mod | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         if isLambda: | 
					
						
							|  |  |  |             klass = FunctionCodeGenerator | 
					
						
							|  |  |  |             name = "<lambda.%d>" % klass.lambdaCount | 
					
						
							|  |  |  |             klass.lambdaCount = klass.lambdaCount + 1 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             name = func.name | 
					
						
							| 
									
										
										
										
											2004-05-19 08:20:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         args, hasTupleArg = generateArgList(func.argnames) | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  |         self.graph = pyassem.PyFlowGraph(name, func.filename, args, | 
					
						
							|  |  |  |                                          optimized=1) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.isLambda = isLambda | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         self.super_init() | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-11 16:24:30 +00:00
										 |  |  |         if not isLambda and func.doc: | 
					
						
							|  |  |  |             self.setDocstring(func.doc) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |         lnf = walk(func.code, self.NameFinder(args), verbose=0) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.locals.push(lnf.getLocals()) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         if func.varargs: | 
					
						
							|  |  |  |             self.graph.setFlag(CO_VARARGS) | 
					
						
							|  |  |  |         if func.kwargs: | 
					
						
							|  |  |  |             self.graph.setFlag(CO_VARKEYWORDS) | 
					
						
							| 
									
										
										
										
											2000-08-04 16:56:51 +00:00
										 |  |  |         self.set_lineno(func) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         if hasTupleArg: | 
					
						
							|  |  |  |             self.generateArgUnpack(func.argnames) | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |     def get_module(self): | 
					
						
							|  |  |  |         return self.module | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def finish(self): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.graph.startExitBlock() | 
					
						
							|  |  |  |         if not self.isLambda: | 
					
						
							|  |  |  |             self.emit('LOAD_CONST', None) | 
					
						
							|  |  |  |         self.emit('RETURN_VALUE') | 
					
						
							| 
									
										
										
										
											2000-02-04 00:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def generateArgUnpack(self, args): | 
					
						
							| 
									
										
										
										
											2001-04-12 17:33:34 +00:00
										 |  |  |         for i in range(len(args)): | 
					
						
							|  |  |  |             arg = args[i] | 
					
						
							| 
									
										
										
										
											2005-11-25 03:17:59 +00:00
										 |  |  |             if isinstance(arg, tuple): | 
					
						
							| 
									
										
										
										
											2001-04-12 17:33:34 +00:00
										 |  |  |                 self.emit('LOAD_FAST', '.%d' % (i * 2)) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |                 self.unpackSequence(arg) | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |     def unpackSequence(self, tup): | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  |         if VERSION > 1: | 
					
						
							|  |  |  |             self.emit('UNPACK_SEQUENCE', len(tup)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.emit('UNPACK_TUPLE', len(tup)) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         for elt in tup: | 
					
						
							| 
									
										
										
										
											2005-11-25 03:17:59 +00:00
										 |  |  |             if isinstance(elt, tuple): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |                 self.unpackSequence(elt) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2001-04-12 06:52:27 +00:00
										 |  |  |                 self._nameOp('STORE', elt) | 
					
						
							| 
									
										
										
										
											2000-02-04 19:37:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |     unpackTuple = unpackSequence | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  | class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode, | 
					
						
							| 
									
										
										
										
											2001-10-18 21:57:37 +00:00
										 |  |  |                             CodeGenerator): | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     super_init = CodeGenerator.__init__ # call be other init | 
					
						
							|  |  |  |     scopes = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __super_init = AbstractFunctionCode.__init__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     def __init__(self, func, scopes, isLambda, class_name, mod): | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |         self.scopes = scopes | 
					
						
							|  |  |  |         self.scope = scopes[func] | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         self.__super_init(func, scopes, isLambda, class_name, mod) | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |         self.graph.setFreeVars(self.scope.get_free_vars()) | 
					
						
							|  |  |  |         self.graph.setCellVars(self.scope.get_cell_vars()) | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |         if self.scope.generator is not None: | 
					
						
							|  |  |  |             self.graph.setFlag(CO_GENERATOR) | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-19 08:20:33 +00:00
										 |  |  | class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode, | 
					
						
							|  |  |  |                            CodeGenerator): | 
					
						
							|  |  |  |     super_init = CodeGenerator.__init__ # call be other init | 
					
						
							|  |  |  |     scopes = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __super_init = AbstractFunctionCode.__init__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, gexp, scopes, class_name, mod): | 
					
						
							|  |  |  |         self.scopes = scopes | 
					
						
							|  |  |  |         self.scope = scopes[gexp] | 
					
						
							|  |  |  |         self.__super_init(gexp, scopes, 1, class_name, mod) | 
					
						
							|  |  |  |         self.graph.setFreeVars(self.scope.get_free_vars()) | 
					
						
							|  |  |  |         self.graph.setCellVars(self.scope.get_cell_vars()) | 
					
						
							|  |  |  |         self.graph.setFlag(CO_GENERATOR) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | class AbstractClassCode: | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     def __init__(self, klass, scopes, module): | 
					
						
							| 
									
										
										
										
											2001-08-27 22:56:16 +00:00
										 |  |  |         self.class_name = klass.name | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |         self.module = module | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         self.graph = pyassem.PyFlowGraph(klass.name, klass.filename, | 
					
						
							| 
									
										
										
										
											2001-08-29 18:14:39 +00:00
										 |  |  |                                            optimized=0, klass=1) | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         self.super_init() | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |         lnf = walk(klass.code, self.NameFinder(), verbose=0) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.locals.push(lnf.getLocals()) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.graph.setFlag(CO_NEWLOCALS) | 
					
						
							| 
									
										
										
										
											2001-04-11 16:24:30 +00:00
										 |  |  |         if klass.doc: | 
					
						
							|  |  |  |             self.setDocstring(klass.doc) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  |     def get_module(self): | 
					
						
							|  |  |  |         return self.module | 
					
						
							| 
									
										
										
										
											2001-04-12 06:49:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     def finish(self): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.graph.startExitBlock() | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |         self.emit('LOAD_LOCALS') | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         self.emit('RETURN_VALUE') | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 22:49:08 +00:00
										 |  |  | class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator): | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |     super_init = CodeGenerator.__init__ | 
					
						
							|  |  |  |     scopes = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __super_init = AbstractClassCode.__init__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |     def __init__(self, klass, scopes, module): | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |         self.scopes = scopes | 
					
						
							|  |  |  |         self.scope = scopes[klass] | 
					
						
							| 
									
										
										
										
											2001-09-17 18:03:55 +00:00
										 |  |  |         self.__super_init(klass, scopes, module) | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  |         self.graph.setFreeVars(self.scope.get_free_vars()) | 
					
						
							|  |  |  |         self.graph.setCellVars(self.scope.get_cell_vars()) | 
					
						
							| 
									
										
										
										
											2002-12-31 18:17:44 +00:00
										 |  |  |         self.set_lineno(klass) | 
					
						
							|  |  |  |         self.emit("LOAD_GLOBAL", "__name__") | 
					
						
							|  |  |  |         self.storeName("__module__") | 
					
						
							|  |  |  |         if klass.doc: | 
					
						
							|  |  |  |             self.emit("LOAD_CONST", klass.doc) | 
					
						
							|  |  |  |             self.storeName('__doc__') | 
					
						
							| 
									
										
										
										
											2001-04-12 06:40:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | def generateArgList(arglist): | 
					
						
							|  |  |  |     """Generate an arg list marking TupleArgs""" | 
					
						
							|  |  |  |     args = [] | 
					
						
							|  |  |  |     extra = [] | 
					
						
							|  |  |  |     count = 0 | 
					
						
							| 
									
										
										
										
											2001-04-12 17:33:34 +00:00
										 |  |  |     for i in range(len(arglist)): | 
					
						
							|  |  |  |         elt = arglist[i] | 
					
						
							| 
									
										
										
										
											2005-11-25 03:17:59 +00:00
										 |  |  |         if isinstance(elt, str): | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             args.append(elt) | 
					
						
							| 
									
										
										
										
											2005-11-25 03:17:59 +00:00
										 |  |  |         elif isinstance(elt, tuple): | 
					
						
							| 
									
										
										
										
											2001-04-12 17:33:34 +00:00
										 |  |  |             args.append(TupleArg(i * 2, elt)) | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |             extra.extend(misc.flatten(elt)) | 
					
						
							| 
									
										
										
										
											2001-04-12 17:33:34 +00:00
										 |  |  |             count = count + 1 | 
					
						
							| 
									
										
										
										
											2000-08-12 20:32:46 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             raise ValueError, "unexpect argument type:", elt | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     return args + extra, count | 
					
						
							| 
									
										
										
										
											2000-02-14 14:14:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | def findOp(node): | 
					
						
							|  |  |  |     """Find the op (DELETE, LOAD, STORE) in an AssTuple tree""" | 
					
						
							|  |  |  |     v = OpFinder() | 
					
						
							| 
									
										
										
										
											2001-08-27 21:51:52 +00:00
										 |  |  |     walk(node, v, verbose=0) | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  |     return v.op | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-17 22:09:35 +00:00
										 |  |  | class OpFinder: | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.op = None | 
					
						
							|  |  |  |     def visitAssName(self, node): | 
					
						
							|  |  |  |         if self.op is None: | 
					
						
							|  |  |  |             self.op = node.flags | 
					
						
							|  |  |  |         elif self.op != node.flags: | 
					
						
							|  |  |  |             raise ValueError, "mixed ops in stmt" | 
					
						
							| 
									
										
										
										
											2001-04-12 20:24:26 +00:00
										 |  |  |     visitAssAttr = visitAssName | 
					
						
							| 
									
										
										
										
											2001-11-09 16:24:34 +00:00
										 |  |  |     visitSubscript = visitAssName | 
					
						
							| 
									
										
										
										
											2000-02-17 22:09:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-13 21:58:13 +00:00
										 |  |  | class Delegator: | 
					
						
							|  |  |  |     """Base class to support delegation for augmented assignment nodes
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     To generator code for augmented assignments, we use the following | 
					
						
							|  |  |  |     wrapper classes.  In visitAugAssign, the left-hand expression node | 
					
						
							|  |  |  |     is visited twice.  The first time the visit uses the normal method | 
					
						
							|  |  |  |     for that node .  The second time the visit uses a different method | 
					
						
							|  |  |  |     that generates the appropriate code to perform the assignment. | 
					
						
							|  |  |  |     These delegator classes wrap the original AST nodes in order to | 
					
						
							|  |  |  |     support the variant visit methods. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     def __init__(self, obj): | 
					
						
							|  |  |  |         self.obj = obj | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __getattr__(self, attr): | 
					
						
							|  |  |  |         return getattr(self.obj, attr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AugGetattr(Delegator): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AugName(Delegator): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AugSlice(Delegator): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AugSubscript(Delegator): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | wrapper = { | 
					
						
							|  |  |  |     ast.Getattr: AugGetattr, | 
					
						
							|  |  |  |     ast.Name: AugName, | 
					
						
							|  |  |  |     ast.Slice: AugSlice, | 
					
						
							|  |  |  |     ast.Subscript: AugSubscript, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def wrap_aug(node): | 
					
						
							|  |  |  |     return wrapper[node.__class__](node) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-16 20:06:59 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     for file in sys.argv[1:]: | 
					
						
							| 
									
										
										
										
											2001-11-27 23:35:10 +00:00
										 |  |  |         compileFile(file) |