Logo Search packages:      
Sourcecode: fauhdlc version File versions

SymbolTable.cpp

/* $Id: SymbolTable.cpp 4323 2009-01-27 13:48:12Z potyra $
 *
 * SymbolTable: Raw storage facility for symbols.
 *
 * Copyright (C) 2007-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include <cassert>
#include <iostream>
#include <sstream>
#include "frontend/misc/SymbolTable.hpp"
#include "frontend/misc/RegisterBuiltins.hpp"

#define DEBUG 0

namespace ast {

00021 SymbolTable::SymbolTable()
{
}

00025 SymbolTable::~SymbolTable() 
{
      for (std::list<Symbol*>::const_iterator i = this->libraries.begin();
            i != this->libraries.end(); i++) {

            DeclarativeRegion* r = (*i)->region;
            assert(r);
            delete r;
            delete *i;
      }
}

Symbol*
00038 SymbolTable::registerSymbol(
      enum symType type,
      SymbolDeclaration &decl
)
{
      assert(! this->regionStack.empty());
      DeclarativeRegion* current = this->getCurrentRegion();
      Symbol* sym = new Symbol(decl.name, type, NULL, decl);

      // FIXME potyra use s.th. different
      current->registerSymbol(sym);

      /* register builtin operations for type symbols as well. */
      if (type == SYMBOL_TYPE) {
            RegisterBuiltins::regTypeOps(decl, *this);
      }

#if DEBUG
      std::cerr << __func__ << ": register=" << *sym << std::endl;
#endif
      return sym;
}

void
00062 SymbolTable::registerSymbolWithRegion(
      enum symType type,
      ast::SymbolDeclaration &decl)
{
      DeclarativeRegion *current;
      DeclarativeRegion *region;

      current = this->getCurrentRegion();
      assert(current);

      this->pushNewRegion();
      region = this->getCurrentRegion();
      assert(region);

      Symbol *sym = new Symbol(decl.name, type, region, decl);

      current->registerSymbol(sym);
      decl.region = region;

      assert(type != SYMBOL_TYPE); /* shouldn't happen, need to 
                              Register builtins here. */
#if DEBUG   
      std::cerr << __func__ << ": register=" << *sym << std::endl;
#endif
}

void
00089 SymbolTable::pushNewRegion(void)
{
      assert(! this->regionStack.empty());
      DeclarativeRegion* current = this->regionStack.top();
      assert(current);
      DeclarativeRegion* n = new DeclarativeRegion(current);
      this->regionStack.push(n);
}

void
00099 SymbolTable::pushLibrary(Library &node)
{
      // there shouldn't be a parent region on the stack.
      assert(this->regionStack.empty());

      DeclarativeRegion *n = NULL;

      // check for existing libraries with same name.
      for (std::list<Symbol*>::const_iterator i = this->libraries.begin();
            i != this->libraries.end(); i++) {

            if ((*(*i)->name) == (*node.name)) {
                  n = (*i)->region;
                  break;
            }
      }

      // eventually allocate new region.
      if (n == NULL) {
            n = new DeclarativeRegion(NULL);
            Symbol *sym = new Symbol(node.name, SYMBOL_LIBRARY, n, node);
            // push on library list
            this->libraries.push_back(sym);

            // add it to imported symbols (as it must be rendered invisible, in 
            // case a Homograph hides it in the library region, instead of 
            // creating a duplicate name error).
            n->imports.push_back(sym);

            // set the region of the symbol to the current region
            node.region = n;
      }

      // push new region on stack
      this->regionStack.push(n);
}

void
00137 SymbolTable::pushRegion(DeclarativeRegion &region)
{
      assert(! this->regionStack.empty());
      this->regionStack.push(&region);
}

void
00144 SymbolTable::popRegion(void)
{
      assert(! this->regionStack.empty());
      this->regionStack.pop();
}

std::list<Symbol*>
00151 SymbolTable::lookup(const std::string &name) const
{
      DeclarativeRegion *current = this->getCurrentRegion();
      assert(current);
      std::list<Symbol*> ret = current->lookup(name);

#if DEBUG
      std::cerr << __func__ << " for " << name << std::endl;
      for (std::list<Symbol*>::const_iterator i = ret.begin();
            i != ret.end(); i++) {

            std::cerr << "    " << **i << std::endl;
      }
      std::cerr << "----" << std::endl;
#endif

      return ret;
}

void
00171 SymbolTable::importSymbol(Symbol &sym)
{
      DeclarativeRegion* current = this->getCurrentRegion();
      assert(current);

      for (std::list<Symbol*>::const_iterator i = current->imports.begin();
            i != current->imports.end(); i++) {

            if (*i == &sym) {
                  return;
            }
      }

      current->imports.push_back(&sym);
#if DEBUG
      std::cerr << __func__ << ": importing=" << sym << std::endl;
#endif
}

bool
00191 SymbolTable::addlibrary(const std::string &name)
{
      for (std::list<Symbol*>::const_iterator i = this->libraries.begin();
            i != this->libraries.end(); i++) {

            if ((*i)->name && (*(*i)->name == name)) {
                  // library found, import it and return.
                  this->importSymbol(**i);
                  return true;
            }
      }

      return false;
}


void
00208 SymbolTable::lateRegisterAttach(
      enum symType type,
      SymbolDeclaration &decl
)
{
      DeclarativeRegion *current = this->getCurrentRegion();
      assert(current);

      Symbol *sym = new Symbol(decl.name, type, current, decl);
      decl.region = current;
      DeclarativeRegion *check = current->parent;
      assert(check);

      this->popRegion();
      DeclarativeRegion *above = this->getCurrentRegion();
      assert(above == check);

      above->registerSymbol(sym);

      if (type == SYMBOL_TYPE) {
            RegisterBuiltins::regTypeOps(decl, *this);
      }

      this->pushRegion(*current);
}

void
00235 SymbolTable::flipStack(void)
{
      DeclarativeRegion *top = this->getCurrentRegion();
      assert(top);
      this->popRegion();
      DeclarativeRegion *last = this->getCurrentRegion();
      assert(last);
      this->popRegion();
      DeclarativeRegion *check = this->getCurrentRegion();
      assert(check);

      assert(last->parent == check);
      assert(top->parent == check);
      last->parent = top;

      this->pushRegion(*top);
      this->pushRegion(*last);
}

void
00255 SymbolTable::importSymbols(const DeclarativeRegion &region)
{
#if DEBUG
      std::cerr << "importSymbols: region.size()=" 
                << region.declarations.size()
              << " at: " << &region
              << std::endl;
#endif
      for (std::list<Symbol*>::const_iterator i = 
            region.declarations.begin();
            i != region.declarations.end();
            i++) {

            this->importSymbol(**i);
      }
}

DeclarativeRegion*
00273 SymbolTable::getCurrentRegion(void) const
{
      if (this->regionStack.empty()) {
            return NULL;
      }

      return this->regionStack.top();
}

void
00283 SymbolTable::pushStdStandard(void)
{
      bool found = false;
      for (std::list<Symbol*>::const_iterator i = this->libraries.begin();
            i != this->libraries.end(); i++) {

            if (*(*i)->name == "std") {
                  assert((*i)->region != NULL);
                  this->regionStack.push((*i)->region);

                  found = true;
                  break;
            }
      }

      assert(found); /* builtin library std not found if assertion fails */
      
      std::list<Symbol*> p = this->lookup("standard");
      assert(p.size() == 1);
      
      Symbol *ps = p.front();
      assert(ps->type == SYMBOL_PACKAGE); // error in std.standard otherwise
      assert(ps->region != NULL);

      this->regionStack.push(ps->region);
}

TypeDeclaration*
00311 SymbolTable::getStdStandardType(const char *name)
{
      typeMap::iterator i = this->stdStandardTypes.find(name);
      if (i == this->stdStandardTypes.end()) {
            // not found in cache
            this->pushStdStandard();
            std::list<Symbol*> l = this->lookup(name);
            this->popRegion(); // standard
            this->popRegion(); // std

            if (l.size() != 1) {
                  return NULL;
            }

            Symbol *sym = l.front();
            if (sym->type != SYMBOL_TYPE) {
                  // not a type
                  return NULL;
            }

            TypeDeclaration *t = dynamic_cast<TypeDeclaration*>(
                                          &sym->declaration);
            if (! t) {
                  return NULL;
            }

            this->stdStandardTypes[name] = t;
            return t;
      }

      return i->second;
}

std::string
00345 SymbolTable::getMangledPathName(void) const
{
      static int cnt = 0;

      std::stringstream stream;
      stream << "__anonymous__";    // prefix
      stream << cnt;
      cnt++;
      std::string result = stream.str();

      return result;
}

}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index