Changeset eba74ba for src/ResolvExpr


Ignore:
Timestamp:
May 25, 2018, 2:51:06 PM (6 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
new-env, with_gc
Children:
cdc4d43
Parents:
3ef35bd (diff), 58e822a (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 remote-tracking branch 'origin/master' into with_gc

Location:
src/ResolvExpr
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r3ef35bd reba74ba  
    689689                        const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
    690690                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    691                 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     691                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
    692692                        // formalType is a TupleType - group actuals into a TupleExpr
    693693                        ++nTuples;
    694694                        for ( Type* type : *tupleType ) {
    695695                                // xxx - dropping initializer changes behaviour from previous, but seems correct
     696                                // ^^^ need to handle the case where a tuple has a default argument
    696697                                if ( ! instantiateArgument(
    697698                                                type, nullptr, args, results, genStart, indexer, nTuples ) )
     
    704705                        }
    705706                        return true;
    706                 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) {
     707                } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {
    707708                        // formalType is a ttype, consumes all remaining arguments
    708709                        // xxx - mixing default arguments with variadic??
     
    907908                                // consider only first exploded actual
    908909                                Expression* expr = expl.exprs.front();
    909                                 Type* actualType = expr->get_result()->clone();
     910                                Type* actualType = expr->result->clone();
    910911
    911912                                PRINT(
     
    938939                ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    939940                // sum cost and accumulate actuals
    940                 std::list<Expression*>& args = appExpr->get_args();
     941                std::list<Expression*>& args = appExpr->args;
    941942                Cost cost = func.cost;
    942943                const ArgPack* pack = &result;
     
    965966                // add all type variables as open variables now so that those not used in the parameter
    966967                // list are still considered open.
    967                 funcEnv.add( funcType->get_forall() );
    968 
    969                 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) {
     968                funcEnv.add( funcType->forall );
     969
     970                if ( targetType && ! targetType->isVoid() && ! funcType->returnVals.empty() ) {
    970971                        // attempt to narrow based on expected target type
    971                         Type * returnType = funcType->get_returnVals().front()->get_type();
     972                        Type * returnType = funcType->returnVals.front()->get_type();
    972973                        if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
    973974                                        indexer ) ) {
     
    982983                std::size_t genStart = 0;
    983984
    984                 for ( DeclarationWithType* formal : funcType->get_parameters() ) {
     985                for ( DeclarationWithType* formal : funcType->parameters ) {
    985986                        ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
    986987                        if ( ! instantiateArgument(
    987                                         obj->get_type(), obj->get_init(), args, results, genStart, indexer ) )
     988                                        obj->type, obj->init, args, results, genStart, indexer ) )
    988989                                return;
    989990                }
     
    10661067        void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) {
    10671068                AlternativeFinder funcFinder( indexer, env );
    1068                 funcFinder.findWithAdjustment( untypedExpr->get_function() );
     1069                funcFinder.findWithAdjustment( untypedExpr->function );
    10691070                // if there are no function alternatives, then proceeding is a waste of time.
    10701071                if ( funcFinder.alternatives.empty() ) return;
     
    12751276                AlternativeFinder finder( indexer, env );
    12761277                finder.targetType = toType;
    1277                 finder.findWithAdjustment( castExpr->get_arg() );
     1278                finder.findWithAdjustment( castExpr->arg );
    12781279
    12791280                AltList candidates;
     
    12821283                        OpenVarSet openVars;
    12831284
     1285                        alt.env.extractOpenVars( openVars );
     1286
    12841287                        // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    12851288                        // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    12861289                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    12871290                        // to.
    1288                         int discardedValues = alt.expr->get_result()->size() - castExpr->get_result()->size();
     1291                        int discardedValues = alt.expr->result->size() - castExpr->result->size();
    12891292                        if ( discardedValues < 0 ) continue;
    12901293                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    12911294                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    12921295                        // unification run for side-effects
    1293                         unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions,
     1296                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12941297                                haveAssertions, openVars, indexer );
    1295                         Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer,
     1298                        Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,
    12961299                                alt.env );
    12971300                        PRINT(
     
    17061709                        AlternativeFinder finder( indexer, env );
    17071710                        finder.targetType = toType;
    1708                         finder.findWithAdjustment( initExpr->get_expr() );
     1711                        finder.findWithAdjustment( initExpr->expr );
    17091712                        for ( Alternative & alt : finder.get_alternatives() ) {
    17101713                                TypeEnvironment newEnv( alt.env );
     
    17131716                                PRINT(
    17141717                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    1715                                  )
     1718                                )
    17161719                                // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    17171720                                // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    17181721                                // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    17191722                                // to.
    1720                                 int discardedValues = alt.expr->get_result()->size() - toType->size();
     1723                                int discardedValues = alt.expr->result->size() - toType->size();
    17211724                                if ( discardedValues < 0 ) continue;
    17221725                                // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    17231726                                // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    17241727                                // unification run for side-effects
    1725                                 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??
    1726 
    1727                                 Cost thisCost = castCost( alt.expr->get_result(), toType, indexer, newEnv );
     1728                                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??
     1729
     1730                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
    17281731                                if ( thisCost != Cost::infinity ) {
    17291732                                        // count one safe conversion for each value that is thrown away
  • src/ResolvExpr/Resolver.cc

    r3ef35bd reba74ba  
    128128
    129129        namespace {
    130                 void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
     130                struct StripCasts {
     131                        Expression * postmutate( CastExpr * castExpr ) {
     132                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     133                                        // generated cast is to the same type as its argument, so it's unnecessary -- remove it
     134                                        Expression * expr = castExpr->arg;
     135                                        castExpr->arg = nullptr;
     136                                        std::swap( expr->env, castExpr->env );
     137                                        return expr;
     138                                }
     139                                return castExpr;
     140                        }
     141
     142                        static void strip( Expression *& expr ) {
     143                                PassVisitor<StripCasts> stripper;
     144                                expr = expr->acceptMutator( stripper );
     145                        }
     146                };
     147
     148                void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
    131149                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    132                         env.makeSubstitution( *expr->get_env() );
     150                        env.makeSubstitution( *expr->env );
     151                        StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
    133152                }
    134153
     
    178197                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    179198                        if ( winners.size() == 0 ) {
    180                                 SemanticError( untyped, toString(
    181                                         "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""),
    182                                         "expression: ") );
     199                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    183200                        } else if ( winners.size() != 1 ) {
    184201                                std::ostringstream stream;
    185                                 stream << "Cannot choose between " << winners.size() << " alternatives for "
    186                                         << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     202                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
    187203                                untyped->print( stream );
    188204                                stream << " Alternatives are:\n";
    189205                                printAlts( winners, stream, 1 );
    190                                
    191206                                SemanticError( untyped->location, stream.str() );
    192207                        }
     
    196211                        if ( findDeletedExpr( choice.expr ) ) {
    197212                                trace( choice.expr );
    198                                 SemanticError( choice.expr,
    199                                         "Unique best alternative includes deleted identifier in " );
     213                                SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
    200214                        }
    201215                        alt = std::move( choice );
     
    416430
    417431        void Resolver::previsit( CaseStmt *caseStmt ) {
    418                 if ( caseStmt->get_condition() ) {
     432                if ( caseStmt->condition ) {
    419433                        std::list< InitAlternative > initAlts = currentObject.getOptions();
    420434                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
     
    422436                        Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
    423437                        findSingleExpression( newExpr, indexer );
    424                         CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
    425                         caseStmt->condition = castExpr->arg;
    426                         castExpr->arg = nullptr;
     438                        // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
     439                        // Ideally we would perform the conversion internally here.
     440                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
     441                                newExpr = castExpr->arg;
     442                                castExpr->arg = nullptr;
     443                                std::swap( newExpr->env, castExpr->env );
     444                        }
     445                        caseStmt->condition = newExpr;
    427446                }
    428447        }
     
    719738                initExpr->expr = nullptr;
    720739                std::swap( initExpr->env, newExpr->env );
    721                 std::swap( initExpr->inferParams, newExpr->inferParams ) ;
     740                // InitExpr may have inferParams in the case where the expression specializes a function pointer,
     741                // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
     742                newExpr->spliceInferParams( initExpr );
    722743
    723744                // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
  • src/ResolvExpr/TypeEnvironment.h

    r3ef35bd reba74ba  
    4141        //
    4242        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
     43        //
     44        // Note: since this compares pointers for position, minor changes in the source file that affect
     45        // memory layout can alter compilation time in unpredictable ways. For example, the placement
     46        // of a line directive can reorder type pointers with respect to each other so that assertions
     47        // are seen in different orders, causing a potentially different number of unification calls when
     48        // resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering line directives
     49        // alone, so it would be nice to fix this comparison so that assertions compare more consistently.
     50        // I've tried to modify this to compare on mangle name instead of type as the second comparator, but
     51        // this causes some assertions to never be recorded. More investigation is needed.
    4352        struct AssertCompare {
    4453                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
  • src/ResolvExpr/Unify.cc

    r3ef35bd reba74ba  
    306306                } else if ( isopen1 ) {
    307307                        result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    308                 } else if ( isopen2 ) {
     308                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    309309                        result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    310310                } else {
Note: See TracChangeset for help on using the changeset viewer.