# mako/codegen.py
# Copyright (C) 2006-2014 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 = 9

# 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("# -*- coding:%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)
