Ignore:
Timestamp:
Mar 15, 2017, 5:01:18 PM (8 years ago)
Author:
Aaron Moss <a3moss@…>
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:
9b443c7f
Parents:
17df48e
Message:

Fixed Box(T*) generic instantiation bug

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/GenPoly.cc

    r17df48e r5a3ac84  
    1515
    1616#include "GenPoly.h"
     17#include "assert.h"
    1718
    1819#include "SynTree/Expression.h"
    1920#include "SynTree/Type.h"
     21#include "ResolvExpr/typeops.h"
    2022
    2123#include <iostream>
     24#include <iterator>
     25#include <list>
     26#include <typeindex>
     27#include <typeinfo>
     28#include <vector>
    2229using namespace std;
    2330
     
    3845                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    3946                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    40                                 assert(paramType && "Aggregate parameters should be type expressions");
     47                                assertf(paramType, "Aggregate parameters should be type expressions");
    4148                                if ( isPolyType( paramType->get_type(), tyVars, env ) ) return true;
    4249                        }
     
    4855                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    4956                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    50                                 assert(paramType && "Aggregate parameters should be type expressions");
     57                                assertf(paramType, "Aggregate parameters should be type expressions");
    5158                                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;
    5279                        }
    5380                        return false;
     
    187214
    188215                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;
    189248        }
    190249
     
    237296        }
    238297
     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
    239430        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    240431                tyVarMap[ tyVar->get_name() ] = TypeDecl::Data{ tyVar };
Note: See TracChangeset for help on using the changeset viewer.