# mako/ast.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

"""utilities for analyzing expressions and blocks of Python
code, as well as generating Python from AST nodes"""

from mako import exceptions, pyparser, compat
from mako.compat import arg_stringname
import re

class PythonCode(object):
    """represents information about a string containing Python code"""
    def __init__(self, code, **exception_kwargs):
        self.code = code

        # represents all identifiers which are assigned to at some point in
        # the code
        self.declared_identifiers = set()

        # represents all identifiers which are referenced before their
        # assignment, if any
        self.undeclared_identifiers = set()

        # note that an identifier can be in both the undeclared and declared
        # lists.

        # using AST to parse instead of using code.co_varnames,
        # code.co_names has several advantages:
        # - we can locate an identifier as "undeclared" even if
        # its declared later in the same block of code
        # - AST is less likely to break with version changes
        # (for example, the behavior of co_names changed a little bit
        # in python version 2.5)
        if isinstance(code, compat.string_types):
            expr = pyparser.parse(code.lstrip(), "exec", **exception_kwargs)
        else:
            expr = code

        f = pyparser.FindIdentifiers(self, **exception_kwargs)
        f.visit(expr)

class ArgumentList(object):
    """parses a fragment of code as a comma-separated list of expressions"""
    def __init__(self, code, **exception_kwargs):
        self.codeargs = []
        self.args = []
        self.declared_identifiers = set()
        self.undeclared_identifiers = set()
        if isinstance(code, compat.string_types):
            if re.match(r"\S", code) and not re.match(r",\s*$", code):
                # if theres text and no trailing comma, insure its parsed
                # as a tuple by adding a trailing comma
                code  += ","
            expr = pyparser.parse(code, "exec", **exception_kwargs)
        else:
            expr = code

        f = pyparser.FindTuple(self, PythonCode, **exception_kwargs)
        f.visit(expr)

class PythonFragment(PythonCode):
    """extends PythonCode to provide identifier lookups in partial control
    statements

    e.g.
        for x in 5:
        elif y==9:
        except (MyException, e):
    etc.
    """
    def __init__(self, code, **exception_kwargs):
        m = re.match(r'^(\w+)(?:\s+(.*?))?:\s*(#|$)', code.strip(), re.S)
        if not m:
            raise exceptions.CompileException(
                          "Fragment '%s' is not a partial control statement" %
                          code, **exception_kwargs)
        if m.group(3):
            code = code[:m.start(3)]
        (keyword, expr) = m.group(1,2)
        if keyword in ['for','if', 'while']:
            code = code + "pass"
        elif keyword == 'try':
            code = code + "pass\nexcept:pass"
        elif keyword == 'elif' or keyword == 'else':
            code = "if False:pass\n" + code + "pass"
        elif keyword == 'except':
            code = "try:pass\n" + code + "pass"
        elif keyword == 'with':
            code = code + "pass"
        else:
            raise exceptions.CompileException(
                                "Unsupported control keyword: '%s'" %
                                keyword, **exception_kwargs)
        super(PythonFragment, self).__init__(code, **exception_kwargs)


class FunctionDecl(object):
    """function declaration"""
    def __init__(self, code, allow_kwargs=True, **exception_kwargs):
        self.code = code
        expr = pyparser.parse(code, "exec", **exception_kwargs)

        f = pyparser.ParseFunc(self, **exception_kwargs)
        f.visit(expr)
        if not hasattr(self, 'funcname'):
            raise exceptions.CompileException(
                              "Code '%s' is not a function declaration" % code,
                              **exception_kwargs)
        if not allow_kwargs and self.kwargs:
            raise exceptions.CompileException(
                                "'**%s' keyword argument not allowed here" %
                                self.kwargnames[-1], **exception_kwargs)

    def get_argument_expressions(self, as_call=False):
        """Return the argument declarations of this FunctionDecl as a printable
        list.

        By default the return value is appropriate for writing in a ``def``;
        set `as_call` to true to build arguments to be passed to the function
        instead (assuming locals with the same names as the arguments exist).
        """

        namedecls = []

        # Build in reverse order, since defaults and slurpy args come last
        argnames = self.argnames[::-1]
        kwargnames = self.kwargnames[::-1]
        defaults = self.defaults[::-1]
        kwdefaults = self.kwdefaults[::-1]

        # Named arguments
        if self.kwargs:
            namedecls.append("**" + kwargnames.pop(0))

        for name in kwargnames:
            # Keyword-only arguments must always be used by name, so even if
            # this is a call, print out `foo=foo`
            if as_call:
                namedecls.append("%s=%s" % (name, name))
            elif kwdefaults:
                default = kwdefaults.pop(0)
                if default is None:
                    # The AST always gives kwargs a default, since you can do
                    # `def foo(*, a=1, b, c=3)`
                    namedecls.append(name)
                else:
                    namedecls.append("%s=%s" % (
                        name, pyparser.ExpressionGenerator(default).value()))
            else:
                namedecls.append(name)

        # Positional arguments
        if self.varargs:
            namedecls.append("*" + argnames.pop(0))

        for name in argnames:
            if as_call or not defaults:
                namedecls.append(name)
            else:
                default = defaults.pop(0)
                namedecls.append("%s=%s" % (
                    name, pyparser.ExpressionGenerator(default).value()))

        namedecls.reverse()
        return namedecls

    @property
    def allargnames(self):
        return tuple(self.argnames) + tuple(self.kwargnames)

class FunctionArgs(FunctionDecl):
    """the argument portion of a function declaration"""

    def __init__(self, code, **kwargs):
        super(FunctionArgs, self).__init__("def ANON(%s):pass" % code,
                **kwargs)
