Logo Search packages:      
Sourcecode: fauhdlc version File versions

ResolveAggregates.cpp

/* $Id: ResolveAggregates.cpp 4323 2009-01-27 13:48:12Z potyra $
 *
 * Resolve ranges of positional and named aggregates.
 *
 * 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/ResolveAggregates.hpp"
#include <cassert>
#include "frontend/ast/Aggregate.hpp"
#include "frontend/ast/Others.hpp"
#include "frontend/ast/ConstInteger.hpp"
#include "frontend/reporting/ErrorRegistry.hpp"

namespace ast {

00020 ResolveAggregates::ResolveAggregates(
      const DiscreteRange &arrayRange
) :
      haveOthers(false),
      named(false),
      positional(false),
      othersErrorReported(false),
      currentRange(NULL),
      sequencer(arrayRange)
{
}

00032 ResolveAggregates::~ResolveAggregates()
{
}

void
00037 ResolveAggregates::visit(Aggregate &node)
{
      assert(node.associations != NULL);

      this->haveOthers = false;
      this->named = false;
      this->positional = false;

      for (std::list<ElementAssociation*>::iterator i = 
            node.associations->begin(); 
            i != node.associations->end();
            i++) {

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

      if (this->named && this->positional) {
            CompileError *ce = 
                  new CompileError(node,
                        "Mixing named with positional association.");
            ErrorRegistry::addError(ce);
            return;
      }

      if (! this->sequencer.rs.empty()) {
            std::string s = 
                  std::string("Indices not covered by aggregate: ");
            s += util::MiscUtil::toString(this->sequencer.rs);

            CompileError *ce = new CompileError(node, s);
            ErrorRegistry::addError(ce);
      }
}

void
00072 ResolveAggregates::visit(ElementAssociation &node)
{
      if (this->haveOthers) {
            // element after an "others" element not allowed.
            if (! this->othersErrorReported) {
                  this->othersErrorReported = true;
                  CompileError *ce = 
                        new CompileError(node,
                              "Associaion after Others.");
                  ErrorRegistry::addError(ce);
                        
            }
            return;
      }

      if (node.choices == NULL) {
            // positional association
            this->positional = true;

            if (this->sequencer.rs.empty()) {
                  CompileError *ce = 
                        new CompileError(node, 
                              "Index out of range.");
                  ErrorRegistry::addError(ce);
                  return;
            }

            universal_integer val = this->sequencer.getNext();
            node.range = new RangeSet(val, val);

            return;
      }

      // node.choices != NULL: either named or others
      this->listTraverse(*node.choices);
      if (this->haveOthers) {
            if (node.choices->size() > 1) {
                  // others mixed with elements.
                  CompileError *ce =
                        new CompileError(node, 
                              "Others in wrong place.");
                  ErrorRegistry::addError(ce);
                  this->currentRange = NULL;
                  return;
            }

            // only one others element. set the Range by it.
            node.range = this->sequencer.getRemainder();
            // all elements have been consumed by others. clear sequencer
            this->sequencer.rs.clear();
            return;
      }

      this->named = true;
      node.range = this->currentRange;
      this->currentRange = NULL;
}

void
00131 ResolveAggregates::visit(Others &node)
{
      if (this->haveOthers) {
            CompileError *ce = 
                  new ast::CompileError(node, 
                              "Duplicate others choice.");
            ErrorRegistry::addError(ce);
      }

      this->haveOthers = true;
}

void
00144 ResolveAggregates::visit(ConstInteger &node)
{
      if (this->currentRange == NULL) {
            this->currentRange = new RangeSet(node.value, node.value);
      } else {
            this->currentRange->plus(node.value, node.value);
      }

      bool ret = this->sequencer.rs.minus(node.value, node.value);
      if (! ret) {
            CompileError *ce = new CompileError(node, 
                        "Aggregate range doesn't fit array range.");
            ErrorRegistry::addError(ce);
      }
}

void
00161 ResolveAggregates::visit(DiscreteRange &node)
{
      if (this->currentRange == NULL) {
            this->currentRange = new RangeSet(node);
      } else {
            this->currentRange->plus(node);
      }

      bool ret = this->sequencer.rs.minus(node);
      if (! ret) {
            CompileError *ce = new CompileError(node, 
                        "Aggregate index doesn't fit array range.");
            ErrorRegistry::addError(ce);
      }
}

void
00178 ResolveAggregates::process(AstNode &node)
{
      CompileError *ce = 
            new CompileError(node, 
                  "Aggregate range/index not locally static.");
      ErrorRegistry::addError(ce);
}

/* ****************** nested class Sequencer **************** */
00187 ResolveAggregates::Sequencer::Sequencer(
      const DiscreteRange &byRange
) : 
      rs(byRange),
      direction(byRange.direction)
{
}

universal_integer
00196 ResolveAggregates::Sequencer::getNext(void)
{
      universal_integer ret = 0;

      switch (this->direction) {
      case DiscreteRange::DIRECTION_UP:
            ret = this->rs.getLowerBound();
            break;

      case DiscreteRange::DIRECTION_DOWN:
            ret = this->rs.getUpperBound();
            break;

      }

      bool b = this->rs.minus(ret, ret);
      assert(b);

      return ret;
}

RangeSet *
00218 ResolveAggregates::Sequencer::getRemainder(void) const
{
      return new RangeSet(this->rs);
}

}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index