class Symbol(object):
    def __init__(self, name, type="Element", is_global=False, node=None, params=None):
        self.name = name
        self.type = type
        self.is_global = is_global
        self.node = node
        self.params = params

    @staticmethod
    def is_func(symb):
        return symb['params'] is not None

    @staticmethod
    def signature(symb):
        if Symbol.is_func(symb):
            params = ", ".join([str(t) for t in symb['params']])
            return "{} function {}({})".format(str(symb['type']),
                                               symb['name'], params)
        else:
            return symb['name']

class SymbolTable(object):
    def __init__(self):
        self.stacks = []

    def open_scope(self):
        self.stacks.append({})

    def close_scope(self):
        self.stacks.pop()

    def add(self, symbol):
        if symbol['name'] in self.stacks[-1]:
            raise Exception("Redefinition of symbol " + str(symbol))
        else:
            self.stacks[-1][symbol['name']] = symbol

    def get(self, name):
        for frame in reversed(self.stacks):
            try:
                return frame[name]
            except KeyError:
                # Not in this scope, so keep going
                pass
        raise KeyError("Undefined symbol: " + name)
