"""Interface to the compiler's internal symbol tables"""
from __future__ import nested_scopes

import _symtable
from _symtable import USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM, \
     DEF_STAR, DEF_DOUBLESTAR, DEF_INTUPLE, DEF_FREE, \
     DEF_FREE_GLOBAL, DEF_FREE_CLASS, DEF_IMPORT, DEF_BOUND

import weakref

__all__ = ["symtable", "SymbolTable", "newSymbolTable", "Class",
           "Function", "Symbol"]

def symtable(code, filename, compile_type):
    raw = _symtable.symtable(code, filename, compile_type)
    return newSymbolTable(raw[0], filename)

class SymbolTableFactory:
    def __init__(self):
        self.__memo = weakref.WeakValueDictionary()

    def new(self, table, filename):
        if table.type == _symtable.TYPE_FUNCTION:
            return Function(table, filename)
        if table.type == _symtable.TYPE_CLASS:
            return Class(table, filename)
        return SymbolTable(table, filename)

    def __call__(self, table, filename):
        key = table, filename
        obj = self.__memo.get(key, None)
        if obj is None:
            obj = self.__memo[key] = self.new(table, filename)
        return obj

newSymbolTable = SymbolTableFactory()

def bool(x):
    """Helper to force boolean result to 1 or 0"""
    if x:
        return 1
    return 0

def is_free(flags):
    if (flags & (USE | DEF_FREE)) \
       and (flags & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)):
        return 1
    if flags & DEF_FREE_CLASS:
        return 1
    return 0

class SymbolTable:
    def __init__(self, raw_table, filename):
        self._table = raw_table
        self._filename = filename
        self._symbols = {}

    def __repr__(self):
        if self.__class__ == SymbolTable:
            kind = ""
        else:
            kind = "%s " % self.__class__.__name__

        if self._table.name == "global":
            return "<%sSymbolTable for module %s>" % (kind, self._filename)
        else:
            return "<%sSymbolTable for %s in %s>" % (kind, self._table.name,
                                                     self._filename)

    def get_type(self):
        if self._table.type == _symtable.TYPE_MODULE:
            return "module"
        if self._table.type == _symtable.TYPE_FUNCTION:
            return "function"
        if self._table.type == _symtable.TYPE_CLASS:
            return "class"
        assert self._table.type in (1, 2, 3), \
               "unexpected type: %s" % self._table.type

    def get_id(self):
        return self._table.id

    def get_name(self):
        return self._table.name

    def get_lineno(self):
        return self._table.lineno

    def is_optimized(self):
        return bool(self._table.type == _symtable.TYPE_FUNCTION
                    and not self._table.optimized)

    def is_nested(self):
        return bool(self._table.nested)

    def has_children(self):
        return bool(self._table.children)

    def has_exec(self):
        return bool()

    def get_identifiers(self):
        return self._table.symbols.keys()

    def lookup(self, name):
        sym = self._symbols.get(name)
        if sym is None:
            flags = self._table.symbols[name]
            namespaces = self.__check_children(name)
            sym = self._symbols[name] = Symbol(name, flags, namespaces)
        return sym

    def get_symbols(self):
        return [self.lookup(ident) for ident in self.get_identifiers()]

    def __check_children(self, name):
        return [newSymbolTable(st, self._filename)
                for st in self._table.children
                if st.name == name]

    def get_children(self):
        return [newSymbolTable(st, self._filename)
                for st in self._table.children]

class Function(SymbolTable):

    # Default values for instance variables
    __params = None
    __locals = None
    __frees = None
    __globals = None

    def __idents_matching(self, test_func):
        return tuple([ident for ident in self.get_identifiers()
                      if test_func(self._table.symbols[ident])])

    def get_parameters(self):
        if self.__params is None:
            self.__params = self.__idents_matching(lambda x:x & DEF_PARAM)
        return self.__params

    def get_locals(self):
        if self.__locals is None:
            self.__locals = self.__idents_matching(lambda x:x & DEF_BOUND)
        return self.__locals

    def get_globals(self):
        if self.__globals is None:
            glob = DEF_GLOBAL | DEF_FREE_GLOBAL
            self.__globals = self.__idents_matching(lambda x:x & glob)
        return self.__globals

    def get_frees(self):
        if self.__frees is None:
            self.__frees = self.__idents_matching(is_free)
        return self.__frees

class Class(SymbolTable):

    __methods = None

    def get_methods(self):
        if self.__methods is None:
            d = {}
            for st in self._table.children:
                d[st.name] = 1
            self.__methods = tuple(d.keys())
        return self.__methods

class Symbol:
    def __init__(self, name, flags, namespaces=None):
        self.__name = name
        self.__flags = flags
        self.__namespaces = namespaces or ()

    def __repr__(self):
        return "<symbol '%s'>" % self.__name

    def get_name(self):
        return self.__name

    def is_referenced(self):
        return bool(self.__flags & _symtable.USE)

    def is_parameter(self):
        return bool(self.__flags & DEF_PARAM)

    def is_global(self):
        return bool((self.__flags & DEF_GLOBAL)
                    or (self.__flags & DEF_FREE_GLOBAL))

    def is_vararg(self):
        return bool(self.flag & DEF_STAR)

    def is_keywordarg(self):
        return bool(self.__flags & DEF_STARSTAR)

    def is_local(self):
        return bool(self.__flags & DEF_BOUND)

    def is_free(self):
        if (self.__flags & (USE | DEF_FREE)) \
            and (self.__flags & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)):
            return 1
        if self.__flags & DEF_FREE_CLASS:
            return 1
        return 0

    def is_imported(self):
        return bool(self.__flags & DEF_IMPORT)

    def is_assigned(self):
        return bool(self.__flags & DEF_LOCAL)

    def is_in_tuple(self):
        return bool(self.__flags & DEF_INTUPLE)

    def is_namespace(self):
        """Returns true if name binding introduces new namespace.

        If the name is used as the target of a function or class
        statement, this will be true.

        Note that a single name can be bound to multiple objects.  If
        is_namespace() is true, the name may also be bound to other
        objects, like an int or list, that does not introduce a new
        namespace.
        """
        return bool(self.__namespaces)

    def get_namespaces(self):
        """Return a list of namespaces bound to this name"""
        return self.__namespaces

    def get_namespace(self):
        """Returns the single namespace bound to this name.

        Raises ValueError if the name is bound to multiple namespaces.
        """
        if len(self.__namespaces) != 1:
            raise ValueError, "name is bound to multiple namespaces"
        return self.__namespaces[0]

if __name__ == "__main__":
    import os, sys
    src = open(sys.argv[0]).read()
    mod = symtable(src, os.path.split(sys.argv[0])[1], "exec")
    for ident in mod.get_identifiers():
        info = mod.lookup(ident)
        print info, info.is_local(), info.is_namespace()
