Changes in src/ResolvExpr/Resolver.cc [d76c588:99d4584]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
rd76c588 r99d4584 21 21 #include "Alternative.h" // for Alternative, AltList 22 22 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 23 #include "Candidate.hpp" 24 #include "CandidateFinder.hpp" 23 25 #include "CurrentObject.h" // for CurrentObject 24 26 #include "RenameVars.h" // for RenameVars, global_renamer … … 27 29 #include "typeops.h" // for extractResultType 28 30 #include "Unify.h" // for unify 31 #include "AST/Decl.hpp" 32 #include "AST/Init.hpp" 29 33 #include "AST/Pass.hpp" 34 #include "AST/Print.hpp" 30 35 #include "AST/SymbolTable.hpp" 31 36 #include "Common/PassVisitor.h" // for PassVisitor … … 45 50 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 46 51 #include "Tuples/Tuples.h" 52 #include "Validate/FindSpecialDecls.h" // for SizeType 47 53 48 54 using namespace std; … … 112 118 113 119 namespace { 114 struct DeleteFinder : public WithShortCircuiting {120 struct DeleteFinder_old : public WithShortCircuiting { 115 121 DeletedExpr * delExpr = nullptr; 116 122 void previsit( DeletedExpr * expr ) { … … 126 132 127 133 DeletedExpr * findDeletedExpr( Expression * expr ) { 128 PassVisitor<DeleteFinder > finder;134 PassVisitor<DeleteFinder_old> finder; 129 135 expr->accept( finder ); 130 136 return finder.pass.delExpr; … … 132 138 133 139 namespace { 134 struct StripCasts {140 struct StripCasts_old { 135 141 Expression * postmutate( CastExpr * castExpr ) { 136 142 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { … … 145 151 146 152 static void strip( Expression *& expr ) { 147 PassVisitor<StripCasts > stripper;153 PassVisitor<StripCasts_old> stripper; 148 154 expr = expr->acceptMutator( stripper ); 149 155 } … … 153 159 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 154 160 env.makeSubstitution( *expr->env ); 155 StripCasts ::strip( expr ); // remove unnecessary casts that may be buried in an expression161 StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression 156 162 } 157 163 … … 237 243 winner.cost = winner.cvtCost; 238 244 } 239 245 240 246 // produce ambiguous errors, if applicable 241 247 if ( winners.size() != 1 ) { … … 257 263 258 264 // xxx - check for ambiguous expressions 259 265 260 266 // output selected choice 261 267 alt = std::move( choice ); … … 421 427 void Resolver_old::handlePtrType( PtrType * type ) { 422 428 if ( type->get_dimension() ) { 423 findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer );429 findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer ); 424 430 } 425 431 } … … 446 452 // default value expressions have an environment which shouldn't be there and trips up 447 453 // later passes. 448 // xxx - it might be necessary to somehow keep the information from this environment, but I 454 // xxx - it might be necessary to somehow keep the information from this environment, but I 449 455 // can't currently see how it's useful. 450 456 for ( Declaration * d : functionDecl->type->parameters ) { … … 797 803 initExpr->expr = nullptr; 798 804 std::swap( initExpr->env, newExpr->env ); 799 // InitExpr may have inferParams in the case where the expression specializes a function 800 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 805 // InitExpr may have inferParams in the case where the expression specializes a function 806 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 801 807 // sufficient. 802 808 newExpr->spliceInferParams( initExpr ); 803 809 delete initExpr; 804 810 805 // get the actual object's type (may not exactly match what comes back from the resolver 811 // get the actual object's type (may not exactly match what comes back from the resolver 806 812 // due to conversions) 807 813 Type * initContext = currentObject.getCurrentType(); … … 816 822 if ( isCharType( pt->get_base() ) ) { 817 823 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) { 818 // strip cast if we're initializing a char[] with a char *, 824 // strip cast if we're initializing a char[] with a char *, 819 825 // e.g. char x[] = "hello"; 820 826 newExpr = ce->get_arg(); … … 839 845 // move cursor into brace-enclosed initializer-list 840 846 currentObject.enterListInit(); 841 // xxx - fix this so that the list isn't copied, iterator should be used to change current 847 // xxx - fix this so that the list isn't copied, iterator should be used to change current 842 848 // element 843 849 std::list<Designation *> newDesignations; 844 850 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 845 // iterate designations and initializers in pairs, moving the cursor to the current 851 // iterate designations and initializers in pairs, moving the cursor to the current 846 852 // designated object and resolving the initializer against that object. 847 853 Designation * des = std::get<0>(p); … … 936 942 /////////////////////////////////////////////////////////////////////////// 937 943 944 namespace { 945 /// Finds deleted expressions in an expression tree 946 struct DeleteFinder_new final : public ast::WithShortCircuiting { 947 const ast::DeletedExpr * delExpr = nullptr; 948 949 void previsit( const ast::DeletedExpr * expr ) { 950 if ( delExpr ) { visit_children = false; } 951 else { delExpr = expr; } 952 } 953 954 void previsit( const ast::Expr * ) { 955 if ( delExpr ) { visit_children = false; } 956 } 957 }; 958 959 /// Check if this expression is or includes a deleted expression 960 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 961 ast::Pass<DeleteFinder_new> finder; 962 expr->accept( finder ); 963 return finder.pass.delExpr; 964 } 965 966 /// Calls the CandidateFinder and finds the single best candidate 967 CandidateRef findUnfinishedKindExpression( 968 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 969 std::function<bool(const Candidate &)> pred, ResolvMode mode = {} 970 ) { 971 if ( ! untyped ) return nullptr; 972 973 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 974 static unsigned recursion_level = 0; 975 976 ++recursion_level; 977 ast::TypeEnvironment env; 978 CandidateFinder finder{ symtab, env }; 979 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 980 --recursion_level; 981 982 // produce a filtered list of candidates 983 CandidateList candidates; 984 for ( auto & cand : finder.candidates ) { 985 if ( pred( *cand ) ) { candidates.emplace_back( cand ); } 986 } 987 988 // produce invalid error if no candidates 989 if ( candidates.empty() ) { 990 SemanticError( untyped, 991 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""), 992 "expression: ") ); 993 } 994 995 // search for cheapest candidate 996 CandidateList winners; 997 bool seen_undeleted = false; 998 for ( CandidateRef & cand : candidates ) { 999 int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost ); 1000 1001 if ( c > 0 ) continue; // skip more expensive than winner 1002 1003 if ( c < 0 ) { 1004 // reset on new cheapest 1005 seen_undeleted = ! findDeletedExpr( cand->expr ); 1006 winners.clear(); 1007 } else /* if ( c == 0 ) */ { 1008 if ( findDeletedExpr( cand->expr ) ) { 1009 // skip deleted expression if already seen one equivalent-cost not 1010 if ( seen_undeleted ) continue; 1011 } else if ( ! seen_undeleted ) { 1012 // replace list of equivalent-cost deleted expressions with one non-deleted 1013 winners.clear(); 1014 seen_undeleted = true; 1015 } 1016 } 1017 1018 winners.emplace_back( std::move( cand ) ); 1019 } 1020 1021 // promote candidate.cvtCost to .cost 1022 for ( CandidateRef & cand : winners ) { 1023 cand->cost = cand->cvtCost; 1024 } 1025 1026 // produce ambiguous errors, if applicable 1027 if ( winners.size() != 1 ) { 1028 std::ostringstream stream; 1029 stream << "Cannot choose between " << winners.size() << " alternatives for " 1030 << kind << (kind != "" ? " " : "") << "expression\n"; 1031 ast::print( stream, untyped ); 1032 stream << " Alternatives are:\n"; 1033 print( stream, winners, 1 ); 1034 SemanticError( untyped->location, stream.str() ); 1035 } 1036 1037 // single selected choice 1038 CandidateRef & choice = winners.front(); 1039 1040 // fail on only expression deleted 1041 if ( ! seen_undeleted ) { 1042 SemanticError( untyped->location, choice->expr.get(), "Unique best alternative " 1043 "includes deleted identifier in " ); 1044 } 1045 1046 return std::move( choice ); 1047 } 1048 1049 /// Strips extraneous casts out of an expression 1050 struct StripCasts_new final { 1051 const ast::Expr * postmutate( const ast::CastExpr * castExpr ) { 1052 if ( 1053 castExpr->isGenerated 1054 && typesCompatible( castExpr->arg->result, castExpr->result ) 1055 ) { 1056 // generated cast is the same type as its argument, remove it after keeping env 1057 ast::ptr<ast::Expr> arg = castExpr->arg; 1058 arg.get_and_mutate()->env = castExpr->env; 1059 return arg; 1060 } 1061 return castExpr; 1062 } 1063 1064 static void strip( ast::ptr< ast::Expr > & expr ) { 1065 ast::Pass< StripCasts_new > stripper; 1066 expr = expr->accept( stripper ); 1067 } 1068 }; 1069 1070 /// Establish post-resolver invariants for expressions 1071 void finishExpr( 1072 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env, 1073 const ast::TypeSubstitution * oldenv = nullptr 1074 ) { 1075 // set up new type substitution for expression 1076 ast::ptr< ast::TypeSubstitution > newenv = 1077 oldenv ? oldenv : new ast::TypeSubstitution{}; 1078 env.writeToSubstitution( *newenv.get_and_mutate() ); 1079 expr.get_and_mutate()->env = std::move( newenv ); 1080 // remove unncecessary casts 1081 StripCasts_new::strip( expr ); 1082 } 1083 1084 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the 1085 /// lowest cost, returning the resolved version 1086 ast::ptr< ast::Expr > findKindExpression( 1087 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 1088 std::function<bool(const Candidate &)> pred, ResolvMode mode = {} 1089 ) { 1090 if ( ! untyped ) return {}; 1091 CandidateRef choice = 1092 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode ); 1093 finishExpr( choice->expr, choice->env, untyped->env ); 1094 return std::move( choice->expr ); 1095 } 1096 1097 /// Predicate for "Candidate has integral type" 1098 bool hasIntegralType( const Candidate & i ) { 1099 const ast::Type * type = i.expr->result; 1100 1101 if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) { 1102 return bt->isInteger(); 1103 } else if ( 1104 dynamic_cast< const ast::EnumInstType * >( type ) 1105 || dynamic_cast< const ast::ZeroType * >( type ) 1106 || dynamic_cast< const ast::OneType * >( type ) 1107 ) { 1108 return true; 1109 } else return false; 1110 } 1111 1112 /// Resolve `untyped` as an integral expression, returning the resolved version 1113 ast::ptr< ast::Expr > findIntegralExpression( 1114 const ast::Expr * untyped, const ast::SymbolTable & symtab 1115 ) { 1116 return findKindExpression( untyped, symtab, "condition", hasIntegralType ); 1117 } 1118 } 1119 938 1120 class Resolver_new final 939 : public ast::WithIndexer, public ast::WithGuards, public ast::WithVisitorRef<Resolver_new>, 940 public ast::WithShortCircuiting, public ast::WithStmtsToAdd<> { 941 1121 : public ast::WithSymbolTable, public ast::WithGuards, 1122 public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 1123 public ast::WithStmtsToAdd<> { 1124 1125 ast::ptr< ast::Type > functionReturn = nullptr; 1126 // ast::CurrentObject currentObject = nullptr; 1127 bool inEnumDecl = false; 1128 942 1129 public: 943 1130 Resolver_new() = default; 944 Resolver_new( const ast::SymbolTable & syms ) { /*symtab = syms;*/}945 946 void previsit( ast::FunctionDecl * functionDecl);947 ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl);948 void previsit( ast::ObjectDecl * objectDecl);949 void previsit( ast::EnumDecl * enumDecl);950 void previsit( ast::StaticAssertDecl * assertDecl);951 952 void previsit( ast::ArrayType * at);953 void previsit( ast::PointerType * pt);954 955 void previsit( ast::ExprStmt * exprStmt);956 void previsit( ast::AsmExpr * asmExpr);957 void previsit( ast::AsmStmt * asmStmt);958 void previsit( ast::IfStmt * ifStmt);959 void previsit( ast::WhileStmt * whileStmt);960 void previsit( ast::ForStmt * forStmt);961 void previsit( ast::SwitchStmt * switchStmt);962 void previsit( ast::CaseStmt * caseStmt);963 void previsit( ast::BranchStmt * branchStmt);964 void previsit( ast::ReturnStmt * returnStmt);965 void previsit( ast::ThrowStmt * throwStmt);966 void previsit( ast::CatchStmt * catchStmt);967 void previsit( ast::WaitForStmt * stmt);968 969 void previsit( ast::SingleInit * singleInit);970 void previsit( ast::ListInit * listInit);971 void previsit( ast::ConstructorInit * ctorInit);1131 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } 1132 1133 void previsit( const ast::FunctionDecl * ); 1134 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * ); 1135 void previsit( const ast::ObjectDecl * ); 1136 void previsit( const ast::EnumDecl * ); 1137 const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * ); 1138 1139 void previsit( const ast::ArrayType * ); 1140 void previsit( const ast::PointerType * ); 1141 1142 void previsit( const ast::ExprStmt * ); 1143 void previsit( const ast::AsmExpr * ); 1144 void previsit( const ast::AsmStmt * ); 1145 void previsit( const ast::IfStmt * ); 1146 void previsit( const ast::WhileStmt * ); 1147 void previsit( const ast::ForStmt * ); 1148 void previsit( const ast::SwitchStmt * ); 1149 void previsit( const ast::CaseStmt * ); 1150 void previsit( const ast::BranchStmt * ); 1151 void previsit( const ast::ReturnStmt * ); 1152 void previsit( const ast::ThrowStmt * ); 1153 void previsit( const ast::CatchStmt * ); 1154 void previsit( const ast::WaitForStmt * ); 1155 1156 void previsit( const ast::SingleInit * ); 1157 void previsit( const ast::ListInit * ); 1158 void previsit( const ast::ConstructorInit * ); 972 1159 }; 973 1160 … … 977 1164 } 978 1165 979 void previsit( ast::FunctionDecl * functionDecl ) { 980 #warning unimplemented; Resolver port in progress 981 (void)functionDecl; 982 assert(false); 983 } 984 985 ast::DeclWithType * postvisit( ast::FunctionDecl * functionDecl ) { 986 #warning unimplemented; Resolver port in progress 987 (void)functionDecl; 988 assert(false); 989 return nullptr; 990 } 991 992 void previsit( ast::ObjectDecl * objectDecl ) { 1166 void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) { 1167 GuardValue( functionReturn ); 1168 functionReturn = extractResultType( functionDecl->type ); 1169 } 1170 1171 const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) { 1172 // default value expressions have an environment which shouldn't be there and trips up 1173 // later passes. 1174 ast::ptr< ast::FunctionDecl > ret = functionDecl; 1175 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) { 1176 const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i]; 1177 1178 if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) { 1179 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) { 1180 if ( init->value->env == nullptr ) continue; 1181 // clone initializer minus the initializer environment 1182 strict_dynamic_cast< ast::SingleInit * >( 1183 strict_dynamic_cast< ast::ObjectDecl * >( 1184 ret.get_and_mutate()->type.get_and_mutate()->params[i].get_and_mutate() 1185 )->init.get_and_mutate() 1186 )->value.get_and_mutate()->env = nullptr; 1187 } 1188 } 1189 } 1190 return ret.get(); 1191 } 1192 1193 void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) { 993 1194 #warning unimplemented; Resolver port in progress 994 1195 (void)objectDecl; … … 996 1197 } 997 1198 998 void previsit( ast::EnumDecl * enumDecl ) { 999 #warning unimplemented; Resolver port in progress 1000 (void)enumDecl; 1001 assert(false); 1002 } 1003 1004 void previsit( ast::StaticAssertDecl * assertDecl ) { 1005 #warning unimplemented; Resolver port in progress 1006 (void)assertDecl; 1007 assert(false); 1008 } 1009 1010 void previsit( ast::ArrayType * at ) { 1199 void Resolver_new::previsit( const ast::EnumDecl * ) { 1200 // in case we decide to allow nested enums 1201 GuardValue( inEnumDecl ); 1202 inEnumDecl = false; 1203 } 1204 1205 const ast::StaticAssertDecl * Resolver_new::previsit( 1206 const ast::StaticAssertDecl * assertDecl 1207 ) { 1208 ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab ); 1209 if ( cond == assertDecl->cond ) return assertDecl; 1210 1211 ast::StaticAssertDecl * ret = mutate( assertDecl ); 1212 ret->cond = cond; 1213 return ret; 1214 } 1215 1216 void Resolver_new::previsit( const ast::ArrayType * at ) { 1011 1217 #warning unimplemented; Resolver port in progress 1012 1218 (void)at; … … 1014 1220 } 1015 1221 1016 void previsit(ast::PointerType * pt ) {1222 void Resolver_new::previsit( const ast::PointerType * pt ) { 1017 1223 #warning unimplemented; Resolver port in progress 1018 1224 (void)pt; … … 1020 1226 } 1021 1227 1022 void previsit(ast::ExprStmt * exprStmt ) {1228 void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1023 1229 #warning unimplemented; Resolver port in progress 1024 1230 (void)exprStmt; … … 1026 1232 } 1027 1233 1028 void previsit(ast::AsmExpr * asmExpr ) {1234 void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1029 1235 #warning unimplemented; Resolver port in progress 1030 1236 (void)asmExpr; … … 1032 1238 } 1033 1239 1034 void previsit(ast::AsmStmt * asmStmt ) {1240 void Resolver_new::previsit( const ast::AsmStmt * asmStmt ) { 1035 1241 #warning unimplemented; Resolver port in progress 1036 1242 (void)asmStmt; … … 1038 1244 } 1039 1245 1040 void previsit(ast::IfStmt * ifStmt ) {1246 void Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1041 1247 #warning unimplemented; Resolver port in progress 1042 1248 (void)ifStmt; … … 1044 1250 } 1045 1251 1046 void previsit(ast::WhileStmt * whileStmt ) {1252 void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1047 1253 #warning unimplemented; Resolver port in progress 1048 1254 (void)whileStmt; … … 1050 1256 } 1051 1257 1052 void previsit(ast::ForStmt * forStmt ) {1258 void Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1053 1259 #warning unimplemented; Resolver port in progress 1054 1260 (void)forStmt; … … 1056 1262 } 1057 1263 1058 void previsit(ast::SwitchStmt * switchStmt ) {1264 void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1059 1265 #warning unimplemented; Resolver port in progress 1060 1266 (void)switchStmt; … … 1062 1268 } 1063 1269 1064 void previsit(ast::CaseStmt * caseStmt ) {1270 void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1065 1271 #warning unimplemented; Resolver port in progress 1066 1272 (void)caseStmt; … … 1068 1274 } 1069 1275 1070 void previsit(ast::BranchStmt * branchStmt ) {1276 void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1071 1277 #warning unimplemented; Resolver port in progress 1072 1278 (void)branchStmt; … … 1074 1280 } 1075 1281 1076 void previsit(ast::ReturnStmt * returnStmt ) {1282 void Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) { 1077 1283 #warning unimplemented; Resolver port in progress 1078 1284 (void)returnStmt; … … 1080 1286 } 1081 1287 1082 void previsit(ast::ThrowStmt * throwStmt ) {1288 void Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) { 1083 1289 #warning unimplemented; Resolver port in progress 1084 1290 (void)throwStmt; … … 1086 1292 } 1087 1293 1088 void previsit(ast::CatchStmt * catchStmt ) {1294 void Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1089 1295 #warning unimplemented; Resolver port in progress 1090 1296 (void)catchStmt; … … 1092 1298 } 1093 1299 1094 void previsit(ast::WaitForStmt * stmt ) {1300 void Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1095 1301 #warning unimplemented; Resolver port in progress 1096 1302 (void)stmt; … … 1098 1304 } 1099 1305 1100 void previsit(ast::SingleInit * singleInit ) {1306 void Resolver_new::previsit( const ast::SingleInit * singleInit ) { 1101 1307 #warning unimplemented; Resolver port in progress 1102 1308 (void)singleInit; … … 1104 1310 } 1105 1311 1106 void previsit(ast::ListInit * listInit ) {1312 void Resolver_new::previsit( const ast::ListInit * listInit ) { 1107 1313 #warning unimplemented; Resolver port in progress 1108 1314 (void)listInit; … … 1110 1316 } 1111 1317 1112 void previsit(ast::ConstructorInit * ctorInit ) {1318 void Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) { 1113 1319 #warning unimplemented; Resolver port in progress 1114 1320 (void)ctorInit;
Note: See TracChangeset
for help on using the changeset viewer.