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