"""Interface to the compiler's internal symbol tables"""

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, \
     OPT_IMPORT_STAR, OPT_EXEC, OPT_BARE_EXEC

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 is_free(flags):
    if (flags & (USE | DEF_FREE)) \
       and (flags & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)):
        return True
    if flags & DEF_FREE_CLASS:
        return True
    return False

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 true if the scope uses exec"""
        return bool(self._table.optimized & (OPT_EXEC | OPT_BARE_EXEC))

    def has_import_star(self):
        """Return true if the scope uses import *"""
        return bool(self._table.optimized & OPT_IMPORT_STAR)

    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)
        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.__flags & DEF_STAR)

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

    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 True
        if self.__flags & DEF_FREE_CLASS:
            return True
        return False

    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()
