Changeset c71b256
- Timestamp:
- Feb 16, 2018, 4:14:29 PM (7 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:
- 7c782af
- Parents:
- 4a161be
- Location:
- src/ResolvExpr
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r4a161be rc71b256 95 95 void postvisit( StmtExpr * stmtExpr ); 96 96 void postvisit( UntypedInitExpr * initExpr ); 97 void postvisit( InitExpr * initExpr ); 98 void postvisit( DeletedExpr * delExpr ); 97 99 98 100 /// Adds alternatives for anonymous members … … 120 122 Type *& targetType; 121 123 }; 122 123 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {124 CastExpr *castToVoid = new CastExpr( expr );125 126 AlternativeFinder finder( indexer, env );127 finder.findWithAdjustment( castToVoid );128 129 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0130 // interpretations, an exception has already been thrown.131 assert( finder.get_alternatives().size() == 1 );132 CastExpr *newExpr = dynamic_cast< CastExpr* >( finder.get_alternatives().front().expr );133 assert( newExpr );134 env = finder.get_alternatives().front().env;135 return newExpr->get_arg()->clone();136 }137 124 138 125 Cost sumCost( const AltList &in ) { … … 1751 1738 findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) ); 1752 1739 } 1740 1741 void AlternativeFinder::Finder::postvisit( InitExpr * ) { 1742 assertf( false, "AlternativeFinder should never see a resolved InitExpr." ); 1743 } 1744 1745 void AlternativeFinder::Finder::postvisit( DeletedExpr * ) { 1746 assertf( false, "AlternativeFinder should never see a DeletedExpr." ); 1747 } 1753 1748 } // namespace ResolvExpr 1754 1749 -
src/ResolvExpr/Resolver.cc
r4a161be rc71b256 105 105 } 106 106 107 // used in resolveTypeof 108 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) { 109 TypeEnvironment env; 110 return resolveInVoidContext( expr, indexer, env ); 107 namespace { 108 struct DeleteFinder : public WithShortCircuiting { 109 DeletedExpr * delExpr = nullptr; 110 void previsit( DeletedExpr * expr ) { 111 if ( delExpr ) visit_children = false; 112 else delExpr = expr; 113 } 114 115 void previsit( Expression * ) { 116 if ( delExpr ) visit_children = false; 117 } 118 }; 119 } 120 121 DeletedExpr * findDeletedExpr( Expression * expr ) { 122 PassVisitor<DeleteFinder> finder; 123 expr->accept( finder ); 124 return finder.pass.delExpr; 111 125 } 112 126 … … 130 144 } // namespace 131 145 146 namespace { 147 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) { 148 assertf( untyped, "expected a non-null expression." ); 149 TypeEnvironment env; 150 AlternativeFinder finder( indexer, env ); 151 finder.find( untyped, adjust, prune, failFast ); 152 153 #if 0 154 if ( finder.get_alternatives().size() != 1 ) { 155 std::cerr << "untyped expr is "; 156 untyped->print( std::cerr ); 157 std::cerr << std::endl << "alternatives are:"; 158 for ( const Alternative & alt : finder.get_alternatives() ) { 159 alt.print( std::cerr ); 160 } // for 161 } // if 162 #endif 163 164 AltList candidates; 165 for ( Alternative & alt : finder.get_alternatives() ) { 166 if ( pred( alt ) ) { 167 candidates.push_back( std::move( alt ) ); 168 } 169 } 170 171 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 172 // choose the lowest cost expression among the candidates 173 AltList winners; 174 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 175 if ( winners.size() == 0 ) { 176 throw SemanticError( toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: "), untyped ); 177 } else if ( winners.size() != 1 ) { 178 std::ostringstream stream; 179 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; 180 untyped->print( stream ); 181 stream << "Alternatives are:\n"; 182 printAlts( winners, stream, 1 ); 183 throw SemanticError( stream.str() ); 184 } 185 186 // there is one unambiguous interpretation - move the expression into the with statement 187 Alternative & choice = winners.front(); 188 if ( findDeletedExpr( choice.expr ) ) { 189 throw SemanticError( "Unique best alternative includes deleted identifier in ", choice.expr ); 190 } 191 alt = std::move( choice ); 192 } 193 194 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 195 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) { 196 if ( ! untyped ) return; 197 Alternative choice; 198 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast ); 199 finishExpr( choice.expr, choice.env, untyped->env ); 200 delete untyped; 201 untyped = choice.expr; 202 choice.expr = nullptr; 203 } 204 205 bool standardAlternativeFilter( const Alternative & ) { 206 // currently don't need to filter, under normal circumstances. 207 // in the future, this may be useful for removing deleted expressions 208 return true; 209 } 210 } // namespace 211 212 // used in resolveTypeof 213 Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) { 214 TypeEnvironment env; 215 return resolveInVoidContext( expr, indexer, env ); 216 } 217 218 Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) { 219 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0 220 // interpretations, an exception has already been thrown. 221 assertf( expr, "expected a non-null expression." ); 222 223 static CastExpr untyped( nullptr ); // cast to void 224 225 // set up and resolve expression cast to void 226 untyped.arg = expr; 227 Alternative choice; 228 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true ); 229 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 230 env = std::move( choice.env ); 231 232 // clean up resolved expression 233 Expression * ret = castExpr->arg; 234 castExpr->arg = nullptr; 235 236 // unlink the arg so that it isn't deleted twice at the end of the program 237 untyped.arg = nullptr; 238 return ret; 239 } 240 132 241 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 133 242 resetTyVarRenaming(); 134 243 TypeEnvironment env; 135 Expression * newExpr = resolveInVoidContext( untyped, indexer, env );244 Expression * newExpr = resolveInVoidContext( untyped, indexer, env ); 136 245 finishExpr( newExpr, env, untyped->env ); 137 246 delete untyped; … … 140 249 141 250 void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) { 142 if ( ! untyped ) return; 143 TypeEnvironment env; 144 AlternativeFinder finder( indexer, env ); 145 finder.find( untyped ); 146 #if 0 147 if ( finder.get_alternatives().size() != 1 ) { 148 std::cerr << "untyped expr is "; 149 untyped->print( std::cerr ); 150 std::cerr << std::endl << "alternatives are:"; 151 for ( const Alternative & alt : finder.get_alternatives() ) { 152 alt.print( std::cerr ); 153 } // for 154 } // if 155 #endif 156 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end: (%zd) %s", finder.get_alternatives().size(), toString( untyped ).c_str() ); 157 Alternative &choice = finder.get_alternatives().front(); 158 Expression *newExpr = choice.expr->clone(); 159 finishExpr( newExpr, choice.env, untyped->env ); 160 delete untyped; 161 untyped = newExpr; 251 findKindExpression( untyped, indexer, "", standardAlternativeFilter ); 162 252 } 163 253 … … 170 260 171 261 namespace { 172 /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 173 template<typename Pred> 174 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) { 175 TypeEnvironment env; 176 AlternativeFinder finder( indexer, env ); 177 finder.findWithAdjustment( untyped ); 178 179 AltList candidates; 180 for ( Alternative & alt : finder.get_alternatives() ) { 181 if ( pred( alt.expr->result ) ) { 182 candidates.push_back( std::move( alt ) ); 183 } 184 } 185 186 // choose the lowest cost expression among the candidates 187 AltList winners; 188 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 189 if ( winners.size() == 0 ) { 190 throw SemanticError( "No reasonable alternatives for " + kindStr + " expression: ", untyped ); 191 } else if ( winners.size() != 1 ) { 192 std::ostringstream stream; 193 stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr + " expression\n"; 194 untyped->print( stream ); 195 stream << "Alternatives are:\n"; 196 printAlts( winners, stream, 1 ); 197 throw SemanticError( stream.str() ); 198 } 199 200 // there is one unambiguous interpretation - move the expression into the with statement 201 Alternative & alt = winners.front(); 202 finishExpr( alt.expr, alt.env, untyped->env ); 203 delete untyped; 204 untyped = alt.expr; 205 alt.expr = nullptr; 206 } 207 208 bool isIntegralType( Type *type ) { 262 bool isIntegralType( const Alternative & alt ) { 263 Type * type = alt.expr->result; 209 264 if ( dynamic_cast< EnumInstType * >( type ) ) { 210 265 return true; … … 559 614 if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor" ); top.append( errors ); throw top; } 560 615 if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; } 561 616 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 562 617 563 618 // Swap the results from the alternative with the unresolved values. … … 592 647 } 593 648 594 bool isStructOrUnion( Type *t ) {595 t =t->stripReferences();649 bool isStructOrUnion( const Alternative & alt ) { 650 Type * t = alt.expr->result->stripReferences(); 596 651 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 597 652 }
Note: See TracChangeset
for help on using the changeset viewer.