Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r2b59f55 r99d4584  
    2929#include "typeops.h"                     // for extractResultType
    3030#include "Unify.h"                       // for unify
    31 #include "AST/Chain.hpp"
    3231#include "AST/Decl.hpp"
    3332#include "AST/Init.hpp"
     
    165164                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    166165                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    167                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     166                                if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    168167                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
    169168                                        expr = castExpr->arg;
     
    411410
    412411        void Resolver_old::previsit( ObjectDecl * objectDecl ) {
    413                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    414                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    415                 // The second analysis changes initContext because of a function type can contain object
    416                 // declarations in the return and parameter types. So each value of initContext is
     412                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 
     413                // class-variable initContext is changed multiple time because the LHS is analysed twice. 
     414                // The second analysis changes initContext because of a function type can contain object 
     415                // declarations in the return and parameter types. So each value of initContext is 
    417416                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    418417                GuardValue( currentObject );
     
    451450
    452451        void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
    453                 // default value expressions have an environment which shouldn't be there and trips up
     452                // default value expressions have an environment which shouldn't be there and trips up 
    454453                // later passes.
    455454                // xxx - it might be necessary to somehow keep the information from this environment, but I
     
    965964                }
    966965
    967                 /// always-accept candidate filter
    968                 bool anyCandidate( const Candidate & ) { return true; }
    969 
    970966                /// Calls the CandidateFinder and finds the single best candidate
    971967                CandidateRef findUnfinishedKindExpression(
    972968                        const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
    973                         std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
     969                        std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
    974970                ) {
    975971                        if ( ! untyped ) return nullptr;
     
    10591055                                ) {
    10601056                                        // generated cast is the same type as its argument, remove it after keeping env
    1061                                         return ast::mutate_field(
    1062                                                 castExpr->arg.get(), &ast::Expr::env, castExpr->env );
     1057                                        ast::ptr<ast::Expr> arg = castExpr->arg;
     1058                                        arg.get_and_mutate()->env = castExpr->env;
     1059                                        return arg;
    10631060                                }
    10641061                                return castExpr;
     
    10701067                        }
    10711068                };
    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                 }
    10831069
    10841070                /// Establish post-resolver invariants for expressions
     
    10951081                        StripCasts_new::strip( expr );
    10961082                }
    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 
     1083               
    11301084                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    11311085                /// lowest cost, returning the resolved version
    11321086                ast::ptr< ast::Expr > findKindExpression(
    1133                         const ast::Expr * untyped, const ast::SymbolTable & symtab,
    1134                         std::function<bool(const Candidate &)> pred = anyCandidate,
    1135                         const std::string & kind = "", ResolvMode mode = {}
     1087                        const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
     1088                        std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
    11361089                ) {
    11371090                        if ( ! untyped ) return {};
     
    11401093                        finishExpr( choice->expr, choice->env, untyped->env );
    11411094                        return std::move( choice->expr );
    1142                 }
    1143 
    1144                 /// Resolve `untyped` to the single expression whose candidate is the best match for the
    1145                 /// given type.
    1146                 ast::ptr< ast::Expr > findSingleExpression(
    1147                         const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
    1148                 ) {
    1149                         assert( untyped && type );
    1150                         const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
    1151                         ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab );
    1152                         removeExtraneousCast( newExpr, symtab );
    1153                         return newExpr;
    11541095                }
    11551096
     
    11731114                        const ast::Expr * untyped, const ast::SymbolTable & symtab
    11741115                ) {
    1175                         return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
    1176                 }
    1177         }
    1178 
    1179         class Resolver_new final
    1180         : public ast::WithSymbolTable, public ast::WithGuards,
    1181           public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
     1116                        return findKindExpression( untyped, symtab, "condition", hasIntegralType );
     1117                }
     1118        }
     1119
     1120        class Resolver_new final 
     1121        : public ast::WithSymbolTable, public ast::WithGuards, 
     1122          public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 
    11821123          public ast::WithStmtsToAdd<> {
    1183 
     1124       
    11841125                ast::ptr< ast::Type > functionReturn = nullptr;
    1185                 ast::CurrentObject currentObject;
     1126                // ast::CurrentObject currentObject = nullptr;
    11861127                bool inEnumDecl = false;
    11871128
    1188         public:
     1129        public: 
    11891130                Resolver_new() = default;
    11901131                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
     
    11991140                void previsit( const ast::PointerType * );
    12001141
    1201                 const ast::ExprStmt *  previsit( const ast::ExprStmt * );
    1202                 const ast::AsmExpr *    previsit( const ast::AsmExpr * );
    1203                 const ast::AsmStmt *    previsit( const ast::AsmStmt * );
    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 * );
    1210                 const ast::ReturnStmt * previsit( const ast::ReturnStmt * );
    1211                 const ast::ThrowStmt * previsit( const ast::ThrowStmt * );
    1212                 const ast::CatchStmt * previsit( const ast::CatchStmt * );
     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 * );
    12131154                void previsit( const ast::WaitForStmt * );
    12141155
     
    12291170
    12301171        const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) {
    1231                 // default value expressions have an environment which shouldn't be there and trips up
     1172                // default value expressions have an environment which shouldn't be there and trips up 
    12321173                // later passes.
    12331174                ast::ptr< ast::FunctionDecl > ret = functionDecl;
    12341175                for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    12351176                        const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
    1236 
     1177                       
    12371178                        if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
    12381179                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    12391180                                        if ( init->value->env == nullptr ) continue;
    12401181                                        // clone initializer minus the initializer environment
    1241                                         ast::chain_mutate( ret )
    1242                                                 ( &ast::FunctionDecl::type )
    1243                                                         ( &ast::FunctionType::params )[i]
    1244                                                                 ( &ast::ObjectDecl::init )
    1245                                                                         ( &ast::SingleInit::value )->env = nullptr;
    1246 
    1247                                         assert( functionDecl != ret.get() || functionDecl->unique() );
    1248                                         assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );
     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;
    12491187                                }
    12501188                        }
     
    12541192
    12551193        void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    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->location, 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{
    1268                                 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
    1269                 }
     1194                #warning unimplemented; Resolver port in progress
     1195                (void)objectDecl;
     1196                assert(false);
    12701197        }
    12711198
     
    12791206                const ast::StaticAssertDecl * assertDecl
    12801207        ) {
    1281                 return ast::mutate_field(
    1282                         assertDecl, &ast::StaticAssertDecl::cond,
    1283                         findIntegralExpression( assertDecl->cond, symtab ) );
    1284         }
    1285 
    1286         template< typename PtrType >
    1287         void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
    1288                 #warning unimplemented; needs support for new Validate::SizeType global
    1289                 (void)type; (void)symtab;
    1290                 assert( false );
     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;
    12911214        }
    12921215
    12931216        void Resolver_new::previsit( const ast::ArrayType * at ) {
    1294                 handlePtrType( at, symtab );
     1217                #warning unimplemented; Resolver port in progress
     1218                (void)at;
     1219                assert(false);
    12951220        }
    12961221
    12971222        void Resolver_new::previsit( const ast::PointerType * pt ) {
    1298                 handlePtrType( pt, symtab );
    1299         }
    1300 
    1301         const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
    1302                 visit_children = false;
    1303                 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
    1304                
    1305                 return ast::mutate_field(
    1306                         exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
    1307         }
    1308 
    1309         const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
    1310                 visit_children = false;
    1311 
    1312                 asmExpr = ast::mutate_field(
    1313                         asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
    1314                
    1315                 if ( asmExpr->inout ) {
    1316                         asmExpr = ast::mutate_field(
    1317                                 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) );
    1318                 }
    1319                
    1320                 return asmExpr;
    1321         }
    1322 
    1323         const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
    1324                 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
    1325                 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
    1326                 visit_children = false;
    1327                 return asmStmt;
    1328         }
    1329 
    1330         const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
    1331                 return ast::mutate_field(
    1332                         ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
    1333         }
    1334 
    1335         const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
    1336                 return ast::mutate_field(
    1337                         whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );
    1338         }
    1339 
    1340         const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
    1341                 if ( forStmt->cond ) {
    1342                         forStmt = ast::mutate_field(
    1343                                 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
    1344                 }
    1345 
    1346                 if ( forStmt->inc ) {
    1347                         forStmt = ast::mutate_field(
    1348                                 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
    1349                 }
    1350 
    1351                 return forStmt;
    1352         }
    1353 
    1354         const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
    1355                 GuardValue( currentObject );
    1356                 switchStmt = ast::mutate_field(
    1357                         switchStmt, &ast::SwitchStmt::cond,
    1358                         findIntegralExpression( switchStmt->cond, symtab ) );
    1359                 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
    1360                 return switchStmt;
    1361         }
    1362 
    1363         const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
    1364                 if ( caseStmt->cond ) {
    1365                         std::vector< ast::InitAlternative > initAlts = currentObject.getOptions();
    1366                         assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
    1367                                 "expression." );
    1368                        
    1369                         const ast::Expr * untyped =
    1370                                 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1371                         ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
    1372                        
    1373                         // case condition cannot have a cast in C, so it must be removed here, regardless of
    1374                         // whether it would perform a conversion.
    1375                         if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
    1376                                 ast::ptr< ast::TypeSubstitution > env = castExpr->env;
    1377                                 newExpr.set_and_mutate( castExpr->arg )->env = env;
    1378                         }
    1379                        
    1380                         caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr );
    1381                 }
    1382                 return caseStmt;
    1383         }
    1384 
    1385         const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
    1386                 visit_children = false;
    1387                 // must resolve the argument of a computed goto
    1388                 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    1389                         // computed goto argument is void*
    1390                         branchStmt = ast::mutate_field(
    1391                                 branchStmt, &ast::BranchStmt::computedTarget,
    1392                                 findSingleExpression(
    1393                                         branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} },
    1394                                         symtab ) );
    1395                 }
    1396                 return branchStmt;
    1397         }
    1398 
    1399         const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
    1400                 visit_children = false;
    1401                 if ( returnStmt->expr ) {
    1402                         returnStmt = ast::mutate_field(
    1403                                 returnStmt, &ast::ReturnStmt::expr,
    1404                                 findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
    1405                 }
    1406                 return returnStmt;
    1407         }
    1408 
    1409         const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
    1410                 visit_children = false;
    1411                 if ( throwStmt->expr ) {
    1412                         const ast::StructDecl * exceptionDecl =
    1413                                 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" );
    1414                         assert( exceptionDecl );
    1415                         ast::ptr< ast::Type > exceptType =
    1416                                 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
    1417                         throwStmt = ast::mutate_field(
    1418                                 throwStmt, &ast::ThrowStmt::expr,
    1419                                 findSingleExpression( throwStmt->expr, exceptType, symtab ) );
    1420                 }
    1421                 return throwStmt;
    1422         }
    1423 
    1424         const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
    1425                 if ( catchStmt->cond ) {
    1426                         ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
    1427                         catchStmt = ast::mutate_field(
    1428                                 catchStmt, &ast::CatchStmt::cond,
    1429                                 findSingleExpression( catchStmt->cond, boolType, symtab ) );
    1430                 }
    1431                 return catchStmt;
     1223                #warning unimplemented; Resolver port in progress
     1224                (void)pt;
     1225                assert(false);
     1226        }
     1227
     1228        void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
     1229                #warning unimplemented; Resolver port in progress
     1230                (void)exprStmt;
     1231                assert(false);
     1232        }
     1233
     1234        void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
     1235                #warning unimplemented; Resolver port in progress
     1236                (void)asmExpr;
     1237                assert(false);
     1238        }
     1239
     1240        void Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
     1241                #warning unimplemented; Resolver port in progress
     1242                (void)asmStmt;
     1243                assert(false);
     1244        }
     1245
     1246        void Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
     1247                #warning unimplemented; Resolver port in progress
     1248                (void)ifStmt;
     1249                assert(false);
     1250        }
     1251
     1252        void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
     1253                #warning unimplemented; Resolver port in progress
     1254                (void)whileStmt;
     1255                assert(false);
     1256        }
     1257
     1258        void Resolver_new::previsit( const ast::ForStmt * forStmt ) {
     1259                #warning unimplemented; Resolver port in progress
     1260                (void)forStmt;
     1261                assert(false);
     1262        }
     1263
     1264        void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
     1265                #warning unimplemented; Resolver port in progress
     1266                (void)switchStmt;
     1267                assert(false);
     1268        }
     1269
     1270        void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
     1271                #warning unimplemented; Resolver port in progress
     1272                (void)caseStmt;
     1273                assert(false);
     1274        }
     1275
     1276        void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
     1277                #warning unimplemented; Resolver port in progress
     1278                (void)branchStmt;
     1279                assert(false);
     1280        }
     1281
     1282        void Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
     1283                #warning unimplemented; Resolver port in progress
     1284                (void)returnStmt;
     1285                assert(false);
     1286        }
     1287
     1288        void Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
     1289                #warning unimplemented; Resolver port in progress
     1290                (void)throwStmt;
     1291                assert(false);
     1292        }
     1293
     1294        void Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
     1295                #warning unimplemented; Resolver port in progress
     1296                (void)catchStmt;
     1297                assert(false);
    14321298        }
    14331299
Note: See TracChangeset for help on using the changeset viewer.