Changeset b6838214 for src/ResolvExpr


Ignore:
Timestamp:
Jan 23, 2018, 5:46:43 PM (8 years ago)
Author:
Alan Kennedy <afakenne@…>
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:
258e6ad5
Parents:
b158d8f (diff), 15d248e (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:

add context switch for ARM

Location:
src/ResolvExpr
Files:
1 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rb158d8f rb6838214  
    6060
    6161namespace ResolvExpr {
     62        struct AlternativeFinder::Finder : public WithShortCircuiting {
     63                Finder( AlternativeFinder & altFinder ) : altFinder( altFinder ), indexer( altFinder.indexer ), alternatives( altFinder.alternatives ), env( altFinder.env ), targetType( altFinder.targetType )  {}
     64
     65                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     66
     67                void postvisit( ApplicationExpr * applicationExpr );
     68                void postvisit( UntypedExpr * untypedExpr );
     69                void postvisit( AddressExpr * addressExpr );
     70                void postvisit( LabelAddressExpr * labelExpr );
     71                void postvisit( CastExpr * castExpr );
     72                void postvisit( VirtualCastExpr * castExpr );
     73                void postvisit( UntypedMemberExpr * memberExpr );
     74                void postvisit( MemberExpr * memberExpr );
     75                void postvisit( NameExpr * variableExpr );
     76                void postvisit( VariableExpr * variableExpr );
     77                void postvisit( ConstantExpr * constantExpr );
     78                void postvisit( SizeofExpr * sizeofExpr );
     79                void postvisit( AlignofExpr * alignofExpr );
     80                void postvisit( UntypedOffsetofExpr * offsetofExpr );
     81                void postvisit( OffsetofExpr * offsetofExpr );
     82                void postvisit( OffsetPackExpr * offsetPackExpr );
     83                void postvisit( AttrExpr * attrExpr );
     84                void postvisit( LogicalExpr * logicalExpr );
     85                void postvisit( ConditionalExpr * conditionalExpr );
     86                void postvisit( CommaExpr * commaExpr );
     87                void postvisit( ImplicitCopyCtorExpr  * impCpCtorExpr );
     88                void postvisit( ConstructorExpr  * ctorExpr );
     89                void postvisit( RangeExpr  * rangeExpr );
     90                void postvisit( UntypedTupleExpr * tupleExpr );
     91                void postvisit( TupleExpr * tupleExpr );
     92                void postvisit( TupleIndexExpr * tupleExpr );
     93                void postvisit( TupleAssignExpr * tupleExpr );
     94                void postvisit( UniqueExpr * unqExpr );
     95                void postvisit( StmtExpr * stmtExpr );
     96                void postvisit( UntypedInitExpr * initExpr );
     97
     98                /// Adds alternatives for anonymous members
     99                void addAnonConversions( const Alternative & alt );
     100                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
     101                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
     102                /// Adds alternatives for member expressions where the left side has tuple type
     103                void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
     104                /// Adds alternatives for offsetof expressions, given the base type and name of the member
     105                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     106                /// Takes a final result and checks if its assertions can be satisfied
     107                template<typename OutputIterator>
     108                void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out );
     109                /// Finds matching alternatives for a function, given a set of arguments
     110                template<typename OutputIterator>
     111                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
     112                /// Checks if assertion parameters match for a new alternative
     113                template< typename OutputIterator >
     114                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     115        private:
     116                AlternativeFinder & altFinder;
     117                const SymTab::Indexer &indexer;
     118                AltList & alternatives;
     119                const TypeEnvironment &env;
     120                Type *& targetType;
     121        };
     122
    62123        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
    63124                CastExpr *castToVoid = new CastExpr( expr );
     
    152213
    153214                void renameTypes( Expression *expr ) {
    154                         expr->get_result()->accept( global_renamer );
     215                        renameTyVars( expr->result );
    155216                }
    156217        } // namespace
     
    185246
    186247        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
    187                 expr->accept( *this );
     248                PassVisitor<Finder> finder( *this );
     249                expr->accept( finder );
    188250                if ( failFast && alternatives.empty() ) {
    189251                        PRINT(
     
    244306        }
    245307
    246         void AlternativeFinder::addAnonConversions( const Alternative & alt ) {
     308        void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) {
    247309                // adds anonymous member interpretations whenever an aggregate value type is seen.
    248310                // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
     
    265327
    266328        template< typename StructOrUnionType >
    267         void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
     329        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    268330                // by this point, member must be a name expr
    269331                NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
     
    284346        }
    285347
    286         void AlternativeFinder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
     348        void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    287349                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    288350                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
     
    308370        }
    309371
    310         void AlternativeFinder::visit( ApplicationExpr *applicationExpr ) {
     372        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    311373                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    312374        }
     
    485547                        Type *adjType = candidate->get_type()->clone();
    486548                        adjustExprType( adjType, newEnv, indexer );
    487                         adjType->accept( global_renamer );
     549                        renameTyVars( adjType );
    488550                        PRINT(
    489551                                std::cerr << "unifying ";
     
    541603
    542604        template< typename OutputIterator >
    543         void AlternativeFinder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
     605        void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
    544606//      PRINT(
    545607//          std::cerr << "inferParameters: assertions needed are" << std::endl;
     
    596658                ArgPack()
    597659                        : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0),
    598 
    599660                          tupleStart(0), nextExpl(0), explAlt(0) {}
    600661
     
    706767                                                Type* argType;
    707768
    708                                                 if ( nTuples > 0 ) {
    709                                                         // first iteration, push empty tuple expression
     769                                                if ( nTuples > 0 || ! results[i].expr ) {
     770                                                        // first iteration or no expression to clone,
     771                                                        // push empty tuple expression
    710772                                                        newResult.parent = i;
    711773                                                        std::list<Expression*> emptyList;
     
    892954
    893955        template<typename OutputIterator>
    894         void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
     956        void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
    895957                        const std::vector<ArgPack>& results, OutputIterator out ) {
    896958                ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
     
    915977
    916978        template<typename OutputIterator>
    917         void AlternativeFinder::makeFunctionAlternatives( const Alternative &func,
     979        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    918980                        FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
    919981                OpenVarSet funcOpenVars;
     
    10221084        }
    10231085
    1024         void AlternativeFinder::visit( UntypedExpr *untypedExpr ) {
     1086        void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) {
    10251087                AlternativeFinder funcFinder( indexer, env );
    10261088                funcFinder.findWithAdjustment( untypedExpr->get_function() );
     
    10291091
    10301092                std::vector< AlternativeFinder > argAlternatives;
    1031                 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
     1093                altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
    10321094                        back_inserter( argAlternatives ) );
    10331095
    10341096                // take care of possible tuple assignments
    10351097                // if not tuple assignment, assignment is taken care of as a normal function call
    1036                 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );
     1098                Tuples::handleTupleAssignment( altFinder, untypedExpr, argAlternatives );
    10371099
    10381100                // find function operators
     
    11721234                        // fix this issue in a more robust way.
    11731235                        targetType = nullptr;
    1174                         visit( untypedExpr );
     1236                        postvisit( untypedExpr );
    11751237                }
    11761238        }
     
    11811243        }
    11821244
    1183         void AlternativeFinder::visit( AddressExpr *addressExpr ) {
     1245        void AlternativeFinder::Finder::postvisit( AddressExpr *addressExpr ) {
    11841246                AlternativeFinder finder( indexer, env );
    11851247                finder.find( addressExpr->get_arg() );
     
    11921254        }
    11931255
    1194         void AlternativeFinder::visit( LabelAddressExpr * expr ) {
     1256        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    11951257                alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
    11961258        }
     
    12231285        }
    12241286
    1225         void AlternativeFinder::visit( CastExpr *castExpr ) {
     1287        void AlternativeFinder::Finder::postvisit( CastExpr *castExpr ) {
    12261288                Type *& toType = castExpr->get_result();
    12271289                assert( toType );
     
    12781340        }
    12791341
    1280         void AlternativeFinder::visit( VirtualCastExpr * castExpr ) {
     1342        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    12811343                assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
    12821344                AlternativeFinder finder( indexer, env );
     
    12901352        }
    12911353
    1292         void AlternativeFinder::visit( UntypedMemberExpr *memberExpr ) {
     1354        void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) {
    12931355                AlternativeFinder funcFinder( indexer, env );
    12941356                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
     
    13121374        }
    13131375
    1314         void AlternativeFinder::visit( MemberExpr *memberExpr ) {
     1376        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    13151377                alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    13161378        }
    13171379
    1318         void AlternativeFinder::visit( NameExpr *nameExpr ) {
     1380        void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) {
    13191381                std::list< SymTab::Indexer::IdData > declList;
    13201382                indexer.lookupId( nameExpr->get_name(), declList );
     
    13371399        }
    13381400
    1339         void AlternativeFinder::visit( VariableExpr *variableExpr ) {
     1401        void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) {
    13401402                // not sufficient to clone here, because variable's type may have changed
    13411403                // since the VariableExpr was originally created.
     
    13431405        }
    13441406
    1345         void AlternativeFinder::visit( ConstantExpr *constantExpr ) {
     1407        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    13461408                alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    13471409        }
    13481410
    1349         void AlternativeFinder::visit( SizeofExpr *sizeofExpr ) {
     1411        void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) {
    13501412                if ( sizeofExpr->get_isType() ) {
    13511413                        Type * newType = sizeofExpr->get_type()->clone();
     
    13681430        }
    13691431
    1370         void AlternativeFinder::visit( AlignofExpr *alignofExpr ) {
     1432        void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) {
    13711433                if ( alignofExpr->get_isType() ) {
    13721434                        Type * newType = alignofExpr->get_type()->clone();
     
    13901452
    13911453        template< typename StructOrUnionType >
    1392         void AlternativeFinder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {
     1454        void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {
    13931455                std::list< Declaration* > members;
    13941456                aggInst->lookup( name, members );
     
    14031465        }
    14041466
    1405         void AlternativeFinder::visit( UntypedOffsetofExpr *offsetofExpr ) {
     1467        void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) {
    14061468                AlternativeFinder funcFinder( indexer, env );
    14071469                // xxx - resolveTypeof?
     
    14131475        }
    14141476
    1415         void AlternativeFinder::visit( OffsetofExpr *offsetofExpr ) {
     1477        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    14161478                alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
    14171479        }
    14181480
    1419         void AlternativeFinder::visit( OffsetPackExpr *offsetPackExpr ) {
     1481        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    14201482                alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
    14211483        }
     
    14441506        }
    14451507
    1446         void AlternativeFinder::visit( AttrExpr *attrExpr ) {
     1508        void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) {
    14471509                // assume no 'pointer-to-attribute'
    14481510                NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
     
    14581520                                        if ( function->get_parameters().size() == 1 ) {
    14591521                                                if ( attrExpr->get_isType() ) {
    1460                                                         resolveAttr( data, function, attrExpr->get_type(), env, *this );
     1522                                                        resolveAttr( data, function, attrExpr->get_type(), env, altFinder);
    14611523                                                } else {
    14621524                                                        AlternativeFinder finder( indexer, env );
     
    14641526                                                        for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    14651527                                                                if ( choice->expr->get_result()->size() == 1 ) {
    1466                                                                         resolveAttr(data, function, choice->expr->get_result(), choice->env, *this );
     1528                                                                        resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder );
    14671529                                                                } // fi
    14681530                                                        } // for
     
    14791541        }
    14801542
    1481         void AlternativeFinder::visit( LogicalExpr *logicalExpr ) {
     1543        void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) {
    14821544                AlternativeFinder firstFinder( indexer, env );
    14831545                firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
     
    14921554        }
    14931555
    1494         void AlternativeFinder::visit( ConditionalExpr *conditionalExpr ) {
     1556        void AlternativeFinder::Finder::postvisit( ConditionalExpr *conditionalExpr ) {
    14951557                // find alternatives for condition
    14961558                AlternativeFinder firstFinder( indexer, env );
     
    15241586        }
    15251587
    1526         void AlternativeFinder::visit( CommaExpr *commaExpr ) {
     1588        void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) {
    15271589                TypeEnvironment newEnv( env );
    15281590                Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv );
     
    15351597        }
    15361598
    1537         void AlternativeFinder::visit( RangeExpr * rangeExpr ) {
     1599        void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) {
    15381600                // resolve low and high, accept alternatives whose low and high types unify
    15391601                AlternativeFinder firstFinder( indexer, env );
     
    15571619        }
    15581620
    1559         void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) {
     1621        void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) {
    15601622                std::vector< AlternativeFinder > subExprAlternatives;
    1561                 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
     1623                altFinder.findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
    15621624                        back_inserter( subExprAlternatives ) );
    15631625                std::vector< AltList > possibilities;
     
    15751637        }
    15761638
    1577         void AlternativeFinder::visit( TupleExpr *tupleExpr ) {
     1639        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    15781640                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15791641        }
    15801642
    1581         void AlternativeFinder::visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     1643        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    15821644                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    15831645        }
    15841646
    1585         void AlternativeFinder::visit( ConstructorExpr * ctorExpr ) {
     1647        void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) {
    15861648                AlternativeFinder finder( indexer, env );
    15871649                // don't prune here, since it's guaranteed all alternatives will have the same type
     
    15931655        }
    15941656
    1595         void AlternativeFinder::visit( TupleIndexExpr *tupleExpr ) {
     1657        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    15961658                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15971659        }
    15981660
    1599         void AlternativeFinder::visit( TupleAssignExpr *tupleAssignExpr ) {
     1661        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    16001662                alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    16011663        }
    16021664
    1603         void AlternativeFinder::visit( UniqueExpr *unqExpr ) {
     1665        void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) {
    16041666                AlternativeFinder finder( indexer, env );
    16051667                finder.findWithAdjustment( unqExpr->get_expr() );
     
    16111673        }
    16121674
    1613         void AlternativeFinder::visit( StmtExpr *stmtExpr ) {
     1675        void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) {
    16141676                StmtExpr * newStmtExpr = stmtExpr->clone();
    16151677                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
     
    16181680        }
    16191681
    1620         void AlternativeFinder::visit( UntypedInitExpr *initExpr ) {
     1682        void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) {
    16211683                // handle each option like a cast
    16221684                AltList candidates;
    1623                 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; )
     1685                PRINT(
     1686                        std::cerr << "untyped init expr: " << initExpr << std::endl;
     1687                )
    16241688                // O(N^2) checks of d-types with e-types
    16251689                for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
     
    16371701                                AssertionSet needAssertions, haveAssertions;
    16381702                                OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    1639                                 PRINT( std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl; )
     1703                                PRINT(
     1704                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
     1705                                 )
    16401706                                // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    16411707                                // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
  • src/ResolvExpr/AlternativeFinder.h

    rb158d8f rb6838214  
    3838        using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;
    3939
    40         class AlternativeFinder : public Visitor {
     40        class AlternativeFinder {
    4141          public:
    4242                AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env );
     
    9494                void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
    9595          private:
    96                 virtual void visit( ApplicationExpr *applicationExpr );
    97                 virtual void visit( UntypedExpr *untypedExpr );
    98                 virtual void visit( AddressExpr *addressExpr );
    99                 virtual void visit( LabelAddressExpr *labelExpr );
    100                 virtual void visit( CastExpr *castExpr );
    101                 virtual void visit( VirtualCastExpr *castExpr );
    102                 virtual void visit( UntypedMemberExpr *memberExpr );
    103                 virtual void visit( MemberExpr *memberExpr );
    104                 virtual void visit( NameExpr *variableExpr );
    105                 virtual void visit( VariableExpr *variableExpr );
    106                 virtual void visit( ConstantExpr *constantExpr );
    107                 virtual void visit( SizeofExpr *sizeofExpr );
    108                 virtual void visit( AlignofExpr *alignofExpr );
    109                 virtual void visit( UntypedOffsetofExpr *offsetofExpr );
    110                 virtual void visit( OffsetofExpr *offsetofExpr );
    111                 virtual void visit( OffsetPackExpr *offsetPackExpr );
    112                 virtual void visit( AttrExpr *attrExpr );
    113                 virtual void visit( LogicalExpr *logicalExpr );
    114                 virtual void visit( ConditionalExpr *conditionalExpr );
    115                 virtual void visit( CommaExpr *commaExpr );
    116                 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
    117                 virtual void visit( ConstructorExpr * ctorExpr );
    118                 virtual void visit( RangeExpr * rangeExpr );
    119                 virtual void visit( UntypedTupleExpr *tupleExpr );
    120                 virtual void visit( TupleExpr *tupleExpr );
    121                 virtual void visit( TupleIndexExpr *tupleExpr );
    122                 virtual void visit( TupleAssignExpr *tupleExpr );
    123                 virtual void visit( UniqueExpr *unqExpr );
    124                 virtual void visit( StmtExpr *stmtExpr );
    125                 virtual void visit( UntypedInitExpr *initExpr );
    126 
    127                 /// Adds alternatives for anonymous members
    128                 void addAnonConversions( const Alternative & alt );
    129                 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    130                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
    131                 /// Adds alternatives for member expressions where the left side has tuple type
    132                 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
    133                 /// Adds alternatives for offsetof expressions, given the base type and name of the member
    134                 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
    135                 /// Takes a final result and checks if its assertions can be satisfied
    136                 template<typename OutputIterator>
    137                 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out );
    138                 /// Finds matching alternatives for a function, given a set of arguments
    139                 template<typename OutputIterator>
    140                 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    141                 /// Checks if assertion parameters match for a new alternative
    142                 template< typename OutputIterator >
    143                 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
    144 
     96                struct Finder;
    14597                const SymTab::Indexer &indexer;
    14698                AltList alternatives;
  • src/ResolvExpr/CastCost.cc

    rb158d8f rb6838214  
    3131
    3232namespace ResolvExpr {
    33         class CastCost : public ConversionCost {
     33        struct CastCost : public ConversionCost {
    3434          public:
    35                 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     35                CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    3636
    37                 virtual void visit( BasicType *basicType );
    38                 virtual void visit( PointerType *pointerType );
     37                using ConversionCost::previsit;
     38                using ConversionCost::postvisit;
     39                void postvisit( BasicType * basicType );
     40                void postvisit( PointerType * pointerType );
    3941        };
    4042
     
    5254                                // all typedefs should be gone by this point
    5355                                TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );
    54                                 if ( type->get_base() ) {
    55                                         return castCost( src, type->get_base(), indexer, env ) + Cost::safe;
     56                                if ( type->base ) {
     57                                        return castCost( src, type->base, indexer, env ) + Cost::safe;
    5658                                } // if
    5759                        } // if
     
    7476                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    7577                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    76                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {
     78                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    7779                                return ptrsCastable( t1, t2, env, indexer );
    7880                        });
    7981                } else {
    80                         CastCost converter( dest, indexer, env );
     82                        PassVisitor<CastCost> converter( dest, indexer, env, castCost );
    8183                        src->accept( converter );
    82                         if ( converter.get_cost() == Cost::infinity ) {
     84                        if ( converter.pass.get_cost() == Cost::infinity ) {
    8385                                return Cost::infinity;
    8486                        } else {
    8587                                // xxx - why are we adding cost 0 here?
    86                                 return converter.get_cost() + Cost::zero;
     88                                return converter.pass.get_cost() + Cost::zero;
    8789                        } // if
    8890                } // if
    8991        }
    9092
    91         CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
    92                 : ConversionCost( dest, indexer, env ) {
     93        CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     94                : ConversionCost( dest, indexer, env, costFunc ) {
    9395        }
    9496
    95         void CastCost::visit( BasicType *basicType ) {
     97        void CastCost::postvisit( BasicType *basicType ) {
    9698                PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
    9799                if ( destAsPointer && basicType->isInteger() ) {
     
    103105        }
    104106
    105         void CastCost::visit( PointerType *pointerType ) {
     107        void CastCost::postvisit( PointerType *pointerType ) {
    106108                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    107                         if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     109                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    108110                                cost = Cost::safe;
    109111                        } else {
    110112                                TypeEnvironment newEnv( env );
    111                                 newEnv.add( pointerType->get_forall() );
    112                                 newEnv.add( pointerType->get_base()->get_forall() );
    113                                 int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer );
     113                                newEnv.add( pointerType->forall );
     114                                newEnv.add( pointerType->base->forall );
     115                                int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer );
    114116                                if ( castResult > 0 ) {
    115117                                        cost = Cost::safe;
  • src/ResolvExpr/CommonType.cc

    rb158d8f rb6838214  
    1818#include <utility>                       // for pair
    1919
     20#include "Common/PassVisitor.h"
    2021#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
    2122#include "SymTab/Indexer.h"              // for Indexer
     
    2930
    3031namespace ResolvExpr {
    31         class CommonType : public Visitor {
    32           public:
     32        struct CommonType : public WithShortCircuiting {
    3333                CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    3434                Type *get_result() const { return result; }
     35
     36                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     37
     38                void postvisit( VoidType * voidType );
     39                void postvisit( BasicType * basicType );
     40                void postvisit( PointerType * pointerType );
     41                void postvisit( ArrayType * arrayType );
     42                void postvisit( ReferenceType * refType );
     43                void postvisit( FunctionType * functionType );
     44                void postvisit( StructInstType * aggregateUseType );
     45                void postvisit( UnionInstType * aggregateUseType );
     46                void postvisit( EnumInstType * aggregateUseType );
     47                void postvisit( TraitInstType * aggregateUseType );
     48                void postvisit( TypeInstType * aggregateUseType );
     49                void postvisit( TupleType * tupleType );
     50                void postvisit( VarArgsType * varArgsType );
     51                void postvisit( ZeroType * zeroType );
     52                void postvisit( OneType * oneType );
     53
    3554          private:
    36                 virtual void visit( VoidType *voidType );
    37                 virtual void visit( BasicType *basicType );
    38                 virtual void visit( PointerType *pointerType );
    39                 virtual void visit( ArrayType *arrayType );
    40                 virtual void visit( ReferenceType *refType );
    41                 virtual void visit( FunctionType *functionType );
    42                 virtual void visit( StructInstType *aggregateUseType );
    43                 virtual void visit( UnionInstType *aggregateUseType );
    44                 virtual void visit( EnumInstType *aggregateUseType );
    45                 virtual void visit( TraitInstType *aggregateUseType );
    46                 virtual void visit( TypeInstType *aggregateUseType );
    47                 virtual void visit( TupleType *tupleType );
    48                 virtual void visit( VarArgsType *varArgsType );
    49                 virtual void visit( ZeroType *zeroType );
    50                 virtual void visit( OneType *oneType );
    51 
    5255                template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
    5356                template< typename RefType > void handleRefType( RefType *inst, Type *other );
     
    8083
    8184        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    82                 CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     85                PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    8386
    8487                int depth1 = type1->referenceDepth();
     
    9194                        // special case where one type has a reference depth of 1 larger than the other
    9295                        if ( diff > 0 || diff < 0 ) {
     96                                // std::cerr << "reference depth diff: " << diff << std::endl;
    9397                                Type * result = nullptr;
    94                                 if ( ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ) ) {
     98                                ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 );
     99                                ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 );
     100                                if ( diff > 0 ) {
     101                                        // deeper on the left
     102                                        assert( ref1 );
     103                                        result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
     104                                } else {
     105                                        // deeper on the right
     106                                        assert( ref2 );
     107                                        result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
     108                                }
     109                                if ( result && ref1 ) {
    95110                                        // formal is reference, so result should be reference
    96                                         result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
    97                                         if ( result ) result = new ReferenceType( ref1->get_qualifiers(), result );
    98                                 } else {
    99                                         // formal is value, so result should be value
    100                                         ReferenceType * ref2 = strict_dynamic_cast< ReferenceType * > ( type2 );
    101                                         result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
     111                                        // std::cerr << "formal is reference; result should be reference" << std::endl;
     112                                        result = new ReferenceType( ref1->get_qualifiers(), result );
    102113                                }
    103114                                // std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
     
    108119
    109120                type1->accept( visitor );
    110                 Type *result = visitor.get_result();
     121                Type *result = visitor.pass.get_result();
    111122                if ( ! result ) {
    112123                        // this appears to be handling for opaque type declarations
     
    180191        }
    181192
    182         void CommonType::visit( __attribute((unused)) VoidType *voidType ) {}
    183 
    184         void CommonType::visit( BasicType *basicType ) {
     193        void CommonType::postvisit( VoidType * ) {}
     194
     195        void CommonType::postvisit( BasicType *basicType ) {
    185196                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    186197                        BasicType::Kind newType = combinedType[ basicType->get_kind() ][ otherBasic->get_kind() ];
     
    211222        }
    212223
    213         void CommonType::visit( PointerType *pointerType ) {
     224        void CommonType::postvisit( PointerType *pointerType ) {
    214225                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    215226                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
     
    246257        }
    247258
    248         void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {}
    249 
    250         void CommonType::visit( ReferenceType *refType ) {
     259        void CommonType::postvisit( ArrayType * ) {}
     260
     261        void CommonType::postvisit( ReferenceType *refType ) {
    251262                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    252263                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     
    283294        }
    284295
    285         void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {}
    286         void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {}
    287         void CommonType::visit( __attribute((unused)) UnionInstType *aggregateUseType ) {}
    288 
    289         void CommonType::visit( EnumInstType *enumInstType ) {
     296        void CommonType::postvisit( FunctionType * ) {}
     297        void CommonType::postvisit( StructInstType * ) {}
     298        void CommonType::postvisit( UnionInstType * ) {}
     299
     300        void CommonType::postvisit( EnumInstType *enumInstType ) {
    290301                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    291302                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    292                         ValueGuard< Type * > temp( type2 );
    293                         type2 = enumInstType;
    294                         temp.old->accept( *this );
    295                 } // if
    296         }
    297 
    298         void CommonType::visit( __attribute((unused)) TraitInstType *aggregateUseType ) {
    299         }
    300 
    301         void CommonType::visit( TypeInstType *inst ) {
     303                        result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
     304                } // if
     305        }
     306
     307        void CommonType::postvisit( TraitInstType * ) {
     308        }
     309
     310        void CommonType::postvisit( TypeInstType *inst ) {
    302311                if ( widenFirst ) {
    303312                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
     
    321330        }
    322331
    323         void CommonType::visit( __attribute((unused)) TupleType *tupleType ) {}
    324         void CommonType::visit( __attribute((unused)) VarArgsType *varArgsType ) {}
    325 
    326         void CommonType::visit( ZeroType *zeroType ) {
     332        void CommonType::postvisit( TupleType * ) {}
     333        void CommonType::postvisit( VarArgsType * ) {}
     334
     335        void CommonType::postvisit( ZeroType *zeroType ) {
    327336                if ( widenFirst ) {
    328337                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    338347        }
    339348
    340         void CommonType::visit( OneType *oneType ) {
     349        void CommonType::postvisit( OneType *oneType ) {
    341350                if ( widenFirst ) {
    342351                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
  • src/ResolvExpr/ConversionCost.cc

    rb158d8f rb6838214  
    4444                        EqvClass eqvClass;
    4545                        NamedTypeDecl *namedType;
    46                         PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); )
    47                         if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
     46                        PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
     47                        if ( env.lookup( destAsTypeInst->name, eqvClass ) ) {
    4848                                if ( eqvClass.type ) {
    4949                                        return conversionCost( src, eqvClass.type, indexer, env );
     
    5151                                        return Cost::infinity;
    5252                                }
    53                         } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
     53                        } else if ( ( namedType = indexer.lookupType( destAsTypeInst->name ) ) ) {
    5454                                PRINT( std::cerr << " found" << std::endl; )
    5555                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    5656                                // all typedefs should be gone by this point
    5757                                assert( type );
    58                                 if ( type->get_base() ) {
    59                                         return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
     58                                if ( type->base ) {
     59                                        return conversionCost( src, type->base, indexer, env ) + Cost::safe;
    6060                                } // if
    6161                        } // if
     
    7777                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    7878                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    79                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){
     79                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
    8080                                return ptrsAssignable( t1, t2, env );
    8181                        });
    8282                } else {
    83                         ConversionCost converter( dest, indexer, env );
     83                        PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
    8484                        src->accept( converter );
    85                         if ( converter.get_cost() == Cost::infinity ) {
     85                        if ( converter.pass.get_cost() == Cost::infinity ) {
    8686                                return Cost::infinity;
    8787                        } else {
    88                                 return converter.get_cost() + Cost::zero;
     88                                return converter.pass.get_cost() + Cost::zero;
    8989                        } // if
    9090                } // if
     
    9292
    9393        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    94                 PRINT( std::cerr << "convert to reference cost... diff " << diff << std::endl; )
     94                PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
    9595                if ( diff > 0 ) {
    9696                        // TODO: document this
    97                         Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env, func );
     97                        Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
    9898                        cost.incReference();
    9999                        return cost;
    100100                } else if ( diff < -1 ) {
    101101                        // TODO: document this
    102                         Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env, func );
     102                        Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func );
    103103                        cost.incReference();
    104104                        return cost;
     
    108108                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
    109109                                PRINT( std::cerr << "converting between references" << std::endl; )
    110                                 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
    111                                         return Cost::safe;
     110                                Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers();
     111                                Type::Qualifiers tq2 = destAsRef->base->get_qualifiers();
     112                                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
     113                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     114                                        if ( tq1 == tq2 ) {
     115                                                // types are the same
     116                                                return Cost::zero;
     117                                        } else {
     118                                                // types are the same, except otherPointer has more qualifiers
     119                                                return Cost::safe;
     120                                        }
    112121                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    113                                         int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer );
     122                                        int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
    114123                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
    115124                                        if ( assignResult > 0 ) {
     
    121130                        } else {
    122131                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    123                                 ConversionCost converter( dest, indexer, env );
     132                                PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
    124133                                src->accept( converter );
    125                                 return converter.get_cost();
     134                                return converter.pass.get_cost();
    126135                        } // if
    127136                } else {
     
    129138                        assert( diff == -1 && destAsRef );
    130139                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    131                         if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
     140                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
    132141                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
    133142                                if ( src->get_lvalue() ) {
     
    137146                                        )
    138147                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
    139                                         if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
     148                                        if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
    140149                                                return Cost::reference; // cost needs to be non-zero to add cast
    141                                         } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
     150                                        } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
    142151                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    143152                                        } else {
    144153                                                return Cost::unsafe;
    145154                                        } // if
    146                                 } else if ( destAsRef->get_base()->get_const() ) {
     155                                } else if ( destAsRef->base->get_const() ) {
    147156                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
    148157                                        // rvalue-to-const-reference conversion: T => const T &
     
    164173        }
    165174
    166         ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
    167                 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {
     175        ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     176                : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
    168177        }
    169178
     
    248257        };
    249258
    250         void ConversionCost::visit( __attribute((unused)) VoidType *voidType ) {
     259        void ConversionCost::postvisit( VoidType * ) {
    251260                cost = Cost::infinity;
    252261        }
    253262
    254         void ConversionCost::visit(BasicType *basicType) {
     263        void ConversionCost::postvisit(BasicType *basicType) {
    255264                if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
    256265                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
     
    269278        }
    270279
    271         void ConversionCost::visit( PointerType * pointerType ) {
     280        void ConversionCost::postvisit( PointerType * pointerType ) {
    272281                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    273                         PRINT( std::cerr << pointerType << " ===> " << destAsPtr; )
    274                         Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
    275                         Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
    276                         if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     282                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
     283                        Type::Qualifiers tq1 = pointerType->base->get_qualifiers();
     284                        Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers();
     285                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
     286                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    277287                                if ( tq1 == tq2 ) {
    278288                                        // types are the same
     
    280290                                } else {
    281291                                        // types are the same, except otherPointer has more qualifiers
    282                                         PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    283292                                        cost = Cost::safe;
    284293                                }
    285                         } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     294                        } else {
    286295                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
    287296                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
    288                                 if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
    289                                         cost = Cost::safe;
     297                                if ( assignResult > 0 && tq1 <= tq2 ) {
     298                                        // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
     299                                        if ( tq1 == tq2 ) {
     300                                                cost = Cost::safe;
     301                                        } else if ( tq1 < tq2 ) {
     302                                                cost = Cost::safe+Cost::safe;
     303                                        }
    290304                                } else if ( assignResult < 0 ) {
    291305                                        cost = Cost::unsafe;
     
    298312        }
    299313
    300         void ConversionCost::visit( ArrayType * ) {}
    301 
    302         void ConversionCost::visit( ReferenceType * refType ) {
     314        void ConversionCost::postvisit( ArrayType * ) {}
     315
     316        void ConversionCost::postvisit( ReferenceType * refType ) {
    303317                // Note: dest can never be a reference, since it would have been caught in an earlier check
    304318                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     
    306320                // recursively compute conversion cost from T1 to T2.
    307321                // cv can be safely dropped because of 'implicit dereference' behavior.
    308                 refType->base->accept( *this );
     322                cost = costFunc( refType->base, dest, indexer, env );
    309323                if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
    310324                        cost.incReference();  // prefer exact qualifiers
     
    317331        }
    318332
    319         void ConversionCost::visit( FunctionType * ) {}
    320 
    321         void ConversionCost::visit( StructInstType * inst ) {
     333        void ConversionCost::postvisit( FunctionType * ) {}
     334
     335        void ConversionCost::postvisit( StructInstType * inst ) {
    322336                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
    323337                        if ( inst->name == destAsInst->name ) {
     
    327341        }
    328342
    329         void ConversionCost::visit( UnionInstType * inst ) {
     343        void ConversionCost::postvisit( UnionInstType * inst ) {
    330344                if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
    331345                        if ( inst->name == destAsInst->name ) {
     
    335349        }
    336350
    337         void ConversionCost::visit( EnumInstType * ) {
     351        void ConversionCost::postvisit( EnumInstType * ) {
    338352                static Type::Qualifiers q;
    339353                static BasicType integer( q, BasicType::SignedInt );
    340                 integer.accept( *this );  // safe if dest >= int
     354                cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
    341355                if ( cost < Cost::unsafe ) {
    342356                        cost.incSafe();
     
    344358        }
    345359
    346         void ConversionCost::visit( TraitInstType * ) {}
    347 
    348         void ConversionCost::visit( TypeInstType *inst ) {
     360        void ConversionCost::postvisit( TraitInstType * ) {}
     361
     362        void ConversionCost::postvisit( TypeInstType *inst ) {
    349363                EqvClass eqvClass;
    350364                NamedTypeDecl *namedType;
    351                 if ( env.lookup( inst->get_name(), eqvClass ) ) {
    352                         cost = conversionCost( eqvClass.type, dest, indexer, env );
     365                if ( env.lookup( inst->name, eqvClass ) ) {
     366                        cost = costFunc( eqvClass.type, dest, indexer, env );
    353367                } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
    354                         if ( inst->get_name() == destAsInst->get_name() ) {
     368                        if ( inst->name == destAsInst->name ) {
    355369                                cost = Cost::zero;
    356370                        }
    357                 } else if ( ( namedType = indexer.lookupType( inst->get_name() ) ) ) {
     371                } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) {
    358372                        TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    359373                        // all typedefs should be gone by this point
    360374                        assert( type );
    361                         if ( type->get_base() ) {
    362                                 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
    363                         } // if
    364                 } // if
    365         }
    366 
    367         void ConversionCost::visit( TupleType * tupleType ) {
     375                        if ( type->base ) {
     376                                cost = costFunc( type->base, dest, indexer, env ) + Cost::safe;
     377                        } // if
     378                } // if
     379        }
     380
     381        void ConversionCost::postvisit( TupleType * tupleType ) {
    368382                Cost c = Cost::zero;
    369383                if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
    370                         std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin();
    371                         std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin();
    372                         while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
    373                                 Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env );
     384                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
     385                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
     386                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
     387                                Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env );
    374388                                if ( newCost == Cost::infinity ) {
    375389                                        return;
     
    377391                                c += newCost;
    378392                        } // while
    379                         if ( destIt != destAsTuple->get_types().end() ) {
     393                        if ( destIt != destAsTuple->types.end() ) {
    380394                                cost = Cost::infinity;
    381395                        } else {
     
    385399        }
    386400
    387         void ConversionCost::visit( VarArgsType * ) {
     401        void ConversionCost::postvisit( VarArgsType * ) {
    388402                if ( dynamic_cast< VarArgsType* >( dest ) ) {
    389403                        cost = Cost::zero;
     
    391405        }
    392406
    393         void ConversionCost::visit( ZeroType * ) {
     407        void ConversionCost::postvisit( ZeroType * ) {
    394408                if ( dynamic_cast< ZeroType * >( dest ) ) {
    395409                        cost = Cost::zero;
     
    408422        }
    409423
    410         void ConversionCost::visit( OneType * ) {
     424        void ConversionCost::postvisit( OneType * ) {
    411425                if ( dynamic_cast< OneType * >( dest ) ) {
    412426                        cost = Cost::zero;
  • src/ResolvExpr/ConversionCost.h

    rb158d8f rb6838214  
    1919
    2020#include "Cost.h"             // for Cost
     21
     22#include "Common/PassVisitor.h"
    2123#include "SynTree/Visitor.h"  // for Visitor
    2224#include "SynTree/SynTree.h"  // for Visitor Nodes
     
    2931        class TypeEnvironment;
    3032
    31         class ConversionCost : public Visitor {
     33        typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
     34        struct ConversionCost : public WithShortCircuiting {
    3235          public:
    33                 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     36                ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
    3437
    3538                Cost get_cost() const { return cost; }
    3639
    37                 virtual void visit(VoidType *voidType);
    38                 virtual void visit(BasicType *basicType);
    39                 virtual void visit(PointerType *pointerType);
    40                 virtual void visit(ArrayType *arrayType);
    41                 virtual void visit(ReferenceType *refType);
    42                 virtual void visit(FunctionType *functionType);
    43                 virtual void visit(StructInstType *aggregateUseType);
    44                 virtual void visit(UnionInstType *aggregateUseType);
    45                 virtual void visit(EnumInstType *aggregateUseType);
    46                 virtual void visit(TraitInstType *aggregateUseType);
    47                 virtual void visit(TypeInstType *aggregateUseType);
    48                 virtual void visit(TupleType *tupleType);
    49                 virtual void visit(VarArgsType *varArgsType);
    50                 virtual void visit(ZeroType *zeroType);
    51                 virtual void visit(OneType *oneType);
     40                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     41
     42                void postvisit( VoidType * voidType );
     43                void postvisit( BasicType * basicType );
     44                void postvisit( PointerType * pointerType );
     45                void postvisit( ArrayType * arrayType );
     46                void postvisit( ReferenceType * refType );
     47                void postvisit( FunctionType * functionType );
     48                void postvisit( StructInstType * aggregateUseType );
     49                void postvisit( UnionInstType * aggregateUseType );
     50                void postvisit( EnumInstType * aggregateUseType );
     51                void postvisit( TraitInstType * aggregateUseType );
     52                void postvisit( TypeInstType * aggregateUseType );
     53                void postvisit( TupleType * tupleType );
     54                void postvisit( VarArgsType * varArgsType );
     55                void postvisit( ZeroType * zeroType );
     56                void postvisit( OneType * oneType );
    5257          protected:
    5358                Type *dest;
     
    5560                Cost cost;
    5661                const TypeEnvironment &env;
     62                CostFunction costFunc;
    5763        };
    5864
    59         typedef std::function<int(Type *, Type *, const TypeEnvironment &, const SymTab::Indexer &)> PtrsFunction;
     65        typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
    6066        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
    6167} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    rb158d8f rb6838214  
    3838
    3939namespace ResolvExpr {
    40         long long int getConstValue( ConstantExpr * constExpr ) {
    41                 if ( BasicType * basicType = dynamic_cast< BasicType * >( constExpr->get_result() ) ) {
    42                         if ( basicType->isInteger() ) {
    43                                 return constExpr->get_constant()->get_ival();
    44                         } else {
    45                                 assertf( false, "Non-integer constant expression in getConstValue %s", toString( constExpr ).c_str() ); // xxx - might be semantic error
    46                         }
    47                 } else if ( dynamic_cast< OneType * >( constExpr->get_result() ) ) {
    48                         return 1;
    49                 } else if ( dynamic_cast< ZeroType * >( constExpr->get_result() ) ) {
    50                         return 0;
    51                 } else {
    52                         assertf( false, "unhandled type on getConstValue %s", toString( constExpr->get_result() ).c_str() ); // xxx - might be semantic error
    53                 }
    54         }
    55 
    5640        template< typename AggrInst >
    5741        TypeSubstitution makeGenericSubstitution( AggrInst * inst ) {
     
    7862                virtual ~MemberIterator() {}
    7963
     64                /// walks the current object using the given designators as a guide
    8065                virtual void setPosition( std::list< Expression * > & designators ) = 0;
     66
     67                /// retrieve the list of possible Type/Designaton pairs for the current position in the currect object
    8168                virtual std::list<InitAlternative> operator*() const = 0;
     69
     70                /// true if the iterator is not currently at the end
    8271                virtual operator bool() const = 0;
     72
     73                /// moves the iterator by one member in the current object
    8374                virtual MemberIterator & bigStep() = 0;
     75
     76                /// moves the iterator by one member in the current subobject
    8477                virtual MemberIterator & smallStep() = 0;
     78
     79                /// the type of the current object
    8580                virtual Type * getType() = 0;
     81
     82                /// the type of the current subobject
    8683                virtual Type * getNext() = 0;
    8784
     85                /// printing for debug
    8886                virtual void print( std::ostream & out, Indenter indent ) const = 0;
    8987
     88                /// helper for operator*; aggregates must add designator to each init alternative, but
     89                /// adding designators in operator* creates duplicates.
    9090                virtual std::list<InitAlternative> first() const = 0; // should be protected
    9191        };
     
    141141                        base = at->get_base();
    142142                        memberIter = createMemberIterator( base );
     143                        if ( at->isVarLen ) throw SemanticError( "VLA initialization does not support @=", at );
    143144                        setSize( at->get_dimension() );
    144145                }
     
    151152                void setSize( Expression * expr ) {
    152153                        if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
    153                                 size = getConstValue( constExpr );
    154                                 PRINT( std::cerr << "array type with size: " << size << std::endl; )
     154                                try {
     155                                        size = constExpr->intValue();
     156                                        PRINT( std::cerr << "array type with size: " << size << std::endl; )
     157                                } catch ( SemanticError & ) {
     158                                        throw SemanticError( "Constant expression of non-integral type in array dimension: ", expr );
     159                                }
    155160                        }       else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    156161                                setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast
     162                        } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
     163                                if ( EnumInstType * inst = dynamic_cast< EnumInstType * > ( varExpr->result ) ) {
     164                                        long long int value;
     165                                        if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
     166                                                size = value;
     167                                        }
     168                                }
    157169                        } else {
    158170                                assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this
     
    164176                        // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions
    165177                        if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
    166                                 index = getConstValue( constExpr );
     178                                try {
     179                                        index = constExpr->intValue();
     180                                } catch( SemanticError & ) {
     181                                        throw SemanticError( "Constant expression of non-integral type in array designator: ", expr );
     182                                }
    167183                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    168184                                setPosition( castExpr->get_arg() );
    169185                        } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    170                                 assertf( dynamic_cast<EnumInstType *> ( varExpr->get_result() ), "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
    171                                 index = 0; // xxx - get actual value of enum constant
     186                                EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() );
     187                                assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
     188                                long long int value;
     189                                if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
     190                                        index = value;
     191                                }
    172192                        } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) {
    173193                                index = 0; // xxx - get actual sizeof/alignof value?
     
    350370                                }
    351371                        }
    352                         // if ( curMember == std::next( decl->get_members().begin(), 1 ) ) { // xxx - this never triggers because curMember is incremented immediately on construction
    353                         if ( atbegin ) { // xxx - this never triggers because curMember is incremented immediately on construction
     372                        if ( atbegin ) {
    354373                                // xxx - what about case of empty struct??
    355374                                // only add self if at the very beginning of the structure
     
    385404                        return *this;
    386405                }
    387                 virtual std::list<InitAlternative> first() const { return std::list<InitAlternative>{}; }
    388406        };
    389407
     
    439457                                return new UnionIterator( uit );
    440458                        } else {
    441                                 assertf( dynamic_cast< TypeInstType * >( type ), "some other reftotype" );
     459                                assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() );
    442460                                return new SimpleIterator( type );
    443461                        }
  • src/ResolvExpr/FindOpenVars.cc

    rb158d8f rb6838214  
    1919#include <map>                    // for map<>::mapped_type
    2020
     21#include "Common/PassVisitor.h"
    2122#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
    2223#include "SynTree/Type.h"         // for Type, Type::ForallList, ArrayType
    23 #include "SynTree/Visitor.h"      // for Visitor
    2424
    2525namespace ResolvExpr {
    26         class FindOpenVars : public Visitor {
    27           public:
     26        struct FindOpenVars : public WithGuards {
    2827                FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    2928
    30           private:
    31                 virtual void visit(PointerType *pointerType);
    32                 virtual void visit(ArrayType *arrayType);
    33                 virtual void visit(FunctionType *functionType);
    34                 virtual void visit(TupleType *tupleType);
     29                void previsit( PointerType * pointerType );
     30                void previsit( ArrayType * arrayType );
     31                void previsit( FunctionType * functionType );
     32                void previsit( TupleType * tupleType );
    3533
    3634                void common_action( Type *type );
     
    4240
    4341        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    44                 FindOpenVars finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
     42                PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
    4543                type->accept( finder );
    4644        }
     
    7068                        } // for
    7169                } // if
    72 ///   std::cout << "type is ";
    73 ///   type->print( std::cout );
    74 ///   std::cout << std::endl << "need is" << std::endl;
    75 ///   printAssertionSet( needAssertions, std::cout );
    76 ///   std::cout << std::endl << "have is" << std::endl;
    77 ///   printAssertionSet( haveAssertions, std::cout );
     70///   std::cerr << "type is ";
     71///   type->print( std::cerr );
     72///   std::cerr << std::endl << "need is" << std::endl;
     73///   printAssertionSet( needAssertions, std::cerr );
     74///   std::cerr << std::endl << "have is" << std::endl;
     75///   printAssertionSet( haveAssertions, std::cerr );
    7876        }
    7977
    80         void FindOpenVars::visit(PointerType *pointerType) {
     78        void FindOpenVars::previsit(PointerType *pointerType) {
    8179                common_action( pointerType );
    82                 Visitor::visit( pointerType );
    8380        }
    8481
    85         void FindOpenVars::visit(ArrayType *arrayType) {
     82        void FindOpenVars::previsit(ArrayType *arrayType) {
    8683                common_action( arrayType );
    87                 Visitor::visit( arrayType );
    8884        }
    8985
    90         void FindOpenVars::visit(FunctionType *functionType) {
     86        void FindOpenVars::previsit(FunctionType *functionType) {
    9187                common_action( functionType );
    9288                nextIsOpen = ! nextIsOpen;
    93                 Visitor::visit( functionType );
    94                 nextIsOpen = ! nextIsOpen;
     89                GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
    9590        }
    9691
    97         void FindOpenVars::visit(TupleType *tupleType) {
     92        void FindOpenVars::previsit(TupleType *tupleType) {
    9893                common_action( tupleType );
    99                 Visitor::visit( tupleType );
    10094        }
    10195} // namespace ResolvExpr
  • src/ResolvExpr/Occurs.cc

    rb158d8f rb6838214  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Occurs.cc -- 
     7// Occurs.cc --
    88//
    99// Author           : Richard C. Bilson
     
    1717#include <string>             // for string
    1818
     19#include "Common/PassVisitor.h"
    1920#include "SynTree/Type.h"     // for TypeInstType, Type
    20 #include "SynTree/Visitor.h"  // for Visitor
    2121#include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2222
    2323namespace ResolvExpr {
    24         class Occurs : public Visitor {
    25           public:
     24        struct Occurs : public WithVisitorRef<Occurs> {
    2625                Occurs( std::string varName, const TypeEnvironment &env );
    27                 bool get_result() const { return result; }
    28                 virtual void visit( TypeInstType *typeInst );
    29           private:
     26                void previsit( TypeInstType * typeInst );
     27
    3028                bool result;
    3129                std::set< std::string > eqvVars;
    32                 const TypeEnvironment &env;
     30                const TypeEnvironment &tenv;
    3331        };
    3432
    3533        bool occurs( Type *type, std::string varName, const TypeEnvironment &env ) {
    36                 Occurs occur( varName, env );
     34                PassVisitor<Occurs> occur( varName, env );
    3735                type->accept( occur );
    38                 return occur.get_result();
     36                return occur.pass.result;
    3937        }
    4038
    41         Occurs::Occurs( std::string varName, const TypeEnvironment &env ) : result( false ), env( env ) {
     39        Occurs::Occurs( std::string varName, const TypeEnvironment & env ) : result( false ), tenv( env ) {
    4240                EqvClass eqvClass;
    43                 if ( env.lookup( varName, eqvClass ) ) {
     41                if ( tenv.lookup( varName, eqvClass ) ) {
    4442                        eqvVars = eqvClass.vars;
    4543                } else {
     
    4846        }
    4947
    50         void Occurs::visit( TypeInstType *typeInst ) {
     48        void Occurs::previsit( TypeInstType * typeInst ) {
    5149                EqvClass eqvClass;
    52 ///   std::cout << "searching for vars: ";
    53 ///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cout, " " ) );
    54 ///   std::cout << std::endl;
     50///   std::cerr << "searching for vars: ";
     51///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) );
     52///   std::cerr << std::endl;
    5553                if ( eqvVars.find( typeInst->get_name() ) != eqvVars.end() ) {
    5654                        result = true;
    57                 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
     55                } else if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) {
    5856                        if ( eqvClass.type ) {
    59 ///       std::cout << typeInst->get_name() << " is bound to";
    60 ///       eqvClass.type->print( std::cout );
    61 ///       std::cout << std::endl;
    62                                 eqvClass.type->accept( *this );
     57///       std::cerr << typeInst->get_name() << " is bound to";
     58///       eqvClass.type->print( std::cerr );
     59///       std::cerr << std::endl;
     60                                eqvClass.type->accept( *visitor );
    6361                        } // if
    6462                } // if
  • src/ResolvExpr/PolyCost.cc

    rb158d8f rb6838214  
    1414//
    1515
     16#include "Common/PassVisitor.h"
    1617#include "SymTab/Indexer.h"   // for Indexer
    1718#include "SynTree/Type.h"     // for TypeInstType, Type
    18 #include "SynTree/Visitor.h"  // for Visitor
    1919#include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2020
    2121namespace ResolvExpr {
    22         class PolyCost : public Visitor {
    23           public:
     22        struct PolyCost {
    2423                PolyCost( const TypeEnvironment &env, const SymTab::Indexer &indexer );
    25                 int get_result() const { return result; }
    26           private:
    27                 virtual void visit(TypeInstType *aggregateUseType);
     24
     25                void previsit( TypeInstType * aggregateUseType );
    2826                int result;
    29                 const TypeEnvironment &env;
     27                const TypeEnvironment &tenv;
    3028                const SymTab::Indexer &indexer;
    3129        };
    3230
    3331        int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {
    34                 PolyCost coster( env, indexer );
     32                PassVisitor<PolyCost> coster( env, indexer );
    3533                type->accept( coster );
    36                 return coster.get_result();
     34                return coster.pass.result;
    3735        }
    3836
    39         PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), env( env ), indexer( indexer ) {
     37        PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), tenv( env ), indexer( indexer ) {
    4038        }
    4139
    42         void PolyCost::visit(TypeInstType * typeInst) {
     40        void PolyCost::previsit(TypeInstType * typeInst) {
    4341                EqvClass eqvClass;
    44                 if ( env.lookup( typeInst->name, eqvClass ) ) {
     42                if ( tenv.lookup( typeInst->name, eqvClass ) ) {
    4543                        if ( eqvClass.type ) {
    4644                                if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) {
  • src/ResolvExpr/PtrsAssignable.cc

    rb158d8f rb6838214  
    1414//
    1515
     16#include "Common/PassVisitor.h"
    1617#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    1718#include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
     
    2021
    2122namespace ResolvExpr {
    22         class PtrsAssignable : public Visitor {
    23           public:
     23        struct PtrsAssignable : public WithShortCircuiting {
    2424                PtrsAssignable( Type *dest, const TypeEnvironment &env );
    2525
    2626                int get_result() const { return result; }
    2727
    28                 virtual void visit( VoidType *voidType );
    29                 virtual void visit( BasicType *basicType );
    30                 virtual void visit( PointerType *pointerType );
    31                 virtual void visit( ArrayType *arrayType );
    32                 virtual void visit( FunctionType *functionType );
    33                 virtual void visit( StructInstType *inst );
    34                 virtual void visit( UnionInstType *inst );
    35                 virtual void visit( EnumInstType *inst );
    36                 virtual void visit( TraitInstType *inst );
    37                 virtual void visit( TypeInstType *inst );
    38                 virtual void visit( TupleType *tupleType );
    39                 virtual void visit( VarArgsType *varArgsType );
    40                 virtual void visit( ZeroType *zeroType );
    41                 virtual void visit( OneType *oneType );
     28                void previsit( Type * ) { visit_children = false; }
     29
     30                void postvisit( VoidType * voidType );
     31                void postvisit( BasicType * basicType );
     32                void postvisit( PointerType * pointerType );
     33                void postvisit( ArrayType * arrayType );
     34                void postvisit( FunctionType * functionType );
     35                void postvisit( StructInstType * inst );
     36                void postvisit( UnionInstType * inst );
     37                void postvisit( EnumInstType * inst );
     38                void postvisit( TraitInstType * inst );
     39                void postvisit( TypeInstType * inst );
     40                void postvisit( TupleType * tupleType );
     41                void postvisit( VarArgsType * varArgsType );
     42                void postvisit( ZeroType * zeroType );
     43                void postvisit( OneType * oneType );
    4244          private:
    4345                Type *dest;
     
    5961                        return -1;
    6062                } else {
    61                         PtrsAssignable ptrs( dest, env );
     63                        PassVisitor<PtrsAssignable> ptrs( dest, env );
    6264                        src->accept( ptrs );
    63                         return ptrs.get_result();
     65                        return ptrs.pass.get_result();
    6466                } // if
    6567        }
     
    6769        PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
    6870
    69         void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) {
     71        void PtrsAssignable::postvisit( VoidType * ) {
    7072                // T * = void * is disallowed - this is a change from C, where any
    7173                // void * can be assigned or passed to a non-void pointer without a cast.
    7274        }
    7375
    74         void PtrsAssignable::visit( __attribute__((unused)) BasicType *basicType ) {}
    75         void PtrsAssignable::visit( __attribute__((unused)) PointerType *pointerType ) {}
    76         void PtrsAssignable::visit( __attribute__((unused)) ArrayType *arrayType ) {}
    77         void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) {}
     76        void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType ) {}
     77        void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType ) {}
     78        void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType ) {}
     79        void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType ) {}
    7880
    79         void PtrsAssignable::visit(  __attribute__((unused)) StructInstType *inst ) {}
    80         void PtrsAssignable::visit(  __attribute__((unused)) UnionInstType *inst ) {}
     81        void PtrsAssignable::postvisit(  __attribute__((unused)) StructInstType *inst ) {}
     82        void PtrsAssignable::postvisit(  __attribute__((unused)) UnionInstType *inst ) {}
    8183
    82         void PtrsAssignable::visit( EnumInstType * ) {
     84        void PtrsAssignable::postvisit( EnumInstType * ) {
    8385                if ( dynamic_cast< BasicType* >( dest ) ) {
    8486                        // int * = E *, etc. is safe. This isn't technically correct, as each
     
    9193        }
    9294
    93         void PtrsAssignable::visit(  __attribute__((unused)) TraitInstType *inst ) {}
    94         void PtrsAssignable::visit( TypeInstType *inst ) {
     95        void PtrsAssignable::postvisit(  __attribute__((unused)) TraitInstType *inst ) {}
     96        void PtrsAssignable::postvisit( TypeInstType *inst ) {
    9597                EqvClass eqvClass;
    9698                if ( env.lookup( inst->get_name(), eqvClass ) && eqvClass.type ) {
     
    100102        }
    101103
    102         void PtrsAssignable::visit(  __attribute__((unused)) TupleType *tupleType ) {}
    103         void PtrsAssignable::visit(  __attribute__((unused)) VarArgsType *varArgsType ) {}
    104         void PtrsAssignable::visit(  __attribute__((unused)) ZeroType *zeroType ) {}
    105         void PtrsAssignable::visit(  __attribute__((unused)) OneType *oneType ) {}
     104        void PtrsAssignable::postvisit(  __attribute__((unused)) TupleType *tupleType ) {}
     105        void PtrsAssignable::postvisit(  __attribute__((unused)) VarArgsType *varArgsType ) {}
     106        void PtrsAssignable::postvisit(  __attribute__((unused)) ZeroType *zeroType ) {}
     107        void PtrsAssignable::postvisit(  __attribute__((unused)) OneType *oneType ) {}
    106108
    107109} // namespace ResolvExpr
  • src/ResolvExpr/PtrsCastable.cc

    rb158d8f rb6838214  
    1414//
    1515
     16#include "Common/PassVisitor.h"
    1617#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    1718#include "SymTab/Indexer.h"              // for Indexer
     
    2122#include "typeops.h"                     // for ptrsAssignable
    2223
    23 
    2424namespace ResolvExpr {
    25         class PtrsCastable : public Visitor {
     25        struct PtrsCastable : public WithShortCircuiting {
    2626          public:
    2727                PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     
    2929                int get_result() const { return result; }
    3030
    31                 virtual void visit(VoidType *voidType);
    32                 virtual void visit(BasicType *basicType);
    33                 virtual void visit(PointerType *pointerType);
    34                 virtual void visit(ArrayType *arrayType);
    35                 virtual void visit(FunctionType *functionType);
    36                 virtual void visit(StructInstType *inst);
    37                 virtual void visit(UnionInstType *inst);
    38                 virtual void visit(EnumInstType *inst);
    39                 virtual void visit(TraitInstType *inst);
    40                 virtual void visit(TypeInstType *inst);
    41                 virtual void visit(TupleType *tupleType);
    42                 virtual void visit(VarArgsType *varArgsType);
    43                 virtual void visit(ZeroType *zeroType);
    44                 virtual void visit(OneType *oneType);
     31                void previsit( Type * ) { visit_children = false; }
     32
     33                void postvisit( VoidType * voidType );
     34                void postvisit( BasicType * basicType );
     35                void postvisit( PointerType * pointerType );
     36                void postvisit( ArrayType * arrayType );
     37                void postvisit( FunctionType * functionType );
     38                void postvisit( StructInstType * inst );
     39                void postvisit( UnionInstType * inst );
     40                void postvisit( EnumInstType * inst );
     41                void postvisit( TraitInstType * inst );
     42                void postvisit( TypeInstType * inst );
     43                void postvisit( TupleType * tupleType );
     44                void postvisit( VarArgsType * varArgsType );
     45                void postvisit( ZeroType * zeroType );
     46                void postvisit( OneType * oneType );
    4547          private:
    4648                Type *dest;
     
    7981                        EqvClass eqvClass;
    8082                        if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
     83                                // xxx - should this be ptrsCastable?
    8184                                return ptrsAssignable( src, eqvClass.type, env );
    8285                        } // if
     
    8588                        return objectCast( src, env, indexer );
    8689                } else {
    87                         PtrsCastable ptrs( dest, env, indexer );
     90                        PassVisitor<PtrsCastable> ptrs( dest, env, indexer );
    8891                        src->accept( ptrs );
    89                         return ptrs.get_result();
     92                        return ptrs.pass.get_result();
    9093                } // if
    9194        }
     
    9598        }
    9699
    97         void PtrsCastable::visit( VoidType * ) {
     100        void PtrsCastable::postvisit( VoidType * ) {
    98101                result = objectCast( dest, env, indexer );
    99102        }
    100103
    101         void PtrsCastable::visit( BasicType * ) {
     104        void PtrsCastable::postvisit( BasicType * ) {
    102105                result = objectCast( dest, env, indexer );
    103106        }
    104107
    105         void PtrsCastable::visit( PointerType * ) {
     108        void PtrsCastable::postvisit( PointerType * ) {
    106109                result = objectCast( dest, env, indexer );
    107110        }
    108111
    109         void PtrsCastable::visit( ArrayType * ) {
     112        void PtrsCastable::postvisit( ArrayType * ) {
    110113                result = objectCast( dest, env, indexer );
    111114        }
    112115
    113         void PtrsCastable::visit( FunctionType * ) {
     116        void PtrsCastable::postvisit( FunctionType * ) {
    114117                // result = -1;
    115118                result = functionCast( dest, env, indexer );
    116119        }
    117120
    118         void PtrsCastable::visit( StructInstType * ) {
     121        void PtrsCastable::postvisit( StructInstType * ) {
    119122                result = objectCast( dest, env, indexer );
    120123        }
    121124
    122         void PtrsCastable::visit( UnionInstType * ) {
     125        void PtrsCastable::postvisit( UnionInstType * ) {
    123126                result = objectCast( dest, env, indexer );
    124127        }
    125128
    126         void PtrsCastable::visit( EnumInstType * ) {
     129        void PtrsCastable::postvisit( EnumInstType * ) {
    127130                if ( dynamic_cast< EnumInstType* >( dest ) ) {
    128131                        result = 1;
     
    138141        }
    139142
    140         void PtrsCastable::visit( TraitInstType * ) {}
     143        void PtrsCastable::postvisit( TraitInstType * ) {}
    141144
    142         void PtrsCastable::visit(TypeInstType *inst) {
     145        void PtrsCastable::postvisit(TypeInstType *inst) {
    143146                //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
    144147                result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
    145148        }
    146149
    147         void PtrsCastable::visit( TupleType * ) {
     150        void PtrsCastable::postvisit( TupleType * ) {
    148151                result = objectCast( dest, env, indexer );
    149152        }
    150153
    151         void PtrsCastable::visit( VarArgsType * ) {
     154        void PtrsCastable::postvisit( VarArgsType * ) {
    152155                result = objectCast( dest, env, indexer );
    153156        }
    154157
    155         void PtrsCastable::visit( ZeroType * ) {
     158        void PtrsCastable::postvisit( ZeroType * ) {
    156159                result = objectCast( dest, env, indexer );
    157160        }
    158161
    159         void PtrsCastable::visit( OneType * ) {
     162        void PtrsCastable::postvisit( OneType * ) {
    160163                result = objectCast( dest, env, indexer );
    161164        }
  • src/ResolvExpr/RenameVars.cc

    rb158d8f rb6838214  
    1919#include <utility>                 // for pair
    2020
     21#include "Common/PassVisitor.h"
    2122#include "Common/SemanticError.h"  // for SemanticError
    2223#include "RenameVars.h"
     
    2728
    2829namespace ResolvExpr {
    29         RenameVars global_renamer;
     30        namespace {
     31                struct RenameVars {
     32                        RenameVars();
     33                        void reset();
    3034
    31         RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) {
    32                 mapStack.push_front( std::map< std::string, std::string >() );
     35                        void previsit( TypeInstType * instType );
     36                        void previsit( Type * );
     37                        void postvisit( Type * );
     38
     39                  private:
     40                        int level, resetCount;
     41                        std::list< std::map< std::string, std::string > > mapStack;
     42                };
     43
     44                PassVisitor<RenameVars> global_renamer;
     45        } // namespace
     46
     47        void renameTyVars( Type * t ) {
     48                t->accept( global_renamer );
    3349        }
    3450
    35         void RenameVars::reset() {
    36                 level = 0;
    37                 resetCount++;
     51        void resetTyVarRenaming() {
     52                global_renamer.pass.reset();
    3853        }
    3954
    40         void RenameVars::visit( VoidType *voidType ) {
    41                 typeBefore( voidType );
    42                 typeAfter( voidType );
    43         }
     55        namespace {
     56                RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) {
     57                        mapStack.push_front( std::map< std::string, std::string >() );
     58                }
    4459
    45         void RenameVars::visit( BasicType *basicType ) {
    46                 typeBefore( basicType );
    47                 typeAfter( basicType );
    48         }
     60                void RenameVars::reset() {
     61                        level = 0;
     62                        resetCount++;
     63                }
    4964
    50         void RenameVars::visit( PointerType *pointerType ) {
    51                 typeBefore( pointerType );
    52                 maybeAccept( pointerType->get_base(), *this );
    53                 typeAfter( pointerType );
    54         }
     65                void RenameVars::previsit( TypeInstType * instType ) {
     66                        previsit( (Type *)instType );
     67                        std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name );
     68                        if ( i != mapStack.front().end() ) {
     69                                instType->name = i->second;
     70                        } // if
     71                }
    5572
    56         void RenameVars::visit( ArrayType *arrayType ) {
    57                 typeBefore( arrayType );
    58                 maybeAccept( arrayType->get_dimension(), *this );
    59                 maybeAccept( arrayType->get_base(), *this );
    60                 typeAfter( arrayType );
    61         }
     73                void RenameVars::previsit( Type * type ) {
     74                        if ( ! type->forall.empty() ) {
     75                                // copies current name mapping into new mapping
     76                                mapStack.push_front( mapStack.front() );
     77                                // renames all "forall" type names to `_${level}_${name}'
     78                                for ( auto td : type->forall ) {
     79                                        std::ostringstream output;
     80                                        output << "_" << resetCount << "_" << level << "_" << td->name;
     81                                        std::string newname( output.str() );
     82                                        mapStack.front()[ td->get_name() ] = newname;
     83                                        td->name = newname;
     84                                        // ditto for assertion names, the next level in
     85                                        level++;
     86                                        // acceptAll( td->assertions, *this );
     87                                } // for
     88                        } // if
     89                }
    6290
    63         void RenameVars::visit( FunctionType *functionType ) {
    64                 typeBefore( functionType );
    65                 acceptAll( functionType->get_returnVals(), *this );
    66                 acceptAll( functionType->get_parameters(), *this );
    67                 typeAfter( functionType );
    68         }
    69 
    70         void RenameVars::visit( StructInstType *aggregateUseType ) {
    71                 typeBefore( aggregateUseType );
    72                 acceptAll( aggregateUseType->get_parameters(), *this );
    73                 typeAfter( aggregateUseType );
    74         }
    75 
    76         void RenameVars::visit( UnionInstType *aggregateUseType ) {
    77                 typeBefore( aggregateUseType );
    78                 acceptAll( aggregateUseType->get_parameters(), *this );
    79                 typeAfter( aggregateUseType );
    80         }
    81 
    82         void RenameVars::visit( EnumInstType *aggregateUseType ) {
    83                 typeBefore( aggregateUseType );
    84                 acceptAll( aggregateUseType->get_parameters(), *this );
    85                 typeAfter( aggregateUseType );
    86         }
    87 
    88         void RenameVars::visit( TraitInstType *aggregateUseType ) {
    89                 typeBefore( aggregateUseType );
    90                 acceptAll( aggregateUseType->get_parameters(), *this );
    91                 typeAfter( aggregateUseType );
    92         }
    93 
    94         void RenameVars::visit( TypeInstType *instType ) {
    95                 typeBefore( instType );
    96                 std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->get_name() );
    97                 if ( i != mapStack.front().end() ) {
    98                         instType->set_name( i->second );
    99                 } else {
    100                 } // if
    101                 acceptAll( instType->get_parameters(), *this );
    102                 typeAfter( instType );
    103         }
    104 
    105         void RenameVars::visit( TupleType *tupleType ) {
    106                 typeBefore( tupleType );
    107                 acceptAll( tupleType->get_types(), *this );
    108                 typeAfter( tupleType );
    109         }
    110 
    111         void RenameVars::visit( VarArgsType *varArgsType ) {
    112                 typeBefore( varArgsType );
    113                 typeAfter( varArgsType );
    114         }
    115 
    116         void RenameVars::visit( ZeroType *zeroType ) {
    117                 typeBefore( zeroType );
    118                 typeAfter( zeroType );
    119         }
    120 
    121         void RenameVars::visit( OneType *oneType ) {
    122                 typeBefore( oneType );
    123                 typeAfter( oneType );
    124         }
    125 
    126         void RenameVars::typeBefore( Type *type ) {
    127                 if ( ! type->get_forall().empty() ) {
    128                         // copies current name mapping into new mapping
    129                         mapStack.push_front( mapStack.front() );
    130                         // renames all "forall" type names to `_${level}_${name}'
    131                         for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
    132                                 std::ostringstream output;
    133                                 output << "_" << resetCount << "_" << level << "_" << (*i)->get_name();
    134                                 std::string newname( output.str() );
    135                                 mapStack.front()[ (*i)->get_name() ] = newname;
    136                                 (*i)->set_name( newname );
    137                                 // ditto for assertion names, the next level in
    138                                 level++;
    139                                 acceptAll( (*i)->get_assertions(), *this );
    140                         } // for
    141                 } // if
    142         }
    143 
    144         void RenameVars::typeAfter( Type *type ) {
    145                 // clears name mapping added by typeBefore()
    146                 if ( ! type->get_forall().empty() ) {
    147                         mapStack.pop_front();
    148                 } // if
    149         }
    150 
     91                void RenameVars::postvisit( Type * type ) {
     92                        // clears name mapping added by typeBefore()
     93                        if ( ! type->forall.empty() ) {
     94                                mapStack.pop_front();
     95                        } // if
     96                }
     97        } // namespace
    15198} // namespace ResolvExpr
    15299
  • src/ResolvExpr/RenameVars.h

    rb158d8f rb6838214  
    2424
    2525namespace ResolvExpr {
     26        /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
     27        void renameTyVars( Type * );
    2628
    27         /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    28         class RenameVars : public Visitor {
    29           public:
    30                 RenameVars();
    31                 void reset();
    32           private:
    33                 virtual void visit( VoidType *basicType );
    34                 virtual void visit( BasicType *basicType );
    35                 virtual void visit( PointerType *pointerType );
    36                 virtual void visit( ArrayType *arrayType );
    37                 virtual void visit( FunctionType *functionType );
    38                 virtual void visit( StructInstType *aggregateUseType );
    39                 virtual void visit( UnionInstType *aggregateUseType );
    40                 virtual void visit( EnumInstType *aggregateUseType );
    41                 virtual void visit( TraitInstType *aggregateUseType );
    42                 virtual void visit( TypeInstType *aggregateUseType );
    43                 virtual void visit( TupleType *tupleType );
    44                 virtual void visit( VarArgsType *varArgsType );
    45                 virtual void visit( ZeroType *zeroType );
    46                 virtual void visit( OneType *oneType );
    47 
    48                 void typeBefore( Type *type );
    49                 void typeAfter( Type *type );
    50                 int level, resetCount;
    51                 std::list< std::map< std::string, std::string > > mapStack;
    52         };
    53 
    54         extern RenameVars global_renamer;
     29        /// resets internal state of renamer to avoid overflow
     30        void resetTyVarRenaming();
    5531} // namespace ResolvExpr
    5632
  • src/ResolvExpr/Resolver.cc

    rb158d8f rb6838214  
    132132
    133133        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    134                 global_renamer.reset();
     134                resetTyVarRenaming();
    135135                TypeEnvironment env;
    136136                Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
     
    155155                } // if
    156156                #endif
    157                 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
     157                assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end: (%zd) %s", finder.get_alternatives().size(), toString( untyped ).c_str() );
    158158                Alternative &choice = finder.get_alternatives().front();
    159159                Expression *newExpr = choice.expr->clone();
     
    171171
    172172        namespace {
     173                /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
     174                template<typename Pred>
     175                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) {
     176                        TypeEnvironment env;
     177                        AlternativeFinder finder( indexer, env );
     178                        finder.findWithAdjustment( untyped );
     179
     180                        AltList candidates;
     181                        for ( Alternative & alt : finder.get_alternatives() ) {
     182                                if ( pred( alt.expr->result ) ) {
     183                                        candidates.push_back( std::move( alt ) );
     184                                }
     185                        }
     186
     187                        // choose the lowest cost expression among the candidates
     188                        AltList winners;
     189                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     190                        if ( winners.size() == 0 ) {
     191                                throw SemanticError( "No reasonable alternatives for " + kindStr + " expression: ", untyped );
     192                        } else if ( winners.size() != 1 ) {
     193                                std::ostringstream stream;
     194                                stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr +  " expression\n";
     195                                untyped->print( stream );
     196                                stream << "Alternatives are:\n";
     197                                printAlts( winners, stream, 1 );
     198                                throw SemanticError( stream.str() );
     199                        }
     200
     201                        // there is one unambiguous interpretation - move the expression into the with statement
     202                        Alternative & alt = winners.front();
     203                        finishExpr( alt.expr, alt.env, untyped->env );
     204                        delete untyped;
     205                        untyped = alt.expr;
     206                        alt.expr = nullptr;
     207                }
     208
    173209                bool isIntegralType( Type *type ) {
    174210                        if ( dynamic_cast< EnumInstType * >( type ) ) {
     
    184220
    185221                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    186                         TypeEnvironment env;
    187                         AlternativeFinder finder( indexer, env );
    188                         finder.find( untyped );
    189 #if 0
    190                         if ( finder.get_alternatives().size() != 1 ) {
    191                                 std::cout << "untyped expr is ";
    192                                 untyped->print( std::cout );
    193                                 std::cout << std::endl << "alternatives are:";
    194                                 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    195                                         i->print( std::cout );
    196                                 } // for
    197                         } // if
    198 #endif
    199                         Expression *newExpr = 0;
    200                         const TypeEnvironment *newEnv = 0;
    201                         for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    202                                 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) {
    203                                         if ( newExpr ) {
    204                                                 throw SemanticError( "Too many interpretations for case control expression", untyped );
    205                                         } else {
    206                                                 newExpr = i->expr->clone();
    207                                                 newEnv = &i->env;
    208                                         } // if
    209                                 } // if
    210                         } // for
    211                         if ( ! newExpr ) {
    212                                 throw SemanticError( "No interpretations for case control expression", untyped );
    213                         } // if
    214                         finishExpr( newExpr, *newEnv, untyped->env );
    215                         delete untyped;
    216                         untyped = newExpr;
    217                 }
    218 
     222                        findKindExpression( untyped, indexer, "condition", isIntegralType );
     223                }
    219224        }
    220225
     
    311316
    312317        void Resolver::previsit( IfStmt *ifStmt ) {
    313                 findSingleExpression( ifStmt->condition, indexer );
     318                findIntegralExpression( ifStmt->condition, indexer );
    314319        }
    315320
    316321        void Resolver::previsit( WhileStmt *whileStmt ) {
    317                 findSingleExpression( whileStmt->condition, indexer );
     322                findIntegralExpression( whileStmt->condition, indexer );
    318323        }
    319324
    320325        void Resolver::previsit( ForStmt *forStmt ) {
    321326                if ( forStmt->condition ) {
    322                         findSingleExpression( forStmt->condition, indexer );
     327                        findIntegralExpression( forStmt->condition, indexer );
    323328                } // if
    324329
     
    579584        }
    580585
     586
    581587        void Resolver::previsit( WithStmt * withStmt ) {
    582588                for ( Expression *& expr : withStmt->exprs )  {
    583                         TypeEnvironment env;
    584                         AlternativeFinder finder( indexer, env );
    585                         finder.findWithAdjustment( expr );
    586 
    587589                        // only struct- and union-typed expressions are viable candidates
    588                         AltList candidates;
    589                         for ( Alternative & alt : finder.get_alternatives() ) {
    590                                 if ( isStructOrUnion( alt.expr->result ) ) {
    591                                         candidates.push_back( std::move( alt ) );
    592                                 }
    593                         }
    594 
    595                         // choose the lowest cost expression among the candidates
    596                         AltList winners;
    597                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    598                         if ( winners.size() == 0 ) {
    599                                 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr );
    600                         } else if ( winners.size() != 1 ) {
    601                                 std::ostringstream stream;
    602                                 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n";
    603                                 expr->print( stream );
    604                                 stream << "Alternatives are:\n";
    605                                 printAlts( winners, stream, 1 );
    606                                 throw SemanticError( stream.str() );
    607                         }
    608 
    609                         // there is one unambiguous interpretation - move the expression into the with statement
    610                         Alternative & alt = winners.front();
    611                         finishExpr( alt.expr, alt.env, expr->env );
    612                         delete expr;
    613                         expr = alt.expr;
    614                         alt.expr = nullptr;
     590                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
    615591
    616592                        // if with expression might be impure, create a temporary so that it is evaluated once
  • src/ResolvExpr/Resolver.h

    rb158d8f rb6838214  
    3333        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer );
    3434        void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer );
     35        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer &indexer );
    3536        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    3637        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
  • src/ResolvExpr/Unify.cc

    rb158d8f rb6838214  
    4444namespace ResolvExpr {
    4545
    46         class Unify : public Visitor {
    47           public:
     46        struct Unify : public WithShortCircuiting {
    4847                Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    4948
    5049                bool get_result() const { return result; }
     50
     51                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     52
     53                void postvisit( VoidType * voidType );
     54                void postvisit( BasicType * basicType );
     55                void postvisit( PointerType * pointerType );
     56                void postvisit( ArrayType * arrayType );
     57                void postvisit( ReferenceType * refType );
     58                void postvisit( FunctionType * functionType );
     59                void postvisit( StructInstType * aggregateUseType );
     60                void postvisit( UnionInstType * aggregateUseType );
     61                void postvisit( EnumInstType * aggregateUseType );
     62                void postvisit( TraitInstType * aggregateUseType );
     63                void postvisit( TypeInstType * aggregateUseType );
     64                void postvisit( TupleType * tupleType );
     65                void postvisit( VarArgsType * varArgsType );
     66                void postvisit( ZeroType * zeroType );
     67                void postvisit( OneType * oneType );
     68
    5169          private:
    52                 virtual void visit(VoidType *voidType);
    53                 virtual void visit(BasicType *basicType);
    54                 virtual void visit(PointerType *pointerType);
    55                 virtual void visit(ArrayType *arrayType);
    56                 virtual void visit(ReferenceType *refType);
    57                 virtual void visit(FunctionType *functionType);
    58                 virtual void visit(StructInstType *aggregateUseType);
    59                 virtual void visit(UnionInstType *aggregateUseType);
    60                 virtual void visit(EnumInstType *aggregateUseType);
    61                 virtual void visit(TraitInstType *aggregateUseType);
    62                 virtual void visit(TypeInstType *aggregateUseType);
    63                 virtual void visit(TupleType *tupleType);
    64                 virtual void visit(VarArgsType *varArgsType);
    65                 virtual void visit(ZeroType *zeroType);
    66                 virtual void visit(OneType *oneType);
    67 
    6870                template< typename RefType > void handleRefType( RefType *inst, Type *other );
    6971                template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
     
    325327                        result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    326328                } else {
    327                         Unify comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     329                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    328330                        type1->accept( comparator );
    329                         result = comparator.get_result();
     331                        result = comparator.pass.get_result();
    330332                } // if
    331333#ifdef DEBUG
     
    404406        }
    405407
    406         void Unify::visit( __attribute__((unused)) VoidType *voidType) {
     408        void Unify::postvisit( __attribute__((unused)) VoidType *voidType) {
    407409                result = dynamic_cast< VoidType* >( type2 );
    408410        }
    409411
    410         void Unify::visit(BasicType *basicType) {
     412        void Unify::postvisit(BasicType *basicType) {
    411413                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    412414                        result = basicType->get_kind() == otherBasic->get_kind();
     
    436438        }
    437439
    438         void Unify::visit(PointerType *pointerType) {
     440        void Unify::postvisit(PointerType *pointerType) {
    439441                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    440442                        result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    444446        }
    445447
    446         void Unify::visit(ReferenceType *refType) {
     448        void Unify::postvisit(ReferenceType *refType) {
    447449                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    448450                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    452454        }
    453455
    454         void Unify::visit(ArrayType *arrayType) {
     456        void Unify::postvisit(ArrayType *arrayType) {
    455457                ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    456458                // to unify, array types must both be VLA or both not VLA
     
    567569        }
    568570
    569         void Unify::visit(FunctionType *functionType) {
     571        void Unify::postvisit(FunctionType *functionType) {
    570572                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    571573                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
     
    669671        }
    670672
    671         void Unify::visit(StructInstType *structInst) {
     673        void Unify::postvisit(StructInstType *structInst) {
    672674                handleGenericRefType( structInst, type2 );
    673675        }
    674676
    675         void Unify::visit(UnionInstType *unionInst) {
     677        void Unify::postvisit(UnionInstType *unionInst) {
    676678                handleGenericRefType( unionInst, type2 );
    677679        }
    678680
    679         void Unify::visit(EnumInstType *enumInst) {
     681        void Unify::postvisit(EnumInstType *enumInst) {
    680682                handleRefType( enumInst, type2 );
    681683        }
    682684
    683         void Unify::visit(TraitInstType *contextInst) {
     685        void Unify::postvisit(TraitInstType *contextInst) {
    684686                handleRefType( contextInst, type2 );
    685687        }
    686688
    687         void Unify::visit(TypeInstType *typeInst) {
     689        void Unify::postvisit(TypeInstType *typeInst) {
    688690                assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    689691                TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
     
    740742        }
    741743
    742         void Unify::visit(TupleType *tupleType) {
     744        void Unify::postvisit(TupleType *tupleType) {
    743745                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    744746                        std::unique_ptr<TupleType> flat1( tupleType->clone() );
     
    757759        }
    758760
    759         void Unify::visit( __attribute__((unused)) VarArgsType *varArgsType ) {
     761        void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    760762                result = dynamic_cast< VarArgsType* >( type2 );
    761763        }
    762764
    763         void Unify::visit( __attribute__((unused)) ZeroType *zeroType ) {
     765        void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    764766                result = dynamic_cast< ZeroType* >( type2 );
    765767        }
    766768
    767         void Unify::visit( __attribute__((unused)) OneType *oneType ) {
     769        void Unify::postvisit( __attribute__((unused)) OneType *oneType ) {
    768770                result = dynamic_cast< OneType* >( type2 );
    769771        }
Note: See TracChangeset for help on using the changeset viewer.