Ignore:
Timestamp:
Aug 15, 2017, 7:14:24 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
1ae06fa
Parents:
c93bc28
Message:

Fix member expressions in the InstantiateGeneric? pass so that they correctly refer to the member from the instantiation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/InstantiateGeneric.cc

    rc93bc28 rf6582243  
    166166                /// Should not make use of type environment to replace types of function parameter and return values.
    167167                bool inFunctionType = false;
     168                /// Index of current member, used to recreate MemberExprs with the member from an instantiation
     169                int memberIndex = -1;
    168170                GenericInstantiator() : instantiations(), dtypeStatics(), typeNamer("_conc_") {}
    169171
     
    171173                Type* postmutate( UnionInstType *inst );
    172174
    173                 void premutate( __attribute__((unused)) FunctionType * ftype ) {
     175                // fix MemberExprs to use the member from the instantiation
     176                void premutate( MemberExpr * memberExpr );
     177                Expression * postmutate( MemberExpr * memberExpr );
     178
     179                void premutate( FunctionType * ) {
    174180                        GuardValue( inFunctionType );
    175181                        inFunctionType = true;
     
    418424        }
    419425
     426        namespace {
     427                bool isGenericType( Type * t ) {
     428                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
     429                                return ! inst->parameters.empty();
     430                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
     431                                return ! inst->parameters.empty();
     432                        }
     433                        return false;
     434                }
     435
     436                AggregateDecl * getAggr( Type * t ) {
     437                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
     438                                return inst->baseStruct;
     439                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
     440                                return inst->baseUnion;
     441                        }
     442                        assertf( false, "Non-aggregate type: %s", toString( t ).c_str() );
     443                }
     444        }
     445
     446        void GenericInstantiator::premutate( MemberExpr * memberExpr ) {
     447                GuardValue( memberIndex );
     448                memberIndex = -1;
     449                if ( isGenericType( memberExpr->aggregate->result ) ) {
     450                        // find the location of the member
     451                        AggregateDecl * aggr = getAggr( memberExpr->aggregate->result );
     452                        std::list< Declaration * > & members = aggr->members;
     453                        memberIndex = std::distance( members.begin(), std::find( members.begin(), members.end(), memberExpr->member ) );
     454                        assertf( memberIndex < (int)members.size(), "Could not find member %s in generic type %s", toString( memberExpr->member ).c_str(), toString( memberExpr->aggregate ).c_str() );
     455                }
     456        }
     457
     458        Expression * GenericInstantiator::postmutate( MemberExpr * memberExpr ) {
     459                if ( memberIndex != -1 ) {
     460                        // using the location from the generic type, find the member in the instantiation and rebuild the member expression
     461                        AggregateDecl * aggr = getAggr( memberExpr->aggregate->result );
     462                        assertf( memberIndex < (int)aggr->members.size(), "Instantiation somehow has fewer members than the generic type." );
     463                        Declaration * member = *std::next( aggr->members.begin(), memberIndex );
     464                        assertf( member->name == memberExpr->member->name, "Instantiation has different member order than the generic type. %s / %s", toString( member ).c_str(), toString( memberExpr->member ).c_str() );
     465                        DeclarationWithType * field = safe_dynamic_cast< DeclarationWithType * >( member );
     466                        MemberExpr * ret = new MemberExpr( field, memberExpr->aggregate->clone() );
     467                        std::swap( ret->env, memberExpr->env );
     468                        delete memberExpr;
     469                        return ret;
     470                }
     471                return memberExpr;
     472        }
     473
    420474        void GenericInstantiator::beginScope() {
    421475                instantiations.beginScope();
Note: See TracChangeset for help on using the changeset viewer.