Changes in / [2b72090:bee7f04]


Ignore:
Location:
src
Files:
16 added
16 deleted
22 edited

Legend:

Unmodified
Added
Removed
  • src/Common/PassVisitor.h

    r2b72090 rbee7f04  
    1919#include "SynTree/Expression.h"
    2020#include "SynTree/Constant.h"
    21 #include "SynTree/TypeSubstitution.h"
     21
     22class TypeSubstitution;
    2223
    2324#include "PassVisitor.proto.h"
     
    403404};
    404405
     406#include "SynTree/TypeSubstitution.h"
    405407#include "PassVisitor.impl.h"
  • src/Common/PassVisitor.impl.h

    r2b72090 rbee7f04  
    6262
    6363template< typename pass_type >
    64 static inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {
     64inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {
    6565        DeclList_t* beforeDecls = visitor.get_beforeDecls();
    6666        DeclList_t* afterDecls  = visitor.get_afterDecls();
     
    9090
    9191template< typename pass_type >
    92 static inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
     92inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
    9393        DeclList_t* beforeDecls = mutator.get_beforeDecls();
    9494        DeclList_t* afterDecls  = mutator.get_afterDecls();
  • src/ControlStruct/LabelFixer.cc

    r2b72090 rbee7f04  
    4444
    4545        void LabelFixer::postvisit( FunctionDecl * functionDecl ) {
    46                 MLEMutator mlemut( resolveJumps(), generator );
     46                PassVisitor<MLEMutator> mlemut( resolveJumps(), generator );
    4747                functionDecl->acceptMutator( mlemut );
    4848        }
  • src/ControlStruct/MLEMutator.cc

    r2b72090 rbee7f04  
    4646        void MLEMutator::fixBlock( std::list< Statement * > &kids ) {
    4747                for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
    48                         *k = (*k)->acceptMutator(*this);
     48                        *k = (*k)->acceptMutator(*visitor);
    4949
    5050                        if ( ! get_breakLabel().empty() ) {
     
    5757        }
    5858
    59         CompoundStmt* MLEMutator::mutate( CompoundStmt *cmpndStmt ) {
    60                 bool labeledBlock = !(cmpndStmt->get_labels().empty());
     59        void MLEMutator::premutate( CompoundStmt *cmpndStmt ) {
     60                visit_children = false;
     61                bool labeledBlock = !(cmpndStmt->labels.empty());
    6162                if ( labeledBlock ) {
    6263                        Label brkLabel = generator->newLabel("blockBreak", cmpndStmt);
     
    6566
    6667                // a child statement may set the break label - if they do, attach it to the next statement
    67                 std::list< Statement * > &kids = cmpndStmt->get_kids();
     68                std::list< Statement * > &kids = cmpndStmt->kids;
    6869                fixBlock( kids );
    6970
     
    7576                        enclosingControlStructures.pop_back();
    7677                } // if
    77 
    78                 return cmpndStmt;
    79         }
    80 
    81         template< typename LoopClass >
    82         Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) {
    83                 // remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine
    84                 // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
    85                 // loops
    86                 Label brkLabel = generator->newLabel("loopBreak", loopStmt);
    87                 Label contLabel = generator->newLabel("loopContinue", loopStmt);
    88                 enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
    89                 loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
    90 
    91                 assert( ! enclosingControlStructures.empty() );
    92                 Entry &e = enclosingControlStructures.back();
    93                 // sanity check that the enclosing loops have been popped correctly
    94                 assert ( e == loopStmt );
    95 
    96                 // this will take the necessary steps to add definitions of the previous two labels, if they are used.
    97                 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
    98                 enclosingControlStructures.pop_back();
    99 
    100                 return loopStmt;
    101         }
    102 
    103         Statement *MLEMutator::mutate( CaseStmt *caseStmt ) {
    104                 caseStmt->set_condition( maybeMutate( caseStmt->get_condition(), *this ) );
    105                 fixBlock( caseStmt->get_statements() );
    106 
    107                 return caseStmt;
    108         }
    109 
    110         template< typename IfClass >
    111         Statement *MLEMutator::handleIfStmt( IfClass *ifStmt ) {
    112                 // generate a label for breaking out of a labeled if
    113                 bool labeledBlock = !(ifStmt->get_labels().empty());
    114                 if ( labeledBlock ) {
    115                         Label brkLabel = generator->newLabel("blockBreak", ifStmt);
    116                         enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
    117                 } // if
    118 
    119                 Parent::mutate( ifStmt );
    120 
    121                 if ( labeledBlock ) {
    122                         if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
    123                                 set_breakLabel( enclosingControlStructures.back().useBreakExit() );
    124                         } // if
    125                         enclosingControlStructures.pop_back();
    126                 } // if
    127                 return ifStmt;
    128         }
    129 
    130         template< typename SwitchClass >
    131         Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
    132                 // generate a label for breaking out of a labeled switch
    133                 Label brkLabel = generator->newLabel("switchBreak", switchStmt);
    134                 enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
    135                 mutateAll( switchStmt->get_statements(), *this );
    136 
    137                 Entry &e = enclosingControlStructures.back();
    138                 assert ( e == switchStmt );
    139 
    140                 // only generate break label if labeled break is used
    141                 if ( e.isBreakUsed() ) {
    142                         // for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a
    143                         // switch should be CastStmts), append the exit label + break to the last case statement; create a default
    144                         // case if there are no cases
    145                         std::list< Statement * > &statements = switchStmt->get_statements();
    146                         if ( statements.empty() ) {
    147                                 statements.push_back( CaseStmt::makeDefault() );
    148                         } // if
    149 
    150                         if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) {
    151                                 Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break );
    152                                 stmt->labels.push_back( brkLabel );
    153                                 c->get_statements().push_back( stmt );
    154                         } else assert(0); // as of this point, all statements of a switch are still CaseStmts
    155                 } // if
    156 
    157                 assert ( enclosingControlStructures.back() == switchStmt );
    158                 enclosingControlStructures.pop_back();
    159                 return switchStmt;
    160         }
     78        }
     79
    16180
    16281        void addUnused( Statement * stmt, const Label & originalTarget ) {
     
    17998
    18099
    181         Statement *MLEMutator::mutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
    182                 std::string originalTarget = branchStmt->get_originalTarget();
     100        Statement *MLEMutator::postmutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
     101                std::string originalTarget = branchStmt->originalTarget;
    183102
    184103                std::list< Entry >::reverse_iterator targetEntry;
     
    215134                // branch error checks, get the appropriate label name and create a goto
    216135                Label exitLabel;
    217                 switch ( branchStmt->get_type() ) {
     136                switch ( branchStmt->type ) {
    218137                  case BranchStmt::Break:
    219138                                assert( targetEntry->useBreakExit() != "");
     
    229148
    230149                // add unused attribute to label to silence warnings
    231                 addUnused( targetEntry->get_controlStructure(), branchStmt->get_originalTarget() );
     150                addUnused( targetEntry->get_controlStructure(), branchStmt->originalTarget );
    232151
    233152                // transform break/continue statements into goto to simplify later handling of branches
     
    260179        }
    261180
    262         Statement *MLEMutator::mutate( WhileStmt *whileStmt ) {
    263                 return handleLoopStmt( whileStmt );
    264         }
    265 
    266         Statement *MLEMutator::mutate( ForStmt *forStmt ) {
    267                 return handleLoopStmt( forStmt );
    268         }
    269 
    270         Statement *MLEMutator::mutate( IfStmt *ifStmt ) {
    271                 return handleIfStmt( ifStmt );
    272         }
    273 
    274         Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) {
    275                 return handleSwitchStmt( switchStmt );
     181        template< typename LoopClass >
     182        void MLEMutator::prehandleLoopStmt( LoopClass * loopStmt ) {
     183                // remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine
     184                // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
     185                // loops
     186                Label brkLabel = generator->newLabel("loopBreak", loopStmt);
     187                Label contLabel = generator->newLabel("loopContinue", loopStmt);
     188                enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
     189        }
     190
     191        template< typename LoopClass >
     192        Statement * MLEMutator::posthandleLoopStmt( LoopClass * loopStmt ) {
     193                assert( ! enclosingControlStructures.empty() );
     194                Entry &e = enclosingControlStructures.back();
     195                // sanity check that the enclosing loops have been popped correctly
     196                assert ( e == loopStmt );
     197
     198                // this will take the necessary steps to add definitions of the previous two labels, if they are used.
     199                loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
     200                enclosingControlStructures.pop_back();
     201                return loopStmt;
     202        }
     203
     204        void MLEMutator::premutate( WhileStmt * whileStmt ) {
     205                return prehandleLoopStmt( whileStmt );
     206        }
     207
     208        void MLEMutator::premutate( ForStmt * forStmt ) {
     209                return prehandleLoopStmt( forStmt );
     210        }
     211
     212        Statement * MLEMutator::postmutate( WhileStmt * whileStmt ) {
     213                return posthandleLoopStmt( whileStmt );
     214        }
     215
     216        Statement * MLEMutator::postmutate( ForStmt * forStmt ) {
     217                return posthandleLoopStmt( forStmt );
     218        }
     219
     220        void MLEMutator::premutate( IfStmt * ifStmt ) {
     221                // generate a label for breaking out of a labeled if
     222                bool labeledBlock = !(ifStmt->get_labels().empty());
     223                if ( labeledBlock ) {
     224                        Label brkLabel = generator->newLabel("blockBreak", ifStmt);
     225                        enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
     226                } // if
     227        }
     228
     229        Statement * MLEMutator::postmutate( IfStmt * ifStmt ) {
     230                bool labeledBlock = !(ifStmt->get_labels().empty());
     231                if ( labeledBlock ) {
     232                        if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
     233                                set_breakLabel( enclosingControlStructures.back().useBreakExit() );
     234                        } // if
     235                        enclosingControlStructures.pop_back();
     236                } // if
     237                return ifStmt;
     238        }
     239
     240        void MLEMutator::premutate( CaseStmt *caseStmt ) {
     241                visit_children = false;
     242                caseStmt->condition = maybeMutate( caseStmt->condition, *visitor );
     243                fixBlock( caseStmt->stmts );
     244        }
     245
     246        void MLEMutator::premutate( SwitchStmt *switchStmt ) {
     247                // generate a label for breaking out of a labeled switch
     248                Label brkLabel = generator->newLabel("switchBreak", switchStmt);
     249                enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
     250        }
     251
     252        Statement * MLEMutator::postmutate( SwitchStmt * switchStmt ) {
     253                Entry &e = enclosingControlStructures.back();
     254                assert ( e == switchStmt );
     255
     256                // only generate break label if labeled break is used
     257                if ( e.isBreakUsed() ) {
     258                        // for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a
     259                        // switch should be CastStmts), append the exit label + break to the last case statement; create a default
     260                        // case if there are no cases
     261                        std::list< Statement * > &statements = switchStmt->statements;
     262                        if ( statements.empty() ) {
     263                                statements.push_back( CaseStmt::makeDefault() );
     264                        } // if
     265
     266                        if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) {
     267                                Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break );
     268                                stmt->labels.push_back( e.useBreakExit() );
     269                                c->stmts.push_back( stmt );
     270                        } else assert(0); // as of this point, all statements of a switch are still CaseStmts
     271                } // if
     272
     273                assert ( enclosingControlStructures.back() == switchStmt );
     274                enclosingControlStructures.pop_back();
     275                return switchStmt;
    276276        }
    277277} // namespace ControlStruct
  • src/ControlStruct/MLEMutator.h

    r2b72090 rbee7f04  
    2020#include <string>                  // for string
    2121
     22#include "Common/PassVisitor.h"
    2223#include "Common/SemanticError.h"  // for SemanticError
    2324#include "SynTree/Label.h"         // for Label
     
    2627
    2728namespace ControlStruct {
    28 class LabelGenerator;
     29        class LabelGenerator;
    2930
    30         class MLEMutator : public Mutator {
     31        class MLEMutator : public WithVisitorRef<MLEMutator>, public WithShortCircuiting {
    3132                class Entry;
    3233
    33                 typedef Mutator Parent;
    3434          public:
    3535                MLEMutator( std::map<Label, Statement *> *t, LabelGenerator *gen = 0 ) : targetTable( t ), breakLabel(std::string("")), generator( gen ) {}
    3636                ~MLEMutator();
    3737
    38                 virtual CompoundStmt *mutate( CompoundStmt *cmpndStmt ) override;
    39                 virtual Statement *mutate( WhileStmt *whileStmt ) override;
    40                 virtual Statement *mutate( ForStmt *forStmt ) override;
    41                 virtual Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError ) override;
    42                 virtual Statement *mutate( CaseStmt *caseStmt ) override;
    43                 virtual Statement *mutate( IfStmt *ifStmt ) override;
    44                 virtual Statement *mutate( SwitchStmt *switchStmt ) override;
     38                void premutate( CompoundStmt *cmpndStmt );
     39                Statement * postmutate( BranchStmt *branchStmt ) throw ( SemanticError );
     40                void premutate( WhileStmt *whileStmt );
     41                Statement * postmutate( WhileStmt *whileStmt );
     42                void premutate( ForStmt *forStmt );
     43                Statement * postmutate( ForStmt *forStmt );
     44                void premutate( CaseStmt *caseStmt );
     45                void premutate( IfStmt *ifStmt );
     46                Statement * postmutate( IfStmt *ifStmt );
     47                void premutate( SwitchStmt *switchStmt );
     48                Statement * postmutate( SwitchStmt *switchStmt );
    4549
    4650                Statement *mutateLoop( Statement *bodyLoop, Entry &e );
     
    5458                                loop( _loop ), breakExit( _breakExit ), contExit( _contExit ), breakUsed(false), contUsed(false) {}
    5559
    56                         bool operator==( const Statement *stmt ) { return ( loop == stmt ); }
    57                         bool operator!=( const Statement *stmt ) { return ( loop != stmt ); }
     60                        bool operator==( const Statement *stmt ) { return loop == stmt; }
     61                        bool operator!=( const Statement *stmt ) { return loop != stmt; }
    5862
    59                         bool operator==( const Entry &other ) { return ( loop == other.get_controlStructure() ); }
     63                        bool operator==( const Entry &other ) { return loop == other.get_controlStructure(); }
    6064
    6165                        Statement *get_controlStructure() const { return loop; }
     
    7882
    7983                template< typename LoopClass >
    80                 Statement *handleLoopStmt( LoopClass *loopStmt );
     84                void prehandleLoopStmt( LoopClass * loopStmt );
    8185
    82                 template< typename IfClass >
    83                 Statement *handleIfStmt( IfClass *switchStmt );
    84 
    85                 template< typename SwitchClass >
    86                 Statement *handleSwitchStmt( SwitchClass *switchStmt );
     86                template< typename LoopClass >
     87                Statement * posthandleLoopStmt( LoopClass * loopStmt );
    8788
    8889                void fixBlock( std::list< Statement * > &kids );
  • src/GenPoly/Box.cc

    r2b72090 rbee7f04  
    302302        Expression *makeOp( const std::string &name, Expression *arg ) {
    303303                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
    304                 expr->get_args().push_back( arg );
     304                expr->args.push_back( arg );
    305305                return expr;
    306306        }
     
    309309        Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
    310310                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
    311                 expr->get_args().push_back( lhs );
    312                 expr->get_args().push_back( rhs );
     311                expr->args.push_back( lhs );
     312                expr->args.push_back( rhs );
    313313                return expr;
    314314        }
     
    316316        /// Returns the dereference of a local pointer variable
    317317        Expression *derefVar( ObjectDecl *var ) {
    318                 return makeOp( "*?", new VariableExpr( var ) );
     318                return UntypedExpr::createDeref( new VariableExpr( var ) );
    319319        }
    320320
     
    831831                                if ( ! isPolyType( arg->get_type() ) ) {
    832832                                        UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    833                                         deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
    834                                         deref->set_result( arg->get_type()->clone() );
     833                                        deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
     834                                        deref->result = arg->get_type()->clone();
     835                                        deref->result->set_lvalue( true );
    835836                                        return deref;
    836837                                } // if
  • src/GenPoly/Lvalue.cc

    r2b72090 rbee7f04  
    4747                        if ( SymTab::dereferenceOperator ) {
    4848                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
    49                                 deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
    50                                 Type * base = InitTweak::getPointerBase( arg->get_result() );
    51                                 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
     49                                deref->result = new PointerType( Type::Qualifiers(), deref->result );
     50                                Type * base = InitTweak::getPointerBase( arg->result );
     51                                assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->result ).c_str() );
    5252                                ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
    53                                 delete ret->get_result();
    54                                 ret->set_result( base->clone() );
    55                                 ret->get_result()->set_lvalue( true );
     53                                delete ret->result;
     54                                ret->result = base->clone();
     55                                ret->result->set_lvalue( true );
    5656                                return ret;
    5757                        } else {
     
    308308                                        int diff = depth1-depth2;
    309309                                        if ( diff == 0 ) {
     310                                                // conversion between references of the same depth
    310311                                                assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
    311312                                                PRINT( std::cerr << castExpr << std::endl; )
    312313                                                return castExpr;
    313314                                        } else if ( diff < 0 ) {
    314                                                 Expression * ret = castExpr->get_arg();
     315                                                // conversion from reference to reference with less depth (e.g. int && -> int &): add dereferences
     316                                                Expression * ret = castExpr->arg;
    315317                                                for ( int i = 0; i < diff; ++i ) {
    316318                                                        ret = mkDeref( ret );
    317319                                                }
    318                                                 ret->set_env( castExpr->get_env() );
    319                                                 delete ret->get_result();
    320                                                 ret->set_result( castExpr->get_result() );
    321                                                 castExpr->set_env( nullptr );
    322                                                 castExpr->set_arg( nullptr );
    323                                                 castExpr->set_result( nullptr );
     320                                                ret->env = castExpr->env;
     321                                                delete ret->result;
     322                                                ret->result = castExpr->result;
     323                                                ret->result->set_lvalue( true ); // ensure result is lvalue
     324                                                castExpr->env = nullptr;
     325                                                castExpr->arg = nullptr;
     326                                                castExpr->result = nullptr;
    324327                                                delete castExpr;
    325328                                                return ret;
    326329                                        } else if ( diff > 0 ) {
    327                                                 Expression * ret = castExpr->get_arg();
     330                                                // conversion from reference to reference with more depth (e.g. int & -> int &&): add address-of
     331                                                Expression * ret = castExpr->arg;
    328332                                                for ( int i = 0; i < diff; ++i ) {
    329333                                                        ret = new AddressExpr( ret );
    330334                                                }
    331                                                 ret->set_env( castExpr->get_env() );
    332                                                 delete ret->get_result();
    333                                                 ret->set_result( castExpr->get_result() );
    334                                                 castExpr->set_env( nullptr );
    335                                                 castExpr->set_arg( nullptr );
    336                                                 castExpr->set_result( nullptr );
     335                                                ret->env = castExpr->env;
     336                                                delete ret->result;
     337                                                ret->result = castExpr->result;
     338                                                castExpr->env = nullptr;
     339                                                castExpr->arg = nullptr;
     340                                                castExpr->result = nullptr;
    337341                                                delete castExpr;
    338342                                                return ret;
     
    342346                                        PRINT( std::cerr << castExpr << std::endl; )
    343347                                        return castExpr;
    344                                 } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
     348                                } else if ( castExpr->arg->result->get_lvalue() ) {
    345349                                        // conversion from lvalue to reference
    346350                                        // xxx - keep cast, but turn into pointer cast??
     
    348352                                        PRINT(
    349353                                                std::cerr << "convert lvalue to reference -- &" << std::endl;
    350                                                 std::cerr << castExpr->get_arg() << std::endl;
     354                                                std::cerr << castExpr->arg << std::endl;
    351355                                        )
    352                                         AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
    353                                         if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
     356                                        AddressExpr * ret = new AddressExpr( castExpr->arg );
     357                                        if ( refType->base->get_qualifiers() != castExpr->arg->result->get_qualifiers() ) {
    354358                                                // must keep cast if cast-to type is different from the actual type
    355                                                 castExpr->set_arg( ret );
     359                                                castExpr->arg = ret;
    356360                                                return castExpr;
    357361                                        }
    358                                         ret->set_env( castExpr->get_env() );
    359                                         delete ret->get_result();
    360                                         ret->set_result( castExpr->get_result() );
    361                                         castExpr->set_env( nullptr );
    362                                         castExpr->set_arg( nullptr );
    363                                         castExpr->set_result( nullptr );
     362                                        ret->env = castExpr->env;
     363                                        delete ret->result;
     364                                        ret->result = castExpr->result;
     365                                        castExpr->env = nullptr;
     366                                        castExpr->arg = nullptr;
     367                                        castExpr->result = nullptr;
    364368                                        delete castExpr;
    365369                                        return ret;
     
    368372                                }
    369373                                assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
    370                         } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     374                        } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) {
    371375                                (void)refType;
    372376                                // conversion from reference to rvalue
     
    375379                                        std::cerr << "was = " << castExpr << std::endl;
    376380                                )
    377                                 Expression * ret = castExpr->get_arg();
    378                                 TypeSubstitution * env = castExpr->get_env();
     381                                Expression * ret = castExpr->arg;
     382                                TypeSubstitution * env = castExpr->env;
    379383                                castExpr->set_env( nullptr );
    380384                                if ( ! isIntrinsicReference( ret ) ) {
     
    382386                                        ret = mkDeref( ret );
    383387                                }
    384                                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
     388                                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->result, castExpr->arg->result->stripReferences(), SymTab::Indexer() ) ) {
    385389                                        // can remove cast if types are compatible, changing expression type to value type
    386                                         ret->set_result( castExpr->get_result()->clone() );
    387                                         castExpr->set_arg( nullptr );
     390                                        ret->result = castExpr->result->clone();
     391                                        ret->result->set_lvalue( true );  // ensure result is lvalue
     392                                        castExpr->arg = nullptr;
    388393                                        delete castExpr;
    389394                                } else {
    390395                                        // must keep cast if types are different
    391                                         castExpr->set_arg( ret );
     396                                        castExpr->arg = ret;
    392397                                        ret = castExpr;
    393398                                }
  • src/GenPoly/ScrubTyVars.cc

    r2b72090 rbee7f04  
    2525
    2626namespace GenPoly {
    27         Type * ScrubTyVars::mutate( TypeInstType *typeInst ) {
     27        Type * ScrubTyVars::postmutate( TypeInstType * typeInst ) {
    2828                if ( ! tyVars ) {
    2929                        if ( typeInst->get_isFtype() ) {
     
    3131                                return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
    3232                        } else {
    33                                 PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
     33                                PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
    3434                                delete typeInst;
    3535                                return ret;
     
    3737                }
    3838
    39                 TyVarMap::const_iterator tyVar = tyVars->find( typeInst->get_name() );
     39                TyVarMap::const_iterator tyVar = tyVars->find( typeInst->name );
    4040                if ( tyVar != tyVars->end() ) {
    4141                        switch ( tyVar->second.kind ) {
     
    4343                          case TypeDecl::Ttype:
    4444                                {
    45                                         PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
     45                                        PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
    4646                                        delete typeInst;
    4747                                        return ret;
     
    5555        }
    5656
    57         Type * ScrubTyVars::mutateAggregateType( Type *ty ) {
     57        Type * ScrubTyVars::mutateAggregateType( Type * ty ) {
    5858                if ( shouldScrub( ty ) ) {
    59                         PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
     59                        PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
    6060                        delete ty;
    6161                        return ret;
     
    6464        }
    6565
    66         Type * ScrubTyVars::mutate( StructInstType *structInst ) {
     66        Type * ScrubTyVars::postmutate( StructInstType * structInst ) {
    6767                return mutateAggregateType( structInst );
    6868        }
    6969
    70         Type * ScrubTyVars::mutate( UnionInstType *unionInst ) {
     70        Type * ScrubTyVars::postmutate( UnionInstType * unionInst ) {
    7171                return mutateAggregateType( unionInst );
    7272        }
    7373
    74         Expression * ScrubTyVars::mutate( SizeofExpr *szeof ) {
     74        void ScrubTyVars::primeBaseScrub( Type * type ) {
     75                // need to determine whether type needs to be scrubbed to determine whether
     76                // automatic recursion is necessary
     77                if ( Type * t = shouldScrub( type ) ) {
     78                        visit_children = false;
     79                        GuardValue( dynType );
     80                        dynType = t;
     81                }
     82        }
     83
     84        Expression * ScrubTyVars::postmutate( SizeofExpr * szeof ) {
    7585                // sizeof( T ) => _sizeof_T parameter, which is the size of T
    76                 if ( Type *dynType = shouldScrub( szeof->get_type() ) ) {
     86                if ( dynType ) {
    7787                        Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) );
    7888                        return expr;
    79                 } else {
    80                         return Mutator::mutate( szeof );
    8189                } // if
     90                return szeof;
    8291        }
    8392
    84         Expression * ScrubTyVars::mutate( AlignofExpr *algnof ) {
     93        Expression * ScrubTyVars::postmutate( AlignofExpr * algnof ) {
    8594                // alignof( T ) => _alignof_T parameter, which is the alignment of T
    86                 if ( Type *dynType = shouldScrub( algnof->get_type() ) ) {
     95                if ( dynType ) {
    8796                        Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) );
    8897                        return expr;
    89                 } else {
    90                         return Mutator::mutate( algnof );
    9198                } // if
     99                return algnof;
    92100        }
    93101
    94         Type * ScrubTyVars::mutate( PointerType *pointer ) {
    95 //              // special case of shouldScrub that takes all TypeInstType pointer bases, even if they're not dynamic
    96 //              Type *base = pointer->get_base();
    97 //              Type *dynType = 0;
    98 //              if ( dynamicOnly ) {
    99 //                      if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( base ) ) {
    100 //                              if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) { dynType = typeInst; }
    101 //                      } else {
    102 //                              dynType = isDynType( base, tyVars );
    103 //                      }
    104 //              } else {
    105 //                      dynType = isPolyType( base, tyVars );
    106 //              }
    107 //              if ( dynType ) {
    108                 if ( Type *dynType = shouldScrub( pointer->get_base() ) ) {
    109                         Type *ret = dynType->acceptMutator( *this );
     102        Type * ScrubTyVars::postmutate( PointerType * pointer ) {
     103                if ( dynType ) {
     104                        Type * ret = dynType->acceptMutator( *visitor );
    110105                        ret->get_qualifiers() |= pointer->get_qualifiers();
    111                         pointer->set_base( 0 );
     106                        pointer->base = nullptr;
    112107                        delete pointer;
    113108                        return ret;
    114109                }
    115                 return Mutator::mutate( pointer );
     110                return pointer;
    116111        }
    117112} // namespace GenPoly
  • src/GenPoly/ScrubTyVars.h

    r2b72090 rbee7f04  
    1818#include <cassert>            // for assert
    1919
     20#include "Common/PassVisitor.h"
    2021#include "GenPoly.h"          // for TyVarMap, isPolyType, isDynType
    2122#include "SynTree/Mutator.h"  // for Mutator
     
    2728
    2829namespace GenPoly {
    29         class ScrubTyVars : public Mutator {
     30        struct ScrubTyVars : public WithVisitorRef<ScrubTyVars>, public WithShortCircuiting, public WithGuards {
    3031                /// Whether to scrub all type variables from the provided map, dynamic type variables from the provided map, or all type variables
    3132                enum ScrubMode { FromMap, DynamicFromMap, All };
     
    5152                static SynTreeClass *scrubAll( SynTreeClass *target );
    5253
    53                 virtual Type* mutate( TypeInstType *typeInst );
    54                 virtual Type* mutate( StructInstType *structInst );
    55                 virtual Type* mutate( UnionInstType *unionInst );
    56                 virtual Expression* mutate( SizeofExpr *szeof );
    57                 virtual Expression* mutate( AlignofExpr *algnof );
    58                 virtual Type* mutate( PointerType *pointer );
     54                /// determine if children should be visited based on whether base type should be scrubbed.
     55                void primeBaseScrub( Type * );
     56
     57                void premutate( TypeInstType * ) { visit_children = false; }
     58                void premutate( StructInstType * ) { visit_children = false; }
     59                void premutate( UnionInstType * ) { visit_children = false; }
     60                void premutate( SizeofExpr * szeof ) { primeBaseScrub( szeof->type ); }
     61                void premutate( AlignofExpr * algnof ) { primeBaseScrub( algnof->type ); }
     62                void premutate( PointerType * pointer ) { primeBaseScrub( pointer->base ); }
     63
     64                Type * postmutate( TypeInstType * typeInst );
     65                Type * postmutate( StructInstType * structInst );
     66                Type * postmutate( UnionInstType * unionInst );
     67                Expression * postmutate( SizeofExpr * szeof );
     68                Expression * postmutate( AlignofExpr * algnof );
     69                Type * postmutate( PointerType * pointer );
    5970
    6071          private:
     
    7586                const TyVarMap *tyVars;  ///< Type variables to scrub
    7687                ScrubMode mode;          ///< which type variables to scrub? [FromMap]
     88
     89                Type * dynType = nullptr; ///< result of shouldScrub
    7790        };
    7891
    7992        template< typename SynTreeClass >
    8093        SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) {
    81                 ScrubTyVars scrubber( tyVars );
     94                PassVisitor<ScrubTyVars> scrubber( tyVars );
    8295                return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
    8396        }
     
    8598        template< typename SynTreeClass >
    8699        SynTreeClass * ScrubTyVars::scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars ) {
    87                 ScrubTyVars scrubber( tyVars, ScrubTyVars::DynamicFromMap );
     100                PassVisitor<ScrubTyVars> scrubber( tyVars, ScrubTyVars::DynamicFromMap );
    88101                return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
    89102        }
     
    91104        template< typename SynTreeClass >
    92105        SynTreeClass * ScrubTyVars::scrubAll( SynTreeClass *target ) {
    93                 ScrubTyVars scrubber;
     106                PassVisitor<ScrubTyVars> scrubber;
    94107                return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
    95108        }
  • src/InitTweak/FixInit.cc

    r2b72090 rbee7f04  
    197197                };
    198198
    199                 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer {
     199                struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> {
    200200                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
    201201                        /// for any member that is missing a corresponding ctor/dtor call.
     
    203203                        static void generate( std::list< Declaration * > & translationUnit );
    204204
    205                         void previsit( FunctionDecl * funcDecl );
    206                         void postvisit( FunctionDecl * funcDecl );
    207 
    208                         void previsit( MemberExpr * memberExpr );
    209                         void previsit( ApplicationExpr * appExpr );
     205                        void premutate( FunctionDecl * funcDecl );
     206                        DeclarationWithType * postmutate( FunctionDecl * funcDecl );
     207
     208                        void premutate( MemberExpr * memberExpr );
     209                        void premutate( ApplicationExpr * appExpr );
     210
     211                        /// Note: this post mutate used to be in a separate visitor. If this pass breaks, one place to examine is whether it is
     212                        /// okay for this part of the recursion to occur alongside the rest.
     213                        Expression * postmutate( UntypedExpr * expr );
    210214
    211215                        SemanticError errors;
     
    220224                        bool isCtor = false; // true if current function is a constructor
    221225                        StructDecl * structDecl = nullptr;
    222                 };
    223 
    224                 // very simple resolver-like mutator class - used to
    225                 // resolve UntypedExprs that are found within newly
    226                 // generated constructor/destructor calls
    227                 class MutatingResolver final : public Mutator {
    228                   public:
    229                         MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
    230 
    231                         using Mutator::mutate;
    232                         virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override;
    233                         virtual Expression* mutate( UntypedExpr *untypedExpr ) override;
    234 
    235                   private:
    236                         SymTab::Indexer & indexer;
    237226                };
    238227
     
    315304                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    316305                        PassVisitor<GenStructMemberCalls> warner;
    317                         acceptAll( translationUnit, warner );
     306                        mutateAll( translationUnit, warner );
    318307                }
    319308
     
    950939                }
    951940
    952                 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
     941                void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) {
    953942                        GuardValue( function );
    954943                        GuardValue( unhandled );
     
    984973                }
    985974
    986                 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {
     975                DeclarationWithType * GenStructMemberCalls::postmutate( FunctionDecl * funcDecl ) {
    987976                        // remove the unhandled objects from usedUninit, because a call is inserted
    988977                        // to handle them - only objects that are later constructed are used uninitialized.
     
    10381027                                                Statement * callStmt = stmt.front();
    10391028
    1040                                                 MutatingResolver resolver( indexer );
    10411029                                                try {
    1042                                                         callStmt->acceptMutator( resolver );
     1030                                                        callStmt->acceptMutator( *visitor );
    10431031                                                        if ( isCtor ) {
    10441032                                                                function->get_statements()->push_front( callStmt );
     
    10561044                                throw errors;
    10571045                        }
     1046                        return funcDecl;
    10581047                }
    10591048
     
    10811070                }
    10821071
    1083                 void GenStructMemberCalls::previsit( ApplicationExpr * appExpr ) {
     1072                void GenStructMemberCalls::premutate( ApplicationExpr * appExpr ) {
    10841073                        if ( ! checkWarnings( function ) ) {
    10851074                                visit_children = false;
     
    11061095                }
    11071096
    1108                 void GenStructMemberCalls::previsit( MemberExpr * memberExpr ) {
     1097                void GenStructMemberCalls::premutate( MemberExpr * memberExpr ) {
    11091098                        if ( ! checkWarnings( function ) || ! isCtor ) {
    11101099                                visit_children = false;
     
    11341123                }
    11351124
    1136                 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {
    1137                         // add object to the indexer assumes that there will be no name collisions
    1138                         // in generated code. If this changes, add mutate methods for entities with
    1139                         // scope and call {enter,leave}Scope explicitly.
    1140                         indexer.addId( objectDecl );
    1141                         return objectDecl;
    1142                 }
    1143 
    1144                 Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) {
     1125                Expression * GenStructMemberCalls::postmutate( UntypedExpr * untypedExpr ) {
    11451126                        Expression * newExpr = untypedExpr;
    11461127                        ResolvExpr::findVoidExpression( newExpr, indexer );
  • src/ResolvExpr/CastCost.cc

    r2b72090 rbee7f04  
    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/ConversionCost.cc

    r2b72090 rbee7f04  
    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
     
    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                                 Type::Qualifiers tq1 = srcAsRef->get_base()->get_qualifiers();
    111                                 Type::Qualifiers tq2 = destAsRef->get_base()->get_qualifiers();
    112                                 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
     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 ) ) {
    113113                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    114114                                        if ( tq1 == tq2 ) {
     
    120120                                        }
    121121                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    122                                         int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer );
     122                                        int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
    123123                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
    124124                                        if ( assignResult > 0 ) {
     
    130130                        } else {
    131131                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    132                                 ConversionCost converter( dest, indexer, env );
     132                                PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
    133133                                src->accept( converter );
    134                                 return converter.get_cost();
     134                                return converter.pass.get_cost();
    135135                        } // if
    136136                } else {
     
    138138                        assert( diff == -1 && destAsRef );
    139139                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    140                         if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
     140                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
    141141                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
    142142                                if ( src->get_lvalue() ) {
     
    146146                                        )
    147147                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
    148                                         if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
     148                                        if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
    149149                                                return Cost::reference; // cost needs to be non-zero to add cast
    150                                         } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
     150                                        } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
    151151                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    152152                                        } else {
    153153                                                return Cost::unsafe;
    154154                                        } // if
    155                                 } else if ( destAsRef->get_base()->get_const() ) {
     155                                } else if ( destAsRef->base->get_const() ) {
    156156                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
    157157                                        // rvalue-to-const-reference conversion: T => const T &
     
    173173        }
    174174
    175         ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
    176                 : 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 ) {
    177177        }
    178178
     
    257257        };
    258258
    259         void ConversionCost::visit( VoidType * ) {
     259        void ConversionCost::postvisit( VoidType * ) {
    260260                cost = Cost::infinity;
    261261        }
    262262
    263         void ConversionCost::visit(BasicType *basicType) {
     263        void ConversionCost::postvisit(BasicType *basicType) {
    264264                if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
    265265                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
     
    278278        }
    279279
    280         void ConversionCost::visit( PointerType * pointerType ) {
     280        void ConversionCost::postvisit( PointerType * pointerType ) {
    281281                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    282282                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
    283                         Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
    284                         Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
    285                         if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     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 ) ) {
    286286                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    287287                                if ( tq1 == tq2 ) {
     
    312312        }
    313313
    314         void ConversionCost::visit( ArrayType * ) {}
    315 
    316         void ConversionCost::visit( ReferenceType * refType ) {
     314        void ConversionCost::postvisit( ArrayType * ) {}
     315
     316        void ConversionCost::postvisit( ReferenceType * refType ) {
    317317                // Note: dest can never be a reference, since it would have been caught in an earlier check
    318318                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     
    320320                // recursively compute conversion cost from T1 to T2.
    321321                // cv can be safely dropped because of 'implicit dereference' behavior.
    322                 refType->base->accept( *this );
     322                cost = costFunc( refType->base, dest, indexer, env );
    323323                if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
    324324                        cost.incReference();  // prefer exact qualifiers
     
    331331        }
    332332
    333         void ConversionCost::visit( FunctionType * ) {}
    334 
    335         void ConversionCost::visit( StructInstType * inst ) {
     333        void ConversionCost::postvisit( FunctionType * ) {}
     334
     335        void ConversionCost::postvisit( StructInstType * inst ) {
    336336                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
    337337                        if ( inst->name == destAsInst->name ) {
     
    341341        }
    342342
    343         void ConversionCost::visit( UnionInstType * inst ) {
     343        void ConversionCost::postvisit( UnionInstType * inst ) {
    344344                if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
    345345                        if ( inst->name == destAsInst->name ) {
     
    349349        }
    350350
    351         void ConversionCost::visit( EnumInstType * ) {
     351        void ConversionCost::postvisit( EnumInstType * ) {
    352352                static Type::Qualifiers q;
    353353                static BasicType integer( q, BasicType::SignedInt );
    354                 integer.accept( *this );  // safe if dest >= int
     354                cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
    355355                if ( cost < Cost::unsafe ) {
    356356                        cost.incSafe();
     
    358358        }
    359359
    360         void ConversionCost::visit( TraitInstType * ) {}
    361 
    362         void ConversionCost::visit( TypeInstType *inst ) {
     360        void ConversionCost::postvisit( TraitInstType * ) {}
     361
     362        void ConversionCost::postvisit( TypeInstType *inst ) {
    363363                EqvClass eqvClass;
    364364                NamedTypeDecl *namedType;
    365                 if ( env.lookup( inst->get_name(), eqvClass ) ) {
    366                         cost = conversionCost( eqvClass.type, dest, indexer, env );
     365                if ( env.lookup( inst->name, eqvClass ) ) {
     366                        cost = costFunc( eqvClass.type, dest, indexer, env );
    367367                } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
    368                         if ( inst->get_name() == destAsInst->get_name() ) {
     368                        if ( inst->name == destAsInst->name ) {
    369369                                cost = Cost::zero;
    370370                        }
    371                 } else if ( ( namedType = indexer.lookupType( inst->get_name() ) ) ) {
     371                } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) {
    372372                        TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    373373                        // all typedefs should be gone by this point
    374374                        assert( type );
    375                         if ( type->get_base() ) {
    376                                 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
    377                         } // if
    378                 } // if
    379         }
    380 
    381         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 ) {
    382382                Cost c = Cost::zero;
    383383                if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
    384                         std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin();
    385                         std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin();
    386                         while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
    387                                 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 );
    388388                                if ( newCost == Cost::infinity ) {
    389389                                        return;
     
    391391                                c += newCost;
    392392                        } // while
    393                         if ( destIt != destAsTuple->get_types().end() ) {
     393                        if ( destIt != destAsTuple->types.end() ) {
    394394                                cost = Cost::infinity;
    395395                        } else {
     
    399399        }
    400400
    401         void ConversionCost::visit( VarArgsType * ) {
     401        void ConversionCost::postvisit( VarArgsType * ) {
    402402                if ( dynamic_cast< VarArgsType* >( dest ) ) {
    403403                        cost = Cost::zero;
     
    405405        }
    406406
    407         void ConversionCost::visit( ZeroType * ) {
     407        void ConversionCost::postvisit( ZeroType * ) {
    408408                if ( dynamic_cast< ZeroType * >( dest ) ) {
    409409                        cost = Cost::zero;
     
    422422        }
    423423
    424         void ConversionCost::visit( OneType * ) {
     424        void ConversionCost::postvisit( OneType * ) {
    425425                if ( dynamic_cast< OneType * >( dest ) ) {
    426426                        cost = Cost::zero;
  • src/ResolvExpr/ConversionCost.h

    r2b72090 rbee7f04  
    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/Resolver.cc

    r2b72090 rbee7f04  
    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/SynTree/AggregateDecl.cc

    r2b72090 rbee7f04  
    9292                } else if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
    9393                        return constExpr->intValue();
     94                // can be -1, +1, etc.
     95                // } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) {
     96                //      if ( untypedExpr-> )
    9497                } else {
    9598                        assertf( false, "Unhandled expression type in getConstValue for enumerators: %s", toString( expr ).c_str() );
  • src/SynTree/Expression.cc

    r2b72090 rbee7f04  
    108108        //      assert( inst->baseEnum );
    109109        //      EnumDecl * decl = inst->baseEnum;
    110         //      for ( Declaration * member : decl->members ) {
    111         //              if ( member == _var ) {
    112         //                      type->set_lvalue( false );
    113         //              }
     110        //      long long int value;
     111        //      if ( decl->valueOf( var, value ) ) {
     112        //              type->set_lvalue( false );
    114113        //      }
    115114        // }
     
    416415                } else {
    417416                        // references have been removed, in which case dereference returns an lvalue of the base type.
    418                         ret->get_result()->set_lvalue( true );
     417                        ret->result->set_lvalue( true );
    419418                }
    420419        }
  • src/SynTree/Label.h

    r2b72090 rbee7f04  
    3333        std::list< Attribute * >& get_attributes() { return attributes; }
    3434
    35         operator std::string() { return name; }
     35        operator std::string() const { return name; }
    3636        bool empty() { return name.empty(); }
    3737  private:
  • src/SynTree/TypeSubstitution.cc

    r2b72090 rbee7f04  
    107107
    108108void TypeSubstitution::normalize() {
     109        PassVisitor<Substituter> sub( *this, true );
    109110        do {
    110                 subCount = 0;
    111                 freeOnly = true;
     111                sub.pass.subCount = 0;
     112                sub.pass.freeOnly = true;
    112113                for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    113                         i->second = i->second->acceptMutator( *this );
     114                        i->second = i->second->acceptMutator( sub );
    114115                }
    115         } while ( subCount );
    116 }
    117 
    118 Type * TypeSubstitution::mutate( TypeInstType *inst ) {
    119         BoundVarsType::const_iterator bound = boundVars.find( inst->get_name() );
     116        } while ( sub.pass.subCount );
     117}
     118
     119Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
     120        BoundVarsType::const_iterator bound = boundVars.find( inst->name );
    120121        if ( bound != boundVars.end() ) return inst;
    121122
    122         TypeEnvType::const_iterator i = typeEnv.find( inst->get_name() );
    123         if ( i == typeEnv.end() ) {
     123        TypeEnvType::const_iterator i = sub.typeEnv.find( inst->get_name() );
     124        if ( i == sub.typeEnv.end() ) {
    124125                return inst;
    125126        } else {
    126 ///         std::cout << "found " << inst->get_name() << ", replacing with ";
    127 ///         i->second->print( std::cout );
    128 ///         std::cout << std::endl;
     127///         std::cerr << "found " << inst->get_name() << ", replacing with ";
     128///         i->second->print( std::cerr );
     129///         std::cerr << std::endl;
    129130                subCount++;
    130                 Type *newtype = i->second->clone();
     131                Type * newtype = i->second->clone();
    131132                newtype->get_qualifiers() |= inst->get_qualifiers();
    132133                delete inst;
     
    135136}
    136137
    137 Expression * TypeSubstitution::mutate( NameExpr *nameExpr ) {
    138         VarEnvType::const_iterator i = varEnv.find( nameExpr->get_name() );
    139         if ( i == varEnv.end() ) {
     138Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
     139        VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
     140        if ( i == sub.varEnv.end() ) {
    140141                return nameExpr;
    141142        } else {
     
    146147}
    147148
    148 template< typename TypeClass >
    149 Type *TypeSubstitution::handleType( TypeClass *type ) {
    150         ValueGuard<BoundVarsType> oldBoundVars( boundVars );
     149void TypeSubstitution::Substituter::premutate( Type * type ) {
     150        GuardValue( boundVars );
    151151        // bind type variables from forall-qualifiers
    152152        if ( freeOnly ) {
    153                 for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    154                         boundVars.insert( (*tyvar )->get_name() );
     153                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
     154                        boundVars.insert( (*tyvar)->name );
    155155                } // for
    156156        } // if
    157         Type *ret = Mutator::mutate( type );
    158         return ret;
    159157}
    160158
    161159template< typename TypeClass >
    162 Type *TypeSubstitution::handleAggregateType( TypeClass *type ) {
    163         ValueGuard<BoundVarsType> oldBoundVars( boundVars );
     160void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
     161        GuardValue( boundVars );
    164162        // bind type variables from forall-qualifiers
    165163        if ( freeOnly ) {
    166                 for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    167                         boundVars.insert( (*tyvar )->get_name() );
     164                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
     165                        boundVars.insert( (*tyvar)->name );
    168166                } // for
    169167                // bind type variables from generic type instantiations
    170168                std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
    171                 if ( baseParameters && ! type->get_parameters().empty() ) {
     169                if ( baseParameters && ! type->parameters.empty() ) {
    172170                        for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
    173                                 boundVars.insert( (*tyvar)->get_name() );
     171                                boundVars.insert( (*tyvar)->name );
    174172                        } // for
    175173                } // if
    176174        } // if
    177         Type *ret = Mutator::mutate( type );
    178         return ret;
    179 }
    180 
    181 Type * TypeSubstitution::mutate( VoidType *voidType ) {
    182         return handleType( voidType );
    183 }
    184 
    185 Type * TypeSubstitution::mutate( BasicType *basicType ) {
    186         return handleType( basicType );
    187 }
    188 
    189 Type * TypeSubstitution::mutate( PointerType *pointerType ) {
    190         return handleType( pointerType );
    191 }
    192 
    193 Type * TypeSubstitution::mutate( ArrayType *arrayType ) {
    194         return handleType( arrayType );
    195 }
    196 
    197 Type * TypeSubstitution::mutate( FunctionType *functionType ) {
    198         return handleType( functionType );
    199 }
    200 
    201 Type * TypeSubstitution::mutate( StructInstType *aggregateUseType ) {
    202         return handleAggregateType( aggregateUseType );
    203 }
    204 
    205 Type * TypeSubstitution::mutate( UnionInstType *aggregateUseType ) {
    206         return handleAggregateType( aggregateUseType );
    207 }
    208 
    209 Type * TypeSubstitution::mutate( EnumInstType *aggregateUseType ) {
    210         return handleType( aggregateUseType );
    211 }
    212 
    213 Type * TypeSubstitution::mutate( TraitInstType *aggregateUseType ) {
    214         return handleType( aggregateUseType );
    215 }
    216 
    217 Type * TypeSubstitution::mutate( TupleType *tupleType ) {
    218         return handleType( tupleType );
    219 }
    220 
    221 Type * TypeSubstitution::mutate( VarArgsType *varArgsType ) {
    222         return handleType( varArgsType );
    223 }
    224 
    225 Type * TypeSubstitution::mutate( ZeroType *zeroType ) {
    226         return handleType( zeroType );
    227 }
    228 
    229 Type * TypeSubstitution::mutate( OneType *oneType ) {
    230         return handleType( oneType );
     175}
     176
     177void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
     178        handleAggregateType( aggregateUseType );
     179}
     180
     181void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
     182        handleAggregateType( aggregateUseType );
    231183}
    232184
  • src/SynTree/TypeSubstitution.h

    r2b72090 rbee7f04  
    2727#include "SynTree/Declaration.h"   // for TypeDecl, Declaration (ptr only)
    2828#include "SynTree/Expression.h"    // for Expression (ptr only), NameExpr (p...
    29 #include "SynTree/Mutator.h"       // for Mutator
    3029#include "SynTree/Type.h"          // for Type, ArrayType (ptr only), BasicT...
    3130
    32 class TypeSubstitution : public Mutator {
    33         typedef Mutator Parent;
     31class TypeSubstitution {
    3432  public:
    3533        TypeSubstitution();
     
    6462        TypeSubstitution *clone() const { return new TypeSubstitution( *this ); }
    6563  private:
    66         virtual Type* mutate(TypeInstType *aggregateUseType);
    67         virtual Expression* mutate(NameExpr *nameExpr);
    6864
    69         /// Records type variable bindings from forall-statements
    70         template< typename TypeClass > Type *handleType( TypeClass *type );
    71         /// Records type variable bindings from forall-statements and instantiations of generic types
    72         template< typename TypeClass > Type *handleAggregateType( TypeClass *type );
    73 
    74         virtual Type* mutate(VoidType *basicType);
    75         virtual Type* mutate(BasicType *basicType);
    76         virtual Type* mutate(PointerType *pointerType);
    77         virtual Type* mutate(ArrayType *arrayType);
    78         virtual Type* mutate(FunctionType *functionType);
    79         virtual Type* mutate(StructInstType *aggregateUseType);
    80         virtual Type* mutate(UnionInstType *aggregateUseType);
    81         virtual Type* mutate(EnumInstType *aggregateUseType);
    82         virtual Type* mutate(TraitInstType *aggregateUseType);
    83         virtual Type* mutate(TupleType *tupleType);
    84         virtual Type* mutate(VarArgsType *varArgsType);
    85         virtual Type* mutate(ZeroType *zeroType);
    86         virtual Type* mutate(OneType *oneType);
     65        // Mutator that performs the substitution
     66        struct Substituter;
    8767
    8868        // TODO: worry about traversing into a forall-qualified function type or type decl with assertions
     
    9777        typedef std::map< std::string, Type* > TypeEnvType;
    9878        typedef std::map< std::string, Expression* > VarEnvType;
    99         typedef std::set< std::string > BoundVarsType;
    10079        TypeEnvType typeEnv;
    10180        VarEnvType varEnv;
    102         BoundVarsType boundVars;
    103         int subCount;
    104         bool freeOnly;
    10581};
    10682
     
    134110
    135111template< typename FormalIterator, typename ActualIterator >
    136 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin )
    137 {
     112TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
    138113        add( formalBegin, formalEnd, actualBegin );
    139114}
     115
     116// include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
     117// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
     118#include "Common/PassVisitor.h"
     119
     120// definitition must happen after PassVisitor is included so that WithGuards can be used
     121struct TypeSubstitution::Substituter : public WithGuards {
     122                Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
     123
     124                Type * postmutate( TypeInstType * aggregateUseType );
     125                Expression * postmutate( NameExpr * nameExpr );
     126
     127                /// Records type variable bindings from forall-statements
     128                void premutate( Type * type );
     129                /// Records type variable bindings from forall-statements and instantiations of generic types
     130                template< typename TypeClass > void handleAggregateType( TypeClass * type );
     131
     132                void premutate( StructInstType * aggregateUseType );
     133                void premutate( UnionInstType * aggregateUseType );
     134
     135                TypeSubstitution & sub;
     136                int subCount = 0;
     137                bool freeOnly;
     138                typedef std::set< std::string > BoundVarsType;
     139                BoundVarsType boundVars;
     140};
    140141
    141142template< typename SynTreeClass >
    142143int TypeSubstitution::apply( SynTreeClass *&input ) {
    143144        assert( input );
    144         subCount = 0;
    145         freeOnly = false;
    146         input = dynamic_cast< SynTreeClass *>( input->acceptMutator( *this ) );
     145        PassVisitor<Substituter> sub( *this, false );
     146        input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
    147147        assert( input );
    148 ///     std::cout << "substitution result is: ";
    149 ///     newType->print( std::cout );
    150 ///     std::cout << std::endl;
    151         return subCount;
     148///     std::cerr << "substitution result is: ";
     149///     newType->print( std::cerr );
     150///     std::cerr << std::endl;
     151        return sub.pass.subCount;
    152152}
    153153
     
    155155int TypeSubstitution::applyFree( SynTreeClass *&input ) {
    156156        assert( input );
    157         subCount = 0;
    158         freeOnly = true;
    159         input = dynamic_cast< SynTreeClass *>( input->acceptMutator( *this ) );
     157        PassVisitor<Substituter> sub( *this, true );
     158        input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
    160159        assert( input );
    161 ///     std::cout << "substitution result is: ";
    162 ///     newType->print( std::cout );
    163 ///     std::cout << std::endl;
    164         return subCount;
     160///     std::cerr << "substitution result is: ";
     161///     newType->print( std::cerr );
     162///     std::cerr << std::endl;
     163        return sub.pass.subCount;
    165164}
    166165
  • src/Tuples/TupleExpansion.cc

    r2b72090 rbee7f04  
    3636namespace Tuples {
    3737        namespace {
    38                 struct MemberTupleExpander final : public Mutator {
    39                         typedef Mutator Parent;
    40                         using Parent::mutate;
    41 
    42                         virtual Expression * mutate( UntypedMemberExpr * memberExpr ) override;
     38                struct MemberTupleExpander final : public WithShortCircuiting, public WithVisitorRef<MemberTupleExpander> {
     39                        void premutate( UntypedMemberExpr * ) { visit_children = false; }
     40                        Expression * postmutate( UntypedMemberExpr * memberExpr );
    4341                };
    4442
     
    7977
    8078        void expandMemberTuples( std::list< Declaration * > & translationUnit ) {
    81                 MemberTupleExpander expander;
     79                PassVisitor<MemberTupleExpander> expander;
    8280                mutateAll( translationUnit, expander );
    8381        }
     
    109107                                // construct a new UntypedMemberExpr with the correct structure , and recursively
    110108                                // expand that member expression.
    111                                 MemberTupleExpander expander;
    112                                 UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->get_aggregate(), aggr->clone() );
    113                                 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member(), inner );
     109                                PassVisitor<MemberTupleExpander> expander;
     110                                UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->aggregate, aggr->clone() );
     111                                UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member, inner );
    114112                                inner->location = newMemberExpr->location = loc;
    115                                 memberExpr->set_member(nullptr);
    116                                 memberExpr->set_aggregate(nullptr);
     113                                memberExpr->member = nullptr;
     114                                memberExpr->aggregate = nullptr;
    117115                                delete memberExpr;
    118116                                return newMemberExpr->acceptMutator( expander );
     
    126124        }
    127125
    128         Expression * MemberTupleExpander::mutate( UntypedMemberExpr * memberExpr ) {
    129                 if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr->get_member() ) ) {
    130                         Expression * aggr = memberExpr->get_aggregate()->clone()->acceptMutator( *this );
     126        Expression * MemberTupleExpander::postmutate( UntypedMemberExpr * memberExpr ) {
     127                if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr->member ) ) {
     128                        Expression * aggr = memberExpr->aggregate->clone()->acceptMutator( *visitor );
    131129                        // aggregate expressions which might be impure must be wrapped in unique expressions
    132130                        // xxx - if there's a member-tuple expression nested in the aggregate, this currently generates the wrong code if a UniqueExpr is not used, and it's purely an optimization to remove the UniqueExpr
    133131                        // if ( Tuples::maybeImpureIgnoreUnique( memberExpr->get_aggregate() ) ) aggr = new UniqueExpr( aggr );
    134132                        aggr = new UniqueExpr( aggr );
    135                         for ( Expression *& expr : tupleExpr->get_exprs() ) {
     133                        for ( Expression *& expr : tupleExpr->exprs ) {
    136134                                expr = reconstructMemberExpr( expr, aggr, memberExpr->location );
    137135                                expr->location = memberExpr->location;
     
    143141                        // there may be a tuple expr buried in the aggregate
    144142                        // xxx - this is a memory leak
    145                         UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member()->clone(), memberExpr->get_aggregate()->acceptMutator( *this ) );
     143                        UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member->clone(), memberExpr->aggregate->acceptMutator( *visitor ) );
    146144                        newMemberExpr->location = memberExpr->location;
    147145                        return newMemberExpr;
  • src/tests/Makefile.am

    r2b72090 rbee7f04  
    7777        ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} -o ${@}
    7878
    79 dtor-early-exit-ERR1: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
    80         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    81 
    82 dtor-early-exit-ERR2: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
    83         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@}
    84 
    8579declarationSpecifier: declarationSpecifier.c @CFA_BINDIR@/@CFA_NAME@
    8680        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
     
    110104        ${CC} ${AM_CFLAGS} ${CFLAGS} -lgmp ${<} -o ${@}
    111105
    112 memberCtors-ERR1: memberCtors.c @CFA_BINDIR@/@CFA_NAME@
    113         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    114 
    115 ctor-autogen-ERR1: ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@
    116         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    117 
    118106completeTypeError : completeTypeError.c @CFA_BINDIR@/@CFA_NAME@
    119107        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     
    124112alloc-ERROR: alloc.c @CFA_BINDIR@/@CFA_NAME@
    125113        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     114
     115# Constructor/destructor tests
     116raii/dtor-early-exit-ERR1: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
     117        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     118
     119raii/dtor-early-exit-ERR2: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
     120        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@}
     121
     122raii/memberCtors-ERR1: raii/memberCtors.c @CFA_BINDIR@/@CFA_NAME@
     123        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     124
     125raii/ctor-autogen-ERR1: raii/ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@
     126        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     127
  • src/tests/Makefile.in

    r2b72090 rbee7f04  
    827827        ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} -o ${@}
    828828
    829 dtor-early-exit-ERR1: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
    830         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    831 
    832 dtor-early-exit-ERR2: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
    833         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@}
    834 
    835829declarationSpecifier: declarationSpecifier.c @CFA_BINDIR@/@CFA_NAME@
    836830        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
     
    860854        ${CC} ${AM_CFLAGS} ${CFLAGS} -lgmp ${<} -o ${@}
    861855
    862 memberCtors-ERR1: memberCtors.c @CFA_BINDIR@/@CFA_NAME@
    863         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    864 
    865 ctor-autogen-ERR1: ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@
    866         ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    867 
    868856completeTypeError : completeTypeError.c @CFA_BINDIR@/@CFA_NAME@
    869857        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     
    873861
    874862alloc-ERROR: alloc.c @CFA_BINDIR@/@CFA_NAME@
     863        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     864
     865# Constructor/destructor tests
     866raii/dtor-early-exit-ERR1: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
     867        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     868
     869raii/dtor-early-exit-ERR2: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@
     870        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@}
     871
     872raii/memberCtors-ERR1: raii/memberCtors.c @CFA_BINDIR@/@CFA_NAME@
     873        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     874
     875raii/ctor-autogen-ERR1: raii/ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@
    875876        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    876877
Note: See TracChangeset for help on using the changeset viewer.