Changeset eba74ba for src/ResolvExpr
- Timestamp:
- May 25, 2018, 2:51:06 PM (6 years ago)
- 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. - Location:
- src/ResolvExpr
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r3ef35bd reba74ba 689 689 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 690 690 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 691 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {691 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { 692 692 // formalType is a TupleType - group actuals into a TupleExpr 693 693 ++nTuples; 694 694 for ( Type* type : *tupleType ) { 695 695 // xxx - dropping initializer changes behaviour from previous, but seems correct 696 // ^^^ need to handle the case where a tuple has a default argument 696 697 if ( ! instantiateArgument( 697 698 type, nullptr, args, results, genStart, indexer, nTuples ) ) … … 704 705 } 705 706 return true; 706 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {707 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) { 707 708 // formalType is a ttype, consumes all remaining arguments 708 709 // xxx - mixing default arguments with variadic?? … … 907 908 // consider only first exploded actual 908 909 Expression* expr = expl.exprs.front(); 909 Type* actualType = expr-> get_result()->clone();910 Type* actualType = expr->result->clone(); 910 911 911 912 PRINT( … … 938 939 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 939 940 // sum cost and accumulate actuals 940 std::list<Expression*>& args = appExpr-> get_args();941 std::list<Expression*>& args = appExpr->args; 941 942 Cost cost = func.cost; 942 943 const ArgPack* pack = &result; … … 965 966 // add all type variables as open variables now so that those not used in the parameter 966 967 // 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() ) { 970 971 // 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(); 972 973 if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 973 974 indexer ) ) { … … 982 983 std::size_t genStart = 0; 983 984 984 for ( DeclarationWithType* formal : funcType-> get_parameters()) {985 for ( DeclarationWithType* formal : funcType->parameters ) { 985 986 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 986 987 if ( ! instantiateArgument( 987 obj-> get_type(), obj->get_init(), args, results, genStart, indexer ) )988 obj->type, obj->init, args, results, genStart, indexer ) ) 988 989 return; 989 990 } … … 1066 1067 void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) { 1067 1068 AlternativeFinder funcFinder( indexer, env ); 1068 funcFinder.findWithAdjustment( untypedExpr-> get_function());1069 funcFinder.findWithAdjustment( untypedExpr->function ); 1069 1070 // if there are no function alternatives, then proceeding is a waste of time. 1070 1071 if ( funcFinder.alternatives.empty() ) return; … … 1275 1276 AlternativeFinder finder( indexer, env ); 1276 1277 finder.targetType = toType; 1277 finder.findWithAdjustment( castExpr-> get_arg());1278 finder.findWithAdjustment( castExpr->arg ); 1278 1279 1279 1280 AltList candidates; … … 1282 1283 OpenVarSet openVars; 1283 1284 1285 alt.env.extractOpenVars( openVars ); 1286 1284 1287 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1285 1288 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1286 1289 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1287 1290 // to. 1288 int discardedValues = alt.expr-> get_result()->size() - castExpr->get_result()->size();1291 int discardedValues = alt.expr->result->size() - castExpr->result->size(); 1289 1292 if ( discardedValues < 0 ) continue; 1290 1293 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1291 1294 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1292 1295 // 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, 1294 1297 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, 1296 1299 alt.env ); 1297 1300 PRINT( … … 1706 1709 AlternativeFinder finder( indexer, env ); 1707 1710 finder.targetType = toType; 1708 finder.findWithAdjustment( initExpr-> get_expr());1711 finder.findWithAdjustment( initExpr->expr ); 1709 1712 for ( Alternative & alt : finder.get_alternatives() ) { 1710 1713 TypeEnvironment newEnv( alt.env ); … … 1713 1716 PRINT( 1714 1717 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1715 1718 ) 1716 1719 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1717 1720 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1718 1721 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1719 1722 // to. 1720 int discardedValues = alt.expr-> get_result()->size() - toType->size();1723 int discardedValues = alt.expr->result->size() - toType->size(); 1721 1724 if ( discardedValues < 0 ) continue; 1722 1725 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1723 1726 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1724 1727 // 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 ); 1728 1731 if ( thisCost != Cost::infinity ) { 1729 1732 // count one safe conversion for each value that is thrown away -
src/ResolvExpr/Resolver.cc
r3ef35bd reba74ba 128 128 129 129 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 ) { 131 149 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 133 152 } 134 153 … … 178 197 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 179 198 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: ") ); 183 200 } else if ( winners.size() != 1 ) { 184 201 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"; 187 203 untyped->print( stream ); 188 204 stream << " Alternatives are:\n"; 189 205 printAlts( winners, stream, 1 ); 190 191 206 SemanticError( untyped->location, stream.str() ); 192 207 } … … 196 211 if ( findDeletedExpr( choice.expr ) ) { 197 212 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 " ); 200 214 } 201 215 alt = std::move( choice ); … … 416 430 417 431 void Resolver::previsit( CaseStmt *caseStmt ) { 418 if ( caseStmt-> get_condition()) {432 if ( caseStmt->condition ) { 419 433 std::list< InitAlternative > initAlts = currentObject.getOptions(); 420 434 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." ); … … 422 436 Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() ); 423 437 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; 427 446 } 428 447 } … … 719 738 initExpr->expr = nullptr; 720 739 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 ); 722 743 723 744 // 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 41 41 // 42 42 // 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. 43 52 struct AssertCompare { 44 53 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const { -
src/ResolvExpr/Unify.cc
r3ef35bd reba74ba 306 306 } else if ( isopen1 ) { 307 307 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? 309 309 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 310 310 } else {
Note: See TracChangeset
for help on using the changeset viewer.