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