Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/InstantiateGeneric.cc

    rea5daeb rf18a711  
    2424#include "GenPoly.h"
    2525#include "ScopedMap.h"
     26#include "ScopedSet.h"
    2627
    2728#include "ResolvExpr/typeops.h"
     
    122123                }
    123124        };
     125
     126        /// Possible options for a given specialization of a generic type
     127        enum class genericType {
     128                dtypeStatic,  ///< Concrete instantiation based solely on {d,f}type-to-void conversions
     129                concrete,     ///< Concrete instantiation requiring at least one parameter type
     130                dynamic       ///< No concrete instantiation
     131        };
     132
     133        genericType& operator |= ( genericType& gt, const genericType& ht ) {
     134                switch ( gt ) {
     135                case genericType::dtypeStatic:
     136                        gt = ht;
     137                        break;
     138                case genericType::concrete:
     139                        if ( ht == genericType::dynamic ) { gt = genericType::dynamic; }
     140                        break;
     141                case genericType::dynamic:
     142                        // nothing possible
     143                        break;
     144                }
     145                return gt;
     146        }
    124147       
    125148        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
     
    127150                /// Map of (generic type, parameter list) pairs to concrete type instantiations
    128151                InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
     152                /// Set of types which are dtype-only generic (and therefore have static layout)
     153                ScopedSet< AggregateDecl* > dtypeStatics;
    129154                /// Namer for concrete types
    130155                UniqueName typeNamer;
    131156
    132157        public:
    133                 GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
     158                GenericInstantiator() : DeclMutator(), instantiations(), dtypeStatics(), typeNamer("_conc_") {}
    134159
    135160                virtual Type* mutate( StructInstType *inst );
     
    147172                /// Wrap instantiation insertion for unions
    148173                void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
     174
     175                /// Strips a dtype-static aggregate decl of its type parameters, marks it as stripped
     176                void stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs );
    149177        };
    150178
     
    154182        }
    155183
    156         //////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////
    157 
    158         /// Possible options for a given specialization of a generic type
    159         enum class genericType {
    160                 dtypeStatic,  ///< Concrete instantiation based solely on {d,f}type-to-void conversions
    161                 concrete,     ///< Concrete instantiation requiring at least one parameter type
    162                 dynamic       ///< No concrete instantiation
    163         };
    164 
    165         genericType& operator |= ( genericType& gt, const genericType& ht ) {
    166                 switch ( gt ) {
    167                 case genericType::dtypeStatic:
    168                         gt = ht;
    169                         break;
    170                 case genericType::concrete:
    171                         if ( ht == genericType::dynamic ) { gt = genericType::dynamic; }
    172                         break;
    173                 case genericType::dynamic:
    174                         // nothing possible
    175                         break;
    176                 }
    177                 return gt;
    178         }
    179 
    180         /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
     184        /// Makes substitutions of params into baseParams; returns dtypeStatic if there is a concrete instantiation based only on {d,f}type-to-void conversions,
     185        /// concrete if there is a concrete instantiation requiring at least one parameter type, and dynamic if there is no concrete instantiation
    181186        genericType makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
    182187                genericType gt = genericType::dtypeStatic;
     
    223228        }
    224229
     230        /// Substitutes types of members according to baseParams => typeSubs, working in-place
     231        void substituteMembers( std::list< Declaration* >& members, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
     232                // substitute types into new members
     233                TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
     234                for ( std::list< Declaration* >::iterator member = members.begin(); member != members.end(); ++member ) {
     235                        subs.apply(*member);
     236                }
     237        }
     238
     239        /// Strips the instances's type parameters
     240        void stripInstParams( ReferenceToType *inst ) {
     241                deleteAll( inst->get_parameters() );
     242                inst->get_parameters().clear();
     243        }
     244       
     245        void GenericInstantiator::stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
     246                substituteMembers( base->get_members(), baseParams, typeSubs );
     247
     248                deleteAll( baseParams );
     249                baseParams.clear();
     250               
     251                dtypeStatics.insert( base );
     252        }
     253
    225254        Type* GenericInstantiator::mutate( StructInstType *inst ) {
    226255                // mutate subtypes
     
    231260                // exit early if no need for further mutation
    232261                if ( inst->get_parameters().empty() ) return inst;
     262
     263                // check for an already-instantiatiated dtype-static type
     264                if ( dtypeStatics.find( inst->get_baseStruct() ) != dtypeStatics.end() ) {
     265                        stripInstParams( inst );
     266                        return inst;
     267                }
     268               
     269                // check if type can be concretely instantiated; put substitutions into typeSubs
    233270                assert( inst->get_baseParameters() && "Base struct has parameters" );
    234 
    235                 // check if type can be concretely instantiated; put substitutions into typeSubs
    236271                std::list< TypeExpr* > typeSubs;
    237272                genericType gt = makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs );
    238273                switch ( gt ) {
    239                 case genericType::dtypeStatic: // TODO strip params off original decl and reuse here
    240                 case genericType::concrete:
    241                 {
     274                case genericType::dtypeStatic:
     275                        stripDtypeParams( inst->get_baseStruct(), *inst->get_baseParameters(), typeSubs );
     276                        stripInstParams( inst );
     277                        break;
     278               
     279                case genericType::concrete: {
    242280                        // make concrete instantiation of generic type
    243281                        StructDecl *concDecl = lookup( inst, typeSubs );
     
    274312                // exit early if no need for further mutation
    275313                if ( inst->get_parameters().empty() ) return inst;
     314
     315                // check for an already-instantiatiated dtype-static type
     316                if ( dtypeStatics.find( inst->get_baseUnion() ) != dtypeStatics.end() ) {
     317                        stripInstParams( inst );
     318                        return inst;
     319                }
     320
     321                // check if type can be concretely instantiated; put substitutions into typeSubs
    276322                assert( inst->get_baseParameters() && "Base union has parameters" );
    277 
    278                 // check if type can be concretely instantiated; put substitutions into typeSubs
    279323                std::list< TypeExpr* > typeSubs;
    280324                genericType gt = makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs );
    281325                switch ( gt ) {
    282                 case genericType::dtypeStatic:  // TODO strip params off original decls and reuse here
     326                case genericType::dtypeStatic:
     327                        stripDtypeParams( inst->get_baseUnion(), *inst->get_baseParameters(), typeSubs );
     328                        stripInstParams( inst );
     329                        break;
     330                       
    283331                case genericType::concrete:
    284332                {
     
    311359                DeclMutator::doBeginScope();
    312360                instantiations.beginScope();
     361                dtypeStatics.beginScope();
    313362        }
    314363
     
    316365                DeclMutator::doEndScope();
    317366                instantiations.endScope();
     367                dtypeStatics.endScope();
    318368        }
    319369
Note: See TracChangeset for help on using the changeset viewer.