Changes in / [2ad507b8:fbcb354]


Ignore:
Location:
src
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r2ad507b8 rfbcb354  
    749749                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    750750                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    751                                                 referenceToRvalueConversion( func->expr );
     751                                                Alternative newFunc( *func );
     752                                                referenceToRvalueConversion( newFunc.expr );
    752753                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    753754                                                        // XXX
    754755                                                        //Designators::check_alternative( function, *actualAlt );
    755                                                         makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     756                                                        makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
    756757                                                }
    757758                                        }
    758759                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
    759                                         referenceToRvalueConversion( func->expr );
    760760                                        EqvClass eqvClass;
    761761                                        if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    762762                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     763                                                        Alternative newFunc( *func );
     764                                                        referenceToRvalueConversion( newFunc.expr );
    763765                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    764                                                                 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     766                                                                makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
    765767                                                        } // for
    766768                                                } // if
     
    773775                                        if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
    774776                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    775                                                         referenceToRvalueConversion( funcOp->expr );
     777                                                        Alternative newFunc( *funcOp );
     778                                                        referenceToRvalueConversion( newFunc.expr );
    776779                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    777780                                                                AltList currentAlt;
    778781                                                                currentAlt.push_back( *func );
    779782                                                                currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
    780                                                                 makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
     783                                                                makeFunctionAlternatives( newFunc, function, currentAlt, std::back_inserter( candidates ) );
    781784                                                        } // for
    782785                                                } // if
  • src/ResolvExpr/RenameVars.cc

    r2ad507b8 rfbcb354  
    8888                typeBefore( aggregateUseType );
    8989                acceptAll( aggregateUseType->get_parameters(), *this );
    90                 acceptAll( aggregateUseType->get_members(), *this );
    9190                typeAfter( aggregateUseType );
    9291        }
  • src/ResolvExpr/TypeEnvironment.cc

    r2ad507b8 rfbcb354  
    2525
    2626namespace ResolvExpr {
    27         // adding this comparison operator significantly improves assertion resolution run time for
    28         // some cases. The current resolution algorithm's speed partially depends on the order of
    29         // assertions. Assertions which have fewer possible matches should appear before
    30         // assertions which have more possible matches. This seems to imply that this could
    31         // be further improved by providing an indexer as an additional argument and ordering based
    32         // on the number of matches of the same kind (object, function) for the names of the
    33         // declarations.
    34         //
    35         // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
    36         bool AssertCompare::operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
    37                         // Objects are always less than functions
    38                         if ( ObjectDecl * objectDecl1 = dynamic_cast< ObjectDecl * >( d1 ) ) {
    39                                 if ( ObjectDecl * objectDecl2 = dynamic_cast< ObjectDecl * >( d2 ) ) {
    40                                         // objects are ordered by name then type pointer, in that order
    41                                         int cmp = objectDecl1->get_name().compare( objectDecl2->get_name() );
    42                                         return cmp < 0 ||
    43                                                 ( cmp == 0 && objectDecl1->get_type() < objectDecl2->get_type() );
    44                                 } else {
    45                                         return true;
    46                                 }
    47                         } else if ( FunctionDecl * funcDecl1 = dynamic_cast< FunctionDecl * >( d1 ) ) {
    48                                 if ( FunctionDecl * funcDecl2 = dynamic_cast< FunctionDecl * >( d2 ) ) {
    49                                         // functions are ordered by name, # parameters, # returnVals, type pointer in that order
    50                                         FunctionType * ftype1 = funcDecl1->get_functionType();
    51                                         FunctionType * ftype2 = funcDecl2->get_functionType();
    52                                         int numThings1 = ftype1->get_parameters().size() + ftype1->get_returnVals().size();
    53                                         int numThings2 = ftype2->get_parameters().size() + ftype2->get_returnVals().size();
    54                                         if ( numThings1 < numThings2 ) return true;
    55                                         if ( numThings1 > numThings2 ) return false;
    56 
    57                                         // if ( ftype1->get_parameters().size() < ftype2->get_parameters().size() ) return true;
    58                                         // else if ( ftype1->get_parameters().size() > ftype2->get_parameters().size() ) return false;
    59                                         // // same number of parameters
    60                                         // if ( ftype1->get_returnVals().size() < ftype2->get_returnVals().size() ) return true;
    61                                         // else if ( ftype1->get_returnVals().size() > ftype2->get_returnVals().size() ) return false;
    62                                         // same number of return vals
    63                                         // int cmp = funcDecl1->get_name().compare( funcDecl2->get_name() );
    64                                         // if ( cmp < 0 ) return true;
    65                                         // else if ( cmp > 0 ) return false;
    66                                         // // same name
    67                                         return ftype1 < ftype2;
    68                                 } else {
    69                                         return false;
    70                                 }
    71                         } else {
    72                                 assert( false );
    73                         }
    74                 }
    75 
    7627        void printAssertionSet( const AssertionSet &assertions, std::ostream &os, int indent ) {
    7728                for ( AssertionSet::const_iterator i = assertions.begin(); i != assertions.end(); ++i ) {
  • src/ResolvExpr/TypeEnvironment.h

    r2ad507b8 rfbcb354  
    2828
    2929namespace ResolvExpr {
     30        // adding this comparison operator significantly improves assertion resolution run time for
     31        // some cases. The current resolution algorithm's speed partially depends on the order of
     32        // assertions. Assertions which have fewer possible matches should appear before
     33        // assertions which have more possible matches. This seems to imply that this could
     34        // be further improved by providing an indexer as an additional argument and ordering based
     35        // on the number of matches of the same kind (object, function) for the names of the
     36        // declarations.
     37        //
     38        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
    3039        struct AssertCompare {
    31                 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const;
     40                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
     41                        int cmp = d1->get_name().compare( d2->get_name() );
     42                        return cmp < 0 ||
     43                                ( cmp == 0 && d1->get_type() < d2->get_type() );
     44                }
    3245        };
    3346        struct AssertionSetValue {
  • src/SymTab/Indexer.cc

    r2ad507b8 rfbcb354  
    554554
    555555
    556         void Indexer::visit( TraitInstType *contextInst ) {
    557                 acceptAll( contextInst->get_parameters(), *this );
    558                 acceptAll( contextInst->get_members(), *this );
     556        void Indexer::visit( TraitInstType *traitInst ) {
     557                acceptAll( traitInst->get_parameters(), *this );
    559558        }
    560559
  • src/SymTab/Validate.cc

    r2ad507b8 rfbcb354  
    127127          public:
    128128                LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
    129                 using Parent::visit;
     129                using Parent::visit;
     130                void visit( TypeInstType *typeInst ) final;
     131
    130132                void visit( EnumInstType *enumInst ) final;
    131133                void visit( StructInstType *structInst ) final;
    132134                void visit( UnionInstType *unionInst ) final;
    133                 void visit( TraitInstType *contextInst ) final;
     135                void visit( TraitInstType *traitInst ) final;
     136
    134137                void visit( EnumDecl *enumDecl ) final;
    135138                void visit( StructDecl *structDecl ) final;
    136139                void visit( UnionDecl *unionDecl ) final;
    137                 void visit( TypeInstType *typeInst ) final;
     140                void visit( TraitDecl * traitDecl ) final;
     141
    138142          private:
    139143                const Indexer *indexer;
     
    453457        }
    454458
    455         void LinkReferenceToTypes::visit( TraitInstType *traitInst ) {
     459        template< typename Decl >
     460        void normalizeAssertions( std::list< Decl * > & assertions ) {
     461                // ensure no duplicate trait members after the clone
     462                auto pred = [](Decl * d1, Decl * d2) {
     463                        // only care if they're equal
     464                        DeclarationWithType * dwt1 = dynamic_cast<DeclarationWithType *>( d1 );
     465                        DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
     466                        if ( dwt1 && dwt2 ) {
     467                                if ( dwt1->get_name() == dwt2->get_name() && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
     468                                        // std::cerr << "=========== equal:" << std::endl;
     469                                        // std::cerr << "d1: " << d1 << std::endl;
     470                                        // std::cerr << "d2: " << d2 << std::endl;
     471                                        return false;
     472                                }
     473                        }
     474                        return d1 < d2;
     475                };
     476                std::set<Decl *, decltype(pred)> unique_members( assertions.begin(), assertions.end(), pred );
     477                // if ( unique_members.size() != assertions.size() ) {
     478                //      std::cerr << "============different" << std::endl;
     479                //      std::cerr << unique_members.size() << " " << assertions.size() << std::endl;
     480                // }
     481
     482                std::list< Decl * > order;
     483                order.splice( order.end(), assertions );
     484                std::copy_if( order.begin(), order.end(), back_inserter( assertions ), [&]( Decl * decl ) {
     485                        return unique_members.count( decl );
     486                });
     487        }
     488
     489        // expand assertions from trait instance, performing the appropriate type variable substitutions
     490        template< typename Iterator >
     491        void expandAssertions( TraitInstType * inst, Iterator out ) {
     492                assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toString( inst ).c_str() );
     493                std::list< DeclarationWithType * > asserts;
     494                for ( Declaration * decl : inst->baseTrait->members ) {
     495                        asserts.push_back( safe_dynamic_cast<DeclarationWithType *>( decl->clone() ) );
     496                }
     497                // substitute trait decl parameters for instance parameters
     498                applySubstitution( inst->baseTrait->parameters.begin(), inst->baseTrait->parameters.end(), inst->parameters.begin(), asserts.begin(), asserts.end(), out );
     499        }
     500
     501        void LinkReferenceToTypes::visit( TraitDecl * traitDecl ) {
     502                Parent::visit( traitDecl );
     503
     504                if ( traitDecl->name == "sized" ) {
     505                        // "sized" is a special trait - flick the sized status on for the type variable
     506                        assertf( traitDecl->parameters.size() == 1, "Built-in trait 'sized' has incorrect number of parameters: %zd", traitDecl->parameters.size() );
     507                        TypeDecl * td = traitDecl->parameters.front();
     508                        td->set_sized( true );
     509                }
     510
     511                // move assertions from type parameters into the body of the trait
     512                for ( TypeDecl * td : traitDecl->parameters ) {
     513                        for ( DeclarationWithType * assert : td->assertions ) {
     514                                if ( TraitInstType * inst = dynamic_cast< TraitInstType * >( assert->get_type() ) ) {
     515                                        expandAssertions( inst, back_inserter( traitDecl->members ) );
     516                                } else {
     517                                        traitDecl->members.push_back( assert->clone() );
     518                                }
     519                        }
     520                        deleteAll( td->assertions );
     521                        td->assertions.clear();
     522                } // for
     523        }
     524
     525        void LinkReferenceToTypes::visit( TraitInstType * traitInst ) {
    456526                Parent::visit( traitInst );
    457                 if ( traitInst->get_name() == "sized" ) {
    458                         // "sized" is a special trait with no members - just flick the sized status on for the type variable
    459                         if ( traitInst->get_parameters().size() != 1 ) {
    460                                 throw SemanticError( "incorrect number of trait parameters: ", traitInst );
    461                         }
    462                         TypeExpr * param = safe_dynamic_cast< TypeExpr * > ( traitInst->get_parameters().front() );
    463                         TypeInstType * inst = safe_dynamic_cast< TypeInstType * > ( param->get_type() );
    464                         TypeDecl * decl = inst->get_baseType();
    465                         decl->set_sized( true );
    466                         // since "sized" is special, the next few steps don't apply
    467                         return;
    468                 }
    469 
    470527                // handle other traits
    471                 TraitDecl *traitDecl = indexer->lookupTrait( traitInst->get_name() );
     528                TraitDecl *traitDecl = indexer->lookupTrait( traitInst->name );
    472529                if ( ! traitDecl ) {
    473                         throw SemanticError( "use of undeclared trait " + traitInst->get_name() );
     530                        throw SemanticError( "use of undeclared trait " + traitInst->name );
    474531                } // if
    475532                if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
    476533                        throw SemanticError( "incorrect number of trait parameters: ", traitInst );
    477534                } // if
    478 
    479                 for ( TypeDecl * td : traitDecl->get_parameters() ) {
    480                         for ( DeclarationWithType * assert : td->get_assertions() ) {
    481                                 traitInst->get_members().push_back( assert->clone() );
    482                         } // for
    483                 } // for
    484 
    485                 // need to clone members of the trait for ownership purposes
    486                 std::list< Declaration * > members;
    487                 std::transform( traitDecl->get_members().begin(), traitDecl->get_members().end(), back_inserter( members ), [](Declaration * dwt) { return dwt->clone(); } );
    488 
    489                 applySubstitution( traitDecl->get_parameters().begin(), traitDecl->get_parameters().end(), traitInst->get_parameters().begin(), members.begin(), members.end(), back_inserter( traitInst->get_members() ) );
     535                traitInst->baseTrait = traitDecl;
    490536
    491537                // need to carry over the 'sized' status of each decl in the instance
     
    498544                        }
    499545                }
     546                // normalizeAssertions( traitInst->members );
    500547        }
    501548
     
    561608        void forallFixer( Type * func ) {
    562609                for ( TypeDecl * type : func->get_forall() ) {
    563                         std::list< DeclarationWithType * > toBeDone, nextRound;
    564                         toBeDone.splice( toBeDone.end(), type->get_assertions() );
    565                         while ( ! toBeDone.empty() ) {
    566                                 for ( DeclarationWithType * assertion : toBeDone ) {
    567                                         if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
    568                                                 // expand trait instance into all of its members
    569                                                 for ( Declaration * member : traitInst->get_members() ) {
    570                                                         DeclarationWithType *dwt = safe_dynamic_cast< DeclarationWithType * >( member );
    571                                                         nextRound.push_back( dwt->clone() );
    572                                                 }
    573                                                 delete traitInst;
    574                                         } else {
    575                                                 // pass assertion through
    576                                                 FixFunction fixer;
    577                                                 assertion = assertion->acceptMutator( fixer );
    578                                                 if ( fixer.get_isVoid() ) {
    579                                                         throw SemanticError( "invalid type void in assertion of function ", func );
    580                                                 }
    581                                                 type->get_assertions().push_back( assertion );
    582                                         } // if
    583                                 } // for
    584                                 toBeDone.clear();
    585                                 toBeDone.splice( toBeDone.end(), nextRound );
    586                         } // while
     610                        std::list< DeclarationWithType * > asserts;
     611                        asserts.splice( asserts.end(), type->assertions );
     612                        // expand trait instances into their members
     613                        for ( DeclarationWithType * assertion : asserts ) {
     614                                if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     615                                        // expand trait instance into all of its members
     616                                        expandAssertions( traitInst, back_inserter( type->assertions ) );
     617                                        delete traitInst;
     618                                } else {
     619                                        // pass other assertions through
     620                                        type->assertions.push_back( assertion );
     621                                } // if
     622                        } // for
     623                        // apply FixFunction to every assertion to check for invalid void type
     624                        for ( DeclarationWithType *& assertion : type->assertions ) {
     625                                FixFunction fixer;
     626                                assertion = assertion->acceptMutator( fixer );
     627                                if ( fixer.get_isVoid() ) {
     628                                        throw SemanticError( "invalid type void in assertion of function ", func );
     629                                } // if
     630                        } // for
     631                        // normalizeAssertions( type->assertions );
    587632                } // for
    588633        }
  • src/SynTree/Mutator.cc

    r2ad507b8 rfbcb354  
    538538Type * Mutator::mutate( TraitInstType *aggregateUseType ) {
    539539        handleReferenceToType( aggregateUseType );
    540         mutateAll( aggregateUseType->get_members(), *this );
    541540        return aggregateUseType;
    542541}
  • src/SynTree/ReferenceToType.cc

    r2ad507b8 rfbcb354  
    132132std::string TraitInstType::typeString() const { return "trait"; }
    133133
    134 TraitInstType::TraitInstType( const TraitInstType &other ) : Parent( other ) {
    135         cloneAll( other.members, members );
     134TraitInstType::TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes ) : Parent( tq, baseTrait->name, attributes ), baseTrait( baseTrait ) {}
     135
     136TraitInstType::TraitInstType( const TraitInstType &other ) : Parent( other ), baseTrait( other.baseTrait ) {
    136137}
    137138
    138139TraitInstType::~TraitInstType() {
    139         deleteAll( members );
    140140}
    141141
  • src/SynTree/Type.h

    r2ad507b8 rfbcb354  
    471471        typedef ReferenceToType Parent;
    472472  public:
    473         // this member is filled in by the validate pass, which instantiates the members of the correponding
    474         // aggregate with the actual type parameters specified for this use of the context
    475         std::list< Declaration* > members;
    476 
    477         TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
     473        // this decl is not "owned" by the trait inst; it is merely a pointer to elsewhere in the tree,
     474        // where the trait used in this type is actually defined
     475        TraitDecl * baseTrait = nullptr;
     476
     477        TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {}
     478        TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    478479        TraitInstType( const TraitInstType & other );
    479480        ~TraitInstType();
    480 
    481         std::list< Declaration* >& get_members() { return members; }
    482481
    483482        virtual bool isComplete() const;
  • src/SynTree/TypeSubstitution.h

    r2ad507b8 rfbcb354  
    177177void applySubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actual, MemberIterator memberBegin, MemberIterator memberEnd, OutputIterator out ) {
    178178        TypeSubstitution sub = TypeSubstitution( formalBegin, formalEnd, actual );
    179         for ( std::list< Declaration* >::iterator i = memberBegin; i != memberEnd; ++i ) {
     179        for ( auto i = memberBegin; i != memberEnd; ++i ) {
    180180                sub.apply( *i );
    181181                *out++ = *i;
  • src/SynTree/Visitor.cc

    r2ad507b8 rfbcb354  
    429429void Visitor::visit( TraitInstType *aggregateUseType ) {
    430430        handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) );
    431         acceptAll( aggregateUseType->get_members(), *this );
    432431}
    433432
  • src/prelude/prelude.cf

    r2ad507b8 rfbcb354  
    1414
    1515// Section numbers from: http://plg.uwaterloo.ca/~cforall/refrat.pdf
     16
     17// ------------------------------------------------------------
     18//
     19// Section 6.7.11 Trait Declarations
     20// Note: the sized trait is used in declarations later in this
     21// file, so it must be out of order.
     22//
     23// ------------------------------------------------------------
     24
     25trait sized(dtype T) {};
    1626
    1727// ------------------------------------------------------------
Note: See TracChangeset for help on using the changeset viewer.