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