Ignore:
Timestamp:
Aug 27, 2018, 4:40:34 PM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
b7c89aa
Parents:
f9feab8 (diff), 305581d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into cleanup-dtors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rf9feab8 r90152a4  
    1010// Created On       : Sat May 16 23:52:08 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug 28 13:47:24 2017
    13 // Update Count     : 32
     12// Last Modified On : Sat Feb 17 11:19:39 2018
     13// Update Count     : 33
    1414//
    1515
     
    2525#include <vector>                  // for vector
    2626
     27#include "CompilationState.h"      // for resolvep
    2728#include "Alternative.h"           // for AltList, Alternative
    2829#include "AlternativeFinder.h"
     
    4950#include "typeops.h"               // for adjustExprType, polyCost, castCost
    5051
    51 extern bool resolvep;
    5252#define PRINT( text ) if ( resolvep ) { text }
    5353//#define DEBUG_COST
     
    6060
    6161namespace ResolvExpr {
    62         Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
    63                 CastExpr *castToVoid = new CastExpr( expr );
    64 
    65                 AlternativeFinder finder( indexer, env );
    66                 finder.findWithAdjustment( castToVoid );
    67 
    68                 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    69                 // interpretations, an exception has already been thrown.
    70                 assert( finder.get_alternatives().size() == 1 );
    71                 CastExpr *newExpr = dynamic_cast< CastExpr* >( finder.get_alternatives().front().expr );
    72                 assert( newExpr );
    73                 env = finder.get_alternatives().front().env;
    74                 return newExpr->get_arg()->clone();
    75         }
     62        struct AlternativeFinder::Finder : public WithShortCircuiting {
     63                Finder( AlternativeFinder & altFinder ) : altFinder( altFinder ), indexer( altFinder.indexer ), alternatives( altFinder.alternatives ), env( altFinder.env ), targetType( altFinder.targetType )  {}
     64
     65                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     66
     67                void postvisit( ApplicationExpr * applicationExpr );
     68                void postvisit( UntypedExpr * untypedExpr );
     69                void postvisit( AddressExpr * addressExpr );
     70                void postvisit( LabelAddressExpr * labelExpr );
     71                void postvisit( CastExpr * castExpr );
     72                void postvisit( VirtualCastExpr * castExpr );
     73                void postvisit( UntypedMemberExpr * memberExpr );
     74                void postvisit( MemberExpr * memberExpr );
     75                void postvisit( NameExpr * variableExpr );
     76                void postvisit( VariableExpr * variableExpr );
     77                void postvisit( ConstantExpr * constantExpr );
     78                void postvisit( SizeofExpr * sizeofExpr );
     79                void postvisit( AlignofExpr * alignofExpr );
     80                void postvisit( UntypedOffsetofExpr * offsetofExpr );
     81                void postvisit( OffsetofExpr * offsetofExpr );
     82                void postvisit( OffsetPackExpr * offsetPackExpr );
     83                void postvisit( AttrExpr * attrExpr );
     84                void postvisit( LogicalExpr * logicalExpr );
     85                void postvisit( ConditionalExpr * conditionalExpr );
     86                void postvisit( CommaExpr * commaExpr );
     87                void postvisit( ImplicitCopyCtorExpr  * impCpCtorExpr );
     88                void postvisit( ConstructorExpr  * ctorExpr );
     89                void postvisit( RangeExpr  * rangeExpr );
     90                void postvisit( UntypedTupleExpr * tupleExpr );
     91                void postvisit( TupleExpr * tupleExpr );
     92                void postvisit( TupleIndexExpr * tupleExpr );
     93                void postvisit( TupleAssignExpr * tupleExpr );
     94                void postvisit( UniqueExpr * unqExpr );
     95                void postvisit( StmtExpr * stmtExpr );
     96                void postvisit( UntypedInitExpr * initExpr );
     97                void postvisit( InitExpr * initExpr );
     98                void postvisit( DeletedExpr * delExpr );
     99                void postvisit( GenericExpr * genExpr );
     100
     101                /// Adds alternatives for anonymous members
     102                void addAnonConversions( const Alternative & alt );
     103                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
     104                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
     105                /// Adds alternatives for member expressions where the left side has tuple type
     106                void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
     107                /// Adds alternatives for offsetof expressions, given the base type and name of the member
     108                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     109                /// Takes a final result and checks if its assertions can be satisfied
     110                template<typename OutputIterator>
     111                void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out );
     112                /// Finds matching alternatives for a function, given a set of arguments
     113                template<typename OutputIterator>
     114                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
     115                /// Checks if assertion parameters match for a new alternative
     116                template< typename OutputIterator >
     117                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     118        private:
     119                AlternativeFinder & altFinder;
     120                const SymTab::Indexer &indexer;
     121                AltList & alternatives;
     122                const TypeEnvironment &env;
     123                Type *& targetType;
     124        };
    76125
    77126        Cost sumCost( const AltList &in ) {
     
    127176                                                selected[ mangleName ] = current;
    128177                                        } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
    129                                                 PRINT(
    130                                                         std::cerr << "marking ambiguous" << std::endl;
    131                                                 )
    132                                                 mapPlace->second.isAmbiguous = true;
     178                                                // if one of the candidates contains a deleted identifier, can pick the other, since
     179                                                // deleted expressions should not be ambiguous if there is another option that is at least as good
     180                                                if ( findDeletedExpr( candidate->expr ) ) {
     181                                                        // do nothing
     182                                                        PRINT( std::cerr << "candidate is deleted" << std::endl; )
     183                                                } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
     184                                                        PRINT( std::cerr << "current is deleted" << std::endl; )
     185                                                        selected[ mangleName ] = current;
     186                                                } else {
     187                                                        PRINT(
     188                                                                std::cerr << "marking ambiguous" << std::endl;
     189                                                        )
     190                                                        mapPlace->second.isAmbiguous = true;
     191                                                }
    133192                                        } else {
    134193                                                PRINT(
     
    152211
    153212                void renameTypes( Expression *expr ) {
    154                         expr->get_result()->accept( global_renamer );
     213                        renameTyVars( expr->result );
    155214                }
    156215        } // namespace
    157216
    158         void referenceToRvalueConversion( Expression *& expr ) {
     217        void referenceToRvalueConversion( Expression *& expr, Cost & cost ) {
    159218                if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
    160219                        // cast away reference from expr
    161220                        expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
     221                        cost.incReference();
    162222                }
    163223        }
     
    185245
    186246        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
    187                 expr->accept( *this );
     247                PassVisitor<Finder> finder( *this );
     248                expr->accept( finder );
    188249                if ( failFast && alternatives.empty() ) {
    189250                        PRINT(
    190251                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
    191252                        )
    192                         throw SemanticError( "No reasonable alternatives for expression ", expr );
     253                        SemanticError( expr, "No reasonable alternatives for expression " );
    193254                }
    194255                if ( prune ) {
     
    206267                                stream << "Cannot choose between " << winners.size() << " alternatives for expression\n";
    207268                                expr->print( stream );
    208                                 stream << "Alternatives are:\n";
     269                                stream << " Alternatives are:\n";
    209270                                printAlts( winners, stream, 1 );
    210                                 throw SemanticError( stream.str() );
     271                                SemanticError( expr->location, stream.str() );
    211272                        }
    212273                        alternatives = move(pruned);
     
    244305        }
    245306
    246         void AlternativeFinder::addAnonConversions( const Alternative & alt ) {
     307        void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) {
    247308                // adds anonymous member interpretations whenever an aggregate value type is seen.
    248309                // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
    249310                std::unique_ptr<Expression> aggrExpr( alt.expr->clone() );
    250                 alt.env.apply( aggrExpr->get_result() );
    251                 Type * aggrType = aggrExpr->get_result();
     311                alt.env.apply( aggrExpr->result );
     312                Type * aggrType = aggrExpr->result;
    252313                if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
    253314                        aggrType = aggrType->stripReferences();
     
    255316                }
    256317
    257                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    258                         NameExpr nameExpr( "" );
    259                         addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
    260                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    261                         NameExpr nameExpr( "" );
    262                         addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
     318                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
     319                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     320                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
     321                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    263322                } // if
    264323        }
    265324
    266325        template< typename StructOrUnionType >
    267         void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    268                 // by this point, member must be a name expr
    269                 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
    270                 if ( ! nameExpr ) return;
    271                 const std::string & name = nameExpr->get_name();
     326        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
    272327                std::list< Declaration* > members;
    273328                aggInst->lookup( name, members );
    274329
    275                 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    276                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    277                                 alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
    278                                 renameTypes( alternatives.back().expr );
    279                                 addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     330                for ( Declaration * decl : members ) {
     331                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
     332                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
     333                                // can't construct in place and use vector::back
     334                                Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
     335                                renameTypes( newAlt.expr );
     336                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     337                                alternatives.push_back( std::move(newAlt) );
    280338                        } else {
    281339                                assert( false );
     
    284342        }
    285343
    286         void AlternativeFinder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
     344        void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    287345                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    288346                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    289                         // xxx - this should be improved by memoizing the value of constant exprs
    290                         // during parsing and reusing that information here.
    291                         std::stringstream ss( constantExpr->get_constant()->get_value() );
    292                         int val = 0;
     347                        auto val = constantExpr->intValue();
    293348                        std::string tmp;
    294                         if ( ss >> val && ! (ss >> tmp) ) {
    295                                 if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
    296                                         alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    297                                 } // if
     349                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
     350                                alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    298351                        } // if
    299                 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
    300                         // xxx - temporary hack until 0/1 are int constants
    301                         if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
    302                                 std::stringstream ss( nameExpr->get_name() );
    303                                 int val;
    304                                 ss >> val;
    305                                 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    306                         }
    307352                } // if
    308353        }
    309354
    310         void AlternativeFinder::visit( ApplicationExpr *applicationExpr ) {
     355        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    311356                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    312357        }
     
    386431                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    387432                                        // convert reference-typed expressions to value-typed expressions
    388                                         referenceToRvalueConversion( *actualExpr );
     433                                        referenceToRvalueConversion( *actualExpr, convCost );
    389434                                        continue;
    390435                                } else {
     
    392437                                }
    393438                        }
     439                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
     440                                // default arguments should be free - don't include conversion cost.
     441                                // Unwrap them here because they are not relevant to the rest of the system.
     442                                *actualExpr = def->expr;
     443                                ++formal;
     444                                continue;
     445                        }
    394446                        Type * formalType = (*formal)->get_type();
    395447                        convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
     
    409461        /// Adds type variables to the open variable set and marks their assertions
    410462        void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
    411                 for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
     463                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    412464                        unifiableVars[ (*tyvar)->get_name() ] = TypeDecl::Data{ *tyvar };
    413                         for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
     465                        for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->assertions.begin(); assert != (*tyvar)->assertions.end(); ++assert ) {
    414466                                needAssertions[ *assert ].isUsed = true;
    415467                        }
     
    418470        }
    419471
    420         // /// Map of declaration uniqueIds (intended to be the assertions in an AssertionSet) to their parents and the number of times they've been included
    421         //typedef std::unordered_map< UniqueId, std::unordered_map< UniqueId, unsigned > > AssertionParentSet;
    422 
    423472        static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
    424         //static const unsigned recursionParentLimit = 1;  ///< Limit to the number of times an assertion can recursively use itself
    425473
    426474        void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
     
    433481
    434482        template< typename ForwardIterator, typename OutputIterator >
    435         void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, /*const AssertionParentSet &needParents,*/
    436                                                  int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     483        void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     484                if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end
    437485                if ( begin == end ) {
    438486                        if ( newNeed.empty() ) {
     
    445493                                return;
    446494                        } else if ( level >= recursionLimit ) {
    447                                 throw SemanticError( "Too many recursive assertions" );
     495                                SemanticError( newAlt.expr->location, "Too many recursive assertions" );
    448496                        } else {
    449497                                AssertionSet newerNeed;
     
    452500                                        printAssertionSet( newNeed, std::cerr, 8 );
    453501                                )
    454                                 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, /*needParents,*/ level+1, indexer, out );
     502                                inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
    455503                                return;
    456504                        }
     
    459507                ForwardIterator cur = begin++;
    460508                if ( ! cur->second.isUsed ) {
    461                         inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/ level, indexer, out );
     509                        inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
    462510                        return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
    463511                }
     
    485533                        Type *adjType = candidate->get_type()->clone();
    486534                        adjustExprType( adjType, newEnv, indexer );
    487                         adjType->accept( global_renamer );
     535                        renameTyVars( adjType );
    488536                        PRINT(
    489537                                std::cerr << "unifying ";
     
    512560                                }
    513561
    514                                 //AssertionParentSet newNeedParents( needParents );
    515                                 // skip repeatingly-self-recursive assertion satisfaction
    516                                 // DOESN'T WORK: grandchild nodes conflict with their cousins
    517                                 //if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
    518                                 Expression *varExpr = data.combine();
     562                                Expression *varExpr = data.combine( newerAlt.cvtCost );
    519563                                delete varExpr->get_result();
    520564                                varExpr->set_result( adjType->clone() );
     
    533577                                // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
    534578                                (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
    535                                 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/ level, indexer, out );
     579                                inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
    536580                        } else {
    537581                                delete adjType;
     
    541585
    542586        template< typename OutputIterator >
    543         void AlternativeFinder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
     587        void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
    544588//      PRINT(
    545589//          std::cerr << "inferParameters: assertions needed are" << std::endl;
     
    555599                addToIndexer( have, decls );
    556600                AssertionSet newNeed;
    557                 //AssertionParentSet needParents;
    558601                PRINT(
    559602                        std::cerr << "env is: " << std::endl;
     
    562605                )
    563606
    564                 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out );
     607                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
    565608//      PRINT(
    566609//          std::cerr << "declaration 14 is ";
     
    573616        ConstantExpr* getDefaultValue( Initializer* init ) {
    574617                if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    575                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
    576                                 return dynamic_cast<ConstantExpr*>( ce->get_arg() );
     618                        if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
     619                                return dynamic_cast<ConstantExpr*>( ce->arg );
     620                        } else {
     621                                return dynamic_cast<ConstantExpr*>( si->value );
    577622                        }
    578623                }
     
    596641                ArgPack()
    597642                        : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0),
    598 
    599643                          tupleStart(0), nextExpl(0), explAlt(0) {}
    600644
     
    648692                        const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
    649693                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    650                 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     694                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
    651695                        // formalType is a TupleType - group actuals into a TupleExpr
    652696                        ++nTuples;
    653697                        for ( Type* type : *tupleType ) {
    654698                                // xxx - dropping initializer changes behaviour from previous, but seems correct
     699                                // ^^^ need to handle the case where a tuple has a default argument
    655700                                if ( ! instantiateArgument(
    656701                                                type, nullptr, args, results, genStart, indexer, nTuples ) )
     
    663708                        }
    664709                        return true;
    665                 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) {
     710                } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {
    666711                        // formalType is a ttype, consumes all remaining arguments
    667712                        // xxx - mixing default arguments with variadic??
     
    706751                                                Type* argType;
    707752
    708                                                 if ( nTuples > 0 ) {
    709                                                         // first iteration, push empty tuple expression
     753                                                if ( nTuples > 0 || ! results[i].expr ) {
     754                                                        // first iteration or no expression to clone,
     755                                                        // push empty tuple expression
    710756                                                        newResult.parent = i;
    711757                                                        std::list<Expression*> emptyList;
     
    834880                                                                indexer ) ) {
    835881                                                        results.emplace_back(
    836                                                                 i, cnstExpr, move(env), move(need), move(have),
     882                                                                i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
    837883                                                                move(openVars), nextArg, nTuples );
    838884                                                }
     
    865911                                // consider only first exploded actual
    866912                                Expression* expr = expl.exprs.front().get();
    867                                 Type* actualType = expr->get_result()->clone();
     913                                Type* actualType = expr->result->clone();
    868914
    869915                                PRINT(
     
    892938
    893939        template<typename OutputIterator>
    894         void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
     940        void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
    895941                        const std::vector<ArgPack>& results, OutputIterator out ) {
    896942                ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    897943                // sum cost and accumulate actuals
    898                 std::list<Expression*>& args = appExpr->get_args();
     944                std::list<Expression*>& args = appExpr->args;
    899945                Cost cost = func.cost;
    900946                const ArgPack* pack = &result;
     
    915961
    916962        template<typename OutputIterator>
    917         void AlternativeFinder::makeFunctionAlternatives( const Alternative &func,
     963        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    918964                        FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
    919965                OpenVarSet funcOpenVars;
     
    923969                // add all type variables as open variables now so that those not used in the parameter
    924970                // list are still considered open.
    925                 funcEnv.add( funcType->get_forall() );
    926 
    927                 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) {
     971                funcEnv.add( funcType->forall );
     972
     973                if ( targetType && ! targetType->isVoid() && ! funcType->returnVals.empty() ) {
    928974                        // attempt to narrow based on expected target type
    929                         Type * returnType = funcType->get_returnVals().front()->get_type();
     975                        Type * returnType = funcType->returnVals.front()->get_type();
    930976                        if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
    931977                                        indexer ) ) {
     
    940986                std::size_t genStart = 0;
    941987
    942                 for ( DeclarationWithType* formal : funcType->get_parameters() ) {
     988                for ( DeclarationWithType* formal : funcType->parameters ) {
    943989                        ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
    944990                        if ( ! instantiateArgument(
    945                                         obj->get_type(), obj->get_init(), args, results, genStart, indexer ) )
     991                                        obj->type, obj->init, args, results, genStart, indexer ) )
    946992                                return;
    947993                }
     
    10221068        }
    10231069
    1024         void AlternativeFinder::visit( UntypedExpr *untypedExpr ) {
     1070        void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) {
    10251071                AlternativeFinder funcFinder( indexer, env );
    1026                 funcFinder.findWithAdjustment( untypedExpr->get_function() );
     1072                funcFinder.findWithAdjustment( untypedExpr->function );
    10271073                // if there are no function alternatives, then proceeding is a waste of time.
     1074                // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
    10281075                if ( funcFinder.alternatives.empty() ) return;
    10291076
    10301077                std::vector< AlternativeFinder > argAlternatives;
    1031                 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
     1078                altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
    10321079                        back_inserter( argAlternatives ) );
    10331080
    10341081                // take care of possible tuple assignments
    10351082                // if not tuple assignment, assignment is taken care of as a normal function call
    1036                 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );
     1083                Tuples::handleTupleAssignment( altFinder, untypedExpr, argAlternatives );
    10371084
    10381085                // find function operators
     
    10401087                AlternativeFinder funcOpFinder( indexer, env );
    10411088                // it's ok if there aren't any defined function ops
    1042                 funcOpFinder.maybeFind( opExpr);
     1089                funcOpFinder.maybeFind( opExpr );
    10431090                PRINT(
    10441091                        std::cerr << "known function ops:" << std::endl;
     
    10531100                        argExpansions.emplace_back();
    10541101                        auto& argE = argExpansions.back();
    1055                         argE.reserve( arg.alternatives.size() );
     1102                        // argE.reserve( arg.alternatives.size() );
    10561103
    10571104                        for ( const Alternative& actual : arg ) {
     
    10611108
    10621109                AltList candidates;
    1063                 SemanticError errors;
     1110                SemanticErrorException errors;
    10641111                for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    10651112                        try {
     
    10691116                                )
    10701117                                // check if the type is pointer to function
    1071                                 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    1072                                         if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     1118                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->result->stripReferences() ) ) {
     1119                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->base ) ) {
    10731120                                                Alternative newFunc( *func );
    1074                                                 referenceToRvalueConversion( newFunc.expr );
     1121                                                referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    10751122                                                makeFunctionAlternatives( newFunc, function, argExpansions,
    10761123                                                        std::back_inserter( candidates ) );
    10771124                                        }
    1078                                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
    1079                                         EqvClass eqvClass;
    1080                                         if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    1081                                                 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     1125                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     1126                                        if ( const EqvClass *eqvClass = func->env.lookup( typeInst->name ) ) {
     1127                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass->type ) ) {
    10821128                                                        Alternative newFunc( *func );
    1083                                                         referenceToRvalueConversion( newFunc.expr );
     1129                                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    10841130                                                        makeFunctionAlternatives( newFunc, function, argExpansions,
    10851131                                                                std::back_inserter( candidates ) );
     
    10871133                                        } // if
    10881134                                }
    1089                         } catch ( SemanticError &e ) {
     1135                        } catch ( SemanticErrorException &e ) {
    10901136                                errors.append( e );
    10911137                        }
     
    11071153                                        // check if type is a pointer to function
    11081154                                        if ( PointerType* pointer = dynamic_cast<PointerType*>(
    1109                                                         funcOp->expr->get_result()->stripReferences() ) ) {
     1155                                                        funcOp->expr->result->stripReferences() ) ) {
    11101156                                                if ( FunctionType* function =
    1111                                                                 dynamic_cast<FunctionType*>( pointer->get_base() ) ) {
     1157                                                                dynamic_cast<FunctionType*>( pointer->base ) ) {
    11121158                                                        Alternative newFunc( *funcOp );
    1113                                                         referenceToRvalueConversion( newFunc.expr );
     1159                                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    11141160                                                        makeFunctionAlternatives( newFunc, function, argExpansions,
    11151161                                                                std::back_inserter( candidates ) );
    11161162                                                }
    11171163                                        }
    1118                                 } catch ( SemanticError &e ) {
     1164                                } catch ( SemanticErrorException &e ) {
    11191165                                        errors.append( e );
    11201166                                }
     
    11311177                        PRINT(
    11321178                                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc.expr );
    1133                                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    1134                                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
    1135                                 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl;
     1179                                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
     1180                                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
     1181                                std::cerr << "Case +++++++++++++ " << appExpr->function << std::endl;
    11361182                                std::cerr << "formals are:" << std::endl;
    1137                                 printAll( function->get_parameters(), std::cerr, 8 );
     1183                                printAll( function->parameters, std::cerr, 8 );
    11381184                                std::cerr << "actuals are:" << std::endl;
    1139                                 printAll( appExpr->get_args(), std::cerr, 8 );
     1185                                printAll( appExpr->args, std::cerr, 8 );
    11401186                                std::cerr << "bindings are:" << std::endl;
    11411187                                withFunc.env.print( std::cerr, 8 );
     1188                                std::cerr << "cost is: " << withFunc.cost << std::endl;
    11421189                                std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    11431190                        )
     
    11721219                        // fix this issue in a more robust way.
    11731220                        targetType = nullptr;
    1174                         visit( untypedExpr );
     1221                        postvisit( untypedExpr );
    11751222                }
    11761223        }
     
    11781225        bool isLvalue( Expression *expr ) {
    11791226                // xxx - recurse into tuples?
    1180                 return expr->result && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    1181         }
    1182 
    1183         void AlternativeFinder::visit( AddressExpr *addressExpr ) {
     1227                return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
     1228        }
     1229
     1230        void AlternativeFinder::Finder::postvisit( AddressExpr *addressExpr ) {
    11841231                AlternativeFinder finder( indexer, env );
    11851232                finder.find( addressExpr->get_arg() );
     
    11921239        }
    11931240
    1194         void AlternativeFinder::visit( LabelAddressExpr * expr ) {
     1241        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    11951242                alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
    11961243        }
    11971244
    1198         Expression * restructureCast( Expression * argExpr, Type * toType ) {
     1245        Expression * restructureCast( Expression * argExpr, Type * toType, bool isGenerated ) {
    11991246                if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) {
    12001247                        // Argument expression is a tuple and the target type is not void and not a reference type.
     
    12111258                                // cast each component
    12121259                                TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
    1213                                 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ) ) );
     1260                                componentExprs.push_back( restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    12141261                        }
    12151262                        delete argExpr;
     
    12191266                } else {
    12201267                        // handle normally
    1221                         return new CastExpr( argExpr, toType->clone() );
    1222                 }
    1223         }
    1224 
    1225         void AlternativeFinder::visit( CastExpr *castExpr ) {
     1268                        CastExpr * ret = new CastExpr( argExpr, toType->clone() );
     1269                        ret->isGenerated = isGenerated;
     1270                        return ret;
     1271                }
     1272        }
     1273
     1274        void AlternativeFinder::Finder::postvisit( CastExpr *castExpr ) {
    12261275                Type *& toType = castExpr->get_result();
    12271276                assert( toType );
     
    12321281                AlternativeFinder finder( indexer, env );
    12331282                finder.targetType = toType;
    1234                 finder.findWithAdjustment( castExpr->get_arg() );
     1283                finder.findWithAdjustment( castExpr->arg );
    12351284
    12361285                AltList candidates;
     
    12391288                        OpenVarSet openVars;
    12401289
     1290                        alt.env.extractOpenVars( openVars );
     1291
    12411292                        // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    12421293                        // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    12431294                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    12441295                        // to.
    1245                         int discardedValues = alt.expr->get_result()->size() - castExpr->get_result()->size();
     1296                        int discardedValues = alt.expr->result->size() - castExpr->result->size();
    12461297                        if ( discardedValues < 0 ) continue;
    12471298                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    12481299                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    12491300                        // unification run for side-effects
    1250                         unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions,
     1301                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12511302                                haveAssertions, openVars, indexer );
    1252                         Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer,
     1303                        Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,
    12531304                                alt.env );
    12541305                        PRINT(
     
    12631314                                // count one safe conversion for each value that is thrown away
    12641315                                thisCost.incSafe( discardedValues );
    1265                                 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env,
     1316                                Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
    12661317                                        alt.cost, thisCost );
    12671318                                inferParameters( needAssertions, haveAssertions, newAlt, openVars,
     
    12781329        }
    12791330
    1280         void AlternativeFinder::visit( VirtualCastExpr * castExpr ) {
     1331        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    12811332                assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
    12821333                AlternativeFinder finder( indexer, env );
     
    12901341        }
    12911342
    1292         void AlternativeFinder::visit( UntypedMemberExpr *memberExpr ) {
     1343        namespace {
     1344                /// Gets name from untyped member expression (member must be NameExpr)
     1345                const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
     1346                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
     1347                        assert( nameExpr );
     1348                        return nameExpr->get_name();
     1349                }
     1350        }
     1351
     1352        void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) {
    12931353                AlternativeFinder funcFinder( indexer, env );
    12941354                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    12951355                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    12961356                        // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
    1297                         std::unique_ptr<Expression> aggrExpr( agg->expr->clone() );
    1298                         Type * aggrType = aggrExpr->get_result();
    1299                         if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
    1300                                 aggrType = aggrType->stripReferences();
    1301                                 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
    1302                         }
     1357                        Cost cost = agg->cost;
     1358                        Expression * aggrExpr = agg->expr->clone();
     1359                        referenceToRvalueConversion( aggrExpr, cost );
     1360                        std::unique_ptr<Expression> guard( aggrExpr );
     1361
    13031362                        // find member of the given type
    13041363                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1305                                 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     1364                                addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    13061365                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1307                                 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     1366                                addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    13081367                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1309                                 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     1368                                addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
    13101369                        } // if
    13111370                } // for
    13121371        }
    13131372
    1314         void AlternativeFinder::visit( MemberExpr *memberExpr ) {
     1373        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    13151374                alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    13161375        }
    13171376
    1318         void AlternativeFinder::visit( NameExpr *nameExpr ) {
     1377        void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) {
    13191378                std::list< SymTab::Indexer::IdData > declList;
    1320                 indexer.lookupId( nameExpr->get_name(), declList );
    1321                 PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
     1379                indexer.lookupId( nameExpr->name, declList );
     1380                PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
    13221381                for ( auto & data : declList ) {
    1323                         Expression * newExpr = data.combine();
    1324                         // xxx - add in extra cost for with-statement exprs?
    1325                         alternatives.push_back( Alternative( newExpr, env, Cost::zero ) );
     1382                        Cost cost = Cost::zero;
     1383                        Expression * newExpr = data.combine( cost );
     1384
     1385                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
     1386                        // can't construct in place and use vector::back
     1387                        Alternative newAlt( newExpr, env, Cost::zero, cost );
    13261388                        PRINT(
    13271389                                std::cerr << "decl is ";
     
    13321394                                std::cerr << std::endl;
    13331395                        )
    1334                         renameTypes( alternatives.back().expr );
    1335                         addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
     1396                        renameTypes( newAlt.expr );
     1397                        addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
     1398                        alternatives.push_back( std::move(newAlt) );
    13361399                } // for
    13371400        }
    13381401
    1339         void AlternativeFinder::visit( VariableExpr *variableExpr ) {
     1402        void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) {
    13401403                // not sufficient to clone here, because variable's type may have changed
    13411404                // since the VariableExpr was originally created.
    1342                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->get_var() ), env, Cost::zero ) );
    1343         }
    1344 
    1345         void AlternativeFinder::visit( ConstantExpr *constantExpr ) {
     1405                alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
     1406        }
     1407
     1408        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    13461409                alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    13471410        }
    13481411
    1349         void AlternativeFinder::visit( SizeofExpr *sizeofExpr ) {
     1412        void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) {
    13501413                if ( sizeofExpr->get_isType() ) {
    13511414                        Type * newType = sizeofExpr->get_type()->clone();
     
    13591422                        findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
    13601423                        if ( winners.size() != 1 ) {
    1361                                 throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() );
     1424                                SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
    13621425                        } // if
    13631426                        // return the lowest cost alternative for the argument
    13641427                        Alternative &choice = winners.front();
    1365                         referenceToRvalueConversion( choice.expr );
     1428                        referenceToRvalueConversion( choice.expr, choice.cost );
    13661429                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13671430                } // if
    13681431        }
    13691432
    1370         void AlternativeFinder::visit( AlignofExpr *alignofExpr ) {
     1433        void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) {
    13711434                if ( alignofExpr->get_isType() ) {
    13721435                        Type * newType = alignofExpr->get_type()->clone();
     
    13801443                        findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
    13811444                        if ( winners.size() != 1 ) {
    1382                                 throw SemanticError( "Ambiguous expression in alignof operand: ", alignofExpr->get_expr() );
     1445                                SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " );
    13831446                        } // if
    13841447                        // return the lowest cost alternative for the argument
    13851448                        Alternative &choice = winners.front();
    1386                         referenceToRvalueConversion( choice.expr );
     1449                        referenceToRvalueConversion( choice.expr, choice.cost );
    13871450                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13881451                } // if
     
    13901453
    13911454        template< typename StructOrUnionType >
    1392         void AlternativeFinder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {
     1455        void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {
    13931456                std::list< Declaration* > members;
    13941457                aggInst->lookup( name, members );
     
    14031466        }
    14041467
    1405         void AlternativeFinder::visit( UntypedOffsetofExpr *offsetofExpr ) {
     1468        void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) {
    14061469                AlternativeFinder funcFinder( indexer, env );
    14071470                // xxx - resolveTypeof?
    14081471                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( offsetofExpr->get_type() ) ) {
    1409                         addOffsetof( structInst, offsetofExpr->get_member() );
     1472                        addOffsetof( structInst, offsetofExpr->member );
    14101473                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( offsetofExpr->get_type() ) ) {
    1411                         addOffsetof( unionInst, offsetofExpr->get_member() );
    1412                 }
    1413         }
    1414 
    1415         void AlternativeFinder::visit( OffsetofExpr *offsetofExpr ) {
     1474                        addOffsetof( unionInst, offsetofExpr->member );
     1475                }
     1476        }
     1477
     1478        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    14161479                alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
    14171480        }
    14181481
    1419         void AlternativeFinder::visit( OffsetPackExpr *offsetPackExpr ) {
     1482        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    14201483                alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
    14211484        }
     
    14361499                        AltList & alternatives = finder.get_alternatives();
    14371500                        if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
    1438                                 alternatives.push_back( Alternative( new AttrExpr( data.combine(), argType->clone() ), env, Cost::zero ) );
     1501                                Cost cost = Cost::zero;
     1502                                Expression * newExpr = data.combine( cost );
     1503                                alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
    14391504                                for ( DeclarationWithType * retVal : function->returnVals ) {
    14401505                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    14441509        }
    14451510
    1446         void AlternativeFinder::visit( AttrExpr *attrExpr ) {
     1511        void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) {
    14471512                // assume no 'pointer-to-attribute'
    14481513                NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
     
    14581523                                        if ( function->get_parameters().size() == 1 ) {
    14591524                                                if ( attrExpr->get_isType() ) {
    1460                                                         resolveAttr( data, function, attrExpr->get_type(), env, *this );
     1525                                                        resolveAttr( data, function, attrExpr->get_type(), env, altFinder);
    14611526                                                } else {
    14621527                                                        AlternativeFinder finder( indexer, env );
     
    14641529                                                        for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    14651530                                                                if ( choice->expr->get_result()->size() == 1 ) {
    1466                                                                         resolveAttr(data, function, choice->expr->get_result(), choice->env, *this );
     1531                                                                        resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder );
    14671532                                                                } // fi
    14681533                                                        } // for
     
    14731538                } else {
    14741539                        for ( auto & data : attrList ) {
    1475                                 alternatives.push_back( Alternative( data.combine(), env, Cost::zero ) );
     1540                                Cost cost = Cost::zero;
     1541                                Expression * newExpr = data.combine( cost );
     1542                                alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
    14761543                                renameTypes( alternatives.back().expr );
    14771544                        } // for
     
    14791546        }
    14801547
    1481         void AlternativeFinder::visit( LogicalExpr *logicalExpr ) {
     1548        void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) {
    14821549                AlternativeFinder firstFinder( indexer, env );
    14831550                firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
    1484                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1485                         AlternativeFinder secondFinder( indexer, first->env );
    1486                         secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
    1487                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
    1488                                 LogicalExpr *newExpr = new LogicalExpr( first->expr->clone(), second->expr->clone(), logicalExpr->get_isAnd() );
    1489                                 alternatives.push_back( Alternative( newExpr, second->env, first->cost + second->cost ) );
    1490                         }
    1491                 }
    1492         }
    1493 
    1494         void AlternativeFinder::visit( ConditionalExpr *conditionalExpr ) {
     1551                if ( firstFinder.alternatives.empty() ) return;
     1552                AlternativeFinder secondFinder( indexer, env );
     1553                secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
     1554                if ( secondFinder.alternatives.empty() ) return;
     1555                for ( const Alternative & first : firstFinder.alternatives ) {
     1556                        for ( const Alternative & second : secondFinder.alternatives ) {
     1557                                TypeEnvironment compositeEnv;
     1558                                compositeEnv.simpleCombine( first.env );
     1559                                compositeEnv.simpleCombine( second.env );
     1560
     1561                                LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
     1562                                alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
     1563                        }
     1564                }
     1565        }
     1566
     1567        void AlternativeFinder::Finder::postvisit( ConditionalExpr *conditionalExpr ) {
    14951568                // find alternatives for condition
    14961569                AlternativeFinder firstFinder( indexer, env );
    1497                 firstFinder.findWithAdjustment( conditionalExpr->get_arg1() );
    1498                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1499                         // find alternatives for true expression
    1500                         AlternativeFinder secondFinder( indexer, first->env );
    1501                         secondFinder.findWithAdjustment( conditionalExpr->get_arg2() );
    1502                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
    1503                                 // find alterantives for false expression
    1504                                 AlternativeFinder thirdFinder( indexer, second->env );
    1505                                 thirdFinder.findWithAdjustment( conditionalExpr->get_arg3() );
    1506                                 for ( AltList::const_iterator third = thirdFinder.alternatives.begin(); third != thirdFinder.alternatives.end(); ++third ) {
     1570                firstFinder.findWithAdjustment( conditionalExpr->arg1 );
     1571                if ( firstFinder.alternatives.empty() ) return;
     1572                // find alternatives for true expression
     1573                AlternativeFinder secondFinder( indexer, env );
     1574                secondFinder.findWithAdjustment( conditionalExpr->arg2 );
     1575                if ( secondFinder.alternatives.empty() ) return;
     1576                // find alterantives for false expression
     1577                AlternativeFinder thirdFinder( indexer, env );
     1578                thirdFinder.findWithAdjustment( conditionalExpr->arg3 );
     1579                if ( thirdFinder.alternatives.empty() ) return;
     1580                for ( const Alternative & first : firstFinder.alternatives ) {
     1581                        for ( const Alternative & second : secondFinder.alternatives ) {
     1582                                for ( const Alternative & third : thirdFinder.alternatives ) {
     1583                                        TypeEnvironment compositeEnv;
     1584                                        compositeEnv.simpleCombine( first.env );
     1585                                        compositeEnv.simpleCombine( second.env );
     1586                                        compositeEnv.simpleCombine( third.env );
     1587
    15071588                                        // unify true and false types, then infer parameters to produce new alternatives
    15081589                                        OpenVarSet openVars;
    15091590                                        AssertionSet needAssertions, haveAssertions;
    1510                                         Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
     1591                                        Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    15111592                                        Type* commonType = nullptr;
    1512                                         if ( unify( second->expr->get_result(), third->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1513                                                 ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
    1514                                                 newExpr->set_result( commonType ? commonType : second->expr->get_result()->clone() );
     1593                                        if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1594                                                ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
     1595                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15151596                                                // convert both options to the conditional result type
    15161597                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
     
    15241605        }
    15251606
    1526         void AlternativeFinder::visit( CommaExpr *commaExpr ) {
     1607        void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) {
    15271608                TypeEnvironment newEnv( env );
    15281609                Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv );
    15291610                AlternativeFinder secondFinder( indexer, newEnv );
    15301611                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    1531                 for ( AltList::const_iterator alt = secondFinder.alternatives.begin(); alt != secondFinder.alternatives.end(); ++alt ) {
    1532                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt->expr->clone() ), alt->env, alt->cost ) );
     1612                for ( const Alternative & alt : secondFinder.alternatives ) {
     1613                        alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
    15331614                } // for
    15341615                delete newFirstArg;
    15351616        }
    15361617
    1537         void AlternativeFinder::visit( RangeExpr * rangeExpr ) {
     1618        void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) {
    15381619                // resolve low and high, accept alternatives whose low and high types unify
    15391620                AlternativeFinder firstFinder( indexer, env );
    1540                 firstFinder.findWithAdjustment( rangeExpr->get_low() );
    1541                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1542                         AlternativeFinder secondFinder( indexer, first->env );
    1543                         secondFinder.findWithAdjustment( rangeExpr->get_high() );
    1544                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
     1621                firstFinder.findWithAdjustment( rangeExpr->low );
     1622                if ( firstFinder.alternatives.empty() ) return;
     1623                AlternativeFinder secondFinder( indexer, env );
     1624                secondFinder.findWithAdjustment( rangeExpr->high );
     1625                if ( secondFinder.alternatives.empty() ) return;
     1626                for ( const Alternative & first : firstFinder.alternatives ) {
     1627                        for ( const Alternative & second : secondFinder.alternatives ) {
     1628                                TypeEnvironment compositeEnv;
     1629                                compositeEnv.simpleCombine( first.env );
     1630                                compositeEnv.simpleCombine( second.env );
    15451631                                OpenVarSet openVars;
    15461632                                AssertionSet needAssertions, haveAssertions;
    1547                                 Alternative newAlt( 0, second->env, first->cost + second->cost );
     1633                                Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
    15481634                                Type* commonType = nullptr;
    1549                                 if ( unify( first->expr->get_result(), second->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1550                                         RangeExpr *newExpr = new RangeExpr( first->expr->clone(), second->expr->clone() );
    1551                                         newExpr->set_result( commonType ? commonType : first->expr->get_result()->clone() );
     1635                                if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1636                                        RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
     1637                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    15521638                                        newAlt.expr = newExpr;
    15531639                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     
    15571643        }
    15581644
    1559         void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) {
     1645        void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) {
    15601646                std::vector< AlternativeFinder > subExprAlternatives;
    1561                 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
     1647                altFinder.findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
    15621648                        back_inserter( subExprAlternatives ) );
    15631649                std::vector< AltList > possibilities;
     
    15751661        }
    15761662
    1577         void AlternativeFinder::visit( TupleExpr *tupleExpr ) {
     1663        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    15781664                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15791665        }
    15801666
    1581         void AlternativeFinder::visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     1667        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    15821668                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    15831669        }
    15841670
    1585         void AlternativeFinder::visit( ConstructorExpr * ctorExpr ) {
     1671        void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) {
    15861672                AlternativeFinder finder( indexer, env );
    15871673                // don't prune here, since it's guaranteed all alternatives will have the same type
     
    15931679        }
    15941680
    1595         void AlternativeFinder::visit( TupleIndexExpr *tupleExpr ) {
     1681        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    15961682                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15971683        }
    15981684
    1599         void AlternativeFinder::visit( TupleAssignExpr *tupleAssignExpr ) {
     1685        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    16001686                alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    16011687        }
    16021688
    1603         void AlternativeFinder::visit( UniqueExpr *unqExpr ) {
     1689        void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) {
    16041690                AlternativeFinder finder( indexer, env );
    16051691                finder.findWithAdjustment( unqExpr->get_expr() );
     
    16111697        }
    16121698
    1613         void AlternativeFinder::visit( StmtExpr *stmtExpr ) {
     1699        void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) {
    16141700                StmtExpr * newStmtExpr = stmtExpr->clone();
    16151701                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
     
    16181704        }
    16191705
    1620         void AlternativeFinder::visit( UntypedInitExpr *initExpr ) {
     1706        void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) {
    16211707                // handle each option like a cast
    16221708                AltList candidates;
    1623                 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; )
     1709                PRINT(
     1710                        std::cerr << "untyped init expr: " << initExpr << std::endl;
     1711                )
    16241712                // O(N^2) checks of d-types with e-types
    16251713                for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
     
    16321720                        AlternativeFinder finder( indexer, env );
    16331721                        finder.targetType = toType;
    1634                         finder.findWithAdjustment( initExpr->get_expr() );
     1722                        finder.findWithAdjustment( initExpr->expr );
    16351723                        for ( Alternative & alt : finder.get_alternatives() ) {
    16361724                                TypeEnvironment newEnv( alt.env );
    16371725                                AssertionSet needAssertions, haveAssertions;
    16381726                                OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    1639                                 PRINT( std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl; )
     1727                                PRINT(
     1728                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
     1729                                )
    16401730                                // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    16411731                                // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    16421732                                // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    16431733                                // to.
    1644                                 int discardedValues = alt.expr->get_result()->size() - toType->size();
     1734                                int discardedValues = alt.expr->result->size() - toType->size();
    16451735                                if ( discardedValues < 0 ) continue;
    16461736                                // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    16471737                                // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    16481738                                // unification run for side-effects
    1649                                 unify( toType, alt.expr->get_result(), newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
    1650 
    1651                                 Cost thisCost = castCost( alt.expr->get_result(), toType, indexer, newEnv );
     1739                                unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
     1740
     1741                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
    16521742                                if ( thisCost != Cost::infinity ) {
    16531743                                        // count one safe conversion for each value that is thrown away
    16541744                                        thisCost.incSafe( discardedValues );
    1655                                         Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
     1745                                        Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
    16561746                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
    16571747                                }
     
    16661756                findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
    16671757        }
     1758
     1759        void AlternativeFinder::Finder::postvisit( InitExpr * ) {
     1760                assertf( false, "AlternativeFinder should never see a resolved InitExpr." );
     1761        }
     1762
     1763        void AlternativeFinder::Finder::postvisit( DeletedExpr * ) {
     1764                assertf( false, "AlternativeFinder should never see a DeletedExpr." );
     1765        }
     1766
     1767        void AlternativeFinder::Finder::postvisit( GenericExpr * ) {
     1768                assertf( false, "_Generic is not yet supported." );
     1769        }
    16681770} // namespace ResolvExpr
    16691771
Note: See TracChangeset for help on using the changeset viewer.