- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r62423350 rd7dc824 604 604 // ) 605 605 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 ) 612 612 addToIndexer( have, decls ); 613 613 AssertionSet newNeed; … … 809 809 } 810 810 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 tuple814 // to its corresponding target type, producing the tuple of those cast expressions. If there are815 // more components of the tuple than components in the target type, then excess components do not816 // 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 component824 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 casts830 return new TupleExpr( componentExprs );831 } else {832 // handle normally833 return new CastExpr( argExpr, toType->clone() );834 }835 }836 837 811 void AlternativeFinder::visit( CastExpr *castExpr ) { 838 812 Type *& toType = castExpr->get_result(); … … 866 840 thisCost += Cost( 0, 0, discardedValues ); 867 841 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 } 869 866 } // if 870 867 } // for … … 1185 1182 } 1186 1183 1187 void AlternativeFinder::visit( UntypedInitExpr *initExpr ) {1188 // handle each option like a cast1189 AltList candidates;1190 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; )1191 // O(N^2) checks of d-types with e-types1192 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 else1197 // polymorphic return types are not properly bound to the initialization type, since return type variables are only open for the duration of resolving1198 // 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 a1208 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results1209 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast1210 // 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 not1214 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))1215 // unification run for side-effects1216 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 away1221 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 the1228 // cvtCost member to the cost member (since the old cost is now irrelevant). Thus, calling findMinCost twice1229 // 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 }1234 1184 } // namespace ResolvExpr 1235 1185
Note:
See TracChangeset
for help on using the changeset viewer.