Logo Search packages:      
Sourcecode: fauhdlc version File versions

ResolveSymbols.cpp

/* $Id: ResolveSymbols.cpp 4323 2009-01-27 13:48:12Z potyra $ 
 *
 * Copyright (C) 2008-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 "frontend/visitor/ResolveSymbols.hpp"
#include <cassert>
#include <set>
#include "frontend/ast/SimpleName.hpp"
#include "frontend/ast/TemporaryName.hpp"
#include "frontend/ast/SelectedName.hpp"
#include "frontend/ast/AttributeName.hpp"
#include "frontend/ast/ConcurrentStat.hpp"
#include "frontend/ast/RecordTypeElement.hpp"
#include "frontend/ast/ValDeclaration.hpp"
#include "frontend/ast/PhysicalTypeUnit.hpp"
#include "frontend/ast/EnumerationElement.hpp"
#include "frontend/ast/FunctionDeclaration.hpp"
#include "frontend/ast/EnumerationType.hpp"
#include "frontend/ast/Subscript.hpp"
#include "frontend/ast/Slice.hpp"
#include "frontend/ast/FunctionCall.hpp"
#include "frontend/ast/CompInstStat.hpp"
#include "frontend/reporting/ErrorRegistry.hpp"
#include "frontend/reporting/UndefinedSymbol.hpp"
#include "frontend/visitor/LookupTypes.hpp"
#include "frontend/misc/NameLookup.hpp"

namespace ast {

void
00035 ResolveSymbols::visit(SimpleName &node)
{     
      assert(node.name);
      node.candidates = this->symTab.lookup(*node.name);
      this->prefixCands = &node.candidates;
}

void
00043 ResolveSymbols::visit(TemporaryName &node)
{
      // only traverse to prefix.
      node.prefix->accept(*this);
}

void
00050 ResolveSymbols::visit(SelectedName &node)
{
      node.prefix->accept(*this);
      if (this->prefixCands == NULL) {
            // error reported somewhere else already
            return;
      }

      std::set<Symbol*> symSet = std::set<Symbol*>();

      for (symListT::iterator i = this->prefixCands->begin();
            i != this->prefixCands->end(); /* nothing */) {
            
            LookupTypes lt = LookupTypes(true, false);
            (*i)->declaration.accept(lt);
            if (lt.declaration == NULL) {
                  i = this->prefixCands->erase(i);
                  continue;
            }

            if (lt.declaration->region == NULL) {
                  i = this->prefixCands->erase(i);
                  continue;
            }
            
            symListT c = lt.declaration->region->lookupLocal(*node.name);
            if (c.empty()) {
                  i = this->prefixCands->erase(i);
            }
            
            // candidate found
            symSet.insert(c.begin(), c.end());
            i++;
      }

      if (symSet.empty()) {
            UndefinedSymbol *us = 
                  new UndefinedSymbol(*node.name, node.location);
            ErrorRegistry::addError(us);
            this->prefixCands = NULL;
            return;
      }

      node.candidates.insert(node.candidates.begin(), symSet.begin(), 
                        symSet.end());
      this->prefixCands = &node.candidates;
}

void
00099 ResolveSymbols::visit(AttributeName &node)
{
      assert(false); // attributes not supported yet
}

void
00105 ResolveSymbols::visit(Slice &node)
{
      node.source->accept(*this);
      symListT *backup = this->prefixCands;
      this->prefixCands = NULL;
      
      node.range->accept(*this);
      this->prefixCands = backup;
}

void
00116 ResolveSymbols::visit(Subscript &node)
{
      node.source->accept(*this);
      if (this->prefixCands == NULL) {
            // error reported already
            return;
      }

      symListT *backup = this->prefixCands;
      this->prefixCands = NULL;

      // traverse to indices
      assert(node.indices != NULL);
      this->listTraverse(*node.indices);

      // FIXME mem leak
      this->prefixCands = new symListT();
      *this->prefixCands = NameLookup::shiftSubscriptCands(
                              *backup,
                              node.location);

      if (this->prefixCands->empty()) {
            // error reported already via NameLookup
            delete this->prefixCands;
            this->prefixCands = NULL;
      }
}

void
00145 ResolveSymbols::visit(FunctionCall &node)
{
      this->prefixCands = NULL;
      node.subprog->accept(*this);
      // leave prefixCands as is, AssociationElement will need them to
      // shift the lookup scope.

      if (node.arguments != NULL) {
            this->listTraverse(*node.arguments);
      }

      // leave prefixCands as is, LookupTypes will deal with function symbols
      // as intended.
}

void
00161 ResolveSymbols::visit(AssociationElement &node)
{
      symListT *backup = this->prefixCands;
      this->prefixCands = NULL;

      if (node.formal != NULL) {
            //FIXME not quite correct, but will work atm.
            // 1) no idea, where the formal part is, parsing might
            //    have been wrong (but that should be fixed in the parser)
            // 2) formal names should be looked up only in local scope

            assert(backup->size() == 1);
            Symbol *sym = backup->front();
            assert(sym->region != NULL);
            this->symTab.pushRegion(*sym->region);

            node.formal->accept(*this);
            this->symTab.popRegion();
      }

      assert(node.actual != NULL);
      node.actual->accept(*this);
      this->prefixCands = backup;
}

void
00187 ResolveSymbols::process(Expression &node)
{
      // cannot be part of a name. get rid of prefixCands
      this->prefixCands = NULL;
}

void
00194 ResolveSymbols::visit(CompInstStat &node)
{
      this->prefixCands = NULL;
      assert(node.entityName != NULL);

      // must have been resolved already by the parser!
      if (node.entityName->candidates.size() != 1) {
            // symbol error already reported from parser, bail
            // out early
            return;
      }

      // set prefixCands to instantiated Entity.
      this->prefixCands = &node.entityName->candidates;

      if (node.genericMap != NULL) {
            this->listTraverse(*node.genericMap);
      }

      if (node.portMap != NULL) {
            this->listTraverse(*node.portMap);
      }
      this->prefixCands = NULL;
}

void
00220 ResolveSymbols::process(AstNode &node)
{
      // should not happen, ResolveSymbols is only meant to resolve 
      // formal parts, so make sure we encounter no unhandled node.
      assert(false);
}

}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index