"""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, \
     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 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 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.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.__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 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()
