Changeset 898ae07 for src/ResolvExpr
- Timestamp:
- Jun 18, 2019, 6:05:30 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 73edfe9
- Parents:
- b408364
- Location:
- src/ResolvExpr
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
rb408364 r898ae07 27 27 #include "Cost.h" 28 28 #include "ExplodedArg.hpp" 29 #include "RenameVars.h" // for renameTyVars 29 30 #include "Resolver.h" 30 31 #include "ResolveTypeof.h" … … 557 558 558 559 /// Generate a cast expression from `arg` to `toType` 559 const ast::Expr * restructureCast( const ast::Expr * arg, const ast::Type * toType, bool isGenerated ) { 560 #warning unimplemented 561 (void)arg; (void)toType; (void)isGenerated; 562 assert(false); 563 return nullptr; 560 const ast::Expr * restructureCast( 561 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated 562 ) { 563 if ( 564 arg->result->size() > 1 565 && ! toType->isVoid() 566 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 567 ) { 568 // Argument is a tuple and the target type is neither void nor a reference. Cast each 569 // member of the tuple to its corresponding target type, producing the tuple of those 570 // cast expressions. If there are more components of the tuple than components in the 571 // target type, then excess components do not come out in the result expression (but 572 // UniqueExpr ensures that the side effects will still be produced) 573 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 574 // expressions which may contain side effects require a single unique instance of 575 // the expression 576 arg = new ast::UniqueExpr{ arg->location, arg }; 577 } 578 std::vector< ast::ptr< ast::Expr > > components; 579 for ( unsigned i = 0; i < toType->size(); ++i ) { 580 // cast each component 581 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 582 components.emplace_back( 583 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 584 } 585 return new ast::TupleExpr{ arg->location, move( components ) }; 586 } else { 587 // handle normally 588 return new ast::CastExpr{ arg->location, arg, toType, isGenerated }; 589 } 590 } 591 592 /// Gets the name from an untyped member expression (must be NameExpr) 593 const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) { 594 if ( memberExpr->member.as< ast::ConstantExpr >() ) { 595 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " ); 596 } 597 598 return memberExpr->member.strict_as< ast::NameExpr >()->name; 564 599 } 565 600 … … 764 799 765 800 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) { 766 addAggMembers( structInst, aggrExpr, cand, Cost::safe, "" );801 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" ); 767 802 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 768 addAggMembers( unionInst, aggrExpr, cand, Cost::safe, "" );803 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" ); 769 804 } 770 805 } … … 773 808 void addAggMembers( 774 809 const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 775 const Candidate Ref& cand, const Cost & addedCost, const std::string & name810 const Candidate & cand, const Cost & addedCost, const std::string & name 776 811 ) { 777 812 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 778 813 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 779 814 CandidateRef newCand = std::make_shared<Candidate>( 780 *cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );815 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 781 816 // add anonymous member interpretations whenever an aggregate value type is seen 782 817 // as a member expression 783 818 addAnonConversions( newCand ); 784 819 candidates.emplace_back( move( newCand ) ); 820 } 821 } 822 823 /// Adds tuple member interpretations 824 void addTupleMembers( 825 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 826 const Cost & addedCost, const ast::Expr * member 827 ) { 828 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 829 // get the value of the constant expression as an int, must be between 0 and the 830 // length of the tuple to have meaning 831 long long val = constantExpr->intValue(); 832 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 833 addCandidate( 834 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 835 addedCost ); 836 } 785 837 } 786 838 } … … 1000 1052 } 1001 1053 1002 // castExpr->result should be replaced with toType 1003 // candidates => matches 1004 1005 #warning unimplemented 1006 (void)castExpr; 1007 assert(false); 1054 // select first on argument cost, then conversion cost 1055 CandidateList minArgCost = findMinCost( matches ); 1056 promoteCvtCost( minArgCost ); 1057 candidates = findMinCost( minArgCost ); 1008 1058 } 1009 1059 … … 1021 1071 1022 1072 void postvisit( const ast::UntypedMemberExpr * memberExpr ) { 1023 #warning unimplemented 1024 (void)memberExpr; 1025 assert(false); 1073 CandidateFinder aggFinder{ symtab, tenv }; 1074 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1075 for ( CandidateRef & agg : aggFinder.candidates ) { 1076 // it's okay for the aggregate expression to have reference type -- cast it to the 1077 // base type to treat the aggregate as the referenced value 1078 Cost addedCost = Cost::zero; 1079 agg->expr = referenceToRvalueConversion( agg->expr, addedCost ); 1080 1081 // find member of the given type 1082 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1083 addAggMembers( 1084 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1085 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1086 addAggMembers( 1087 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1088 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { 1089 addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member ); 1090 } 1091 } 1026 1092 } 1027 1093 … … 1030 1096 } 1031 1097 1032 void postvisit( const ast::NameExpr * variableExpr ) { 1033 #warning unimplemented 1034 (void)variableExpr; 1035 assert(false); 1098 void postvisit( const ast::NameExpr * nameExpr ) { 1099 std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name ); 1100 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1101 for ( auto & data : declList ) { 1102 Cost cost = Cost::zero; 1103 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1104 1105 CandidateRef newCand = std::make_shared<Candidate>( 1106 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1107 cost ); 1108 PRINT( 1109 std::cerr << "decl is "; 1110 ast::print( std::cerr, data.id ); 1111 std::cerr << std::endl; 1112 std::cerr << "newExpr is "; 1113 ast::print( std::cerr, newExpr ); 1114 std::cerr << std::endl; 1115 ) 1116 newCand->expr = ast::mutate_field( 1117 newCand->expr.get(), &ast::Expr::result, 1118 renameTyVars( newCand->expr->result ) ); 1119 // add anonymous member interpretations whenever an aggregate value type is seen 1120 // as a name expression 1121 addAnonConversions( newCand ); 1122 candidates.emplace_back( move( newCand ) ); 1123 } 1036 1124 } 1037 1125 … … 1048 1136 1049 1137 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 1050 #warning unimplemented 1051 (void)sizeofExpr; 1052 assert(false); 1138 if ( sizeofExpr->type ) { 1139 addCandidate( 1140 new ast::SizeofExpr{ 1141 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 1142 tenv ); 1143 } else { 1144 // find all candidates for the argument to sizeof 1145 CandidateFinder finder{ symtab, tenv }; 1146 finder.find( sizeofExpr->expr ); 1147 // find the lowest-cost candidate, otherwise ambiguous 1148 CandidateList winners = findMinCost( finder.candidates ); 1149 if ( winners.size() != 1 ) { 1150 SemanticError( 1151 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1152 } 1153 // return the lowest-cost candidate 1154 CandidateRef & choice = winners.front(); 1155 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1156 choice->cost = Cost::zero; 1157 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } ); 1158 } 1053 1159 } 1054 1160 1055 1161 void postvisit( const ast::AlignofExpr * alignofExpr ) { 1056 #warning unimplemented 1057 (void)alignofExpr; 1058 assert(false); 1162 if ( alignofExpr->type ) { 1163 addCandidate( 1164 new ast::AlignofExpr{ 1165 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 1166 tenv ); 1167 } else { 1168 // find all candidates for the argument to alignof 1169 CandidateFinder finder{ symtab, tenv }; 1170 finder.find( alignofExpr->expr ); 1171 // find the lowest-cost candidate, otherwise ambiguous 1172 CandidateList winners = findMinCost( finder.candidates ); 1173 if ( winners.size() != 1 ) { 1174 SemanticError( 1175 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1176 } 1177 // return the lowest-cost candidate 1178 CandidateRef & choice = winners.front(); 1179 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1180 choice->cost = Cost::zero; 1181 addCandidate( 1182 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1183 } 1059 1184 } 1060 1185 1061 1186 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) { 1062 #warning unimplemented 1063 (void)offsetofExpr; 1064 assert(false); 1187 const ast::ReferenceToType * aggInst; 1188 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ; 1189 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ; 1190 else return; 1191 1192 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1193 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1194 addCandidate( 1195 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1196 } 1065 1197 } 1066 1198 … … 1139 1271 common ) 1140 1272 ) { 1141 #warning unimplemented 1142 assert(false); 1273 // generate typed expression 1274 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1275 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1276 newExpr->result = common ? common : r2->expr->result; 1277 // convert both options to result type 1278 Cost cost = r1->cost + r2->cost + r3->cost; 1279 newExpr->arg2 = computeExpressionConversionCost( 1280 newExpr->arg2, newExpr->result, symtab, env, cost ); 1281 newExpr->arg3 = computeExpressionConversionCost( 1282 newExpr->arg3, newExpr->result, symtab, env, cost ); 1283 // output candidate 1284 CandidateRef newCand = std::make_shared<Candidate>( 1285 newExpr, move( env ), move( open ), move( need ), cost ); 1286 inferParameters( newCand, candidates ); 1143 1287 } 1144 1288 } … … 1198 1342 common ) 1199 1343 ) { 1344 // generate new expression 1200 1345 ast::RangeExpr * newExpr = 1201 1346 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1202 1347 newExpr->result = common ? common : r1->expr->result; 1203 1204 #warning unimplemented 1205 assert(false); 1348 // add candidate 1349 CandidateRef newCand = std::make_shared<Candidate>( 1350 newExpr, move( env ), move( open ), move( need ), 1351 r1->cost + r2->cost ); 1352 inferParameters( newCand, candidates ); 1206 1353 } 1207 1354 } -
src/ResolvExpr/RenameVars.cc
rb408364 r898ae07 96 96 } 97 97 } // namespace 98 99 const ast::Type * renameTyVars( const ast::Type * t ) { 100 #warning unimplemented; make sure resetTyVarRenaming() updated when implemented 101 (void)t; 102 assert(false); 103 return t; 104 } 98 105 } // namespace ResolvExpr 99 106 -
src/ResolvExpr/RenameVars.h
rb408364 r898ae07 23 23 #include "SynTree/Visitor.h" // for Visitor 24 24 25 namespace ast { 26 class Type; 27 } 28 25 29 namespace ResolvExpr { 26 30 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 27 31 void renameTyVars( Type * ); 32 const ast::Type * renameTyVars( const ast::Type * ); 28 33 29 34 /// resets internal state of renamer to avoid overflow
Note: See TracChangeset
for help on using the changeset viewer.