| .. _compiler: | |
| *********************** | |
| Python compiler package | |
| *********************** | |
| .. deprecated:: 2.6 | |
| The :mod:`compiler` package has been removed in Python 3. | |
| .. sectionauthor:: Jeremy Hylton <jeremy@zope.com> | |
| The Python compiler package is a tool for analyzing Python source code and | |
| generating Python bytecode. The compiler contains libraries to generate an | |
| abstract syntax tree from Python source code and to generate Python | |
| :term:`bytecode` from the tree. | |
| The :mod:`compiler` package is a Python source to bytecode translator written in | |
| Python. It uses the built-in parser and standard :mod:`parser` module to | |
| generate a concrete syntax tree. This tree is used to generate an abstract | |
| syntax tree (AST) and then Python bytecode. | |
| The full functionality of the package duplicates the built-in compiler provided | |
| with the Python interpreter. It is intended to match its behavior almost | |
| exactly. Why implement another compiler that does the same thing? The package | |
| is useful for a variety of purposes. It can be modified more easily than the | |
| built-in compiler. The AST it generates is useful for analyzing Python source | |
| code. | |
| This chapter explains how the various components of the :mod:`compiler` package | |
| work. It blends reference material with a tutorial. | |
| The basic interface | |
| =================== | |
| .. module:: compiler | |
| :synopsis: Python code compiler written in Python. | |
| :deprecated: | |
| The top-level of the package defines four functions. If you import | |
| :mod:`compiler`, you will get these functions and a collection of modules | |
| contained in the package. | |
| .. function:: parse(buf) | |
| Returns an abstract syntax tree for the Python source code in *buf*. The | |
| function raises :exc:`SyntaxError` if there is an error in the source code. The | |
| return value is a :class:`compiler.ast.Module` instance that contains the tree. | |
| .. function:: parseFile(path) | |
| Return an abstract syntax tree for the Python source code in the file specified | |
| by *path*. It is equivalent to ``parse(open(path).read())``. | |
| .. function:: walk(ast, visitor[, verbose]) | |
| Do a pre-order walk over the abstract syntax tree *ast*. Call the appropriate | |
| method on the *visitor* instance for each node encountered. | |
| .. function:: compile(source, filename, mode, flags=None, dont_inherit=None) | |
| Compile the string *source*, a Python module, statement or expression, into a | |
| code object that can be executed by the exec statement or :func:`eval`. This | |
| function is a replacement for the built-in :func:`compile` function. | |
| The *filename* will be used for run-time error messages. | |
| The *mode* must be 'exec' to compile a module, 'single' to compile a single | |
| (interactive) statement, or 'eval' to compile an expression. | |
| The *flags* and *dont_inherit* arguments affect future-related statements, but | |
| are not supported yet. | |
| .. function:: compileFile(source) | |
| Compiles the file *source* and generates a .pyc file. | |
| The :mod:`compiler` package contains the following modules: :mod:`ast`, | |
| :mod:`consts`, :mod:`future`, :mod:`misc`, :mod:`pyassem`, :mod:`pycodegen`, | |
| :mod:`symbols`, :mod:`transformer`, and :mod:`visitor`. | |
| Limitations | |
| =========== | |
| There are some problems with the error checking of the compiler package. The | |
| interpreter detects syntax errors in two distinct phases. One set of errors is | |
| detected by the interpreter's parser, the other set by the compiler. The | |
| compiler package relies on the interpreter's parser, so it get the first phases | |
| of error checking for free. It implements the second phase itself, and that | |
| implementation is incomplete. For example, the compiler package does not raise | |
| an error if a name appears more than once in an argument list: ``def f(x, x): | |
| ...`` | |
| A future version of the compiler should fix these problems. | |
| Python Abstract Syntax | |
| ====================== | |
| The :mod:`compiler.ast` module defines an abstract syntax for Python. In the | |
| abstract syntax tree, each node represents a syntactic construct. The root of | |
| the tree is :class:`Module` object. | |
| The abstract syntax offers a higher level interface to parsed Python source | |
| code. The :mod:`parser` module and the compiler written in C for the Python | |
| interpreter use a concrete syntax tree. The concrete syntax is tied closely to | |
| the grammar description used for the Python parser. Instead of a single node | |
| for a construct, there are often several levels of nested nodes that are | |
| introduced by Python's precedence rules. | |
| The abstract syntax tree is created by the :mod:`compiler.transformer` module. | |
| The transformer relies on the built-in Python parser to generate a concrete | |
| syntax tree. It generates an abstract syntax tree from the concrete tree. | |
| .. index:: | |
| single: Stein, Greg | |
| single: Tutt, Bill | |
| The :mod:`transformer` module was created by Greg Stein and Bill Tutt for an | |
| experimental Python-to-C compiler. The current version contains a number of | |
| modifications and improvements, but the basic form of the abstract syntax and of | |
| the transformer are due to Stein and Tutt. | |
| AST Nodes | |
| --------- | |
| .. module:: compiler.ast | |
| The :mod:`compiler.ast` module is generated from a text file that describes each | |
| node type and its elements. Each node type is represented as a class that | |
| inherits from the abstract base class :class:`compiler.ast.Node` and defines a | |
| set of named attributes for child nodes. | |
| .. class:: Node() | |
| The :class:`Node` instances are created automatically by the parser generator. | |
| The recommended interface for specific :class:`Node` instances is to use the | |
| public attributes to access child nodes. A public attribute may be bound to a | |
| single node or to a sequence of nodes, depending on the :class:`Node` type. For | |
| example, the :attr:`bases` attribute of the :class:`Class` node, is bound to a | |
| list of base class nodes, and the :attr:`doc` attribute is bound to a single | |
| node. | |
| Each :class:`Node` instance has a :attr:`lineno` attribute which may be | |
| ``None``. XXX Not sure what the rules are for which nodes will have a useful | |
| lineno. | |
| All :class:`Node` objects offer the following methods: | |
| .. method:: getChildren() | |
| Returns a flattened list of the child nodes and objects in the order they | |
| occur. Specifically, the order of the nodes is the order in which they | |
| appear in the Python grammar. Not all of the children are :class:`Node` | |
| instances. The names of functions and classes, for example, are plain | |
| strings. | |
| .. method:: getChildNodes() | |
| Returns a flattened list of the child nodes in the order they occur. This | |
| method is like :meth:`getChildren`, except that it only returns those | |
| children that are :class:`Node` instances. | |
| Two examples illustrate the general structure of :class:`Node` classes. The | |
| :keyword:`while` statement is defined by the following grammar production:: | |
| while_stmt: "while" expression ":" suite | |
| ["else" ":" suite] | |
| The :class:`While` node has three attributes: :attr:`test`, :attr:`body`, and | |
| :attr:`else_`. (If the natural name for an attribute is also a Python reserved | |
| word, it can't be used as an attribute name. An underscore is appended to the | |
| word to make it a legal identifier, hence :attr:`else_` instead of | |
| :keyword:`else`.) | |
| The :keyword:`if` statement is more complicated because it can include several | |
| tests. :: | |
| if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] | |
| The :class:`If` node only defines two attributes: :attr:`tests` and | |
| :attr:`else_`. The :attr:`tests` attribute is a sequence of test expression, | |
| consequent body pairs. There is one pair for each :keyword:`if`/:keyword:`elif` | |
| clause. The first element of the pair is the test expression. The second | |
| elements is a :class:`Stmt` node that contains the code to execute if the test | |
| is true. | |
| The :meth:`getChildren` method of :class:`If` returns a flat list of child | |
| nodes. If there are three :keyword:`if`/:keyword:`elif` clauses and no | |
| :keyword:`else` clause, then :meth:`getChildren` will return a list of six | |
| elements: the first test expression, the first :class:`Stmt`, the second text | |
| expression, etc. | |
| The following table lists each of the :class:`Node` subclasses defined in | |
| :mod:`compiler.ast` and each of the public attributes available on their | |
| instances. The values of most of the attributes are themselves :class:`Node` | |
| instances or sequences of instances. When the value is something other than an | |
| instance, the type is noted in the comment. The attributes are listed in the | |
| order in which they are returned by :meth:`getChildren` and | |
| :meth:`getChildNodes`. | |
| +-----------------------+--------------------+---------------------------------+ | |
| | Node type | Attribute | Value | | |
| +=======================+====================+=================================+ | |
| | :class:`Add` | :attr:`left` | left operand | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | right operand | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`And` | :attr:`nodes` | list of operands | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`AssAttr` | | *attribute as target of | | |
| | | | assignment* | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`expr` | expression on the left-hand | | |
| | | | side of the dot | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`attrname` | the attribute name, a string | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`flags` | XXX | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`AssList` | :attr:`nodes` | list of list elements being | | |
| | | | assigned to | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`AssName` | :attr:`name` | name being assigned to | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`flags` | XXX | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`AssTuple` | :attr:`nodes` | list of tuple elements being | | |
| | | | assigned to | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Assert` | :attr:`test` | the expression to be tested | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`fail` | the value of the | | |
| | | | :exc:`AssertionError` | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Assign` | :attr:`nodes` | a list of assignment targets, | | |
| | | | one per equal sign | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`expr` | the value being assigned | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`AugAssign` | :attr:`node` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`op` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Backquote` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Bitand` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Bitor` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Bitxor` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Break` | | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`CallFunc` | :attr:`node` | expression for the callee | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`args` | a list of arguments | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`star_args` | the extended \*-arg value | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`dstar_args` | the extended \*\*-arg value | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Class` | :attr:`name` | the name of the class, a string | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`bases` | a list of base classes | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`doc` | doc string, a string or | | |
| | | | ``None`` | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`code` | the body of the class statement | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Compare` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`ops` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Const` | :attr:`value` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Continue` | | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Decorators` | :attr:`nodes` | List of function decorator | | |
| | | | expressions | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Dict` | :attr:`items` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Discard` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Div` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Ellipsis` | | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Expression` | :attr:`node` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Exec` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`locals` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`globals` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`FloorDiv` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`For` | :attr:`assign` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`list` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`body` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`else_` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`From` | :attr:`modname` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`names` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Function` | :attr:`decorators` | :class:`Decorators` or ``None`` | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`name` | name used in def, a string | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`argnames` | list of argument names, as | | |
| | | | strings | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`defaults` | list of default values | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`flags` | xxx | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`doc` | doc string, a string or | | |
| | | | ``None`` | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`code` | the body of the function | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`GenExpr` | :attr:`code` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`GenExprFor` | :attr:`assign` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`iter` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`ifs` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`GenExprIf` | :attr:`test` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`GenExprInner` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`quals` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Getattr` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`attrname` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Global` | :attr:`names` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`If` | :attr:`tests` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`else_` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Import` | :attr:`names` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Invert` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Keyword` | :attr:`name` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Lambda` | :attr:`argnames` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`defaults` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`flags` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`code` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`LeftShift` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`List` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`ListComp` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`quals` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`ListCompFor` | :attr:`assign` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`list` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`ifs` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`ListCompIf` | :attr:`test` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Mod` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Module` | :attr:`doc` | doc string, a string or | | |
| | | | ``None`` | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`node` | body of the module, a | | |
| | | | :class:`Stmt` | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Mul` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Name` | :attr:`name` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Not` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Or` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Pass` | | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Power` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Print` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`dest` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Printnl` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`dest` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Raise` | :attr:`expr1` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`expr2` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`expr3` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Return` | :attr:`value` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`RightShift` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Slice` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`flags` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`lower` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`upper` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Sliceobj` | :attr:`nodes` | list of statements | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Stmt` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Sub` | :attr:`left` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`right` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Subscript` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`flags` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`subs` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`TryExcept` | :attr:`body` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`handlers` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`else_` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`TryFinally` | :attr:`body` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`final` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Tuple` | :attr:`nodes` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`UnaryAdd` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`UnarySub` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`While` | :attr:`test` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`body` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`else_` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`With` | :attr:`expr` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`vars` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | | :attr:`body` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| | :class:`Yield` | :attr:`value` | | | |
| +-----------------------+--------------------+---------------------------------+ | |
| Assignment nodes | |
| ---------------- | |
| There is a collection of nodes used to represent assignments. Each assignment | |
| statement in the source code becomes a single :class:`Assign` node in the AST. | |
| The :attr:`nodes` attribute is a list that contains a node for each assignment | |
| target. This is necessary because assignment can be chained, e.g. ``a = b = | |
| 2``. Each :class:`Node` in the list will be one of the following classes: | |
| :class:`AssAttr`, :class:`AssList`, :class:`AssName`, or :class:`AssTuple`. | |
| Each target assignment node will describe the kind of object being assigned to: | |
| :class:`AssName` for a simple name, e.g. ``a = 1``. :class:`AssAttr` for an | |
| attribute assigned, e.g. ``a.x = 1``. :class:`AssList` and :class:`AssTuple` for | |
| list and tuple expansion respectively, e.g. ``a, b, c = a_tuple``. | |
| The target assignment nodes also have a :attr:`flags` attribute that indicates | |
| whether the node is being used for assignment or in a delete statement. The | |
| :class:`AssName` is also used to represent a delete statement, e.g. :class:`del | |
| x`. | |
| When an expression contains several attribute references, an assignment or | |
| delete statement will contain only one :class:`AssAttr` node -- for the final | |
| attribute reference. The other attribute references will be represented as | |
| :class:`Getattr` nodes in the :attr:`expr` attribute of the :class:`AssAttr` | |
| instance. | |
| Examples | |
| -------- | |
| This section shows several simple examples of ASTs for Python source code. The | |
| examples demonstrate how to use the :func:`parse` function, what the repr of an | |
| AST looks like, and how to access attributes of an AST node. | |
| The first module defines a single function. Assume it is stored in | |
| :file:`doublelib.py`. :: | |
| """This is an example module. | |
| This is the docstring. | |
| """ | |
| def double(x): | |
| "Return twice the argument" | |
| return x * 2 | |
| In the interactive interpreter session below, I have reformatted the long AST | |
| reprs for readability. The AST reprs use unqualified class names. If you want | |
| to create an instance from a repr, you must import the class names from the | |
| :mod:`compiler.ast` module. :: | |
| >>> import compiler | |
| >>> mod = compiler.parseFile("doublelib.py") | |
| >>> mod | |
| Module('This is an example module.\n\nThis is the docstring.\n', | |
| Stmt([Function(None, 'double', ['x'], [], 0, | |
| 'Return twice the argument', | |
| Stmt([Return(Mul((Name('x'), Const(2))))]))])) | |
| >>> from compiler.ast import * | |
| >>> Module('This is an example module.\n\nThis is the docstring.\n', | |
| ... Stmt([Function(None, 'double', ['x'], [], 0, | |
| ... 'Return twice the argument', | |
| ... Stmt([Return(Mul((Name('x'), Const(2))))]))])) | |
| Module('This is an example module.\n\nThis is the docstring.\n', | |
| Stmt([Function(None, 'double', ['x'], [], 0, | |
| 'Return twice the argument', | |
| Stmt([Return(Mul((Name('x'), Const(2))))]))])) | |
| >>> mod.doc | |
| 'This is an example module.\n\nThis is the docstring.\n' | |
| >>> for node in mod.node.nodes: | |
| ... print node | |
| ... | |
| Function(None, 'double', ['x'], [], 0, 'Return twice the argument', | |
| Stmt([Return(Mul((Name('x'), Const(2))))])) | |
| >>> func = mod.node.nodes[0] | |
| >>> func.code | |
| Stmt([Return(Mul((Name('x'), Const(2))))]) | |
| Using Visitors to Walk ASTs | |
| =========================== | |
| .. module:: compiler.visitor | |
| The visitor pattern is ... The :mod:`compiler` package uses a variant on the | |
| visitor pattern that takes advantage of Python's introspection features to | |
| eliminate the need for much of the visitor's infrastructure. | |
| The classes being visited do not need to be programmed to accept visitors. The | |
| visitor need only define visit methods for classes it is specifically interested | |
| in; a default visit method can handle the rest. | |
| XXX The magic :meth:`visit` method for visitors. | |
| .. function:: walk(tree, visitor[, verbose]) | |
| .. class:: ASTVisitor() | |
| The :class:`ASTVisitor` is responsible for walking over the tree in the correct | |
| order. A walk begins with a call to :meth:`preorder`. For each node, it checks | |
| the *visitor* argument to :meth:`preorder` for a method named 'visitNodeType,' | |
| where NodeType is the name of the node's class, e.g. for a :class:`While` node a | |
| :meth:`visitWhile` would be called. If the method exists, it is called with the | |
| node as its first argument. | |
| The visitor method for a particular node type can control how child nodes are | |
| visited during the walk. The :class:`ASTVisitor` modifies the visitor argument | |
| by adding a visit method to the visitor; this method can be used to visit a | |
| particular child node. If no visitor is found for a particular node type, the | |
| :meth:`default` method is called. | |
| :class:`ASTVisitor` objects have the following methods: | |
| XXX describe extra arguments | |
| .. method:: default(node[, ...]) | |
| .. method:: dispatch(node[, ...]) | |
| .. method:: preorder(tree, visitor) | |
| Bytecode Generation | |
| =================== | |
| The code generator is a visitor that emits bytecodes. Each visit method can | |
| call the :meth:`emit` method to emit a new bytecode. The basic code generator | |
| is specialized for modules, classes, and functions. An assembler converts that | |
| emitted instructions to the low-level bytecode format. It handles things like | |
| generation of constant lists of code objects and calculation of jump offsets. | |