1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# -*- coding: utf-8 -*-
2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)"""
3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    jinja2.compiler
4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ~~~~~~~~~~~~~~~
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Compiles nodes into python code.
7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    :copyright: (c) 2010 by the Jinja Team.
9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    :license: BSD, see LICENSE for more details.
10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)"""
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from itertools import chain
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from copy import deepcopy
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)from keyword import iskeyword as is_python_keyword
14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2 import nodes
15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2.nodes import EvalContext
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2.visitor import NodeVisitor
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2.exceptions import TemplateAssertionError
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)from jinja2.utils import Markup, concat, escape
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)from jinja2._compat import range_type, next, text_type, string_types, \
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)     iteritems, NativeStringIO, imap
21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)operators = {
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'eq':       '==',
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'ne':       '!=',
26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'gt':       '>',
27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'gteq':     '>=',
28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'lt':       '<',
29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'lteq':     '<=',
30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'in':       'in',
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    'notin':    'not in'
32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# what method to iterate over items do we want to use for dict iteration
35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# in generated code?  on 2.x let's go with iteritems, on 3.x with items
36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)if hasattr(dict, 'iteritems'):
37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    dict_item_iter = 'iteritems'
38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)else:
39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    dict_item_iter = 'items'
40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# does if 0: dummy(x) get us x into the scope?
43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def unoptimize_before_dead_code():
44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    x = 42
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def f():
46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if 0: dummy(x)
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return f
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)# The getattr is necessary for pypy which does not set this attribute if
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)# no closure is on the function
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)unoptimize_before_dead_code = bool(
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    getattr(unoptimize_before_dead_code(), '__closure__', None))
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def generate(node, environment, name, filename, stream=None,
56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             defer_init=False):
57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """Generate the python source for a node tree."""
58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if not isinstance(node, nodes.Template):
59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        raise TypeError('Can\'t compile non template nodes')
60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    generator = CodeGenerator(environment, name, filename, stream, defer_init)
61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    generator.visit(node)
62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if stream is None:
63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return generator.stream.getvalue()
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def has_safe_repr(value):
67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """Does the node have a safe representation?"""
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if value is None or value is NotImplemented or value is Ellipsis:
69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return True
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if isinstance(value, (bool, int, float, complex, range_type,
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            Markup) + string_types):
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return True
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if isinstance(value, (tuple, list, set, frozenset)):
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for item in value:
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not has_safe_repr(item):
76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                return False
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return True
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    elif isinstance(value, dict):
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        for key, value in iteritems(value):
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not has_safe_repr(key):
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                return False
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not has_safe_repr(value):
83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                return False
84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return True
85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return False
86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def find_undeclared(nodes, names):
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """Check if the names passed are accessed undeclared.  The return value
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    is a set of all the undeclared names from the sequence of names found.
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """
92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visitor = UndeclaredNameVisitor(names)
93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    try:
94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for node in nodes:
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            visitor.visit(node)
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    except VisitorExit:
97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        pass
98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return visitor.undeclared
99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class Identifiers(object):
102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """Tracks the status of identifiers in frames."""
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def __init__(self):
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # variables that are known to be declared (probably from outer
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # frames or because they are special for the frame)
107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.declared = set()
108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # undeclared variables from outer scopes
110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outer_undeclared = set()
111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # names that are accessed without being explicitly declared by
113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # this one or any of the outer scopes.  Names can appear both in
114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # declared and undeclared.
115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.undeclared = set()
116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # names that are declared locally
118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.declared_locally = set()
119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # names that are declared by parameters
121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.declared_parameter = set()
122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def add_special(self, name):
124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Register a special name like `loop`."""
125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.undeclared.discard(name)
126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.declared.add(name)
127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def is_declared(self, name):
129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Check if a name is declared in this or an outer scope."""
130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if name in self.declared_locally or name in self.declared_parameter:
131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            return True
132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return name in self.declared
133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def copy(self):
135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return deepcopy(self)
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class Frame(object):
139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """Holds compile time information for us."""
140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def __init__(self, eval_ctx, parent=None):
142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.eval_ctx = eval_ctx
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.identifiers = Identifiers()
144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # a toplevel frame is the root + soft frames such as if conditions.
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.toplevel = False
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the root frame is basically just the outermost frame, so no if
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # conditions.  This information is used to optimize inheritance
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # situations.
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.rootlevel = False
152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # in some dynamic inheritance situations the compiler needs to add
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # write tests around output statements.
155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.require_output_check = parent and parent.require_output_check
156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # inside some tags we are using a buffer rather than yield statements.
158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # this for example affects {% filter %} or {% macro %}.  If a frame
159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # is buffered this variable points to the name of the list used as
160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # buffer.
161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.buffer = None
162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the name of the block we're in, otherwise None.
164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.block = parent and parent.block or None
165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # a set of actually assigned names
167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.assigned_names = set()
168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the parent of this frame
170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.parent = parent
171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if parent is not None:
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.identifiers.declared.update(
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                parent.identifiers.declared |
175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                parent.identifiers.declared_parameter |
176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                parent.assigned_names
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            )
178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.identifiers.outer_undeclared.update(
179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                parent.identifiers.undeclared -
180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.identifiers.declared
181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            )
182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.buffer = parent.buffer
183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def copy(self):
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Create a copy of the current one."""
186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        rv = object.__new__(self.__class__)
187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        rv.__dict__.update(self.__dict__)
188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        rv.identifiers = object.__new__(self.identifiers.__class__)
189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        rv.identifiers.__dict__.update(self.identifiers.__dict__)
190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return rv
191b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def inspect(self, nodes):
193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Walk the node and check for identifiers.  If the scope is hard (eg:
194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        enforce on a python level) overrides from outer scopes are tracked
195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        differently.
196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
197b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        visitor = FrameIdentifierVisitor(self.identifiers)
198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for node in nodes:
199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            visitor.visit(node)
200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def find_shadowed(self, extra=()):
202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Find all the shadowed names.  extra is an iterable of variables
203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        that may be defined with `add_special` which may occour scoped.
204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        i = self.identifiers
206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return (i.declared | i.outer_undeclared) & \
207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               (i.declared_locally | i.declared_parameter) | \
208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               set(x for x in extra if i.is_declared(x))
209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def inner(self):
211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Return an inner frame."""
212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return Frame(self.eval_ctx, self)
213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def soft(self):
215b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Return a soft frame.  A soft frame may not be modified as
216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        standalone thing as it shares the resources with the frame it
217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        was created of, but it's not a rootlevel frame any longer.
218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        rv = self.copy()
220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        rv.rootlevel = False
221b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return rv
222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
223b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    __copy__ = copy
224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
225b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
226b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class VisitorExit(RuntimeError):
227b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
230b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class DependencyFinderVisitor(NodeVisitor):
231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """A visitor that collects filter and test calls."""
232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
233b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def __init__(self):
234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.filters = set()
235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.tests = set()
236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Filter(self, node):
238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.generic_visit(node)
239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.filters.add(node.name)
240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Test(self, node):
242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.generic_visit(node)
243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.tests.add(node.name)
244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Block(self, node):
246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Stop visiting at blocks."""
247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class UndeclaredNameVisitor(NodeVisitor):
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """A visitor that checks if a name is accessed without being
251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    declared.  This is different from the frame visitor as it will
252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    not stop at closure frames.
253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """
254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def __init__(self, names):
256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.names = set(names)
257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.undeclared = set()
258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Name(self, node):
260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.ctx == 'load' and node.name in self.names:
261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.undeclared.add(node.name)
262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if self.undeclared == self.names:
263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                raise VisitorExit()
264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.names.discard(node.name)
266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Block(self, node):
268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Stop visiting a blocks."""
269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class FrameIdentifierVisitor(NodeVisitor):
272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """A visitor for `Frame.inspect`."""
273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def __init__(self, identifiers):
275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.identifiers = identifiers
276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Name(self, node):
278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """All assignments to names go through this function."""
279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.ctx == 'store':
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.identifiers.declared_locally.add(node.name)
281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif node.ctx == 'param':
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.identifiers.declared_parameter.add(node.name)
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif node.ctx == 'load' and not \
284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             self.identifiers.is_declared(node.name):
285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.identifiers.undeclared.add(node.name)
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_If(self, node):
288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.test)
289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        real_identifiers = self.identifiers
290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        old_names = real_identifiers.declared_locally | \
292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    real_identifiers.declared_parameter
293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        def inner_visit(nodes):
295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not nodes:
296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                return set()
297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.identifiers = real_identifiers.copy()
298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for subnode in nodes:
299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(subnode)
300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            rv = self.identifiers.declared_locally - old_names
301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # we have to remember the undeclared variables of this branch
302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # because we will have to pull them.
303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            real_identifiers.undeclared.update(self.identifiers.undeclared)
304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.identifiers = real_identifiers
305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            return rv
306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        body = inner_visit(node.body)
308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else_ = inner_visit(node.else_ or ())
309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the differences between the two branches are also pulled as
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # undeclared variables
312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        real_identifiers.undeclared.update(body.symmetric_difference(else_) -
313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                           real_identifiers.declared)
314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # remember those that are declared.
316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        real_identifiers.declared_locally.update(body | else_)
317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Macro(self, node):
319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.identifiers.declared_locally.add(node.name)
320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Import(self, node):
322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.generic_visit(node)
323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.identifiers.declared_locally.add(node.target)
324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_FromImport(self, node):
326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.generic_visit(node)
327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for name in node.names:
328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if isinstance(name, tuple):
329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.identifiers.declared_locally.add(name[1])
330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.identifiers.declared_locally.add(name)
332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Assign(self, node):
334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Visit assignments in the correct order."""
335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.node)
336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.target)
337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_For(self, node):
339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Visiting stops at for blocks.  However the block sequence
340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        is visited as part of the outer scope.
341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.iter)
343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_CallBlock(self, node):
345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.call)
346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_FilterBlock(self, node):
348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.filter)
349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Scope(self, node):
351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Stop visiting at scopes."""
352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Block(self, node):
354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Stop visiting at blocks."""
355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class CompilerExit(Exception):
358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """Raised if the compiler encountered a situation where it just
359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    doesn't make sense to further process the code.  Any block that
360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    raises such an exception is not further processed.
361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    """
362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class CodeGenerator(NodeVisitor):
365b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def __init__(self, environment, name, filename, stream=None,
367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 defer_init=False):
368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if stream is None:
36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            stream = NativeStringIO()
370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.environment = environment
371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.name = name
372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.filename = filename
373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.stream = stream
374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.created_block_context = False
375b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.defer_init = defer_init
376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # aliases for imports
378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.import_aliases = {}
379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # a registry for all blocks.  Because blocks are moved out
381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # into the global python scope they are registered here
382b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.blocks = {}
383b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the number of extends statements so far
385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.extends_so_far = 0
386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # some templates have a rootlevel extends.  In this case we
388b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # can safely assume that we're a child template and do some
389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # more optimizations.
390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.has_known_extends = False
391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the current line number
393b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.code_lineno = 1
394b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # registry of all filters and tests (global, not block local)
396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.tests = {}
397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.filters = {}
398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the debug information
400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.debug_info = []
401b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._write_debug_info = None
402b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the number of new lines before the next write()
404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._new_lines = 0
405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the line number of the last written statement
407b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._last_line = 0
408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # true if nothing was written so far.
410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._first_write = True
411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # used by the `temporary_identifier` method to get new
413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # unique, temporary identifier
414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._last_identifier = 0
415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the current indentation
417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._indentation = 0
418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    # -- Various compilation helpers
420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def fail(self, msg, lineno):
422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Fail with a :exc:`TemplateAssertionError`."""
423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        raise TemplateAssertionError(msg, lineno, self.name, self.filename)
424b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def temporary_identifier(self):
426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Get a new unique identifier."""
427b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._last_identifier += 1
428b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return 't_%d' % self._last_identifier
429b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
430b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def buffer(self, frame):
431b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Enable buffering for the frame from that point onwards."""
432b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.buffer = self.temporary_identifier()
433b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('%s = []' % frame.buffer)
434b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def return_buffer_contents(self, frame):
436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Return the buffer contents of the frame."""
437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.eval_ctx.volatile:
438b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('if context.eval_ctx.autoescape:')
439b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
440b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('return Markup(concat(%s))' % frame.buffer)
441b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
442b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('else:')
443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('return concat(%s)' % frame.buffer)
445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif frame.eval_ctx.autoescape:
447b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('return Markup(concat(%s))' % frame.buffer)
448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('return concat(%s)' % frame.buffer)
450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def indent(self):
452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Indent by one."""
453b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._indentation += 1
454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
455b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def outdent(self, step=1):
456b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Outdent by step."""
457b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._indentation -= step
458b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
459b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def start_write(self, frame, node=None):
460b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Yield or write into the frame buffer."""
461b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.buffer is None:
462b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('yield ', node)
463b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
464b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('%s.append(' % frame.buffer, node)
465b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
466b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def end_write(self, frame):
467b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """End the writing process started by `start_write`."""
468b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.buffer is not None:
469b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(')')
470b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
471b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def simple_write(self, s, frame, node=None):
472b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Simple shortcut for start_write + write + end_write."""
473b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.start_write(frame, node)
474b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(s)
475b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.end_write(frame)
476b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
477b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def blockvisit(self, nodes, frame):
478b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Visit a list of nodes as block in a frame.  If the current frame
479b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        is no buffer a dummy ``if 0: yield None`` is written automatically
480b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        unless the force_generator parameter is set to False.
481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.buffer is None:
483b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('if 0: yield None')
484b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('pass')
486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        try:
487b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for node in nodes:
488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node, frame)
489b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        except CompilerExit:
490b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            pass
491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def write(self, x):
493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Write a string into the output stream."""
494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if self._new_lines:
495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not self._first_write:
496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.stream.write('\n' * self._new_lines)
497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.code_lineno += self._new_lines
498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if self._write_debug_info is not None:
499b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.debug_info.append((self._write_debug_info,
500b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                            self.code_lineno))
501b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self._write_debug_info = None
502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self._first_write = False
503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.stream.write('    ' * self._indentation)
504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self._new_lines = 0
505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.stream.write(x)
506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def writeline(self, x, node=None, extra=0):
508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Combination of newline and write."""
509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.newline(node, extra)
510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(x)
511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def newline(self, node=None, extra=0):
513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Add one or more newlines before the next write."""
514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self._new_lines = max(self._new_lines, 1 + extra)
515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node is not None and node.lineno != self._last_line:
516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self._write_debug_info = node.lineno
517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self._last_line = node.lineno
518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def signature(self, node, frame, extra_kwargs=None):
520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Writes a function call to the stream for the current node.
521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        A leading comma is added automatically.  The extra keyword
522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        arguments may not include python keywords otherwise a syntax
523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        error could occour.  The extra keyword arguments should be given
524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        as python dict.
525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if any of the given keyword arguments is a python keyword
527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # we have to make sure that no invalid call is created.
528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        kwarg_workaround = False
529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
530b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if is_python_keyword(kwarg):
531b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                kwarg_workaround = True
532b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                break
533b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
534b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for arg in node.args:
535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(', ')
536b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(arg, frame)
537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if not kwarg_workaround:
539b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for kwarg in node.kwargs:
540b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', ')
541b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(kwarg, frame)
542b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if extra_kwargs is not None:
54358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                for key, value in iteritems(extra_kwargs):
544b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.write(', %s=%s' % (key, value))
545b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.dyn_args:
546b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(', *')
547b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.dyn_args, frame)
548b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
549b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if kwarg_workaround:
550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if node.dyn_kwargs is not None:
551b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', **dict({')
552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', **{')
554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for kwarg in node.kwargs:
555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('%r: ' % kwarg.key)
556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(kwarg.value, frame)
557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', ')
558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if extra_kwargs is not None:
55958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                for key, value in iteritems(extra_kwargs):
560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.write('%r: %s, ' % (key, value))
561b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if node.dyn_kwargs is not None:
562b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('}, **')
563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.dyn_kwargs, frame)
564b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(')')
565b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('}')
567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif node.dyn_kwargs is not None:
569b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(', **')
570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.dyn_kwargs, frame)
571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
572b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def pull_locals(self, frame):
573b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Pull all the references identifiers into the local scope."""
574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for name in frame.identifiers.undeclared:
575b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('l_%s = context.resolve(%r)' % (name, name))
576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def pull_dependencies(self, nodes):
578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Pull all the dependencies."""
579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        visitor = DependencyFinderVisitor()
580b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for node in nodes:
581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            visitor.visit(node)
582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for dependency in 'filters', 'tests':
583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            mapping = getattr(self, dependency)
584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for name in getattr(visitor, dependency):
585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if name not in mapping:
586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    mapping[name] = self.temporary_identifier()
587b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('%s = environment.%s[%r]' %
588b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                               (mapping[name], dependency, name))
589b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
590b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def unoptimize_scope(self, frame):
591b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Disable Python optimizations for the frame."""
592b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # XXX: this is not that nice but it has no real overhead.  It
593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # mainly works because python finds the locals before dead code
594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # is removed.  If that breaks we have to add a dummy function
595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # that just accepts the arguments and does nothing.
596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.identifiers.declared:
597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('%sdummy(%s)' % (
598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                unoptimize_before_dead_code and 'if 0: ' or '',
599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                ', '.join('l_' + name for name in frame.identifiers.declared)
600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            ))
601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def push_scope(self, frame, extra_vars=()):
603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """This function returns all the shadowed variables in a dict
604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        in the form name: alias and will write the required assignments
605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        into the current scope.  No indentation takes place.
606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        This also predefines locally declared variables from the loop
608b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        body because under some circumstances it may be the case that
609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
610b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        `extra_vars` is passed to `Frame.find_shadowed`.
611b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
612b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        aliases = {}
613b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for name in frame.find_shadowed(extra_vars):
614b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            aliases[name] = ident = self.temporary_identifier()
615b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('%s = l_%s' % (ident, name))
616b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        to_declare = set()
617b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for name in frame.identifiers.declared_locally:
618b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if name not in aliases:
619b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                to_declare.add('l_' + name)
620b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if to_declare:
621b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline(' = '.join(to_declare) + ' = missing')
622b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return aliases
623b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
624b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def pop_scope(self, aliases, frame):
625b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Restore all aliases and delete unused variables."""
62658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        for name, alias in iteritems(aliases):
627b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('l_%s = %s' % (name, alias))
628b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        to_delete = set()
629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for name in frame.identifiers.declared_locally:
630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if name not in aliases:
631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                to_delete.add('l_' + name)
632b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if to_delete:
633b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # we cannot use the del statement here because enclosed
634b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # scopes can trigger a SyntaxError:
635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            #   a = 42; b = lambda: a; del a
636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline(' = '.join(to_delete) + ' = missing')
637b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
638b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def function_scoping(self, node, frame, children=None,
639b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                         find_special=True):
640b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """In Jinja a few statements require the help of anonymous
641b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        functions.  Those are currently macros and call blocks and in
642b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        the future also recursive loops.  As there is currently
643b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        technical limitation that doesn't allow reading and writing a
644b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        variable in a scope where the initial value is coming from an
645b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        outer scope, this function tries to fall back with a common
646b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        error message.  Additionally the frame passed is modified so
647b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        that the argumetns are collected and callers are looked up.
648b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        This will return the modified frame.
650b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """
651b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # we have to iterate twice over it, make sure that works
652b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if children is None:
653b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            children = node.iter_child_nodes()
654b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        children = list(children)
655b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_frame = frame.inner()
656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_frame.inspect(children)
657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
658b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # variables that are undeclared (accessed before declaration) and
659b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # declared locally *and* part of an outside scope raise a template
660b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # assertion error. Reason: we can't generate reasonable code from
661b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # it without aliasing all the variables.
662b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # this could be fixed in Python 3 where we have the nonlocal
663b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # keyword or if we switch to bytecode generation
66458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        overridden_closure_vars = (
665b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.identifiers.undeclared &
666b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.identifiers.declared &
667b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            (func_frame.identifiers.declared_locally |
668b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             func_frame.identifiers.declared_parameter)
669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        )
67058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if overridden_closure_vars:
671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.fail('It\'s not possible to set and access variables '
672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                      'derived from an outer scope! (affects: %s)' %
67358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      ', '.join(sorted(overridden_closure_vars)), node.lineno)
674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
675b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # remove variables from a closure from the frame's undeclared
676b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # identifiers.
677b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_frame.identifiers.undeclared -= (
678b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.identifiers.undeclared &
679b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.identifiers.declared
680b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        )
681b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
682b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # no special variables for this scope, abort early
683b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if not find_special:
684b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            return func_frame
685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
686b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_frame.accesses_kwargs = False
687b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_frame.accesses_varargs = False
688b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_frame.accesses_caller = False
689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_frame.arguments = args = ['l_' + x.name for x in node.args]
690b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
691b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
692b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
693b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if 'caller' in undeclared:
694b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.accesses_caller = True
695b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.identifiers.add_special('caller')
696b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            args.append('l_caller')
697b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if 'kwargs' in undeclared:
698b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.accesses_kwargs = True
699b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.identifiers.add_special('kwargs')
700b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            args.append('l_kwargs')
701b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if 'varargs' in undeclared:
702b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.accesses_varargs = True
703b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_frame.identifiers.add_special('varargs')
704b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            args.append('l_varargs')
705b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return func_frame
706b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
707b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def macro_body(self, node, frame, children=None):
708b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Dump the function def of a macro or call block."""
709b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame = self.function_scoping(node, frame, children)
710b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # macros are delayed, they never require output checks
711b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.require_output_check = False
712b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        args = frame.arguments
713b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # XXX: this is an ugly fix for the loop nesting bug
714b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # (tests.test_old_bugs.test_loop_call_bug).  This works around
715b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # a identifier nesting problem we have in general.  It's just more
716b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # likely to happen in loops which is why we work around it.  The
717b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # real solution would be "nonlocal" all the identifiers that are
718b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # leaking into a new python frame and might be used both unassigned
719b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # and assigned.
720b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if 'loop' in frame.identifiers.declared:
721b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            args = args + ['l_loop=l_loop']
722b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('def macro(%s):' % ', '.join(args), node)
723b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.indent()
724b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.buffer(frame)
725b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pull_locals(frame)
726b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.blockvisit(node.body, frame)
727b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.return_buffer_contents(frame)
728b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outdent()
729b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return frame
730b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
731b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def macro_def(self, node, frame):
732b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Dump the macro definition for the def created by macro_body."""
733b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        arg_tuple = ', '.join(repr(x.name) for x in node.args)
734b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        name = getattr(node, 'name', None)
735b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if len(node.args) == 1:
736b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            arg_tuple += ','
737b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('Macro(environment, macro, %r, (%s), (' %
738b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   (name, arg_tuple))
739b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for arg in node.defaults:
740b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(arg, frame)
741b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(', ')
742b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('), %r, %r, %r)' % (
743b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            bool(frame.accesses_kwargs),
744b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            bool(frame.accesses_varargs),
745b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            bool(frame.accesses_caller)
746b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        ))
747b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
748b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def position(self, node):
749b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Return a human readable position for the node."""
750b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        rv = 'line %d' % node.lineno
751b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if self.name is not None:
752b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            rv += ' in ' + repr(self.name)
753b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return rv
754b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
755b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    # -- Statement Visitors
756b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
757b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Template(self, node, frame=None):
758b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        assert frame is None, 'no root frame allowed'
759b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        eval_ctx = EvalContext(self.environment, self.name)
760b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
761b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        from jinja2.runtime import __all__ as exported
762b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('from __future__ import division')
763b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('from jinja2.runtime import ' + ', '.join(exported))
764b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if not unoptimize_before_dead_code:
765b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('dummy = lambda *x: None')
766b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
767b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if we want a deferred initialization we cannot move the
768b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # environment into a local name
769b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        envenv = not self.defer_init and ', environment=environment' or ''
770b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
771b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # do we have an extends tag at all?  If not, we can save some
772b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # overhead by just not processing any inheritance code.
773b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        have_extends = node.find(nodes.Extends) is not None
774b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
775b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # find all blocks
776b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for block in node.find_all(nodes.Block):
777b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if block.name in self.blocks:
778b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.fail('block %r defined twice' % block.name, block.lineno)
779b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.blocks[block.name] = block
780b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
781b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # find all imports and import them
782b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for import_ in node.find_all(nodes.ImportedName):
783b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if import_.importname not in self.import_aliases:
784b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                imp = import_.importname
785b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.import_aliases[imp] = alias = self.temporary_identifier()
786b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if '.' in imp:
787b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    module, obj = imp.rsplit('.', 1)
788b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.writeline('from %s import %s as %s' %
789b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                   (module, obj, alias))
790b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                else:
791b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.writeline('import %s as %s' % (imp, alias))
792b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
793b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # add the load name
794b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('name = %r' % self.name)
795b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
796b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # generate the root render function.
797b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('def root(context%s):' % envenv, extra=1)
798b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
799b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # process the root
800b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame = Frame(eval_ctx)
801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.inspect(node.body)
802b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.toplevel = frame.rootlevel = True
803b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.require_output_check = have_extends and not self.has_known_extends
804b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.indent()
805b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if have_extends:
806b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('parent_template = None')
807b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if 'self' in find_undeclared(node.body, ('self',)):
808b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            frame.identifiers.add_special('self')
809b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('l_self = TemplateReference(context)')
810b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pull_locals(frame)
811b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pull_dependencies(node.body)
812b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.blockvisit(node.body, frame)
813b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outdent()
814b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
815b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # make sure that the parent root is called.
816b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if have_extends:
817b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not self.has_known_extends:
818b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.indent()
819b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('if parent_template is not None:')
820b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
821b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('for event in parent_template.'
822b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           'root_render_func(context):')
823b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
824b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('yield event')
825b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent(2 + (not self.has_known_extends))
826b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
827b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # at this point we now have the blocks collected and can visit them too.
82858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        for name, block in iteritems(self.blocks):
829b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            block_frame = Frame(eval_ctx)
830b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            block_frame.inspect(block.body)
831b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            block_frame.block = name
832b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('def block_%s(context%s):' % (name, envenv),
833b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           block, 1)
834b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
835b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            undeclared = find_undeclared(block.body, ('self', 'super'))
836b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if 'self' in undeclared:
837b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                block_frame.identifiers.add_special('self')
838b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('l_self = TemplateReference(context)')
839b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if 'super' in undeclared:
840b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                block_frame.identifiers.add_special('super')
841b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('l_super = context.super(%r, '
842b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                               'block_%s)' % (name, name))
843b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.pull_locals(block_frame)
844b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.pull_dependencies(block.body)
845b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.blockvisit(block.body, block_frame)
846b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
847b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
848b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
849b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                   for x in self.blocks),
850b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       extra=1)
851b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
852b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # add a function that returns the debug info
853b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
854b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                    in self.debug_info))
855b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
856b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Block(self, node, frame):
857b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Call a block and register it for the template."""
858b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        level = 1
859b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.toplevel:
860b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # if we know that we are a child template, there is no need to
861b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # check if we are one
862b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if self.has_known_extends:
863b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                return
864b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if self.extends_so_far > 0:
865b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('if parent_template is None:')
866b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.indent()
867b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                level += 1
868b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        context = node.scoped and 'context.derived(locals())' or 'context'
869b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('for event in context.blocks[%r][0](%s):' % (
870b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       node.name, context), node)
871b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.indent()
872b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.simple_write('event', frame)
873b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outdent(level)
874b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
875b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Extends(self, node, frame):
876b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Calls the extender."""
877b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if not frame.toplevel:
878b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.fail('cannot use extend from a non top-level scope',
879b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                      node.lineno)
880b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
881b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if the number of extends statements in general is zero so
882b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # far, we don't have to add a check if something extended
883b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the template before this one.
884b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if self.extends_so_far > 0:
885b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
886b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # if we have a known extends we just add a template runtime
887b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # error into the generated code.  We could catch that at compile
888b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # time too, but i welcome it not to confuse users by throwing the
889b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # same error at different times just "because we can".
890b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not self.has_known_extends:
891b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('if parent_template is not None:')
892b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.indent()
893b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('raise TemplateRuntimeError(%r)' %
894b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           'extended multiple times')
895b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
896b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # if we have a known extends already we don't need that code here
897b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # as we know that the template execution will end here.
898b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if self.has_known_extends:
899b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                raise CompilerExit()
90058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            else:
90158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                self.outdent()
902b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
903b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('parent_template = environment.get_template(', node)
904b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.template, frame)
905b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(', %r)' % self.name)
906b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('for name, parent_block in parent_template.'
907b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       'blocks.%s():' % dict_item_iter)
908b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.indent()
909b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('context.blocks.setdefault(name, []).'
910b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       'append(parent_block)')
911b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outdent()
912b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
913b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if this extends statement was in the root level we can take
914b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # advantage of that information and simplify the generated code
915b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # in the top level from this point onwards
916b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.rootlevel:
917b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.has_known_extends = True
918b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
919b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # and now we have one more
920b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.extends_so_far += 1
921b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
922b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Include(self, node, frame):
923b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Handles includes."""
924b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.with_context:
925b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.unoptimize_scope(frame)
926b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.ignore_missing:
927b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('try:')
928b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
929b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
930b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func_name = 'get_or_select_template'
931b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if isinstance(node.template, nodes.Const):
93258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            if isinstance(node.template.value, string_types):
933b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                func_name = 'get_template'
934b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            elif isinstance(node.template.value, (tuple, list)):
935b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                func_name = 'select_template'
936b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif isinstance(node.template, (nodes.Tuple, nodes.List)):
937b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_name = 'select_template'
938b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
939b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('template = environment.%s(' % func_name, node)
940b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.template, frame)
941b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(', %r)' % self.name)
942b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.ignore_missing:
943b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
944b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('except TemplateNotFound:')
945b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
946b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('pass')
947b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
948b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('else:')
949b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
950b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
951b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.with_context:
952b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('for event in template.root_render_func('
953b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           'template.new_context(context.parent, True, '
954b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           'locals())):')
955b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
956b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('for event in template.module._body_stream:')
957b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
958b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.indent()
959b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.simple_write('event', frame)
960b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outdent()
961b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
962b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.ignore_missing:
963b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
964b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
965b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Import(self, node, frame):
966b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Visit regular imports."""
967b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.with_context:
968b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.unoptimize_scope(frame)
969b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('l_%s = ' % node.target, node)
970b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.toplevel:
971b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('context.vars[%r] = ' % node.target)
972b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('environment.get_template(')
973b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.template, frame)
974b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(', %r).' % self.name)
975b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.with_context:
976b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('make_module(context.parent, True, locals())')
977b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
978b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('module')
979b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.toplevel and not node.target.startswith('_'):
980b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('context.exported_vars.discard(%r)' % node.target)
981b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.assigned_names.add(node.target)
982b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
983b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_FromImport(self, node, frame):
984b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        """Visit named imports."""
985b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.newline(node)
986b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('included_template = environment.get_template(')
987b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.template, frame)
988b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(', %r).' % self.name)
989b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.with_context:
990b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('make_module(context.parent, True)')
991b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
992b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('module')
993b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
994b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        var_names = []
995b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        discarded_names = []
996b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for name in node.names:
997b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if isinstance(name, tuple):
998b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                name, alias = name
999b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1000b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                alias = name
1001b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('l_%s = getattr(included_template, '
1002b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           '%r, missing)' % (alias, name))
1003b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('if l_%s is missing:' % alias)
1004b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1005b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('l_%s = environment.undefined(%r %% '
1006b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           'included_template.__name__, '
1007b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           'name=%r)' %
1008b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           (alias, 'the template %%r (imported on %s) does '
1009b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           'not export the requested name %s' % (
1010b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                self.position(node),
1011b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                repr(name)
1012b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           ), name))
1013b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
1014b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if frame.toplevel:
1015b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                var_names.append(alias)
1016b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if not alias.startswith('_'):
1017b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    discarded_names.append(alias)
1018b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            frame.assigned_names.add(alias)
1019b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1020b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if var_names:
1021b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if len(var_names) == 1:
1022b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                name = var_names[0]
1023b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('context.vars[%r] = l_%s' % (name, name))
1024b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1025b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('context.vars.update({%s})' % ', '.join(
1026b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    '%r: l_%s' % (name, name) for name in var_names
1027b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                ))
1028b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if discarded_names:
1029b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if len(discarded_names) == 1:
1030b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('context.exported_vars.discard(%r)' %
1031b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                               discarded_names[0])
1032b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1033b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('context.exported_vars.difference_'
103458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                               'update((%s))' % ', '.join(imap(repr, discarded_names)))
1035b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1036b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_For(self, node, frame):
1037b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # when calculating the nodes for the inner frame we have to exclude
1038b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the iterator contents from it
1039b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        children = node.iter_child_nodes(exclude=('iter',))
1040b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.recursive:
1041b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            loop_frame = self.function_scoping(node, frame, children,
1042b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                               find_special=False)
1043b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1044b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            loop_frame = frame.inner()
1045b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            loop_frame.inspect(children)
1046b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1047b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # try to figure out if we have an extended loop.  An extended loop
1048b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # is necessary if the loop is in recursive mode if the special loop
1049b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # variable is accessed in the body.
1050b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        extended_loop = node.recursive or 'loop' in \
1051b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        find_undeclared(node.iter_child_nodes(
1052b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                            only=('body',)), ('loop',))
1053b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1054b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if we don't have an recursive loop we have to find the shadowed
1055b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # variables at that point.  Because loops can be nested but the loop
1056b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # variable is a special one we have to enforce aliasing for it.
1057b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if not node.recursive:
1058b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            aliases = self.push_scope(loop_frame, ('loop',))
1059b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1060b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # otherwise we set up a buffer and add a function def
1061b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
106258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            self.writeline('def loop(reciter, loop_render_func, depth=0):', node)
1063b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1064b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.buffer(loop_frame)
1065b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            aliases = {}
1066b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1067b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # make sure the loop variable is a special one and raise a template
1068b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # assertion error if a loop tries to write to loop
1069b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if extended_loop:
107058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            self.writeline('l_loop = missing')
1071b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            loop_frame.identifiers.add_special('loop')
1072b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for name in node.find_all(nodes.Name):
1073b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if name.ctx == 'store' and name.name == 'loop':
1074b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.fail('Can\'t assign to special loop variable '
1075b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                          'in for-loop target', name.lineno)
1076b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1077b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pull_locals(loop_frame)
1078b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.else_:
1079b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            iteration_indicator = self.temporary_identifier()
1080b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('%s = 1' % iteration_indicator)
1081b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1082b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # Create a fake parent loop if the else or test section of a
1083b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # loop is accessing the special loop variable and no parent loop
1084b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # exists.
1085b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if 'loop' not in aliases and 'loop' in find_undeclared(
1086b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)           node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1087b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline("l_loop = environment.undefined(%r, name='loop')" %
1088b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                ("'loop' is undefined. the filter section of a loop as well "
1089b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 "as the else block don't have access to the special 'loop'"
1090b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 " variable of the current loop.  Because there is no parent "
1091b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 "loop it's undefined.  Happened in loop on %s" %
1092b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 self.position(node)))
1093b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1094b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('for ', node)
1095b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.target, loop_frame)
1096b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
1097b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1098b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if we have an extened loop and a node test, we filter in the
1099b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # "outer frame".
1100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if extended_loop and node.test is not None:
1101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('(')
1102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.target, loop_frame)
1103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(' for ')
1104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.target, loop_frame)
1105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(' in ')
1106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if node.recursive:
1107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('reciter')
1108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.iter, loop_frame)
1110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(' if (')
1111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            test_frame = loop_frame.copy()
1112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.test, test_frame)
1113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('))')
1114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif node.recursive:
1116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('reciter')
1117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.iter, loop_frame)
1119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.recursive:
112158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            self.write(', loop_render_func, depth):')
1122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(extended_loop and '):' or ':')
1124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # tests in not extended loops become a continue
1126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if not extended_loop and node.test is not None:
1127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('if not ')
1129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.test, loop_frame)
1130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(':')
1131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('continue')
1133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent(2)
1134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.indent()
1136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.blockvisit(node.body, loop_frame)
1137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.else_:
1138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('%s = 0' % iteration_indicator)
1139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outdent()
1140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.else_:
1142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('if %s:' % iteration_indicator)
1143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.blockvisit(node.else_, loop_frame)
1145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
1146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # reset the aliases if there are any.
1148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if not node.recursive:
1149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.pop_scope(aliases, loop_frame)
1150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if the node was recursive we have to return the buffer contents
1152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # and start the iteration code
1153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.recursive:
1154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.return_buffer_contents(loop_frame)
1155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
1156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.start_write(frame, node)
1157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('loop(')
1158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.iter, frame)
1159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(', loop)')
1160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.end_write(frame)
1161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_If(self, node, frame):
1163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if_frame = frame.soft()
1164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('if ', node)
1165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.test, if_frame)
1166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(':')
1167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.indent()
1168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.blockvisit(node.body, if_frame)
1169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.outdent()
1170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.else_:
1171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('else:')
1172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.blockvisit(node.else_, if_frame)
1174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
1175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Macro(self, node, frame):
1177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        macro_frame = self.macro_body(node, frame)
1178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.newline()
1179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.toplevel:
1180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if not node.name.startswith('_'):
1181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('context.exported_vars.add(%r)' % node.name)
1182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('context.vars[%r] = ' % node.name)
1183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('l_%s = ' % node.name)
1184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.macro_def(node, macro_frame)
1185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.assigned_names.add(node.name)
1186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_CallBlock(self, node, frame):
1188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        children = node.iter_child_nodes(exclude=('call',))
1189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        call_frame = self.macro_body(node, frame, children)
1190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('caller = ')
1191b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.macro_def(node, call_frame)
1192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.start_write(frame, node)
1193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit_Call(node.call, call_frame, forward_caller=True)
1194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.end_write(frame)
1195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_FilterBlock(self, node, frame):
1197b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        filter_frame = frame.inner()
1198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        filter_frame.inspect(node.iter_child_nodes())
1199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        aliases = self.push_scope(filter_frame)
1200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pull_locals(filter_frame)
1201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.buffer(filter_frame)
1202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.blockvisit(node.body, filter_frame)
1203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.start_write(frame, node)
1204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit_Filter(node.filter, filter_frame)
1205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.end_write(frame)
1206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pop_scope(aliases, filter_frame)
1207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_ExprStmt(self, node, frame):
1209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.newline(node)
1210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.node, frame)
1211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Output(self, node, frame):
1213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if we have a known extends statement, we don't output anything
1214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if we are in a require_output_check section
1215b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if self.has_known_extends and frame.require_output_check:
1216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            return
1217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if self.environment.finalize:
121958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            finalize = lambda x: text_type(self.environment.finalize(x))
1220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
122158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            finalize = text_type
1222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1223b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if we are inside a frame that requires output checking, we do so
1224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        outdent_later = False
1225b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.require_output_check:
1226b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('if parent_template is None:')
1227b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            outdent_later = True
1229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1230b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # try to evaluate as many chunks as possible into a static
1231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # string at compile time.
1232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        body = []
1233b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for child in node.nodes:
1234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            try:
1235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                const = child.as_const(frame.eval_ctx)
1236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            except nodes.Impossible:
1237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                body.append(child)
1238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                continue
1239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # the frame can't be volatile here, becaus otherwise the
1240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # as_const() function would raise an Impossible exception
1241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            # at that point.
1242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            try:
1243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if frame.eval_ctx.autoescape:
1244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    if hasattr(const, '__html__'):
1245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        const = const.__html__()
1246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    else:
1247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        const = escape(const)
1248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                const = finalize(const)
1249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            except Exception:
1250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                # if something goes wrong here we evaluate the node
1251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                # at runtime for easier debugging
1252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                body.append(child)
1253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                continue
1254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if body and isinstance(body[-1], list):
1255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                body[-1].append(const)
1256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                body.append([const])
1258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if we have less than 3 nodes or a buffer we yield or extend/append
1260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if len(body) < 3 or frame.buffer is not None:
1261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if frame.buffer is not None:
1262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                # for one item we append, for more we extend
1263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if len(body) == 1:
1264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.writeline('%s.append(' % frame.buffer)
1265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                else:
1266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.writeline('%s.extend((' % frame.buffer)
1267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.indent()
1268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for item in body:
1269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if isinstance(item, list):
1270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    val = repr(concat(item))
1271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    if frame.buffer is None:
1272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.writeline('yield ' + val)
1273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    else:
1274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.writeline(val + ', ')
1275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                else:
1276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    if frame.buffer is None:
1277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.writeline('yield ', item)
1278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    else:
1279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.newline(item)
1280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    close = 1
1281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    if frame.eval_ctx.volatile:
1282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.write('(context.eval_ctx.autoescape and'
1283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                   ' escape or to_string)(')
1284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    elif frame.eval_ctx.autoescape:
1285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.write('escape(')
1286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    else:
1287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.write('to_string(')
1288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    if self.environment.finalize is not None:
1289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.write('environment.finalize(')
1290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        close += 1
1291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.visit(item, frame)
1292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.write(')' * close)
1293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    if frame.buffer is not None:
1294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.write(', ')
1295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if frame.buffer is not None:
1296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                # close the open parentheses
1297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.outdent()
1298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline(len(body) == 1 and ')' or '))')
1299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # otherwise we create a format string as this is faster in that case
1301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            format = []
1303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            arguments = []
1304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for item in body:
1305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if isinstance(item, list):
1306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    format.append(concat(item).replace('%', '%%'))
1307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                else:
1308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    format.append('%s')
1309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    arguments.append(item)
1310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('yield ')
1311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(repr(concat(format)) + ' % (')
1312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            idx = -1
1313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.indent()
1314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            for argument in arguments:
1315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.newline(argument)
1316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                close = 0
1317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if frame.eval_ctx.volatile:
1318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.write('(context.eval_ctx.autoescape and'
1319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                               ' escape or to_string)(')
1320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    close += 1
1321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                elif frame.eval_ctx.autoescape:
1322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.write('escape(')
1323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    close += 1
1324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if self.environment.finalize is not None:
1325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.write('environment.finalize(')
1326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    close += 1
1327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(argument, frame)
1328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(')' * close + ', ')
1329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
1330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline(')')
1331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if outdent_later:
1333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.outdent()
1334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Assign(self, node, frame):
1336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.newline(node)
1337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # toplevel assignments however go into the local namespace and
1338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # the current template's context.  We create a copy of the frame
1339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # here and add a set so that the Name visitor can add the assigned
1340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # names here.
1341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.toplevel:
1342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            assignment_frame = frame.copy()
1343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            assignment_frame.toplevel_assignments = set()
1344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            assignment_frame = frame
1346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.target, assignment_frame)
1347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(' = ')
1348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.node, frame)
1349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # make sure toplevel assignments are added to the context.
1351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.toplevel:
1352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            public_names = [x for x in assignment_frame.toplevel_assignments
1353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                            if not x.startswith('_')]
1354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if len(assignment_frame.toplevel_assignments) == 1:
1355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                name = next(iter(assignment_frame.toplevel_assignments))
1356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('context.vars[%r] = l_%s' % (name, name))
1357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.writeline('context.vars.update({')
1359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                for idx, name in enumerate(assignment_frame.toplevel_assignments):
1360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    if idx:
1361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        self.write(', ')
1362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.write('%r: l_%s' % (name, name))
1363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('})')
1364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if public_names:
1365b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                if len(public_names) == 1:
1366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.writeline('context.exported_vars.add(%r)' %
1367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                   public_names[0])
1368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                else:
1369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                    self.writeline('context.exported_vars.update((%s))' %
137058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   ', '.join(imap(repr, public_names)))
1371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    # -- Expression Visitors
1373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Name(self, node, frame):
1375b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.ctx == 'store' and frame.toplevel:
1376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            frame.toplevel_assignments.add(node.name)
1377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('l_' + node.name)
1378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.assigned_names.add(node.name)
1379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Const(self, node, frame):
1381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        val = node.value
1382b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if isinstance(val, float):
1383b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(str(val))
1384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(repr(val))
1386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_TemplateData(self, node, frame):
1388b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        try:
1389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(repr(node.as_const(frame.eval_ctx)))
1390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        except nodes.Impossible:
1391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)'
1392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       % node.data)
1393b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1394b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Tuple(self, node, frame):
1395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('(')
1396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        idx = -1
1397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for idx, item in enumerate(node.items):
1398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if idx:
1399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', ')
1400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(item, frame)
1401b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(idx == 0 and ',)' or ')')
1402b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_List(self, node, frame):
1404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('[')
1405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for idx, item in enumerate(node.items):
1406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if idx:
1407b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', ')
1408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(item, frame)
1409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(']')
1410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Dict(self, node, frame):
1412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('{')
1413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for idx, item in enumerate(node.items):
1414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if idx:
1415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', ')
1416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(item.key, frame)
1417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(': ')
1418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(item.value, frame)
1419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('}')
1420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def binop(operator, interceptable=True):
1422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        def visitor(self, node, frame):
1423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if self.environment.sandboxed and \
1424b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               operator in self.environment.intercepted_binops:
1425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('environment.call_binop(context, %r, ' % operator)
1426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.left, frame)
1427b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(', ')
1428b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.right, frame)
1429b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1430b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('(')
1431b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.left, frame)
1432b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write(' %s ' % operator)
1433b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.right, frame)
1434b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(')')
1435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return visitor
1436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def uaop(operator, interceptable=True):
1438b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        def visitor(self, node, frame):
1439b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if self.environment.sandboxed and \
1440b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               operator in self.environment.intercepted_unops:
1441b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('environment.call_unop(context, %r, ' % operator)
1442b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.node, frame)
1443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.write('(' + operator)
1445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                self.visit(node.node, frame)
1446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(')')
1447b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return visitor
1448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Add = binop('+')
1450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Sub = binop('-')
1451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Mul = binop('*')
1452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Div = binop('/')
1453b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_FloorDiv = binop('//')
1454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Pow = binop('**')
1455b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Mod = binop('%')
1456b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_And = binop('and', interceptable=False)
1457b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Or = binop('or', interceptable=False)
1458b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Pos = uaop('+')
1459b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Neg = uaop('-')
1460b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    visit_Not = uaop('not ', interceptable=False)
1461b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    del binop, uaop
1462b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1463b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Concat(self, node, frame):
1464b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if frame.eval_ctx.volatile:
1465b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_name = '(context.eval_ctx.volatile and' \
1466b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                        ' markup_join or unicode_join)'
1467b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif frame.eval_ctx.autoescape:
1468b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_name = 'markup_join'
1469b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1470b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            func_name = 'unicode_join'
1471b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('%s((' % func_name)
1472b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for arg in node.nodes:
1473b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(arg, frame)
1474b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(', ')
1475b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('))')
1476b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1477b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Compare(self, node, frame):
1478b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.expr, frame)
1479b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for op in node.ops:
1480b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(op, frame)
1481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Operand(self, node, frame):
1483b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(' %s ' % operators[node.op])
1484b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.expr, frame)
1485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Getattr(self, node, frame):
1487b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('environment.getattr(')
1488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.node, frame)
1489b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(', %r)' % node.attr)
1490b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Getitem(self, node, frame):
1492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # slices bypass the environment getitem method.
1493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if isinstance(node.arg, nodes.Slice):
1494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.node, frame)
1495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('[')
1496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.arg, frame)
1497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(']')
1498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1499b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('environment.getitem(')
1500b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.node, frame)
1501b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(', ')
1502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.arg, frame)
1503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(')')
1504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Slice(self, node, frame):
1506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.start is not None:
1507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.start, frame)
1508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(':')
1509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.stop is not None:
1510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.stop, frame)
1511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.step is not None:
1512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write(':')
1513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.step, frame)
1514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Filter(self, node, frame):
1516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(self.filters[node.name] + '(')
1517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        func = self.environment.filters.get(node.name)
1518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if func is None:
1519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.fail('no filter named %r' % node.name, node.lineno)
1520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if getattr(func, 'contextfilter', False):
1521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('context, ')
1522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif getattr(func, 'evalcontextfilter', False):
1523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('context.eval_ctx, ')
1524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif getattr(func, 'environmentfilter', False):
1525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('environment, ')
1526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # if the filter node is None we are inside a filter block
1528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        # and want to write to the current buffer
1529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.node is not None:
1530b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(node.node, frame)
1531b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif frame.eval_ctx.volatile:
1532b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('(context.eval_ctx.autoescape and'
1533b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       ' Markup(concat(%s)) or concat(%s))' %
1534b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       (frame.buffer, frame.buffer))
1535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        elif frame.eval_ctx.autoescape:
1536b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('Markup(concat(%s))' % frame.buffer)
1537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('concat(%s)' % frame.buffer)
1539b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.signature(node, frame)
1540b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(')')
1541b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1542b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Test(self, node, frame):
1543b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(self.tests[node.name] + '(')
1544b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if node.name not in self.environment.tests:
1545b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.fail('no test named %r' % node.name, node.lineno)
1546b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.node, frame)
1547b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.signature(node, frame)
1548b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(')')
1549b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_CondExpr(self, node, frame):
1551b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        def write_expr2():
1552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            if node.expr2 is not None:
1553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                return self.visit(node.expr2, frame)
1554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('environment.undefined(%r)' % ('the inline if-'
1555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       'expression on %s evaluated to false and '
1556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                       'no else section was defined.' % self.position(node)))
1557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
155858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.write('(')
155958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.visit(node.expr1, frame)
156058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.write(' if ')
156158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.visit(node.test, frame)
156258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.write(' else ')
156358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        write_expr2()
156458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        self.write(')')
1565b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Call(self, node, frame, forward_caller=False):
1567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if self.environment.sandboxed:
1568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('environment.call(context, ')
1569b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        else:
1570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.write('context.call(')
1571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.node, frame)
1572b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        extra_kwargs = forward_caller and {'caller': 'caller'} or None
1573b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.signature(node, frame, extra_kwargs)
1574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(')')
1575b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Keyword(self, node, frame):
1577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(node.key + '=')
1578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.value, frame)
1579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1580b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    # -- Unused nodes for extensions
1581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_MarkSafe(self, node, frame):
1583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('Markup(')
1584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.expr, frame)
1585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(')')
1586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1587b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_MarkSafeIfAutoescape(self, node, frame):
1588b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('(context.eval_ctx.autoescape and Markup or identity)(')
1589b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit(node.expr, frame)
1590b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(')')
1591b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1592b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_EnvironmentAttribute(self, node, frame):
1593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('environment.' + node.name)
1594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_ExtensionAttribute(self, node, frame):
1596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
1597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_ImportedName(self, node, frame):
1599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(self.import_aliases[node.importname])
1600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_InternalName(self, node, frame):
1602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write(node.name)
1603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_ContextReference(self, node, frame):
1605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.write('context')
1606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Continue(self, node, frame):
1608b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('continue', node)
1609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1610b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Break(self, node, frame):
1611b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('break', node)
1612b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1613b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_Scope(self, node, frame):
1614b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        scope_frame = frame.inner()
1615b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        scope_frame.inspect(node.iter_child_nodes())
1616b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        aliases = self.push_scope(scope_frame)
1617b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pull_locals(scope_frame)
1618b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.blockvisit(node.body, scope_frame)
1619b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.pop_scope(aliases, scope_frame)
1620b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1621b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_EvalContextModifier(self, node, frame):
1622b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for keyword in node.options:
1623b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.writeline('context.eval_ctx.%s = ' % keyword.key)
1624b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(keyword.value, frame)
1625b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            try:
1626b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                val = keyword.value.as_const(frame.eval_ctx)
1627b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            except nodes.Impossible:
1628b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                frame.eval_ctx.volatile = True
1629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            else:
1630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                setattr(frame.eval_ctx, keyword.key, val)
1631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1632b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    def visit_ScopedEvalContextModifier(self, node, frame):
1633b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        old_ctx_name = self.temporary_identifier()
1634b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        safed_ctx = frame.eval_ctx.save()
1635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
1636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.visit_EvalContextModifier(node, frame)
1637b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for child in node.body:
1638b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            self.visit(child, frame)
1639b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        frame.eval_ctx.revert(safed_ctx)
1640b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)
1641