Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r77971f6 rb6fe7e6  
    3838#include "SynTree/TypeSubstitution.h"
    3939#include "SymTab/Validate.h"
    40 #include "Tuples/Tuples.h"
     40#include "Tuples/TupleAssignment.h"
     41#include "Tuples/NameMatcher.h"
    4142#include "Common/utility.h"
    4243#include "InitTweak/InitTweak.h"
    43 #include "InitTweak/GenInit.h"
    4444#include "ResolveTypeof.h"
    4545
     
    6464        }
    6565
    66         Cost sumCost( const AltList &in ) {
    67                 Cost total;
    68                 for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
    69                         total += i->cost;
    70                 }
    71                 return total;
    72         }
    73 
    7466        namespace {
    7567                void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
     
    8476                                out.push_back( i->expr->clone() );
    8577                        }
     78                }
     79
     80                Cost sumCost( const AltList &in ) {
     81                        Cost total;
     82                        for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
     83                                total += i->cost;
     84                        }
     85                        return total;
    8686                }
    8787
     
    101101                                PruneStruct current( candidate );
    102102                                std::string mangleName;
    103                                 {
    104                                         Type * newType = candidate->expr->get_result()->clone();
     103                                for ( std::list< Type* >::const_iterator retType = candidate->expr->get_results().begin(); retType != candidate->expr->get_results().end(); ++retType ) {
     104                                        Type *newType = (*retType)->clone();
    105105                                        candidate->env.apply( newType );
    106                                         mangleName = SymTab::Mangler::mangle( newType );
     106                                        mangleName += SymTab::Mangler::mangle( newType );
    107107                                        delete newType;
    108108                                }
     
    133133                                if ( ! target->second.isAmbiguous ) {
    134134                                        Alternative &alt = *target->second.candidate;
    135                                         alt.env.applyFree( alt.expr->get_result() );
     135                                        for ( std::list< Type* >::iterator result = alt.expr->get_results().begin(); result != alt.expr->get_results().end(); ++result ) {
     136                                                alt.env.applyFree( *result );
     137                                        }
    136138                                        *out++ = alt;
    137139                                }
    138140                        }
     141
     142                }
     143
     144                template< typename InputIterator, typename OutputIterator >
     145                void findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
     146                        AltList alternatives;
     147
     148                        // select the alternatives that have the minimum parameter cost
     149                        Cost minCost = Cost::infinity;
     150                        for ( AltList::iterator i = begin; i != end; ++i ) {
     151                                if ( i->cost < minCost ) {
     152                                        minCost = i->cost;
     153                                        i->cost = i->cvtCost;
     154                                        alternatives.clear();
     155                                        alternatives.push_back( *i );
     156                                } else if ( i->cost == minCost ) {
     157                                        i->cost = i->cvtCost;
     158                                        alternatives.push_back( *i );
     159                                }
     160                        }
     161                        std::copy( alternatives.begin(), alternatives.end(), out );
     162                }
     163
     164                template< typename InputIterator >
     165                void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
     166                        while ( begin != end ) {
     167                                result.simpleCombine( (*begin++).env );
     168                        }
    139169                }
    140170
    141171                void renameTypes( Expression *expr ) {
    142                         expr->get_result()->accept( global_renamer );
     172                        for ( std::list< Type* >::iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
     173                                (*i)->accept( global_renamer );
     174                        }
    143175                }
    144176        }
     
    172204                for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    173205                        if ( adjust ) {
    174                                 adjustExprType( i->expr->get_result(), i->env, indexer );
     206                                adjustExprTypeList( i->expr->get_results().begin(), i->expr->get_results().end(), i->env, indexer );
    175207                        }
    176208                }
     
    208240        }
    209241
    210         // std::unordered_map< Expression *, UniqueExpr * > ;
    211 
    212242        template< typename StructOrUnionType >
    213         void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    214                 // by this point, member must be a name expr
    215                 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
    216                 const std::string & name = nameExpr->get_name();
     243        void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string &name ) {
    217244                std::list< Declaration* > members;
    218245                aggInst->lookup( name, members );
     
    227254        }
    228255
    229         void AlternativeFinder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    230                 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    231                         // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    232                         // xxx - this should be improved by memoizing the value of constant exprs
    233                         // during parsing and reusing that information here.
    234                         std::stringstream ss( constantExpr->get_constant()->get_value() );
    235                         int val;
    236                         std::string tmp;
    237                         if ( ss >> val && ! (ss >> tmp) ) {
    238                                 if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
    239                                         alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    240                                 } // if
    241                         } // if
    242                 } // if
    243         }
    244 
    245256        void AlternativeFinder::visit( ApplicationExpr *applicationExpr ) {
    246257                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
     
    248259
    249260        Cost computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    250                 ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( alt.expr );
    251                 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    252                 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
     261                ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( alt.expr );
     262                assert( appExpr );
     263                PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
     264                assert( pointer );
     265                FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
     266                assert( function );
    253267
    254268                Cost convCost( 0, 0, 0 );
     
    256270                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    257271                std::list< Expression* >& actuals = appExpr->get_args();
    258 
    259                 std::list< Type * > formalTypes;
    260                 std::list< Type * >::iterator formalType = formalTypes.end();
    261 
    262272                for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    263 
    264273                        PRINT(
    265274                                std::cerr << "actual expression:" << std::endl;
    266275                                (*actualExpr)->print( std::cerr, 8 );
    267276                                std::cerr << "--- results are" << std::endl;
    268                                 (*actualExpr)->get_result()->print( std::cerr, 8 );
     277                                printAll( (*actualExpr)->get_results(), std::cerr, 8 );
    269278                        )
    270279                        std::list< DeclarationWithType* >::iterator startFormal = formal;
    271280                        Cost actualCost;
    272                         std::list< Type * > flatActualTypes;
    273                         flatten( (*actualExpr)->get_result(), back_inserter( flatActualTypes ) );
    274                         for ( std::list< Type* >::iterator actualType = flatActualTypes.begin(); actualType != flatActualTypes.end(); ++actualType ) {
    275 
    276 
    277                                 // tuple handling code
    278                                 if ( formalType == formalTypes.end() ) {
    279                                         // the type of the formal parameter may be a tuple type. To make this easier to work with,
    280                                         // flatten the tuple type and traverse the resulting list of types, incrementing the formal
    281                                         // iterator once its types have been extracted. Once a particular formal parameter's type has
    282                                         // been exhausted load the next formal parameter's type.
    283                                         if ( formal == formals.end() ) {
    284                                                 if ( function->get_isVarArgs() ) {
    285                                                         convCost += Cost( 1, 0, 0 );
    286                                                         break;
    287                                                 } else {
    288                                                         return Cost::infinity;
    289                                                 }
     281                        for ( std::list< Type* >::iterator actual = (*actualExpr)->get_results().begin(); actual != (*actualExpr)->get_results().end(); ++actual ) {
     282                                if ( formal == formals.end() ) {
     283                                        if ( function->get_isVarArgs() ) {
     284                                                convCost += Cost( 1, 0, 0 );
     285                                                break;
     286                                        } else {
     287                                                return Cost::infinity;
    290288                                        }
    291                                         formalTypes.clear();
    292                                         flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
    293                                         formalType = formalTypes.begin();
    294                                         ++formal;
    295289                                }
    296 
    297290                                PRINT(
    298291                                        std::cerr << std::endl << "converting ";
    299                                         (*actualType)->print( std::cerr, 8 );
     292                                        (*actual)->print( std::cerr, 8 );
    300293                                        std::cerr << std::endl << " to ";
    301294                                        (*formal)->get_type()->print( std::cerr, 8 );
    302295                                )
    303                                 Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
     296                                Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
    304297                                PRINT(
    305298                                        std::cerr << std::endl << "cost is" << newCost << std::endl;
     
    312305                                actualCost += newCost;
    313306
    314                                 convCost += Cost( 0, polyCost( *formalType, alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
    315 
    316                                 formalType++;
     307                                convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer ), 0 );
     308
     309                                formal++;
    317310                        }
    318311                        if ( actualCost != Cost( 0, 0, 0 ) ) {
     
    363356        /// Adds type variables to the open variable set and marks their assertions
    364357        void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
    365                 for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
     358                for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    366359                        unifiableVars[ (*tyvar)->get_name() ] = (*tyvar)->get_kind();
    367360                        for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
     
    372365        }
    373366
    374         /// instantiate a single argument by matching actuals from [actualIt, actualEnd) against formalType,
    375         /// producing expression(s) in out and their total cost in cost.
    376         template< typename AltIterator, typename OutputIterator >
    377         bool instantiateArgument( Type * formalType, Initializer * defaultValue, AltIterator & actualIt, AltIterator actualEnd, OpenVarSet & openVars, TypeEnvironment & resultEnv, AssertionSet & resultNeed, AssertionSet & resultHave, const SymTab::Indexer & indexer, Cost & cost, OutputIterator out ) {
    378                 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) {
    379                         // formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType
    380                         TupleExpr * tupleExpr = new TupleExpr();
    381                         for ( Type * type : *tupleType ) {
    382                                 if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( tupleExpr->get_exprs() ) ) ) {
    383                                         delete tupleExpr;
    384                                         return false;
    385                                 }
    386                         }
    387                         tupleExpr->set_result( Tuples::makeTupleType( tupleExpr->get_exprs() ) );
    388                         *out++ = tupleExpr;
    389                 } else if ( actualIt != actualEnd ) {
    390                         // both actualType and formalType are atomic (non-tuple) types - if they unify
    391                         // then accept actual as an argument, otherwise return false (fail to instantiate argument)
    392                         Expression * actual = actualIt->expr;
    393                         Type * actualType = actual->get_result();
    394                         PRINT(
    395                                 std::cerr << "formal type is ";
    396                                 formalType->print( std::cerr );
    397                                 std::cerr << std::endl << "actual type is ";
    398                                 actualType->print( std::cerr );
    399                                 std::cerr << std::endl;
    400                         )
    401                         if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    402                                 return false;
    403                         }
    404                         // move the expression from the alternative to the output iterator
    405                         *out++ = actual;
    406                         actualIt->expr = nullptr;
    407                         cost += actualIt->cost;
    408                         ++actualIt;
    409                 } else {
    410                         // End of actuals - Handle default values
    411                         if ( SingleInit *si = dynamic_cast<SingleInit *>( defaultValue )) {
    412                                 // so far, only constant expressions are accepted as default values
    413                                 if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) ) {
    414                                         if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) ) {
    415                                                 if ( unify( formalType, cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    416                                                         // xxx - Don't know if this is right
    417                                                         *out++ = cnstexpr->clone();
    418                                                         return true;
    419                                                 } // if
    420                                         } // if
    421                                 } // if
    422                         } // if
    423                         return false;
    424                 } // if
    425                 return true;
    426         }
    427 
    428         bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ) {
     367        bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave ) {
    429368                simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
    430369                // make sure we don't widen any existing bindings
     
    434373                resultEnv.extractOpenVars( openVars );
    435374
    436                 // flatten actuals so that each actual has an atomic (non-tuple) type
    437                 AltList exploded;
    438                 Tuples::explode( actuals, indexer, back_inserter( exploded ) );
    439 
    440                 AltList::iterator actualExpr = exploded.begin();
    441                 AltList::iterator actualEnd = exploded.end();
    442                 for ( DeclarationWithType * formal : formals ) {
    443                         // match flattened actuals with formal parameters - actuals will be grouped to match
    444                         // with formals as appropriate
    445                         Cost cost;
    446                         std::list< Expression * > newExprs;
    447                         ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
    448                         if ( ! instantiateArgument( obj->get_type(), obj->get_init(), actualExpr, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( newExprs ) ) ) {
    449                                 deleteAll( newExprs );
    450                                 return false;
    451                         }
    452                         // success - produce argument as a new alternative
    453                         assert( newExprs.size() == 1 );
    454                         out.push_back( Alternative( newExprs.front(), resultEnv, cost ) );
    455                 }
    456                 if ( actualExpr != actualEnd ) {
    457                         // there are still actuals remaining, but we've run out of formal parameters to match against
    458                         // this is okay only if the function is variadic
    459                         if ( ! isVarArgs ) {
    460                                 return false;
    461                         }
    462                         out.splice( out.end(), exploded, actualExpr, actualEnd );
     375                /*
     376                  Tuples::NameMatcher matcher( formals );
     377                  try {
     378                  matcher.match( actuals );
     379                  } catch ( Tuples::NoMatch &e ) {
     380                  std::cerr << "Alternative doesn't match: " << e.message << std::endl;
     381                  }
     382                */
     383                std::list< DeclarationWithType* >::iterator formal = formals.begin();
     384                for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
     385                        for ( std::list< Type* >::iterator actual = actualExpr->expr->get_results().begin(); actual != actualExpr->expr->get_results().end(); ++actual ) {
     386                                if ( formal == formals.end() ) {
     387                                        return isVarArgs;
     388                                }
     389                                PRINT(
     390                                        std::cerr << "formal type is ";
     391                                        (*formal)->get_type()->print( std::cerr );
     392                                        std::cerr << std::endl << "actual type is ";
     393                                        (*actual)->print( std::cerr );
     394                                        std::cerr << std::endl;
     395                                )
     396                                if ( ! unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     397                                        return false;
     398                                }
     399                                formal++;
     400                        }
     401                }
     402                // Handling of default values
     403                while ( formal != formals.end() ) {
     404                        if ( ObjectDecl *od = dynamic_cast<ObjectDecl *>( *formal ) )
     405                                if ( SingleInit *si = dynamic_cast<SingleInit *>( od->get_init() ))
     406                                        // so far, only constant expressions are accepted as default values
     407                                        if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) )
     408                                                if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) )
     409                                                        if ( unify( (*formal)->get_type(), cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     410                                                                // XXX Don't know if this is right
     411                                                                actuals.push_back( Alternative( cnstexpr->clone(), env, Cost::zero ) );
     412                                                                formal++;
     413                                                                if ( formal == formals.end()) break;
     414                                                        }
     415                        return false;
    463416                }
    464417                return true;
     
    547500                                //if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
    548501                                Expression *varExpr = new VariableExpr( candDecl );
    549                                 delete varExpr->get_result();
    550                                 varExpr->set_result( adjType->clone() );
     502                                deleteAll( varExpr->get_results() );
     503                                varExpr->get_results().clear();
     504                                varExpr->get_results().push_front( adjType->clone() );
    551505                                PRINT(
    552506                                        std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
     
    591545
    592546        template< typename OutputIterator >
    593         void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ) {
     547        void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out ) {
    594548                OpenVarSet openVars;
    595549                AssertionSet resultNeed, resultHave;
    596550                TypeEnvironment resultEnv;
    597551                makeUnifiableVars( funcType, openVars, resultNeed );
    598                 AltList instantiatedActuals; // filled by instantiate function
    599                 if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) {
     552                if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave ) ) {
    600553                        ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    601                         Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) );
    602                         makeExprList( instantiatedActuals, appExpr->get_args() );
     554                        Alternative newAlt( appExpr, resultEnv, sumCost( actualAlt ) );
     555                        makeExprList( actualAlt, appExpr->get_args() );
    603556                        PRINT(
    604557                                std::cerr << "need assertions:" << std::endl;
     
    621574                                PointerType pt( Type::Qualifiers(), v.clone() );
    622575                                UntypedExpr *vexpr = untypedExpr->clone();
    623                                 vexpr->set_result( pt.clone() );
     576                                vexpr->get_results().push_front( pt.clone() );
    624577                                alternatives.push_back( Alternative( vexpr, env, Cost()) );
    625578                                return;
     
    634587                combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
    635588
    636                 // take care of possible tuple assignments
    637                 // if not tuple assignment, assignment is taken care of as a normal function call
    638                 Tuples::handleTupleAssignment( *this, untypedExpr, possibilities );
     589                Tuples::TupleAssignSpotter tassign( this );
     590                if ( tassign.isTupleAssignment( untypedExpr, possibilities ) ) {
     591                        // take care of possible tuple assignments, or discard expression
     592                        return;
     593                } // else ...
    639594
    640595                AltList candidates;
     
    649604                                // check if the type is pointer to function
    650605                                PointerType *pointer;
    651                                 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) {
     606                                if ( func->expr->get_results().size() == 1 && ( pointer = dynamic_cast< PointerType* >( func->expr->get_results().front() ) ) ) {
    652607                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    653608                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     
    685640                                                // check if the type is pointer to function
    686641                                                PointerType *pointer;
    687                                                 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) {
     642                                                if ( funcOp->expr->get_results().size() == 1
     643                                                        && ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_results().front() ) ) ) {
    688644                                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    689645                                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     
    709665
    710666                        PRINT(
    711                                 ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( withFunc->expr );
    712                                 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    713                                 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
     667                                ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( withFunc->expr );
     668                                assert( appExpr );
     669                                PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
     670                                assert( pointer );
     671                                FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
     672                                assert( function );
    714673                                std::cerr << "Case +++++++++++++" << std::endl;
    715674                                std::cerr << "formals are:" << std::endl;
     
    733692
    734693        bool isLvalue( Expression *expr ) {
    735                 // xxx - recurse into tuples?
    736                 return expr->has_result() && expr->get_result()->get_isLvalue();
     694                for ( std::list< Type* >::const_iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
     695                        if ( !(*i)->get_isLvalue() ) return false;
     696                } // for
     697                return true;
    737698        }
    738699
     
    748709
    749710        void AlternativeFinder::visit( CastExpr *castExpr ) {
    750                 Type *& toType = castExpr->get_result();
    751                 toType = resolveTypeof( toType, indexer );
    752                 SymTab::validateType( toType, &indexer );
    753                 adjustExprType( toType, env, indexer );
     711                for ( std::list< Type* >::iterator i = castExpr->get_results().begin(); i != castExpr->get_results().end(); ++i ) {
     712                        *i = resolveTypeof( *i, indexer );
     713                        SymTab::validateType( *i, &indexer );
     714                        adjustExprType( *i, env, indexer );
     715                } // for
    754716
    755717                AlternativeFinder finder( indexer, env );
     
    765727                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    766728                        // to.
    767                         int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
     729                        int discardedValues = (*i).expr->get_results().size() - castExpr->get_results().size();
    768730                        if ( discardedValues < 0 ) continue;
    769                         // xxx - may need to go into tuple types and extract relavent types and use unifyList
     731                        std::list< Type* >::iterator candidate_end = (*i).expr->get_results().begin();
     732                        std::advance( candidate_end, castExpr->get_results().size() );
    770733                        // unification run for side-effects
    771                         unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
    772                         Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );
     734                        unifyList( castExpr->get_results().begin(), castExpr->get_results().end(),
     735                                           (*i).expr->get_results().begin(), candidate_end,
     736                                   i->env, needAssertions, haveAssertions, openVars, indexer );
     737                        Cost thisCost = castCostList( (*i).expr->get_results().begin(), candidate_end,
     738                                                                                  castExpr->get_results().begin(), castExpr->get_results().end(),
     739                                                                                  indexer, i->env );
    773740                        if ( thisCost != Cost::infinity ) {
    774741                                // count one safe conversion for each value that is thrown away
     
    793760
    794761                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    795                         if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
    796                                 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    797                         } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
    798                                 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    799                         } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) {
    800                                 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     762                        if ( agg->expr->get_results().size() == 1 ) {
     763                                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_results().front() ) ) {
     764                                        addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     765                                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_results().front() ) ) {
     766                                        addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     767                                } // if
    801768                        } // if
    802769                } // for
     
    824791                        renameTypes( alternatives.back().expr );
    825792                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( (*i)->get_type() ) ) {
    826                                 NameExpr nameExpr( "" );
    827                                 addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, &nameExpr );
     793                                addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
    828794                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( (*i)->get_type() ) ) {
    829                                 NameExpr nameExpr( "" );
    830                                 addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, &nameExpr );
     795                                addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
    831796                        } // if
    832797                } // for
     
    929894                        alternatives.push_back( Alternative( new AttrExpr( new VariableExpr( funcDecl ), argType->clone() ), env, Cost::zero ) );
    930895                        for ( std::list< DeclarationWithType* >::iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
    931                                 alternatives.back().expr->set_result( (*i)->get_type()->clone() );
     896                                alternatives.back().expr->get_results().push_back( (*i)->get_type()->clone() );
    932897                        } // for
    933898                } // if
     
    952917                                                        finder.find( attrExpr->get_expr() );
    953918                                                        for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    954                                                                 if ( choice->expr->get_result()->size() == 1 ) {
    955                                                                         resolveAttr(*i, function, choice->expr->get_result(), choice->env );
     919                                                                if ( choice->expr->get_results().size() == 1 ) {
     920                                                                        resolveAttr(*i, function, choice->expr->get_results().front(), choice->env );
    956921                                                                } // fi
    957922                                                        } // for
     
    995960                                        AssertionSet needAssertions, haveAssertions;
    996961                                        Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
    997                                         Type* commonType;
    998                                         if ( unify( second->expr->get_result(), third->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     962                                        std::list< Type* > commonTypes;
     963                                        if ( unifyList( second->expr->get_results().begin(), second->expr->get_results().end(), third->expr->get_results().begin(), third->expr->get_results().end(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
    999964                                                ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
    1000                                                 newExpr->set_result( commonType ? commonType : second->expr->get_result()->clone() );
     965                                                std::list< Type* >::const_iterator original = second->expr->get_results().begin();
     966                                                std::list< Type* >::const_iterator commonType = commonTypes.begin();
     967                                                for ( ; original != second->expr->get_results().end() && commonType != commonTypes.end(); ++original, ++commonType ) {
     968                                                        if ( *commonType ) {
     969                                                                newExpr->get_results().push_back( *commonType );
     970                                                        } else {
     971                                                                newExpr->get_results().push_back( (*original)->clone() );
     972                                                        } // if
     973                                                } // for
    1001974                                                newAlt.expr = newExpr;
    1002975                                                inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     
    1026999                        TupleExpr *newExpr = new TupleExpr;
    10271000                        makeExprList( *i, newExpr->get_exprs() );
    1028                         newExpr->set_result( Tuples::makeTupleType( newExpr->get_exprs() ) );
     1001                        for ( std::list< Expression* >::const_iterator resultExpr = newExpr->get_exprs().begin(); resultExpr != newExpr->get_exprs().end(); ++resultExpr ) {
     1002                                for ( std::list< Type* >::const_iterator resultType = (*resultExpr)->get_results().begin(); resultType != (*resultExpr)->get_results().end(); ++resultType ) {
     1003                                        newExpr->get_results().push_back( (*resultType)->clone() );
     1004                                } // for
     1005                        } // for
    10291006
    10301007                        TypeEnvironment compositeEnv;
     
    10471024                }
    10481025        }
    1049 
    1050         void AlternativeFinder::visit( TupleIndexExpr *tupleExpr ) {
    1051                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    1052         }
    1053 
    1054         void AlternativeFinder::visit( TupleAssignExpr *tupleAssignExpr ) {
    1055                 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    1056         }
    1057 
    1058         void AlternativeFinder::visit( UniqueExpr *unqExpr ) {
    1059                 // this won't work because the unqExprs wont share an expression anymore...
    1060                 AlternativeFinder finder( indexer, env );
    1061                 finder.findWithAdjustment( unqExpr->get_expr() );
    1062                 for ( Alternative & alt : finder.alternatives ) {
    1063                         // xxx - attach a resolved ConstructorInit node?
    1064                         // xxx - is it possible to make the objDecl's type const?
    1065                         static UniqueName tempNamer( "_unq_expr_" );
    1066                         ObjectDecl * objDecl = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, alt.expr->get_result()->clone(), nullptr );
    1067                         // must be done on two lines because genCtorInit accesses objDecl's fields
    1068                         objDecl->set_init( InitTweak::genCtorInit( objDecl ) );
    1069 
    1070                         UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1071                         newUnqExpr->set_object( objDecl );
    1072 
    1073                         resolveObject( indexer, objDecl );
    1074 
    1075                         alternatives.push_back( Alternative( newUnqExpr, env, Cost::zero ) );
    1076                 }
    1077         }
    1078 
    10791026} // namespace ResolvExpr
    10801027
Note: See TracChangeset for help on using the changeset viewer.