Changeset 5bf4712


Ignore:
Timestamp:
Dec 1, 2015, 2:44:13 PM (6 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, deferred_resn, demangler, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, string, with_gc
Children:
e58be8e, f8b961b
Parents:
b0b958a
Message:

Generic instantiator now only instantiates complete types; can stub in incomplete types

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/InstantiateGeneric.cc

    rb0b958a r5bf4712  
    4444                ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
    4545
    46                 /// Extracts types from a list of Expression* (which should be TypeExpr*)
    47                 ConcreteType(AggregateDecl *_base, const std::list< Expression* >& _params) : base(_base), params() {
    48                         for ( std::list< Expression* >::const_iterator it = _params.begin(); it != _params.end(); ++it ) {
    49                                 TypeExpr *param = dynamic_cast< TypeExpr* >(*it);
    50                                 assert(param && "Aggregate parameters should be type expressions");
    51                                 params.push_back( param->get_type()->clone() );
     46                /// Extracts types from a list of TypeExpr*
     47                ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {
     48                        for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
     49                                params.push_back( (*param)->get_type()->clone() );
    5250                        }
    5351                }
     
    6664
    6765                bool operator== (const ConcreteType& that) const {
     66                        if ( base != that.base ) return false;
     67
    6868                        SymTab::Indexer dummy;
    69 
    70                         if ( base != that.base ) return false;
    7169                        if ( params.size() != that.params.size() ) return false;
    7270                        for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
     
    8280        /// Maps a concrete type to the instantiated struct type, accounting for scope
    8381        class InstantiationMap {
    84                 /// Pair of concrete type and declaration that instantiates it
    85                 typedef std::pair< ConcreteType, AggregateDecl* > Instantiation;
     82                /// Instantiation of a generic type, with key information to find it
     83                struct Instantiation {
     84                        ConcreteType key;     ///< Instantiation parameters for this type
     85                        AggregateDecl *decl;  ///< Declaration of the instantiated generic type
     86
     87                        Instantiation() : key(), decl(0) {}
     88                        Instantiation(const ConcreteType &_key, AggregateDecl *_decl) : key(_key), decl(_decl) {}
     89                };
    8690                /// Map of generic types to instantiations of them
    8791                typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
     
    107111                /// Gets the declaration for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
    108112                /// Returns NULL on none such.
    109                 AggregateDecl* lookup( AggregateDecl *generic, std::list< Expression* >& params ) {
     113                AggregateDecl* lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {
    110114                        ConcreteType key(generic, params);
    111115                        // scan scopes from innermost out
     
    116120                                // look through instantiations for matches to concrete type
    117121                                for ( std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
    118                                         if ( inst->first == key ) return inst->second;
     122                                        if ( inst->key == key ) return inst->decl;
    119123                                }
    120124                        }
     
    123127                }
    124128        public:
    125                 StructDecl* lookup( StructInstType *inst ) { return (StructDecl*)lookup( inst->get_baseStruct(), inst->get_parameters() ); }
    126                 UnionDecl* lookup( UnionInstType *inst ) { return (UnionDecl*)lookup( inst->get_baseUnion(), inst->get_parameters() ); }
     129                StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); }
     130                UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); }
    127131
    128132        private:
    129133                /// Adds a declaration for a concrete type to the current scope
    130                 void insert( AggregateDecl *generic, std::list< Expression* >& params, AggregateDecl *decl ) {
     134                void insert( AggregateDecl *generic, const std::list< TypeExpr* > &params, AggregateDecl *decl ) {
    131135                        ConcreteType key(generic, params);
    132                         scopes.back()[generic].push_back( std::make_pair( key, decl ) );
     136                        scopes.back()[generic].push_back( Instantiation( key, decl ) );
    133137                }
    134138        public:
    135                 void insert( StructInstType *inst, StructDecl *decl ) { insert( inst->get_baseStruct(), inst->get_parameters(), decl ); }
    136                 void insert( UnionInstType *inst, UnionDecl *decl ) { insert( inst->get_baseUnion(), inst->get_parameters(), decl ); }
     139                void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); }
     140                void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); }
    137141        };
    138142
     
    144148        public:
    145149                Instantiate() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
     150
     151//              virtual Declaration* mutate( StructDecl *aggregateDecl );
     152//              virtual Declaration* mutate( UnionDecl *aggregateDecl );
    146153
    147154                virtual Type* mutate( StructInstType *inst );
     
    157164        }
    158165
    159         /// Substitutes types of members of in according to baseParams => params, appending the result to out
    160         void substituteMembers( const std::list< Declaration* >& in,
    161                                                         const std::list< TypeDecl * >& baseParams, const std::list< Expression* >& params,
     166        /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
     167        bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
     168                bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
     169
     170                // substitute concrete types for given parameters, and incomplete types for placeholders
     171                std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     172                std::list< Expression* >::const_iterator param = params.begin();
     173                for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
     174                        switch ( (*baseParam)->get_kind() ) {
     175                        case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
     176                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     177                                assert(paramType && "Aggregate parameters should be type expressions");
     178                                out.push_back( paramType->clone() );
     179                                // check that the substituted type isn't a type variable itself
     180                                if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
     181                                        allConcrete = false;
     182                                }
     183                                break;
     184                        }
     185                        case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     186                                out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     187                                break;
     188                        case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     189                                out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     190                                break;
     191                        }
     192                }
     193
     194                // if not enough parameters given, substitute remaining incomplete types for placeholders
     195                for ( ; baseParam != baseParams.end(); ++baseParam ) {
     196                        switch ( (*baseParam)->get_kind() ) {
     197                        case TypeDecl::Any:    // no more substitutions here, fail early
     198                                return false;
     199                        case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     200                                out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     201                                break;
     202                        case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     203                                out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     204                                break;
     205                        }
     206                }
     207
     208                return allConcrete;
     209        }
     210       
     211        /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
     212        void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,
    162213                                                    std::list< Declaration* >& out ) {
    163214                // substitute types into new members
    164                 TypeSubstitution subs( baseParams.begin(), baseParams.end(), params.begin() );
     215                TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
    165216                for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
    166217                        Declaration *newMember = (*member)->clone();
     
    178229                // exit early if no need for further mutation
    179230                if ( inst->get_parameters().empty() ) return inst;
     231                assert( inst->get_baseParameters() && "Base struct has parameters" );
     232
     233                // check if type can be concretely instantiated; put substitutions into typeSubs
     234                std::list< TypeExpr* > typeSubs;
     235                if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     236                        deleteAll( typeSubs );
     237                        return inst;
     238                }
    180239               
    181240                // make concrete instantiation of generic type
    182                 StructDecl *concDecl = instantiations.lookup( inst );
     241                StructDecl *concDecl = instantiations.lookup( inst, typeSubs );
    183242                if ( ! concDecl ) {
    184                         assert( inst->get_baseParameters() && "Base struct has parameters" );
    185243                        // set concDecl to new type, insert type declaration into statements to add
    186244                        concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
    187                         substituteMembers( inst->get_baseStruct()->get_members(),
    188                                                                 *inst->get_baseParameters(), inst->get_parameters(),
    189                                                                 concDecl->get_members() );
     245                        substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs,        concDecl->get_members() );
    190246                        DeclMutator::addDeclaration( concDecl );
    191                         instantiations.insert( inst, concDecl );
     247                        instantiations.insert( inst, typeSubs, concDecl );
    192248                }
    193249                StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
    194250                newInst->set_baseStruct( concDecl );
     251
     252                deleteAll( typeSubs );
    195253                delete inst;
    196254                return newInst;
     
    205263                // exit early if no need for further mutation
    206264                if ( inst->get_parameters().empty() ) return inst;
    207 
     265                assert( inst->get_baseParameters() && "Base union has parameters" );
     266
     267                // check if type can be concretely instantiated; put substitutions into typeSubs
     268                std::list< TypeExpr* > typeSubs;
     269                if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     270                        deleteAll( typeSubs );
     271                        return inst;
     272                }
     273               
    208274                // make concrete instantiation of generic type
    209                 UnionDecl *concDecl = instantiations.lookup( inst );
     275                UnionDecl *concDecl = instantiations.lookup( inst, typeSubs );
    210276                if ( ! concDecl ) {
    211277                        // set concDecl to new type, insert type declaration into statements to add
    212                         assert( inst->get_baseParameters() && "Base union has parameters" );
    213278                        concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
    214                         substituteMembers( inst->get_baseUnion()->get_members(),
    215                                                                 *inst->get_baseParameters(), inst->get_parameters(),
    216                                                                 concDecl->get_members() );
     279                        substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
    217280                        DeclMutator::addDeclaration( concDecl );
    218                         instantiations.insert( inst, concDecl );
     281                        instantiations.insert( inst, typeSubs, concDecl );
    219282                }
    220283                UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
    221284                newInst->set_baseUnion( concDecl );
     285
     286                deleteAll( typeSubs );
    222287                delete inst;
    223288                return newInst;
Note: See TracChangeset for help on using the changeset viewer.