Changeset dc0557d for src/GenPoly


Ignore:
Timestamp:
Mar 10, 2017, 4:32:54 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
ebb5ed9
Parents:
a9b657a
Message:

simplify and generalize Specialize transform to work for different tuple structures

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Specialize.cc

    ra9b657a rdc0557d  
    7777        }
    7878
     79        /// True if both types have the same structure, but not necessarily the same types.
     80        /// That is, either both types are tuple types with the same size (recursively), or
     81        /// both are not tuple types.
     82        bool matchingTupleStructure( Type * t1, Type * t2 ) {
     83                TupleType * tuple1 = dynamic_cast< TupleType * >( t1 );
     84                TupleType * tuple2 = dynamic_cast< TupleType * >( t2 );
     85                if ( tuple1 && tuple2 ) {
     86                        if ( tuple1->size() != tuple2->size() ) return false;
     87                        for ( auto types : group_iterate( tuple1->get_types(), tuple2->get_types() ) ) {
     88                                if ( ! matchingTupleStructure( std::get<0>( types ), std::get<1>( types ) ) ) return false;
     89                        }
     90                        return true;
     91                } else if ( ! tuple1 && ! tuple2 ) return true;
     92                return false;
     93        }
     94
    7995        bool needsTupleSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    80                 if ( FunctionType * ftype = getFunctionType( formalType ) ) {
    81                         return ftype->isTtype();
     96                // Needs tuple specialization if the structure of the formal type and actual type do not match.
     97                // This is the case if the formal type has ttype polymorphism, or if the structure  of tuple types
     98                // between the function do not match exactly.
     99                if ( FunctionType * fftype = getFunctionType( formalType ) ) {
     100                        if ( fftype->isTtype() ) return true;
     101                        FunctionType * aftype = getFunctionType( actualType );
     102                        assertf( aftype, "formal type is a function type, but actual type is not." );
     103                        if ( fftype->get_parameters().size() != aftype->get_parameters().size() ) return true;
     104                        for ( auto params : group_iterate( fftype->get_parameters(), aftype->get_parameters() ) ) {
     105                                DeclarationWithType * formal = std::get<0>(params);
     106                                DeclarationWithType * actual = std::get<1>(params);
     107                                if ( ! matchingTupleStructure( formal->get_type(), actual->get_type() ) ) return true;
     108                        }
    82109                }
    83110                return false;
     
    110137        }
    111138
    112         /// restructures arg to match the structure of a single formal parameter. Assumes that atomic types are compatible (as the Resolver should have ensured this)
    113         template< typename OutIterator >
    114         void matchOneFormal( Expression * arg, unsigned & idx, Type * formal, OutIterator out ) {
    115                 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formal ) ) {
     139        /// restructures the arguments to match the structure of the formal parameters of the actual function.
     140        /// [begin, end) are the exploded arguments.
     141        template< typename Iterator, typename OutIterator >
     142        void structureArg( Type * type, Iterator & begin, Iterator end, OutIterator out ) {
     143                if ( TupleType * tuple = dynamic_cast< TupleType * >( type ) ) {
    116144                        std::list< Expression * > exprs;
    117                         for ( Type * t : *tupleType ) {
    118                                 matchOneFormal( arg, idx, t, back_inserter( exprs ) );
     145                        for ( Type * t : *tuple ) {
     146                                structureArg( t, begin, end, back_inserter( exprs ) );
    119147                        }
    120148                        *out++ = new TupleExpr( exprs );
    121149                } else {
    122                         *out++ = new TupleIndexExpr( arg->clone(), idx++ );
    123                 }
    124         }
    125 
    126         /// restructures the ttype argument to match the structure of the formal parameters of the actual function.
    127         /// [begin, end) are the formal parameters.
    128         /// args is the list of arguments currently given to the actual function, the last of which needs to be restructured.
    129         template< typename Iterator, typename OutIterator >
    130         void fixLastArg( Expression * last, Iterator begin, Iterator end, OutIterator out ) {
    131                 if ( Tuples::isTtype( last->get_result() ) ) {
    132                         *out++ = last;
    133                 } else {
    134                         // safe_dynamic_cast for the assertion
    135                         safe_dynamic_cast< TupleType * >( last->get_result() );
    136                         unsigned idx = 0;
    137                         for ( ; begin != end; ++begin ) {
    138                                 DeclarationWithType * formal = *begin;
    139                                 Type * formalType = formal->get_type();
    140                                 matchOneFormal( last, idx, formalType, out );
    141                         }
    142                         delete last;
     150                        assertf( begin != end, "reached the end of the arguments while structuring" );
     151                        *out++ = *begin++;
     152                }
     153        }
     154
     155        /// explode assuming simple cases: either type is pure tuple (but not tuple expr) or type is non-tuple.
     156        template< typename OutputIterator >
     157        void explodeSimple( Expression * expr, OutputIterator out ) {
     158                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( expr->get_result() ) ) {
     159                        // tuple type, recursively index into its components
     160                        for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
     161                                explodeSimple( new TupleIndexExpr( expr->clone(), i ), out );
     162                        }
     163                        delete expr;
     164                } else {
     165                        // non-tuple type - output a clone of the expression
     166                        *out++ = expr;
    143167                }
    144168        }
     
    173197                std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin();
    174198                std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end();
    175                 std::list< DeclarationWithType * >::iterator formalBegin = funType->get_parameters().begin();
    176                 std::list< DeclarationWithType * >::iterator formalEnd = funType->get_parameters().end();
    177 
     199
     200                std::list< Expression * > args;
    178201                for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) {
    179                         // walk the parameters to the actual function alongside the parameters to the thunk to find the location where the ttype parameter begins to satisfy parameters in the actual function.
     202                        // name each thunk parameter and explode it - these are then threaded back into the actual function call.
    180203                        param->set_name( paramNamer.newName() );
    181                         assertf( formalBegin != formalEnd, "Reached end of formal parameters before finding ttype parameter" );
    182                         if ( Tuples::isTtype((*formalBegin)->get_type()) ) {
    183                                 fixLastArg( new VariableExpr( param ), actualBegin, actualEnd, back_inserter( appExpr->get_args() ) );
    184                                 break;
    185                         }
    186                         assertf( actualBegin != actualEnd, "reached end of actual function's arguments before finding ttype parameter" );
    187                         ++actualBegin;
    188                         ++formalBegin;
    189 
    190                         appExpr->get_args().push_back( new VariableExpr( param ) );
    191                 } // for
     204                        explodeSimple( new VariableExpr( param ), back_inserter( args ) );
     205                }
     206
     207                // walk parameters to the actual function alongside the exploded thunk parameters and restructure the arguments to match the actual parameters.
     208                std::list< Expression * >::iterator argBegin = args.begin(), argEnd = args.end();
     209                for ( ; actualBegin != actualEnd; ++actualBegin ) {
     210                        structureArg( (*actualBegin)->get_type(), argBegin, argEnd, back_inserter( appExpr->get_args() ) );
     211                }
     212
    192213                appExpr->set_env( maybeClone( env ) );
    193214                if ( inferParams ) {
Note: See TracChangeset for help on using the changeset viewer.