| |
| .. _compiler: |
| |
| *********************** |
| Python compiler package |
| *********************** |
| |
| .. deprecated:: 2.6 |
| The :mod:`compiler` package has been removed in Python 3. |
| |
| .. sectionauthor:: Jeremy Hylton <[email protected]> |
| |
| |
| 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. |
| |