Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/GenPoly.cc

    r5a3ac84 r7350ff97  
    1515
    1616#include "GenPoly.h"
    17 #include "assert.h"
    1817
    1918#include "SynTree/Expression.h"
    2019#include "SynTree/Type.h"
    21 #include "ResolvExpr/typeops.h"
    2220
    2321#include <iostream>
    24 #include <iterator>
    25 #include <list>
    26 #include <typeindex>
    27 #include <typeinfo>
    28 #include <vector>
    2922using namespace std;
    3023
     
    4538                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    4639                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    47                                 assertf(paramType, "Aggregate parameters should be type expressions");
     40                                assert(paramType && "Aggregate parameters should be type expressions");
    4841                                if ( isPolyType( paramType->get_type(), tyVars, env ) ) return true;
    4942                        }
     
    5548                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    5649                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    57                                 assertf(paramType, "Aggregate parameters should be type expressions");
     50                                assert(paramType && "Aggregate parameters should be type expressions");
    5851                                if ( isDynType( paramType->get_type(), tyVars, env ) ) return true;
    59                         }
    60                         return false;
    61                 }
    62 
    63                 /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present
    64                 bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
    65                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    66                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    67                                 assertf(paramType, "Aggregate parameters should be type expressions");
    68                                 if ( includesPolyType( paramType->get_type(), env ) ) return true;
    69                         }
    70                         return false;
    71                 }
    72 
    73                 /// Checks a parameter list for inclusion of polymorphic parameters from tyVars; will substitute according to env if present
    74                 bool includesPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    75                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    76                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    77                                 assertf(paramType, "Aggregate parameters should be type expressions");
    78                                 if ( includesPolyType( paramType->get_type(), tyVars, env ) ) return true;
    7952                        }
    8053                        return false;
     
    214187
    215188                return isPolyType( type, tyVars, env );
    216         }
    217 
    218         bool includesPolyType( Type *type, const TypeSubstitution *env ) {
    219                 type = replaceTypeInst( type, env );
    220 
    221                 if ( dynamic_cast< TypeInstType * >( type ) ) {
    222                         return true;
    223                 } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
    224                         if ( includesPolyType( pointerType->get_base(), env ) ) return true;
    225                 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    226                         if ( includesPolyParams( structType->get_parameters(), env ) ) return true;
    227                 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    228                         if ( includesPolyParams( unionType->get_parameters(), env ) ) return true;
    229                 }
    230                 return false;
    231         }
    232 
    233         bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    234                 type = replaceTypeInst( type, env );
    235 
    236                 if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
    237                         if ( tyVars.find( typeInstType->get_name() ) != tyVars.end() ) {
    238                                 return true;
    239                         }
    240                 } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
    241                         if ( includesPolyType( pointerType->get_base(), tyVars, env ) ) return true;
    242                 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    243                         if ( includesPolyParams( structType->get_parameters(), tyVars, env ) ) return true;
    244                 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    245                         if ( includesPolyParams( unionType->get_parameters(), tyVars, env ) ) return true;
    246                 }
    247                 return false;
    248189        }
    249190
     
    296237        }
    297238
    298         namespace {
    299                 /// Checks if is a pointer to D
    300                 template<typename D, typename B>
    301                 bool is( const B* p ) { return type_index{typeid(D)} == type_index{typeid(*p)}; }
    302 
    303                 /// Converts to a pointer to D without checking for safety
    304                 template<typename D, typename B>
    305                 inline D* as( B* p ) { return reinterpret_cast<D*>(p); }
    306 
    307                 /// Flattens a declaration list
    308                 template<typename Output>
    309                 void flattenList( list< DeclarationWithType* > src, Output out ) {
    310                         for ( DeclarationWithType* decl : src ) {
    311                                 ResolvExpr::flatten( decl->get_type(), out );
    312                         }
    313                 }
    314 
    315                 /// Flattens a list of types
    316                 template<typename Output>
    317                 void flattenList( list< Type* > src, Output out ) {
    318                         for ( Type* ty : src ) {
    319                                 ResolvExpr::flatten( ty, out );
    320                         }
    321                 }
    322 
    323                 /// Checks if two lists of parameters are equal up to polymorphic substitution.
    324                 bool paramListsPolyCompatible( const list< Expression* >& aparams, const list< Expression* >& bparams ) {
    325                         if ( aparams.size() != bparams.size() ) return false;
    326 
    327                         for ( list< Expression* >::const_iterator at = aparams.begin(), bt = bparams.begin();
    328                                         at != aparams.end(); ++at, ++bt ) {
    329                                 TypeExpr *aparam = dynamic_cast< TypeExpr* >(*at);
    330                                 assertf(aparam, "Aggregate parameters should be type expressions");
    331                                 TypeExpr *bparam = dynamic_cast< TypeExpr* >(*bt);
    332                                 assertf(bparam, "Aggregate parameters should be type expressions");
    333 
    334                                 // xxx - might need to let VoidType be a wildcard here too; could have some voids
    335                                 // stuffed in for dtype-statics.
    336                                 // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
    337                                 if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;
    338                         }
    339                        
    340                         return true;
    341                 }
    342         }
    343 
    344         bool typesPolyCompatible( Type *a, Type *b ) {
    345                 type_index aid{ typeid(*a) };
    346                 // polymorphic types always match
    347                 if ( aid == type_index{typeid(TypeInstType)} ) return true;
    348                
    349                 type_index bid{ typeid(*b) };
    350                 // polymorphic types always match
    351                 if ( bid == type_index{typeid(TypeInstType)} ) return true;
    352                
    353                 // can't match otherwise if different types
    354                 if ( aid != bid ) return false;
    355 
    356                 // recurse through type structure (conditions borrowed from Unify.cc)
    357                 if ( aid == type_index{typeid(BasicType)} ) {
    358                         return as<BasicType>(a)->get_kind() == as<BasicType>(b)->get_kind();
    359                 } else if ( aid == type_index{typeid(PointerType)} ) {
    360                         PointerType *ap = as<PointerType>(a), *bp = as<PointerType>(b);
    361 
    362                         // void pointers should match any other pointer type
    363                         return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )
    364                                 || typesPolyCompatible( ap->get_base(), bp->get_base() );
    365                 } else if ( aid == type_index{typeid(ArrayType)} ) {
    366                         ArrayType *aa = as<ArrayType>(a), *ba = as<ArrayType>(b);
    367 
    368                         if ( aa->get_isVarLen() ) {
    369                                 if ( ! ba->get_isVarLen() ) return false;
    370                         } else {
    371                                 if ( ba->get_isVarLen() ) return false;
    372 
    373                                 ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() );
    374                                 ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() );
    375                                 if ( ad && bd
    376                                                 && ad->get_constant()->get_value() != bd->get_constant()->get_value() )
    377                                         return false;
    378                         }
    379 
    380                         return typesPolyCompatible( aa->get_base(), ba->get_base() );
    381                 } else if ( aid == type_index{typeid(FunctionType)} ) {
    382                         FunctionType *af = as<FunctionType>(a), *bf = as<FunctionType>(b);
    383 
    384                         vector<Type*> aparams, bparams;
    385                         flattenList( af->get_parameters(), back_inserter( aparams ) );
    386                         flattenList( bf->get_parameters(), back_inserter( bparams ) );
    387                         if ( aparams.size() != bparams.size() ) return false;
    388 
    389                         vector<Type*> areturns, breturns;
    390                         flattenList( af->get_returnVals(), back_inserter( areturns ) );
    391                         flattenList( bf->get_returnVals(), back_inserter( breturns ) );
    392                         if ( areturns.size() != breturns.size() ) return false;
    393 
    394                         for ( unsigned i = 0; i < aparams.size(); ++i ) {
    395                                 if ( ! typesPolyCompatible( aparams[i], bparams[i] ) ) return false;
    396                         }
    397                         for ( unsigned i = 0; i < areturns.size(); ++i ) {
    398                                 if ( ! typesPolyCompatible( areturns[i], breturns[i] ) ) return false;
    399                         }
    400                         return true;
    401                 } else if ( aid == type_index{typeid(StructInstType)} ) {
    402                         StructInstType *aa = as<StructInstType>(a), *ba = as<StructInstType>(b);
    403 
    404                         if ( aa->get_name() != ba->get_name() ) return false;
    405                         return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
    406                 } else if ( aid == type_index{typeid(UnionInstType)} ) {
    407                         UnionInstType *aa = as<UnionInstType>(a), *ba = as<UnionInstType>(b);
    408 
    409                         if ( aa->get_name() != ba->get_name() ) return false;
    410                         return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
    411                 } else if ( aid == type_index{typeid(EnumInstType)} ) {
    412                         return as<EnumInstType>(a)->get_name() == as<EnumInstType>(b)->get_name();
    413                 } else if ( aid == type_index{typeid(TraitInstType)} ) {
    414                         return as<TraitInstType>(a)->get_name() == as<TraitInstType>(b)->get_name();
    415                 } else if ( aid == type_index{typeid(TupleType)} ) {
    416                         TupleType *at = as<TupleType>(a), *bt = as<TupleType>(b);
    417 
    418                         vector<Type*> atypes, btypes;
    419                         flattenList( at->get_types(), back_inserter( atypes ) );
    420                         flattenList( bt->get_types(), back_inserter( btypes ) );
    421                         if ( atypes.size() != btypes.size() ) return false;
    422 
    423                         for ( unsigned i = 0; i < atypes.size(); ++i ) {
    424                                 if ( ! typesPolyCompatible( atypes[i], btypes[i] ) ) return false;
    425                         }
    426                         return true;
    427                 } else return true; // VoidType, VarArgsType, ZeroType & OneType just need the same type
    428         }
    429 
    430239        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    431240                tyVarMap[ tyVar->get_name() ] = TypeDecl::Data{ tyVar };
Note: See TracChangeset for help on using the changeset viewer.