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