Run `./2to3.py -w jinja2`
[jinja2.git] / jinja2 / compiler.py
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 io import StringIO
12 from itertools import chain
13 from copy import deepcopy
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, is_python_keyword, next
19
20
21 operators = {
22     'eq':       '==',
23     'ne':       '!=',
24     'gt':       '>',
25     'gteq':     '>=',
26     'lt':       '<',
27     'lteq':     '<=',
28     'in':       'in',
29     'notin':    'not in'
30 }
31
32 try:
33     exec('(0 if 0 else 0)')
34 except SyntaxError:
35     have_condexpr = False
36 else:
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
42 if hasattr(dict, 'iteritems'):
43     dict_item_iter = 'iteritems'
44 else:
45     dict_item_iter = 'items'
46
47
48 # does if 0: dummy(x) get us x into the scope?
49 def unoptimize_before_dead_code():
50     x = 42
51     def f():
52         if 0: dummy(x)
53     return f
54 unoptimize_before_dead_code = bool(unoptimize_before_dead_code().__closure__)
55
56
57 def 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
68 def 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, float, complex, str,
73                           range, 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.items():
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
90 def 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
103 class 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):
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         return name in self.declared
135
136     def copy(self):
137         return deepcopy(self)
138
139
140 class Frame(object):
141     """Holds compile time information for us."""
142
143     def __init__(self, eval_ctx, parent=None):
144         self.eval_ctx = eval_ctx
145         self.identifiers = Identifiers()
146
147         # a toplevel frame is the root + soft frames such as if conditions.
148         self.toplevel = False
149
150         # the root frame is basically just the outermost frame, so no if
151         # conditions.  This information is used to optimize inheritance
152         # situations.
153         self.rootlevel = False
154
155         # in some dynamic inheritance situations the compiler needs to add
156         # write tests around output statements.
157         self.require_output_check = parent and parent.require_output_check
158
159         # inside some tags we are using a buffer rather than yield statements.
160         # this for example affects {% filter %} or {% macro %}.  If a frame
161         # is buffered this variable points to the name of the list used as
162         # buffer.
163         self.buffer = None
164
165         # the name of the block we're in, otherwise None.
166         self.block = parent and parent.block or None
167
168         # a set of actually assigned names
169         self.assigned_names = set()
170
171         # the parent of this frame
172         self.parent = parent
173
174         if parent is not None:
175             self.identifiers.declared.update(
176                 parent.identifiers.declared |
177                 parent.identifiers.declared_parameter |
178                 parent.assigned_names
179             )
180             self.identifiers.outer_undeclared.update(
181                 parent.identifiers.undeclared -
182                 self.identifiers.declared
183             )
184             self.buffer = parent.buffer
185
186     def copy(self):
187         """Create a copy of the current one."""
188         rv = object.__new__(self.__class__)
189         rv.__dict__.update(self.__dict__)
190         rv.identifiers = object.__new__(self.identifiers.__class__)
191         rv.identifiers.__dict__.update(self.identifiers.__dict__)
192         return rv
193
194     def inspect(self, nodes):
195         """Walk the node and check for identifiers.  If the scope is hard (eg:
196         enforce on a python level) overrides from outer scopes are tracked
197         differently.
198         """
199         visitor = FrameIdentifierVisitor(self.identifiers)
200         for node in nodes:
201             visitor.visit(node)
202
203     def find_shadowed(self, extra=()):
204         """Find all the shadowed names.  extra is an iterable of variables
205         that may be defined with `add_special` which may occour scoped.
206         """
207         i = self.identifiers
208         return (i.declared | i.outer_undeclared) & \
209                (i.declared_locally | i.declared_parameter) | \
210                set(x for x in extra if i.is_declared(x))
211
212     def inner(self):
213         """Return an inner frame."""
214         return Frame(self.eval_ctx, self)
215
216     def soft(self):
217         """Return a soft frame.  A soft frame may not be modified as
218         standalone thing as it shares the resources with the frame it
219         was created of, but it's not a rootlevel frame any longer.
220         """
221         rv = self.copy()
222         rv.rootlevel = False
223         return rv
224
225     __copy__ = copy
226
227
228 class VisitorExit(RuntimeError):
229     """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
230
231
232 class DependencyFinderVisitor(NodeVisitor):
233     """A visitor that collects filter and test calls."""
234
235     def __init__(self):
236         self.filters = set()
237         self.tests = set()
238
239     def visit_Filter(self, node):
240         self.generic_visit(node)
241         self.filters.add(node.name)
242
243     def visit_Test(self, node):
244         self.generic_visit(node)
245         self.tests.add(node.name)
246
247     def visit_Block(self, node):
248         """Stop visiting at blocks."""
249
250
251 class UndeclaredNameVisitor(NodeVisitor):
252     """A visitor that checks if a name is accessed without being
253     declared.  This is different from the frame visitor as it will
254     not stop at closure frames.
255     """
256
257     def __init__(self, names):
258         self.names = set(names)
259         self.undeclared = set()
260
261     def visit_Name(self, node):
262         if node.ctx == 'load' and node.name in self.names:
263             self.undeclared.add(node.name)
264             if self.undeclared == self.names:
265                 raise VisitorExit()
266         else:
267             self.names.discard(node.name)
268
269     def visit_Block(self, node):
270         """Stop visiting a blocks."""
271
272
273 class FrameIdentifierVisitor(NodeVisitor):
274     """A visitor for `Frame.inspect`."""
275
276     def __init__(self, identifiers):
277         self.identifiers = identifiers
278
279     def visit_Name(self, node):
280         """All assignments to names go through this function."""
281         if node.ctx == 'store':
282             self.identifiers.declared_locally.add(node.name)
283         elif node.ctx == 'param':
284             self.identifiers.declared_parameter.add(node.name)
285         elif node.ctx == 'load' and not \
286              self.identifiers.is_declared(node.name):
287             self.identifiers.undeclared.add(node.name)
288
289     def visit_If(self, node):
290         self.visit(node.test)
291         real_identifiers = self.identifiers
292
293         old_names = real_identifiers.declared_locally | \
294                     real_identifiers.declared_parameter
295
296         def inner_visit(nodes):
297             if not nodes:
298                 return set()
299             self.identifiers = real_identifiers.copy()
300             for subnode in nodes:
301                 self.visit(subnode)
302             rv = self.identifiers.declared_locally - old_names
303             # we have to remember the undeclared variables of this branch
304             # because we will have to pull them.
305             real_identifiers.undeclared.update(self.identifiers.undeclared)
306             self.identifiers = real_identifiers
307             return rv
308
309         body = inner_visit(node.body)
310         else_ = inner_visit(node.else_ or ())
311
312         # the differences between the two branches are also pulled as
313         # undeclared variables
314         real_identifiers.undeclared.update(body.symmetric_difference(else_) -
315                                            real_identifiers.declared)
316
317         # remember those that are declared.
318         real_identifiers.declared_locally.update(body | else_)
319
320     def visit_Macro(self, node):
321         self.identifiers.declared_locally.add(node.name)
322
323     def visit_Import(self, node):
324         self.generic_visit(node)
325         self.identifiers.declared_locally.add(node.target)
326
327     def visit_FromImport(self, node):
328         self.generic_visit(node)
329         for name in node.names:
330             if isinstance(name, tuple):
331                 self.identifiers.declared_locally.add(name[1])
332             else:
333                 self.identifiers.declared_locally.add(name)
334
335     def visit_Assign(self, node):
336         """Visit assignments in the correct order."""
337         self.visit(node.node)
338         self.visit(node.target)
339
340     def visit_For(self, node):
341         """Visiting stops at for blocks.  However the block sequence
342         is visited as part of the outer scope.
343         """
344         self.visit(node.iter)
345
346     def visit_CallBlock(self, node):
347         self.visit(node.call)
348
349     def visit_FilterBlock(self, node):
350         self.visit(node.filter)
351
352     def visit_Scope(self, node):
353         """Stop visiting at scopes."""
354
355     def visit_Block(self, node):
356         """Stop visiting at blocks."""
357
358
359 class CompilerExit(Exception):
360     """Raised if the compiler encountered a situation where it just
361     doesn't make sense to further process the code.  Any block that
362     raises such an exception is not further processed.
363     """
364
365
366 class CodeGenerator(NodeVisitor):
367
368     def __init__(self, environment, name, filename, stream=None,
369                  defer_init=False):
370         if stream is None:
371             stream = StringIO()
372         self.environment = environment
373         self.name = name
374         self.filename = filename
375         self.stream = stream
376         self.created_block_context = False
377         self.defer_init = defer_init
378
379         # aliases for imports
380         self.import_aliases = {}
381
382         # a registry for all blocks.  Because blocks are moved out
383         # into the global python scope they are registered here
384         self.blocks = {}
385
386         # the number of extends statements so far
387         self.extends_so_far = 0
388
389         # some templates have a rootlevel extends.  In this case we
390         # can safely assume that we're a child template and do some
391         # more optimizations.
392         self.has_known_extends = False
393
394         # the current line number
395         self.code_lineno = 1
396
397         # registry of all filters and tests (global, not block local)
398         self.tests = {}
399         self.filters = {}
400
401         # the debug information
402         self.debug_info = []
403         self._write_debug_info = None
404
405         # the number of new lines before the next write()
406         self._new_lines = 0
407
408         # the line number of the last written statement
409         self._last_line = 0
410
411         # true if nothing was written so far.
412         self._first_write = True
413
414         # used by the `temporary_identifier` method to get new
415         # unique, temporary identifier
416         self._last_identifier = 0
417
418         # the current indentation
419         self._indentation = 0
420
421     # -- Various compilation helpers
422
423     def fail(self, msg, lineno):
424         """Fail with a :exc:`TemplateAssertionError`."""
425         raise TemplateAssertionError(msg, lineno, self.name, self.filename)
426
427     def temporary_identifier(self):
428         """Get a new unique identifier."""
429         self._last_identifier += 1
430         return 't_%d' % self._last_identifier
431
432     def buffer(self, frame):
433         """Enable buffering for the frame from that point onwards."""
434         frame.buffer = self.temporary_identifier()
435         self.writeline('%s = []' % frame.buffer)
436
437     def return_buffer_contents(self, frame):
438         """Return the buffer contents of the frame."""
439         if frame.eval_ctx.volatile:
440             self.writeline('if context.eval_ctx.autoescape:')
441             self.indent()
442             self.writeline('return Markup(concat(%s))' % frame.buffer)
443             self.outdent()
444             self.writeline('else:')
445             self.indent()
446             self.writeline('return concat(%s)' % frame.buffer)
447             self.outdent()
448         elif frame.eval_ctx.autoescape:
449             self.writeline('return Markup(concat(%s))' % frame.buffer)
450         else:
451             self.writeline('return concat(%s)' % frame.buffer)
452
453     def indent(self):
454         """Indent by one."""
455         self._indentation += 1
456
457     def outdent(self, step=1):
458         """Outdent by step."""
459         self._indentation -= step
460
461     def start_write(self, frame, node=None):
462         """Yield or write into the frame buffer."""
463         if frame.buffer is None:
464             self.writeline('yield ', node)
465         else:
466             self.writeline('%s.append(' % frame.buffer, node)
467
468     def end_write(self, frame):
469         """End the writing process started by `start_write`."""
470         if frame.buffer is not None:
471             self.write(')')
472
473     def simple_write(self, s, frame, node=None):
474         """Simple shortcut for start_write + write + end_write."""
475         self.start_write(frame, node)
476         self.write(s)
477         self.end_write(frame)
478
479     def blockvisit(self, nodes, frame):
480         """Visit a list of nodes as block in a frame.  If the current frame
481         is no buffer a dummy ``if 0: yield None`` is written automatically
482         unless the force_generator parameter is set to False.
483         """
484         if frame.buffer is None:
485             self.writeline('if 0: yield None')
486         else:
487             self.writeline('pass')
488         try:
489             for node in nodes:
490                 self.visit(node, frame)
491         except CompilerExit:
492             pass
493
494     def write(self, x):
495         """Write a string into the output stream."""
496         if self._new_lines:
497             if not self._first_write:
498                 self.stream.write('\n' * self._new_lines)
499                 self.code_lineno += self._new_lines
500                 if self._write_debug_info is not None:
501                     self.debug_info.append((self._write_debug_info,
502                                             self.code_lineno))
503                     self._write_debug_info = None
504             self._first_write = False
505             self.stream.write('    ' * self._indentation)
506             self._new_lines = 0
507         self.stream.write(x)
508
509     def writeline(self, x, node=None, extra=0):
510         """Combination of newline and write."""
511         self.newline(node, extra)
512         self.write(x)
513
514     def newline(self, node=None, extra=0):
515         """Add one or more newlines before the next write."""
516         self._new_lines = max(self._new_lines, 1 + extra)
517         if node is not None and node.lineno != self._last_line:
518             self._write_debug_info = node.lineno
519             self._last_line = node.lineno
520
521     def signature(self, node, frame, extra_kwargs=None):
522         """Writes a function call to the stream for the current node.
523         A leading comma is added automatically.  The extra keyword
524         arguments may not include python keywords otherwise a syntax
525         error could occour.  The extra keyword arguments should be given
526         as python dict.
527         """
528         # if any of the given keyword arguments is a python keyword
529         # we have to make sure that no invalid call is created.
530         kwarg_workaround = False
531         for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
532             if is_python_keyword(kwarg):
533                 kwarg_workaround = True
534                 break
535
536         for arg in node.args:
537             self.write(', ')
538             self.visit(arg, frame)
539
540         if not kwarg_workaround:
541             for kwarg in node.kwargs:
542                 self.write(', ')
543                 self.visit(kwarg, frame)
544             if extra_kwargs is not None:
545                 for key, value in extra_kwargs.items():
546                     self.write(', %s=%s' % (key, value))
547         if node.dyn_args:
548             self.write(', *')
549             self.visit(node.dyn_args, frame)
550
551         if kwarg_workaround:
552             if node.dyn_kwargs is not None:
553                 self.write(', **dict({')
554             else:
555                 self.write(', **{')
556             for kwarg in node.kwargs:
557                 self.write('%r: ' % kwarg.key)
558                 self.visit(kwarg.value, frame)
559                 self.write(', ')
560             if extra_kwargs is not None:
561                 for key, value in extra_kwargs.items():
562                     self.write('%r: %s, ' % (key, value))
563             if node.dyn_kwargs is not None:
564                 self.write('}, **')
565                 self.visit(node.dyn_kwargs, frame)
566                 self.write(')')
567             else:
568                 self.write('}')
569
570         elif node.dyn_kwargs is not None:
571             self.write(', **')
572             self.visit(node.dyn_kwargs, frame)
573
574     def pull_locals(self, frame):
575         """Pull all the references identifiers into the local scope."""
576         for name in frame.identifiers.undeclared:
577             self.writeline('l_%s = context.resolve(%r)' % (name, name))
578
579     def pull_dependencies(self, nodes):
580         """Pull all the dependencies."""
581         visitor = DependencyFinderVisitor()
582         for node in nodes:
583             visitor.visit(node)
584         for dependency in 'filters', 'tests':
585             mapping = getattr(self, dependency)
586             for name in getattr(visitor, dependency):
587                 if name not in mapping:
588                     mapping[name] = self.temporary_identifier()
589                 self.writeline('%s = environment.%s[%r]' %
590                                (mapping[name], dependency, name))
591
592     def unoptimize_scope(self, frame):
593         """Disable Python optimizations for the frame."""
594         # XXX: this is not that nice but it has no real overhead.  It
595         # mainly works because python finds the locals before dead code
596         # is removed.  If that breaks we have to add a dummy function
597         # that just accepts the arguments and does nothing.
598         if frame.identifiers.declared:
599             self.writeline('%sdummy(%s)' % (
600                 unoptimize_before_dead_code and 'if 0: ' or '',
601                 ', '.join('l_' + name for name in frame.identifiers.declared)
602             ))
603
604     def push_scope(self, frame, extra_vars=()):
605         """This function returns all the shadowed variables in a dict
606         in the form name: alias and will write the required assignments
607         into the current scope.  No indentation takes place.
608
609         This also predefines locally declared variables from the loop
610         body because under some circumstances it may be the case that
611
612         `extra_vars` is passed to `Frame.find_shadowed`.
613         """
614         aliases = {}
615         for name in frame.find_shadowed(extra_vars):
616             aliases[name] = ident = self.temporary_identifier()
617             self.writeline('%s = l_%s' % (ident, name))
618         to_declare = set()
619         for name in frame.identifiers.declared_locally:
620             if name not in aliases:
621                 to_declare.add('l_' + name)
622         if to_declare:
623             self.writeline(' = '.join(to_declare) + ' = missing')
624         return aliases
625
626     def pop_scope(self, aliases, frame):
627         """Restore all aliases and delete unused variables."""
628         for name, alias in aliases.items():
629             self.writeline('l_%s = %s' % (name, alias))
630         to_delete = set()
631         for name in frame.identifiers.declared_locally:
632             if name not in aliases:
633                 to_delete.add('l_' + name)
634         if to_delete:
635             # we cannot use the del statement here because enclosed
636             # scopes can trigger a SyntaxError:
637             #   a = 42; b = lambda: a; del a
638             self.writeline(' = '.join(to_delete) + ' = missing')
639
640     def function_scoping(self, node, frame, children=None,
641                          find_special=True):
642         """In Jinja a few statements require the help of anonymous
643         functions.  Those are currently macros and call blocks and in
644         the future also recursive loops.  As there is currently
645         technical limitation that doesn't allow reading and writing a
646         variable in a scope where the initial value is coming from an
647         outer scope, this function tries to fall back with a common
648         error message.  Additionally the frame passed is modified so
649         that the argumetns are collected and callers are looked up.
650
651         This will return the modified frame.
652         """
653         # we have to iterate twice over it, make sure that works
654         if children is None:
655             children = node.iter_child_nodes()
656         children = list(children)
657         func_frame = frame.inner()
658         func_frame.inspect(children)
659
660         # variables that are undeclared (accessed before declaration) and
661         # declared locally *and* part of an outside scope raise a template
662         # assertion error. Reason: we can't generate reasonable code from
663         # it without aliasing all the variables.
664         # this could be fixed in Python 3 where we have the nonlocal
665         # keyword or if we switch to bytecode generation
666         overriden_closure_vars = (
667             func_frame.identifiers.undeclared &
668             func_frame.identifiers.declared &
669             (func_frame.identifiers.declared_locally |
670              func_frame.identifiers.declared_parameter)
671         )
672         if overriden_closure_vars:
673             self.fail('It\'s not possible to set and access variables '
674                       'derived from an outer scope! (affects: %s)' %
675                       ', '.join(sorted(overriden_closure_vars)), node.lineno)
676
677         # remove variables from a closure from the frame's undeclared
678         # identifiers.
679         func_frame.identifiers.undeclared -= (
680             func_frame.identifiers.undeclared &
681             func_frame.identifiers.declared
682         )
683
684         # no special variables for this scope, abort early
685         if not find_special:
686             return func_frame
687
688         func_frame.accesses_kwargs = False
689         func_frame.accesses_varargs = False
690         func_frame.accesses_caller = False
691         func_frame.arguments = args = ['l_' + x.name for x in node.args]
692
693         undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
694
695         if 'caller' in undeclared:
696             func_frame.accesses_caller = True
697             func_frame.identifiers.add_special('caller')
698             args.append('l_caller')
699         if 'kwargs' in undeclared:
700             func_frame.accesses_kwargs = True
701             func_frame.identifiers.add_special('kwargs')
702             args.append('l_kwargs')
703         if 'varargs' in undeclared:
704             func_frame.accesses_varargs = True
705             func_frame.identifiers.add_special('varargs')
706             args.append('l_varargs')
707         return func_frame
708
709     def macro_body(self, node, frame, children=None):
710         """Dump the function def of a macro or call block."""
711         frame = self.function_scoping(node, frame, children)
712         # macros are delayed, they never require output checks
713         frame.require_output_check = False
714         args = frame.arguments
715         # XXX: this is an ugly fix for the loop nesting bug
716         # (tests.test_old_bugs.test_loop_call_bug).  This works around
717         # a identifier nesting problem we have in general.  It's just more
718         # likely to happen in loops which is why we work around it.  The
719         # real solution would be "nonlocal" all the identifiers that are
720         # leaking into a new python frame and might be used both unassigned
721         # and assigned.
722         if 'loop' in frame.identifiers.declared:
723             args = args + ['l_loop=l_loop']
724         self.writeline('def macro(%s):' % ', '.join(args), node)
725         self.indent()
726         self.buffer(frame)
727         self.pull_locals(frame)
728         self.blockvisit(node.body, frame)
729         self.return_buffer_contents(frame)
730         self.outdent()
731         return frame
732
733     def macro_def(self, node, frame):
734         """Dump the macro definition for the def created by macro_body."""
735         arg_tuple = ', '.join(repr(x.name) for x in node.args)
736         name = getattr(node, 'name', None)
737         if len(node.args) == 1:
738             arg_tuple += ','
739         self.write('Macro(environment, macro, %r, (%s), (' %
740                    (name, arg_tuple))
741         for arg in node.defaults:
742             self.visit(arg, frame)
743             self.write(', ')
744         self.write('), %r, %r, %r)' % (
745             bool(frame.accesses_kwargs),
746             bool(frame.accesses_varargs),
747             bool(frame.accesses_caller)
748         ))
749
750     def position(self, node):
751         """Return a human readable position for the node."""
752         rv = 'line %d' % node.lineno
753         if self.name is not None:
754             rv += ' in ' + repr(self.name)
755         return rv
756
757     # -- Statement Visitors
758
759     def visit_Template(self, node, frame=None):
760         assert frame is None, 'no root frame allowed'
761         eval_ctx = EvalContext(self.environment, self.name)
762
763         from jinja2.runtime import __all__ as exported
764         self.writeline('from __future__ import division')
765         self.writeline('from jinja2.runtime import ' + ', '.join(exported))
766         if not unoptimize_before_dead_code:
767             self.writeline('dummy = lambda *x: None')
768
769         # if we want a deferred initialization we cannot move the
770         # environment into a local name
771         envenv = not self.defer_init and ', environment=environment' or ''
772
773         # do we have an extends tag at all?  If not, we can save some
774         # overhead by just not processing any inheritance code.
775         have_extends = node.find(nodes.Extends) is not None
776
777         # find all blocks
778         for block in node.find_all(nodes.Block):
779             if block.name in self.blocks:
780                 self.fail('block %r defined twice' % block.name, block.lineno)
781             self.blocks[block.name] = block
782
783         # find all imports and import them
784         for import_ in node.find_all(nodes.ImportedName):
785             if import_.importname not in self.import_aliases:
786                 imp = import_.importname
787                 self.import_aliases[imp] = alias = self.temporary_identifier()
788                 if '.' in imp:
789                     module, obj = imp.rsplit('.', 1)
790                     self.writeline('from %s import %s as %s' %
791                                    (module, obj, alias))
792                 else:
793                     self.writeline('import %s as %s' % (imp, alias))
794
795         # add the load name
796         self.writeline('name = %r' % self.name)
797
798         # generate the root render function.
799         self.writeline('def root(context%s):' % envenv, extra=1)
800
801         # process the root
802         frame = Frame(eval_ctx)
803         frame.inspect(node.body)
804         frame.toplevel = frame.rootlevel = True
805         frame.require_output_check = have_extends and not self.has_known_extends
806         self.indent()
807         if have_extends:
808             self.writeline('parent_template = None')
809         if 'self' in find_undeclared(node.body, ('self',)):
810             frame.identifiers.add_special('self')
811             self.writeline('l_self = TemplateReference(context)')
812         self.pull_locals(frame)
813         self.pull_dependencies(node.body)
814         self.blockvisit(node.body, frame)
815         self.outdent()
816
817         # make sure that the parent root is called.
818         if have_extends:
819             if not self.has_known_extends:
820                 self.indent()
821                 self.writeline('if parent_template is not None:')
822             self.indent()
823             self.writeline('for event in parent_template.'
824                            'root_render_func(context):')
825             self.indent()
826             self.writeline('yield event')
827             self.outdent(2 + (not self.has_known_extends))
828
829         # at this point we now have the blocks collected and can visit them too.
830         for name, block in self.blocks.items():
831             block_frame = Frame(eval_ctx)
832             block_frame.inspect(block.body)
833             block_frame.block = name
834             self.writeline('def block_%s(context%s):' % (name, envenv),
835                            block, 1)
836             self.indent()
837             undeclared = find_undeclared(block.body, ('self', 'super'))
838             if 'self' in undeclared:
839                 block_frame.identifiers.add_special('self')
840                 self.writeline('l_self = TemplateReference(context)')
841             if 'super' in undeclared:
842                 block_frame.identifiers.add_special('super')
843                 self.writeline('l_super = context.super(%r, '
844                                'block_%s)' % (name, name))
845             self.pull_locals(block_frame)
846             self.pull_dependencies(block.body)
847             self.blockvisit(block.body, block_frame)
848             self.outdent()
849
850         self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
851                                                    for x in self.blocks),
852                        extra=1)
853
854         # add a function that returns the debug info
855         self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
856                                                     in self.debug_info))
857
858     def visit_Block(self, node, frame):
859         """Call a block and register it for the template."""
860         level = 1
861         if frame.toplevel:
862             # if we know that we are a child template, there is no need to
863             # check if we are one
864             if self.has_known_extends:
865                 return
866             if self.extends_so_far > 0:
867                 self.writeline('if parent_template is None:')
868                 self.indent()
869                 level += 1
870         context = node.scoped and 'context.derived(locals())' or 'context'
871         self.writeline('for event in context.blocks[%r][0](%s):' % (
872                        node.name, context), node)
873         self.indent()
874         self.simple_write('event', frame)
875         self.outdent(level)
876
877     def visit_Extends(self, node, frame):
878         """Calls the extender."""
879         if not frame.toplevel:
880             self.fail('cannot use extend from a non top-level scope',
881                       node.lineno)
882
883         # if the number of extends statements in general is zero so
884         # far, we don't have to add a check if something extended
885         # the template before this one.
886         if self.extends_so_far > 0:
887
888             # if we have a known extends we just add a template runtime
889             # error into the generated code.  We could catch that at compile
890             # time too, but i welcome it not to confuse users by throwing the
891             # same error at different times just "because we can".
892             if not self.has_known_extends:
893                 self.writeline('if parent_template is not None:')
894                 self.indent()
895             self.writeline('raise TemplateRuntimeError(%r)' %
896                            'extended multiple times')
897             self.outdent()
898
899             # if we have a known extends already we don't need that code here
900             # as we know that the template execution will end here.
901             if self.has_known_extends:
902                 raise CompilerExit()
903
904         self.writeline('parent_template = environment.get_template(', node)
905         self.visit(node.template, frame)
906         self.write(', %r)' % self.name)
907         self.writeline('for name, parent_block in parent_template.'
908                        'blocks.%s():' % dict_item_iter)
909         self.indent()
910         self.writeline('context.blocks.setdefault(name, []).'
911                        'append(parent_block)')
912         self.outdent()
913
914         # if this extends statement was in the root level we can take
915         # advantage of that information and simplify the generated code
916         # in the top level from this point onwards
917         if frame.rootlevel:
918             self.has_known_extends = True
919
920         # and now we have one more
921         self.extends_so_far += 1
922
923     def visit_Include(self, node, frame):
924         """Handles includes."""
925         if node.with_context:
926             self.unoptimize_scope(frame)
927         if node.ignore_missing:
928             self.writeline('try:')
929             self.indent()
930
931         func_name = 'get_or_select_template'
932         if isinstance(node.template, nodes.Const):
933             if isinstance(node.template.value, str):
934                 func_name = 'get_template'
935             elif isinstance(node.template.value, (tuple, list)):
936                 func_name = 'select_template'
937         elif isinstance(node.template, (nodes.Tuple, nodes.List)):
938             func_name = 'select_template'
939
940         self.writeline('template = environment.%s(' % func_name, node)
941         self.visit(node.template, frame)
942         self.write(', %r)' % self.name)
943         if node.ignore_missing:
944             self.outdent()
945             self.writeline('except TemplateNotFound:')
946             self.indent()
947             self.writeline('pass')
948             self.outdent()
949             self.writeline('else:')
950             self.indent()
951
952         if node.with_context:
953             self.writeline('for event in template.root_render_func('
954                            'template.new_context(context.parent, True, '
955                            'locals())):')
956         else:
957             self.writeline('for event in template.module._body_stream:')
958
959         self.indent()
960         self.simple_write('event', frame)
961         self.outdent()
962
963         if node.ignore_missing:
964             self.outdent()
965
966     def visit_Import(self, node, frame):
967         """Visit regular imports."""
968         if node.with_context:
969             self.unoptimize_scope(frame)
970         self.writeline('l_%s = ' % node.target, node)
971         if frame.toplevel:
972             self.write('context.vars[%r] = ' % node.target)
973         self.write('environment.get_template(')
974         self.visit(node.template, frame)
975         self.write(', %r).' % self.name)
976         if node.with_context:
977             self.write('make_module(context.parent, True, locals())')
978         else:
979             self.write('module')
980         if frame.toplevel and not node.target.startswith('_'):
981             self.writeline('context.exported_vars.discard(%r)' % node.target)
982         frame.assigned_names.add(node.target)
983
984     def visit_FromImport(self, node, frame):
985         """Visit named imports."""
986         self.newline(node)
987         self.write('included_template = environment.get_template(')
988         self.visit(node.template, frame)
989         self.write(', %r).' % self.name)
990         if node.with_context:
991             self.write('make_module(context.parent, True)')
992         else:
993             self.write('module')
994
995         var_names = []
996         discarded_names = []
997         for name in node.names:
998             if isinstance(name, tuple):
999                 name, alias = name
1000             else:
1001                 alias = name
1002             self.writeline('l_%s = getattr(included_template, '
1003                            '%r, missing)' % (alias, name))
1004             self.writeline('if l_%s is missing:' % alias)
1005             self.indent()
1006             self.writeline('l_%s = environment.undefined(%r %% '
1007                            'included_template.__name__, '
1008                            'name=%r)' %
1009                            (alias, 'the template %%r (imported on %s) does '
1010                            'not export the requested name %s' % (
1011                                 self.position(node),
1012                                 repr(name)
1013                            ), name))
1014             self.outdent()
1015             if frame.toplevel:
1016                 var_names.append(alias)
1017                 if not alias.startswith('_'):
1018                     discarded_names.append(alias)
1019             frame.assigned_names.add(alias)
1020
1021         if var_names:
1022             if len(var_names) == 1:
1023                 name = var_names[0]
1024                 self.writeline('context.vars[%r] = l_%s' % (name, name))
1025             else:
1026                 self.writeline('context.vars.update({%s})' % ', '.join(
1027                     '%r: l_%s' % (name, name) for name in var_names
1028                 ))
1029         if discarded_names:
1030             if len(discarded_names) == 1:
1031                 self.writeline('context.exported_vars.discard(%r)' %
1032                                discarded_names[0])
1033             else:
1034                 self.writeline('context.exported_vars.difference_'
1035                                'update((%s))' % ', '.join(map(repr, discarded_names)))
1036
1037     def visit_For(self, node, frame):
1038         # when calculating the nodes for the inner frame we have to exclude
1039         # the iterator contents from it
1040         children = node.iter_child_nodes(exclude=('iter',))
1041         if node.recursive:
1042             loop_frame = self.function_scoping(node, frame, children,
1043                                                find_special=False)
1044         else:
1045             loop_frame = frame.inner()
1046             loop_frame.inspect(children)
1047
1048         # try to figure out if we have an extended loop.  An extended loop
1049         # is necessary if the loop is in recursive mode if the special loop
1050         # variable is accessed in the body.
1051         extended_loop = node.recursive or 'loop' in \
1052                         find_undeclared(node.iter_child_nodes(
1053                             only=('body',)), ('loop',))
1054
1055         # if we don't have an recursive loop we have to find the shadowed
1056         # variables at that point.  Because loops can be nested but the loop
1057         # variable is a special one we have to enforce aliasing for it.
1058         if not node.recursive:
1059             aliases = self.push_scope(loop_frame, ('loop',))
1060
1061         # otherwise we set up a buffer and add a function def
1062         else:
1063             self.writeline('def loop(reciter, loop_render_func):', node)
1064             self.indent()
1065             self.buffer(loop_frame)
1066             aliases = {}
1067
1068         # make sure the loop variable is a special one and raise a template
1069         # assertion error if a loop tries to write to loop
1070         if extended_loop:
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(', recurse=loop_render_func):')
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: str(self.environment.finalize(x))
1220         else:
1221             finalize = str
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(map(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         if not have_condexpr:
1559             self.write('((')
1560             self.visit(node.test, frame)
1561             self.write(') and (')
1562             self.visit(node.expr1, frame)
1563             self.write(',) or (')
1564             write_expr2()
1565             self.write(',))[0]')
1566         else:
1567             self.write('(')
1568             self.visit(node.expr1, frame)
1569             self.write(' if ')
1570             self.visit(node.test, frame)
1571             self.write(' else ')
1572             write_expr2()
1573             self.write(')')
1574
1575     def visit_Call(self, node, frame, forward_caller=False):
1576         if self.environment.sandboxed:
1577             self.write('environment.call(context, ')
1578         else:
1579             self.write('context.call(')
1580         self.visit(node.node, frame)
1581         extra_kwargs = forward_caller and {'caller': 'caller'} or None
1582         self.signature(node, frame, extra_kwargs)
1583         self.write(')')
1584
1585     def visit_Keyword(self, node, frame):
1586         self.write(node.key + '=')
1587         self.visit(node.value, frame)
1588
1589     # -- Unused nodes for extensions
1590
1591     def visit_MarkSafe(self, node, frame):
1592         self.write('Markup(')
1593         self.visit(node.expr, frame)
1594         self.write(')')
1595
1596     def visit_MarkSafeIfAutoescape(self, node, frame):
1597         self.write('(context.eval_ctx.autoescape and Markup or identity)(')
1598         self.visit(node.expr, frame)
1599         self.write(')')
1600
1601     def visit_EnvironmentAttribute(self, node, frame):
1602         self.write('environment.' + node.name)
1603
1604     def visit_ExtensionAttribute(self, node, frame):
1605         self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
1606
1607     def visit_ImportedName(self, node, frame):
1608         self.write(self.import_aliases[node.importname])
1609
1610     def visit_InternalName(self, node, frame):
1611         self.write(node.name)
1612
1613     def visit_ContextReference(self, node, frame):
1614         self.write('context')
1615
1616     def visit_Continue(self, node, frame):
1617         self.writeline('continue', node)
1618
1619     def visit_Break(self, node, frame):
1620         self.writeline('break', node)
1621
1622     def visit_Scope(self, node, frame):
1623         scope_frame = frame.inner()
1624         scope_frame.inspect(node.iter_child_nodes())
1625         aliases = self.push_scope(scope_frame)
1626         self.pull_locals(scope_frame)
1627         self.blockvisit(node.body, scope_frame)
1628         self.pop_scope(aliases, scope_frame)
1629
1630     def visit_EvalContextModifier(self, node, frame):
1631         for keyword in node.options:
1632             self.writeline('context.eval_ctx.%s = ' % keyword.key)
1633             self.visit(keyword.value, frame)
1634             try:
1635                 val = keyword.value.as_const(frame.eval_ctx)
1636             except nodes.Impossible:
1637                 frame.eval_ctx.volatile = True
1638             else:
1639                 setattr(frame.eval_ctx, keyword.key, val)
1640
1641     def visit_ScopedEvalContextModifier(self, node, frame):
1642         old_ctx_name = self.temporary_identifier()
1643         safed_ctx = frame.eval_ctx.save()
1644         self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
1645         self.visit_EvalContextModifier(node, frame)
1646         for child in node.body:
1647             self.visit(child, frame)
1648         frame.eval_ctx.revert(safed_ctx)
1649         self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)