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