Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r62423350 rd7dc824  
    604604//          )
    605605                SymTab::Indexer decls( indexer );
    606                 // PRINT(
    607                 //      std::cerr << "============= original indexer" << std::endl;
    608                 //      indexer.print( std::cerr );
    609                 //      std::cerr << "============= new indexer" << std::endl;
    610                 //      decls.print( std::cerr );
    611                 // )
     606                PRINT(
     607                        std::cerr << "============= original indexer" << std::endl;
     608                        indexer.print( std::cerr );
     609                        std::cerr << "============= new indexer" << std::endl;
     610                        decls.print( std::cerr );
     611                )
    612612                addToIndexer( have, decls );
    613613                AssertionSet newNeed;
     
    809809        }
    810810
    811         Expression * restructureCast( Expression * argExpr, Type * toType ) {
    812                 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) {
    813                         // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
    814                         // to its corresponding target type, producing the tuple of those cast expressions. If there are
    815                         // more components of the tuple than components in the target type, then excess components do not
    816                         // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
    817                         if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
    818                                 // expressions which may contain side effects require a single unique instance of the expression.
    819                                 argExpr = new UniqueExpr( argExpr );
    820                         }
    821                         std::list< Expression * > componentExprs;
    822                         for ( unsigned int i = 0; i < toType->size(); i++ ) {
    823                                 // cast each component
    824                                 TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
    825                                 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ) ) );
    826                         }
    827                         delete argExpr;
    828                         assert( componentExprs.size() > 0 );
    829                         // produce the tuple of casts
    830                         return new TupleExpr( componentExprs );
    831                 } else {
    832                         // handle normally
    833                         return new CastExpr( argExpr, toType->clone() );
    834                 }
    835         }
    836 
    837811        void AlternativeFinder::visit( CastExpr *castExpr ) {
    838812                Type *& toType = castExpr->get_result();
     
    866840                                thisCost += Cost( 0, 0, discardedValues );
    867841
    868                                 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
     842                                Expression * argExpr = i->expr->clone();
     843                                if ( argExpr->get_result()->size() > 1 && ! castExpr->get_result()->isVoid() ) {
     844                                        // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
     845                                        // to its corresponding target type, producing the tuple of those cast expressions. If there are
     846                                        // more components of the tuple than components in the target type, then excess components do not
     847                                        // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
     848                                        if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
     849                                                // expressions which may contain side effects require a single unique instance of the expression.
     850                                                argExpr = new UniqueExpr( argExpr );
     851                                        }
     852                                        std::list< Expression * > componentExprs;
     853                                        for ( unsigned int i = 0; i < castExpr->get_result()->size(); i++ ) {
     854                                                // cast each component
     855                                                TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
     856                                                componentExprs.push_back( new CastExpr( idx, castExpr->get_result()->getComponent( i )->clone() ) );
     857                                        }
     858                                        delete argExpr;
     859                                        assert( componentExprs.size() > 0 );
     860                                        // produce the tuple of casts
     861                                        candidates.push_back( Alternative( new TupleExpr( componentExprs ), i->env, i->cost, thisCost ) );
     862                                } else {
     863                                        // handle normally
     864                                        candidates.push_back( Alternative( new CastExpr( argExpr->clone(), toType->clone() ), i->env, i->cost, thisCost ) );
     865                                }
    869866                        } // if
    870867                } // for
     
    11851182        }
    11861183
    1187         void AlternativeFinder::visit( UntypedInitExpr *initExpr ) {
    1188                 // handle each option like a cast
    1189                 AltList candidates;
    1190                 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; )
    1191                 // O(N^2) checks of d-types with e-types
    1192                 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
    1193                         Type * toType = resolveTypeof( initAlt.type, indexer );
    1194                         SymTab::validateType( toType, &indexer );
    1195                         adjustExprType( toType, env, indexer );
    1196                         // Ideally the call to findWithAdjustment could be moved out of the loop, but unfortunately it currently has to occur inside or else
    1197                         // polymorphic return types are not properly bound to the initialization type, since return type variables are only open for the duration of resolving
    1198                         // the UntypedExpr. This is only actually an issue in initialization contexts that allow more than one possible initialization type, but it is still suboptimal.
    1199                         AlternativeFinder finder( indexer, env );
    1200                         finder.targetType = toType;
    1201                         finder.findWithAdjustment( initExpr->get_expr() );
    1202                         for ( Alternative & alt : finder.get_alternatives() ) {
    1203                                 TypeEnvironment newEnv( alt.env );
    1204                                 AssertionSet needAssertions, haveAssertions;
    1205                                 OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    1206                                 PRINT( std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl; )
    1207                                 // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    1208                                 // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    1209                                 // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    1210                                 // to.
    1211                                 int discardedValues = alt.expr->get_result()->size() - toType->size();
    1212                                 if ( discardedValues < 0 ) continue;
    1213                                 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    1214                                 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    1215                                 // unification run for side-effects
    1216                                 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??
    1217 
    1218                                 Cost thisCost = castCost( alt.expr->get_result(), toType, indexer, newEnv );
    1219                                 if ( thisCost != Cost::infinity ) {
    1220                                         // count one safe conversion for each value that is thrown away
    1221                                         thisCost += Cost( 0, 0, discardedValues );
    1222                                         candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
    1223                                 }
    1224                         }
    1225                 }
    1226 
    1227                 // findMinCost selects the alternatives with the lowest "cost" members, but has the side effect of copying the
    1228                 // cvtCost member to the cost member (since the old cost is now irrelevant).  Thus, calling findMinCost twice
    1229                 // selects first based on argument cost, then on conversion cost.
    1230                 AltList minArgCost;
    1231                 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( minArgCost ) );
    1232                 findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
    1233         }
    12341184} // namespace ResolvExpr
    12351185
Note: See TracChangeset for help on using the changeset viewer.