Changeset 67fa9f9 for src/ResolvExpr/AlternativeFinder.cc
- Timestamp:
- Jul 5, 2017, 10:50:22 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 0614d14
- Parents:
- 11dbfe1 (diff), 307a732 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r11dbfe1 r67fa9f9 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 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 811 837 void AlternativeFinder::visit( CastExpr *castExpr ) { 812 838 Type *& toType = castExpr->get_result(); … … 840 866 thisCost += Cost( 0, 0, discardedValues ); 841 867 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 } 868 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); 866 869 } // if 867 870 } // for … … 1182 1185 } 1183 1186 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 } 1184 1234 } // namespace ResolvExpr 1185 1235
Note:
See TracChangeset
for help on using the changeset viewer.