Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r99d4584 r2b59f55  
    2929#include "typeops.h"                     // for extractResultType
    3030#include "Unify.h"                       // for unify
     31#include "AST/Chain.hpp"
    3132#include "AST/Decl.hpp"
    3233#include "AST/Init.hpp"
     
    164165                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    165166                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    166                                 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     167                                if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    167168                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
    168169                                        expr = castExpr->arg;
     
    410411
    411412        void Resolver_old::previsit( ObjectDecl * objectDecl ) {
    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 
     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
    416417                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    417418                GuardValue( currentObject );
     
    450451
    451452        void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
    452                 // default value expressions have an environment which shouldn't be there and trips up 
     453                // default value expressions have an environment which shouldn't be there and trips up
    453454                // later passes.
    454455                // xxx - it might be necessary to somehow keep the information from this environment, but I
     
    964965                }
    965966
     967                /// always-accept candidate filter
     968                bool anyCandidate( const Candidate & ) { return true; }
     969
    966970                /// Calls the CandidateFinder and finds the single best candidate
    967971                CandidateRef findUnfinishedKindExpression(
    968972                        const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
    969                         std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
     973                        std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
    970974                ) {
    971975                        if ( ! untyped ) return nullptr;
     
    10551059                                ) {
    10561060                                        // 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;
     1061                                        return ast::mutate_field(
     1062                                                castExpr->arg.get(), &ast::Expr::env, castExpr->env );
    10601063                                }
    10611064                                return castExpr;
     
    10671070                        }
    10681071                };
     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                }
    10691083
    10701084                /// Establish post-resolver invariants for expressions
     
    10811095                        StripCasts_new::strip( expr );
    10821096                }
    1083                
     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
    10841130                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    10851131                /// lowest cost, returning the resolved version
    10861132                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 = {}
     1133                        const ast::Expr * untyped, const ast::SymbolTable & symtab,
     1134                        std::function<bool(const Candidate &)> pred = anyCandidate,
     1135                        const std::string & kind = "", ResolvMode mode = {}
    10891136                ) {
    10901137                        if ( ! untyped ) return {};
     
    10931140                        finishExpr( choice->expr, choice->env, untyped->env );
    10941141                        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;
    10951154                }
    10961155
     
    11141173                        const ast::Expr * untyped, const ast::SymbolTable & symtab
    11151174                ) {
    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, 
     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,
    11231182          public ast::WithStmtsToAdd<> {
    1124        
     1183
    11251184                ast::ptr< ast::Type > functionReturn = nullptr;
    1126                 // ast::CurrentObject currentObject = nullptr;
     1185                ast::CurrentObject currentObject;
    11271186                bool inEnumDecl = false;
    11281187
    1129         public: 
     1188        public:
    11301189                Resolver_new() = default;
    11311190                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
     
    11401199                void previsit( const ast::PointerType * );
    11411200
    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 * );
     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 * );
    11541213                void previsit( const ast::WaitForStmt * );
    11551214
     
    11701229
    11711230        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 
     1231                // default value expressions have an environment which shouldn't be there and trips up
    11731232                // later passes.
    11741233                ast::ptr< ast::FunctionDecl > ret = functionDecl;
    11751234                for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    11761235                        const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
    1177                        
     1236
    11781237                        if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
    11791238                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    11801239                                        if ( init->value->env == nullptr ) continue;
    11811240                                        // 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;
     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 );
    11871249                                }
    11881250                        }
     
    11921254
    11931255        void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    1194                 #warning unimplemented; Resolver port in progress
    1195                 (void)objectDecl;
    1196                 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->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                }
    11971270        }
    11981271
     
    12061279                const ast::StaticAssertDecl * assertDecl
    12071280        ) {
    1208                 ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab );
    1209                 if ( cond == assertDecl->cond ) return assertDecl;
     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 );
     1291        }
     1292
     1293        void Resolver_new::previsit( const ast::ArrayType * at ) {
     1294                handlePtrType( at, symtab );
     1295        }
     1296
     1297        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" );
    12101304               
    1211                 ast::StaticAssertDecl * ret = mutate( assertDecl );
    1212                 ret->cond = cond;
    1213                 return ret;
    1214         }
    1215 
    1216         void Resolver_new::previsit( const ast::ArrayType * at ) {
    1217                 #warning unimplemented; Resolver port in progress
    1218                 (void)at;
    1219                 assert(false);
    1220         }
    1221 
    1222         void Resolver_new::previsit( const ast::PointerType * pt ) {
    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);
     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;
    12981432        }
    12991433
Note: See TracChangeset for help on using the changeset viewer.