Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r2fd9f24 r2a6292d  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Oct 05 09:43:00 2018
    13 // Update Count     : 214
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb 17 11:19:40 2018
     13// Update Count     : 213
    1414//
    1515
     16#include <stddef.h>                      // for NULL
    1617#include <cassert>                       // for strict_dynamic_cast, assert
    1718#include <memory>                        // for allocator, allocator_traits<...
    1819#include <tuple>                         // for get
    19 #include <vector>                        // for vector
     20#include <vector>
    2021
    2122#include "Alternative.h"                 // for Alternative, AltList
     
    3031#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    3132#include "Resolver.h"
    32 #include "ResolvMode.h"                  // for ResolvMode
    3333#include "SymTab/Autogen.h"              // for SizeType
    3434#include "SymTab/Indexer.h"              // for Indexer
     
    168168
    169169        namespace {
    170                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
     170                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    171171                        assertf( untyped, "expected a non-null expression." );
    172 
    173                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    174                         static unsigned recursion_level = 0;
    175 
    176                         ++recursion_level;
    177172                        TypeEnvironment env;
    178173                        AlternativeFinder finder( indexer, env );
    179                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    180                         --recursion_level;
     174                        finder.find( untyped, adjust, prune, failFast );
    181175
    182176                        #if 0
     
    191185                        #endif
    192186
    193                         // produce filtered list of alternatives
    194187                        AltList candidates;
    195188                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    199192                        }
    200193
    201                         // produce invalid error if no candidates
    202                         if ( candidates.empty() ) {
     194                        // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
     195                        // choose the lowest cost expression among the candidates
     196                        AltList winners;
     197                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     198                        if ( winners.size() == 0 ) {
    203199                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    204                         }
    205 
    206                         // search for cheapest candidate
    207                         AltList winners;
    208                         bool seen_undeleted = false;
    209                         for ( unsigned i = 0; i < candidates.size(); ++i ) {
    210                                 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
    211 
    212                                 if ( c > 0 ) continue; // skip more expensive than winner
    213 
    214                                 if ( c < 0 ) {
    215                                         // reset on new cheapest
    216                                         seen_undeleted = ! findDeletedExpr( candidates[i].expr );
    217                                         winners.clear();
    218                                 } else /* if ( c == 0 ) */ {
    219                                         if ( findDeletedExpr( candidates[i].expr ) ) {
    220                                                 // skip deleted expression if already seen one equivalent-cost not
    221                                                 if ( seen_undeleted ) continue;
    222                                         } else if ( ! seen_undeleted ) {
    223                                                 // replace list of equivalent-cost deleted expressions with one non-deleted
    224                                                 winners.clear();
    225                                                 seen_undeleted = true;
    226                                         }
    227                                 }
    228 
    229                                 winners.emplace_back( std::move( candidates[i] ) );
    230                         }
    231 
    232                         // promote alternative.cvtCost to .cost
    233                         // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
    234                         for ( Alternative& winner : winners ) {
    235                                 winner.cost = winner.cvtCost;
    236                         }
    237                        
    238                         // produce ambiguous errors, if applicable
    239                         if ( winners.size() != 1 ) {
     200                        } else if ( winners.size() != 1 ) {
    240201                                std::ostringstream stream;
    241202                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    246207                        }
    247208
    248                         // single selected choice
    249                         Alternative& choice = winners.front();
    250 
    251                         // fail on only expression deleted
    252                         if ( ! seen_undeleted ) {
     209                        // there is one unambiguous interpretation - move the expression into the with statement
     210                        Alternative & choice = winners.front();
     211                        if ( findDeletedExpr( choice.expr ) ) {
    253212                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    254213                        }
    255 
    256                         // xxx - check for ambiguous expressions
    257                        
    258                         // output selected choice
    259214                        alt = std::move( choice );
    260215                }
    261216
    262217                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    263                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
     218                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    264219                        if ( ! untyped ) return;
    265220                        Alternative choice;
    266                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
     221                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
    267222                        finishExpr( choice.expr, choice.env, untyped->env );
    268223                        delete untyped;
     
    295250                untyped.arg = expr;
    296251                Alternative choice;
    297                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
     252                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
    298253                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    299254                env = std::move( choice.env );
     
    402357
    403358        void Resolver::previsit( ObjectDecl *objectDecl ) {
    404                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    405                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    406                 // The second analysis changes initContext because of a function type can contain object
    407                 // declarations in the return and parameter types. So each value of initContext is
    408                 // retained, so the type on the first analysis is preserved and used for selecting the RHS.
     359                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
     360                // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes
     361                // initContext because of a function type can contain object declarations in the return and parameter types. So
     362                // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting
     363                // the RHS.
    409364                GuardValue( currentObject );
    410365                currentObject = CurrentObject( objectDecl->get_type() );
     
    442397
    443398        void Resolver::postvisit( FunctionDecl *functionDecl ) {
    444                 // default value expressions have an environment which shouldn't be there and trips up
    445                 // later passes.
    446                 // xxx - it might be necessary to somehow keep the information from this environment, but I
    447                 // can't currently see how it's useful.
     399                // default value expressions have an environment which shouldn't be there and trips up later passes.
     400                // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
     401                // see how it's useful.
    448402                for ( Declaration * d : functionDecl->type->parameters ) {
    449403                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    795749                initExpr->expr = nullptr;
    796750                std::swap( initExpr->env, newExpr->env );
    797                 // InitExpr may have inferParams in the case where the expression specializes a function
    798                 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
    799                 // sufficient.
     751                // InitExpr may have inferParams in the case where the expression specializes a function pointer,
     752                // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
    800753                newExpr->spliceInferParams( initExpr );
    801754                delete initExpr;
    802755
    803                 // get the actual object's type (may not exactly match what comes back from the resolver
    804                 // due to conversions)
     756                // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
    805757                Type * initContext = currentObject.getCurrentType();
    806758
     
    814766                                        if ( isCharType( pt->get_base() ) ) {
    815767                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    816                                                         // strip cast if we're initializing a char[] with a char *,
    817                                                         // e.g.  char x[] = "hello";
     768                                                        // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
    818769                                                        newExpr = ce->get_arg();
    819770                                                        ce->set_arg( nullptr );
     
    837788                // move cursor into brace-enclosed initializer-list
    838789                currentObject.enterListInit();
    839                 // xxx - fix this so that the list isn't copied, iterator should be used to change current
    840                 // element
     790                // xxx - fix this so that the list isn't copied, iterator should be used to change current element
    841791                std::list<Designation *> newDesignations;
    842792                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    843                         // iterate designations and initializers in pairs, moving the cursor to the current
    844                         // designated object and resolving the initializer against that object.
     793                        // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
     794                        // the initializer against that object.
    845795                        Designation * des = std::get<0>(p);
    846796                        Initializer * init = std::get<1>(p);
     
    872822                // fall back on C-style initializer
    873823                delete ctorInit->get_ctor();
    874                 ctorInit->set_ctor( nullptr );
     824                ctorInit->set_ctor( NULL );
    875825                delete ctorInit->get_dtor();
    876                 ctorInit->set_dtor( nullptr );
     826                ctorInit->set_dtor( NULL );
    877827                maybeAccept( ctorInit->get_init(), *visitor );
    878828        }
     
    917867
    918868                // xxx - todo -- what about arrays?
    919                 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     869                // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    920870                //      // can reduce the constructor down to a SingleInit using the
    921871                //      // second argument from the ctor call, since
    922872                //      delete ctorInit->get_ctor();
    923                 //      ctorInit->set_ctor( nullptr );
     873                //      ctorInit->set_ctor( NULL );
    924874
    925875                //      Expression * arg =
Note: See TracChangeset for help on using the changeset viewer.