# 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(as_call=True)

        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 = [
                        "%s=%s" % ((a.split('=')[0],) * 2) if '=' in a else 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:
                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(as_call=True)
            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)
