- Timestamp:
- Jun 6, 2019, 3:40:48 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:
- 8c0d801
- Parents:
- d3b2c32a
- Location:
- src
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Node.hpp
rd3b2c32a rb7d92b96 18 18 #include <cassert> 19 19 #include <iosfwd> 20 #include <type_traits> // for remove_reference 20 21 21 22 #include "Common/ErrorObjects.h" // for SemanticErrorException … … 82 83 }; 83 84 84 // Mutate a node, non-member function to avoid static type85 // problems and be able to use auto return85 /// Mutate a node, non-member function to avoid static type 86 /// problems and be able to use auto return 86 87 template<typename node_t> 87 88 node_t * mutate( const node_t * node ) { … … 95 96 ); 96 97 return node->clone(); 98 } 99 100 /// Mutate a node field (only clones if not equal to existing value) 101 template<typename node_t, typename field_t> 102 const node_t * mutate_field( 103 const node_t * node, 104 typename std::remove_const<typename std::remove_reference<field_t>::type>::type node_t::* field, 105 field_t&& val 106 ) { 107 if ( node->*field == val ) return node; 108 109 node_t * ret = mutate( node ); 110 ret->*field = std::forward< field_t >( val ); 111 return ret; 97 112 } 98 113 -
src/ResolvExpr/CurrentObject.cc
rd3b2c32a rb7d92b96 579 579 } // namespace ResolvExpr 580 580 581 namespace ast { 582 583 /// Iterates members of a type by initializer 584 class MemberIterator { 585 public: 586 virtual ~MemberIterator() {} 587 }; 588 589 /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry 590 class SimpleIterator final : public MemberIterator { 591 const Type * type = nullptr; 592 public: 593 SimpleIterator( const Type * t ) : type( t ) {} 594 }; 595 596 CurrentObject::CurrentObject( const ast::Type * type ) : objStack() { 597 objStack.emplace_back( new SimpleIterator{ type } ); 598 } 599 600 #warning ast::CurrentObject port incomplete 601 } 602 581 603 // Local Variables: // 582 604 // tab-width: 4 // -
src/ResolvExpr/CurrentObject.h
rd3b2c32a rb7d92b96 17 17 18 18 #include <list> // for list 19 #include <memory> // for unique_ptr 19 20 #include <stack> // for stack 21 #include <vector> 20 22 21 23 class Designation; … … 52 54 } // namespace ResolvExpr 53 55 56 namespace ast { 57 // AST class types 58 class Designation; 59 class InitAlternative; 60 class Type; 61 62 // forward declaration of internal detail 63 class MemberIterator; 64 65 /// Builds initializer lists in resolution 66 class CurrentObject final { 67 std::vector< std::shared_ptr<MemberIterator> > objStack; 68 69 public: 70 CurrentObject() = default; 71 CurrentObject( const Type * type ); 72 }; 73 } // namespace ast 74 54 75 // Local Variables: // 55 76 // tab-width: 4 // -
src/ResolvExpr/Resolver.cc
rd3b2c32a rb7d92b96 165 165 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 166 166 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 167 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {167 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 168 168 // cast is to the same type as its argument, so it's unnecessary -- remove it 169 169 expr = castExpr->arg; … … 965 965 } 966 966 967 /// always-accept candidate filter 968 bool anyCandidate( const Candidate & ) { return true; } 969 967 970 /// Calls the CandidateFinder and finds the single best candidate 968 971 CandidateRef findUnfinishedKindExpression( 969 972 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 970 std::function<bool(const Candidate &)> pred , ResolvMode mode = {}973 std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {} 971 974 ) { 972 975 if ( ! untyped ) return nullptr; … … 1056 1059 ) { 1057 1060 // generated cast is the same type as its argument, remove it after keeping env 1058 ast::ptr<ast::Expr> arg = castExpr->arg; 1059 arg.get_and_mutate()->env = castExpr->env; 1060 return arg; 1061 return ast::mutate_field( 1062 castExpr->arg.get(), &ast::Expr::env, castExpr->env ); 1061 1063 } 1062 1064 return castExpr; … … 1068 1070 } 1069 1071 }; 1072 1073 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts) 1074 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) { 1075 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 1076 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) { 1077 // cast is to the same type as its argument, remove it 1078 ast::ptr< ast::TypeSubstitution > env = castExpr->env; 1079 expr.set_and_mutate( castExpr->arg )->env = env; 1080 } 1081 } 1082 } 1070 1083 1071 1084 /// Establish post-resolver invariants for expressions … … 1082 1095 StripCasts_new::strip( expr ); 1083 1096 } 1084 1097 1098 /// Find the expression candidate that is the unique best match for `untyped` in a `void` 1099 /// context. 1100 ast::ptr< ast::Expr > resolveInVoidContext( 1101 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1102 ) { 1103 assertf( expr, "expected a non-null expression" ); 1104 1105 // set up and resolve expression cast to void 1106 ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr }; 1107 CandidateRef choice = findUnfinishedKindExpression( 1108 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1109 1110 // a cast expression has either 0 or 1 interpretations (by language rules); 1111 // if 0, an exception has already been thrown, and this code will not run 1112 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1113 env = std::move( choice->env ); 1114 1115 return castExpr->arg; 1116 } 1117 1118 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1119 /// context. 1120 ast::ptr< ast::Expr > findVoidExpression( 1121 const ast::Expr * untyped, const ast::SymbolTable & symtab 1122 ) { 1123 resetTyVarRenaming(); 1124 ast::TypeEnvironment env; 1125 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env ); 1126 finishExpr( newExpr, env, untyped->env ); 1127 return newExpr; 1128 } 1129 1085 1130 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the 1086 1131 /// lowest cost, returning the resolved version … … 1094 1139 finishExpr( choice->expr, choice->env, untyped->env ); 1095 1140 return std::move( choice->expr ); 1141 } 1142 1143 /// Resolve `untyped` to the single expression whose candidate is the best match for the 1144 /// given type. 1145 ast::ptr< ast::Expr > findSingleExpression( 1146 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab 1147 ) { 1148 assert( untyped && type ); 1149 const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type }; 1150 ast::ptr< ast::Expr > newExpr = 1151 findKindExpression( castExpr, symtab, "", anyCandidate ); 1152 removeExtraneousCast( newExpr, symtab ); 1153 return newExpr; 1096 1154 } 1097 1155 … … 1125 1183 1126 1184 ast::ptr< ast::Type > functionReturn = nullptr; 1127 //ast::CurrentObject currentObject = nullptr;1185 ast::CurrentObject currentObject = nullptr; 1128 1186 bool inEnumDecl = false; 1129 1187 … … 1141 1199 void previsit( const ast::PointerType * ); 1142 1200 1143 voidprevisit( const ast::ExprStmt * );1144 voidprevisit( const ast::AsmExpr * );1201 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 1202 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 1145 1203 void previsit( const ast::AsmStmt * ); 1146 voidprevisit( const ast::IfStmt * );1147 voidprevisit( const ast::WhileStmt * );1148 voidprevisit( const ast::ForStmt * );1149 voidprevisit( const ast::SwitchStmt * );1150 voidprevisit( const ast::CaseStmt * );1151 voidprevisit( const ast::BranchStmt * );1204 const ast::IfStmt * previsit( const ast::IfStmt * ); 1205 const ast::WhileStmt * previsit( const ast::WhileStmt * ); 1206 const ast::ForStmt * previsit( const ast::ForStmt * ); 1207 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 1208 const ast::CaseStmt * previsit( const ast::CaseStmt * ); 1209 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 1152 1210 void previsit( const ast::ReturnStmt * ); 1153 1211 void previsit( const ast::ThrowStmt * ); … … 1196 1254 1197 1255 void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) { 1198 #warning unimplemented; Resolver port in progress 1199 (void)objectDecl; 1200 assert(false); 1256 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 1257 // class-variable `initContext` is changed multiple times because the LHS is analyzed 1258 // twice. The second analysis changes `initContext` because a function type can contain 1259 // object declarations in the return and parameter types. Therefore each value of 1260 // `initContext` is retained so the type on the first analysis is preserved and used for 1261 // selecting the RHS. 1262 GuardValue( currentObject ); 1263 currentObject = ast::CurrentObject{ objectDecl->get_type() }; 1264 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) { 1265 // enumerator initializers should not use the enum type to initialize, since the 1266 // enum type is still incomplete at this point. Use `int` instead. 1267 currentObject = ast::CurrentObject{ new ast::BasicType{ ast::BasicType::SignedInt } }; 1268 } 1201 1269 } 1202 1270 … … 1210 1278 const ast::StaticAssertDecl * assertDecl 1211 1279 ) { 1212 ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab ); 1213 if ( cond == assertDecl->cond ) return assertDecl; 1280 return ast::mutate_field( 1281 assertDecl, &ast::StaticAssertDecl::cond, 1282 findIntegralExpression( assertDecl->cond, symtab ) ); 1283 } 1284 1285 template< typename PtrType > 1286 void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) { 1287 #warning unimplemented; needs support for new Validate::SizeType global 1288 (void)type; (void)symtab; 1289 assert( false ); 1290 } 1291 1292 void Resolver_new::previsit( const ast::ArrayType * at ) { 1293 handlePtrType( at, symtab ); 1294 } 1295 1296 void Resolver_new::previsit( const ast::PointerType * pt ) { 1297 handlePtrType( pt, symtab ); 1298 } 1299 1300 const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1301 visit_children = false; 1302 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" ); 1214 1303 1215 ast::StaticAssertDecl * ret = mutate( assertDecl ); 1216 ret->cond = cond; 1217 return ret; 1218 } 1219 1220 void Resolver_new::previsit( const ast::ArrayType * at ) { 1221 #warning unimplemented; Resolver port in progress 1222 (void)at; 1223 assert(false); 1224 } 1225 1226 void Resolver_new::previsit( const ast::PointerType * pt ) { 1227 #warning unimplemented; Resolver port in progress 1228 (void)pt; 1229 assert(false); 1230 } 1231 1232 void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1233 #warning unimplemented; Resolver port in progress 1234 (void)exprStmt; 1235 assert(false); 1236 } 1237 1238 void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1239 #warning unimplemented; Resolver port in progress 1240 (void)asmExpr; 1241 assert(false); 1304 return ast::mutate_field( 1305 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) ); 1306 } 1307 1308 const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1309 visit_children = false; 1310 1311 asmExpr = ast::mutate_field( 1312 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) ); 1313 1314 if ( asmExpr->inout ) { 1315 asmExpr = ast::mutate_field( 1316 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) ); 1317 } 1318 1319 return asmExpr; 1242 1320 } 1243 1321 … … 1248 1326 } 1249 1327 1250 void Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1251 #warning unimplemented; Resolver port in progress 1252 (void)ifStmt; 1253 assert(false); 1254 } 1255 1256 void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1257 #warning unimplemented; Resolver port in progress 1258 (void)whileStmt; 1259 assert(false); 1260 } 1261 1262 void Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1263 #warning unimplemented; Resolver port in progress 1264 (void)forStmt; 1265 assert(false); 1266 } 1267 1268 void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1269 #warning unimplemented; Resolver port in progress 1270 (void)switchStmt; 1271 assert(false); 1272 } 1273 1274 void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1275 #warning unimplemented; Resolver port in progress 1276 (void)caseStmt; 1277 assert(false); 1278 } 1279 1280 void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1281 #warning unimplemented; Resolver port in progress 1282 (void)branchStmt; 1283 assert(false); 1328 const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1329 return ast::mutate_field( 1330 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) ); 1331 } 1332 1333 const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1334 return ast::mutate_field( 1335 whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) ); 1336 } 1337 1338 const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1339 if ( forStmt->cond ) { 1340 forStmt = ast::mutate_field( 1341 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) ); 1342 } 1343 1344 if ( forStmt->inc ) { 1345 forStmt = ast::mutate_field( 1346 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) ); 1347 } 1348 1349 return forStmt; 1350 } 1351 1352 const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1353 GuardValue( currentObject ); 1354 switchStmt = ast::mutate_field( 1355 switchStmt, &ast::SwitchStmt::cond, 1356 findIntegralExpression( switchStmt->cond, symtab ) ); 1357 currentObject = ast::CurrentObject{ switchStmt->cond->result }; 1358 return switchStmt; 1359 } 1360 1361 const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1362 if ( caseStmt->cond ) { 1363 #warning unimplemented, depends on currentObject implementation 1364 assert(false); 1365 } 1366 return caseStmt; 1367 } 1368 1369 const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1370 visit_children = false; 1371 // must resolve the argument of a computed goto 1372 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1373 // computed goto argument is void* 1374 branchStmt = ast::mutate_field( 1375 branchStmt, &ast::BranchStmt::computedTarget, 1376 findSingleExpression( 1377 branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 1378 symtab ) ); 1379 } 1380 return branchStmt; 1284 1381 } 1285 1382
Note: See TracChangeset
for help on using the changeset viewer.