Changes in src/ResolvExpr/Resolver.cc [99d4584:d76c588]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (35 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r99d4584 rd76c588 21 21 #include "Alternative.h" // for Alternative, AltList 22 22 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 23 #include "Candidate.hpp"24 #include "CandidateFinder.hpp"25 23 #include "CurrentObject.h" // for CurrentObject 26 24 #include "RenameVars.h" // for RenameVars, global_renamer … … 29 27 #include "typeops.h" // for extractResultType 30 28 #include "Unify.h" // for unify 31 #include "AST/Decl.hpp"32 #include "AST/Init.hpp"33 29 #include "AST/Pass.hpp" 34 #include "AST/Print.hpp"35 30 #include "AST/SymbolTable.hpp" 36 31 #include "Common/PassVisitor.h" // for PassVisitor … … 50 45 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 51 46 #include "Tuples/Tuples.h" 52 #include "Validate/FindSpecialDecls.h" // for SizeType53 47 54 48 using namespace std; … … 118 112 119 113 namespace { 120 struct DeleteFinder _old: public WithShortCircuiting {114 struct DeleteFinder : public WithShortCircuiting { 121 115 DeletedExpr * delExpr = nullptr; 122 116 void previsit( DeletedExpr * expr ) { … … 132 126 133 127 DeletedExpr * findDeletedExpr( Expression * expr ) { 134 PassVisitor<DeleteFinder _old> finder;128 PassVisitor<DeleteFinder> finder; 135 129 expr->accept( finder ); 136 130 return finder.pass.delExpr; … … 138 132 139 133 namespace { 140 struct StripCasts _old{134 struct StripCasts { 141 135 Expression * postmutate( CastExpr * castExpr ) { 142 136 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { … … 151 145 152 146 static void strip( Expression *& expr ) { 153 PassVisitor<StripCasts _old> stripper;147 PassVisitor<StripCasts> stripper; 154 148 expr = expr->acceptMutator( stripper ); 155 149 } … … 159 153 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 160 154 env.makeSubstitution( *expr->env ); 161 StripCasts _old::strip( expr ); // remove unnecessary casts that may be buried in an expression155 StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression 162 156 } 163 157 … … 243 237 winner.cost = winner.cvtCost; 244 238 } 245 239 246 240 // produce ambiguous errors, if applicable 247 241 if ( winners.size() != 1 ) { … … 263 257 264 258 // xxx - check for ambiguous expressions 265 259 266 260 // output selected choice 267 261 alt = std::move( choice ); … … 427 421 void Resolver_old::handlePtrType( PtrType * type ) { 428 422 if ( type->get_dimension() ) { 429 findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );423 findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer ); 430 424 } 431 425 } … … 452 446 // default value expressions have an environment which shouldn't be there and trips up 453 447 // later passes. 454 // xxx - it might be necessary to somehow keep the information from this environment, but I 448 // xxx - it might be necessary to somehow keep the information from this environment, but I 455 449 // can't currently see how it's useful. 456 450 for ( Declaration * d : functionDecl->type->parameters ) { … … 803 797 initExpr->expr = nullptr; 804 798 std::swap( initExpr->env, newExpr->env ); 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 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 807 801 // sufficient. 808 802 newExpr->spliceInferParams( initExpr ); 809 803 delete initExpr; 810 804 811 // get the actual object's type (may not exactly match what comes back from the resolver 805 // get the actual object's type (may not exactly match what comes back from the resolver 812 806 // due to conversions) 813 807 Type * initContext = currentObject.getCurrentType(); … … 822 816 if ( isCharType( pt->get_base() ) ) { 823 817 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) { 824 // strip cast if we're initializing a char[] with a char *, 818 // strip cast if we're initializing a char[] with a char *, 825 819 // e.g. char x[] = "hello"; 826 820 newExpr = ce->get_arg(); … … 845 839 // move cursor into brace-enclosed initializer-list 846 840 currentObject.enterListInit(); 847 // xxx - fix this so that the list isn't copied, iterator should be used to change current 841 // xxx - fix this so that the list isn't copied, iterator should be used to change current 848 842 // element 849 843 std::list<Designation *> newDesignations; 850 844 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 851 // iterate designations and initializers in pairs, moving the cursor to the current 845 // iterate designations and initializers in pairs, moving the cursor to the current 852 846 // designated object and resolving the initializer against that object. 853 847 Designation * des = std::get<0>(p); … … 942 936 /////////////////////////////////////////////////////////////////////////// 943 937 944 namespace {945 /// Finds deleted expressions in an expression tree946 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 expression960 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 candidate967 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 resolver974 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 candidates983 CandidateList candidates;984 for ( auto & cand : finder.candidates ) {985 if ( pred( *cand ) ) { candidates.emplace_back( cand ); }986 }987 988 // produce invalid error if no candidates989 if ( candidates.empty() ) {990 SemanticError( untyped,991 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),992 "expression: ") );993 }994 995 // search for cheapest candidate996 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 winner1002 1003 if ( c < 0 ) {1004 // reset on new cheapest1005 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 not1010 if ( seen_undeleted ) continue;1011 } else if ( ! seen_undeleted ) {1012 // replace list of equivalent-cost deleted expressions with one non-deleted1013 winners.clear();1014 seen_undeleted = true;1015 }1016 }1017 1018 winners.emplace_back( std::move( cand ) );1019 }1020 1021 // promote candidate.cvtCost to .cost1022 for ( CandidateRef & cand : winners ) {1023 cand->cost = cand->cvtCost;1024 }1025 1026 // produce ambiguous errors, if applicable1027 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 choice1038 CandidateRef & choice = winners.front();1039 1040 // fail on only expression deleted1041 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 expression1050 struct StripCasts_new final {1051 const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {1052 if (1053 castExpr->isGenerated1054 && typesCompatible( castExpr->arg->result, castExpr->result )1055 ) {1056 // generated cast is the same type as its argument, remove it after keeping env1057 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 expressions1071 void finishExpr(1072 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,1073 const ast::TypeSubstitution * oldenv = nullptr1074 ) {1075 // set up new type substitution for expression1076 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 casts1081 StripCasts_new::strip( expr );1082 }1083 1084 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the1085 /// lowest cost, returning the resolved version1086 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 version1113 ast::ptr< ast::Expr > findIntegralExpression(1114 const ast::Expr * untyped, const ast::SymbolTable & symtab1115 ) {1116 return findKindExpression( untyped, symtab, "condition", hasIntegralType );1117 }1118 }1119 1120 938 class Resolver_new final 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 939 : public ast::WithIndexer, public ast::WithGuards, public ast::WithVisitorRef<Resolver_new>, 940 public ast::WithShortCircuiting, public ast::WithStmtsToAdd<> { 941 1129 942 public: 1130 943 Resolver_new() = default; 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 *);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 ); 1159 972 }; 1160 973 … … 1164 977 } 1165 978 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 ) { 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 ) { 1194 993 #warning unimplemented; Resolver port in progress 1195 994 (void)objectDecl; … … 1197 996 } 1198 997 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 ) { 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 ) { 1217 1011 #warning unimplemented; Resolver port in progress 1218 1012 (void)at; … … 1220 1014 } 1221 1015 1222 void Resolver_new::previsit( constast::PointerType * pt ) {1016 void previsit( ast::PointerType * pt ) { 1223 1017 #warning unimplemented; Resolver port in progress 1224 1018 (void)pt; … … 1226 1020 } 1227 1021 1228 void Resolver_new::previsit( constast::ExprStmt * exprStmt ) {1022 void previsit( ast::ExprStmt * exprStmt ) { 1229 1023 #warning unimplemented; Resolver port in progress 1230 1024 (void)exprStmt; … … 1232 1026 } 1233 1027 1234 void Resolver_new::previsit( constast::AsmExpr * asmExpr ) {1028 void previsit( ast::AsmExpr * asmExpr ) { 1235 1029 #warning unimplemented; Resolver port in progress 1236 1030 (void)asmExpr; … … 1238 1032 } 1239 1033 1240 void Resolver_new::previsit( constast::AsmStmt * asmStmt ) {1034 void previsit( ast::AsmStmt * asmStmt ) { 1241 1035 #warning unimplemented; Resolver port in progress 1242 1036 (void)asmStmt; … … 1244 1038 } 1245 1039 1246 void Resolver_new::previsit( constast::IfStmt * ifStmt ) {1040 void previsit( ast::IfStmt * ifStmt ) { 1247 1041 #warning unimplemented; Resolver port in progress 1248 1042 (void)ifStmt; … … 1250 1044 } 1251 1045 1252 void Resolver_new::previsit( constast::WhileStmt * whileStmt ) {1046 void previsit( ast::WhileStmt * whileStmt ) { 1253 1047 #warning unimplemented; Resolver port in progress 1254 1048 (void)whileStmt; … … 1256 1050 } 1257 1051 1258 void Resolver_new::previsit( constast::ForStmt * forStmt ) {1052 void previsit( ast::ForStmt * forStmt ) { 1259 1053 #warning unimplemented; Resolver port in progress 1260 1054 (void)forStmt; … … 1262 1056 } 1263 1057 1264 void Resolver_new::previsit( constast::SwitchStmt * switchStmt ) {1058 void previsit( ast::SwitchStmt * switchStmt ) { 1265 1059 #warning unimplemented; Resolver port in progress 1266 1060 (void)switchStmt; … … 1268 1062 } 1269 1063 1270 void Resolver_new::previsit( constast::CaseStmt * caseStmt ) {1064 void previsit( ast::CaseStmt * caseStmt ) { 1271 1065 #warning unimplemented; Resolver port in progress 1272 1066 (void)caseStmt; … … 1274 1068 } 1275 1069 1276 void Resolver_new::previsit( constast::BranchStmt * branchStmt ) {1070 void previsit( ast::BranchStmt * branchStmt ) { 1277 1071 #warning unimplemented; Resolver port in progress 1278 1072 (void)branchStmt; … … 1280 1074 } 1281 1075 1282 void Resolver_new::previsit( constast::ReturnStmt * returnStmt ) {1076 void previsit( ast::ReturnStmt * returnStmt ) { 1283 1077 #warning unimplemented; Resolver port in progress 1284 1078 (void)returnStmt; … … 1286 1080 } 1287 1081 1288 void Resolver_new::previsit( constast::ThrowStmt * throwStmt ) {1082 void previsit( ast::ThrowStmt * throwStmt ) { 1289 1083 #warning unimplemented; Resolver port in progress 1290 1084 (void)throwStmt; … … 1292 1086 } 1293 1087 1294 void Resolver_new::previsit( constast::CatchStmt * catchStmt ) {1088 void previsit( ast::CatchStmt * catchStmt ) { 1295 1089 #warning unimplemented; Resolver port in progress 1296 1090 (void)catchStmt; … … 1298 1092 } 1299 1093 1300 void Resolver_new::previsit( constast::WaitForStmt * stmt ) {1094 void previsit( ast::WaitForStmt * stmt ) { 1301 1095 #warning unimplemented; Resolver port in progress 1302 1096 (void)stmt; … … 1304 1098 } 1305 1099 1306 void Resolver_new::previsit( constast::SingleInit * singleInit ) {1100 void previsit( ast::SingleInit * singleInit ) { 1307 1101 #warning unimplemented; Resolver port in progress 1308 1102 (void)singleInit; … … 1310 1104 } 1311 1105 1312 void Resolver_new::previsit( constast::ListInit * listInit ) {1106 void previsit( ast::ListInit * listInit ) { 1313 1107 #warning unimplemented; Resolver port in progress 1314 1108 (void)listInit; … … 1316 1110 } 1317 1111 1318 void Resolver_new::previsit( constast::ConstructorInit * ctorInit ) {1112 void previsit( ast::ConstructorInit * ctorInit ) { 1319 1113 #warning unimplemented; Resolver port in progress 1320 1114 (void)ctorInit;
Note:
See TracChangeset
for help on using the changeset viewer.