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