a6f26a59219558333ef140a3b8f90c6d399474ac
[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
360         # aliases for imports
361         self.import_aliases = {}
362
363         # a registry for all blocks.  Because blocks are moved out
364         # into the global python scope they are registered here
365         self.blocks = {}
366
367         # the number of extends statements so far
368         self.extends_so_far = 0
369
370         # some templates have a rootlevel extends.  In this case we
371         # can safely assume that we're a child template and do some
372         # more optimizations.
373         self.has_known_extends = False
374
375         # the current line number
376         self.code_lineno = 1
377
378         # registry of all filters and tests (global, not block local)
379         self.tests = {}
380         self.filters = {}
381
382         # the debug information
383         self.debug_info = []
384         self._write_debug_info = None
385
386         # the number of new lines before the next write()
387         self._new_lines = 0
388
389         # the line number of the last written statement
390         self._last_line = 0
391
392         # true if nothing was written so far.
393         self._first_write = True
394
395         # used by the `temporary_identifier` method to get new
396         # unique, temporary identifier
397         self._last_identifier = 0
398
399         # the current indentation
400         self._indentation = 0
401
402     # -- Various compilation helpers
403
404     def fail(self, msg, lineno):
405         """Fail with a `TemplateAssertionError`."""
406         raise TemplateAssertionError(msg, lineno, self.name, self.filename)
407
408     def temporary_identifier(self):
409         """Get a new unique identifier."""
410         self._last_identifier += 1
411         return 't_%d' % self._last_identifier
412
413     def buffer(self, frame):
414         """Enable buffering for the frame from that point onwards."""
415         frame.buffer = self.temporary_identifier()
416         self.writeline('%s = []' % frame.buffer)
417
418     def return_buffer_contents(self, frame):
419         """Return the buffer contents of the frame."""
420         if self.environment.autoescape:
421             self.writeline('return Markup(concat(%s))' % frame.buffer)
422         else:
423             self.writeline('return concat(%s)' % frame.buffer)
424
425     def indent(self):
426         """Indent by one."""
427         self._indentation += 1
428
429     def outdent(self, step=1):
430         """Outdent by step."""
431         self._indentation -= step
432
433     def start_write(self, frame, node=None):
434         """Yield or write into the frame buffer."""
435         if frame.buffer is None:
436             self.writeline('yield ', node)
437         else:
438             self.writeline('%s.append(' % frame.buffer, node)
439
440     def end_write(self, frame):
441         """End the writing process started by `start_write`."""
442         if frame.buffer is not None:
443             self.write(')')
444
445     def simple_write(self, s, frame, node=None):
446         """Simple shortcut for start_write + write + end_write."""
447         self.start_write(frame, node)
448         self.write(s)
449         self.end_write(frame)
450
451     def blockvisit(self, nodes, frame):
452         """Visit a list of nodes as block in a frame.  If the current frame
453         is no buffer a dummy ``if 0: yield None`` is written automatically
454         unless the force_generator parameter is set to False.
455         """
456         if frame.buffer is None:
457             self.writeline('if 0: yield None')
458         else:
459             self.writeline('pass')
460         try:
461             for node in nodes:
462                 self.visit(node, frame)
463         except CompilerExit:
464             pass
465
466     def write(self, x):
467         """Write a string into the output stream."""
468         if self._new_lines:
469             if not self._first_write:
470                 self.stream.write('\n' * self._new_lines)
471                 self.code_lineno += self._new_lines
472                 if self._write_debug_info is not None:
473                     self.debug_info.append((self._write_debug_info,
474                                             self.code_lineno))
475                     self._write_debug_info = None
476             self._first_write = False
477             self.stream.write('    ' * self._indentation)
478             self._new_lines = 0
479         self.stream.write(x)
480
481     def writeline(self, x, node=None, extra=0):
482         """Combination of newline and write."""
483         self.newline(node, extra)
484         self.write(x)
485
486     def newline(self, node=None, extra=0):
487         """Add one or more newlines before the next write."""
488         self._new_lines = max(self._new_lines, 1 + extra)
489         if node is not None and node.lineno != self._last_line:
490             self._write_debug_info = node.lineno
491             self._last_line = node.lineno
492
493     def signature(self, node, frame, extra_kwargs=None):
494         """Writes a function call to the stream for the current node.
495         A leading comma is added automatically.  The extra keyword
496         arguments may not include python keywords otherwise a syntax
497         error could occour.  The extra keyword arguments should be given
498         as python dict.
499         """
500         # if any of the given keyword arguments is a python keyword
501         # we have to make sure that no invalid call is created.
502         kwarg_workaround = False
503         for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
504             if is_python_keyword(kwarg):
505                 kwarg_workaround = True
506                 break
507
508         for arg in node.args:
509             self.write(', ')
510             self.visit(arg, frame)
511
512         if not kwarg_workaround:
513             for kwarg in node.kwargs:
514                 self.write(', ')
515                 self.visit(kwarg, frame)
516             if extra_kwargs is not None:
517                 for key, value in extra_kwargs.iteritems():
518                     self.write(', %s=%s' % (key, value))
519         if node.dyn_args:
520             self.write(', *')
521             self.visit(node.dyn_args, frame)
522
523         if kwarg_workaround:
524             if node.dyn_kwargs is not None:
525                 self.write(', **dict({')
526             else:
527                 self.write(', **{')
528             for kwarg in node.kwargs:
529                 self.write('%r: ' % kwarg.key)
530                 self.visit(kwarg.value, frame)
531                 self.write(', ')
532             if extra_kwargs is not None:
533                 for key, value in extra_kwargs.iteritems():
534                     self.write('%r: %s, ' % (key, value))
535             if node.dyn_kwargs is not None:
536                 self.write('}, **')
537                 self.visit(node.dyn_kwargs, frame)
538                 self.write(')')
539             else:
540                 self.write('}')
541
542         elif node.dyn_kwargs is not None:
543             self.write(', **')
544             self.visit(node.dyn_kwargs, frame)
545
546     def pull_locals(self, frame):
547         """Pull all the references identifiers into the local scope."""
548         for name in frame.identifiers.undeclared:
549             self.writeline('l_%s = context.resolve(%r)' % (name, name))
550
551     def pull_dependencies(self, nodes):
552         """Pull all the dependencies."""
553         visitor = DependencyFinderVisitor()
554         for node in nodes:
555             visitor.visit(node)
556         for dependency in 'filters', 'tests':
557             mapping = getattr(self, dependency)
558             for name in getattr(visitor, dependency):
559                 if name not in mapping:
560                     mapping[name] = self.temporary_identifier()
561                 self.writeline('%s = environment.%s[%r]' %
562                                (mapping[name], dependency, name))
563
564     def unoptimize_scope(self, frame):
565         """Disable Python optimizations for the frame."""
566         # XXX: this is not that nice but it has no real overhead.  It
567         # mainly works because python finds the locals before dead code
568         # is removed.  If that breaks we have to add a dummy function
569         # that just accepts the arguments and does nothing.
570         if frame.identifiers.declared:
571             self.writeline('if 0: dummy(%s)' % ', '.join(
572                 'l_' + name for name in frame.identifiers.declared))
573
574     def push_scope(self, frame, extra_vars=()):
575         """This function returns all the shadowed variables in a dict
576         in the form name: alias and will write the required assignments
577         into the current scope.  No indentation takes place.
578
579         This also predefines locally declared variables from the loop
580         body because under some circumstances it may be the case that
581
582         `extra_vars` is passed to `Frame.find_shadowed`.
583         """
584         aliases = {}
585         for name in frame.find_shadowed(extra_vars):
586             aliases[name] = ident = self.temporary_identifier()
587             self.writeline('%s = l_%s' % (ident, name))
588         to_declare = set()
589         for name in frame.identifiers.declared_locally:
590             if name not in aliases:
591                 to_declare.add('l_' + name)
592         if to_declare:
593             self.writeline(' = '.join(to_declare) + ' = missing')
594         return aliases
595
596     def pop_scope(self, aliases, frame):
597         """Restore all aliases and delete unused variables."""
598         for name, alias in aliases.iteritems():
599             self.writeline('l_%s = %s' % (name, alias))
600         to_delete = set()
601         for name in frame.identifiers.declared_locally:
602             if name not in aliases:
603                 to_delete.add('l_' + name)
604         if to_delete:
605             # we cannot use the del statement here because enclosed
606             # scopes can trigger a SyntaxError:
607             #   a = 42; b = lambda: a; del a
608             self.writeline(' = '.join(to_delete) + ' = missing')
609
610     def function_scoping(self, node, frame, children=None,
611                          find_special=True):
612         """In Jinja a few statements require the help of anonymous
613         functions.  Those are currently macros and call blocks and in
614         the future also recursive loops.  As there is currently
615         technical limitation that doesn't allow reading and writing a
616         variable in a scope where the initial value is coming from an
617         outer scope, this function tries to fall back with a common
618         error message.  Additionally the frame passed is modified so
619         that the argumetns are collected and callers are looked up.
620
621         This will return the modified frame.
622         """
623         # we have to iterate twice over it, make sure that works
624         if children is None:
625             children = node.iter_child_nodes()
626         children = list(children)
627         func_frame = frame.inner()
628         func_frame.inspect(children, hard_scope=True)
629
630         # variables that are undeclared (accessed before declaration) and
631         # declared locally *and* part of an outside scope raise a template
632         # assertion error. Reason: we can't generate reasonable code from
633         # it without aliasing all the variables.
634         # this could be fixed in Python 3 where we have the nonlocal
635         # keyword or if we switch to bytecode generation
636         overriden_closure_vars = (
637             func_frame.identifiers.undeclared &
638             func_frame.identifiers.declared &
639             (func_frame.identifiers.declared_locally |
640              func_frame.identifiers.declared_parameter)
641         )
642         if overriden_closure_vars:
643             self.fail('It\'s not possible to set and access variables '
644                       'derived from an outer scope! (affects: %s)' %
645                       ', '.join(sorted(overriden_closure_vars)), node.lineno)
646
647         # remove variables from a closure from the frame's undeclared
648         # identifiers.
649         func_frame.identifiers.undeclared -= (
650             func_frame.identifiers.undeclared &
651             func_frame.identifiers.declared
652         )
653
654         # no special variables for this scope, abort early
655         if not find_special:
656             return func_frame
657
658         func_frame.accesses_kwargs = False
659         func_frame.accesses_varargs = False
660         func_frame.accesses_caller = False
661         func_frame.arguments = args = ['l_' + x.name for x in node.args]
662
663         undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
664
665         if 'caller' in undeclared:
666             func_frame.accesses_caller = True
667             func_frame.identifiers.add_special('caller')
668             args.append('l_caller')
669         if 'kwargs' in undeclared:
670             func_frame.accesses_kwargs = True
671             func_frame.identifiers.add_special('kwargs')
672             args.append('l_kwargs')
673         if 'varargs' in undeclared:
674             func_frame.accesses_varargs = True
675             func_frame.identifiers.add_special('varargs')
676             args.append('l_varargs')
677         return func_frame
678
679     def macro_body(self, node, frame, children=None):
680         """Dump the function def of a macro or call block."""
681         frame = self.function_scoping(node, frame, children)
682         # macros are delayed, they never require output checks
683         frame.require_output_check = False
684         args = frame.arguments
685         # XXX: this is an ugly fix for the loop nesting bug
686         # (tests.test_old_bugs.test_loop_call_bug).  This works around
687         # a identifier nesting problem we have in general.  It's just more
688         # likely to happen in loops which is why we work around it.  The
689         # real solution would be "nonlocal" all the identifiers that are
690         # leaking into a new python frame and might be used both unassigned
691         # and assigned.
692         if 'loop' in frame.identifiers.declared:
693             args = args + ['l_loop=l_loop']
694         self.writeline('def macro(%s):' % ', '.join(args), node)
695         self.indent()
696         self.buffer(frame)
697         self.pull_locals(frame)
698         self.blockvisit(node.body, frame)
699         self.return_buffer_contents(frame)
700         self.outdent()
701         return frame
702
703     def macro_def(self, node, frame):
704         """Dump the macro definition for the def created by macro_body."""
705         arg_tuple = ', '.join(repr(x.name) for x in node.args)
706         name = getattr(node, 'name', None)
707         if len(node.args) == 1:
708             arg_tuple += ','
709         self.write('Macro(environment, macro, %r, (%s), (' %
710                    (name, arg_tuple))
711         for arg in node.defaults:
712             self.visit(arg, frame)
713             self.write(', ')
714         self.write('), %r, %r, %r)' % (
715             bool(frame.accesses_kwargs),
716             bool(frame.accesses_varargs),
717             bool(frame.accesses_caller)
718         ))
719
720     def position(self, node):
721         """Return a human readable position for the node."""
722         rv = 'line %d' % node.lineno
723         if self.name is not None:
724             rv += ' in ' + repr(self.name)
725         return rv
726
727     # -- Statement Visitors
728
729     def visit_Template(self, node, frame=None):
730         assert frame is None, 'no root frame allowed'
731         from jinja2.runtime import __all__ as exported
732         self.writeline('from __future__ import division')
733         self.writeline('from jinja2.runtime import ' + ', '.join(exported))
734
735         # do we have an extends tag at all?  If not, we can save some
736         # overhead by just not processing any inheritance code.
737         have_extends = node.find(nodes.Extends) is not None
738
739         # are there any block tags?  If yes, we need a copy of the scope.
740         have_blocks = node.find(nodes.Block) is not None
741
742         # find all blocks
743         for block in node.find_all(nodes.Block):
744             if block.name in self.blocks:
745                 self.fail('block %r defined twice' % block.name, block.lineno)
746             self.blocks[block.name] = block
747
748         # find all imports and import them
749         for import_ in node.find_all(nodes.ImportedName):
750             if import_.importname not in self.import_aliases:
751                 imp = import_.importname
752                 self.import_aliases[imp] = alias = self.temporary_identifier()
753                 if '.' in imp:
754                     module, obj = imp.rsplit('.', 1)
755                     self.writeline('from %s import %s as %s' %
756                                    (module, obj, alias))
757                 else:
758                     self.writeline('import %s as %s' % (imp, alias))
759
760         # add the load name
761         self.writeline('name = %r' % self.name)
762
763         # generate the root render function.
764         self.writeline('def root(context, environment=environment):', extra=1)
765
766         # process the root
767         frame = Frame()
768         frame.inspect(node.body)
769         frame.toplevel = frame.rootlevel = True
770         frame.require_output_check = have_extends and not self.has_known_extends
771         self.indent()
772         if have_extends:
773             self.writeline('parent_template = None')
774         if have_blocks:
775             self.writeline('block_context = context._block()')
776         if 'self' in find_undeclared(node.body, ('self',)):
777             frame.identifiers.add_special('self')
778             self.writeline('l_self = TemplateReference(context)')
779         self.pull_locals(frame)
780         self.pull_dependencies(node.body)
781         self.blockvisit(node.body, frame)
782         self.outdent()
783
784         # make sure that the parent root is called.
785         if have_extends:
786             if not self.has_known_extends:
787                 self.indent()
788                 self.writeline('if parent_template is not None:')
789             self.indent()
790             self.writeline('for event in parent_template.'
791                            'root_render_func(context):')
792             self.indent()
793             self.writeline('yield event')
794             self.outdent(2 + (not self.has_known_extends))
795
796         # at this point we now have the blocks collected and can visit them too.
797         for name, block in self.blocks.iteritems():
798             block_frame = Frame()
799             block_frame.inspect(block.body)
800             block_frame.block = name
801             self.writeline('def block_%s(context, environment=environment):'
802                            % name, block, 1)
803             self.indent()
804             undeclared = find_undeclared(block.body, ('self', 'super'))
805             if 'self' in undeclared:
806                 block_frame.identifiers.add_special('self')
807                 self.writeline('l_self = TemplateReference(context)')
808             if block.find(nodes.Block) is not None:
809                 self.writeline('block_context = context._block(%r)' % name)
810             if 'super' in undeclared:
811                 block_frame.identifiers.add_special('super')
812                 self.writeline('l_super = context.super(%r, '
813                                'block_%s)' % (name, name))
814             self.pull_locals(block_frame)
815             self.pull_dependencies(block.body)
816             self.blockvisit(block.body, block_frame)
817             self.outdent()
818
819         self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
820                                                    for x in self.blocks),
821                        extra=1)
822
823         # add a function that returns the debug info
824         self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
825                                                     in self.debug_info))
826
827     def visit_Block(self, node, frame):
828         """Call a block and register it for the template."""
829         level = 1
830         if frame.toplevel:
831             # if we know that we are a child template, there is no need to
832             # check if we are one
833             if self.has_known_extends:
834                 return
835             if self.extends_so_far > 0:
836                 self.writeline('if parent_template is None:')
837                 self.indent()
838                 level += 1
839         if node.scoped:
840             context = 'block_context.derived(locals())'
841         else:
842             context = 'block_context'
843         self.writeline('for event in context.blocks[%r][0](%s):' % (
844                        node.name, context), node)
845         self.indent()
846         self.simple_write('event', frame)
847         self.outdent(level)
848
849     def visit_Extends(self, node, frame):
850         """Calls the extender."""
851         if not frame.toplevel:
852             self.fail('cannot use extend from a non top-level scope',
853                       node.lineno)
854
855         # if the number of extends statements in general is zero so
856         # far, we don't have to add a check if something extended
857         # the template before this one.
858         if self.extends_so_far > 0:
859
860             # if we have a known extends we just add a template runtime
861             # error into the generated code.  We could catch that at compile
862             # time too, but i welcome it not to confuse users by throwing the
863             # same error at different times just "because we can".
864             if not self.has_known_extends:
865                 self.writeline('if parent_template is not None:')
866                 self.indent()
867             self.writeline('raise TemplateRuntimeError(%r)' %
868                            'extended multiple times')
869             self.outdent()
870
871             # if we have a known extends already we don't need that code here
872             # as we know that the template execution will end here.
873             if self.has_known_extends:
874                 raise CompilerExit()
875
876         self.writeline('parent_template = environment.get_template(', node)
877         self.visit(node.template, frame)
878         self.write(', %r)' % self.name)
879         self.writeline('for name, parent_block in parent_template.'
880                        'blocks.iteritems():')
881         self.indent()
882         self.writeline('context.blocks.setdefault(name, []).'
883                        'append(parent_block)')
884         self.outdent()
885
886         # if this extends statement was in the root level we can take
887         # advantage of that information and simplify the generated code
888         # in the top level from this point onwards
889         if frame.rootlevel:
890             self.has_known_extends = True
891
892         # and now we have one more
893         self.extends_so_far += 1
894
895     def visit_Include(self, node, frame):
896         """Handles includes."""
897         if node.with_context:
898             self.unoptimize_scope(frame)
899         if node.ignore_missing:
900             self.writeline('try:')
901             self.indent()
902         self.writeline('template = environment.get_template(', node)
903         self.visit(node.template, frame)
904         self.write(', %r)' % self.name)
905         if node.ignore_missing:
906             self.outdent()
907             self.writeline('except TemplateNotFound:')
908             self.indent()
909             self.writeline('pass')
910             self.outdent()
911             self.writeline('else:')
912             self.indent()
913
914         if node.with_context:
915             self.writeline('for event in template.root_render_func('
916                            'template.new_context(context.parent, True, '
917                            'locals())):')
918         else:
919             self.writeline('for event in template.module._body_stream:')
920
921         self.indent()
922         self.simple_write('event', frame)
923         self.outdent()
924
925         if node.ignore_missing:
926             self.outdent()
927
928     def visit_Import(self, node, frame):
929         """Visit regular imports."""
930         if node.with_context:
931             self.unoptimize_scope(frame)
932         self.writeline('l_%s = ' % node.target, node)
933         if frame.toplevel:
934             self.write('context.vars[%r] = ' % node.target)
935         self.write('environment.get_template(')
936         self.visit(node.template, frame)
937         self.write(', %r).' % self.name)
938         if node.with_context:
939             self.write('make_module(context.parent, True, locals())')
940         else:
941             self.write('module')
942         if frame.toplevel and not node.target.startswith('_'):
943             self.writeline('context.exported_vars.discard(%r)' % node.target)
944         frame.assigned_names.add(node.target)
945
946     def visit_FromImport(self, node, frame):
947         """Visit named imports."""
948         self.newline(node)
949         self.write('included_template = environment.get_template(')
950         self.visit(node.template, frame)
951         self.write(', %r).' % self.name)
952         if node.with_context:
953             self.write('make_module(context.parent, True)')
954         else:
955             self.write('module')
956
957         var_names = []
958         discarded_names = []
959         for name in node.names:
960             if isinstance(name, tuple):
961                 name, alias = name
962             else:
963                 alias = name
964             self.writeline('l_%s = getattr(included_template, '
965                            '%r, missing)' % (alias, name))
966             self.writeline('if l_%s is missing:' % alias)
967             self.indent()
968             self.writeline('l_%s = environment.undefined(%r %% '
969                            'included_template.__name__, '
970                            'name=%r)' %
971                            (alias, 'the template %%r (imported on %s) does '
972                            'not export the requested name %s' % (
973                                 self.position(node),
974                                 repr(name)
975                            ), name))
976             self.outdent()
977             if frame.toplevel:
978                 var_names.append(alias)
979                 if not alias.startswith('_'):
980                     discarded_names.append(alias)
981             frame.assigned_names.add(alias)
982
983         if var_names:
984             if len(var_names) == 1:
985                 name = var_names[0]
986                 self.writeline('context.vars[%r] = l_%s' % (name, name))
987             else:
988                 self.writeline('context.vars.update({%s})' % ', '.join(
989                     '%r: l_%s' % (name, name) for name in var_names
990                 ))
991         if discarded_names:
992             if len(discarded_names) == 1:
993                 self.writeline('context.exported_vars.discard(%r)' %
994                                discarded_names[0])
995             else:
996                 self.writeline('context.exported_vars.difference_'
997                                'update((%s))' % ', '.join(map(repr, discarded_names)))
998
999     def visit_For(self, node, frame):
1000         # when calculating the nodes for the inner frame we have to exclude
1001         # the iterator contents from it
1002         children = node.iter_child_nodes(exclude=('iter',))
1003         if node.recursive:
1004             loop_frame = self.function_scoping(node, frame, children,
1005                                                find_special=False)
1006         else:
1007             loop_frame = frame.inner()
1008             loop_frame.inspect(children)
1009
1010         # try to figure out if we have an extended loop.  An extended loop
1011         # is necessary if the loop is in recursive mode if the special loop
1012         # variable is accessed in the body.
1013         extended_loop = node.recursive or 'loop' in \
1014                         find_undeclared(node.iter_child_nodes(
1015                             only=('body',)), ('loop',))
1016
1017         # if we don't have an recursive loop we have to find the shadowed
1018         # variables at that point.  Because loops can be nested but the loop
1019         # variable is a special one we have to enforce aliasing for it.
1020         if not node.recursive:
1021             aliases = self.push_scope(loop_frame, ('loop',))
1022
1023         # otherwise we set up a buffer and add a function def
1024         else:
1025             self.writeline('def loop(reciter, loop_render_func):', node)
1026             self.indent()
1027             self.buffer(loop_frame)
1028             aliases = {}
1029
1030         # make sure the loop variable is a special one and raise a template
1031         # assertion error if a loop tries to write to loop
1032         if extended_loop:
1033             loop_frame.identifiers.add_special('loop')
1034         for name in node.find_all(nodes.Name):
1035             if name.ctx == 'store' and name.name == 'loop':
1036                 self.fail('Can\'t assign to special loop variable '
1037                           'in for-loop target', name.lineno)
1038
1039         self.pull_locals(loop_frame)
1040         if node.else_:
1041             iteration_indicator = self.temporary_identifier()
1042             self.writeline('%s = 1' % iteration_indicator)
1043
1044         # Create a fake parent loop if the else or test section of a
1045         # loop is accessing the special loop variable and no parent loop
1046         # exists.
1047         if 'loop' not in aliases and 'loop' in find_undeclared(
1048            node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1049             self.writeline("l_loop = environment.undefined(%r, name='loop')" %
1050                 ("'loop' is undefined. the filter section of a loop as well "
1051                  "as the else block doesn't have access to the special 'loop'"
1052                  " variable of the current loop.  Because there is no parent "
1053                  "loop it's undefined.  Happened in loop on %s" %
1054                  self.position(node)))
1055
1056         self.writeline('for ', node)
1057         self.visit(node.target, loop_frame)
1058         self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
1059
1060         # if we have an extened loop and a node test, we filter in the
1061         # "outer frame".
1062         if extended_loop and node.test is not None:
1063             self.write('(')
1064             self.visit(node.target, loop_frame)
1065             self.write(' for ')
1066             self.visit(node.target, loop_frame)
1067             self.write(' in ')
1068             if node.recursive:
1069                 self.write('reciter')
1070             else:
1071                 self.visit(node.iter, loop_frame)
1072             self.write(' if (')
1073             test_frame = loop_frame.copy()
1074             self.visit(node.test, test_frame)
1075             self.write('))')
1076
1077         elif node.recursive:
1078             self.write('reciter')
1079         else:
1080             self.visit(node.iter, loop_frame)
1081
1082         if node.recursive:
1083             self.write(', recurse=loop_render_func):')
1084         else:
1085             self.write(extended_loop and '):' or ':')
1086
1087         # tests in not extended loops become a continue
1088         if not extended_loop and node.test is not None:
1089             self.indent()
1090             self.writeline('if not ')
1091             self.visit(node.test, loop_frame)
1092             self.write(':')
1093             self.indent()
1094             self.writeline('continue')
1095             self.outdent(2)
1096
1097         self.indent()
1098         self.blockvisit(node.body, loop_frame)
1099         if node.else_:
1100             self.writeline('%s = 0' % iteration_indicator)
1101         self.outdent()
1102
1103         if node.else_:
1104             self.writeline('if %s:' % iteration_indicator)
1105             self.indent()
1106             self.blockvisit(node.else_, loop_frame)
1107             self.outdent()
1108
1109         # reset the aliases if there are any.
1110         if not node.recursive:
1111             self.pop_scope(aliases, loop_frame)
1112
1113         # if the node was recursive we have to return the buffer contents
1114         # and start the iteration code
1115         if node.recursive:
1116             self.return_buffer_contents(loop_frame)
1117             self.outdent()
1118             self.start_write(frame, node)
1119             self.write('loop(')
1120             self.visit(node.iter, frame)
1121             self.write(', loop)')
1122             self.end_write(frame)
1123
1124     def visit_If(self, node, frame):
1125         if_frame = frame.soft()
1126         self.writeline('if ', node)
1127         self.visit(node.test, if_frame)
1128         self.write(':')
1129         self.indent()
1130         self.blockvisit(node.body, if_frame)
1131         self.outdent()
1132         if node.else_:
1133             self.writeline('else:')
1134             self.indent()
1135             self.blockvisit(node.else_, if_frame)
1136             self.outdent()
1137
1138     def visit_Macro(self, node, frame):
1139         macro_frame = self.macro_body(node, frame)
1140         self.newline()
1141         if frame.toplevel:
1142             if not node.name.startswith('_'):
1143                 self.write('context.exported_vars.add(%r)' % node.name)
1144             self.writeline('context.vars[%r] = ' % node.name)
1145         self.write('l_%s = ' % node.name)
1146         self.macro_def(node, macro_frame)
1147         frame.assigned_names.add(node.name)
1148
1149     def visit_CallBlock(self, node, frame):
1150         children = node.iter_child_nodes(exclude=('call',))
1151         call_frame = self.macro_body(node, frame, children)
1152         self.writeline('caller = ')
1153         self.macro_def(node, call_frame)
1154         self.start_write(frame, node)
1155         self.visit_Call(node.call, call_frame, forward_caller=True)
1156         self.end_write(frame)
1157
1158     def visit_FilterBlock(self, node, frame):
1159         filter_frame = frame.inner()
1160         filter_frame.inspect(node.iter_child_nodes())
1161         aliases = self.push_scope(filter_frame)
1162         self.pull_locals(filter_frame)
1163         self.buffer(filter_frame)
1164         self.blockvisit(node.body, filter_frame)
1165         self.start_write(frame, node)
1166         self.visit_Filter(node.filter, filter_frame)
1167         self.end_write(frame)
1168         self.pop_scope(aliases, filter_frame)
1169
1170     def visit_ExprStmt(self, node, frame):
1171         self.newline(node)
1172         self.visit(node.node, frame)
1173
1174     def visit_Output(self, node, frame):
1175         # if we have a known extends statement, we don't output anything
1176         # if we are in a require_output_check section
1177         if self.has_known_extends and frame.require_output_check:
1178             return
1179
1180         if self.environment.finalize:
1181             finalize = lambda x: unicode(self.environment.finalize(x))
1182         else:
1183             finalize = unicode
1184
1185         self.newline(node)
1186
1187         # if we are inside a frame that requires output checking, we do so
1188         outdent_later = False
1189         if frame.require_output_check:
1190             self.writeline('if parent_template is None:')
1191             self.indent()
1192             outdent_later = True
1193
1194         # try to evaluate as many chunks as possible into a static
1195         # string at compile time.
1196         body = []
1197         for child in node.nodes:
1198             try:
1199                 const = child.as_const()
1200             except nodes.Impossible:
1201                 body.append(child)
1202                 continue
1203             try:
1204                 if self.environment.autoescape:
1205                     if hasattr(const, '__html__'):
1206                         const = const.__html__()
1207                     else:
1208                         const = escape(const)
1209                 const = finalize(const)
1210             except:
1211                 # if something goes wrong here we evaluate the node
1212                 # at runtime for easier debugging
1213                 body.append(child)
1214                 continue
1215             if body and isinstance(body[-1], list):
1216                 body[-1].append(const)
1217             else:
1218                 body.append([const])
1219
1220         # if we have less than 3 nodes or a buffer we yield or extend/append
1221         if len(body) < 3 or frame.buffer is not None:
1222             if frame.buffer is not None:
1223                 # for one item we append, for more we extend
1224                 if len(body) == 1:
1225                     self.writeline('%s.append(' % frame.buffer)
1226                 else:
1227                     self.writeline('%s.extend((' % frame.buffer)
1228                 self.indent()
1229             for item in body:
1230                 if isinstance(item, list):
1231                     val = repr(concat(item))
1232                     if frame.buffer is None:
1233                         self.writeline('yield ' + val)
1234                     else:
1235                         self.writeline(val + ', ')
1236                 else:
1237                     if frame.buffer is None:
1238                         self.writeline('yield ', item)
1239                     else:
1240                         self.newline(item)
1241                     close = 1
1242                     if self.environment.autoescape:
1243                         self.write('escape(')
1244                     else:
1245                         self.write('to_string(')
1246                     if self.environment.finalize is not None:
1247                         self.write('environment.finalize(')
1248                         close += 1
1249                     self.visit(item, frame)
1250                     self.write(')' * close)
1251                     if frame.buffer is not None:
1252                         self.write(', ')
1253             if frame.buffer is not None:
1254                 # close the open parentheses
1255                 self.outdent()
1256                 self.writeline(len(body) == 1 and ')' or '))')
1257
1258         # otherwise we create a format string as this is faster in that case
1259         else:
1260             format = []
1261             arguments = []
1262             for item in body:
1263                 if isinstance(item, list):
1264                     format.append(concat(item).replace('%', '%%'))
1265                 else:
1266                     format.append('%s')
1267                     arguments.append(item)
1268             self.writeline('yield ')
1269             self.write(repr(concat(format)) + ' % (')
1270             idx = -1
1271             self.indent()
1272             for argument in arguments:
1273                 self.newline(argument)
1274                 close = 0
1275                 if self.environment.autoescape:
1276                     self.write('escape(')
1277                     close += 1
1278                 if self.environment.finalize is not None:
1279                     self.write('environment.finalize(')
1280                     close += 1
1281                 self.visit(argument, frame)
1282                 self.write(')' * close + ', ')
1283             self.outdent()
1284             self.writeline(')')
1285
1286         if outdent_later:
1287             self.outdent()
1288
1289     def visit_Assign(self, node, frame):
1290         self.newline(node)
1291         # toplevel assignments however go into the local namespace and
1292         # the current template's context.  We create a copy of the frame
1293         # here and add a set so that the Name visitor can add the assigned
1294         # names here.
1295         if frame.toplevel:
1296             assignment_frame = frame.copy()
1297             assignment_frame.toplevel_assignments = set()
1298         else:
1299             assignment_frame = frame
1300         self.visit(node.target, assignment_frame)
1301         self.write(' = ')
1302         self.visit(node.node, frame)
1303
1304         # make sure toplevel assignments are added to the context.
1305         if frame.toplevel:
1306             public_names = [x for x in assignment_frame.toplevel_assignments
1307                             if not x.startswith('_')]
1308             if len(assignment_frame.toplevel_assignments) == 1:
1309                 name = next(iter(assignment_frame.toplevel_assignments))
1310                 self.writeline('context.vars[%r] = l_%s' % (name, name))
1311             else:
1312                 self.writeline('context.vars.update({')
1313                 for idx, name in enumerate(assignment_frame.toplevel_assignments):
1314                     if idx:
1315                         self.write(', ')
1316                     self.write('%r: l_%s' % (name, name))
1317                 self.write('})')
1318             if public_names:
1319                 if len(public_names) == 1:
1320                     self.writeline('context.exported_vars.add(%r)' %
1321                                    public_names[0])
1322                 else:
1323                     self.writeline('context.exported_vars.update((%s))' %
1324                                    ', '.join(map(repr, public_names)))
1325
1326     # -- Expression Visitors
1327
1328     def visit_Name(self, node, frame):
1329         if node.ctx == 'store' and frame.toplevel:
1330             frame.toplevel_assignments.add(node.name)
1331         self.write('l_' + node.name)
1332         frame.assigned_names.add(node.name)
1333
1334     def visit_Const(self, node, frame):
1335         val = node.value
1336         if isinstance(val, float):
1337             self.write(str(val))
1338         else:
1339             self.write(repr(val))
1340
1341     def visit_TemplateData(self, node, frame):
1342         self.write(repr(node.as_const()))
1343
1344     def visit_Tuple(self, node, frame):
1345         self.write('(')
1346         idx = -1
1347         for idx, item in enumerate(node.items):
1348             if idx:
1349                 self.write(', ')
1350             self.visit(item, frame)
1351         self.write(idx == 0 and ',)' or ')')
1352
1353     def visit_List(self, node, frame):
1354         self.write('[')
1355         for idx, item in enumerate(node.items):
1356             if idx:
1357                 self.write(', ')
1358             self.visit(item, frame)
1359         self.write(']')
1360
1361     def visit_Dict(self, node, frame):
1362         self.write('{')
1363         for idx, item in enumerate(node.items):
1364             if idx:
1365                 self.write(', ')
1366             self.visit(item.key, frame)
1367             self.write(': ')
1368             self.visit(item.value, frame)
1369         self.write('}')
1370
1371     def binop(operator):
1372         def visitor(self, node, frame):
1373             self.write('(')
1374             self.visit(node.left, frame)
1375             self.write(' %s ' % operator)
1376             self.visit(node.right, frame)
1377             self.write(')')
1378         return visitor
1379
1380     def uaop(operator):
1381         def visitor(self, node, frame):
1382             self.write('(' + operator)
1383             self.visit(node.node, frame)
1384             self.write(')')
1385         return visitor
1386
1387     visit_Add = binop('+')
1388     visit_Sub = binop('-')
1389     visit_Mul = binop('*')
1390     visit_Div = binop('/')
1391     visit_FloorDiv = binop('//')
1392     visit_Pow = binop('**')
1393     visit_Mod = binop('%')
1394     visit_And = binop('and')
1395     visit_Or = binop('or')
1396     visit_Pos = uaop('+')
1397     visit_Neg = uaop('-')
1398     visit_Not = uaop('not ')
1399     del binop, uaop
1400
1401     def visit_Concat(self, node, frame):
1402         self.write('%s((' % (self.environment.autoescape and
1403                              'markup_join' or 'unicode_join'))
1404         for arg in node.nodes:
1405             self.visit(arg, frame)
1406             self.write(', ')
1407         self.write('))')
1408
1409     def visit_Compare(self, node, frame):
1410         self.visit(node.expr, frame)
1411         for op in node.ops:
1412             self.visit(op, frame)
1413
1414     def visit_Operand(self, node, frame):
1415         self.write(' %s ' % operators[node.op])
1416         self.visit(node.expr, frame)
1417
1418     def visit_Getattr(self, node, frame):
1419         self.write('environment.getattr(')
1420         self.visit(node.node, frame)
1421         self.write(', %r)' % node.attr)
1422
1423     def visit_Getitem(self, node, frame):
1424         # slices bypass the environment getitem method.
1425         if isinstance(node.arg, nodes.Slice):
1426             self.visit(node.node, frame)
1427             self.write('[')
1428             self.visit(node.arg, frame)
1429             self.write(']')
1430         else:
1431             self.write('environment.getitem(')
1432             self.visit(node.node, frame)
1433             self.write(', ')
1434             self.visit(node.arg, frame)
1435             self.write(')')
1436
1437     def visit_Slice(self, node, frame):
1438         if node.start is not None:
1439             self.visit(node.start, frame)
1440         self.write(':')
1441         if node.stop is not None:
1442             self.visit(node.stop, frame)
1443         if node.step is not None:
1444             self.write(':')
1445             self.visit(node.step, frame)
1446
1447     def visit_Filter(self, node, frame):
1448         self.write(self.filters[node.name] + '(')
1449         func = self.environment.filters.get(node.name)
1450         if func is None:
1451             self.fail('no filter named %r' % node.name, node.lineno)
1452         if getattr(func, 'contextfilter', False):
1453             self.write('context, ')
1454         elif getattr(func, 'environmentfilter', False):
1455             self.write('environment, ')
1456
1457         # if the filter node is None we are inside a filter block
1458         # and want to write to the current buffer
1459         if node.node is not None:
1460             self.visit(node.node, frame)
1461         elif self.environment.autoescape:
1462             self.write('Markup(concat(%s))' % frame.buffer)
1463         else:
1464             self.write('concat(%s)' % frame.buffer)
1465         self.signature(node, frame)
1466         self.write(')')
1467
1468     def visit_Test(self, node, frame):
1469         self.write(self.tests[node.name] + '(')
1470         if node.name not in self.environment.tests:
1471             self.fail('no test named %r' % node.name, node.lineno)
1472         self.visit(node.node, frame)
1473         self.signature(node, frame)
1474         self.write(')')
1475
1476     def visit_CondExpr(self, node, frame):
1477         def write_expr2():
1478             if node.expr2 is not None:
1479                 return self.visit(node.expr2, frame)
1480             self.write('environment.undefined(%r)' % ('the inline if-'
1481                        'expression on %s evaluated to false and '
1482                        'no else section was defined.' % self.position(node)))
1483
1484         if not have_condexpr:
1485             self.write('((')
1486             self.visit(node.test, frame)
1487             self.write(') and (')
1488             self.visit(node.expr1, frame)
1489             self.write(',) or (')
1490             write_expr2()
1491             self.write(',))[0]')
1492         else:
1493             self.write('(')
1494             self.visit(node.expr1, frame)
1495             self.write(' if ')
1496             self.visit(node.test, frame)
1497             self.write(' else ')
1498             write_expr2()
1499             self.write(')')
1500
1501     def visit_Call(self, node, frame, forward_caller=False):
1502         if self.environment.sandboxed:
1503             self.write('environment.call(context, ')
1504         else:
1505             self.write('context.call(')
1506         self.visit(node.node, frame)
1507         extra_kwargs = forward_caller and {'caller': 'caller'} or None
1508         self.signature(node, frame, extra_kwargs)
1509         self.write(')')
1510
1511     def visit_Keyword(self, node, frame):
1512         self.write(node.key + '=')
1513         self.visit(node.value, frame)
1514
1515     # -- Unused nodes for extensions
1516
1517     def visit_MarkSafe(self, node, frame):
1518         self.write('Markup(')
1519         self.visit(node.expr, frame)
1520         self.write(')')
1521
1522     def visit_EnvironmentAttribute(self, node, frame):
1523         self.write('environment.' + node.name)
1524
1525     def visit_ExtensionAttribute(self, node, frame):
1526         self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
1527
1528     def visit_ImportedName(self, node, frame):
1529         self.write(self.import_aliases[node.importname])
1530
1531     def visit_InternalName(self, node, frame):
1532         self.write(node.name)
1533
1534     def visit_ContextReference(self, node, frame):
1535         self.write('context')
1536
1537     def visit_Continue(self, node, frame):
1538         self.writeline('continue', node)
1539
1540     def visit_Break(self, node, frame):
1541         self.writeline('break', node)
1542
1543     def visit_Scope(self, node, frame):
1544         scope_frame = frame.inner()
1545         scope_frame.inspect(node.iter_child_nodes())
1546         aliases = self.push_scope(scope_frame)
1547         self.pull_locals(scope_frame)
1548         self.blockvisit(node.body, scope_frame)
1549         self.pop_scope(aliases, scope_frame)