Logo Search packages:      
Sourcecode: fauhdlc version File versions

ResolveTypes.hpp

/* $Id: ResolveTypes.hpp 4323 2009-01-27 13:48:12Z potyra $ 
 * ResolveTypes: perform type analysis.
 *
 * 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.
 */

#ifndef __RESOLVE_TYPES_HPP_INCLUDED
#define __RESOLVE_TYPES_HPP_INCLUDED

#include <list>
#include <set>
#include "frontend/visitor/TopDownVisitor.hpp"
#include "frontend/ast/ValDeclaration.hpp"
#include "frontend/ast/LibUnit.hpp"
#include "frontend/ast/ConcurrentStat.hpp"
#include "frontend/ast/RecordTypeElement.hpp"
#include "frontend/ast/EnumerationElement.hpp"
#include "frontend/ast/PhysicalTypeUnit.hpp"
#include "frontend/ast/EnumerationType.hpp"
#include "frontend/misc/SymbolTable.hpp"
#include "frontend/ast/NodeFactory.hpp"

namespace ast {

//! Resolve all types.
/** This visitor will resolve all types from the set of candidates
 *  evaluated by the SymbolTable.
 *
 *  Notes:
 *  * implicit conversions: 
 *    universal_integer -> any integer type.
 *    universal_real -> any floating point type.
 *    array definition: index_constraint -> "integer", in case both bounds
 *                      are universal_integer and literals or attributes.
 *
 *      function calls: parameter must match subtype!
 */
00041 class ResolveTypes : public TopDownVisitor {
public:
      //! c'tor
      /** @param symTab symbol table instance.
       */
00046       ResolveTypes(SymbolTable &symTab) : symbolTable(symTab) {}

private:
      /** Visit a CompInstStat
       *  @param node CompInstStat node that gets visited.
       */
      virtual void visit(CompInstStat &node);

      /** Visit an AssociationElement
       *  @param node AssociationElement node that gets visited.
       */
      virtual void visit(AssociationElement &node);

      /** Visit an UnconstrainedArrayType
       *  @param node UnconstrainedArrayType node that gets visited.
       */
      virtual void visit(UnconstrainedArrayType &node);

      /** Visit a DiscreteRange
       *  @param node DiscreteRange node that gets visited.
       */
      virtual void visit(DiscreteRange &node);

      /** Visit a VarAssignStat
       *  @param node VarAssignStat node that gets visited.
       */
      virtual void visit(VarAssignStat &node);

      /** Visit a SigAssignStat
       *  @param node SigAssignStat node that gets visited.
       */
      virtual void visit(SigAssignStat &node);

      /** Visit a Subscript node.
       *  @param node Subscript node that gets visited.
       */
      virtual void visit(Subscript &node);

      /** Visit a SimpleName node.
       *  @param node SimpleName node that gets visited.
       */
      virtual void visit(SimpleName &node);

      /** Visit a SelectedName node.
       *  @param node SelectedName node that gets visited.
       */
      virtual void visit(SelectedName &node);

      /** Visit an AttributeName node.
       *  @param node AttributeName node that gets visited.
       */
      virtual void visit(AttributeName &node);

      /** Visit a FunctionCall node.
       *  @param node FunctionCall node that gets visited.
       */
      virtual void visit(FunctionCall &node);

      /** Visit a ConstInteger node.
       *  @param node ConstInteger node that gets visited.
       */
      virtual void visit(ConstInteger &node);

      /** Visit a ConstReal node.
       *  @param node ConstReal node that gets visited.
       */
      virtual void visit(ConstReal &node);

      /** Visit an Aggregate node.
       *  @param node Aggregate node that gets visited.
       */
      virtual void visit(Aggregate &node);

      /** Visit an ElementAssociation node.
       *  @param node ElementAssociation node that gets visited.
       */
      virtual void visit(ElementAssociation &node);

      /** Visit an Others node.
       *  @param node Others node that gets visited.
       */
      virtual void visit(Others &node);

      /** Visit a Slice node.
       *  @param node Slice node that gets visited.
       */
      virtual void visit(Slice &node);

      /** Visit a TemporaryName node.
       *  @param node TemporaryName node that gets visited.
       */
      virtual void visit(TemporaryName &node);

      /** visit a ReturnStat
         *  @param node node that get's visited.
         */
      virtual void visit(ReturnStat &node);

      /** visit a RangeConstraintType
         *  @param node node that get's visited.
         */
      virtual void visit(RangeConstraintType &node);

      /** visit a PhysicalType
         *  @param node node that get's visited.
         */
      virtual void visit(PhysicalType &node);

      /** visit a RecordType
         *  @param node node that get's visited.
         */
      virtual void visit(RecordType &node);

      /** visit a FunctionDeclaration
         *  @param node node that get's visited.
         */
      virtual void visit(FunctionDeclaration &node);

      /** visit a ProcCallStat
         *  @param node node that get's visited.
         */
      virtual void visit(ProcCallStat &node);

      /** visit a SubtypeIndication
         *  @param node node that get's visited.
         */
      virtual void visit(SubtypeIndication &node);

      /** Visit a ForLoopStat
       *  @param node ForLoopStat node that get's visited.
       */
      virtual void visit(ForLoopStat &node);

      /** Visit a WhileLoopStat
       *  @param node WhileLoopStat node that get's visited.
       */
      virtual void visit(WhileLoopStat &node);

      /** Visit an AssertStat
       *  @param node AssertStat node that get's visited.
       */
      virtual void visit(AssertStat &node);

      /** Visit a CaseStat
       *  @param node CaseStat node that get's visited.
       */
      virtual void visit(CaseStat &node);

      /** Visit a WaitStat
       *  @param node WaitStat node that get's visited.
       */
      virtual void visit(WaitStat &node);

      /** Visit a Process node.
       *  @param node Process node that get's visited.
       */
      virtual void visit(Process& node);

      /** Visit a WaveFormElem
       *  @param node WaveFormElem node that get's visited.
       */
      virtual void visit(WaveFormElem &node);

      /** Visit an AttributeSpecification node.
       *  @param node AttributeSpecification node that gets visited.
       */
      virtual void visit(AttributeSpecification &node);

public:
      /** do both TypeDeclarations have the same base type?
       *  @param t1 first TypeDeclaration to check.
       *  @param t2 second TypeDeclaration to check.
       *  @return true, if t1 and t2 have the same base type,
       *          false otherwise.
       */
      static bool 
      baseTypeEqual(
            const TypeDeclaration &t1,
            const TypeDeclaration &t2);

      /** find the base type of t and return it.
       *  @param t type, for which the base type should get looked up.
       *  @return base type of t (or t, if it's no subtype). NULL on error.
       */
      static const TypeDeclaration*
      findBaseType(const TypeDeclaration *t);

      /** pick up all index constraints from constrainedArray and store it
       *  in indexConstraints.
       *  @param constrainedArray type referring to a constrained array.
       *  @param indexConstraint list to which indexConstraints should 
       *         get added.
       *  @return base type definition of the array.
       */
      static const UnconstrainedArrayType*
      pickupIndexConstraint(
            const TypeDeclaration *constrainedArray,
            std::list<DiscreteRange*> &indexConstraint
      );

private:
      using TopDownVisitor::process;

      /** process a CaseAlternative node.
       *  @param node CaseAlternative node to process
       */
      void processAlternative(CaseAlternative &node);

      /** process a generic ValDeclaration node.
       *  @param node node to process
       */
      virtual void process(ValDeclaration &node);

      /** process a generic LibUnit node.
       *  @param node node to process.
       */
      virtual void process(LibUnit &node);

      /** process a generic ConditionedStat node.
       *  @param node node to process.
       */
      virtual void process(ConditionedStat &node);

      /** process a generic SeqStat node.
       *  @param node node to process.
       */
      virtual void process(SeqStat &node);

      /** process array aggregates
       *  @param node Array Aggregate to process */
      void processArrayAgg(Aggregate &node);

      /** process an ElementAssociation that's part of an Array
       *  Aggregate.
       */
      void processArrayAssoc(ElementAssociation &node);

      /** process a DiscreteRange that is defined by a 
       *  range attribute name.
       *  @param node DiscreteRange node.
       */
      void processDRByName(DiscreteRange &node);

      /** process a range attribute name 
       *  @param node range attribute name node.
       */
      void processRangeAttr(AttributeName &node);

      /** process a left attribute name 
       *  @param node left attribute name node.
       */
      void processLeftAttr(AttributeName &node);

      /** process a right attribute name 
       *  @param node right attribute name node.
       */
      void processRightAttr(AttributeName &node);

      /** determine the TypeDeclaration resulting when stripping the first
       *  nIdx off.
       *  @param array TypeDeclaration referring to an array type.
       *  @param nIdx number of indices to strip off (flat model:
       *         a multidimensional index counts with the number of
       *         indices. This way it's possible to subscribe to 
       *         a single array dimension of a multidimensional array
       *         (which results in an anonymous type).
       *  @param loc Location to use in case an anonymous type should
       *         get created.
       */
      static const TypeDeclaration *
      subscribedType(
            const TypeDeclaration &array, 
            unsigned int nIdx,
            Location loc
      );

      /** process either a physical type or a range constraint type. 
       *  @param node node to process */
      template <typename T>
      void processConstraintType(T &node);

      /** process a ConstInteger or ConstReal (if it's not physical type.).
       *  In case there are no candidates, put directMatch on the stack. 
       *  If candidates are there, check if there are compatible types to
       *  directMatch and return these.
       *  If there aren't filter on possible types that are built from 
       *  implicit conversations based on icCompatible.
       *  
       *  @param node ConstInteger or ConstReal node.
       *  @param directMatch native type of the node.
       *  @param icCompatible base type, to which fallback implicit 
       *         conversions can be done.
       */
      void 
      processUniversal(
            Expression &node, 
            const TypeDeclaration *directMatch,
            enum BaseType icCompatible);

      /** process a generic Subprogram call.
       *  @param node ProcedureCall statement or FunctionCall statement.
       *  @param mustSingle must the result be unambiguous?
       */
      template <typename T>
      void processSubprogCall(T &node, bool mustSingle);

      /** private type definition of the type declaration list */
00353       typedef std::set<const TypeDeclaration*> typeSetT;
      
      /** report an error, if the type is either ambiguous or no
       *  type candidates are left.
       *  @param node errorenous node
       *  @return true if exactly one type is in TypeCandidates.
       */
      bool needUniqueType(AstNode &node) const;

      /** report an error, if the type is either ambiuous or no 
       *  type candidates are left.
       *  Also set the single type candidate as the type of the 
       *  Expression.
       *  @param node Expression to which the type should get applied.
       */
      bool needUniqueType(Expression &node) const;

      /** FIXME interface ...
       * report an error, if no type candidates are there.
       * @param loc location of the error.
       */
      void needNotEmpty(Location loc);

      /** transform the base type of a range, register an error if 
       *  given type is not transformable.
       *  @param rangeType the range inherits.
       *  @param loc Location of the Range
       *  @return the resolved base type.
       */
      static enum BaseType 
      transformBaseType(enum BaseType rangeType, Location loc);

      /** print all types on stderr for debugging purposes
       *  @param types set of types to print.
       */
      static void
      debugPrintTypes(const typeSetT &types);

public:
      /** determine the first index range for a type an array aggregate 
       *  which has the tpye at and the associations assocs.
       *  @param at array type.
       *  @param assocs list of association elements.
       */
      static DiscreteRange *
      determineIndexRangeAgg(
            const UnconstrainedArrayType *at, 
            const std::list<ElementAssociation*> &assocs);

private:
      /** determine the range constraint of the range type.
       *  @param rangeType range type in question.
       */
      static DiscreteRange *
      findRange(const TypeDeclaration *rangeType);

      /** possible types.
       *  When entering a node from its parent node:
       *  - an empty list means to return all possible types
       *  - a list with one element means that this is the wanted type
       *    and that types should get nailed down on this very type.
       *  - a list with several elements means that these are the possible
       *    types and that this list should get reduced by possible types
       *    of this node.
       */
00418       typeSetT typeCandidates;

      /** symbol table instance. */
00421       SymbolTable &symbolTable;

      /** nested class to perform type filtering.
       *  The TypeFilter can be used to reduce a set of symbol candidates to
       *  the ones matching any given wanted types.
       *
       *  If the wanted types set is empty, it can also fill it with all 
       *  possible types that the candidate symbols can provide.
       */
      template <typename T>
00431       class TypeFilter {
      private:
            /** reference to list of candidate symbols. */
00434             T &candidates;
            /** reference list with wanted types */
00436             typeSetT &wantedTypes;
      public:
            /** c'tor 
             *  @param cands list of candidate types.
             *  @param wantTypes list of wanted types.
             */
            TypeFilter(
                  T &cands,
                  typeSetT &wantTypes
            );

            /** virtual d'tor */
00448             virtual ~TypeFilter() {}

            /** apply type filtering. */
            void apply(void);

      private:
            /** operation to map a candidate to a type.
             *  @param element candidate symbol
             *  @return associated type or NULL if no type could get
             *          determined.
             */
            virtual const TypeDeclaration*
            operator()(typename T::value_type element) const = 0;

            /** check if given type is compatible to one of 
             *  possibleTypes
             *  @param t type to check.
             *  @return true, if the type is compatible.
             */
            bool checkType(const TypeDeclaration *t) const;
      };

      /** class for filtering on list of Symbols. Default implementation does
       *  a type lookup via LookupTypes of a symbol.
       */
00473       class SymbolFilter : public TypeFilter< std::list<Symbol*> > {
      public:
            /** c'tor 
             *  @param cands list of candidate types.
             *  @param wantTypes list of wanted types.
             */
00479             SymbolFilter(
                  std::list<Symbol*> &cands,
                  typeSetT &wantTypes
                  ) :   TypeFilter< std::list<Symbol*> >(cands, 
                                               wantTypes) {}

            /** operation to map a candidate to a type.
             *  @param element candidate symbol
             *  @return associated type or NULL if no type could get
             *          determined.
             */
            virtual const TypeDeclaration*
            operator()(Symbol *element) const;
      };

      /** symbol filter which projects the n-ths argument of an 
       *  association list to a type.
       */
00497       class ProjectPositionalArg : public SymbolFilter {
      public:
            /** c'tor
             *  @param cands candidate symbols.
             *  @param wantTypes wanted types for the n'ths argument
             *  @param n position of the argument.
             */
00504             ProjectPositionalArg(
                  std::list<Symbol*> &cands,
                  typeSetT &wantTypes,
                  unsigned int n
                  ) :   SymbolFilter(cands, wantTypes),
                        position(n) {}

            /** position of the argument. */
00512             unsigned int position;
      private:
            /** operation to map a candidate to a type.
             *  @param element candidate symbol
             *  @return associated type or NULL if no type could get
             *          determined.
             */
            virtual const TypeDeclaration*
            operator()(Symbol *element) const;

      };

      //! compare the subscripted type to wanted type
      /** subscribe to wantTypes and compare the result with
       *  candidates, filtering all non-matching types.
       */
00528       class SubscriptFilter : public TypeFilter< typeSetT > {
      public:
            /** c'tor
             *  @param cands type candidates, that will get subscribed.
             *  @param wantTypes wanted types 
             */
00534             SubscriptFilter(
                  typeSetT &cands,
                  typeSetT &wantTypes
                  ) :   TypeFilter< typeSetT >(cands, wantTypes) {}
      protected:

            /** resolve the type of the source to a subscribed
             *  type.
             *  @param element source type 
             *  @return subscribed type.
             */
            virtual const TypeDeclaration*
            operator()(typeSetT::value_type element) const;

      }; /* nested class SubscriptFilter */

      //! transform/filter cands into an index type.
      /** take the first SubtypeIndication of indexTypes and check
       *  against it.
       */
00554       class IndexTypeFilter : public TypeFilter< typeSetT > {
      public:
            /** c'tor
             *  @param cands type candidates, for which the index will
             *         get looked up.
             *  @param wantTypes wanted types (will get filled or reduced
             *  @param idx number of the index to filter (1=1st).
             */
00562             IndexTypeFilter(
                  typeSetT &cands, 
                  typeSetT &wantTypes,
                  unsigned int idx
                  ) :   TypeFilter< typeSetT >(cands, wantTypes),
                        nIdx(idx) {}

      private:
            /** resolve the type of the source to an index type of 
             *  an array.
             *  @param element source type
             *  @return index type or NULL if not applicable.
             */
            virtual const TypeDeclaration*
            operator()(typeSetT::value_type element) const;

            /** number of the index to filter */
00579             unsigned int nIdx;
      };

      // needs the ability to preload typeCandidates.
      friend class NodeFactory::TypeDeclHelper;
};

}; /* namespace ast */

#endif /* __RESOLVE_TYPES_HPP_INCLUDED */

Generated by  Doxygen 1.6.0   Back to index