Changeset 2162c2c for src/GenPoly


Ignore:
Timestamp:
Jan 11, 2017, 4:11:02 PM (9 years ago)
Author:
Thierry Delisle <tdelisle@…>
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:
075734f
Parents:
bb82c03 (diff), d3a85240 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src/GenPoly
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rbb82c03 r2162c2c  
    136136                        template< typename DeclClass >
    137137                        DeclClass *handleDecl( DeclClass *decl, Type *type );
    138 
    139                         using PolyMutator::mutate;
     138                        template< typename AggDecl >
     139                        AggDecl * handleAggDecl( AggDecl * aggDecl );
     140
     141                        typedef PolyMutator Parent;
     142                        using Parent::mutate;
    140143                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
    141144                        virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
     145                        virtual StructDecl *mutate( StructDecl *structDecl ) override;
     146                        virtual UnionDecl *mutate( UnionDecl *unionDecl ) override;
    142147                        virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
    143148                        virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ) override;
     
    686691                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    687692                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    688                                 assert(paramType && "Aggregate parameters should be type expressions");
     693                                assertf(paramType, "Aggregate parameters should be type expressions");
    689694                                paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
    690695                        }
     
    783788                void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
    784789                        for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->get_parameters().end(); ++param, ++arg ) {
    785                                 assert( arg != appExpr->get_args().end() );
     790                                assertf( arg != appExpr->get_args().end(), "boxParams: missing argument for param %s to %s in %s", toString( *param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
    786791                                addCast( *arg, (*param)->get_type(), exprTyVars );
    787792                                boxParam( (*param)->get_type(), *arg, exprTyVars );
     
    11271132                        makeTyVarMap( function, exprTyVars ); // xxx - should this take into account the variables already bound in scopeTyVars (i.e. remove them from exprTyVars?)
    11281133                        ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
    1129                         Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();// ?: dynRetType; // xxx - is concRetType a good name?
    1130 
     1134
     1135                        // NOTE: addDynRetParam needs to know the actual (generated) return type so it can make a temp variable, so pass the result type from the appExpr
     1136                        // passTypeVars needs to know the program-text return type (i.e. the distinction between _conc_T30 and T3(int))
     1137                        // concRetType may not be a good name in one or both of these places. A more appropriate name change is welcome.
    11311138                        if ( dynRetType ) {
     1139                                Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
    11321140                                ret = addDynRetParam( appExpr, function, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
    11331141                        } else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...?
     
    11421150                        arg = appExpr->get_args().begin();
    11431151
     1152                        Type *concRetType = replaceWithConcrete( appExpr, dynRetType );
    11441153                        passTypeVars( appExpr, concRetType, arg, exprTyVars ); // xxx - used to use dynRetType instead of concRetType; this changed so that the correct type paramaters are passed for return types (it should be the concrete type's parameters, not the formal type's)
    11451154                        addInferredParams( appExpr, function, arg, exprTyVars );
     
    12711280                template< typename DeclClass >
    12721281                DeclClass * Pass2::handleDecl( DeclClass *decl, Type *type ) {
    1273                         DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
     1282                        DeclClass *ret = static_cast< DeclClass *>( Parent::mutate( decl ) );
    12741283
    12751284                        return ret;
     
    13051314                }
    13061315
     1316                template< typename AggDecl >
     1317                AggDecl * Pass2::handleAggDecl( AggDecl * aggDecl ) {
     1318                        // prevent tyVars from leaking into containing scope
     1319                        scopeTyVars.beginScope();
     1320                        Parent::mutate( aggDecl );
     1321                        scopeTyVars.endScope();
     1322                        return aggDecl;
     1323                }
     1324
     1325                StructDecl * Pass2::mutate( StructDecl *aggDecl ) {
     1326                        return handleAggDecl( aggDecl );
     1327                }
     1328
     1329                UnionDecl * Pass2::mutate( UnionDecl *aggDecl ) {
     1330                        return handleAggDecl( aggDecl );
     1331                }
     1332
    13071333                TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
    13081334                        addToTyVarMap( typeDecl, scopeTyVars );
     
    13101336                                return handleDecl( typeDecl, typeDecl->get_base() );
    13111337                        } else {
    1312                                 return Mutator::mutate( typeDecl );
     1338                                return Parent::mutate( typeDecl );
    13131339                        }
    13141340                }
     
    13221348                        makeTyVarMap( pointerType, scopeTyVars );
    13231349
    1324                         Type *ret = Mutator::mutate( pointerType );
     1350                        Type *ret = Parent::mutate( pointerType );
    13251351
    13261352                        scopeTyVars.endScope();
  • src/GenPoly/InstantiateGeneric.cc

    rbb82c03 r2162c2c  
    1818#include <utility>
    1919#include <vector>
     20#include <unordered_map>
    2021
    2122#include "InstantiateGeneric.h"
     
    2425#include "GenPoly.h"
    2526#include "ScopedSet.h"
     27#include "PolyMutator.h"
    2628
    2729#include "ResolvExpr/typeops.h"
     
    146148        }
    147149
     150        // collect the environments of each TypeInstType so that type variables can be replaced
     151        // xxx - possibly temporary solution. Access to type environments is required in GenericInstantiator, but it needs to be a DeclMutator which does not provide easy access to the type environments.
     152        class EnvFinder final : public GenPoly::PolyMutator {
     153        public:
     154                virtual Type * mutate( TypeInstType * inst ) override {
     155                        if ( env ) envMap[inst] = env;
     156                        return inst;
     157                }
     158
     159                // don't want to associate an environment with TypeInstTypes that occur in function types - this may actually only apply to function types belonging to DeclarationWithTypes (or even just FunctionDecl)?
     160                virtual Type * mutate( FunctionType * ftype ) override {
     161                        return ftype;
     162                }
     163                std::unordered_map< ReferenceToType *, TypeSubstitution * > envMap;
     164        };
     165
    148166        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
    149167        class GenericInstantiator final : public DeclMutator {
     
    154172                /// Namer for concrete types
    155173                UniqueName typeNamer;
    156 
     174                /// Reference to mapping of environments
     175                const std::unordered_map< ReferenceToType *, TypeSubstitution * > & envMap;
    157176        public:
    158                 GenericInstantiator() : DeclMutator(), instantiations(), dtypeStatics(), typeNamer("_conc_") {}
     177                GenericInstantiator( const std::unordered_map< ReferenceToType *, TypeSubstitution * > & envMap ) : DeclMutator(), instantiations(), dtypeStatics(), typeNamer("_conc_"), envMap( envMap ) {}
    159178
    160179                using DeclMutator::mutate;
     
    174193                void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
    175194
     195                void replaceParametersWithConcrete( std::list< Expression* >& params );
     196                Type *replaceWithConcrete( Type *type, bool doClone );
     197
    176198                /// Strips a dtype-static aggregate decl of its type parameters, marks it as stripped
    177199                void stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs );
     
    179201
    180202        void instantiateGeneric( std::list< Declaration* > &translationUnit ) {
    181                 GenericInstantiator instantiator;
     203                EnvFinder finder;
     204                mutateAll( translationUnit, finder );
     205                GenericInstantiator instantiator( finder.envMap );
    182206                instantiator.mutateDeclarationList( translationUnit );
    183207        }
     
    209233                                // can pretend that any ftype is `void (*)(void)`
    210234                                out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     235                                break;
     236                        case TypeDecl::Ttype:
     237                                assertf( false, "Ttype parameters are not currently allowed as parameters to generic types." );
    211238                                break;
    212239                        }
     
    253280        }
    254281
     282        /// xxx - more or less copied from box -- these should be merged with those somehow...
     283        void GenericInstantiator::replaceParametersWithConcrete( std::list< Expression* >& params ) {
     284                for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
     285                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     286                        assertf(paramType, "Aggregate parameters should be type expressions");
     287                        paramType->set_type( replaceWithConcrete( paramType->get_type(), false ) );
     288                }
     289        }
     290
     291        Type *GenericInstantiator::replaceWithConcrete( Type *type, bool doClone ) {
     292                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
     293                        if ( envMap.count( typeInst ) ) {
     294                                TypeSubstitution * env = envMap.at( typeInst );
     295                                Type *concrete = env->lookup( typeInst->get_name() );
     296                                if ( concrete ) {
     297                                        return concrete->clone();
     298                                }
     299                                else return typeInst->clone();
     300                        }
     301                } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
     302                        if ( doClone ) {
     303                                structType = structType->clone();
     304                        }
     305                        replaceParametersWithConcrete( structType->get_parameters() );
     306                        return structType;
     307                } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
     308                        if ( doClone ) {
     309                                unionType = unionType->clone();
     310                        }
     311                        replaceParametersWithConcrete( unionType->get_parameters() );
     312                        return unionType;
     313                }
     314                return type;
     315        }
     316
     317
    255318        Type* GenericInstantiator::mutate( StructInstType *inst ) {
    256319                // mutate subtypes
     
    262325                if ( inst->get_parameters().empty() ) return inst;
    263326
     327                // need to replace type variables to ensure that generic types are instantiated for the return values of polymorphic functions (in particular, for thunks, because they are not [currently] copy constructed).
     328                replaceWithConcrete( inst, false );
     329
    264330                // check for an already-instantiatiated dtype-static type
    265331                if ( dtypeStatics.find( inst->get_baseStruct() ) != dtypeStatics.end() ) {
     
    269335
    270336                // check if type can be concretely instantiated; put substitutions into typeSubs
    271                 assert( inst->get_baseParameters() && "Base struct has parameters" );
     337                assertf( inst->get_baseParameters(), "Base struct has parameters" );
    272338                std::list< TypeExpr* > typeSubs;
    273339                genericType gt = makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs );
  • src/GenPoly/ScrubTyVars.cc

    rbb82c03 r2162c2c  
    3131                          case TypeDecl::Any:
    3232                          case TypeDecl::Dtype:
     33                          case TypeDecl::Ttype:
    3334                                {
    3435                                        PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
  • src/GenPoly/Specialize.cc

    rbb82c03 r2162c2c  
    3232#include "Common/utility.h"
    3333#include "InitTweak/InitTweak.h"
     34#include "Tuples/Tuples.h"
    3435
    3536namespace GenPoly {
    36         const std::list<Label> noLabels;
    37 
     37        class Specializer;
    3838        class Specialize final : public PolyMutator {
     39                friend class Specializer;
    3940          public:
    40                 Specialize( std::string paramPrefix = "_p" );
    41 
    4241                using PolyMutator::mutate;
    4342                virtual Expression * mutate( ApplicationExpr *applicationExpr ) override;
     
    4847                // virtual Expression * mutate( CommaExpr *commaExpr );
    4948
    50           private:
    51                 Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams = 0 );
    52                 Expression *doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams = 0 );
     49                Specializer * specializer = nullptr;
    5350                void handleExplicitParams( ApplicationExpr *appExpr );
    54 
    55                 UniqueName thunkNamer;
    56                 std::string paramPrefix;
    5751        };
    5852
    59         void convertSpecializations( std::list< Declaration* >& translationUnit ) {
    60                 Specialize specializer;
    61                 mutateAll( translationUnit, specializer );
    62         }
    63 
    64         Specialize::Specialize( std::string paramPrefix )
    65                 : thunkNamer( "_thunk" ), paramPrefix( paramPrefix ) {
    66         }
     53        class Specializer {
     54          public:
     55                Specializer( Specialize & spec ) : spec( spec ), env( spec.env ), stmtsToAdd( spec.stmtsToAdd ) {}
     56                virtual bool needsSpecialization( Type * formalType, Type * actualType, TypeSubstitution * env ) = 0;
     57                virtual Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) = 0;
     58                virtual Expression *doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams = 0 );
     59
     60          protected:
     61                Specialize & spec;
     62                std::string paramPrefix = "_p";
     63                TypeSubstitution *& env;
     64                std::list< Statement * > & stmtsToAdd;
     65        };
     66
     67        // for normal polymorphic -> monomorphic function conversion
     68        class PolySpecializer : public Specializer {
     69          public:
     70                PolySpecializer( Specialize & spec ) : Specializer( spec ) {}
     71                virtual bool needsSpecialization( Type * formalType, Type * actualType, TypeSubstitution * env ) override;
     72                virtual Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) override;
     73        };
     74
     75        // // for tuple -> non-tuple function conversion
     76        class TupleSpecializer : public Specializer {
     77          public:
     78                TupleSpecializer( Specialize & spec ) : Specializer( spec ) {}
     79                virtual bool needsSpecialization( Type * formalType, Type * actualType, TypeSubstitution * env ) override;
     80                virtual Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) override;
     81        };
    6782
    6883        /// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type.
    69         bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
     84        bool PolySpecializer::needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    7085                if ( env ) {
    7186                        using namespace ResolvExpr;
     
    92107
    93108        /// Generates a thunk that calls `actual` with type `funType` and returns its address
    94         Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
     109        Expression * PolySpecializer::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
     110                static UniqueName thunkNamer( "_thunk" );
     111
    95112                FunctionType *newType = funType->clone();
    96113                if ( env ) {
    97                         TypeSubstitution newEnv( *env );
    98114                        // it is important to replace only occurrences of type variables that occur free in the
    99115                        // thunk's type
    100                         newEnv.applyFree( newType );
     116                        env->applyFree( newType );
    101117                } // if
    102118                // create new thunk with same signature as formal type (C linkage, empty body)
     
    125141                std::list< Statement* > oldStmts;
    126142                oldStmts.splice( oldStmts.end(), stmtsToAdd );
    127                 handleExplicitParams( appExpr );
     143                spec.handleExplicitParams( appExpr );
    128144                paramPrefix = oldParamPrefix;
    129145                // write any statements added for recursive specializations into the thunk body
     
    147163        }
    148164
    149         Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
     165        Expression * Specializer::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
    150166                assertf( actual->has_result(), "attempting to specialize an untyped expression" );
    151167                if ( needsSpecialization( formalType, actual->get_result(), env ) ) {
    152                         FunctionType *funType;
    153                         if ( ( funType = getFunctionType( formalType ) ) ) {
     168                        if ( FunctionType *funType = getFunctionType( formalType ) ) {
    154169                                ApplicationExpr *appExpr;
    155170                                VariableExpr *varExpr;
     
    170185        }
    171186
     187        bool TupleSpecializer::needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
     188                if ( FunctionType * ftype = getFunctionType( formalType ) ) {
     189                        return ftype->isTtype();
     190                }
     191                return false;
     192        }
     193
     194        /// restructures arg to match the structure of a single formal parameter. Assumes that atomic types are compatible (as the Resolver should have ensured this)
     195        template< typename OutIterator >
     196        void matchOneFormal( Expression * arg, unsigned & idx, Type * formal, OutIterator out ) {
     197                if ( TupleType * tupleType = dynamic_cast< TupleType * >( formal ) ) {
     198                        std::list< Expression * > exprs;
     199                        for ( Type * t : *tupleType ) {
     200                                matchOneFormal( arg, idx, t, back_inserter( exprs ) );
     201                        }
     202                        *out++ = new TupleExpr( exprs );
     203                } else {
     204                        *out++ = new TupleIndexExpr( arg->clone(), idx++ );
     205                }
     206        }
     207
     208        /// restructures the ttype argument to match the structure of the formal parameters of the actual function.
     209        // [begin, end) are the formal parameters.
     210        // args is the list of arguments currently given to the actual function, the last of which needs to be restructured.
     211        template< typename Iterator, typename OutIterator >
     212        void fixLastArg( Expression * last, Iterator begin, Iterator end, OutIterator out ) {
     213                // safe_dynamic_cast for the assertion
     214                safe_dynamic_cast< TupleType * >( last->get_result() );
     215                unsigned idx = 0;
     216                for ( ; begin != end; ++begin ) {
     217                        DeclarationWithType * formal = *begin;
     218                        Type * formalType = formal->get_type();
     219                        matchOneFormal( last, idx, formalType, out );
     220                }
     221                delete last;
     222        }
     223
     224        Expression * TupleSpecializer::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
     225                static UniqueName thunkNamer( "_tupleThunk" );
     226
     227                FunctionType *newType = funType->clone();
     228                if ( env ) {
     229                        // it is important to replace only occurrences of type variables that occur free in the
     230                        // thunk's type
     231                        env->applyFree( newType );
     232                } // if
     233                // create new thunk with same signature as formal type (C linkage, empty body)
     234                FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( noLabels ), false, false );
     235                thunkFunc->fixUniqueId();
     236
     237                // thunks may be generated and not used - silence warning with attribute
     238                thunkFunc->get_attributes().push_back( new Attribute( "unused" ) );
     239
     240                // thread thunk parameters into call to actual function, naming thunk parameters as we go
     241                UniqueName paramNamer( paramPrefix );
     242                ApplicationExpr *appExpr = new ApplicationExpr( actual );
     243
     244                FunctionType * actualType = getFunctionType( actual->get_result() )->clone();
     245                if ( env ) {
     246                        // need to apply the environment to the actual function's type, since it may itself be polymorphic
     247                        env->apply( actualType );
     248                }
     249                std::unique_ptr< FunctionType > actualTypeManager( actualType ); // for RAII
     250                std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin();
     251                std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end();
     252                std::list< DeclarationWithType * >::iterator formalBegin = funType->get_parameters().begin();
     253                std::list< DeclarationWithType * >::iterator formalEnd = funType->get_parameters().end();
     254
     255                Expression * last = nullptr;
     256                for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) {
     257                        // 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.
     258                        param->set_name( paramNamer.newName() );
     259                        assertf( formalBegin != formalEnd, "Reached end of formal parameters before finding ttype parameter" );
     260                        if ( Tuples::isTtype((*formalBegin)->get_type()) ) {
     261                                last = new VariableExpr( param );
     262                                break;
     263                        }
     264                        assertf( actualBegin != actualEnd, "reached end of actual function's arguments before finding ttype parameter" );
     265                        ++actualBegin;
     266                        ++formalBegin;
     267
     268                        appExpr->get_args().push_back( new VariableExpr( param ) );
     269                } // for
     270                assert( last );
     271                fixLastArg( last, actualBegin, actualEnd, back_inserter( appExpr->get_args() ) );
     272                appExpr->set_env( maybeClone( env ) );
     273                if ( inferParams ) {
     274                        appExpr->get_inferParams() = *inferParams;
     275                } // if
     276
     277                // handle any specializations that may still be present
     278                std::string oldParamPrefix = paramPrefix;
     279                paramPrefix += "p";
     280                // save stmtsToAdd in oldStmts
     281                std::list< Statement* > oldStmts;
     282                oldStmts.splice( oldStmts.end(), stmtsToAdd );
     283                spec.mutate( appExpr );
     284                paramPrefix = oldParamPrefix;
     285                // write any statements added for recursive specializations into the thunk body
     286                thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd );
     287                // restore oldStmts into stmtsToAdd
     288                stmtsToAdd.splice( stmtsToAdd.end(), oldStmts );
     289
     290                // add return (or valueless expression) to the thunk
     291                Statement *appStmt;
     292                if ( funType->get_returnVals().empty() ) {
     293                        appStmt = new ExprStmt( noLabels, appExpr );
     294                } else {
     295                        appStmt = new ReturnStmt( noLabels, appExpr );
     296                } // if
     297                thunkFunc->get_statements()->get_kids().push_back( appStmt );
     298
     299                // add thunk definition to queue of statements to add
     300                stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) );
     301                // return address of thunk function as replacement expression
     302                return new AddressExpr( new VariableExpr( thunkFunc ) );
     303        }
     304
    172305        void Specialize::handleExplicitParams( ApplicationExpr *appExpr ) {
    173306                // create thunks for the explicit parameters
     
    178311                std::list< Expression* >::iterator actual;
    179312                for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) {
    180                         *actual = doSpecialization( (*formal )->get_type(), *actual, &appExpr->get_inferParams() );
     313                        *actual = specializer->doSpecialization( (*formal )->get_type(), *actual, &appExpr->get_inferParams() );
    181314                }
    182315        }
     
    190323                        // don't need to do this for intrinsic calls, because they aren't actually passed
    191324                        for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
    192                                 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
     325                                inferParam->second.expr = specializer->doSpecialization( inferParam->second.formalType, inferParam->second.expr, inferParam->second.inferParams.get() );
    193326                        }
    194 
    195327                        handleExplicitParams( appExpr );
    196328                }
    197 
    198329                return appExpr;
    199330        }
     
    202333                addrExpr->get_arg()->acceptMutator( *this );
    203334                assert( addrExpr->has_result() );
    204                 addrExpr->set_arg( doSpecialization( addrExpr->get_result(), addrExpr->get_arg() ) );
     335                addrExpr->set_arg( specializer->doSpecialization( addrExpr->get_result(), addrExpr->get_arg() ) );
    205336                return addrExpr;
    206337        }
     
    212343                        return castExpr;
    213344                }
    214                 Expression *specialized = doSpecialization( castExpr->get_result(), castExpr->get_arg() );
     345                Expression *specialized = specializer->doSpecialization( castExpr->get_result(), castExpr->get_arg() );
    215346                if ( specialized != castExpr->get_arg() ) {
    216347                        // assume here that the specialization incorporates the cast
     
    236367        //      return commaExpr;
    237368        // }
     369
     370        void convertSpecializations( std::list< Declaration* >& translationUnit ) {
     371                Specialize spec;
     372
     373                TupleSpecializer tupleSpec( spec );
     374                spec.specializer = &tupleSpec;
     375                mutateAll( translationUnit, spec );
     376
     377                PolySpecializer polySpec( spec );
     378                spec.specializer = &polySpec;
     379                mutateAll( translationUnit, spec );
     380        }
    238381} // namespace GenPoly
    239382
Note: See TracChangeset for help on using the changeset viewer.