# mako/codegen.py
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
#
# This module is part of Mako and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

"""provides functionality for rendering a parsetree constructing into module
source code."""

import time
import re
from mako.pygen import PythonPrinter
from mako import util, ast, parsetree, filters, exceptions
from mako import compat


MAGIC_NUMBER = 8

# names which are hardwired into the
# template and are not accessed via the
# context itself
RESERVED_NAMES = set(['context', 'loop', 'UNDEFINED'])

def compile(node,
                uri,
                filename=None,
                default_filters=None,
                buffer_filters=None,
                imports=None,
                future_imports=None,
                source_encoding=None,
                generate_magic_comment=True,
                disable_unicode=False,
                strict_undefined=False,
                enable_loop=True,
                reserved_names=frozenset()):

    """Generate module source code given a parsetree node,
      uri, and optional source filename"""

    # if on Py2K, push the "source_encoding" string to be
    # a bytestring itself, as we will be embedding it into
    # the generated source and we don't want to coerce the
    # result into a unicode object, in "disable_unicode" mode
    if not compat.py3k and isinstance(source_encoding, compat.text_type):
        source_encoding = source_encoding.encode(source_encoding)


    buf = util.FastEncodingBuffer()

    printer = PythonPrinter(buf)
    _GenerateRenderMethod(printer,
                            _CompileContext(uri,
                                            filename,
                                            default_filters,
                                            buffer_filters,
                                            imports,
                                            future_imports,
                                            source_encoding,
                                            generate_magic_comment,
                                            disable_unicode,
                                            strict_undefined,
                                            enable_loop,
                                            reserved_names),
                                node)
    return buf.getvalue()

class _CompileContext(object):
    def __init__(self,
                    uri,
                    filename,
                    default_filters,
                    buffer_filters,
                    imports,
                    future_imports,
                    source_encoding,
                    generate_magic_comment,
                    disable_unicode,
                    strict_undefined,
                    enable_loop,
                    reserved_names):
        self.uri = uri
        self.filename = filename
        self.default_filters = default_filters
        self.buffer_filters = buffer_filters
        self.imports = imports
        self.future_imports = future_imports
        self.source_encoding = source_encoding
        self.generate_magic_comment = generate_magic_comment
        self.disable_unicode = disable_unicode
        self.strict_undefined = strict_undefined
        self.enable_loop = enable_loop
        self.reserved_names = reserved_names

class _GenerateRenderMethod(object):
    """A template visitor object which generates the
       full module source for a template.

    """
    def __init__(self, printer, compiler, node):
        self.printer = printer
        self.last_source_line = -1
        self.compiler = compiler
        self.node = node
        self.identifier_stack = [None]
        self.in_def = isinstance(node, (parsetree.DefTag, parsetree.BlockTag))

        if self.in_def:
            name = "render_%s" % node.funcname
            args = node.get_argument_expressions()
            filtered = len(node.filter_args.args) > 0
            buffered = eval(node.attributes.get('buffered', 'False'))
            cached = eval(node.attributes.get('cached', 'False'))
            defs = None
            pagetag = None
            if node.is_block and not node.is_anonymous:
                args += ['**pageargs']
        else:
            defs = self.write_toplevel()
            pagetag = self.compiler.pagetag
            name = "render_body"
            if pagetag is not None:
                args = pagetag.body_decl.get_argument_expressions()
                if not pagetag.body_decl.kwargs:
                    args += ['**pageargs']
                cached = eval(pagetag.attributes.get('cached', 'False'))
                self.compiler.enable_loop = self.compiler.enable_loop or eval(
                                        pagetag.attributes.get(
                                                'enable_loop', 'False')
                                    )
            else:
                args = ['**pageargs']
                cached = False
            buffered = filtered = False
        if args is None:
            args = ['context']
        else:
            args = [a for a in ['context'] + args]

        self.write_render_callable(
                            pagetag or node,
                            name, args,
                            buffered, filtered, cached)

        if defs is not None:
            for node in defs:
                _GenerateRenderMethod(printer, compiler, node)

    @property
    def identifiers(self):
        return self.identifier_stack[-1]

    def write_toplevel(self):
        """Traverse a template structure for module-level directives and
        generate the start of module-level code.

        """
        inherit = []
        namespaces = {}
        module_code = []

        self.compiler.pagetag = None

        class FindTopLevel(object):
            def visitInheritTag(s, node):
                inherit.append(node)
            def visitNamespaceTag(s, node):
                namespaces[node.name] = node
            def visitPageTag(s, node):
                self.compiler.pagetag = node
            def visitCode(s, node):
                if node.ismodule:
                    module_code.append(node)

        f = FindTopLevel()
        for n in self.node.nodes:
            n.accept_visitor(f)

        self.compiler.namespaces = namespaces

        module_ident = set()
        for n in module_code:
            module_ident = module_ident.union(n.declared_identifiers())

        module_identifiers = _Identifiers(self.compiler)
        module_identifiers.declared = module_ident

        # module-level names, python code
        if self.compiler.generate_magic_comment and \
            self.compiler.source_encoding:
            self.printer.writeline("# -*- encoding:%s -*-" %
                                    self.compiler.source_encoding)

        if self.compiler.future_imports:
            self.printer.writeline("from __future__ import %s" %
                                   (", ".join(self.compiler.future_imports),))
        self.printer.writeline("from mako import runtime, filters, cache")
        self.printer.writeline("UNDEFINED = runtime.UNDEFINED")
        self.printer.writeline("__M_dict_builtin = dict")
        self.printer.writeline("__M_locals_builtin = locals")
        self.printer.writeline("_magic_number = %r" % MAGIC_NUMBER)
        self.printer.writeline("_modified_time = %r" % time.time())
        self.printer.writeline("_enable_loop = %r" % self.compiler.enable_loop)
        self.printer.writeline(
                            "_template_filename = %r" % self.compiler.filename)
        self.printer.writeline("_template_uri = %r" % self.compiler.uri)
        self.printer.writeline(
                    "_source_encoding = %r" % self.compiler.source_encoding)
        if self.compiler.imports:
            buf = ''
            for imp in self.compiler.imports:
                buf += imp + "\n"
                self.printer.writeline(imp)
            impcode = ast.PythonCode(
                            buf,
                            source='', lineno=0,
                            pos=0,
                            filename='template defined imports')
        else:
            impcode = None

        main_identifiers = module_identifiers.branch(self.node)
        module_identifiers.topleveldefs = \
            module_identifiers.topleveldefs.\
                union(main_identifiers.topleveldefs)
        module_identifiers.declared.add("UNDEFINED")
        if impcode:
            module_identifiers.declared.update(impcode.declared_identifiers)

        self.compiler.identifiers = module_identifiers
        self.printer.writeline("_exports = %r" %
                            [n.name for n in
                            main_identifiers.topleveldefs.values()]
                        )
        self.printer.write("\n\n")

        if len(module_code):
            self.write_module_code(module_code)

        if len(inherit):
            self.write_namespaces(namespaces)
            self.write_inherit(inherit[-1])
        elif len(namespaces):
            self.write_namespaces(namespaces)

        return list(main_identifiers.topleveldefs.values())

    def write_render_callable(self, node, name, args, buffered, filtered,
            cached):
        """write a top-level render callable.

        this could be the main render() method or that of a top-level def."""

        if self.in_def:
            decorator = node.decorator
            if decorator:
                self.printer.writeline(
                                 "@runtime._decorate_toplevel(%s)" % decorator)

        self.printer.writelines(
            "def %s(%s):" % (name, ','.join(args)),
                # push new frame, assign current frame to __M_caller
                "__M_caller = context.caller_stack._push_frame()",
                "try:"
        )
        if buffered or filtered or cached:
            self.printer.writeline("context._push_buffer()")

        self.identifier_stack.append(
                                   self.compiler.identifiers.branch(self.node))
        if (not self.in_def or self.node.is_block) and '**pageargs' in args:
            self.identifier_stack[-1].argument_declared.add('pageargs')

        if not self.in_def and (
                                len(self.identifiers.locally_assigned) > 0 or
                                len(self.identifiers.argument_declared) > 0
                                ):
            self.printer.writeline("__M_locals = __M_dict_builtin(%s)" %
                                    ','.join([
                                            "%s=%s" % (x, x) for x in
                                            self.identifiers.argument_declared
                                            ]))

        self.write_variable_declares(self.identifiers, toplevel=True)

        for n in self.node.nodes:
            n.accept_visitor(self)

        self.write_def_finish(self.node, buffered, filtered, cached)
        self.printer.writeline(None)
        self.printer.write("\n\n")
        if cached:
            self.write_cache_decorator(
                                node, name,
                                args, buffered,
                                self.identifiers, toplevel=True)

    def write_module_code(self, module_code):
        """write module-level template code, i.e. that which
        is enclosed in <%! %> tags in the template."""
        for n in module_code:
            self.write_source_comment(n)
            self.printer.write_indented_block(n.text)

    def write_inherit(self, node):
        """write the module-level inheritance-determination callable."""

        self.printer.writelines(
            "def _mako_inherit(template, context):",
                "_mako_generate_namespaces(context)",
                "return runtime._inherit_from(context, %s, _template_uri)" %
                 (node.parsed_attributes['file']),
                None
            )

    def write_namespaces(self, namespaces):
        """write the module-level namespace-generating callable."""
        self.printer.writelines(
            "def _mako_get_namespace(context, name):",
                "try:",
                    "return context.namespaces[(__name__, name)]",
                "except KeyError:",
                    "_mako_generate_namespaces(context)",
                "return context.namespaces[(__name__, name)]",
            None, None
            )
        self.printer.writeline("def _mako_generate_namespaces(context):")


        for node in namespaces.values():
            if 'import' in node.attributes:
                self.compiler.has_ns_imports = True
            self.write_source_comment(node)
            if len(node.nodes):
                self.printer.writeline("def make_namespace():")
                export = []
                identifiers = self.compiler.identifiers.branch(node)
                self.in_def = True
                class NSDefVisitor(object):
                    def visitDefTag(s, node):
                        s.visitDefOrBase(node)

                    def visitBlockTag(s, node):
                        s.visitDefOrBase(node)

                    def visitDefOrBase(s, node):
                        if node.is_anonymous:
                            raise exceptions.CompileException(
                                "Can't put anonymous blocks inside "
                                "<%namespace>",
                                **node.exception_kwargs
                            )
                        self.write_inline_def(node, identifiers, nested=False)
                        export.append(node.funcname)
                vis = NSDefVisitor()
                for n in node.nodes:
                    n.accept_visitor(vis)
                self.printer.writeline("return [%s]" % (','.join(export)))
                self.printer.writeline(None)
                self.in_def = False
                callable_name = "make_namespace()"
            else:
                callable_name = "None"

            if 'file' in node.parsed_attributes:
                self.printer.writeline(
                                "ns = runtime.TemplateNamespace(%r,"
                                " context._clean_inheritance_tokens(),"
                                " templateuri=%s, callables=%s, "
                                " calling_uri=_template_uri)" %
                                (
                                   node.name,
                                   node.parsed_attributes.get('file', 'None'),
                                   callable_name,
                                )
                            )
            elif 'module' in node.parsed_attributes:
                self.printer.writeline(
                                "ns = runtime.ModuleNamespace(%r,"
                                " context._clean_inheritance_tokens(),"
                                " callables=%s, calling_uri=_template_uri,"
                                " module=%s)" %
                                (
                                   node.name,
                                   callable_name,
                                   node.parsed_attributes.get('module', 'None')
                                )
                            )
            else:
                self.printer.writeline(
                                "ns = runtime.Namespace(%r,"
                                " context._clean_inheritance_tokens(),"
                                " callables=%s, calling_uri=_template_uri)" %
                                (
                                    node.name,
                                    callable_name,
                                )
                            )
            if eval(node.attributes.get('inheritable', "False")):
                self.printer.writeline("context['self'].%s = ns" % (node.name))

            self.printer.writeline(
                   "context.namespaces[(__name__, %s)] = ns" % repr(node.name))
            self.printer.write("\n")
        if not len(namespaces):
            self.printer.writeline("pass")
        self.printer.writeline(None)

    def write_variable_declares(self, identifiers, toplevel=False, limit=None):
        """write variable declarations at the top of a function.

        the variable declarations are in the form of callable
        definitions for defs and/or name lookup within the
        function's context argument. the names declared are based
        on the names that are referenced in the function body,
        which don't otherwise have any explicit assignment
        operation. names that are assigned within the body are
        assumed to be locally-scoped variables and are not
        separately declared.

        for def callable definitions, if the def is a top-level
        callable then a 'stub' callable is generated which wraps
        the current Context into a closure. if the def is not
        top-level, it is fully rendered as a local closure.

        """

        # collection of all defs available to us in this scope
        comp_idents = dict([(c.funcname, c) for c in identifiers.defs])
        to_write = set()

        # write "context.get()" for all variables we are going to
        # need that arent in the namespace yet
        to_write = to_write.union(identifiers.undeclared)

        # write closure functions for closures that we define
        # right here
        to_write = to_write.union(
                        [c.funcname for c in identifiers.closuredefs.values()])

        # remove identifiers that are declared in the argument
        # signature of the callable
        to_write = to_write.difference(identifiers.argument_declared)

        # remove identifiers that we are going to assign to.
        # in this way we mimic Python's behavior,
        # i.e. assignment to a variable within a block
        # means that variable is now a "locally declared" var,
        # which cannot be referenced beforehand.
        to_write = to_write.difference(identifiers.locally_declared)

        if self.compiler.enable_loop:
            has_loop = "loop" in to_write
            to_write.discard("loop")
        else:
            has_loop = False

        # if a limiting set was sent, constraint to those items in that list
        # (this is used for the caching decorator)
        if limit is not None:
            to_write = to_write.intersection(limit)

        if toplevel and getattr(self.compiler, 'has_ns_imports', False):
            self.printer.writeline("_import_ns = {}")
            self.compiler.has_imports = True
            for ident, ns in self.compiler.namespaces.items():
                if 'import' in ns.attributes:
                    self.printer.writeline(
                            "_mako_get_namespace(context, %r)."\
                                    "_populate(_import_ns, %r)" %
                            (
                                ident,
                                re.split(r'\s*,\s*', ns.attributes['import'])
                            ))

        if has_loop:
            self.printer.writeline(
                'loop = __M_loop = runtime.LoopStack()'
            )

        for ident in to_write:
            if ident in comp_idents:
                comp = comp_idents[ident]
                if comp.is_block:
                    if not comp.is_anonymous:
                        self.write_def_decl(comp, identifiers)
                    else:
                        self.write_inline_def(comp, identifiers, nested=True)
                else:
                    if comp.is_root():
                        self.write_def_decl(comp, identifiers)
                    else:
                        self.write_inline_def(comp, identifiers, nested=True)

            elif ident in self.compiler.namespaces:
                self.printer.writeline(
                            "%s = _mako_get_namespace(context, %r)" %
                                (ident, ident)
                            )
            else:
                if getattr(self.compiler, 'has_ns_imports', False):
                    if self.compiler.strict_undefined:
                        self.printer.writelines(
                        "%s = _import_ns.get(%r, UNDEFINED)" %
                        (ident, ident),
                        "if %s is UNDEFINED:" % ident,
                            "try:",
                                "%s = context[%r]" % (ident, ident),
                            "except KeyError:",
                                "raise NameError(\"'%s' is not defined\")" %
                                    ident,
                            None, None
                        )
                    else:
                        self.printer.writeline(
                        "%s = _import_ns.get(%r, context.get(%r, UNDEFINED))" %
                        (ident, ident, ident))
                else:
                    if self.compiler.strict_undefined:
                        self.printer.writelines(
                            "try:",
                                "%s = context[%r]" % (ident, ident),
                            "except KeyError:",
                                "raise NameError(\"'%s' is not defined\")" %
                                    ident,
                            None
                        )
                    else:
                        self.printer.writeline(
                            "%s = context.get(%r, UNDEFINED)" % (ident, ident)
                        )

        self.printer.writeline("__M_writer = context.writer()")

    def write_source_comment(self, node):
        """write a source comment containing the line number of the
        corresponding template line."""
        if self.last_source_line != node.lineno:
            self.printer.writeline("# SOURCE LINE %d" % node.lineno)
            self.last_source_line = node.lineno

    def write_def_decl(self, node, identifiers):
        """write a locally-available callable referencing a top-level def"""
        funcname = node.funcname
        namedecls = node.get_argument_expressions()
        nameargs = node.get_argument_expressions(include_defaults=False)

        if not self.in_def and (
                                len(self.identifiers.locally_assigned) > 0 or
                                len(self.identifiers.argument_declared) > 0):
            nameargs.insert(0, 'context.locals_(__M_locals)')
        else:
            nameargs.insert(0, 'context')
        self.printer.writeline("def %s(%s):" % (funcname, ",".join(namedecls)))
        self.printer.writeline(
                       "return render_%s(%s)" % (funcname, ",".join(nameargs)))
        self.printer.writeline(None)

    def write_inline_def(self, node, identifiers, nested):
        """write a locally-available def callable inside an enclosing def."""

        namedecls = node.get_argument_expressions()

        decorator = node.decorator
        if decorator:
            self.printer.writeline(
                          "@runtime._decorate_inline(context, %s)" % decorator)
        self.printer.writeline(
                          "def %s(%s):" % (node.funcname, ",".join(namedecls)))
        filtered = len(node.filter_args.args) > 0
        buffered = eval(node.attributes.get('buffered', 'False'))
        cached = eval(node.attributes.get('cached', 'False'))
        self.printer.writelines(
            # push new frame, assign current frame to __M_caller
            "__M_caller = context.caller_stack._push_frame()",
            "try:"
            )
        if buffered or filtered or cached:
            self.printer.writelines(
                "context._push_buffer()",
                )

        identifiers = identifiers.branch(node, nested=nested)

        self.write_variable_declares(identifiers)

        self.identifier_stack.append(identifiers)
        for n in node.nodes:
            n.accept_visitor(self)
        self.identifier_stack.pop()

        self.write_def_finish(node, buffered, filtered, cached)
        self.printer.writeline(None)
        if cached:
            self.write_cache_decorator(node, node.funcname,
                                        namedecls, False, identifiers,
                                        inline=True, toplevel=False)

    def write_def_finish(self, node, buffered, filtered, cached,
            callstack=True):
        """write the end section of a rendering function, either outermost or
        inline.

        this takes into account if the rendering function was filtered,
        buffered, etc.  and closes the corresponding try: block if any, and
        writes code to retrieve captured content, apply filters, send proper
        return value."""

        if not buffered and not cached and not filtered:
            self.printer.writeline("return ''")
            if callstack:
                self.printer.writelines(
                    "finally:",
                        "context.caller_stack._pop_frame()",
                    None
                )

        if buffered or filtered or cached:
            if buffered or cached:
                # in a caching scenario, don't try to get a writer
                # from the context after popping; assume the caching
                # implemenation might be using a context with no
                # extra buffers
                self.printer.writelines(
                    "finally:",
                        "__M_buf = context._pop_buffer()"
                )
            else:
                self.printer.writelines(
                   "finally:",
                       "__M_buf, __M_writer = context._pop_buffer_and_writer()"
                )

            if callstack:
                self.printer.writeline("context.caller_stack._pop_frame()")

            s = "__M_buf.getvalue()"
            if filtered:
                s = self.create_filter_callable(node.filter_args.args, s,
                                                False)
            self.printer.writeline(None)
            if buffered and not cached:
                s = self.create_filter_callable(self.compiler.buffer_filters,
                                                s, False)
            if buffered or cached:
                self.printer.writeline("return %s" % s)
            else:
                self.printer.writelines(
                    "__M_writer(%s)" % s,
                    "return ''"
                )

    def write_cache_decorator(self, node_or_pagetag, name,
                                    args, buffered, identifiers,
                                    inline=False, toplevel=False):
        """write a post-function decorator to replace a rendering
            callable with a cached version of itself."""

        self.printer.writeline("__M_%s = %s" % (name, name))
        cachekey = node_or_pagetag.parsed_attributes.get('cache_key',
                                                         repr(name))

        cache_args = {}
        if self.compiler.pagetag is not None:
            cache_args.update(
                (
                    pa[6:],
                    self.compiler.pagetag.parsed_attributes[pa]
                )
                for pa in self.compiler.pagetag.parsed_attributes
                if pa.startswith('cache_') and pa != 'cache_key'
            )
        cache_args.update(
            (
                pa[6:],
                node_or_pagetag.parsed_attributes[pa]
            ) for pa in node_or_pagetag.parsed_attributes
            if pa.startswith('cache_') and pa != 'cache_key'
        )
        if 'timeout' in cache_args:
            cache_args['timeout'] = int(eval(cache_args['timeout']))

        self.printer.writeline("def %s(%s):" % (name, ','.join(args)))

        # form "arg1, arg2, arg3=arg3, arg4=arg4", etc.
        pass_args = [
                        '=' in a and "%s=%s" % ((a.split('=')[0],)*2) or a
                        for a in args
                    ]

        self.write_variable_declares(
                            identifiers,
                            toplevel=toplevel,
                            limit=node_or_pagetag.undeclared_identifiers()
                        )
        if buffered:
            s = "context.get('local')."\
                "cache._ctx_get_or_create("\
                "%s, lambda:__M_%s(%s),  context, %s__M_defname=%r)" % \
                            (cachekey, name, ','.join(pass_args),
                            ''.join(["%s=%s, " % (k, v)
                            for k, v in cache_args.items()]),
                            name
                            )
            # apply buffer_filters
            s = self.create_filter_callable(self.compiler.buffer_filters, s,
                                            False)
            self.printer.writelines("return " + s, None)
        else:
            self.printer.writelines(
                    "__M_writer(context.get('local')."
                    "cache._ctx_get_or_create("\
                    "%s, lambda:__M_%s(%s), context, %s__M_defname=%r))" %
                    (cachekey, name, ','.join(pass_args),
                    ''.join(["%s=%s, " % (k, v)
                        for k, v in cache_args.items()]),
                    name,
                    ),
                    "return ''",
                None
            )

    def create_filter_callable(self, args, target, is_expression):
        """write a filter-applying expression based on the filters
        present in the given filter names, adjusting for the global
        'default' filter aliases as needed."""

        def locate_encode(name):
            if re.match(r'decode\..+', name):
                return "filters." + name
            elif self.compiler.disable_unicode:
                return filters.NON_UNICODE_ESCAPES.get(name, name)
            else:
                return filters.DEFAULT_ESCAPES.get(name, name)

        if 'n' not in args:
            if is_expression:
                if self.compiler.pagetag:
                    args = self.compiler.pagetag.filter_args.args + args
                if self.compiler.default_filters:
                    args = self.compiler.default_filters + args
        for e in args:
            # if filter given as a function, get just the identifier portion
            if e == 'n':
                continue
            m = re.match(r'(.+?)(\(.*\))', e)
            if m:
                (ident, fargs) = m.group(1,2)
                f = locate_encode(ident)
                e = f + fargs
            else:
                x = e
                e = locate_encode(e)
                assert e is not None
            target = "%s(%s)" % (e, target)
        return target

    def visitExpression(self, node):
        self.write_source_comment(node)
        if len(node.escapes) or \
                (
                    self.compiler.pagetag is not None and
                    len(self.compiler.pagetag.filter_args.args)
                ) or \
                len(self.compiler.default_filters):

            s = self.create_filter_callable(node.escapes_code.args,
                                            "%s" % node.text, True)
            self.printer.writeline("__M_writer(%s)" % s)
        else:
            self.printer.writeline("__M_writer(%s)" % node.text)

    def visitControlLine(self, node):
        if node.isend:
            self.printer.writeline(None)
            if node.has_loop_context:
                self.printer.writeline('finally:')
                self.printer.writeline("loop = __M_loop._exit()")
                self.printer.writeline(None)
        else:
            self.write_source_comment(node)
            if self.compiler.enable_loop and node.keyword == 'for':
                text = mangle_mako_loop(node, self.printer)
            else:
                text = node.text
            self.printer.writeline(text)
            children = node.get_children()
            # this covers the three situations where we want to insert a pass:
            #    1) a ternary control line with no children,
            #    2) a primary control line with nothing but its own ternary
            #          and end control lines, and
            #    3) any control line with no content other than comments
            if not children or (
                    compat.all(isinstance(c, (parsetree.Comment,
                                            parsetree.ControlLine))
                             for c in children) and
                    compat.all((node.is_ternary(c.keyword) or c.isend)
                             for c in children
                             if isinstance(c, parsetree.ControlLine))):
                self.printer.writeline("pass")

    def visitText(self, node):
        self.write_source_comment(node)
        self.printer.writeline("__M_writer(%s)" % repr(node.content))

    def visitTextTag(self, node):
        filtered = len(node.filter_args.args) > 0
        if filtered:
            self.printer.writelines(
                "__M_writer = context._push_writer()",
                "try:",
            )
        for n in node.nodes:
            n.accept_visitor(self)
        if filtered:
            self.printer.writelines(
                "finally:",
                "__M_buf, __M_writer = context._pop_buffer_and_writer()",
                "__M_writer(%s)" %
                self.create_filter_callable(
                                node.filter_args.args,
                                "__M_buf.getvalue()",
                                False),
                None
                )

    def visitCode(self, node):
        if not node.ismodule:
            self.write_source_comment(node)
            self.printer.write_indented_block(node.text)

            if not self.in_def and len(self.identifiers.locally_assigned) > 0:
                # if we are the "template" def, fudge locally
                # declared/modified variables into the "__M_locals" dictionary,
                # which is used for def calls within the same template,
                # to simulate "enclosing scope"
                self.printer.writeline(
                      '__M_locals_builtin_stored = __M_locals_builtin()')
                self.printer.writeline(
                      '__M_locals.update(__M_dict_builtin([(__M_key,'
                      ' __M_locals_builtin_stored[__M_key]) for __M_key in'
                      ' [%s] if __M_key in __M_locals_builtin_stored]))' %
                      ','.join([repr(x) for x in node.declared_identifiers()]))

    def visitIncludeTag(self, node):
        self.write_source_comment(node)
        args = node.attributes.get('args')
        if args:
            self.printer.writeline(
                      "runtime._include_file(context, %s, _template_uri, %s)" %
                      (node.parsed_attributes['file'], args))
        else:
            self.printer.writeline(
                        "runtime._include_file(context, %s, _template_uri)" %
                        (node.parsed_attributes['file']))

    def visitNamespaceTag(self, node):
        pass

    def visitDefTag(self, node):
        pass

    def visitBlockTag(self, node):
        if node.is_anonymous:
            self.printer.writeline("%s()" % node.funcname)
        else:
            nameargs = node.get_argument_expressions(include_defaults=False)
            nameargs += ['**pageargs']
            self.printer.writeline("if 'parent' not in context._data or "
                                  "not hasattr(context._data['parent'], '%s'):"
                                  % node.funcname)
            self.printer.writeline(
                "context['self'].%s(%s)" % (node.funcname, ",".join(nameargs)))
            self.printer.writeline("\n")

    def visitCallNamespaceTag(self, node):
        # TODO: we can put namespace-specific checks here, such
        # as ensure the given namespace will be imported,
        # pre-import the namespace, etc.
        self.visitCallTag(node)

    def visitCallTag(self, node):
        self.printer.writeline("def ccall(caller):")
        export = ['body']
        callable_identifiers = self.identifiers.branch(node, nested=True)
        body_identifiers = callable_identifiers.branch(node, nested=False)
        # we want the 'caller' passed to ccall to be used
        # for the body() function, but for other non-body()
        # <%def>s within <%call> we want the current caller
        # off the call stack (if any)
        body_identifiers.add_declared('caller')

        self.identifier_stack.append(body_identifiers)
        class DefVisitor(object):
            def visitDefTag(s, node):
                s.visitDefOrBase(node)

            def visitBlockTag(s, node):
                s.visitDefOrBase(node)

            def visitDefOrBase(s, node):
                self.write_inline_def(node, callable_identifiers, nested=False)
                if not node.is_anonymous:
                    export.append(node.funcname)
                # remove defs that are within the <%call> from the
                # "closuredefs" defined in the body, so they dont render twice
                if node.funcname in body_identifiers.closuredefs:
                    del body_identifiers.closuredefs[node.funcname]

        vis = DefVisitor()
        for n in node.nodes:
            n.accept_visitor(vis)
        self.identifier_stack.pop()

        bodyargs = node.body_decl.get_argument_expressions()
        self.printer.writeline("def body(%s):" % ','.join(bodyargs))

        # TODO: figure out best way to specify
        # buffering/nonbuffering (at call time would be better)
        buffered = False
        if buffered:
            self.printer.writelines(
                "context._push_buffer()",
                "try:"
            )
        self.write_variable_declares(body_identifiers)
        self.identifier_stack.append(body_identifiers)

        for n in node.nodes:
            n.accept_visitor(self)
        self.identifier_stack.pop()

        self.write_def_finish(node, buffered, False, False, callstack=False)
        self.printer.writelines(
            None,
            "return [%s]" % (','.join(export)),
            None
        )

        self.printer.writelines(
            # push on caller for nested call
            "context.caller_stack.nextcaller = "
                "runtime.Namespace('caller', context, "
                                  "callables=ccall(__M_caller))",
            "try:")
        self.write_source_comment(node)
        self.printer.writelines(
                "__M_writer(%s)" % self.create_filter_callable(
                                                    [], node.expression, True),
            "finally:",
                "context.caller_stack.nextcaller = None",
            None
        )

class _Identifiers(object):
    """tracks the status of identifier names as template code is rendered."""

    def __init__(self, compiler, node=None, parent=None, nested=False):
        if parent is not None:
            # if we are the branch created in write_namespaces(),
            # we don't share any context from the main body().
            if isinstance(node, parsetree.NamespaceTag):
                self.declared = set()
                self.topleveldefs = util.SetLikeDict()
            else:
                # things that have already been declared
                # in an enclosing namespace (i.e. names we can just use)
                self.declared = set(parent.declared).\
                         union([c.name for c in parent.closuredefs.values()]).\
                         union(parent.locally_declared).\
                         union(parent.argument_declared)

                # if these identifiers correspond to a "nested"
                # scope, it means whatever the parent identifiers
                # had as undeclared will have been declared by that parent,
                # and therefore we have them in our scope.
                if nested:
                    self.declared = self.declared.union(parent.undeclared)

                # top level defs that are available
                self.topleveldefs = util.SetLikeDict(**parent.topleveldefs)
        else:
            self.declared = set()
            self.topleveldefs = util.SetLikeDict()

        self.compiler = compiler

        # things within this level that are referenced before they
        # are declared (e.g. assigned to)
        self.undeclared = set()

        # things that are declared locally.  some of these things
        # could be in the "undeclared" list as well if they are
        # referenced before declared
        self.locally_declared = set()

        # assignments made in explicit python blocks.
        # these will be propagated to
        # the context of local def calls.
        self.locally_assigned = set()

        # things that are declared in the argument
        # signature of the def callable
        self.argument_declared = set()

        # closure defs that are defined in this level
        self.closuredefs = util.SetLikeDict()

        self.node = node

        if node is not None:
            node.accept_visitor(self)

        illegal_names = self.compiler.reserved_names.intersection(
                                                         self.locally_declared)
        if illegal_names:
            raise exceptions.NameConflictError(
                "Reserved words declared in template: %s" %
                ", ".join(illegal_names))


    def branch(self, node, **kwargs):
        """create a new Identifiers for a new Node, with
          this Identifiers as the parent."""

        return _Identifiers(self.compiler, node, self, **kwargs)

    @property
    def defs(self):
        return set(self.topleveldefs.union(self.closuredefs).values())

    def __repr__(self):
        return "Identifiers(declared=%r, locally_declared=%r, "\
                "undeclared=%r, topleveldefs=%r, closuredefs=%r, "\
                "argumentdeclared=%r)" %\
                (
                    list(self.declared),
                    list(self.locally_declared),
                    list(self.undeclared),
                    [c.name for c in self.topleveldefs.values()],
                    [c.name for c in self.closuredefs.values()],
                    self.argument_declared)

    def check_declared(self, node):
        """update the state of this Identifiers with the undeclared
            and declared identifiers of the given node."""

        for ident in node.undeclared_identifiers():
            if ident != 'context' and\
                       ident not in self.declared.union(self.locally_declared):
                self.undeclared.add(ident)
        for ident in node.declared_identifiers():
            self.locally_declared.add(ident)

    def add_declared(self, ident):
        self.declared.add(ident)
        if ident in self.undeclared:
            self.undeclared.remove(ident)

    def visitExpression(self, node):
        self.check_declared(node)

    def visitControlLine(self, node):
        self.check_declared(node)

    def visitCode(self, node):
        if not node.ismodule:
            self.check_declared(node)
            self.locally_assigned = self.locally_assigned.union(
                                                   node.declared_identifiers())

    def visitNamespaceTag(self, node):
        # only traverse into the sub-elements of a
        # <%namespace> tag if we are the branch created in
        # write_namespaces()
        if self.node is node:
            for n in node.nodes:
                n.accept_visitor(self)

    def _check_name_exists(self, collection, node):
        existing = collection.get(node.funcname)
        collection[node.funcname] = node
        if existing is not None and \
            existing is not node and \
            (node.is_block or existing.is_block):
            raise exceptions.CompileException(
                    "%%def or %%block named '%s' already "
                    "exists in this template." %
                    node.funcname, **node.exception_kwargs)

    def visitDefTag(self, node):
        if node.is_root() and not node.is_anonymous:
            self._check_name_exists(self.topleveldefs, node)
        elif node is not self.node:
            self._check_name_exists(self.closuredefs, node)

        for ident in node.undeclared_identifiers():
            if ident != 'context' and\
                       ident not in self.declared.union(self.locally_declared):
                self.undeclared.add(ident)

        # visit defs only one level deep
        if node is self.node:
            for ident in node.declared_identifiers():
                self.argument_declared.add(ident)

            for n in node.nodes:
                n.accept_visitor(self)

    def visitBlockTag(self, node):
        if node is not self.node and \
            not node.is_anonymous:

            if isinstance(self.node, parsetree.DefTag):
                raise exceptions.CompileException(
                        "Named block '%s' not allowed inside of def '%s'"
                        % (node.name, self.node.name), **node.exception_kwargs)
            elif isinstance(self.node,
                            (parsetree.CallTag, parsetree.CallNamespaceTag)):
                raise exceptions.CompileException(
                        "Named block '%s' not allowed inside of <%%call> tag"
                        % (node.name, ), **node.exception_kwargs)

        for ident in node.undeclared_identifiers():
            if ident != 'context' and \
                       ident not in self.declared.union(self.locally_declared):
                self.undeclared.add(ident)

        if not node.is_anonymous:
            self._check_name_exists(self.topleveldefs, node)
            self.undeclared.add(node.funcname)
        elif node is not self.node:
            self._check_name_exists(self.closuredefs, node)
        for ident in node.declared_identifiers():
            self.argument_declared.add(ident)
        for n in node.nodes:
            n.accept_visitor(self)

    def visitTextTag(self, node):
        for ident in node.undeclared_identifiers():
            if ident != 'context' and \
                ident not in self.declared.union(self.locally_declared):
                self.undeclared.add(ident)

    def visitIncludeTag(self, node):
        self.check_declared(node)

    def visitPageTag(self, node):
        for ident in node.declared_identifiers():
            self.argument_declared.add(ident)
        self.check_declared(node)

    def visitCallNamespaceTag(self, node):
        self.visitCallTag(node)

    def visitCallTag(self, node):
        if node is self.node:
            for ident in node.undeclared_identifiers():
                if ident != 'context' and\
                       ident not in self.declared.union(self.locally_declared):
                    self.undeclared.add(ident)
            for ident in node.declared_identifiers():
                self.argument_declared.add(ident)
            for n in node.nodes:
                n.accept_visitor(self)
        else:
            for ident in node.undeclared_identifiers():
                if ident != 'context' and\
                       ident not in self.declared.union(self.locally_declared):
                    self.undeclared.add(ident)


_FOR_LOOP = re.compile(
        r'^for\s+((?:\(?)\s*[A-Za-z_][A-Za-z_0-9]*'
        r'(?:\s*,\s*(?:[A-Za-z_][A-Za-z0-9_]*),??)*\s*(?:\)?))\s+in\s+(.*):'
    )

def mangle_mako_loop(node, printer):
    """converts a for loop into a context manager wrapped around a for loop
    when access to the `loop` variable has been detected in the for loop body
    """
    loop_variable = LoopVariable()
    node.accept_visitor(loop_variable)
    if loop_variable.detected:
        node.nodes[-1].has_loop_context = True
        match = _FOR_LOOP.match(node.text)
        if match:
            printer.writelines(
                    'loop = __M_loop._enter(%s)' % match.group(2),
                    'try:'
                    #'with __M_loop(%s) as loop:' % match.group(2)
                )
            text = 'for %s in loop:' % match.group(1)
        else:
            raise SyntaxError("Couldn't apply loop context: %s" % node.text)
    else:
        text = node.text
    return text


class LoopVariable(object):
    """A node visitor which looks for the name 'loop' within undeclared
    identifiers."""

    def __init__(self):
        self.detected = False

    def _loop_reference_detected(self, node):
        if 'loop' in node.undeclared_identifiers():
            self.detected = True
        else:
            for n in node.get_children():
                n.accept_visitor(self)

    def visitControlLine(self, node):
        self._loop_reference_detected(node)

    def visitCode(self, node):
        self._loop_reference_detected(node)

    def visitExpression(self, node):
        self._loop_reference_detected(node)
