Changeset 4c925cd for src/ResolvExpr
- Timestamp:
- Aug 14, 2020, 11:40:04 AM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 5715d43, fa5e0112
- Parents:
- 309d814 (diff), badd22f (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:
-
- 20 edited
-
AdjustExprType.cc (modified) (1 diff)
-
Candidate.hpp (modified) (2 diffs)
-
CandidateFinder.cpp (modified) (92 diffs)
-
CandidateFinder.hpp (modified) (4 diffs)
-
CastCost.cc (modified) (7 diffs)
-
CommonType.cc (modified) (4 diffs)
-
ConversionCost.cc (modified) (14 diffs)
-
ConversionCost.h (modified) (3 diffs)
-
CurrentObject.cc (modified) (15 diffs)
-
PolyCost.cc (modified) (2 diffs)
-
PtrsAssignable.cc (modified) (1 diff)
-
PtrsCastable.cc (modified) (1 diff)
-
RenameVars.cc (modified) (11 diffs)
-
ResolveTypeof.cc (modified) (5 diffs)
-
Resolver.cc (modified) (7 diffs)
-
SatisfyAssertions.cpp (modified) (9 diffs)
-
SatisfyAssertions.hpp (modified) (1 diff)
-
SpecCost.cc (modified) (4 diffs)
-
Unify.cc (modified) (12 diffs)
-
typeops.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AdjustExprType.cc
r309d814 r4c925cd 100 100 101 101 namespace { 102 struct AdjustExprType_new final : public ast::WithShortCircuiting { 102 class AdjustExprType_new final : public ast::WithShortCircuiting { 103 const ast::SymbolTable & symtab; 104 public: 103 105 const ast::TypeEnvironment & tenv; 104 const ast::SymbolTable & symtab;105 106 106 107 AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms ) 107 : tenv( e ), symtab( syms) {}108 : symtab( syms ), tenv( e ) {} 108 109 109 void pre mutate( const ast::VoidType * ) { visit_children = false; }110 void pre mutate( const ast::BasicType * ) { visit_children = false; }111 void pre mutate( const ast::PointerType * ) { visit_children = false; }112 void pre mutate( const ast::ArrayType * ) { visit_children = false; }113 void pre mutate( const ast::FunctionType * ) { visit_children = false; }114 void pre mutate( const ast::StructInstType * ) { visit_children = false; }115 void pre mutate( const ast::UnionInstType * ) { visit_children = false; }116 void pre mutate( const ast::EnumInstType * ) { visit_children = false; }117 void pre mutate( const ast::TraitInstType * ) { visit_children = false; }118 void pre mutate( const ast::TypeInstType * ) { visit_children = false; }119 void pre mutate( const ast::TupleType * ) { visit_children = false; }120 void pre mutate( const ast::VarArgsType * ) { visit_children = false; }121 void pre mutate( const ast::ZeroType * ) { visit_children = false; }122 void pre mutate( const ast::OneType * ) { visit_children = false; }110 void previsit( const ast::VoidType * ) { visit_children = false; } 111 void previsit( const ast::BasicType * ) { visit_children = false; } 112 void previsit( const ast::PointerType * ) { visit_children = false; } 113 void previsit( const ast::ArrayType * ) { visit_children = false; } 114 void previsit( const ast::FunctionType * ) { visit_children = false; } 115 void previsit( const ast::StructInstType * ) { visit_children = false; } 116 void previsit( const ast::UnionInstType * ) { visit_children = false; } 117 void previsit( const ast::EnumInstType * ) { visit_children = false; } 118 void previsit( const ast::TraitInstType * ) { visit_children = false; } 119 void previsit( const ast::TypeInstType * ) { visit_children = false; } 120 void previsit( const ast::TupleType * ) { visit_children = false; } 121 void previsit( const ast::VarArgsType * ) { visit_children = false; } 122 void previsit( const ast::ZeroType * ) { visit_children = false; } 123 void previsit( const ast::OneType * ) { visit_children = false; } 123 124 124 const ast::Type * post mutate( const ast::ArrayType * at ) {125 const ast::Type * postvisit( const ast::ArrayType * at ) { 125 126 return new ast::PointerType{ at->base, at->qualifiers }; 126 127 } 127 128 128 const ast::Type * post mutate( const ast::FunctionType * ft ) {129 const ast::Type * postvisit( const ast::FunctionType * ft ) { 129 130 return new ast::PointerType{ ft }; 130 131 } 131 132 132 const ast::Type * post mutate( const ast::TypeInstType * inst ) {133 const ast::Type * postvisit( const ast::TypeInstType * inst ) { 133 134 // replace known function-type-variables with pointer-to-function 134 135 if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) { -
src/ResolvExpr/Candidate.hpp
r309d814 r4c925cd 51 51 52 52 Candidate( const ast::Expr * x, const ast::TypeEnvironment & e ) 53 : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {} 53 : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() { 54 assert(x->result); 55 } 54 56 55 57 Candidate( const Candidate & o, const ast::Expr * x, const Cost & addedCost = Cost::zero ) 56 58 : expr( x ), cost( o.cost + addedCost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ), 57 need( o.need ) {} 59 need( o.need ) { 60 assert(x->result); 61 } 58 62 59 63 Candidate( 60 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 64 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 61 65 const ast::AssertionSet & n, const Cost & c, const Cost & cvt = Cost::zero ) 62 : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {} 66 : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) { 67 assert(x->result); 68 } 63 69 64 70 Candidate( … … 66 72 ast::AssertionSet && n, const Cost & c, const Cost & cvt = Cost::zero ) 67 73 : expr( x ), cost( c ), cvtCost( cvt ), env( std::move( e ) ), open( std::move( o ) ), 68 need( n.begin(), n.end() ) {} 74 need( n.begin(), n.end() ) { 75 assert(x->result); 76 } 69 77 }; 70 78 -
src/ResolvExpr/CandidateFinder.cpp
r309d814 r4c925cd 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 // Last Modified By : A aron B. Moss12 // Last Modified On : Wed Jun 5 14:30:00 201913 // Update Count : 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 14:55:00 2019 13 // Update Count : 2 14 14 // 15 15 … … 54 54 return new ast::CastExpr{ expr, expr->result->stripReferences() }; 55 55 } 56 56 57 57 return expr; 58 58 } … … 61 61 UniqueId globalResnSlot = 0; 62 62 63 Cost computeConversionCost( 64 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,65 const ast:: TypeEnvironment & env63 Cost computeConversionCost( 64 const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue, 65 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 66 66 ) { 67 67 PRINT( … … 74 74 std::cerr << std::endl; 75 75 ) 76 Cost convCost = conversionCost( argType, paramType, symtab, env );76 Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env ); 77 77 PRINT( 78 78 std::cerr << std::endl << "cost is " << convCost << std::endl; … … 107 107 108 108 /// Computes conversion cost for a given expression to a given type 109 const ast::Expr * computeExpressionConversionCost( 110 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 109 const ast::Expr * computeExpressionConversionCost( 110 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 111 111 ) { 112 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env ); 112 Cost convCost = computeConversionCost( 113 arg->result, paramType, arg->get_lvalue(), symtab, env ); 113 114 outCost += convCost; 114 115 115 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 116 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 116 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 117 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 117 118 // infer parameters and this does not currently work for the reason stated below 118 119 Cost tmpCost = convCost; … … 123 124 return new ast::CastExpr{ arg, newType }; 124 125 125 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 126 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 126 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 127 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 127 128 // once this is fixed it should be possible to resolve the cast. 128 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 129 // but it shouldn't be because this makes the conversion from DT* to DT* since 129 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 130 // but it shouldn't be because this makes the conversion from DT* to DT* since 130 131 // commontype(zero_t, DT*) is DT*, rather than nothing 131 132 132 133 // CandidateFinder finder{ symtab, env }; 133 134 // finder.find( arg, ResolvMode::withAdjustment() ); 134 // assertf( finder.candidates.size() > 0, 135 // assertf( finder.candidates.size() > 0, 135 136 // "Somehow castable expression failed to find alternatives." ); 136 // assertf( finder.candidates.size() == 1, 137 // assertf( finder.candidates.size() == 1, 137 138 // "Somehow got multiple alternatives for known cast expression." ); 138 139 // return finder.candidates.front()->expr; … … 143 144 144 145 /// Computes conversion cost for a given candidate 145 Cost computeApplicationConversionCost( 146 CandidateRef cand, const ast::SymbolTable & symtab 146 Cost computeApplicationConversionCost( 147 CandidateRef cand, const ast::SymbolTable & symtab 147 148 ) { 148 149 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >(); … … 167 168 if ( function->isVarArgs ) { 168 169 convCost.incUnsafe(); 169 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 170 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 170 171 << convCost << std::endl; ; ) 171 172 // convert reference-typed expressions into value-typed expressions 172 cand->expr = ast::mutate_field_index( 173 appExpr, &ast::ApplicationExpr::args, i, 173 cand->expr = ast::mutate_field_index( 174 appExpr, &ast::ApplicationExpr::args, i, 174 175 referenceToRvalueConversion( args[i], convCost ) ); 175 176 continue; … … 180 181 // Default arguments should be free - don't include conversion cost. 181 182 // Unwrap them here because they are not relevant to the rest of the system 182 cand->expr = ast::mutate_field_index( 183 cand->expr = ast::mutate_field_index( 183 184 appExpr, &ast::ApplicationExpr::args, i, def->expr ); 184 185 ++param; … … 188 189 // mark conversion cost and also specialization cost of param type 189 190 const ast::Type * paramType = (*param)->get_type(); 190 cand->expr = ast::mutate_field_index( 191 appExpr, &ast::ApplicationExpr::args, i, 192 computeExpressionConversionCost( 191 cand->expr = ast::mutate_field_index( 192 appExpr, &ast::ApplicationExpr::args, i, 193 computeExpressionConversionCost( 193 194 args[i], paramType, symtab, cand->env, convCost ) ); 194 195 convCost.decSpec( specCost( paramType ) ); … … 198 199 if ( param != params.end() ) return Cost::infinity; 199 200 200 // specialization cost of return types can't be accounted for directly, it disables 201 // specialization cost of return types can't be accounted for directly, it disables 201 202 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 202 203 // … … 215 216 } 216 217 217 void makeUnifiableVars( 218 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 219 ast::AssertionSet & need 218 void makeUnifiableVars( 219 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 220 ast::AssertionSet & need 220 221 ) { 221 222 for ( const ast::TypeDecl * tyvar : type->forall ) { … … 254 255 255 256 ArgPack() 256 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 257 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 257 258 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 258 259 ArgPack( 260 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 259 260 ArgPack( 261 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 261 262 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 262 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 263 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 263 264 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 264 265 265 266 ArgPack( 266 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 267 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 268 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 267 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 268 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 269 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 269 270 unsigned nextExpl = 0, unsigned explAlt = 0 ) 270 271 : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ), 271 272 have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ), 272 273 nextExpl( nextExpl ), explAlt( explAlt ) {} 273 274 274 275 ArgPack( 275 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 276 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 276 277 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added ) 277 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 278 need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 278 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 279 need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 279 280 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {} 280 281 281 282 /// true if this pack is in the middle of an exploded argument 282 283 bool hasExpl() const { return nextExpl > 0; } … … 286 287 return args[ nextArg-1 ][ explAlt ]; 287 288 } 288 289 289 290 /// Ends a tuple expression, consolidating the appropriate args 290 291 void endTuple( const std::vector< ArgPack > & packs ) { … … 307 308 308 309 /// Instantiates an argument to match a parameter, returns false if no matching results left 309 bool instantiateArgument( 310 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 311 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 312 unsigned nTuples = 0 310 bool instantiateArgument( 311 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 312 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 313 unsigned nTuples = 0 313 314 ) { 314 315 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { … … 318 319 // xxx - dropping initializer changes behaviour from previous, but seems correct 319 320 // ^^^ need to handle the case where a tuple has a default argument 320 if ( ! instantiateArgument( 321 if ( ! instantiateArgument( 321 322 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 322 323 nTuples = 0; … … 329 330 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) { 330 331 // paramType is a ttype, consumes all remaining arguments 331 332 332 333 // completed tuples; will be spliced to end of results to finish 333 334 std::vector< ArgPack > finalResults{}; … … 342 343 for ( std::size_t i = genStart; i < genEnd; ++i ) { 343 344 unsigned nextArg = results[i].nextArg; 344 345 345 346 // use next element of exploded tuple if present 346 347 if ( results[i].hasExpl() ) { … … 352 353 results.emplace_back( 353 354 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 354 copy( results[i].need ), copy( results[i].have ), 355 copy( results[i].need ), copy( results[i].have ), 355 356 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl, 356 357 results[i].explAlt ); … … 370 371 // push empty tuple expression 371 372 newResult.parent = i; 372 std::vector< ast::ptr< ast::Expr > > emptyList; 373 newResult.expr = 374 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) }; 373 newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} }; 375 374 argType = newResult.expr->result; 376 375 } else { … … 400 399 401 400 // check unification for ttype before adding to final 402 if ( 403 unify( 401 if ( 402 unify( 404 403 ttype, argType, newResult.env, newResult.need, newResult.have, 405 newResult.open, symtab ) 404 newResult.open, symtab ) 406 405 ) { 407 406 finalResults.emplace_back( move( newResult ) ); … … 424 423 if ( expl.exprs.empty() ) { 425 424 results.emplace_back( 426 results[i], move( env ), copy( results[i].need ), 425 results[i], move( env ), copy( results[i].need ), 427 426 copy( results[i].have ), move( open ), nextArg + 1, expl.cost ); 428 427 429 428 continue; 430 429 } … … 432 431 // add new result 433 432 results.emplace_back( 434 i, expl.exprs.front(), move( env ), copy( results[i].need ), 435 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 433 i, expl.exprs.front(), move( env ), copy( results[i].need ), 434 copy( results[i].have ), move( open ), nextArg + 1, nTuples, 436 435 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 437 436 } … … 479 478 480 479 results.emplace_back( 481 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 480 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 482 481 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 483 482 } … … 495 494 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 496 495 results.emplace_back( 497 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 496 i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 498 497 move( need ), move( have ), move( open ), nextArg, nTuples ); 499 498 } … … 517 516 if ( expl.exprs.empty() ) { 518 517 results.emplace_back( 519 results[i], move( env ), move( need ), move( have ), move( open ), 518 results[i], move( env ), move( need ), move( have ), move( open ), 520 519 nextArg + 1, expl.cost ); 521 520 522 521 continue; 523 522 } … … 539 538 // add new result 540 539 results.emplace_back( 541 i, expr, move( env ), move( need ), move( have ), move( open ), 540 i, expr, move( env ), move( need ), move( have ), move( open ), 542 541 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 543 542 } … … 548 547 genStart = genEnd; 549 548 550 return genEnd != results.size(); 549 return genEnd != results.size(); // were any new results added? 551 550 } 552 551 553 552 /// Generate a cast expression from `arg` to `toType` 554 const ast::Expr * restructureCast( 553 const ast::Expr * restructureCast( 555 554 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast 556 555 ) { 557 if ( 558 arg->result->size() > 1 559 && ! toType->isVoid() 560 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 556 if ( 557 arg->result->size() > 1 558 && ! toType->isVoid() 559 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 561 560 ) { 562 // Argument is a tuple and the target type is neither void nor a reference. Cast each 563 // member of the tuple to its corresponding target type, producing the tuple of those 564 // cast expressions. If there are more components of the tuple than components in the 565 // target type, then excess components do not come out in the result expression (but 561 // Argument is a tuple and the target type is neither void nor a reference. Cast each 562 // member of the tuple to its corresponding target type, producing the tuple of those 563 // cast expressions. If there are more components of the tuple than components in the 564 // target type, then excess components do not come out in the result expression (but 566 565 // UniqueExpr ensures that the side effects will still be produced) 567 566 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 568 // expressions which may contain side effects require a single unique instance of 567 // expressions which may contain side effects require a single unique instance of 569 568 // the expression 570 569 arg = new ast::UniqueExpr{ arg->location, arg }; … … 574 573 // cast each component 575 574 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 576 components.emplace_back( 575 components.emplace_back( 577 576 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 578 577 } … … 594 593 595 594 /// Actually visits expressions to find their candidate interpretations 596 struct Finder final : public ast::WithShortCircuiting { 595 class Finder final : public ast::WithShortCircuiting { 596 const ast::SymbolTable & symtab; 597 public: 598 static size_t traceId; 597 599 CandidateFinder & selfFinder; 598 const ast::SymbolTable & symtab;599 600 CandidateList & candidates; 600 601 const ast::TypeEnvironment & tenv; 601 602 ast::ptr< ast::Type > & targetType; 602 603 604 enum Errors { 605 NotFound, 606 NoMatch, 607 ArgsToFew, 608 ArgsToMany, 609 RetsToFew, 610 RetsToMany, 611 NoReason 612 }; 613 614 struct { 615 Errors code = NotFound; 616 } reason; 617 603 618 Finder( CandidateFinder & f ) 604 : s elfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),619 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ), 605 620 targetType( f.targetType ) {} 606 621 607 622 void previsit( const ast::Node * ) { visit_children = false; } 608 623 … … 611 626 void addCandidate( Args &&... args ) { 612 627 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } ); 628 reason.code = NoReason; 613 629 } 614 630 … … 639 655 640 656 /// Completes a function candidate with arguments located 641 void validateFunctionCandidate( 642 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 643 CandidateList & out 657 void validateFunctionCandidate( 658 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 659 CandidateList & out 644 660 ) { 645 ast::ApplicationExpr * appExpr = 661 ast::ApplicationExpr * appExpr = 646 662 new ast::ApplicationExpr{ func->expr->location, func->expr }; 647 663 // sum cost and accumulate arguments … … 657 673 appExpr->args = move( vargs ); 658 674 // build and validate new candidate 659 auto newCand = 675 auto newCand = 660 676 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 661 677 PRINT( … … 669 685 /// Builds a list of candidates for a function, storing them in out 670 686 void makeFunctionCandidates( 671 const CandidateRef & func, const ast::FunctionType * funcType, 687 const CandidateRef & func, const ast::FunctionType * funcType, 672 688 const ExplodedArgs_new & args, CandidateList & out 673 689 ) { … … 676 692 ast::TypeEnvironment funcEnv{ func->env }; 677 693 makeUnifiableVars( funcType, funcOpen, funcNeed ); 678 // add all type variables as open variables now so that those not used in the parameter679 // list are still considered open694 // add all type variables as open variables now so that those not used in the 695 // parameter list are still considered open 680 696 funcEnv.add( funcType->forall ); 681 697 … … 683 699 // attempt to narrow based on expected target type 684 700 const ast::Type * returnType = funcType->returns.front()->get_type(); 685 if ( ! unify( 686 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 701 if ( ! unify( 702 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 687 703 ) { 688 704 // unification failed, do not pursue this candidate … … 698 714 for ( const ast::DeclWithType * param : funcType->params ) { 699 715 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 700 // Try adding the arguments corresponding to the current parameter to the existing 716 // Try adding the arguments corresponding to the current parameter to the existing 701 717 // matches 702 if ( ! instantiateArgument( 718 if ( ! instantiateArgument( 703 719 obj->type, obj->init, args, results, genStart, symtab ) ) return; 704 720 } … … 750 766 if ( expl.exprs.empty() ) { 751 767 results.emplace_back( 752 results[i], move( env ), copy( results[i].need ), 753 copy( results[i].have ), move( open ), nextArg + 1, 768 results[i], move( env ), copy( results[i].need ), 769 copy( results[i].have ), move( open ), nextArg + 1, 754 770 expl.cost ); 755 771 … … 760 776 results.emplace_back( 761 777 i, expl.exprs.front(), move( env ), copy( results[i].need ), 762 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 778 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 763 779 expl.exprs.size() == 1 ? 0 : 1, j ); 764 780 } … … 780 796 /// Adds implicit struct-conversions to the alternative list 781 797 void addAnonConversions( const CandidateRef & cand ) { 782 // adds anonymous member interpretations whenever an aggregate value type is seen. 783 // it's okay for the aggregate expression to have reference type -- cast it to the 798 // adds anonymous member interpretations whenever an aggregate value type is seen. 799 // it's okay for the aggregate expression to have reference type -- cast it to the 784 800 // base type to treat the aggregate as the referenced value 785 801 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 786 802 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 787 803 cand->env.apply( aggrType ); 788 804 789 805 if ( aggrType.as< ast::ReferenceType >() ) { 790 806 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; … … 799 815 800 816 /// Adds aggregate member interpretations 801 void addAggMembers( 802 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 803 const Candidate & cand, const Cost & addedCost, const std::string & name 817 void addAggMembers( 818 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 819 const Candidate & cand, const Cost & addedCost, const std::string & name 804 820 ) { 805 821 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 806 822 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 807 CandidateRef newCand = std::make_shared<Candidate>( 823 CandidateRef newCand = std::make_shared<Candidate>( 808 824 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 809 // add anonymous member interpretations whenever an aggregate value type is seen 825 // add anonymous member interpretations whenever an aggregate value type is seen 810 826 // as a member expression 811 827 addAnonConversions( newCand ); … … 815 831 816 832 /// Adds tuple member interpretations 817 void addTupleMembers( 818 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 819 const Cost & addedCost, const ast::Expr * member 833 void addTupleMembers( 834 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 835 const Cost & addedCost, const ast::Expr * member 820 836 ) { 821 837 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 822 // get the value of the constant expression as an int, must be between 0 and the 838 // get the value of the constant expression as an int, must be between 0 and the 823 839 // length of the tuple to have meaning 824 840 long long val = constantExpr->intValue(); 825 841 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 826 842 addCandidate( 827 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 843 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 828 844 addedCost ); 829 845 } … … 837 853 if ( funcFinder.candidates.empty() ) return; 838 854 839 std::vector< CandidateFinder > argCandidates = 855 reason.code = NoMatch; 856 857 std::vector< CandidateFinder > argCandidates = 840 858 selfFinder.findSubExprs( untypedExpr->args ); 841 859 842 860 // take care of possible tuple assignments 843 861 // if not tuple assignment, handled as normal function call … … 877 895 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 878 896 CandidateRef newFunc{ new Candidate{ *func } }; 879 newFunc->expr = 897 newFunc->expr = 880 898 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 881 899 makeFunctionCandidates( newFunc, function, argExpansions, found ); 882 900 } 883 } else if ( 884 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 901 } else if ( 902 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 885 903 ) { 886 904 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) { 887 905 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 888 906 CandidateRef newFunc{ new Candidate{ *func } }; 889 newFunc->expr = 907 newFunc->expr = 890 908 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 891 909 makeFunctionCandidates( newFunc, function, argExpansions, found ); … … 901 919 std::vector< ExplodedArg > funcE; 902 920 funcE.reserve( funcFinder.candidates.size() ); 903 for ( const CandidateRef & func : funcFinder ) { 921 for ( const CandidateRef & func : funcFinder ) { 904 922 funcE.emplace_back( *func, symtab ); 905 923 } … … 913 931 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 914 932 CandidateRef newOp{ new Candidate{ *op} }; 915 newOp->expr = 933 newOp->expr = 916 934 referenceToRvalueConversion( newOp->expr, newOp->cost ); 917 935 makeFunctionCandidates( newOp, function, argExpansions, found ); … … 922 940 } 923 941 924 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 942 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 925 943 // candidates 926 944 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } … … 934 952 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 935 953 auto function = pointer->base.strict_as< ast::FunctionType >(); 936 954 937 955 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 938 956 std::cerr << "parameters are:" << std::endl; … … 957 975 promoteCvtCost( winners ); 958 976 959 // function may return a struct/union value, in which case we need to add candidates 960 // for implicit conversions to each of the anonymous members, which must happen after 977 // function may return a struct/union value, in which case we need to add candidates 978 // for implicit conversions to each of the anonymous members, which must happen after 961 979 // `findMinCost`, since anon conversions are never the cheapest 962 980 for ( const CandidateRef & c : winners ) { … … 966 984 967 985 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 968 // If resolution is unsuccessful with a target type, try again without, since it 986 // If resolution is unsuccessful with a target type, try again without, since it 969 987 // will sometimes succeed when it wouldn't with a target type binding. 970 988 // For example: … … 983 1001 /// true if expression is an lvalue 984 1002 static bool isLvalue( const ast::Expr * x ) { 985 return x->result && ( x-> result->is_lvalue() || x->result.as< ast::ReferenceType >() );1003 return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() ); 986 1004 } 987 1005 … … 989 1007 CandidateFinder finder{ symtab, tenv }; 990 1008 finder.find( addressExpr->arg ); 1009 1010 if( finder.candidates.empty() ) return; 1011 1012 reason.code = NoMatch; 1013 991 1014 for ( CandidateRef & r : finder.candidates ) { 992 1015 if ( ! isLvalue( r->expr ) ) continue; … … 1009 1032 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1010 1033 1034 if( !finder.candidates.empty() ) reason.code = NoMatch; 1035 1011 1036 CandidateList matches; 1012 1037 for ( CandidateRef & cand : finder.candidates ) { … … 1016 1041 cand->env.extractOpenVars( open ); 1017 1042 1018 // It is possible that a cast can throw away some values in a multiply-valued 1019 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1020 // subexpression results that are cast directly. The candidate is invalid if it 1043 // It is possible that a cast can throw away some values in a multiply-valued 1044 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1045 // subexpression results that are cast directly. The candidate is invalid if it 1021 1046 // has fewer results than there are types to cast to. 1022 1047 int discardedValues = cand->expr->result->size() - toType->size(); … … 1025 1050 // unification run for side-effects 1026 1051 unify( toType, cand->expr->result, cand->env, need, have, open, symtab ); 1027 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env ); 1052 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1053 symtab, cand->env ); 1028 1054 PRINT( 1029 1055 std::cerr << "working on cast with result: " << toType << std::endl; … … 1037 1063 // count one safe conversion for each value that is thrown away 1038 1064 thisCost.incSafe( discardedValues ); 1039 CandidateRef newCand = std::make_shared<Candidate>( 1040 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1041 copy( cand->env ), move( open ), move( need ), cand->cost, 1065 CandidateRef newCand = std::make_shared<Candidate>( 1066 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1067 copy( cand->env ), move( open ), move( need ), cand->cost, 1042 1068 cand->cost + thisCost ); 1043 1069 inferParameters( newCand, matches ); … … 1057 1083 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1058 1084 for ( CandidateRef & r : finder.candidates ) { 1059 addCandidate( 1060 *r, 1085 addCandidate( 1086 *r, 1061 1087 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1062 1088 } … … 1067 1093 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1068 1094 for ( CandidateRef & agg : aggFinder.candidates ) { 1069 // it's okay for the aggregate expression to have reference type -- cast it to the 1095 // it's okay for the aggregate expression to have reference type -- cast it to the 1070 1096 // base type to treat the aggregate as the referenced value 1071 1097 Cost addedCost = Cost::zero; … … 1074 1100 // find member of the given type 1075 1101 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1076 addAggMembers( 1102 addAggMembers( 1077 1103 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1078 1104 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1079 addAggMembers( 1105 addAggMembers( 1080 1106 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1081 1107 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { … … 1092 1118 std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name ); 1093 1119 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1120 if( declList.empty() ) return; 1121 1122 reason.code = NoMatch; 1123 1094 1124 for ( auto & data : declList ) { 1095 1125 Cost cost = Cost::zero; … … 1097 1127 1098 1128 CandidateRef newCand = std::make_shared<Candidate>( 1099 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1129 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1100 1130 cost ); 1101 1131 PRINT( … … 1107 1137 std::cerr << std::endl; 1108 1138 ) 1109 newCand->expr = ast::mutate_field( 1110 newCand->expr.get(), &ast::Expr::result, 1139 newCand->expr = ast::mutate_field( 1140 newCand->expr.get(), &ast::Expr::result, 1111 1141 renameTyVars( newCand->expr->result ) ); 1112 // add anonymous member interpretations whenever an aggregate value type is seen 1142 // add anonymous member interpretations whenever an aggregate value type is seen 1113 1143 // as a name expression 1114 1144 addAnonConversions( newCand ); … … 1120 1150 // not sufficient to just pass `variableExpr` here, type might have changed since 1121 1151 // creation 1122 addCandidate( 1152 addCandidate( 1123 1153 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1124 1154 } … … 1130 1160 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 1131 1161 if ( sizeofExpr->type ) { 1132 addCandidate( 1133 new ast::SizeofExpr{ 1134 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1162 addCandidate( 1163 new ast::SizeofExpr{ 1164 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1135 1165 tenv ); 1136 1166 } else { … … 1141 1171 CandidateList winners = findMinCost( finder.candidates ); 1142 1172 if ( winners.size() != 1 ) { 1143 SemanticError( 1173 SemanticError( 1144 1174 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1145 1175 } … … 1154 1184 void postvisit( const ast::AlignofExpr * alignofExpr ) { 1155 1185 if ( alignofExpr->type ) { 1156 addCandidate( 1157 new ast::AlignofExpr{ 1158 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1186 addCandidate( 1187 new ast::AlignofExpr{ 1188 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1159 1189 tenv ); 1160 1190 } else { … … 1165 1195 CandidateList winners = findMinCost( finder.candidates ); 1166 1196 if ( winners.size() != 1 ) { 1167 SemanticError( 1197 SemanticError( 1168 1198 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1169 1199 } … … 1172 1202 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1173 1203 choice->cost = Cost::zero; 1174 addCandidate( 1204 addCandidate( 1175 1205 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1176 1206 } … … 1185 1215 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1186 1216 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1187 addCandidate( 1217 addCandidate( 1188 1218 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1189 1219 } … … 1206 1236 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1207 1237 if ( finder2.candidates.empty() ) return; 1238 1239 reason.code = NoMatch; 1208 1240 1209 1241 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1218 1250 1219 1251 addCandidate( 1220 new ast::LogicalExpr{ 1252 new ast::LogicalExpr{ 1221 1253 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1222 1254 move( env ), move( open ), move( need ), r1->cost + r2->cost ); … … 1240 1272 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1241 1273 if ( finder3.candidates.empty() ) return; 1274 1275 reason.code = NoMatch; 1242 1276 1243 1277 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1256 1290 ast::AssertionSet have; 1257 1291 1258 // unify true and false results, then infer parameters to produce new 1292 // unify true and false results, then infer parameters to produce new 1259 1293 // candidates 1260 1294 ast::ptr< ast::Type > common; 1261 if ( 1262 unify( 1263 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1264 common ) 1295 if ( 1296 unify( 1297 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1298 common ) 1265 1299 ) { 1266 1300 // generate typed expression 1267 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1301 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1268 1302 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1269 1303 newExpr->result = common ? common : r2->expr->result; 1270 1304 // convert both options to result type 1271 1305 Cost cost = r1->cost + r2->cost + r3->cost; 1272 newExpr->arg2 = computeExpressionConversionCost( 1306 newExpr->arg2 = computeExpressionConversionCost( 1273 1307 newExpr->arg2, newExpr->result, symtab, env, cost ); 1274 1308 newExpr->arg3 = computeExpressionConversionCost( … … 1287 1321 ast::TypeEnvironment env{ tenv }; 1288 1322 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env ); 1289 1323 1290 1324 CandidateFinder finder2{ symtab, env }; 1291 1325 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); … … 1317 1351 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1318 1352 if ( finder2.candidates.empty() ) return; 1353 1354 reason.code = NoMatch; 1319 1355 1320 1356 for ( const CandidateRef & r1 : finder1.candidates ) { … … 1330 1366 1331 1367 ast::ptr< ast::Type > common; 1332 if ( 1333 unify( 1334 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1335 common ) 1368 if ( 1369 unify( 1370 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1371 common ) 1336 1372 ) { 1337 1373 // generate new expression 1338 ast::RangeExpr * newExpr = 1374 ast::RangeExpr * newExpr = 1339 1375 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1340 1376 newExpr->result = common ? common : r1->expr->result; 1341 1377 // add candidate 1342 1378 CandidateRef newCand = std::make_shared<Candidate>( 1343 newExpr, move( env ), move( open ), move( need ), 1379 newExpr, move( env ), move( open ), move( need ), 1344 1380 r1->cost + r2->cost ); 1345 1381 inferParameters( newCand, candidates ); … … 1350 1386 1351 1387 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1352 std::vector< CandidateFinder > subCandidates = 1388 std::vector< CandidateFinder > subCandidates = 1353 1389 selfFinder.findSubExprs( tupleExpr->exprs ); 1354 1390 std::vector< CandidateList > possibilities; … … 1370 1406 1371 1407 addCandidate( 1372 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1408 new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 1373 1409 move( env ), move( open ), move( need ), sumCost( subs ) ); 1374 1410 } … … 1412 1448 toType = SymTab::validateType( initExpr->location, toType, symtab ); 1413 1449 toType = adjustExprType( toType, tenv, symtab ); 1414 // The call to find must occur inside this loop, otherwise polymorphic return 1415 // types are not bound to the initialization type, since return type variables are 1416 // only open for the duration of resolving the UntypedExpr. 1450 // The call to find must occur inside this loop, otherwise polymorphic return 1451 // types are not bound to the initialization type, since return type variables are 1452 // only open for the duration of resolving the UntypedExpr. 1417 1453 CandidateFinder finder{ symtab, tenv, toType }; 1418 1454 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1419 1455 for ( CandidateRef & cand : finder.candidates ) { 1456 if(reason.code == NotFound) reason.code = NoMatch; 1457 1420 1458 ast::TypeEnvironment env{ cand->env }; 1421 1459 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; … … 1426 1464 ) 1427 1465 1428 // It is possible that a cast can throw away some values in a multiply-valued 1429 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1430 // the subexpression results that are cast directly. The candidate is invalid 1466 // It is possible that a cast can throw away some values in a multiply-valued 1467 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1468 // the subexpression results that are cast directly. The candidate is invalid 1431 1469 // if it has fewer results than there are types to cast to. 1432 1470 int discardedValues = cand->expr->result->size() - toType->size(); … … 1435 1473 // unification run for side-effects 1436 1474 unify( toType, cand->expr->result, env, need, have, open, symtab ); 1437 Cost thisCost = castCost( cand->expr->result, toType, symtab, env ); 1438 1475 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1476 symtab, env ); 1477 1439 1478 if ( thisCost != Cost::infinity ) { 1440 1479 // count one safe conversion for each value that is thrown away 1441 1480 thisCost.incSafe( discardedValues ); 1442 CandidateRef newCand = std::make_shared<Candidate>( 1443 new ast::InitExpr{ 1444 initExpr->location, restructureCast( cand->expr, toType ), 1445 initAlt.designation }, 1481 CandidateRef newCand = std::make_shared<Candidate>( 1482 new ast::InitExpr{ 1483 initExpr->location, restructureCast( cand->expr, toType ), 1484 initAlt.designation }, 1446 1485 copy( cand->env ), move( open ), move( need ), cand->cost, thisCost ); 1447 1486 inferParameters( newCand, matches ); … … 1469 1508 }; 1470 1509 1471 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1510 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder"); 1511 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1472 1512 /// return type. Skips ambiguous candidates. 1473 1513 CandidateList pruneCandidates( CandidateList & candidates ) { … … 1486 1526 { 1487 1527 ast::ptr< ast::Type > newType = candidate->expr->result; 1528 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get()); 1488 1529 candidate->env.apply( newType ); 1489 1530 mangleName = Mangle::mangle( newType ); … … 1494 1535 if ( candidate->cost < found->second.candidate->cost ) { 1495 1536 PRINT( 1496 std::cerr << "cost " << candidate->cost << " beats " 1537 std::cerr << "cost " << candidate->cost << " beats " 1497 1538 << found->second.candidate->cost << std::endl; 1498 1539 ) … … 1500 1541 found->second = PruneStruct{ candidate }; 1501 1542 } else if ( candidate->cost == found->second.candidate->cost ) { 1502 // if one of the candidates contains a deleted identifier, can pick the other, 1503 // since deleted expressions should not be ambiguous if there is another option 1543 // if one of the candidates contains a deleted identifier, can pick the other, 1544 // since deleted expressions should not be ambiguous if there is another option 1504 1545 // that is at least as good 1505 1546 if ( findDeletedExpr( candidate->expr ) ) { … … 1515 1556 } else { 1516 1557 PRINT( 1517 std::cerr << "cost " << candidate->cost << " loses to " 1558 std::cerr << "cost " << candidate->cost << " loses to " 1518 1559 << found->second.candidate->cost << std::endl; 1519 1560 ) … … 1530 1571 1531 1572 CandidateRef cand = target.second.candidate; 1532 1573 1533 1574 ast::ptr< ast::Type > newResult = cand->expr->result; 1534 1575 cand->env.applyFree( newResult ); 1535 1576 cand->expr = ast::mutate_field( 1536 1577 cand->expr.get(), &ast::Expr::result, move( newResult ) ); 1537 1578 1538 1579 out.emplace_back( cand ); 1539 1580 } … … 1549 1590 1550 1591 if ( mode.failFast && candidates.empty() ) { 1551 SemanticError( expr, "No reasonable alternatives for expression " ); 1592 switch(finder.core.reason.code) { 1593 case Finder::NotFound: 1594 { SemanticError( expr, "No alternatives for expression " ); break; } 1595 case Finder::NoMatch: 1596 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; } 1597 case Finder::ArgsToFew: 1598 case Finder::ArgsToMany: 1599 case Finder::RetsToFew: 1600 case Finder::RetsToMany: 1601 case Finder::NoReason: 1602 default: 1603 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); } 1604 } 1552 1605 } 1553 1606 … … 1558 1611 std::vector< std::string > errors; 1559 1612 for ( CandidateRef & candidate : candidates ) { 1560 satisfyAssertions( candidate, symtab, satisfied, errors );1613 satisfyAssertions( candidate, localSyms, satisfied, errors ); 1561 1614 } 1562 1615 … … 1583 1636 1584 1637 CandidateList pruned = pruneCandidates( candidates ); 1585 1638 1586 1639 if ( mode.failFast && pruned.empty() ) { 1587 1640 std::ostringstream stream; … … 1602 1655 ) 1603 1656 PRINT( 1604 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1657 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1605 1658 << std::endl; 1606 1659 ) 1607 1660 } 1608 1661 1609 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1662 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1610 1663 // adjusted 1611 1664 if ( mode.adjust ) { 1612 1665 for ( CandidateRef & r : candidates ) { 1613 r->expr = ast::mutate_field( 1614 r->expr.get(), &ast::Expr::result, 1615 adjustExprType( r->expr->result, r->env, symtab) );1666 r->expr = ast::mutate_field( 1667 r->expr.get(), &ast::Expr::result, 1668 adjustExprType( r->expr->result, r->env, localSyms ) ); 1616 1669 } 1617 1670 } … … 1625 1678 } 1626 1679 1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1628 const std::vector< ast::ptr< ast::Expr > > & xs 1680 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1681 const std::vector< ast::ptr< ast::Expr > > & xs 1629 1682 ) { 1630 1683 std::vector< CandidateFinder > out; 1631 1684 1632 1685 for ( const auto & x : xs ) { 1633 out.emplace_back( symtab, env );1686 out.emplace_back( localSyms, env ); 1634 1687 out.back().find( x, ResolvMode::withAdjustment() ); 1635 1688 1636 1689 PRINT( 1637 1690 std::cerr << "findSubExprs" << std::endl; -
src/ResolvExpr/CandidateFinder.hpp
r309d814 r4c925cd 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 // Last Modified By : A aron B. Moss12 // Last Modified On : Wed Jun 5 14:30:00 201913 // Update Count : 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 9:51:00 2019 13 // Update Count : 2 14 14 // 15 15 … … 28 28 struct CandidateFinder { 29 29 CandidateList candidates; ///< List of candidate resolutions 30 const ast::SymbolTable & symtab; ///< Symbol table to lookup candidates30 const ast::SymbolTable & localSyms; ///< Symbol table to lookup candidates 31 31 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 32 32 ast::ptr< ast::Type > targetType; ///< Target type for resolution 33 33 34 CandidateFinder( 35 const ast::SymbolTable & sym tab, const ast::TypeEnvironment & env,34 CandidateFinder( 35 const ast::SymbolTable & syms, const ast::TypeEnvironment & env, 36 36 const ast::Type * tt = nullptr ) 37 : candidates(), symtab( symtab), env( env ), targetType( tt ) {}37 : candidates(), localSyms( syms ), env( env ), targetType( tt ) {} 38 38 39 39 /// Fill candidates with feasible resolutions for `expr` … … 49 49 iterator begin() { return candidates.begin(); } 50 50 const_iterator begin() const { return candidates.begin(); } 51 51 52 52 iterator end() { return candidates.end(); } 53 53 const_iterator end() const { return candidates.end(); } … … 55 55 56 56 /// Computes conversion cost between two types 57 Cost computeConversionCost( 58 const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,59 const ast:: TypeEnvironment & env );57 Cost computeConversionCost( 58 const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue, 59 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 60 60 61 61 } // namespace ResolvExpr -
src/ResolvExpr/CastCost.cc
r309d814 r4c925cd 10 10 // Created On : Sun May 17 06:57:43 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T hu Aug 8 16:12:00 201913 // Update Count : 812 // Last Modified On : Tue Oct 4 15:00:00 2019 13 // Update Count : 9 14 14 // 15 15 … … 142 142 143 143 CastCost_new( 144 const ast::Type * dst, const ast::SymbolTable & symtab,144 const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab, 145 145 const ast::TypeEnvironment & env, CostCalculation costFunc ) 146 : ConversionCost_new( dst, s ymtab, env, costFunc ) {}146 : ConversionCost_new( dst, srcIsLvalue, symtab, env, costFunc ) {} 147 147 148 148 void postvisit( const ast::BasicType * basicType ) { … … 152 152 cost = Cost::unsafe; 153 153 } else { 154 cost = conversionCost( basicType, dst, s ymtab, env );154 cost = conversionCost( basicType, dst, srcIsLvalue, symtab, env ); 155 155 } 156 156 } … … 183 183 } 184 184 }; 185 186 #warning For overload resolution between the two versions. 187 int localPtrsCastable(const ast::Type * t1, const ast::Type * t2, 188 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) { 189 return ptrsCastable( t1, t2, symtab, env ); 190 } 191 Cost localCastCost( 192 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 193 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 194 ) { return castCost( src, dst, srcIsLvalue, symtab, env ); } 185 195 } // anonymous namespace 186 196 197 198 187 199 Cost castCost( 188 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,189 const ast:: TypeEnvironment & env200 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 201 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 190 202 ) { 191 203 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { … … 193 205 // check cast cost against bound type, if present 194 206 if ( eqvClass->bound ) { 195 return castCost( src, eqvClass->bound, s ymtab, env );207 return castCost( src, eqvClass->bound, srcIsLvalue, symtab, env ); 196 208 } else { 197 209 return Cost::infinity; … … 201 213 auto type = strict_dynamic_cast< const ast::TypeDecl * >( named ); 202 214 if ( type->base ) { 203 return castCost( src, type->base, s ymtab, env ) + Cost::safe;215 return castCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe; 204 216 } 205 217 } … … 224 236 #warning cast on ptrsCastable artifact of having two functions, remove when port done 225 237 return convertToReferenceCost( 226 src, refType, symtab, env, 227 ( int (*)( 228 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 229 const ast::TypeEnvironment & ) 230 ) ptrsCastable ); 238 src, refType, srcIsLvalue, symtab, env, localPtrsCastable ); 231 239 } else { 232 240 #warning cast on castCost artifact of having two functions, remove when port done 233 ast::Pass< CastCost_new > converter{ 234 dst, symtab, env, 235 ( Cost (*)( 236 const ast::Type *, const ast::Type *, const ast::SymbolTable &, 237 const ast::TypeEnvironment & ) 238 ) castCost }; 241 ast::Pass< CastCost_new > converter( 242 dst, srcIsLvalue, symtab, env, localCastCost ); 239 243 src->accept( converter ); 240 return converter. pass.cost;244 return converter.core.cost; 241 245 } 242 246 } -
src/ResolvExpr/CommonType.cc
r309d814 r4c925cd 666 666 const ast::OpenVarSet & open; 667 667 public: 668 static size_t traceId; 668 669 ast::ptr< ast::Type > result; 669 670 … … 893 894 }; 894 895 896 // size_t CommonType_new::traceId = Stats::Heap::new_stacktrace_id("CommonType_new"); 895 897 namespace { 896 898 ast::ptr< ast::Type > handleReference( … … 939 941 ast::ptr< ast::Type > result; 940 942 const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >(); 941 const ast::ReferenceType * ref2 = type 1.as< ast::ReferenceType >();943 const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >(); 942 944 943 945 if ( depth1 > depth2 ) { … … 966 968 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open }; 967 969 type1->accept( visitor ); 968 ast::ptr< ast::Type > result = visitor. pass.result;970 ast::ptr< ast::Type > result = visitor.core.result; 969 971 970 972 // handling for opaque type declarations (?) -
src/ResolvExpr/ConversionCost.cc
r309d814 r4c925cd 481 481 } 482 482 483 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2, 484 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {485 return ptrsAssignable( t1, t2, env );486 } 487 488 // TODO: This is used for overload resolution. It might be able to be dropped once the old system 489 // is removed. 490 static Cost localConversionCost( 491 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,492 const ast::TypeEnvironment & env493 ) { return conversionCost( src, dst, symtab, env );}483 namespace { 484 # warning For overload resolution between the two versions. 485 int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2, 486 const ast::SymbolTable &, const ast::TypeEnvironment & env ) { 487 return ptrsAssignable( t1, t2, env ); 488 } 489 Cost localConversionCost( 490 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 491 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 492 ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); } 493 } 494 494 495 495 Cost conversionCost( 496 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,497 const ast:: TypeEnvironment & env496 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 497 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 498 498 ) { 499 499 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { 500 500 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) { 501 501 if ( eqv->bound ) { 502 return conversionCost(src, eqv->bound, s ymtab, env );502 return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env ); 503 503 } else { 504 504 return Cost::infinity; … … 508 508 assertf( type, "Unexpected typedef." ); 509 509 if ( type->base ) { 510 return conversionCost( src, type->base, s ymtab, env ) + Cost::safe;510 return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe; 511 511 } 512 512 } … … 518 518 } else if ( const ast::ReferenceType * refType = 519 519 dynamic_cast< const ast::ReferenceType * >( dst ) ) { 520 return convertToReferenceCost( src, refType, s ymtab, env, localPtrsAssignable );520 return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable ); 521 521 } else { 522 ast::Pass<ConversionCost_new> converter( dst, s ymtab, env, localConversionCost );522 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost ); 523 523 src->accept( converter ); 524 return converter. pass.cost;525 } 526 } 527 528 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, 524 return converter.core.cost; 525 } 526 } 527 528 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 529 529 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 530 NumCostCalculation func ) {530 PtrsCalculation func ) { 531 531 if ( 0 < diff ) { 532 532 Cost cost = convertToReferenceCost( 533 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, 534 dst, (diff - 1), symtab, env, func );533 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst, 534 srcIsLvalue, (diff - 1), symtab, env, func ); 535 535 cost.incReference(); 536 536 return cost; … … 538 538 Cost cost = convertToReferenceCost( 539 539 src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base, 540 (diff + 1), symtab, env, func );540 srcIsLvalue, (diff + 1), symtab, env, func ); 541 541 cost.incReference(); 542 542 return cost; … … 563 563 } 564 564 } else { 565 ast::Pass<ConversionCost_new> converter( dst, s ymtab, env, localConversionCost );565 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost ); 566 566 src->accept( converter ); 567 return converter. pass.cost;567 return converter.core.cost; 568 568 } 569 569 } else { … … 572 572 assert( dstAsRef ); 573 573 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) { 574 if ( src ->is_lvalue()) {574 if ( srcIsLvalue ) { 575 575 if ( src->qualifiers == dstAsRef->base->qualifiers ) { 576 576 return Cost::reference; … … 591 591 592 592 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst, 593 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,594 NumCostCalculation func ) {593 bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 594 PtrsCalculation func ) { 595 595 int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth(); 596 return convertToReferenceCost( src, dst, s depth - ddepth, symtab, env, func );596 return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func ); 597 597 } 598 598 … … 651 651 assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) ); 652 652 653 cost = costCalc( refType->base, dst, s ymtab, env );653 cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env ); 654 654 if ( refType->base->qualifiers == dst->qualifiers ) { 655 655 cost.incReference(); … … 667 667 void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) { 668 668 (void)enumInstType; 669 static const ast::BasicType integer( ast::BasicType::SignedInt );670 cost = costCalc( &integer, dst, symtab, env );669 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 670 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 671 671 if ( cost < Cost::unsafe ) { 672 672 cost.incSafe(); … … 680 680 void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) { 681 681 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) { 682 cost = costCalc( eqv->bound, dst, s ymtab, env );682 cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env ); 683 683 } else if ( const ast::TypeInstType * dstAsInst = 684 684 dynamic_cast< const ast::TypeInstType * >( dst ) ) { … … 690 690 assertf( type, "Unexpected typedef."); 691 691 if ( type->base ) { 692 cost = costCalc( type->base, dst, s ymtab, env ) + Cost::safe;692 cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe; 693 693 } 694 694 } … … 703 703 auto dstEnd = dstAsTuple->types.end(); 704 704 while ( srcIt != srcEnd && dstIt != dstEnd ) { 705 Cost newCost = costCalc( * srcIt++, * dstIt++, s ymtab, env );705 Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env ); 706 706 if ( newCost == Cost::infinity ) { 707 707 return; … … 738 738 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 739 739 } 740 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) { 741 cost = Cost::zero; 742 // +1 for zero_t ->, +1 for disambiguation 743 cost.incSafe( maxIntCost + 2 ); 740 744 } 741 745 } … … 755 759 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 756 760 } 757 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) { 758 cost = Cost::zero; 759 cost.incSafe( maxIntCost + 2 ); 760 } 761 } 762 761 } 762 } 763 // size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost"); 763 764 764 765 } // namespace ResolvExpr -
src/ResolvExpr/ConversionCost.h
r309d814 r4c925cd 72 72 73 73 // Some function pointer types, differ in return type. 74 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, 74 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool, 75 75 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 76 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,76 using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *, 77 77 const ast::SymbolTable &, const ast::TypeEnvironment &)>; 78 78 … … 81 81 protected: 82 82 const ast::Type * dst; 83 bool srcIsLvalue; 83 84 const ast::SymbolTable & symtab; 84 85 const ast::TypeEnvironment & env; 85 86 CostCalculation costCalc; 86 87 public: 88 static size_t traceId; 87 89 Cost cost; 88 90 89 ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,91 ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab, 90 92 const ast::TypeEnvironment & env, CostCalculation costCalc ) : 91 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity ) 93 dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ), 94 costCalc( costCalc ), cost( Cost::infinity ) 92 95 {} 93 96 … … 110 113 111 114 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest, 112 const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func ); 115 bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, 116 PtrsCalculation func ); 113 117 114 118 } // namespace ResolvExpr -
src/ResolvExpr/CurrentObject.cc
r309d814 r4c925cd 21 21 #include <string> // for string, operator<<, allocator 22 22 23 #include "AST/Copy.hpp" // for shallowCopy 23 24 #include "AST/Expr.hpp" // for InitAlternative 24 25 #include "AST/GenericSubstitution.hpp" // for genericSubstitution 25 26 #include "AST/Init.hpp" // for Designation 26 27 #include "AST/Node.hpp" // for readonly 28 #include "AST/Print.hpp" // for readonly 27 29 #include "AST/Type.hpp" 28 30 #include "Common/Indenter.h" // for Indenter, operator<< … … 596 598 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {} 597 599 598 void setPosition( 599 std::deque< ptr< Expr > >::const_iterator begin, 600 void setPosition( 601 std::deque< ptr< Expr > >::const_iterator begin, 600 602 std::deque< ptr< Expr > >::const_iterator end 601 603 ) override { … … 637 639 auto res = eval(expr); 638 640 if ( ! res.second ) { 639 SemanticError( location, 641 SemanticError( location, 640 642 toString("Array designator must be a constant expression: ", expr ) ); 641 643 } … … 644 646 645 647 public: 646 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 648 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 647 649 : location( loc ), array( at ), base( at->base ) { 648 650 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) … … 655 657 656 658 void setPosition( const Expr * expr ) { 657 // need to permit integer-constant-expressions, including: integer constants, 658 // enumeration constants, character constants, sizeof expressions, alignof expressions, 659 // need to permit integer-constant-expressions, including: integer constants, 660 // enumeration constants, character constants, sizeof expressions, alignof expressions, 659 661 // cast expressions 660 662 if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { … … 662 664 index = constExpr->intValue(); 663 665 } catch ( SemanticErrorException & ) { 664 SemanticError( expr, 666 SemanticError( expr, 665 667 "Constant expression of non-integral type in array designator: " ); 666 668 } 667 669 } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) { 668 670 setPosition( castExpr->arg ); 669 } else if ( 670 dynamic_cast< const SizeofExpr * >( expr ) 671 || dynamic_cast< const AlignofExpr * >( expr ) 671 } else if ( 672 dynamic_cast< const SizeofExpr * >( expr ) 673 || dynamic_cast< const AlignofExpr * >( expr ) 672 674 ) { 673 675 index = 0; 674 676 } else { 675 assertf( false, 677 assertf( false, 676 678 "bad designator given to ArrayIterator: %s", toString( expr ).c_str() ); 677 679 } 678 680 } 679 681 680 void setPosition( 681 std::deque< ptr< Expr > >::const_iterator begin, 682 void setPosition( 683 std::deque< ptr< Expr > >::const_iterator begin, 682 684 std::deque< ptr< Expr > >::const_iterator end 683 685 ) override { … … 758 760 } 759 761 760 AggregateIterator( 761 const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 762 AggregateIterator( 763 const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 762 764 const MemberList & ms ) 763 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 765 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 764 766 sub( genericSubstitution( i ) ) { 765 767 PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; ) … … 768 770 769 771 public: 770 void setPosition( 771 std::deque< ptr< Expr > >::const_iterator begin, 772 void setPosition( 773 std::deque< ptr< Expr > >::const_iterator begin, 772 774 std::deque< ptr< Expr > >::const_iterator end 773 775 ) final { … … 786 788 return; 787 789 } 788 assertf( false, 790 assertf( false, 789 791 "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); 790 792 } else { 791 assertf( false, 793 assertf( false, 792 794 "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() ); 793 795 } … … 803 805 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } ); 804 806 // need to substitute for generic types so that casts are to concrete types 807 alt.type = shallowCopy(alt.type.get()); 805 808 PRINT( std::cerr << " type is: " << alt.type; ) 806 809 sub.apply( alt.type ); // also apply to designation?? … … 842 845 for ( InitAlternative & alt : ret ) { 843 846 PRINT( std::cerr << "iterating and adding designators" << std::endl; ) 844 alt.designation.get_and_mutate()->designators.emplace_front( 847 alt.designation.get_and_mutate()->designators.emplace_front( 845 848 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } ); 846 849 } … … 897 900 class TupleIterator final : public AggregateIterator { 898 901 public: 899 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 900 : AggregateIterator( 901 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 902 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 903 : AggregateIterator( 904 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 902 905 ) {} 903 906 … … 926 929 return new UnionIterator{ loc, uit }; 927 930 } else { 928 assertf( 929 dynamic_cast< const EnumInstType * >( aggr )930 || dynamic_cast< const TypeInstType * >( aggr ),931 assertf( 932 dynamic_cast< const EnumInstType * >( type ) 933 || dynamic_cast< const TypeInstType * >( type ), 931 934 "Encountered unhandled ReferenceToType in createMemberIterator: %s", 932 935 toString( type ).c_str() ); … … 949 952 using DesignatorChain = std::deque< ptr< Expr > >; 950 953 PRINT( std::cerr << "___findNext" << std::endl; ) 951 954 952 955 // find all the d's 953 956 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts; … … 1013 1016 // set new designators 1014 1017 assertf( ! objStack.empty(), "empty object stack when setting designation" ); 1015 Designation * actualDesignation = 1018 Designation * actualDesignation = 1016 1019 new Designation{ designation->location, DesignatorChain{d} }; 1017 1020 objStack.back()->setPosition( d ); // destroys d -
src/ResolvExpr/PolyCost.cc
r309d814 r4c925cd 58 58 59 59 // TODO: When the old PolyCost is torn out get rid of the _new suffix. 60 struct PolyCost_new { 60 class PolyCost_new { 61 const ast::SymbolTable &symtab; 62 public: 61 63 int result; 62 const ast::SymbolTable &symtab;63 64 const ast::TypeEnvironment &env_; 64 65 65 PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :66 result( 0 ), symtab( symtab), env_( env ) {}66 PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) 67 : symtab( symtab ), result( 0 ), env_( env ) {} 67 68 68 69 void previsit( const ast::TypeInstType * type ) { … … 86 87 ast::Pass<PolyCost_new> costing( symtab, env ); 87 88 type->accept( costing ); 88 return costing. pass.result;89 return costing.core.result; 89 90 } 90 91 -
src/ResolvExpr/PtrsAssignable.cc
r309d814 r4c925cd 155 155 ast::Pass<PtrsAssignable_new> visitor( dst, env ); 156 156 src->accept( visitor ); 157 return visitor. pass.result;157 return visitor.core.result; 158 158 } 159 159 -
src/ResolvExpr/PtrsCastable.cc
r309d814 r4c925cd 293 293 ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab }; 294 294 src->accept( ptrs ); 295 return ptrs. pass.result;295 return ptrs.core.result; 296 296 } 297 297 } -
src/ResolvExpr/RenameVars.cc
r309d814 r4c925cd 19 19 #include <utility> // for pair 20 20 21 #include "AST/ForallSubstitutionTable.hpp" 21 22 #include "AST/Pass.hpp" 22 23 #include "AST/Type.hpp" … … 30 31 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 31 32 33 #include "AST/Copy.hpp" 34 32 35 namespace ResolvExpr { 33 36 … … 37 40 int resetCount = 0; 38 41 ScopedMap< std::string, std::string > nameMap; 42 public: 43 ast::ForallSubstitutionTable subs; 39 44 40 public:41 45 void reset() { 42 46 level = 0; … … 44 48 } 45 49 46 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;47 48 50 void rename( TypeInstType * type ) { 49 mapConstIteratorit = nameMap.find( type->name );51 auto it = nameMap.find( type->name ); 50 52 if ( it != nameMap.end() ) { 51 53 type->name = it->second; … … 65 67 // ditto for assertion names, the next level in 66 68 level++; 67 // acceptAll( td->assertions, *this ); 68 } // for 69 } // if 69 } 70 } 70 71 } 71 72 … … 77 78 78 79 const ast::TypeInstType * rename( const ast::TypeInstType * type ) { 79 mapConstIterator it = nameMap.find( type->name ); 80 // re-linking of base type handled by WithForallSubstitutor 81 82 // rename 83 auto it = nameMap.find( type->name ); 80 84 if ( it != nameMap.end() ) { 81 ast::TypeInstType * mutType = ast::mutate( type ); 82 mutType->name = it->second; 83 type = mutType; 85 // unconditionally mutate because map will *always* have different name, 86 // if this mutates, will *always* have been mutated by ForallSubstitutor above 87 ast::TypeInstType * mut = ast::mutate( type ); 88 mut->name = it->second; 89 type = mut; 84 90 } 91 85 92 return type; 86 93 } … … 88 95 template<typename NodeT> 89 96 const NodeT * openLevel( const NodeT * type ) { 90 if ( !type->forall.empty() ) { 91 nameMap.beginScope(); 92 // Load new names from this forall clause and perform renaming. 93 NodeT * mutType = ast::mutate( type ); 94 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) { 95 std::ostringstream output; 96 output << "_" << resetCount << "_" << level << "_" << td->name; 97 std::string newname( output.str() ); 98 nameMap[ td->name ] = newname; 99 ++level; 97 if ( type->forall.empty() ) return type; 100 98 101 ast::TypeDecl * decl = ast::mutate( td.get() ); 102 decl->name = newname; 103 td = decl; 104 } 99 nameMap.beginScope(); 100 101 // Load new names from this forall clause and perform renaming. 102 NodeT * mutType = ast::mutate( type ); 103 assert( type == mutType && "mutated type must be unique from ForallSubstitutor" ); 104 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) { 105 std::ostringstream output; 106 output << "_" << resetCount << "_" << level << "_" << td->name; 107 std::string newname = output.str(); 108 nameMap[ td->name ] = newname; 109 ++level; 110 111 ast::TypeDecl * mutDecl = ast::mutate( td.get() ); 112 assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" ); 113 mutDecl->name = newname; 114 // assertion above means `td = mutDecl;` is unnecessary 105 115 } 116 // assertion above means `type = mutType;` is unnecessary 117 106 118 return type; 107 119 } 108 120 109 template<typename NodeT> 110 const NodeT * closeLevel( const NodeT * type ) { 111 if ( !type->forall.empty() ) { 112 nameMap.endScope(); 113 } 114 return type; 121 void closeLevel( const ast::ParameterizedType * type ) { 122 if ( type->forall.empty() ) return; 123 124 nameMap.endScope(); 115 125 } 116 126 }; … … 119 129 RenamingData renaming; 120 130 121 struct RenameVars {131 struct RenameVars_old { 122 132 void previsit( TypeInstType * instType ) { 123 133 renaming.openLevel( (Type*)instType ); … … 130 140 renaming.closeLevel( type ); 131 141 } 142 }; 143 144 struct RenameVars_new /*: public ast::WithForallSubstitutor*/ { 145 #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor 146 ast::ForallSubstitutionTable & subs = renaming.subs; 132 147 133 148 const ast::FunctionType * previsit( const ast::FunctionType * type ) { … … 146 161 return renaming.rename( renaming.openLevel( type ) ); 147 162 } 148 const ast::ParameterizedType *postvisit( const ast::ParameterizedType * type ) {149 re turn renaming.closeLevel( type );163 void postvisit( const ast::ParameterizedType * type ) { 164 renaming.closeLevel( type ); 150 165 } 151 166 }; … … 154 169 155 170 void renameTyVars( Type * t ) { 156 PassVisitor<RenameVars > renamer;171 PassVisitor<RenameVars_old> renamer; 157 172 t->accept( renamer ); 158 173 } 159 174 160 175 const ast::Type * renameTyVars( const ast::Type * t ) { 161 ast::Pass<RenameVars> renamer; 162 return t->accept( renamer ); 176 ast::Type *tc = ast::deepCopy(t); 177 ast::Pass<RenameVars_new> renamer; 178 // return t->accept( renamer ); 179 return tc->accept( renamer ); 163 180 } 164 181 -
src/ResolvExpr/ResolveTypeof.cc
r309d814 r4c925cd 99 99 // replace basetypeof(<enum>) by int 100 100 if ( dynamic_cast<EnumInstType*>(newType) ) { 101 Type* newerType = 102 new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 101 Type* newerType = 102 new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 103 103 newType->attributes }; 104 104 delete newType; 105 105 newType = newerType; 106 106 } 107 newType->get_qualifiers().val 107 newType->get_qualifiers().val 108 108 = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals; 109 109 } else { 110 110 newType->get_qualifiers().val |= oldQuals; 111 111 } 112 112 113 113 return newType; 114 114 } … … 120 120 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {} 121 121 122 void pre mutate( const ast::TypeofType * ) { visit_children = false; }122 void previsit( const ast::TypeofType * ) { visit_children = false; } 123 123 124 const ast::Type * post mutate( const ast::TypeofType * typeofType ) {124 const ast::Type * postvisit( const ast::TypeofType * typeofType ) { 125 125 // pass on null expression 126 126 if ( ! typeofType->expr ) return typeofType; … … 133 133 // typeof wrapping expression 134 134 ast::TypeEnvironment dummy; 135 ast::ptr< ast::Expr > newExpr = 135 ast::ptr< ast::Expr > newExpr = 136 136 resolveInVoidContext( typeofType->expr, localSymtab, dummy ); 137 137 assert( newExpr->result && ! newExpr->result->isVoid() ); … … 143 143 // replace basetypeof(<enum>) by int 144 144 if ( newType.as< ast::EnumInstType >() ) { 145 newType = new ast::BasicType{ 145 newType = new ast::BasicType{ 146 146 ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) }; 147 147 } 148 reset_qualifiers( 149 newType, 148 reset_qualifiers( 149 newType, 150 150 ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers ); 151 151 } else { … … 153 153 } 154 154 155 return newType ;155 return newType.release(); 156 156 } 157 157 }; -
src/ResolvExpr/Resolver.cc
r309d814 r4c925cd 982 982 ast::Pass<DeleteFinder_new> finder; 983 983 expr->accept( finder ); 984 return finder. pass.delExpr;984 return finder.core.delExpr; 985 985 } 986 986 … … 1072 1072 /// Strips extraneous casts out of an expression 1073 1073 struct StripCasts_new final { 1074 const ast::Expr * post mutate( const ast::CastExpr * castExpr ) {1074 const ast::Expr * postvisit( const ast::CastExpr * castExpr ) { 1075 1075 if ( 1076 castExpr->isGenerated 1076 castExpr->isGenerated == ast::GeneratedCast 1077 1077 && typesCompatible( castExpr->arg->result, castExpr->result ) 1078 1078 ) { … … 1128 1128 1129 1129 // set up and resolve expression cast to void 1130 ast:: CastExpr *untyped = new ast::CastExpr{ expr };1130 ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr }; 1131 1131 CandidateRef choice = findUnfinishedKindExpression( 1132 1132 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); … … 1236 1236 1237 1237 public: 1238 static size_t traceId; 1238 1239 Resolver_new() = default; 1239 1240 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } … … 1266 1267 const ast::ConstructorInit * previsit( const ast::ConstructorInit * ); 1267 1268 }; 1268 1269 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) { 1270 ast::Pass< Resolver_new > resolver;1271 a ccept_all( translationUnit, resolver);1269 // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver"); 1270 1271 void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) { 1272 ast::Pass< Resolver_new >::run( translationUnit ); 1272 1273 } 1273 1274 … … 1299 1300 // default value expressions have an environment which shouldn't be there and trips up 1300 1301 // later passes. 1301 as t::ptr< ast::FunctionDecl > ret = functionDecl;1302 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {1303 const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i]; 1304 1305 if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {1302 assert( functionDecl->unique() ); 1303 ast::FunctionType * mutType = mutate( functionDecl->type.get() ); 1304 1305 for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) { 1306 if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) { 1306 1307 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) { 1307 1308 if ( init->value->env == nullptr ) continue; 1308 1309 // clone initializer minus the initializer environment 1309 ast::chain_mutate( ret ) 1310 ( &ast::FunctionDecl::type ) 1311 ( &ast::FunctionType::params )[i] 1312 ( &ast::ObjectDecl::init ) 1313 ( &ast::SingleInit::value )->env = nullptr; 1314 1315 assert( functionDecl != ret.get() || functionDecl->unique() ); 1316 assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env ); 1310 auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() ); 1311 auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() ); 1312 auto mutValue = mutate( mutInit->value.get() ); 1313 1314 mutValue->env = nullptr; 1315 mutInit->value = mutValue; 1316 mutParam->init = mutInit; 1317 mutType->params[i] = mutParam; 1318 1319 assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env); 1317 1320 } 1318 1321 } 1319 1322 } 1320 return ret.get(); 1323 mutate_field(functionDecl, &ast::FunctionDecl::type, mutType); 1324 return functionDecl; 1321 1325 } 1322 1326 … … 1341 1345 // in case we decide to allow nested enums 1342 1346 GuardValue( inEnumDecl ); 1343 inEnumDecl = false;1347 inEnumDecl = true; 1344 1348 } 1345 1349 -
src/ResolvExpr/SatisfyAssertions.cpp
r309d814 r4c925cd 9 9 // Author : Aaron B. Moss 10 10 // Created On : Mon Jun 10 17:45:00 2019 11 // Last Modified By : A aron B. Moss12 // Last Modified On : Mon Jun 10 17:45:00 201913 // Update Count : 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 13:56:00 2019 13 // Update Count : 2 14 14 // 15 15 … … 188 188 189 189 matches.emplace_back( 190 cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ),190 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 191 191 std::move( newOpen ), crntResnSlot ); 192 192 } … … 229 229 InferMatcher( InferCache & inferred ) : inferred( inferred ) {} 230 230 231 const ast::Expr * post mutate( const ast::Expr * expr ) {231 const ast::Expr * postvisit( const ast::Expr * expr ) { 232 232 // Skip if no slots to find 233 if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr; 234 233 if ( !expr->inferred.hasSlots() ) return expr; 234 // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr; 235 std::vector<UniqueId> missingSlots; 235 236 // find inferred parameters for resolution slots 236 ast::InferredParams newInferred;237 ast::InferredParams * newInferred = new ast::InferredParams(); 237 238 for ( UniqueId slot : expr->inferred.resnSlots() ) { 238 239 // fail if no matching assertions found 239 240 auto it = inferred.find( slot ); 240 241 if ( it == inferred.end() ) { 241 assert(!"missing assertion"); 242 std::cerr << "missing assertion " << slot << std::endl; 243 missingSlots.push_back(slot); 244 continue; 242 245 } 243 246 … … 245 248 for ( auto & entry : it->second ) { 246 249 // recurse on inferParams of resolved expressions 247 entry.second.expr = post mutate( entry.second.expr );248 auto res = newInferred .emplace( entry );250 entry.second.expr = postvisit( entry.second.expr ); 251 auto res = newInferred->emplace( entry ); 249 252 assert( res.second && "all assertions newly placed" ); 250 253 } … … 252 255 253 256 ast::Expr * ret = mutate( expr ); 254 ret->inferred.set_inferParams( std::move( newInferred ) ); 257 ret->inferred.set_inferParams( newInferred ); 258 if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots; 255 259 return ret; 256 260 } … … 299 303 Cost cost; 300 304 301 OutType( 302 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 305 OutType( 306 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 303 307 const std::vector< DeferRef > & as, const ast::SymbolTable & symtab ) 304 308 : env( e ), open( o ), assns( as ), cost( Cost::zero ) { … … 306 310 for ( const DeferRef & assn : assns ) { 307 311 // compute conversion cost from satisfying decl to assertion 308 cost += computeConversionCost( 309 assn.match.adjType, assn.decl->get_type(), symtab, env );310 312 cost += computeConversionCost( 313 assn.match.adjType, assn.decl->get_type(), false, symtab, env ); 314 311 315 // mark vars+specialization on function-type assertions 312 const ast::FunctionType * func = 316 const ast::FunctionType * func = 313 317 GenPoly::getFunctionType( assn.match.cdata.id->get_type() ); 314 318 if ( ! func ) continue; … … 317 321 cost.decSpec( specCost( param->get_type() ) ); 318 322 } 319 323 320 324 cost.incVar( func->forall.size() ); 321 325 322 326 for ( const ast::TypeDecl * td : func->forall ) { 323 327 cost.decSpec( td->assertions.size() ); … … 329 333 }; 330 334 331 CandidateEnvMerger( 332 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 335 CandidateEnvMerger( 336 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 333 337 const ast::SymbolTable & syms ) 334 338 : crnt(), envs{ env }, opens{ open }, symtab( syms ) {} -
src/ResolvExpr/SatisfyAssertions.hpp
r309d814 r4c925cd 28 28 29 29 /// Recursively satisfies all assertions provided in a candidate; returns true if succeeds 30 void satisfyAssertions( 31 CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out, 30 void satisfyAssertions( 31 CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out, 32 32 std::vector<std::string> & errors ); 33 33 -
src/ResolvExpr/SpecCost.cc
r309d814 r4c925cd 10 10 // Created On : Tue Oct 02 15:50:00 2018 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jun 19 10:43:00 2019 13 // Update Count : 2 14 // 15 12 // Last Modified On : Wed Jul 3 11:07:00 2019 13 // Update Count : 3 14 // 15 16 #include <cassert> 16 17 #include <limits> 17 18 #include <list> … … 129 130 typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type; 130 131 132 #warning Should use a standard maybe_accept 133 void maybe_accept( ast::Type const * type ) { 134 if ( type ) { 135 auto node = type->accept( *visitor ); 136 assert( node == nullptr || node == type ); 137 } 138 } 139 131 140 // Update the minimum to the new lowest non-none value. 132 141 template<typename T> … … 134 143 for ( const auto & node : list ) { 135 144 count = -1; 136 ma pper( node )->accept( *visitor);145 maybe_accept( mapper( node ) ); 137 146 if ( count != -1 && count < minimum ) minimum = count; 138 147 } … … 208 217 } 209 218 ast::Pass<SpecCounter> counter; 210 type->accept( *counter.pass.visitor );211 return counter. pass.get_count();219 type->accept( counter ); 220 return counter.core.get_count(); 212 221 } 213 222 -
src/ResolvExpr/Unify.cc
r309d814 r4c925cd 25 25 #include <vector> 26 26 27 #include "AST/Copy.hpp" 27 28 #include "AST/Decl.hpp" 28 29 #include "AST/Node.hpp" 29 30 #include "AST/Pass.hpp" 31 #include "AST/Print.hpp" 30 32 #include "AST/Type.hpp" 31 33 #include "AST/TypeEnvironment.hpp" … … 135 137 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 136 138 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 139 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 139 140 } 140 141 … … 148 149 newFirst->get_qualifiers() = Type::Qualifiers(); 149 150 newSecond->get_qualifiers() = Type::Qualifiers(); 150 /// std::cerr << "first is "; 151 /// first->print( std::cerr ); 152 /// std::cerr << std::endl << "second is "; 153 /// second->print( std::cerr ); 154 /// std::cerr << std::endl << "newFirst is "; 155 /// newFirst->print( std::cerr ); 156 /// std::cerr << std::endl << "newSecond is "; 157 /// newSecond->print( std::cerr ); 158 /// std::cerr << std::endl; 151 159 152 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 160 153 delete newFirst; … … 170 163 ast::AssertionSet need, have; 171 164 172 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 173 env.apply( newFirst ); 174 env.apply( newSecond ); 175 reset_qualifiers( newFirst ); 176 reset_qualifiers( newSecond ); 165 ast::Type * newFirst = shallowCopy( first ); 166 ast::Type * newSecond = shallowCopy( second ); 167 newFirst ->qualifiers = {}; 168 newSecond->qualifiers = {}; 169 ast::ptr< ast::Type > t1_(newFirst ); 170 ast::ptr< ast::Type > t2_(newSecond); 171 172 ast::ptr< ast::Type > subFirst = env.apply(newFirst).node; 173 ast::ptr< ast::Type > subSecond = env.apply(newSecond).node; 177 174 178 175 return unifyExact( 179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 176 subFirst, 177 subSecond, 178 newEnv, need, have, open, noWiden(), symtab ); 180 179 } 181 180 … … 326 325 327 326 void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) { 328 /// std::cerr << "assertion set is" << std::endl;329 /// printAssertionSet( assertions, std::cerr, 8 );330 /// std::cerr << "looking for ";331 /// assert->print( std::cerr );332 /// std::cerr << std::endl;333 327 AssertionSet::iterator i = assertions.find( assert ); 334 328 if ( i != assertions.end() ) { 335 /// std::cerr << "found it!" << std::endl;336 329 i->second.isUsed = true; 337 330 } // if … … 709 702 const ast::SymbolTable & symtab; 710 703 public: 704 static size_t traceId; 711 705 bool result; 712 706 … … 943 937 944 938 private: 945 template< typename RefType > 946 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 939 // Returns: other, cast as XInstType 940 // Assigns this->result: whether types are compatible (up to generic parameters) 941 template< typename XInstType > 942 const XInstType * handleRefType( const XInstType * inst, const ast::Type * other ) { 947 943 // check that the other type is compatible and named the same 948 auto otherInst = dynamic_cast< const RefType * >( other );949 result = otherInst && inst->name == otherInst->name;944 auto otherInst = dynamic_cast< const XInstType * >( other ); 945 this->result = otherInst && inst->name == otherInst->name; 950 946 return otherInst; 951 947 } … … 968 964 } 969 965 970 template< typename RefType >971 void handleGenericRefType( const RefType * inst, const ast::Type * other ) {966 template< typename XInstType > 967 void handleGenericRefType( const XInstType * inst, const ast::Type * other ) { 972 968 // check that other type is compatible and named the same 973 const RefType * inst2= handleRefType( inst, other );974 if ( ! inst2) return;969 const XInstType * otherInst = handleRefType( inst, other ); 970 if ( ! this->result ) return; 975 971 976 972 // check that parameters of types unify, if any 977 973 const std::vector< ast::ptr< ast::Expr > > & params = inst->params; 978 const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;974 const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params; 979 975 980 976 auto it = params.begin(); … … 1140 1136 }; 1141 1137 1138 // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new"); 1142 1139 bool unify( 1143 1140 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, … … 1188 1185 ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab }; 1189 1186 type1->accept( comparator ); 1190 return comparator. pass.result;1187 return comparator.core.result; 1191 1188 } 1192 1189 } … … 1202 1199 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and 1203 1200 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1204 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1205 reset_qualifiers( t1 ); 1206 reset_qualifiers( t2 ); 1201 ast::Type * t1 = shallowCopy(type1.get()); 1202 ast::Type * t2 = shallowCopy(type2.get()); 1203 t1->qualifiers = {}; 1204 t2->qualifiers = {}; 1205 ast::ptr< ast::Type > t1_(t1); 1206 ast::ptr< ast::Type > t2_(t2); 1207 1207 1208 1208 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { 1209 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones1210 1211 1209 // if exact unification on unqualified types, try to merge qualifiers 1212 1210 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1213 common = type1;1214 reset_qualifiers( common, q1 | q2 );1211 t1->qualifiers = q1 | q2; 1212 common = t1; 1215 1213 return true; 1216 1214 } else { … … 1219 1217 1220 1218 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) { 1221 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones1222 1223 1219 // no exact unification, but common type 1224 reset_qualifiers( common, q1 | q2 ); 1220 auto c = shallowCopy(common.get()); 1221 c->qualifiers = q1 | q2; 1222 common = c; 1225 1223 return true; 1226 1224 } else { -
src/ResolvExpr/typeops.h
r309d814 r4c925cd 10 10 // Created On : Sun May 17 07:28:22 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T hu Aug 8 16:36:00 201913 // Update Count : 512 // Last Modified On : Tue Oct 1 09:45:00 2019 13 // Update Count : 6 14 14 // 15 15 … … 83 83 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 84 84 Cost castCost( 85 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,86 const ast:: TypeEnvironment & env );85 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 86 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 87 87 88 88 // in ConversionCost.cc … … 90 90 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 91 91 Cost conversionCost( 92 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,93 const ast:: TypeEnvironment & env );92 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 93 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 94 94 95 95 // in AlternativeFinder.cc
Note:
See TracChangeset
for help on using the changeset viewer.