Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rbf32bb8 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"
     
    6364        }
    6465
    65         Cost sumCost( const AltList &in ) {
    66                 Cost total;
    67                 for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
    68                         total += i->cost;
    69                 }
    70                 return total;
    71         }
    72 
    7366        namespace {
    7467                void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
     
    8376                                out.push_back( i->expr->clone() );
    8477                        }
     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;
    8586                }
    8687
     
    100101                                PruneStruct current( candidate );
    101102                                std::string mangleName;
    102                                 {
    103                                         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();
    104105                                        candidate->env.apply( newType );
    105                                         mangleName = SymTab::Mangler::mangle( newType );
     106                                        mangleName += SymTab::Mangler::mangle( newType );
    106107                                        delete newType;
    107108                                }
     
    132133                                if ( ! target->second.isAmbiguous ) {
    133134                                        Alternative &alt = *target->second.candidate;
    134                                         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                                        }
    135138                                        *out++ = alt;
    136139                                }
    137140                        }
     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                        }
    138169                }
    139170
    140171                void renameTypes( Expression *expr ) {
    141                         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                        }
    142175                }
    143176        }
     
    171204                for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    172205                        if ( adjust ) {
    173                                 adjustExprType( i->expr->get_result(), i->env, indexer );
     206                                adjustExprTypeList( i->expr->get_results().begin(), i->expr->get_results().end(), i->env, indexer );
    174207                        }
    175208                }
     
    208241
    209242        template< typename StructOrUnionType >
    210         void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    211 
    212                 // by this point, member must be a name expr
    213                 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
    214                 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 ) {
    215244                std::list< Declaration* > members;
    216245                aggInst->lookup( name, members );
     
    225254        }
    226255
    227         void AlternativeFinder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    228                 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    229                         // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    230                         // xxx - this should be improved by memoizing the value of constant exprs
    231                         // during parsing and reusing that information here.
    232                         std::stringstream ss( constantExpr->get_constant()->get_value() );
    233                         int val;
    234                         std::string tmp;
    235                         if ( ss >> val && ! (ss >> tmp) ) {
    236                                 if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
    237                                         alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    238                                 } // if
    239                         } // if
    240                 } // if
    241         }
    242 
    243256        void AlternativeFinder::visit( ApplicationExpr *applicationExpr ) {
    244257                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
     
    246259
    247260        Cost computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    248                 ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( alt.expr );
    249                 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    250                 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 );
    251267
    252268                Cost convCost( 0, 0, 0 );
     
    254270                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    255271                std::list< Expression* >& actuals = appExpr->get_args();
    256 
    257                 std::list< Type * > formalTypes;
    258                 std::list< Type * >::iterator formalType = formalTypes.end();
    259 
    260272                for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    261 
    262273                        PRINT(
    263274                                std::cerr << "actual expression:" << std::endl;
    264275                                (*actualExpr)->print( std::cerr, 8 );
    265276                                std::cerr << "--- results are" << std::endl;
    266                                 (*actualExpr)->get_result()->print( std::cerr, 8 );
     277                                printAll( (*actualExpr)->get_results(), std::cerr, 8 );
    267278                        )
    268279                        std::list< DeclarationWithType* >::iterator startFormal = formal;
    269280                        Cost actualCost;
    270                         std::list< Type * > flatActualTypes;
    271                         flatten( (*actualExpr)->get_result(), back_inserter( flatActualTypes ) );
    272                         for ( std::list< Type* >::iterator actualType = flatActualTypes.begin(); actualType != flatActualTypes.end(); ++actualType ) {
    273 
    274 
    275                                 // tuple handling code
    276                                 if ( formalType == formalTypes.end() ) {
    277                                         // the type of the formal parameter may be a tuple type. To make this easier to work with,
    278                                         // flatten the tuple type and traverse the resulting list of types, incrementing the formal
    279                                         // iterator once its types have been extracted. Once a particular formal parameter's type has
    280                                         // been exhausted load the next formal parameter's type.
    281                                         if ( formal == formals.end() ) {
    282                                                 if ( function->get_isVarArgs() ) {
    283                                                         convCost += Cost( 1, 0, 0 );
    284                                                         break;
    285                                                 } else {
    286                                                         return Cost::infinity;
    287                                                 }
     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;
    288288                                        }
    289                                         formalTypes.clear();
    290                                         flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
    291                                         formalType = formalTypes.begin();
    292                                         ++formal;
    293289                                }
    294 
    295290                                PRINT(
    296291                                        std::cerr << std::endl << "converting ";
    297                                         (*actualType)->print( std::cerr, 8 );
     292                                        (*actual)->print( std::cerr, 8 );
    298293                                        std::cerr << std::endl << " to ";
    299294                                        (*formal)->get_type()->print( std::cerr, 8 );
    300295                                )
    301                                 Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
     296                                Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
    302297                                PRINT(
    303298                                        std::cerr << std::endl << "cost is" << newCost << std::endl;
     
    310305                                actualCost += newCost;
    311306
    312                                 convCost += Cost( 0, polyCost( *formalType, alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
    313 
    314                                 formalType++;
     307                                convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer ), 0 );
     308
     309                                formal++;
    315310                        }
    316311                        if ( actualCost != Cost( 0, 0, 0 ) ) {
     
    361356        /// Adds type variables to the open variable set and marks their assertions
    362357        void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
    363                 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 ) {
    364359                        unifiableVars[ (*tyvar)->get_name() ] = (*tyvar)->get_kind();
    365360                        for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
     
    370365        }
    371366
    372         /// instantiate a single argument by matching actuals from [actualIt, actualEnd) against formalType,
    373         /// producing expression(s) in out and their total cost in cost.
    374         template< typename AltIterator, typename OutputIterator >
    375         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 ) {
    376                 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) {
    377                         // formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType
    378                         TupleExpr * tupleExpr = new TupleExpr();
    379                         for ( Type * type : *tupleType ) {
    380                                 if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( tupleExpr->get_exprs() ) ) ) {
    381                                         delete tupleExpr;
    382                                         return false;
    383                                 }
    384                         }
    385                         tupleExpr->set_result( Tuples::makeTupleType( tupleExpr->get_exprs() ) );
    386                         *out++ = tupleExpr;
    387                 } else if ( actualIt != actualEnd ) {
    388                         // both actualType and formalType are atomic (non-tuple) types - if they unify
    389                         // then accept actual as an argument, otherwise return false (fail to instantiate argument)
    390                         Expression * actual = actualIt->expr;
    391                         Type * actualType = actual->get_result();
    392                         PRINT(
    393                                 std::cerr << "formal type is ";
    394                                 formalType->print( std::cerr );
    395                                 std::cerr << std::endl << "actual type is ";
    396                                 actualType->print( std::cerr );
    397                                 std::cerr << std::endl;
    398                         )
    399                         if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    400                                 return false;
    401                         }
    402                         // move the expression from the alternative to the output iterator
    403                         *out++ = actual;
    404                         actualIt->expr = nullptr;
    405                         cost += actualIt->cost;
    406                         ++actualIt;
    407                 } else {
    408                         // End of actuals - Handle default values
    409                         if ( SingleInit *si = dynamic_cast<SingleInit *>( defaultValue )) {
    410                                 // so far, only constant expressions are accepted as default values
    411                                 if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) ) {
    412                                         if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) ) {
    413                                                 if ( unify( formalType, cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    414                                                         // xxx - Don't know if this is right
    415                                                         *out++ = cnstexpr->clone();
    416                                                         return true;
    417                                                 } // if
    418                                         } // if
    419                                 } // if
    420                         } // if
    421                         return false;
    422                 } // if
    423                 return true;
    424         }
    425 
    426         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 ) {
    427368                simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
    428369                // make sure we don't widen any existing bindings
     
    432373                resultEnv.extractOpenVars( openVars );
    433374
    434                 // flatten actuals so that each actual has an atomic (non-tuple) type
    435                 AltList exploded;
    436                 Tuples::explode( actuals, back_inserter( exploded ) );
    437 
    438                 AltList::iterator actualExpr = exploded.begin();
    439                 AltList::iterator actualEnd = exploded.end();
    440                 for ( DeclarationWithType * formal : formals ) {
    441                         // match flattened actuals with formal parameters - actuals will be grouped to match
    442                         // with formals as appropriate
    443                         Cost cost;
    444                         std::list< Expression * > newExprs;
    445                         ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
    446                         if ( ! instantiateArgument( obj->get_type(), obj->get_init(), actualExpr, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( newExprs ) ) ) {
    447                                 deleteAll( newExprs );
    448                                 return false;
    449                         }
    450                         // success - produce argument as a new alternative
    451                         assert( newExprs.size() == 1 );
    452                         out.push_back( Alternative( newExprs.front(), resultEnv, cost ) );
    453                 }
    454                 if ( actualExpr != actualEnd ) {
    455                         // there are still actuals remaining, but we've run out of formal parameters to match against
    456                         // this is okay only if the function is variadic
    457                         if ( ! isVarArgs ) {
    458                                 return false;
    459                         }
    460                         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;
    461416                }
    462417                return true;
     
    545500                                //if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
    546501                                Expression *varExpr = new VariableExpr( candDecl );
    547                                 delete varExpr->get_result();
    548                                 varExpr->set_result( adjType->clone() );
     502                                deleteAll( varExpr->get_results() );
     503                                varExpr->get_results().clear();
     504                                varExpr->get_results().push_front( adjType->clone() );
    549505                                PRINT(
    550506                                        std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
     
    589545
    590546        template< typename OutputIterator >
    591         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 ) {
    592548                OpenVarSet openVars;
    593549                AssertionSet resultNeed, resultHave;
    594550                TypeEnvironment resultEnv;
    595551                makeUnifiableVars( funcType, openVars, resultNeed );
    596                 AltList instantiatedActuals; // filled by instantiate function
    597                 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 ) ) {
    598553                        ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    599                         Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) );
    600                         makeExprList( instantiatedActuals, appExpr->get_args() );
     554                        Alternative newAlt( appExpr, resultEnv, sumCost( actualAlt ) );
     555                        makeExprList( actualAlt, appExpr->get_args() );
    601556                        PRINT(
    602557                                std::cerr << "need assertions:" << std::endl;
     
    619574                                PointerType pt( Type::Qualifiers(), v.clone() );
    620575                                UntypedExpr *vexpr = untypedExpr->clone();
    621                                 vexpr->set_result( pt.clone() );
     576                                vexpr->get_results().push_front( pt.clone() );
    622577                                alternatives.push_back( Alternative( vexpr, env, Cost()) );
    623578                                return;
     
    632587                combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
    633588
    634                 // take care of possible tuple assignments
    635                 // if not tuple assignment, assignment is taken care of as a normal function call
    636                 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 ...
    637594
    638595                AltList candidates;
     
    647604                                // check if the type is pointer to function
    648605                                PointerType *pointer;
    649                                 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() ) ) ) {
    650607                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    651608                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     
    683640                                                // check if the type is pointer to function
    684641                                                PointerType *pointer;
    685                                                 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() ) ) ) {
    686644                                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    687645                                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     
    707665
    708666                        PRINT(
    709                                 ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( withFunc->expr );
    710                                 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    711                                 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 );
    712673                                std::cerr << "Case +++++++++++++" << std::endl;
    713674                                std::cerr << "formals are:" << std::endl;
     
    731692
    732693        bool isLvalue( Expression *expr ) {
    733                 // xxx - recurse into tuples?
    734                 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;
    735698        }
    736699
     
    746709
    747710        void AlternativeFinder::visit( CastExpr *castExpr ) {
    748                 Type *& toType = castExpr->get_result();
    749                 toType = resolveTypeof( toType, indexer );
    750                 SymTab::validateType( toType, &indexer );
    751                 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
    752716
    753717                AlternativeFinder finder( indexer, env );
     
    763727                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    764728                        // to.
    765                         int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
     729                        int discardedValues = (*i).expr->get_results().size() - castExpr->get_results().size();
    766730                        if ( discardedValues < 0 ) continue;
    767                         // 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() );
    768733                        // unification run for side-effects
    769                         unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
    770                         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 );
    771740                        if ( thisCost != Cost::infinity ) {
    772741                                // count one safe conversion for each value that is thrown away
     
    791760
    792761                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    793                         if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
    794                                 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    795                         } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
    796                                 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    797                         } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) {
    798                                 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
    799768                        } // if
    800769                } // for
     
    822791                        renameTypes( alternatives.back().expr );
    823792                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( (*i)->get_type() ) ) {
    824                                 NameExpr nameExpr( "" );
    825                                 addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, &nameExpr );
     793                                addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
    826794                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( (*i)->get_type() ) ) {
    827                                 NameExpr nameExpr( "" );
    828                                 addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, &nameExpr );
     795                                addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
    829796                        } // if
    830797                } // for
     
    927894                        alternatives.push_back( Alternative( new AttrExpr( new VariableExpr( funcDecl ), argType->clone() ), env, Cost::zero ) );
    928895                        for ( std::list< DeclarationWithType* >::iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
    929                                 alternatives.back().expr->set_result( (*i)->get_type()->clone() );
     896                                alternatives.back().expr->get_results().push_back( (*i)->get_type()->clone() );
    930897                        } // for
    931898                } // if
     
    950917                                                        finder.find( attrExpr->get_expr() );
    951918                                                        for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    952                                                                 if ( choice->expr->get_result()->size() == 1 ) {
    953                                                                         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 );
    954921                                                                } // fi
    955922                                                        } // for
     
    993960                                        AssertionSet needAssertions, haveAssertions;
    994961                                        Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
    995                                         Type* commonType;
    996                                         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 ) ) {
    997964                                                ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
    998                                                 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
    999974                                                newAlt.expr = newExpr;
    1000975                                                inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     
    1024999                        TupleExpr *newExpr = new TupleExpr;
    10251000                        makeExprList( *i, newExpr->get_exprs() );
    1026                         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
    10271006
    10281007                        TypeEnvironment compositeEnv;
     
    10451024                }
    10461025        }
    1047 
    1048         void AlternativeFinder::visit( TupleIndexExpr *tupleExpr ) {
    1049                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    1050         }
    1051 
    1052         void AlternativeFinder::visit( TupleAssignExpr *tupleAssignExpr ) {
    1053                 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    1054         }
    1055 
    1056         void AlternativeFinder::visit( UniqueExpr *unqExpr ) {
    1057                 AlternativeFinder finder( indexer, env );
    1058                 finder.findWithAdjustment( unqExpr->get_expr() );
    1059                 for ( Alternative & alt : finder.alternatives ) {
    1060                         // xxx - it's possible that this won't always do the right thing, i.e. two UniqueExprs
    1061                         // with the same ID may resolve to different expressions. If this ever happens, it might be necessary
    1062                         // to try to select an alternative here (i.e. error is there is not a unique min-cost expression).
    1063                         // One other thought is to to resolve each ID once and map the IDs to resolved expressions,
    1064                         // but this isn't as simple as it sounds since the alternative is not selected here, meaning it might
    1065                         // require complicated tracking throughout the system.
    1066 
    1067                         // brand the new UniqueExprs with the same id so that they are recognized as the same expression by the expansion pass
    1068                         alternatives.push_back( Alternative( new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ), env, Cost::zero ) );
    1069                 }
    1070         }
    1071 
    10721026} // namespace ResolvExpr
    10731027
Note: See TracChangeset for help on using the changeset viewer.